// ==UserScript==
// @name        Hoeditor
// @description simple texteditor & launcher
// @namespace   http://a-h.parfe.jp/einfach/
// @include     *
// @version 0.4
// ==/UserScript==

(function () {

if (self.location.href!=top.location.href) return;

var init = function(){
	layer = new Layer;
	setApp = new GremonApp;
	var editor = new Hoeditor;
	var launcher = new HoeLauncher;
	var search = new HoeSearch;
}


/* from
/*  Prototype JavaScript framework, version 1.5.0_rc0
 *  (c) 2005 Sam Stephenson <sam@conio.net>
 *
 *  Prototype is freely distributable under the terms of an MIT-style license.
 *  For details, see the Prototype web site: http://prototype.conio.net/
 *
/*--------------------------------------------------------------------------*/

var Class = {
  create: function() {
    return function() {
      this.initialize.apply(this, arguments);
    }
  }
}

Object.extend = function(destination, source) {
  for (var property in source) {
    destination[property] = source[property];
  }
  return destination;
}

Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}

Function.prototype.bindAsEventListener = function(object) {
  var __method = this;
  return function(event) {
    return __method.call(object, event || window.event);
  }
}

var $A = Array.from = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0; i < iterable.length; i++)
      results.push(iterable[i]);
    return results;
  }
}

function $() {
  var results = [], element;
  for (var i = 0; i < arguments.length; i++) {
    element = arguments[i];
    if (typeof element == 'string')
      element = document.getElementById(element);
    results.push(Element.extend(element));
  }
  return results.length < 2 ? results[0] : results;
}
document.getElementsByClassName = function(className, parentElement) {
  var children = ($(parentElement) || document.body).getElementsByTagName('*');
  return $A(children).inject([], function(elements, child) {
    if (child.className.match(new RegExp("(^|\\s)" + className + "(\\s|$)")))
      elements.push(Element.extend(child));
    return elements;
  });
}


//if (!window.Element)
  var Element = new Object();

Element.extend = function(element) {
  if (!element) return;
  //if (_nativeExtensions) return element;

  if (!element._extended && element.tagName && element != window) {
    var methods = Element.Methods, cache = Element.extend.cache;
    for (property in methods) {
      var value = methods[property];
      if (typeof value == 'function')
        element[property] = cache.findOrStore(value);
    }
  }

  element._extended = true;
  return element;
}

Element.extend.cache = {
  findOrStore: function(value) {
    return this[value] = this[value] || function() {
      return value.apply(null, [this].concat($A(arguments)));
    }
  }
}

Element.Methods = {
  visible: function(element) {
    return $(element).style.display != 'none';
  },

  toggle: function() {
    for (var i = 0; i < arguments.length; i++) {
      var element = $(arguments[i]);
      Element[Element.visible(element) ? 'hide' : 'show'](element);
    }
  },

  hide: function() {
    for (var i = 0; i < arguments.length; i++) {
      var element = $(arguments[i]);
      element.style.display = 'none';
    }
  },

  show: function() {
    for (var i = 0; i < arguments.length; i++) {
      var element = $(arguments[i]);
      element.style.display = '';
    }
  },

  remove: function(element) {
    element = $(element);
    element.parentNode.removeChild(element);
  },

  update: function(element, html) {
    $(element).innerHTML = html.stripScripts();
    setTimeout(function() {html.evalScripts()}, 10);
  },
  getStyle: function(element, style) {
    element = $(element);
    var value = element.style[style.camelize()];
    if (!value) {
      if (document.defaultView && document.defaultView.getComputedStyle) {
        var css = document.defaultView.getComputedStyle(element, null);
        value = css ? css.getPropertyValue(style) : null;
      } else if (element.currentStyle) {
        value = element.currentStyle[style.camelize()];
      }
    }

    if (window.opera && ['left', 'top', 'right', 'bottom'].include(style))
      if (Element.getStyle(element, 'position') == 'static') value = 'auto';

    return value == 'auto' ? null : value;
  },

  setStyle: function(element, style) {
    element = $(element);
    for (var name in style)
      element.style[name.camelize()] = style[name];
  },

  getOpacity: function(element){  
    var opacity;
    if (opacity = Element.getStyle(element, 'opacity'))  
      return parseFloat(opacity);  
    if (opacity = (Element.getStyle(element, 'filter') || '').match(/alpha\(opacity=(.*)\)/))  
      if(opacity[1]) return parseFloat(opacity[1]) / 100;  
    return 1.0;  
  },

  setOpacity: function(element, value){  
    element= $(element);  
    if (value == 1){
      Element.setStyle(element, { opacity: 
        (/Gecko/.test(navigator.userAgent) && !/Konqueror|Safari|KHTML/.test(navigator.userAgent)) ? 
        0.999999 : null });
      if(/MSIE/.test(navigator.userAgent))  
        Element.setStyle(element, {filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'')});  
    } else {  
      if(value < 0.00001) value = 0;  
      Element.setStyle(element, {opacity: value});
      if(/MSIE/.test(navigator.userAgent))  
       Element.setStyle(element, 
         { filter: Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') +
                   'alpha(opacity='+value*100+')' });  
    }
}  

  
}

Object.extend(Element, Element.Methods);

Object.extend(String.prototype, {
  camelize: function() {
    var oStringList = this.split('-');
    if (oStringList.length == 1) return oStringList[0];

    var camelizedString = this.indexOf('-') == 0
      ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1)
      : oStringList[0];

    for (var i = 1, len = oStringList.length; i < len; i++) {
      var s = oStringList[i];
      camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
    }

    return camelizedString;
  }
});

var $break    = new Object();
var $continue = new Object();

Object.extend(Array.prototype, {
  _each: function(iterator) {

    var iter = 0;
    var len = this.length;
    var i = len % 8;
    if (i>0) do {
        iterator(this[iter++]);
      } while (--i);

    i = parseInt(len >> 3);
    if (i>0) do {
      iterator(this[iter++]);
      iterator(this[iter++]);
      iterator(this[iter++]);
      iterator(this[iter++]);
      iterator(this[iter++]);
      iterator(this[iter++]);
      iterator(this[iter++]);
      iterator(this[iter++]);
    } while (--i);

/*
    for (var i = 0; i < this.length; i++)
      iterator(this[i]);
*/
  },
  each: function(iterator) {
    var index = 0;
    try {
      this._each(function(value) {
        try {
          iterator(value, index++);
        } catch (e) {
          if (e != $continue) throw e;
        }
      });
    } catch (e) {
      if (e != $break) throw e;
    }
  },
  inject: function(memo, iterator) {
    this.each(function(value, index) {
      memo = iterator(memo, value, index);
    });
    return memo;
  }
});

Object.extend(Event, {
  KEY_BACKSPACE: 8,
  KEY_TAB:       9,
  KEY_RETURN:   13,
  KEY_ESC:      27,
  KEY_LEFT:     37,
  KEY_UP:       38,
  KEY_RIGHT:    39,
  KEY_DOWN:     40,
  KEY_DELETE:   46,

  stop: function(event) {
    if (event.preventDefault) {
      event.preventDefault();
      event.stopPropagation();
    } else {
      event.returnValue = false;
      event.cancelBubble = true;
    }
  },

  _observeAndCache: function(element, name, observer, useCapture) {
    if (!this.observers) this.observers = [];
    if (element.addEventListener) {
      this.observers.push([element, name, observer, useCapture]);
      element.addEventListener(name, observer, useCapture);
    } else if (element.attachEvent) {
      this.observers.push([element, name, observer, useCapture]);
      element.attachEvent('on' + name, observer);
    }
  },

    observe: function(element, name, observer, useCapture) {
    var element = $(element);
    useCapture = useCapture || false;

    if (name == 'keypress' &&
        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
        || element.attachEvent))
      name = 'keydown';

    this._observeAndCache(element, name, observer, useCapture);
  },

    stopObserving: function(element, name, observer, useCapture) {
    var element = $(element);
    useCapture = useCapture || false;

    if (name == 'keypress' &&
        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
        || element.detachEvent))
      name = 'keydown';

    if (element.removeEventListener) {
      element.removeEventListener(name, observer, useCapture);
    } else if (element.detachEvent) {
      element.detachEvent('on' + name, observer);
    }
  }
});

//from
/*
 hotkey.js
 http://la.ma.la/blog/diary_200511041713.htm
/*
 hotkey.js
  usage :
   var kb = new HotKey;
   kb.add("a",function(){alert("a")});
   kb.add("A",function(){alert("Shift+a")});
*/
function HotKey(element){
	this.target = element || document;
	this._keyfunc = {};
	this.init();

}
HotKey.kc2char = function(kc){
	var between = function(a,b){
		return a <= kc && kc <= b
	}
	var _32_40 = "space pageup pagedown end home left up right down".split(" ");
	var kt = {
		8  : "back",
		9  : "tab"  ,
		13 : "enter",
		16 : "shift",
		17 : "ctrl",
		46 : "delete"
	};
	return (
		between(65,90)  ? String.fromCharCode(kc+32) : // a-z
		between(48,57)  ? String.fromCharCode(kc) :    // 0-9
		between(96,105) ? String.fromCharCode(kc-48) : // num 0-9
		between(32,40)  ? _32_40[kc-32] :
		kt.hasOwnProperty(kc) ? kt[kc] : 
		null
	)
}

HotKey.prototype.ignore = /input|textarea/i;
HotKey.prototype.init = function(){
	var self = this;
	var listener = function(e){
		self.onkeydown.call(self,e)
	};
	if(this.target.addEventListener){
		this.target.addEventListener("keydown", listener, true);
	}else{
		this.target.attachEvent("onkeydown", listener)
	}
}
HotKey.prototype.onkeydown = function(e){
	var tag = (e.target || e.srcElement).tagName;
	if(this.ignore.test(tag)) return;
	var input = HotKey.kc2char(e.keyCode);

	if(e.shiftKey && input.length == 1){
		input = input.toUpperCase()
	}
	if(e.ctrlKey) input = "C" + input;

	if(this._keyfunc.hasOwnProperty(input)){
		this._keyfunc[input].call(this,e)
	}
}
HotKey.prototype.sendKey = function(key){
	this._keyfunc[key] && this._keyfunc[key]()
}
HotKey.prototype.add = function(key,func){
	if(key.constructor == Array){
		for(var i=0;i<key.length;i++)
			this._keyfunc[key[i]] = func;
	}else{
		this._keyfunc[key] = func;
	}
}

/*
Tab Maker
http://a-h.parfe.jp/einfach/archives/2006/1012175043.html
*/

var TabMaker = Class.create()
TabMaker.prototype = {
	initialize: function(tab) {
		this.tabLnegth = gcn(tab).length;
		this.tabName = tab;
	},
	create: function() {
		var menu = new TabIndex(this.tabName);
		for (var i = 0; i < this.tabLnegth; i++) {
			menu.appendTab(new Tab(this.tabName + i, (i==0)));
		}
		menu.setTab();
	}
}

var Tab = Class.create();
Tab.prototype = {
	initialize: function(name, open) {
		this.name = name;
		this.page = name + 'Box';
		this.open = open;
	},
	styleTab: function() {
		if (this.open)
			this.setStyle('visible', '', 'open');
		else
			this.setStyle('hidden', 'absolute', 'close');
		this.open = false;
	},
	setStyle: function(visibility, position, className){
		var page = $(this.page).style;
		var name = $(this.name);
		page.visibility = visibility;
		page.position = position;
		name.className = className;
	}
}

