Сегодня я расскажу как сделать редактируемые зоны сайта, которые можно изменять не прибегая к помощи визуальных редакторов и редакторов кода.
Задача - сделать максимально интуитивный интерфейс для редактирования. Я буду показывать на примере таблицы, но эту технику можно приспособить (изменив пару строк) для любых блочных элементов, вплоть до body (хотя тут смысла уже мало).
Приступим. Есть таблица, программер и пользователь. Пользователь не знает и знать не хочет html. Программер очень ленится делать админку с визуальным редактором, а потом чистить код, полученный от этого редактора. И есть таблица, которую должен редактировать пользователь.
Такая:
1 | 2 | 3 |
4 | 5 | 6 |
7 | 8 | 9 |
Вот ее код:
<table border="1px"> <tr> <td>1</td> <td>2</td> <td>3</td> </tr> <tr> <td>4</td> <td>5/td> <td>6/td> </tr> <tr> <td>7</td> <td>8</td> <td>9</td> </tr> </table>
Я хочу чтобы при клике на ячейке таблицы, появлялось текстовое поле с содержимым этой ячейки. А при уходе фокуса с этого поля, его текущее содержимое становилось содержимым ячейки.
Конечно, эта задача решается на JavaScript. И конечно я буду использовать горячо любимый мной jQuery.
$(function() { $('td').click(function() { var val = $(this).html(); //получаем значение ячейки //формируем код текстового поля var code = '<input type="text" id="edit" value="'+val+'" />'; //удаляем содержимое ячейки, вставляем в нее сформированное поле $(this).empty().append(code); //устанавливаем фокус на свеженарисованное поле $('#edit').focus(); }); });
Круто. Оно даже работает. Поля появляются. Но не исчезают. Для того, чтобы они исчезали, нужно вешать на событие blur еще один обработчик. Причем делать это нужно каждый раз, как мы генерируем поле. Поэтому дописываем.
$(function() { $('td').click(function() { var val = $(this).html(); //получаем значение ячейки //формируем код текстового поля var code = '<input type="text" id="edit" value="'+val+'" />'; //удаляем содержимое ячейки, вставляем в нее сформированное поле $(this).empty().append(code); //устанавливаем фокус на свеженарисованное поле $('#edit').focus(); $('#edit').blur(function() { //устанавливаем обработчик var val = $(this).val(); //получаем то, что в поле находится //находим ячейку, опустошаем, вставляем значение из поля $(this).parent().empty().html(val); }); }); });
Теперь все работает. Почти... Глюки начинаются когда мы тыкаем по самому полю. Событие click для ячейки тоже срабатывает. Поэтому мы получаем код поля редактирования и вставляем его в поле редактирования. Такая вот рекурсия. Чтобы этого не происходило, нужно отлавливать элемент, по которому происходит клик.
$(function() { $('td').click(function(e) { //ловим элемент, по которому кликнули var t = e.target || e.srcElement; //получаем название тега var elm_name = t.tagName.toLowerCase(); //если это инпут - ничего не делаем if(elm_name == 'input') {return false;} var val = $(this).html(); var code = '<input type="text" id="edit" value="'+val+'" />'; $(this).empty().append(code); $('#edit').focus(); $('#edit').blur(function() { var val = $(this).val(); $(this).parent().empty().html(val); }); }); });
Все. Теперь при кликах на разные поля таблицы, мы будем получать текстовые поля, заполнив которые, можно редактировать таблицу. Примерно такой интерфейс у всеми нами любимых табличных редакторов вроде Excel или Calc. Нативней не придумаешь, пожалуй.
Единственное, что мне хотелось бы изменить - возможность сохранения изменений по Enter. Нет ничего проще.
$(window).keydown(function(event){ //ловим событие нажатия клавиши if(event.keyCode == 13) { //если это Enter $('#edit').blur(); //снимаем фокус с поля ввода } });
На снятии фокуса у нас уже есть обработчик, который делает что нужно.
Вот что у нас получилось. Тыцкайте на ячейки.
1 | 2 | 3 |
4 | 5 | 6 |
7 | 8 | 9 |
Этот скрипт, конечно, можно развить для конкретных нужд. Например, можно править не только ячейки, но и блоки div. Можно приспособить к этой же идее переписывание src у картинок. На ум сразу приходит, что нужно бы привязываться не к имени блока, а к специальному классу. Например, редактировать разрешать только элементы с классом editable. Если смотреть дальше, то можно сделать дополнительные классы ed-text и ed-line и по ним определять рисовать ли input или textarea.
Как сохранить результат - думаю понятно. Нужно при помощи того же JavaScript взять весь измененный контент и каким-либо образом отправить на сервер, где скрипт знает что с этим делать. Я бы просто использовал метод $.post().
Лично я при помощи такого нехитрого метода сделал интерфейс, при помощи которого специальный человек может редактировать большую таблицу. Это гораздо проще и эффективней, чем если бы он присылал мне аналог этой таблицы в Excel или говорил в какую по счету ячейку что вставить.
Если вам понравилась идея и вы считаете что при помощи нее сможете решить свою задачу - используйте ее смело. А если использовать ее самостоятельно не получается - обращайтесь ко мне.