/* Page Load Stuff */
$j(document).ready(function($){

	// Hide the iframe with src about:blank on contact page.
	$('iframe').each(function(){
		if(this.src == 'about:blank'){
			$(this).hide();
		}
	});
	
	// Observe inputs with class clear_if_default.
	(function(){
		$('input.clear_if_default').each(function(){
			var default_value = this.value;
			$j(this).click(function(){
				clearIfString(this, default_value);
			});
		});
	})()
	
	// Call verify observe
	verify_observe($);

})

// Fake console.log for browsers without console
if(!window.console || !window.console.log) {  
	window.console = {
		log : function () {} 
	};   
}

// QBD Object
window.qbd = window.qbd || {};
	
/**
* Array of croppers currently on page
*/
qbd.croppers = [];

/**
* Cropper wrapper class.
* Creates a new cropper with a few additional methods and parameters.
*
* @param obj/string img the image to crop
* @param obj opt the options to pass straight to the cropper
* @param onEndCrop function the function to run when the cropping completes.
*
*/
qbd.Cropper = function(img, opt){
	this.opt = opt;
	this.onEndCrop = typeof this.opt.onEndCrop == 'function' ? this.opt.onEndCrop : function(){};
	this.img = $(img);
	this.ratio = 1;
	this.resize = typeof opt.resize != 'undefined' ? opt.resize : true; // resize defaults to true
	this.cropper = null;
			
	// Need to access a member function from within the actual cropper.
	var self = this;
	// Make the onEndCrop function of the cropper call the onEndCrop function of this so we can use ratio.
	this.opt.onEndCrop = function(coords, dimensions){
		// Calculate coordinates and dimensions as if they were on original sized image.
		var orig_coords = orig_dims = {};
		for(var coord in coords){
			if(coords.hasOwnProperty(coord)){
				orig_coords[coord] = Math.ceil(coords[coord] / self.ratio);
			}
		}
		
		for(var dim in dimensions){
			if(dimensions.hasOwnProperty(dim)){
				orig_dims[dim] = Math.ceil(dimensions[dim] / self.ratio);
			}
		}
		
		self.onEndCrop(orig_coords, orig_dims);
	};
	
	if(this.resize == true){
		// try to resize - if it is resized, change the minwidth and height accordingly
		if(this.resizeToFit() === true){
			this.opt.minWidth = this.opt.minWidth * this.ratio;
			this.opt.minHeight = this.opt.minHeight * this.ratio;
		}
	}

	this.createCropper();
	
	qbd.croppers.push(this);
}

/**
* Resizes the image to fit on the screen before initializing a croppr.
*
*/
qbd.Cropper.prototype.resizeToFit = function(){
	var PADDING = 100; // Amount of space to leave around image in iframe.
	// Find window dimensions
	//var viewportDims = document.viewport.getDimensions();
	
	var viewportDims = {};
	// Find the current document/iframes dimensions.
	if(self === top){ // Not in an iframe
		viewportDims = document.viewport.getDimensions();
	}else{ // iFrame
		// Find this iframe			
		parent.$$('iframe').each(function(iframe){
			try{
				// If the location of the iframe we're inside matches the URL of the current iframe in loop
				if(self.location.href == iframe.contentWindow.location || iframe.contentDocument.URL){
					viewportDims.width = iframe.getWidth();
					viewportDims.height = iframe.getHeight();
					//throw $break;
				}
			}catch(e){
				// Ignore SOP errors
			}
		});	
	}
	
	var imgDims = {
		width : this.img.width,
		height : this.img.height
	};
			
	var ratio = {};
	ratio.width = (viewportDims.width - PADDING) / imgDims.width;
	ratio.height = (viewportDims.height - PADDING) / imgDims.height;
	// We should use the ratio which makes the biggest change to current dimensions.
	ratio = ratio.width < ratio.height ? ratio.width : ratio.height;
	// If the image is larger than viewport, resize it to fit.
	if(ratio < 1){
		this.img.width = this.img.width * ratio;
		this.ratio = ratio;
		return true;
	}
	return false;
}

qbd.Cropper.prototype.createCropper = function(){
	this.cropper = new Cropper.ImgWithPreview(this.img,this.opt);
}

///////////////////////////////////////////// Timeout Array
window.timeOuts=[]; 
function clearAllTimeouts(){  
    for(var key in timeOuts ){ 
        clearTimeout(timeOuts[key]);  
    }  
}

