GreaseMonkey

индекс
148,13

Используем jQuery в скриптах GreaseMonkey

Я хочу рассказать об удобных и неоправданно редко использующихся новшествах GreaseMonkey версии 0.8, которая доступна уже более года. Они помогут сделать пользовательские скрипты более модульными, а главное — дадут возможность без ухищрений использовать jQuery, что позволит нам «писать меньше, а делать больше». Речь идет о новых мета-параметрах пользовательских скриптов: @resource и @require.

Рассмотрим небольшой пример: habratest.user.js. Скрипт добавляет в меню Хабрахабра логотип GreaseMonkey, при клике по которому отобразится текст «Hello, world!», взятый из внешнего файла.
// ==Userscript==
// @name   habratest
// @namespace habratest
// @include  http://habrahabr.ru/*
// @include  http://*.habrahabr.ru/*
// @resource gm_logo http://veg.slutsk.net/habr/greasemonkey.png
// @resource hello http://veg.slutsk.net/habr/hello.txt
// @require  http://ajax.googleapis.com/ajax/libs/jquery/1.3/jquery.min.js
// ==/Userscript==


$(document).ready(function()
{
    $("ul.panel-nav-top").append('<li style="float: right;" id="habratest"></li>');
    $("#habratest").append('<img src="'+GM_getResourceURL("gm_logo")+'">');
    $("#habratest img").click(function()
    {
        alert(GM_getResourceText("hello"));
    });
});

@resource позволяет привязать к пользовательскому скрипту внешние файлы: картинки, текстовые файлы и т.д. — все что может понадобиться во время выполнения. В примере «gm_logo» — это имя ресурса. Функция GM_getResourceURL предназначена для получения локальной ссылки на файл (например, на картинку), GM_getResourceText — для получения текста из файла (файл может содержать, например, большой кусок HTML). Обе функции принимают в качестве параметра имя ресурса. Преимущество использования ресурсов вместо прямых ссылок на сервер заключается в том, что указанные файлы загружаются один раз во время установки скрипта и в дальнейшем всегда берутся с локальной машины.

Куда более интересен @require, который позволяет подключать внешние библиотеки к скрипту. Можно конечно же городить какой-нибудь код с динамическим созданием тега script, достаточно нетривиальными способами ожидать его загрузки. Но в таком случае файл библиотеки будет запрашиваться с сервера каждый раз при открытии новой страницы в браузере. Этих недостатков лишен @require — файл будет запрошен всего один раз при установке, а главное — он будет будет гарантированно выполнен до того, как начнется выполнение вашего пользовательского скрипта.

В качестве полезного примера предлагаю посмотреть код скрипта yandexru.user.js, который на страницах результатов поиска добавляет в форму запроса опцию «Поиск без исключения», поле «Поиск по сайту», а также отображает повлиял ли установленный регион на результаты поиска.

К сожалению, сегодня подобные вещи можно делать только в Firefox. Есть смысл намекнуть разработчикам аналогов GreaseMonkey для других браузеров, чтобы те задумались о поддержке столь полезных функций. Но если вы пишете скрипт для личного пользования — воспользоваться данными возможностями вполне можно уже сегодня.
+34
2 ноября 2009, 18:51
50
VEG

комментарии (24)

