/**
* Centryl - centralize your business
* http://www.centryl.bg
* Copyright (c) 2011 Centryl Ltd
*
* License
*/
Object.extend = function(destination, source) {
    for (var property in source)
        if(!destination[property])
            destination[property] = source[property];
    return destination;
};
Object.extend(Function.prototype, {
    bind: function() {
        var method = this;
        var slice = Array.prototype.slice;
        var args = slice.call(arguments), obj = args.shift();
        return function() {
            return method.apply(obj, args.concat(slice.call(arguments)));
        }
    }
});
Object.extend(Array.prototype, {
    forEach: function(func) {
        (function (a, func) {
            for(var i=0,l=a.length;i<l;i++)
                func(a[i], i);
        })(this,func);
    }
});
var cl = {
    toArray: function(o) {
        var arr=[];
        for(var i=0,l=o.length;i<l;i++) 
            arr.push(o[i]);
        return arr;
    },
    centerElCoords: function(el) {
        var width = this.getDimensions(el).width;
        var height = this.getDimensions(el).height;
        var docElement = document.documentElement;
        var page_center_x = docElement.clientWidth/2+docElement.scrollLeft;
        var page_center_y = docElement.clientHeight/2+docElement.scrollTop;
        return {
            y:parseInt(page_center_y-height/2),
            x:parseInt(page_center_x-width/2)
        };
    },
    getPosition: function(element) {
        var valueT = 0, valueL = 0;
        do {
            valueT += element.offsetTop - element.scrollTop || 0;
            valueL += element.offsetLeft - element.scrollLeft || 0;
            element = element.offsetParent;
        } while (element);
        return {
            y:valueT,
            x:valueL
        }
    },
    pointer: function(event) {
        var docElement = document.documentElement,
        body = document.body || {scrollLeft: 0, scrollTop: 0};
        return {
            x: event.pageX || (event.clientX + docElement.clientLeft),
            y: event.pageY || (event.clientY + docElement.scrollTop)
        };
    },
    addEvent: function(element,event,func) {
        element = this.$(element);
        if (element.addEventListener) {
            element.addEventListener (event,func,false);
        } else if (element.attachEvent) {
            element.attachEvent ('on'+event,func);
        } else
            return false;
    },
    removeEvent: function(element,event,func) {
        element = this.$(element);
        if (element.removeEventListener) {
            element.removeEventListener(event, func, false)
        }
        else if (element.detachEvent) {
            element.detachEvent('on'+event, func)
        }
        else
            return false;
    },
    stop: function(event) {
        if(event.preventDefault)
            event.preventDefault();
        if(event.stopPropagation)
            event.stopPropagation();
        event.stopped = true;
    },
    getStyle: function(el, css) {
        var strValue = "";
	if(document.defaultView && document.defaultView.getComputedStyle) {
            strValue = document.defaultView.getComputedStyle(el, "").getPropertyValue(css);
	}
	else if(el.currentStyle) {
            css = css.replace(/\-(\w)/g, function (strMatch, p1){return p1.toUpperCase();});
            strValue = el.currentStyle[css];
	}
	return strValue;
    },
    getDimensions: function(element) {
        element = this.$(element);
        return {
            width: element.offsetWidth,
            height: element.offsetHeight
        };
    },
    $: function(obj) {
        if(typeof obj == 'string')
            return document.getElementById(obj)
        return obj;
    },
    dc: function(tag) {
        return document.createElement(tag);
    },
    getElementsByClassName: function(className, elm, arr) {
	var testClass = new RegExp("(^|\\s)" + className + "(\\s|$)");
	var elm = this.$(elm) || document;
	var elements = elm.getElementsByTagName('*');
	var returnElements = [];
	var current;
	var length = elements.length;
	for(var i=0; i<length; i++){
            current = elements[i];
            if(testClass.test(current.className)){
                returnElements.push(current);
            }
	}
        if(returnElements.length==1 && !arr)
            return returnElements[0];
	return returnElements;
    },
    addStyle: function (el,styles) {
        for(var i in styles)
            el.style[i] = styles[i];
        return el;
    },
    setStyle: function (el,styles) {
        if(styles['cssFloat'] && document.all) {
            styles['styleFloat'] = styles['cssFloat'];
            delete styles['cssFloat'];
        }
        for(var i in styles) {
            el.style[i] = styles[i];
        }
        return el;
    },
    evalJson: function(json) {
        if(window.JSON && ("function" === typeof window.JSON.parse))
            return JSON.parse(json)
        else
            return eval('('+json+')');
    },
    toJSON: function(input){
        switch (typeof input) {
          case 'string':return '"' + encodeURIComponent(input.replace(/(\")|(\')/g,"\\\"")) + '"';
          case 'number':return input.toString();
          case 'boolean':return input.toString();
          case 'object':
                if(input === null)
                    return '"' + input + '"';
                var buf = [];
                if ('splice' in input && 'join' in input) {
                    for(var i=0,l=input.length;i<l;i++)
                        buf.push(this.toJSON(input[i]));
                    return '[' + buf.join(', ') + ']';
                }
                for (var k in input)
                  buf.push('"'+ k + '" : ' + this.toJSON(input[k]))
                    return '{ ' + buf.join(', ') + '} ';
          default:
                return 'null';
        }
    },
    ajax: {
        getXHR: function() {
           var ids = ['Msxml2.XMLHTTP',
                      'Microsoft.XMLHTTP'];
           try {
               return new XMLHttpRequest();
           } catch(e) {};
           for (var i=0;i<ids.length;i++) {
               try{
                   return new ActiveXObject(ids[i]);
                   break;
               } catch(e) {};
           }
        },
        send: function(url,pars,func,method) {
            var xhr = this.getXHR();
            xhr.onreadystatechange = (function(_this,myxhr,func) {
                return function(){_this.changeState(myxhr,func)};
            })(this,xhr,func);
            if(method && method.toUpperCase()=='GET') {
                url += '?'+pars;
                pars = '';
            }
            else
                method = 'POST';
            xhr.open(method, url, true);
            xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
            xhr.send(pars);
        },
        changeState: function(xhr,func) {
            if (xhr.readyState < 4)
                return false;
            if (xhr.status !== 200)
                return false;
            func(xhr);
        }
    },
    blurPage: function(el) {
        var blur = this.$("blurPage");
        if (blur) {
            document.body.removeChild(blur);
            return;
        }
        var el = (el)? this.$(el) : this.$(document.body);
        var pos = this.getPosition(el);
        var dims = this.getDimensions(el);
        var blur = this.dc("div");
        blur.id = 'blurPage';
        this.addStyle(blur,{
            position:'absolute',
            zIndex:'996',
            position:'absolute',
            top:pos.y+"px",
            left:pos.x+"px",
            background:'#000000',
            opacity:'0',
            filter:'alpha(opacity=0)',
            width:dims.width+"px",
            height:dims.height+"px"
        })
        document.body.appendChild(blur);
        this.animations().add(500,'',0,{obj:blur,prop:{opacity:[0,0.2]}}).animate();
        return blur;
    },
    animations: function () {
        function Animation() {
            this.interval = 20;
            this.delay = 0;
            this.frame = [];
            this.timer = [];
            this.func = function(){};
        }
        Animation.prototype = {
            add: function(duration,effect,wait){
                var objects = [];
                for(var i=0;i<arguments.length;i++)
                    objects.push(arguments[i]);
                objects.splice(0, 3);
                this.delay = wait || 0;
                var easing = this.fx[effect] || this.fx.easeInOutQuad;
                var totalFrames = Math.ceil(duration/this.interval);
                for(var i=0;i<=totalFrames;i++) {
                    this.frame[i] = [];
                    for(var j=0;j<objects.length;j++) {
                        var a = {};
                        for(var p in objects[j].prop)
                            a[p] = easing(this.interval*i,objects[j].prop[p][0],objects[j].prop[p][1]-objects[j].prop[p][0],duration);
                        this.frame[i][this.frame[i].length] = {
                            obj:objects[j].obj,
                            sets:a
                        }
                    }
                }
                return this;
            },
            animate: function() {
                for(var i=0,l=this.frame.length;i<=l;i++) {
                    var func = (i==l)? this.func.bind(func) : this.set.bind(this,this.frame[i]);
                    (function(func,delay) {
                        this.timer[this.timer.length] = setTimeout(func,delay);
                    }.bind(this))(func,this.delay+i*this.interval);
                }
                return true;
            },
            stop: function() {
                this.timer.forEach(function(t) {
                    window.clearTimeout(t);
                });
            },
            set: function(frm) {
                for(var i=0,l=frm.length;i<l;i++) {
                    var cur_frm = frm[i];
                    for(var p in cur_frm.sets) {
                        var obj = cur_frm.obj;
                        var set = cur_frm.sets[p];
                        if(p=='opacity') {
                            obj.style.filter = "alpha(opacity="+set*100+")";
                            obj.style.opacity = set;
                            continue;
                        }
                        if(p=='scrollTop' || p=='scrollLeft') {
                            obj[p] = set;
                            continue;
                        }
                        obj.style[p] = set+'px';
                    }
                }
                return true;
            },
            fx: {
                easeInOutQuad: function (t, b, c, d) {
                    if ((t/=d/2) < 1) return c/2*t*t + b;
                    return -c/2 * ((--t)*(t-2) - 1) + b;
                }
            }
        }
        return new Animation();
    }
}
