/**
 * Ozein
 *  (c) 2007 NEXT CO.,LTD. (http://www.next-group.jp/)
 */

var Ozein = {
	Version: '0.1.0',
	PrototypeVersion: '',
	ScriptaculousVersion: '',
	initialize: function() {
		if (typeof Prototype == 'undefined') {
			throw("Ozein requires prototype.js");
		} else {
			this.PrototypeVersion = parseFloat(Prototype.Version.split(".")[0] + "." + Prototype.Version.split(".")[1]);
			if (this.PrototypeVersion < 1.5) {
				throw("Ozein requires prototype.js >= 1.5");
			}
		}
	},
	require: function(libraryName) {
		document.write('<script type="text/javascript" src="'+libraryName+'"></script>');
	},
	load: function() {
		$A(document.getElementsByTagName("script")).findAll( function(s) {
			return (s.src && s.src.match(/Ozein\.js(\?.*)?$/))
		}).each( function(s) {
			var path = s.src.replace(/ozein\.js(\?.*)?$/,'');
			var includes = s.src.match(/\?.*load=([a-z,]*)/);
			(includes ? includes[1] : 'kernel,effects,components').split(',').each(
				function(include) { Ozein.require(path+include+'.js') });
		});
	}
}
Ozein.initialize();

/*------------------------------------------------------------*
   Utilities
 *------------------------------------------------------------*/
if (Prototype.BrowserFeatures.XPath) {
  document.getElementsByAttribute = function(attrName, attrValue, parentElement) {
    if (attrValue == '*') {
        var q = ".//*[@" + attrName + "]";
    } else {
        var q = ".//*[contains(@" + attrName + ", '" + attrValue + "')]";
    }
    return document._getElementsByXPath(q, parentElement);
  }
} else document.getElementsByAttribute = function(attrName, attrValue, parentElement) {
  var children = ($(parentElement) || document.body).getElementsByTagName('*');
  var elements = [], child;
  for (var i = 0, length = children.length; i < length; i++) {
    child = children[i];
    if (v = child.getAttribute(attrName)) {
      if (attrValue == '*' || v == attrValue) {
        elements.push(Element.extend(child));
      }
    }
  }
  return elements;
};

Object.extend(String.prototype, {
  eqi: function(s) {
    return this.toLowerCase() == s.toLowerCase()
  },
  sliceBefore: function(needle, alternative) {
    if (needle == "") return alternative;
    var pos = this.indexOf(needle);
    if (pos == -1) {
      return alternative;
    } else {
      return this.slice(0, pos);
    }
  },
  ozeinEncode: function() {
        return encodeURI(this.gsub('/','',this));
  }
});



/*------------------------------------------------------------*
   Behaviours
 *------------------------------------------------------------*/
/**
 * Ozein Invoker
 */
Ozein.Invoker = {
  var_stock: new Array(),
  complete : function(){
    if(arguments.callee.done) return;
    arguments.callee.done = true;
    if(typeof _timer != 'undefined'){
      clearInterval(_timer);
      _timer = null;
    }
    Ozein.Invoker.onload();
  },
  check : function(){
    if(document.addEventListener && !/Opera/i.test(navigator.userAgent)){
      document.addEventListener("DOMContentLoaded", Ozein.Invoker.complete, false);
    }
    if(navigator.userAgent.match(/webkit|safari|khtml/i)){
      var _timer = setInterval(function(){
        if(document.readyState.match(/loaded|complete/)){
          Ozein.Invoker.complete();
        }
      }, 50);
    }
    if(/MSIE/.test(navigator.userAgent)){
      document.write('<script id="_decoy_" defer="defer" src="//:"><\/script>');
      document.getElementById("_decoy_").onreadystatechange = function(){
        if(this.readyState=='complete'){
          Ozein.Invoker.complete();
        }
      };
    }
    Event.observe(window, "load", Ozein.Invoker.complete);
  },
  onload : function(){
    var nodes = document.getElementsByAttribute('ozein', '*');
    this._invoke(nodes);
  },
  invokeElement: function(node) {
    var nodes = document.getElementsByAttribute('ozein', '*',node);
    this._invoke(nodes);
  },
  _invoke: function(nodes) {
    nodes.each( function(e){
      var attr = e.getAttribute('ozein');
      if ((inx = attr.indexOf('|')) > 0) {
        className = attr.substring(0, inx);
        eval('options = {' + attr.substring(inx + 1, attr.length) + '}');
      } else {
        className = attr;
        options = {};
      }
      if (Ozein[className]) {
        var obj = new Ozein[className](e, options);
        var name = e.getAttribute('ozein_name');
        if(name) {
            Ozein.Invoker.var_stock[name] = obj;
        }
      }
    });
  }
}
Ozein.Invoker.check();

/**
 * Ozein ie hover
 */
