Мастер-классы по Javascript, AJAX/COMET, jQuery Узнать больше...
Javascript.RU

Букмарклеты и правила их написания

Букмарклет(bookmarklet) - это javascript-код, который сохраняется как закладка в браузере. Он работает за счет использования протокола <a href="javascript:...">.

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

Поэтому де-факто букмарклет - это javascript-плагин к браузеру.

Для примера сделаем букмарклет, который осуществляет поиск выделенного текста в гугле.

Функция на javascript была бы такая:

function searchGoogle() {
  var selected
  
  if (window.getSelection) selected = window.getSelection()
  else if (document.getSelection) selected = document.getSelection()
  else selected = document.selection.createRange().text
  var q = "" + selected

  if (q)  location="http://www.google.com/search?q="+encodeURIComponent(q);
  void 0;
}

В конце функции searchGoogle стоит void 0. Это кроссбраузерно останавливает обработку ссылки браузером, предотвращая ненужный переход.

Испытаем ее:

<a href="javascript:searchGoogle();">Искать выделенное</a>

Выделите текст и кликните: Искать выделенное

Чтобы превратить функцию в букмарклет - достаточно "запаковать" ее в одну строку и заменить кавычки на одинарные (или на &quot;,), чтобы не было конфликта с закрывающими кавычками javascript:

<a href="javascript: if (window.getSelection) selected = window.getSelection(); else if (document.getSelection) selected = document.getSelection(); else selected = document.selection.createRange().text; q = &quot;&quot;+selected; if (q) location=&quot;http://www.google.com/search?q=&quot;+encodeURIComponent(q);  void 0; ">Искать выделенное</a>

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

После этого достаточно выделить текст на странице и кликнуть на закладку, чтобы найти выделенный текст в гугл.

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

Есть несколько способов обойти эту проблему.

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

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

if(frames.length > document.getElementsByTagName('iframe').length)
  alert('Извините, фреймы не поддерживаются.');
else{
  /* код букмарклета */
}

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

Решение - рекурсивный обход фреймов:

function traverse(win){
  try{
    /* Работа с win.document */
    ...
  } catch(e){
    /* Ошибка доступа к фрейму */
  }

  /* Вызов traverse для вложенных фреймов */
  for(var i=0; i<win.frames.length; i++) {
      traverse(win.frames[i]);
  }
}
traverse(window);

Вызов traverse(window) рекурсивно обрабатывает(например, ищет выделение) все фреймы, начиная с текущего окна.

В нее добавлена конструкция try ... catch для обработки возможных ошибок безопасности браузера, которые происходят, если доступ к фрейму противоречит политике Same Origin. Например, когда ифрейм используется для показа рекламы с другого домена.

Так как букмарклет закрыт в двойные кавычки - желательно использовать в коде либо &quot;, либо одинарные.

Например, в букмарклете для поиска в гугл можно заменить все &quot; на одинарные кавычки. Тоже будет работать:

<a href="javascript: if (window.getSelection) selected = window.getSelection(); else if (document.getSelection) selected = document.getSelection(); else selected = document.selection.createRange().text; q = ''+selected; if (q) location='http://www.google.com/search?q='+encodeURIComponent(q);  void 0; ">Искать выделенное</a>

Если функция или операция присваивания возвращает значение - то, какое бы оно ни было, букмарклет перенаправит посетителя на новую страницу, которая показывает это значение.

Иногда это можно грамотно использовать. например показать сводку по ключевым словам в документе. Обычно же это значение перехватывают и обнуляют при помощи void. Типичное решение - поставить в конце букмарклета:

void 0;

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

<a href="javascript: (function(){ .... })()">переколбасить страницу</a>

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

Букмарклет работает в глобальной области видимости.

Это значит, что даже переменная, объявленная с var, будет глобальной:

<a href="javascript: var a = 5; void 0">Запишет в window.a</a>

Чтобы это обойти - используют 2 способа.

Первый - назначить переменным уникальные имена типа aBBZZ. Это криво.

