//some components from my favorite library ztools
 
 /**
  * static class with some useful methods
  * "nest" for all other classes
  */
  
 /**
  * static class with some useful methods
  * "nest" for all other classes
  */
function z(s){ //
  if (typeof(s)==='string'){
    return z.id(s);
  }
  else {
    return z.get(s);
  }
}
  

/**
 * returns Element if element is exists
 */
z.id = function(id){
     return z.Element.id(id);
};
   
z.get = function(el){
     return z.Element.get(el);
};
   
/**
 * copy all properties except prototype
 */
z.copy = function(dst,src){
      for(key in src){
        if (key!=='prototype'){
          dst[key] = src[key];
        }
      }
};

z.each = function(obj,fn){
        for(key in obj){
            if (obj.constructor.prototype[key]!==obj[key]){
                if (fn(key,obj[key])===false) break;
            }
        }
};
   
z.request = function(){
        try {
            return new ActiveXObject('MSXML2.XMLHTTP');
        }
        catch(e){};
        try {
            return new XMLHttpRequest();
        }
        catch(e){}
};
      
z.loadJS = function(url){
        r = z.request();
        r.open('get',url,false);
        r.send(null);
        if (window.execScript){
            window.execScript(r.responseText);
        } else {
            var script = document.createElement('script');
            script.setAttribute('type', 'text/javascript');
            script.text = r.responseText;
            var head = document.getElementsByTagName('head')[0];
            head.appendChild(script);
            head.removeChild(script);
        }
}; 
/**
 * experimental
 */    
z.bind = function(fn,obj){
      return function(){
        return fn.apply(obj,arguments);
      }
} 
 
 
 /**
  * inhetitance in JavaScript
  */
z.Class = function(){};
z.base = null;
z.Class.extend = function(obj){
    var this1 = this;
    var obj1 = function(){
        if (obj.construct!==undefined){
            obj.construct.apply(this,arguments);
        }
        else {
            if (this1.prototype.construct!==undefined){
                this1.prototype.construct.apply(this,arguments);
            }
        }
    }

    z.copy(obj1.prototype,this.prototype);
    z.copy(obj1.prototype,obj);
    z.copy(obj1,this);

    var old_constr = this1.prototype.construct;
    obj1.prototype.base = function(){
        if (this1.prototype.base){
            this.base = this1.prototype.base;
        }
        old_constr.apply(this,arguments);    
    };
    return obj1;
}

z.Class.implement = function(obj){
    z.copy(this.prototype,obj);
}   
 
 
/**
 * cross browser manitulations with element properties, events, styles
 */
z.Element = z.Class.extend({
    origin:null,
    events:{},
    construct:function(origin){
        origin._z = this;
        this.events = {};
        this.origin = origin;        
        this.css = this.style;
        this.p = this.prop;
    },
       
    /*
    shortEvents:function(names){
        var i = 0;
        for(i=0;i<names.length;i++){
            this[names[i]] = new Function("fn","remove","this.on('"+[names[i]]+"',fn,remove)");
        }
    },
    */
   /**
    * add event listener
    */   
    on:function(eventname,func,remove){
        	if (remove) return this.removeEvent(eventname,func);
        	if (!this.events[eventname]) {	
     	    	this.events[eventname] = [];
     	    	var t1 = this;
     	    	if (this.origin.addEventListener){
                	this.origin.addEventListener(eventname, function(e){t1.fireEvent(eventname,e)},false);
            	}
            	else {
                	this.origin.attachEvent('on'+eventname, function(e){t1.fireEvent(eventname,e)});
            	}
        	};
        	this.events[eventname].push(func);
    },         
   
    fireEvent:function(eventname,e){
        var hooks;
        if (e){
            e = z.Event.get(e);
        }
        else {
            e = z.Event.get(window.event);
        }
        e.owner = this;
        if (hooks = this.events[eventname]) {
     	    for(var i=0;i<hooks.length;i++){
     		    hooks[i].apply(this,[e]);
     	    }
        }
    },
   
  /**
   * removes event
   */
    removeEvent:function(eventname,func){
        if (this.events[eventname]){
            var found=false,i,len = this.events[eventname].length;
            for (i=0;i<len;i++){                
                if (this.events[eventname][i]==func){
                    found = i;                    
                    break;
                }
            }
            if (found!==false) {
                this.events[eventname].splice(found,1);
            }
        }
    },
   /**
    * sets or gets style
    * to make all similar functions to be built similar way?
    */
    style:function(key_name,key_value){
        if(arguments.length==2){
            try {
                this.setStyle(key_name,key_value);
            }
            catch(e){
                alert("wrong property:"+key_name+":"+key_value);
            }
        }
        else {
            if (typeof(key_name)=='object'){
                var this1 = this;
                z.each(key_name,function(key){
                    this1.style(key,key_name[key]);
                });
            } 
            else {
                return this.getStyle(key_name);
            }
        }
    },    
    setStyle:function(key_name,key_value){
        if (Object.isIE && (key_name=='opacity')){
            this.origin.style.filter = "alpha(opacity:"+(key_value*100)+")";
        }
        else {
            this.origin.style[key_name] = key_value;
        }
    },
   /*
    * returns style
    * TODO make it crossbrowser too?
    */
    getStyle:function(key_name){
        return this.origin.style[key_name];
    },
    
   /**
    * sets or retrieve property
    *
    */
    prop:function(key_name,key_value){
        if(arguments.length==2){
            this.setProp(key_name,key_value);
                
        }
        else {
            if (typeof(key_name)=='object'){
                var this1 = this;
                z.each(key_name,function(key){
                    this1.prop(key,key_name[key]);
                });
            } 
            else {
                return this.getProp(key_name);
            }
        }    
    },

   /**
    * sets property
    */
    setProp:function(key_name,key_value){
        try {
            this.origin[key_name] = key_value;        
        }
        catch(e){
            alert("wrong property:"+key_name+":"+key_value);
        }
    },
   /*
    * returns property
    * TODO make it crossbrowser too?
    */
    getProp:function(key_name){
        if (key_name=='text') return (this.origin['text'] || this.origin['innerText']); 
        return this.origin[key_name];
    },    
    //credits of prototype lib
    hasClass:function(className){
        return z.Element.hasClass(this.origin.className,className)
    },
    addClass:function(className){
        if (!this.hasClass(className)){
            this.origin.className = this.origin.className+' '+className;
        }
    },
    removeClass:function(className){
        this.origin.className = this.origin.className.replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)'), '$1');
    },
        
    putBefore:function(el){
        if (el.origin) el = el.origin //it's z.Element
        el.parentNode.insertBefore(this.origin,el);
    },
            
    putAfter:function(el){
        if (el.origin) el = el.origin //it's z.Element
        if (el.nextSibling){
            el.parentNode.insertBefore(this.origin,el.nextSibling);
        }
        else {
            el.parentNode.appendChild(this.origin);
        }
    },
    putInto:function(el){
        if (el.origin) el = el.origin //it's z.Element
        el.appendChild(this.origin);
    },
    //the same as ordinal appand child but argument can be also an array
    appendChild:function(el){
        if (el.origin) el = el.origin //it's z.Element
        if (el.constructor === Array) {
          var i,len = el.length;
          for(i=0;i<len;i++){
            this.appendChild(el[i]);
          }
          return;
        }
        this.origin.appendChild(el);
    },
    remove:function(el){
        if (el) {
            if (el.origin)  el = el.origin //it's z.Element
        }
        else el = this.origin;        
        el.parentNode.removeChild(el);
    }
});

z.Element.shortEvents = function(names){
   var events = {}
   z.each(names,
	    function(key,event){
	    	events[event] = new Function("fn","remove","this.on('"+[event]+"',fn,remove)");
	    }
   )
   this.implement(events);
}

z.Element.shortEvents(['click','mousedown','mouseup','mousemove','mouseover','mouseout','focus','blur','change','keypress','keydown','keyup']);

 
z.Element.get = function (e){
 	if (e._z!==undefined) return e._z;
    return new this(e);
};

z.Element.id = function(id){
    var e = document.getElementById(id);
    if (e){
       return this.get(e);
    }
    return null;
}

