Салимóненко Дмитрий Александрович

Разное


Мой визуальный редактор HTML

В свое время, как только начал более-менее серьезно заниматься сайтами и т.д., стал искать себе подходящий редактор HTML. Чтобы, по возможности, быстрее делать вебстраницы. Как я уже писал тут где-то у себя, перебрал достаточно много разных редакторов. В итоге, остановился на Notepad++ (для мелких и легких работ) и PHPStorm. Ну, и, конечно, плагин – doctoHtml, если изначально текст страницы создаю в Word.

Однако, все-таки оба этих редактора предназначены больше для профессиональной работы с программным кодом (т.е. для программирования), а не с контентом вебстраницы. Контент в них, конечно, тоже можно делать (что я и делал; да и не только я), но, как бы сказать, хотелось бы что-то поудобнее. Несмотря на то, что тот же PHPStorm имеет возможность создавать макросы, шаблоны вставок кода и шаблоны вебстраниц в целом и ряд другой полезной функциональности. Но там не хватает именно визуальности. Ну, т.е. это чтобы пару раз кнопкой мыши щелкнуть – и было готово, без лишних размышлений и воспоминаний, какое сочетание клавиш надо нажать, какую аббревиатуру ввести и т.д. Чтобы я перед вставкой шаблона html-кода видел его глазами – примерно как он будет выглядеть. Иными словами, все-таки постоянно думал (лет этак 10) о редакторе WYSIWYG (переводится примерно так: что вижу, то и делаю - What You See Is What You Get). Согласно Википедии,

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

А я люблю оформлять страницы не просто в виде текста/рисунков/таблиц – а с учетом пояснений, выделенных мест и т.д. Да, это вполне можно делать вручную (т.е. путем набора html-тегов) в том же PHPStorm, но оправданно это лишь для простых выделений или чего-то подобного. А когда нужно реализовать более сложный (пусть и готовый) шаблон – это уже приходится его, как минимум, найти. Например, на этом сайте пара широко применяемых мною шаблонов присутствует на Технической странице.

После этого следует скопировать, вставить его в нужное место html-кода, затем заполнить контентом (т.е. словами или чем-то еще). Добро, если страница – небольшая. А при довольно большом ее размере – каждый раз при вставке шаблона кода приходится искать место, куда же его следует вставить. Потом надо посмотреть в браузере – как оно отображается на странице. Потом снова надо в PHPStorm, снова делать вставки, исправления и т.д. Если нужно вставить шаблон – нужно помнить его название/аббревиатуру; ну, или открывать список шаблонов, где они показаны, увы, в виде html-кода, а не визуально.

Т.е. это все вполне можно делать, но как-то хлопотно.

Иными словами, это вполне делается и довольно быстро (при надлежащей сноровке), но хочется еще быстрее и удобнее. А это уже – WYSIWYG. Причем, работающий через браузер. Ибо именно в браузере страница отображается так, как она будет видна мне и пользователям.

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

И очень хорошо, что забросил ВОВРЕМЯ. Иначе было бы потрачено время (много), а в итоге пришлось бы потом много чего переделывать. Потому что в то время я еще не до конца знал и понимал ряд некоторых вещей. Т.е. получилось бы в итоге, как с разработчиком WYSIWYG редактора NVU (уже не помню, как его зовут). Который, в свое время, видимо, понял, что шел не туда; а вот делать все ЗАНОВО у него, видимо, желания уже не было. Поэтому он сообщил, что "этот редактор требуется переписать" и просто прекратил работу над ним.

А недавно вспомнил и кое-что поменял. И что-то в итоге получилось.

Надо сказать, что в общем случае WYSIWYG редактор HTML невозможен. Как минимум, потому, что:

  1. Часть контента страницы может формироваться путем работы скриптов (javascript). А скрипты, в свою очередь, могут формироваться и сами,
  2. Часть контента может подгружаться или изменяться в процессе взаимодействия со страницей.
  3. Кроме того, существуют еще требования адаптивного дизайна. Без которых нынче не обходится, наверное, ни один (более-менее качественный) сайт.

Реализовывать все это автоматически возможно, разве что, при помощи искусственного интеллекта. Ну, или вручную – что обычно и делают.

Да, еще путем применения разных библиотек (сетки-grid там разные), но это, на мой взгляд, гиблый путь, если начать им злоупотреблять. Потому что в итоге разработчик оказывается более-менее привязанным к той или иной библиотеке. А потом, когда обнаружится ее ограниченность или ошибки – может встать вопрос о кардинальном переходе на другую библиотеку. А это – довольно напряженно и трудно.

Поэтому я сразу обозначил для себя, скажем так, технические условия.

Любопытно, но мне приходится даже для СЕБЯ устанавливать некоторые правила/ограничения, чтобы двигаться в разработке дальше.

1. Ограничил область деятельности:

WYSIWYG-редактированию подлежит только определенная область на странице (например, основной контент), содержащаяся внутри тега с определенным id (задается в настройках сайта). Все остальное можно исправлять только обычным образом – через PHPStorm или что-то подобное.

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

Эти комментарии НЕ ДОЛЖНЫ содержать внутри символов @.

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

<div id="content_razn">

    <!--  __Begin_main_content__ -->

… (контент) …

    <!--  __Finish-main-content__ -->

</div>

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

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

2. Суть технологии работы редактора – достаточно простая:

на странице делаются изменения (осуществляется ее редактирование), после чего контент, содержащийся между указанными комментариями, пересылается на сервер и там вставляется в соответствующее место в файле, в котором содержится html-код страницы. Точнее, старый контент, ранее присутствовавший между данными комментариями в этом файле, заменяется на новый контент, пришедший от клиента (браузера). Попутно, перед этим, на всякий случай, старая версия вебстраницы сохраняется в каталоге запасных файлов. Кстати, на базе этого потом, если понадобится, можно будет сделать откатку (отмену последних сделанных пользователем действий), в дополнение к имеющейся в браузере стандартной операции Ctrl + Z.

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

3. Само редактирование делается средствами браузера + javascript.

Для этого на редактируемую страницу после ее очередного обновления добавляется определенный скрипт (в несколько сотен килобайт), который, собственно, и управляет всей работой. На страницу добавляется специальная рабочая панель, ну, и т.д.

4. Режим редактирования

Это если на сайте включен(!) режим редактирования. Тогда на страницу добавляется панель редактирования. Если он выключен, то страница отображается в обычном режиме, без панели.

Т.е. страница отображается в режиме максимально приближенному к режиму «как есть» - именно в браузере. И редактировать ее можно прямо в процессе просмотра, визуально. Попутно, не тратя время, сразу смотреть, насколько она адапттивна.

5. В редактируемой области НЕ ДОЛЖНО быть контента, который формируется или изменяется при помощи javascript перед редактированием.

Т.е. там может быть только «сырой» HTML-контент. Такой, который, возможно, в процессе работы МОЖЕТ быть подвергнут изменению средствами javascript в обычном режиме, но не в режиме редактирования. Это означает, что соответствующие скрипты НЕ ДОЛЖНЫ функционировать в процессе редактирования контента страницы.

Это же относится к скриптам со сторонних сайтов, типа Яндекс.Метрики, Google-analytics и т.п. Собственно, подобные скрипты существенно замедляют загрузку страниц сайта и при редактировании только мешаются, поэтому на это время их лучше отключить (что я и сделал).

6. Редактирование производится только локально

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

7. Редактируемая страница ДОЛЖНА представлять собой корректный XML-код

Точнее, XHTML. В общем-то, это у меня и так соблюдается; это только разные бездельники сожалеют в интернетах и мечтают о "свободе" верстки. Однако, это - не свобода, а безалаберность, вызванная исключительно недостаточным знанием и умением. Поэтому если html-код по каким-то причинам стал некорректным с точки зрения XML (а это, кстати, более строгий стандарт по сравнению с HTML) - выдается ошибка и изменения сохранены не будут.

Кстати, поэтому эти разные нововведения, позволяющие "писать меньше кода" (ну, например, те же стрелочные функции или троеточия в JS) у меня ничего, кроме отвращения, не вызывают. Потому как экономия в телодвижениях - крайне сомнительная; ведь тот же PHPStorm практически всё набирает САМ, путем автокомплита. А вот лишний (и совершенно излишний) синтаксис в языке и, как следствие, возможные новые скрытые баги - вот это вполне даже. Не говоря уж о росте объема кода движков JS и, как следствие, более медленная работа браузеров. На мой искренний взгляд, использование стрелочных функций и т.п. в JS - это болезнь типа понтов; посмотрите, мол, я тут "новую функциональность освоил(а) и использую".

8. Редактор WYSIWYG НЕ ДОЛЖЕН позволять редактирование, которое может привести к сбою функциональности javascript на странице

Т.е. такой редактор должен служить, в основном, для выполнения именно "визуальных операций" и не более того. Например, редактор НЕ ДОЛЖЕН позволять выполнять операции удаления или назначения id с произвольными значениями. Необходимость назначения id может быть вызвана потребностью реализации ссылки на ту или иную часть (область) контента, для чего id выступает в роли якоря. Поэтому нельзя просто так удалять уже имеющиеся id или, наоборот, назначать id с любыми значениями. Подобные операции необходимо выполнять уже не в WYSIWYG, а в редакторах, специально предназначенных для выполнения разметки и т.д., например, в Notepad++. Как минимум, потому, что нередко id служит для управления блоками посредством JS. Впрочем, этой же цели служит и ряд других атрибутов, например, классы и др. Конечно, уследить за удалением или назначением отдельного, важного с точки зрения JS, функционирующего на этой странице, атрибута - это задача, мягко говоря.... сложная. Ведь это придется реализовывать уже часть функциональности, к примеру, PHPStorm (впрочем, даже там, по-моему, такая функциональность сделана недостаточно). 

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

9. WYSIWYG-редактирование НЕ ДОЛЖНО пытаться заменять собой верстку страницы

Это, пожалуй, ГЛАВНОЕ. Иными словами, не стоит ждать от WYSIWYG-редактора неких "чудесных" возможностей. Он неспособен и НЕ ДОЛЖЕН реализовывать логику верстки и неспособен думать вместо разработчика. Чтобы там кто ни говорил ("искусственный интеллект" и протчая), реализация макета верстки - это задача грамотного разработчика/верстальщика, никакой WYSIWYG тут не поможет. Ну, за исключением совсем уж тупых и отвратительных макетов страниц, типа тех, что делают нейросети и т.п. Грамотная верстка - это, как правило, достаточно творческое занятие, здесь не поможет автоматизированный подход. 

А вот что касается корректировки, редактирования уже в рамках сверстанного макета - вот тут (и, как правило, только тут) WYSIWYG-редактор вполне может сказать свое веское слово. Существенно облегчив и ускорив этот процесс.

Конечно, есть, скажем, визуально ориентированные программы NVU, Adobe DreamWaver и, может, еще какие-то. И они даже могут реализовывать некую верстку, в самом деле. Но... как бы это сказать... Это всё - верстка на уровне дошкольников. Для начинающих. В лучшем случае - на уровне конструкторов сайтов. Т.е. аналог нейросетевых - примитивных, грубых макетов html-страниц (сейчас это называется "современный вебдизайн"). Поэтому ЛУЧШЕ, если подобная функциональность не будет фигурировать в WYSIWYG-редакторе вообще. Ну, чтобы не обманывать пользователя и не создавать ложное впечатление о, якобы, неких "расширенных возможностях".

10. Типичный браузер НЕ предназначен для серьезного редактирования вебстраниц

Т.е. реализация редактора HTML через браузер - это костыли и костылями погоняют. Поверьте на слово. В самом деле, ну, что же хотеть от полностью бесплатной программы. Как минимум, по той причине, что типичный браузер, вообще-то, не предназначен для этого. Он предназначен для ПРОСМОТРА вебстраниц. А не для редактирования. Ну, и (лишь для небольшого) оформления пользовательских сообщений (фон, шрифт, добавить рисунок, видео и, по сути, ... всё). Он преобразует то, что есть на вебстранице, в корректный НTML-контент самостоятельно. Сам добавляет недостающие теги, убирает в некоторых местах лишние, по его мнению, пробелы и т.д. А может, наоборот, самостоятельно добавить, скажем, перенос строки. И, похоже, нет возможности вмешаться в этот процесс. Например, пусть в исходном коде вебстраницы присутствует что-то вроде

<p     class  =  "x y   "    atr   =    "data-attr   "   >

Однако, браузер САМ, автоматически преобразует этот тег в следующий:

<p class="x y   " atr="data-attr   ">

Разница видна, вроде бы. Т.е. он убирает, например, лишние пробелы, которые для корректного отображения страницы и в самом деле не нужны. А вот для редактора HTML они - могут быть очень актуальными. Ну, мало ли, зачем их решил оставить верстальщик. Может, это - не ошибка, а задумка такая. Так вот, браузер сам, принудительно ликвидирует их, эти пробелы (а также, в некоторых случаях, переносы строк). И, похоже, с этим бороться даже теоретически невозможно, если исходить из стандартной функциональности браузера.

Или - другой пример. Скажем, решил разработчик сделать нестандартный тег <gh>. Так вот, браузер его самостоятельно закроет, т.е. добавит </gh>. А ведь иногда это не нужно. Можно, конечно, сделать плагин к нему или что-то подобное, при помощи которого будут решены эти и аналогичные проблемы. Но, написание плагинов для браузера - это, как бы сказать, уже даже не 2-я, а 3-я или даже 4-я ступень в вебразработке. Т.е. это не просто сделать сайт, типа, на каком-нибудь условном laravel.

Впрочем, конечно, если работать по стандарту XHTML, то вполне можно, скажем, объявить свое пространство имен и там, в свою очередь, объявить свои авторские (кастомные) теги XML, например, тег <gh/>. Объявив его самозакрывающимся, типа <br/>. Тогда браузер не будет закрывать его. Более того, можно даже на одной странице сделать теги, принадлежащие к разным пространствам имен и к ним, соответственно, будет применяться JS, предназначенный только для этого, т.е. "своего" пространства имен. Таким образом вполне можно иметь на одной странице несколько элементов с одинаковыми id (но в разных пространствах имен) и такие элементы будут корректно обрабатываться браузером.Т.е  следует признать, что реализация редактора вебстраниц посредством браузера, без написания плагинов, это - костыль. Понятно, что и на костылях люди как-то передвигаются (если уж надо). И, нередко, вполне успешно. Но, по идее, это - не лучшее средство для передвижения. 
Впрочем, это смотря в каком смысле "не лучшее"... Дело в том, что, конечно, в настоящее время чего только нет, есть и профессиональные издательские системы, которые способны не только редактировать вебстраницы, а и делать много чего другого разного. Однако, следует освежить в памяти, во-первых, стоимость подобных систем. Во-вторых, это - тяжелое программное обеспечение, требующее соответствующего компьютера, которое загружается довольно долго. В-третьих, там - масса разных функций, которые, к примеру, лично мне не нужны совсем и только путаются под руками.

Однако, зачастую имеется совершенно другая, более простая задача: набрать готовый текст статьи для вебстраницы, оформить его (некоторые места) в соответствии с принятыми (лично мною, к примеру) стандартами. Или требуется по-быстрому исправить в статье пару фраз, изменить кое-где оформление, добавить или убрать рисунки, т.д. Для этого использование тяжелой издательской системы будет совершенно излишним, требуется нечто более легкое и быстродействующее. Однако, если брать Notepad++ (или его аналоги), то это приходится лезть в исходный код вебстраницы, выискивать там необходимые места. Это, при достаточно массовой работе, более-менее напрягает.

