Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Web Development
Code

Создание системы редактирования для использования на месте

by
Difficulty:IntermediateLength:LongLanguages:

Russian (Pусский) translation by AlexBioJS (you can also view the original English article)

(* системы редактирования, которую можно использовать на той же странице, где размещается оригинальный текст. Здесь и далее примеч. пер.). Вынуждать пользователей переходить между несколькими страницами лишь для того, чтобы отредактировать текст, – это прошлый век. В этом руководстве вы узнаете, как создать систему редактирования для использования на месте, подобную той, что используется на популярных сайтах вроде Flickr.


От автора

Со всей этой шумихой вокруг Web 2.0 (* термин относится к сайтам, где особое значение придается контенту, создаваемому пользователями, удобству использования, культуре совместного создания контента и функциональной совместимости с другими системами, устройствами...), удобство использования теперь важно, как никогда ранее. Наличие возможности отредактировать какой-то контент без необходимости перехода на другую страницу, – то, что многим пользователям очень нужно. На множестве известных веб-сайтов эта возможность уже реализована весьма эффективно. Если вы использовали Flickr, то, вероятно, уже видели, как это выглядит в действии.

Думаю, что лучше один раз увидеть, чем сто раз услышать. Ознакомьтесь с демоверсией и поиграйтесь с ней сами.

Сегодня мы рассмотрим, как реализовать эту возможность при помощи, вы угадали, нашей любимой библиотеки JavaScript, jQuery. Заинтересовало? Давайте прямо сейчас и приступим к делу!

Требования к системе

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

  • Нам нужно предоставить пользователю возможность редактировать контент, оставаясь на той же странице. Это исходное требование.
  • Система должна либо работать в целом, либо не работать вообще (* по принципу «все или ничего»). Если у пользователя отключен JS, то мы не хотим прибегать к странным ухищрениям.
  • Пользователь должен быть в курсе, что контент можно редактировать. Он должен это понять из-за незначительного изменения цвета фона на светло-голубой.
  • При выборе способа активации возможности редактирования у нас имеется пара вариантов. Мы можем предоставить пользователям эту возможность либо когда они единожды нажимают кнопку мыши, либо когда дважды. Я остановил свой выбор на последнем варианте, поскольку случайные двойные нажатия кнопки мыши происходят реже, чем случайные одинарные. Для того чтобы его сменить, нужно всего лишь изменить аргумент метода bind.
  • У пользователя должна быть возможность сохранить внесенные изменения или отказаться от них.
  • Обработчики для сохранения или редактирования могут быть запущены двумя способами. За счет событий, возникающих при работе с клавиатурой, или событий, возникающих при работе с мышкой. Я остановил свой выбор на последнем варианте, поскольку событиям, возникающим при работе с клавиатурой, не хватает определенности (* они могут возникнуть и при выполнении нами действий, не связанных конкретно с нашей системой редактирования).
  • Что касается событий, возникающих при работе с мышкой, то вы могли бы использовать либо традиционные кнопки, либо обычные ссылки. Я выбрал ссылки без особой причины.
  • У пользователя должна быть возможность возобновить редактирование, даже если он нажимает за пределами поля ввода или уходит со страницы и приходит снова.
  • Также у пользователя должна быть возможность редактировать как можно больше полей одновременно.

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

План действий

Теперь нам нужно будет составить последовательный план того, что необходимо выполнить.

Шаг 1: Нам нужно будет добавить класс editable к каждому элементу, для которого требуется реализовать возможность редактирования текста на месте.

Шаг 2: Далее нам будет необходимо добавить классы для изменения стилевого оформления элемента в случаях, когда поверх него перемещается курсор, для каждого редактируемого элемента, чтобы привлечь внимание пользователей к тому, что контент того элемента можно редактировать. Мы добавим и удалим эти классы при помощи JavaScript, а не CSS. Это делается, главным образом, для устройств или браузеров с отключенным JavaScript. Мы не хотим отправлять им ложные визуальные подсказки.

Шаг 3: При двойном нажатии по редактируемому элементу нам нужно заменить его текстовым полем со старым текстом.

Шаг 4а: Когда пользователь хочет сохранить внесенные изменения, нам необходимо скопировать значение поля в родительский элемент и удалить поле для ввода данных.

Шаг 4b: Или когда пользователь хочет отказаться от внесенных изменений, то нам нужно вернуть старый контент и удалить поле ввода.

Это базовые шаги, которые нужно выполнить для реализации возможности редактирования текста на месте. Естественно, есть еще несколько незначительных моментов, однако я объясню их по мере того, как мы будем продвигаться.

Основной HTML-код

