Букмарклеты и правила их написания
Букмарклет(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 и инструмент к твоим услугам.
Успешного плагинописания!
|
Грамотная статья!
раскрыты некоторые особенности, про которые нет ни слова в других статьях про букмарклеты.
Большое спасибо
> Максимальное кол-во символов
Google Chrome > 2000 (проверено с ~16000 символами)
Safari Win - около 2000 символов
Ну наконецто хоть тут раскрыты некоторые особенности.
Для надежной работы надо исключить ифреймы полностью.
Грамотная статья! и очень понятная
Для меня лично непонятно даже мой друг непонял..
а можно ли выбрать window.getSelection() из нужного div?
Хорошая статейка, СПАСИБО! А хто-нить подскажет, каг сделать чтобы этот выделенный текст, который потом ишет Гугл, открывался в новой вкладке?
open('http://www.google.com/search?q='+encodeURIComponent(q))
вместо
location='http://www.google.com/search?q='+encodeURIComponent(q)
Офигенская статья, спасибо вам большое! Только что открыл для себя удивителный мир букмарклетов, буду думать, как его можно использовать для себя
Да, здорово!
Как я понимаю, поколдовав с запросом и кодом, можно как проводить google-поиск по конкретному сайту или сайтами, а может и выводить результаты в рамках своего ресурса.
Это к предмету вывода "в рамках"
void 0 - не нужен
.ня
Прочитав статью я сразу же обрадовался и попытался сделать такой букмарклет
<a href="javascript: var img = document.getElementsByTagName('img'); img[0].src = 'тут свой рисунок';">images</a>но к сожалению это не работает ))
где-то так:
<a href="javascript:(function(){var img = document.getElementsByTagName('img'); img?(img[0].src='http://javascript.ru/modules/smileys/packs/smilies/smile.gif'):0;})()">Заменить</a>popa, для FireFox есть дополнение GreaseMonkey которое все ети скрипты управлять и можно неограниченная длинна. Но оно никому не надо. Опера, Хроме = Отстой, Сафари мы любим, Но самый самый фаирфокс!
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. Лучшее "спасибо" - не комментарий, как все здорово, а рекомендация или ссылка на статью.Для остальных вопросов и обсуждений есть форум.