Разработка web приложений. Как сделать редактор списка в стиле Web 2.0 (главная страница)

Владимир | | Ajax, JavaScript, PHP.

Скриншот WebListEditor
В прошлый раз мы начали создание web приложения, позволяющего редактировать простой список. На данный момент мы разобрали общую структуру приложения и функцию подключения к базе данных (БД).

Примечание. Вы можете посмотреть демонстрационную версию редактора или скачать архив с файлами проекта.

Теперь переходим к созданию главной страницы (index.php). Html разметку постараемся максимально упростить, т.к. нам придется изменять ее в процессе работы web приложения.
Заголовок страницы, в общем-то, обычный

<?php
require_once("scripts/dbdata.php");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ru">
<head>
<title>WebListEditor</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="css/styles.css" />
<script type="text/javascript" src="scripts/libs/prototype.js"></script>
<script type="text/javascript" src="scripts/libs/scriptaculous.js?load=effects,controls"></script>
<script type="text/javascript" src="scripts/tasks.js"></script>
</head>

Прежде всего, мы подключаем файл dbdata.php с функцией подключения к БД, затем указываем тип страницы, кодировку, размещения файлов с таблицей стилей и JavaScript библиотеками.

Обратите внимание на то, как подключена библиотека Scriptaculous (строка 11). Эта библиотека состоит из семи файлов (версия 1.7.0), большинство из которых мы не используем. Поэтому с помощью параметра load указываем, какие файлы нужно загрузить. В данном случае нам нужна библиотека эффектов (effects) для подсветки вставленных элементов и библиотека элементов управления (controls) для создания встраиваемого редактора.

Теперь рассмотрим основную часть страницы.
Т.к. страница получилась довольно длинной, я разбил ее на три части.

Первая часть выполняет подключение к БД (с помощью функции connect() из файла dbdata.php) и отправляет запрос получения списка.

<?php $con = connect(); ?>
<div id="content">
<?php
$res = mysql_query("SELECT * FROM listitems");
if ($res === FALSE) {
	echo "Ошибка при отправке запроса к БД:".mysql_error();
}
elseif (mysql_num_rows($res) == 0) {
	echo "<div id=\"noItems\">Записей нет</div>";
}
else {
?>

Если ошибок не было, результаты выполнения запроса будут находиться в переменной $res.

Вторая часть самая интересная. Здесь мы формируем блок со списком.

<p>Список:</p>
<ul id="list">
<?php
	$i = 0;
	while ($item = mysql_fetch_array($res, MYSQL_ASSOC)) {
		$i++;
?>
<li id="listNum_<?php echo $i - 1; ?>">
<div class='itemNum'><?php echo $i; ?></div>
<div class='itemValue' onclick='closeOtherEditors(<?php echo $i - 1; ?>)'
id="itemId_<?php echo $item['id']; ?>"><?php echo $item['item']; ?></div>
<a href="#" class="deleteLink" onclick="deleteItem(<?php echo $item['id']; ?>)">
<img src="css/images/delete.gif" alt="Удалить" title="Удалить" />
</a>
<script type="text/javascript">
editors.push(addEditor("itemId_<?php echo $item['id'];?>",
	"<?php echo $item['id'];?>"));
</script>
</li>
<?php
	}
?>
</ul>
<?php
}
?>
</div>
<?php
mysql_free_result($res);
mysql_close($con);
?>

Основной цикл, который вставляет элементы списка, находится в строках с 5 по 21. Это обычный while цикл, в котором с помощью функции mysql_fetch_array мы получаем результаты запроса и формируем разметку списка.

Обратите внимание на имена атрибутов тегов списка. Для тега li установлен атрибут вида listNum_номер_записи (это порядковый номер записи в списке, а не id в БД).
Внутри тега li находятся три блока (теги div). В первом блоке находится номер элемента списка. Во втором – текст записи. Атрибут id этого элемента имеет вид itemId_номер_в_БД (здесь используется значение поля id из БД). В третьем блоке находится ссылка «Удалить» с картинкой.

В строках 15-18 мы вставили немного JavaScript кода. Он создает встраиваемый текстовый редактор для текущего элемента и добавляет его в массив (с помощью функции push).

Рассмотрим функцию addEditor подробнее (она находится в файле tasks.js).

var editors = [];

function addEditor(item, id) {
	return new Ajax.InPlaceEditor(item,
		"scripts/updateitem.php",
		{
			formId: "listForm",
			okText: "Обновить",
			cancelText: "Отмена",
			highlightcolor: "#ffffff",
			size: "30",
			savingText: "Сохраняю...",
			callback: function(form, value) {
				return "value=" + value + "&id=" + id;
			}
		});
}

В самом начале скрипта мы объявили глобальный массив (editors), в котором будем хранить встраиваемые редакторы (как вы, наверное, догадались, эти редакторы должны быть созданы отдельно для каждого элемента списка).
Функция addEditor выполняет только одну операцию: создает и настраивает встраиваемый редактор для заданного элемента списка. В первом параметре функции указываем id блока, к которому будет присоединен редактор, второй параметр – id записи в БД.

На скриншоте в начале статьи показан активированный встроенный редактор. Принцип его действия заключается в следующем. При щелчке по блоку, для которого установлен редактор, этот блок заменяется формой, содержащей текстовое поле, кнопку «Обновить» и ссылку «Отмена».

Редактор создается с помощью функции InPlaceEditor() объекта Ajax из библиотеки Scriptaculous. В первом параметре этой функции мы указываем имя php скрипта (updateitem.php), которому будут отправлены данные после нажатия на кнопку «Сохранить». Во втором параметре – массив с настройками редактора. Рассмотрим их по порядку:
formId – значение атрибута id формы редактора (используется для установки стилей);
okText – текст на кнопке;
cancelText – текст ссылки «Отмена»;
highlightcolor – цвет подсветки (при появлении формы к ней автоматически применяется эффект highlight, о котором я писал в статье «Подсветка элементов web страницы»);
size – размер текстового поля формы;
savingText – текст, который отображается пока идет обновление данных;
callback – функция, выполняющая отправку данных серверному скрипту.

На последнем параметре остановимся подробнее. Если его опустить, то при обновлении данных редактор отправит только значение, введенное в текстовое поле. Такое поведение нас не устраивает, т.к. нам нужно знать id записи, которую нужно обновить, а не только ее значение. Поэтому мы объявили свою собственную анонимную функцию, которая добавляет в запрос id выбранного элемента в БД.

Примечание. Здесь рассмотрены только те параметры настройки встраиваемого редактора, которые используются в данном приложении. Почитать об остальных можно в документации к библиотеке Scriptaculous.

Если вы внимательно читали разметку html страницы, то заметили, что при щелчке по тексту записи вызывается функция closeOtherEditors(). Этой функции передается номер выбранной записи.

Посмотрим на ее исходный код

function closeOtherEditors(curEditor) {
	editors.each(
		function(editor, index) {
			if (index != curEditor) {
				editor.leaveEditMode();
			}
		}
	);
}

Как видите, эта функция переводит все встроенные редакторы, кроме указанного, в неактивное состояние (с помощью leaveEditMode()). Дело в том, что созданные нами редакторы не зависят один от другого, и по-умолчанию они закрываются только при нажатии на ссылку «Отмена». Это не очень удобно, поэтому в этой функции мы закрываем все редакторы кроме выбранного.

Третья часть страницы содержит форму для добавления новой записи в список. При нажатии на кнопку «Добавить» будет вызвана функция addItem(), размещенная в файле tasks.js.

<form action="#" id="add_item_form">
<p>
<label for="item_value"></label>
<input type="text" id="item_value" size="30" />
<input type="button" value="Добавить" onclick="addItem()" />
</p>
</form>

Подведем небольшой итог. Формирование страницы включает следующие этапы:
1) создание html разметки;
2) получение данных из БД;
3) создание встроенных редакторов для всех записей списка.

В следующий раз мы рассмотрим добавление новых записей в список.

Интересно почитать

