1 /*** BEGIN LICENSE BLOCK {{{
2 Copyright (c) 2008 suVene<suvene@zeromemory.info>
4 distributable under the terms of an MIT-style license.
5 http://www.opensource.jp/licenses/mit-license.html
6 }}} END LICENSE BLOCK ***/
11 <description>request, and the result is displayed to the buffer.</description>
12 <description lang="ja">リクエストの結果をバッファに出力する。</description>
13 <author mail="suvene@zeromemory.info" homepage="http://zeromemory.sblo.jp/">suVene</author>
14 <version>0.4.15</version>
15 <license>MIT</license>
16 <minVersion>2.0pre</minVersion>
17 <maxVersion>2.1pre</maxVersion>
18 <updateURL>http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk/multi_requester.js</updateURL>
21 - _libly.js(ver.0.1.19)
22 @see http://coderepos.org/share/browser/lang/javascript/vimperator-plugins/trunk/_libly.js
26 command[!] subcommand [ANY_TEXT]
29 - ANY_TEXT your input text
33 :mr alc[,goo,any1,any2…] ANY_TEXT -> request by the input text, and display to the buffer.
34 :mr! goo[,any1,any2,…] {window.selection} -> request by the selected text, and display to the new tab.
37 == Custumize .vimperatorrc ==
38 === Command(default [ mr ]) ===
40 let g:multi_requester_command = "ANY1, ANY2, ……"
42 liberator.globalVariables.multi_requester_command = [ ANY1, ANY2, …… ];
45 === Default Sites (default undefined) ===
47 liberator.globalVariables.multi_requester_default_sites = "alc,goo"
49 These sites(subcommands) will be used, if this variable has been defined and you do not specify subcommands.
55 liberator.globalVariables.multi_requester_siteinfo = [
57 map: ",me", // optional: keymap for this siteinfo call
58 bang: true, // optional:
59 args: "any" // optional:
60 name: "ex", // required: subcommand name
61 description: "example", // required: commandline short help
62 url: "http://example.com/?%s", // required: %s <-- replace string
63 xpath: "//*", // optional: default all
64 srcEncode: "SHIFT_JIS", // optional: default UTF-8
65 urlEncode: "SHIFT_JIS", // optional: default srcEncode
66 ignoreTags: "img", // optional: default script, syntax "tag1,tag2,……"
67 extractLink: "//xpath" // optional: extract permalink
73 === other siteinfo by wedata. ===
74 @see http://wedata.net/databases/Multi%20Requester/items
80 liberator.globalVariables.multi_requester_mappings = [
81 [ ",ml", "ex" ], // == :mr ex
82 [ ",mg", "goo", "!" ], // == :mr! goo
83 [ ",ma", "alc", , "args" ], // == :mr alc args
90 let g:multi_requester_use_wedata = "false" // true by default
92 wedata を利用しない場合は false を設定してください。
94 let g:multi_requester_default_sites = 'alc';
96 subcommand を省略した場合に利用されるサイトを設定します。
98 let g:multi_requester_order = 'count'; // date by default
100 補完の順番を設定します。(大きい順に並びます)
101 "count" または "date" を設定してください。
107 if (!liberator.plugins.libly) {
108 liberator.log("multi_requester: needs _libly.js");
112 // global variables {{{
113 var DEFAULT_COMMAND = [ "mr" ];
117 description: "SPACE ALC (\u82F1\u8F9E\u6717 on the Web)",
118 url: "http://eow.alc.co.jp/%s/UTF-8/",
119 xpath: 'id("resultsList")'
122 var libly = liberator.plugins.libly;
124 var logger = $U.getLogger("multi_requester");
125 var mergedSiteinfo = {};
126 var store = storage.newMap('plugins-multi_requester', true);
129 // Vimperator plugin command register {{{
130 var CommandRegister = {
131 register: function(cmdClass, siteinfo) {
132 cmdClass.siteinfo = siteinfo;
134 commands.addUserCommand(
136 cmdClass.description,
137 $U.bind(cmdClass, cmdClass.cmdAction),
139 completer: cmdClass.cmdCompleter || function(context, arg) {
142 context.title = [ "Name", "Descprition" ];
143 var sorted = siteinfo.sort(function(a, b)
144 typeof liberator.globalVariables.multi_requester_order == "undefined" ||
145 liberator.globalVariables.multi_requester_order == "date" ? store.get(b.name).lastPostTime - store.get(a.name).lastPostTime :
146 liberator.globalVariables.multi_requester_order == "count" ? store.get(b.name).count - store.get(a.name).count :
147 store.get(b.name).lastPostTime - store.get(a.name).lastPostTime);
148 var filters = context.filter.split(",");
149 var prefilters = filters.slice(0, filters.length - 1);
150 var prefilter = !prefilters.length ? "" : prefilters.join(",") + ",";
151 var subfilters = sorted.filter(function(s) prefilters.every(function(p) s.name != p));
152 var allSuggestions = subfilters.map(function(s) [prefilter + s.name, s.description]);
153 context.completions = context.filter
154 ? allSuggestions.filter(function(s) s[0].indexOf(context.filter) == 0)
157 options: cmdClass.cmdOptions,
158 argCount: cmdClass.argCount || undefined,
159 bang: cmdClass.bang || true,
160 count: cmdClass.count || false
166 addUserMaps: function(prefix, mapdef) {
167 mapdef.forEach(function([ key, command, bang, args ]) {
168 var cmd = prefix + (bang ? "! " : " ") + command + " ";
170 [ modes.NORMAL, modes.VISUAL ],
172 "user defined mapping",
175 liberator.execute(cmd + args);
177 let sel = $U.getSelectedString();
179 liberator.execute(cmd + sel);
181 commandline.open(":", cmd, modes.EX);
195 // initial data access class {{{
197 getCommand: function() {
198 var c = liberator.globalVariables.multi_requester_command;
200 if (typeof c == "string") {
202 } else if (typeof c == "Array") {
205 ret = DEFAULT_COMMAND;
209 getSiteInfo: function() {
212 var useWedata = typeof liberator.globalVariables.multi_requester_use_wedata == "undefined" ?
213 true : $U.eval(liberator.globalVariables.multi_requester_use_wedata);
215 if (liberator.globalVariables.multi_requester_siteinfo) {
216 liberator.globalVariables.multi_requester_siteinfo.forEach(function(site) {
217 if (!mergedSiteinfo[site.name]) mergedSiteinfo[site.name] = {};
218 $U.extend(mergedSiteinfo[site.name], site);
219 if (!store.get(site.name)) {
220 store.set(site.name, { count: 0, lastPostTime: (new Date()).getTime() });
224 CommandRegister.addUserMaps(MultiRequester.name[0],
225 [[ site.map, site.name, site.bang, site.args ]]);
230 SITEINFO.forEach(function(site) {
231 if (!mergedSiteinfo[site.name]) mergedSiteinfo[site.name] = {};
232 $U.extend(mergedSiteinfo[site.name], site);
233 if (!store.get(site.name)) {
234 store.set(site.name, { count: 0, lastPostTime: (new Date()).getTime() });
238 CommandRegister.addUserMaps(MultiRequester.name[0],
239 [[ site.map, site.name, site.bang, site.args ]]);
244 logger.log("use wedata");
245 var wedata = new libly.Wedata("Multi%20Requester");
246 wedata.getItems(24 * 60 * 60 * 1000,
248 var site = item.data;
249 if (mergedSiteinfo[site.name]) return;
250 mergedSiteinfo[site.name] = {};
251 $U.extend(mergedSiteinfo[site.name], site);
252 if (!store.get(site.name)) {
253 store.set(site.name, { count: 0, lastPostTime: (new Date()).getTime() });
257 function(isSuccess, data) {
258 if (!isSuccess) return;
259 CommandRegister.register(MultiRequester, $U.A(mergedSiteinfo));
264 return $U.A(mergedSiteinfo);
269 // main controller {{{
270 var MultiRequester = {
271 name: DataAccess.getCommand(),
272 description: "request, and display to the buffer",
273 defaultSites: liberator.globalVariables.multi_requester_default_sites,
278 cmdAction: function(args) { //{{{
280 if (MultiRequester.doProcess) return;
282 var bang = args.bang;
283 var count = args.count;
285 var parsedArgs = this.parseArgs(args);
286 if (parsedArgs.count == 0) { return; } // do nothing
288 MultiRequester.doProcess = true;
289 MultiRequester.requestNames = parsedArgs.names;
290 MultiRequester.requestCount = 0;
291 MultiRequester.echoHash = {};
292 var siteinfo = parsedArgs.siteinfo;
293 for (let i = 0, len = parsedArgs.count; i < len; i++) {
295 let info = siteinfo[i];
296 let name = info.name;
298 let history = store.get(name);
300 history.lastPostTime = (new Date()).getTime();
301 store.set(name, history);
305 // see: http://fifnel.com/2008/11/14/1980/
306 let srcEncode = info.srcEncode || "UTF-8";
307 let urlEncode = info.urlEncode || srcEncode;
309 let repStrCount = let (m = url.match(/%s/g)) (m && m.length);
310 if (repStrCount && !parsedArgs.strs.length) continue;
312 // via. lookupDictionary.js
313 let ttbu = Components.classes["@mozilla.org/intl/texttosuburi;1"]
314 .getService(Components.interfaces.nsITextToSubURI);
317 url = url.replace(/%s/g, function(m, i) ttbu.ConvertAndEscape(urlEncode,
318 (cnt >= parsedArgs.strs.length ? parsedArgs.strs[cnt - 1] :
319 cnt >= (repStrCount - 1) ? parsedArgs.strs.splice(cnt).join(' ') :
320 parsedArgs.strs[cnt++])));
321 logger.log(url + "[" + srcEncode + "][" + urlEncode + "]::" + info.xpath);
324 liberator.open(url, liberator.NEW_TAB);
326 let req = new libly.Request(url, null, {
335 req.addEventListener("onException", $U.bind(this, this.onException));
336 req.addEventListener("onSuccess", $U.bind(this, this.onSuccess));
337 req.addEventListener("onFailure", $U.bind(this, this.onFailure));
339 MultiRequester.requestCount++;
343 if (MultiRequester.requestCount) {
344 logger.echo("Loading " + parsedArgs.names + " ...", commandline.FORCE_SINGLELINE);
346 MultiRequester.doProcess = false;
349 // return {names: "", strs: [""], count: 0, siteinfo: [{}]}
350 parseArgs: function(args) {
357 var sel = $U.getSelectedString();
359 if (args.length < 1 && !sel.length) return ret;
361 function parse(args, names) {
362 args = Array.concat(args);
364 ret.names = names || args.shift() || "";
365 ret.strs = (args.length < 1 ? [ sel.replace(/[\n\r]+/g, "") ] : args);
367 ret.names.split(",").forEach(function(name) {
368 var site = self.getSite(name);
371 ret.siteinfo.push(site);
378 if (!ret.siteinfo.length && this.defaultSites)
379 parse(args, this.defaultSites);
383 getSite: function(name) {
384 if (!name) this.siteinfo[0];
386 this.siteinfo.forEach(function(s) {
387 if (s.name == name) ret = s;
391 extractLink: function(res, extractLink) { //{{{
393 var el = res.getHTMLDocument(extractLink);
394 if (!el) throw "extract link failed.: extractLink -> " + extractLink;
395 var url = $U.pathToURL(el[0], res.req.url);
396 var req = new libly.Request(url, null, $U.extend(res.req.options, { extractLink: true }));
397 req.addEventListener("onException", $U.bind(this, this.onException));
398 req.addEventListener("onSuccess", $U.bind(this, this.onSuccess));
399 req.addEventListener("onFailure", $U.bind(this, this.onFailure));
401 MultiRequester.requestCount++;
402 MultiRequester.doProcess = true;
405 onSuccess: function(res) { //{{{
407 if (!MultiRequester.doProcess) {
408 MultiRequester.requestCount = 0;
412 logger.log("success!!: " + res.req.url);
413 MultiRequester.requestCount--;
414 if (MultiRequester.requestCount == 0) {
415 MultiRequester.doProcess = false;
418 var url, escapedUrl, xpath, doc, html, extractLink, ignoreTags;
422 if (!res.isSuccess() || res.responseText == "") throw "response is fail or null";
425 escapedUrl = util.escapeHTML(url);
426 xpath = res.req.options.siteinfo.xpath;
427 extractLink = res.req.options.siteinfo.extractLink;
429 if (extractLink && !res.req.options.extractLink) {
430 this.extractLink(res, extractLink);
433 ignoreTags = [ "script" ].concat(libly.$U.A(res.req.options.siteinfo.ignoreTags));
434 doc = document.createElementNS(null, "div");
435 res.getHTMLDocument(xpath, null, ignoreTags, function(node, i) {
436 if (node.tagName.toLowerCase() != "html")
437 doc.appendChild(node);
439 if (!doc || !doc.childNodes.length) throw "XPath result is undefined or null.: XPath -> " + xpath;
441 $U.getNodesFromXPath("descendant-or-self::a | descendant-or-self::img", doc, function(node) {
442 var tagName = node.tagName.toLowerCase();
443 if (tagName == "a") {
444 node.href = $U.pathToURL(node, url, res.doc);
445 } else if (tagName == "img") {
446 node.src = $U.pathToURL(node, url, res.doc);
450 html = '<a href="' + escapedUrl + '" class="hl-Title" target="_self">' + escapedUrl + '</a>' +
451 $U.xmlSerialize(doc);
453 MultiRequester.echoHash[res.req.options.siteinfo.name] = html;
456 logger.log("error!!: " + e);
457 MultiRequester.echoHash[res.req.options.siteinfo.name] =
458 '<span style="color: red;">error!!: ' + e + '</span>';
461 if (MultiRequester.requestCount == 0) {
463 MultiRequester.requestNames.split(",").forEach(function(name) {
464 echoList.push(MultiRequester.echoHash[name]);
466 html = '<div style="white-space:normal;"><base href="' + escapedUrl + '"/>' +
469 try { logger.echo(new XMLList(html)); } catch (e) { logger.log(e); logger.echo(html); }
473 onFailure: function(res) {
474 MultiRequester.doProcess = false;
475 logger.echoerr("request failure!!: " + res.statusText);
477 onException: function(e) {
478 MultiRequester.doProcess = false;
479 logger.echoerr("exception!!: " + e);
485 CommandRegister.register(MultiRequester, DataAccess.getSiteInfo());
486 if (liberator.globalVariables.multi_requester_mappings) {
487 CommandRegister.addUserMaps(MultiRequester.name[0], liberator.globalVariables.multi_requester_mappings);
491 return MultiRequester;
494 // vim: set fdm=marker sw=2 ts=2 sts=0 et: