Букмарклет(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>
Выделите текст и кликните: Искать выделенное
Чтобы превратить функцию в букмарклет - достаточно "запаковать" ее в одну строку и заменить кавычки на одинарные (или на ",), чтобы не было конфликта с закрывающими кавычками javascript:
<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>
Все, букмарклет готов. Для установки - достаточно перетащить мышкой эту ссылку в закладки.
После этого достаточно выделить текст на странице и кликнуть на закладку, чтобы найти выделенный текст в гугл.
Открытый документ может представлять собой фреймсет. При этом способы обращения к содержимому, использованные в нашем примере, работать не будут. Текст надо искать во фреймах, а не в текущем окне.
Есть несколько способов обойти эту проблему.
Если букмарклет не задуман для работы с фреймами - можно проверять их наличие и выводить предупреждение.
Для более надежной работы исключим ифреймы: в подавляющем большинстве сайтов они используются чисто технологически: в 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. Например, когда ифрейм используется для показа рекламы с другого домена.
Так как букмарклет закрыт в двойные кавычки - желательно использовать в коде либо ", либо одинарные.
Например, в букмарклете для поиска в гугл можно заменить все " на одинарные кавычки. Тоже будет работать:
<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 и инструмент к твоим услугам.
Успешного плагинописания!