]> gitweb @ CieloNegro.org - sugar.git/blobdiff - dot-files/_vimperator/plugin/_libly_js
Auto commit by The Sugar System.
[sugar.git] / dot-files / _vimperator / plugin / _libly_js
index 6d547a88ee21de93fdb0ec2966be2d38e849b630..be989d7266f66a0a7ea9c5c42cb602f752e2aa78 100644 (file)
@@ -1,21 +1,23 @@
 /*** BEGIN LICENSE BLOCK {{{
     Copyright (c) 2008 suVene<suvene@zeromemory.info>
+    Copyright (c) 2008-2011 anekos<anekos@snca.net>
 
     distributable under the terms of an MIT-style license.
     http://www.opensource.jp/licenses/mit-license.html
 }}}  END LICENSE BLOCK ***/
 // PLUGIN_INFO//{{{
-var PLUGIN_INFO =
+/*
+var PLUGIN_INFO = xml`
 <VimperatorPlugin>
     <name>libly(filename _libly.js)</name>
     <description>Vimperator plugins library?</description>
     <description lang="ja">適当なライブラリっぽいものたち。</description>
     <author mail="suvene@zeromemory.info" homepage="http://zeromemory.sblo.jp/">suVene</author>
+    <author mail="anekos@snca.net" homepage="http://snca.net/">anekos</author>
     <license>MIT</license>
-    <version>0.1.24</version>
-    <minVersion>1.2</minVersion>
-    <maxVersion>2.0pre</maxVersion>
-    <updateURL>http://svn.coderepos.org/share/lang/javascript/vimperator-plugins/trunk/_libly.js</updateURL>
+    <version>0.1.38</version>
+    <minVersion>2.3pre</minVersion>
+    <updateURL>https://github.com/vimpr/vimperator-plugins/raw/master/_libly.js</updateURL>
     <detail><![CDATA[
 == Objects ==
 - liberator.plugins.libly.$U
@@ -34,14 +36,25 @@ extend(dst, src):
     オブジェクトを拡張します。
 A(iterable):
     オブジェクトを配列にします。
-around(obj, name, func):
+around(obj, name, func, autoRestore):
   obj がもつ name 関数を、func に置き換えます。
   func は
     function (next, args) {...}
   という形で呼ばれます。
   next はオリジナルの関数を呼び出すための関数、
   args はオリジナルの引数列です。
-  next には引数を渡す必要はありません。
+  通常、next には引数を渡す必要はありません。
+  (任意の引数を渡したい場合は配列で渡します。)
+  また、autoRestore が真であれば、プラグインの再ロードなどで around が再実行されたときに、関数の置き換え前にオリジナル状態に書き戻します。
+  (多重に置き換えられなくなるので、auto_source.js などを使ったプラグイン開発で便利です)
+  返値は以下のオブジェクトです
+  >||
+  {
+    original: オリジナルの関数
+    current: 現在の関数
+    restore: 元に戻すための関数
+  }
+  ||<
 bind(obj, func):
     func に obj を bind します。
     func内からは this で obj が参照できるようになります。
@@ -112,13 +125,13 @@ Request(url, headers, options):
         以下のようにHTTPヘッダの値を指定できる(省略可)
         >||
         {
-            'Referrer' : 'http://example.com/'
+            'Referer' : 'http://example.com/'
         }
         ||<
         以下の値はデフォルトで設定される('Content-type'はPOST時のみ)
         >||
         {
-            'Accept': 'text/javascript, application/javascript, text/html, application/xhtml+xml, application/xml, text/xml, */*;q=0.1',
+            'Accept': 'text/javascript, application/javascript, text/html, application/xhtml+xml, application/xml, text/xml, * /*;q=0.1',
             'Content-type': 'application/x-www-form-urlencoded; charset=' + options.encodingの値
         }
         ||<
@@ -126,7 +139,7 @@ Request(url, headers, options):
     options:
         オプションとして以下のようなオブジェクトを指定できる(省略可)
         asynchronous:
-            true: 同期モード/false: 非同期モード(デフォルト:true)
+            true: 非同期モード/false: 同期モード(デフォルト:true)
         encoding:
             エンコーディング(デフォルト: 'UTF-8')
         username:
@@ -135,14 +148,14 @@ Request(url, headers, options):
             BASIC認証時のパスワード
         postBody:
             POSTメソッドにより送信するbody
-addEventLister(name, func):
+addEventListener(name, func):
     イベントリスナを登録する。
     name:
-        'onSuccess':
+        'success':
             成功時
-        'onFailure':
+        'failure':
             失敗を表すステータスコードが返ってきた時
-        'onException':
+        'exception':
             例外発生時
     func:
         イベント発火時の処理
