В процессе работы над Pastemark (пост-анонс) мне понадобилось, во-первых, написать довольно сложный букмарклет и, во-вторых, сделать динамическую генерацию букмарклетов с разными параметрами. Не возьмусь претендовать на новизну, а лишь просто поделюсь найденным мною подходом.
О букмарклетах
Для тех, кто с ними еще не сталкивался с букмарклетами, букмарклет — это разновидность закладки, но от обычной закладки он отличается тем, что вместо адреса страницы в ней записан скрипт, как правило не очень большой.
Спектр применений букмарклетов довольно широк: от простого изменения размера шрифта на текущей странице до анализа ее содержимого и передачи извлеченных данных какому-нибудь третьему сервису. В качестве примера можно привести букмарклет твиттера.
Кроме того, букмарклет — это практически единственный шанс для честного вебмастера выполнить свой код в контексте чужого сайта (-:
Когда нужно писать букмарклет?
Собственно, ответ уже дан в предыдущем параграфе. Фактически, букмарклет занимает промежуточную роль между скриптами на сайте и расширением браузера: его функциональность все еще ограничена по сравнению с полноценным расширением, но он уже не привязан к какому-то одному сайту. Еще одна приятная сторона — один и тот же букмарклет может работать во всех браузерах сразу, включая те, которые не поддерживают расширения как таковые (реверанс в сторону мобильных браузеров).
Так как же его написать?
Основные концепции написания букмарклетов хорошо изложены в статье на javascript.ru. Я же не буду лишний раз повторяться и сразу перейду к своей методике.
Мы все привыкли писать нормальные JS-функции, пользуясь IDE или просто блокнотом, а букмарклеты требуют от нас вытягивать весь код в одну строчку да еще и экранировать, что довольно муторно. Поэтому логично переложить эту работу на программу, а еще лучше — позволить программе самой себя приводить в нужный вид.
И так, прежде всего, нам нужно написать функцию, из которой мы будем делать букмарклет. Здесь нам все близко и знакомо, лишь только вместо привычного синтаксиса
1
2
3
|
function my_bookmarklet() {
/* ... */
}
|
Мы прибегнем к альтернативному варианту:
1
2
3
|
var my_bookmarklet = function (arg1, arg2) {
/* ... */
};
|
Это связано с тем, что в букмарклете нам нужна не именованная функция, а анонимная, чтобы не засорять пространство имен и избежать конфликтов.
Генерация итогового букмарклета
После того, как мы написали функцию, нам нужно превратить ее в букмарклет. Краткости ради я сразу приведу фрагмент кода, выполняющий эту функцию:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
// Ключевой момент: делаем из анонимной функции строку с ее исходниками.
var code = my_bookmarklet.toString();
// Вырезаем однострочные и многострочные комментарии.
code = code.replace(/\/\/.*/g, "");
code = code.replace(/\/\*[\s\S]*\*\//, "");
// Заменяем переносы строк пробелами
code = code.replace(/\n/g, " ");
// Вырезаем повторяющиеся пробелы. Если у вас внутри строковых литералов
// есть повторяющиеся пробелы, то этого лучше не делать.
code = code.replace(/\s+/g, " ");
// Генерируем uri, при этом экранируем спецсимволы.
var link = encodeURI(
"javascript:void(" +
code +
'("' +
value_for_arg1 +
'", "' +
value_for_arg2 +
'"))'
);
|
Обратите внимание на переменные value_for_arg1 и value_for_arg2. Если вам нужно (как в моем случае) генерировать параметризованные букмарклеты, то вы можете это легко реализовать, передавая параметры вашей анонимной функции.
Далее с переменной link можно делать все, что хотите — генерировать и вставлять на страницу ссылку с этим значением href, отображать просто так или что вам еще в голову придет.
Грабли
Есть только одни грабли, на которые легко попасться в процессе написания букмарклета таким способом: ни в коем случае нельзя пользоваться какими-либо функциями или переменными, объявленными вне экспортируемой функции, ведь во время исполнения букмарклета (а это почти наверняка произойдет не на вашем сайте и в чужом окружении) все они доступны не будут. Я, кстати, на эти грабли тоже наступил, правда, довольно быстро это обнаружил и исправился.
Итог
В качестве итога еще раз перечислю все бонусы, которые мы получаем при разработке букмарклетов таким способом:
- Правильно форматированный код.
- Возможность спокойно писать код в вашей любимой IDE.
- Простота тестирования - вы можете в считанные секунды сгенерировать тестовый букмарклет и запустить его, не тратя время на его переформатирование оформление.
- Возможность динамически генерировать букмакрлеты с разным поведением, за счет использования параметров.
Честно говоря, долго не мог выбрать, какую песню вставить, эту или The Illusionist. Рекомендую обе, они обалденные :-)