Второй - оборачивать букмарклет в анонимную функцию:

<a href="javascript:(function(){ var a = 5; })()">Запишет в локальную переменную</a>

При этом также отпадает необходимость в void.

Так выглядит поисковый букмарклет, обернутый в анонимную функцию:

<a href="javascript:(function(){ var selected; if (window.getSelection) selected = window.getSelection(); else if (document.getSelection) selected = document.getSelection(); else selected = document.selection.createRange().text; var q = ''+selected; if (q) location='http://www.google.com/search?q='+encodeURIComponent(q);})(); ">Искать выделенное</a>

В отличие от исходного варианта, он не загрязняет глобальную область переменными selected и q.

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

Вот некоторые данные:

Браузер Максимальное кол-во символов
Netscape > 2000
Firefox > 2000
Opera > 2000
IE 4 2084
IE 5 2084
IE 6 508
IE 6 SP 2 488
IE 7 2084

Как видите, Internet Explorer 6.0 держит до 508 символов, а Internet Explorer 6.0 SP2 - еще хуже, всего лишь 488 символов. Так что, если вы хотите быть уверенными, что букмарклет запустится в IE6 - ограничьте его 488 символами.

Это ограничение не относится напрямую к размеру скрипта в <a href="javascript:...">. Оно срабатывает когда букмарклет добавляют в избранное. Вы можете сделать замечательный букмарклет, он будет работать на странице, но при добавлении в избранное код будет обрезан.

Чтобы это обойти, букмарклет в IE может подключать внешние скрипты:

...
var script=document.createElement('script')
script.src='http://my.bookmarklet.ru/myscript.js'
document.getElementsByTagName('head')[0].appendChild(script)
...

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

Например, многие SEO'шные букмарклеты сделаны именно так. Хочешь использовать - поставь FF и инструмент к твоим услугам.

Успешного плагинописания!


Автор: Gvozd, дата: 25 октября, 2008 - 18:46
#permalink

Грамотная статья!
раскрыты некоторые особенности, про которые нет ни слова в других статьях про букмарклеты.
Большое спасибо


Автор: Lex1 (не зарегистрирован), дата: 16 ноября, 2008 - 19:12
#permalink

> Максимальное кол-во символов
Google Chrome > 2000 (проверено с ~16000 символами)
Safari Win - около 2000 символов


Автор: Mussolini (не зарегистрирован), дата: 14 января, 2009 - 13:47
#permalink

Ну наконецто хоть тут раскрыты некоторые особенности.


Автор: Time (не зарегистрирован), дата: 15 января, 2009 - 13:59
#permalink

Для надежной работы надо исключить ифреймы полностью.


Автор: Grif (не зарегистрирован), дата: 16 января, 2009 - 13:51
#permalink

Грамотная статья! и очень понятная


Автор: Life (не зарегистрирован), дата: 19 января, 2009 - 16:06
#permalink

Для меня лично непонятно даже мой друг непонял..


Автор: Гость (не зарегистрирован), дата: 16 февраля, 2009 - 19:52
#permalink

а можно ли выбрать window.getSelection() из нужного div?


Автор: FRACTAL (не зарегистрирован), дата: 20 февраля, 2009 - 12:43
#permalink

Хорошая статейка, СПАСИБО! А хто-нить подскажет, каг сделать чтобы этот выделенный текст, который потом ишет Гугл, открывался в новой вкладке?


Автор: Гость (не зарегистрирован), дата: 26 марта, 2009 - 14:47
#permalink

 open('http://www.google.com/search?q='+encodeURIComponent(q))
вместо
location='http://www.google.com/search?q='+encodeURIComponent(q)


Автор: dantistus (не зарегистрирован), дата: 9 апреля, 2009 - 22:58
#permalink

Офигенская статья, спасибо вам большое! Только что открыл для себя удивителный мир букмарклетов, буду думать, как его можно использовать для себя