@@ -177,13 +190,19 @@ clearCache:
   wedata 読込み成功したら、強制的にキャッシュと置き換えるの作って!
 
     ]]></detail>
-</VimperatorPlugin>;
+</VimperatorPlugin>`;
+*/
 //}}}
 //if (!liberator.plugins.libly) {
 
 liberator.plugins.libly = {};
 var libly = liberator.plugins.libly;
 
+// XXX for backward compatibillity
+function fixEventName(name) {
+    return name.replace(/^on/, '').toLowerCase();
+}
+
 libly.$U = {//{{{
     // Logger {{{
     getLogger: function(prefix) {
@@ -223,14 +242,55 @@ libly.$U = {//{{{
         }
         return ret;
     },
-    around: function around (obj, name, func) {
-        let next = obj[name];
-        let current = obj[name] = function () {
-            let self = this, args = arguments;
-            return func.call(self, function () next.apply(self, args), args);
+    around: (function () {
+        function getPluginPath () {
+          let pluginPath;
+          Error('hoge').stack.split(/\n/).some(
+            function (s)
+              let (m = s.match(/-> liberator:\/\/template\/chrome:\/\/liberator\/content\/liberator\.js -> (.+):\d+$/))
+                (m && (pluginPath = m[1].replace(/\?.*$/, '')))
+          );
+          return pluginPath;
+        }
+
+        let restores = {};
+
+        return function (obj, name, func, autoRestore) {
+            let original;
+            let restore = function () obj[name] = original;
+            if (autoRestore) {
+                let pluginPath = getPluginPath();
+                if (pluginPath) {
+                    restores[pluginPath] =
+                        (restores[pluginPath] || []).filter(
+                            function (res) (
+                                res.object != obj ||
+                                res.name != name ||
+                                (res.restore() && false)
+                            )
+                        );
+                    restores[pluginPath].push({
+                        object: obj,
+                        name: name,
+                        restore: restore
+                    });
+                } else {
+                    liberator.echoerr('getPluginPath failed');
+                }
+            }
+            original = obj[name];
+            let current = obj[name] = function () {
+                let self = this, args = arguments;
+                return func.call(self, function (_args) original.apply(self, _args || args), args);
+            };
+            libly.$U.extend(current, {original: original && original.original || original, restore: restore});
+            return libly.$U.extend({
+                original: original,
+                current: current,
+                restore: restore
+            }, [original, current]);
         };
-        return [next, current];
-    },
+    })(),
     bind: function(obj, func) {
         return function() {
             return func.apply(obj, arguments);
@@ -322,7 +382,7 @@ libly.$U = {//{{{
     // }}}
     // System {{{
     readDirectory: function(path, filter, func) {
-        var d = io.getFile(path);
+        var d = io.File(path);
         if (d.exists() && d.isDirectory()) {
             let enm = d.directoryEntries;
             let flg = false;
@@ -366,7 +426,8 @@ libly.$U = {//{{{
         let uhService = Cc["@mozilla.org/feed-unescapehtml;1"].getService(Ci.nsIScriptableUnescapeHTML);
         let text = str.replace(/^[\s\S]*?<body([ \t\n\r][^>]*)?>[\s]*|<\/body[ \t\r\n]*>[\S\s]*$/ig, '');
         let fragment = uhService.parseFragment(text, false, null, root);
-        let htmlFragment = document.implementation.createDocument(null, 'html', null);
+        let doctype = document.implementation.createDocumentType('html', '-//W3C//DTD HTML 4.01//EN', 'http://www.w3.org/TR/html4/strict.dtd');
+        let htmlFragment = document.implementation.createDocument(null, 'html', doctype);
         htmlFragment.documentElement.appendChild(htmlFragment.importNode(fragment,true));
         return htmlFragment;
         /* うまく動いていない場合はこちらに戻してください
@@ -404,21 +465,7 @@ libly.$U = {//{{{
     },
     xmlToDom: function xmlToDom(node, doc, nodes)
     {
-        XML.prettyPrinting = false;
-        switch (node.nodeKind())
-        {
-            case "text":
-                return doc.createTextNode(node);
-            case "element":
-                let domnode = doc.createElementNS(node.namespace(), node.localName());
-                for each (let attr in node.@*)
-                    domnode.setAttributeNS(attr.name() == "highlight" ? NS.uri : attr.namespace(), attr.name(), String(attr));
-                for each (let child in node.*)
-                    domnode.appendChild(arguments.callee(child, doc, nodes));
-                if (nodes && node.@key)
-                    nodes[node.@key] = domnode;
-                return domnode;
-        }
+        return util.xmlToDom(node, doc, nodes);
     },
     getElementPosition: function(elem) {
         var offsetTrail = elem;
@@ -463,14 +510,16 @@ libly.Request.prototype = {
         this.observers = {};
     },
     addEventListener: function(name, func) {
+        name = fixEventName(name);
         try {
             if (typeof this.observers[name] == 'undefined') this.observers[name] = [];
             this.observers[name].push(func);
         } catch (e) {
-            if (!this.fireEvent('onException', new libly.Response(this), e)) throw e;
+            if (!this.fireEvent('exception', new libly.Response(this), e)) throw e;
         }
     },
     fireEvent: function(name, args, asynchronous) {
+        name = fixEventName(name);
         if (!(this.observers[name] instanceof Array)) return false;
         this.observers[name].forEach(function(event) {
             if (asynchronous) {
@@ -491,20 +540,29 @@ libly.Request.prototype = {
             this.transport = new XMLHttpRequest();
             this.transport.open(method, this.url, this.options.asynchronous, this.options.username, this.options.password);
 
-            this.transport.onreadystatechange = libly.$U.bind(this, this._onStateChange);
+            var stateChangeException;
+            this.transport.onreadystatechange = libly.$U.bind(this, function () {
+                try {
+                    this._onStateChange();
+                } catch (e) {
+                    stateChangeException = e;
+                }
+            });
             this.setRequestHeaders();
-            this.transport.overrideMimeType('text/html; charset=' + this.options.encoding);
+            this.transport.overrideMimeType(this.options.mimetype || 'text/html; charset=' + this.options.encoding);
 
             this.body = this.method == 'POST' ? this.options.postBody : null;
 
             this.transport.send(this.body);
 
+            if (!this.options.asynchronous && stateChangeException) throw stateChangeException;
+
             // Force Firefox to handle ready state 4 for synchronous requests
             if (!this.options.asynchronous && this.transport.overrideMimeType)
                 this._onStateChange();
 
         } catch (e) {
-            if (!this.fireEvent('onException', new libly.Response(this), e)) throw e;
+            if (!this.fireEvent('exception', new libly.Response(this), e)) throw e;
         }
     },
     _onStateChange: function() {
@@ -529,9 +587,9 @@ libly.Request.prototype = {
             libly.Request.requestCount--;
             try {
                 this._complete = true;
-                this.fireEvent('on' + (this.isSuccess() ? 'Success' : 'Failure'), res, this.options.asynchronous);
+                this.fireEvent(this.isSuccess() ? 'success' : 'failure', res, this.options.asynchronous);
             } catch (e) {
-                if (!this.fireEvent('onException', res, e)) throw e;
+                if (!this.fireEvent('exception', res, e)) throw e;
             }
         }
     },
@@ -579,6 +637,7 @@ libly.Response.prototype = {
             this.status = this.getStatus();
             this.statusText = this.getStatusText();
             this.responseText = (this.transport.responseText == null) ? '' : this.transport.responseText;
+            this.responseXML = this.transport.responseXML;
         }
 
         this.doc = null;
@@ -619,8 +678,8 @@ libly.Wedata.prototype = {
     getItems: function(expire, itemCallback, finalCallback) {
 
         var logger = this.logger;
-        var STORE_KEY = 'plugins-libly-wedata-' + this.dbname + '-items';
-        var store = storage.newMap(STORE_KEY, true);
+        var STORE_KEY = 'plugins-libly-wedata-' + encodeURIComponent(this.dbname) + '-items';
+        var store = storage.newMap(STORE_KEY, {store: true});
         var cache = store && store.get('data');
 
         if (store && cache && new Date(store.get('expire')) > new Date()) {
@@ -646,11 +705,11 @@ libly.Wedata.prototype = {
             }
         }
 
-        var req = new libly.Request(this.HOST_NAME + 'databases/' + this.dbname + '/items.json');
-        req.addEventListener('onSuccess', libly.$U.bind(this, function(res) {
+        var req = new libly.Request(this.HOST_NAME + 'databases/' + encodeURIComponent(this.dbname) + '/items.json');
+        req.addEventListener('success', libly.$U.bind(this, function(res) {
             var text = res.responseText;
             if (!text) {
-                errDispatcher('respons is null.', cache);
+                errDispatcher('response is null.', cache);
                 return;
             }
             var json = libly.$U.evalJson(text);
@@ -666,8 +725,8 @@ libly.Wedata.prototype = {
             if (typeof finalCallback == 'function')
                 finalCallback(true, json);
         }));
-        req.addEventListener('onFailure', function() errDispatcher('onFailure', cache));
-        req.addEventListener('onException', function() errDispatcher('onException', cache));
+        req.addEventListener('failure', function() errDispatcher('onFailure', cache));
+        req.addEventListener('exception', function() errDispatcher('onException', cache));
         req.get();
     }
 };