Букмарклеты

    Всем привет, сегодня речь пойдет про использование букмарклета, или закладки для браузера.

    Кто не знает, это такая штука, которую можно добавить в закладки (да, я сегодня дебютирую в роли Капитана Очевидность :) и, при нажатии на нее, произвести какой-нибудь эффект.

    Примером может служить герой сегодняшней заметки, который расположен по адресу http://ulizko. com/demo/allthat/. Инструкция по применению:
    1. Перетащите ссылку «link» на панель закладок или щелкните по ней правой кнопкой мыши и выберите пункт меню «добавить в избранное».
    2. Зайдите на какой-нибудь сайт, вроде http://twitter. com, и нажмите на эту закладку (ну или на избранное).


    Появится окошко, в которое можно ввести данные. Вообще, предполагается, что это будет интерфейс добавления желаний в вишлисты (предварительно созданные на каком-то сайте), настроить триггеры оповещений, и прочее. Есть даже какая-то валидация начального уровня. И налажен обмен данными с сервером — то есть, на любом домене к вам приходит список ваших вишлистов, а ваше новое желание с любого домена долетит на крыльях любви к вишлисту и уютно устроится в его объятьях1.

    Но. Мы сегодня не об этом, а о том, как делать такие штуки в принципе.




    Прежде чем перейти непосредственно к разбору кода, хотелось бы ответить на вопрос (который мне никто не задавал :), а именно, "Какие возможности дает букмарклет?". Правильный ответ — любые. Так как мы получаем возможность подгрузить любой скрипт, мы можем сделать с клиентской страничкой все, что угодно. Например — сделать «выносной» виджет, в котором на любой страничке можно будет добавить запись в блокнот или таскменджер. Или вообще сделать весь таскменеджер выносным. Что тоже важно, они будут работать практически везде — это не плагины к firefox’у и не виджеты к opera. Букмарклетам не важно (ну, почти :), какая у вас ОС или браузер. В общем, есть простор для фантазии.

    Итак, как же делать эти самые букмарклеты?
    Очень просто: надо создать на страничке элемент anchor с атрибутом href, содержащим javascript-код. Если перевести на русский, то надо сделать вот такую ссылку, адрес которой, по большому счету, и будет букмарклетом:

    <a href="javascript:alert('I am bookmarklet'); void 0;">Bookmarklet</a>

    * This source code was highlighted with Source Code Highlighter.


    Для того, чтобы javascript код в адресе ссылки заработал, надо добавит перед ним слово javascript:. Если мне не изменяет мой склероз, это называется «указание псевдопротокола javascript». Еще одна важная деталь — если ваш код вернет какое-то значение, то браузер воспримет его в качестве адреса, по которому нужно перейти, и уйдет с текущей страницы. Чтобы избежать этого, не возвращайте значения, то есть допишите в конец скрипта void 0;, либо оберните весь код в анонимную функцию, невозвращающую значения — (function(){... ваш код мог бы быть здесь...})().

    В любом случае, все эти вопросы подробно рассмотрены у Ильи Кантора в его заметке Букмарклеты и правила их написания, к которой я вас и отсылаю за подробностями.

    Единственную вещь, которую нам еще нужно знать — это то, что все браузеры ограничивают максимальную длину кода букмарклета. И, подобно тому, как скорость каравана равна скорости самого медленного верблюда, так и максимальный размер кроссбраузерного букмарклета равен ограничению, наложенному IE 6 SP2, то есть, 488 символам.

    Таким образом, вряд ли мы сможем закодить какую-то комплексную логику в неполных пятистах символах, так что чаще всего букмарклеты просто создают новый тэг script, в который уже сгружают код приложения.

    Так поступил и я. Вот код моего букмарклета в человекоадаптированном виде:

    (function () {
      // создаем новую внутреннюю переменную a (лучше в данном случае использовать короткие идентификаторы)
      // и сразу же добавляем свой объект в глобальный объект window, и записываем в него данные, которые уникальны
      // для каждого пользователя (ведь они сгенерированы сервером для пользователя перед тем, как он добавил этот букмарклет к себе)
      var a = window.allThat = {
        userId : '123345456',
        server : 'http://mysite.com/',
        script : document.createElement('script'), // создадим и запомним тэг скрипт,
        // который сгрузит нам код нашего приложения - мы его потом удалим, если пользователь нажмет кнопку "закрыть"
        css : document.createElement('link') // аналогично
      },
      /* динамически создаем и добавляем в DOM элементы: */
      h = document.getElementsByTagName('head')[0];
      a.css.rel = 'stylesheet';
      a.css.href = a.server + 'css/bookmarklet.2.css';
      h.appendChild(a.css);
      a.script.src = a.server + 'js/bookmarklet.7.js';
      h.appendChild(a.script);
      h=null;
    })();


    * This source code was highlighted with Source Code Highlighter.


    Потом подгружается непосредственно код самого окошка. Думаю, он может представлять некий интерес сам по себе, так что и его я сюда запощу (все комментарии идут на английском, так как заказчик американец):

    Если интересно, вот Исходный код букмарклета.

    Примечания:
    • Вообще скрипт выполнен мной на заказ в рамках моей фрилансерской деятельности, так что не удивляйтесь идее, логотипам и дизайну.
    Ads
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More

    Comments 35

      +3
      Хорошее изложение и примеры, всё стало понятно. Благодарю!
      Единственный минус, при первом взгляде километры текста пугают =)
        +1
        Километры кода убрал, оставил только ссылку на исходник.
        +1
        интересно
          0
          Спасибо.
          +1
          Интересный механизм, я не знал, что закладка может получить доступ к текущей странице, открытой в браузере.
          В принципе подгрузив свой js можно делать кучу прикольных вещей.
          Мне например первое что пришло в голову — это сохранение выделенных кусков текста и картинок у себя на сервера, т.е. погрузил скрипт, выделил кусок страницы и нажал отправить себе в архим, а оно осхранилось уже на сервере, где ты далее можешь это посмотреть.

          В общем основной плюс, за счет того, что мы получаем доступ к коду текущей страници и можем с ними совершать какие-то действия. В остальном, наверное, погрузка сервиса на эту же страницу не нужна.
            0
            Это да, ради этого все обычно и затевается.

            Но основной плюс как технологии — это не то, что мы можем многое сделать, а простота использования для конечного пользователя — добавить ссылку в закладки очень просто, еще проще, чем установить дополнение.
              +1
              Кстати, а механизм будет работать, если ссылку установить как «Домашнюю»? — это было бы удобно, т.к. например я ей вобще не пользуюсь, а вот в таком виде ей можно найти применение :).
              Вобще нужно что бы эти ссылки были под рукой, а не спрятаны в менюшках.
                0
                Я, если честно, не знаю, что такое «Домашняя» ссылка, поэтому и на вопрос не знаю, как ответить…
                  +1
                  В браузерах ссылочка «Домой» — обычно там нарисован домик :)
                  Щас посмотрел, в Файерфоксе её по-умолчанию спилили, а я как-то и не заметил :)
                    0
                    Туплю :)

                    Да, работает, по крайней мере в ff. В остальных браузерах — не знаю.
                      +1
                      В других тоже работает, я проверил :)
                      Было бы вобще супер, если бы можно было иконку для кнопки на тулбаре задавать.

                      Эх, очень хочется поставить Вам плюсик, но к сожалению не имею возможности :(
                        +1
                        Не, это уже моветон. JS не должен иметь возможности управлять размером, положением, внешним видом браузера — а то подумайте, какие возможности для рекламщиков появятся. По сравнению с ними popup window покажутся милой невинной забавой.
          • UFO just landed and posted this here
              +2
              Пожалуйста :)

              А польза, действительно, может быть огромная, в этом я с вами согласен.
              +1
              Сори за офтоп. Понудю.

              "(все комментарии идут на английском, так как заказчик американец)" — комментарии всегда надо писать на английском!

              За статью спасибо
                +1
                Спасибо :)

                Уточнение очень хорошее, у нас в стандарте оформления кода это прописано. Я обычно так и делаю, но в статьях заменяю комментарии на русские для пущей понятности, поэтому и извиняюсь за комментарии на английском.
                  +1
                  Ну тогда вообще все здорово ;)
                +1
                Спасибо за статью. Мне вообще нравится сама идея букмарклетов.
                  0
                  Пожалуйста :)
                  +1
                  Спасибо за статью! Как раз недавно об этом думал! :)
                  Главный вопрос:

                  > «Какие возможности дает букмарклет?». Правильный ответ — любые.
                  Я хочу в своем букмарклете делать скриншоты текущей страницы. Возможно ли это?
                  Использование предполагается в Фаерфоксе, поэтому задачу можно упростить — использовать какие-нибудь плагины ФФ. Может ли яваскрипт обращаться к таким плагинам?
                    0
                    Сам по себе javascript не может этого сделать, но, подозреваю, это может сделать flash а javascript может с ним работать и подгружать его.

                    Опять же, вы можете либо копировать содержимое страницы вместе со всеми картинками и стилевыми файлами, чтобы построить где-нибудь на сервере копию страницы и снять скриншот.

                    Насчет дополнений — если плагин предусматривает такого рода функциональность, то обратиться к нему из js можно.
                      0
                      Скриншотить надо с локального компа — т.к. на сервере все может быть по-другому.

                      Нашел плагинчик, который делает все, что нужно — www.screengrab.org/
                      Но вот как его вызвать? И как решается вопрос с безопасностью? Чтобы стороние скрипты на странице не могли его вызывать?
                      Куда копать?
                        +1
                        Копать в сторону общения с автором плагина, он расскажет, планировал ли он такого рода взаимодействие. Если он ничего путнего не скажет, то тогда нужно взять исходный код и попробовать вшить эту функциональность в плагин, потом опубликовать его и уже в самом конце сделать букмарклет.

                        Что касается проблем безопастности — ну, можно закрыть доступ к плагину хоть по тому же паролю. Букмарклет же динамически генерится, верно? Туда можно и логин и пароль добавить, и будет он уникальным для пользователя. А плагин перед тем, как делать то, что скрипт просит, запрашивает сервер, адекватный ли ему предоставили логин/пароль.
                    0
                    Я все же советую поступать другим путем:
                    Не запихивать весь код букмарклета в ссылку, а добавить в букмарклет лишь код инжектора, который включит в страницу яваскрипт с вашего сервера. Это позволит отследить пользовательскую активность и избавит пользователей от необходимости устанавливать новую версию букмарклета при каждом багфиксе или добавлении новой фичи.

                    javascript:(function(){
                     var s=document.createElement('script');
                     s.setAttribute('src', 'http://scripts.uadev.net/script.js');
                     document.getElementsByTagName('body')[0].appendChild(s);void(s);
                    })()

                    * This source code was highlighted with Source Code Highlighter.
                      +1
                      Простите, но вы, мне кажется, невнимательно читали. Именно об этом и пишу в посте. Сравните еще раз ваш код и мой.
                        0
                        А void(s); зачем?
                          0
                          Аттавизм из прошлого кода, случайно затесался. Да и не важно уже. Все равно это всего-лишь упрощенная версия приведенного выше кода.
                            0
                            А я про тайный смысл думал.
                        +1
                        А можно узнать букмарклет для какого вишлистового сервиса делается?
                          0
                          Чуть-чуть позже, после того, как выполним полностью готовый проект, напишу.
                          Возможно, даже напишу какой-нибудь топик — наверняка там будут какие-нибудь интересные проблемы, решение которых пригодится хабралюдям.
                          +1
                          Хотел показать букмарклет для создания многострочного статуса вконтакте, который сделал после вашего поста, но кто-то сделал мне карму -1, теперь не могу создать топик (
                          0
                          если случайно нажать «пару раз» на вызове букмарклета — то будет несколько окон поверх друг друга — и при этом они не закрываются…
                            0
                            Кстати да, этот случай совершенно не продуман. Спасибо, поправлю.

                          Only users with full accounts can post comments. Log in, please.