/* credit: Kevin Hale
   http://particletree.com/features/javascript-basics-for-prototyping/ */

String.prototype.trim = function() {
    return this.replace( /^\s+|\s+$/, "" );
}

var vanilla = {

    has_swfobject : 1,

	getElementById : function( id ) {
		if ( document.getElementById ) {
			return document.getElementById( id );
		} else if ( document.all ) {
			return document.all[ id ];
		} else {
			return null;
		}
	},

	/* credit: Stephen Chapman (modified)
	   http://javascript.about.com/library/bldom08.htm */

	getElementsByClassName : function( clName ) {
		var elements = [];
		var pattern = new RegExp("\\b" + clName + "\\b");
		var els = document.getElementsByTagName('*');
		for (var i = 0; i < els.length; i++) {
			var classes = els[i].className;
			if ( pattern.test( classes ) ) elements.push( els[i] );
		}
		return elements;
	},

	/* credit: Kevin Hale
	   http://particletree.com/features/javascript-basics-for-prototyping/ */

	addClassName : function( el, className ) {
    	vanilla.removeClassName( el, className );
    	el.className = ( el.className + " " + className ).trim();
	},

	removeClassName : function( el, className ) {
    	el.className = el.className.replace( className, "" ).trim();
	},

	/* credit: Simon Willison
	   http://simon.incutio.com/archive/2004/05/26/addLoadEvent */

	addLoadEvent : function( func ) {
		var oldonload = window.onload;
		if ( typeof window.onload != 'function' ) {
			window.onload = func;
		} else {
			window.onload = function() {
				if ( oldonload ) oldonload(); // use conditional to keep IE7 happy
				func();
			}
		}
	},

	/* This function is used primarily to support popup video windows. */

	popup : function( p, h, w ) {
		if ( p != null ) {
			var widgets = "toolbar=0,location=0,directories=0,status=0,menubar=0,scrollbars=1,resizable=1,height=" + h + ", width=" + w;
			var popupWin = window.open( p, "popupWin", widgets );
		}
	},

	/* This function was originally used to pass parameters from a stub form to a full form,
	   prefilling the values without having to trigger processing resulting in error messages. */

	getParams : function() {
		var query = decodeURI( location.search.substring( 1 ) );
		var params = new Array();
		var pairs = query.split( '&' );
		for ( var i = 0; i < pairs.length; i++ ) {
			var nameVal = pairs[i].split( '=' );
			params[nameVal[0]] = decodeURIComponent( nameVal[1] );
		}
		return params;
	},

	/* The following two functions are for those clients who refuse to follow best practices
	   and insist that links open in a new window. By setting the class name of links to
	   "newwindow", we allow javascript to do the work and avoid deprecated target attributes.

	   credit: Roger Johansson (modified)
	   http://www.456bereastreet.com/archive/200605/using_javascript_instead_of_target_to_open_new_windows/ */

	openInNewWindow : function( e ) {
		var event;
		if ( !e ) {
			event = window.event;
		} else {
			event = e;
		}

		// Abort if a modifier key is pressed
		if ( event.shiftKey || event.altKey || event.ctrlKey || event.metaKey ) {
			return true;
		} else {
			// Change "_blank" to something like "newWindow" to load all links in the same new window
		    var newWindow = window.open( this.getAttribute('href'), '_blank' );
			if ( newWindow ) {
				if ( newWindow.focus ) {
					newWindow.focus();
				}
				return false;
			}
			return true;
		}
	},

	/* We might need to know if someone is logged in. cookie.js is sometimes loaded in 
	   the body of page in the login box block, so let's get a value ealier. */

	hasAuthCookie : function() {
		var pos = document.cookie.indexOf('auth_tkt=');
		if ( pos != -1 ) {
			return true;
		} else {
			return false;
		}
	},

	/* The following three functions get, set, and delete cookies. They were first added
	   to support better splash-page handling.

	   credit: http://www.echoecho.com/jscookies02.htm (modified) */

	getCookie : function( name ) {
		if (document.cookie.length > 0) {
			var begin = document.cookie.indexOf( name + '=' );
			if ( begin != -1 ) {
				begin += name.length + 1;
				var end = document.cookie.indexOf( ";", begin );
				if (end == -1) end = document.cookie.length;
				return unescape( document.cookie.substring(begin, end) );
			}
		}
		return null;
	},

    setCookie : function(name, value, expireDays, path, domain) {
        var expires = new Date ();
        expires.setTime(expires.getTime() + (expireDays * 24 * 3600 * 1000));
        document.cookie = name + "=" + escape(value) +
            ((expireDays == null) ? "" : "; expires=" + expires.toGMTString()) +
            ((path == null) ? "" : "; path=" + path) +
            ((domain == null) ? "" : "; domain=" + domain);
    },

	delCookie : function( name ) {
		if ( getCookie( name ) ) {
			document.cookie = name + "=" +
			  "; expires=Thu, 01-Jan-70 00:00:01 GMT";
		}
	},
	
    /* vanilla.is_logged_in()
        returns true if the person is logged in, else returns false */
    is_logged_in : function() {
        return !!vanilla.cookie.auth_params().email;
    },

    /* vanilla.cookie namespace
    a bunch of cookie related helper methods */
    cookie : {
        AUTH_COOKIE_NAME        : 'auth_tkt',
        PERSISTENT_COOKIE_NAME  : 'ARCOS_PERSISTENT_LOGIN',
        /* vanilla.cookie.get(name)
            The following three functions get, set, and delete cookies. They were first added
            to support better splash-page handling.
            credit: http://www.echoecho.com/jscookies02.htm (modified) */
        get : function(name) {
            if (document.cookie.length > 0) {
                var begin = document.cookie.indexOf(name + '=');
                if (begin != -1) {
                    begin += name.length + 1;
                    var end = document.cookie.indexOf(";", begin);
                    if (end == -1) end = document.cookie.length;
                    return unescape(document.cookie.substring(begin, end));
                }
            }
            return null;
        },
        /* vanilla.cookie.set(name, value, days, path, domain) */
        set : function(name, value, expireDays, path, domain) {
            var expires = new Date ();
            expires.setTime(expires.getTime() + (expireDays * 24 * 3600 * 1000));
            document.cookie = name + "=" + escape(value) +
                ((expireDays == null) ? "" : "; expires=" + expires.toGMTString()) +
                ((path == null) ? "" : "; path=" + path) +
                ((domain == null) ? "" : "; domain=" + domain);
        },
        /* vanilla.cookie.del(name) */
        del : function(name) {
            if (vanilla.cookie.get(name)) {
                document.cookie = name + "=" +
                  "; expires=Thu, 01-Jan-70 00:00:01 GMT";
            }
        },
        /* vanilla.cookie.auth_params()
            Get the Base64 encoded data out of our mod_auth_tkt cookie and return it as a JS hash */
        _auth_params : null,
        auth_params : function() {
            if( vanilla.cookie._auth_params != null )
                return vanilla.cookie._auth_params;

            // no cookies for our domain at all
            var allcookies = document.cookie;
            if( allcookies == null || allcookies == '' ) {
                vanilla.cookie._auth_params = {};
                return vanilla.cookie._auth_params;
            }

            // first look for the auth cookie, which is base64 encoded
            var value = vanilla.cookie.get(vanilla.cookie.AUTH_COOKIE_NAME);
            if( value ) {
                // Base64 decode the value
                value = vanilla.base64.decode(value);
                // now just get the DATA portion of the mod_auth_tkt cookie
                value = value.substr(40);       // this removes the digest and timestamp
                var bits = value.split('!');    // breaks up the uid, tokens and user data
                value = bits[bits.length -1];
            }

            // if that failed, look for the persistent cookie, which is not base64 encoded
            if (value == null) {
                value = vanilla.cookie.get(vanilla.cookie.PERSISTENT_COOKIE_NAME);
                if( value ) {
                    // break off the hash and UID
                    var bits = value.split('!');
                    value = bits[bits.length -1];
                }
            }
            // if after all that we found something, break it up into pairs for param
            vanilla.cookie._auth_params = {};
            if (value != null) {
                // split it into name-value pairs and put into the params hash
                var pairs = value.split('&');
                for (var i = 0; i < pairs.length; i++) {
                    var splitPair = pairs[i].split('=');
                    vanilla.cookie._auth_params[decodeURIComponent(splitPair[0])] =
                        decodeURIComponent(splitPair[1]);
                }
            }

            return vanilla.cookie._auth_params;
        }
    },


    /* vanilla.base64.decode(string)
        Adapted from the GPL code found at http://ostermiller.org/calc/encode.html */
    base64 : {
        END_OF_INPUT : -1,
        CHARS : {
            'A' :  0, 'B' :  1, 'C' :  2, 'D' :  3, 'E' :  4, 'F' :  5, 'G' :  6, 'H' : 7,
            'I' :  8, 'J' :  9, 'K' : 10, 'L' : 11, 'M' : 12, 'N' : 13, 'O' : 14, 'P' : 15,
            'Q' : 16, 'R' : 17, 'S' : 18, 'T' : 19, 'U' : 20, 'V' : 21, 'W' : 22, 'X' : 23,
            'Y' : 24, 'Z' : 25, 'a' : 26, 'b' : 27, 'c' : 28, 'd' : 29, 'e' : 30, 'f' : 31,
            'g' : 32, 'h' : 33, 'i' : 34, 'j' : 35, 'k' : 36, 'l' : 37, 'm' : 38, 'n' : 39,
            'o' : 40, 'p' : 41, 'q' : 42, 'r' : 43, 's' : 44, 't' : 45, 'u' : 46, 'v' : 47,
            'w' : 48, 'x' : 49, 'y' : 50, 'z' : 51, '0' : 52, '1' : 53, '2' : 54, '3' : 55,
            '4' : 56, '5' : 57, '6' : 58, '7' : 59, '8' : 60, '9' : 61, '+' : 62, '/' : 63
        },
        CURRENT_STR : null,
        CURRENT_COUNT : null,
        decode : function(str) {
            vanilla.base64.CURRENT_STR = str;
            vanilla.base64.CURRENT_COUNT = 0;
            var result = "";
            var inBuffer = new Array(4);
            var done = false;
            while (!done && (inBuffer[0] = vanilla.base64._next_char()) != vanilla.base64.END_OF_INPUT
                && (inBuffer[1] = vanilla.base64._next_char()) != vanilla.base64.END_OF_INPUT){
                inBuffer[2] = vanilla.base64._next_char();
                inBuffer[3] = vanilla.base64._next_char();
                result += vanilla.base64._ntos((((inBuffer[0] << 2) & 0xff)| inBuffer[1] >> 4));
                if (inBuffer[2] != vanilla.base64.END_OF_INPUT){
                    result +=  vanilla.base64._ntos((((inBuffer[1] << 4) & 0xff)| inBuffer[2] >> 2));
                    if (inBuffer[3] != vanilla.base64.END_OF_INPUT){
                        result +=  vanilla.base64._ntos((((inBuffer[2] << 6)  & 0xff) | inBuffer[3]));
                    } else {
                        done = true;
                    }
                } else {
                    done = true;
                }
            }
            return result;
        },
        _next_char : function() {   
            if (!vanilla.base64.CURRENT_STR) return vanilla.base64.END_OF_INPUT;
            while (true){      
                if (vanilla.base64.CURRENT_COUNT >= vanilla.base64.CURRENT_STR.length) return vanilla.base64.END_OF_INPUT;
                var nextCharacter = vanilla.base64.CURRENT_STR.charAt(vanilla.base64.CURRENT_COUNT);
                vanilla.base64.CURRENT_COUNT++;
                if (vanilla.base64.CHARS[nextCharacter]){
                    return vanilla.base64.CHARS[nextCharacter];
                }
                if (nextCharacter == 'A') return 0;
            }
            return vanilla.base64.END_OF_INPUT;
        },
        _ntos : function(n) {
            n=n.toString(16);
            if (n.length == 1) n="0"+n;
            n="%"+n;
            return unescape(n);
        }
    },
    
    /* This function enables IE Win to do state change on hover like better browsers.
	   It is used for menus set up as unordered lists. Change the nav root id 
	   if needed, and remember to add an "over" class to your stylesheet. */

	enableHover : function() {
		if ( navigator.userAgent.indexOf("MSIE ") != -1 ) {
			if ( vanilla.getElementById( "mainnav" ) ) { // prevent script warning in IE
				var nodes = vanilla.getElementById( "mainnav" ).getElementsByTagName( "LI" );
				for ( i = 0; i < nodes.length; i++ ) {
					var node = nodes[i];
					node.onmouseover = function() {
						vanilla.addClassName( this, "over" );
					}
					node.onmouseout = function() {
						vanilla.removeClassName( this, "over" );
					}
				}
			}
		}
	},

	/* This function adds three extra divs to an element in order to apply rounded
	   corners to a liquid box. Set the class name to "roundbutton" and add styles for that
	   class for the unstyled appearance. The class name is changed to "roundedbutton". */

	makeRoundedButtons : function() {
		var els = vanilla.getElementsByClassName( "roundbutton" );

		for (var i = 0; i < els.length; i++) {
			var el = els[i];

			/* Change class name for background images */
			vanilla.removeClassName( el, "roundbutton" );
			vanilla.addClassName( el, "roundedbutton" );
			
			/* gather up the children */
			var children = el.childNodes;
			var childElements = new Array();
			for ( var j = 0; j < children.length; j++ ) {
				if ( children[j].nodeType == 1 ) {
					childElements.push( children[j] );
				}
			}

			/* create new divs and append */
			var div1 = document.createElement( "div" );
			var div2 = document.createElement( "div" );
			var div3 = document.createElement( "div" );

			for ( var j = 0; j < childElements.length; j++ ) {
				div3.appendChild( childElements[j] );
			}

			div2.appendChild( div3 );
			div1.appendChild( div2 );
			el.appendChild( div1 );
		}
	},

	/* This function adds a number of extra divs to an element in order to apply rounded
	   corners to a fixed-width box. Set the class name to "roundbox" and add styles for that
	   class for the unstyled appearance. The class name is changed to "roundedbox". */

	makeRoundedBoxes : function() {
		var els = vanilla.getElementsByClassName( "roundbox" );

		for (var i = 0; i < els.length; i++) {
			var el = els[i];

			/* Change class name for background images */
			vanilla.removeClassName( el, "roundbox" );
			vanilla.addClassName( el, "roundedbox" );

			/* gather up the children */
			var children = el.childNodes;
			var childElements = new Array();
			for ( var j = 0; j < children.length; j++ ) {
				if ( children[j].nodeType == 1 ) {
					childElements.push( children[j] );
				}
			}

			/* create top and bottom divs */
			var topdiv = document.createElement( "div" );
			topdiv.className = "top";
			var topinner = document.createElement( "div" );
			topinner.appendChild( document.createComment( "ie6 fix" ) );
			topdiv.appendChild( topinner );

			var btmdiv = document.createElement( "div" );
			btmdiv.className = "bottom";
			var btminner = document.createElement( "div" );
			btminner.appendChild( document.createComment( "ie6 fix" ) );
			btmdiv.appendChild( btminner );


			/* wrap children in middle divs */
			var middiv1 = document.createElement( "div" );
			middiv1.className = "middle";
			var middiv2 = document.createElement( "div" );
			var middiv3 = document.createElement( "div" );

			for ( var j = 0; j < childElements.length; j++ ) {
				middiv3.appendChild( childElements[j] );
			}

			middiv2.appendChild( middiv3 );
			middiv1.appendChild( middiv2 );

			/* put them all together */
			el.appendChild( topdiv );
			el.appendChild( middiv1 );
			el.appendChild( btmdiv );
		}
	},

	/* This function is used on dropdown menus to send users to a new URL */

	jumpTo : function( select ) {
		var url = select[select.selectedIndex].value;
		if ( !url ) return;
		window.location = url;
	},

	/* This function is used on the homepage to rotate thru the top features. */

	switchFeature : function() {
		var features = vanilla.getElementsByClassName( 'home_feature' );
		for ( var i = 1; i <= features.length; i++ ) {
			vanilla.getElementById( 'home_feature_' + i ).style.display = 'none';
		}
		vanilla.getElementById( 'home_feature_' + nextFeature ).style.display = 'block';
		nextFeature += 1;
		if ( nextFeature > ctFeatures ) nextFeature = 1;
	},

	/* This function is used on the homepage to rotate thru the news features. */

	switchNews : function() {
		var news = vanilla.getElementsByClassName( 'news_pic' );
		for ( var i = 1; i <= news.length; i++ ) {
			vanilla.getElementById( 'news_pic_' + i ).style.display = 'none';
		}
		vanilla.getElementById( 'news_pic_' + nextNews ).style.display = 'block';
		nextNews += 1;
		if ( nextNews > ctNews ) nextNews = 1;
	},

    /* This function is used on the candidate section page to rotate thru the top-left images. */

    rotateImages : function() {
        var rotaters = vanilla.getElementsByClassName( 'rotater' );
        for ( var i = 1; i <= rotaters.length; i++ ) {
            vanilla.getElementById( 'rotater_' + i ).style.display = 'none';
        }
        var next = vanilla.getElementById( 'rotater_' + nextImg )
        if (next) next.style.display = 'block';
        nextImg += 1;
        if ( nextImg > ctImgs ) nextImg = 0;
    },
    
    // like Perl's Number::Format::format_number
    format_number : function(num) {
        num += '';
        x = num.split('.');
        x1 = x[0];
        x2 = x.length > 1 ? '.' + x[1] : '';
        var rgx = /(\d+)(\d{3})/;
        while (rgx.test(x1)) {
            x1 = x1.replace(rgx, '$1' + ',' + '$2');
        }
        return x1 + x2;
    },
    
    /* This function is used to toggle the values in certain form fields without field labels */

    swapValue : function( field, revert, defValue ) {
        if (defValue == undefined) defValue = field.defaultValue;
	    if (field.value == (revert ? '' : defValue)) {
	        field.value = (revert ? defValue : '');
	    }
	}

};