Работа в Белгороде поможет преодолеть кризис
Из этой статьи вы узнаете как раскрутить сайт
На нашем сайте вы можете дать объявление бесплатно

  • Очень хорошо описано, спасибо за полезную информацию.

  • Очень хорошо описано, спасибо за полезную информацию.

  • Олег

    Очень инетерсный редактор. Все разобрал свой запрос вставил. Только непонятно как сделать, чтобы отображался не один столбец, а несколько. Что надо класть в цикл для этого ? Где изменить кодировку по умолчанию с UTF на CP1251 ?

    • Столбцы создаются с помощью таблицы стилей. Т.е. в html разметке все блоки идут друг за другом, а размещение в одну строку обеспечивается правилом
      float: right

      Например, если вы вставляете еще один столбец, между номером (<div class=‘itemNum’>) и текстом (<div class=‘itemValue’>), то для этого блока нужно будет задать float: right. Если ваш блок идет последним, то float: right задаете для предыдущего блока.

      Это, конечно, не единственный способ размещения контента в несколько колонок.

      С кодировкой сложнее. Насколько я знаю, ajax запросы всегда отправляются в UTF8.
      Если ваш эта кодировка не устраивает, то можно использовать функцию
      mb_convert_encoding
      для преобразования кодировок.

  • Олег

    Очень инетерсный редактор. Все разобрал свой запрос вставил. Только непонятно как сделать, чтобы отображался не один столбец, а несколько. Что надо класть в цикл для этого ? Где изменить кодировку по умолчанию с UTF на CP1251 ?

    • Столбцы создаются с помощью таблицы стилей. Т.е. в html разметке все блоки идут друг за другом, а размещение в одну строку обеспечивается правилом
      float: right

      Например, если вы вставляете еще один столбец, между номером (<div class=‘itemNum’>) и текстом (<div class=‘itemValue’>), то для этого блока нужно будет задать float: right. Если ваш блок идет последним, то float: right задаете для предыдущего блока.

      Это, конечно, не единственный способ размещения контента в несколько колонок.

      С кодировкой сложнее. Насколько я знаю, ajax запросы всегда отправляются в UTF8.
      Если ваш эта кодировка не устраивает, то можно использовать функцию
      mb_convert_encoding
      для преобразования кодировок.

  • Тоха

    Подключил как написано, все нормально. Но когда пытаюсь изменить значение в ячейке появляется подобная запись.
    Notice: Use of undefined constant id — assumed 'id' in C:apachelocalhostwwwscriptsupdateitem.php on line 14
    В чем может быть проблем?
    P.S. : в исходниках поменял только название базы, имя пользователя и пароль.

    • Прошу прощения, виноват.
      Строку 14 в файле updateitem.php нужно изменить:
      if (($v != null) && ($v != «») && ($id != null) && ($id != «») ) {

      Исправленный вариант я уже выложил.

      Похоже моя версия PHP сама исправляла ошибку или просто игнорировала ее 🙂

  • Тоха

    Подключил как написано, все нормально. Но когда пытаюсь изменить значение в ячейке появляется подобная запись.
    Notice: Use of undefined constant id — assumed 'id' in C:\apache\localhost\www\scripts\updateitem.php on line 14
    В чем может быть проблем?
    P.S. : в исходниках поменял только название базы, имя пользователя и пароль.

    • Прошу прощения, виноват.
      Строку 14 в файле updateitem.php нужно изменить:
      if (($v != null) && ($v != «») && ($id != null) && ($id != «») ) {

      Исправленный вариант я уже выложил.

      Похоже моя версия PHP сама исправляла ошибку или просто игнорировала ее 🙂

  • Тоха

    Добрый день. Подскажите пожалуйста как добавить к этому всему 2 столбца(Столбец 1, Столебц 2). Заранее благодарен за совет.

    • Тут может быть несколько вариантов. В html разметке все блоки идут друг за другом, а колонки создаются только за счет таблицы стилей.

      Поэтому просто добавьте
      Столбец 1
      Столбец 2
      перед строкой 12 (листинг 3). А в файле в таблице стилей установите float:left

      Но если планируете использовать много столбцов, возможно, будет удобнее использовать таблицы.

  • Тоха

    Добрый день. Подскажите пожалуйста как добавить к этому всему 2 столбца(Столбец 1, Столебц 2). Заранее благодарен за совет.

    • Тут может быть несколько вариантов. В html разметке все блоки идут друг за другом, а колонки создаются только за счет таблицы стилей.

      Поэтому просто добавьте

      Столбец 1
      Столбец 2

      перед строкой 12 (листинг 3). А в файле в таблице стилей установите float:left

      Но если планируете использовать много столбцов, возможно, будет удобнее использовать таблицы.

  • Олег

    Конечно редактор классный, но я на него забил и написал свой чисто на пхп потомучто разгребать чужой код не люблю, но всеравно спасибо

    • Правильно сделали 🙂 Даже если своим не будете пользоваться, все равно польза будет просто от того, что вы его сами написали.
      А этот редактор вобщем-то демонстрационный. Минимальный набор возможностей.
      Но даже в таком варианте описание растянулось на 6 статей 🙂

  • Олег

    Конечно редактор классный, но я на него забил и написал свой чисто на пхп потомучто разгребать чужой код не люблю, но всеравно спасибо

    • Правильно сделали 🙂 Даже если своим не будете пользоваться, все равно польза будет просто от того, что вы его сами написали.
      А этот редактор вобщем-то демонстрационный. Минимальный набор возможностей.
      Но даже в таком варианте описание растянулось на 6 статей 🙂

  • jelena

    Zdravstvuite!!
    Spasibo ogromnoe za eto podrobnoe opisanie! Mozet etot vopros zdes' ne sovsem umesten, no nadejus' mozet smozite mne pomo4'!! ja ispol'zuju Ajax.InPlaceCollectionEditor dlja redaktirovanija select box. I mne nado peredavt' 2 zna4enija : value i id pri pomoshi callback. No eto ne rabotaet:::( Mozet vi mozete podskazt' po4emu?

    Jelena

    • А что именно не работает? Можно взглянуть на код?

      • jelena

        polu4aetsja tak 4to callback dlja InPlaceCollectionEditor prosto ignoriruetsja. Segodnja zelii den razbiralas , no tak i ne nashla otveta….

        <span «onclick='closeOtherEditors()' id=»exact_»>

        editors.push(addEditorSelect(«exact_»,
        «»));

        i 4ast kotoraja ne rabotaet ( to4nee prosto ignoriruetsja callback)

        function addEditorSelect(item, id) {
        return new Ajax.InPlaceCollectionEditor(item,
        «../form/scripts/updateitem.php»,
        { callback: function(form, value) {
        return «value=» + value + «&id=» + id;
        },
        collection: ['Yes','No'],
        value:'Ei',

        okText: «ok»,
        cancelText: «cancel»,
        highlightcolor: «#ffffff»,
        size: «30»,
        savingText: «saving»,
        ajaxOptions: {method: 'get'},

        });
        }

      • jelena

        nu nikak ne polu4aetsja vilozit kod normalno;( Pozaluista izvinite.
        T.e u menja vse toze samoe 4to i u vas v opisanii, tolko ispolzuju ne InPlaceEditor a InPlaceCollectionEditor s dvumja zna4enijami (da / net). i mne nado 4tobi serveru otpravljalos 2 zne4enija : id zapisi i zna4enie iz select box..

  • jelena

    Zdravstvuite!!
    Spasibo ogromnoe za eto podrobnoe opisanie! Mozet etot vopros zdes' ne sovsem umesten, no nadejus' mozet smozite mne pomo4'!! ja ispol'zuju Ajax.InPlaceCollectionEditor dlja redaktirovanija select box. I mne nado peredavt' 2 zna4enija : value i id pri pomoshi callback. No eto ne rabotaet:::( Mozet vi mozete podskazt' po4emu?

    Jelena

    • А что именно не работает? Можно взглянуть на код?

      • jelena

        polu4aetsja tak 4to callback dlja InPlaceCollectionEditor prosto ignoriruetsja. Segodnja zelii den razbiralas , no tak i ne nashla otveta….

        <span «onclick='closeOtherEditors()' id=»exact_»>

        editors.push(addEditorSelect(«exact_»,
        «»));

        i 4ast kotoraja ne rabotaet ( to4nee prosto ignoriruetsja callback)

        function addEditorSelect(item, id) {
        return new Ajax.InPlaceCollectionEditor(item,
        «../form/scripts/updateitem.php»,
        { callback: function(form, value) {
        return «value=» + value + «&id=» + id;
        },
        collection: ['Yes','No'],
        value:'Ei',

        okText: «ok»,
        cancelText: «cancel»,
        highlightcolor: «#ffffff»,
        size: «30»,
        savingText: «saving»,
        ajaxOptions: {method: 'get'},

        });
        }

      • jelena

        nu nikak ne polu4aetsja vilozit kod normalno;( Pozaluista izvinite.
        T.e u menja vse toze samoe 4to i u vas v opisanii, tolko ispolzuju ne InPlaceEditor a InPlaceCollectionEditor s dvumja zna4enijami (da / net). i mne nado 4tobi serveru otpravljalos 2 zne4enija : id zapisi i zna4enie iz select box..

  • jelena

    4to to ja v predidushem poste slu4aino sterla:(

    <span «onclick='closeOtherEditors()'
    id=»exact_»>

    editors.push(addEditorSelect(«exact_»,
    «»));

  • jelena

    4to to ja v predidushem poste slu4aino sterla:(

    <span «onclick='closeOtherEditors()'
    id=»exact_»>

    editors.push(addEditorSelect(«exact_»,
    «»));

  • jelena


    <span "onclick='closeOtherEditors()'
    id="exact_">

    editors.push(addEditorSelect("exact_",
    ""));

    function addEditorSelect(item, id) {
    return new Ajax.InPlaceCollectionEditor(item,
    "../form/scripts/updateitem.php",
    { callback: function(form, value) {
    return "value=" + value + "&id=" + id;
    },
    collection: ['Yes','No'],
    value:'No',

    okText: "ok",
    cancelText: "cancel",
    highlightcolor: "#ffffff",
    size: "30",
    savingText: "saving",
    ajaxOptions: {method: 'get'},

    });
    }

    • Я поэкспериментирую с callback, но, возможно, вам подойдет другое решение.
      При создании списка указать id:
      collection: [['1','Yes'],['0','No']]

      В этом случае при отправке вместо Yes будет отправлена 1. Т.к. все записи в списке имеют уникальный id (1, 0), то передавать значение (Yes, No), по-моему, смысла нет.

  • jelena


    <span "onclick='closeOtherEditors()'
    id="exact_">

    editors.push(addEditorSelect("exact_",
    ""));

    function addEditorSelect(item, id) {
    return new Ajax.InPlaceCollectionEditor(item,
    "../form/scripts/updateitem.php",
    { callback: function(form, value) {
    return "value=" + value + "&id=" + id;
    },
    collection: ['Yes','No'],
    value:'No',

    okText: "ok",
    cancelText: "cancel",
    highlightcolor: "#ffffff",
    size: "30",
    savingText: "saving",
    ajaxOptions: {method: 'get'},

    });
    }

    • Я поэкспериментирую с callback, но, возможно, вам подойдет другое решение.
      При создании списка указать id:
      collection: [['1','Yes'],['0','No']]

      В этом случае при отправке вместо Yes будет отправлена 1. Т.к. все записи в списке имеют уникальный id (1, 0), то передавать значение (Yes, No), по-моему, смысла нет.

  • Vasiliy

    а как вставить элемент в начало списка ?
    function parseAddItemResponse(transport)
    //вставляем новый элемент в конец списка

    пробовал так
    <li id='listNum_"+(editors.length - editors.length)
    но эффекту не дало
    разобрался только как его подсветить если элемент когда то встанет наверх
    Effect.Highlight(items.first(),

  • Vasiliy

    а как вставить элемент в начало списка ?
    function parseAddItemResponse(transport)
    //вставляем новый элемент в конец списка

    пробовал так
    <li id='listNum_"+(editors.length - editors.length)
    но эффекту не дало
    разобрался только как его подсветить если элемент когда то встанет наверх
    Effect.Highlight(items.first(),

  • Vasiliy

    сори я в ещё новичок оказывается нужно было сменить
    Insertion.Bottom на
    Insertion.Top

  • Vasiliy

    сори я в ещё новичок оказывается нужно было сменить
    Insertion.Bottom на
    Insertion.Top

  • Vasiliy

    я добавил в index.php в форму

    Плиз подскажите как мне получить в tasks.js в функции addItem
    значение этого инпута и потом отправить его вместе с item_value в addItem.php

    для получения я использовал аналогичный метод как и для item_value
    var v2 = $('item_log').value;
    //формируем строку с параметрами запроса
    var pars2 = $F(item_log).value;

    а вот с отправкой всё очень туманно .

    • Vasiliy

      вроде code забыл закрыть
      строка исчезла после слов

      я добавил в index.php в форму
      input id="item_log" type="hidden" value="777"

      • Попробуйте так:

        var v = $('item_value').value;
        var vl = $('item_log').value;
        //формируем строку с параметрами запроса
        var pars = $H({value:v, log:vl}).toQueryString();

  • Vasiliy

    я добавил в index.php в форму

    Плиз подскажите как мне получить в tasks.js в функции addItem
    значение этого инпута и потом отправить его вместе с item_value в addItem.php

    для получения я использовал аналогичный метод как и для item_value
    var v2 = $('item_log').value;
    //формируем строку с параметрами запроса
    var pars2 = $F(item_log).value;

    а вот с отправкой всё очень туманно .

    • Vasiliy

      вроде code забыл закрыть
      строка исчезла после слов

      я добавил в index.php в форму
      input id="item_log" type="hidden" value="777"

      • Попробуйте так:

        var v = $('item_value').value;
        var vl = $('item_log').value;
        //формируем строку с параметрами запроса
        var pars = $H({value:v, log:vl}).toQueryString();

  • Александр

    хотелось узнать не смогли ли Вы исправить проблему с Ajax.InPlaceCollectionEditor при отправке 2 переменных. а то у меня возник ла аналогичная проблема.

    • Нет, с этой проблемой я до конца не разобрался. Как временное решение можно при создании списка указать id:
      collection: [['1','Yes'],['0','No']]
      (я о нём написал несколькими комментариями выше).

      Сейчас я с prototype практически не работаю, переключился на jQuery. Она удобнее, и объём скриптов получается меньше.

  • Александр

    хотелось узнать не смогли ли Вы исправить проблему с Ajax.InPlaceCollectionEditor при отправке 2 переменных. а то у меня возник ла аналогичная проблема.

    • Нет, с этой проблемой я до конца не разобрался. Как временное решение можно при создании списка указать id:
      collection: [['1','Yes'],['0','No']]
      (я о нём написал несколькими комментариями выше).

      Сейчас я с prototype практически не работаю, переключился на jQuery. Она удобнее, и объём скриптов получается меньше.

  • Александр

    спасибо за ответ. подскажите пожалуйста где можно посмотреть аналогичную функцию (желательно рабочую уже) на jQuery

  • Александр

    спасибо за ответ. подскажите пожалуйста где можно посмотреть аналогичную функцию (желательно рабочую уже) на jQuery

  • Я сам для создания inplace редакторов использовал плагин jeditable — меня всё устраивало. Но таких плагинов довольно много, например, jquery-in-place-editor. Как правило, разработчики делают демонстрационные странички, поэтому найти нужную функцию и посмотреть как она работает несложно.

  • Я сам для создания inplace редакторов использовал плагин jeditable — меня всё устраивало. Но таких плагинов довольно много, например, jquery-in-place-editor. Как правило, разработчики делают демонстрационные странички, поэтому найти нужную функцию и посмотреть как она работает несложно.

  • Александр

    спасибо. как раз читал статью про jquery-in-place-editor. и на вашем сайте тоже нашел интересную статью.

  • Александр

    спасибо. как раз читал статью про jquery-in-place-editor. и на вашем сайте тоже нашел интересную статью.

  • Александр

    пожалуйста станьте моим личным консультантом. у меня есть вопросы, а ответить на них никто не может или не хочет

    • Честно говоря, первый раз ко мне с подобной просьбой обращаются 🙂
      Если никто не может ответить на ваши вопросы, то почему вы решили, что я знаю эти ответы?
      Вообще ситуация простая. Вы можете задать любой вопрос. Если я знаю ответ, то постараюсь ответить. Если для ответа нужно будет написать статью, то, возможно, я это сделаю, но когда появится свободное время.
      А если вам нужно написать скрипт на заказ, то этот вопрос тоже можно обсудить в индивидуальном порядке.

  • Александр

    пожалуйста станьте моим личным консультантом. у меня есть вопросы, а ответить на них никто не может или не хочет

    • Честно говоря, первый раз ко мне с подобной просьбой обращаются 🙂
      Если никто не может ответить на ваши вопросы, то почему вы решили, что я знаю эти ответы?
      Вообще ситуация простая. Вы можете задать любой вопрос. Если я знаю ответ, то постараюсь ответить. Если для ответа нужно будет написать статью, то, возможно, я это сделаю, но когда появится свободное время.
      А если вам нужно написать скрипт на заказ, то этот вопрос тоже можно обсудить в индивидуальном порядке.