/*
  Commons functions
*/

if (!Array.prototype.forEach){
  Array.prototype.forEach = function(fun){
    var len = this.length;
    var thisp = arguments[1];
    for (var i = 0; i < len; i++){
      if (i in this)
        fun.call(thisp, this[i], i, this);
    }
  };
}

/* 
  browser detection
*/

window.xpath = !!(document.evaluate);
if (window.ActiveXObject) window.ie = window[window.XMLHttpRequest ? 'ie7' : 'ie6'] = true;
else if (document.childNodes && !document.all && !navigator.taintEnabled) window.webkit = window[window.xpath ? 'webkit420' : 'webkit419'] = true;

if (window.ie6) try {document.execCommand("BackgroundImageCache", false, true);} catch(e){};
/* 
  DOM 
  for add an element in the three verified
*/
function addElement(tag,options){
  var element = document.createElement(tag);
  for(var property in options){    
    var val = options[property];
    switch(property){      
		  case 'styles': setStyles(element,val);break;
		  case 'style': element.style.cssText = val;break;
		  case 'opacity': setOpacity(element,val);break;
		  case 'class': element.className = val;break;
		  case 'text':addTextNode(element,val);break;
		  default: element[property] = val;
	  }     
  }
  return element;
}; 

function addTextNode(node,text){
  var textNode =document.createTextNode(text);
  node.appendChild(textNode);
}

function setStyles(el,val){
  for(var styles in val){  
    if(styles == 'opacity')setOpacity(el,val[styles]);
		else el.style[styles] = val[styles];
  }
};

function getStyle(el,styleProp){
  if(el.currentStyle){
    return(el.currentStyle[styleProp])
  }
  if(document.defaultView.getComputedStyle){
    return(document.defaultView.getComputedStyle(el,"")[styleProp])
  }
  return(null)
}

function hasClass(el, cn){
  if(el) return el.className.match(new RegExp("(^|\\s)"+cn+"(\\s|$)"));
}

function addClass(el, cn){
  if (!el.className) el.className = cn;
	else if (!hasClass(el, cn)) el.className += " " + cn;
}

function removeClass(el,cn) {
  if (hasClass(el,cn)) {
    var reg = new RegExp('(\\s|^)'+cn+'(\\s|$)');
    el.className=el.className.replace(reg,' ');
  }
}

function replaceClass(el,oldCn,newCn){
  removeClass(el,oldCn);
  addClass(el,newCn);
}

function reverseClass(el,firstC,nextC){
  if(hasClass(el,firstC))replaceClass(el,firstC,nextC);
  else if(hasClass(el,nextC))replaceClass(el,nextC,firstC);
}

function changeClass(items,event,opener,topen,stop){
  var reverse = function(context,el,op){
    reverseClass(el,opener[0],opener[1]);
    reverseClass($el(context,'.'+op)[0],topen[0],topen[1]);  
  }
  var fclose = [];
  var fopen = [];
  var toOpenBox = [];
  items.forEach(function(item,index){
    toOpenBox[index] = $el(item,'.'+opener[0])[0];
    fclose[index] = function(e){
      if(!stop) stopEvent(e);
      removeEvent(this,event,fclose[index]);
      reverse(items[index],this,topen[1]);
      addEvent(toOpenBox[index],event,fopen[index]);   
    }
    fopen[index] = function(e){
      if(!stop) stopEvent(e);
      removeEvent(this,event,fopen[index]);
      reverse(item,this,topen[0]); 
      addEvent($el(item,'.'+opener[1])[0],event,fclose[index]);
    }
    addEvent(toOpenBox[index],event,fopen[index]);
  });
};

function changeClassById(item,event,opener,topen,change,stop){
  var openerEl = opener[0].split(/#/);
  var openers = [];
  $el($(item),openerEl[0]).forEach(function(item,i){
    if(item.id.indexOf(openerEl[1]) != -1) openers[i] = item;
  });
  openers.forEach(function(item,i){
    addEvent(item,event,function(e){
      if(!stop) stopEvent(e);
      if(hasClass(item,opener[1]) || change){
        reverseClass(this,opener[1],opener[2]);
        reverseClass($(topen[0]+item.id.replace(openerEl[1],"")),topen[1],topen[2]);
        if(!change){
          openers.forEach(function(other,j){
            if(i!=j){
              if(hasClass(other,opener[2])){
                reverseClass(other,opener[1],opener[2]);
                reverseClass($(topen[0]+other.id.replace(openerEl[1],"")),topen[1],topen[2]);
              }
            }       
          });
        }
      }
    });
  });
};


function firstNodeChild(el) {
  if(!el.childNodes.length)return;
  for(var i=0,l=el.childNodes.length; i<=l; ++i ) {
    if(el.childNodes[i].nodeType == 1)return el.childNodes[i];
  }
  return;
}

/* 
  EVENT 
  event helper
*/

function addEvents(obj, type, fn, par){
  for(var i=0, l=obj.length;i<l;i++) addEvent(obj[i], type, fn, par);
};

var eventListeners = [];

function addEvent(node, type, handler, par){

	if (!handler.$$guid) handler.$$guid = eventListeners.length+1;

  var handlerEvent = function(event){
    if (!event) var event = window.event;   
    return handler.call(node, event, par);
	};
  if(node.addEventListener){
    if(type == 'mouseenter' || type == 'mouseleave'){     
      handlerEvent = function(e){  
        if(this == e.relatedTarget)return;
        else{
          var t = this.getElementsByTagName('*');var l = t.length;     
          for(var i = 0;i < l; i++){
            if(e.relatedTarget == t[i])return;
          }
        }
        handler.call(this, e, par);
      };
      if(type == 'mouseenter')type='mouseover';
      if(type == 'mouseleave')type='mouseout';
    }
		node.addEventListener(type, handlerEvent, false);
  }else{
    node.attachEvent('on' + type, handlerEvent);
  }
  eventListeners.push({node: node, event: type, id: handler.$$guid, handler: handlerEvent});
}

function removeEventIndex(index){
  var ev = eventListeners[index];
  delete eventListeners[index];
  if(ev.node.removeEventListener) ev.node.removeEventListener(ev.event,ev.handler, false);  
  else ev.node.detachEvent('on' + ev.event,ev.handler);
}

function removeEvent(node, event, handler){
  for(i in eventListeners){
    if (eventListeners[i].id == handler.$$guid) removeEventIndex(i);
  }
  return null;
}

function cleanupEventListeners(){
  for (var i = eventListeners.length; i > 0; i--){
    if (eventListeners[i] != undefined) removeEventIndex(i);
  }
}

addEvent(window, 'unload', cleanupEventListeners);

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

/* 
  SELECTORS
*/

function $(el){
  var element = (typeof el == 'string')? document.getElementById(el) :  el;
	return element ? element : null;
};

function $css(selector){ 
  var str = selector.split(/\s/);
  if(str[1]){  
    var context = str[0]; 
    var tagOrStyle = str[1];
    return $el(context,tagOrStyle);
  }else
    return $el(document,selector); 	
};

function $el(context,selector){

  if(!context)return [];
  
  if(typeof context == 'string'){
    if(context.match(/^#/)) 
      context = $(context.replace(/#/,''));
    else{
      var contexts = $el(document,context);
    }
  }else if(context instanceof Array){
    var contexts = context;
  }
  
  var ret = [];
  
  if(contexts && contexts.length > 1){
    contexts.forEach(function(item){
      if(item && item.nodeType === 1){
        var newEls = $el(item,selector);  
        ret = ret.concat(newEls);
      }
    });
  }else if(context){
    context = (contexts)? contexts[0] : context;
    if(selector.match(/^\./)){
      var clas = selector.replace(/\./,'');
      var tag = "*";
    }else if(selector.match(/\./)){
      var str = selector.split(/\./);
      var clas = str[1];
      var tag = str[0];
    }  
    if(clas){
      if(document.getElementsByClassName){
        var els = context.getElementsByClassName(clas);
        for (var i=0;els[i]; i++){
          if(els[i].tagName.toLowerCase() == tag) ret.push(els[i]);
          else if(!tag||tag=="*") ret.push(els[i]);
        }
      }else{
        var tags = context.getElementsByTagName(tag);
        for (var i=0;tags[i]; i++){
          if(hasClass(tags[i], clas)) ret.push(tags[i]);
        }
      }
    }else{ 
      var els = context.getElementsByTagName(selector);
      for (var i=0;els[i];i++){
        ret.push(els[i]);
      }
    }
  }  
  return ret;
   	
};

/* 
  SIZE
  event helper
*/


function findPos(el){
	var x = y = 0;
	if(el.offsetParent) {
		x = el.offsetLeft;
		y = el.offsetTop;
		while(el = el.offsetParent) {
			x += el.offsetLeft;
			y += el.offsetTop;
		}
	}
	return {'left':x, 'top':y};
};

function Cursor(e){
  var e = e || window.event;
  return { 
    page: {'x': e.pageX || e.clientX + Window.scrollLeft(),'y': e.pageY || e.clientY + Window.scrollTop()},
    client: {"x": e.clientX, "y": e.clientY}
  }
};

var Window = (function(){
  function documentSize(name){
    return Math.max( 
		  Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]), 
		  Math.max(document.body["offset" + name], document.documentElement["offset" + name]) 
    )
  };
  function documentCompat(name){
    return document.documentElement[name] || document.body[name];
  };
  return {
    width: function() {
			return (window.webkit419)? window.innerWidth : (window.opera)? document.body.clientWidth : documentCompat('clientWidth');
		},
    height: function() {
			return (window.webkit419)? window.innerHeight : (window.opera)? document.body.clientHeight : documentCompat('clientHeight');
		}, 
    scrollWidth: function(){return documentSize('Width')},
    scrollHeight: function(){return documentSize('Height')},
    scrollLeft: function(){return window.pageXOffset || documentCompat('scrollLeft')},
    scrollTop: function(){return window.pageYOffset || documentCompat('scrollTop')}
  }
})();

/* ajax request */
function ajaxRequest(url){
  
  var fn,par;
  var xhr = (window.XMLHttpRequest) ? new XMLHttpRequest() : (window.ActiveXObject ? new ActiveXObject('Microsoft.XMLHTTP') : false);
  
  this.callBack = function(action,param){
    fn = action;
    par = param;
  };
  
  this.get = function(){
    if(xhr){
      xhr.open("GET",url,true);
      if(fn){this.send()}
      xhr.send(null);
    }else{return false}
  };
  
  this.post = function(variables){
    if(xhr){
      xhr.open("POST",url,true);
      xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
      if(fn){this.send()}
      var postString = '';
      for(var prop in variables){
        postString += '&'+prop+'='+encodeURIComponent(variables[prop]);
      } 
      var postString = postString.substring(1,postString.length);
      xhr.send(postString);
    }else{return false}
  };
  
  this.send = function(){
    xhr.onreadystatechange = function(){
			if(xhr.readyState == 4){
				if (xhr.status == 200){
          if(par) fn.call(this,xhr,par);
          else fn.call(this,xhr);        
				}else{
          fn(xhr.status);
        }
			}
		}
  };

};

//usefull for get xml node
function Xml(xml){
  return { 
    tag: function(tagName){
      var node = (xml.getElementsByTagName(tagName)[0])? xml.getElementsByTagName(tagName) : null;
      var firstNode = (node)? node[0] : null;
      var firstValue = (node)? ((node[0].firstChild)? node[0].firstChild.nodeValue : '' ) : '';
      return {'all': node, 'first': firstNode, 'value': firstValue}    
    }
  }
};


// based on work by Matthias Miller, Dean Edwards and John Resig
onDomReady = (function(){

  // create event function stack
  var load_events = [],load_timer,done,exec,old_onload,
  init = function () {
    done = true;    
    clearInterval(load_timer);// kill the timer
    while (exec = load_events.shift()){
      exec();
    }
  };

  return function(func){
    
    if (done) return func();// if the init function was already ran, just run 
    
    if (!load_events[0]) {
      if(document.readyState && window.ActiveXObject){
        if (!document.getElementById('ie_ready')){
          var src = (window.location.protocol == 'https:') ? '://0' : 'javascript:void(0)';
				  document.write('<script id="ie_ready" defer src="' + src + '"><\/script>');
				  document.getElementById('ie_ready').onreadystatechange = function(){
				    if (this.readyState == "complete"){
					    init();
					  }
				  };
			  }
      }else if (document.readyState && /WebKit/i.test(navigator.userAgent)){ // for Safari      
        load_timer = setInterval(function() {
          if (/loaded|complete/.test(document.readyState))
            init(); // call the onload handler
          }, 30);          
      }else if(document.addEventListener){// for other browsers
        document.addEventListener("DOMContentLoaded", init, false);        
      }else{
        old_onload = window.onload;
        window.onload = function() {
          init();
          if (old_onload) old_onload();
        };
      }
    }
    load_events.push(func);
  }
})();

/* opacity  */
function setOpacity(obj,xOpacity){
  var zOpacity = (xOpacity >= 1)? 1 : Math.round(xOpacity*100)/100;
  obj.style.opacity = zOpacity;
	obj.style.MozOpacity = zOpacity;
	obj.style.KHTMLOpacity = zOpacity;
	obj.style.filter = 'alpha(opacity=' + (xOpacity*100) + ')';
	if(xOpacity>0.95 && window.ie) obj.style.removeAttribute('filter');
};


// Javascript Fx Functions
function Fx(){
  
  this.options = {
		duration:1000,
    curve:['cos',4],
    lightbox:false
	};
	
	this.initialize = function(el,options){
	  if(el[0]){
	    this.multi = true;
      this.element = el;
	  }else{
      this.element = [];
	    this.element[0] = el;
	  }
	  for(var property in options)this.options[property] = options[property];	
    if(!this.options.curve[1])this.options.curve[1]=null;	
	};
	
	this.setFx = function(e,p,c){
	  for (var i = 0, l = this.property[e].length; i < l; i++){
      if(this.isColor[e][i]){
        var color = [];
        for (var j = 0;j < 3; j++)
          color.push(Math.round((this.to[e][i][j]-this.from[e][i][j])*this.effect(p,c)+this.from[e][i][j]));
        this.element[e].style[this.property[e][i]] = 'rgb(' + color.join(',') + ')';
      }else if(this.property[e][i]=='backgroundPosition'){
        var xPos = Math.round((this.to[e][i][0]-this.from[e][i][0])*this.effect(p,c)+this.from[e][i][0]);
        var yPos = Math.round((this.to[e][i][2]-this.from[e][i][2])*this.effect(p,c)+this.from[e][i][2]);
        this.element[e].style[this.property[e][i]] = xPos+this.to[e][i][1]+' '+yPos+this.to[e][i][3];
      }else{
        this.setStyle(e,this.property[e][i],(this.to[e][i]-this.from[e][i])*this.effect(p,c)+this.from[e][i]);
      }
    }
	};
	
	this.step = function(e){
		var time = new Date().getTime();
		if (time < this.time + this.options.duration){
		  var p=(time - this.time)/this.options.duration, c=this.options.curve[1];
      if(this.multi){
        for(var d in e) this.setFx(d,p,c);
      }else this.setFx(e,p,c);
		}else{		  
			clearInterval(this.timer);
			if(this.multi){
        for(var d in e) this.set(d)
      }else this.set(e);
      if(this.callBack){ 
        if(!this.done) this.callBack.call();
        this.done = true;
      }
		}
	};
	
	this.set = function(e){
	  for (var i=0, l=this.property[e].length; i<l; i++){
      this.setStyle(e,this.property[e][i],this.to[e][i]);
    }
  };
  
  this.setStyle = function(e,prop,style){
    if(prop == 'opacity')setOpacity(this.element[e],style);
    else this.element[e].style[prop] = Math.round(style)+'px';
  };

	this.start = function(par,action){
	  if(this.timer)clearInterval(this.timer);//security
    this.done = false;
    this.property = [];
    this.from = [];
    this.to = [];
    this.add = [];
    this.isColor = [];  
		this.callBack = (action)? action : false;
		this.effect = this.transition[this.options.curve[0]];	
		this.time = new Date().getTime();
		if(this.multi){
		  var e = par;
      for(var i in par) this.setFromTo(par[i],i);
    }else{
      var e = 0;
      this.setFromTo(par,0);
    }
    this.timer = setInterval(function(fn){		
      return function(){
        fn.step(e);
      }     
    }(this),20);
	};
	
	this.setFromTo = function(par,i){
	  this.property[i] = [];
	  this.from[i] = [];
		this.to[i] = [];
		this.isColor[i] = [];
    for(var prop in par){
	    this.property[i].push(prop);
	    if(prop.match(/color/i)){
        this.isColor[i].push(true);
	      this.from[i].push(this.getColor(par[prop][0]));
	      this.to[i].push(this.getColor(par[prop][1]));
	    }else if(prop=='backgroundPosition'){
	      this.isColor[i].push(false);
	      this.from[i].push(this.getBackgroundPos(par[prop][0]));
	      this.to[i].push(this.getBackgroundPos(par[prop][1]));
      }else{
        this.isColor[i].push(false);
	      this.from[i].push(parseFloat(par[prop][0]));
	      this.to[i].push(parseFloat(par[prop][1]));
	    }    
	  };
  };

  /* Easing Equations by Robert Penner, <http://www.robertpenner.com/easing/>  */
	this.transition = {
	  linear: function(p){return p;},
	  cos: function(p){return -(Math.cos(Math.PI * p) - 1) / 2;},		
		easeIn:function(p,c){return Math.pow(p,c);},
		easeOut:function(p,c){return 1 - Math.pow(1 - p,c);},
	  easeInOut:function(p,c){return (p <= 0.5) ? Math.pow((2 * p),c) / 2 : (2 - Math.pow(2 * (1 - p),c)) / 2;},
    Back: function(p,c){return 1 - (Math.pow((1-p), c) * ((1.68 + 1) * (1-p) - 1.68));},
	  circIn: function(p){return 1 - Math.sin(Math.acos(p));},
	  circOut: function(p){return 1 - (1 - Math.sin(Math.acos(1 - p)));}
  };
  
  /* @author Alexander Farkas http://www.corrupt-system.de/jquery/backgroundPosition/ */
  this.getBackgroundPos = function(pos){
    pos = pos.replace(/left|top/g,'0px');
    pos = pos.replace(/right|bottom/g,'100%');
    pos = pos.replace(/(\d+)(\s|\)|$)/g,"$1px$2");
    var res = pos.match(/(\d+)(px|\%|em|pt)\s(\d+)(px|\%|em|pt)/);
    return [parseFloat(res[1]),res[2],parseFloat(res[3]),res[4]];
  };
  
  this.getColor = function(color){
    var c = color.replace('#','');
    if(color.match(/(rgb)/)){
      var r = color.match(/\d{1,3}/g);
      return [parseInt(r[0]),parseInt(r[1]),parseInt(r[2])];
    }
    return [parseInt(c.substring(0,2),16),parseInt(c.substring(2,4),16),parseInt(c.substring(4,6),16)];
  };

};

