Как заменить содержимое элементов jquery. Создание JQuery-плагина поиска и замены

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

Таблица 7-5: Методы для замены элементов

Методы replaceWith и replaceAll работают одинаковым образом, за исключением того, что роли объекта jQuery и аргумента меняются местами. В представлены оба метода.

Листинг 7-19: Использование методов replaceWith и replaceAll $(document).ready(function () { var newElems = $("") .append("") .append("Orchid:") .append("") .css("border", "thick solid red"); $("#row1").children().first().replaceWith(newElems); $("").replaceAll("#row2 img") .css("border", "thick solid red"); });

В этом скрипте я использую метод replaceWith , что заменить первый дочерний элемент в row1 div новым контеном (результатом этого является замена астры на орхидею). Я также использую метод replaceAll , чтобы заменить все элементы img , являющиеся потомками row2 , на рисунок гвоздики. Результат работы скрипта можно увидеть на .

Рисунок 7-14: Замена контекста при помощи методов replaceWith и replaceAll Замена элементов с использованием функции

Можно заменить элементы динамически, если методу replaceWith добавить функцию. Этой функции не передается ни один аргумент, но переменная this устанавливается для обрабатываемого элемента. В листинге 7-20 представлен пример.

Листинг 7-20: Замена элементов с использованием функции $(document).ready(function () { $("div.drow img").replaceWith(function () { if (this.src.indexOf("rose") > -1) { return $(" } else if (this.src.indexOf("peony") > -1) { return $("").css("border", "thick solid red"); } else { return $(this).clone(); } }); });

В этом скрипте я заменяю элементы img , основываясь на их src атрибуте. Если src атрибут содержит rose , тогда я заменяю элемент img другим, отображающим carnation.png . Если src атрибут содержит peony , тогда я заменяю элемент img другим, отображающим lily.png . У обоих замененных элементов есть красная рамка, чтобы была четко видна их позиция в документе.

Приветствую всех.

jBone - микро библиотека (2кб gzipped) для работы с DOM в современных браузерах. Она частично имплементирует интерфейсы jQuery для основных методов необходимых для корректной работы Backbone, но может использоваться и независимо.

Проблема jBone родился при решении конкретной задачи - разработки мобильного приложения. Основными требованиями были отзывчивость UI и скорость загрузки приложения. Очень скоро стало ясно, что почти половину всего кода у нас занимает jQuery, причем решались с помощью него очень простые задачи.

Было принято решение отказаться от jQuery. Я действительно люблю его, за интуитивно понятные интерфейсы и кроссбраузерность. Интерфейсы хотелось бы оставить, но полная кроссбраузреность была не нужна, и я знал, что для имплементации подобной функциональности нужно намного меньше кода. К тому же можно получить хороший скачек в производительности используя современные возможности браузера вместо методов jQuery.Поиски решения Анализ показал, что есть уже готовые инструменты для решений этой задачи, но все они имеют недостатки. В начале я решил посмотреть на Zepto , около 30 кб, не так уж и мало, хоть и значительно меньше чем jQuery, к тому же он имеет существенные проблемы с производительностью проигрывая по перформансу в разы даже jQuery. Следующим шагом я попробовал собрать «свой jQuery» с помощью Ender , но полученный размер файла не вписывался в рамки моих ожиданий. Третьей попыткой стало желание получить Backbone без дополнительных библиотек для работы с DOM. Первым я нашел Backbone.Native . Идея неплохая, но отказываться от удобных алиасов мне кажется неразумно, количество кода будет расти намного быстрее, и процесс написания кода будет не столь удобен. Намного интереснее выглядит этот пулл реквест , идея в том, чтобы сделать jQuery опциональным для тех, кому он нужен, для остальных есть возможность использовать нативные методы, как в Backbone.Native, но проблема удобства и скорости разработки остается.

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

Решение Сейчас jBone это примерно 10кб несжатого кода, полностью покрытого тестами и обеспечивающий замену jQuery для Backbone.

Поговорим немного о реализации и отличиях от jQuery.

Selector engine Это простой querySelector , с его преимуществами и недостатками , во первых это не sizzle и не ждите от него полной совместимости с ним. Зато он быстрый, очень быстрый по сравнению с jQuery.Events Главное отличие в том, что вам придется работать с нативными событиями джаваскрипта, и это хорошо. Дело в том, что в jQuery почти полностью переписаны события. Например если добавить на элемент слушатель с помощью метода addEventListener , то событие не будет «всплывать», если нода не находится внутри документа, jQuery же решает эту «проблему», думаю из за этой «фичи» и вопросов обратной совместимостью, им еще очень долго не удастся перейти к полностью нативным эвентам. У jQuery есть свой объект Event, который имеет набор свойств отличный от стандартного, и так далее. Это все мелочи, но их нужно держать в голове.CSS В jBone метод css принимает свойства в camelCase стиле, то есть вместо border-color нужно писать borderColor .Атрибуты, Анимации Для работы с атрибутами в jBone нет практически ничего, потому что все что нужно есть в JavaScript.

Работа с атрибутами element.
Работа с классами element.classList.add
Работа с data-атрибутами element.dataset

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

AJAX, Deferred Эта часть в библиотеке не покрыта совсем и оставлено право выбора. Реализаций AJAX"a есть

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

Основные принципы

Есть несколько моментов, которые нужно знать при разработке плагинов. В этом разделе я расскажу о них. Рассмотрим следующий фрагмент кода:

(function ($) { $.fn.functionName = function() { return this.addClass("my-class"); }; }(jQuery));

Вы, возможно, заметили, что я использую this вместо $(this) . Это потому, что $.fn делает functionName частью одного и того же объекта JQuery , что и метод .addClass() .

Использование $.fn всегда возвращает объект, который содержит все методы, которые используются в JQuery . Если вы создали свои собственные методы, они также будут частью этого объекта. Так как ваша функция уже является частью объекта JQuery , можете использовать this вместо $(this) .

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

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

Создание плагина

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

(function($) { $.fn.findReplace = function(options) { return this.each(function() { $(this).html($(this).html().replace(/Lorem Ipsum/g, "Замена")); }); }; }(jQuery));

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

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

var settings = $.extend({ // Значения по умолчанию. findText: null, replaceText: "", backgroundColor: "#FFF" }, options);

Я задал для findText значение null . Для replaceText имеет смысл оставить пустую строку, потому что, возможно, так хотел пользователь. Наиболее подходящее значение для backgroundColor — это цвет фона веб-страницы, который в большинстве случаев является белым.

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

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

return this.each(function() { var StringToFind = settings.findText; var regExpression = new RegExp(StringToFind, "g"); var replacement = "" + settings.replaceText + ""; $(this).html($(this).html().replace(regExpression, replacement)); });

Текст, который должен быть найден, можно получить с помощью setting.findText . Он хранится в переменной для последующего применения. Я использую конструктор RegExp , чтобы создать объект регулярного выражения. Он может применяться для динамической замены регулярных выражений.

Использование глобального модификатора гарантирует, что все вхождения StringToFind будут заменены. Я заключаю текст на замену в элемент span с встроенными стилями. И изменяю HTML-код элемента, который вызывает нашу функцию findReplace .

Посмотреть демо-версию плагина

Внесение улучшений

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

Но если пользователь решит изменить размер шрифта или произвести какие-нибудь другие изменения, он не сможет этого сделать. Кроме этого предоставлять пользователю возможность задавать все эти параметры непрактично. Вместо этого можно дать пользователям возможность добавлять к заменяемым элементам класс по своему выбору. Таким образом, они смогут вносить изменения в CSS код, а наш плагин будет по-прежнему компактным и простым.

Все, что нужно сделать, это в нашей более ранней версии плагина JQuery изменить параметр backgroundColor на customClass .

var settings = $.extend({ findText: null, replaceText: "", backgroundColor: "#FFF" }, options); // Теперь должно быть var settings = $.extend({ findText: null, replaceText: "", customClass: "" }, options); var replacement = "" + settings.replaceText + ""; // Теперь должно быть var replacement = "" + settings.replaceText + "";

Некоторые пользователи плагина возможно захотят вызвать callback-функцию после того, как плагин сделал свою работу. Сделать это довольно просто. При написании плагина JQuery нужно добавить параметр completeCallback , чтобы получить функцию обратного вызова. Тогда следующий код сделает все остальное:

if ($.isFunction(settings.completeCallback)) { settings.completeCallback.call(this); }

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

$("a").findReplace({ findText: "Lorem Ipsum", replaceText: "I was replaced too!", customClass: "match-link", completeCallback: function() { $(".notification").text("Executed the plugin on all links").fadeOut(5000); } });

Вот скриншот плагина в действии:

Ниже приводится полный код JQuery плагина для сайта, позволяющий убедиться, что вы ничего не упустили и не перепутали:

(function($) { $.fn.findReplace = function(options) { var settings = $.extend({ findText: null, replaceText: "", customClass: "", completeCallback: null }, options); return this.each(function() { var StringToFind = settings.findText; var regExpression = new RegExp(StringToFind, "g"); var replacement = "" + settings.replaceText + ""; $(this).html($(this).html().replace(regExpression, replacement)); if ($.isFunction(settings.completeCallback)) { settings.completeCallback.call(this); } }); }; }(jQuery));

Окончательная демо-версия

Заключение

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

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

Я надеюсь, вам понравилась эта статья. Если у вас есть какие-либо вопросы, задайте их в комментариях.

Перевод статьи «Create a Find and Replace Plugin in jQuery » был подготовлен дружной командой проекта

В настоящий момент ситуация такова, что все больше и больше разработчиков приходят в мир JavaScript через ворота jQuery. И новички являются счастливчиками. Они получают доступ к изобилию новых API JavaScript, которые делают процесс работы с DOM существенно легче. Но, к сожалению, они не имеют представления об этих API! В данном уроке мы рассмотрим несколько типовых задач, которые решаются средствами jQuery, и преобразуем решения в обычный JavaScript.

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

Вступление

Обратите внимание, что некоторые варианты из набора "наследие" в данной статье используют простую, кросс-браузерную функцию addEvent . Данная функция нормализует два варианта - рекомендованную W3C модель событий addEventListener и вариант для Internet Explorer attachEvent .

Когда используется функция addEvent(els, event, handler) в коде, она представляет собой следующий код:

Var addEvent = (function () { var filter = function(el, type, fn) { for (var i = 0, len = el.length; i < len; i++) { addEvent(el[i], type, fn); } }; if (document.addEventListener) { return function (el, type, fn) { if (el && el.nodeName || el === window) { el.addEventListener(type, fn, false); } else if (el && el.length) { filter(el, type, fn); } }; } return function (el, type, fn) { if (el && el.nodeName || el === window) { el.attachEvent("on" + type, function () { return fn.call(el, window.event); }); } else if (el && el.length) { filter(el, type, fn); } }; })(); // Использование addEvent(document.getElementsByTagName("a"), "click", fn);

1 - $("#container");

Данная функция обращается к DOM для получения элемента с идентификатором container и создает новый объект jQuery .

Модерн

Var container = document.querySelector("#container");

querySelector является частью API Selectors , которая обеспечивает возможность обращения к DOM с помощью селекторов CSS.

Данный метод возвращает первый элемент, который соответствует переданному селектору.

Наследие

Var container = document.getElementById("container");

2 - $("#container").find("li");

В данном случае мы получаем любое количество пунктов списка, которые являются потомками элемента #container .

Модерн

Var lis = document.querySelectorAll("#container li");

querySelectorAll возвращает все элементы, которые соответствуют определенному CSS селектору.

Ограничения. Хотя все браузеры поддерживают API Selectors, передача определенных селекторов CSS ограничивается возможностью браузера. Например: Internet Explorer 8 поддерживает только селекторы CSS 2.1.

Наследие

Var lis = document.getElementById("container").getElementsByTagName("li");

3 - $("a").on("click", fn);

В данном примере обработчик события click привязывается ко всем ссылкам на странице.

Модерн

ForEach.call(document.querySelectorAll("a"), function(el) { // на ссылку нажали });

Выше приведенный код выглядит ужасно, но он не так уж и плох. Так как querySelectorAll возвращает NodeList , а не массив, то мы не можем непосредственно использовать метод, например, forEach . Данный момент обходится вызовом forEach для объекта Array и передачей результата querySelectorAll как this .

Наследие

Var anchors = document.getElementsbyTagName("a"); addEvent(anchors[i], "click", fn);

4 - $("ul").on("click", "a", fn);

Данный пример немного отличается. Код jQuery используется для делегирования события. Обработчик click используется для всех неупорядоченных списков. Но возвратная функция будет запускаться только целью (где пользователь нажимает кнопку) является ссылка.

Модерн

Document.addEventListener("click", function(e) { if (e.target.matchesSelector("ul a")) { // Обработка } }, false);

Технически, данный метод JavaScript не является полным соответствием примеру jQuery. Он привязывает обработчик события непосредственно к document . А затем используется метод matchesSelector для определения того факта, что цель (узел, на котором произошло нажатие кнопки) соответствует указанному селектору. Таким образом, мы привязываем единственный обработчик события.

Обратите внимание, что на момент написания урока все браузеры реализовывали matchesSelector с использованием префиксов: mozMatchesSelector , webkitMatchesSelector , и так далее. Для нормализации метода, вы можете написать:

Var matches; (function(doc) { matches = doc.matchesSelector || doc.webkitMatchesSelector || doc.mozMatchesSelector || doc.oMatchesSelector || doc.msMatchesSelector; })(document.documentElement); document.addEventListener("click", function(e) { if (matches.call(e.target, "ul a")) { // Обработка } }, false);

Наследие

Var uls = document.getElementsByTagName("ul"); addEvent(uls, "click", function() { var target = e.target || e.srcElement; if (target && target.nodeName === "A") { // Обработка } });

Для обеспечения обратной совместимости мы проверяем, что свойство nodeName (имя целевого элемента) равно нашему запросу. Обратите внимание на факт, что старые версии Internet Explorer иногда играют своими собственными правилами. Вы не захотите получать доступ к цели непосредственно из объекта event . Зазочется использовать event.srcElement .

5 - $("#box").addClass("wrap");

jQuery обеспечивает удобный API для модификации имени класса для набора элементов.

Модерн

Document.querySelector("#box").classList.add("wrap");

Новая техника использует новый API classList для добавления, удаления и переключения класса (add , remove , и toggle).

Var container = document.querySelector("#box"); container.classList.add("wrap"); container.classList.remove("wrap"); container.classList.toggle("wrap");

Наследие

Box = document.getElementById("box"), hasClass = function (el, cl) { var regex = new RegExp("(?:\\s|^)" + cl + "(?:\\s|$)"); return !!el.className.match(regex); }, addClass = function (el, cl) { el.className += " " + cl; }, removeClass = function (el, cl) { var regex = new RegExp("(?:\\s|^)" + cl + "(?:\\s|$)"); el.className = el.className.replace(regex, " "); }, toggleClass = function (el, cl) { hasClass(el, cl) ? removeClass(el, cl) : addClass(el, cl); }; addClass(box, "drago"); removeClass(box, "drago"); toggleClass(box, "drago"); // Если элемент не имеет класса "drago", добавляем его.

Обратная совместимость требует достаточно много действий.

6 - $("#list").next();

Метод jQuery next возвращает элемент, который следует непосредственно за текущим элементом наборе.

Модерн

Var next = document.querySelector("#list").nextElementSibling; // IE9

nextElementSibling ссылается на следующий узел за элементом. К сожалению, Internet Explorer 8 и старше не поддерживают его.

Наследие

Var list = document.getElementById("list"), next = list.nextSibling; // Нам нужен следующий элемент, а не текст. while (next.nodeType > 1) next = next.nextSibling;

Есть пара способов для реализации задачи. В данном примере мы определяем тип узла nodeType , который следует на определенным элементом. Это может быть текст, элемент или, даже, комментарий. Так как нам нужен именно следующий элемент, то мы ищем nodeType равный 1 . Если next.nodeType возвращает номер больше, чем 1 , то мы пропускаем узел, так как он, вероятно, является текстом.

7 - $("").appendTo("body");

В дополнение к запросам DOM jQuery также предлагаем возможность создавать и вставлять элементы.

Модерн

Var div = document.createElement("div"); div.id = "box"; document.body.appendChild(div);

В данном примере нет ничего нового. Таким способом выполнялся процесс создания и вставки элемента в структуру DOM очень давно.

Вероятно, что вам понадобится добавить содержание в элемент. В данном случае вы можете использовать innerHTML или createTextNode .

Div.appendChild(document.createTextNode("wacka wacka")); // или div.innerHTML = "wacka wacka";

8 - $(document).ready(fn)

Метод jQuery document.ready невероятно удобен. Он позволяет нам выполнять код сразу по завершению загрузки DOM.

Модерн

Document.addEventListener("DOMContentLoaded", function() { // Наш код });

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

Наследие

// http://dustindiaz.com/smallest-domready-ever function ready(cb) { /in/.test(document.readyState) // in = loadINg ? setTimeout("ready("+cb+")", 9) : cb(); } ready(function() { // Получаем нужное из DOM });

Решение для обратной совместимости - каждые 9 миллисекунд мы проверяем значение document.readyState . Если возвращается “loading”, то документ все еще не загружен полностью (/in/.test()). Как только значение document.readyState будет равно “complete,” выполнится возвратная функция.

9 - $(".box").css("color", "red");

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

Модерн

ForEach.call(document.querySelectorAll(".box"), function(el) { el.style.color = "red"; // или добавляем класс });

Снова мы используем технику .forEach.call() для фильтрации всех элементов с классом box и придания им красного цвета с помощью объекта style .

Наследие

Var box = document.getElementsByClassName("box"), // смотрите пример 10 ниже для кросс-браузерного решения i = box.length; while (i-- > 0 && (box[i].style.color = "red"));

Мы используем трюк с циклом while . По существу, мы имитируем:

Var i = 0, len; for (len = box.length; i < len; i++) { box[i].style.color = "red"; }

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

10 - $()

Определенно, цель полностью заменить jQuery API выходит за рамки данного урока. Но часто в проектах функции $ или $$ используются для короткой записи получения одного или нескольких элементов из DOM.

Модерн

Var $ = function(el) { return document.querySelectorAll(el); }; // Использование = $(".box");

Это просто односимвольный указатель на document.querySelector . Сохраняет время!

Наследие

If (!document.getElementsByClassName) { document.getElementsByClassName = function(cl, tag) { var els, matches = , i = 0, len, regex = new RegExp("(?:\\s|^)" + cl + "(?:\\s|$)"); // Если не задано имен тегов, // мы будем получать все элементы из DOM els = document.getElementsByTagName(tag || "*"); if (!els) return false; for (len = els.length; i < len; i++) { if (els[i].className.match(regex)) { matches.push(els[i]); } } return matches; // массив элементов, которые имеют определённое имя класса }; } // Очень простая реализация. Проверяем id, класс и имя тега. var $ = function(el, tag) { var firstChar = el.charAt(0); if (document.querySelectorAll) return document.querySelectorAll(el); switch (firstChar) { case "#": return document.getElementById(el.slice(1)); case ".": return document.getElementsByClassName(el.slice(1), tag); default: return document.getElementsByTagName(el); } }; // Использование $("#container"); $(".box"); // Любые элементы с классом box $(".box", "div"); // Элементы div с классом box $("p"); // Получаем все элементы p

К сожалению, метод обратной достаточно большой. В данном случае лучше использовать библиотеку. jQuery оптимизирован для работы с DOM! Пример выше будет работать, но он не поддерживает сложные селекторы CSSв старых браузерах.



Есть вопросы?

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: