jQuery в помощь: BBCode html-toolbar средствами jCaret

jQuery в помощь: BBCode html-toolbar средствами jCaret

Оригинал статьи: Janko   СС-лицензия: byncsa

comments Комментариев 11

Несмотря на то, что многие пользователи не согласны с тем, что продукты Microsoft могут служить примером удачного дизайна, всплывающая мини-панель инструментов (minibar, mini-toolbar), впервые появившаяся в Office 2007 стала очень удачным дизайн-решением. Всплывающая мини-панель – это разновидность панели инструментов, которая разворачивается непосредственно около выделенного участка текста, что позволяет пользователю очень быстро осуществлять действия над выделенным фрагментом.

В этой статье я показу, как с помощью замечательного j-Query плагина jCaret создать ВОТ ТАКОЕ всплывающее меню, содержащее bbcode-кнопки <b>, <i>, <ul> и <link> (прим. перев.: основываясь на демонстрируемой технике, остальные желаемые кнопки форматирования вы сможете добавить сами).

html-toolbar

Как это работает

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

Создаём разметку

Перво-наперво, формируем html-разметку. Она должна выглядеть следующим образом:

<textarea  id="description" rows="8"  cols="50"></textarea>
  <div  id="menu">
  <a href="#"  id="bold">b</a>
  <a href="#"  id="italic">i</a>
  <a href="#"  id="underline">u</a>
  <a href="#"  id="link">Link</a>
  </div>

Оформляем toolbar

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

#menu  {
  padding:5px; 
  background-color:#f5f5f5;
  background-color:rgba(245, 245, 245, 0.6);
  display:none; 
  position:absolute;
  top:0px;
  left:0px;
  overflow:hidden;
  border:solid 1px #929292;
  border-radius:3px;
  -moz-border-radius:3px;
  -webit-border-radius:3px;
  box-shadow: 5px 5px 5px #888;
  -moz-box-shadow: 1px 1px 3px #555;
  -webkit-box-shadow: 5px 5px 5px #888;
  }
  #menu:hover  {background-color:rgba(245, 245, 245, 1);}

Появление и исчезновение

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

$(document).ready(function() { 
  //создаём  переменные для координат точки курсора
  var mouseX = 0;
  var mouseY = 0;
  
  $("#description").mousemove(function(e)  {
  // отслеживаем позицию курсора
  mouseX = e.pageX;
  mouseY = e.pageY;
  });
  
  // Прячем тулбар
  $("#description").mousedown(function() {
  $("#menu").fadeOut("1000");
  });
  
  $("#description").select(function() {
  // вычисляем  позицию курсора и показываем тулбар при наступлении события .select 
  $("#menu").css("top",  mouseY - 30)
  .css("left", mouseX +  10).fadeIn("1000");
  });
});

Нажатие на кнопку

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

function wrapText(startText, endText){
  // находим  и помещаем в переменную текст, расположенный до начала выделенного фрагмента
  var before =  $("#description").val().substring(0,  $("#description").caret().start);
  
  // находим и помещаем в переменную  текст, расположенный после выделенного фрагмента
  var after =  $("#description").val().substring($("#description").caret().end,  $("#description").val().length);
  
  // объединяем все фрагменты текста:  фрагмент до выделения, обрамляющие теги и выделенный фрагмент, а также фрагмент  после выделения
  $("#description").val(before  + startText + $("#description").caret().text + endText + after);
  }

Эта функция основывается на jQuery-плагине jCaret. Она заключает выделенный фрагмент в теги и присоединяет к нему предществующий и последующий фрагменты. Довольно просто, не так ли?! Осталось только прописать, какими тегами функции wrapText() следует обрамлять выделенный фрагмент при наступлении события .click на кнопке bbcode-панели.

$("#bold").click(function()  {
  wrapText("<strong>",  "</strong>");
  $("#menu").fadeOut("1000");
  });
  $("#italic").click(function()  {
  wrapText("<em>",  "</em>");
  $("#menu").fadeOut("1000");
  });
  $("#underline").click(function()  {
  wrapText("<u>",  "</u>");
  $("#menu").fadeOut("1000");
  });
  $("#link").click(function()  {
  var url = prompt("Введите адрес ссылки:",  "http://");
  if (url != null)
  wrapText("<a href='" + url  + "'>", "</a>");
  $("#menu").fadeOut("1000");
  });

Обработка кликов по кнопкам <b>, <i> и <u> довольно проста: вызываем функцию wrapText(), передаём ей в параметрах открывающий и закрывающий теги и затем плавно скрываем наш минибар. А вот для кнопки с кнопкой <link> немного сложнее: тут нам прежде всего необходимо попросить пользователя ввести текст ссылки, затем поместить его в переменную, и только потом вызвать функцию wrapText().

Заключение

Регулярно используя Word, я порой ощущаю некоторую нехватку такой панельки при наборе текста на страницах веб-сайтов. Мне, например, очень бы хотелось, чтобы таким виджетом были оборудованы WYSIWYG редакторы, такие как TinyMCE. Тулбар можно с успехом использовать для контакт- и коммент-форм.

Приведённый в этой статье код – это не догма, а всего лишь один из примеров реализации самой идеи. Дорабатывайте и совершенствуйте его по своему усмотрению. Удачи!

  • Понравилась статья?
    Добавь в закладки
    или поделись с друзьями:  

Комментарии


no avatar
17:53 24.02.11

Почему-то в Мозилле и Эксплолере не работает! :(
А так круто, спасибо! Только что делать с ФайрФоксом?


#1 Цитировать

@D1ma Z.
В каких версиях браузеров Вы проверяли?

Сейчас проверил страницу примера в IE8 и FF 3.6.13 - сценарий работает исправно...

В IE, конечно, будет отсутствовать полупрозрачность панельки и склуглённость уголков, т.к. эксплорер “не понимает” CSS3, но сам jQuery-сценарий срабатывает как должен.


#2 Цитировать

no avatar
14:25 25.02.11

Спасибо! Разобрался.
Файрфокс тот же. Да и в ИЕ7 даже работает. Только работает тогда, когда прописываю в одном файле все наши скрипты и все содержимое с файла jcaret.
А когда подключал на странице их отдельно, не работало почему-то.


#3 Цитировать

no avatar
10:03 01.03.11

Здравствуйте! Все работает, спасибо, очень нравится, только есть одно НО. Корректно теги добавляются в текст только в том случае, если он сплошной, т.е. в <textarea> он идет одной строчкой и без переносов строк (без нажатия по клавиши Enter). Сначала подумал, что это я испортил, когда менял что-то. А нет, глянул в Вашем примере, а там точно такая же ошибка.
Если это возможно, помогите пожалуйста исправить это. Заранее спасибо!


#4 Цитировать

@D1ma Z.

Если честно, не совсем понял проблему...

Сейчас проверил так: порасставлял разрывов строк в <textarea>, затем повыделял фрагменты (как включающие сам разрыв строки, так и не включающие) и покликал по bbcode-менюшке. Теги оперативно вставляются в <div id=“preview”>. Иными словами, проблемы не обнаружил.

Если же Вы имеете в виду отображение в <div id=“preview”> самого разрыва строки, то тут он, конечно, не предусмотрен, т.к. данная статья немного не о том, как сделать динамический предпросмотр вводимого сообщения. :)

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

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


#5 Цитировать

no avatar
14:52 01.03.11

Нууу, если можно, был бы весьма признателен за динамический сценарий. :)

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

Вот, так сказать, для наглядноти то, что я имею ввиду :) :
http://download52.files.mail.ru/O1FC9I/270e3cfa27ac8008c15180e16f99ddbb/рисунок.jpg

Я ввел слово Информация и в каждой строке выделял одни и те же буквы - рм. И вот как то оно сдвигается с каждой строкой. :(


#6 Цитировать

@D1ma Z.

Вот: http://web-bricks.ru/ex/dynamic_preview.html первая попытка интеграции предпросмотра и bbcode-тулбара.

Сейчас пока есть кое-какие недоработочки... В частности, те о которых Вы и писали - функция wrapText срабатывает не совсем корректно, если присутствуют символы возврата каретки “/n”. Только вот локализовать причину пока не удалось.

Думаю, если будет время, на ближайших выходных поправлю.

P.S. Может даже сделаю отдельную статью по этому сценарию, если баги удастся побороть. ;)


#7 Цитировать

no avatar
07:48 02.03.11

Обязательно посмотрю! :)
Только Вы тогда тут отпишитесь пожалуйста, чтоб мне на e-mail письмо пришло.


#8 Цитировать

no avatar
09:51 02.04.11

2 Иван Саломатин, D1ma Z.
Под виндами перевод каретки осуществляется комбинацией \r\n, может в этом дело?


#9 Цитировать

@Василий

Ну, не совсем. Тут есть некоторая разница в работе с textarea между gecko-браузерами (FF, Chrome, Safari) и прочими.

Также, IE не воспринимает методы selectionStart и selectionEnd, что вынуждает для него использовать объект selection и его метод createRange…

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


#10 Цитировать

Итак, вот пример несколько поправленного предпросмотра с интегрированной bbcode-панелью: http://web-bricks.ru/ex/bbcprev.html

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

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

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


#11 Цитировать

Добавить комментарий


Сообщать о последующих комментариях

Пожалуйста, введите слово, которое Вы видите на изображении:



© WEB-BRICKS.RU 2010 | УСЛОВИЯ КОПИРОВАНИЯ | ОБРАТНАЯ СВЯЗЬ | СПИСОК ПОЛЬЗОВАТЕЛЕЙ