///////////////////////////////////////////// Search
var tsearch=function(sss,ttt) {
    clearAllTimeouts();
    timeOuts['search'] = setTimeout("dosearch('"+sss+"','"+ttt+"')",1000)
}
var dosearch=function(sss,ttt) {
    if (sss.length>2)
    {
        var dname='col2';
        $(dname).innerHTML='<img id="ajaxloader" src="../library/ajaxloader.gif" alt="loading..." />';
        var act='search';
        new Ajax.Updater(dname,'ajax.asp',{parameters:{act:act,term:sss,h1:ttt},evalScripts:true});
    }
}
////////////////////////////////////////////////////////////////////////////////////////// Jamies JS Pformatter
var pformat=function(sss) {
    if (sss!="") {
        sss=sss.replace(/ /g,'_');
        sss=sss.replace(/__/g,'_');
        sss=sss.replace(/'/g,"");
        sss=sss.replace(/:/g,"");
        sss=sss.replace(/,/g,"");
        sss=sss.replace(/\//g,"");
        sss=sss.replace(/%/g,"");
        sss=sss.replace(/&/g,"");
        sss=sss.replace(/$/g,"");
        sss=sss.replace(/£/g,"");
        sss=sss.replace(/""/g,"");
        sss=sss.replace(/!/g,"");
        sss=sss.replace(/\?/g,"");
        sss=sss.replace(/#/g,"");
        sss=sss.replace(/@/g,"");
        sss=sss.replace(/~/g,"");
        sss=sss.replace(/</g,"");
        sss=sss.replace(/>/g,"");
        sss=sss.replace(/\*/g,"");
        sss=sss.replace(/^/g,"");
        sss=sss.replace(/__/g,"_");
    }
    sss=sss.toLowerCase();
    return sss;
}
///////////////////////////////////////////// Leftnav Slider
var showleft=function(sss,ttt) {
    Effect.Queues.get("lefter").cancel(sss)
    if ($(sss).style.display=='none') {
        Effect.Appear(sss,{ queue:{scope:"lefter"} });
    }
    else {
        $(sss).morph('height:'+eval(ttt*40)+'px;',{ queue:{scope:"lefter"} });
    }
}
var hideleft=function(sss) {
    Effect.Queues.get("lefter").cancel(sss)
    Effect.BlindUp(sss,{queue:{scope:"lefter"}, scaleContent:true, scaleMode:'contents' }); 
}
///////////////////////////////////////////// Bottom Slider
var domorph=function(sss) {
    $(sss).morph('height:120px;'); 
    return false;
}
var unmorph=function(sss) {
    $(sss).morph('height:35px;');
    return false;
}

////////////////////////////////////////////////////////////////////////////////////////// Editing Functions
var pos=function(table,list) {
    var thelist=Sortable.sequence(list);
    var fullist=''
    for (x in thelist) {
        if (parseInt(thelist[1,x])==thelist[1,x]) {
            fullist=fullist+thelist[1,x]+'-'
        }
    }
    new Ajax.Request('ajax.asp',{method:'post',parameters:{act:'pos',table:table,ids:fullist}});
}

var activ = function(el,table,id,val1,val2){
	activaterExtreme(el,"activate",table,id,val1,val2)
};
var activaterExtreme = function(el,act,table,id,val1,val2,el2){
	if ($(el)) {
		$(el).innerHTML='';
		new Ajax.Request('ajax.asp',{
			parameters:{
				act:act,
				id:id,
				table:table,
				val1:val1,
				val2:val2
			},
			onComplete : function(res){
				$(el).update(res.responseText);
				if ($(el2)) {
					$(el2).update(res.responseText);
				}
			},
			insertion:Insertion.Top,
			evalScripts:true
		});
	}
};

var activate=function(table,id,val1,val2) {
    $('activate'+id).innerHTML='';
    new Ajax.Updater('activate'+id,'ajax.asp',{parameters:{act:'activate',id:id,table:table,val1:val1,val2:val2},insertion:Insertion.Top,evalScripts:true});
}

var activatepng=function(table,id,val1,val2) {
    $('activate'+id).innerHTML='';
    new Ajax.Updater('activate'+id,'ajax.asp',{parameters:{act:'activate',id:id,table:table,val1:val1,val2:val2,png:1},insertion:Insertion.Top,evalScripts:true});
}
var activatenav=function(table,id,val1,val2) {
    $('nav_activate'+id).innerHTML='';
    new Ajax.Updater('nav_activate'+id,'ajax.asp',{parameters:{act:'activate',id:id,table:table,val1:val1,val2:val2},insertion:Insertion.Top,evalScripts:true});
}
var activateopt=function(table,id,val1,val2) {
    $('opt_activate_'+id).innerHTML='';
    new Ajax.Updater('opt_activate_'+id,'ajax.asp',{parameters:{act:'activate',id:id,table:table,val1:val1,val2:val2},insertion:Insertion.Top,evalScripts:true});
}
var del=function(table,id,fid,title,fid2,fid3,fid4,fid5) {
    $('msg').innerHTML='';
    new Ajax.Updater('msg','ajax.asp',{parameters:{act:'del',id:id,table:table,fid:fid,title:title,fid2:fid2,fid3:fid3,fid4:fid4,fid5:fid5},insertion:Insertion.Top,evalScripts:true, queue:{position:'end',scope:'doqueue'}});
}
var kill=function(table,id,fid,fid2,fid3,fid4,fid5) {
    new Ajax.Updater('dname','ajax.asp',{parameters:{act:'kill',id:id,table:table,fid:fid,fid2:fid2,fid3:fid3,fid4:fid4,fid5:fid5},insertion:Insertion.Top,evalScripts:true, queue:{position:'end',scope:'doqueue'}});
}
var addblogitem=function(id) {
	var btitle = $('btitle').value;
    new Ajax.Updater('dname','ajax.asp',{parameters:{act:'addblogitem',id:id,btitle:btitle},insertion:Insertion.Top,evalScripts:true, queue:{position:'end',scope:'doqueue'}});
}
var redopage=function(act,id,extra) {
	document.location = "?act="+act+"&id="+id+"&"+extra;	
}
var datesave=function(table,id,fid,vid,iid,rsc,vtype) {
    $(vid).innerHTML='';
    var val=$(fid).value+' '+$(fid+'_hour').value+':'+$(fid+'_min').value+':00';
    new Ajax.Updater(vid,'ajax.asp',{parameters:{act:'editsave',table:table,id:id,fid:fid,vid:vid,val:val,rsc:rsc,vtype:vtype},insertion:Insertion.Top,evalScripts:true, queue:{position:'end',scope:'doqueue'}});
}
var esave=function(table,id,fid,vid,element,rsc,vtype) {
    clearTimeout(timeOuts['timedsave_'+fid]); 
    timeOuts['timedsave_'+fid] = setTimeout(function(){
    	dosave(table,id,fid,vid,element,rsc,vtype)
    },500);    	
}
var dosave=function(table,id,fid,vid,element,rsc,vtype,opt) {
	var val='', onComplete, form;

    opt = typeof opt == "object" ? opt : {};
    onComplete = opt.onComplete || function(){};
    
    element = $(element);
    
    // Get current form
    form = element.up('form');
    
    // Add's a vid span if not exist
    if( !$(vid) ){
    	var new_velement = new Element('span',{id:vid});
    	$(element).parentNode.insert(new_velement, {after:element} );
    }
    $(vid).innerHTML='';
    
    
    switch(element.type) {
    	case 'checkbox':
	    	// Pull in all checkboxes with the same name
	    	var checkboxGroup = form.select('input[type=checkbox][name=' + element.name + ']');
	        val=checkboxGroup.collect(function(checkbox){
	        	return checkbox.checked ? 1 : 0; // Gotta be 1/0 for database.
	        });
	        
	        // Make hyphenated string if more than one checked.
	        if ( val.length > 1 ){
	       		val = val.join('-');
	       		// Make the string look like - string - cuz we need extra dashes for some reason...
	      		val = "-" + val + "-";
	       	}else if(val.length > 0){
	       		val = val[0];
	       	}else{
	       		val = 0;
	       	}

	        break;
	       
		case 'radio':
			// Pull in same named radio buttons
			var radioButton = form.select('input[type=radio][name=' + element.name + ']:checked');
			
			val = radioButton.length > 0 ? radioButton[0].value : 0;
	        
	        break;
		
    	case 'select-one':
    		var val=$(element).options[$(element).selectedIndex].value;
    		break;
    		
    	default:
    		var val=$F(element);
    }
    
    // Ajax it up!
    new Ajax.Updater(vid,'ajax.asp',{
        parameters:{
            act:'editsave',
            table:table,
            id:id,
            fid:fid,
            vid:vid,
            val:val,
            rsc:rsc,
            vtype:vtype
        },
        evalScripts:true,
        queue:{
            position:'end',
            scope:'doqueue'
        },
        onComplete : onComplete
    });
}
var ecursave=function(table,id,fid,vid,iid,rsc,vtype) {
    clearTimeout(timeOuts['timedsave_'+fid]); 
    timeOuts['timedsave_'+fid] = setTimeout("docursave('"+table+"','"+id+"','"+fid+"','"+vid+"','"+iid+"','"+rsc+"','"+vtype+"')",1000);
}
var docursave=function(table,id,fid,vid,iid,rsc,vtype) {
    $(vid).innerHTML='';
    var val=cformat($(iid).value);
    new Ajax.Updater(vid,'ajax.asp',{parameters:{act:'editsave',table:table,id:id,fid:fid,vid:vid,val:val,rsc:rsc,vtype:vtype},insertion:Insertion.Top,evalScripts:true, queue:{position:'end',scope:'doqueue'}});
}
var fsave=function(formid,asppage,iid,vid) {
	var form = $(formid);
    form.target=iid;
    form.action=asppage;
    submitform(form);
    $(vid).innerHTML='<img src="/library/ajax-loader.gif" alt="please wait">';
}

var fsave2=function(form,aspurl,iframeId,vid){
	form = $(form);
    form.target=iframeId;
    form.action=aspurl;
    
    submitform(form);
    $(vid).addClassName('loading');
}

var foldersave=function(table,id,fid,vid,iid,vtype) {
    clearTimeout(timeOuts['timedsave_'+fid]); 
    timeOuts['timedsave_'+fid] = setTimeout("folderesave('"+table+"','"+id+"','"+fid+"','"+vid+"','"+iid+"','"+vtype+"')",1000);
}
var folderesave=function(table,id,fid,vid,iid,vtype) {
    $(vid).innerHTML='';
    var val=$(fid).value;
    new Ajax.Updater(vid,'ajax.asp',{parameters:{act:'foldersave',table:table,id:id,fid:fid,vid:vid,val:val},insertion:Insertion.Top,evalScripts:true, queue:{position:'end',scope:'doqueue'}});
}

//------------------------- MODULE SPECIFIC ---------------------------//
var activatemod=function(table,id,col,val1,val2) {
    $('activate'+id).innerHTML='';
    new Ajax.Updater('activate'+id,'module_admin_ajax.asp',{parameters:{act:'activatemod',id:id,table:table,val1:val1,val2:val2,col:col},insertion:Insertion.Top,evalScripts:true});
}
var delmod=function(table,id,col,fid,title,fid2,fid3,fid4,fid5) {
    $('msg').innerHTML='';
    new Ajax.Updater('msg','module_admin_ajax.asp',{parameters:{act:'delmod',id:id,col:col,table:table,fid:fid,title:title,fid2:fid2,fid3:fid3,fid4:fid4,fid5:fid5},insertion:Insertion.Top,evalScripts:true, queue:{position:'end',scope:'doqueue'}});
}
var killmod=function(table,id,col,fid,fid2,fid3,fid4,fid5) {
    new Ajax.Updater('dname','module_admin_ajax.asp',{parameters:{act:'killmod',id:id,table:table,fid:fid,fid2:fid2,fid3:fid3,fid4:fid4,fid5:fid5,col:col},insertion:Insertion.Top,evalScripts:true, queue:{position:'end',scope:'doqueue'}});
}
var posmod=function(table,list,col) {
    var thelist=Sortable.sequence(list);
    var fullist=''
    for (x in thelist) {
        if (parseInt(thelist[1,x])==thelist[1,x]) {
            fullist=fullist+thelist[1,x]+'-'
        }
    }
    new Ajax.Updater('dname','module_admin_ajax.asp',{method:'post',parameters:{act:'posmod',table:table,ids:fullist,col:col},evalScripts:true,evalJS:true});
}
////////////////////////////////////////////////////////////////////////////////////////// Interface
var useful=function(act,id) {
    $(fid).innerHTML='';
    new Ajax.Updater('use','ajax.asp',{parameters:{act:act,id:id},insertion:Insertion.Top,evalScripts:true, queue:{position:'end',scope:'doqueue'}});
}
var fadeusebox=function() {
    $('useholder').fade();
    new Effect.Opacity('pageholder',{ duration: 0.5, from: 0.3, to: 1 });    
}
var hidemsg=function() {
    $('msgholder').fade();
    if ($('useholder').style.display=='none') {
        new Effect.Opacity('pageholder',{ duration: 0.5, from: 0.3, to: 1 });    
    }
}
var fadepage=function() {
    $('pageholder').fade({from: 1, to: 0.3 });
}
var fadebody=function() {
    $('pageholder').fade({from: 1, to: 0.3 });
    $('botholder').fade({from: 1, to: 0.3 });
}
var restorebody=function() {
    $('pageholder').fade({from: 0.3, to: 1 });
    $('botholder').fade({from: 0.3, to: 1 });
}
var fadetmsg=function() {
    $('tmsg').fade({ duration: 2.0, from: 1, to: 0, delay: 4.0 });
}
var toggleme=function(sss) {
    if ( $(sss).style.display != 'none' )    {
        $('msgholder').appear();
    }
    else {
        $('msgholder').fade();
    }
}
var toggleshow=function(sss) {
    Effect.Queues.get("shower").cancel(sss)
    $(sss).appear({queue:{scope:"shower"}});
}
var togglehide=function(sss) {
    Effect.Queues.get("shower").cancel(sss)
    $(sss).fade({queue:{scope:"shower"}});
}
var toggleimg=function(sss,ttt,uuu) {
    if ($(sss).src==ttt) {
        $(sss).src=uuu;
    }
    else {
        $(sss).src=ttt;
    }
}
////////////////////////////////////////////////////////////////////////////////////////// Jump to URL
var jump=function(sss) {
    if (sss != "null") {
        document.location.href = sss;
    }
}
////////////////////////////////////////////////////////////////////////////////////////// Forms
var submitform=function(sss) {
    if (sss!="") {
        $(sss).submit();
    }
}
var clearme=function(sss) {
    if (sss.value == sss.defaultValue) {
        sss.value = "";
    }
}
////////////////////////////////////////////////////////////////////////////////////////// Show/Hide Item
var toggleme=function(sss) {
    if ( $(sss).style.display != 'none' )    {
        togglehide(sss);
    }
    else {
        toggleshow(sss);
    }
    document.body.style.overflow="auto";
}
////////////////////////////////////////////////////////////////////////////////////////// Bookmark Page
var bookmarksite=function(title,url) {
    /* Bookmark site script- © Dynamic Drive DHTML Code library 
    (www.dynamicdrive.com) This notice MUST stay intact for legal use
    Visit Dynamic Drive at http://www.dynamicdrive.com/ for full source code*/
    if (window.sidebar) // firefox
    {
        window.sidebar.addPanel(title,url,"");
    }
    else if (window.opera && window.print) // opera
    {
        var elem = document.createElement('a');
        elem.setAttribute('href',url);
        elem.setAttribute('title',title);
        elem.setAttribute('rel','sidebar');
        elem.click();
    } 
    else if(document.all)// ie
    {
        window.external.AddFavorite(url, title);
    }
}
////////////////////////////////////////////////////////////////////////////////////////// Cookies
var docookie=function(name,val) {
    document.cookie=name+'='+val+';'
}
var getcookie=function(sss) {
    var results = document.cookie.match ( '(^|;) ?' + sss + '=([^;]*)(;|$)' );
    if (results) {
        return (unescape(results[2]));
    }
    else {
        return null;
    }
}
////////////////////////////////////////////////////////////////////////////////////////// Currency Formatting
var cformat=function(sss) {
    var i = parseFloat(sss);
    if(isNaN(i)) {
        i = 0.00;
    }
    var minus = '';
    if(i < 0) {
        minus = '-';
    }
    i = Math.abs(i);
    i = parseInt((i + .005) * 100);
    i = i / 100;
    s = new String(i);
    if(s.indexOf('.') < 0) {
        s += '.00';
    }
    if(s.indexOf('.') == (s.length - 2)) {
        s += '0';
    }
    s = minus + s;
    return s;
}
///////////////////////////////////////////// get elements by class
/*
    Developed by Robert Nyman, http://www.robertnyman.com
    Code/licensing: http://code.google.com/p/getelementsbyclassname/
*/    
var getElementsByClassName = function (className, tag, elm){
    if (document.getElementsByClassName) {
        getElementsByClassName = function (className, tag, elm) {
            elm = elm || document;
            var elements = elm.getElementsByClassName(className),
                nodeName = (tag)? new RegExp("\\b" + tag + "\\b", "i") : null,
                returnElements = [],
                current;
            for(var i=0, il=elements.length; i<il; i+=1){
                current = elements[i];
                if(!nodeName || nodeName.test(current.nodeName)) {
                    returnElements.push(current);
                }
            }
            return returnElements;
        };
    }
    else if (document.evaluate) {
        getElementsByClassName = function (className, tag, elm) {
            tag = tag || "*";
            elm = elm || document;
            var classes = className.split(" "),
                classesToCheck = "",
                xhtmlNamespace = "http://www.w3.org/1999/xhtml",
                namespaceResolver = (document.documentElement.namespaceURI === xhtmlNamespace)? xhtmlNamespace : null,
                returnElements = [],
                elements,
                node;
            for(var j=0, jl=classes.length; j<jl; j+=1){
                classesToCheck += "[contains(concat(' ', @class, ' '), ' " + classes[j] + " ')]";
            }
            try    {
                elements = document.evaluate(".//" + tag + classesToCheck, elm, namespaceResolver, 0, null);
            }
            catch (e) {
                elements = document.evaluate(".//" + tag + classesToCheck, elm, null, 0, null);
            }
            while ((node = elements.iterateNext())) {
                returnElements.push(node);
            }
            return returnElements;
        };
    }
    else {
        getElementsByClassName = function (className, tag, elm) {
            tag = tag || "*";
            elm = elm || document;
            var classes = className.split(" "),
                classesToCheck = [],
                elements = (tag === "*" && elm.all)? elm.all : elm.getElementsByTagName(tag),
                current,
                returnElements = [],
                match;
            for(var k=0, kl=classes.length; k<kl; k+=1){
                classesToCheck.push(new RegExp("(^|\\s)" + classes[k] + "(\\s|$)"));
            }
            for(var l=0, ll=elements.length; l<ll; l+=1){
                current = elements[l];
                match = false;
                for(var m=0, ml=classesToCheck.length; m<ml; m+=1){
                    match = classesToCheck[m].test(current.className);
                    if (!match) {
                        break;
                    }
                }
                if (match) {
                    returnElements.push(current);
                }
            }
            return returnElements;
        };
    }
    return getElementsByClassName(className, tag, elm);
}
//
var mdlencheck = function() {
    var mdlen = $("metadesc").value.length;
    var mdcont = $("metadesc").value;
    $("mdlen").innerHTML = mdlen;
    if (mdlen>254)
    {
        var mdconc = mdcont.substr(0,254);
        $("metadesc").value = mdconc;
        $("mtlen").innerHTML = '255';
    }
}
//
var mtlencheck = function() {
    var mtlen = $("mtitle").value.length;
    var mtcont = $("mtitle").value;
    $("mtlen").innerHTML = mtlen;
    if (mtlen>254)
    {
        var mtconc = mtcont.substr(0,254);
        $("mtitle").value = mtconc;
        $("mtlen").innerHTML = '255';
    }
}
//
var keylencheck = function() {
    var keylen = $("keywords").value.length;
    var keycont = $("keywords").value;
    $("keylen").innerHTML = keylen;
    if (keylen>254)
    {
        var keyconc = keycont.substr(0,254);
        $("keywords").value = keyconc;
        $("mtlen").innerHTML = '255';
    }
};
// Adams Queue
// Cancel any effect on the specified element
Effect.ScopedQueue.prototype.cancel = function(el)
{
    if(typeof(el) != 'object'){
        el = $(el);    
    }
    
    this._each(function(qel){
        if(qel.element == el){
            qel.cancel();
        }
    })
}
// Adam function check if element is hidden (or if it's ancestors are hidden)
// These are a bit messy as you must use element.addMethods for element.prototype changes in IE
var isHidden = function(elem){

    // recurse through parentNodes    
    var parentWalk = function(currNode){
        var $node = $(currNode);
        
        if($node.nodeType == 9){ //at top level of node tree            
            return false;
        }else if($node.nodeType == 1){
            if($node.getStyle('display') == "none"){
                return true;
            }else{
                return parentWalk($node.parentNode);
            }
        }
    }
    
    // Call parentWalk on this element
    return parentWalk(elem);
}

// Recursive Function to recurse through parentNodes and match them against a function
// Pass a function that accepts one parameter of the current element in the search.
var findAncestor = function(elem, findFunc){
	var parentWalk = function(currNode){
		var $node = $(currNode);
		
		if($node.nodeType == 9){ // At top level of node tree
			return false;
		}else if($node.nodeType == 1){
			// Does this node match the find function
			if(findFunc($node) == true){
				return $node;
			}else{
				return parentWalk($node.parentNode);
			}
		}
	}
	
	// Start recursion
	return parentWalk(elem);
}

//Element.prototype.isHidden = isHidden;

//Opposite of insertBefore...
var insertAfter = function(elem,node,referenceNode){
    elem.insertBefore(node,referenceNode.nextSibling);
}
//Element.prototype.insertAfter = insertAfter;


/**
* 	Hides the current element and shows the passed element
*/
var swapVisibility = function(elem, withElem){
	elem = $(elem);
	withElem = $(withElem);
	
	elem.toggle();
	withElem.toggle();
}

// Because IE can't handle Element.prototype modification...
var methods = {
    insertAfter : insertAfter,
    isHidden    : isHidden,
    findAncestor : findAncestor,
    swapVisibility : swapVisibility 
}
Element.addMethods(methods);

// Make sure element contains a number. Run on keyup to parse out other characters.
// Set isfloat to true to not parse '.'s
var isnum=function(el,isfloat,nozero) {
    var el = (typeof el != "object") ? $(el) : el;
    
    var val = el.value;
    var thisno = '';
    
    if(val.length > 0){
        for(var i=0; i < val.length; i++){
            if((val.charAt(i) == "." && isfloat == true) || !isNaN(val.charAt(i)))
                thisno += val.charAt(i);
        }
    }else{
        thisno = '0';    
    }
    
    if(isfloat == true){
        //thisno = parseFloat(thisno);
    }else
        thisno = parseInt(thisno,10);

    el.value=thisno;
    if(nozero == true && thisno == 0)
        el.value = '';
    return thisno;
}

// Call this to observe all inputs on a page with the class 'number' and call isnum on all of them.
// If they have class 'float' then will pass float = true to isnum
var numput = function(){
    var isfloat = false;
    var nozero = false;
    // Observe input class = number with isnum 
    $$('input.number').each(function(e){
        if(e.hasClassName('float'))
            isfloat = true;
        if(e.hasClassName('nozero'))
            nozero = false;
        e.observe('keyup',function(evt){isnum(evt.element(),isfloat,nozero)});    
    });
}
    
// Returns most fitting event eg. onChange, onClick for an element.
var getObserveType = function(el){
    var returnType;
    
    // Switch on element type
    switch (el.type){
        case 'select-one':
            returnType = 'change';
            break;
        
        case 'radio': case 'checkbox':
            returnType = 'click';
            break;
        
        default:
            returnType = 'keyup';
            break;
    }
    
    // Special cases
    if( el.hasClassName('color') )
        returnType = 'change';
        
    return returnType;
}

// Saves a form with formception.
var save_form = function(evt,form_id){
    evt.stop();
    // Get the element that was clicked on.
    var el = evt.element();
    
    // Clear any error messages
    $$('.error_hold').each(function(eh){eh.remove();});
    $$('input.error').each(function(ie){ie.removeClassName('error');});
                
    // Handle errors
    var errFlag = 0;
    var make_err = function(el,err){
        var errSpan = new Element('span',{'class':'error'}).update(err);
        var errSpanHold = new Element('span',{'class':'error_hold'}).update(errSpan);
        
        el.parentNode.insertAfter(errSpanHold,el);
        el.addClassName('error');
        
        errFlag=1;
    }
    
    /*Uncomment if we're using CodeMirror for textbox syntax highlighting. You can probably add a CKEditor.Instances.invoke("updateElement") or whatever here too
    if(codeMirrors.length > 0)
        codeMirrors.invoke('save');
    */
    
	var CKInstances = CKEDITOR.instances
	for( var CKI in CKInstances){
		if(CKInstances.hasOwnProperty(CKI)){
			CKInstances[CKI].updateElement();	
		}
	}
	
    // set form action to ajax.asp
    form_id = 'save_form' || form_id;
    var form = $(form_id);
    form.action = form.action || "ajax.asp";
    
    var inputs = form.getInputs();
    inputs.each(function(inp){
        if(inp.hasClassName("required") && inp.value == '')
            make_err(inp,'This field cannot be empty');
    });
    
    // If there are no immediate issues picked up by js
    if(errFlag == 0 ){
        
        // We need to sort out checkboxes before sending them as otherwise they'll only be sent if they're checked.
        var checked = {}
        var checkBoxes = form.getInputs('checkbox');
        checkBoxes.each(function(cb){
            checked[cb.name] = cb.checked ? 1 : 0;
        });
        
        // Params to pass to ajax
        params = {
            act : 'save_form'    
        };
        
        // Merge params with checked object -> if they're sent as params they take precidence over the actual form items
        params = Object.extend(params,checked);
        
        // Ajax submit form
        form.request({
            parameters: params,
            onComplete:function(res){                
                // If there is no response text then assume success.
                var rText = res.responseText;
                if (!rText || rText === ""){
                    // Goto the links href.
                    window.location.href = el.href;    
                }else{
                    var json =     res.responseText.evalJSON();
                    
                    // Loop through json and create relevant errors
                    for(var js in json){
                        if( json.hasOwnProperty(js)){
                            var jsEl = $(json[js].name);
                            var err = json[js].error;
                            
                            make_err(jsEl,err);
                        }
                    }
                }
            },
            evalScripts : true
        });
    }
}

// Ajax updater for event calendar
var calendarAjax = function(){
	$$('.cal_link[href="calendar"]').each(function(cal_link){
		// Find the ancestor calendar holder
		var cal_holder = cal_link.up('.cal_holder');
		
		cal_link.observe('click',function(evt){
			evt.stop();
			var newDate = cal_link.getAttribute('data-date');
			
			new Ajax.Updater(cal_holder,'/ajax/calendar.asp',{
				parameters:{
					monthdate : newDate
				},
				evalScripts:true
			});
		});
	});
}

// Parses first occurence of number in string
var parseFirstInt = function(str){
	// Loop through string
	for (var i=0; i<str.length; i++) 
	{ 
		// If this part of the string is a number
		if (!isNaN(str[i]))
			return parseInt(str.substr(i,str.length)); 
	}
	// No number found
	return;	
} 

var parseFirstFloat = function(str){
	// Loop through string
	for (var i=0; i<str.length; i++) 
	{ 
		// If this part of the string is a number
		if (!isNaN(str[i]))
			return parseFloat(str.substr(i,str.length)); 
	}
	// No number found
	return;	
}

var mguid = function(){
	return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
	    var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
	    return v.toString(16);
	});
}


/**
*	Upload class
*	Allows an ajax-y upload to an iframe. Uses the action set on the form and creates an iframe.
*
*	@param	form			obj/string	 	the form/form id to upload
*	@param	completeFunc	function		the function to run on upload complete
*
*	REMEMBER TO CALL WITH 'new' SO new qbd.upload(...);
*/
qbd.uploads = [];
qbd.upload = function(form, opt){
	var IFRAME_CLASS = "upload_iframe";
	var IFRAME_HOLDER = "#iframeholder" // Where to put the iframe
	var fake_form;
	
	opt = typeof(opt) == 'object' ? opt : {};
	
	// Add to array of uploads
	this.upload_id = qbd.uploads.push(this) - 1; // -1 as push returns length rather than position
	
	this.completeFunc = opt.onComplete || function(){};
	var specificInput = $(opt.input);
	this.specificInput = specificInput;
	
	// Add qbd_upload_id to form action
	this.form = $(form);
	var action = this.form.getAttribute('action');
	action = action.replace(/.qbd_upload_id=\d*/,"");
	action += action.indexOf("?") > -1 ? "&" : "?";
	action += 'qbd_upload_id=' + this.upload_id;
	// If a form is inside another form, modern browsers pretend it doesn't exist. Therefore,
	// we want this to work on other elements.
	// We still need to submit a real form though, so we will create a form as a js object.
	if(this.form.nodeName != 'FORM'){
		var form_contents = $j(this.form).contents();
		fake_form = $j('<form enctype="multipart/form-data" method="post"></form>');
		fake_form.append(form_contents);
		$j(this.form).append(fake_form[0]);
		this.form = fake_form[0];
	}
	this.form.action = action;
	
	// Loop through file inputs
	this.file_inputs = this.form.select('input[type=file]');
	this.file_inputs.each(function(inp){
		// Add a loading class to the file inputs
		inp.addClassName('loading');
		
		// If specific input then disable other file inputs
		if(specificInput && specificInput != inp){
			inp.setAttribute('disabled','disabled');
		}
	});
 	
	// Create an iframe to upload to
	this.iframe = new Element('iframe',{
		'class': IFRAME_CLASS,
		'name':	'qbd_upload_iframe_' + this.upload_id,
		'id' : 'qbd_upload_iframe_' + this.upload_id
	});
	
	// Save original form target so it can be reset after upload
	this.originalTarget = this.form.target;
	this.form.target = this.iframe.name;
	
	this.iframe_holder = $$(IFRAME_HOLDER)[0];
	this.iframe_holder.appendChild(this.iframe);
	this.iframe_holder.show();
	
	submitform(this.form);
}

/*
*	Function that runs on completion of upload
*/
qbd.upload.prototype.complete = function(){
	this.completeFunc(arguments);
	
	// Delete the iframe
	this.iframe_holder.removeChild(this.iframe);
	this.iframe_holder.hide();
	
	// Reset form target
	this.form.target = this.originalTarget;
	
	// Re-enable file inputs
	if(this.specificInput){
		this.file_inputs.each(function(inp){
			inp.removeAttribute('disabled');
		});
	}
	
	// remove loading class
	this.form.select('input[type=file]').invoke('removeClassName','loading');
}

/*////////////////////////////////////////// Modules JS ///////////////////////////////////////*/
var addmodule=function(pageid) {
	var modwidth=600
	var modheight=600
	$('siteframe').src='/cp/addmodules.asp?id='+pageid;
	$('siteframe').style.display='block';
	//$('siteframe').style.height=modheight+'px';
	//$('siteframe').style.width=modwidth+'px';
	toggleshow('iframeholder');
	$("preview").innerHTML='Close';
	window.scrollTo(0, $("preview").offsetTop);
	toggleme('iframeholder');
	closeLeft=eval(document.viewport.getWidth()/2)
	closeLeft=closeLeft+(modwidth/2)-15
};

var addmodfromcol=function(pageid,col,modtype) {
	var modwidth=600
	var modheight=600
	$('siteframe').src='/cp/addmodules.asp?act=gotdata&inpage=1&id='+pageid+'&col='+col+'&modtype='+modtype;
	$('siteframe').style.display='block';
	//$('siteframe').style.height=modheight+'px';
	//$('siteframe').style.width=modwidth+'px';
	toggleshow('iframeholder');
	$("preview").innerHTML='Close';
	window.scrollTo(0, $("preview").offsetTop);
	toggleme('iframeholder');
	closeLeft=eval(document.viewport.getWidth()/2)
	closeLeft=closeLeft+(modwidth/2)-15
};

var editmodule=function(modid,modtype,modwidth,modheight,col,isnew,pagetype) {
	if (isnew==0) {
		if (modtype=='navigation') {
			$('siteframe').src='/cp/pages.asp?act=editnav&inpage=1&id='+modid+'&thiscol='+col;
		}
		else {
			$('siteframe').src='/cp/mod_'+modtype+'.asp?act=edit&inpage=1&id='+modid+'&thiscol='+col;
		}
	} else {
		if (modtype=='navigation') {
			$('siteframe').src='/cp/pages.asp?act=addnav&inpage=1&parid='+modid+'&modtype='+modtype+'&thiscol='+col+'&ptype='+pagetype;
		}
		else {
			$('siteframe').src='/cp/mod_'+modtype+'.asp?act=add&inpage=1&parid='+modid+'&modtype='+modtype+'&thiscol='+col+'&ptype='+pagetype;
		}
	}
	$('siteframe').style.display='block';
	//$('siteframe').style.height=modheight+'px';
	//$('siteframe').style.width=modwidth+'px';
	toggleshow('iframeholder');
	$("preview").innerHTML='Close';
	window.scrollTo(0, $("preview").offsetTop);
	closeLeft=eval(document.viewport.getWidth()/2)
	closeLeft=closeLeft+(modwidth/2)-15
};

var doUpdatecols=function(pageid,col,modtype,modid,pagetype) {
	new Ajax.Updater('cols','ajax.asp',{parameters:{act:'addmodule',type:pagetype,modtype:modtype,pageid:pageid,thiscol:col,modid:modid},evalScripts:true,evalJS:true, queue:{position:'end',scope:'doqueue'}});	
	document.getElementById("preview").innerHTML='Preview';
}

/*/////////////////////////////////////////// PUBLISH / PREVIEW //////////////////////////////////////*/
function isEmpty(ob){
   	for(var i in ob){ return false;}
 	return true;
}

var ckgo=function(id,onComplete) {
	var dbtable=$F('table');
	var ii=0;
	onComplete = onComplete || function(){};
	
	if (!isEmpty(CKEDITOR.instances)) {
		for(var ck in CKEDITOR.instances) {
			if (ii>0) {
				onComplete = null;
			}
			CKEDITOR.instances[ck].updateElement();
			dosave(dbtable,id,ck,'v'+ck,ck,'xs','1',{
					
				onComplete:onComplete
			});
			ii++;
		}
	}
	else {
		onComplete();
	}
};

var publish=function(id){
	ckgo(id,function(){
		document.location='?act=publish&id='+id;
	});
};

var publishmod=function(id,col,inpage){
	ckgo(id,function(){
		document.location='?act=publish&id='+id+'&thiscol='+col+'&inpage='+inpage;
	});
};

var dopreview=function(iframe,url,id,sd) {
	ckgo(id,function(){
		url=pformat(url);
		if ($(iframe).style.display=='none') {
			$(iframe).src='http://'+sd+'/'+url+'?preview=1';
			$(iframe).style.display='block';
			$(iframe).style.height=document.viewport.getHeight()-100 +'px';
			$(iframe).style.width=document.viewport.getWidth()-100 +'px';
			$("preview").innerHTML='Close';
			window.scrollTo(0, $("preview").offsetTop);
			toggleme('iframeholder');
		}
		else {
			$(iframe).style.display='none';
			$("preview").innerHTML='Preview';
			togglehide('iframeholder');
		}
	});
};

var loadAjaxFile = function(el, path, params, onComplete){
	var ajaxParams = {};
	
	onComplete = onComplete || function(){};
	
	params = params.split("&");
	params.each(function(param){
		param = param.split('=');
		ajaxParams[param[0]] = param[1];
	});
	
	new Ajax.Updater(el, path, {
		parameters:ajaxParams,
		evalScripts:true,
		onComplete : onComplete
	});
};

var esave_observe = function(){
	$$('.esave').each(function(e){
		if(!e.hasClassName('esave_observed')){
			
			var vtype='0';
			var rsc='xs';
			
			if (e.hasClassName('vali')) {
				vtype='1';
			}
			
			// Get event name to observe
			var meth = getObserveType(e);
			
			// Get either form wide table and id or page wide table and id
			var form = e.up('fieldset'),
				tbl,id;
			if(!form) form = e.up('form');
			
			if( form ){
				tbl= form.select('input[name=table]');
				tbl = tbl.length > 0 ? tbl[0] : null;
				
				id= form.select('input[name=id]');
				id = id.length > 0 ? id[0] : null;
			}
			tbl = $F(tbl || 'table');
			id = $F(id || 'id');
			
			//If id of element is not the same as the field name, get the name
			var fid=e.getAttribute('name') || e.id 
			
			// Array of arguments we will pass to esave
			var args = [
				tbl,
				id,
				fid, 
				'v'+e.id, 
				e, //Pass element rather than id. 
				rsc, 
				vtype,
				{
					form : form
				}
			];
			
			// Do observes
			if (e.hasClassName('cur')) {
				e.observe(meth,function(){
					ecursave.apply(this, args);
				});
				e.observe('blur',function(){
					ecursave.apply(this, args);
				});
			}
			else if (e.hasClassName('date')) {
				e.observe(meth,function(){
					datesave.apply(this, args);
				});
				e.observe('blur',function(){
					datesave.apply(this, args);
				});
			}else if( e.hasClassName('ck') ){
				// Should we replace with a ckeditor?
				// Note: CKEDITOR automatically replaces class="ckeditor" If CKEDITOR.replaceByClassEnabled = 1
				// make observe
				
				// If there's already a ckeditor with this name, we'll have to destroy it and recreate.
				// This is usually when we pull in a textarea again with ajax and it doesn't have the esave_observed class
				if( CKEDITOR.instances[e.id] ){
					CKEDITOR.instances[e.id].destroy();
				}
				
				CKEDITOR.replace(e,{
					customConfig: '/cp/ckeditor/config_pages.js'
				});
				
				CKEDITOR.instances[e.id].on('instanceReady', function(){	
					var ck = this;
						
					var sCK = function(){
						ck.updateElement();
						esave.apply(this, args);
					}
					
					this.document.on('keyup',sCK);
					this.document.on('click',sCK);
					this.document.on('blur',sCK);
					this.document.on('paste',sCK);
					
					// also save on unonload
					window.onunload = function(){
						ck.updateElement();
						dosave.apply(this, args);
					}
				});
			}
			else {
				e.observe(meth,function(){
					esave.apply(this, args);
				});
				e.observe('blur',function(){
					esave.apply(this, args);
				});
			}
		
			// So we don't double observe.]
			e.addClassName('esave_observed');
		}
	});
};

// Find elements with class verify and ensure that the elements referred to verify.
var verify_observe = function($){
	$('.verify').each(function(){
		var $this = $(this),
			verifythat = $this.data('that');
		
		$this.hide();
		
		// real code goes here in future.
		var weight_to = $('#weight_to');
		var weight_from = $('#weight_from');
		
		weight_to.add(weight_from).keyup(function(){
			if(weight_to.val() > weight_from.val()){
				$this.hide();
			}else{
				$this.show();
			}
		});
	});
}

var checkpcm=function(checkbox,page,cols,modid,modtyp,typ) {
	var checked=checkbox.checked ? 1 : 0;
    new Ajax.Request('ajax.asp',{method:'post',parameters:{act:'checkpcm',checked:checked,page:page,cols:cols,modid:modid,modtyp:modtyp,typ:typ}});
}

var basket = {
	/*
	*	Remove product from basket
	*/
	removeProduct : function(el){
		new Ajax.Updater( el, '/ajax/ecommerce.asp',{
			parameters : {
				act : 'removeProduct',
				id : el.getAttribute('data-id')
			},
			
			onComplete: function(){
				el.remove();
			}
		});
	},
	
	updateQuantity : function(el, quantity){
		// Get quantity holder
		var price_holder = el.down('.price');
		if(!price_holder) throw "Basket row must have a div class = price to hold items price"
		var subtotal_holder = el.down('.subtotal');
		if(!subtotal_holder) throw "Basket row must have a div class = subtotal to hold items price * q"
		
		new Ajax.Updater( price_holder, '/ajax/ecommerce.asp',{
			parameters : {
				act : 'updatePrice',
				id : el.getAttribute('data-id'),
				quantity : quantity
			},
		})		
		new Ajax.Updater( subtotal_holder, '/ajax/ecommerce.asp',{
			parameters : {
				act : 'updateSubTotal',
				id : el.getAttribute('data-id'),
				quantity : quantity
			},
			onComplete: function(){
				basket.reTotal();
			}
		})
	},
	
	/*
	*	Update an element with a basket property. Allowed properties specified in ajax/ecommerce.asp
	*/
	get : function(el, property){
		if( $(el) ) {
			new Ajax.Updater( el, '/ajax/ecommerce.asp',{
				parameters : {
					act : 'get',
					property: property
				}
			});
		}
	},
	
	/*
	*	Updates subtotal, vat and total. Make sure id matches those properties.
	*/
	reTotal : function(){
		['subtotal', 'vat', 'total', 'delivery'].each(function(el){
			basket.get(el, el); // Name of element is same as property
		});
	},
	
	/*
	*	Change delivery
	*/
	changeDelivery : function(id){
		new Ajax.Request( '/ajax/ecommerce.asp', {
			parameters : {
				act : 'delivery',
				id : id
			},
			onComplete : function(){
				basket.reTotal();
			}
		})
	},
	
	/*
	*	Clear / empty basket
	*/
	clear : function(){
		new Ajax.Request( '/ajax/ecommerce.asp', {
			parameters : {
				act : 'clear'
			},
			onComplete : function(){
				jump("/");
			}
		});
	}
}

/*
*	Takes a form and a commad list of errors and gives input with name matching error a class of error
*/
var mark_form_errors = function(form, list){
	var errors = list.toLowerCase().split(",");
	
	// Loop through form and for each input check if it errored and give it a class accordingly.
	var inps = $(form).select('input','select','textarea');
	inps.each(function(inp){
		if( errors.indexOf(inp.name) > -1 ){
			inp.addClassName('error');
		}else{
			inp.removeClassName('error');
		}
	});
}

/*
*	Update h1 
*/
var h1 = function( text ){
	$j('h1').html( text );
}

/*
*	Get/set Querystring param
*	If set, it returns the new qs.
*	params:
*	key : the key in the qs
*	val(optional): value to change to
*	querystring(optional): the querystring to test on.
*/
var qs = function(){
	var key,val,setter;
	
	key = arguments[0];
	if ( arguments.length > 0 ){
		setter=true;
		val=arguments[1];
	}
	
	var full = window.location.search.substring(1);
	if ( arguments.length == 2 ) full = arguments[2];
	
	full=full.split("&");
	for(var i=0; i< full.length; i++){
		var keyval = full[i].split("=");
		if (keyval[0] == key){
			// If setter, set qs param/else, change
			if(setter){
				keyval[1] = val;
				keyval=keyval.join("=");
				full[i] = keyval;
				return full.join("&");
			}else{
				return keyval[1];
			}
		}
	};
	
	// Add to end of qs if not already in qs
	if(setter){
		full.push(key + '=' + val);
		full = full.join("&");
		return full;
	}
	return '';
}

/*
 *	Reset image width and height to original
 */
var resetImage = function(img){
	var tempImg = new Image();
	tempImg.src=img.src;
	tempImg.onLoad = function(){
		img.setAttribute('width', tempImg.width);
		img.setAttribute('height', tempImg.height);
	}
}

/*
*	Clear the input on click if it matches a string
*/
var clearIfString = function(element, str){
	if(element.value == str){
		element.value = '';
	}
};

/*	
*	This function is used by the price adjustment part of product option in cp
*/
var price_adjust = function(amount){
	var val = $j('#price_adjustment').value;
	
};

/*	
*	Show version info
*/
var showchangelog=function() {
	$('siteframe').src='/cp/changelog.asp';
	$('siteframe').style.display='block';
	toggleshow('iframeholder');
	$("preview").innerHTML='Close';
	window.scrollTo(0, $("preview").offsetTop);
	closeLeft=eval(document.viewport.getWidth()/2)
	closeLeft=closeLeft+(modwidth/2)-15
};


/*	
*	Bung products into basket
*/
var addtobasket=function(prodid) {
	var opt = $('opter') ? $('opter').value : 0;
	var q=$('q').value;
    new Ajax.Updater('msg','/ajax/ecommerce.asp',{parameters:{act:'addproduct',id:prodid,opt:opt,q:q},evalScripts:true,onComplete: function() {
		loadAjaxFile('minibasket','/ajax/minibasket.asp','')
	}});
	fadebody();
	$('msgholder').appear({ duration: 0.5, from: 0, to: 1 });
};