HTML-разметка нашей страницы с демоверсией выглядит следующим образом:

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

Также мы подключили библиотеку jQuery и наш собственный файл с кодом скрипта.

CSS-код

Здесь нет ничего особенного. Просто кучка кода для позиционирования элементов и добавления стилевого оформления.

Обратите особое внимание на классы editHover и noPad. Мы ими воспользуемся совсем скоро.

Код JavaScript

Теперь, когда у нас имеется базовый код разметки и некоторое базовое стилевое оформление, мы можем приступить к написанию кода для реализации необходимых функциональных возможностей. Обязательно обратите внимание на то, что мы будем очень широко использовать jQuery. Конкретней, нам будет необходима как минимум версия 1.3 или более поздняя. Если вы будете использовать любую более раннюю версию, то демоверсия работать не будет.

Добавление классов для изменения стилевого оформления элемента в случаях, когда поверх него перемещается курсор

Hovers

Как было упомянуто ранее, нам необходимо будет добавить светло-голубой фон к редактируемым элементам, чтобы указать, что их можно редактировать. Мы уже создали класс editHover для этого.

При помощи этого небольшого фрагмента кода реализуется эта возможность. Мы используем метод jQuery hover для добавления класса editHover, когда поверх элемента перемещен курсор, и его удаления, когда нет. Мы используем this, чтобы сослаться на конкретный элемент, поверх которого перемещен курсор. Если бы мы воспользовались вместо этого в качестве селектора .editable, то ко всем элементам без исключения был бы добавлен вышеуказанный класс. Так что мы используем this, чтобы получить только тот элемент, который нам необходим.

Смена элементов

Для начала нам необходимо обеспечить то, чтобы наш код выполнялся при двойном нажатии по целевому элементу. Так что мы для начала подключим обработчик для обработки события, возникающего при этом.

Мы привязываем функцию replaceHTML к событию dblclick для редактируемого элемента при помощи того однострочника (* программа, эффект которой значительно больше, чем можно было бы предположить по её размеру). Теперь мы можем перейти к смене элементов.

Давайте пройдемся по нашему коду строчка за строчкой.

Я реализую функциональные возможности в отдельной именованной функции, а не анонимной, по конкретной причине: я буду использовать эту функцию несколько раз. Далее мы сохраняем контент элемента для использования в будущем при помощи метода html jQuery и убираем все кавычки, поскольку из-за этого в конечном счете портится конечный результа.

Теперь, когда наш контент надежно сохранен для дальнейшего использования, мы можем сменить наши элементы. Для начала мы освобождаем элемент li, передавая методу html в качестве аргумента пустую строку. Далее идет кое-какой стандартный HTML-код для добавления поля ввода. Мы добавляем ему некоторые классы для задания его стилевого оформления. Важнее то, что мы устанавливаем в качестве значения его свойства value оригинальный текст, содержащийся в элементе, хранящемся в oldText. Также мы добавляем несколько ссылок для реализации возможности сохранения и отказа от внесенных изменений. Также мы добавили им классы, чтобы их можно было легко получить и добавить для них стилевое оформление.

Как всегда мы используем this для получения элемента, на котором было сгенерировано событие.

Сохранение внесенных изменений

Edited Text

Для начала позвольте мне вам представить метод live jQuery. Вы, вероятно, не часто встречались с ним до этого, так что я вкратце обрисую вам его:

Вы не можете подвязать обработчики к событиям, генерируемым элементами, которых даже не было в DOM, когда страница и JavaScript-код были загружены. Если вы используете обычные функции для привязывания обработчиков, то их код не сработает по вышеуказанной причине. Эта проблема решается при помощи метода live.

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

Давайте теперь взглянем на код. Сначала мы подвязываем код, содержащийся в анонимной функции, к событию click. В этой функции мы сперва сохраняем текст, содержащийся в поле для ввода. Это не так-то легко сделать, поскольку у поля для ввода нет ID. Так что мы для начала получаем элемент для добавления формы, который является сиблингом (* элементы, имеющие общего «родителя») элемента ссылки для сохранения изменений, и затем проходим по дереву, чтобы найти элемент input. Затем мы копируем его значение после того, как удалили все кавычки, которые могут в нем содержаться.

Затем мы получаем родительский элемент ссылки, элемент li, и заменяем его HTML-контент на текст, скопированный нами в предыдущем шаге.

Этот блок кода можно было бы запросто записать в одну строку, однако я разбил его на две строки для улучшения читабельности кода.

Отказ от внесенных изменений

Здесь все так просто, как выглядит. Поскольку пользователь не хочет сохранять изменения, то мы просто заменяем HTML-контент родительского элемента на оригинальный текст, который скопировали ранее в переменную oldText.

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

