/* 
	j123 -- JavaScript common library
	mail: sebastian.hanula@gmail.com
	www:  http://www.hanula.com/lab/j123

	j123 core library
*/


j123 = {
	ver : { major:0,minor:1},
	
	onInitFunctions:[],
	registerOnInit : function(fn) {
		this.onInitFunctions.push(fn);
	},
	
	init: function() {
		for(var i=0;i<this.onInitFunctions.length;i++) {
			this.onInitFunctions[i]();
		}
	},
		
	extend: function(dst,src) {
		for(prop in src) {
			dst[prop] = src[prop];
		}
		return dst;
	}
}



j123.browser = {
	isIE : null,
	isOpera:null,
	
	init : function() {
		var ua = navigator.userAgent.toLowerCase(); 
		j123.browser.isIE = (ua.indexOf('msie') != -1);
		j123.browser.isOpera  = (ua.indexOf('opera') != -1); 
	}	
};
j123.registerOnInit(j123.browser.init);


j123.common = {
	each : function(arr,fn) {
		for(var i=0;i<arr.length;i++) fn(arr[i]);
	},
	init: function() {
				
	}
};
j123.registerOnInit(j123.common.init);


/////////// 		HTML 

function $(x){ return document.getElementById(x);}

function findPosX(obj) {
	var curleft = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curleft += obj.offsetLeft
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
		curleft += obj.x;
	return curleft;
};

j123.HTML = {
	showElement : function(el) {
		if(j123.browser.isIE) {
			
		}
		el.style.visibility.display = 'visible';
	},
	hideElement: function(el) {
		el.style.visiblity = 'hidden';
	},
	
	removeElement: function(el) {
		if(el.parentNode) el.parentNode.removeChild(el);
	},
	
	// a przed b
	moveBefore: function(a,b) {
		b.parentNode.insertBefore(a,b);		
		j123.HTML.removeElement(a);
	},
	
	// a za b
	moveAfter : function(a,b) {
		a.parentNode.insertBefore(a, a ? b.nextSibling :null);
		ji123.HTML.removeElement(a);
	},
	
	findPosY : function(el) {
		var curtop = 0;
		if (el.offsetParent) {
			while (el.offsetParent) {
				curtop += el.offsetTop
				el = el.offsetParent;
			}
		}
		else if (el.y)
			curtop += el.y;
		return curtop;
	},
	findPosX : function(el) {
		var curleft = 0;
		if (el.offsetParent) {
			while (el.offsetParent)	{
				curleft += el.offsetLeft
				el = el.offsetParent;
			}
		}
		else if (el.x)
			curleft += el.x;
		return curleft;
	},
	setTextContent :function(el,content) {
		if(j123.browser.isIE || j123.browser.isOpera) el.innerText = content;
		else el.textContent = content;
	},
	getTextContent :function(el) {
		if(j123.browser.isIE || j123.browser.isOpera) return el.innerText;
		else return el.textContent;
	}
	
	// TODO CSS
};


/// here is some stuff from prototype.js

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.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}


j123.Class = {
    // Creators
    create: function (proto)
    {
        /* Accepting prototype definition of the class.  Idea presented by Greg
         * Wiley: http://wiki.script.aculo.us/scriptaculous/show/ExtendClass
         */
        var klass = function ()
        {
            if (this.initialize && arguments.callee.caller != j123.Class.extend)
            {
                this.__class__ = arguments.callee.prototype;
                j123.extend(this, j123.Class.Methods);
                this.initialize.apply(this, arguments);
            }
        };
        klass.prototype = proto || {};
        klass.extend = j123.Class.extend;
        return klass;
    },
    singleton: function (proto)
    {
        var klass =
        {
            instance: function ()
            {
                if (!this.__instance__)
                {
                    var klass = j123.Class.create(proto);
                    this.__instance__ = eval('new klass');
                    proto = null;
                }
                return this.__instance__;
            }
        };
        return klass;
    },

    // Care-takers
    append_features: function (object, module)
    {
        for (var prop in module)
            if (j123.Class.kind_of(module[prop], Function))
                (function (method)
                {
                    object[method] = function ()
                    {
                        return module[method].apply(object, arguments);
                    };
                })(prop);
            else
                object[prop] = module[prop];
    },
    extend: function (subobj)   // implementation of inheritance
    {
        /* Create an instance of the superclass.  This is necessary to maintain
         * a prototype chain correctly.
         */
        var subproto = new this;
        // Update it with the subclass definitions
        j123.extend(subproto, subobj);
        subproto.__super__ = this.prototype;
        return j123.Class.create(subproto);
    },
    get_method: function (klass, args)  // obtain method name being called
    {
        var c = args.callee.caller;
        for (var method in klass)
            if (klass[method] == c)
                return method;
        return null;
    },
    call_super: function (superclass, self, method, args)
    {
        // NOTE: `self' should always refer to the object being instantiated
        if (superclass && superclass[method])
        {
            /* Make the next call of `this.SUPER()' in the superclass refer
             * farther up the class hierarchy */
            var __class__  = self.__class__;
            self.__class__ = superclass;
            self.__super__ = superclass.__super__;

            try
            {
                superclass[method].apply(self, args);
            }
            finally
            {
                // Restore values
                self.__class__ = __class__;
                self.__super__ = superclass;
            }
        }
    },
    kind_of: function (object, klass)
    {
        return eval('klass.prototype.isPrototypeOf(object)');
    }
};

/*
 * MODULE - Class instance methods
 * Mixed into class-instances, so that these methods will become available as
 * instance methods
 */
j123.Class.Methods =
{
    extend: function ()
    {
        var i = arguments.length;
        while (--i >= 0)
            j123.extend(this, arguments[i]);
        return this;
    },
    include: function ()
    {
        var i = arguments.length;
        while (--i >= 0)
            j123.Class.append_features(this, arguments[i]);
        return this;
    },
    kind_of: function (klass)
    {
        return j123.Class.kind_of(this, klass);
    },
    SUPER: function ()
    {
        var method = j123.Class.get_method(this.__class__, arguments);
        j123.Class.call_super(this.__super__, this, method, arguments);
    }
};
