/*
**	Simple html hybrid behaviour Javascript framework
**
**	(c) 2010 Mikoon Webservices
*/

var CB_Base = new Class({
	
	Implements: Options,
	
	_attributes: new Array(),
	_classes: new Array(),
	_storage: new Array(),
	
	options: {
		namespaceprefix: 'cb:',
		classprefix: '.cb_'
    },
	
	initialize: function(options){
		//	set options
		this.setOptions(options);
	},
	
	set_cookie: function(name, value, expires, path, domain, secure) {
    	document.cookie= name + "=" + escape(value) +
        ((expires) ? "; expires=" + expires.toGMTString() : "") +
        ((path) ? "; path=" + path : "") +
        ((domain) ? "; domain=" + domain : "") +
        ((secure) ? "; secure" : "");
	},

	get_cookie: function(name) {
	    var dc = document.cookie;
	    var prefix = name + "=";
	    var begin = dc.indexOf("; " + prefix);
	    if (begin == -1) {
	        begin = dc.indexOf(prefix);
	        if (begin != 0) return null;
	    } else{
	        begin += 2;
     	}
	    var end = document.cookie.indexOf(";", begin);
	    if (end == -1) end = dc.length;
	    return unescape(dc.substring(begin + prefix.length, end));
	},
	
	register_attribute: function(in_selector, in_attribute, in_behaviour, in_arguments){
 		if (typeof this._attributes != "object") this._attributes = new Array();
 		//	check for pre-registered attributes for this selector
    	if (typeof this._attributes[in_selector] != "object") this._attributes[in_selector] = new Array();
    	//	register attribute for this selector
    	this._attributes[in_selector][this._attributes[in_selector].length] = {'attribute': in_attribute, 'behaviour': in_behaviour, 'arguments': in_arguments};
	},
	
	register_class: function(in_selector, in_class, in_behaviour, in_arguments){
 		if (typeof this._classes != "object") this._classes = new Array();
 		//	check for pre-registered attributes for this selector
    	if (typeof this._classes[in_selector] != "object") this._classes[in_selector] = new Array();
    	//	register attribute for this selector
    	this._classes[in_selector][this._classes[in_selector].length] = {'classname': in_class, 'behaviour': in_behaviour, 'arguments': in_arguments};
	},
	
	process: function(){
		//	check for registered attributes
		if (typeof this._attributes == "object"){
			//	loop through registered attribute/behaviour selectors
		    for(var selector in this._attributes) {
		        if (typeof this._attributes[selector] == "function" || selector == '$family') continue;
		        //	loop through matched selector elements
		        $$(selector).each(function(el){
		        	//	loop through registered behaviours for this selector
		            this._attributes[selector].each(function(ab){
		                if (el.get(this.options.namespaceprefix+ab.attribute)){
		                	//	run behaviour function on this element
	                		new ab.behaviour(el, 'attribute', ab.arguments, this);
	                	}
		            }, this);
		        }, this);
		    }
   		}
		//	check for registered classes
		if (typeof this._classes == "object"){
			//	loop through registered attribute/behaviour selectors
		    for(var selector in this._classes){
		    	if(typeof this._classes[selector] == "function" || selector == '$family') continue;
				//	loop through registered behaviours for this selector
				this._classes[selector].each(function(ab){
						//	loop through matched attribute/selector elements
						$$(selector+this.options.classprefix+ab.classname).each(function(el){
		            		//	run behaviour function on this element
		                	new ab.behaviour(el, 'class', ab.arguments, this);
			            }, this);
	         	}, this);
		    }
	    }
	}
	
});

/*
**
**	Prototype behaviour class
**
*/
var CB_Behaviour = new Class({

	Implements: Options,
	
	el: {},
	cb: {},
	
	options: {},
	
	initialize: function(in_element, in_method, options, in_cb){
		
		//	set local variables
		this.el = in_element;
		this.method = in_method;
		this.cb = in_cb;
		
		//	pre process
		options = this.preprocess(options);
	
		//	set options
		this.setOptions(options);
		
		//	run setup
		this.setup();
	},
	
	preprocess: function(in_options){
		if(this.method == 'attribute' && !in_options.datatag) in_options.datatag = this.cb.options.namespaceprefix+this.options.attribute;
		return in_options;
	},
	
	setup: function(){
		this.el.store('processed', true);
	}
	
});

/*
**
**	HoverImage behaviour class
**
*/
var CB_HoverImage = new Class({

	Extends: CB_Behaviour,

	options: {
		datatag: 'title',
		attribute: 'hoverimage'
    },	
    
    setup: function(){
    	
    	// preload the hover image
    	var preloadimg = new Image();
    	preloadimg.src = this.el.get(this.options.datatag);

    	//	store sources
    	this.el.set('origsrc', this.el.get('src'));
    	this.el.set('oversrc', this.el.get(this.options.datatag));
    	
    	//	add events
    	this.el.addEvent('mouseenter', function(){ this.set('src', this.get('oversrc')); });
    	this.el.addEvent('mouseleave', function(){ this.set('src', this.get('origsrc')); });
    	
    	// clear attribute
    	this.el.set(this.options.datatag, '');
    	
    	// run parent setup function
    	CB_Behaviour.prototype.setup.apply(this);
    }
	
});

/*
**
**	ToggleGroup behaviour class
**
*/
var CB_ToggleGroup = new Class({

	Extends: CB_Behaviour,

	options: {
		datatag: 'title',
		attribute: 'togglegroup'
    },	
    
    setup: function(){
    	
    	//	get value
    	var togglegroup = this.el.get(this.options.datatag);
    	
    	//	create storage arrays
		if (typeof this.cb._storage.togglegroups != "object") this.cb._storage.togglegroups = new Array();
    	if (typeof this.cb._storage.togglegroups[togglegroup] != "object") this.cb._storage.togglegroups[togglegroup] = new Array();
    	
    	//	store group info
    	this.cb._storage.togglegroups[togglegroup][this.cb._storage.togglegroups[togglegroup].length] = this.el;
    	
    	//	set visibility
    	var cookieval = this.cb.get_cookie("CB_togglegroup_"+togglegroup);
    	if(cookieval){
    		if(cookieval == this.el.id){
	    		this.el.setStyle('display', 'block');	
	    	} else {
	    		this.el.setStyle('display', 'none');
	    	}
		} else {
			if(this.cb._storage.togglegroups[togglegroup].length == 1){
				this.el.setStyle('display', 'block');	
	    	} else {
	    		this.el.setStyle('display', 'none');
	    	}
		}	
    	
    	// clear attribute
    	this.el.set(this.options.datatag, '');
    	
    	// run parent setup function
    	CB_Behaviour.prototype.setup.apply(this);
    },
    
    toggle: function(in_group, in_id){
    	if (typeof CB._storage.togglegroups != "object") return;
    	if (typeof CB._storage.togglegroups[in_group] != "object") return;
    	CB._storage.togglegroups[in_group].each(function(el,i){
    		if(el.id == in_id){
    			el.setStyle('display', 'block');
				CB.set_cookie("CB_togglegroup_"+in_group, in_id);	
    		} else {
    			el.setStyle('display', 'none');
    		}
    	});
    }
    
});

//	register static interface function
CB_ToggleGroup.toggle = CB_ToggleGroup.prototype.toggle;

/*
**
**	GroupToggler behaviour class
**
*/
var CB_GroupToggler = new Class({

	Extends: CB_Behaviour,

	options: {
		datatag: 'title',
		attribute: 'grouptoggler',
		status: 'block'
    },	
    
    setup: function(){
    	
    	//	get value
    	var selector = this.el.get(this.options.datatag);
    	
    	//	set default visibility
    	var cookieval = this.cb.get_cookie("CB_grouptoggle_"+selector);
    	if(cookieval){
    		$$(selector).setStyle('display', (cookieval=='none'?'none':'block'));	
    		this.options.status = (cookieval=='none'?'none':'block');
    	} else {
    		$$(selector).setStyle('display', (this.options.status=='none'?'none':'block'));
    	}
    	
    	//	add click event
    	this.el.addEvent('click', (function(){
  			this.options.status = (this.options.status=='none'?'block':'none');
		  	$$(selector).setStyle('display', this.options.status);
		  	//	store in cookie
		  	CB.set_cookie("CB_grouptoggle_"+selector, this.options.status);
    	}).bind(this));

		// clear attribute
    	this.el.set(this.options.datatag, '');

    	// run parent setup function
    	CB_Behaviour.prototype.setup.apply(this);
    }
    
});

/*
**
**	NoFocus behaviour class
**
*/
var CB_NoFocus = new Class({

	Extends: CB_Behaviour,

	options: {
		attribute: 'nofocus'
    },	
    
    setup: function(){
    	//	add click event
    	this.el.addEvent('focus', function(){ this.blur(); });

    	// run parent setup function
    	CB_Behaviour.prototype.setup.apply(this);
    }
    
});

/*
**
**	Instantiate and run base behaviour processor
**
*/
var CB = new CB_Base();	//	global CB object

window.addEvent('domready', function(){
	
	//	register behaviours
	CB.register_attribute('img', 		'hoverimage', 	CB_HoverImage,		{});
	CB.register_attribute('div', 		'togglegroup', 	CB_ToggleGroup,		{});
	CB.register_attribute('a', 			'grouptoggler',	CB_GroupToggler,	{});
	CB.register_attribute('a', 			'nofocus',		CB_NoFocus,			{});
	
	CB.register_class('img', 		'hoverimage', 	CB_HoverImage,		{datatag: 'title'});
	CB.register_class('div', 		'togglegroup', 	CB_ToggleGroup,		{datatag: 'title'});
	CB.register_class('a', 			'grouptoggler',	CB_GroupToggler,	{datatag: 'rel'});
	CB.register_class('a', 			'nofocus',		CB_NoFocus,			{});
	
	// process attributes
	CB.process();	
	
});
