/** 
 * The PayPal Mini Cart enables a tighter integration with the 
 * PayPal Cart by allowing the user to never leave the merchant's 
 * site. When the user clicks on an "Add" button an editable 
 * cart will appear on top of your site.
 * 
 * To use simply include the script on a PayPal Cart enabled page.
 * 
 * Author: Jeff Harrell
 * Website: https://minicart.paypal-labs.com/
 */

(function() {
	
	var cart, products = [], settings = {};
	
	var init = function() {	
		if (!MiniCart) { MiniCart = {}; }
		
		// if the script has been run then bail
		if (MiniCart.active) return;
		MiniCart.active = true;
		
		// set some sensible defaults if they haven't already been configured
		MiniCart.edge = (MiniCart.edge == 'L') ? 'left' : 'right';
		MiniCart.distance = MiniCart.distance || '50px';
		MiniCart.path = MiniCart.path || '/';
		MiniCart.base = MiniCart.base || 'https://minicart.paypal-labs.com/';
		MiniCart.subdomain = MiniCart.subdomain || 'www';
		
		createCart();
		hijackForms();
		
		// load the data from the cookie
		try {
			var data = readData();

			if (data) {
				settings = data.settings;
				products = data.products;
					
				for (var i=0; i<products.length; i++) {	
					cart.add(products[i]);
				}
				
				data = null;
				
				setTimeout(function() { cart.hide(); }, 250);
			}
		} catch(e) {}

		// for all non-cart related clicks hide the cart 
		addEvent(document, 'click', function(e) {
			if (products.length > 0) {
				var current = e.target;
				
				if (current.tagName != 'INPUT') {
					while (current.nodeType == 1) {
						if (current == cart) {
							return;
						}
					
						current = current.parentNode;
					}
				
					cart.hide();
				}
			}
		});	
	};
	
	
	var createCart = function() {	
		cart = document.createElement('form');
		cart.style.position = 'fixed';
		cart.style.styleFloat = 'none';
		cart.style.cssFloat = 'none';
		cart.style.top = '-232px';
		cart.style.zIndex = '999';
		cart.style[MiniCart.edge] = MiniCart.distance;
		cart.style.width = '265px';
		cart.style.height = '155px';
		cart.style.background = '#fff url(' + MiniCart.base + 'images/paypal_logo.gif) no-repeat 10px 15px';
		cart.style.border = '1px solid #999';
		cart.style.borderTop = '0';
		cart.style.margin = '0';
		cart.style.padding = '50px 10px 0';
		cart.style.fontSize = '13px';
		cart.style.fontFamily = 'arial';
		cart.style.color = '#333';
		cart.style.opacity = '.9';
		cart.style.filter = 'alpha(opacity=95)';
		cart.style.MozBorderRadius = '0 0 8px 8px';
		cart.style.WebkitBorderBottomLeftRadius = '8px';
		cart.style.WebkitBorderBottomRightRadius = '8px';
		cart.empty = true;
		
		// IE 6 doesn't support position fixed
		if (window.external && typeof window.XMLHttpRequest == 'undefined') {
			cart.style.position = 'absolute';
		}
		
		var cartItemList = document.createElement('ul');
		cartItemList.style.position = 'relative';
		cartItemList.style.overflowX = 'hidden';
		cartItemList.style.overflowY = 'auto';
		cartItemList.style.height = '113px';
		cartItemList.style.margin = '0 0 13px';
		cartItemList.style.padding = '0';
		cartItemList.style.listStyleType = 'none';
		cartItemList.style.borderTop = '1px solid #ccc';
		cartItemList.style.borderBottom = '1px solid #ccc';
		cart.appendChild(cartItemList);
		
		var cartEmpty = document.createElement('li');
		cartEmpty.style.margin = '5px 0 0';
		cartEmpty.appendChild(document.createTextNode('Your cart is empty'));
		cartItemList.appendChild(cartEmpty);

		var cartSummary = document.createElement('p');
		cartSummary.style.display = 'inline';
		cartSummary.style.padding = '0 0 0 20px';
		cartSummary.style.background = 'url(' + MiniCart.base + 'images/arrow_down.gif) no-repeat 0 5px';
		cartSummary.style.fontWeight = 'bold';
		cartSummary.style.fontSize = '14px';
		cartSummary.onmouseover = function() {
			this.style.cursor = 'pointer';
		};
		cartSummary.onclick = function() {
			if (parseInt(cart.style.top, 10) == 0) {
				cart.hide();
			} else {
				cart.show();
			}
		};
		var cartTotal = document.createElement('span');
		cartTotal.appendChild(document.createTextNode('Subtotal: $'));
		cartSummary.appendChild(cartTotal);
		
		var cartTotalNumber = document.createElement('span');
		cartTotalNumber.appendChild(document.createTextNode('0.00'));
		cartTotal.appendChild(cartTotalNumber);
		
		var checkoutLink = document.createElement('a');
		checkoutLink.href = 'javascript:;';
		checkoutLink.onclick = doCheckout;
		checkoutLink.style.position = 'absolute';
		checkoutLink.style.right = '10px';
		checkoutLink.style.margin = '-1px 0 0';
		checkoutLink.style.padding = '1px 4px';
		checkoutLink.style.textDecoration = 'none';
		checkoutLink.style.fontWeight = 'normal';
		checkoutLink.style.color = '#000';
		checkoutLink.style.background = '#ffa822 url(' + MiniCart.base + 'images/button_submit.gif) left center repeat-x';
		checkoutLink.style.border = '1px solid #d5bd98';
		checkoutLink.style.borderRightColor = '#935e0d';
		checkoutLink.style.borderBottomColor = '#935e0d';
		checkoutLink.appendChild(document.createTextNode('Checkout'));
		
		cartSummary.appendChild(checkoutLink);
		cart.appendChild(cartSummary);
		
		cart.show = function() {
			var from = parseInt(this.style.top, 10);
			var to = 0;
	
			animateProp(this, 'top', from, to);
			cartSummary.style.backgroundImage = 'url(' + MiniCart.base + 'images/arrow_up.gif)';
		};
		
		cart.hide = function() {
			var from = parseInt(this.style.top, 10);
			var to = ((parseInt(this.style.height, 10) + parseInt(this.style.paddingTop, 10) + parseInt(this.style.paddingBottom, 10) - 34) * -1);
			
			animateProp(this, 'top', from, to);
			cartSummary.style.backgroundImage = 'url(' + MiniCart.base + 'images/arrow_down.gif)';
		};
		
		cart.add = function(product) {
			// add in a blank element so the numbers don't get out of wack
			if (!product.item_name && !product.item_number) {
				var emptyItem = document.createElement('input');
				emptyItem.type = 'hidden';
				emptyItem.disabled = true;
				
				var emptyLine = document.createElement('li');
				emptyLine.style.display = 'none';
				emptyLine.appendChild(emptyItem);
				
				cartItemList.appendChild(emptyLine);
				
				return;
			}
					
			var name = '';
			name += (product.item_number) ? '#' + product.item_number + ' ' : '';
			name += (product.item_name) ? product.item_name + ' ' : '';
			name += (product.on0 != '' && product.os0 != '') ? product.on0 + ': ' + product.os0 + ' ' : '';
			name += (product.on1 != '' && product.os1 != '') ? product.on1 + ': ' + product.os1 + ' ' : '';			
			name = (name.length > 20) ? name.substr(0, 20) + '...' : name;
			
			var price = parseFloat(product.amount);
			var quantity = (parseInt(product.quantity, 10) > 0) ? parseInt(product.quantity, 10) : 1;
			var total = parseFloat(cartTotalNumber.innerHTML);
			// remove the empty cart text
			if (cart.empty) {
				while (cartItemList.hasChildNodes()) {
					cartItemList.removeChild(cartItemList.firstChild);
				}
				
				cart.empty = false;
			}
			
			var itemQty = document.createElement('input');
			itemQty.name = 'quantity_' + product.offset;
			itemQty.value = product.quantity;
			itemQty.type = 'text';
			itemQty.style.position = 'absolute';
			itemQty.style.right = '78px';
			itemQty.style.width = '22px';
			itemQty.style.border = '1px solid #83a8cc';
			itemQty.style.padding = '1px';
			itemQty.style.textAlign = 'right';
			
			// if the quantity box changes then update 
			itemQty.onblur = function() { 
				this.value = parseInt(this.value, 10);
				this.value = (isNaN(this.value)) ? 1 : this.value;
				
				if (this.value == 0) {
					products[product.offset - 1] = {};
					saveData();
					
					animateProp(item, 'opacity', 1, 0);
					animateProp(item, 'height', 18, 0, null, function() {
						item.style.display = 'none';
					});
				} else {
					products[product.offset - 1].quantity = this.value;
					saveData();	
				}
				
				// updated the total
				var newTotal = 0;

				for (var i=0; i<products.length; i++) {
					if (products[i].quantity) {
						newTotal += parseFloat(products[i].amount) * parseInt(products[i].quantity, 10);
					}
				}
		
				cartTotalNumber.innerHTML = newTotal.toFixed(2);
				yellowFade(cartTotal);
			};
			
			var itemX = document.createElement('img');
			itemX.src = MiniCart.base + 'images/x.gif';
			itemX.style.position = 'absolute';
			itemX.style.right = '63px';
			itemX.style.top = '9px';
			itemX.style.cursor = 'pointer';
			itemX.onclick = function() {
				itemQty.value = '0';
				itemQty.focus();
				itemQty.blur();
			};

			var itemPrice = document.createElement('span');
			itemPrice.style.position = 'absolute';
			itemPrice.style.right = '4px';
			itemPrice.appendChild(document.createTextNode('$' + price.toFixed(2)));

			var itemName = document.createElement('a');
			itemName.appendChild(document.createTextNode(name));
			itemName.href = document.location.href;			
			itemName.style.textDecoration = 'none';
			itemName.style.border = '0';
			itemName.style.color = '#333';
			
			var item = document.createElement('li');
			item.style.position = 'relative';
			item.style.margin = '0';
			item.style.padding = '6px 5px 6px 0';
			item.style.opacity = '0';
			item.style.borderBottom = '1px solid #f2f2f2';
			item.appendChild(itemQty);
			item.appendChild(itemX);
			item.appendChild(itemPrice);
			item.appendChild(itemName);
			
	
			
			cartTotalNumber.innerHTML = (total + (price * quantity)).toFixed(2);
			cartItemList.appendChild(item);
			
			// fade the item in
			animateProp(item, 'opacity', 0, 1);
				
			yellowFade(cartTotal);
		};
		
		document.body.appendChild(cart);
	};
	
	
	var hijackForms = function() {
		var forms = document.getElementsByTagName('form');

		for (var i=0; i<forms.length; i++) {
			var form = forms[i];
				
			// look for all _cart forms on the page
			if (form.cmd && form.cmd.value == '_cart') {
				// if it contains an "add" value then use it to add the product
				if (form.add) {
					addEvent(form, 'submit', function(event) { 
						submitForm.apply(this);
						event.preventDefault(); 
					});
				// if it contains a "display" value then use it to display the vart
				} else if (form.display) {
					addEvent(form, 'submit', function(event) { 
						cart.show();
						event.preventDefault(); 
					});
				}
			}
		}
	};
	
	
	var submitForm = function() {
		// see if any of the generic settings on this for have not been populated in the main cart yet
		for (var i=0; i< this.elements.length; i++) {
			if (/^(?:business|currency_code|lc|paymentaction|no_shipping|no_note|invoice|weight_unit|page_style|return|cancel_return|rm)/.test(this.elements[i].name)) {
				settings[this.elements[i].name] = this.elements[i].value;
			}
		}

		// check the products to see if this variation already exists; if it does update it's quantity
		for (var i=0; i<products.length; i++) {
			if ((!this.elements.item_name || products[i].item_name == this.elements.item_name.value) &&
				(!this.elements.item_number || products[i].item_number == this.elements.item_number.value) && 
				(!this.elements.os0 || products[i].os0 == this.elements.os0.value) &&
				(!this.elements.os1 || products[i].os1 == this.elements.os1.value)) {
					
					products[i].quantity++;
					var input = cart.elements[products[i].offset - 1];

					// trigger the update function
					if (input) {
						input.value = products[i].quantity;
						input.focus();
						input.blur();
				
						cart.show();
					}
					
					return;
			}
		}
		
		// if we're not updating a product then create a blank one and populate it with the form's content
		var data = {};
		data.item_name = '';
		data.item_number = '';
		data.on0 = '';
		data.os0 = '';
		data.on1 = '';
		data.os1 = '';
		data.amount = '';
		data.quantity = 1;
		data.offset = products.length + 1;
	
		for (var i=0; i< this.elements.length; i++) {
			if (/^(?:item_number|item_name|amount|quantity|on|os)/.test(this.elements[i].name)) {
				data[this.elements[i].name] = this.elements[i].value;
			}
		}
				
		products.push(data);
		saveData();
	
		cart.add(data);
		cart.show();
	};
	

	var doCheckout = function() {
		if (products.length > 0) {
			var form = document.createElement('form');
			form.action = 'https://' + MiniCart.subdomain + '.paypal.com/cgi-bin/webscr';
			form.method = 'post';
			form.style.display = 'none';
			
			var addInput = function(name, value) {
				var input = document.createElement('input');
				input.type = 'hidden';
				input.name = name;
				input.value = value;
				form.appendChild(input);
			};
			
			// add the settings
			addInput('cmd', '_cart');
			addInput('upload', '1');
			addInput('bn', 'MiniCart_AddToCart_WPS_US');

			for (var key in settings) {
				addInput(key, settings[key]);
			}
		
			// add the products
			for (var i=0, j=0; i<products.length; i++) {
				var product = products[i];
				
				if (product.quantity > 0) {
					j = j + 1;
									
					for (var key in product) {
						addInput(key + '_' + j, product[key]);
					}
				}
			}

			document.body.appendChild(form);
		
			setTimeout(function() {
				form.submit();
				deleteData();
			}, 50);
		}
	};
	
	
	var readData = function() {
		var name = 'cart=';
		var cookies = document.cookie.split(';');
		
		for (var i=0;i < cookies.length;i++) {
			var cookie = cookies[i];
			while (cookie.charAt(0) == ' ') cookie = cookie.substring(1, cookie.length);
			
			if (cookie.indexOf(name) == 0) {
				var data = cookie.substring(name.length, cookie.length);
				return JSON.parse(data);
			}
		}
		
		return null;
	};
	

	var saveData = function(duration) {
		duration = duration || 30;
		
		var date = new Date();
		date.setTime(date.getTime() + duration * 24 * 60 * 60 * 1000);
		
		var data = {
			'settings': settings,
			'products': products
		};
		
		document.cookie = 'cart=' + JSON.stringify(data) + '; expires=' + date.toGMTString() + '; path=' + MiniCart.path;
	};
	
	
	var deleteData = function() {
		saveData(-1);
	};
	
	
	var animateProp = function(element, prop, from, to, duration, callback) {
		var duration = duration || 10;
		var step = ((to - from) / 20);
		
		var current = from;
		var unit = '';
		
		if (prop == 'top' || prop == 'height') {
			unit = 'px';
		}
		
		function func() {
			element.style[prop] = current + unit;
			current += step;
			
			if ((step > 0 && current > to) || (step < 0 && current < to) || step == 0) {
				element.style[prop] = to + unit;
				
				if (typeof callback == 'function') {
					callback();
				}
				
				return;
			}
			
			setTimeout(func, length);
		};

		func();
	};
	
	
	var yellowFade = function(element, duration, callback) {
		var color = { 1: 'ff', 2: 'ee', 3: 'dd', 4: 'cc', 5: 'bb', 6: 'aa', 7: '99' };
		var duration = duration || 50;
		var current = 7;
		var to = 1;
		var step = -1;
		
		function func() {
			element.style['backgroundColor'] = '#ffff' + color[current];
			current += step;

			if ((step > 0 && current > to) || (step < 0 && current < to) || step == 0) {
				element.style['backgroundColor'] = 'transparent';
				
				if (typeof callback == 'function') {
					callback();
				}
				
				return;
			}

			setTimeout(func, duration);
		};

		func();
	};
	
	
	var addEvent = function(obj, event, fn, capture) {
		if (obj.addEventListener) {
			obj.addEventListener(event, fn, capture);
			return true;
		} else if (obj.attachEvent) {
			// wrap IE's callback and normalize the event
			var wrapperFn = function() {
				var e = window.event;
				e.target = e.target || e.srcElement;
				
				e.preventDefault = function() {
					window.event.returnValue = false;
				};
				
				fn.call(obj, e);
			};
			
			return obj.attachEvent('on' + event, wrapperFn);
		}
	};
	
	addEvent(window, 'load', init);	
}());




// http://www.json.org/js.html
if (!this.JSON) { JSON = {}; }

(function () {

	function f(n) {
		return n < 10 ? '0' + n : n;
	}

	if (typeof Date.prototype.toJSON !== 'function') {
		Date.prototype.toJSON = function (key) {
			return this.getUTCFullYear() + '-' + f(this.getUTCMonth() + 1) + '-' + f(this.getUTCDate())      + 'T' + f(this.getUTCHours())     + ':' + f(this.getUTCMinutes())   + ':' + f(this.getUTCSeconds())   + 'Z';
		};

		String.prototype.toJSON =
		Number.prototype.toJSON =
		Boolean.prototype.toJSON = function (key) {
			return this.valueOf();
		};
	}

	var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
		escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
		gap,
		indent,
		meta = { '\b': '\\b', '\t': '\\t', '\n': '\\n', '\f': '\\f', '\r': '\\r', '"' : '\\"', '\\': '\\\\' },
		rep;


    function quote(string) {
        escapable.lastIndex = 0;
        return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
			var c = meta[a];
			return typeof c === 'string' ? c : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); 
		}) + '"' : '"' + string + '"';
    }


	function str(key, holder) {
		var i, k, v, length, mind = gap, partial, value = holder[key];

		if (value && typeof value === 'object' && typeof value.toJSON === 'function') {
			value = value.toJSON(key);
		}

		if (typeof rep === 'function') {
			value = rep.call(holder, key, value);
		}

		switch (typeof value) {
			case 'string':
				return quote(value);

			case 'number':
				return isFinite(value) ? String(value) : 'null';

			case 'boolean':
			case 'null':
				return String(value);

			case 'object':
				if (!value) { return 'null'; }

				gap += indent;
				partial = [];


				if (Object.prototype.toString.apply(value) === '[object Array]') {
					length = value.length;
			
					for (i = 0; i < length; i += 1) {
						partial[i] = str(i, value) || 'null';
					}

					v = partial.length === 0 ? '[]' : gap ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' : '[' + partial.join(',') + ']';
					gap = mind;
					return v;
				}

				if (rep && typeof rep === 'object') {
					length = rep.length;
					for (i = 0; i < length; i += 1) {
						k = rep[i];
						if (typeof k === 'string') {
							v = str(k, value);
							if (v) {
								partial.push(quote(k) + (gap ? ': ' : ':') + v);
							}
						}
					}
				} else {
					for (k in value) {
						if (Object.hasOwnProperty.call(value, k)) {
							v = str(k, value);
							if (v) {
								partial.push(quote(k) + (gap ? ': ' : ':') + v);
							}
						}
					}
				}

				v = partial.length === 0 ? '{}' : gap ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' : '{' + partial.join(',') + '}'; 
				gap = mind;
				return v;
		}
	}

	if (typeof JSON.stringify !== 'function') {
		JSON.stringify = function (value, replacer, space) {
			var i;
			gap = '';
			indent = '';

			if (typeof space === 'number') {
				for (i = 0; i < space; i += 1) {
					indent += ' ';
				}

			} else if (typeof space === 'string') {
				indent = space;
			}

			rep = replacer;
			if (replacer && typeof replacer !== 'function' &&
					(typeof replacer !== 'object' ||
					 typeof replacer.length !== 'number')) {
				throw new Error('JSON.stringify');
			}

			return str('', {'': value});
		};
	}

    if (typeof JSON.parse !== 'function') {
        JSON.parse = function (text, reviver) {
            var j;

            function walk(holder, key) {
                var k, v, value = holder[key];
                if (value && typeof value === 'object') {
                    for (k in value) {
                        if (Object.hasOwnProperty.call(value, k)) {
                            v = walk(value, k);
                            if (v !== undefined) {
                                value[k] = v;
                            } else {
                                delete value[k];
                            }
                        }
                    }
                }
                return reviver.call(holder, key, value);
            }

            cx.lastIndex = 0;
            if (cx.test(text)) {
                text = text.replace(cx, function (a) {
                    return '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                });
            }

            if (/^[\],:{}\s]*$/.
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {


                j = eval('(' + text + ')');

                return typeof reviver === 'function' ?
                    walk({'': j}, '') : j;
            }

            throw new SyntaxError('JSON.parse');
        };
    }
})();