Автор: vk (не зарегистрирован), дата: 20 апреля, 2009 - 02:38
#permalink

Да, здорово!
Как я понимаю, поколдовав с запросом и кодом, можно как проводить google-поиск по конкретному сайту или сайтами, а может и выводить результаты в рамках своего ресурса.


Автор: Гость (не зарегистрирован), дата: 21 декабря, 2009 - 02:44
#permalink
if (top != window) ...

Это к предмету вывода "в рамках"


Автор: tenshi, дата: 14 февраля, 2010 - 17:16
#permalink

void 0 - не нужен

.ня


Автор: HelpeR, дата: 28 марта, 2010 - 09:59
#permalink

Прочитав статью я сразу же обрадовался и попытался сделать такой букмарклет

<a href="javascript: var img = document.getElementsByTagName('img'); img[0].src = 'тут свой рисунок';">images</a>

но к сожалению это не работает ))


Автор: Артём Шегеда, дата: 25 августа, 2010 - 23:51
#permalink

где-то так:

<a href="javascript:(function(){var img = document.getElementsByTagName('img'); img?(img[0].src='http://javascript.ru/modules/smileys/packs/smilies/smile.gif'):0;})()">Заменить</a>

Автор: Increazon, дата: 15 апреля, 2010 - 01:30
#permalink

popa, для FireFox есть дополнение GreaseMonkey которое все ети скрипты управлять и можно неограниченная длинна. Но оно никому не надо. Опера, Хроме = Отстой, Сафари мы любим, Но самый самый фаирфокс!


Автор: max_the_best (не зарегистрирован), дата: 26 июня, 2010 - 18:10
#permalink

HelpeR,
код типа:

<a href="javascript: var img = document.getElementsByTagName('img'); img[0].src = 'тут свой рисунок';">images</a>

не будет работать в принципе, так как img[0].src вставляет изображение в массив img , а не в документ.Правильно так:

<a href="javascript:document.getElementsByTagName('img')[0].src='/forum/loading.gif'; void(0);">images</a>

прочитай про букмарклеты ещё раз внимательнее.


Отправить комментарий

Приветствуются комментарии:
  • Полезные.
  • Дополняющие прочитанное.
  • Вопросы по прочитанному. Именно по прочитанному, чтобы ответ на него помог другим разобраться в предмете статьи. Другие вопросы могут быть удалены.
    Для остальных вопросов и обсуждений есть форум.
P.S. Лучшее "спасибо" - не комментарий, как все здорово, а рекомендация или ссылка на статью.
Содержание этого поля является приватным и не предназначено к показу.
  • Адреса страниц и электронной почты автоматически преобразуются в ссылки.
  • Разрешены HTML-таги: <strike> <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd> <u> <i> <b> <pre> <img> <abbr> <blockquote> <h1> <h2> <h3> <h4> <h5> <p> <div> <span> <sub> <sup>
  • Строки и параграфы переносятся автоматически.
  • Текстовые смайлы будут заменены на графические.

Подробнее о форматировании

CAPTCHA
Антиспам
3 + 1 =
Введите результат. Например, для 1+3, введите 4.
 
Новости

Открылась регистрация на мастер-классы по профессиональному Javascript, AJAX/COMET, jQuery в городах:

  • Ярославль (24-25 сентября)
  • Новосибирск (3-4 октября)
  • Казань (9-10 октября)
  • Минск (16-17 октября)
  • Днепропетровск (23-24 октября)
  • Одесса (30-31 октября)
  • Самара (13-14 ноября)

Более подробно - на странице мастер-классов.

Если вас интересует другой город - посмотрите здесь, выбрав "Другие города".

Текущий раздел
Поиск по сайту
Содержание

Учебник javascript

Основные элементы языка

Сундучок с инструментами

Интерфейсы

Все об AJAX

Оптимизация

Разное

Дерево всех статей

Статьи и мероприятия

Будьте в курсе наших последних новостей!

Последние обсуждения на форуме
Forum
Последние комментарии