Привязывание и отвязывание обработчиков

Если вы протестировали наш код на данном этапе, то, вероятно, столкнулись со следующим багом, нарушающим работу системы: когда пользователь дважды нажимает кнопку мыши в появившемся поле для ввода данных, то оно наполняется HTML-контентом системы редактирования. Попробуйте сами. При каждом последующем двойном нажатии в поле для ввода данных добавляется дополнительный фрагмент текста. Эта проблема, вероятно, была бы намного серьезнее, если бы вы выбрали click в качестве события, при возникновении которого запускаются обработчики.

Чтобы это исправить, нам необходимо отвязать обработчик событий лишь для того элемента, на котором возникает событие, и привязать его сразу после того, как пользователь переходит либо по ссылке для сохранения внесенных изменений, либо по ссылке для отказа от них. Давайте теперь это реализуем.

Наши предыдущие блоки кода теперь должны быть отредактированы следующим образом:

Мы отвязываем обработчик для элемента, на котором было сгенерировано событие. У остальных элементов с классом editable по-прежнему имеются их обработчики, и они отреагируют на события.

Далее мы привязываем этот обработчик обратно независимо от того, решает ли пользователь их редактировать или нет. Если мы не подвяжем его заново, то поле можно будет редактировать только один раз. При повторном двойном нажатии по ним, обработчики более не привязаны к событиям. Мы исправляем это за счет привязывания обработчиков обратно к событиям.

Несколько небольших поправок

Последний фрагмент кода предназначен исключительно для того, чтобы улучшить внешний вид нашего эффекта. Если вы заметили, у элементов li заданы небольшие поля, чтобы улучшить внешний вид текста в них. Однако когда текст удаляется и заменяется на текстовое поле, то результат выглядит ужасно и портит наш эффект. Нам необходимо, чтобы текстовое поле занимало точно такое же пространство, как и оригинальный текст. Учитывая это, мы добавляем класс noPad для элемента, когда по нему дважды нажали кнопкой мышки, и убираем снова, когда пользователь сохраняет или отказывается от внесенных изменений.

Мы отвязываем обработчик для элемента, на котором было сгенерировано событие. У остальных элементов с классом editable по-прежнему имеются их обработчики, и они отреагируют на события.

Весь код

Ниже показано, как выглядит весь код:

Неплохо. Пятьдесят необычных строк для добавления некоторых продвинутых возможностей.

Совершенствование демоверсии: серверная часть

Для того чтобы это руководство не было слишком длинным, я рассмотрел реализацию только функциональных возможностей клиентской части. Если бы вы захотели реализовать рассматриваемую здесь систему в своих собственных проектах, то неявно подразумевается, что у вас должна была бы иметься в наличии серверная часть системы для сохранения внесенных изменений и, что более важно, вам нужно было бы использовать AJAX-запрос для выполнения запроса для этого асинхронно.

Добавление этой возможности не должно вызвать трудностей, однако обратите на это внимание. Код выше был написан всего лишь, чтобы проиллюстрировать образец рассматриваемой здесь системы, а не для для того, чтобы использовать его в качестве финальной версии системы. Поэтому я не стал добавлять дополнительные атрибуты ID для элементов и атрибуты name для текстовых полей. В коде вашей финальной версии системы обязательно добавьте их все, так чтобы для атрибута name текстового поля можно было задать осмысленное значение, благодаря чему у серверной части была бы возможность понять, какой фрагмент данных необходимо обновить.

Для добавления AJAX-запроса наш обработчик для сохранения внесенных изменений должен был бы быть обновлен следующим образом:

Помните, что для того чтобы серверная часть как-то понимала то, что вы отправляете, вам необходимы некоторые дополнительные данные помимо обновленного текста, за счет чего приложение понимает, какие данные необходимо редактировать. Вы могли бы запросто отправить более одного фрагмента данных скрипту при необходимости.

Заключение

Вот и все; мы разобрались с тем, как добавить удобную для пользователя возможность в ваши проекты. Надеюсь, что вам было интересно работать с этим руководством и оно оказалось вам полезным. При желании можете повторно использовать этот код где угодно в ваших проектах и присоединиться к обсуждению здесь, если у вас возникнут трудности.

Есть вопросы? Хотите пожелать что-то приятное? Имеются какие-либо критические замечания? Перейдите к разделу с комментариями и оставьте мне комментарий. Удачного вам программирования!

  • Подпишитесь на нас на Twitter или на Nettuts+ RSS Feed, чтобы быть в курсе о новых руководствах и статьях по веб-разработке.


Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.