Ozein.ieHover = {
  csshoverReg: /(^|\s)(([^a]([^ ]+)?)|(a([^#.][^ ]+)+)):(hover|active)/i,
  activators: {
    onhover:{on:'onmouseover', off:'onmouseout'},
    onactive:{on:'onmousedown', off:'onmouseup'}
  },
  currentSheet: null,
  hoverEvents: [],
  enable: true,
  setEnable: function(enable) {
    this.enable = enable;
  },
  parseStylesheets: function() {
    if(!this.enable) return;
    if(!/MSIE (5|6|7)/.test(navigator.userAgent)) return;
    Event.observe(window, 'unload', this.unhookHoverEvents.bindAsEventListener(this));
    var sheets = document.styleSheets, l = sheets.length;
    for(var i=0; i<l; i++) {
      this.parseStylesheet(sheets[i]);
    }
  },
  parseStylesheet: function(sheet) {
    if(sheet.imports) {
      try {
        var imports = sheet.imports, l = imports.length;
        for(var i=0; i<l; i++) this.parseStylesheet(sheet.imports[i]);
      } catch(securityException) {}
    }
    try {
      var rules = (this.currentSheet = sheet).rules, l = rules.length;
      for(var j=0; j<l; j++) this.parseCssRule(rules[j]);
    } catch(securityException) {}
  },
  parseCssRule: function(rule) {
    var select = rule.selectorText, style = rule.style.cssText;
    if(!this.csshoverReg.test(select) || !style) return;
    var pseudo = select.replace(/[^:]+:([a-z-]+).*/i, 'on$1');
    var newSelect = select.replace(/(\.([a-z0-9_-]+):[a-z]+)|(:[a-z]+)/gi, '.$2' + pseudo);
    var className = (/\.([a-z0-9_-]*on(hover|active))/i).exec(newSelect)[1];
    var affected = select.replace(/:(hover|active).*$/, '');
    var elements = this.getElementsBySelect(affected);
    if(elements.length == 0) return;
    this.currentSheet.addRule(newSelect, style);
    for(var i=0; i<elements.length; i++) {
      new this.HoverElement(elements[i], className, this.activators[pseudo]);
    }
  },
  HoverElement: function(node, className, events) {
    if(!node.hovers) node.hovers = {};
    if(node.hovers[className]) return;
    node.hovers[className] = true;
    Ozein.ieHover.hookHoverEvent(node, events.on, function() { node.className += ' ' + className; });
    Ozein.ieHover.hookHoverEvent(node, events.off, function() { node.className = node.className.replace(new RegExp('\\s+'+className, 'g'),''); });
  },
  hookHoverEvent: function(node, type, handler) {
    node.attachEvent(type, handler);
    this.hoverEvents[this.hoverEvents.length] = { 
      node:node, type:type, handler:handler 
    };
  },
  unhookHoverEvents: function() {
    for(var e,i=0; i<this.hoverEvents.length; i++) {
      e = this.hoverEvents[i]; 
      e.node.detachEvent(e.type, e.handler);
    }
  },
  getElementsBySelect: function(rule) {
    var parts, nodes = [document];
    parts = rule.split(' ');
    for(var i=0; i<parts.length; i++) {
      nodes = this.getSelectedNodes(parts[i], nodes);
    }
    return nodes;
  },
  getSelectedNodes: function(select, elements) {
    var result, node, nodes = [];
    var identify = (/\#([a-z0-9_-]+)/i).exec(select);
    if(identify) {
      var element = document.getElementById(identify[1]);
      return element? [element]:nodes;
    }
    var classname = (/\.([a-z0-9_-]+)/i).exec(select);
    var tagName = select.replace(/(\.|\#|\:)[a-z0-9_-]+/i, '');
    var classReg = classname? new RegExp('\\b' + classname[1] + '\\b'):false;
    for(var i=0; i<elements.length; i++) {
      result = tagName? elements[i].all.tags(tagName):elements[i].all; 
      for(var j=0; j<result.length; j++) {
        node = result[j];
        if(classReg && !classReg.test(node.className)) continue;
        nodes[nodes.length] = node;
      }
    }	
    return nodes;
  }
}
Event.observe(window, 'load', Ozein.ieHover.parseStylesheets.bindAsEventListener(Ozein.ieHover));

/**
 * Ozein Unique ID dispatcher
 */
Ozein.IdDispatcher = {
  _sentry: {},
  get: function(prefix) {
    if (!this._sentry[prefix]) {
      this._sentry[prefix] = 0;
    }
    ++this._sentry[prefix];
    var id = prefix + '-' + this._sentry[prefix];
    return id;
  }
}

/**
 * Ozein auto label
 */
Ozein.autoLabel = function() {
  var labels = document.getElementsByTagName('label');
  for(var i=0; i<labels.length; ++i){
    var l = labels[i];
    var for_attr = l.attributes.getNamedItem('for');
    if (!for_attr || !for_attr.value) {
      var inputs = l.getElementsByTagName('input');
      if (inputs.length) {
        var inp = inputs[0];
        var id = inp.getAttribute('id');
        if (!id) {
          id = Ozein.IdDispatcher.get('ozein-autolabelid');
          inp.setAttribute('id', id);
        }
        if (for_attr == null) {
          for_attr = document.createAttribute('for');
          for_attr.value = id;
          l.attributes.setNamedItem(for_attr);
        } else {
          for_attr.value = id;
        }
      }
    }
  }
}
Event.observe(window, 'load', Ozein.autoLabel.bindAsEventListener(Ozein.autoLabel));

/**
 * Ozein Safari resolver
 */
Ozein.resolveSafari = function(e) {
  var node = Event.element(e);
  if (!/Safari/.test(navigator.userAgent)) return;
  if (!node.tagName.eqi('label')) return;
  var target = node.getAttribute('for');
  if (target) {
    node = $(target.value);
    if (node.disabled) return false;
    if (node.tagName.eqi('input')) {
      if (node.type.eqi('checkbox')) node.checked = !node.checked;
      if (node.type.eqi('radio')) node.checked = true;
    }
  }
}
Event.observe(document, 'click', Ozein.resolveSafari.bindAsEventListener(Ozein.resolveSafari));