Created
December 6, 2009 03:32
-
-
Save yosmoc/250028 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // ==UserScript== | |
| // @name AutoFocus | |
| // @namespace http://d.hatena.ne.jp/samurai20000/ | |
| // @description auto focus on where you wish | |
| // @include http://* | |
| // @include https://* | |
| // @version 0.0.7 | |
| // ==/UserScript== | |
| // | |
| // this script based on autopagerize.user.js | |
| // thanks to id:swdyh | |
| // | |
| const CACHE_EXPIRE = 24 * 60 * 60 * 1000; | |
| const SITEINFO_URLS = ['http://wedata.net/databases/AutoFocus/items.json']; | |
| const XHR_TIMEOUT = 30 * 1000; | |
| const SITEINFO = [ | |
| /* sample | |
| { | |
| url: 'http://reader\\.livedoor\\.com/', | |
| focus: '//div[@id="login"]/h3/a' | |
| } | |
| */ | |
| /* templete | |
| { | |
| url: '', | |
| focus: '' | |
| } | |
| */ | |
| ]; | |
| var AutoFocus = function(info) { | |
| var focus_element = getFocusElementByXpath(info.focus); | |
| focus_element.focus(); | |
| }; | |
| var launchAutoFocus = function(list) { | |
| log(GM_getValue('lasturl')); | |
| add_focus_style(); | |
| if (!isreloaded(GM_getValue('lasturl'))) { | |
| for (var i = 0; i < list.length; i++) { | |
| try { | |
| if (!af && location.href.match(list[i].url) && getFocusElementByXpath(list[i].focus)) { | |
| af = new AutoFocus(list[i]); | |
| } | |
| } | |
| catch(e) { | |
| log(e); | |
| continue; | |
| } | |
| } | |
| } | |
| setlasturl(location.href); | |
| }; | |
| var getsiteinfo = function(urls) { | |
| var xhrStates = {}; | |
| cacheInfo = getCache(); | |
| urls.forEach(function(i) { | |
| if(!cacheInfo[i] || cacheInfo[i].expire < new Date()) { | |
| var opt = { | |
| method : 'get', | |
| url : i, | |
| onload : function(res) { | |
| xhrStates[i] = 'loaded'; | |
| getCacheCallback(res, i); | |
| }, | |
| onerror : function(res) { | |
| xhrStates[i] = 'error'; | |
| getCacheErrorCallback(i); | |
| } | |
| }; | |
| xhrStates[i] = 'start'; | |
| GM_xmlhttpRequest(opt); | |
| setTimeout(function() { if (xhrStates[i] == 'start') { getCacheErrorCallback(i); }} , XHR_TIMEOUT); | |
| } | |
| else { | |
| launchAutoFocus(cacheInfo[i].info); | |
| } | |
| }); | |
| }; | |
| var add_focus_style = function() { | |
| // based on http://userstyles.org/styles/305 | |
| var css = 'a:hover:active {color: #10bae0;}' + | |
| 'a:not(:hover):active { color: #0000ff;}' + | |
| '*:focus {-moz-outline: 4px solid -moz-rgba(16,186,224,0.3) !important;-moz-outline-offset: 1px !important;-moz-outline-radius: 3px !important;}' + | |
| 'button:focus,input[type="reset"]:focus,input[type="button"]:focus,input[type="submit"]:focus,input[type="file"] > input[type="button"]:focus {-moz-outline-radius: 5px !important;}' + | |
| 'button:focus::-moz-focus-inner {border-color: transparent !important;}' + | |
| 'button::-moz-focus-inner,input[type="reset"]::-moz-focus-inner,input[type="button"]::-moz-focus-inner,input[type="submit"]::-moz-focus-inner,input[type="file"] > input[type="button"]::-moz-focus-inner {border: 1px dotted transparent !important;}' + | |
| 'textarea:focus, button:focus, select:focus, input:focus {-moz-outline-offset: -1px !important;}' + | |
| 'input[type="radio"]:focus {-moz-outline-radius: 12px;-moz-outline-offset: 0px !important;}' + | |
| 'a:focus {-moz-outline-offset: 0px !important;}'; | |
| addstyle(css); | |
| }; | |
| // utility SITE_INFO | |
| function parseInfo(str) { | |
| var lines = str.split(/\r?\n|\r/); | |
| var strip = str.replace(/^\s+|\s+$/g, ''); | |
| var re = /^([^:]+?):(.*)$/; | |
| var info = {}; | |
| lines.forEach(function(line) { | |
| if (re.test(line)) { | |
| info[RegExp.$1] = RegExp.$2.replace(/^\s+/, ''); | |
| } | |
| }); | |
| var isValid = function(info) { | |
| return !['url', 'focus'].some(function(property) { | |
| return !info.hasOwnProperty(property); | |
| }); | |
| }; | |
| return isValid(info) ? info : null; | |
| } | |
| function clearCache() { | |
| GM_setValue('cacheInfo', ''); | |
| } | |
| function getCache() { | |
| return eval(GM_getValue('cacheInfo')) || {}; | |
| } | |
| function getCacheCallback(res, url) { | |
| if (res.status != 200) { | |
| return getCacheErrorCallback(url); | |
| } | |
| var info | |
| try { | |
| info = eval(res.responseText).map(function(i) { return i.data }) | |
| } catch(e) { | |
| var info = []; | |
| var matched = false; | |
| var hdoc = createHTMLDocumentByString(res.responseText); | |
| var textareas = getElementsByXPath('//*[@class="autofocus_data"]', hdoc) || []; | |
| textareas.forEach(function(textareass) { | |
| var d = parseInfo(textareas.innerHTML); | |
| if (!d) return; | |
| info.push(d); | |
| if (!matched && location.href.match(d.url)) { | |
| matched = d; | |
| } | |
| }); | |
| } | |
| if (info.length > 0) { | |
| cacheInfo[url] = { | |
| urls : url, | |
| expire : new Date(new Date().getTime() + CACHE_EXPIRE), | |
| info : info | |
| }; | |
| GM_setValue('cacheInfo', cacheInfo.toSource()); | |
| log('cache!'); | |
| if (!af && !!matched) { | |
| af = new AutoFocus(matched); | |
| } | |
| } | |
| } | |
| function getCacheErrorCallback(url) { | |
| if (cacheInfo[url]) { | |
| cacheInfo[url].expire = new Date(new Date().getTime() + CACHE_EXPIRE); | |
| GM_setValue('cacheInfo', cacheInfo.toSource()); | |
| launchAutoFocus(cacheInfo[url].info); | |
| } | |
| } | |
| function createHTMLDocumentByString(str) { | |
| var html = str.replace(/<!DOCTYPE[ \t\r\n][^>]*>|<html(?:(?=<)|[ \t\r\n]*>|[ \t\r\n][^<>]*(?:>|(?=<)))|<\/html(?:[ \t\r\n>].*)?$/ig, ''); | |
| var htmlDoc = document.implementation.createDocument(null, 'html', null); | |
| var fragment = createDocumentFragmentByString(html); | |
| try { | |
| fragment = htmlDoc.adoptNode(fragment); | |
| } catch(e) { | |
| fragment = htmlDoc.importNode(fragment, true); | |
| }; | |
| htmlDoc.documentElement.appendChild(fragment); | |
| return htmlDoc; | |
| } | |
| function createDocumentFragmentByString(str) { | |
| var range = document.createRange(); | |
| range.setStartAfter(document.body); | |
| return range.createContextualFragment(str); | |
| } | |
| function getFocusElementByXpath(xpath) { | |
| var result = document.evaluate(xpath, document, null, | |
| XPathResult.FIRST_ORDERED_NODE_TYPE, null); | |
| return result.singleNodeValue ? result.singleNodeValue: null; | |
| } | |
| function getElementsByXPath(xpath, node) { | |
| var node = node || document; | |
| var nodesSnapshot = document.evaluate(xpath, node, null, | |
| XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); | |
| var data = []; | |
| for (var i = 0; i < nodesSnapshot.snapshotLength; i++) { | |
| data.push(nodesSnapshot.snapshotItem(i)); | |
| } | |
| return (data.length >= 1) ? data : null; | |
| } | |
| //this code based ldrize.user.js | |
| function addstyle(css) { | |
| var link = document.createElement('link'); | |
| link.rel = 'stylesheet'; | |
| link.href = 'data:text/css,' + escape(css); | |
| document.documentElement.childNodes[0].appendChild(link); | |
| } | |
| function isreloaded (previous_url) { | |
| var reloaded = false; | |
| if (window.location.href == previous_url) { | |
| reloaded = true; | |
| } | |
| return reloaded; | |
| } | |
| function setlasturl(url) { | |
| GM_setValue('lasturl', url); | |
| } | |
| function log(message) { | |
| GM_log(message); | |
| } | |
| //main | |
| GM_registerMenuCommand('AutoFocus - clear cache', clearCache) | |
| var af = null; | |
| launchAutoFocus(SITEINFO); | |
| getsiteinfo(SITEINFO_URLS); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment