host= "http://" + location.host + "/"; baseurl = host + "blog/"; listurl = host + "list.txt"; var ajax_filter = function(t){return t}; if(navigator.appVersion.indexOf( "KHTML" ) > -1){ ajax_filter = function(t){ var esc = escape(t); return(esc.indexOf("%u") < 0 && esc.indexOf("%") > -1) ? decodeURIComponent(esc) : t } } function init(){ sx = new DOMRef("search"); doc = document; if(!XMLHttpRequest) return; var req = new XMLHttpRequest; req.open("GET",listurl,true); req.onload = function(){ var text = this.responseText; text = ajax_filter(text); entry_list = text.splitLine().compact().map(function(value){ var tmp = value.split("<>"); var item = { entry : tmp[0], title : tmp[1], date : tmp[2] }; item.toString = item_formatter; return item; }); }.bindThis(req); req.send(null); sx.ae({ focus : show_menu, click : show_menu, keyup : entry_search, keydown : keydown, keypress : keypress, mousewheel : function(e){ show_menu(e); e.keyCode = e.get("wheelDelta") < 0 ? KEYCODE.DOWN : KEYCODE.UP; e.stop(); keydown(e) } }); new DOMRef(document.body).ae({ click : hide_menu }); } // CONST KEYCODE = { UP : 38, DOWN : 40 } // Global var Global = { hilight : 0, query : "" } var max = 21; var col = 3; // 1行の表示件数 var entry_list = []; var last_result = []; var Seek = []; var st_window = 0; var sr = 0; String.prototype.splitLine = function(){ return this.split(/\r\n|\r|\n/) } String.prototype.include = function(str){ return str.isRegExp ? str.test(this) : this.indexOf(str) != -1 } String.prototype.element = String.prototype.el = function(){ return document.getElementById(this) } /* 複数回呼ばれても指定ミリ秒待ってから1回実行するように変形 */ Function.prototype.forceWait = function(wait){ var self = this; return function(){ var now = new Date().getTime(); var nfunc = arguments.callee; if(!nfunc.lastcall){ nfunc.lastcall = now; nfunc.reserve = []; } nfunc.reserve.shift(); nfunc.reserve.push(self.applied(this,arguments)); if(now - nfunc.lastcall > wait){ nfunc.reserve.shift().later(wait/2)(); nfunc.lastcall = now; }else{ (function(){ if(nfunc.reserve.length){ nfunc.reserve.shift().later(wait/2)(); nfunc.lastcall = now; } }).later(wait/2)(); } } } var Text = {}; Text.QuickTemplate = function(){ this.initialize.apply(this, arguments); return this; }; // static function Text.QuickTemplate.extend({ clear_cache : function(){ Text.QuickTemplate.prototype.cache = {}; return this; } }); Text.QuickTemplate.prototype = { initialize : function(){ this.params = {}; this.tmpl = this.get(arguments[0]) || arguments[0]; this.delimiters = ["\\{\\{", "\\}\\}"]; if(arguments[1]) this.extend(arguments[1]); var str = this.delimiters[0]+"(.*?)"+this.delimiters[1]; this.sep = new RegExp(str,"g"); }, cache : {}, clear_cache : function(){ Text.QuickTemplate.prototype.cache = {}; return this; }, param : function(){ var self = this; arguments.toArray().forEach(function(v,i){ self.params.extend(v) }); return this; }, clear : function(){ this.params = {}; return this; }, get : function(id){ var self = this; if(self.cache[id]){ return self.cache[id] } var d = document.getElementById("tmpl_"+id); if(!d){return null} var tmp = d.innerHTML; self.cache[id] = tmp.replace(/(\r|\n|\t)*?(\r|\n|\t)*/g,""); return self.cache[id] }, set : function(id,value){ var self = this; self.cache[id] = value; return this; }, compile : function(){ var str = ""+this.delimiters[0]+"(.*?)"+this.delimiters[1]+""; var sep = new RegExp(str,"g"); var buf = []; var builder = function(){ var param = arguments.callee.param; arguments.toArray().forEach(function(v,i){ param.extend(v) }); return buf.join("") }; builder.param = {}; var last = 0; this.tmpl.replace(sep,function(){ var a = arguments; buf.push(a[3].slice(last,a[2])); last = a[2] + a[0].length; var n = []; n.toString = function(){ return builder.param[a[1]] ? builder.param[a[1]].toString ? builder.param[a[1]].toString() :"" :"" } buf.push(n); return arguments[1]; }); buf.push(this.tmpl.slice(last)); return builder; }, fill : function(){ var self = this; var buf = this.tmpl; var arg = arguments; var sep = this.sep; arg.toArray().forEach(function(v,i){ self.params.extend(v) }); return buf.replace(sep,function(){ return (undefined == self.params[arguments[1]])?"":self.params[arguments[1]]; }); }, fill_expr : function(){ var self = this; var buf = this.tmpl; var arg = arguments; var sep = this.sep; arg.toArray().forEach(function(v,i){ self.params.extend(v) }); return buf.replace(sep,function(){ var match = arguments[1]; var pair = match.split("="); if(pair.length == 2){ self.params[pair[0]] = pair[1]; return ""; } var p = self.params[arguments[1]]; if(typeof p == "function"){ return p.call(self.params) } return (undefined == p)?"":p; }); }, toString : function(){ return this.fill(); } }; var QT = Text.QuickTemplate; String.prototype.fill = function(){ var tmp = new QT(this); return tmp.fill.apply(tmp,arguments); }; String.prototype.fill_expr = function(){ var tmp = new QT(this); return tmp.fill_expr.apply(tmp,arguments); }; Array.prototype.iterator = function(){ return new Iterator(this) } function Iterator(ary,offset){ this.offset = offset || 0; } Iterator.prototype = { next : function(){ this.offset++; return this.result[this.offset] }, hasNext : function(){ return (this.result[this.offset+1]) ? true : false } }; Array.prototype.rangeseek = function(offset,len){ return new RangeSeek(this,offset,len); } // 範囲付きのイテレータ // 配列、開始位置、長さ function RangeSeek(ary,offset,len){ this._array = ary; this._offset = offset; this._length = len; } RangeSeek.prototype = { next : function(){ return this._array[this._offset++ + this._length]; }, prev : function(){ return this._offset == 0 ? false : this._array[--this._offset] }, hasNext : function(){ return this._array.own(this._offset + this._length) }, hasPrev : function(){ return this._offset == 0 ? false : this._array.own(this._offset-1); }, getOffset : function(){ return this._offset } } /* XMLHttpRequest風検索ルーチン methodは将来的に拡張予定 */ function SearchRequest(){} SearchRequest.prototype = { open : function(method,data,async,freq){ this.source = data; this.async = async; this.freq = freq || 50; this.offset = 0; this.__result__ = []; this.onhit = function(){}; this.onprogress = function(){}; this.oncomplete = function(){}; this.onreadystatechange = function(){}; }, addCallback : function(type ,func){ this["on"+type] = func }, abort : function(){ if(this.timer){ this.timer.cancel(); } }, result : function(){ return this.__result__ }, __request__ : function(count){ var self = this; var target = this.source.slice(this.offset,this.offset+count); target.forEach(function(v,i){ if(this.query.isFunction){ this.query(v) && this.__result__.push(v) && this.onhit(); } }.bindThis(this)); this.onprogress(); if(target.length < count){ this.oncomplete(); }else{ this.offset+=count; this.async ? this.timer = this.__request__.later(this.freq).apply(this,arguments): this.__request__(count); } }, send : function(query,count){ var self = this; this.query = query; this.__request__(count); } }; Object.prototype.search = function(query){ var hit = 0; this.each(function(value,key){ if (hit) return; if (!value) return; if (!value.isString) return; hit = query[key] ? value.include(query[key]) ? 1 : 0 : 0 }); return hit ? hit : 0; } // bold String.prototype.hilight = function(q){ return this.replace(q,function(){return ""+arguments[0]+""}) } function update_scroll(){ Seek.hasNext() ? sr.delClass("cant_down") : sr.addClass("cant_down"); Seek.hasPrev() ? sr.delClass("cant_up") : sr.addClass("cant_up"); } function update_status(text){ if(!st_window){ var div = doc.createElement("div"); var d = new DOMRef(div); d.ss({ position : "absolute", fontSize : "14px", padding : "1px", paddingLeft : "1em", height : "16px", right : "10px", top : "10px", border : "1px solid #999", borderBottom : "none", background : "#555", color : "#FFF" }); d.move(sx.gx() , sx.gy() - 19); d.resize((sx.gw() - 4)/3); d.appendTo(doc.body); st_window = d; } st_window.set({className : ""}) st_window.print(text) } function keypress(e){ var kc = e.keyCode; if(kc == KEYCODE.DOWN || kc == KEYCODE.UP){ e.stop(); } } function keydown(e){ var kc = e.keyCode; switch(kc){ case KEYCODE.DOWN : if(!Seek.hasNext()) return "no_more"; var da = new DOMArray("result_body".el().getElementsByTagName("LI")); da.shift(); da.push({ li : "{{item}}
".fill({item : Seek.next().join("")}), className : "rows" }); update_scroll(); e.stop(); return case KEYCODE.UP : if(!Seek.hasPrev()) return "no_more"; var da = new DOMArray("result_body".el().getElementsByTagName("LI")); da.pop(); da.unshift({ li : "{{item}}
".fill({item : Seek.prev().join("")}), className : "rows" }); update_scroll() e.stop(); return } } var item = '
{{date}}{{title}}
'; var item_compile = new QT(item).compile(); var item_formatter = function(){ if(Global.hilight){ return item_compile( this.map(function(val,key){ return (key == "title" || key == "date") ? val.hilight(Global.query) : val }), {width:(99.9/col)} ) }else{ return item_compile(this,{width:(99.9/col)}) } } var tmpl = '
  • {{item}}
  • '; var format_list = new QT(tmpl).compile(); var before = ""; var read_up = "
    "; function update_list(){ sr.print( read_up , last_result.slice(0,max/col).map(function(v,i){ return format_list({item : v.join("")}) }).join("") ,read_down ); Seek = last_result.rangeseek(0,max/col); attach_event(); update_scroll(); } function entry_search(e){ if(!arguments.callee.req){ var req = arguments.callee.req = new SearchRequest; }else{ var req = arguments.callee.req; } var q = "search".el().value; if(q == before){return} before = q; q = new RegExp(roma2.fuzzy(q),"i"); window.status = q; var query = { date : q, title : q } if(!before){ Global.hilight = 0; last_result = entry_list.splitPer(col); update_list(); return } req.abort(); req.open("GET", entry_list, true,10); req.addCallback( "progress", function(){ var total = Math.ceil(10*req.offset/req.source.length); var hit = Math.ceil(total*req.__result__.length/req.offset); update_status( [req.source.length,"件中 ",req.__result__.length , "件ヒット ", "", "■".x(hit),"", "■".x(total-hit),"" ].join("") ) } ); req.oncomplete = function(){ Global.hilight = 1; Global.query = q; var hit = Math.ceil(10*req.__result__.length/req.source.length); update_status( [req.source.length,"件中 ",req.__result__.length , "件ヒット " , "", "■".x(hit) , "", "■".x(10-hit),"" ].join("") ) last_result = req.result().splitPer(col); update_list(); } req.send( function(v){ var hit = q.test(v.date) || q.test(v.title); return hit; }, 10 ); } function show_menu(e){ e.stop(); if(sr) return ; sx.ss({color : "#444"}); var div = doc.createElement("div"); var d = new DOMRef(div); sr = d; d.set({ id : "search_result", className : "drop" }); d.ss({position : "absolute"}); d.move(sx.gx() , sx.gy() + sx.gh() - 1); d.resize(sx.gw() - 2); d.appendTo(doc.body); sx.sv(""); sr.ae({ click : function(e){e.stopEvent()}, dblclick : hide_menu, mousewheel : function(e){ e.keyCode = e.get("wheelDelta") < 0 ? KEYCODE.DOWN : KEYCODE.UP; e.stop(); keydown(e) } }); last_result = entry_list.splitPer(col); update_list(); } function attach_event(){ var scroll; new DOMRef("down").ae({ mouseover : function(e){ e.keyCode = KEYCODE.DOWN; scroll = function(){if(keydown(e) == "no_more") arguments.callee.kill()}; scroll.bg(100); }, mouseout : function(e){ scroll.kill(); } }) new DOMRef("up").ae({ mouseover : function(e){ e.keyCode = KEYCODE.UP; scroll = function(){if(keydown(e) == "no_more") arguments.callee.kill()}; scroll.bg(100); }, mouseout : function(e){ scroll.kill(); } }) } function hide_menu(e){ sr = sr ? sr.remove() : 0; st_window && st_window.set({className : "hidden"}); }