/* enable or disable as needed */

// vanilla.addLoadEvent( vanilla.getNewWindowLinks );
// vanilla.addLoadEvent( vanilla.makeRoundedButtons );
// vanilla.addLoadEvent( vanilla.makeRoundedBoxes );
vanilla.addLoadEvent( vanilla.enableHover );


$(document).ready(function() {
    $(".carousel").jCarouselLite({
        auto: 2000,
        speed: 1000,
        vertical: true,
        visible: 19
    });
    
    // rotate thru a set of divs -- this ties into innerfade.js
    // edit to change default options
    $('#fade').innerfade({
        speed: 2000,
        timeout: 8000,
        containerheight: 338,
        tracker: 'switcher',
        trackerclass: 'selected'
    });

    $('.selector').click(function() {
        if (this.id == 'stop' || this.id == 'start') {
            return;
        }

        if($('#fade').data('timer')) {
            clearTimeout($('#fade').data('timer'));
            $('#fade').removeData('timer');
            $('#stop').hide();
            $('#start').show();
        }

        var id = Number(this.id.substr(1));
        $('.selector').removeClass('selected');
        $(this).addClass('selected');
        $('#fade').children(':visible').fadeOut(2000);
        $('#feature_' + id).fadeIn(2000);
        var num = $('#fade').data('num_elements');
        if (id < num) {
            $('#fade').data('next', id);
        } else {
            $('#fade').data('next', 0);
        }
        return false;
    });
    
    // tribute giving
    $("#id_dedicate_gift").click( function() {
        if ($("#id_dedicate_gift").attr("checked")) {
            $("#dedicate_fields").show();
        } else {
            $("#dedicate_fields").hide();
        }
    });
    
    // handlers for fields in signup stub form
    $("input.swap").focus(function() {
        vanilla.swapValue(this, false);
    });
    $("input.swap").blur(function() {
        vanilla.swapValue(this, true);
    });
    
    // open certain classed links in new window
    $("a.newwindow").each(function() {
        $(this).css("padding-right", "18px").css("background", "url(/images/newwindow.png) no-repeat right").click(vanilla.openInNewWindow);
    });
    $("a.newwindow_noicon").each(function() {
        $(this).click(vanilla.openInNewWindow);
    });

});