z.Element.hasClass = function(elementClassName,className){
    return (elementClassName.length > 0 && (elementClassName == className ||
            new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
}

z.Element.create = function(name,props,styles,children){
    var el = z.Element.get(document.createElement(name));
    if (props) el.prop(props);
    if (styles) el.style(styles);
    if (children) el.appendChild(children)
    return el;
};

/**
 * 
 */
z.Element.implement({
    getCoordinates:function(){
        function getPOL(obj){
            var x;
            x = obj.offsetLeft;
            if (obj.offsetParent != null)
            x += getPOL(obj.offsetParent);
            return x;       
        };
        function getPOT(obj){
            var y;
            y = obj.offsetTop;
            if (obj.offsetParent != null)
            y += getPOT(obj.offsetParent);
            return y;
        };
        return {top:getPOT(this.origin),left:getPOL(this.origin),width:this.origin.clientWidth,height:this.origin.clientHeight};
    }
});

/**
 * XHTML Selector
 */
 
(function(){
   /**
    * if element is complies with search it get applied to res
    *
    */
    function appendResult(search,el,res,constr){//private function
        var fail = false;
        z.each(search, function(key){
            if (key=='depth') return;
            if (key=='tag' || key=='tagName') { //tag name is case insensitive
                if (el.tagName.toUpperCase()!=(search[key]).toUpperCase()){
                  fail = true;
                  return false;
                }
                return;
            }
            if (key=='class'){
                if (!z.Element.hasClass(el.className,search['class'])){
                  fail = true;
                  return false;
                }
                return;
            }
            if (!el[key]) {fail = true; return false;};
            if (el[key]!==search[key]) {fail = true; return false;};
        });
        if (fail) return;
        res.elements.push(constr.get(el));
        
    };
    
    function selectElement(el, search, res, constr){
    	constr = constr || z.Element;
    	
        var tagname = search['tagName'] || search['tag'];// || 'div'; //shorthands
        var depth = search['depth'] || -1; //-1 recursive, 1 - only first level childs, 2 frist level and second level and so on
        
        if ((tagname) && (depth===-1)){
            var els = el.getElementsByTagName(tagname);
            var i,els_l = els.length;        
            for(i=0;i<els_l;i++){
                appendResult(search,els[i],res,constr);     
            }
        }
        else { //all elements
            var child;
            for(child = el.firstChild;child;child = child.nextSibling){
                if (child.nodeType!=1) continue; //need only elements
                appendResult(search,child,res,constr);
                if (depth === -1) selectElement(child, search, res, constr);
                else if (depth > 1) {search[depth] = depth--; selectElement(child, search, res, constr)} 
            }
        }
    };
    
    z.Element.implement({
        select:function(search,result,constr){
            var res = result || (new z.CompoundElement());
            selectElement(this.origin,search,res,constr);
            return res;
        },
        children:function(search,result,constr){
            search['depth'] = 1;
            return this.select(search,result,constr); 
        }    
    });
})();
 
z.select = function(search){
    return z.Document.select(search);
} 
 
z.CompoundElement = z.Class.extend({
    elements:[], //list of z.Element items
    construct:function(){
        this.elements = [];
    },
   /**
    * selects among all children
    */
    select:function(search, result){
        var result = result || new z.CompoundElement();
        var i,len = this.elements.length;
        for(i=0;i<len;i++){
            this.elements[i].select(search, result);
        }
        return result;
    },
   /**
    * selects among all children
    */
    children:function(search, result){
        search['depth'] = 1;
        return this.select(search,result1); 
    },    
   /**
    * call function for each element
    */
    each:function(fn){
        //var args = args || []
        var i,len = this.elements.length;
        for(i=0;i<len;i++){
            if (fn.apply(this.elements[i],[this.elements[i]])===false) 
                break;
        }
    },
   /**
    *
    */
    get:function(key){
        return this.elements[key];
    } 
}); 
/**
 * 
 */ 
(function(){
    var events = {
		on:function(eventname,fn,remove){
			this.each(function(el){
				el.on(eventname,fn,remove);
			})
		},
		addClass:function(className){
		    this.each(function(el){
                el.addClass(className);
            })
		},
	    removeClass:function(className){
            this.each(function(el){
                el.removeClass(className);
            })
        }
    }
	z.each(['click','mousedown','mouseup','mousemove','mouseover','mouseout','focus','blur','change','keypress','keydown','keyup'],
	    function(key,event){
	    	events[event] = new Function("fn","remove","this.on('"+[event]+"',fn,remove)");
	    }
	)
	z.CompoundElement.implement(events);
})();


 
/**
 * cross browser event object
 */

z.Event = z.Class.extend({
    origin:null,
    owner:null,
    construct:function(e){
        this.origin = e;
        e._z = this;
     
        this.shift = e.shiftKey,
        this.ctrl  = e.ctrlKey,
        this.alt   = e.altKey,
        this.meta  = e.metaKey
    },
   /**
    * get Page coordinates
    */
    page:function(){
        var doc = document;
            doc = (!doc.compatMode || doc.compatMode == 'CSS1Compat') ? doc.documentElement : doc.body;
        
        return {
            x: this.origin.pageX || this.origin.clientX + doc.scrollLeft,
            y: this.origin.pageY || this.origin.clientY + doc.scrollTop
        };
    },
   /**
    * get key code
    */
    keyCode:function(){
        return this.origin.which || this.origin.keyCode;
    },
    
    keyCodes:{
        '13':'enter',
        '38':'up',
        '40':'down',
        '37':'left',
        '39':'right',
        '27':'esc',
        '32':'space',
        '8':'backspace',
        '9':'tab',
        '46':'delete'
    },
    
   /**
    *
    */
    key:function(){
        var code = this.keyCode();
        var key = this.keyCodes[code];
        if (this.origin.type == 'keydown'){
                var fKey = code - 111;
                if (fKey > 0 && fKey < 13) key = 'f' + fKey;
        }
        key = key || String.fromCharCode(code).toLowerCase();
        return key;    
    },
   /**
    * stops booble
    */
    stop:function(){
        if (this.origin.stopPropagation){
            this.origin.stopPropagation();
        }
        else {
            this.origin.cancelBubble = true;//ie
        }
    },
   /**
    * cancels default behaviour
    */
    cancel:function(){
        if (this.origin.stopPropagation){
            this.origin.preventDefault();
        }
        else {
            this.origin.returnValue = false;//ie
        }
    },
    halt:function(){
        this.stop();
        this.cancel();
    }
});

z.Event.get = function(e){
  if (e._z) return e._z;
  return new z.Event(e);
}

 
/**
 * Browser detection
 *
 */
z.Browser = {
	Engine: {name: 'unknown', version: ''},
	Platform: {name: (navigator.platform.match(/mac|win|linux/i) || ['other'])[0].toLowerCase()}
};

if (window.opera) z.Browser.Engine = {name: 'presto', version: (document.getElementsByClassName) ? 950 : 925};
else if (window.ActiveXObject) z.Browser.Engine = {name: 'trident', version: (window.XMLHttpRequest) ? 5 : 4};
else if (!navigator.taintEnabled) z.Browser.Engine = {name: 'webkit', version: (!!(document.evaluate)) ? 420 : 419};
else if (document.getBoxObjectFor != null) z.Browser.Engine = {name: 'gecko', version: (document.getElementsByClassName) ? 19 : 18};
z.Browser.Engine[z.Browser.Engine.name] = z.Browser.Engine[z.Browser.Engine.name + z.Browser.Engine.version] = true;
if (window.orientation != undefined) z.Browser.Platform.name = 'ipod';
z.Browser.Platform[z.Browser.Platform.name] = true;

/**
 * domready event
 */
z.Document = {
    isReady:false,
    queue:[],    
    bind:function(){
		// Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
		// If IE is used and is not in a frame
		// Continually check to see if the document is ready
		if ( z.Browser.Engine.trident && window == top ) (function(){
			if (this.isReady) return;
			try {
				// If IE is used, use the trick by Diego Perini
				// http://javascript.nwbox.com/IEContentLoaded/
				document.documentElement.doScroll("left");
			} catch( error ) {
				setTimeout( arguments.callee, 0 );
				return;
			}
			// and execute any waiting functions
			z.Document.invokeQueue();
		})();
		if ( z.Browser.Engine.presto || z.Browser.Engine.webkit ) {
			var numStyles;
			(function(){
				if (this.isReady) return;
				if ( document.readyState != "loaded" && document.readyState != "complete" ) {
					setTimeout( arguments.callee, 0 );
					return;
				}
				z.Document.invokeQueue();
			})();
			return;
		}
		if (document.addEventListener){
  			document.addEventListener( "DOMContentLoaded", function(){z.Document.invokeQueue()}, false );
		}
    },
    invokeQueue:function(){
    	this.isReady = true;
      	var i;
      	for (i=0;i<this.queue.length;i++){
        	var f = this.queue[i];
        	f();
      	}
    },
    ready:function(f){
		if (this.isReady) {
   	 		f();
    	}
    	else {
	  		this.queue.push(f);
    	}
  	}
}
z.copy(z.Document,new z.Element(document));
z.Document.bind();

/**
 * debugger
 */
z.console = {
  log:function(msg){
    if (typeof(console)!=='undefined'){
        console.log("%s",msg);
    } 
    else {
        Debugger.trace(msg);
    }
  }
}

z.log = function(m){
  z.console.log(m);
};

/**
 * inputs
 * thanks to prototype
 */
z.Form = z.Element.extend({
    getValues:function(){
        //var objForm;
        var submitDisabledElements=false;
        if(arguments.length > 1 && arguments[1]==true)
            submitDisabledElements=true;var prefix="";
        if(arguments.length > 2)
            prefix=arguments[2];
        var values = {};
            var formElements=this.origin.elements;
            for(var i=0;i < formElements.length;i++){
                if(!formElements[i].name) continue;
                if(formElements[i].name.substring(0,prefix.length)!=prefix) continue;
                if(formElements[i].type && (formElements[i].type=='radio' 
                || formElements[i].type=='checkbox') && formElements[i].checked==false) continue;
                if(formElements[i].disabled && formElements[i].disabled==true && submitDisabledElements==false) continue;
                var name=formElements[i].name;
                if(name){
                    values[name] = formElements[i].value;
                }
            }
        //}
        return values;
    }
});

z.Element.shortEvents(['submit']); //onsubmit event

z.Form.get = function (e){
    if (e._z!==undefined) return e._z;
    return new z.Form(e);
};

z.delay = function(fn,timeout,autostart,repeat){
    var d = new z.Delayer(fn, timeout,(autostart===false?false:true), repeat);
    return d;
};

z.Delayer = z.Class.extend({
    fn:null,
    delay:null,
    repeat:false,
    timeout:null,
    construct:function(fn, delay, autostart, repeat){
        this.fn = fn;
        this.delay = delay;
        this.repeat = repeat;
        if (autostart) this.call();
    },
    start:function(){
        this.stop();
        this.call();
    },
    call:function(){
        var this1 = this;
        this.timeout = window.setTimeout(function(){
        	this1.callTimeout();
        },this.delay);
    },
    callTimeout:function(){    
        this.fn();
        if (this.repeat && (this.timeout!==null)){ //if timeout==null that means amimation was stoppend
            this.call();
        }
        else {
            this.timeout = null;
        }
    },
    stop:function(){
        if (this.timeout){
            window.clearTimeout(this.timeout);
            this.timeout = null;
        }
    }
});


function validateEmail(email) {
  var splitted = email.match("^(.+)@(.+)$");
  if(splitted == null) { alert('Please enter a valid email address.'); return false; }
  if(splitted[1] != null ) {
    //var regexp_user=/^\"?[\w-_\.]*\"?$/;
    var regexp_user=/^\"?^[A-Za-z0-9._%-]*\"?$/;
    if(splitted[1].match(regexp_user) == null) { alert('Please enter a valid email address.'); return false; }
  }
  if(splitted[2] != null) {
    var regexp_domain=/^[\w-\.]*\.[A-Za-z]{2,6}$/;
    //var regexp_domain=/^[\w-\.]*\.[A-Za-z]{2,4}$/;
    if(splitted[2].match(regexp_domain) == null) {
      var regexp_ip =/^\[\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\]$/;
      if(splitted[2].match(regexp_ip) == null) { alert('Please enter a valid email address.'); return false; } else return true;
      }// if
    return true;
  }
  return false;
}

function emailIsValid(email){
  return validateEmail(email)
}

function validateContactForm(form){
  if (form.Email.value==''){
    alert('Please enter your email');
    form.Email.focus();
  	return false;
  }
  if (!emailIsValid(form.Email.value)){
    form.Email.focus();
    return false;
  }
  if (form.Description.value==''){
    alert('Please enter your message');
    form.Description.focus();
    return false;
  }
  return true;
}

//look for contact form and change retUrl value according current url
z.Document.ready(function(){
    var forms = z.Document.select({'tag':'form','class':'contact_form'});
    forms.each(function(form){
        if (typeof(form.origin.returnURL)!=='undefined')
  	    form.origin.returnURL.value = form.origin.returnURL.value+'?url='+encodeURIComponent(document.location.href);  
    })
    
    var downloadform = z.id("downloadform");
    if (downloadform){
      var form = downloadform.select({'tag':'form'},null,z.Form).get(0);
      form.submit(function(e){
    	if (this.origin.Company.value==''){
		    alert('Company, name and email are required');
		    this.origin.Company.focus();
		    e.halt();
    	}
    	else if (this.origin['Last Name'].value==''){
		    alert('Company, name and email are required');
		    this.origin['Last Name'].focus();
		    e.halt();
    	}
    	else if (this.origin.Email.value==''){
    		alert('Company, name and email are required');
    		this.origin.Email.focus();
    		e.halt();
    	}    	
    	else if (!emailIsValid(this.origin.Email.value)){
    		this.origin.Email.focus();
    		e.halt();
    	}
      });
    }
  
    var links = z.Document.select({'tag':'div','class':'subhdr_txt_rgt'}).select({'tag':'a'});
    
    i = 2;
    links.each(function(e){
        if (this.p('onclick')){        
            this.mouseover(function(){
				var i = 2;
    			links.each(function(e){
        			if (this.p('onclick')){        
            			this.addClass('hover');
            			i++;
        			}
    			});            	            	
            });
            this.mouseout(function(){
            	var i = 2;
    			links.each(function(e){
        			if (this.p('onclick')){        
            			this.removeClass('hover');
            			i++;
        			}
    			});  
            });            
            i++;
        }
    });

    
  
});
