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 символов


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

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


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

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


Автор: Гость (не зарегистрирован), дата: 15 января, 2013 - 01:26
#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='loading.gif'; void(0);">images</a>

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


Автор: Гость (не зарегистрирован), дата: 8 августа, 2011 - 16:00
#permalink

Гений! Гений!!
Кто-нибудь объясните человеку про присвоение и передачу ссылок на объекты


Автор: Гость (не зарегистрирован), дата: 17 октября, 2010 - 15:58
#permalink

А как подсчитать количество знаков в выделенном тексте в Хроме


Автор: B@rmaley.e><e, дата: 18 октября, 2010 - 08:18
#permalink
<div>Select this text</div>
<span id="counter">Hover this div to know length of selection</span>
<script>
document.getElementById('counter').onmouseover = function(){
  var selection = document.getSelection ? document.getSelection() : window.getSelection();
  this.innerHTML = selection.toString().length;
}
</script>

Автор: Гость (не зарегистрирован), дата: 23 октября, 2010 - 04:46
#permalink

Доброго времени суток, подскажите, где может быть ошибка?

Пытаюсь реализовать описанный для IE способ подключения скриптов через внешние файлы:

имеется закладка

<a href="javascript:(function(){document.getElementsByTagName('head')[0].appendChild(document.createElement('SCRIPT')).src='file:///C:/scripts/test.js';})();"></a>

которая подгружает локальный файл со скриптом

function somefunc()
{
alert("run");
}
somefunc();

Пытался добавлять тоже самое в body, а также вызывать функцию "вручную" через консоль firebug. Сам скрипт и его содержимое появляется в html отладчика, но консоль выдаёт, что функция "not defined", и ничего не происходит. NoScript'ом разрешены локальные скрипты.
Я что-то делаю неправильно, или это какая-то политика безопасности браузера, либо ещё что?


Автор: Гость (не зарегистрирован), дата: 26 октября, 2010 - 03:13
#permalink

Отвечаю на собственный вопрос: действительно, всё дело в политике безопасности браузера (во всяком случае это касается firefox). Вот тут кое-что имеется на эту тему.


Автор: Андрей (гость) (не зарегистрирован), дата: 24 октября, 2010 - 14:27
#permalink

про букмарклеты знаю "не вчера", но только сейчас возник вопрос, в котором гугл - не помощь. Как "защититься" от этих букмарклетов? Используя их не составит труда изменить (например) значения скрытых инпутов форм. Конечно, подобные поля при правильной логике не содержат критической информации.. Но, например, баловства ради, добавить комментарий не в ту ветку, или к другому высказыванию.. и т.п. Судя по моим "изысканиям" такой защиты нет, верно?


Автор: AweMerC (не зарегистрирован), дата: 13 января, 2011 - 08:18
#permalink

Создаю свой проект. И возник точно такой же вопрос, как и у Вас. Ведь любой школьник уже сможет с легкостью поломать мне мою задумку. Сейчас этих так называемых готовых букмарклетов хоть отбавляй! Но никто не пишет как от них защититься, возможно никто и не знает как это сделать. Может все-таки есть умники? Так же, этот вопрос попробую решить сам. Если найду решение, обязательно отпишусь.


Автор: Aндрeй (не зарегистрирован), дата: 1 февраля, 2011 - 01:58
#permalink

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


Автор: sparc64, дата: 15 декабря, 2013 - 02:37
#permalink

Сейчас появилась возможность отключить скрипты из неизвестных источников.
Посмотрите в сторону заголовков ответа сервера: "content-security-policy" и "x-content-security-policy"


Автор: ksi, дата: 1 апреля, 2011 - 19:15
#permalink

Скажите, а обязательно использовать encodeURIComponent() (в поисковом запросе)?


Автор: guest (не зарегистрирован), дата: 1 ноября, 2013 - 00:04
#permalink

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


Автор: Hfub (не зарегистрирован), дата: 7 мая, 2011 - 09:36
#permalink

Подскажите, можно ли сделать так чтобы скрипт (Букмарклет) выполнялся автоматически сразу при загрузке страницы? Т.е. как совместить его написание а адресной строке вместе с адресом сайта?


Автор: Гость (не зарегистрирован), дата: 8 мая, 2011 - 22:29
#permalink

Букмарклет тут не поможет. Смотрите в сторону UserJS.


Автор: Гость (не зарегистрирован), дата: 5 июля, 2011 - 15:50
#permalink

Добрый день!
Подскажите пожалуйста, мне необходимо реализовать букмарклет, палитры цветов для сайта, и при наличии изображения необходимо вытащить из него все цвета, но я не могу воспользоваться же для этого canvas, так как он не является js кодом, а по другому пройти каждый пиксель изображения не знаю как.
Заранее спасибо!


Автор: _SR_71_, дата: 25 марта, 2012 - 21:39
#permalink

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


Автор: zenitchik (не зарегистрирован), дата: 4 июня, 2012 - 12:02
#permalink

_SR_71_
Букмарклет вы храните у себя, а применяете к любому сайту, не обязательно своему.
Например, можно удалить рекламу (у меня был случай, когда реклама была внатуре нестерпимо мерзкая, и расположенная рябом с видио, которое мне нужно было просмотреть).

Эпидемия jQuery головного мозга, СИЛЬНО облегчает разработку букмарклетов
На более-менее крупном сайте наверняка включён jQuery, а если нет - то какая-то другая библиотека.


Автор: Гость (не зарегистрирован), дата: 1 июля, 2014 - 08:01
#permalink

><><>\>


Автор: zames (не зарегистрирован), дата: 14 ноября, 2014 - 22:28
#permalink

День добрый!
Народ помогите пожалуйста начинающему разобраться со следующей конструкцией из примера:

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;
Условие не выполнилось значит алерт мы не увидим, но фрейм на странице есть
Вопрос где я ошибаюсь?

Очень надеюсь на Вашу помощь!
Спасибо!


Автор: serega386, дата: 30 июля, 2016 - 00:41
#permalink

Есть еще один нюанс с символом %. Их нужно заменить на %25 и отделить пробелом от последующего числа.


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

Приветствуются комментарии:
  • Полезные.
  • Дополняющие прочитанное.
  • Вопросы по прочитанному. Именно по прочитанному, чтобы ответ на него помог другим разобраться в предмете статьи. Другие вопросы могут быть удалены.
    Для остальных вопросов и обсуждений есть форум.
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 + 0 =
Введите результат. Например, для 1+3, введите 4.
 
Текущий раздел
Поиск по сайту
Реклама
Содержание

Учебник javascript

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

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

Интерфейсы

Все об AJAX

Оптимизация

Разное

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

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