function scRealTimePrice( pitId, pId, spId, ysId ) {
	pitId = (pitId && (pitId = pitId.toString()))? pitId : "product-info-table";
	pId = (pId && (pId = pId.toString()))? pId : "pitPriceBx";
	spId = (spId && (spId = spId.toString()))? spId : "pitSalePriceBx";
	ysId = (ysId && (ysId = ysId.toString()))? ysId : "pitYouSaveBx";

	var addListener = function() {
		if ( window.addEventListener ) {
			return function(el, type, fn) {
				el.addEventListener(type, fn, false);
			};
		} else if ( window.attachEvent ) {
			return function(el, type, fn) {
				var f = function() {
					fn.call(el, window.event);
				};
				el.attachEvent('on'+type, f);
			};
		} else {
			return function(el, type, fn) {
				el['on'+type] = fn;
			};
		}
	}();
	
	function forceFloat( num ) {
		/*
			forceFloat - Private - Forces data of an undefined type into an floating point value
			PARAMETERS: num - should be an floating point value, but may be of a different type
			RETURN: an floating point value
		*/
		return (isNaN(num = parseFloat((typeof num === Number)? num : num.toString().replace(/^.*?([\+\-]?[\d\.]+).*?$/, "$1"))))? 0.0 : num;
	}
	
	function toPrice( num, currency ) {
		/*
			toPrice - Private - Converts a number value into a formatted price string; commas are added at thousand mark, decimals are forced to 2 digits, and the currency is added to the front of the string.
			PARAMETERS: num - should be an floating point or integer value; currency should be a character or string value
			RETURN: a string of the number as a price in a given currency
		*/
		if (num) {
			num = forceFloat(num).toFixed(2).toString();
			var intEnd = num.indexOf(".") - 3;
			for (var i = intEnd, j = 0; i > j; i -= 3) {
				num = num.substring(0, i) + "," + num.substring(i, num.length);
			}
			num = num;
		} else {
			num = "0.00";
		}
		if (currency) {
			if (typeof currency !== String) {
				currency = currency.toString();
			}
		} else {
			currency = "";
		}
		return currency + num;
	}
	
	this.init = function() {
		/*
			init - Public - Starts the process of scraping the product info table and updating price values
			PARAMETERS: none
			RETURN: none
		*/
		var pit = document.getElementById(pitId);
		if (pit) {
			var ins = pit.getElementsByTagName("input");
			var trs = pit.getElementsByTagName("tr");
			if (ins && trs) {
				var insToCheck = [];
				for (var i = 0, j = ins.length; i < j; i++) {
					var inType = ins[i].type.toLowerCase();
					if ((inType == "radio") || (inType == "checkbox")) {
						insToCheck.push(ins[i]);
					}
				}
				var selsToCheck = pit.getElementsByTagName("select");
				
				if (insToCheck || selsToCheck) {
					var prices = [];
					prices[pId] = document.getElementById(pId);
					prices[spId] = document.getElementById(spId);
					prices[ysId] = document.getElementById(ysId);
					
					if (prices[pId] || prices[spId] || prices[ysId]) {
						var priceExp = /\$([\d\,\.]+)/;
						function stripPrice( str ) {
							/*
								stripPrice - Private - Strips out a price value from a string
								PARAMETERS: str - the string to parse for a price
								RETURN: the price as a floating point number
							*/
							str = str.match(priceExp);
							str = (str)? forceFloat(str[1]) : 0;
							return str;
						}
						
						function regexPrice( num ) {
							/*
								regexPrice - Private - Converts a price to a price string that can be used in a regex replace
								PARAMETERS: num - the price as a floating point number
								RETURN: a string value of the price (dollar sign is escaped by another dollar sign for regex use)
							*/
							return ((window.scRTPcurrency && (scRTPcurrency != "$"))? scRTPcurrency : "$$") + toPrice(num);
						}
						
						var basePrices = [];
						if (prices[pId]) {
							basePrices[pId] = stripPrice(prices[pId].innerHTML);
						}
						if (prices[spId]) {
							basePrices[spId] = stripPrice(prices[spId].innerHTML);
						}
						
						function updatePrices() {
							/*
								updatePrices - Private - checks opts for price updates, calculates new totals, and outputs the new values in their respective (HTML element) containers
								PARAMETERS: none
								RETURN: none
							*/
							var price = basePrices[pId];
							var salePrice = basePrices[spId];
							var optExp = /\((.+?)\)/;
							
							for (var i = 0, j = insToCheck.length; i < j; i++) {
								if (insToCheck[i].checked) {
									var optCost = insToCheck[i].value.match(optExp);
									if (optCost) {
										price += forceFloat(optCost[1]);
										salePrice += forceFloat(optCost[1]);
									}
								}
							}
							for (var i = 0, j = selsToCheck.length; i < j; i++) {
								var optCost = selsToCheck[i].options[selsToCheck[i].selectedIndex].value.match(optExp);
								if (optCost) {
									price += forceFloat(optCost[1]);
									salePrice += forceFloat(optCost[1]);
								}
							}
						
							if (prices[pId]) {
								prices[pId].innerHTML = prices[pId].innerHTML.replace(priceExp, regexPrice(price));
							}
							if (prices[spId]) {
								prices[spId].innerHTML = prices[spId].innerHTML.replace(priceExp, regexPrice(salePrice));
							}
							if (prices[ysId]) {
								var youSave = price - salePrice;
								var youSavePer = Math.round(youSave / price * 100);
								prices[ysId].innerHTML = prices[ysId].innerHTML.replace(priceExp, regexPrice(youSave));
								prices[ysId].innerHTML = prices[ysId].innerHTML.replace(/[\d]+\%/, youSavePer + "%");
							}
						}
						
						// initialize option input listeners
						for (var i = 0, j = insToCheck.length; i < j; i++) {
							addListener(insToCheck[i], "click", updatePrices);
						}
						for (var i = 0, j = selsToCheck.length; i < j; i++) {
							addListener(selsToCheck[i], "change", updatePrices);
						}
						updatePrices(); // run an initial sweep to sync prices out of the box
					}
				}
			}
		}
	};
}