var TabIndex = Class.create();
TabIndex.prototype = {
	initialize : function(tab) {
		this.last = 0;
		this.tabs = new Array();
		this.tabName = tab;
	},
	getTabAt : function(index) {
		return this.tabs[index];
	},
	appendTab : function(tab) {
		this.tabs[this.last] = tab;
		gcn(this.tabName)[this.last].id = tab.name;
		gcn(this.tabName+'Box')[this.last].id = tab.page;
		this.last++;
		var link = document.createElement('a');
		link.innerHTML = $(tab.name).innerHTML;
		link.href = 'javascript:void(0);'
		$(tab.name).innerHTML = '';
		$(tab.name).appendChild(link);
		Event.observe(tab.name, 'click', function(){
			tab.open = true;
			this.setTab();
		}.bind(this), false);
	},
	getLength : function() {
		return this.last;
	},
	each : function(func) {
		for (var i = 0; i < this.getLength(); i++) {
			func(this.getTabAt(i));
		}
	},
	setTab: function() {
		this.each(function(tab) {
				tab.styleTab();
		});
	}
};
function gcn(id){
	return document.getElementsByClassName(id);
}

/*
from
--------------------------------------------------------
glayer.js - (grey out + layer) = glayer
Version 1.0.0 (Update 2006/08/07)

- onozaty (http://www.enjoyxstudy.com)

Released under the Creative Commons License(Attribution 2.1 Japan):
 http://creativecommons.org/licenses/by/2.1/jp/

depends on prototype.js(http://prototype.conio.net/)

For details, see the web site:
 http://www.enjoyxstudy.com/javascript/glayer/

--------------------------------------------------------
*/

var Layer = Class.create();
Layer.prototype = {
  initialize: function(){
  },
  show: function(element) {

    var position = Element.getStyle(element, 'position');
    var opacity  = Element.getOpacity(element);

    //if (position != 'fixed') {
	if ($(element).id == '__hoeditor_edit' || $(element).id == '__hoe_search') {
      var size = this.getWindowSize();
      $(element).style.width  = size[0] - 90 + 'px';
      $(element).style.height = size[1] - 150 + 'px';
	}else if ($(element).id == '__hoe_launcher') {
      var size = this.getWindowSize();
      $(element).style.left  = size[0]/2 - 250 + 'px';
      $(element).style.top = size[1]/2 - 50 + 'px';
	}
    Element.show(element);
  },
  hide: function(element) {
      if(!$(element)) return;
      Element.hide(element);
  },

  getWindowSize: function() {
    var width;
    var height;

    if (document.compatMode == 'CSS1Compat' && !window.opera) {
      // Strict Mode && Non Opera
      width  = document.documentElement.clientWidth;
      height = document.documentElement.clientHeight;
    } else {
      // other
      width  = document.body.clientWidth;
      height = document.body.clientHeight;
    }

    return [width, height];
  },
  getPageSize: function() {

    var windowSize = this.getWindowSize();

    var width  = windowSize[0];
    var height = windowSize[1];

    if (document.compatMode == 'CSS1Compat') {
      if (document.documentElement.scrollWidth > width) {
        width  = document.documentElement.scrollWidth;
      }
      if (document.documentElement.scrollHeight > height) {
        height = document.documentElement.scrollHeight;
      }
    } else {
      if (document.body.scrollWidth > width) {
        width  = document.body.scrollWidth;
      }
      if (document.body.scrollHeight > height) {
        height = document.body.scrollHeight;
      }
    }

    return [width, height];
  }
}


// from
// XPath, $X function, NSResolver
// http://lowreal.net/logs/2006/03/16/1
//

