738 lines
28 KiB
JavaScript
738 lines
28 KiB
JavaScript
/*** 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 = 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.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
|
||
- liberator.plugins.libly.Request
|
||
- liberator.plugins.libly.Response
|
||
- liberator.plugins.libly.Wedata
|
||
|
||
== Logger ==
|
||
getLogger(prefix):
|
||
log(msg, level), echo(msg, flg), echoerr(msg)
|
||
のメソッドを持つ logger インスタンスを取得します。
|
||
ログの書式は prefix + ': ' + yyyy/MM/dd + msg となります。
|
||
|
||
== Object Utility ==
|
||
extend(dst, src):
|
||
オブジェクトを拡張します。
|
||
A(iterable):
|
||
オブジェクトを配列にします。
|
||
around(obj, name, func, autoRestore):
|
||
obj がもつ name 関数を、func に置き換えます。
|
||
func は
|
||
function (next, args) {...}
|
||
という形で呼ばれます。
|
||
next はオリジナルの関数を呼び出すための関数、
|
||
args はオリジナルの引数列です。
|
||
通常、next には引数を渡す必要はありません。
|
||
(任意の引数を渡したい場合は配列で渡します。)
|
||
また、autoRestore が真であれば、プラグインの再ロードなどで around が再実行されたときに、関数の置き換え前にオリジナル状態に書き戻します。
|
||
(多重に置き換えられなくなるので、auto_source.js などを使ったプラグイン開発で便利です)
|
||
返値は以下のオブジェクトです
|
||
>||
|
||
{
|
||
original: オリジナルの関数
|
||
current: 現在の関数
|
||
restore: 元に戻すための関数
|
||
}
|
||
||<
|
||
bind(obj, func):
|
||
func に obj を bind します。
|
||
func内からは this で obj が参照できるようになります。
|
||
eval(text):
|
||
Sandbox による、window.eval を極力利用するようにします。
|
||
Snadbox が利用できない場合は、unsafe な window の eval が直接利用されます。
|
||
evalJson(str, toRemove):
|
||
str を decode します。
|
||
toRemove が true の場合、文字列の前後を1文字削除します。
|
||
"(key:value)" 形式の場合などに true を指定して下さい。
|
||
dateFormat(dtm, fmt):
|
||
Date型インスタンスを、指定されたフォーマットで文字列に変換します。
|
||
fmt を省略した場合、"%y/%M/%d %h:%m:%s" となります。
|
||
runnable(generator):
|
||
gererator を実行し、再帰的に resume する為の引数を渡します。
|
||
|
||
== Browser ==
|
||
getSelectedString:
|
||
window の選択文字列を返却します。
|
||
getUserAndPassword(hostname, formSubmitURL, username):
|
||
login-manager から [username, password] を取得します。
|
||
引数の username が省略された場合、検索された 1件目を返却します。
|
||
データが存在しない場合は、null を返却します。
|
||
|
||
== System ==
|
||
readDirectory(path, fileter, func):
|
||
path で指定したディレクトリから、filter で指定された正規表現に match する場合、
|
||
func をファイル名を引数にコールバックします。
|
||
filter は Function を指定することも可能です。
|
||
|
||
== HTML, XML, DOM, E4X ==
|
||
pathToURL(a, baseURL, doc):
|
||
相対パスを絶対パスに変換します。
|
||
getHTMLFragment(html):
|
||
<html>※1</html>
|
||
※1 の文字列を取得します。
|
||
stripTags(str, tags):
|
||
str から tags で指定されたタグを取り除いて返却します。
|
||
tags は文字列、または配列で指定して下さい。
|
||
createHTMLDocument(str, xmlns):
|
||
引数 str より、HTMLFragment を作成します。
|
||
getFirstNodeFromXPath(xpath, context):
|
||
xpath を評価しオブジェクトをを返却します。
|
||
getNodesFromXPath(xpath, context, callback, thisObj):
|
||
xpath を評価し snapshot の配列を返却します。
|
||
xmlSerialize(xml):
|
||
xml を文字列化します。
|
||
xmlToDom(node, doc, nodes):
|
||
for vimperator1.2.
|
||
@see vimperator2.0pre util.
|
||
getElementPosition(elem):
|
||
elem の offset を返却します。
|
||
return {top: 0, left: 0}
|
||
toStyleText(style):
|
||
スタイルが格納されているオブジェクトを
|
||
>||
|
||
position: fixed;
|
||
left: 10px;
|
||
||<
|
||
のような文字列に変換します。
|
||
|
||
== Object Request ==
|
||
Request(url, headers, options):
|
||
コンストラクタ
|
||
url:
|
||
HTTPリクエスト先のURL
|
||
headers:
|
||
以下のようにHTTPヘッダの値を指定できる(省略可)
|
||
>||
|
||
{
|
||
'Referer' : 'http://example.com/'
|
||
}
|
||
||<
|
||
以下の値はデフォルトで設定される('Content-type'はPOST時のみ)
|
||
>||
|
||
{
|
||
'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の値
|
||
}
|
||
||<
|
||
|
||
options:
|
||
オプションとして以下のようなオブジェクトを指定できる(省略可)
|
||
asynchronous:
|
||
true: 非同期モード/false: 同期モード(デフォルト:true)
|
||
encoding:
|
||
エンコーディング(デフォルト: 'UTF-8')
|
||
username:
|
||
BASIC認証時のuser名
|
||
password:
|
||
BASIC認証時のパスワード
|
||
postBody:
|
||
POSTメソッドにより送信するbody
|
||
addEventListener(name, func):
|
||
イベントリスナを登録する。
|
||
name:
|
||
'success':
|
||
成功時
|
||
'failure':
|
||
失敗を表すステータスコードが返ってきた時
|
||
'exception':
|
||
例外発生時
|
||
func:
|
||
イベント発火時の処理
|
||
引数として以下Responseオブジェクトが渡される
|
||
get():
|
||
GETメソッドによりHTTPリクエストを発行する。
|
||
post():
|
||
POSTメソッドによりHTTPリクエストを発行する。
|
||
|
||
== Object Response ==
|
||
HTTPレスポンスを表すオブジェクト
|
||
req:
|
||
レスポンスと対となるRequestオブジェクト
|
||
doc:
|
||
レスポンスから生成されたHTMLDocumentオブジェクト
|
||
isSuccess():
|
||
ステータスコードが成功を表していればtrue、失敗であればfalse
|
||
getStatus():
|
||
ステータスコードを取得する
|
||
getStatusText():
|
||
ステータを表す文字列を取得する
|
||
getHTMLDocument(xpath, xmlns, ignoreTags, callback, thisObj):
|
||
レスポンスからHTMLDocumentオブジェクトを生成し、xpath を評価した結果の snapshot の配列を返す
|
||
|
||
== Object Wedata ==
|
||
~/vimperator/info/profile_name/plugins-libly-wedata-?????
|
||
に store されます。
|
||
getItems(expire, itemCallback, finalCallback):
|
||
インスタンス作成時に指定した dbname から、item を読込みます。
|
||
=== TODO ===
|
||
clearCache:
|
||
wedata 読込み成功したら、強制的にキャッシュと置き換えるの作って!
|
||
|
||
]]></detail>
|
||
</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) {
|
||
return new function() {
|
||
this.log = function(msg, level) {
|
||
if (typeof msg == 'object') msg = util.objectToString(msg);
|
||
liberator.log(libly.$U.dateFormat(new Date()) + ': ' + (prefix || '') + ': ' + msg, (level || 0));
|
||
};
|
||
this.echo = function(msg, flg) {
|
||
flg = flg || commandline.FORCE_MULTILINE;
|
||
// this.log(msg);
|
||
liberator.echo(msg, flg);
|
||
};
|
||
this.echoerr = function(msg) {
|
||
this.log('error: ' + msg);
|
||
liberator.echoerr(msg);
|
||
};
|
||
}
|
||
},
|
||
// }}}
|
||
// Object Utility {{{
|
||
extend: function(dst, src) {
|
||
for (let prop in src)
|
||
dst[prop] = src[prop];
|
||
return dst;
|
||
},
|
||
A: function(iterable) {
|
||
var ret = [];
|
||
if (!iterable) return ret;
|
||
if (typeof iterable == 'string') return [iterable];
|
||
if (!(typeof iterable == 'function' && iterable == '[object NodeList]') &&
|
||
iterable.toArray) return iterable.toArray();
|
||
if (typeof iterable.length != 'undefined') {
|
||
for (let i = 0, len = iterable.length; i < len; ret.push(iterable[i++]));
|
||
} else {
|
||
for each (let item in iterable) ret.push(item);
|
||
}
|
||
return ret;
|
||
},
|
||
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]);
|
||
};
|
||
})(),
|
||
bind: function(obj, func) {
|
||
return function() {
|
||
return func.apply(obj, arguments);
|
||
}
|
||
},
|
||
eval: function(text) {
|
||
var fnc = window.eval;
|
||
var sandbox;
|
||
try {
|
||
sandbox = new Components.utils.Sandbox("about:blank");
|
||
if (Components.utils.evalInSandbox('true', sandbox) === true) {
|
||
fnc = function(text) { return Components.utils.evalInSandbox(text, sandbox); };
|
||
}
|
||
} catch (e) { liberator.log('warning: _libly.js is working with unsafe sandbox.'); }
|
||
|
||
return fnc(text);
|
||
},
|
||
evalJson: function(str, toRemove) {
|
||
var json;
|
||
try {
|
||
json = Components.classes['@mozilla.org/dom/json;1'].getService(Components.interfaces.nsIJSON);
|
||
if (toRemove) str = str.substring(1, str.length - 1);
|
||
return json.decode(str);
|
||
} catch (e) { return null; }
|
||
},
|
||
dateFormat: function(dtm, fmt) {
|
||
var d = {
|
||
y: dtm.getFullYear(),
|
||
M: dtm.getMonth() + 1,
|
||
d: dtm.getDate(),
|
||
h: dtm.getHours(),
|
||
m: dtm.getMinutes(),
|
||
s: dtm.getSeconds(),
|
||
'%': '%'
|
||
};
|
||
for (let [n, v] in Iterator(d)) {
|
||
if (v < 10)
|
||
d[n] = '0' + v;
|
||
}
|
||
return (fmt || '%y/%M/%d %h:%m:%s').replace(/%([yMdhms%])/g, function (_, n) d[n]);
|
||
},
|
||
/**
|
||
* example)
|
||
* $U.runnable(function(resume) {
|
||
* // execute asynchronous function.
|
||
* // goto next yield;
|
||
* var val = yield setTimeout(function() { resume('value!'), 1000) });
|
||
* alert(val); // value!
|
||
* yield;
|
||
* });
|
||
*/
|
||
runnable: function(generator) {
|
||
var it = generator(function(value) {
|
||
try { it.send(value); } catch (e) {}
|
||
});
|
||
it.next();
|
||
},
|
||
// }}}
|
||
// Browser {{{
|
||
getSelectedString: function() {
|
||
return (new XPCNativeWrapper(window.content.window)).getSelection().toString();
|
||
},
|
||
getUserAndPassword: function(hostname, formSubmitURL, username) {
|
||
var passwordManager, logins;
|
||
try {
|
||
passwordManager = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
|
||
logins = passwordManager.findLogins({}, hostname, formSubmitURL, null);
|
||
if (logins.length) {
|
||
if (username) {
|
||
for (let i = 0, len = logins.lengh; i < len; i++) {
|
||
if (logins[i].username == username)
|
||
return [logins[i].username, logins[i].password]
|
||
}
|
||
liberator.log(this.dateFormat(new Date()) +': [getUserAndPassword] username notfound');
|
||
//throw 'username notfound.';
|
||
return [];
|
||
} else {
|
||
return [logins[0].username, logins[0].password];
|
||
}
|
||
} else {
|
||
liberator.log(this.dateFormat(new Date()) + ': [getUserAndPassword] account notfound');
|
||
return [];
|
||
}
|
||
} catch (e) {
|
||
liberator.log(this.dateFormat(new Date()) + ': [getUserAndPassword] error: ' + e, 0);
|
||
return null;
|
||
}
|
||
},
|
||
// }}}
|
||
// System {{{
|
||
readDirectory: function(path, filter, func) {
|
||
var d = io.File(path);
|
||
if (d.exists() && d.isDirectory()) {
|
||
let enm = d.directoryEntries;
|
||
let flg = false;
|
||
while (enm.hasMoreElements()) {
|
||
let item = enm.getNext();
|
||
item.QueryInterface(Components.interfaces.nsIFile);
|
||
flg = false;
|
||
if (typeof filter == 'string') {
|
||
if ((new RegExp(filter)).test(item.leafName)) flg = true;
|
||
} else if (typeof filter == 'function') {
|
||
flg = filter(item);
|
||
}
|
||
if (flg) func(item);
|
||
}
|
||
}
|
||
},
|
||
// }}}
|
||
// HTML, XML, DOM, E4X {{{
|
||
pathToURL: function(a, baseURL, doc) {
|
||
if (!a) return '';
|
||
var XHTML_NS = "http://www.w3.org/1999/xhtml";
|
||
var XML_NS = "http://www.w3.org/XML/1998/namespace";
|
||
//var path = (a.href || a.getAttribute('src') || a.action || a.value || a);
|
||
var path = (a.getAttribute('href') || a.getAttribute('src') || a.action || a.value || a);
|
||
if (/^https?:\/\//.test(path)) return path;
|
||
var link = (doc || window.content.documtent).createElementNS(XHTML_NS, 'a');
|
||
link.setAttributeNS(XML_NS, 'xml:base', baseURL);
|
||
link.href = path;
|
||
return link.href;
|
||
},
|
||
getHTMLFragment: function(html) {
|
||
if (!html) return html;
|
||
return html.replace(/^[\s\S]*?<html(?:[ \t\n\r][^>]*)?>|<\/html[ \t\r\n]*>[\S\s]*$/ig, '');
|
||
},
|
||
stripTags: function(str, tags) {
|
||
var ignoreTags = '(?:' + [].concat(tags).join('|') + ')';
|
||
return str.replace(new RegExp('<' + ignoreTags + '(?:[ \\t\\n\\r][^>]*|/)?>([\\S\\s]*?)<\/' + ignoreTags + '[ \\t\\r\\n]*>', 'ig'), '');
|
||
},
|
||
createHTMLDocument: function(str, xmlns, doc) {
|
||
let root = document.createElementNS("http://www.w3.org/1999/xhtml", "html");
|
||
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 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;
|
||
/* うまく動いていない場合はこちらに戻してください
|
||
doc = doc || window.content.document;
|
||
var htmlFragment = doc.implementation.createDocument(null, 'html', null);
|
||
var range = doc.createRange();
|
||
range.setStartAfter(doc.body);
|
||
htmlFragment.documentElement.appendChild(htmlFragment.importNode(range.createContextualFragment(str), true));
|
||
return htmlFragment;
|
||
*/
|
||
},
|
||
getFirstNodeFromXPath: function(xpath, context) {
|
||
if (!xpath) return null;
|
||
context = context || window.content.document;
|
||
var result = (context.ownerDocument || context).evaluate(xpath, context, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null);
|
||
return result.singleNodeValue || null;
|
||
},
|
||
getNodesFromXPath: function(xpath, context, callback, thisObj) {
|
||
var ret = [];
|
||
if (!xpath) return ret;
|
||
context = context || window.content.document;
|
||
var nodesSnapshot = (context.ownerDocument || context).evaluate(xpath, context, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
|
||
for (let i = 0, l = nodesSnapshot.snapshotLength; i < l; i++) {
|
||
if (typeof callback == 'function') callback.call(thisObj, nodesSnapshot.snapshotItem(i), i);
|
||
ret.push(nodesSnapshot.snapshotItem(i));
|
||
}
|
||
return ret;
|
||
},
|
||
xmlSerialize: function(xml) {
|
||
try {
|
||
return (new XMLSerializer()).serializeToString(xml)
|
||
.replace(/<!--(?:[^-]|-(?!->))*-->/g, '')
|
||
.replace(/<\s*\/?\s*\w+/g, function(all) all.toLowerCase());
|
||
} catch (e) { return '' }
|
||
},
|
||
xmlToDom: function xmlToDom(node, doc, nodes)
|
||
{
|
||
return util.xmlToDom(node, doc, nodes);
|
||
},
|
||
getElementPosition: function(elem) {
|
||
var offsetTrail = elem;
|
||
var offsetLeft = 0;
|
||
var offsetTop = 0;
|
||
while (offsetTrail) {
|
||
offsetLeft += offsetTrail.offsetLeft;
|
||
offsetTop += offsetTrail.offsetTop;
|
||
offsetTrail = offsetTrail.offsetParent;
|
||
}
|
||
offsetTop = offsetTop || null;
|
||
offsetLeft = offsetLeft || null;
|
||
return {top: offsetTop, left: offsetLeft};
|
||
},
|
||
toStyleText: function(style) {
|
||
var result = '';
|
||
for (let name in style) {
|
||
result += name.replace(/[A-Z]/g, function (c) ('-' + c.toLowerCase())) +
|
||
': ' +
|
||
style[name] +
|
||
';\n';
|
||
}
|
||
return result;
|
||
}
|
||
// }}}
|
||
};
|
||
//}}}
|
||
|
||
libly.Request = function() {//{{{
|
||
this.initialize.apply(this, arguments);
|
||
};
|
||
libly.Request.EVENTS = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
|
||
libly.Request.requestCount = 0;
|
||
libly.Request.prototype = {
|
||
initialize: function(url, headers, options) {
|
||
this.url = url;
|
||
this.headers = headers || {};
|
||
this.options = libly.$U.extend({
|
||
asynchronous: true,
|
||
encoding: 'UTF-8'
|
||
}, options || {});
|
||
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('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) {
|
||
setTimeout(event, 10, args);
|
||
} else {
|
||
event(args);
|
||
}
|
||
});
|
||
return true;
|
||
},
|
||
_complete: false,
|
||
_request: function(method) {
|
||
|
||
try {
|
||
libly.Request.requestCount++;
|
||
|
||
this.method = method;
|
||
this.transport = new XMLHttpRequest();
|
||
this.transport.open(method, this.url, this.options.asynchronous, this.options.username, this.options.password);
|
||
|
||
var stateChangeException;
|
||
this.transport.onreadystatechange = libly.$U.bind(this, function () {
|
||
try {
|
||
this._onStateChange();
|
||
} catch (e) {
|
||
stateChangeException = e;
|
||
}
|
||
});
|
||
this.setRequestHeaders();
|
||
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('exception', new libly.Response(this), e)) throw e;
|
||
}
|
||
},
|
||
_onStateChange: function() {
|
||
var readyState = this.transport.readyState;
|
||
if (readyState > 1 && !(readyState == 4 && this._complete))
|
||
this.respondToReadyState(this.transport.readyState);
|
||
},
|
||
getStatus: function() {
|
||
try {
|
||
return this.transport.status || 0;
|
||
} catch (e) { return 0; }
|
||
},
|
||
isSuccess: function() {
|
||
var status = this.getStatus();
|
||
return !status || (status >= 200 && status < 300);
|
||
},
|
||
respondToReadyState: function(readyState) {
|
||
var state = libly.Request.EVENTS[readyState];
|
||
var res = new libly.Response(this);
|
||
|
||
if (state == 'Complete') {
|
||
libly.Request.requestCount--;
|
||
try {
|
||
this._complete = true;
|
||
this.fireEvent(this.isSuccess() ? 'success' : 'failure', res, this.options.asynchronous);
|
||
} catch (e) {
|
||
if (!this.fireEvent('exception', res, e)) throw e;
|
||
}
|
||
}
|
||
},
|
||
setRequestHeaders: function() {
|
||
var headers = {
|
||
'Accept': 'text/javascript, application/javascript, text/html, application/xhtml+xml, application/xml, text/xml, */*;q=0.1'
|
||
};
|
||
|
||
if (this.method == 'POST') {
|
||
headers['Content-type'] = 'application/x-www-form-urlencoded' +
|
||
(this.options.encoding ? '; charset=' + this.options.encoding : '');
|
||
|
||
if (this.transport.overrideMimeType) {
|
||
let year = parseInt((navigator.userAgent.match(/\bGecko\/(\d{4})/) || [0, 2005])[1], 10);
|
||
if (0 < year && year < 2005)
|
||
headers['Connection'] = 'close';
|
||
}
|
||
}
|
||
|
||
for (let key in this.headers)
|
||
if (this.headers.hasOwnProperty(key)) headers[key] = this.headers[key];
|
||
|
||
for (let name in headers)
|
||
this.transport.setRequestHeader(name, headers[name]);
|
||
},
|
||
get: function() {
|
||
this._request('GET');
|
||
},
|
||
post: function() {
|
||
this._request('POST');
|
||
}
|
||
};//}}}
|
||
|
||
libly.Response = function() {//{{{
|
||
this.initialize.apply(this, arguments);
|
||
};
|
||
libly.Response.prototype = {
|
||
initialize: function(req) {
|
||
this.req = req;
|
||
this.transport = req.transport;
|
||
this.isSuccess = req.isSuccess;
|
||
this.readyState = this.transport.readyState;
|
||
|
||
if (this.readyState == 4) {
|
||
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;
|
||
this.htmlFragmentstr = '';
|
||
},
|
||
status: 0,
|
||
statusText: '',
|
||
getStatus: libly.Request.prototype.getStatus,
|
||
getStatusText: function() {
|
||
try {
|
||
return this.transport.statusText || '';
|
||
} catch (e) { return ''; }
|
||
},
|
||
getHTMLDocument: function(xpath, xmlns, ignoreTags, callback, thisObj) {
|
||
if (!this.doc) {
|
||
//if (doc.documentElement.nodeName != 'HTML') {
|
||
// return new DOMParser().parseFromString(str, 'application/xhtml+xml');
|
||
//}
|
||
this.htmlFragmentstr = libly.$U.getHTMLFragment(this.responseText);
|
||
this.htmlStripScriptFragmentstr = libly.$U.stripTags(this.htmlFragmentstr, ignoreTags);
|
||
this.doc = libly.$U.createHTMLDocument(this.htmlStripScriptFragmentstr, xmlns);
|
||
}
|
||
if (!xpath) xpath = '//*';
|
||
return libly.$U.getNodesFromXPath(xpath, this.doc, callback, thisObj);
|
||
}
|
||
};
|
||
//}}}
|
||
|
||
libly.Wedata = function(dbname) { // {{{
|
||
this.initialize.apply(this, arguments);
|
||
};
|
||
libly.Wedata.prototype = {
|
||
initialize: function(dbname) {
|
||
this.HOST_NAME = 'http://wedata.net/';
|
||
this.dbname = dbname;
|
||
this.logger = libly.$U.getLogger('libly.Wedata');
|
||
},
|
||
getItems: function(expire, itemCallback, finalCallback) {
|
||
|
||
var logger = this.logger;
|
||
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()) {
|
||
logger.log('return cache. ');
|
||
cache.forEach(function(item) { if (typeof itemCallback == 'function') itemCallback(item); });
|
||
if (typeof finalCallback == 'function')
|
||
finalCallback(true, cache);
|
||
return;
|
||
}
|
||
|
||
expire = expire || 0;
|
||
|
||
function errDispatcher(msg, cache) {
|
||
if (cache) {
|
||
logger.log('return cache. -> ' + msg);
|
||
cache.forEach(function(item) { if (typeof itemCallback == 'function') itemCallback(item); });
|
||
if (typeof finalCallback == 'function')
|
||
finalCallback(true, cache);
|
||
} else {
|
||
logger.log(msg + ': cache notfound.');
|
||
if (typeof finalCallback == 'function')
|
||
finalCallback(false, msg);
|
||
}
|
||
}
|
||
|
||
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('response is null.', cache);
|
||
return;
|
||
}
|
||
var json = libly.$U.evalJson(text);
|
||
if (!json) {
|
||
errDispatcher('failed eval json.', cache);
|
||
return;
|
||
}
|
||
logger.log('success get wedata.');
|
||
store.set('expire', new Date(new Date().getTime() + expire).toString());
|
||
store.set('data', json);
|
||
store.save();
|
||
json.forEach(function(item) { if (typeof itemCallback == 'function') itemCallback(item); });
|
||
if (typeof finalCallback == 'function')
|
||
finalCallback(true, json);
|
||
}));
|
||
req.addEventListener('failure', function() errDispatcher('onFailure', cache));
|
||
req.addEventListener('exception', function() errDispatcher('onException', cache));
|
||
req.get();
|
||
}
|
||
};
|
||
//}}}
|
||
|
||
//}
|
||
// vim: set fdm=marker sw=4 ts=4 sts=0 et:
|
||
|