// CF thermometer
vanilla.addLoadEvent(function() {
    if (typeof vanilla.cf_data == 'undefined') {
        return;
    }
    
    // we delay this a bit so the user will see the entire effect
    setTimeout(function() {
        jQuery('#cf_progress #goal').html('$' + vanilla.format_number(vanilla.cf_data.goal));
        jQuery('#cf_progress #count').html(vanilla.cf_data.count + ((vanilla.cf_data.count == 1) ? ' donor' : ' donors'));
        jQuery('#cf_progress #average').html('$' + vanilla.format_number((vanilla.cf_data.raised/vanilla.cf_data.count).toFixed(2)));

        // on the dashboard
        jQuery("body.community_contribution_editor_form #cf_progress").progressBar({
            value    : Math.round(vanilla.cf_data.raised * 100 / vanilla.cf_data.goal),
            height   : 190,
            width    : 32,
            callback : function(config) {
                var raised = 0;
                if (config.value > 0) {
                    raised = vanilla.format_number((vanilla.cf_data.raised * (config.runningValue / config.value)).toFixed(2));
                    raised = raised.replace('.00', '');
                }
                jQuery('#cf_progress #raised').html('$' + raised);
                
                if (config.runningValue == config.max) {
                    jQuery('#cf_progress').addClass('goal_reached');
                    jQuery('#cf_progress #scale').hide();
                }
                if (config.runningValue > config.max) {
                    jQuery('#cf_progress').addClass('goal_exceeded');
                    jQuery('#cf_progress #scale').hide();
                }
            }
        });
        
        // on the cf form
        jQuery("body.community_contribution_form #cf_progress").progressBar({
            value    : Math.round(vanilla.cf_data.raised * 100 / vanilla.cf_data.goal),
            height   : 161,
            width    : 11,
            barImage    : '/images/thermometer2_scale.jpg',
            callback : function(config) {
                var raised = 0;
                if (config.value > 0) {
                    raised = vanilla.format_number((vanilla.cf_data.raised * (config.runningValue / config.value)).toFixed(2));
                    raised = raised.replace('.00', '');
                }
                jQuery('#cf_progress #raised').html('$' + raised);
                
                if (config.runningValue == config.max) {
                    jQuery('#cf_progress').addClass('goal_reached');
                    jQuery('#cf_progress #scale').hide();
                }
                if (config.runningValue > config.max) {
                    jQuery('#cf_progress').addClass('goal_exceeded');
                    jQuery('#cf_progress #scale').hide();
                }
            }
        });
    }, 500);
});

