Для хранения используется localStorage, а если он недоступен, то кукисы. Реализация вполне стандартна, только куки перебираются с конца, что для подобного применения быстрее и при установке проверяется их максимальная длина. Функции аналогичны GM_getValue и GM_setValue.
var getValue = function(name){ if(window.localStorage){ return window.localStorage.getItem(name) || ''; } else{ var eq = name+'=', ca = document.cookie.split(';'); for(var i = ca.length; i--;){ var c = ca[i]; while(c.charAt(0) == ' ')c = c.slice(1); if(c.indexOf(eq) == 0)return unescape(c.slice(eq.length)); }; return ''; } };
var setValue = function(name, value, del){ if(window.localStorage){ if(del){window.localStorage.removeItem(name)}else{window.localStorage.setItem(name, value)}; } else{ if(document.cookie.split(';').length < 30 && document.cookie.length-escape(getValue(name)).length+escape(value).length < 4000){ var date = new Date(); date.setTime(date.getTime()+((del ? -1 : 10*365)*24*60*60*1000)); document.cookie = name+'='+escape(value)+'; expires='+date.toGMTString()+'; path=/'; } else{ alert('Cookies is full!'); } } };
Работа со стилями
Первая функция создаёт элемент style из переданной строки, аналогично GM_addStyle. Единственная тонкость в ней, это проверка на HTMLHtmlElement, т.к. Opera работает и на wap-страницах.
Вторая функция возвращает массив селекторов полученных из переданной строки. Простой split(',') не подходит, т.к. запятая может встречаться, например в ссылках.
var addStyle = function(css){ if(document.documentElement instanceof HTMLHtmlElement){ var s = document.createElement('style'); s.setAttribute('type', 'text/css'); s.setAttribute('style', 'display: none !important;'); s.appendChild(document.createTextNode(css)); return (document.getElementsByTagName('head')[0] || document.documentElement).appendChild(s); } };
var splitCss = function(css){ var rez = []; css.replace(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/g, function(s, m){rez.push(m.replace(/^\s+|\s+$/g, ''))}); return rez; };
Включение/выключение userjs кнопкой или букмарклетом
Обычно, для возможности взаимодействия с userjs им создаётся глобальная переменная/объект, которая при необходимости вызывается с помощью кнопки. Недостатком такого способа, кроме некоторого засорения глобальной области видимости, является невозможность отключения userjs внутри ифреймов внедрённых в страницу с других доменов. Использование сообщений, не имеющих таких ограничений, решает обе эти проблемы.
// userjs var prefix = ujs_something; var toggle = function(block){ var postMsg = function(msg){for(var i = 0, f = window.frames, l = f.length; i < l; i++)f[i].postMessage(msg, '*')}; if(arguments.length ? !block : getValue(prefix) != 'disabled'){ setValue(prefix, 'disabled'); postMsg(prefix + '_disable'); } else{ setValue(prefix, '', true); postMsg(prefix + '_enable'); } }; window.addEventListener('message', function(e){ if(e.data == prefix + '_disable')toggle(false); if(e.data == prefix + '_enable')toggle(true); }, false);
Контекстное меню
Данная функция позволяет создавать контекстное меню в Opera 8.5-10.5. Для предотвращения показа собственного меню браузера, под курсором создаётся небольшая невидимая кнопка.
Требуется включение настройки "Allow script to recieve right clicks" в Tools→Preferences→Advanced→Content→Javascript options.
// Вызываем в нужном месте var lng = getLng(); alert(lng.msg);
Убираем ошибку при случайном запуске userjs в Windows
Данный код выведет осмысленное сообщение при попытке запуска userjs в Windows.
(function(){ if(typeof WScript == 'object' && WScript.Arguments){WScript.Echo('Please, copy this file to userjs folder!'); return}; ... })()
Передаём длинную строку внешней программе
Предварительно вам следует задать реакцию браузера на нужный MIME тип. Ctrl+F12→Загрузки→Добавить, указываете тип и ставите радиокнопку "Открыть в другой программе". Теперь при вызове функции saveFile, указанная программа получит в командной строке путь к текстовому файлу содержащему уже раскодированную строку.
Кодирование с помощью encodeBase64, вообще говоря не является обязательным, но оно позволяет избежать нежелательного срабатывания встроенного блокера оперы, обрабатывающего в том числе и data: URI.
var encodeBase64 = function(string){var out='',charCode=0,i=0,endBytes='',length=string.length;var puffer=[];var base64EncodeChars="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";while(charCode=string.charCodeAt(i++)){if(charCode<0x80){puffer[puffer.length]=charCode}else if(charCode<0x800){puffer[puffer.length]=0xc0|(charCode>>6);puffer[puffer.length]=0x80|(charCode&0x3f)}else if(charCode<0x10000){puffer[puffer.length]=0xe0|(charCode>>12);puffer[puffer.length]=0x80|((charCode>>6)&0x3f);puffer[puffer.length]=0x80|(charCode&0x3f)}else{puffer[puffer.length]=0xf0|(charCode>>18);puffer[puffer.length]=0x80|((charCode>>12)&0x3f);puffer[puffer.length]=0x80|((charCode>>6)&0x3f);puffer[puffer.length]=0x80|(charCode&0x3f)}if(i==length){while(puffer.length%3){puffer[puffer.length]=0;endBytes+='='}}if(puffer.length>2){out+=base64EncodeChars.charAt(puffer[0]>>2);out+=base64EncodeChars.charAt(((puffer.shift()&3)<<4)|(puffer[0]>>4));out+=base64EncodeChars.charAt(((puffer.shift()&0xf)<<2)|(puffer[0]>>6));out+=base64EncodeChars.charAt(puffer.shift()&0x3f)}}return(out+endBytes)};
var saveFile = function(txt){ if(txt.length>131071){alert('Error! String too long!');return}; var src='data:text/something;charset=UTF-8;base64,'+encodeBase64(txt); if(top==self){ var f=document.createElement('iframe'); f.width=0; f.height=0; f.frameBorder='no'; f.scrolling='no'; document.documentElement.appendChild(f); f.src=src; setTimeout(function(){f.parentNode.removeChild(f)},1) }else{ location.href=src } };
Работа с JSON без использования eval
JSON достаточно удобен в случае использования внешней программы, т.к. его парсеры существуют для большинства языков (кстати этот код можно использовать и в WSH).
Следует заметить, что Opera 10.5 уже имеет встроенную поддержку JSON-а.
// Пример использования // Сначала создадим объект с координатами if(typeof navigator.lastClick != 'object')navigator.lastClick = {}; document.addEventListener('mouseup', function(e){ if(e && e.button == 0){ navigator.lastClick.left = e.clientX; navigator.lastClick.top = e.clientY; } }, false);
// И после этого окошко createWindow('Content', 'Status', 'Title', '_myId', navigator.lastClick);
// Другой пример. Открываем в этом окне ифрейм с результатами проверки текущей страницы DrWeb-ом. javascript:void(createWindow('<iframe width=640 height=400 frameborder=0 src=http://online.drweb.com/result?url='+escape(location.href)+'>','','Dr-Web','',navigator.lastClick,{width: '644px', height: '404px'}))
Определение основных версий Opera
Объект opera может быть убран на некоторых сайтах из соображений совместимости, поэтому добавлена проверка на существование характерных функций.
var ver = (window.opera && window.opera.version) ? window.opera.version() : (window.postMessage ? 9.5 : (window.getSelection ? 9 : 8));
Получение выделенного текста включая textarea
В Opera 10.5 больше не поддерживается объект document.selection позволявший легко получить выделенный текст на странице и в textarea. Эта функция является некоторой альтернативой.
var getText=function(){var d=document,s=d.getSelection(),t=d.getElementsByTagName('textarea');if(!s)for(var i=0,e;e=t[i];i++){if(s=e.value.substring(e.selectionStart,e.selectionEnd))break}return s};
Вы должны войти, чтобы отправлять комментарии на этот сайт - пожалуйста, либо войдите, либо - если вы еще не зарегистрированы - щелкните здесь , чтобы зарегистрироваться
Этот сайт работает на e107, которая распространяется на условиях лицензии GNU GPL.