А тут - открыл, как обычно, страницу сайта в браузере. Включил режим редактирования. И всё, можно непосредственно вносить исправления, редактировать страницу прямо в браузере, не отвлекаясь на другое ПО. Если же надо детализации, более детальной и сложной работы с HTML-кодом или javascript - нет проблем, нажал одну кнопку и страница открылась в текстовом редакторе, например, в Notepad++, как раз на том месте, где потребовались исправления. При этом не нужно искать, где эта страница (в каком каталоге) находится, где именно та строчка, которую следует исправить: все определится и произойдет автоматически. Не нужно самостоятельно искать место, где требуются исправления. Нужно, еще раз, просто нажать на одну кнопку. Все-таки, мне кажется, это - более удобно и быстро, по сравнению с какой-нибудь массивной издательской системой.

Так вот, именно для этого я и решил сделать себе редактор вебстраниц.

Так что несколько вот таких условий.

Кстати, чистый WYSIWYG, похоже, и в самом деле невозможен. Даже если взять текстовый редактор Microsoft Word. Ведь даже и там используется, например, режим просмотра непечатаемых символов. Кстати, я, как правило, только в нем и работаю - так как-то удобнее и нагляднее. А это уже не совсем чистая визуальность, так как хоть какие-то элементы "разметки" в таком режиме показываются. Не говоря уж о виде в разных режимах. А что уж говорить о редакторе вебстраниц - ведь там гораздо более обширная функциональность в плане верстки. Например, в Word, вроде бы, невозможно реализовать адаптивный дизайн. А если и можно, то это будет, мягко говоря, неудобно для работы. А в браузере (для вебстраниц) сегодня адаптивный дизайн - это базовое требование.

Вообще, подобная функциональность присутствует в конструкторах сайтов

Которых ныне – очень-очень много. У меня даже тут где-то есть соответствующее задание для студентов - реализация "сайта" в конструкторе. Причем, там можно редактировать не только основной контент, а и всю вебстраницу. Но, во-первых, любой конструктор подразумевает работу с тем или иным шаблоном страницы все равно. Некоторые конструкторы имеют множество разных шаблонов, некоторые – поменьше, но они таки применяются. Совсем без шаблона в конструкторе, как минимум, не получится делать адаптивные страницы.

Во-вторых, после конструкторов, вроде как, получается не очень чистый html-код. А сайты с грязным, неряшливым кодом, по идее, уже давно канули в лету. Сейчас считается, как минимум, признаком нехорошего тона, если на сайте грубый, «непричесанный» код. Впрочем, наверное, разные конструкторы есть, не знаю.

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

В-четвертых, мало-мальски серьезный конструктор является платным. Бесплатные возможности – их, как правило, хватает лишь для новичков, на начальной стадии работы с сайтом. Кроме того, как правило, это - достаточно тяжелая вещь, типа PHPStorm. Который загружается несколько минут. Т.е. не получится открыть его по-быстрому для мелких визуальных исправлений.

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

В-шестых (это актуально для меня лично, по крайней мере) многие конструкторы уже, к сожалению, не поддерживают работу используемых мною браузеров (24-й, 36-й Firefox). А переходить на более современные браузеры у меня нет желания от слова СОВСЕМ.

Как я это сделал

Опять же, на каждом сайте, видимо, будет слегка по-разному. Т.к. все зависит от шаблона вебстраницы. Ну, у меня, к примеру, все «дополнительные» (не нужные при редактировании) скрипты находятся в футере. Поэтому при переключении в режим редактирования на сайте всего-навсего запасается старые (исходные) футеры в файлы с некими временными именами; из них берется содержимое, из которого вырезаются ненужные скрипты и т.д. После чего оставшееся содержимое сохраняется в файлы с соответствующими (исходными) именами футеров. Ну, а при выключении режима редактирования – эти файлы удаляются, а ранее переименованным файлам футеров возвращаются их прежние (исходные) имена. Т.е. тут тоже все просто.

Ну, а вот что касается клиентской части (на JS) – там, конечно, пришлось «слегка» поработать. Ведь нужно что было сделать. Скажем, выделил я на странице слово (или предложение, или пару абзацев) и хочу к ним применить требуемый стиль (да, совсем в редакторе Word, скажем). Так это надо учитывать, где там начало контейнера, где конец; сохранять это в диапазон; сделать так, чтобы выделение сохранялось при кликах мыши по определенным местам на странице; ну, и т.д.

Свои проблемы создавали баги в функциях execCommand() (работающие тогда, когда у редактируемого блока установлен атрибут contenteditable=”true”). А также, устаревшая работа этих функций. Например, при выделении жирным шрифтом применение этой функции формирует теги <b>…</b>. А ведь уже лет 10 эти теги являются устаревшими (deprecated). Вместо них нужно <span style="font-weight: bold>...</span>.

Понятно, что такое преобразование пришлось производить вручную, уже после работы функции execCommand(). Да еще если выделенный диапазон включает в себя блочные теги, то пар тегов <b>…</b> образуется несколько. С одной стороны, это – удобно, но с другой – приходится вручную (уже циклом) заменять их на указанные <span style="font-weight: bold >...</span>.

Функции execCommand() ныне являются, вроде как, устаревшими. Пока они, конечно, работают и в новых браузерах тоже, но… в будущем могут перестать работать. Возможно, как раз по той причине, что они хотя и работают в целом приемлемо, но все же дают иногда досадные ошибки. Хотя, эти ошибки не критические и их вполне можно учитывать, делать для них, своего рода, патчи. Кроме того, их отклик (т.е. возвращаемые значения) - от слова не очень. Всего два - true или false.

Любопытно, что в некоторых случаях НЕКОТОРЫЕ пары тегов <b>…</b> НЕ заменялись на <span style="font-weight: bold>...</span>. Да, вот не заменялись, да и все, что тут скажешь; и ошибок не было. Пришлось делать повторную замену – для контроля…

То же касается, например, тегов <i>…</i> - выделение курсивом, а также тегов <u> и <srike> - все они являются устаревшими и вместо них рекомендуется использовать тег <span> с соответствующими свойствами. Т.е. для них тоже пришлось обеспечивать замену.

Если начинать выделение с НАЧАЛА абзаца – то именем контейнера (свойство commonAncestorContainer) является #text… а если НЕ с начала абзаца (например, со второго его символа) – то р, т.е. тег абзаца… (хотя, должно быть, вроде как, наоборот). Почему, я так и не понял, как ни пытался. Поэтому пришлось предусмотреть, своего рода, «костыль» для корректной обработки данной ситуации. 

Для тега, например, <code>...</code> (которым рекомендуется оформлять программный код) пришлось изощриться и использовать сначала вставку тегов <i>...</i> (так как функции execCommand() в браузере не работают для тегов <code>), а потом уже "менять" на <code>. Точнее, не менять (ибо просто замена имен тегов в браузере невозможна, ну, в моем, по крайней мере), а создавать новый тег, копировать туда html-содержимое, затем делать замену.

Или, скажем, такое. По стандарту html допускаются одиночные теги БЕЗ самозакрытия. Т.е. вместо <br /> (тег переноса строки) допускается <br>. Поэтому и сам браузер тоже (даже принудительно) преобразует их в некорректные (точнее, в не соответствующие строгому стандарту XHTML, который я стараюсь соблюдать). Поэтому и подобные теги тоже пришлось, перед сохранением редактируемого контента на сервере, преобразовывать обратно в, так сказать, канонические.

Почему крайне предпочтительно соблюдать строгий стандарт XHTML? Это не просто так. Дело в том, что следует ИЗНАЧАЛЬНО работать корректно. Потому что иначе в итоге, если привыкнуть работать тяп-ляп, рано или поздно накопится определенное, критическое количество ошибок и вот ТОГДА даже сложно будет исправить, тогда будет проще сделать все заново. Как конечный итог такой работы - человек дойдет уже до того, начнет смотреть лете-визор, станет членом какой-нибудь секты (например, свидетелей "короно-вируса") и т.д.
В этой связи очень показательны творения одного (***) под названием артемий лебедев. Есть такой нынче. Так вот, как она делает сайты. Бывает, тупо, в исходном коде пропускается строчек 30 пустых - чтобы валидатор не мог определить, корректный ли html код или нет. Ну, не знаю, как сейчас, а еще лет 7-10 назад я видел эти сайты - поделия (мне их показывали, слышал об их авторе со слов других людей). Самое интересное, что они еще и в браузерах открывались. Хотя, сделать корректную, строгую верстку - это вообще ничего сложного. Банально, я бы сказал.

Напомню, что нынче он - типа, директор по дизайну сети ВКонтакте. Любопытно, что у него еще и последователи есть.

