/*	name			: ClassBehaviours, the javascript framework based on class-name parsing	update			: 9.3.17	author			: Maurice van Creij	dependencies	: jquery.classbehaviours.js	info			: http://www.classbehaviours.com/

    This file is part of jQuery.classBehaviours.
    
    ClassBehaviours is a javascript framework based on class-name parsing.
    Copyright (C) 2008  Maurice van Creij

    ClassBehaviours is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    ClassBehaviours is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with ClassBehaviours. If not, see http://www.gnu.org/licenses/gpl.html.*/

	// create the jQuery object if it doesn't already exist
	if(typeof(jQuery)=='undefined') jQuery = function(){};
	
	// create the root classbehaviours object if it doesn't already exist
	if(typeof(jQuery.classBehaviours)=='undefined') jQuery.classBehaviours = function(){};
	
	// create the handlers child object if it doesn't already exist
	if(typeof(jQuery.classBehaviours.handlers)=='undefined') jQuery.classBehaviours.handlers = function(){}

	// Construct an empty stylesheet based on the hierarchy of tags
	jQuery.classBehaviours.handlers.makeStylesheet = {
		// properties
		name: 'makeStylesheet',
		styleSheet: "",
		referenceCss: "",
		// methods
		start: function(node){
			// create the default CSS entry
			this.styleSheet = "\t/* " + document.location.href.split('/')[document.location.href.split('/').length-1] + " */\n";
			this.styleSheet += "\thtml {}\n";
			this.styleSheet += (document.body.getAttribute('class')!=null) ? "\t\tbody." + document.body.className.replace(/ /gi, ".") + " {}\n" : "\t\tbody {}\n" ;
			// make a reference stylesheet from the current stylesheets
			this.makeReferenceCss();
			// markup the stylesheet making button
//			node.style.position = 'absolute';
//			node.style.right = '4px';
//			node.style.top = '4px';
			node.onclick = this.showNodeClasses;
			/* how to read stylesheet content
			debug(
				document.styleSheets[0].cssRules[1].selectorText,
				document.styleSheets[0].cssRules[1].cssText,
				document.styleSheets[0].cssRules[1].style.getPropertyValue('font-family')
			);
			*/
		},
		makeReferenceCss: function(){
			for(var a=0; a<document.styleSheets.length; a++)
				if(document.styleSheets[a].cssRules)
					for(var b=0; b<document.styleSheets[a].cssRules.length; b++)
						this.referenceCss += document.styleSheets[a].cssRules[b].selectorText + ' {}\n\t';
		},
		isFormElement: function(tagName){
			return (('input,select,textarea,button,INPUT,SELECT,TEXTAREA,BUTTON').indexOf(tagName)>-1);
		},
		isClassBehaviours: function(newEntry){
			foundHandler = false;
			// for all behaviours, if the behaviour's name exists in the class name, remember it
			if(typeof(newEntry)=='string')
				for(var b=0; b<jQuery.classBehaviours.handlers.length; b++)
					foundHandler = (newEntry.indexOf(jQuery.classBehaviours.handlers[b].name)>-1) ? true : foundHandler;
			// report back
			return foundHandler;
		},
		isInStylesheet: function(newEntry, onlyChanges){
			foundStyle = false;
			// clean the new entry
			newEntry = newEntry.replace(/\t/gi,'').replace(' {}\n','').replace(',','');
			// if the style allready exists in this constructed stylesheet
			foundStyle = (this.styleSheet.indexOf(newEntry)>-1);
			// if the style allready exists in any rule in another stylesheet
			foundStyle = (this.referenceCss.indexOf(newEntry)>-1 && onlyChanges) ? true : foundStyle ;
			// report back
			return foundStyle;
		},
		getNodeClasses: function(objNode, intRecursion, oldPrefix, onlyChanges, simplified){
			var tagPrefix, idPrefix, classPrefix, newEntry, newSuffix;
			// for every recursion add one tab
			var strTabs = '\t\t';
			for(var intB=0; intB<=intRecursion; intB++) strTabs += '\t';
			// for every childnode
			var objChildNodes = objNode.childNodes;
			for(var intA=0; intA<objChildNodes.length; intA++){
				childNode = objChildNodes[intA];
				// reset prefixes
				tagPrefix 		= (childNode.nodeName.indexOf('#')<0) ? childNode.nodeName : '' ;
				idPrefix 		= (childNode.id) ? '#' + childNode.getAttribute('id') : '' ;
				classPrefix 	= (childNode.className) ? '.' + childNode.getAttribute('class') : '' ;
				typePrefix		= '' // (childNode.type) ? childNode.getAttribute('type') : '' ;
				newPrefix 		= '';
				newEntry		= '';
				newSuffix		= '';
				// construct prefixes
				if(tagPrefix!=''){
					tagPrefix 		= childNode.nodeName.toLowerCase();
					idPrefix 		= (!this.isClassBehaviours(idPrefix) && !this.isFormElement(tagPrefix)) ? idPrefix : '' ;
					classPrefix 	= classPrefix.replace(/^\s+|\s+$/g, '').replace(/ /g, '.') ;
					typePrefix		= (typePrefix!='') ? '[type=' + typePrefix + ']' : '' ;
					newPrefix 		= oldPrefix + ' ' + tagPrefix + typePrefix + idPrefix + classPrefix;
					newPrefix 		= (newPrefix.split('#').length>1 && simplified) ? '#' + newPrefix.split('#')[newPrefix.split('#').length-1] : newPrefix ;
					newEntry 		= strTabs + newPrefix + ' {}\n';
					newSuffix 		= (tagPrefix=='a') ? strTabs + newPrefix + ':link,\n' + strTabs + newPrefix + ':visited {}\n' + strTabs + newPrefix + ':hover,\n' + strTabs + newPrefix + ':active {}\n' : '' ;
				}
				// add the new stylesheet entry
				if(!this.isInStylesheet(newEntry, onlyChanges)) this.styleSheet += newEntry + newSuffix;
				// recurse if it this node has childNodes
				if(objChildNodes[intA].childNodes.length>0) this.getNodeClasses(objChildNodes[intA], intRecursion+1, newPrefix, onlyChanges, simplified);
			}
		},
		showNodeClasses: function(that){
			var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
			var mss = jQuery.classBehaviours.handlers.makeStylesheet;
			// position it out of the way
			document.body.style.textAlign = 'left';
			document.body.style.background = '#ffffff none';
			document.body.style.color = '#000000';
			document.body.style.fontFamily = 'Sans Serif';
			document.body.style.fontSize = '10pt';
			// are only the changes to the existing stylesheets required?
			onlyChanges = (jQuery.classBehaviours.utilities.getClassParameter(objNode, 'changesOnly', 'yes')=='yes');
			// is a simplified stylesheet requested
			simplified = (jQuery.classBehaviours.utilities.getClassParameter(objNode, 'simplified', 'yes')=='yes');
			// get the document root
			documentRoot = (simplified) ? document.body : document ;
			// generate the stylesheet code
			mss.getNodeClasses(documentRoot, 0 , '', onlyChanges, simplified);
			// replace the page with the stylesheet prototype
			document.body.innerHTML = (navigator.userAgent.indexOf('MSIE 6')>-1) ? '<textarea style="width:720px;height:480px;border:solid 1px #000000;">' + mss.styleSheet + '</textarea>' : '<textarea style="position:absolute;left:5%;top:5%;width:90%;height:90%;border:solid 1px #000000;">' + mss.styleSheet + '</textarea>';
		}
	}
			
	// add this addon to the jQuery object
	if(typeof(jQuery.fn)!='undefined'){
		// extend jQuery with this method
		jQuery.fn.makeStylesheet = function(){
			return this.each(
				function(){
					jQuery.classBehaviours.handlers.makeStylesheet.start(this);
				}
			);
		};
		// set the event handler for this jQuery method
		$(document).ready(
			function(){
				$(".makeStylesheet").makeStylesheet();
			}
		);
	}

