/*
	name			: ClassBehaviours, the javascript framework based on class-name parsing
	update			: 9.11.9
	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(){}

	// Replace a link to external content with the actual content
	jQuery.classBehaviours.handlers.reloadFromUrl = {
		// properties
		name: 'reloadFromUrl',
		focus: '',
		index: 0,
		respite: 100,
		// methods
		start: function(node){
			// if the node is marked to load automatically start loading else set an onclick event
			automatic = jQuery.classBehaviours.utilities.getClassParameter(node, 'auto', 'no');
			if(node.nodeName=='IFRAME' || automatic=='yes') this.clicked(node)
			else if(node.nodeName == 'FORM') node.onsubmit = this.clicked
			else if(node.nodeName == 'BUTTON') node.onclick = this.clicked
			else if(node.nodeName == 'INPUT' && (node.type=='button' || node.type=='submit')) node.onclick = this.clicked
			else if(node.nodeName == 'INPUT' && (node.type=='radio' || node.type=='checkbox')) node.onclick = this.changed
			else if(node.nodeName == 'INPUT') node.onchange = this.changed
			else if(node.nodeName == 'SELECT') node.onchange = this.changed
			else if(node.nodeName == 'TEXTAREA') node.onchange = this.changed
			else if(node.nodeName == 'FIELDSET') null
			else node.onclick = this.clicked;
			//  Added for hijacking .NET postback event
			if(node.nodeName=='A' && node.href.indexOf('javascript:__doPostBack')>-1){
				node.href = '';
				node.onclick = this.clicked;
			}
		},
		wait: function(importProgress, referedNode, importError, requestTime){
			var rfu = jQuery.classBehaviours.handlers.reloadFromUrl;
			// get the target for the indicator
			targetId = jQuery.classBehaviours.utilities.getClassParameter(referedNode, 'target', '');
			if(targetId!='') targetNode = document.getElementById(targetId)
			else targetNode = referedNode;
			// update the progress indicator
			jQuery.classBehaviours.utilities.setClassParameter(targetNode, 'progress', importProgress);
			jQuery.classBehaviours.utilities.setClassParameter(targetNode, 'error', importError);
			// only turn on the progress indicator after a short pause
			shownStatus = (new Date()-requestTime > rfu.respite) ? 1 : 0 ;
			jQuery.classBehaviours.utilities.setClassParameter(targetNode, 'show', shownStatus);
		},
		insert: function(importedObj, referedNode, importedText, requestTime){
			var rfu = jQuery.classBehaviours.handlers.reloadFromUrl;
			// get the optional parameters from the refered node
			targetId = jQuery.classBehaviours.utilities.getClassParameter(referedNode, 'target', null);
			sourceId = jQuery.classBehaviours.utilities.getClassParameter(referedNode, 'source', null);
			//  if a form is in the response take the action and reload
			noformId = jQuery.classBehaviours.utilities.getClassParameter(referedNode, 'noform', null);
			nonIntrusive = (jQuery.classBehaviours.utilities.getClassParameter(referedNode, 'gently', '0')=='1');
			// get the content from the imported node
			importedNode = (sourceId!=null) ?
				jQuery.classBehaviours.utilities.getXmlElementById(sourceId, importedObj, true) :
				importedObj ;
			// forcefully insert the content into the target node
			if(!nonIntrusive){
				// get the source HTML from the imported document
				importedHTML = jQuery.classBehaviours.ajax.serialize(importedNode, true);
				// strip any left over body tags from the content
				if(importedHTML.indexOf('<body')>-1){
					importedHTML = importedHTML.split('<body')[1].split('</body>')[0];
					importedHTML = importedHTML.substr(importedHTML.indexOf('>') + 1, importedHTML.length);
				}
				// if no id was given for the target node
				if(targetId==null){
					// replace the refered node
					newDiv = document.createElement('div');
					newDiv.id = rfu.name + rfu.index++ ;
					referedNode.parentNode.replaceChild(newDiv, referedNode);
					targetNode = document.getElementById(newDiv.id);
				}
				// else
				else{
					// use the target id to find the node
					targetNode = document.getElementById(targetId);
				}
				//  if a full page is loaded and the noform is set do a redirect.
				if (noformId == '1' && new String(importedHTML).toLowerCase().indexOf('<form') > -1) {
					url = new String(importedHTML).toLowerCase();
					index = url.indexOf('action') + 8;
					url = url.substr(index, url.length - index);
					//  IE removed the " from the action="".
					index = url.indexOf('"') > url.indexOf('>') ? url.indexOf('>') : url.indexOf('"');
					url = url.substr(0, index);
					location.href = url;
					return;
				}
				// insert the imported HTML
				if(targetNode!=null)
					targetNode.innerHTML = importedHTML;
					Cufon.refresh();
				// set the focus (if any)
				if (document.getElementById(rfu.focus) != null)
					document.getElementById(rfu.focus).focus();
			}
			// or gently compare classnames and text
			else{
				// for all imported nodes
				importedChildNodes = importedNode.getElementsByTagName('*');
				for(var a=importedChildNodes.length-1; a>=0; a--){
					// get the target ID
					exportedChildNodeId = importedChildNodes[a].getAttribute('id');
					// if it's a node with an existing IDww
					if(exportedChildNodeId!=null && exportedChildNodeId!=''){
						// get the target node
						exportedChildNode = document.getElementById(exportedChildNodeId);
						// does this node actually exist?
						if(exportedChildNode!=null){
							// sync the classname
							exportedChildNode.className = (importedChildNodes[a].className!=null) ? importedChildNodes[a].className : importedChildNodes[a].getAttribute('class') ;
							// sync the select options
							if(importedChildNodes[a].nodeName=='SELECT'){
								// every node in this select
								importedSelectOptions = importedChildNodes[a].getElementsByTagName('OPTION');
								exportedSelectOptions = exportedChildNode.getElementsByTagName('OPTION');
								// choose the longest list
								selectOptionsLength = (importedSelectOptions.length>exportedSelectOptions.length) ? importedSelectOptions.length : exportedSelectOptions.length ;
								// for every item in the list
								for(var b=selectOptionsLength-1; b>=0; b--){
									// if there is no exported option
									if(b>=exportedSelectOptions.length){
										// make a new option node
										newOptionElement = document.createElement('OPTION');
										newOptionText = document.createTextNode(importedSelectOptions[b].firstChild.nodeValue);
										newOptionElement.appendChild(newOptionText);
										newOptionElement.setAttribute('value', importedSelectOptions[b].value);
										exportedChildNode.appendChild(newOptionElement);
									}
									// if there is no imported option
									else if(b>=importedSelectOptions.length){
										// remove an option node
										exportedSelectOptions[b].parentNode.removeChild(exportedSelectOptions[b]);
									}
									// else
									else{
										// transfer the imported to the exported node
										exportedSelectOptions[b].firstChild.nodeValue = importedSelectOptions[b].firstChild.nodeValue;
										exportedSelectOptions[b].value = importedSelectOptions[b].value;
									}
								}
							}
							// sync the text
							importedHTML = jQuery.classBehaviours.ajax.serialize(importedChildNodes[a]);
							importedHTML = importedHTML.substring(importedHTML.indexOf('>') + 1, importedHTML.lastIndexOf('<'));
							isInlineMarkup = (
								exportedChildNode.innerHTML.toUpperCase().indexOf('<DIV')<0 &&
								exportedChildNode.innerHTML.toUpperCase().indexOf('<SECTION')<0 &&
								exportedChildNode.innerHTML.toUpperCase().indexOf('<ARTICLE')<0 &&
								exportedChildNode.innerHTML.toUpperCase().indexOf('<HEADER')<0 &&
								exportedChildNode.innerHTML.toUpperCase().indexOf('<FOOTER')<0 &&
								exportedChildNode.innerHTML.toUpperCase().indexOf('<NAV')<0 &&
								exportedChildNode.innerHTML.toUpperCase().indexOf('<FIELDSET')<0 &&
								exportedChildNode.innerHTML.toUpperCase().indexOf('<SELECT')<0 &&
								exportedChildNode.nodeName!='SELECT' &&
								exportedChildNode.innerHTML.toUpperCase().indexOf('<OPTION')<0 &&
								exportedChildNode.innerHTML.toUpperCase().indexOf('<TEXTAREA')<0 &&
								exportedChildNode.nodeName!='TEXTAREA' &&
								exportedChildNode.innerHTML.toUpperCase().indexOf('<INPUT')<0 &&
								exportedChildNode.nodeName!='INPUT'
							);
							if(isInlineMarkup) exportedChildNode.innerHTML = importedHTML;
						}
					}
				}
			}
			// reset the progress indicator
			jQuery.classBehaviours.utilities.setClassParameter(targetNode, 'progress', 4);
			jQuery.classBehaviours.utilities.setClassParameter(targetNode, 'error', 200);
			// activate any classbehaviours in there
			jQuery.classBehaviours.parser.parseNode(targetNode);
			// OPTIONAL: replace the title
			replaceTitleId = jQuery.classBehaviours.utilities.getClassParameter(referedNode, 'title', null);
			if(replaceTitleId!=null) document.getElementById(replaceTitleId).innerHTML = referedNode.title;
		},
		// events
		clicked: function(that){
			var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
			var rfu = jQuery.classBehaviours.handlers.reloadFromUrl;
			// reminder the focus
			rfu.focus = objNode.id;
			// try to get a URL from somewhere
			targetHref = objNode.getAttribute('href');
			targetSrc = objNode.getAttribute('src');
			targetLongdesc = objNode.getAttribute('longdesc');
			rootForm = jQuery.classBehaviours.utilities.rootNode(objNode, 'FORM', null);
			targetAction = rootForm.getAttribute('action');
			//  get the id reference with holds the URI information
			hrefTarget = jQuery.classBehaviours.utilities.getClassParameter(objNode, 'id', '');
			// decide which URL has priority
			targetUrl = (targetHref != null && targetHref != '') ? targetHref :
				(hrefTarget != null && hrefTarget != '') ? document.getElementById(hrefTarget).href :
				(targetAction != null && targetAction != '') ? targetAction :
				(targetLongdesc != null && targetLongdesc != '') ? targetLongdesc :
				(targetSrc != null && targetSrc != '') ? targetSrc :
				document.location.href;
			// get the post values
			postValues = jQuery.classBehaviours.ajax.getPostValues(objNode);
			// get the post method
			postPrefix = (targetUrl.indexOf('?')<0) ? '?' : '&' ;
			// place the AJAX request and cancel the click
			return (new String(rootForm.getAttribute('method')).toLowerCase() == 'post') ?
				jQuery.classBehaviours.ajax.addRequest(targetUrl, rfu.insert, rfu.wait, postValues, objNode) :
				jQuery.classBehaviours.ajax.addRequest(targetUrl + postPrefix  + postValues, rfu.insert, rfu.wait, null, objNode) ;
		},
		changed: function(that){
			var objNode = (typeof(this.nodeName)=='undefined') ? that : this ;
			var rfu = jQuery.classBehaviours.handlers.reloadFromUrl;
			// find the fieldset that belongs to this part of the form
			submitNode = jQuery.classBehaviours.utilities.rootNode(objNode, 'FIELDSET', null);
			// use the entire form if no fieldset was found
			if(submitNode.nodeName=='BODY'){
				submitNode = jQuery.classBehaviours.utilities.rootNode(objNode, 'FORM', null);
			}
			// find any buttons in this fieldset
			buttonNodes = submitNode.getElementsByTagName('BUTTON');
			if(buttonNodes.length>0){
				submitNode = buttonNodes[0];
			}
			// or find any submit inputs in this fieldset instead
			else{
				inputNodes = submitNode.getElementsByTagName('INPUT');
				for(var a=0; a<inputNodes.length; a++) if(inputNodes[a].type=='submit' || inputNodes[a].type=='button') submitNode = inputNodes[a];
			}
			// post it
			void(rfu.clicked(submitNode));
			return true ;
		}
	}

	// add this addon to the jQuery object
	if(typeof(jQuery.fn)!='undefined'){
		// extend jQuery with this method
		jQuery.fn.reloadFromUrl = function(){
			return this.each(
				function(){
					jQuery.classBehaviours.handlers.reloadFromUrl.start(this);
				}
			);
		};
		// set the event handler for this jQuery method
		$(document).ready(
			function(){
				$(".reloadFromUrl").reloadFromUrl();
			}
		);
	}