Или такой "хак", который осуществляется браузером. Это когда в самый конец редактируемого абзаца еще добавляется и тег переноса строки. Его действие все равно не заметно, но он есть. Пришлось вручную (т.е. строкой $str = str_replace('<br /></p>', '</p>', $str); удалять их.

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

Ну, и т.д., и т.д. Просто масса всего такого, разных тонкостей. Естественно, делал все (точнее, почти все, что было возможно) кроссбраузерно, без этих разных "новых технологий", толком не работающих в хороших и удобных браузерах. 

Иной раз, когда обнаруживается очередная халтура от Яндекса, пишу им - мол, давайте переделаю вам, чтобы было и работало по-человечески. Даже денег не надо, сделайте (или давайте вместе сделаем) только, чтобы все корректно работало. Но, увы, лишь благодарят. И не всегда исправляют в итоге. Хотя, конечно, в целом - все более-менее работает.

Впрочем, НАКОНЕЦ-то они довели до ума капчу в электронной почте - теперь она вполне корректно работает. Спасибо. Кстати, это, похоже, их ноу-хау - такая капча. Это ГОРАЗДО продуманнее, чем разные катера/автомобили/мосты/... от Google.

Собственно, оно и неудивительно. Как только начинаешь что-то делать чуть больше, чем просто «типичная» функциональность – количество разных сложностей и тонкостей резко возрастает (как нынешний госдолг США или "патриотизм" россиян).

Попутно, добавил получение списка последних 10 измененных файлов (ибо, скорее всего, именно их может потребоваться редактировать). Ну, и связал с этим очистку html-кода после плагина docToHtml и копирования "сырого" текста из программы Word (это у меня уже и раньше было) в PHPStorm, к примеру.

Попутно, кстати, браузер хорошо подсвечивает (красными волнистыми линиями) незнакомые для него слова, видны многие грамматические ошибки.

Вот примерно как происходит процесс работы

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


Обновив карту сайта, выводится список последних 10 наиболее недавно измененных файлов. Кликнув по имени одного из них, получаем его html-код (только редактируемой области):


Код, по идее, был очищен ранее, так что более очистки не требуется.

Окраска кода – от слова не очень, т.к. я ее делал по-быстрому, сам, без использования библиотек.

Кликнув по кнопке «HTML», можно выделить его. Останется лишь скопировать его и вставить куда-то (например. в PHPStorm), при необходимости.

А если кликнуть по ссылке слева сверху – откроется эта страница в режиме редактирования (т.к. он – включен).


Пока, конечно, функциональность довольно скудная - та, которая для меня наиболее актуальна. Можно выделять текст жирным, курсивом, зачеркнутым, подчеркнутым; оформить текст как верхний или нижний индекс; вставить теги <code> (для оформления текста программного кода); заголовки (h1 - h5). 

Для них я решил НЕ плодить лишних кнопок. Сделал выпадающим списком, назначив обработчики событий onclick на соответствующие теги <options>. В итоге, получилось очень удобно: ровно два клика мышью - и выделенная фраза в редактируемой области становится заголовком выбранного типа.

Можно было, конечно, сделать и единый обработчик на общий тег <select>, но получалось как-то не очень: в итоге он срабатывал каждый раз при раскрытии списка. А мне нужно, чтобы обработчик срабатывал только после выбора того или иного пункта списка (в данном случае, определяющего тип заголовка; причем, это важно, обработчик должен срабатывать, даже если выбран тот же самый пункт, который был выбран раньше - последнее было бы невозможно, если бы я использовал событие onchange).

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

Так как после возникновения окна параметров ссылки и их редактировании выделение ее текста снимается, мне пришлось сделать фиктивное выделение - при помощи тегов <span>...</span>. Фон сделал специально близким, но не тем же самым цветом, чтобы можно было отличить это выделение от настоящего, но чтобы все же было понятно, что это - именно "выделение". Также можно убрать уже имеющуюся ссылку; при этом текст ее останется, а вот остальные параметры  (URL и title) исчезнут.

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


Скриншшот: шаблоны моего редактора html

В середине отображается шаблон с примером текста (окаймован синим фоном, для наглядности) точно так, как он будет выглядеть на вебстранице. Если нажать кнопку «Посмотреть теги», то серым цветом будут показаны ВСЕ теги, которые применены для создания этого шаблона (вместе со всеми атрибутами).

Справа приведена только разметка этого шаблона, без примера текста (текст автоматически вырезается, чтобы потом не копировать его). Одинарный клик по шаблону, во-первых, переместит его в верх на странице шаблонов, чтобы он был по-виднее. Кроме того, одинарный клик выделяет его, обозначая среди всех остальных шаблонов (я сделал выделение толстой тенью синего цвета). Двойной клик по шаблону выделит его разметку. И после копирования она может быть вставлена в любое место html-кода в том или ином текстовом редакторе, например, в PHPStorm. Т.е. чтобы вставить шаблон на редактируемую страницу (в визуальном режиме), можно поступить тремя путями:

  1. Либо сделать ДВОЙНОЙ клик по шаблону, затем скопировав (нажав Ctrl + C или как-то иначе) не собственно его, а лишь его html-разметку; потом ее можно вставить в текстовый редактор, типа Notepad++ или PHPStorm. Также разметку можно также вставить и в какую-нибудь статью в режиме редактирования, если потребуется именно описать разметку того или иного шаблона, а не использовать ее для оформления.
  2. Либо сделать ТРОЙНОЙ клик по шаблону и затем уже его непосредственно (т.е. визуально) скопировать в буфер обмена. Далее можно закрыть панель с шаблонами и, перейдя к редактируемой области, сделать вставку из буфера (Ctrl + V). Шаблон вставится визуально (а не в виде html-кода, как при копировании после ДВОЙНОГО клика).
  3. Либо просто нажать кнопку «Вставить» (этот слева наверху, где изображен портфель с листом бумаги – типичный значок для операции вставки; раз уж я делал для себя - то постарался найти достаточно красивую, на мой взгляд, иконку для этого, а не ту мерзость, которая продвигается разного рода артемо-лебедевщиной и пр.). При этом панель шаблонов закроется, а шаблон, по которому кликнули, автоматически вставится в то место редактируемой области, где стоит (стоял) курсор. При этом фокус (курсор) будут перемещен в начало шаблона, т.е. останется только начать набирать текст или вставить что-то еще. Кстати, если курсор стоял посередине абзаца, этот абзац будет поделен на два абзаца и шаблон будет вставлен между ними. Это, конечно, стандартная функциональность функции execCommand().

Далее можно вводить в шаблон текст и т.д.

Добавление новых шаблонов верстки у меня тут хотя и не автоматизировано (ибо, все-таки, они появляются довольно редко), но делается очень легко. Нужно просто открыть файл с шаблонами и вставить туда соответствующую разметку (которая, конечно, должна быть качественной, т.е. корректной с точки зрения XHTML, кроссбраузерной - вплоть до IE10...11 - и адаптивной), задать название (оно потом отобразится выделенным зеленым цветом, как на рисунке выше). И всё, редактор потом сам отобразит этот шаблон в перечне шаблонов, потребуется только выбрать необходимый.

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

Также решил реализовать возможность редактирования метатегов (ну, основных), та ще тега <title>. Практически все метатеги, за исключением тех, которые редактировать уж точно не придется. Их редактор берет самостоятельно из раздела <head> и затем их наименования приводятся в панели (окне), где их значения можно редактировать. Вот примерно так это выглядит:

Именно для title я сделал также возможность добавления его на страницу, если его вдруг там еще не было и он необходим. Также сделал для него отдельную кнопку "Изменить" - для того, чтобы можно было увидеть его изменения без сохранения на сервере. По идее, это все уже в последние годы необязательно (за исключением title, конечно; хотя, кое-кто не делает и его тоже). Типа, поисковые системы и так, мол, все распознают, "не обращая внимания на метатеги".

Это, конечно, любопытно, но есть нюанс. Наоборот, в последние годы внедряется микроразметка (уже очередного, нового типа). Это однозначно означает, что поисковые системы таки все еще НЕ МОГУТ правильно классифицировать вебстраницы, исходя только из их содержимого (контента). Ну, а иначе зачем микроразметка-то? Ведь это - полный аналог метатегов, только в чем-то - более детальный. А это, в свою очередь, означает, что все их "искусственно-интеллектуальные" системы анализа текстов - это, как бы сказать. В основном, лишь много болтовни, да и всё (не удивлюсь, если это - исключительно ради получения финансирования, например, со стороны конгресса США). Ну, как и с этим, "короно-вирусом"-то. Особенно, конечно, в этом отношении любопытен Google: там уже практически НИЧЕГО невозможно найти, ну, за исключением чего-то уж очень распространенного.

Т.е. сказать что, мягко говоря, УДОБНО - это ничего не сказать. ОЧЕНЬ УДОБНО стало. Пару кликов мышью - и требуемая разметка появляется на вебстранице. Остается лишь добавить в нее текстовый контент, ну, и сохранить вебстраницу. 

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

А это не есть хорошо для зрения. Тоже вот надо что-то думать, как улучшить эргономичность... Вплоть до того, чтобы хотя бы основным кнопкам назначить, скажем, обработчики нажатия клавиш малой клавиатуры (той, которая находится справа).

Наверное, в профессиональных редакторах типа DreamWaver, а также в конструкторах сайтов такая функциональность также есть.

Ну, а продолжать редактирование, как обычно. После чего – нажать кнопку «Сохранить изменения». Если все нормально, ошибок не было, то содержимое редактируемой области будет записана в файл, содержащий html-код редактируемой вебстраницы.

Если будут ошибки – они появятся либо в стандартных сообщениях (alert() ), либо в панели редактирования слева.

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

Я специально выбрал скриншот с большими числом тегов разной степени вложенности. Все теги, имеющиеся внутри элемента, на который наведена мышь, будут показываться полупрозрачным серым цветом фона. И чем больше степень вложенности, тем более темным будет фон. Это, кстати, сделал при помощи встроенного в javascript итератора (Iterator), который как раз и предназначен для таких целей, т.е. для рекурсивного обхода всех узлом того или иного (под)дерева DOM. В этом режиме, если навести указатель мыши на участок редактируемой области (тег), то появятся его теги БЕЗ текстового контента. Причем, ТОЛЬКО его теги. Если нужно посмотреть теги того или иного вложенного узла - нужно переместить указатель мыши к нему. Режим подсветки тегов должен быть, разумеется, включен. 

Если затем кликнуть по появившемуся окну с тегами (желтого цвета), то уже закрепится и не исчезнет при перемещениях мыши, пока его не закрыть (нажав на крестик, ОК или клавишу Escape). Ну, или пока страница не будет обновлена.

Здесь можно подправить конкретный тег (БЕЗ его текстового содержимого, т.к. последнее удобнее править непосредственно, без всплывающего окна; это чтобы текстовое содержимое не мешалось и не отвлекало внимание), а также, например, убрать, исправить или добавить класс, стиль, другой атрибут. Это если неохота лишний раз переключаться в окно с редактором (типа PHPStorm) и искать там соответствующее место для исправления. Все-таки, непосредственно в браузере, когда все видишь, как оно должно выглядеть, делать это проще и быстрее. Правда, нет автокомплита (хотя, контроль совпадения левой и правой частей тега я сделал). И, конечно, тут возможности довольно ограничены. Но, зато быстро и непосредственно, визуально. Это если так, что-то по-быстрому подправить, РАЗУМЕЕТСЯ, не вдаваясь в серьезное изменение верстки.

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

Отдельно по поводу тега <br>. Он ведь - пустой и, пожалуй, единственный (за исключением тегов типа <script>), который не принимает практически никаких атрибутов, т.е. ему невозможно назначить стиль (формат отображения). Как его показать на странице врежиме подсветки? Ну, пришлось мне в итоге временно преобразовывать его в обычный <div> с определенным классом - пока включен режим подветки. А уже для этого тега задаю стиль - чтобы его было видно в режиме подсветки. Внутрь этого тега я помещаю, на запас, тот самый <br> - чтобы потом извлечь его обратно и поместить туда, где он был раньше -  когда режим подсветки будет выключен.

Возникла проблема с пустыми тегами - ведь они незаметны на странице в визуальном режиме. Решил ее так: в режиме подсветки тегов (выборочном или полном) добавил специальный формат для каждого тега: принудительно задал левую и правую границы, а также левые и правые внутренние отступы (padding). Это позволило визуально видеть почти все теги, даже и пустые. Правда, те, в которых назначено display:none заметны все равно не будут. И, разумеется, не будут заметны теги <script> (хотя, последних не должно быть в пределах редактируемой области). 

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

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



Также добавил, по аналогии со ссылками, возможность редактирования параметров рисунков. Нужно дважды кликнуть по рисунку - и возникнет аналогичная панель для редактирования его параметров. При этом, если изменить src (задающий URL рисунка), то при нажатии кнопки "ОК" рисунок автоматически изменится на тот, который соответствует новому src. Основные атрибуты разместил в начале окна (как на скриншоте), а остальные, если они есть, идут ниже.

Правда, пока вот с (подрисуночным) текстом не пойму - как быть. Дело в том, что текст у меня в шаблоне рисунка идет в отдельном теге (span). Однако, в будущем вполне могут быть другие шаблоны, содержащие текст в другом теге. И придется реализовывать уже дополнительную функциональность по работе с подрисуночным текстом. А вот как сделать универсально - пока не пойму.

Хотя, конечно, по уму-то надо бы использовать соответствующие теги html5 - тогда и проблем не будет.

Автоматический запуск редактора Notepad++ прямо из браузера (в 1 клик)

 

И, НАКОНЕЦ-то(!) я, во-первых, додумался, что так можно сделать (хотя бы теоретически), а, во-вторых, реализовал это, т.е. запуск текстового редактора прямо из браузера. А раньше даже как-то в голову не приходило, что можно сделать такое.

Сам придумал так сделать (хотя, возможно, где-то это уже используется). Ну, так как PHPStorm запускается очень медленно, ждать придется долго, то использую Notepad++. Это, собственно, следовало сделать еще много лет назад - оказывается, настолько удобно, существенно экономит время и усилия. Т.е. нажимаешь кнопку на панели управления редактора (на редактируемой странице) и через пару секунд запускается Notepad++, причем он сам автоматически открывает редактируемый файл (если тот еще не был открыт), и сам же перелистывает его к той самой строчке и к  той самой позиции, на которой произошел последний клик мышью в браузере (если он был в пределах редактируемой области). Это, собственно, СТОИТ ТОГО.

Иными словами, если требуется более тщательное редактирование HTML-кода (например, добавить разметку, которая не предусмотрена моими шаблонами), если не хватает возможностей моего редактора - то тут же этот код можно открыть в Notepad++ по нажатию соответствующей кнопки, в 1 клик. И, что самое главное - НЕ НУЖНО теперь лазить по всему коду и искать требуемое место: как правило, курсор сам устанавливается там, где он и находится в браузере. И переходить к другому месту редактирования, опять-таки, гораздо удобнее именно в браузере (потому как визуально виден текст, без разметки и тегов), а уж потом, нажав кнопку, браузер даст команду редактору Notepad++, а тот уж САМ запустится, откроет указанный файл, если он еще не был открыт и, с учетом переданных ему параметров при запуске, перелистнет этот файл именно туда, где стоит курсор в браузере. Именно в той самой позиции.

Пока реализовал это только для Windows, но и в Linux это тоже будет работать, просто надо будет добавить одно условие и еще одну строчку кода. Ну, пока не стал этим заниматься. Правда, там вместо Notepad++ придется использовать Notepadqq. И я даже пока не знаю, можно ли его там запускать так, чтобы он сам открывал требуемый файл и сам же перелистывал его именно к тому месту, на котором находится курсор (фокус) в браузере.

Иконку (значок) для Notepad++ в итоге взял тупо копированием скриншота открытого этого редактора. Бо, честно говоря, разного рода зеленых мышей, грызущих что-то там, как-то не хочется отображать. Уж тут хоть так, хоть  эдак посмотреть. А этот значок - вполне себе, да и знакомый.

Честно говоря, вначале хотел сделать более детальный редактор HTML-кода тоже через браузер, через свой редактор. Тем более, что у меня, по сути, есть возможность для этого - как показано на 2-м (вроде) скриншоте. Осталось только сделать эту область редактируемой, улучшить подсветку тегов и кое-что еще. Но, суть-то в том, что ВСЕ РАВНО придется отвлекаться (переводить взгляд) от визуального редактирования и переходить к непосредственно HTML-коду. А раз уж так - то с точки зрения визуальности нет никакой разницы, на что отвлекаться: на другую вкладку в браузере или на окно Notepad++. При том, что последний, разумеется, обладает более высокой функциональностью по сравнению просто с режимом contenteditable="true".  Там все сделано уже до меня. Поэтому, конечно, запуск Notepad++ - гораздо эффективнее. Так что, думаю, этим решится и проблема, скажем, с заполнением подрисуночной подписи и т.д. Тем более, что ее не всегда нужно бывает заполнять.
Кстати, чтобы реализовать запуск Notepad++ и перемещение курсора в открываемом файле именно в то место, пришлось, мягко говоря, повозиться. Потому что браузер преобразует содержимое тегов, по крайней мере, так, что при этом удаляются лишние пробелы. Это делается автоматически посредством свойства innerHTML и ничего тут не поделаешь. И именно в этом, преобразованном содержимом-то и определяется позиция курсора в браузере. И именно она передается серверу для того, чтобы он, в свою очередь, запустил Notepad++ с этим параметром. Однако, на сервере-то может храниться исходный вариант файла, где эти лишние пробелы не удалены. В итоге - позиция курсора в Notepad++ по горизонтали (число колонок-символов) будет заниженная, не соответствующая позиции курсора в браузере. И выход тут, пожалуй, один: взяв сервером соответствующую строку из файла, проделать с ней те же самые манипуляции по удалению пробельных символов, по аналогии с браузером, посчитать, сколько их удалилось в итоге - и уже с учетом этого определять позицию курсора в данной строке. Именно так я и сделал.
В свое время я долго думал, как получить в браузере "сырой" текст вебстраницы. Т.е. без учета манипуляций браузера по удалению лишний пробельных символов, закрытию тегов, которые не были по ошибке закрыты и т.д. Вроде бы, получить его нельзя, так как браузер обязательно проделает все перечисленное ПЕРЕД тем, как построить DOM. А javascript работает уже с ГОТОВЫМ DOM, т.е. с преобразованным. Спрашивал на форумах - но там помалкивали на этот счет. Я уж начал было думать в сторону плагинов к браузеру или промежуточных прокси-серверов...

А недавно, уже в ходе работы над своим редактором, наконец, придумал способ. Это - получение "сырого" html-кода из ответа на запрос AJAX. Т.е. можно сделать запрос на получение (повторно) кода всей страницы, но не давать браузеру его преобразовывать в DOM. В итоге сервер отдаст код страницы, который появится в переменной xhr.responseText. Т.е. там появится именно тот самый "сырой" текст, без каких-либо преобразований. Со всеми лишними пробелами, незакрытые теги не будут закрыты и т.д. Чтобы браузер начал преобразовывать его в DOM, это еще нужно записать полученный сырой текст в какой-нибудь блок (<div> или т.п.). А если там еще и скрипт - так его требуется вначале еще и "приживить" на странице, чтобы он заработал. Но, можно и НЕ записывать, а работать с полученным текстом БЕЗ использования свойств и методов DOM, как с обычной строкой (или используя их выборочно, не ко всему тексту). Например, с применением регулярных выражений. Это, конечно, трудоемко, но зато максимум возможностей.

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

Посмотрел - только один файл (основной) с javascript-кодом занимает "всего" 200+ кБ. На сегодня там - более 4 тыс. строк. Все кроссбраузерно, по идее, должно работать чуть ли не в IE11.

Открытие рисунка в графическом редакторе Paint

Раз уж, как говорится. Раз уж с текстом получилось столь удобно - то сделал аналогично и для рисунков. Судя по всему, нет смысла делать "комбайны", которые позволят редактировать графику (рисунки) прямо в браузере (разве что, для совсем уж мелких исправлений). Можно, но не нужно. Поэтому решил я сделать аналогичную функциональность, как и для редактирования текста в Notepad++, в отношении рисунков (пока - только растровых). Если кликнуть по какому-нибудь рисунку, присутствующему на редактируемой странице, а потом нажать кнопку с изображением иконки (значка) Paint, то соответствующий файл рисунка будет открыт в нем. При условии, конечно, что этот файл присутствует на сервере, т.е. сохранен. А то ведь могут быть и иные варианты: например, src рисунка может вести на сторонний сайт, либо рисунок может быть сохранен прямо в теле страницы (по протоколу data:). 

С этим, кстати, пришлось повозиться тоже, но с другой стороны. Интересно, что, в отличие от Notepad++, редактор Paint ведет себя несколько странно. Пока его окно (с загруженным рисунком) не закрыто, скрипт РНР зависает и прекращает выполнение (с Notepad++ таких проблем нет). И ждет либо до момента закрытия Paint, либо до истечения максимального времени (в Denwer у меня по умолчанию установлено 30 сек.). Это не то, чтобы мешает, но как-то некорректно. Смотрел-смотрел я возможные решения (stackoverflow.com и т.д.) - и толком ничего не нашел, за исключением такого, которое и в самом деле заработало. Перед выполнением команды по открытию Paint вначале создается временный shell-файл, в него записывается команда, затем он выполняется и сразу же после этого удаляется. Так как вывод-то направляется теперь не в РНР, а в CMD (командная оболочка Windows), то все хорошо: PHP продолжает выполнение сразу после того, как запустит CMD. Ну, а CMD, выполнив команду открытия Paint, прекращает работу. А уж что там делает Paint, как он взаимодействует с CMD - этим РНР уже не озабочивается, не ждет результатов его работы.

Понятно, что это - костыль (очередной), но все остальное, в том числе с перенаправлением вывода команды exec() (как рекомендуется в мануалах РНР), увы, неработоспособно именно в данном случае. У меня, по крайней мере. Пытался даже сделать таймер, по той аналогии, как утверждалось, которая применяется во фреймворке Sympfony - не получилось, тот же самый результат. Т.е. таймер-то работает, все хорошо, но скрипт РНР все так же ждет, пока окно Paint не будет закрыто. То ли это потому, что Paint, в отличие от Notepad++, является предустановленной, "родной" для Windows программой (и, возможно, она как-то по-особому контролируется системой), то ли не знаю, почему. Ну, да ладно. Пусть и через костыль, но все работает.

В кабине нет шофера,
Но троллейбус идёт;
И мотор заржавел, но мы едем вперед.

В. Цой.

Cобственно, будь оно С/С++, я бы давно и легко вышел из положения. Но, на РНР всё несколько более ограниченно... Тут, конечно, тоже есть, к примеру, потоки, но.

Ну, и еще, до кучи, как говорится, сделал еще и возможность открытия каталога, содержащего рисунок или саму вебстраницу, в проводнике Windows. Это бывает полезно, если требуется задать уникальное имя для рисунка, когда оно похоже на уже имеющиеся имена. Т.е. надо кликнуть, например, по рисунку, потом - нажать соответствующую кнопку. После чего запустится проводник (Explorer), в нем откроется каталог, содержащий рисунок; сам он в списке файлов будет выделен.

Сохранение и загрузка рисунков

Я раньше делал это по-старинке. Т.е. сохранял файл рисунка в каком-нибудь графическом редакторе (обычно Paint - он идеален для этого, если не требуется серьезная работа с рисунком - очень легкий и быстрый).

Правда, в новых его версиях, к сожалению, сверху идет весьма широкая панель управления с кнопками. Которые расположены в два и даже в три "этажа". Да еще между ними - определенное расстояние. Да еще внизу - информационная строка. В итоге - по высоте занято 25% экрана. Очень неудобно. Примерно как в "новом" Word (это который сохраняет файлы с расширением .docx) - именно поэтому я им вообще не пользуюсь, использую Word 2003 и (очень редко) Word 1997.

Вот в GIMP в этом плане гораздо удобнее: управляющая панель находится слева и ее можно передвигать.

А потом в html-коде, в теге img, прописывал src для него. А сейчас - решил упростить. Теперь я просто вставляю шаблон (html-обертку) с рисунком там, где требуется. Изначально там - стандартный рисунок (фавиконка редактируемого сайта). Затем, кликая по ней, просто вставляю туда (через Ctrl + V или как-то иначе) рисунок из буфера обмена. Заранее скопированный туда из того же Paint, скажем. Или откуда-то еще. И все, после сохранения изменений рисунок будет сохранен в html-коде страницы. Правда, как правило, предварительно он будет там в виде data:image/png;base64,iVBOR... и т.д. И в соответствующем каталоге рисунков его пока не будет. Для того, чтобы рисунок присутствовал не в коде страницы, а именно в отдельном каталоге (и был доступен для других страниц сайта), сделал его сохранение и замену src на типичный, вида http://site.ru/dir/.../pic.png. Т.е. во всплывающем окне нужно задать имя (pic.png), после чего рисунок (после проверок на корректность) сохраняется на сервере и при этом в html-коде странице src заменяется на соответствующий.

Правда, с рисунками, точнее, со вставкой их из буфера обмена непосредственно на страницу, открытую в браузере, возникли определенные сложности. Оказывается, ЕСТЬ разница, откуда был скопирован (в буфер обмена) рисунок - в зависимости от этого он вставляется по-разному. Так, если скопировать его, скажем, из Paint, то он вставится по протоколу data:. А если скопировать с сайта (тоже открытого в браузере) - так он вставится с соответствующим src и, что самое главное, СО ВСЕМИ атрибутами. В том числе и с обработчиками JS, разумеется. Правда, как пишет Mozzilla, на первое время эти обработчики сработать не должны. Но, ведь это - редактор. Т.е. при сохранении страницы и последующем ее обновлении обработчики уже вполне себе сработают. Т.е. это - огромная брешь в безопасности.

Любопытно, еще когда я разрабатывал себе простенький графический редактор для рабочего сайта для студентов (salimonenko.pw), так там при попытке вставки в <canvas> рисунка, скопированного с ДРУГОГО сайта, браузер молча блокировал эту операцию в целях безопасности (да, как раз для того, чтобы на страницу вдруг не попали опасные атрибуты рисунка). Поэтому приходилось вначале вставлять его, скажем, в Paint, а уже оттуда копировать и вставлять в <canvas>. А вот через execCommand() рисунок вполне вставляется даже и с другого сайта. И если разработчик этот нюанс не предвидел и не обработал - рано или поздно с сайтом может быть очень нехорошо...

Поэтому пришлось перехватывать событие вставки (paste), а затем долго и нудно обрабатывать разные возможные варианты вставки, в зависимости от содержимого буфера обмена. И не только для рисунков, но и для текстовых данных (потому как там тоже могут присутствовать обработчики событий JS). Вот такие (это что-то типа ТЗ для себя):

* 1. Вставку чистого текста (с юникодом), без HTML                     : Текст (с entities)
* 2. Вставку HTML (с юникодом) с редактируемого сайта                  : HTML и текст (с entities) (на выбор)
* 3. Вставку HTML (с юникодом) с другого сайта из текущего браузера    : Текст (с entities)
* 4. Вставку HTML (с юникодом) из ДРУГОГО браузера                     : Текст (с entities)
* 5. Вставку HTML (с юникодом) из PHPStorm/Word (цветной текст)        : Текст (с entities)
* 6. Вставку HTML-подобного текста (с юникодом) (код HTML)             : HTML и Текст (с entities) (на выбор)
* 7. Вставку рисунка, скопированного с текущего сайта                   : <img src="http://domen/...  >
* 8. Вставку рисунка, скопированного с другого сайта                    : <img src="data:...  >
* 9. Вставку рисунка, скопированного из Paint, Word                     : <img src="data:...  >

Юникод я не использую (ибо пока что не доверяю ему), поэтому преобразую его в html-entities. Вот столько вариантов тестирования приходится тестировать. Ну, понятно, что один раз делается.

Кстати, о непосредственной вставке рисунков на страницу. Т.е. из буфера обмена. Речь здесь веду о Windows, как оно будет в Linux - пока не знаю. Как я выяснил путем экспериментов, корректно вставляются лишь рисунки из графических редакторов (типа Paint), через скриншот (RrintScrn) или из браузера (с текущего или иного домена). И из pdf-файлов тоже, вроде бы, рисунки вставляются корректно. А вот вставка рисунка из Word вызывает проблемы. А из Excel рисунок и вовсе не вставляется вообще.

Поэтому пришлось делать обработчик события paste, т.е. перехватывать процесс вставки из буфера обмена и перед тем, как разрешить вставку на страницу, вначале анализировать его содержимое. Да еще эта особенность браузеров Firefox (по крайней мере, тех, которые я использую) - там НЕТ такого типа данных, взятых из буфера обмена, как "image/png". Т.е. браузер рисунок-то вполне может вставить на страницу, да вот только перед вставкой никоим образом не дает выяснить, рисунок ли это вообще. Это, кстати, известный баг и он обсуждался разработчиками Firefox лет 10 назад.

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

Например, при вставке рисунка с другого домена браузер (Firexox) выдает Seruriry error и всё. А при вставке из Microsoft Word рисунок появляется в html-коде редактируемой вебстраницы... по локальному протоколу file:///. А это означает, что он НЕ будет доступен скриптам JS. Потому как такова политика безопасности (мало-мальски любого) браузера.
Вот прямо сейчас пишу и подумалось: это если только сообщить серверу этот самый (локальный) путь, при его наличии. А уж сервер, если найдет этот рисунок в файловой системе, проверит его на корректность, а потом, если сочтет нужным, извлечет его и пришлет браузеру. А последний, в свою очередь, вставит рисунок на страницу (которая, в свою очередь, может быть сохранена на сервере обычным образом)... М-да...

В Linux (в частности, в Firefox 68), рисунок вставляется примерно так же - в виде абсолютного пути, НО не на некий временный файл в где-то в каталоге Temp (как в Windows), а на сам файл рисунка. Любопытно, что точно так же вставляется и абсолютный путь к видео (если последнее предварительно скопировать, как файл целиком).


Пришлось реализовывать тестовую вставку содержимого буфера обмена на <canvas> - чисто для проверки, корректный ли там содержится рисунок или нет - обернув все это в try-catch. И только если все хорошо - уже потом вставлять, собственно, рисунок туда, где находится курсор или где выделен текст (в пределах редактируемой области). Такой вот обходной, но вполне рабочий путь. И, главное, - кроссбраузерный и универсальный путь. Обходной - значит, универсальный. В данном случае.
Это уж я придумал путем перебора разных вариантов - чтобы сделать обязательно кроссбраузерно. Чтобы без проблем работало в браузерах, по крайней мере, сделанных лет 10 назад.


Любопытно, что в зависимости от того, копировать ли содержимое графического файла из Paint целиком (после выбора команды "Выделить все") или только часть, выделив ее мышью, как бы рамкой, наблюдается разное время вставки рисунка в canvas (в первом случае - больше). Так как рисунок вставляется не сразу, приходится ждать, пока это произойдет, поэтому я сделал соответствующий таймер. Я поначалу установил задержку времени в 100 мс, так она оказалась слишком мала, если вставлять изображение целиком; пришлось сделать 300 мс. Почему такое наблюдается - так и не понял. Видимо, какие-то низкоуровневые особенности работы Paint.
А без таймера не обойтись, т.к. вставка рисунка может вообще никогда не закончиться, поэтому требуется задать определенное разумное время ожидания. И если такое время превышено - выдается соответствующая ошибка.

А еще есть видео и иные ресурсы, по идее... Да еще что понимать под термином "текст": он с html-сущностями (типа &lt;), или с их символами? Да еще, чтобы было кроссбраузерно. Потому как эти новые современные браузеры мне... НУ, НА ДУХ ДАЖЕ НЕ НАДО.

Использую, конечно, иногда Edge (или относительно новый Firefox) для "особенных" сайтов, но делаю это с определенной брезгливостью.
Т.е. еще раз. Переход на новые (и новые, и новые, и т.д.) программы, в частности, браузеры НЕХОРОШО отражается на зрении. Потому что каждый раз приходится привыкать к новым очертаниям и цветам кнопок, панелей и т.д. А перед этим приходится вглядываться в них. В общем-то, пристальное вглядывание во что-то, например, в элементы дисплея/монитора - это один из самых верных путей угробить зрение. Еще надежнее действует, разве что, СВЧ-излучение. Ну, или если постоянно сыпать в глаза пыль и т.п.

Т.е. дело тут не столько в привычке и уж отнюдь не в "нежелании освоить новое", а в банальном желании самосохранения. Кому как, ну, а для меня таки важно сохранить и улучшить зрение. Но, вот как это донести до современных бездельников (которые делают НЕкроссбраузерные сайты) - даже ума не приложу... Говорить-то им об этом, за редким исключением, бесполезно. Хотя, немало и тех, кто это всё понимает.

Кроме того, новые браузеры обладают некоторой мешающей мне функциональностью. Например, относительно новый Firefox при каждом запуске выдает всплывающее окно с вопросом об обновлении браузера. И отключить появление этого окна, судя по всему, нет возможности (в отличие от старых версий Firefox). Ну, и т.д. Не говоря уж об отвратительном дизайне (от которого реально воротит) браузеров типа Edge или Google Chrome. Не говоря уж о сверхрасходе оперативной памяти и иных ресурсов компьютера у того же Edge по сравнению, к примеру, с Firefox 24.
Насчет же желания глаз видеть красивые, новые изображения, обстановку - это совсем про другое. Это хорошо где-нибудь в картинной галерее. Да или просто на улице, в конце концов. В лесу там, на море, в горах, еще где. Но не при работе с компьютерными программами.

Попутно, уже в процессе использования редактора, я обнаружил потребность - выбирать/заменять ссылку на рисунок не вручную, а "визуально". Т.е. вывел список рисунков на экран (по типу, как в Проводнике Windows, к примеру), кликнул по строчке с нужным именем - и ссылка на этот рисунок вставилась на страницу. Для этого я добавил функциональность.

 

Например, изначально рисунок представлял собой фавиконку этого сайта (как на скриншоте). Но, нужно заменить рисунок на другой, имеющийся в том или ином каталоге сервера. Например, на изображение обложки книги Бейтса.

При нажатии на соответствующую кнопку возникает дополнительное окно (или панель - как правильно назвать), содержащее список каталогов и файлов (только рисунки), содержащиеся в целевом каталоге для рисунков (img) для редактируемой страницы. Там можно найти требуемый файл. После клика по нему ссылка на него автоматически вставится в поле "src". И после нажатия кнопки "ОК" на странице будет отображаться уже тот рисунок, имя которого было выбрано. Для контроля, в окне справа наверху отображается уменьшенное изображение выбранного рисунка (в данном случае - фотография обложки книги Бейтса). 

Можно, как обычно (в Проводнике, к примеру), кликая по именам каталогов, переходить в них - вплоть до корневого каталога сервера (при этом с сервера будет передаваться список файлов-рисунков и каталогов соответствующего каталога, в который был совершен переход).

Точнее, по имени которого был сделан клик мышью. Это дает возможность, попутно, просматривать через браузер миниатюры рисунков примерно так, как в Проводнике Windows (там миниатюра рисунка, который выделен в панели Проводника, видна внизу слева).

Это, кстати, оказалось очень полезным для вставки рисунков SVG, ранее сохраненных на сервере. Сделал было еще вывод миниатур ВСЕХ рисунков, содержащихся в текущем каталоге (как в Проводнике Windows 7 в режимах просмотра Обычные значки, Крупные значки) , но оказалось, что при достаточно большом их количестве (более нескольких сотен) эта операция происходит довольно медленно. Ведь при этом нужно открыть КАЖДЫЙ рисунок, сделать его миниатюру (tbumbnail) и отправить браузеру. Все-таки, РНР - это не самый быстродействующий язык. И ему, разумеется, не угнаться за С++ (на котором сделан Проводник). Не говоря уж о некоторых низкоуровневых нюансах.

Можно, конечно, как-то индексировать и заранее создавать эти миниатюры... А можно и не делать такую функциональность и выводить миниатюру только того рисунка, по имени которого (в списке, как на скриншоте) был сделан клик. Что я и сделал.

Вставка рисунков SVG

С растровыми рисунками получилось более-менее. Т.е. можно вставить скриншот или из графического редактора что-то. По желанию, можно рисунок так и оставить внедренным на странице (т.е. у него будет src="data:image..."), и можно сохранить в каком-нибудь каталоге для рисунков. Последнее делается в несколько кликов. Не надо искать каталог для них, т.к. редактор сам предлагает ближайший каталог (в зависимости от URL редактируемой страницы). Или можно вставить рисунок с src в виде ссылки. Это - рисунки вида gif, png, jpg и т.д.

А вот с svg (векторный рисунок) пока даже не знаю, как быть. Во-первых, они копируются по-разному, в зависимости от того, в каком виде присутствуют на странице: в виде <img src="http://site.ru/svg/pic.svg" />, в виде <object onload="init()" type="image/svg+xml" data="http://site.ru/svg/pic.svg"></object> или встроены прямо на страницу, например:

<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 248 248" version="1.1">
    <g id="icon" transform="translate(0,-804.33071)">
 <path d="m76.4 1042.7c-2.2-0.2-4.7-0.7-5.6-1-0.8-0.3-9.3-2.9-18.9-5.6-9.6-2.8-17.5-5.1-17.5-5.2-0.2-0.2 2.3-42.5 2.9-48.1 2.3-21.6 6-32.2 14.9-41.6 7.6-8.1 14.9-11.8 27.5-13.7 5.5-0.9 39.4-1.2 47.6-0.5 13 1.1 21.3 3.1 29.1 6.9 3.9 1.9 5.5 3.1 9.1 6.7 9.4 9.4 13.8 22.4 15.9 47.4 1.2 14 2.5 42.6 2 43.1-0.9 0.9-17.7 5.6-23.4 6.5-20.4 3.4-70.3 6.5-83.6 5.1z" />
        <ellipse cx="107" cy="883.1" rx="40.7" ry="38.3" />
    </g>
</svg>

Последние еще и не скопируешь просто так, требуется смотреть исходный код и копировать уже оттуда. Т.е. не визуально копировать (кликнув перед этим по рисунку мышью), а в виде кода. "Стандартно" (через Ctrl+C) скопировать и потом вставить на страницу (Ctrl+V) можно лишь svg первого вида. Т.е. просто так, не раздумывая, рисунок svg, получается, на редактируемую страницу не разместить.

Ну, думал сделать так: парсить сервером вебстраницу, на которой находится интересующий меня рисунок. Затем - вырезать из ее html-кода все, что относится к svg и отдавать браузера, на редактируемую страницу. А уж там, после клика на понравившийся рисунок - он бы встраивался в html-код страницы, ну, и сохранялся потом, как и растровые рисунки. Но, для этого пришлось бы копировать URL вебстраницы, на которой находится svg-рисунок и вставлять его в соответствующее поле формы на редактируемой странице (чтобы потом она отослала URL на сервер и т.д.). Т.е. несколько лишних кликов сделать бы таки пришлось... как-то волокитно.

Еще возможный вариант: запускаю на странице, где есть нужный мне svg-рисунок, букмарклет, который просматривает ее исходный код, вырезает из нее все, что относится к svg, собирает в массив, затем в JSON.stringify и, окончательно, создает где-нибудь посередине страницы окно, туда вставляет полученный JSON и выделяет вставленную строку. Останется сделать Ctrl+C. Затем - вернуться на редактируемую страницу, там сделать Ctrl+V в определенном месте, после чего появятся те рисунки, которые содержались в JSON. И уже после этого - выбрать нужный рисунок и нажать кнопку "Сохранить". Это - тоже как-то волокитно.

А потом, когда начал потихоньку реализацию, отчетливо понял, что так делать НЕЛЬЗЯ. Ведь svg - это разметка. И вот что может быть скопировано с чужого (не со своего, т.е.) сайта:

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg version="1.0" xmlns="http://www.w3.org/2000/svg">

...

</svg>

<?$xml; $version="1.0"; $standalone="no"?>

Как видно, первая и последняя строчки ОЧЕНЬ сходны. Однако, первая означает начало файла XML (например, svg), а вот последняя - код PHP......

Какого чёрта разработчики языка РНР, в угоду современным веб-бездельникам, в дополнение к стандартному оформлению тегов РНР <?php ... ?> сделали еще и укороченный (чёрт бы побрал их, а также всех остальных любителей укороченного синтаксиса) в виде <?... ?> - я, честно говоря, так и не понял. Видимо, от совсем уж нечего делать. А в итоге эти теги стали напоминать обозначение начала, первой строки файла XML, их легко перепутать. Т.е. - очень легкая возможность внесения уязвимостей на редактируемый сайт. В 1 клик, как говорится.

Т.е. я к тому, что просто так, без тщательного просмотра, svg-код вставлять на вебстраницу НЕЛЬЗЯ. Перед вставкой его необходимо тщательно просмотреть на предмет наличия подобных нюансов и иных нехороших вещей. Ну, а раз так - то и нет смысла реализовывать способ его визуальной вставки из буфера обмена (или т.п.). Тогда уж проще, если надо, посмотреть исходный код целевой страницы, найти нужный svg, внимательно посмотреть его outerHTML, затем скопировать, ну, и вставить на редактируемую страницу. Т.е. это как раз тот случай, когда облегчение работы, удобство может очень сильно навредить.

Также сделал вставку спецсимволов

Ну, таких, которых нет на клавиатуре. Вот таких. Это - разного рода стрелки, математические символы, греческие буквы и т.д. т.е. понятно, что можно (как я раньше и делал) открыть ту страницы с символами (по ссылке), выбрать нужный, а потом - вставить на страницу через Ctrl + V, например. Это вполне можно, но требует ряд действий. Поэтому я сделал попроще: чтобы нажал кнопку - открылось всплывающее окно (панель) со спецсимволами. А там уже, только выбрал нужный символ - как он уже сам вставился на странице - там, где до этого находился курсор. Вначале подумывал - сделать так, чтобы это работало, если нажата клавиша Ctrl, например. Однако, потом решил сделать еще проще: только кликнул мышью по соответствующему спецсимволу (или по его html-сущности - тогда вставится уже она, а не сам спецсимвол), так он сразу вставится в место редактируемой области, где находился курсор. Т.е. можно много раз кликать по разным спецсимволам - и они каждый раз будут вставляться на страницу. Т.е. практически так же, как в Word, только не надо каждый раз нажимать кнопку "Вставить".

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

  1. Сохранять положение курсора средствами браузера. Т.е. чтобы при клике по панели спецсимволов положение курсора (или выделение) на редактируемой области оставалось нетронутым. Для этого, пожалуй, один выход: располагать панель спецсимволов в теге <iframe>. Все бы ничего, но я решил обеспечить возможность передвижения по экрану этой панели. Т.е. пришлось бы двигать iframe (что, впрочем, даже проще было бы). Да и потом, есть некоторые (хотя и небольшие) сложности с передачей данных из iframe в основное окно (window).
  2. Восстанавливать выделение или положение курсора в редактируемой области после каждого клика по панели спецсимволов. Тоже вполне можно сделать, но при этом как быть с выделением самого (вставляемого, находящегося на панели) спецсимвола? Ведь оно пропадет. А мне хотелось сохранить его (может, и зря, ведь достаточно было, по идее, просто изменить стиль спецсимвола, сделав его похожим на выделение).
  3. Вставить на редактируемую область "муляж" курсора. Т.е. тег <span> с уникальным id. При этом есть возможность - оформить его как-то заметнее, по сравнению с обычным курсором. Это важно - так как внимание-то будет временно переключено на панель спецсимволов - чтобы впоследствии не искать курсор на странице. Поэтому, в итоге, поразмыслив, я выбрал именно этот вариант в качестве рабочего.
 

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

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

Чтобы было ясно видно, какой из режимов включен, какая из панелей открыта, соответствующие кнопки меняют фон (на красный). Т.е. одно дело, когда просто видишь перед собой соответствующую панель (окно, т.д.). Типа того, и так, мол, видно, зачем еще дополнительно сигнализировать об этом. А это важно. Хотя бы для того, чтобы не забывать, какая из кнопок какой именно панели соответствует. Ну, и для обеспечения так называемой обратной связи.

Удаление излишне вставленных переносов строк

Т.е. тегов <br>. Их браузер вставляет принудительно в конце абзаца, если нажимать клавишу Enter. Причем, такую вставку он делает тогда, когда слева от курсора находится пробел, но не иной символ. Также, браузер делает такую вставку в пустых абзацах, которые создаются после очередного нажатия клавиши Enter. Ну, Firefox 24, 36, к примеру. Делает он это для того, чтобы, если при нажатии Enter не возникало пустых абзацев (если курсор стоит в самом конце уже имеющегося абзаца). Иначе последние будут иметь нулевую высоту и, соответственно, с ними не получится работать в визуальном режиме... Однако, когда абзац содержит хотя бы 1 символ текста, перенос строки в его конце уже не нужен (впрочем, это не совсем так). Отчасти, это обсуждают здесь. В общем-то, эти теги не вредят особо, но они - излишние, ни к чему. Поэтому пришлось их столь же принудительно удалять (при очередном сохранении страницы на сервере). Если тег абзаца содержит что-то еще, кроме переноса строки, тогда удаляем последний; если же абзац - пустой, т.е. представляет собой что-то типа <p><br></p>, тогда - оставляем. Решение - от слова не очень, но более оптимального - я не придумал.

Хотел было сделать обработчик нажатия клавиши Enter, которая, собственно, и порождает новые абзацы (с переносами строк внутри них), но оказалось, что там вообще все сложно и неоднозначно - даже в рамках одного браузера. В зависимости от контекста - разные anchorNode и т.д.
Т.е. этот conteneditable, конечно, не без проблем, мягко говоря. Об этом говорят и другие разработчики. Однако, если их, эти проблемы, принимать во внимание и учитывать, то работать с ним вполне можно.

Это, по всей видимости, один из немногих нюансов, который у меня здесь (по крайней мере, на данный момент) НЕкроссбраузерный.

При этом возникла проблема, обусловленная поведением браузера. Если удалить из блочного тега, например, из абзаца (<p>) его последнего потомка - тег <br>, то при дальнейшем наборе текста В КОНЦЕ этого абзаца браузер ведет себя по-разному. Если последний символ был любой, кроме пробела, то все хорошо. А вот если был пробел - то при положении курсора справа от него и при наборе символов он "съедается", т.е. исчезает. В итоге, первый набранный символ встает на место этого пробела. И приходится добавлять его вручную. Например, есть абзац:

<p>Text. </p>. После слова "Text" идет пробел. Так вот, если курсор будет стоять СПРАВА от него (т.е. в самом конце содержимого тега р) и попытаться продолжить набор текста, например, нажав на клавиатуре букву W, то получится вот что:

<p>Text.W</p>. Т.е. пробел исчезнет. Я некоторое время находился в непонимании, почему же вдруг стали исчезать пробелы в конце предложений после очередного сохранения страницы. Потом понял. Проблема наблюдается, по крайней мере, в Firefox  24, 36. Очень скудная информация в интернете позволяет  сделать вывод, что это - еще и не очень кроссбраузерно, увы. Т.е. каждый браузер тут может действовать по-своему.

Т.е., с одной стороны, эти лишние переносы строк в конце каждого абзаца абсолютно не нужны, только загромождают html-код страницы. С другой стороны, без них наблюдается такая ситуация, когда после сохранения приходится в конце каждой строки добавлять пробелы дополнительно (несмотря на то, что визуально они там есть), если там нужно добавить текст (ну, или заканчивать набор текста, перед очередным сохранением, любым символом, кроме пробела). Т.е. это - стабильное такое поведение. И оно - достаточно неудобно. Потому как я уже давно привык заканчивать строки, перед очередным сохранением текста (неважно, набираемого в браузере или в Word) пробелами и только потом сохранять.

В общем, подумав, в итоге я решил сделать так. При переходе курсора на тот или иной блочный (block) или инлайн-блочный (inline-block) тег добавляется в самый его конец перенос строки. Это, конечно, не очень, т.к. при переходе курсора по разным абзацам (тегам) в них будет добавляться переносы строк, даже если эти абзацы не будут редактироваться. Но, потом, перед очередным сохранением страницы на сервере, все такие переносы строк будут все равно удалены.

Лучше варианта я не нашел. Потому что перехватить событие нажатия клавиши (возникающее при наборе текста), например, не получается. Потому как "съедание" пробела в конце строки (если там нет <br>) происходит ДО того, как начинает срабатывать обработчик события onkeydown. Видимо, браузер делает это очень быстро. Поэтому, чисто логически, остается только вариант - "подготовить" строку заранее, т.е. вставить в нее тег переноса строки до того, как в ней начнется (или продолжится) набор текста. И потом, перед сохранением на сервере, удалить. Несколько комично, но что поделаешь...

Для этого пришлось дополнять обработчик onclick, назначенный на редактируемую область - это если переход курсора на тот или иной тег, содержащийся внутри нее, произошел в результате клика мышью. А также - сделать обработчики нажатий некоторых кнопок: стрелок ← ↑ → ↓, Home, PageUp, PageDown на клавиатуре, при помощи которых может быть осуществлен переход. Т.е. всех тех кнопок, которые могут инициировать переход курсора в конец строки где-нибудь в пределах редактируемой области.

Можно, конечно, добавлять переносы строк вообще во все целевые теги перед началом редактирования (а потом - удалять все их перед сохранением страницы), но тогда они будут "маячить" везде, например, при включенном режиме подсветки тегов, что как-то не очень.

Кстати, интересно получилось с обработчиком нажатий клавиш для стрелок. Например, если взять стрелку вверх. Обработчик срабатывает сразу после нажатия стрелки, а уже ПОТОМ курсор переходит наверх, в частности, на более вышележащий абзац. В итоге, свойство event.target соответствует предыдущему тегу, а не целевому, не тому, на который произошел переход. В конце концов, ведь нажатие клавиши стрелки произошло именно на текущем теге, когда курсор пока еще находился там. 

Чтобы как-то обойти эту ситуацию, пришлось предусмотреть таймер (минимальную задержку в 1 мс). А потом, дождавшись перехода курсора, брать уже не event.target, а getSelection().getRangeAt(0).endContainer.

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

Создание новых страниц

Наконец, добавил возможность создания новых страниц на основе ранее созданных шаблонов. Конечно, такая функциональность есть в PHPStorm. однако там (вроде бы?), шаблоны являются общими для всех проектов (сайтов). Потом, если шаблонов будет много - то выбирать их в PHPStorm - несколько проблематично. Кроме того, в любом случае, придется запускать PHPStorm. А ведь в этом нет необходимости (теперь), если не стоит задача программирования, т.е. - реализации программных кодов или изменения/добавления новой верстки.

Шаблоны можно будет выбрать только для текущего сайта (т.е. того, который редактируется). Они могут находиться как в одном каталоге (как на скриншоте), так и в разных каталогах (по типам шаблонов). Вроде бы, удобно. Удобнее, чем в PHPStorm, по крайней мере.

 

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

Примечание

Правда, уже при формировании этой статьи наткнулся на новые проблемы. Например, строчка
&lt;!-- &nbsp;__Begin_main_content__ --&gt;
Оказывается, в процессе редактирования страницы (причем, не в этом месте) вполне себе самостоятельно преобразуется именно в комментарий, т.е. в
<!--  __Begin_main_content__ -->

И еще кое-что. Надо будет исправлять.

Собственно, то, что я сделал - так или иначе хотел/мечтал/думал лет уж, наверное, 7-10 последних. К сожалению, среди готового ПО как-то не удалось найти ничего подходящего. Тот же PHPSrorm, несомненно, мощнее в 1000...10000 раз, но ему как раз не хватает именно визуальности. Точнее, визуальность - это немного не то, для чего он разработан. "Считается", что профессионал не должен заботиться о визуальности, довольствуясь командной строкой. Именно это говорят, к примеру, приверженцы Linux. Однако, это - полуправда. Ибо визуальность СУЩЕСТВЕННО сокращает время, особенно, при поточной или массовой работе. Особенно, когда помимо программирования (и запоминания консольных команд) есть и еще, в общем-то, масса разных дел.

По идее, в моей этой разработке, конечно, нет ничего сверхнового. Потому как эта (и не только эта) функциональность в той или иной форме присутствует, наверное, во всех CMS (content manage system), которые существуют в настоящее время. Смысл ее, в основном, в том, чтобы сделать возможным визуальное редактирование статико-динамических сайтов. Т.е. таких, которые не в полной мере являются динамическими.

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

При том, что я практически вообще не связан никакими ограничениями возможностей и особенностей, налагаемыми теми или иными CMS.

По сути, в настройках моего редактора следует указать лишь id тега, который включает в себе редактируемую область (и только ее). Т.е. структура страницы ДОЛЖНА содержать соответствующий тег. Также нужно указать домен сайта, ну, и еще пару мелочей. Кроме того, в html-коде вебстраницы, внутри этого тега, должны присутствовать два уникальных комментария, также ограничивающих редактируемую область (они тоже указываются в настройках). Да, еще - требования к рисункам, первично сохраняемым через редактор (путем вставки из буфера обмена прямо на страницу в браузере, в нужное место): их каталог (и, соответственно, src) должен содержаться в том же самом каталоге (т.е. быть его подкаталогом), в котором находится редактируемая вебстраница. В общем-то, такое поведение можно было бы и поменять, но я не нахожу необходимости для этого. Тем более, что потом, после вставки/сохранения рисунка, легко можно (тоже через редактор) заменить его src на вообще любой, даже с другого сайта.

И, в общем-то, всё. Более, вроде, - никаких ограничений.

И интерфейс редактора сделал именно под СЕБЯ. Чтобы не приходилось (напрягая свое зрение и сажая его) выискивать, где какая вкладка или кнопка.

Для тех, кто, в отличие от коронобесов, бандитов, летевизорников, фашистов, поддержателей/разжигателей войны, и прочей аналогичной им зловредной публики, хотел бы сохранить и улучшить свое зрение, скажу так. Дисплей, клавиатура, да и интерфейс программ - в общем, все то, с чем визуально работает пользователь - должны быть ТАКИМИ, чтобы ему вообще не приходилось куда-либо вглядываться, всматриваться и что-то там выискивать. ВСЕ (ну, хотя бы 99%) визуальные элементы, будь то символы на клавишах, иконки/кнопки на сайтах, ДОЛЖНЫ рекогнисцироваться пользователем практически мгновенно, без каких-либо зрительных усилий. Как пишет Бэйтс, КАЖДАЯ попытка, даже на долю секунды, всматривания, вглядывания (не говоря уж о пристальном смотрении, напряженном вглядывании) ведет к аберрациям зрения, а когда они накапливаются - зрение начинает ослабевать, возникают хронические нюансы. И это в самом деле так. Ибо просветления зрения (у меня, в частности) как раз и получаются тогда, когда человек НЕ пытается увидеть, а просто смотрит, да и всё. Недоросли от медицины (99% офтальмологов) называют это "ленивым зрением". Оставляю этот термин на их (пожизненной) совести, но, все же даю возможность (предлагаю) раскаяться и тем самым сберечь зрение своих пациентов - хотя бы тех, которые придут к этим офтальмологам уже после их искреннего раскаяния.
Т.е. глаз, как и человек в целом, ПРЕДНАЗНАЧЕН для (зрительной) работы, даже для усиленной и длительной (поверьте моему практическому опыту); глазу она - в радость. Т.е. не стоит думать, что глаза следует предохранять от работы, мол, чем меньше глаза работают, тем дольше сохранится зрение (это не совсем так). НО: условия ее ДОЛЖНЫ быть безопасными и безвредными. Оптимизированными, т.е.

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

Отдельно надо бы сказать о, так сказать, технических решениях. Понятно, что редактор, даже с перечисленным довольно скромным функционалом, все-таки делает много чего. А для обеспечения этого требовались и соответствующие решения. Такое-то окно открыть/закрыть, такой-то параметр туда-то записать или изменить, ну, и т.д., и т.п. А еще - многое из того, что происходит, нужно контролировать. Самое простое решение - это назначить наблюдатель за DOM, который будет фиксировать всё и вся. Однако... оказалось, что работа (особенно, обновление страницы) стала происходить как-то медленнее. И это, повторюсь, даже при довольно скромном функционале. А что было бы, будь функционал более обширным и развернутым. Поэтому я решил сделать редактор более легким - путем экспресс-назначения соответствующих обработчиков событий точечно - только там, где они могут понадобиться в конкретный момент; и - сразу удаляя их, как только они перестанут быть необходимыми. Это избавило от медлительности. Правда, больше обдумывать пришлось. Ибо точечность - это всегда более затратно с точки зрения усилий, затраченных на разработку.

Ради быстроты работы редактора, конечно, практически никакого ООП (только самый минимум там, где оно реально необходимо).

Ну, и т.д., на самом деле. СТОЛЬКО всего пришлось продумать. А для этого - пришлось читать просто массу разных материалов, чаще - англоязычных. А, например, мануалы по РНР я часто специально читаю на английском языке (хотя там вполне есть русскоязычная версия тоже - достаточно переключить язык прямо на странице). Делаю это для того, чтобы слиться с англоязычной грамматикой и лексикой, если можно так выразиться. Чтобы лучше понимать написанное в будущем.

И однажды, когда задал вопрос на одном русскоязычном форуме, уже "поймал" себя на ощущении, что по-английски мне сказать некую фразу как-то привычнее. Ибо, когда речь идет о программировании, думается по-английски; там фразы как-то компактнее, что ли. Даже стал мысленно искать замену англоязычному произношению, для чего пришлось ВСПОМИНАТЬ русские слова.
Кстати, если искать в интернете что-то более-менее конкретное, тонкости и особенности - то в 90% случаев это есть ТОЛЬКО на иностранных (англоязычных) сайтах. На русскоязычных сайтах, за редким исключением, имеются лишь перепечатки с тех же англоязычных ресурсов (и/или переводы), либо же попросту неприкрытый плагиат (копи-паст). Изложенные, иной раз, так, что вообще ничего непонятно (видимо, по причине того, что и их авторы сами не разобрались в том, о чем пишут статьи). Ну, либо очевидные, общеизвестные вещи, которые разные сайты перепечатывают друг у друга. И так практически во всем, что касается тонкостей программирования.
Кстати, именно поэтому даже сама попытка разработки программных сред, языков программирования на русском языке сейчас, в XXI веке, - это даже не глупость, а наглая глупость, попахивающая очковтирательством, как минимум. Хотя бы потому, что программисту все равно придется хорошо знать английский язык, чтобы читать соответствующие руководства и мануалы. И периодическое переключение на русскоязычные команды будет лишь отвлекать его, снижая эффективность работы.


Например, в свое время для меня, как и для "специалистов", было полной загадкой, как работает стек протоколов TCP/IP. Мне, в то время преподававшему работу компьютерных сетей, это было нужно. Однако, ВЕЗДЕ, включая даже хорошие толстые книги, были лишь общие слова. Которых достаточно, чтобы обсуждать тему, но недостаточно, чтобы понимать ее. Не говоря уж об интернете. И лишь буквально на паре англоязычных ресурсов (только там), наконец, удалось найти хороший материал. Прочитав который, я, наконец-то, детально разобрался в сути происходящего при сетевых взаимодействиях. А до этого - да, имел лишь некое общее понимание. Которого, конечно, хватало не только для обсуждения, но даже и для работы с интернетом, разработки сайтов и т.д. Но при этом суть происходящего при сетевых запросах представляла для меня собой некое "магическое" (как говорят программисты) явление. Ну, как и практически для всех, кто занимается сайтами, к примеру. Особенно с использованием разных фреймворков, типа laravel.

Одно время я долго не мог понять, почему так... Ну, почему же в русскоязычном сегменте как-то мало статей, детально и качественно описывающих тонкости. Почему практически все статьи - ограничиваются лишь копи-пастом и/или изложением банальных, общеизвестных нюансов. Но потом уж понял, что это - банальное следствие всей российско-советской системы. Суть которой - как будто бы даже принудительно - не делать самостоятельно, НЕ ДАВАТЬ ДЕЛАТЬ самостоятельно другим, а хапнуть, отнять готовое, кем-то созданное, да еще и обвинив при этом собственника в чем-нибудь. Именно в этом суть всех этих КГБ/ФБС/НКВД/... Которые, насколько я уж понял, для подобных деяний-то и создавались, в основном. Именно потому - и бесконтрольные, огромные полномочия, финансирование, покрывание разного рода махинаций и пр. Когда даже атомную бомбу - и то, как оказалось, нагло скопировали с американских чертежей и проектов. Именно поэтому тут, на россии, и законодательство такое, которое разрешает отнимать дома у собственников, к примеру; в обмен на смехотворную "компенсацию". И так далее. Т.е. это не просто чьи-то там, якобы, "недоработки", "ошибки" или "недосмотр", а именно - уже давно оформившаяся и целенаправленная СИСТЕМА. Суть которой: самим толком ничего не делать, только заниматься болтовней на своих сборищах-сходняках и создавать видимость "бурной деятельности", а при этом сидеть и смотреть, когда у соседа появится что-то ценное; а как только появится - отжать, отнять, а соседа - оттеснить/убить/посадить в тюрьму. Попутно, обвинив его во всем, в чем только получится. Для этого, разумеется, необходимы и мощные "органы", обладающие беспредельными полномочиями, и соответствующее законодательство, и т.д.

Ну, а если же человек пусть и не создаст новый завод/автомобиль/телефон или что-то подобное, но хотя бы просто (ну, надо же, как посмел-то) в чем-то детально разберется - так через какое-то время постараются его оклеветать.

Попутно (по мере, так сказать) возникают новые идеи. Например, сделать возможность для удаления тегов в один-два клика. Но... нужно ли это? Ведь, в конце концов, работая в Word, мне НИ РАЗУ не потребовалось удалять абзацы в 1 клик: обычно выделяешь то, что нужно и удаляешь. И, видимо, так поступают практически все. Поэтому, наверное, такая функциональность будет лишней, только отвлекающей внимание и ресурсы компьютера. Да и ни к чему: нажмешь ненароком и потом восстанавливать абзац придется. В итоге, сделал возможность такого удаления только для тегов переноса строки <br> в режиме подсветки тегов. Потому что их, бывает, браузер создает сам при создании новых абзацев.

Или по поводу того, чтобы редактировать атрибуты тега в специальном всплывающем окне, по аналогии со ссылками и рисунками. Однако, последние - это все-таки "особые" теги, с ними-то все понятно. Еще есть теги для видео и аудио - тоже из той же серии. А вот для всех остальных, видимо, такая возможность будет излишней. Не лучше ли будет открыть страницу в Notepad++ (благо, теперь это делается очень быстро - в 1 клик и курсор в открытом файле сам устанавливается точно в требуемое место) и уже там внести исправления.

Впрочем, все же сделал в итоге функциональность, обеспечивающую вставку HTML из буфера обмена еще и третьим способом. Например, в буфер обмена скопирован текстовая строка <p style="color: red;">Text</p>, представляющий собой html-код абзаца р (см. ниже). Если скопировать в буфер обмена не строку, а именно непосредственно html, то у меня реализовано две возможности вставки: либо только текстового содержимого (textContent), либо обычная html-вставка. Но, это если, повторюсь, скопирован html откуда-нибудь. А вот если скопирована строка, представляющая собой корректный html?

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

Конечно, это уже - не WYSIWYG-возможность. Это уже относится все-таки к работе в текстовом редакторе. Поэтому, с одной стороны, лучше уж это делать в том же Notepad++, например. А редактор - не перегружать этой возможностью. Иначе получится в итоге некий запутанный "комбайн" и сам потом запутаешься в его функциональности.

Хотя, с другой стороны, у меня, конечно, есть аналогичная функциональность, но только по отношению к заранее созданным (и выверенным) шаблонам, но, и только. Ведь при вставке шаблона я, как правило, не смотрю, каков его html-код, а просто вставляю, да и всё (т.е. это - WYSIWYG-операция). И что попало вставлять в виде строки html через WYSIWYG, видимо, не есть правильно. В том числе и потому, что так можно внести и уязвимость на редактируемую вебстраницу (например, если вставлять SVG или, хуже того, РНР-код...). 

Но, все же иногда такая быстрая вставка какой-нибудь разметки на страницу, минуя текстовый редактор, довольно удобна. Как минимум, потому, что не надо лишний раз двигать мышью и нажимать кнопку "Открыть в Notepad++". Не надо ждать, пока он, текстовый редактор, откроется. Это нужно, в частности, тогда, когда требуется продемонстрировать на странице, как работает тот или иной небольшой отрывок (заведомо безопасного) html-кода. Который вставляется вначале как текстовая строка (т.е. со всеми тегами, атрибутами) - для демонстрации самого этого кода, а потом - как html - для демонстрации того, как его отображает браузер.

Функциональность вставки текстового содержимого из буфера обмена

Скажем, взять вышеприведенный html-код (зеленого цвета). Представляющий собой:

 ‹code style="color: green;"›<p style="color: red;">Text</p>‹/code›

Т.е. это - тег <code> с атрибутом style, где, в свою очередь, задано CSS-свойство color: green. Внутри этого тега содержится текстовая строка, представляющая собой html-код абзаца, внутри которого есть текстовый контент Text.

Как я уже писал, для обозначения "истинной" html-разметки и ее строкового представления я использую французские кавычки (‹ и ›) вместо символов < и >. В данном случае, тег code оформлен c их помощью. Это нужно, чтобы как-то различать истинную разметку от текстовых строк, содержащих разметку (последняя может использоваться, например, в методе innerHTML).

Если указанный зеленый фрагмент текста выделить и скопировать, а потом пытаться вставить где-нибудь на странице (например, сделав Ctrl + V, или через "Правка" → "Вставить", или т.п.), то вот какие я сделал возможности.

1. Обычная вставка: <p style="color: red;">Text</p>. Т.е. этот фрагмент вставился как есть, без изменений.

2. Вставка содержимого тега <code>, т.е. его текстового контента: <p style="color: red;">Text</p>. Т.е. теги <code> проигнорированы, вставлено только их содержимое (textContent). Это особенно удобно при копировании и вставке html-кода со сторонних сайтов.

3. Вставка содержимого тега <code>, но не как текста, а как html-кода (т.е. текст преобразуется в html). При этом теги html внедряются в разметку страницы и будут обработаны браузером:

Text

В данном случае вставился абзац (тег <p>) вместе с его содержимым (слово Text). Как видно, был применен стиль - красный цвет текста, как и положено. Или даже можно скопировать html-разметку из какого-нибудь текстового редактора (того же PHPStorm) и вставить ее 3-м способом на вебстраницу в моем редакторе (т.е. в режиме WYSIWYG). И она будет сохранена, будет обработана браузером с учетом ее тегов и атрибутов.

Однако, это - "долгий" процесс. Так как перед вставкой из буфера обмена вначале появляется всплывающее окно, на котором можно кликом мыши выбрать тот или иной вариант, нажав затем "ОК". Как я уже писал, есть и более быстрый способ, без этого окна, через Ctrl + Shift+ V. Результат будет совпадать с результатом из п.2.

Т.е. получилось три разных возможности вставки из буфера обмена (и, плюс к тому, вставка рисунков, конечно; там - тоже три разных возможности). 

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

 Если все-таки неохота открывать Notepad++ или, тем более, PHPStorm

набрать некий html-код, а потом вырезать его и вставить уже как html. Ну, или скопировать фрагмент кода с какого-нибудь сайта-форума и вставить так или иначе.

Можно также сделать и функциональность по превращению текстовой строки, представляющей собой html-код, в разметку. Но, мне кажется, это будет излишняя, дублирующая функциональность (ведь такую строку легко можно вырезать и затем вставить, как разметку). Хотя...

Если текст скопирован из Word

Оттуда можно скопировать просто текст, а затем вставить на вебстраницу. Однако, это неудобно, так как, например, абзацы после этого приходится формировать заново (вместо них создаются переносы строк). Поэтому, как я уже писал, использую плагин DocToHtml. Он формирует HTML-код из выделенного в Word фрагмента текста (в том числе, и таблицы, если они там есть).

Пример всплывающего окна для вставки из буфера обмена (перед очисткой)

Но, проблема в том, что код получается несколько грязным, с ненужными классами и стилями. И хорошо бы делать его очистку непосредственно перед вставкой на вебстраницу из буфера обмена. Что я и сделал в итоге. На первом рисунке - содержимое буфера обмена, скопированное из Word при помощи DocToHtml. Как видно, присутствует совершенно ненужный стиль text-indent:36pt. Кроме того, Word-овский класс A1_1 тоже совершенно ни к чему. Их, конечно, можно удалить руками. Или потом обработать файл целиком так, как я делал раньше.

Но, это, так или иначе, излишние действия. Поэтому возможность очистки я предусмотрел непосредственно перед вставкой из буфера обмена. Если нажать на кнопку с иконкой (значком) DocToHtml, то вставляемый текст будет более-менее очищен и, попутно, для абзацев, списков будут заданы типичные классы, наиболее принятые на конкретном сайте.

Пример всплывающего окна для вставки из буфера обмена (после очистки)

Т.е. получится примерно следующее. Как видно, HTML-код очистился и классы заменились на актуальные.

Ну, а дальше можно выбрать режим вставки. Если вставлять как текст, то на вебстранице появится именно то, что приведено в поле всплывающего окна (т.е. с символами < >, в частности). Если же вставлять как HTML, то фрагменты текста, находящиеся между этими символами, заменятся на теги (которые будут отображаться с учетом их функциональности и классов).

* * *

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

Единственное, пожалуй, НО: в некоторых случаях результат того или иного действия может быть не совсем очевидным и предсказуемым. Например, одно дело, если копировать и вставлять часть абзаца; другой дело - когда сразу несколько. Ну, или еще некоторые моменты (как я уже тут писал, например, при вставке рисунков, в зависимости от того, откуда именно они были скопированы). Хотя, такие "спорные" нюансы возникают достаточно редко и просто делаешь Ctrl + Z, да и все.

Кстати, о патенте фирмы Microsoft

Любопытно, но есть у нее (старый) патент о WYSIWYG-редакторах. Там главным предметом (идеей) фигурирует термин "поверхность". Это то место, где происходит редактирование вебстраницы. Судя по содержанию патента, насколько я понял, поверхность эта возникает перед началом редактирования, типа как бы панель, на которой представлен редактируемый контент. Т.е. когда текст на вебстранице отображается в редактируемом режиме, по сути, он и находится на подобной поверхности. Такое бывает, например, на форумах, когда пользователь редактирует свое сообщение. При этом сообщение отображается в текстовом виде, с управляющими символами (которые впоследствии, после сохранения сообщения, преобразуются в теги).

А меня же в редакторе никакой поверхности не используется. За исключением некоторых панелей-меню для задания параметров. Но, это - не поверхность, т.к. общеизвестные панели для задания параметров.

Так что, в итоге, сам того не замечая, сделал я для себя мини-CMS

Точнее, микро-CMS (т.к. обычно WYSIWYG редактор входит в состав мало-мальски серьезной CMS, как одна из ее компонент). Сейчас, собственно, одна у меня главная проблема с этим редактором: как сделать более удобным управляющую панель слева. Там сверху - основная информация о результатах работы редактора (как бы лог последних происшедших 1-3 важных событий. ошибок), а ниже - кнопки управления. Проблема в том, что все это занимает много места. Особенно, если в будущем появятся дополнительные кнопки/вкладки панели. Конечно, можно скрывать/открывать информационную часть, но это - лишнее действие, хотелось бы, чтобы подобная информация была всегда на виду. Сделать более мелким шрифт - можно, но тоже не особо. Ибо, даже если туда сознательно не смотреть, глаза ВСЁ РАВНО будут сканировать эту область; и, если разглядеть что-то будет непросто - могут начать напрягаться. Т.е. для зрения такое - нехорошо.

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

Конечно, если потянуть за синюю толстую полосу - можно менять ширину панели (которая потом сохранится в настройках для конкретного сайта, если сохранить сделанные изменения). Таким образом, информация (лог) будет видна более наглядно. Пока думаю так: сделаю клавишу F1 как переключатель. Т.е. нажал ее - панель редактора расширилась на полэкрана и можно посмотреть лог в развернутом виде. Нажал еще раз - панель приняла исходное состояние. Все равно она ведь не задействована браузером. По идее, это - клавиша для вызова справки (по общему смыслу).

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

И возникла проблема несогласованности версий вебстраниц

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

А потом, через время, натыкаюсь на РАНЕЕ открытую страницу, на которой, на тот момент, присутствуют не все изменения, сделанные позже. А браузер-то берет информацию поначалу из кэша... Т.е. в подобных случаях он отобразит устаревшую версию страницы. И если ее начать редактировать, а потом сохранить, все более поздние изменения будут потеряны. Правда, их можно найти в каталоге для запасных копий страницы (каждая очередная копия делается при каждом сохранении). Но, это ка-кто не очень. Ведь и забыть можно. Что, кстати, уже пару раз было.

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

Можно, конечно, запретить кэширование, если сайт открыт в режиме редактирования. И каждый раз выдавать страницу с сервера - так будет обеспечено получение актуальной копии. Однако, с этим возникли проблемы - не очень это удобно, как оказалось.

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

Можно использовать COOKIES или даже сессии браузера. Последнее, казалось бы, идеально: они, во-первых, существуют индивидуально для каждой вкладки (даже если есть вкладки с одним и тем же URL), а, во-вторых, должны исчезать после закрытия браузера. Однако... в Firefox (моих версий, по крайней мере) они НЕ исчезают, вполне надежно появляясь после очередного запуска браузера. Исчезают они, это если только закрыть вкладку, а не браузер целиком. Т.е. придется контролировать и делать некий счетчик...

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

Ну, а COOKIES создаются на домен. Можно, конечно, создавать их для каждого URL в отдельности, но тогда как быть с одним и тем же URL, который открыт/сохранен в разных вкладках одного и того же браузера(?). Ну, да, можно использовать некий счетчик открытых вкладок, т.д.... В общем - проблемы...

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


Вообще, эти размышления на тему эргономики - довольно длительные. Пока поймешь, как именно будет удобно - проходит, иной раз, немало времени. Не только в рамках того, что присутствует на дисплее. Это касается и мебели, обстановки дома, в огороде, да мало ли чего. Вот, скажем, банальный пример. У меня у знакомого одного есть джип Форд. Так я обратил внимание, что там как-то... тесно на переднем сидении. Несмотря на то, что внешне машина - довольно большая, да и салон - не маленький. Чтобы дотянуться до рукоятки изменения наклона спинки (у себя-то на Ниве я ее использую достаточно часто), приходится чуть ли не приоткрывать дверь. Да и наклон регулируется не плавно, а ступенчато. Т.е. сидеть, конечно, можно, но... когда привыкаешь к более лучшему - недостатки сразу видны.
Не говоря уж о том, что впереди не заметно... КАПОТА. Вообще. А тогда - каким образом-то близко подъезжать к препятствиям? Всегда по камерам, что ли? После этого я понял, почему некоторые автомобили, стоя на красный свет светофора, не доезжают до стоп линии на приличное расстояние... Не зря раньше, на старых автомобилях, капоты делались сужающимися впереди, чтобы водитель видел бампер - хотя бы его края и, тем самым, лучше ориентировался.
Т.е. это - примеры непродуманной эргономики. Впрочем, кого-то это, наверное, не столь напрягает.
Скажем, ну кто еще, кроме меня, задумался о том, что практически ВСЕ (как офисные, так и для руководителей) кресла подлежат модернизации и переделке? Так думаю, что никто. Т.е. люди тупо сидят на том, что купят или что им выдадут, да и всё.

А все потому, что понять, увидеть такое можно лишь после осознания (мне так думается). А пока человек не будет в бытии, не научится искренности и покаянию, он толком ничего не осознает. И поэтому сможет, разве что, прислушаться к советам других в этом направлении.
И, кроме того, после того, как спина (позвоночник), искаженный неправильным креслом, все же, по каким-то причинам, станет лучше. Например, в результате мануального массажа. Ибо пока он искажен - человеку вполне может казаться, что то самое кресло, под влиянием которого произошло искажение, оно, якобы, "довольно удобное".

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

Может, в будущем попробую, если сочту необходимым, сделать еще горячие клавиши и задействовать для них правую часть клавиатуры (ибо ею я все равно никогда не пользовался, стоит без дела, как говорится). Правда, лично мне (т.к. - левша процентов на 50) удобнее было бы, чтобы дополнительная клавиатура располагалась СЛЕВА, а не справа... Хоть отпиливай ту часть клавиатуры и перемещай влево. Тем более, правая-то рука занята мышью, и переводить ее на клавиатуру хотя и быстро, но это таки приводит к затратам времени, равно как и к отвлечению внимания. И я в курсе, что есть специальные клавиатуры для левшей, но...

 
Но, проблема тут еще и в том, что почти все то, что удается видеть в продаже, оно, во-первых, работает через USB-порт. А у меня-то PS/2. По той причине, что не хочу нагружать USB-линию. Мало ли, вдруг там что-то зависнет или еще что. А так, PS/2 работает независимо от USB.
Во-вторых, сейчас они, за редким-редким исключением, черные. И буквы там - красно-белые (и то и бело-белые, что вообще кошмар - видимо, это - тренажер такой для ускорения деградации зрения пользователей). Что, конечно, КРАЙНЕ неудобно. Помнится, в университетских (где я когда-то работал) аудиториях были именно такие клавиатуры. Так чтобы их использовать - мне приходилось напрягаться. Поэтому, собственно, старался избегать там что-либо серьезное делать на компьютерах.
 Лет 10 назад я купил было новую клавиатуру. Белую, с красно-черными клавишами, как и у меня. И, вроде, даже через PS/2. И даже с нажимающимися клавишами (см. ниже). НО... там нажатия были, как бы сказать... какие-то неощущаемые, что ли. Какие-то непонятные. Да и клавиши - какие-то низкие, типа, как на ноутбуках. Неудобная, в общем. Так что, после нескольких дней использования я положил ее на полку, так и лежит.


В-третьих, при всем упомянутом, это еще надо поискать такую клавиатуру, клавиши которой именно НАЖИМАЛИСЬ бы, с ощущением. Причем, без неких щелчков, которые происходят у современных клавиатур, сделанных специально для любителей ощущения нажатий каждой клавиши. Чтобы просто - мягко чувствовалось, что я именно НАЖАЛ (так уж нажал) клавишу, да и всё.
В итоге, той клавиатуре, на которой работаю (в том числе и прямо сейчас, набирая этот текст), где-то 20+ лет. Разумеется, через несколько лет начали стираться надписи на клавишах.
Это же СКОЛЬКО раз надо было нажать на эту клавишу, чтобы они достигла такого вот состояния?...

А правые клавиши Shift и Ctrl в итоге износились просто НАСКВОЗЬ, так, что там дыры около 1 см диаметром и даже больше. Поначалу я покупал соответствующие наклейки, несколько комплектов... Но и они стирались вскоре. Что вот поделаешь... Тем более, не всегда и наклейки можно купить. Пришлось в итоге поверх наклеек налеплять прозрачный скотч. Его, что любопытно, хватает даже на дольше, чем самих наклеек. Правда, выглядит это все не очень эстетично, особенно, через время - но как раз это меня в данном случае заботит меньше всего. Потому как для глаз никакого напряжения или вреда нет (в отличие от нередко неэстетичных надписей или изображений на дисплее, в теле видениях и пр.).

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

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


Насчет цвета клавиатуры - тут дело даже не столько в моих предпочтениях (из серии "на вкус и цвет"), а и в рекомендации доктора Бейтса. Он справедливо утверждает, что глаз оптимально и без напряжений видит, когда на белом фоне есть резкая граница между ним и черной буквой (или иным символом). Поэтому клавиатура должна быть БЕЛОЙ. Ну, или светло-серой в крайнем случае, т.п., в общем - светлых тонов.
Впрочем, возможно, не будет плохо, если и наоборот. НО: при этом белые буквы на черном фоне должны быть столь же весьма высоко-контрастными, ясно различимыми. А не так, как на современных черных клавиатурах - там же вообще еле разберешь, что за символы на клавишах... И ведь не у всех такая память, что человек способен печатать вслепую, не глядя на клавиатуру.


А надписи на ней - черными, ну, или какого-то иного, столь же высоко-контрастного цвета, например, красного или насыщенного синего. И чем явственнее, отчетливее, эстетичнее, привлекательнее выглядят надписи, тем глаз активнее видит, не создавая своему организму помех - как физиологических, так и психологических блоков, фильтров и т.п., ведущих впоследствии к аномалиям зрения.
Ну, и так, на досуге, в качестве самостоятельного задания, можете подумать, КТО(??) из врачей вам был бы способен рассказать, причем детально, все это (чтобы вы имели возможность сберечь, а то и улучшить зрение свое и своих близких)?... Есть ли хоть ОДИН такой врач?...


А дальше-то что?...

А что дальше-то, в самом деле? По идее, то, что перечислено (в виде сводного итога - чуть ниже), это - вполне достаточно для более-менее полноценного WYSIVYG-редактора. Но - суть-то в том, что хочется большего. Говорят, что так, наверное, во всем: что человек имеет, а хочется еще лучше и/или больше. Ну, возможно. Это, по идее, крайне спорная (да и банально - вредная) концепция, ну, да ладно.

А дальше я вдруг увидел, что... стоит ли путать CMS и редактор/IDE ?... В самом деле, редактор/IDE - это вещь универсальная, пригодная для, более-менее, работы со всеми сайтами. А вот CMS - это уже своя "философия", своя технология организации работы сайта, свои частные функции. В том числе - свои виды макетов верстки страниц. Т.е. речь уже идет не о том, чтобы там что-то в файле подправить/отредактировать, а об автоматизации некоторых (или многих) нюансов, действий. 

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

Эту функциональность я еще недавно, периодически и нудно разрабатывал/дорабатывал, но теперь мне она, разумеется, не нужна. Ну, пригодилась примерно 3 года (5-6 семестров) - и то хорошо.

Ну, или взять - автоматизированное заполнение тематических страниц со ссылками на группы вебстраниц (например, раздел "Разное" на этом сайте). Это тоже нужно не везде. Т.е. включать такую функцию в редактор - будет, видимо, неким перебором, ибо такая функция должна быть в составе CMS, а не редактора. Это уже сайто-специфичная функциональность.

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

А почему встал такой вопрос: просто хотелось-то сделать нечто универсальное, portable, пригодное для всех сайтов, для всех тех, у которых верны пункты 1-10, перечисленные выше. Чтобы просто скопировал в некую папку на нужном сайте - и все, можно работать. Но, видимо, это уже будет не тем, что стоит делать, если говорить именно о сайто-специфичных функциях...<p>qwe</p>

Итак, что у меня получилось, типа сводного итога (практически, всё, за исключением работы в Notepad++/Paint, делается прямо в браузере, т.е. визуально)

Все кроссбраузерно (наверное, вплоть до IE11, как минимум). Кстати, Яндекс.почта, рекомендую вам перенять такой подход работы (вместо того, чтобы создавать проблемы для пользователей). Безо всяких там библиотек (типа jQuerry) и прочих костылей, к которым практически никаких чувств не испытываю, за исключением отвращения и искреннего непонимания - ну, зачем же их таки используют-то. Это только непосредственно по самому редактору, без системы включения/отключения режима редактирования, очистки кода и т.д. Итак, я сделал такую функциональность:

1. Форматирование текста: нижний/верхний индексы; жирный, курсив, подчеркнутый, зачеркнутый;

2. Оформление выделенной части текста тегами <code>;

3. Заголовки (h1 - h5). Почему-то я не захотел использовать h6;

4. Корректирование основных метатегов, а также содержимого тега <title> (заголовок страницы, который частично отображается на вкладке в браузере; полностью он отображается при наведении мыши на вкладку);

5. Вставка заранее подготовленных шаблонов html-кода из файла с шаблонами в 2-3 клика мышью. Этот файл автоматически подключается при работе редактора, но открыть шаблоны отдельно и копировать оттуда;

6. Очистка формата выделенного фрагмента (убираются теги <span> вместе с их атрибутами);

7. Подсветка элементов редактируемой области: выборочная (при наведении указателя мыши на тот или иной элемент) и всеобщая, когда подсвечиваются почти все теги, в том числе пустые и теги переноса строки <br/>. При этом каждый раз возникает окно, в котором в режиме редактирования появляется тег элемента (без текстового его содержимого), на который была наведена мышь. И этот тег, его атрибуты тоже можно редактировать. Если удерживать клавишу Ctrl, то окно тегов будет возникать примерно (чтобы удобнее было перейти мышью в это окно) в том месте, где находится указатель мыши, как только он попадет на тот или иной тег. Если Ctrl не нажата, то левый нижний угол окна располагается около левого верхнего угла тега;

8. Возможность редактирования атрибутов подсвеченных тегов и самих тегов;

9. Открытие html-файла страницы в редакторе текста Notepad++  в 1 клик мышью. Файл открывается и курсор в нем устанавливается точно в том же месте, в котором он находился непосредственно перед этим в браузере;

10. Открытие рисунка в редакторе Paint в 1-2 клика (если такой рисунок сохранен на сервере; если нет - выдается ошибка). Перед этим должен быть сделан клик на соответствующем рисунке.

11. Вставка/удаление ссылок, добавление и редактирование их основных параметров (href, title, alt). Редактирование параметров ссылки производится после двойного клика по ней - возникает всплывающее окно и т.д.;

12. Вставка рисунка (тоже прямо в браузере) путем вставки из буфера обмена (Ctrl + V или как-то иначе). Можно вставить прямо в текст, но я, как правило, вставляю в один из шаблонов, вместо стандартного рисунка, который там присутствует по умолчанию. При этом, если рисунок вставляется с другого домена/сайта, то перед вставкой во всплывающем окне показывается его outerHTML. А то вдруг там у него будут какие-нибудь нехорошие атрибуты, с которыми нельзя его сохранять на сервере. Если же рисунок вставляется, будучи скопированным из графического редактора (например, из Paint), то это происходит примерно  так же, как и при вставке рисунка в Word, Excel. После этого можно оставить рисунок в HTML-коде как есть, т.е. внедренным по протоколу data:, а можно, задав желаемое имя, сохранить его на сервере - в этом случае в html-коде вместо внедренного рисунка будет присутствовать соответствующий src;

13. Попутно, сделал возможность легкой замены ссылки рисунка (т.е. src). Возникает всплывающее окно, в котором можно, прямо как в Проводнике Windows, переходить по каталогам локального сервера и выбрать нужный рисунок. После клика по нему src текущего рисунка заменится на новый. Или можно задать, отредактировать эту ссылку вручную - тоже там же, во всплывающем окне;

14. Вставка якорей (идентификаторов id) в требуемый элемент. Причем, имя якоря предварительно (автоматически) предлагается уникальным. Имя якоря обязательно будет начинаться с символов anchor_. Такие якоря можно редактировать или удалять (вместе с идентификаторами). Если же потребуется вставить/редактировать/удалить якорь с другим именем, то в редакторе это запрещено (в целях безопасности);

15. Режим показа всех якорей (и установленных через данный редактор, и иными способами, например, через Notepad++ или PHPStorm). Это требуется, в частности, для реализации хэша ссылки на тот или иной элемент страницы. Попутно к этому, для каждого якоря - формирование и показ готовой ссылки, с учетом этого якоря, которая выделяется по клику по ней; остается лишь скопировать, ну, и вставить в требуемое место той или иной вебстраницы;

16. Горячая клавиша F1 для быстрого, в 1 нажатие, передвижения правой границы панели редактора вправо/влево;

17. Сохранение положения границы панели редактора при сохранении изменений. После этого при последующих обновлениях страницы граница будет отстоять от левого края экрана на ранее установленную величину;

18. Горячая клавиша F2 для быстрого (чтобы не тянуться к мыши) сохранения страницы на сервере (с подтверждающим сообщением - окном, исчезающим по нажатию клавиши Escape или самопроизвольно через 1,5 сек.), если курсор находится где-то на странице. Если же курсор находится за пределами страницы (например, в адресной строке браузера), то нажатие клавиши F2 вызовет обновление страницы;

19. Сообщение об основных событиях процесса редактирования в окно панели редактора. Например, если на странице присутствуют рисунки (теги <img />), которые имеют src вида data:image/png;base64,iVBOR... , которые не сохранены на сервере (т.е. они "вшиты" в html-код страницы по протоколу data:), то в окне панели будет сообщение об этом и, кроме того, появятся навигационные ссылки на эти рисунки, чтобы можно было в 1 клик перейти к ним и исправить - например, задать им имена и сохранить их на сервере. Прокрутку к таким рисункам сделал более-менее плавную (не мгновенную), но и не слишком длительную, чтобы глаза ПОНИМАЛИ, что фиксироваться на странице, пока она прокручивается, НЕ СТОИТ; но и чтобы не было резкого "удара" по глазам в результате очень быстрой прокрутки;

20. Чтобы не плодить ненужных id в редактируемом html-коде (хотя бы даже и временно), прокрутку я сделал не по якорям/хэшам (вида http://site.ru.page.html#hash), а "неявным" образом. Т.е., например, для навигации по рисункам, внедренным в html-код вебстраницы: вначале делается подсчет их общего числа; затем создаются теги, имеющие вид "ссылок" - по числу рисунков. И, наконец, в каждую "ссылку" вставляется обработчик события onclick, который прокручивает страницу к соответствующему рисунку. Т.е. функциональность абсолютно та же, но при этом в теги рисунков не добавляется ничего;

21. Задание (после двойного клика по выбранному рисунку) основных атрибутов рисунков: src, title, alt. Если рисунок имеет вид, как в предыдущем пункте (т.е. является внедренным), то дополнительно есть возможность, задав ему то или иное имя, сохранить его на сервере. При этом src будет назначен и записан в тег <img /> автоматически. Если рисунок имеет еще и другие атрибуты (например, если он был вставлен после копирования с другого сайта), их тоже можно редактировать;

22. Контроль символов, вводимых при задании имени рисунка, см. предыдущий пункт: пользователь (т.е. я) сможет ввести лишь латинские буквы, цифры, дефис и символ подчеркивания. Расширение вводить не нужно, оно определяется сервером автоматически (и также автоматически попадает затем в src). На сервере проводится тройная проверка рисунка перед сохранением. Во-первых, уточняется тип-расширение (двумя способами проверки, при несовпадении - возвращается ошибка). Во-вторых, тип-расширение проверяется через белый и черный списки расширений по отдельности. В-третьих, проверяется рисунок на корректность, что он представляет собой именно графическое изображение, причем - правильное. Т.е. если там вместо тела рисунка будет некий программный код или что-то еще - вернется ошибка и рисунок сохранен не будет;

23. При наведении мыши на кнопки управления работой редактора их цвет (почти каждой из них) меняется на более заметный, но не раздражающее яркий - на желто-коричневый; при клике на них их иконки (значки) становятся темнее и смещаются чуть вправо и вниз, создавая иллюзию нажатия. Ну, НЕ ЛЮБЛЮ я эти современные сайты (да и некоторые программы), выполненные бездельниками, на которых кнопки никак не окрашиваются - ни при наведении мыши, ни при нажатии (это называется "современный дизайн", от которого воротит, как от помойной ямы). Поэтому для себя сделал так, чтобы все "нажималось" и было контрастно;

24. Возможность очистки формата текста перед вставкой из буфера обмена (любым способом). Это бывает полезно - убрать ненужное форматирование, - если вставлять текст после копирования с других сайтов или из PHPStorm, Word и т.п. (особенно если из Word - оттуда попутно копируется просто масса разных стилей форматирования). Т.е. текст вставляется просто как текст, вообще без тегов (т.е. без ссылок, иных тегов, атрибутов). Это может быть сделано двумя путями:

  1.  При вставке путем нажатия Ctrl + Shift + V. При этом временно (до отпускания клавиши Ctrl) отменяется обработчик события "paste" и строка копируется просто как текст (с учетом символов юникода и html-сущностей, которые вставляются так, как видятся, т.е. в виде символов). Кстати, точно такой же режим вставки (заданный теми же клавишами) я сделал себе и в Word - посредством соответствующего макроса. А то иногда там такое форматирование вставляется, что.
  2. При вставке обычным способом, т.е. посредством Ctrl + V (или путем "Правка, вставить", или через правую кнопку мыши) появляется всплывающее окно и там уже можно выбрать режим вставки: либо как простой текст (без тегов, атрибутов), либо как html-строка (тогда теги и атрибуты будут сохранены). Если тегов нет, то автоматически остается только 1 режим вставки - простого текста.

При выборе режима вставки во всплывающем окне видны оба варианта. Если во вставляемом фрагменте содержатся комментарии - они автоматически будут удалены перед вставкой.

25. Сохранение копии файла страницы с уникальным (включающим временную метку UNIX) именем при каждом ее сохранении. Однажды мне это даже пригодилось;

26. Контроль редактируемой области перед сохранением на наличие посторонних элементов/атрибутов, временно установленных для работы редактора (на всякий случай). Если такие элементы присутствуют - выдается ошибка;

27. Вставка специальных символов. Типа таких: ↕ ►∀ и т.д. Буквально в 1-2 клика мышью;

28. Открытие каталога, содержащего файл редактируемой вебстраницы или тот или иной рисунок, имеющийся на ней, в проводнике Windows.

29. Создание новых вебстраниц на основе шаблонов (templates);

30. Удаление ненужных (расположенных в самых концах блочных и инлайн-блочных тегов) переносов строк перед сохранением на сервере. При этом - временное их добавление (только в редактируемые теги указанных видов), чтобы браузер не "съедал" последние пробельные символы в строках текста вебстраницы при их редактировании;

31. А это, пожалуй, попутно. Это если надо, скажем, применить какой-нибудь стиль (или даже слегка изменить шаблон стилей) - применительно к конкретной вебстранице. Это можно быстро сделать в браузере, как обычно, через инструменты разработчика. И не надо копировать куда-то html-код со сделанными изменениями (как я делал раньше), а достаточно просто сохранить страницу, при этом все сделанные изменения будут сохранены. Очень удобно, конечно;

32. Проверка актуальности страницы, в браузере (т.е. - не устарела ли она, не была ли открыта из кэша; если это так, то выдается сообщение с просьбой - обновить страницу, чтобы получить с сервера наиболее актуальную ее версию). Кроме того, для информации, в панели сообщений показываются первые 20 символов, присутствующих в html-коде страницы, открытой в браузере, которые содержат отличия между этой версией страницы и последней ее версией, сохраненной на сервере. Для удобства, в отдельном каталоге при этом также сохраняется часть соответствующего файла, содержащего в самом конце эти 20 символов.

33. Это, конечно, остается за кадром. При работе редактора то и дело возникает всплывающее окно, а там есть кнопки с обработчиками событий. Когда такое окно в очередной раз удаляется, я реализовал удаление (итератором) всех обработчиков, назначенных ранее его элементам. Не знаю как современные браузеры(?), но в старых, насколько мне известно, существуют утечки памяти. Это когда элемент удаляется, а программный код его обработчиков событий продолжает оставаться в оперативной памяти вплоть до обновления страницы. Т.е. если перед удалением элемента не удалить его обработчики, то они останутся в памяти. И если будет 10 раз создано, а потом 10 раз удалено всплывающее окно с обработчиками событий, то в памяти останутся, соответственно, 10 копий обработчиков каждого соответствующего события. Такое, по идее, еще допустимо на "обычной" вебстранице, но совершенно ни к чему для html-редактора.

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

В целом скажу так. Все-таки, когда делаешь сам под себя (точнее, сам ДЛЯ себя, а то вдруг кто-то поймет не совсем правильно), получается довольно удобно. Правда, все это требует затрат времени и усилий. Ну, и умений. Собственно, делал все перечисленное не просто наобум (из серии, "чтоб было"), а исключительно по потребности. Т.е. сделаешь нечто, потом... ой, а вот тут неудобно или некорректно - сразу доработаешь. После этого - ой, а вот еще здесь надо так и так, само собой просится. Ну, и т.д.

Мне иной раз отвечали, мол, не стоит насиловать браузер и использовать его для того, для чего он не предназначен. Лучше, мол, использовать С++, Qt, java или что-то подобное. Но, все работает, в итоге. В конце концов, браузер - очень функциональная, надежная и удобная графическая оболочка. По сути, браузер + локальный сервер + CMD (Shell) - это более-менее полноценная программная среда, которая способна работать далеко не только с вебстраницами. Тем более, такой браузер, который способен работать одновременно с многими десятками, а то и сотнями разных вкладок, не требуя при этом много ресурсов (это - лишь Firefox и ему подобные браузеры).

Вообще, чем больше работаю с браузерами, тем сильнее понимаю, что в паре с (локальным) сервером они могут заменить, пожалуй, многие программы, такие, как проводник, тот же Paint и т.д. Не говоря уж об Excel и иже с ним. А в Linux, с его богатством консольных команд, возможностей гораздо больше.
Помнится, один знакомый попросил сделать некие расчеты. Так там пришлось некоторые данные подбирать, причем - с умом - так, чтобы суммы определенных показателей совпадали. Вручную это было довольно сложно и долго. В Excel - тоже как-то не очень. Потому как - большой объем данных, да еще и расположены они были в нескольких файлах. А на JS я, помнится, сделал простенькую программу в течение часа.


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

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

Впрочем, если говорить о Windows, то есть не только файлы html, но и hta, к примеру, там окна могут быть, в целом, разными. Хотя, последнее, вроде как, уже устарело.

Почему для меня это актуально, почему вообще пишу об этом? Банально: чтобы не распыляться на разные языки-технологии, если требуется сделать некие мелочи, дополнительную функциональность.

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

С уважением, Салимоненко Д.А.