$X = function (exp, context) {
    if (!context) context = document;
    var resolver = function (prefix) {
        var o = document.createNSResolver(context)(prefix);
        return o ? o : (document.contentType == "text/html") ? "" : "http://www.w3.org/1999/xhtml";
    }
    var exp = document.createExpression(exp, resolver);
    
    var result = exp.evaluate(context, XPathResult.ANY_TYPE, null);
    switch (result.resultType) {
        case XPathResult.STRING_TYPE : return result.stringValue;
        case XPathResult.NUMBER_TYPE : return result.numberValue;
        case XPathResult.BOOLEAN_TYPE: return result.booleanValue;
        case XPathResult.UNORDERED_NODE_ITERATOR_TYPE: {
            result = exp.evaluate(context, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
            var ret = [];
            for (var i = 0, len = result.snapshotLength; i < len ; i++) {
                ret.push(result.snapshotItem(i));
            }
            return ret;
        }
    }
    return null;
}
/*
alert($X("//x:p")); // Array of p elements
alert($X("count(//node())")); // => node number
alert($X("count(//x:body) = 1")); //=> must be true
*/


// Greasemonkey Application

var GremonApp = Class.create();
GremonApp.prototype = {
	initialize: function(tab) {
		Event.observe(document, 'keydown', this.hotkey.bind(this), false);
		Event.observe(unsafeWindow,'resize', this.redraw.bind(this), true);
		this.layerName = '__hoeditor_overlay';
		this.makeOverLayer();
		this._title = document.title;
		this.appList = [];
		this.setStyle();
	},
	make: function(app){
		app.div = setApp.makeLayer(app.name);
		this.addList(app);
		app.setKey();
		app.addStyle();
	},
	addList: function(app){
		this.appList.push(app);
		this.setDefaultStyle(app.name);
	},
	hotkey: function(event){
		if(event.keyCode == 27){ // 'Esc'
			this.appList.each(function(e){
				e.hide();
			});
		}
	},
	makeLayer: function(divName){
		var layer = document.createElement('div');
		layer.id = divName;
		document.body.appendChild(layer);
		layer.style.display = 'none';
		return layer;
	},
	makeOverLayer: function(){
		var overlay = this.makeLayer(this.layerName);
		Event.observe(overlay, 'dblclick', function(){
			this.appList.each(function(e){
				e.hide();
			});
		}.bind(this), false);
	},
	show: function(app){
		layer.show(this.layerName);
		layer.show(app.name);
		document.title = app.mark + setApp._title;
	},
	hide: function(app){
		this.imeOff();
		layer.hide(this.layerName);
		layer.hide(app.name);
		document.title = this._title;
	},
	redraw: function(){
		this.appList.each(function(e){
			if($(e.name).style.display!='none')
				e.show();
		});
	},
	makeKey: function(keys, app){
		var kb = new HotKey;
		keys.each(function(key){
			var cmd = (key[1]!='') ? key[1] : function(){return false};
			var cmd2 = (key[2]!='') ? key[2] : function(){return false};
			kb.add(key[0], function(e){
				(this.isShow(app)) ? cmd(e) : cmd2(e);
			}.bind(this));
		}.bind(this));
	},
	isShow: function(name){
		return $(name).style.display=='none' && $(setApp.layerName).style.display=='none';
	},
	addStyle: function(style){
		GM_addStyle(style);
	},
	setStyle: function(){
		var temp = [
		'#__hoeditor_overlay {',
			'position: fixed!important;',
			'position: absolute;',
			'top: 0;',
			'left: 0;',
			'width: 100%;',
			'height: 100%;',
			'z-index: 10000;',
			'background-color: #1F1F1F;',
			'-moz-opacity: 0.9;',
			'opacity: .80;',
			'filter: alpha(opacity=80);',
		'}',
			'}',
		].join('\n');
		this.addStyle(temp);
	},
	setDefaultStyle: function(appName){
		var temp = [
		'#'+appName+' {',
			'position: fixed!important;',
			'position: absolute;',
			'top: 0;',
			'left: 0;',
			'z-index: 10001;',
			'text-indent: 0;',
			'text-align: left;',
			'padding: 2% 4% 0 4%;',
		'}',
		'#'+appName+' * {',
			'float: none;',
			'color: #000;',
			'decoration: none;',
			'text-indent: 0;',
			'text-align: left;',
			'background-color: transparent;',
			'padding: 0;',
			'margin: 0;',
			'border: 0;',
		'}',
		].join('\n');
		this.addStyle(temp);
	},
	imeOff: function(){
		var s = document.createElement('input');
		s.type = 'password';
		s.id = 'element_id';
	/*
		s.style.border = 'none';
		s.style.width = '0px';
		s.style.display = 'none';
	*/
		$(this.layerName).appendChild(s);
		s.focus();
		setTimeout(function(){$(this.layerName).removeChild(s);}.bind(this),500);
	}
}


// Hoeditor

var Hoeditor = Class.create();
Hoeditor.prototype = {
	initialize: function() {
		//
		this.name = '__hoeditor_edit';
		this.mark = '*';
		setApp.make(this);

		this.saveDataLength = GM_getValue('HoeSaveLength');
		if(!this.saveDataLength){
			this.saveDataLength = 2;
		}

		this.makeMenu();
		this.makeMessage();
		this.makeTab();
		this.makeButton();

		this.loadData();

	},
	makeMenu: function(){
		var menuArea = document.createElement('ul');
		menuArea.id = '__hoe_menuArea';
		var menus = [
			['\u4fdd\u5b58', this.saveHoe, '\u4fdd\u5b58\u3057\u307e\u3057\u305f\u3002'],
			['\u7d42\u4e86', this.hide, '\u4fdd\u5b58\u305b\u305a\u306b\u7d42\u4e86\u3057\u307e\u3059\u3002'],
			['Gmail', this.Gmail, 'Gmail\u306b\u9001\u4fe1\u3057\u307e\u3057\u305f\u3002\u91cf\u304c\u591a\u3044\u5834\u5408\u306f\u30a8\u30e9\u30fc\u306b\u306a\u308b\u3053\u3068\u304c\u3042\u308a\u307e\u3059\u3002'],
			['\u30d5\u30a1\u30a4\u30eb\u306b\u4fdd\u5b58', this.fileSave, '\u53f3\u30af\u30ea\u30c3\u30af\u3067\u540d\u524d\u3092\u4ed8\u3051\u3066\u4fdd\u5b58\u3067\u304d\u307e\u3059\u3002'],
			['\u30b0\u30ea\u30e2\u30f3', this.Grimon, '\u4f5c\u6210\u3057\u305fGreasemonkey\u30b9\u30af\u30ea\u30d7\u30c8\u3092\u30a4\u30f3\u30b9\u30c8\u30fc\u30eb\u3067\u304d\u307e\u3059\u3002'],
			['\u30d8\u30eb\u30d7', function(){
				location.href = 'http://a-h.parfe.jp/einfach/';
			}, '']
		];
		menus.each(function(e){
			var menu = document.createElement('li');
			menu.innerHTML = e[0];
			Event.observe(menu, 'click', e[1].bind(this), false);
			menu.setAttribute('__hoe_messeage', e[2]);
			menuArea.appendChild(menu);
		}.bind(this));
		this.div.appendChild(menuArea);
	},
	makeMessage: function(){
		var message = document.createElement('input');
		message.type = 'text';
		message.id = '__hoe_message';
		this.div.appendChild(message);
	},
	makeTab: function(){
		var tabIndex = document.createElement('ul');
		tabIndex.id = '__hoe_tabIndex';
		this.div.appendChild(tabIndex);

		var tabBoxIndex = document.createElement('div');
		tabBoxIndex.id = '__hoe_tabBoxIndex';
		this.div.appendChild(tabBoxIndex);
		//

		var tabs = [];
		for(var i=0; i<this.saveDataLength; i++){
			tabs.push('\u30bf\u30d6' + i)
		}

		tabs.each(function(e, index){
			var tab = document.createElement('li');
			tab.innerHTML = e;
			tab.className = '__hoe_tab';
			tab.style.styleFloat = 'left';
			tabIndex.appendChild(tab);

			var tabBox = document.createElement('div');
			tabBox.className = '__hoe_tabBox';
			tabBoxIndex.appendChild(tabBox);
			var editor = document.createElement('textarea');
			editor.id = this.name + index;
			editor.className = '__hoe_editor_edit';
			tabBox.appendChild(editor);
		}.bind(this));

		var start = new TabMaker('__hoe_tab');
		start.create();
	},
	makeButton: function(){
		var buttons = [
			['\u4fdd\u5b58', this.saveHoe, '\u4fdd\u5b58\u3057\u307e\u3057\u305f'],
			['\u4fdd\u5b58/\u7d42\u4e86', this.saveHide, ''],
			['\u7d42\u4e86', this.hide, '']
		];
		buttons.each(function(e){
			var Button = document.createElement('input');
			Button.type = 'button';
			Button.value = e[0];
			Button.setAttribute('__hoe_messeage', e[2]);
			Button.className = '__hoe_button';
			Event.observe(Button, 'click', e[1].bind(this), false);
			$('__hoe_tabBoxIndex').appendChild(Button);
		}.bind(this));
	},
	loadData: function(){
		for(var i=0; i<this.saveDataLength; i++){
			var saveData = GM_getValue('HoeSave' + i);
			if(saveData){
				$(this.name + i).value = decodeURIComponent(saveData);
			}
		}
	},
	show: function(){
		this.loadData();
		setApp.show(this);
		for(var i=0; i<this.saveDataLength; i++){
			Element.show(this.name+i);
		}
		$(this.name + '0').focus();
	},
	hide: function(){
		setApp.hide(this);
		for(var i=0; i<this.saveDataLength; i++){
			Element.hide(this.name+i);
		}
	},
	saveHide: function(e){
		this.saveHoe(e);
		this.hide();
	},
	sourceShow: function(){
		this.show();
		$(this.name + '1').value = document.body.parentNode.innerHTML;
	},
	showMsg: function(text){
		$('__hoe_message').value = text;
	},
	saveHoe: function(e){
		for(var i=0; i<this.saveDataLength; i++){
			var textData = encodeURIComponent($(this.name+i).value);
			GM_setValue('HoeSave' + i, textData);
		}
		if(e.target.getAttribute)
			this.showMsg(e.target.getAttribute('__hoe_messeage'));
	},
	Gmail: function(e){
		var d=document;
		//
		var tx= $(this.name+0).value;
		void(open('http://mail.google.com/mail/?view=cm&cmid=0&fs=1&tearoff=1&su=&body='+encodeURIComponent(d.title+'\n'+location.href+tx),'gmail', 'toolbar=no,width=700,height=700'));
		this.showMsg(e.target.getAttribute('__hoe_messeage'));
	},
	fileSave: function(e){
		//
		var data = $(this.name+0).value;
		e.target.innerHTML = '\u30d5\u30a1\u30a4\u30eb\u306b\u4fdd\u5b58\u3000\u2192<a href="' + 
		'data:text/text;charset=utf-8,' + 
		encodeURIComponent(data) + 
		'">hoeditor.txt</a>';
		Event.stopObserving(e.target, 'click', this.fileSave, false);
		this.showMsg(e.target.getAttribute('__hoe_messeage'));
	},
	Grimon: function(e){
		//
		var data = $(this.name+0).value;
		e.target.innerHTML = '\u30b0\u30ea\u30e2\u30f3\u3000\u2192<a href="' + 
		'data:text/javascript;charset=utf-8,' + 
		encodeURIComponent(data) +
		'//.user.js">script.user.js</a>';
		Event.stopObserving(e.target, 'click', this.Grimon, false);
		this.showMsg(e.target.getAttribute('__hoe_messeage'));
	},
	buttonPress: function(){
		this.className = '__hoe_button_press';
	},
	buttonUp: function(){
		this.className = '__hoe_button';
	},
	setKey: function(){
		var Keys = [
			['E', function(e){
					Event.stop(e);
					this.sourceShow();
				}.bind(this), ''],
			['e', function(e){
					Event.stop(e);
					this.show();
				}.bind(this), '']
		];
		setApp.makeKey(Keys, this.name);
	},
	addStyle: function(){
		var temp = [
		'#__hoeditor_edit {',
		'}',
		'#__hoe_menuArea li {',
			'color: #fff;',
		'}',
		'#__hoe_menuArea  li, #__hoe_tabIndex li {',
			'float: left;',
			'margin-right: 5px;',
			'padding: 0.5em;',
			'list-style-type: none;',
			'decoration: underline;',
			'cursor: pointer;',
		'}',
		'#__hoe_message {',
			'color: #000;',
			'background-color: #fff;',
			'padding: 5px;',
			'height: 2.2em;',
			'width: 103%;',
			'border: 0;',
			'clear: both;',
		'}',
		'#__hoe_tabIndex {',
			'margin-top: 5px;',
		'}',
		'#__hoe_tabIndex .close {',
			'background-color: #FFF7D6;',
			'color:#0000FF;',
		'}',
		'#__hoe_tabIndex .close a {',
			'color: #333;',
			'text-decoration: underline;',
		'}',
		'#__hoe_tabIndex .open {',
			'background-color: #FFD363;',
			'text-decoration: none;',
		'}',
		'#__hoe_tabIndex .open a {',
			'color: #333;',
		'}',
		'#__hoe_tabIndex li {',
			'float: left;',
			'margin-right: 5px;',
		'}',
		'#__hoe_tabBoxIndex {',
			'color: #fff;',
			'background-color:#FFD363;',
			'padding: 1em;',
			'margin: 0;',
			'width: 100%;',
			'height: 90%;',
			'clear: both;',
		'}',
		'.__hoe_tabBox {',
			'color: #fff;',
			'width: 100%;',
			'height: 95%;',
		'}',
		'.__hoe_editor_edit {',
			'background-color: #fff!important;',
			'height: 100%;',
			'width: 100%;',
			'padding: 10px;',
			'border : 2px solid #e0e0e0!important;',
			'border-color : gray white white gray!important;',
		'}',
		'.__hoe_editor_edit:focus {',
			'background-color: #FFFCF0!important;',
		'}',
		'.__hoe_button {',
			'background-color: #D6D3CE!important;',
			'margin-top: 15px!important;',
			'margin-right: 10px!important;',
			'padding: 5px!important;',
			'border : 2px solid #e0e0e0!important;',
			'border-color : white gray gray white!important;',
		'}',
		'.__hoe_button_press {',
			'background-color: #D6D3CE!important;',
			'margin-top: 15px!important;',
			'margin-right: 10px!important;',
			'padding: 5px!important;',
			'border : 2px solid #e0e0e0!important;',
			'border-color : gray white white gray!important;',
		'}',
		'#__hoeditor_edit a { color: #fff;}'
		].join('\n');
		setApp.addStyle(temp);
	}
}

//Hoe Launcher

var HoeLauncher = Class.create();
HoeLauncher.prototype = {
	initialize: function() {
		this.name = '__hoe_launcher';
		this.mark = '+';
		setApp.make(this);

		this.applications = [];
		this.load();
		this.makeMenu();
		this.makeIcon();

		this.nowMenu;

	},
	load: function(){
		var default_applications =[
			['Google', 'http://www.google.co.jp/'],
			['Amazon', 'http://www.amazon.co.jp/'],
			['Gmail', 'https://mail.google.com/mail/'],
			['livedoor Reader', 'http://reader.livedoor.com/reader/'],
			['checkpad', 'http://www.checkpad.jp/'],
			['Google Calendar', 'https://www.google.com/calendar/render'],
			['Google Docs & Spreadsheets', 'http://docs.google.com/'],
			['mixi', 'http://mixi.jp/']
		];

		//reset save_value
		//GM_setValue('launcher_setting', default_applications.join('\n'));

		var temp = decodeURIComponent(GM_getValue('launcher_setting', default_applications.join('\n')));
		temp = temp.split('\n');
		temp.each(function(e){
			var buf = e.split(',');
			if(e[1])
				this.applications.push([buf[0], buf[1]]); 
		}.bind(this));
	},
	makeMenu: function(){
		var launcherMenuName = document.createElement('p');
		launcherMenuName.id = '__hoe_launcherMenuName';
		this.div.appendChild(launcherMenuName);

		var launcherMenuNameSpan = document.createElement('span');
		launcherMenuNameSpan.innerHTML = 'quick launcher';
		launcherMenuName.appendChild(launcherMenuNameSpan);

		var launcherIndex = document.createElement('div');
		launcherIndex.id = '__hoe_launcherIndex';
		this.div.appendChild(launcherIndex);
	},
	makeIcon: function(){
		this.applications.each(function(e){
			
			var link = document.createElement('a');
			link.className = '__hoe_launcherMenuLink';
			link.href = e[1];

			var url = link.protocol  + '//' + link.hostname + '/favicon.ico';

			GM_xmlhttpRequest({
				method: 'GET',
				url: url,
				onload: function(details) {
					var icon = document.createElement('img');
					if(details.status!='404'){
						icon.src = link.protocol + '//' + link.hostname + '/favicon.ico';
					}else{
						icon.src = 'moz-icon://.html?size=128';
					}
					icon.className = '__hoe_launcherIcon';

					link.appendChild(icon);
					link.title = e[0];
					//link.appendChild(document.createTextNode(e[0]));
					$('__hoe_launcherIndex').appendChild(link);
				}
			})
		});
	},
	show: function(){
		setApp.show(this);
		$('__hoe_launcherIndex').style.left = (500 / 2 - 52) + 'px';
		this.nowMenu = 0;
		this.focusMenu();
	},
	hide: function(){
		setApp.hide(this);
		layer.hide(this.name + '_setting');
	},
	focusMenu: function(){
		var menu = gcn('__hoe_launcherMenuLink')[this.nowMenu];
		menu.focus();
		$('__hoe_launcherMenuName').title = menu.title;
		$('__hoe_launcherMenuName').firstChild.innerHTML = menu.title;
		var w = $('__hoe_launcherMenuName').firstChild.offsetWidth /2 ;
		$('__hoe_launcherMenuName').style.marginLeft = (500 / 2 - w) + 'px!important';
	},
	scrollMenu: function(move){
		var menuLeft = $('__hoe_launcherIndex').offsetLeft;
		$('__hoe_launcherIndex').style.left = ( menuLeft - move) + 'px';
	},
	focusNextMenu: function(){
		if(this.nowMenu==this.applications.length -1) return;
		this.nowMenu++;
		this.scrollMenu(70);
		this.focusMenu();
	},
	focusPreviousMenu: function(){
		if(this.nowMenu==0) return;
		this.nowMenu--;
		this.scrollMenu(-70);
		this.focusMenu();
	},
	setLauncher: function(){
		setApp.imeOff();
		layer.hide(this.name);
		document.title = setApp._title;

		var settingDiv = document.createElement('div');
		settingDiv.id = this.name + '_setting';
		
		var setting = document.createElement('textarea');
		setting.id = this.name + '_setting_value';
		settingDiv.appendChild(setting);
		var temp = [];
		this.applications.each(function(e){
			temp.push(e[0] + ',' + e[1]);
		});
		setting.value = temp.join('\n');
		
		var buttonDiv = document.createElement('div');
		settingDiv.appendChild(buttonDiv);

		var buttons = [
			['\u4fdd\u5b58/\u7d42\u4e86', this.saveSetting],
			['\u3053\u306e\u30da\u30fc\u30b8\u3092\u8ffd\u52a0', this.addPage],
			['\u7d42\u4e86', this.hideSetting]
		];
		buttons.each(function(e){
			var Button = document.createElement('input');
			Button.type = 'button';
			Button.value = e[0];
			Button.className = '__hoe_setting_button';
			Event.observe(Button, 'click', e[1].bind(this), false);
			buttonDiv.appendChild(Button);
		}.bind(this));

		document.body.appendChild(settingDiv);
	},
	hideSetting: function(){
		document.body.removeChild($(this.name+'_setting'));
		layer.hide(setApp.layerName);
	},
	saveSetting: function(){
		var temp = $(this.name+'_setting_value').value;
		GM_setValue('launcher_setting', encodeURIComponent(temp));
		document.body.removeChild($(this.name+'_setting'));
		layer.hide(setApp.layerName);
	},
	addPage: function(){
		$(this.name+'_setting_value').value += '\n' + setApp._title + ',' + location.href;
	},
	setKey: function(){
		var Keys = [
			['Q', '', this.focusPreviousMenu.bind(this)],
			['q', this.show.bind(this), this.focusNextMenu.bind(this)],
			['right', '', this.focusNextMenu.bind(this)],
			['left', '', this.focusPreviousMenu.bind(this)],
			['S', '', this.setLauncher.bind(this)]
		];
		setApp.makeKey(Keys, this.name);
	},
	addStyle: function(){
		var temp = [
		'#__hoe_launcher {',
			'overflow: hidden;',
			'height: 140px;',
			'width: 500px;',
			'padding: 8px!important;',
			'text-indent: 0;',
			'text-align: left;',
			'background-color: #fff;',
			'-moz-opacity: 0.9;',
			'opacity: .90;',
			'filter: alpha(opacity=90);',
			'-moz-border-radius: 10px;',
		'}',
		'#__hoe_launcherMenuName {',
			'position:relative;',
			'display:block;',
			'font-weight: bold;',
			'width: 100%;',
			'z-index: 10002;',
		'}',
		'#__hoe_launcherMenuName span {',
			'color:#333!important;',
			'position:absolute;',
			'display:block;',
			'top:0px;',
		'}',
		'#__hoe_launcherMenuName:before {',
			'color:#999!important;',
			'display:block;',
			'padding:1px;',
			'content: attr(title);',
		'}',
		'#__hoe_launcherIndex {',
			'width: 3000px;',
			'position: absolute!important;',
			'top: 2em;',
			'z-index: 10002;',
		'}',
		'#__hoe_launcherIndex a {',
			'margin-right: 6px!important;',
		'}',
		'#__hoe_launcherIndex a img {',
			'height: 64px;',
			'width: 64px;',
		'}',
		'#__hoe_launcherIndex a:focus  img {',
			'padding: 20px!important;',
			'height: 82px;',
			'width: 82px;',
			'border: solid 1px #666!important;',
		'}',
		'#__hoe_launcherIndex a:focus + a  img {',
			'padding: 5px!important;',
			'height: 70px;',
			'width: 70px;',
		'}',
		'#__hoe_launcherIndex a:focus + a  img + a  img {',
			'padding: 10px!important;',
			'height: 76px;',
			'width: 76px;',
		'}',
		'#__hoe_launcher_setting {',
			'position: fixed!important;',
			'position: absolute;',
			'top: 0;',
			'left: 0;',
			'padding: 20px;',
			'z-index: 10003;',
		'}',
		'#__hoe_launcher_setting textarea {',
			'width: 800px;',
			'height: 550px;',
			'padding: 5px;',
		'}',
		].join('\n');
		setApp.addStyle(temp);
	}
}

// HoeSearch

var HoeSearch = Class.create();
HoeSearch.prototype = {
	initialize: function() {
		this.name = '__hoe_search';
		this.mark = '?';

		setApp.make(this);

		this.key = false;
		this.searchParts = [
			{
				type: 'wikipedia',
				name: '\u8D85\u5F29\u7D1AWikipedia\u691C\u7D22',
				req: 'http://athlon64.fsij.org/~mikio/wikipedia/estseek.cgi?perpage=1&clip=-1&navi=0&attr=&order=&phrase=',
				limit: 1,
				areaExp: /<div id="estresult" class="estresult">(.*?)<\/div><div id="estinfo" class="estinfo">/g,
				matchExp: /<dl class="doc" id="doc_.*?">(.*?)<\/dl>/g,
				replaceHtml: '<dl>$1</dl>',
				startHtml: '',
				endHtml: '',
				style:[
					'$ {',
						'height: 15%;',
						'overflow: auto;',
					'}',
					'$ dd {',
						'font-size:0.8em;',
						'line-height: 135%;',
					'}',
					'$ dd.doc_text {margin: 0em 1.3em;}',
					'$ dl.doc dd {font-size: smaller; color: #222222;}',
					'$ span.doc_link {color: #007744;}',
					'$ strong.key1 { background-color: #ffffcc; }',
					'$ strong.key2 { background-color: #ffeeee; }',
					'$ strong.key3 { background-color: #eeeeff; }',
					'$ strong.key4 { background-color: #eeffdd; }'
				]
			},
			{
				type: 'hatena',
				name: '\u4EBA\u529B\u691C\u7D22\u306F\u3066\u306A',
				req: 'http://q.hatena.ne.jp/list?word=',
				limit: 5,
				areaExp: /<table class="questionlisttable" width="100%">(.*?)<\/table>/g,
				matchExp: /<tr>.*?<td class="questioncell">.*?<a href="(.*?)">(.*?)<\/a>.*?<\/td>.*?<\/tr>/g,
				replaceHtml: '<li><a href="http://q.hatena.ne.jp$1">$2<\/li>',
				startHtml: '<ul>',
				endHtml: '</ul>',
				style:[
					'$ {',
						'height: 15%;',
						'overflow: auto;',
					'}',
					'$ a {',
						'font-size:0.8em;',
						'line-height: 135%;',
					'}',
					'$ a:link, $ a:active{',
						'color:#00c;',
						'text-decoration: none;',
					'}',
					'$ a:visited{',
						'color:#551a8b;',
						'text-decoration: none;',
					'}',
					'$ li {',
						'border-bottom: #666 1px solid;',
					'}'
				]
			},
			{
				type: 'yhateb',
				name: 'Yahoo!\u691C\u7D22 \u306F\u3066\u30D6\u9806',
				req: 'http://k52.if.tv/tool/y_hateb/sr.cgi?search=',
				limit: 6,
				areaExp: /<div class="result">(.*?)<div><!-- Begin Yahoo!/g,
				matchExp: /<div class="result">.*?<\/div>(.*?)<span class="small">/g,
				replaceHtml: '<li>$1</li>',
				startHtml: '<ul>',
				endHtml: '</ul>',
				style:[
					'$ {',
						'height: 10%;',
						'overflow: auto;',
						'-moz-column-count: 2;',
					'}',
					'$ span.a {',
						'color: red;',
						'background-color: #fcc;',
						'font-weight: bold;',
					'}',
					'$ span.b {',
						'color: #ff6666;',
						'background-color: #fff0f0;',
						'font-weight: bold;',
					'}',
					'$ span.c {',
						'display: none;',
					'}',
					'$ .n {',
						'color: #f66;',
					'}',
					'$ .red{',
						'color:red;',
					'}',
					'$ .gray{',
						'color:#999;',
					'}'
				]
			},
			{
				type: 'gweb',
				name: 'Google',
				req: 'http://www.google.co.jp/search?q=',
				limit: 20,
				areaExp: /<!--a--><div>(.*?)<!--z--><\/div>/g,
				matchExp: /<div class=g>(.*?)<\/div>/g,
				replaceHtml: '<li>$1</li>',
				startHtml: '<ul>',
				endHtml: '</ul>',
				style:[
					'$ {',
						'height: 60%;',
						'overflow: auto;',
					'}',
					'$ a:active,$ .fl:active{color:red}',
					'$ .a,$ .a:link{color:green!important}',
					'$ .sm{display:block;margin:0;margin-left:40px}',
					'$ .r{font-size:1em}',
					'$ .sl,$ .r{font-weight:normal;margin:0;display:inline}'
				]
			}

		//parts template
		// $ - '#'+parts.type  ex) #gweb
		/*
			{
				type: 'gweb',
				name: 'Google',
				req: 'http://www.google.co.jp/search?q=',
				limit: 20,
				areaExp: /<!--a--><div>(.*?)<!--z--><\/div>/g,
				matchExp: /<div class=g>(.*?)<\/div>/g,
				replaceHtml: '$1',
				style:[
					'$ {',
						'height: 60%;',
						'overflow: auto;',
					'}'
					'$ span.a {',
						'color: red;',
						'background-color: #fcc;',
						'font-weight: bold;',
					'}',
				]
			}
		*/
		];
		this.setParts();
		var temp ='';
		this.searchParts.each(function(parts){
			temp += parts.style.join('\n').replace(/\$/g, '#'+this.name+parts.type);
		}.bind(this));
		GM_addStyle(temp);
	},
	show: function(){
		setApp.show(this);
		var d=document;
		var tx=d.selection?d.selection.createRange().text:window.getSelection();
		var key = (tx)?tx:(this.key)?this.key:'';
		this.key = prompt('Keyword?',key);
		if(!this.key)return;
		this.searchData();
		this.key = this.key.replace(/[\s@]+/, ' ');
	},
	hide: function(){
		setApp.hide(this);
	},
	setParts: function(){
		this.searchParts.each(function(parts){
			var resDiv = document.createElement('div');
			resDiv.className = 'res';
			resDiv.id = this.name+parts.type;
			$(this.name).appendChild(resDiv);
			//this.setDiv(resDiv);
		}.bind(this));
	},
	searchData: function(){
		this.searchParts.each(function(parts){
			this.getData(parts);
		}.bind(this));
	},
	getData: function(parts) {
		$(this.name+parts.type).innerHTML = '';
		var url = parts.req + encodeURIComponent(this.key);
		GM_xmlhttpRequest({
			method: 'GET',
			url   : url,
			headers: {'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 5.0; ja-JP; rv:1.8.1) Gecko/20061024 Forefox/2.0',
					  'Content-type': 'application/x-www-form-urlencoded'},
			onload:function(req){
				parts.res = req.responseText;
				this.showRes(parts);
			}.bind(this)
		});
	},	
	showRes: function(parts) {
		parts.url = parts.req + encodeURIComponent(this.key);
		var temp = '';
		var ret = parts.res.replace(/\n/g,'').match(parts.areaExp);
		if(ret == null) return;
		var rets = ret[0].match(parts.matchExp);
		if(rets == null) return;
		rets.each(function(e, index){
			if(index==parts.limit)throw $break;
			temp += e.replace(parts.matchExp, parts.replaceHtml);
		});
		temp = this.makeHeader(parts) + parts.startHtml + temp + parts.endHtml + this.makeFooter(parts);
		$(this.name+parts.type).innerHTML = temp;
		setApp.imeOff();
	},
	makeHeader: function(parts){
		return '<h3>' + parts.name + '</h3>';
	},
	makeFooter: function(parts){
		return '<h4><a href="' + parts.url + '">' + parts.name + '\u306E\u691C\u7D22\u7D50\u679C : ' + this.key + '</a></h4>';
	},
	setKey: function(){
		var Keys = [
			['s', this.show.bind(this), this.show.bind(this)]
		];
		setApp.makeKey(Keys, this.name);
	},
	addStyle: function(){
		var temp = [
		'#__hoe_search {',
		'}',
		'#__hoe_search a:link,#__hoe_search a:active{',
			'color:#00c;',
		'}',
		'#__hoe_search a:visited{',
			'color:#551a8b;',
		'}',
		'#__hoe_search h3 {',
			'position:fixed;',
			'font-size:400%;',
			//'text-align:right;',
			'color:#eee;',
			'z-index:-1000;',
		'}',
		'#__hoe_search h4 {',
			'width:100%;',
			'font-size:85%;',
			'text-align:right;',
			'margin-top: 1em;',
		'}',
		'#__hoe_search .res {',
			'background-color: #fff;',
			'padding: 1em;',
		'}',
		'#__hoe_search a {',
			'decoration: none;',
		'}',
		'.res li {',
			'list-style-type: none;',
			'margin-bottom: 1em;',
			'line-height: 135%;',
		'}',
		].join('\n');
		setApp.addStyle(temp);
	}
}


// GremonApp template
/*

var HoeLauncher = Class.create();
HoeLauncher.prototype = {
	initialize: function() {
		this.name = '';
		this.mark = '*';
		setApp.make(this);
	},
	show: function(){
		setApp.show(this);
	},
	hide: function(){
		setApp.hide(this);
	},
	setKey: function(){
		var Keys = [
			['s', this.show.bind(this), '']
		];
		setApp.makeKey(Keys, this.name);
	},
	addStyle: function(){
		var temp = [
		'#__hoe_launcher {',
		'}',
		].join('\n');
		setApp.addStyle(temp);
	}
}
var launcher = new HoeLauncher;
*/

init();

//debug

function log(obj){
	return unsafeWindow.console.log(obj);
}

})();
