﻿/* 
CartTotalCalculator
---------
Description: 
Calculates the cost of a user's input selection and displays what the order total would be.
created: 		2/2009
last modified: 	2/9/2009 by keithr
version:		0.5

Usage:
	priceAttributeName - the dynamic attribute holding the prices string for all possible quantity selections
							ex.  'itemPrice', itemPrice="45.0,0,23.14"
	priceClassName - the class name of the elements holding the prices in the priceAttributeName attrib
							ex. 'CartTotal_PriceItem'
	quantityClassName - the class name of the elements holding the quantity values
							ex. 'CartTotal_QtyItem'
	startingCartTotal - starting value to add the calculation too
	subTotalOutputControl - the element whose innerHtml will be replaced by the caclulated sub-total
	cartTotalOutputControl - the element whose innerHtml will be replaced by the caclulated complete total
	
Notes:
	This control can calculate against a variety of form input scenarios by playing with the price values
		, including a ticket reservation page with multiple sections/radios and price_types/quantities/selects
		, a series of text boxes for purchasing flex passes
		or radio buttons representing suggested donations or to not donate.
	The same element can be both the price and quantity control by setting both priceClassName and quantityClassName on it.
			ex. 'class="CartTotal_PriceItem CartTotal_QtyItem"'
	The priceAttributeName attrib value on each price element needs to hold a value for each possible quantity
		element. A zero can be used to implement a 'selection represents a "none"' scenario. 
			ex. itemPrice="45.0,75.32,23.14",  itemPrice="0,1,0",   itemPrice="0,0,0"
*/
var CartTotalCalculator = Class.create(
{
    initialize: function(parentElementId, priceAttributeName, priceClassName, quantityClassName
                        , startingCartTotal
                        , subTotalOutputControl
                        , cartTotalOutputControl) 
    {
        this._priceAttributeName = priceAttributeName;
        this._priceClassName = priceClassName;
        this._quantityClassName = quantityClassName;
        this._startingCartTotal = startingCartTotal;
        this._subTotalOutputControl = subTotalOutputControl;
        this._cartTotalOutputControl = cartTotalOutputControl;

// debug
//alert(yo.yo);

        // price controls
        this._priceInputControls = $$(parentElementId + ' ' + priceClassName);

        // quantity controls
        this._quantityInputControls = $$(parentElementId + ' ' + quantityClassName);


		// for each price control, build price for each quantity control
		//	and store for calculating total upon click of each control.
		for(var controlIndex = 0; controlIndex < this._priceInputControls.length; controlIndex++)
		{
			control = this._priceInputControls[controlIndex];
			
			var priceValue = control.readAttribute(this._priceAttributeName);
        
            if (priceValue)
            {
                var priceValues = priceValue.split(',');
                
                // make numeric
                var pricesArray = new Array(priceValues.length);
                
                for(var index = 0; index < priceValues.length; index++)
                {
					pricesArray[index] = parseInt(priceValues[index]);
                }
                
                control.pricesArray = pricesArray;
                
				control.observe('click', this.Calculate.bindAsEventListener(this)); // recalc total on click
            }
		}

		// recalc total on click or keyup
		for(var controlIndex = 0; controlIndex < this._quantityInputControls.length; controlIndex++)
		{
			control = this._quantityInputControls[controlIndex];
			
			if ( this.__IsTextBox(control))
			{
				control.observe('keyup', this.Calculate.bindAsEventListener(this)); 
			}
			if ( this.__IsSelectList(control))
			{
				control.observe('change', this.Calculate.bindAsEventListener(this)); 
			}
			control.observe('click', this.Calculate.bindAsEventListener(this));
        }
        
        // run initial calculation on first load
        this.Calculate();
    },

    Calculate: function(e) 
    {
        // build price total of each item selected
        
        var priceTotal = 0.0;
        

        for(var controlIndex = 0; controlIndex < this._priceInputControls.length; controlIndex++)
        {
			// test control type and pull out the appropriate price
        
			control = this._priceInputControls[controlIndex];
        
			if ((control.checked || control.selectedIndex || this.__IsTextBox(control)) 
					&& control.pricesArray)
			{
				// radio/checkbox
				
				for(var index = 0; index < control.pricesArray.length; index++)
				{
					if (this._quantityInputControls.length >= index)
					{
						var quantityControl = this._quantityInputControls[index];
						
						var quantity = this.__GetQuantityValueFromControl(quantityControl);
						
						if (quantity && control.pricesArray[index] != NaN)
						{
							priceTotal += quantity * control.pricesArray[index];
						}
					}
				}
			}
        }

		// display total
		if (this._subTotalOutputControl)
		{
			this._subTotalOutputControl.update('$' + this.__FormatCurrency(priceTotal));
		}
		if (this._cartTotalOutputControl)
		{
			this._cartTotalOutputControl.update('$' + this.__FormatCurrency(this._startingCartTotal + priceTotal));
		}
    },
    
    __GetQuantityValueFromControl: function(control)
    {
		if (control && control.value)
		{
			var quantity = parseInt(control.value);
			
			/* for non=numeric values, returning 1 is needed for radios that hold the price and quantity  */
			if (isNaN(quantity))
			{
				if (this.__IsTextBox(control)){ quantity = 0; }
				else { quantity = 1; }
			}
			
			return quantity;
		}
		// check other control values
		
		return null;
    },
    
    __IsTextBox: function(control)
    {
		return (control.tagName == 'INPUT' && control.type == 'text');
    },

    __IsSelectList: function(control)
    {
		return (control.tagName == 'SELECT');
    },
        
    __FormatCurrency: function(num)
    {
    	// add commas
		if ((num >= 1000 || num <= -1000)) 
		{
			var tmpNumStr = num.toFixed(2);
			
			var iStart = tmpNumStr.indexOf(".");
			if (iStart < 0)
				iStart = tmpNumStr.length;

			iStart -= 3;
			while (iStart >= 1) 
			{
				tmpNumStr = tmpNumStr.substring(0,iStart) + "," + tmpNumStr.substring(iStart,tmpNumStr.length)
				iStart -= 3;
			}
			
			return tmpNumStr;
		}
		else { return num.toFixed(2); }
	}

});
