Букмарклеты и правила их написания
Букмарклет(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-поиск по конкретному сайту или сайтами, а может и выводить результаты в рамках своего ресурса.
Это к предмету вывода "в рамках"
Прочитав статью я сразу же обрадовался и попытался сделать такой букмарклет
но к сожалению это не работает ))
где-то так:
popa, для FireFox есть дополнение GreaseMonkey которое все ети скрипты управлять и можно неограниченная длинна. Но оно никому не надо. Опера, Хроме = Отстой, Сафари мы любим, Но самый самый фаирфокс!
HelpeR,
код типа:
не будет работать в принципе, так как img[0].src вставляет изображение в массив img , а не в документ.Правильно так:
прочитай про букмарклеты ещё раз внимательнее.
Гений! Гений!!
Кто-нибудь объясните человеку про присвоение и передачу ссылок на объекты
А как подсчитать количество знаков в выделенном тексте в Хроме
Доброго времени суток, подскажите, где может быть ошибка?
Пытаюсь реализовать описанный для IE способ подключения скриптов через внешние файлы:
имеется закладка
которая подгружает локальный файл со скриптом
Пытался добавлять тоже самое в body, а также вызывать функцию "вручную" через консоль firebug. Сам скрипт и его содержимое появляется в html отладчика, но консоль выдаёт, что функция "not defined", и ничего не происходит. NoScript'ом разрешены локальные скрипты.
Я что-то делаю неправильно, или это какая-то политика безопасности браузера, либо ещё что?
Отвечаю на собственный вопрос: действительно, всё дело в политике безопасности браузера (во всяком случае это касается firefox). Вот тут кое-что имеется на эту тему.
про букмарклеты знаю "не вчера", но только сейчас возник вопрос, в котором гугл - не помощь. Как "защититься" от этих букмарклетов? Используя их не составит труда изменить (например) значения скрытых инпутов форм. Конечно, подобные поля при правильной логике не содержат критической информации.. Но, например, баловства ради, добавить комментарий не в ту ветку, или к другому высказыванию.. и т.п. Судя по моим "изысканиям" такой защиты нет, верно?
Создаю свой проект. И возник точно такой же вопрос, как и у Вас. Ведь любой школьник уже сможет с легкостью поломать мне мою задумку. Сейчас этих так называемых готовых букмарклетов хоть отбавляй! Но никто не пишет как от них защититься, возможно никто и не знает как это сделать. Может все-таки есть умники? Так же, этот вопрос попробую решить сам. Если найду решение, обязательно отпишусь.
Нет, не "защититься". Все, что на стороне пользователя и всё, что от него приходит - на веру принимать нельзя )) Только (своего рода) кеширование формы перед выдачей и пост-проверка возвращаемых значений
Сейчас появилась возможность отключить скрипты из неизвестных источников.
Посмотрите в сторону заголовков ответа сервера: "content-security-policy" и "x-content-security-policy"
Скажите, а обязательно использовать encodeURIComponent() (в поисковом запросе)?
Да, обязательно. Это кодирует специальные символы в URLEncode, иначе данные могут отправиться не правильно.
Подскажите, можно ли сделать так чтобы скрипт (Букмарклет) выполнялся автоматически сразу при загрузке страницы? Т.е. как совместить его написание а адресной строке вместе с адресом сайта?
Букмарклет тут не поможет. Смотрите в сторону UserJS.
Добрый день!
Подскажите пожалуйста, мне необходимо реализовать букмарклет, палитры цветов для сайта, и при наличии изображения необходимо вытащить из него все цвета, но я не могу воспользоваться же для этого canvas, так как он не является js кодом, а по другому пройти каждый пиксель изображения не знаю как.
Заранее спасибо!
А что именно полезного в букмарклетах, ведь то же самое можно написать в функциях, а потом запускать эту функцию при нажатии на ту же ссылку.
Да, и можно по подробнее, как нанести вред с помощью букмарклетов, потому что пример с формами я не понял.
_SR_71_
Букмарклет вы храните у себя, а применяете к любому сайту, не обязательно своему.
Например, можно удалить рекламу (у меня был случай, когда реклама была внатуре нестерпимо мерзкая, и расположенная рябом с видио, которое мне нужно было просмотреть).
Эпидемия jQuery головного мозга, СИЛЬНО облегчает разработку букмарклетов
На более-менее крупном сайте наверняка включён jQuery, а если нет - то какая-то другая библиотека.
День добрый!
Народ помогите пожалуйста начинающему разобраться со следующей конструкцией из примера:
1 if(frames.length > document.getElementsByTagName('iframe').length)
2 alert('Извините, фреймы не поддерживаются.');
3 else{
4 /* код букмарклета */
5 }
А именно ,не могу сообразить в каких ситуациях условие в if вернет истину.
Как рассуждаю я , есть допустить на странице один элемент Iframe , следовательно
window.frames.length = 1;
Обьект NodeList Возвращаемый методом getElementsByTagName , будет содержать 1 обьект iframe , значит document.getElementsByTagName('iframe').length= 1;
Условие не выполнилось значит алерт мы не увидим, но фрейм на странице есть
Вопрос где я ошибаюсь?
Очень надеюсь на Вашу помощь!
Спасибо!
1 if(frames.length >= document.getElementsByTagName('iframe').length)
2 alert('Извините, фреймы не поддерживаются.');
3 else{
4 /* код букмарклета */
5 }
Есть еще один нюанс с символом %. Их нужно заменить на %25 и отделить пробелом от последующего числа.
Огонь, спасибо за мануал, и вообще сайт крутой
Я вот тут https://iksweb.ru/tools/bookmarklet/ букмарклеты беру и доволен.