Блоґ одного кібера

Історія хвороби контуженого інформаційним вибухом

Як написати свій букмарклет?

with 22 comments

Букмарклет (bookmark) – це слово створене поєднанням слів bookmark (закладка) і applet (application (застосунок) + зменшувальний суфікс -let). Таким чином правильним перекладом bookmarklet було б “закластуночок” (чи “застокладочка”), але ви цього краще не кажіть Юрку Зеленому. Але я відхиляюсь. Отож, букмарклет, це маленька програма що міститься в закладці.

Як її туди помістили? Ну, виявляється браузери крім протоколів http, ftp, ітп, розуміють такий протокол як javascript. І коли отримують посилання з цим протоколом, при кліку по ньому не змінюють сторінку, а виконують його href як код JavaScript. Щоб побачити приклад простого букмарклету, створіть документ bookmarklet.htm, і помістіть в нього такий код:

<html>
<head><meta charset="utf-8" /></head>
<body>
<a href="javascript:
    alert('Привіт!')
">Мій букмарклет</a>
</body>
</html>

Якщо відкрити його в браузері, ви побачите чисту сторінку з єдиним посиланням Мій букмарклет, яке при кліку буде показувати повідомлення “Привіт!”. Якщо перетягнути це посилання на панель закладок в браузері, то тепер ви зможете в будь-який момент отримати привітання на будь-якій сторінці яку дивитесь, досить лише натиснути букмарклет.

Але це не дуже корисний букмарклет. Щоб він робив щось корисніше, досить замінити код в рядку 5, на якийсь корисніший.

Наприклад є такий сайт – lib.rus.ec. Вони хоч мають домен еквадору – але москалі, і коли відкрити їх сайт, то вискакує повідомлення, яке блокує доступ до сторінки, і просить грошей за чужі книжки. Я переконаний що в цьому випадку дозволяється використати принцип “грабуй награбоване”, і додати в букмарклет такий код:

 document.getElementsByClassName('lsp-overlay')[0].remove()

І тоді при кліку по букмарклету це вікно пропадатиме. Клас, правда? (Не забудьте забрати виклик alert() який ми написали там раніше)

Але давайте зробимо ще щось складніше і корисніше. Давайте зробимо букмарклет, який оформлює посилання на веб-сторінку в форматі вікіпедії cite web, і дає її нам в якомусь вікні. Це такий шаблон, який гарно оформлює посилання, але заповнювати його руками – ще та морока.

Для букмарклетів є кілька правил. Їх код все таки міститься всередині атрибуту елемента HTML, і повинен відповідати стандартам цієї мови. Наприклад всі подвійні лапки """ (ну ви зрозуміли), повинні бути заміненими HTML-кодом ". Крім того, перехід на новий рядок вважається еквівалентним пробілу, тому однорядкові коментарі можливі лише в кінці скрипта:

alert('Це вискочить');
// alert('Це не вискочить бо закоментовано');
alert('Це теж не вискочить бо коментар продовжується');

Ну і тому що ввесь скрипт здається браузеру написаним на одному рядку – бажано шанувати крапки з комою.

Якщо ми хочемо написати великий букмарклет, який можливо використовуватиме jQuery, та інші бібліотеки, нам захочеться їх якось підвантажувати. Але, віднедавна в адміністраторів серверів з’явилась нова можливість збільшувати безпеку вводячи обмеження на джерела з яких на сайт завантажуються ресурси – Content Security Policy, тому такі букмарклети можуть працювати не всюди. Можливо доведеться все переписати, мініфікувати і запакувати, але на всяк випадок, ось вам код підвантаження скрипта:

(function () {
    var script = document.createElement('script');
    script.src='https://gist.githubusercontent.com/bunyk/6ae97e5c3de490cfb4a1/raw/b7fcfde5c40314262893761418a6a25dd6ed0ce8/cite_web.js';
    document.body.appendChild(script);
}());

Подібним чином вже з того скрипта ми можемо підвантажити jQuery та наприклад CSS.

Я тут наковбасив трохи JavaScript, який можливо не на всіх сайтах працює, і не всі дані статті витягує, але на моєму блозі він дає щось подібне до цього:

cite_web

Щоб поставити собі такий, перенесіть оце посилання в закладки: “{{cite web|…“, а тоді в контекстному меню закладки натисніть “Властивості”, чи “Редагувати”, і замініть текст поля “Location” на

javascript:(function () {
    var script = document.createElement('script');
    script.src='https://gist.githubusercontent.com/bunyk/6ae97e5c3de490cfb4a1/raw/3102c3e285c6e24a9aed98d1bc7f0b7abeda20fc/cite_web.js';
    document.body.appendChild(script);
}());

Ось код:


console.log('Почато завантаження букмарклета');
(function(){
var get_meta_property = function(name) {
var element = document.querySelector('meta[property="' + name + '"]');
return element && element.getAttribute("content") || '';
};
var get_article_time = function() {
var text = get_meta_property('article:modified_time');
if(text) {
return format_date(new Date(text));
} else {
return '';
};
};
var get_author = function() {
return document.querySelector('a[rel=author] [itemprop=name]').innerHTML;
};
/** Now we can create new site handlers that will reuse functionality of the default site handler. */
function SiteHandler(params) {
this.get_title = params.get_title || function () { return document.title; };
this.get_website = params.get_website || function () { return get_meta_property('og:site_name'); };
this.get_publisher = params.get_publisher || function () { return get_meta_property('article:publisher'); };
this.get_date = params.get_date || function () { return get_article_time(); };
this.get_author = params.get_author || function () { return get_author(); };
}
var siteHandlers = {
'na.mil.gov.ua' : new SiteHandler ({
get_website : function () { return 'Народна Армія'; },
get_publisher : function () { return 'Міністерство Оборони України'; }
})
};
var get_template_text = function () {
var domain = window.location.hostname;
var handler = ( siteHandlers[domain] || new SiteHandler({}) );
return '<ref name="">{{cite web\n' +
'|url = ' + window.location.href + '\n' +
'|title = ' + handler.get_title() + '\n' +
'|author = ' + handler.get_author() + '\n' +
'|date = ' + handler.get_date() + '\n' +
'|website = ' + handler.get_website() + '\n' +
'|publisher = ' + handler.get_publisher() + '\n' +
'|accessdate = ' + format_date(new Date()) + '\n' +
'}}</ref>'
.replace('|', '&#124;') // escape template delimiters
.replace('\n&#124;', '\n|') // but undo delimiters at the beginning of line
.replace('&', '&amp;') // escape html
.replace('<', '&lt;');
};
var init = function () {
console.log('Очікування завантаження сторінки');
jQuery(function($){
console.log('Створюємо вікно');
$(css_style).appendTo("head");
var panel = $('<div class="cite_web_panel"></div>');
var header = $('<div class="header">Ctrl+C щоб скопіювати</div>');
var close = $('<a href="#">Закрити</span>').click(function() {
panel.remove();
});
var content = $('<textarea>' + get_template_text() + '</textarea>');
header.append(close);
panel.append(header);
panel.append(content);
$('body').append(panel);
SelectText(content[0]);
wikiBookmarkletDone(); // remove style with wait cursor
console.log('Готово!')
});
};
var SelectText = function (element) {
// http://stackoverflow.com/a/987376/816449
var doc = document, range, selection;
if (doc.body.createTextRange) {
range = document.body.createTextRange();
range.moveToElementText(element);
range.select();
} else if (window.getSelection) {
selection = window.getSelection();
range = document.createRange();
range.selectNodeContents(element);
selection.removeAllRanges();
selection.addRange(range);
}
};
var monthNames = [
"січня", "лютого",
"березня", "квітня", "травня",
"червня", "липня", "серпня",
"вересня", "жовтня", "листопада",
"грудня"
];
var format_date = function(date) {
var day = date.getDate();
var monthIndex = date.getMonth();
var year = date.getFullYear();
return day + ' ' + monthNames[monthIndex] + ' ' + year;
};
console.log('Очікуємо завантаження jQuery');
if (window.jQuery === undefined) {
var script = document.createElement("script");
script.src = "https://code.jquery.com/jquery-1.12.0.min.js&quot;;
script.onload = init;
document.body.appendChild(script);
} else {
init();
};
var css_style = '' +
'<style type="text/css">' +
'.cite_web_panel {' +
' position: fixed;' +
' left: 20%;' +
' top: 10%;' +
' width: 60%;' +
' height: 80%;' +
' overflow: auto;' +
' border: 1px solid black;' +
' background: white;' +
' z-index: 9999;' +
'}' +
'.cite_web_panel .header {' +
' width: 100%;' +
' background: lightblue;' +
' border: 1px solid black;' +
' box-sizing: border-box;' +
' padding: 2px;' +
' font-family: sans-serif;' +
' font-weight: bold;' +
'}' +
'.cite_web_panel .header a {' +
' float: right;' +
'}' +
'.cite_web_panel textarea {' +
' width: 100%;' +
' margin: 0px;' +
' padding: 15px;' +
' box-sizing: border-box;' +
' font-family: monospace;' +
'}' +
'</style>';
})();

view raw

cite_web.js

hosted with ❤ by GitHub

Written by bunyk

10 Березня, 2016 at 14:31

Відповідей: 22

Subscribe to comments with RSS.

  1. Букмарклети дійсно корисна штука, користуюсь деякими для seo. Ось їх приклади – http://www.searchengines.ru/articles/69_poleznykh_bu.html , http://www.lucky-seo.com/services/bookmarklets

    Ivan

    11 Березня, 2016 at 10:58

  2. та, букмарклети цікава штука, не знав, що є букмарклет який пише посилання в вікі. В мене особисто недавно була якась біда з посиланнями. Пробував перекладати одну статтю, а посилання скопіювати, але таке враження, що при копіюванні ті посилання якось пошкодились, а я не до кінця знаю, як їх виправити – і в тій статті пише “Помилка цитування: Некоректний теґ ; назва «PRL-20160211» визначена кілька разів з різним вмістом Помилка цитування: Некоректний теґ ; назва «PRL-20160211» визначена кілька разів з різним вмістом”

    patlatus

    12 Березня, 2016 at 15:48

  3. […] ще щойно подумав що мій букмарклет cite web, при застосуванні на сайті Google Books повинен був би […]

  4. Можливо той букмарклет для cite web міг би запитувати у користувача ім’я автора і все інше в одній формі з деякими полями вже заповненими. Тільки це мало б бути не модальне вікно.

    harmyder

    13 Березня, 2016 at 18:17

    • Там стоїть content editable, тобто можна дописати прямо в тексті. А не модальне це яке?

      Думаю я з цим проектом продовжу, бо бачу що не одному мені воно може знадобитись. 🙂

      bunyk

      13 Березня, 2016 at 19:20

      • може у вебі такого немає, та з моїх давніх запасів знань модальне – це таке, що головне вікно стає не доступним поки ти це не закриєш.

        harmyder

        17 Березня, 2016 at 19:22

  5. Твоя маленька цукерка для cite-web дуже корисна, коли треба накидати нового на ВП:ППВ 🙂 Тільки дату створення воно майже ніколи не визначає. Чого так?

    Vira Motorko

    27 Вересня, 2016 at 11:21

    • Бо воно працює лише на сайтах о підтримують Open Graph Protocol (http://ogp.me/), а саме містять тег meta property=”article:modified_time”. А на яких найчастіше треба дату визначати? Може додати код який її знаходить?

      bunyk

      27 Вересня, 2016 at 17:02

      • Всілякі новинні сайти. (Якщо твоя ласка, то погортай ВП:ППВ).

        Vira Motorko

        29 Вересня, 2016 at 14:43


Залишити коментар

Цей сайт використовує Akismet для зменшення спаму. Дізнайтеся, як обробляються ваші дані коментарів.