В этом уроке по Nettuts + мы узнаем, как создать динамическую систему редактирования контента с использованием фабрики виджетов пользовательского интерфейса jQuery. Мы рассмотрим, как разработать логический объектно-ориентированный виджет пользовательского интерфейса jQuery, преобразовать различные узлы в редактируемые текстовые поля, делегировать события в рамках виджета, управлять контекстом, переключать значки, сериализовывать данные и, конечно, редактировать, восстанавливать и удалять данные. используя фантастические функциональные возможности JQuery AJAX!
Создание плана виджета
Первое, что мы сделаем, это создадим план для нашего виджета, который мы назовем «редактируемым» и чье пространство имен будет «ui». Имя виджета будет первым аргументом при вызове метода фабрики виджетов. Второй аргумент будет литералом объекта, содержащим различные свойства и методы для самого виджета. Это очень простой, чистый и эффективный способ создания плагинов. Для виджета пользовательского интерфейса есть ряд присущих ему свойств и методов. Мы будем использовать следующие ванильные реквизиты $.widget
:
-
Параметры{…}
Этот литерал объекта является единственным свойством нашего виджета, которое будет доступно пользователям. Здесь пользователи смогут передавать свои аргументы виджету, который, конечно, переопределяет любые параметры по умолчанию, которые мы указываем. Примеры включают в себя обратные вызовы, селекторы элементов, классы элементов и т. Д.
-
_Создайте()
Это первый метод, вызываемый во время инициализации виджета, и он вызывается только один раз. Это наш метод «установки», в котором мы будем создавать / манипулировать элементами в DOM, а также связывать обработчики событий.
-
_Destroy ()
Этот метод является единственным общедоступным методом нашего виджета, в котором пользователи могут указать «уничтожить» в качестве аргумента для вызова виджета. Этот метод используется для разрушения / уничтожения созданного экземпляра виджета. Например, мы будем использовать команду destroy для удаления любого HTML-кода, сгенерированного нашим виджетом, отмены привязки обработчиков событий и, конечно, для уничтожения экземпляра виджета относительно элемента, для которого он был вызван.
Вот что мы будем использовать:
1
2
3
4
5
6
7
8
|
$.widget(«ui.editable», {
options: {},
_create: function(){},
destroy: function(){}
}
|
Обратите внимание на подчеркивание, которое предшествует методу _create
. Подчеркивания означают закрытый / внутренний метод, который недоступен извне виджета.
Для получения дополнительной информации о разработке виджетов пользовательского интерфейса, а также о других присущих методах, таких как _trigger (), _getData (), _setData (), вы можете проверить следующие полезные ресурсы:
- JQuery UI Widget Factory Разработка Wiki
- Руководство разработчика API jQuery UI
- Советы по разработке виджетов jQuery UI 1.8 от Eric Hynds
- Руководство по обновлению виджета jQuery UI для jQuery 1.8
- Форумы jQuery — отличное сообщение от Ричарда Д. Ворта, руководителя проекта для пользовательского интерфейса jQuery и блестящего разработчика, в котором противопоставляются и объясняются _init и _create , методы и их использование.
Мозговой штурм : какие методы нам нужны? Что нужно сделать нашему виджету?
Поскольку мы создаем виджет редактирования контента, нам, очевидно, потребуется какой-то способ редактирования контента. Кроме того, нам понадобится возможность удалять контент, а также отменять ревизии. Нам также понадобятся триггеры «редактирования», скажем значки, которые при нажатии будут переключать состояние нашего контента, а также состояние между значками по умолчанию и значками редактора. Имея в виду эту функциональность, давайте теперь определим некоторые общие методы:
-
_CreateEditor ()
Как правило, хорошо разделять логику логичным, понятным и понятным способом. Хотя большая часть создания и вставки DOM может выполняться внутри самого метода _create (), поскольку мы будем создавать редакторы для нескольких наборов содержимого (например, строк таблицы), давайте использовать независимый метод, который мы можем вызвать из цикла for! _CreateEditor () будет вызываться для обработки создания и вставки основных элементов редактора. Такое разделение логики должно облегчить понимание виджета, а также помочь нам поддерживать наш код в будущем.
-
_ClickHandler ()
Этот метод говорит сам за себя, это обработчик, который будет использоваться, когда пользователь нажимает на один из наших значков «редактора». Хотя мы можем привязать обработчик к каждому отдельному типу значков, давайте просто воспользуемся одним обработчиком и переключателем регистра для вызова соответствующих методов, основанных на том, какой значок был нажат. Существуют незначительные преимущества и недостатки, связанные с привязкой одного обработчика для всех значков и отдельных обработчиков для каждого значка, так что на самом деле это просто вопрос предпочтений и производительности.
-
_ShowIconSet ()
Этот метод будет использоваться для изменения наших значков из состояния «по умолчанию» в состояние «редактор». Как уже упоминалось выше, нам понадобится возможность редактировать / удалять элемент, а также сохранять / отменять изменения. Нам нужно отображать только две иконки в любой момент времени (редактировать / удалять и сохранять / отменять соответственно), поэтому этот метод переключает наши иконки между этими двумя состояниями.
-
_TransformElements ()
Вот где берется основная логика преобразования элементов туда и обратно из исходного состояния в редактируемые поля и наоборот. Этот метод будет использоваться, когда мы делаем элементы редактируемыми, сохраняем изменения или отменяем изменения. Этот метод также будет отвечать за заполнение / повторное заполнение элемента / ввода соответствующим текстом.
-
_RemoveElements ()
Этот метод будет отвечать за удаление элементов из DOM, когда элемент удаляется пользователем.
-
_Encode ()
Поскольку мы будем сохранять / удалять данные с помощью мощных функций JJuery AJAX, нам понадобится способ преобразовать эти текстовые узлы и сформировать входные данные вместе с соответствующими им «именами полей» в стандартную строку в кодировке URL. Таким образом, этот метод будет обрабатывать сериализацию текстовых / входных значений.
-
_Почта()
Этот метод будет обрабатывать всю нашу логику AJAX. Он будет отвечать как за сохранение, так и за удаление данных, а его обратные вызовы будут использоваться для обновления DOM при необходимости. Кроме того, любые определенные пользователем обратные вызовы AJAX также будут запускаться отсюда.
Вот посмотрите на план нашего виджета до сих пор:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
$.widget(«ui.editable», {
options: {},
_create: function(){},
_createEditor:function(){},
_clickHandler: function(event){},
_showIconSet: function(){},
_transformElements: function(){},
_removeElements: function(){},
_encode: function(){},
_post: function(){},
destroy: function(){}
});
|
Обратите внимание, что большинству наших методов предшествует подчеркивание. Подчеркивание обозначает закрытый метод, который означает, что любое свойство или метод, которому предшествует подчеркивание, не будут доступны извне виджета. Нет нужды делать какие-либо наши методы общедоступными, поэтому мы продолжим их подчеркиванием.
Полный скринкаст
Параметры, параметры и дополнительные параметры!
Теперь давайте определим некоторые изменяемые пользователем опции для нашего виджета! Это всегда забавный шаг, потому что есть множество действительно интересных и изящных вещей, которые можно сделать здесь. Например, создание обратных вызовов. Мы можем создавать необязательные обратные вызовы для почти чего угодно, сохраняя данные, удаляя данные, ошибки, успех, завершение, события и т. Д. Кроме того, мы можем легко определить контекст этих обратных вызовов. Итак, хотите оживить цвет строки после успешного обновления? Нет проблем! Хотите, чтобы каждое поле мигало в быстрой последовательности в качестве визуального подтверждения? Проще простого! Для меня это одна из самых забавных и мощных функций любого виджета. Способность формировать функциональность и интерактивность в соответствии с потребностями пользователей.
Кроме того, мы также определим некоторые важные основные параметры, такие как селектор для тех элементов, которые мы хотим сделать редактируемыми, где мы хотим вставить наши значки, имена пользовательских классов, а также некоторые другие параметры AJAX. Вот посмотрите на наши параметры, которые являются литералом объекта:
1
|
<strong>options: {…}</strong>
|
Некоторые общие параметры
Здесь мы определим некоторые основные параметры для нашего виджета, такие как селекторы элементов, имена классов, имена полей и так далее …
-
Элементы:
Это будет строка селектора для тех элементов, которые мы хотим сделать редактируемыми. Мы будем использовать селектор для элементов ячейки таблицы
"td"
в качестве селектора по умолчанию. Это может быть отменено, хотя. Любая допустимая строка селектора jQuery будет работать. Например:- «тд»
- «тд> маленький»
- «.editable-контент»
- «. editable p»
- «ДИВ: есть (р)»
Для получения дополнительной информации о селекторах jQuery см. API селекторов jQuery.
-
elementParent:
Здесь мы позволим пользователю определить селектор, который будет служить сервером в качестве родительского контейнера для наборов редактируемого контента. Вы могли почти думать об этом как о наборе псевдополей, используемом для группировки входов, или даже в строке таблицы, которая группирует ячейки вместе. Это полезно, если пользователь хочет сделать что-то кроме строк таблицы редактируемыми.
Таким образом, этот селектор очень важен. Мы будем перебирать каждый
elementParent
при создании, добавлении, связывании и кэшировании элементов! Как и в случае со свойствомelements
, любой действительный селектор jQuery будет работать здесь в контексте элемента, для которого был вызван виджет. В качестве значения по умолчанию мы будем использоватьtbody tr
чтобы выбрать все строки таблицы в теле таблицы.Примечание. Если вам интересно, почему мы не указываем родительский контейнер, выполняя что-то вроде этого:
1this.element.parent();Учтите, что непосредственный родительский элемент не может быть общим родительским для всех редактируемых узлов для данной строки / блока. Что если редактируемые узлы вложены в другой элемент? Указывая неявный родительский контейнер, мы знаем, что имеем дело, в частности, с соответствующим контейнером верхнего уровня для всего редактируемого содержимого в данной строке / блоке.
-
insertMethod:
Здесь мы позволим пользователю определить, какой метод вставки jQuery будет использоваться для добавления значков и их контейнера.
insertAfter
должна быть указана правильная строка метода вставки jQuery, напримерappendTo
,prependTo
,insertBefore
илиinsertAfter
. Метод вставки по умолчанию будетappendTo
. -
Классы:
Разрешение пользователю указывать свои собственные / дополнительные имена классов открывает множество новых возможностей, таких как использование CSS-инфраструктуры, такой как jQuery UI CSS Framework, или, возможно, классы иконок из созданного ими спрайта изображения! Здесь пользователь может указать дополнительные имена классов в виде строки для ряда различных элементов. Мы установим некоторые классы по умолчанию для значков, используя классы значков jQuery UI Themeroller. Таким образом,
classes
будут литералом объекта со свойствами следующим образом:- iconContainer: строка, разделенная пробелами, представляющая дополнительные классы для родительского элемента значков
- edit: разделенная пробелами строка, представляющая дополнительные классы для иконки редактирования
- удалить: разделенная пробелами строка, представляющая дополнительные классы для значка удаления
- save: разделенная пробелами строка, представляющая дополнительные классы для значка сохранения
- cancel: строка, разделенная пробелами, представляющая дополнительные классы для значка отмены
- th: разделенная пробелами строка, представляющая дополнительные классы для элемента заголовка таблицы, который будет создан условно
Для получения дополнительной информации о CSS-структуре jQuery UI Themeroller см. API-интерфейс jQuery UI Themeroller, а также jQuery UI Themeroller.
-
: имена полей
Эта опция будет простым массивом, представляющим численно индексированные имена полей содержимого, которое делается редактируемым. Так, например, если редактируемый контент представляет собой поля «фамилия», «имя» и «адрес», мы указали бы имена этих полей в хронологическом порядке, порядке, в котором эти элементы отображаются в DOM, из first to last, [«фамилия», «имя» «адрес»]. Например:
1fieldNames: [«last-name», «first-name», «address»]Мы инициализируем пустой массив как значение по умолчанию.
1fieldNames: [] -
Действие:
Эта опция будет литералом объекта, который используется для указания свойства псевдодействия для наших запросов AJAX. Проще говоря, он будет содержать строки url, в которые будет отправляться
$.ajax
jQuery. Он будет содержать два свойства:-
Редактировать:
Строка URL, используемая при редактировании содержимого.
-
Удалять:
Строка URL, используемая при удалении содержимого.
В качестве значений по умолчанию мы будем использовать свойство
location.href
javascript, которое является URL текущей страницы:1234action : {edit : location.href,remove : location.href} -
-
ajaxType:
Эта строка определяет тип запроса
$.ajax
мы будем использовать. По умолчанию используется методpost
но пользователь может указать что-то еще, если возникнет такая необходимость.
Callbacks
Здесь мы определим несколько пустых функций / заполнителей для пользовательских обратных вызовов AJAX …
-
Создайте:
Этот необязательный обратный вызов будет вызываться в конце метода
_create
в контекстеthis.element
. -
уничтожить:
Этот необязательный предварительный обратный вызов будет вызываться в начале метода
destroy
также в контекстеthis.element
. -
ajaxBefore:
Этот необязательный обратный вызов будет вызван до того, как запрос AJAX начнется в контексте общего родительского объекта редактируемого содержимого. Это может быть использовано для ряда вещей, таких как, например, отображение GIF-файла загрузчика AJAX.
-
ajaxError:
Этот необязательный обратный вызов будет вызван в случае ошибки в запросе AJAX в контексте общего родительского объекта редактируемого содержимого. С помощью этого обратного вызова вы даете пользователю обратную связь, сообщая ему, что его сообщение не завершено.
-
ajaxSuccess:
Этот необязательный обратный вызов будет вызван, опять же, в контексте общего родительского объекта редактируемого содержимого, если есть успешный запрос вызова AJAX. Это, как указано выше, может использоваться для ряда различных вещей, таких как уведомление пользователя о том, что запрос был успешным.
-
ajaxComplete:
Этот необязательный обратный вызов будет вызван, когда запрос AJAX будет завершен — независимо от успеха или ошибки также в контексте общего родительского объекта редактируемого содержимого. Это может, например, использоваться для удаления GIF-файла загрузчика AJAX, означающего, что запрос завершен.
Давайте посмотрим на виджет сейчас, когда мы определили наши параметры:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
|
$.widget(«ui.editable», {
options: {
elements : «TD»,
elementParent : «TBODY TR»,
insertMethod : «appendTo»,
classes : {
iconContainer : «»,
edit : «ui-icon ui-icon-pencil»,
remove : «ui-icon ui-icon-closethick»,
save : «ui-icon ui-icon-check»,
cancel : «ui-icon ui-icon-arrowreturnthick-1-w»,
th: «»
},
fieldNames : [],
ajaxType : «post»,
action : {
edit : location.href,
remove : location.href
},
create : null,
destroy : null,
ajaxBefore : null,
ajaxError : null,
ajaxSuccess : null,
ajaxComplete : null
},
_create: function(){},
_createEditor:function(){},
_clickHandler: function(event){},
_showIconSet: function(){},
_transformElements: function(){},
_removeElements: function(){},
_encode: function(){},
_post: function(){},
destroy(){}
});
|
Создание, добавление, связывание и кэширование с помощью метода _Create!
Определив план нашего виджета, а также его параметры, нашим следующим шагом будет создание самого виджета! Этот метод вызывается только один раз, при инициализации виджетов.
В методе _create
мы сначала определим количество внутренних реквизитов (читай: свойства), которые будут использоваться позже в виджете. По сути, мы будем кэшировать селекторы и логические значения, а также определять имена классов и тому подобное. Затем мы перейдем к созданию, вставке и кэшированию элементов, а также добавлению классов и привязке обработчика событий.
1
|
<strong>_create: function(){}</strong>
|
Определение некоторых свойств
Как упоминалось выше, первым шагом в _create
будет определение некоторых свойств. Давайте рассмотрим их по одному:
-
this._element:
Это свойство будет селектором jQuery, представляющим элемент, который использовался для создания экземпляра виджета.
1this._element = $(this.element), -
этот стол:
Это логическое свойство будет использовать троичный оператор, чтобы определить, является ли
this._element
таблицей. Если это свойство имеет значение true, позже мы создадим элемент заголовка таблицы, чтобы количество столбцов вthead
иtbody
соответствовало.Для получения дополнительной информации о троичных / условных операторах см. Сеть разработчиков Mozilla или MDN.
1this._table = (this._element.is(‘table’) ? true : false);Примечание. Вместо использования троичного здесь мы могли бы просто использовать выражение «this._element.is (‘table’)», так как оно возвращает логическое значение. Здесь лучше просто кэшировать логическое значение, а не повторно вызывать метод
is
. Это также намного более читабельно. -
this._elementParent:
Используя строку селектора jQuery из аргумента options, мы будем кэшировать селектор jQuery для общего родительского элемента редактируемого содержимого в контексте
this._element
1this._elementParent = $(this.options.elementParent, this._element), -
this._editable:
Здесь мы инициализируем пустой массив, который вскоре будет заполнен коллекциями jQuery редактируемого содержимого относительно индекса их родительского контейнера. Ключ массива будет напрямую соответствовать индексу родительского элемента. Другими словами,
_editable[0]
будет коллекцией jQuery всего редактируемого содержимого в_elementParent[0]
. Это отличный / быстрый способ кэширования редактируемых коллекций для последующего использования.1this._editable = [], -
this._triggers:
Это будет литерал объекта, содержащий классы «action» для наших значков редактора. Я называю их классами действий, поскольку эти классы будут использоваться для определения того, какое действие следует предпринять в нашем обработчике событий.
При определении этих классов мы будем использовать другое свойство, предоставляемое каркасом виджета,
this.widgetBaseClass
. Это свойство всегда возвращает базовый класс для виджета, который в этом случае будетui-editable
.Итак, по сути, мы будем объединять
widgetBaseClass
с соответствующими именами классов для каждого из наших значков. Эти триггерные классы не зависят от любых других классов, которые могут иметь значки. Хотя они могут использоваться для стилизации значков с помощью css, они в основном используются в нашем обработчике событий.Для получения дополнительной информации о конкатенации строк см. Mozilla Develops Network.
123456this._triggers = {edit : this.widgetBaseClass + «-edit»,remove : this.widgetBaseClass + «-remove»,save : this.widgetBaseClass + «-save»,cancel : this.widgetBaseClass + «-cancel»}, -
this._classes:
В отличие от свойства
_triggers
приведенного выше,this._classes
также будет объектным литералом имен классов. Разница здесь в том, что_classes
будет содержать объединение предопределенных и определенных пользователем имен классов.Используя тернарный оператор, мы будем объединять базовые классы с любыми необязательными классами, указанными в
options.classes
.123456789this._classes = {editable : this.widgetBaseClass + ‘-element’,iconContainer : this.widgetBaseClass + «-icons» + (this.options.classes.iconContainer ? » » + this.options.classes.iconContainer : «»),tableHeader : this.widgetBaseClass + «-header» + (this.options.classes.th ? » » + this.options.classes.th : «»),edit : this._triggers.edit + (this.options.classes.edit ? » » + this.options.classes.edit : «»),remove : this._triggers.remove + (this.options.classes.remove ? » » + this.options.classes.remove : «»),save : this._triggers.save + (this.options.classes.save ? » » + this.options.classes.save : «»),cancel : this._triggers.cancel + (this.options.classes.cancel ? » » + this.options.classes.cancel : «»)},
Добавление классов в редактируемый контент
Теперь, когда мы определили ряд свойств, мы готовы добавить соответствующий класс в наш редактируемый контент.
Этот шаг настолько прост, насколько простым может быть. Мы будем использовать селектор jQuery для всего редактируемого контента в контексте this._elementParent
. Мы определим селектор со строкой, данной нам в аргументе options.elements
. Затем, используя метод addClass
jQuery, мы добавим имя класса, которое мы кэшировали недавно в объекте _classes
.
-
1$(this.options.elements, this._elementParent).addClass(this._classes.editable);
Для получения дополнительной информации о методе addClass
в jQuery см. API jQuery.
Создание нашего редактора и привязка прочь!
Иконки и их контейнеры будут создаваться, когда мы перебираем нашу коллекцию _elementParent
.
Другими словами, каждый _elementParent
будет иметь свой собственный набор иконок.
Мы также кешируем селекторы, в контексте, для этих значков, их контейнера и редактируемого содержимого относительно текущего _elementParent
в цикле.
-
Несколько переменных для цикла
Перед тем как стать циклом
for(){...}
, мы инициализируем переменную для начального выражения, то есть итератор, который увеличивает цикл. Затем мы определим целое число, представляющее, сколько элементов кэшируется в коллекции_elementParent
, используя методsize
jQuery.1var i, total = this._elementParent.size();Для получения дополнительной информации о заявлениях см. Сеть разработчиков Mozilla.
Для документации методаsize
jQuery см. API jQuery -
Кэширование и создание иконок и их контейнера:
Здесь мы будем
_iconContainer
пустой массив_iconContainer
, присваивая ему возвращаемое значение метода_createEditor
в качестве нового реквизита,i
Как вы увидите, на мгновение_createEditor
вернет селектор jQuery для вновь созданного контейнера значков.Таким образом, поскольку
i
равен индексу текущего_elementParent
в нашем цикле,_iconContainer[i]
будет контейнером для наших значков только внутри_elementParent[i]
!При выполнении итерации мы будем использовать итератор,
i
в качестве ключа массива для нескольких коллекций jQuery, включая массив_icons
массив_icons
а также массив_iconContainer
.1this._iconContainer[i] = this._createEditor(i);Примечание. Ключи массива для
_editable
,_iconContainer
и_icons
всегда будут соответствовать индексу_elementParent
в текущей итерации циклаfor
. -
Кэширование редактируемого селектора в контексте
_iconContainer
массиву_iconContainer
, теперь мы будем кэшировать селектор для всего редактируемого содержимого в контексте_elementParent[i]
.Мы определим строку селектора редактируемого содержимого путем объединения a
.
с соответствующим именем класса, хранящимся в нашей_classes.editable
prop.1this._editable[i] = $(‘.’ + this._classes.editable, this._elementParent[i]); -
Привязка обработчика событий к нашим иконкам
Последнее, что мы сделаем в нашем цикле
for
— это привязка обработчика к событию click наших вновь созданных значков. Так как мы связывали обработчик в контексте виджета / объекта пользовательского интерфейса jQuery, нам необходимо обратить особое внимание, поскольку контекстthis
в типичном обработчике событий jQuery относится к элементу, который получил событие. Это одна из самых приятных функций jQuery, поскольку она стандартизирует то, что происходит во всех браузерах. (Я смотрю на тебя IE;)Итак, вот два простых подхода к обработке контекста в обработчике события виджета.
-
event.data
Прежде всего, мы можем просто передать этот экземпляр нашего виджета обработчику в качестве аргумента
event.data
который предоставляется некоторыми из различных методовbind
типа jQuery. По сути, второй аргумент, который обрабатывает вызов функции, может быть литералом объекта данных, которые мы хотим передать обработчику. В обработчике эти данные доступны в объектеevent
как свойствоevent.data
! Вот как это выглядит:1this._icons[i].bind(‘click’, {widget:this, i:i}, this._clickHandler);Таким образом,
event.data.widget
будет ссылкой на наш экземпляр виджета, аevent.data.i
будет ссылкой на наш итератор!Передача аргумента event.data — это здорово, если вы не хотите изменять контекст
this
в своем обработчике. Кроме того, он не требует другого вызова функции, как следующий метод,$.proxy
. -
$ .Proxy ()
Как указано в jQuery API, «этот метод наиболее полезен для присоединения обработчиков событий к элементу, контекст которого указывает на другой объект».
Другими словами, передавая наш виджет обработчику,
this
будет ссылаться на наш экземпляр виджета, а не на элемент, который получил событие.Даже если целевой элемент больше не будет назначен
this
, он все равно будет доступен в объектеevent
jQuery как свойствоevent.target
. Поскольку многие разработчики уже имеют привычку кэшировать селектор для$(this)
в обработчиках событий, было бы не слишком сложно кешировать селектор$(event.target)
вместо этого.Без лишних слов, вот метод $ .proxy в действии:
1this._icons[i].bind(‘click’, $.proxy(this, this._clickHandler);
-
-
Привязка обработчика с
event.data
аргументаevent.data
С пониманием как
event.data
и$.proxy
, давайте использовать аргументevent.data
для передачи нашего виджета и итератора в обработчик.1this._icons[i].bind(‘click’, {widget:this, i:i}, this._clickHandler);
Давайте теперь посмотрим на логику нашего цикла for
:
01
02
03
04
05
06
07
08
09
10
11
12
|
var i, total = this._elementParent.size();
for(i=0; i<total; i++){
this._iconContainer[i] = this._createEditor(i);
this._editable[i] = $(‘.’ + this._classes.editable, this._elementParent[i]);
this._icons[i].bind(‘click’, {widget:this, i:i}, this._clickHandler);
};
|
Как насчет заголовков таблицы?
С иконками, созданными, вставленными и связанными, нам нужно сделать небольшую корректировку, если this.element
является таблицей.
Хотя мы еще не определили метод _createEditor
, тип _createEditor
элемента контейнера значков соответствует this.element
.
Таким образом, если вы работаете за столом, он создаст td
и добавит его в таблицу. Если бы работал любой другой тип элемента, он создаст div
.
Таким образом, добавление еще одного td
к строке таблицы оставляет нам неполный заголовок таблицы, поскольку в теле будет больше ячеек таблиц, чем в заголовке таблицы.
Итак, нам нужно проверить, является ли this.element
таблицей или нет, и если это так, мы создадим, insertMethod
и insertMethod
, используя insertMethod
указанный в аргументе options
, элемент th
. Хотя создание DOM-элементов с помощью jQuery простое и чистое, мне иногда нравится писать его в простом javascript. Давайте посмотрим на логику:
-
Проверка для таблицы
Сначала мы проверим наше свойство
table
которое, как вы помните, является логическим значением, представляющим, является лиthis.element
таблицей.123if(this._table){} -
Это таблица, создайте заголовок!
Если
this.element
является таблицей, нам нужно создать и добавить новыйth
в первую и, надеюсь, единственную строку таблицы, вот как мы это сделаем:-
Создание заголовка таблицы
Если
this.element
является таблицей, мы создадим новый элементth
в качестве переменнойth
.123if(this._table){var th = document.createElement(‘th’);} -
Давать ему некоторый класс!
Далее мы установим свойство
className
для этого элемента какtableHeader
классаtableHeader
указанное в объекте_classes
.1234if(this._table){var th = document.createElement(‘th’);th.className = this._classes.tableHeader;} -
Установка
innerHTML
заголовка таблицыЗатем мы установим
innerHtml
, который в данном случае является просто текстом, этого элемента.12345if(this._table){var th = document.createElement(‘th’);th.className = this._classes.tableHeader;th.innerHTML = «Edit»;} -
Как насчет небольшого
style
?Мы определим одно правило CSS,
text-align
какcenter
. Это отцентрирует текст заголовка и выглядит хорошо, так как сами значки также будут центрированы через css.123456if(this._table){var th = document.createElement(‘th’);th.className = this._classes.tableHeader;th.innerHTML = «Edit»;th.style.textAlign = «center»;} -
Присоединение заголовка таблицы к заголовку таблицы
Наконец, используя jQuery insertMethod, указанный пользователем, мы динамически вставим элемент в заголовок таблицы нашей таблицы. Обратите внимание на нашу вставку DOM:
12345678if(this._table){var th = document.createElement(‘th’);th.className = this._classes.tableHeader;th.innerHTML = «Edit»;th.style.textAlign = «center»;$(th)[this.options.insertMethod](‘thead tr:first’, this._element)}Вы заметили, что у нас есть метод вставки в квадратных скобках сразу после селектора jQuery?
Вам может быть интересно, что это такое и как это работает. По сути, думайте о jQuery как об одном большом (удивительном) объекте. В качестве объекта вы можете использовать ассоциативную нотацию с массивом / квадратной скобкой! Этот сокращенный вариант дает нам большую гибкость в динамическом вызове методов в зависимости от условий!
-
Как насчет обратного звонка!
Последнее, что мы сделаем в методе _create
это вызов определяемого пользователем обратного вызова create
если он был указан.
Существует множество причин для использования обратного вызова в методе _cerate. Вот один пример!
Допустим, пользователь с обратным вызовом об успешном изменении цвета ячеек таблицы отражает успешное обновление. Если виджет будет уничтожен, им понадобится способ восстановить цвет ячеек таблицы. Конечно, они могли бы неявно установить цвет вручную в обратном вызове destroy, но как насчет сохранения цвета ячейки таблицы с помощью метода $.data
jQuery, который является гораздо более динамичным подходом! Эти данные будут прикреплены к этому this.element
как это будет контекстом нашего обратного вызова.
1
2
3
4
5
6
|
create: function(){
var color = $(«td», this).css(«color»);
$.data(this, «color», color);
}
|
Таким образом, когда виджет уничтожен, пользователь может просто установить цвет обратно к значению по умолчанию, открыв соответствующий $ .data
1
2
3
4
5
6
|
destroy: function(){
var color = $.data(this, «color»);
$(«td», this).css(«color», color);
}
|
Объяснения виджетов
Поскольку определяемые пользователем обратные вызовы являются необязательными, их значения по умолчанию всегда будут равны null
.
Таким образом, мы будем использовать метод isFunction
jQuery, чтобы определить, является ли тип обратного вызова function
а затем вызвать его, если это так.
В качестве альтернативы, мы могли бы использовать собственный оператор typeof
javascript, чтобы определить, является ли обратный вызов typeof
функцией. Мы должны были бы заключить оператор typeof
в parens, чтобы мы могли взять его возвращаемое значение и преобразовать его в нижний регистр, используя собственный метод toLowerCase
javascript, чтобы стандартизировать вывод. Тем не менее, гораздо проще использовать метод isFunction
jQuery, но мы рассмотрим эту технику в vanilla javascript:
-
1if((typeof this.options.create).toLowerCase() === «function»){…}
Вот как мы сделаем это с помощью jQuery:
1
|
if($.isFunction(this.options.create)) this.options.create.call(this.element);
|
Итак, если обратный вызов является функцией, мы выполним ее, используя собственный метод call
javascript.
Метод call
позволяет нам определять контекст наших обратных вызовов. Другими словами, он будет определять, к чему this
относится в функции обратного вызова.
Таким образом, мы будем использовать this.element
в качестве контекста, который определит this
как элемент, для которого был создан наш виджет.
Внутри метода _createEditor
В предыдущем разделе мы обнаружили логику того, как мы будем создавать элементы. Теперь давайте посмотрим на реализацию. Метод _createEditor
будет вызываться изнутри методов _create
for
цикла, чтобы выполнить все создание и вставку элемента относительно индекса текущего _elementParent
в цикле.
1
|
<strong>_createEditor: function(i){}</strong>
|
аргументы
Метод _createEditor
принимает один аргумент i
, который равен индексу текущего _elementParent
из методов _create
for
цикла.
Инициализация нескольких переменных
Первое, что мы сделаем здесь, это инициализируем несколько переменных, которые мы будем использовать при создании нашего элемента. Мы инициализируем переменные для значка редактирования, а также для значка удаления.
1
|
var edit, remove;
|
Создание наших иконок
С этими инициализированными переменными давайте продолжим и создадим наши иконки, используя простой JavaScript! По сути, мы будем использовать те же методы, что и для условного заголовка таблицы, но с одним исключением. Вместо того, чтобы устанавливать innerHtml
ссылки, которую мы создаем, мы вместо этого установим атрибут title. Таким образом, при наведении курсора на пользователя мы увидим описание всплывающей подсказки о том, что делает иконка! Вот посмотрите на наше создание якоря / иконки:
1
2
3
4
5
6
7
|
edit = document.createElement(‘a’);
edit.className = this._classes.edit;
edit.title = ‘Edit’;
remove = document.createElement(‘a’);
remove.className = this._classes.remove;
remove.title = ‘Remove’;
|
Создание контейнера значков
Когда значки готовы к работе, нам нужно создать для них контейнер. Тип элемента этого контейнера будет зависеть от того, работаем мы с таблицей или нет. Таким образом, используя логическое значение _table
мы определили в методе _create
и троичный оператор, мы создадим элемент td
если будем работать с элементом table и div
если мы будем работать с чем-то еще. Затем мы установим className
контейнера, используя класс _iconContainer
мы определили в объекте _classes
.
1
2
|
_iconContainer[i] = document.createElement( (this._table) ? ‘td’ : ‘div’);
_iconContainer[i].className = this._classes.iconContainer;
|
Кэширование селектора для наших иконок
Теперь мы начнем _icons
массив _icons
селектором jQuery для вновь создаваемых значков, мы передадим эти значки в виде массива.
Ключом массива для этой коллекции будет i
, поэтому _icons[i]
будет представлять все значки, содержащиеся в _elementParent[i]
.
1
|
this._icons[i] = $([edit,remove]);
|
Возврат контейнера значков после установки его HTML и добавления его в DOM
Теперь мы скомпонуем несколько методов jQuery вместе, чтобы установить HTML _iconContainer[i]
и добавить его в DOM.
Во-первых, используя html
метод jQuery , мы установим html _iconContainer[i]
для this._icons[i]
.
Затем, добавив к значкам наши значки _iconContainer[i]
, мы динамически добавим их в DOM, используя options.insertMethod
строку в квадратных скобках / ассоциативный массив.
Наконец, так как большинство методов jQuery используют return
фактический селектор jQuery, используемый в самом выражении, это выражение будет return
$(iconContainer[i])
.
Таким образом, то, this._iconContainer[i]
что определяется в цикле _create
метода for
, будет равно $(iconContainer[i])
.
1
|
return $(_iconContainer[i]).html( this ._icons[i])[ this .options.insertMethod]( this ._elementParent[i]); |
Для получения дополнительной информации о возврате значений из функции, проверьте Сеть разработчиков Mozilla
Документацию по методу jQuery html можно найти в API jQuery.
Обработчик событий нашего виджета, метод _ClickHandler
Теперь, когда наш виджет создан и готов к работе, пришло время справиться с его поведением. Логика этого виджета такова, что обработчик щелчков будет служить своего рода «контроллером» в том смысле, что он будет определять, какое действие необходимо предпринять, основываясь на классе значка, получившего щелчок.
Другими словами, если пользователи щелкают значок редактирования, обработчик проверяет класс значков, а затем вызывает соответствующие функции редактирования виджета и т. Д.
1
|
<strong>_clickHandler: function (event){}</strong> |
аргументы
_clickHandler
Метод принимает один аргумент, event
. Указав здесь пустой аргумент, jQuery автоматически назначит event
объект этому аргументу. Объект события содержит ряд очень полезных свойств , таких как target
, timeStamp
, preventDefault
и , stopPropagation
чтобы назвать несколько. Мы будем использовать пару таких методов / методов в нашем обработчике событий.
Предотвращение поведения по умолчанию
Первое, что мы сделаем в нашем обработчике событий, это вызов preventDefault
метода event
объекта jQuery . Этот метод предотвратит любые действия по умолчанию в результате события. Для нас это означает, что когда пользователь нажимает на один из значков, который на самом деле является якорем, preventDefault
остановит запуск любого типа навигации / прокрутки — довольно изящно, а?
1
|
event.preventDefault();
|
Определение нескольких переменных
Сначала мы кэшируем селектор jQuery для this
, который, конечно, является элементом, который получил событие.
Далее мы определим переменную, i
которая была передана нашему обработчику в event.data
Это был итератор, используемый в цикле _create
метода for
для кэширования селекторов для различных элементов относительно _elementParent[i]
.
Затем мы определим переменную widget
, присвоив evet.data.widget
ей ссылку на текущий экземпляр нашего виджета.
Теперь мы определим своего рода переменную быстрого доступаtriggers
как widget._triggers
свойство. Это свойство содержит все классы триггеров наших значков, которые мы будем использовать, чтобы определить, какие действия предпринять.
Наконец, мы инициализируем переменные, data
и inputs
. Эти переменные будут использоваться только тогда, когда нам нужно сериализовать данные для запросов AJAX.
1
2
3
4
5
|
var target = $( this ), i = event.data.i, widget = event.data.widget, triggers = widget._triggers, data, inputs; |
Определение того, что делать с переключателем дела
Оператор switch
очень похож на if
оператор в том, что он вычисляет выражение и выполняет определенный код, только если выполняется условие. В некоторых случаях он может быть чище / легче для чтения. Тем не менее, у каждого утверждения есть свои преимущества и недостатки, но оно будет уместным при соблюдении надлежащих условий.
Мы будем оценивать четыре условия на основе switch
метки операторов, которую мы установим как true
. Мы собираемся проверить класс иконки, используя hasClass
метод jQuery, который возвращает a boolean
. Если значок имеет имя класса, указанное в аргументе, он будет return true
.
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
|
switch ( true ){ case (target.hasClass(triggers.edit)): break;
case (target.hasClass(triggers.remove)): break;
case (target.hasClass(triggers.save)): break;
case (target.hasClass(triggers.cancel)): break;
default:
break;
};
|
Как вы можете видеть, это простой и понятный способ оценить, какая иконка была нажата. Очевидно, что есть несколько разных способов сделать это, и if
заявление будет работать так же хорошо. Теперь давайте подробнее рассмотрим каждый случай и то, что мы будем делать!
-
Иконка Редактировать
Если щелкнуть по значку редактирования, нам нужно, во-первых, переключить значки по умолчанию («Редактировать» и «Удалить») на значки редактора «Сохранить» и «Отмена». Итак, мы будем называть
_showIconSet
метод.Вы можете вспомнить этот метод из проекта виджета, который мы создали ранее. Хотя мы еще не определили его, он принимает два аргумента,
i
которые будут использоваться для выбора значков, которые мы будем переключать иeditor
. Вeditor
аргумент определяет , какие IconSet , чтобы показать, по умолчанию или редактора.Как только мы определили больше методов нашего виджета, вы увидите, что большинство из них попадают в соответствие с jQuery, как обычно
return this
. В результате мы объединяем большинство этих методов вместе. Итак, давайте добавим еще один метод к этому выражениюtransformElements
.transformElements
это своего рода рабочая лошадка в том смысле, что она отвечает за то, чтобы сделать контент редактируемым, восстановить его в прежнее состояние, а также обновить отредактированный контент. Этот метод также принимает два аргумента,i
которые, опять же, мы будем использовать для выбора соответствующей_editable
коллекции, и i,type
который будет определять тип «преобразования». Вот посмотрите:123case
(target.hasClass(triggers.edit)):
widget._showIconSet(i,
"editor"
)._transformElements(i,
"edit"
);
break; -
Значок «Удалить»
Если щелкнуть значок удаления, нам нужно удалить этот редактируемый контент как из DOM, так и из базы данных.
Мы, конечно, будем использовать AJAX-запрос для удаления этого элемента из базы данных, но, поскольку мы не отправляем здесь форму и у нас нет никаких входных данных, которые автоматически сериализуются при отправке, нам потребуется способ сериализации / кодирования текста этих элементов в допустимую строку URL.
Итак, мы вызовем
_encode
метод нашего виджета для сериализации этих данных. Мы передадим один аргумент_encode
селектору jQuery для удаляемых элементов._encode
будет сериализовать текст этих элементов для нас и вернет правильную строку URL. Итак, мы определим переменнуюdata
как это значение.Наконец, мы вызовем
_post
метод нашего виджета, который отправит запрос AJAX на сервер. Мы передадим три аргумента_post
, сериализованные данные, переменную, которая указывает, сохраняем ли мы или удаляем данные, иi
которая будет использоваться в$.ajax
обратном вызове успеха для фактического удаления удаленных элементов из DOM.1234case
(target.hasClass(triggers.remove)):
data = widget._encode(widget._editable[i]);
widget._post(data,
"remove"
, i)
break; -
Иконка Сохранить
Если щелкнуть значок сохранения, нам нужно будет сериализовать наши входные данные, как мы делали выше, используя
_serialize
метод. Затем нам нужно вызвать метод post нашего виджета, чтобы отправить запрос AJAX на сервер.Таким образом, мы определим две переменные здесь,
inputs
иdata
.inputs
будет определен как набор входных данных jQuery в контексте этого элемента иdata
будетreturn
значением_encode
метода, как указано выше.Наконец, мы вызовем
_post
метод с его тремя аргументами: сериализованнымdata
, типом поста, который мы создаем (в данном случае «save») иi
который используется в$.ajax
обратном вызове success для обновления соответствующих элементов в DOM.12345case
(target.hasClass(triggers.save)):
inputs = $(
'input'
, widget._editable[i]);
data = widget._encode(inputs);
widget._post(data,
"save"
, i)
break; -
Иконка Отмена
Наконец, если щелкнуть значок отмены, мы вернем значки и редактируемый контент в состояние по умолчанию.
Для этого мы сначала вызовем
_showIconSet
метод с двумя аргументами,i
иdefault
.i
будет использоваться, чтобы выбрать соответствующую коллекцию из нашего_icons
массива иdefault
указать, какой значок установить для отображения.Далее мы будем связывать
_transformElements
метод с этим выражением одним аргументом,i
который, как обычно, используется для выбора соответствующей коллекции из нашего_editable
массива.123case
(target.hasClass(triggers.cancel)):
widget._showIconSet(i,
"default"
)._transformElements(i,
"restore"
);
break;Примечание. Если вы не совсем уверены в том, что происходит в вызываемых нами методах, это нормально. Мы еще не определили эти методы, поэтому нет причин, по которым вы действительно должны понимать. Держитесь крепко, мы скоро определим эти методы.
-
Заявление о полном переключении
0102030405060708091011121314151617181920212223switch
(
true
){
case
(target.hasClass(triggers.edit)):
widget._showIconSet(i,
"editor"
)._transformElements(i,
"edit"
);
break;case
(target.hasClass(triggers.remove)):
data = widget._encode(widget._editable[i]);
widget._post(data,
"remove"
, i);
break;case
(target.hasClass(triggers.save)):
inputs = $(
'input'
, widget._editable[i]);
data = widget._encode(inputs);
widget._post(data,
"save"
, i);
break;case
(target.hasClass(triggers.cancel)):
widget._showIconSet(i,
"default"
)._transformElements(i,
"restore"
);
break;default:break;}
Это все за клик!
Вот как _clickHandler
выглядит завершенный метод теперь, когда мы его определили:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
_clickHandler: function (event){ event.preventDefault();
var target = $( this ), i = event.data.i, widget = event.data.widget, triggers = widget._triggers, data, inputs; switch ( true ){ case (target.hasClass(triggers.edit)): widget._showIconSet(i, "editor" )._transformElements(i, "edit" ); break;
case (target.hasClass(triggers.remove)): data = widget._encode(widget._editable[i]); widget._post(data, "remove" , i); break;
case (target.hasClass(triggers.save)): inputs = $( 'input' , widget._editable[i]); data = widget._encode(inputs); widget._post(data, "save" , i); break;
case (target.hasClass(triggers.cancel)): widget._showIconSet(i, "default" )._transformElements(i, "restore" ); break;
default:
break;
}
}
|
Переключение иконок туда и сюда!
В нашем обработчике событий мы вызываем _showIconSet
метод всякий раз, когда нам нужно переключить состояние значка между редактором и значением по умолчанию. Это метод, ответственный за внесение этих изменений.
_showIconSet
Метод, шаг за шагом!
Используя удивительные возможности jQuery для создания цепочек, давайте посмотрим, как мы можем изменить состояние значка с помощью одной переменной и оператора!
-
Вар Титлы
Прежде всего, собирались определить новую переменную,
titles
как массив, используя троичный оператор.Эта переменная будет содержать атрибуты заголовка для наших значков.
Мы проверим
iconSet
аргумент, чтобы определить, какие значки мы отображаем, и соответствующим образом заполним массив соответствующими заголовками.1var
titles = (iconSet ===
"default"
) ? [
'Edit'
,
'Remove'
] : [
'Save'
,
'Cancel'
];
-
this._icons [я]
Теперь, используя,
i
мы выберем соответствующую коллекцию элементов из нашего_icons
массива.123var
titles = (iconSet ===
"default"
) ? [
'Edit'
,
'Remove'
] : [
'Save'
,
'Cancel'
];
this
._icons[i]
-
Уравнение (0)
eq
Метод используется в качестве фильтра против коллекции JQuery в том , что он возвращает элемент с указанным индексом. Таким образом, вызовeq(0)
в контексте_icons[i]
метода сузит наш выбор до иконки с индексом 0 в этой коллекции. Другими словами, первая иконка.123var
titles = (iconSet ===
"default"
) ? [
'Edit'
,
'Remove'
] : [
'Save'
,
'Cancel'
];
this
._icons[i].eq(0)
Для получения дополнительной информации о
eq
методе jQuery, проверьте API jQuery. -
toggleClass ()
Используя
toggleClass
метод jQuery , мы добавим и удалим классы для наших иконок соответственно. Таким образом, если указанный класс присутствует, он будет удален. И наоборот, если указанный класс отсутствует, он будет добавлен.Мы объединяем соответствующие классы для каждого значка с пробелом, так как
toggleClass
метод принимает несколько имен классов в виде списка, разделенного пробелами. Довольно изящно!1234var
titles = (iconSet ===
"default"
) ? [
'Edit'
,
'Remove'
] : [
'Save'
,
'Cancel'
];
this
._icons[i].eq(0)
.toggleClass(
this
._classes.edit +
' '
+
this
._classes.save)
Документацию по
toggleClass
методу jQuery можно найти в jQuery API. -
Attr (‘title’, Titles [0])
Теперь, когда классы нашего первого значка установлены, мы определим его атрибут title с помощью
attr
метода jQuery . Мы установим заголовок, используя соответствующее значение, хранящееся вtitle
массиве, который мы создали всего минуту назад. Ключи массива дляtitle
массива соответствуют индексу иконки, выбранной в данный момент, поэтому заголовок для иконки доступен какtitles[0]
.12345var
titles = (iconSet ===
"default"
) ? [
'Edit'
,
'Remove'
] : [
'Save'
,
'Cancel'
];
this
._icons[i].eq(0)
.toggleClass(
this
._classes.edit +
' '
+
this
._classes.save)
.attr(
'title'
, titles[0])
Чтобы прочитать о
attr
методе jQuery , проверьте API jQuery -
Конец()
end
Метод jQuery используется для удаления самого последнего фильтра, примененного к коллекции. Позвонивend
сюда, мы удалимeq
фильтр из нашей коллекции. Другими словами, мы будем работать с_icons[i] again.
123456var
titles = (iconSet ===
"default"
) ? [
'Edit'
,
'Remove'
] : [
'Save'
,
'Cancel'
];
this
._icons[i].eq(0)
.toggleClass(
this
._classes.edit +
' '
+
this
._classes.save)
.attr(
'title'
, titles[0])
.end()
Документацию по
end
методу jQuery можно найти в jQuery API. -
… следующий стих такой же, как первый!
Мы снова будем использовать метод eQ jQuery, чтобы указать второй значок. Второй значок будет иметь индекс, равный единице, поскольку индикаторы начинаются с нуля, и поэтому мы будем использовать его
eq(1)
для выбора.После набора с приведенным выше выражением мы будем использовать те же методы для второго значка, что и для первого, но с соответствующими именами классов и заголовками.
12345678var
titles = (iconSet ===
"default"
) ? [
'Edit'
,
'Remove'
] : [
'Save'
,
'Cancel'
];
this
._icons[i].eq(0)
.toggleClass(
this
._classes.edit +
' '
+
this
._classes.save)
.attr(
'title'
, titles[0])
.end().eq(1)
.toggleClass(
this
._classes.remove +
' '
+
this
._classes.cancel)
.attr(
'title'
, titles[1]);
-
Верните это
Последнее, что мы сделаем здесь, это
return this
чтобы не нарушать цепочку методов.01020304050607080910var
titles = (iconSet ===
"default"
) ? [
'Edit'
,
'Remove'
] : [
'Save'
,
'Cancel'
];
this
._icons[i].eq(0)
.toggleClass(
this
._classes.edit +
' '
+
this
._classes.save)
.attr(
'title'
, titles[0])
.end().eq(1)
.toggleClass(
this
._classes.remove +
' '
+
this
._classes.cancel)
.attr(
'title'
, titles[1]);
return this;
Вуаля!
Теперь, когда мы определили нашу переменную и выражение, давайте теперь посмотрим на весь _showIconSet
метод:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
_showIconSet: function (i, iconSet){ var titles = (iconSet === "default" ) ? [ 'Edit' , 'Remove' ] : [ 'Save' , 'Cancel' ]; this ._icons[i].eq(0) .toggleClass( this ._classes.edit + ' ' + this ._classes.save) .attr( 'title' , titles[0]) .end().eq(1) .toggleClass( this ._classes.remove + ' ' + this ._classes.cancel) .attr( 'title' , titles[1]) return this;
},
|
_transformElements
: Метод рабочей лошадки!
В этом методе мы будем перебирать редактируемый контент, чтобы получить / установить соответствующую строку text / html для этого элемента относительно типа преобразования, которое мы делаем. Затем мы просто установим html элемента.
После цикла, как обычно, мы будем return this
!
аргументы
Этот метод принимает два аргумента i
и type
.
i
, Будет использоваться , чтобы выбрать соответствующую коллекцию JQuery из _editable
массива относительно _iconContainer[i]
от _create
метода.
type
Аргумент просто определяет тип преобразования , который вызывается. Этот метод обрабатывает три типа преобразования :
- Создание содержимого для редактирования и сохранение текущих значений для возможного поиска
- Восстановление редактируемого содержимого до состояния по умолчанию с исходными значениями
- Восстановление редактируемого содержимого до состояния по умолчанию с новыми значениями
Таким образом, тип будет либо «редактировать», «восстанавливать» или «обновлять».
1
|
_transformElements: function (i, type){}, |
Необходимый ярлык …
Во-первых, нам нужно определить переменную, которая ссылается на options.fieldNames
массив.
Необходимо определить эту ссылку в контексте этого метода, чтобы он был доступен для внутренней функции $.each
, которую мы будем вызывать в ближайшее время.
fieldNames
Вар будет использоваться только тогда , когда делает элементы редактирования.
1
|
var fieldNames = this .options.fieldNames; |
Итерация по нашему редактируемому контенту
Используя $.each
метод jQuery , мы проведем итерацию _editable[i]
. Мы будем передавать пустой аргумент, index
к $.each
. Числовой индекс каждого элемента в цикле будет присвоен этому аргументу.
1
|
this ._editable[i].each( function (index){...}); |
Переменные в методе $ .each
В рамках $.each
, мы определим / инициализируем еще две переменные соответственно:
-
Html:
Хорошо инициализируйте
html
переменную здесь, в области действия$.each
. Эта переменная будет содержать HTML-строку, если мы делаем контент редактируемым, и текстовую строку, если мы обновляем или восстанавливаем контент.12345this
._editable[i].each(
function
(index){
var
html;
}); -
Самостоятельная:
Мы будем кэшировать селектор jQuery для
this
селектора текущего элемента в цикле.12345this
._editable[i].each(
function
(index){
var
html, self = $(
this
);
});
Используя Переключатель, чтобы Получить и Установить!
После того, как наши переменные инициализированы и определены, мы теперь будем использовать оператор switch для type
аргумента, чтобы определить, что именно мы будем делать.
-
Дело «Правка»:
Если дело обстоит так
edit
, мы сделаем этот элемент редактируемым. В результате нам нужно сделать три вещи:-
Текстовое значение элемента
Прежде всего, мы определим новую переменную
val
как значениеthis
элементаtext
.1234switch
(type){
case
"edit"
:
var
val = self.text();
break; -
Хранение текста на потом
Используя
$.data
метод jQuery , мы прикрепимval
кthis
элементу! Этот$.data
метод является фантастическим способом связать данные с элементом. Для настройки данных нам нужно указать три аргументаelement
,key
иvalue
.12345switch
(type){
case
"edit"
:
var
val = self.text();
$.data(
this
,
'value'
, val);
break;Для получения дополнительной информации о методе $ .data в jQuery обратитесь к API jQuery.
-
Определение
html
строкиНаконец, мы определим
html
var как строковое представление входного элемента. Эта строка будет использоваться как для создания, так и для внедрения этого элемента с помощью всего одного вызова html-метода jQuery.Мы установим атрибут имени для этого ввода путем объединения соответствующего значения из
fieldNames
массива в строку html. Здесь мы будем использоватьindex
аргумент, так как он представляет индекс текущего элемента в цикле. Таким образом, если вы работаете с_editable[0]
соответствующим именем поля, оно должно быть сохранено вfieldNames[0]
!Таким же образом мы будем объединять
val
в строку атрибут входного значения.123456switch
(type){
case
"edit"
:
var
val = self.text();
$.data(
this
,
'value'
, val);
html =
'<input type="text" name="'
+ fieldNames[index] +
'" value="'
+ val +
'">'
;
break;
-
-
Дело «Восстановить»:
Если
type
оцениватьrestore
, нам нужно только получить текст для этого элемента.-
Получение
$.data
Получить $ .data так же просто, как установить его. Нам нужно только вызвать метод $ .data с двумя аргументами
element
иkey
.123case
"restore"
:
html = $.data(
this
,
'value'
);
break;
-
-
Дело «Обновление»:
Если
type
аргумент оценивается какupdate
мы определим нашуhtml
переменную как обновленное значение изvalue
атрибута этого элементаinput
.Затем,
$.data
снова используя метод jQuery , мы обновим значение, которое мы прикрепили к этому элементу, чтобы он отражал новое значение!-
Получение значения входов
Используя
attr
метод jQuery . мы определимhtml
var как атрибут значения для ввода.1234case
"update"
:
html = $(
"input"
, self).attr(
'value'
);
$.data(
this
,
'value'
, html);
break;
-
-
По умолчанию:
-
Установка по умолчанию:
У нас будет переключатель по умолчанию для возврата в случае, если аргумент типа как-то не вычисляется в одну из соответствующих строк.
12default:return;
-
Все switch
заявление
Определив все наши случаи, мы рассмотрим весь оператор switch
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
switch (type){ case "edit" : var val = self.text(); $.data( this , 'value' , val); html = '<input type="text" name="' + fieldNames[index] + '" value="' + val + '">' ; break;
case "restore" : html = $.data( this , 'value' ); break;
case "update" : html = $( "input" , self).attr( 'value' ); $.data( this , 'value' , html); break;
default:
return;
};
|
Настройка HTML
Используя html
метод jQuery , мы теперь установим строку, которую мы определили как html для this
элемента.
1
|
self.html(html); |
Возвращая что-то полезное
$.each
Закончив наш цикл, мы готовы завершить этот метод. Мы сделаем это, вернув, this
чтобы этот метод был цепным.
1
|
return this;
|
_transformElements
в целом
Вот и все, вот посмотрите на завершенный метод _transformElements:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
_transformElements: function (i, type){ var fieldNames = this .options.fieldNames; this ._editable[i].each( function (index){ var html, self = $( this ); switch ( true ){ case (type === "edit" ): var val = self.text(); $.data( this , 'value' , val); html = '<input type="text" name="' + fieldNames[index] + '" value="' + val + '">' ; break;
case (type === "restore" ): html = $.data( this , 'value' ); break;
case (type === "update" ): html = $( "input" , self).attr( 'value' ); $.data( this , 'value' , html); break;
default:
return;
};
self.html(html); });
return this;
},
|
Удаление элементов из DOM с _removeElements
_removeElements
Метод будет вызываться только тогда , когда пользователь успешно удалены данные с запросом AJAX. Другими словами, этот метод будет обратным вызовом для успешного удаления AJAX.
аргументы
Этот метод принимает только один аргумент, i
который будет использоваться для выбора соответствующего селектора для удаляемого _elementParent
нами.
1
|
<strong>_removeElements: function (i){...},</strong> |
Выбор контента
Сначала мы укажем, что _elementParent
мы удаляем, используя i
квадратную скобку / обозначение ассоциативного массива. Это даст нам элемент с индексом, i
а не селектором jQuery. Итак, мы сделаем новый выбор jQuery из этого выражения.
Мы могли бы также легко использовать jQuery get
или eq
методы здесь, не делая новый выбор jQuery. Однако, в соответствии с соглашением о кодировании, которое мы использовали, давайте просто сделаем следующее:
1
2
3
4
5
|
_removeElements: function (i){ $( this ._elementParent[i]) },
|
Для получения дополнительной информации о методе get jQuery, проверьте API jQuery
Документацию по методу eQ в jQuery можно также найти в API jQuery.
Удаление контента
Используя remove
метод jQuery , мы удалим эти элементы из DOM!
1
2
3
4
5
|
_removeElements: function (i){ $( this ._elementParent[i]).remove(); },
|
Документацию по методу удаления в jQuery можно найти в jQuery API
возврате this
Наконец, мы будем, return this
чтобы не разорвать цепь.
1
2
3
4
5
6
7
|
_removeElements: function (i){ $( this ._elementParent[i]).remove(); return this;
},
|
_encode
: Подготовка данных для подачи!
_encode
Метод вызывается непосредственно перед запроса AJAX. Используя jQuery serialize
и $.param
методы, _encode
сериализует пары ключ / значение и возвращает строку в кодировке URL.
аргументы
Этот метод принимает один аргумент, inputs
представляющий коллекцию jQuery элементов, которые мы хотим сериализовать.
1
|
_encode: function (inputs){...}, |
Сериализация входов, легкий путь!
Используя is
метод jQuery , который возвращает логическое значение, мы проверим inputs
аргумент против "input"
селектора. Если имеют дело с входами, is
будет return true
и как таковой, мы будем называть то JQuery в serialize
метод на этой коллекции. serialize
принимает форму или набор входных данных и возвращает закодированную в URL строку пар ключ / значение.
1
2
3
4
5
|
_encode: function (inputs){ if (inputs.is( "input" )) return inputs.serialize(); },
|
Для получения дополнительной информации о is
методе jQuery , проверьте API jQuery
документацию по serialize
методу jQuery можно также найти в API jQuery
Сериализация всего остального!
Если inputs
коллекция не состоит из элементов ввода, мы создадим литерал объекта, состоящий из пар ключ-значение, представляющих, своего рода, псевдо-имя и атрибуты значения.
Как только мы создали этот объект, мы можем передать его jQuery $.param
в качестве аргумента. $.param
будет сериализовать массив или объект и вернет строку, закодированную в URL, в отличие от serialize
метода jQuery .
-
Инициализация пустого объекта
Давайте инициализируем переменную
data
пустым объектом. Мы заполним этот объект через мгновение, пока будем перебирать нашinputs
.1var
data = {},
-
Делать
this.options.fieldNames
доступнымДалее мы определим переменную
fieldNames
как ссылку наthis.options.fieldNames
. Делая это, мы делаемthis.options.fieldNames
доступной внутреннюю функцию этого метода$.each
.fieldNames
также служит своего рода сокращенным способом доступа кoptions.fieldNames
массиву.12var
data = {},
fieldNames =
this
.options.fieldNames;
-
Цикл хотя
inputs
Используя
$.each
метод jQuery , мы будем итерироватьinputs
. Опять же, мы передаем пустой аргументindex
, чтобыinputs
. В результате индекс текущего элемента в цикле будет присвоенindex
. Далее, логика нашего цикла!123inputs.each(
function
(index){
});-
Кэширование
this
Сначала давайте кешируем селектор jQuery для
this
текущего элемента в нашем цикле.123inputs.each(
function
(index){
var
self = $(
this
),
}); -
Определение
key
Переменная
key
будет представлятьname
атрибут для этого элемента. Значение ключа хранится вfieldNames
массиве, и его индекс в этом массиве равен индексу текущего элемента в нашем цикле. Таким образом,fieldNames[index]
должно содержать соответствующее имя поля дляinputs[index]
.1234inputs.each(
function
(index){
var
self = $(
this
),
key = fieldNames[index],
}); -
Извлечение
value
Наконец, мы определяем переменную
val
как своего рода псевдоатрибутvalue
. Мы будем использоватьtext
метод jQuery, чтобы получить текст текущего элемента в цикле.12345inputs.each(
function
(index){
var
self = $(
this
),
key = fieldNames[index],
val = self.text();
}); -
Строительство
data
объектаОпределив наши пары ключ / значение, мы начнем заполнять объект, используя квадратную скобку / обозначение ассоциативного массива. Мы установим ключ для каждого элемента как
key
и значение какval
. Преимущество использования этого типа записи в данном конкретном контексте заключается в том, что мы можем установить ключ с помощью переменной. В буквальном обозначении переменнаяkey
будет интерпретироваться как строка"key"
.1234567inputs.each(
function
(index){
var
self = $(
this
),
key = fieldNames[index],
val = self.text();
data[key] = val;
});
-
-
Возврат закодированных данных
Теперь, когда наша итерация завершена и
data
объект заполнен, мы будем вызывать$.param
метод jQuery сdata
аргументом.$.param
вернет закодированное в виде строки строковое представление объекта или массива, переданного ему.1return
$.param(data);
Для получения дополнительной информации о методе jQuery $ .param проверьте API jQuery .
Полный _serialize
метод
Вот посмотрите на полный _serialize
метод:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
|
_encode: function (inputs){ if (inputs.is( "input" )) return inputs.serialize(); var data = {}, fieldNames = this .options.fieldNames; inputs.each( function (index){ var self = $( this ), key = fieldNames[index], val = self.text(); data[key] = val; });
return $.param(data); },
|