aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--_libly.js307
-rw-r--r--notifier.js236
-rw-r--r--notifier/jquery.jgrowl.css87
-rw-r--r--notifier/observer_growl.js120
-rw-r--r--notifier/subject_test.js52
5 files changed, 802 insertions, 0 deletions
diff --git a/_libly.js b/_libly.js
new file mode 100644
index 0000000..13dc034
--- /dev/null
+++ b/_libly.js
@@ -0,0 +1,307 @@
+/**
+ * ==VimperatorPlugin==
+ * @name _libly.js
+ * @description suvene's library
+ * @description-ja 適当なライブラリっぽいものたち
+ * @author suVene suvene@zeromemory.info
+ * @version 0.1.0
+ * @minVersion 1.2
+ * @maxVersion 2.0pre
+ * Last Change: 07-Dec-2008.
+ * ==/VimperatorPlugin==
+ *
+ * HEAD COMMENT {{{
+ * }}}
+ */
+if (!liberator.plugins.libly) {
+
+liberator.plugins.libly = {};
+var lib = liberator.plugins.libly;
+
+lib.$U = {//{{{
+ getLogger: function(prefix) {
+ return new function() {
+ this.log = function(msg, level) {
+ if (typeof msg == 'object') msg = util.objectToString(msg);
+ liberator.log(lib.$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);
+ };
+ }
+ },
+ extend: function(dst, src) {
+ for (let prop in src)
+ dst[prop] = src[prop];
+ return dst;
+ },
+ A: function(hash, iter) {
+ var ret = [];
+ for each (let item in hash) ret.push(item);
+ return ret;
+ },
+ bind: function(obj, func) {
+ return function() {
+ return func.apply(obj, arguments);
+ }
+ },
+ stripTags: function(str, tags) {
+ var ignoreTags = [].concat(tags);
+ ignoreTags = '(?:' + ignoreTags.join('|') + ')';
+ return str.replace(new RegExp('<' + ignoreTags + '(?:[ \\t\\n\\r][^>]*|/)?>([\\S\\s]*?)<\/' + ignoreTags + '[ \\t\\r\\n]*>', 'ig'), '');
+ },
+ eval: function(text) {
+ var fnc = window.eval;
+ var sandbox;
+ try {
+ sandbox = new Components.utils.Sandbox(window);
+ if (Components.utils.evalInSandbox('true', sandbox) === true) {
+ fnc = function(text) { return Components.utils.evalInSandbox(text, sandbox); };
+ }
+ } catch (e) { $U.log('warning: multi_requester.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; }
+ },
+ getSelectedString: function() {
+ return (new XPCNativeWrapper(window.content.window)).getSelection().toString();
+ },
+ pathToURL: function(path) {
+ if (/^https?:\/\//.test(path)) return path;
+ var link = document.createElement('a');
+ link.href= path;
+ return link.href;
+ },
+ dateFormat: function(dtm, fmt) {
+ var y = dtm.getFullYear();
+ var M = dtm.getMonth() + 1;
+ var d = dtm.getDay();
+ var h = dtm.getHours();
+ var m = dtm.getMinutes();
+ var s = dtm.getSeconds();
+
+ if (M < 10) M = '0' + M;
+ if (d < 10) d = '0' + d;
+ if (h < 10) h = '0' + h;
+ if (m < 10) m = '0' + m;
+ if (s < 10) s = '0' + s;
+ return y + '/' + M + '/' + d + ' ' + h + ':' + m + ':' + s;
+ },
+ readDirectory: function(path, filter, func) {
+ var d = io.getFile(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);
+ }
+ }
+ },
+};
+//}}}
+
+lib.Request = function() {//{{{
+ this.initialize.apply(this, arguments);
+};
+lib.Request.EVENTS = ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
+lib.Request.requestCount = 0;
+lib.Request.prototype = {
+ initialize: function(url, headers, options) {
+ this.url = url;
+ this.headers = headers || {};
+ this.options = lib.$U.extend({
+ asynchronous: true,
+ encoding: 'UTF-8'
+ }, options || {});
+ this.observers = {};
+ },
+ addEventListener: function(name, func) {
+ try {
+ if (typeof this.observers[name] == 'undefined') this.observers[name] = [];
+ this.observers[name].push(func);
+ } catch (e) {
+ if (!this.fireEvent('onException', e)) throw e;
+ }
+ },
+ fireEvent: function(name, args, asynchronous) {
+ 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 {
+ lib.Request.requestCount++;
+
+ this.transport = new XMLHttpRequest();
+ this.transport.open(method, this.url, this.options.asynchronous);
+
+ this.transport.onreadystatechange = lib.$U.bind(this, this._onStateChange);
+ this.setRequestHeaders();
+ this.transport.overrideMimeType('text/html; charset=' + this.options.encoding);
+
+ this.body = this.method == 'POST' ? this.options.postBody : null;
+
+ this.transport.send(this.body);
+
+ // 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', e, this.options.asynchronous)) 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() {
+ return !status || (status >= 200 && status < 300);
+ },
+ respondToReadyState: function(readyState) {
+ var state = lib.Request.EVENTS[readyState];
+ var res = new lib.Response(this);
+
+ if (state == 'Complete') {
+ lib.Request.requestCount--;
+ try {
+ this._complete = true;
+ this.fireEvent('on' + (this.isSuccess() ? 'Success' : 'Failure'), res, this.options.asynchronous);
+ } catch (e) {
+ if (!this.fireEvent('onException', e, this.options.asynchronous)) 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');
+ }
+};//}}}
+
+lib.Response = function() {//{{{
+ this.initialize.apply(this, arguments);
+};
+lib.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.doc = null;
+ this.htmlFragmentstr = '';
+ },
+ status: 0,
+ statusText: '',
+ getStatus: lib.Request.prototype.getStatus,
+ getStatusText: function() {
+ try {
+ return this.transport.statusText || '';
+ } catch (e) { return ''; }
+ },
+ getHTMLDocument: function(xpath, xmlns) {
+ if (!this.doc) {
+ this.htmlFragmentstr = this.responseText.replace(/^[\s\S]*?<html(?:[ \t\n\r][^>]*)?>|<\/html[ \t\r\n]*>[\S\s]*$/ig, '').replace(/[\r\n]+/g, ' ');
+ let ignoreTags = ['script'];
+ if (this.req.options.siteinfo.ignoreTags) {
+ ignoreTags.concat(this.req.options.siteinfo.ignoreTags.split(','));
+ }
+ this.htmlStripScriptFragmentstr = lib.$U.stripTags(this.htmlFragmentstr, 'script');
+ this.doc = this._createHTMLDocument(this.htmlStripScriptFragmentstr, xmlns);
+ }
+
+ var ret = this.doc;
+ if (xpath) {
+ ret = this.getNodeFromXPath(xpath, this.doc);
+ }
+ return ret;
+ },
+ _createHTMLDocument: function(str) {
+ var htmlFragment = document.implementation.createDocument(null, 'html', null);
+ var range = document.createRange();
+ range.setStartAfter(window.content.document.body);
+ htmlFragment.documentElement.appendChild(htmlFragment.importNode(range.createContextualFragment(str), true));
+ return htmlFragment;
+ },
+ getNodeFromXPath: function(xpath, doc, parentNode) {
+ if (!xpath || !doc) return doc;
+ var node = doc || document;
+ var nodesSnapshot = (node.ownerDocument || node).evaluate(xpath, node, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
+
+ if (nodesSnapshot.snapshotLength == 0) return parentNode;
+ parentNode = parentNode || document.createElementNS(null, 'div');
+ for (let i = 0, l = nodesSnapshot.snapshotLength; i < l; parentNode.appendChild(nodesSnapshot.snapshotItem(i++)));
+ return parentNode;
+ }
+};
+//}}}
+
+}
+// vim: set fdm=marker sw=4 ts=4 sts=0 et:
+
diff --git a/notifier.js b/notifier.js
new file mode 100644
index 0000000..9269ed4
--- /dev/null
+++ b/notifier.js
@@ -0,0 +1,236 @@
+/**
+ * ==VimperatorPlugin==
+ * @name notifier.js
+ * @description notice of change framework.
+ * @description-ja 変更通知フレームワーク。
+ * @author suVene suvene@zeromemory.info
+ * @version 0.1.0
+ * @minVersion 2.0pre
+ * @maxVersion 2.0pre
+ * Last Change: 07-Dec-2008.
+ * ==/VimperatorPlugin==
+ *
+ * HEAD COMMENT {{{
+ * }}}
+ */
+(function() {
+if (!liberator.plugins.libly) {
+ liberator.log('notifier: needs _libly.js');
+ return;
+}
+
+if (liberator.plugins.notifier && liberator.plugins.notifier._self) {
+ liberator.plugins.notifier._self.stop(function() { liberator.plugins.notifier._self = bootstrap(); });
+} else {
+ liberator.plugins.notifier = {};
+ liberator.plugins.notifier._self = bootstrap();
+}
+
+function bootstrap() {
+
+ var lib = liberator.plugins.libly;
+ var $U = lib.$U;
+ var logger = $U.getLogger('notifier');
+
+ var Loader = function() {//{{{
+ this.initialize.apply(this, arguments);
+ };
+ Loader.prototype = {
+ initialize: function(name, registerHook) {
+ liberator.plugins.notifier[name] = this;
+ this.name = name;
+ this.plugins = [];
+ this.registerHook = registerHook;
+ this.load(name);
+ },
+ load: function(name) {
+ io.getRuntimeDirectories('plugin/notifier').forEach(function(dir) {
+ $U.readDirectory(io.expandPath(dir.path), '^' + name, function(f) {
+ try {
+ io.source(f.path, true)
+ logger.log('plugin load success: ' + f.leafName);
+ } catch (e) {
+ logger.log('plugin load failed: ' + f.leafName);
+ }
+ });
+ });
+ },
+ register: function(plugin) {
+ this.plugins.push(this.registerHook(plugin));
+ },
+ unregister: function(plugin) {
+ var ret = [];
+ this.plugins.forEach(function(p) { if (p != plugin) ret.push(p); });
+ this.plugins = ret;
+ },
+ getPlugins: function() {
+ return this.plugins;
+ }
+ };
+ //}}}
+
+ var Message = function() {//{{{
+ this.initialize.apply(this, arguments);
+ };
+ Message.prototype = {
+ initialize: function(title, message, options) {
+ try {
+ if (typeof title == 'undefined' || title == null) throw 'title is undefined.';
+ if (typeof message == 'undefined' || message == null) throw 'message is undefined.';
+ this.title = title;
+ this.message = message;
+ this.options = options;
+ } catch (e) {
+ logger.log('Message.initialize error: ' + e);
+ throw e;
+ }
+ }
+ };//}}}
+
+ var Observer = function() {//{{{
+ this.__initialize__.apply(this, arguments);
+ };
+ Observer.prototype = {
+ __initialize__: function(args) {
+ $U.extend(this, args);
+ if (typeof this.initialize == 'function') this.initialize();
+ }
+ };//}}}
+
+ var Subject = function() {//{{{
+ this.__initialize__.apply(this, arguments);
+ };
+ Subject.prototype = {
+ __initialize__: function(args) {
+ this.isActive = false;
+ this.observers = [];
+ this.interval = 0;
+ //if (this.interval < 60) this.interval = 60;
+ this.__nextTime = new Date();
+ $U.extend(this, args);
+ if (typeof this.initialize == 'function') this.initialize();
+ },
+ attach: function(observer) {
+ this.observers.push(observer);
+ },
+ notify: function(message) {
+ if (!message) return;
+ this.observers.forEach(function(o) {
+ if (!o || typeof o.update != 'function') return;
+ try {
+ o.update(message);
+ } catch (e) {
+ logger.log(e);
+ }
+ });
+ },
+ check: function() { throw 'needs override.' }
+ };//}}}
+
+ var Notifier = function() {//{{{
+ this.initialize.apply(this, arguments);
+ };
+ Notifier.prototype = {
+ initialize: function(args) {//{{{
+ this.id = (new Date()).getTime();
+ this.observers;
+ this.subjects;
+ this.timer = false;
+ this.finallycallback;
+ this.isBusy = false;
+ },//}}}
+ setup: function() {//{{{
+
+ if (this.isBusy) {
+ logger.log('bussy.' + this.id);
+ return;
+ }
+
+ this.isBusy = true;
+
+ commands.addUserCommand(['notifierstart'], 'start the notifier',
+ $U.bind(this, function(args) { this.start() }), null, true
+ );
+ commands.addUserCommand(['notifierrestart'], 'restart the notifier',
+ $U.bind(this, function(args) { this.stop($U.bind(this, function() { this.start() })) }),
+ null, true
+ );
+ commands.addUserCommand(['notifierstop'], 'stop the notifier',
+ $U.bind(this, function(args) { this.stop() }), null, true
+ );
+
+ liberator.plugins.notifier.lib = lib;
+ liberator.plugins.notifier.Message = Message;
+
+ this.observers = new Loader('observer', function(args) new Observer(args));
+ this.subjects = new Loader('subject', function(args) new Subject(args));
+
+ this.observers.getPlugins().forEach($U.bind(this, function(o) {
+ this.subjects.getPlugins().forEach(function(s) s.attach(o));
+ }));
+
+ this.isBusy = false;
+ },//}}}
+ start: function() {//{{{
+
+ if (this.timer) {
+ logger.log('already running.' + this.id);
+ return;
+ }
+
+ if (this.isBusy) {
+ logger.log('bussy.' + this.id);
+ return;
+ }
+
+ var start = $U.dateFormat(new Date());
+ setTimeout($U.bind(this, function() {
+ logger.echo('notifier[' + this.id + '] running at ' + start, commandline.force_singleline);
+ this.timer = true;
+ while (this.timer) { //{{{
+ liberator.dump('window:' + window.content.window);
+ this.subjects.getPlugins().forEach(function(s) {
+ let now = new Date();
+ if (!s.__nextTime) s.nexttime = now;
+ if (s.interval > 0 && !s.isActive && s.__nextTime <= now) {
+ setTimeout(function() {
+ let start = (new Date()).getTime();
+ s.isActive = true;
+ if (typeof s.check == 'function')
+ try { s.check(); } catch (e) { logger.log('subject.check error: ' + e) }
+ let stop = (new Date()).getTime();
+ let elapse = (stop - start);
+ s.isActive = false;
+ s.__nextTime = new Date(s.__nextTime.getTime() + s.interval * 1000);
+ if (s.__nextTime < now) s.__nextTime = now;
+ }, 10);
+ }
+ });
+ liberator.sleep(3 * 1000);
+ }//}}}
+ if (typeof this.finallycallback == 'function') this.finallycallback();
+ logger.echo('notifier[' + this.id + '] stoped.(' + start + ')', commandline.force_singleline);
+ }), 10);
+
+ logger.log('start end');
+ },//}}}
+ stop: function(finallycallback) {//{{{
+ if (!this.timer) {
+ logger.log('not running.');
+ if (typeof finallycallback == 'function') finallycallback();
+ return;
+ }
+ this.finallycallback = finallycallback;
+ this.timer = false;
+ }//}}}
+ };//}}}
+
+ var instance = new Notifier();
+ instance.setup();
+ instance.start();
+ return instance;
+};
+
+})();
+// vim: set fdm=marker sw=4 ts=4 sts=0 et:
+
diff --git a/notifier/jquery.jgrowl.css b/notifier/jquery.jgrowl.css
new file mode 100644
index 0000000..5cbd9ed
--- /dev/null
+++ b/notifier/jquery.jgrowl.css
@@ -0,0 +1,87 @@
+
+div.observer_growl {
+ padding: 10px;
+ z-index: 9999;
+}
+
+/** Normal Style Positions **/
+body > div.observer_growl {
+ position: fixed;
+}
+
+body > div.observer_growl.top-left {
+ left: 0px;
+ top: 0px;
+}
+
+body > div.observer_growl.top-right {
+ right: 0px;
+ top: 0px;
+}
+
+body > div.observer_growl.bottom-left {
+ left: 0px;
+ bottom: 0px;
+}
+
+body > div.observer_growl.bottom-right {
+ right: 0px;
+ bottom: 0px;
+}
+
+body > div.observer_growl.center {
+ top: 0px;
+ width: 50%;
+ left: 25%;
+}
+
+/** Cross Browser Styling **/
+div.center div.observer_growl_notification, div.center div.observer_growl-closer {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+div.observer_growl div.observer_growl_notification, div.observer_growl div.observer_growl-closer {
+ background-color: #000;
+ color: #fff;
+ opacity: .85;
+ filter: alpha(opacity = 85);
+ zoom: 1;
+ width: 235px;
+ padding: 10px;
+ margin-top: 5px;
+ margin-bottom: 5px;
+ font-family: Tahoma, Arial, Helvetica, sans-serif;
+ font-size: 12px;
+ text-align: left;
+ display: none;
+ -moz-border-radius: 5px;
+ -webkit-border-radius: 5px;
+}
+
+div.observer_growl div.observer_growl_notification {
+ min-height: 40px;
+}
+
+div.observer_growl div.observer_growl_notification div.header {
+ font-weight: bold;
+ font-size: 10px;
+}
+
+div.observer_growl div.observer_growl_notification div.close {
+ float: right;
+ font-weight: bold;
+ font-size: 12px;
+ cursor: pointer;
+}
+
+div.observer_growl div.observer_growl-closer {
+ height: 15px;
+ padding-top: 4px;
+ padding-bottom: 4px;
+ cursor: pointer;
+ font-size: 11px;
+ font-weight: bold;
+ text-align: center;
+}
+
diff --git a/notifier/observer_growl.js b/notifier/observer_growl.js
new file mode 100644
index 0000000..b6f1d96
--- /dev/null
+++ b/notifier/observer_growl.js
@@ -0,0 +1,120 @@
+/**
+ * notifier.js plugin observer
+ * @name observer_growl.js
+ * @description growl when notified.
+ * @description-ja Growl風通知。
+ * @author suVene suvene@zeromemory.info
+ * @version 0.1.0
+ * Last Change: 07-Dec-2008.
+ *
+ * use JQuery
+ * http://jquery.com/
+ * use JGrowl
+ * http://stanlemon.net/projects/jgrowl.html
+ */
+(function() {
+
+var notifier = liberator.plugins.notifier;
+if (!notifier) return;
+
+var lib = notifier.lib;
+var $U = lib.$U;
+var logger = $U.getLogger('observer_growl');
+
+var Growl = function() {//{{{
+ this.initialize.apply(this, arguments);
+}
+Growl.prototype = {
+ defaults: {
+ life: 3000
+ },
+ initialize: function(dom, container) {
+ this.dom = dom;
+ this.container = container;
+ this.created = new Date();
+ this.life = this.defaults.life;
+ dom.childNodes[0].addEventListener("click", $U.bind(this, this.remove), false);
+ },
+ remove: function() {
+ this.container.removeChild(this.dom);
+ },
+
+}//}}}
+
+notifier.observer.register({
+ initialize: function () {
+ logger.log('initialize');
+ this.count = 1;
+
+ io.getRuntimeDirectories('').forEach(function(dir) {
+ let path = io.expandPath(dir.path + '/plugin/notifier');
+ $U.readDirectory(path, '^jquery' , function(f) {
+ try {
+ io.source(f.path, true)
+ logger.log('load success: ' + f.leafName);
+ } catch (e) {
+ logger.log('load failed: ' + f.leafName);
+ }
+ });
+ });
+ },
+ update: function(message) {
+ logger.log('update:' + this.count);
+
+ var doc = window.content.document;
+ var container = doc.getElementById("observer_growl");
+ if (!container) {
+ doc.body.appendChild(util.xmlToDom(<div id="observer_growl" class="observer_growl top-right" />, doc));
+ container = doc.getElementById("observer_growl");
+ }
+
+ this.createPopup(doc, message, container);
+ container.appendChild(this.createPopup(doc, message, container));
+
+ if (container.childNodes.length == 1) {
+ var interval = setInterval($U.bind(this, this.checkStatus), 1000);
+ container.__interval__ = interval;
+ }
+
+ this.count++;
+ },
+ createPopup: function(doc, message, nodes) {
+ var dom;
+ var html =
+ <div class="observer_growl_notification" style="display: block;">
+ <div class="close">&#215;</div>
+ <div class="header">{util.escapeHTML(this.count + ': ' + message.title)}</div>
+ <div class="message">{util.escapeHTML(message.message)}</div>
+ </div>;
+ dom = util.xmlToDom(html, doc, nodes);
+ dom.__data__ = new Growl(dom, nodes);
+
+ let count = this.count;
+ return dom;
+ },
+ checkStatus: function() {
+
+ var doc = window.content.document;
+ var container = doc.getElementById("observer_growl");
+ if (!container) return;
+
+ var removeNodes = [];
+ for (let i = 0, len = container.childNodes.length; i < len; i++) {
+ let item = container.childNodes[i];
+ let growl = item.__data__;
+ if (growl && growl.created &&
+ growl.created.getTime() + growl.life < (new Date()).getTime()) {
+ removeNodes.push(item);
+ }
+ }
+ removeNodes.forEach(function(n) container.removeChild(n));
+
+ if (container.childNodes.length == 0)
+ clearInterval(container.__interval__);
+
+ }
+});
+
+})();
+// vim: set fdm=marker sw=4 ts=4 sts=0 et:
+
diff --git a/notifier/subject_test.js b/notifier/subject_test.js
new file mode 100644
index 0000000..b5689c6
--- /dev/null
+++ b/notifier/subject_test.js
@@ -0,0 +1,52 @@
+/**
+ * notifier.js plugin subject
+ * @name subject_test.js
+ * @description notify if ...
+ * @description-ja ... の時ポップアップ通知。
+ * @author suVene suvene@zeromemory.info
+ * @version 0.1.0
+ * Last Change: 07-Dec-2008.
+ */
+(function() {
+
+var notifier = liberator.plugins.notifier;
+if (!notifier) return;
+
+var lib = notifier.lib;
+var $U = lib.$U;
+var logger = $U.getLogger('subject_test');
+
+notifier.subject.register({
+ interval: 3,
+ initialize: function() {
+ logger.log('initialize');
+ this.count = 0;
+ },
+ check: function() {
+ this.count++;
+ logger.log('check');
+ var req = new lib.Request(
+ 'http://localhost:8080/index.html',
+ null, // headers {}
+ {
+ encode: 'shift_jis'
+ }
+ );
+ req.addEventListener('onSuccess', $U.bind(this, function(res) {
+ var text = res.responseText;
+ logger.log('success!! ');
+ var message = new notifier.Message('TEST', text);
+ this.notify(message);
+
+ if (this.count == 5) {
+ notifier.subject.unregister(this);
+ this.count = 0;
+ }
+ }));
+ req.get();
+ }
+});
+
+})();
+// vim: set fdm=marker sw=4 ts=4 sts=0 et:
+