/** * ==VimperatorPlugin== * @name gmperator * @description Vimperator plugin for Greasemonkey * @author teramako teramako@gmail.com * @namespace http://d.hatena.ne.jp/teramako/ * @version 0.3a * ==/VimperatorPlugin== * * --------------------------- * Usage: * --------------------------- * {{{ * * :gmli[st] {filter} -> show user scripts matches {filter} * :gmli[st]! -> show all user scripts * :gmli[st] full -> same as :gmli[st]! * * :gmlo[ad] {name|filename} -> load the user script to the current page * but, don't dispatch load event * so maybe you should edit the scripts before load * :gmlo[ad]! {name|filename} -> force load the user script * * :gmset! -> toggle enable/disable Greasemonkey * :gmset! {filename} -> toogle enable/disable the script * :gmset {filename} {options} * {options}: * -n[ame] {value} -> change name to {value} * -i[nclude] {expr[,expr,...]} -> change includes to expr list ("," demiliter) * -e[xclude] {expr[,expr,...]} -> change excludes to expr list ("," demiliter) * * Caution: * The change is permanent, not only the session. * And cannot get back. * * e.g.) * :gmset! {filename} -n fooScriptName -i http://*,https://* -e http://example.com/* * toggle enable or disable, * name to "fooScriptName", * includes to "http://*" and "https://*", * and excludes to "http://example.com/*" * * }}} * --------------------------- * For plugin developer: * --------------------------- * {{{ * * 1). you can access to the sandbox of Greasemonkey !!! * 2). you can register commands to execute * when the user script is executed on the URI * @see liberator.plugins.gmperator.addAutoCommand * * liberator.plugins.gmperator => ( * allItem : return object of key : {panalID}, * value : {GmContainer} * {panelID} => @see gBrowser.mTags[].linkedPanel * currentPanel * currentContainer : return the current {GmContainer} object * currentSandbox : return the current sandbox object * gmScripts : return array of {userScripts} * {userScripts} => ( * filename : {String} * name : {String} * namespace : {String} * description: {String} * enabled : {Boolean} * includes : {String[]} * encludes : {String[]} * ) * addAutoCommand : function( uri, script, cmd ) * If both of uri and script are matched * * ) * }}} */ (function(){ const Cc = Components.classes; const Ci = Components.interfaces; const gmID = '@greasemonkey.mozdev.org/greasemonkey-service;1'; if (!Cc[gmID]) { log('Greasemonkey is not installed'); return; } if(!liberator.plugins) liberator.plugins = {}; liberator.plugins.gmperator = (function(){ //{{{ // ----------------------- // PUBLIC section // ----------------------- // {{{ var manager = { register: function (uri,sandbox,script){ var panelID = getPanelID(sandbox.window); var gmCon; if (containers[panelID]){ gmCon = containers[panelID]; } else { gmCon = new GmContainer(uri,sandbox); containers[panelID] = gmCon; this.__defineGetter__(panelID,function() gmCon); //log('gmpeartor: Registered: ' + panelID + ' - ' + uri); } gmCon.sandbox = sandbox; gmCon.addScript(script); gmCon.uri = uri; autocommands.trigger('GMInjectedScript',uri+'\n'+script.filename); }, get gmScripts() getScripts(), get allItem() containers, get currentPanel() getBrowser().mCurrentTab.linkedPanel, get currentContainer() containers[this.currentPanel] || null, get currentSandbox(){ var id = this.currentPanel; return containers[id] ? containers[id].sandbox : null; }, getSandboxFromWindow: function(win){ for each(var c in containers){ if(c.sandbox.window == win) return sandbox; } return null; }, getContainersFromURI: function(uri){ var list = []; for each(var c in containers){ if (c.uri == uri) list.push(c); } return list.length > 0 ? list : null; }, addAutoCommand: function(uri, script, cmd){ var reg = uri+'.*\n'+script+'\.user\.js'; autocommands.add('GMInjectedScript', reg, cmd); }, removeAutoCommand: function(uri, script){ var reg = uri+'.*\n'+script+'\.user\.js'; autocommands.remove('GMInjectedScript', reg); }, }; // }}} // ----------------------- // PRIVATE section // ----------------------- // {{{ var containers = {}; var gmSvc = Cc[gmID].getService().wrappedJSObject; function appendCode(target,name,func){ var original = target[name]; target[name] = function(){ var tmp = original.apply(target,arguments); func.apply(this,arguments); return tmp; }; } appendCode(gmSvc, 'evalInSandbox', function(code,uri,sandbox,script){ liberator.plugins.gmperator.register(uri,sandbox,script); }); function getPanelID(win){ var tabs = getBrowser().mTabs; for (var i=0; tabs.length; i++){ var tab = tabs.item(i); if (tab.linkedBrowser.contentWindow == win){ return tab.linkedPanel; } } //liberator.log(win + 'is not found'); } function updateGmContainerList(e){ var t = e.target; if (t && t.localName == 'tab' && t.linkedPanel){ delete containers[t.linkedPanel]; delete plugins.gmperator[t.linkedPanel]; } } getBrowser().mTabContainer.addEventListener('TabClose',updateGmContainerList,false); // }}} return manager; })(); //}}} // --------------------------- // User Command // --------------------------- commands.addUserCommand(['gmli[st]','lsgm'], 'list Greasemonkey scripts', //{{{ function(arg,special){ var str = ''; var scripts = getScripts(); var reg; if (special || arg == 'full'){ reg = new RegExp('.*'); } else if( arg ){ reg = new RegExp(arg,'i'); } if (reg){ scripts.forEach(function(s){ if ( reg.test(s.name) || reg.test(s.filename) ) { str += scriptToString(s) + '\n\n'; } }); } else { var table =
// Vimperator Plugin: Param Editor // Version: 0.1 (function (){ var doc = null; var xpath = function(query, node){ var snap = doc.evaluate(query, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); var res = []; for(let i = 0, l = snap.snapshotLength; i < l; i++){ res.push(snap.snapshotItem(i)); } return res; }; var Form = function(form, i){ this.uid = i; this.method = (form.method.length) ? form.method.toUpperCase() : "GET"; this.action = form.action; this.name = (form.name.length) ? form.name : this.uid; this.e = form; this.member = []; //var elems = xpath("descendant::*[@name]", form); var elems = Array.slice(form.elements); var count = 0; elems.forEach(function(e, i){ if(!e.type) return; var type = e.type.toLowerCase(); if(type == "radio" || type == "checkbox"){ let mg = null; for(let i = 0, l = this.member.length; i < l; i++){ if(this.member[i].constructor == FormMemberGroup && this.member[i].name == e.name){ mg = this.member[i]; break; } } if(!mg){ mg = new FormMemberGroup(e, count++); this.member.push(mg); } mg.add_elem(e); }else{ this.member.push(new FormMember(e, count++)); } }, this); this.html = form2html(this); }; var FormMember = function(elem, i){ this.uid = i; this.elem = elem; }; ["name", "value", "type"].forEach(function(n){ FormMember.prototype.__defineGetter__(n, function(){ return this.elem[n]; }); FormMember.prototype.__defineSetter__(n, function(v){ this.elem[n] = v; }); }); var FormMemberGroup = function(e, i){ this.uid = i; this.type = e.type.toLowerCase(); this.name = e.name; this.elems = []; }; FormMemberGroup.prototype.__defineGetter__("value", function(){ var v = []; this.elems.forEach(function(e){ var _v = e.value; if(e.checked){ _v = "[" + _v + "]"; } v.push(_v); }); return v.join(" "); }); FormMemberGroup.prototype.__defineSetter__("value", function(v){ var check = function(n){ if(this.type == "radio"){ this.elems[n].checked = true; }else if(this.type == "checkbox"){ this.elems[n].checked = (this.elems[n].checked) ? false : true; } }; for(let i = 0, l = this.elems.length; i < l; i++){ if(this.elems[i].value == v){ check.call(this, i); return; } } if(this.elems[v]){ check.call(this, v); } }); FormMemberGroup.prototype.add_elem = function(e){ this.elems.push(e); }; var form2html = function(form){ var html = [ '<style type="text/css">', '.red { color:#c00 !important}', '.blue { color:#00c !important}', 'caption { margin:5px 0; text-align:left; font-weight:bold !important;}', 'th { padding:0 7px; text-align:left; font-weight:bold !important;}', 'td { padding:0 7px;}', '</style>', '<table style="width:100%;">', '<caption><span class="blue">' + form.method + '</span> name:<span class="red">' + form.name + '</span> =>' + form.action + '</caption>', '<tr><th style="width:15%;"> Name</th><th style="width:15%;"> Type</th><th> Value</th></tr>']; form.member.forEach(function(e){ var uid = (e.uid < 10) ? e.uid + " " : e.uid; html.push('<tr><td>'+ uid + ' ' + e.name + '</td><td>| ' + e.type + '</td><td>| ' + e.value + '</td></tr>'); }); html.push( '</table>' ); return html.join(''); }; var get_forms = function(){ var r = []; var f = doc.forms; for(let i = 0, l = f.length; i < l; i++){ r.push(new Form(f[i], i)); } return r; }; var select = function(a, q){ var cand = []; for(let i = 0, l = a.length; i < l; i++){ if(a[i].name == q || a[i].uid == q){ cand.push(a[i]); break; }else if(new RegExp("^"+q).test(a[i].name)){ cand.push(a[i]); } } if(cand.length == 1){ return cand[0]; }else{ return null; } }; liberator.commands.addUserCommand( ["pls"], "Listing current value of forms", function(q){ doc = window.content.document; var forms = get_forms(); var html = null; if(q){ let form = select(forms, q); if(form) html = form.html; }else if(forms.length){ html = ""; forms.forEach(function(f){ html += f.html; html += "<br/>"; }); } if(html){ liberator.commandline.echo(html, liberator.commandline.HL_NORMAL, liberator.commandline.FORCE_MULTILINE); }else{ liberator.echoerr("Form not found"); } /* forms.forEach(function(f){ liberator.log(f, 9); f.member.forEach(function(m){ liberator.log(m, 9); }); }); */ window.content.vimp_param_editor_forms = forms; }, null, true ); liberator.commands.addUserCommand( ["pe[dit]"], "Edit value of a form element", function(q, submit){ var _ = q.match(/^\s*([^.\s]+)\.([^=\s]+)\s*=\s*(.*)$/); if(!_){ liberator.echoerr("Failed to parse query"); return; } var [, f, m, v] = _; //liberator.log([f, m, v], 9); doc = window.content.document; var forms = window.content.vimp_param_editor_forms || get_forms(); var form = select(forms, f); if(form == null){ liberator.echoerr("Form not found"); return; } //liberator.log(form, 9); var mem = select(form.member, m); if(mem == null){ liberator.echoerr("FormMember not found"); return; } //liberator.log(mem, 9); mem.value = v; if(submit){ form.e.submit(); } }, null, true ); })();