0
VEG #
В какой блог лучше поместить: в GreaseMonkey или в jQuery?
+6
MiXei4 #
По-моему логичнее в GM. Ведь топик о конкретной фиче GM, а jQuery используется как пример.
+3
DevEx #
$(document).ready(function()........
это лишнее, т.к. GreaseMonkey запускает скрипт как только поступит событие DOMContentLoaded

wiki.greasespot.net/DOMContentLoaded
0
arty #
фича хорошая, жаль, что не кроссбраузерная

впрочем, зря вы так категорично «будет запрашиваться с сервера каждый раз». С правильным кешированием они максимум раз в месяц будут качаться. А например у гуглового хостинга популярных библиотек кеширование наверняка правильное. Я именно его собираюсь использовать.
+2
Stalker_RED #
// Add jQuery
var GM_JQ = document.createElement('script');
GM_JQ.src = 'http://jquery.com/src/jquery-latest.js';
GM_JQ.type = 'text/javascript';
document.getElementsByTagName('head')[0].appendChild(GM_JQ);


вот кроссбраузерная
+1
VEG #
Не забывайте, что jquery-latest.js загрузится и выполнится не сразу, поэтому нужно еще отлавливать момент, объект jQuery станет доступным.
+2
Pongo #
Stalker_RED привел не полный вариант кода. Полный вариант, с проверкой, загрузился ли jquery, здесь и здесь.
0
arty #
ой, зачем же таймеры? у script есть вполне рабочий onload
+1
ibnteo #
Есть рабочий код?
0
arty #
конечно, я же не нафантазировал сейчас всё это: )
+1
ibnteo #
Можно ссылку на него, или сам код привести здесь?
GМ скрипты не удобно отлаживать.
0
arty #
очевидно же:
var proto = document.createElement('script');
proto.src = 'http://ajax.googleapis.com/ajax/libs/prototype/1.6.1/prototype.js';
proto.onload = onload();
document.body.appendChild(proto);

0
arty #
а, забыл сам обработчик (хотя можно и без него):
function onload() {
  if (window.Prototype && window.init) window.init()
}
0
blindlybright #
а как насчет того, что в proto.onload сохраняется не функция, а результат работы этой функции?
соответственно onload() выполняется не в момент наступления события onLoad, а в момент присвоения proto.onload, что может случиться раньше, чем загрузится соответствующий js
0
arty #
это опечатка, там не должно быть "()"
0
Stalker_RED #
ок, как-то так: joanpiedra.com/jquery/greasemonkey/
это вообще гуглится с пол-пинка, по словам jquery и greasemonkey
0
Stalker_RED #
или через script onload, да.
0
ELV1S #
Фича плохая. Как мне в Опере или Сафари её реализовать? Никак.

Была бы это функция GM_require, таких проблем бы не было.
+2
VEG #
GreaseMonkey был первым, в остальных браузерах используется его формат заголовка. Не вижу причин почему бы всем не реализовать более полную совместимость с GreaseMonkey последних версий.
А фича эта очень полезная, если скрипт пишется заведомо для Firefox. Например я часто пишу пользовательские скрипты только для себя, и jQuery здесь здорово экономит время.
Кстати, я не совсем хорошо осведомлен насчет отсутствия поддержки этой опции в других браузерах. Может быть где-то еще это уже реализовано.
+1
spqer #
я конечно не в тему, но может кто знает, есть ли GM для беты FF 3.6?
0
alrond #
Библиотека jQuery интегрированные в браузер через расширение jQuery. Стоят последние jQuery и jQuery UI.

Благодаря названию «0 jQuery» грузится первее всех расширений (проверено на убунте и виндовсе), поэтому объект $ доступен всем расширениям(невидим для сайтов), ну и конечно можно как-нибудь прикрутить к greasemonkey.

Я его создал, потому как иногда использую в приватных и коммерческих расширениях, и лучше объеденить под одной крышей, чтобы не захломлять браузер кучей копий
0
trg #
Когда то мне тоже надо было использовать jQuery из GreaseMonkey, причем на сайте, где исполнялся скрипт, jQuery уже был. Нашел такое решение:

//wait for jQuery to be loaded
function waitForJquery(){
	if (typeof unsafeWindow.jQuery == 'undefined') {  
		window.setTimeout(waitForJquery, 100);
	} else {
		$ = unsafeWindow.jQuery;
		//your code here
	}
}
waitForJquery();
0
how #
У GreaseMonkey возникают конфликты с последними версиями jQuery.
Последняя версия, которая нормально работает — 1.3.2
// @require ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js
0
questor #
Мне не удалось заставить нормально работать $.getJSON из-под GreaseMonkey ни на одной версии jQuery начиная от 1.2, где эта функция была введена и до текущей.
Запрос к целевому сайту делает, а потом выдаёт ошибку вида «функция jsonp123456789 не определена».

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