Скрипт для редактирования страницы в браузере
При написании веб-страниц и приложений вам придётся часто каким-либо образом управлять структурой документа. Обычно это делается с помощью Document Object Model (DOM), набора API для управления разметкой HTML и стилями, которая сильно использует объект Document . В этой статье мы подробно рассмотрим, как использовать DOM и некоторые другие интересные API, которые могут изменить вашу среду интересными способами.
Предпосылки: | Базовая компьютерная грамотность, базовое понимание HTML, CSS и JavaScript - включая объекты JavaScript. |
---|---|
Задача: | Познакомиться с основными DOM API и другими API, обычно связанными с DOM, и манипулированием документами |
Важные элементы веб-браузера
Веб-браузеры - очень сложные части программного обеспечения с множеством движущихся частей, многие из которых не могут контролироваться или управляться веб-разработчиком с использованием JavaScript. Вы можете подумать, что такие ограничения - это плохо, но браузеры заблокированы по уважительным причинам (в основном ради безопасности). Представьте себе, что веб-сайт может получить доступ к вашим сохранённым паролям или другой конфиденциальной информации и войти на веб-сайты так, как если бы это были вы?
Несмотря на ограничения, Web API по-прежнему дают нам доступ к множеству функциональных возможностей, которые позволяют нам многое делать с веб-страницами. Есть несколько действительно очевидных моментов, на которые вы будете регулярно ссылаться в своём коде. Рассмотрим следующую диаграмму, которая представляет основные части браузера, непосредственно участвующие в просмотре веб-страниц:
- Окно - это вкладка браузера, в которую загружается веб-страница; это представлено в JavaScript объектом Window . Используя методы, доступные для этого объекта, вы можете делать такие вещи, как возврат размера окна (см. Window.innerWidth (en-US) и Window.innerHeight ), манипулировать документом, загруженным в этот window, хранить данные, специфичные для этого документа на стороне клиента (например, используя локальную базу данных или другой механизм хранения), присоединить обработчик событий (event handler) к текущему окну и многое другое.
- Навигатор представляет состояние и идентификатор браузера (т. е. пользовательский агент), как он существует в Интернете. В JavaScript это представлено объектом Navigator . Вы можете использовать этот объект для извлечения таких вещей, как геолокационная информация, предпочтительный язык пользователя, медиапоток с веб-камеры пользователя и т. д.
- Документ (представленный DOM в браузерах) представляет собой фактическую страницу, загруженную в окно, и представлен в JavaScript объектом Document . Вы можете использовать этот объект для возврата и обработки информации о HTML и CSS, содержащей документ, например, получить ссылку на элемент в DOM, изменить его текстовый контент, применить к нему новые стили, создать новые элементы и добавить их в текущий элемент как дочерний элемент, или даже вообще удалить его.
В этой статье мы сосредоточимся главным образом на манипулировании документом, но мы покажем ещё несколько полезных моментов.
Объектная модель документа
Документ, загруженный в каждый из ваших вкладок браузера, представлен объектной моделью документа. Это представление «древовидной структуры», созданное браузером, которое позволяет легко получить доступ к структуре HTML с помощью языков программирования - например, сам браузер использует его для применения стиля и другой информации к правильным элементам, поскольку он отображает страницу, а разработчики (как Вы) могут манипулировать DOM с JavaScript после того, как страница была отображена.
Мы создали простую страницу примера в dom-example.html (см. также live). Попробуйте открыть это в своём браузере - это очень простая страница, содержащая элемент , внутри которого вы можете найти изображение и абзац со ссылкой внутри. Исходный код HTML выглядит так:
DOM, с другой стороны, выглядит так:
Примечание. Эта диаграмма дерева DOM была создана с использованием Live DOM viewer Яна Хиксона.
Вы можете видеть здесь, что каждый элемент и бит текста в документе имеют свою собственную запись в дереве - каждый из них называется узлом (node). Вы также столкнётесь с различными терминами, используемыми для описания типа узла, и их положением в дереве относительно друг друга:
- Element node: элемент, как он существует в DOM.
- Root node: верхний узел в дереве, который в случае HTML всегда является узлом HTML (другие словари разметки, такие как SVG и пользовательский XML, будут иметь разные корневые элементы)..
- Child node: узел непосредственно внутри другого узла. Например, IMG является дочерним элементом SECTION в приведённом выше примере.
- Descendant node (узел потомок): узел внутри дочернего элемента. Например, IMG является дочерним элементом SECTION в приведённом выше примере, и он также является потомком для родителя SECTION . IMG не является ребёнком BODY , так как он находится на двух уровнях ниже дерева в дереве, но он является потомком BODY .
- Parent node: узел, в котором текущий узел. Например, BODY является родительским узлом SECTION в приведённом выше примере.
- Sibling nodes (одноуровневый узел): узлы, которые расположены на одном уровне в дереве DOM. Например, IMG и P являются братьями и сёстрами в приведённом выше примере.
- Text node: узел, содержащий текстовую строку.
Полезно ознакомиться с этой терминологией перед тем, как работать с DOM, поскольку некоторые термины кода, с которыми вы столкнётесь, используют их.. Возможно, вы уже сталкивались с ними, если вы изучали CSS (например, селектор потомков, дочерний селектор).
Активное обучение: основы управления структурой DOM
Чтобы начать изучение по управлению структуры DOM, давайте начнём с практического примера.
- Возьмите локальную копию страницы dom-example.html page и изображение, которое вместе с ним.
- Добавьте элемент чуть выше закрывающего тега .
- Чтобы управлять элементом внутри DOM, вам сначала нужно выбрать его и сохранить ссылку на него внутри переменной. Внутри вашего скриптового элемента добавьте следующую строку:
Обратите внимание, что, как и во многих вещах в JavaScript, существует множество способов выбора элемента и хранения ссылки на него в переменной. Document.querySelector() - рекомендуемый современный подход, который считается удобным, потому что он позволяет вам выбирать элементы с помощью селекторов CSS. Вышеупомянутый запрос querySelector() будет соответствовать первому элементу , который появляется в документе. Если вы хотите совместить и делать что-то с несколькими элементами, вы можете использовать Document.querySelectorAll() , который соответствует каждому элементу документа, который соответствует селектору и сохраняет ссылки на них в массиве массива-подобном объекте, называемом NodeList.
Существуют более старые методы для захвата ссылок на элементы, например:
-
, который выбирает элемент с заданным значением атрибута id , например
Мой абзац
. Идентификатор передаётся функции как параметр, т.е. var elementRef = document.getElementById('myId') . , который возвращает массив, содержащий все элементы на странице данного типа, например, и т.д. Тип элемента передаётся к функции в качестве параметра, то есть var elementRefArray = document.getElementsByTagName('p') .
Эти два работают в более старых браузерах, чем современные методы, такие как querySelector() , но не так удобны. Осмотритесь и вы увидите, что ещё можно найти!
Создание и размещение новых узлов
Вышесказанное дало вам немного представления о том, что вы можете сделать, но давайте продолжим и посмотрим, как мы можем создавать новые элементы.
Это большая часть того, что вам нужно для добавления узлов в DOM - вы будете использовать эти методы при построении динамических интерфейсов (мы рассмотрим некоторые примеры позже).
Перемещение и удаление элементов
Могут быть моменты, когда вы хотите переместить узлы или вообще удалить их из DOM. Это вполне возможно.
Если бы мы хотели переместить абзац со ссылкой внутри него в нижней части раздела, мы могли бы просто сделать это:
Это переводит абзац вниз в нижнюю часть раздела. Вы могли подумать, что это сделает вторую копию, но это не так - linkPara - ссылка на единственную копию этого абзаца. Если вы хотите сделать копию и добавить её также, вам нужно будет использовать Node.cloneNode() .
Удаление узла довольно просто, по крайней мере, когда у вас есть ссылка на удаляемый узел и его родительский элемент. В нашем случае мы просто используем Node.removeChild() , например:
Он становится немного сложнее, если вы хотите удалить узел, основанный только на ссылке на себя, что довольно распространено. Нет способа сообщить узлу удалить себя, поэтому вам нужно будет сделать следующее.
Попробуйте добавить вышеуказанные строки в свой код.
Управление стилями
Можно управлять стилями CSS с помощью JavaScript различными способами.
Для начала вы можете получить список всех таблиц стилей, прикреплённых к документу, с помощью Document.stylesheets (en-US), который возвращает массив объектов CSSStyleSheet . Затем вы можете добавлять / удалять стили по желанию. Однако мы не будем расширять эти функции, потому что они являются несколько архаичным и трудным способом манипулирования стилем. Есть гораздо более простые способы.
Первый способ - добавить встроенные стили непосредственно на элементы, которые вы хотите динамически стилизовать. Это делается с помощью свойства HTMLElement.style (en-US), которое содержит встроенную информацию о стиле для каждого элемента документа. Вы можете установить свойства этого объекта для непосредственного обновления стилей элементов.
-
В качестве примера попробуйте добавить эти строки в наш текущий пример:
Примечание: Обратите внимание на то, как версии свойств JavaScript стилей CSS пишутся в нижнем регистре верблюжьего стиля (lower camel case), в то время как версии свойств стилей CSS используют дефисы (например, backgroundColor и background-color ). Убедитесь, что вы не перепутали их, иначе это не сработает.
Существует ещё один распространённый способ динамического управления стилями вашего документа, который мы рассмотрим сейчас.
- Удалите предыдущие пять строк, добавленных в JavaScript.
- Добавьте в свой HTML-код следующее: :
- Теперь мы перейдём к очень полезному методу для общего манипулирования HTML - Element.setAttribute() - это принимает два аргумента, атрибут, который вы хотите установить для элемента, и значение, которое вы хотите для его установки. В этом случае мы укажем имя класса выделения в нашем абзаце:
Какой метод вы выбираете, зависит от вас; оба имеют свои преимущества и недостатки. Первый метод принимает меньше настроек и хорош для простого использования, тогда как второй метод более пурист (без смешивания CSS и JavaScript, без встроенных стилей, которые рассматриваются как плохая практика). Когда вы начнёте создавать более крупные приложения, вы, вероятно, начнёте использовать второй метод больше, но это действительно зависит от вас.
На данный момент мы не сделали ничего полезного! Нет смысла использовать JavaScript для создания статического контента - вы можете просто записать его в свой HTML и не использовать JavaScript. Это сложнее, чем HTML, и для создания вашего контента с помощью JavaScript также есть другие связанные с ним проблемы (например, не читаемые поисковыми системами).
В следующих параграфах мы рассмотрим ещё несколько практических применений DOM API.
Активное обучение: Получение полезной информации из объекта Window
До сих пор мы действительно смотрели на использование функций Node и Document для управления документами, но нет причин, по которым вы не можете получить данные из других источников и использовать его в пользовательском интерфейсе. Вспомните нашу простую демонстрацию maps-example.html из последней статьи - там мы извлекли некоторые данные о местоположении и использовали её для отображения карты вашей области. Вам просто нужно убедиться, что ваши данные в правильном формате; JavaScript упрощает работу, чем многие другие языки, будучи слабо типизированным - например, числа автоматически преобразуются в строки, когда вы хотите распечатать их на экране.
В этом примере мы решим общую проблему: убедитесь, что ваше приложение имеет размер как окно, в котором он просматривается, независимо от его размера. Это часто полезно в таких ситуациях, как игры, где вы хотите использовать как можно большую площадь экрана, чтобы играть в игру.
-
Прежде всего, давайте возьмём ссылку на div, а затем возьмём ширину и высоту окна просмотра (внутреннее окно, где отображается ваш документ) и сохраните их в переменных - эти два значения удобно содержатся в Window.innerWidth (en-US) и Window.innerHeight . Добавьте следующие строки внутри существующего элемента :
Примечание. Если у вас возникла проблема, посмотрите на наш законченный пример изменения размера окна (см. также live).
Активное обучение: динамический список покупок
Чтобы завершить статью, мы хотели бы задать вам небольшой вызов - мы хотим сделать простой пример списка покупок, который позволяет динамически добавлять элементы в список с помощью ввода формы и кнопки. Когда вы добавляете элемент на вход и нажимаете кнопку:
Готовое демо будет выглядеть примерно так:
Чтобы завершить упражнение, выполните следующие действия и убедитесь, что список ведёт себя так, как описано выше.
- Для начала загрузите копию нашего начального файла shopping-list.html и скопируйте его где-нибудь. Вы увидите, что у него есть минимальный CSS, список с меткой, ввод и кнопка, пустой список и элемент . Вы будете делать все свои дополнения внутри скрипта.
- Создайте три переменные, содержащие ссылки на список ( , и элементы.
- Создайте function, которая будет запускаться в ответ на нажатие кнопки.
- Внутри тела функции начните с сохранения текущего значения (value) входного элемента в переменной.
- Затем очистите элемент ввода, установив его значение в пустую строку — '' .
- Создайте три новых элемента - элемент списка ( ), и и сохраните их в переменных.
- Добавьте диапазон и кнопку в качестве дочерних элементов списка.
- Установите текстовое содержимое диапазона на значение входного элемента, которое вы сохранили ранее, и текстовое содержимое кнопки «Удалить».
- Добавить элемент списка в качестве дочернего списка.
- Прикрепите обработчик события к кнопке удаления, чтобы при щелчке удалял весь элемент списка, внутри которого он находится.
- Наконец, используйте метод focus() , чтобы сфокусировать входной элемент, готовый для входа в следующий элемент списка покупок.
Примечание: Если у вас возникла действительно сложная проблема, взгляните на наши примеры finished shopping list (see it running live also.)
Краткая информация
Мы закончили изучение документа и манипулирования DOM. На этом этапе вы должны понимать, что важная часть веб-браузера связана с управлением документами и другими аспектами веб-интерфейса пользователя. Самое главное, вы должны понять, что такое Document Object Model, и как манипулировать им для создания полезных функций.
Дополнительная информация
Есть много возможностей, которые можно использовать для управления вашими документами. Ознакомьтесь с некоторыми нашими рекомендациями и узнайте, что вы можете обнаружить:
В процессе создания очередного статического сайта-заглушки появилась потребность оптимизировать процесс. Что из этого получилось?
Итак цель — создание удобного редактора статических HTML страниц в браузере. Редактор имеет два режима. Редактирование текста и редактирование HTML.
Редактирование текста активируется кликом на нужном элементе. Для редактирования HTML делаем двойным клик.
В режиме редактирования HTML подсветка кода на основе google-code-prettify (известный по использованию в документации twitter bootstrap) и jsbeautifier для форматирования кода.
Для сохранения изменений используется простой node.js сервер позволяющий сохранять изменения и создавать копию текущей страницы.
Как это работает:
Активация WYSIWYG режим редактирования
Активация HTML редактора
После окончания редактирования элемента
В случае если редактировался текст
В случае HTML редактора необходимо очистить HTML от элементов добавленных prettify парсером
Установка и пример использования:
Воспользуемся bootstrap шаблоном от initializr
Для вызова редактора добавляем в index.html перед строку:
В ксрипте inplaceeditor.js нужно поменять
Node.js
Устанавливаем зависимости для node.js
- Клик на элементе для редактирования текста страницы
- Двойной клик для активации режима редактирования HTML
- Справа вверху кнопка Save сохраняет изменения. Кнопка Copy рядом делает копию текущей страницы и делает переход на неё
- Для завершения редактирования можно использовать клик на не редактируемом элементе или ESC
Перед загрузкой на сервер не забываем удалять вызов редактора!
Чего не хватает?
Портировать node.js на phpДобавить возможность аутентификации для редактирования непосредственно на сервере
Update 2: Добавлена возможность аутентификации пользователя для защиты от редактирования
Имя/пароль прописаны в server.js admin:secret
Update 3: Добавленa поддержка PHP
В inplaceeditor.js нужно поменять
P.S. Хотелось бы услышать отзывы от тех кто пользуеться редактором
Скрипты для создания/редактирования HTML-кода в браузере и скрипты для редактирования файлов из браузера
В виду того, что часть кода ответственная за считывание/запись файлов, реализуется, обычно, другими скриптами, тут будут, в основном, WYSIWYG редакторы на javascript. Скрипты поддерживаемые только одним браузером (IE), а также без демостраницы, удалены из шапки.
Наиболее популярные:
[js] CKEditor (бывший FCKEditor) - интегрируется почти с любым вебязыком и умеет практически все, что нужно для редактора. обсуждение
[js] CLEditor - простой и легкий плагин для jQuery
[js] dijit.Editor - виджет javascript-фрэймворка Dojo Toolkit
[js] markItUp! - плагин для jQuery
[js] Cross-Browser Rich Text Editor (сайт)-- редактор для IE5.5+/Mozilla 1.3+/Firefox 0.6.1+/Netscape 7.1+/Mac Safari 1.3+/Opera 9+
[Flash] Rich Text on-Screen Editor (WYSIWYG) (сайт)-- HTML-редактор на флэш, .fla-исходник прилагается. (не дружит c русскими шрифтами, поэтому для того, чтобы можно было использовать на странице-- необходимо в исходнике заменить шрифты на кириллические).
[Java] Ekit Java HTML Editor (сайт)-- open source HTML-редактор в виде Java-аплета
[Java] ZWebEdit (сайт)-- Простейший редактор: умеет только заключать в тэги , или выделенную часть введённого текста
WYSIWYG-редактор
Редактор WYSIWYG из системы управления сайтом Bitrix
[Perl] AutoHTMLite (сайт)-- скрипт для создания HTML-файлов на сервере из браузера + для заливки файлов на сервер из браузера
[Perl] Genie (сайт)-- Простой скрипт для редактирования файлов или заливки готовых файлов на сервер из браузера
[Perl, SSI] Page Updater (сайт)-- скрипт позволяет вставлять/заменять часть текста на странице, для обновления новостей на странице не подойдёт-- не может сохранять предыдущие обновления, но для вставки кода баннеров, обновления любой информации, не требующей сохранения при её замене (напр., цены и т.п.), вполне сгодится. По сути делает то же, что и SSI, но есть возможность изменять информацию из браузера.
[PHP] SnippetMaster LITE (сайт)-- скрипт для изменения содержимого страниц сайта (редактируемые места необходимо определять заранее при помощи специальных коментариев)
ты шапку читал? %)
Это уже есть. + несколько более-менее нормальных вещей оттуда %)
А вообще, скоро тема по вебмастерскому софту будет готова
-->
(А причем тут эта тема?)
Namo ActiveSquare 5
Навороты:
- Многоязычность
- подключение необходимого CSS прямо в окно редактора
- Большой набор функций форматирования
- Корректная(!) работа с изображениями
- Легко интегрируется
- Можно создавать собственные панели инструментов
- Автоматически определяет язык браузера и включает нужнуюю локаль
Минусы
- Работает тока под виндой и IE5+
- Иногда глючит автоопределения языка браузера
Теги в принципе можно и все при желании впихнуть
Жду отзывов
Добавлено
ЗЫ. работает только в ИЕ 5.5+
Даже в МайИЕ не так как надо работает
В HTML любой элемент может быть доступен для редактирования. Используя некоторые обработчики событий JavaScript, вы можете превратить свою веб-страницу в полноценный и быстрый текстовый редактор. В этой статье содержится некоторая информация об этой функции.
Как это работает?
Все, что вам нужно сделать, это установить атрибут contenteditable почти на любой элемент HTML, чтобы сделать его доступным для редактирования.
Вот приведённый выше HTML-код в песочнице:
Выполнение команд
Когда HTML-элемент имеет contenteditable установленный в true , метод document.execCommand() становится доступным. Это позволяет запускать команды для управления содержимым редактируемого региона. Большинство команд влияют на выбор документа, например, применяя стиль к тексту (полужирный, курсив и т. д.), в то время как другие вставляют новые элементы (например, добавление ссылки) или влияют на всю строку (отступы). При использовании contentEditable , вызов execCommand() будет влиять на текущий активный редактируемый элемент.
Различия в генерации разметки
Использование contenteditable в разных браузерах было болезненным в течение длительного времени из-за различий в сгенерированной разметке между браузерами. Например, даже что-то простое, что происходит, когда вы нажимаете Enter/Return для создания новой строки текста внутри редактируемого элемента, обрабатывалось по-разному в основных браузерах (Firefox вставлял элементы , IE/Opera использовала , в Chrome/Safari использовался ).
К счастью, в современных браузерах ситуация несколько более последовательна. Начиная с Firefox 60, Firefox будет обновлён, чтобы обернуть отдельные строки в элементах , соответствующих поведению Chrome, современной Opera, Edge и Safari.
Попробуйте это в приведённом выше примере.
Примечание: Internet Explorer, который больше не разрабатывается, использует элементы вместо .
Если вы хотите использовать другой разделитель абзацев, все вышеперечисленные браузеры поддерживают document.execCommand , предоставляющий для этих изменений команду defaultParagraphSeparator . Например, чтобы использовать элементы :
Безопасность
По соображениям безопасности Firefox не позволяет JavaScript-коду использовать связанные с буфером функции (копировать, вставлять и т. д.) по умолчанию. Используя about:config вы можете включить их, установив настройки, показанные ниже:
Пример:
Простой, но полный текстовый редактор:
Примечание: если вы хотите увидеть, как стандартизировать создание и вставку вашего редактора на свою страницу, см. наш более полный пример редактора.
Одним из наиболее распространённых вариантов использования расширений является внесение изменение в веб-страницу. К примеру, расширение может изменить стиль, применённый к странице, скрыть существующие или вставить на страницу дополнительные DOM-узлы.
Существует два способа сделать это используя WebExtensions API:
- Декларативно: объявить шаблон, которому соответствует набор URL-адресов, и загрузить набор скриптов на страницы, которые попадают в под этот шаблон.
- Программно: используя JavaScript API, загрузить скрипт на страницу, из определённой вкладки.
В любом случае, эти скрипты называются контентными скриптами, и отличаются от других скриптов, которые составляют расширение:
В этой статье мы рассмотрим оба способа загрузки скрипта.
Модификация страниц, подпадающих под URL-шаблон
Прежде всего создадим новую директорию, назовём её "modify-page". В этой директории, создадим файл "manifest.json", со следующим содержимым:
Поскольку свойство "js" ключа content_scripts это массив, вы можете использовать его, для внедрения более одного скрипта. Если вы сделаете это, страницы получат набор, как если бы эти скрипты были загружены самой страницей, они будут загружены в той же очерёдности, в которой они расположены в массиве.
Ключ content_scripts также имеет свойство "css" , которое вы можете использовать для вставки CSS-таблиц.
Далее, создадим файл "page-eater.js", внутри директории "modify-page":
Программная модификация страницы
Что, если вы всё ещё хотите "съедать" страницы, но лишь в тех случаях, когда пользователь попросил об этом? Давайте обновим этот пример таким образом, чтобы мы внедряли контентный скрипт, когда пользователь выбирает соответствующий пункт контентного меню.
Для начала обновим "manifest.json":
Мы удалили ключ content_scripts и добавили два новых:
- permissions (разрешения) : для внедрения скрипта, нам нужны разрешения для страниц, которые мы модифицируем. Разрешение activeTab это способ получить доступ к текущей вкладки. Нам также нужно разрешение contextMenus , чтобы добавлять в контекстное меню новые элементы.
- background (фоновый) : мы используем этот ключ, для загрузки постоянного "фонового скрипта", с именем "background.js", в котором мы настроим контекстное меню и внедрим контентный скрипт.
Давайте создадим этот файл. Создадим новый файл "background.js" в директории "modify-page" и поместим в него следующий код:
В этом скрипте мы создаём элемент контекстного меню, передавая ему определённый идентификатор и заголовок (текст будет отображаться в элементе контекстного меню). Затем мы настраиваем обработчик событий таким образом, чтобы когда пользователь выбирает пункт контекстного меню, осуществлялась проверка, наш ли это элемент eat-page . Если это так - внедряем скрипт "page-eater.js" в текущую вкладку, используя tabs.executeScript() API. Это API опционально принимает идентификатор вкладки, в качестве аргумента. Мы опустили его, это означает, что скрипт будет внедряться в текущую активную вкладку.
На данном этапе расширение должно иметь следующий вид:
Теперь перезагрузим расширение, откроем страницу (на этот раз любую) активируем контекстное меню и выберем "Съесть эту страницу":
Далее, обновим "page-eater.js":
Все эти примеры внедряют JavaScript; вы можете программно внедрять стилевые таблицы CSS используя функцию tabs.insertCSS() .
Читайте также: