
// twister.js, 2008-08-05-1431 


// (FILE: /detail-page-features/twister-event-manager/n2-event-manager.js) 

function N2EventManager()
{
  this.aEvents = {};

  // 1) Register a widget to be notified when any event in the
  // given list is published.
  // ARGS: oWidget a ref to a widget
  //       aMessages a ref to an array of events to subscribe to
  this.subscribe = function(oWidget, aEvents) {
    var i;
    for (i = 0; i< aEvents.length; i++) {
      var sEvent = aEvents[i];
      var aWidgets = this.aEvents[sEvent];
      if (!aWidgets) {
        aWidgets = this.aEvents[sEvent] = [];
      }
      // Push widget onto array
      aWidgets.push(oWidget);
    }
  };

  // 2) When an event comes in notify all the widgets that have 
  // subscribed to the event
  this.publish = function(oSrcWidget, sEvent, oData) {
    var aWidgets = this.aEvents[sEvent];
    if (aWidgets) {
      var i;
      for (i = 0; i < aWidgets.length; i++) {
        var oWidget = aWidgets[i];
        oWidget.onEvent(oSrcWidget, sEvent, oData);
      }
    }    
  };
}

// (FILE: /utility/twister-utilities.js) 


var twIsIE=false,twIsMozilla=false;
// XHR Factory object
var objID = 1;

TwisterXHRFactory = function() {
 var objID;
  var oXHR=false;
  // Native XMLHttpRequest object (Firefox, Safari, IE 7, etc.)
	if (!oXHR && typeof XMLHttpRequest!='undefined') {
		try {
      twIsMozilla = true;
			oXHR = new XMLHttpRequest();
		} catch (e) {
		}
    // IE/Windows ActiveX version (IE 5.5, 6)
  } else if(window.ActiveXObject) {
    twIsIE = true;
    try {
      oXHR = new ActiveXObject("Msxml2.XMLHTTP");
    } catch(e) {
      try {
        oXHR = new ActiveXObject("Microsoft.XMLHTTP");
      } catch(e) {
        oXHR = false;
      }
		}
  }
	return oXHR;
}

TwisterAjaxFactory = function(server, sessionId, requestId) {
  var server = server;
  var sessionId = sessionId;
  var requestId = requestId;

  this.getAjaxObject = function() {
    var ajaxObj = new TwisterXHRFactory();
//    ajaxObj.objID = objID; objID++;
    var oAjaxObj = new TwisterAjaxObject(ajaxObj, server, sessionId, requestId);
    oAjaxObj.objID = objID; objID++;
    return oAjaxObj;
  }
}

TwisterAjaxObject = function(oXHR, server, sessionId, requestId) {
  var oXHR = oXHR;
  var server = server;
  var sessionId = sessionId;
  var requestId = requestId;
  
  var asin = ''; 
  var myURL = '';
  var oLastArgs;
  var fnLastOnAbort;
  var inProcess = false;

  var rType = 'ajax';
  var rStart = null;
  var rCount = 0;

  // closure for the callback
  var self = this;
  var evalFn = function() {self.TwisterEvalResults();};

  this.getAsin = function() {
     return asin;
  }
   
  this.setAsin = function(inAsin) {
     asin = inAsin;
  } 

  this.setRequestType = function(r) {
     rType = r;
  } 

  this.setURL = function(url) {
    myURL = server + url + '/' + sessionId;
  }
  
  this.request = function(oArgs, onAbort, noTimeOut) {
	  setTimeout(function() { self.asyncRequest(oArgs, onAbort); } , 0);
          rCount = rCount + 1;
  }

  this.asyncRequest = function(oArgs, onAbort) {
    try {
      if (inProcess) { 
        oXHR.onreadystatechange = doNothing;
        oXHR.abort();
        if (onAbort) {
          onAbort(oLastArgs);
        }
        inProcess = false;
        if (shouldLogTwister()) {
            var params = {};
            params['reqAbort:'+rType+':' + rCount + ':'+ asin] = 1;
            addClientLog(params);
        }
        setTimeout(function() { self.request(oArgs, onAbort); } , 0);
        return;
      }  
      else if (twIsIE){
       	 oXHR.abort();
         inProcess = false;
      }

      var thisUrl = myURL + '?' + 'sid=' + sessionId + '&rid=' + requestId + '&';
      for (var i in oArgs) {
        thisUrl += i + '=' + oArgs[i] + '&';
      }
      if (shouldLogTwister()) {
        rStart = new Date();    
      }
      oXHR.open('GET', thisUrl, true);
      // oXHR.onreadystatechange = evalFn;
      oXHR.onreadystatechange = function() {self.TwisterEvalResults();};
      oXHR.send(null);
      oLastArgs = oArgs;
      fnLastOnAbort = onAbort;
      inProcess = true;
    } catch (e){
      inProcess = false;
      if (onAbort) {
	      onAbort(oArgs);
      }
    }
  }

  this.TwisterEvalResults = function() {
    if (oXHR.readyState == 4) {
      inProcess = false;
      try{
        if (oXHR.status == 200) {
          var params = {};
          if (shouldLogTwister()) {
            params['ajaxTime:'+rType+':'+rCount+':'+asin] = new Date().getTime() - rStart.getTime();
            rStart = new Date();
          }
          eval(oXHR.responseText);
          if (shouldLogTwister()) {
            params['evalTime:'+rType+':'+rCount+':'+asin] = new Date().getTime() - rStart.getTime();
            addClientLog(params);
          }  
        } else {
        }
      }catch(e) {
        if (fnLastOnAbort) {
          fnLastOnAbort(oLastArgs);
        }
      }
    } 
  }

  this.getObjInfo = function() {
    return 'TwisterAjaxObject:(' + oXHR.objID + ')' + myURL + ':';
  }
}

function doNothing()
{
//log("did nothing");
}

function formatString(templateString,argumentsObject)
{
	var outStr=templateString;
	for (var i in argumentsObject)
	{
		outStr=outStr.replace(i,argumentsObject[i]);
	}
	//alert(outStr);
	return outStr;
}

function executeScripts(divId)
{
   var div = document.getElementById(divId);
  // div.innerHTML = innerHTML;
   var x = div.getElementsByTagName("script");
   for(var i=0;i<x.length;i++)
   {
       eval(x[i].text);
   }
}

function dumpObj(obj) {
  var str = '[';
  for (var att in obj) {
      str += att+'='+obj[att]+', ';
  }
  str += ']';
  return str;
}

function unfadeDiv(divObj)
{
  fadeDiv(divObj,100);
}
        
function fadeDiv(divObj,fadePercent)
{
  if (fadePercent==null)
    fadePercent=50;
  divObj.style.opacity=fadePercent/100; //for Mozilla
  divObj.style.filter="alpha(opacity='"+fadePercent+"')"; //for IE
}

function setLoadingBar2Line(div)
{
	if (div !=null && window.loadingBarHTML2Line)
	{
	if (div.getAttribute('loadingBarSet')==1)
		{
		//console.log('still loading');
		return;
		}
	else
	  div.setAttribute('loadingBarSet',1);     
		div.innerHTML=loadingBarHTML2Line;
	}
}

function getFeatureHeaderRow(featureDiv)
{
 var headerRow;
 var candidateRows = new Array("h2", "h1", "b");
 
 if (featureDiv.id == 'fast-track_feature_div'
     || featureDiv.id == 'fma-seller-messages_feature_div') {
   return headerRow;
 }

  // Search for the usual suspects
 for (var i in candidateRows) {
  var candidates = featureDiv.getElementsByTagName(candidateRows[i]);
   for (var i in candidates) {
     if (candidates && candidates[i] && candidates[i].tagName) {
          headerRow = candidates[i];
          break;
       }
    }
 }

 
return 	headerRow;

}

function setFeatureLoadingBar(div,theContentDiv,pickContentDiv)
{
	if (div==null) return;
	if (div.getAttribute('loadingBarSet')==1)
		{
		//console.log('still loading');
		return;
		}
	else
	  div.setAttribute('loadingBarSet',1);       
         var headerRow,contentDiv=theContentDiv,headerDiv;
 	 var currObj;
        headerRow=getFeatureHeaderRow(div);
	if (headerRow==null)
		return;		
	 var divsColl=div.getElementsByTagName('div');
	  for (var i in divsColl)
	  	{
			
			if (contentDiv!=null && headerDiv!=null)
				break;
			currObj=divsColl[i];
			if (contentDiv==null && currObj!=null && currObj.className=='content')
			{
				contentDiv=currObj;				
			}
			else if (headerDiv==null && currObj!=null && currObj.className=='disclaim')
			{
				headerDiv=currObj;
			}
			
		}
	var nextSib=headerRow.nextSibling;	
	while (pickContentDiv==true)
	{		
		if (nextSib.nodeName=='DIV')
		{
			contentDiv=nextSib;
			break;
		}
		nextSib=nextSib.nextSibling;
	}		
	  var headerHTML=headerRow.innerHTML;	
  	  var newDiv=document.createElement('DIV');
           headerRow.innerHTML='';
	   newDiv.innerHTML='<b class="h1">'+headerHTML+'</b>'+featureLoadingBarHTML;
	  headerRow.parentNode.insertBefore(newDiv,headerRow);
	  if (contentDiv!=null)
	  	{
		  contentDiv.style.width='100%';
		  fadeDiv(contentDiv,25);
		 }
	  if (headerDiv!=null)	
	  {  
		  headerDiv.style.width='100%';
		  fadeDiv(headerDiv,25);
	  }
}


var logTwister = false;
var twisterLogs = {}
var productGroup = 'unknown';
var hoverCount = 0;
var asinCount = 0;
var prevOnUnload;

function flushClientLog(event) {
  if (window.clientLogger) {
    twisterLogs['hoverCount'] = hoverCount;
    twisterLogs['asinCount'] = asinCount;
    clientLogger.sendCLOGEntry("twister","detail_ajax", twisterLogs); 
  }
  if (prevOnUnload) {
    prevOnUnload(event);
  }
}

function enableTwisterLogging(prodGroup) {
  try {
    if (prodGroup) {
      productGroup = prodGroup; 
    }
    logTwister = true;
    twisterLogs['prodGroup'] = productGroup;
    prevOnUnload = window.onbeforeunload;
    window.onbeforeunload = flushClientLog;
  } catch(e) {
  }
}

function shouldLogTwister() {
  return logTwister;
}

var logCount = 0;
function addClientLog(params) {
  if (!logTwister) {return;}
  
  for(var l in params) {
    twisterLogs[l] = params[l];
  }

  logCount = logCount+1;
  if (logCount >= 10) {
    if (window.clientLogger) {
      clientLogger.sendCLOGEntry("twister","detail_ajax", twisterLogs);
    }
    twisterLogs = {};
    twisterLogs['prodGroup'] = productGroup;
    logCount = 0;
  }
}

function incrementHoverCount() {
 // add 0.5 to de dup in / out events
  hoverCount = hoverCount + 1;
}
function setTotalASINCount(nCount) {
  asinCount = nCount;
}




// (FILE: /detail-page-features/twister-manager/twister-manager.js) 


// Twister manager object
function TwisterManager(
  oEventManager,
  oTwisterVariations,
  oTwisterPriceBlock,
  oTwisterAvailability,
  oTwisterAltImages,
  oTwisterBuyBox,
  oTwisterPrime,
  oTwisterManagerArgs,
  oOnlyUnqualifiedOffers) {

  var oEventManager = oEventManager;
  var oTwisterVariations = oTwisterVariations;
  var oTwisterPriceBlock = oTwisterPriceBlock;
  var oTwisterAvailability = oTwisterAvailability;
  var oTwisterAltImages = oTwisterAltImages;
  var oTwisterBuyBox = oTwisterBuyBox;
  var oTwisterPrime = oTwisterPrime;
  var oTwisterManagerArgs = oTwisterManagerArgs;
  var oOnlyUnqualifiedOffers = oOnlyUnqualifiedOffers;
  if (oTwisterManagerArgs['oTMAjaxObj']) {
     oTwisterManagerArgs['oTMAjaxObj'].setURL('/gp/twister/dynamic-update/offers-item.html');
  }
  if (oTwisterManagerArgs['oDUAjaxObj']) {
     oTwisterManagerArgs['oDUAjaxObj'].setURL('/gp/product/twister-update/' + oTwisterManagerArgs['oDUAjaxObj'].getAsin());
  }

  var oTMAjaxObj = oTwisterManagerArgs['oTMAjaxObj'];
  var oDUAjaxObj = oTwisterManagerArgs['oDUAjaxObj'];
  var sTwisterManagerName = oTwisterManagerArgs['sTwisterManagerName'];


  // Child ASIN offer data
  var oOfferData = {};
  // Offer data can be in 4 states (null means not needed)
  var oOfferDataState = {};
  var oOfferDataTries = {};
  var REQUEST_PENDING = 1;
  var REQUEST_SENT = 2;
  var REQUEST_RECEIVED = 3;
  var NOT_BUYABLE = 4;
  // Ajax queue
  var oAjaxQueue = new Array();
  var oAjaxTimeout = null;

  // State for when offer data is not yet available
  var sLastPreviewASIN = null;
  var sLastSelectASIN = null;
  var oLastSelectData = {};

  // state of dynamic features
  var sDynFeatureASIN = null;
  var sCurrentSelectedASIN = null;
  if (oTwisterManagerArgs['sChildASIN']) { 
    sDynFeatureASIN = oTwisterManagerArgs['sChildASIN'];
  }
  var oDynFeatureCache = {};
  var oDynFeatureDiv = {};
  var sParentASIN = oTwisterManagerArgs['sParentASIN'];
  var sTwisterView = oTwisterManagerArgs['sourceView'];
  var sMerchantID = oTwisterManagerArgs['merchantID'];
  var sDropdownSelection = oTwisterManagerArgs['dropdown-selection'];
  var sStoreID = null;
  if (oTwisterManagerArgs['storeID']) {
    sStoreID = oTwisterManagerArgs['storeID'];
  }

  var oFeatureAjaxUpdateFns=new Object();
  var oFeatureCachedUpdateFns=new Object();
  var parentCallbacksMap = new Object();  
  var cacheReselectCallbackMap = new Object();  
  
//update states
  var AJAX_UPDATE=1;
  var CACHE_UPDATE=2;
  
  var NO_FUNC=-1; 
  var inOnLoad = false;

  // prime & MBC features
  var oPrimeDiv = -1;
  var oMBCDiv = -1;
  
  var oFeatureDivsWithLoadingBar=new Object();

  // Subscribe to preview and select events
  if (oTwisterVariations) {
    var aEvents = [
      gsTwisterVariationsEventName_PreviewVariations,
      gsTwisterVariationsEventName_SelectVariations,
      ];

    goEventManager.subscribe(this, aEvents);
  }

  this.getOfferData = function() {
    return oOfferData;
  }
  
 this.onEvent = function(oSrcWidget, sEvent, oData) {
    var oTwisterVariationData = oData;
    var aAsinList = oTwisterVariationData.aAsinList;
    var hSelectedVariations = oTwisterVariationData.oSelectedVariations;
    var numOfVariations = oTwisterVariationData.nVariationsSelected; 
    var totalNumOfVariations = oTwisterVariationData.nVariationsTotal;
    var oDisplayableNames = oTwisterVariationData.oVariationTypeDisplayLabels;
    var sBuyableASIN = oTwisterVariationData.sBuyableASIN; 
    var updateFeatures=true;
    if (oData.bUpdateFeatures)
	    updateFeatures=oData.bUpdateFeatures.value;   

    if  (sEvent == gsTwisterVariationsEventName_PreviewVariations)
    {
      if (sBuyableASIN && !oOfferData[sBuyableASIN]) {
        // Offer data not available for this preview; save for later
        sLastPreviewASIN = sBuyableASIN;
      }

      // Price block
      if (oTwisterPriceBlock) {
        if (sBuyableASIN && oOfferData[sBuyableASIN]) {
          oTwisterPriceBlock.update(sBuyableASIN, oOfferData[sBuyableASIN],oOnlyUnqualifiedOffers);
        } else {
          oTwisterPriceBlock.update(null, null,oOnlyUnqualifiedOffers);
        }
      }
      // Availability Block
      if (oTwisterAvailability) {
        if (sBuyableASIN && oOfferData[sBuyableASIN]) {
          oTwisterAvailability.update(sBuyableASIN, oOfferData[sBuyableASIN],oOnlyUnqualifiedOffers);
        } else {
          oTwisterAvailability.update(null, null,oOnlyUnqualifiedOffers);
        }
	var anyVariationSelected=(numOfVariations!=null && numOfVariations>0);
	oTwisterAvailability.onPreviewEvent(sBuyableASIN,oOfferData[sBuyableASIN],anyVariationSelected);
      }

      if (oTwisterBuyBox){
        oTwisterBuyBox.updateSubscribeInfo(oOfferData[sBuyableASIN]);
      }

      // Product images
      if (oTwisterAltImages) {
        oTwisterAltImages.previewVariationValues(oTwisterVariationData);
      } 

      if (shouldLogTwister()) {
       incrementHoverCount(); 
      }
    }
    else if (sEvent == gsTwisterVariationsEventName_SelectVariations)
    { 
      if (updateFeatures && sBuyableASIN == null) {
	setTimeout(sTwisterManagerName+".triggerParentCallbacks()",0);
      }
     
      if ( oMBCDiv == -1 ) {
          oMBCDiv = document.getElementById('more-buying-choices_feature_div');
      }
      if ( oPrimeDiv == -1 ) {
          oPrimeDiv = document.getElementById('prime_feature_div');
      }
      // Preload offer data on select events
      if (numOfVariations >= (totalNumOfVariations - 1)) {
        this.preloadOfferData(oTwisterVariationData);
      }

      if (sBuyableASIN && !oOfferData[sBuyableASIN]) {
        // Offer data not available for this select; save for later
        sLastSelectASIN = sBuyableASIN;
        oLastSelectData.nVariationsSelected = oTwisterVariationData.nVariationsSelected;
        oLastSelectData.nVariationsTotal = oTwisterVariationData.nVariationsTotal;
        oLastSelectData.oSelectedVariations = oTwisterVariationData.oSelectedVariations;
        oLastSelectData.oDisplayableNames = oTwisterVariationData.oVariationTypeDisplayLabels;
      } else {
        sLastSelectASIN = null;
        oLastSelectData = {};
      }     
	if (!updateFeatures)  {
	  if (!sBuyableASIN && oTwisterBuyBox)  {	 //update buybox to 'inaccessible' state
	   oTwisterBuyBox.update(null, null, 
            numOfVariations, totalNumOfVariations, 
            hSelectedVariations, oDisplayableNames,oOnlyUnqualifiedOffers);
	  }
	 return;	
	}	
	 
      // Price block
      if (oTwisterPriceBlock  ) {
        if (sBuyableASIN && oOfferData[sBuyableASIN]) {
          oTwisterPriceBlock.update(sBuyableASIN, oOfferData[sBuyableASIN],oOnlyUnqualifiedOffers);
        } else {
          oTwisterPriceBlock.update(null, null,oOnlyUnqualifiedOffers);
        }
      }
      //Availability Block
      if (oTwisterAvailability) {
        if (sBuyableASIN && oOfferData[sBuyableASIN]) {
           oTwisterAvailability.update(sBuyableASIN, oOfferData[sBuyableASIN],oOnlyUnqualifiedOffers);
        } else {
          oTwisterAvailability.update(null, null,oOnlyUnqualifiedOffers);
        }
	oTwisterAvailability.onSelectEvent(sBuyableASIN,oOfferData[sBuyableASIN]);
      }


      // Variations
      if (oTwisterVariations ) {
        if (sBuyableASIN && oOfferData[sBuyableASIN]) {
          oTwisterVariations.updateSizeChart(oOfferData[sBuyableASIN]);
        } else {
          oTwisterVariations.clearSizeChart();
        }
      }

      // Buy box
      if (oTwisterBuyBox) {
        if (sBuyableASIN) {
          oTwisterBuyBox.update(sBuyableASIN, oOfferData[sBuyableASIN], 
            numOfVariations, totalNumOfVariations, 
            hSelectedVariations, oDisplayableNames,oOnlyUnqualifiedOffers);
        } else {
          oTwisterBuyBox.update(null, null, 
            numOfVariations, totalNumOfVariations, 
            hSelectedVariations, oDisplayableNames,oOnlyUnqualifiedOffers);
        }
      }

      // suppress MBC when there is not buyable ASIN
      if (!sBuyableASIN){
          if (oMBCDiv) {
              oMBCDiv.innerHTML = '';
          }
          if (oPrimeDiv) {
              oPrimeDiv.innerHTML = oTwisterPrime.getParentContent();
          }
      }

      // Product images
      if (oTwisterAltImages) {
        oTwisterAltImages.selectVariationValues(oTwisterVariationData);
      }

      sCurrentSelectedASIN = sBuyableASIN;
      if (sBuyableASIN) {
       if (sBuyableASIN != sDynFeatureASIN) {
              if (!inOnLoad) { sDynFeatureASIN = sBuyableASIN; }

              // don't send update for  during onLoad
              if (!inOnLoad) {
                if (oDynFeatureCache[sDynFeatureASIN]) {//log('got cache for '+sDynFeatureASIN);
                  if (oDynFeatureCache[sDynFeatureASIN]['status'] == 'complete') {//log('loading from  cache for '+sDynFeatureASIN);
                      this.showChildContent(sDynFeatureASIN,CACHE_UPDATE);
                  }
                } else {//log ("requesting data for "+sDynFeatureASIN);
                  var oArgs = new Object();
                  oArgs['childASIN'] = sDynFeatureASIN;
                  oArgs['twisterView'] = sTwisterView;
                  oArgs['PowerBar'] = 0;
                  if (sMerchantID && sMerchantID != '') { 
                      oArgs['m'] = sMerchantID; 
                  } 
                  if (sStoreID && sStoreID != '') { 
                      oArgs['s'] = sStoreID; 
                  }
                  if (sDropdownSelection && sDropdownSelection != '') { 
                      oArgs['dropdown-selection'] = sDropdownSelection; 
                  }
                  oDynFeatureCache[sDynFeatureASIN] = new Object();
                  oDynFeatureCache[sDynFeatureASIN]['status'] = 'waiting';		
                  oDUAjaxObj.request(oArgs, this.onDUAbort, sDynFeatureASIN);
    		    this.setLoadingIndicators();	

                }
              }
       } else {
              setTimeout(sTwisterManagerName+".triggerCacheReselectCallback('"+sBuyableASIN+"')",0);           
              if (oDynFeatureCache[sDynFeatureASIN]) {
                  if (oDynFeatureCache[sDynFeatureASIN]['status'] == 'complete') {
                     if (oMBCDiv) {
                         oMBCDiv.innerHTML = oDynFeatureCache[sDynFeatureASIN]['more-buying-choices'];
                     } 
                     if (oPrimeDiv) {
                         oPrimeDiv.innerHTML = oDynFeatureCache[sDynFeatureASIN]['prime'];
                     } 
                  }
	      }
          }
      }
      if (shouldLogTwister()) {
       incrementHoverCount(); // capture this for non swatches
      }
    }
  }
 
 
 this.triggerParentCallbacks = function() {
    for (var i in oFeatureDivsWithLoadingBar) {
        var feature_name = (i.split("_feature_div"))[0];
        var callbackfunc;
        if (!(callbackfunc = parentCallbacksMap[feature_name])) {
        	callbackfunc=window['onParentUpdate_'+feature_name.replace(/-/g,"_")];               
                parentCallbacksMap[feature_name] = callbackfunc ? callbackfunc : NO_FUNC;
        } 
	if (callbackfunc!=null && callbackfunc != NO_FUNC) {
           // Potential Confusion so I'm adding a comment here
           // If callbackfunc exists in the map, this branch happens if callbackfunc == NO_FUNC
           // If callbackfunc does not exist in the map, this branch happens if callbackfunc == null
    	    callbackfunc();
        }
    }
  }
 
 
 this.triggerCacheReselectCallback = function(asin) {
  for (var i in oFeatureDivsWithLoadingBar) {
        var feature_name = (i.split("_feature_div"))[0];
        var callbackfunc;
	var callbackfuncName;
        if (!(callbackfunc = cacheReselectCallbackMap[feature_name])) {
		callbackfuncName='onCacheUpdateReselect_'+feature_name.replace(/-/g,"_");
        	callbackfunc=window[callbackfuncName];    		
                cacheReselectCallbackMap[feature_name] = callbackfunc ? callbackfunc : NO_FUNC;	
        } 
	if (callbackfunc!=null && callbackfunc != NO_FUNC) {          
    	   callbackfunc(asin);   
        }
    }
 
 }
 

  this.onDUAbort = function(oArgs){
    var sChildASIN = oArgs['childASIN'];
    if (!sChildASIN) return;
    var  childAsinCache=oDynFeatureCache[sChildASIN];
    if (oDynFeatureCache[sChildASIN]) {
       if (oDynFeatureCache[sChildASIN]['status'] != 'complete') {
         oDynFeatureCache[sChildASIN] = null;
       }
    }
  }
  
 this.setLoadingIndicators = function ()
 {
  setLoadingBar2Line(document.getElementById('more-buying-choice-content-div')); 
  for ( featId in oFeatureDivsWithLoadingBar) {

	var featDiv=oFeatureDivsWithLoadingBar[featId];  
	if (featId.indexOf('more-buying-choices')>-1)
		continue;
	else if (featId.indexOf('accessories-and-compatible-products')>-1)
		 setFeatureLoadingBar(featDiv,null,true);
	else
		setFeatureLoadingBar(featDiv);
	}
    

 }

 this.initFeatureDivsWithLoadingBar= function()
 {
   //h multi-variation-alt-images.mivar currTime=new Date().getTime();
    var divColl=document.getElementsByTagName('div'); //var cnt=0;
    var aDiv,divId;
    for (var i in divColl)
     {
  	aDiv=divColl[i];divId=aDiv.id;//cnt++;
	if ((divId !=null) && divId.indexOf('_feature_div')>-1)
	{	
	oFeatureDivsWithLoadingBar[divId]=aDiv; 
	}
		
     }//alert('cycled through '+cnt +' divs in '+(new Date().getTime()-currTime)+' ms');
     //alert('inited feat divs list in '+(new Date().getTime()-currTime) +' ms');
 
 }
 
this.setFeatureHTML= function(featureDiv,featHTML)
 {  
	if (twIsIE)
	{	
	 //this roundabout way of setting innerHTML
	 //is needed because direct innerHTML call to the feature
	 //div results in occasional errors in IE 
	 var newDiv=document.createElement('div');
	 newDiv.innerHTML=featHTML;
	  featureDiv.innerHTML ="";
	  featureDiv.appendChild(newDiv);
	}
	else
	  featureDiv.innerHTML =featHTML;
    if(featureDiv.id == 'more-buying-choices_feature_div') { 
      if (shovelerMain && typeof shovelerMain == 'function') {
        shovelerMain(1);
     }
   }
 
 } 


  this.onOfferDataUpdate = function() {
    // Update the page with pending selected ASIN
    if (sLastSelectASIN && oOfferData[sLastSelectASIN]) {
      // Price block
      if (oTwisterPriceBlock ) {
        oTwisterPriceBlock.update(sLastSelectASIN, oOfferData[sLastSelectASIN],oOnlyUnqualifiedOffers);
      }
      // Availability Block
      if (oTwisterAvailability) {
        oTwisterAvailability.update(sLastSelectASIN, oOfferData[sLastSelectASIN],oOnlyUnqualifiedOffers);
      }


      // Variations
      if (oTwisterVariations) {
        oTwisterVariations.updateSizeChart(oOfferData[sLastSelectASIN]);
      }

      // Buy box
      if (oTwisterBuyBox) {
        oTwisterBuyBox.update(sLastSelectASIN, 
          oOfferData[sLastSelectASIN], 
          oLastSelectData.nVariationsSelected, 
          oLastSelectData.nVariationsTotal,
          oLastSelectData.oSelectedVariations, 
          oLastSelectData.oDisplayableNames,oOnlyUnqualifiedOffers);
      }

      sLastSelectASIN = null;
      oLastSelectData = {};
    }

    // Update the page with pending preview ASIN
    if (sLastPreviewASIN && oOfferData[sLastPreviewASIN]) {
      // Price block
      if (oTwisterPriceBlock ) {
        oTwisterPriceBlock.update(sLastPreviewASIN, oOfferData[sLastPreviewASIN],oOnlyUnqualifiedOffers);
      }
       // Availability block
      if (oTwisterAvailability) {
        oTwisterAvailability.update(sLastPreviewASIN, oOfferData[sLastPreviewASIN],oOnlyUnqualifiedOffers);
      }

      sLastPreviewASIN = null;
    }
  }

  this.onLoad = function() {

    inOnLoad = true;   
    var numSelected=0;

    if (oTwisterVariations) 
	    numSelected=oTwisterVariations.getNumberOfSelectedVariations();
    // Buy box must come before variations
    if (numSelected==0 && oTwisterBuyBox) {
      oTwisterBuyBox.onLoad();
    }
    if (oTwisterVariations) {
      oTwisterVariations.onLoad();
    }
    var func="goTwisterManager.initFeatureDivsWithLoadingBar()";
    setTimeout(func , 0);
    inOnLoad = false;

    // Select initial selection
    var selection = goTwisterVariations.getInitialSelection();
    if (selection && selection['type'] == 'swatch') {
      goTwisterVariations.onClickSwatch(selection['key'], selection['value']);
    } else if (selection && selection['type'] == 'dropdown') {
      goTwisterVariations.onChangeDropdown(selection['key']);
    }

    if(shouldLogTwister() && oTwisterVariations) {
      setTotalASINCount(oTwisterVariations.getChildCount());
    }
  }

  this.preloadOfferData = function(oTwisterVariationData) {
    var aAsinList = oTwisterVariationData.aAsinList;

    // Add new ASINs in pending state
    var nCount = 0;
    for (var i = 0; i < aAsinList.length; i++) {
      var sASIN = aAsinList[i];
      if (oOfferDataState[sASIN] == null) {
        oOfferDataState[sASIN] = REQUEST_PENDING;
        nCount++;
      }
    }

    // If any new ASINs, generate requests
    this.processAjax();
  }

  this.processAjax = function() {
    // If there's an outstanding request, return
    if (oAjaxTimeout != null) {
      return;
    }
    // Build a request
    var sRequestList = '';
    var nCount = 0;

    // Make sure offer data for selected ASIN loads ASAP
    if (sLastSelectASIN) {
      var nState = oOfferDataState[sLastSelectASIN];
      if ((nState == null) || (nState == REQUEST_PENDING)) {
        oOfferDataState[sLastSelectASIN] = REQUEST_SENT;
        sRequestList += (sLastSelectASIN + ',');
        nCount++;
      }
    }

    // Add up to 20 other pending ASINs
    for (var sASIN in oOfferDataState) {
      if (oOfferDataState[sASIN] == REQUEST_PENDING) {
        oOfferDataState[sASIN] = REQUEST_SENT;
        sRequestList += (sASIN + ',');
        nCount++;
      }

      if (nCount == 20) {
        break;
      }
    }

    // Make the request
    if (nCount) {
      var oArgs = new Object;
      if (sMerchantID && sMerchantID != '') {
	oArgs['merchantID'] = sMerchantID;
      }
      if (sStoreID && sStoreID != '') {
	oArgs['storeID'] = sStoreID;
      }
      if (sDropdownSelection && sDropdownSelection != '') { 
        oArgs['dropdown-selection'] = sDropdownSelection; 
      }
      oArgs['asinList'] = sRequestList;
      oArgs['productGroupID'] =  oTwisterManagerArgs['productGroupID'];
      oArgs['PowerBar'] = 0;


      oTMAjaxObj.request(oArgs);
      oAjaxTimeout = setTimeout(sTwisterManagerName + ".offerDataTimeout();", 10000);
    }
  }

  this.resetPending = function() {
    // Reset any sent ASINs that weren't received to pending
   for (var sASIN in oOfferDataState) {
      if (oOfferDataState[sASIN] != REQUEST_RECEIVED) {
        oOfferDataState[sASIN] = REQUEST_PENDING;
        if (oOfferDataTries[sASIN]) {
          oOfferDataTries[sASIN] += 1;
          if (oOfferDataTries[sASIN] == 4) {
            oOfferDataState[sASIN] = NOT_BUYABLE;
          }
        } else {
          oOfferDataTries[sASIN] = 1;
        }
      }
    }
  }
 
  this.setOfferingData = function(sASIN, oOffering) {
    if (oOffering) {
      oOfferData[sASIN] = oOffering;
      oOfferDataState[sASIN] = REQUEST_RECEIVED;
    }
  }

  this.offerDataReceived = function() {
    // The Ajax request came back, so clear the timeout
    clearTimeout(oAjaxTimeout);
    oAjaxTimeout = null;

    // Reset any sent (but not received) ASINs to pending
    this.resetPending();

    // Process any more Ajax requests we need to make.
    setTimeout(sTwisterManagerName + ".processAjax();", 0);
    // Do any updates based on newly available offer data.
    setTimeout(sTwisterManagerName + ".onOfferDataUpdate();", 0);
  }

  this.offerDataTimeout = function() {
    // The Ajax request timed out
    clearTimeout(oAjaxTimeout);
    oAjaxTimeout = null;

    // Reset any sent (but not received) ASINs to pending
    this.resetPending();

    // Retry a new request
    this.processAjax();
  }

 
this.setDeferredFeatureContent = function(sChildASIN, sFeatureName, sContent) {
     var featureDiv=oDynFeatureDiv[sFeatureName];
      if (!featureDiv) {
          featureDiv = document.getElementById(sFeatureName + '_feature_div');
          if (featureDiv) {
              oDynFeatureDiv[sFeatureName] = featureDiv;	      
          }
      }
      if (!oDynFeatureCache[sChildASIN]) {
          oDynFeatureCache[sChildASIN] = new Object();
      }       
      oDynFeatureCache[sChildASIN][sFeatureName] = sContent;
	var func="goTwisterManager.renderContent('"+sChildASIN+"','"+sFeatureName+"')";
	setTimeout(func,0);
     oDynFeatureCache[sChildASIN]['status'] = 'complete';
 }

this.renderContent = function(sChildASIN, sFeatureName){
     if (!sCurrentSelectedASIN) {
       if ( sFeatureName == 'prime' || 
            sFeatureName == 'more-buying-choices' || 
            sFeatureName == 'fast-track') 
       return;
     } else if (sCurrentSelectedASIN != sChildASIN) {return;}

	var featureDiv=oDynFeatureDiv[sFeatureName];
	try{
           if (featureDiv) {
               this.setFeatureHTML(featureDiv,oDynFeatureCache[sChildASIN][sFeatureName]) ; 
	       featureDiv.setAttribute('loadingBarSet',0); 
	   }
	   callbackFunc=oFeatureAjaxUpdateFns[sFeatureName];
           if (callbackFunc==null) {
	       callbackFunc=window['onAjaxUpdate_'+sFeatureName.replace(/-/g,"_")];
               if (callbackFunc==null)
	           callbackFunc=NO_FUNC;
	       else              
    	           callbackFunc(sChildASIN);
          
	       oFeatureAjaxUpdateFns[sFeatureName]=callbackFunc;
	   } else if (callbackFunc!=NO_FUNC) {
	       callbackFunc(sChildASIN);  
	   }
        } catch(e){}    
     }

this.showChildContent = function(sChildASIN,showStatus){
      if (!oDynFeatureCache[sChildASIN] ||
              oDynFeatureCache[sChildASIN]['status'] != 'complete') {
          return;
      }

      var sDate = new Date();
      for ( fName in oDynFeatureDiv) {
         try {
         if (oDynFeatureCache[sChildASIN][fName] != undefined) {
	  var featureDiv=oDynFeatureDiv[fName];
	 this.setFeatureHTML(featureDiv,oDynFeatureCache[sChildASIN][fName]);
	  featureDiv.setAttribute('loadingBarSet',0);
         }
	 if (showStatus!=null)
	 {
	    if (showStatus==AJAX_UPDATE)
	     {	
              callbackFunc=oFeatureAjaxUpdateFns[fName];
	      if (callbackFunc==null)
	      {
	      	callbackFunc=window['onAjaxUpdate_'+fName.replace(/-/g,"_")];
	     	 if (callbackFunc==null)
	           callbackFunc=NO_FUNC;
	         else              
    	           callbackFunc(sChildASIN);
          
	        oFeatureAjaxUpdateFns[fName]=callbackFunc;
	      }
	      else if (callbackFunc!=NO_FUNC) {
	       callbackFunc(sChildASIN);	     
        }
	     }
	     else if (showStatus==CACHE_UPDATE)
	     {	
               callbackFunc=oFeatureCachedUpdateFns[fName];
	       if (callbackFunc==null)
	        {
	         callbackFunc=window['onCacheUpdate_'+fName.replace(/-/g,"_")];
                 if (callbackFunc==null)
	           callbackFunc=NO_FUNC;
	         else              
	          callbackFunc(sChildASIN);
	        }
	      else if (callbackFunc!=NO_FUNC)
                  callbackFunc(sChildASIN);
                  oFeatureCachedUpdateFns[fName]=callbackFunc;
              }
	     }
         } catch (e) {
         }

      }
      if(shouldLogTwister()) {
        var func = "logCacheUpdateTime( '"+ sChildASIN + "'," + (new Date().getTime() - sDate.getTime())+");";
        setTimeout(func,0);
      }
   }
}

function logCacheUpdateTime(asin, time) {
  var params = {};
  params['cacheTime:'+asin] = time;
  addClientLog(params);
}

function log(s)
{
	//alert(s);
	//console.log(s);
	/*if (console && console.log)
		console.log(s);
	else
		alert(s);	*/
}




// (FILE: /detail-page-features/twister-variations/twister-variations-events.js) 

// Events published by the Twister Variations component
var gsTwisterVariationsEventName_PreviewVariations        = "TWISTER_VARIATIONS_PREVIEW_VARIATIONS";
var gsTwisterVariationsEventName_SelectVariations         = "TWISTER_VARIATIONS_SELECT_VARIATIONS";
/* Performance Testing Code */
var gsTwisterVariationsEventName_StartTimer				  =	"TWISTER_VARIATIONS_START_TIMER";		
var gsTwisterVariationsEventName_EndTimer				  =	"TWISTER_VARIATIONS_END_TIMER";

// (FILE: /detail-page-features/twister-variations/twister-swatches.js) 

function TwisterVariations(oEventManager, oVariationLabels, oVariationValues, oSelectedVariationValues, oChildItems, oSwatchVariationKeys, oDropdownVariationKeys, oVariationArgs) {
var oEventManager = oEventManager;
var oVariationLabels = oVariationLabels;
var oVariationValues = oVariationValues;
var oChildItems = oChildItems;
var oVariationArgs = oVariationArgs;

// Selection items array (maps selection to ASIN lists)
var oSelectionItems = new Array();
// Selection/hover state
var nVariationsTotal = 0;
var oSelectedVarValues = oSelectedVariationValues;
var oHoveredVarValues = new Array();
// Variation display types (swatch or dropdown)
var oVariationDisplayTypes = new Array();
// Swatch element and state cache
var oSwatchElements = new Array();
var oSwatchStateCache = new Array();
// Dropdown lookup state
var oDropdownLookupState = new Array();

// partial selection lookup
var oParSelLook = new Object();

// array of variation keys
var oVarKeys = new Array();

// new lookup table
var oNewLookup = new Object();

// Text colors for dropdown
var availColor = "#006699";
var notAvailColor = "#BBBBBB";

// Initial selection
var oInitialSelection;

this.setInitialSelection = function(type, key, value) {
  oInitialSelection = new Object();
  oInitialSelection['type'] = type;
  oInitialSelection['key'] = key;
  oInitialSelection['value'] = value;
}

this.getInitialSelection = function() {
  return oInitialSelection;
}


  // IE retains states on dropdowns, so reset it whenever the page loads
  // (specifically, this addresses the issue when the user hits back)
  this.resetDropdowns = function() {
    for (sVarKey in oSelectedVarValues) {
      if (oVariationDisplayTypes[sVarKey] != 'd') 
	continue
      var dropdown = document.getElementById(sVarKey);
      if (dropdown) {
	var index = parseInt(oSelectedVarValues[sVarKey]);
	if (dropdown.options[index + 1])
	  dropdown.options[index + 1].selected = true; // add 1 to skip 'Select' option
      }
    }
  }

this.populateTree = function(item, parentNode, ignoreKey, depth) {
  if (oVarKeys[depth] == ignoreKey) {
    if (parentNode ['*'] == null) {
      parentNode['*'] = new Array();
    }
 
    if (depth == (oVarKeys.length -1)) {
      parentNode['*'][item[ignoreKey]] = 1;
    } else {
      this.populateTree(item, parentNode['*'], ignoreKey, depth+1);
    }
    return;
  } 

  if ( depth == (oVarKeys.length - 1)) {
    if (parentNode ['-1'] == null) {
      parentNode['-1'] = new Array();
    }  
    parentNode['-1'][item[ignoreKey]] = 1;
    if (parentNode [item[oVarKeys[depth]]] == null) {
      parentNode[item[oVarKeys[depth]]] = new Array();
    }  
    parentNode[item[oVarKeys[depth]]][item[ignoreKey]] = 1; 
    return;
  }

  // set current key values
  if (parentNode['-1'] == null) {
    parentNode['-1'] = new Object();
  }

  this.populateTree(item, parentNode['-1'], ignoreKey, depth+1);

  if (parentNode[item[oVarKeys[depth]]] == null) {
    parentNode[item[oVarKeys[depth]]] = new Object();
  }

  this.populateTree(item, parentNode[item[oVarKeys[depth]]], ignoreKey, depth+1);
}


this.insertIntoLookupTree = function(item) {
  for (var sKey in oSelectedVarValues) {
    var dimSubSet = oParSelLook[sKey];
    if (dimSubSet == null) {
      dimSubSet = new Object();
      oParSelLook[sKey] = dimSubSet;
    }
    this.populateTree(item, dimSubSet, sKey, 0); 
  }
}

this.initLookup = function () {
  for (var sKey in oSelectedVarValues) {
    this.insertLookupKey('', oParSelLook[sKey], 0); 
  }
}

this.insertLookupKey = function (sPartKey, parentNode, depth) {
  if (depth == oVarKeys.length-1){
    for (var val in parentNode) {
      oSelectionItems[sPartKey+val+' '] = parentNode[val];
    }
    return;
  }
  for (var val in parentNode) {
    for (var val in parentNode) {
      this.insertLookupKey(sPartKey+val+' ', parentNode[val], depth+1);
    }
  }
}

{
  // Initialize variation value state
  for (var sVarKey in oSelectedVarValues) {
    oHoveredVarValues[sVarKey] = -1;
    oVarKeys[nVariationsTotal] = sVarKey;
    nVariationsTotal++;
  }

  // Populate element and state cache from the DOM
  for (var i = 0; i < oSwatchVariationKeys.length; i++) {
    var sVarKey = oSwatchVariationKeys[i];
    oSwatchElements[sVarKey] = new Array();
    oSwatchStateCache[sVarKey] = new Array();
    for (var nVarValue in oVariationValues[sVarKey]) {
      var sDivId = sVarKey + '_' + nVarValue;
      oSwatchElements[sVarKey][nVarValue] = document.getElementById(sDivId);
      oSwatchStateCache[sVarKey][nVarValue] = oSwatchElements[sVarKey][nVarValue].className;
    }
  }

  // Populate variation display types (swatch or dropdown)
  var oVariationDisplayTypes = new Array();
  for (var i in oSwatchVariationKeys) {
    var sVarKey = oSwatchVariationKeys[i];
    if (oSwatchStateCache[sVarKey][0] == 'swatchPreSelect') {
      oVariationDisplayTypes[oSwatchVariationKeys[i]] = 'f'; // fixed swatch
    } else {
      oVariationDisplayTypes[oSwatchVariationKeys[i]] = 's'; // modifiable swatch
    }
  }
  for (var i in oDropdownVariationKeys) {
    oVariationDisplayTypes[oDropdownVariationKeys[i]] = 'd'; // dropdown
  }

  // Compute mapping from selection to buyable ASIN list
  for (var i = 0; i < oChildItems.length; i++) {
    var oChildItem = oChildItems[i];
    var sLookup;
    var oItems;

    // Add single buyable ASIN for N variations selected
    sLookup = '';
    for (var sVarKey in oSelectedVarValues) {
      sLookup += (oChildItem[sVarKey] + " ");
    }
    oItems = oSelectionItems[sLookup];
    if (oItems == undefined) {
      oItems = new Array();
    }
    // Just index 0 (always 1 ASIN)
    oItems[0] = oChildItem['ASIN'];
    oSelectionItems[sLookup] = oItems;

    // populate partial seletion tree for items more than2 dimensions
    if (oVarKeys.length > 1 ) {
      this.insertIntoLookupTree(oChildItem);
    }
    // Add to list of ASINs for N-1 variations selected
    for (var sIgnoreVarKey in oSelectedVarValues) {
      sLookup = '';
      for (var sVarKey in oSelectedVarValues) {
        if (sVarKey != sIgnoreVarKey) {
          sLookup += (oChildItem[sVarKey] + " ");
        } else {
          sLookup += "-1 ";
        }
      }
      oItems = oSelectionItems[sLookup];
      if (oItems == undefined) {
        oItems = new Array();
      }
      // Index by the remaining selection value
      oItems[oChildItem[sIgnoreVarKey]] = oChildItem['ASIN'];
      oSelectionItems[sLookup] = oItems;
    }
  }

  // populate lookup table
  if (oVarKeys.length > 1) {
    this.initLookup();
  }
}

this.onLoad = function() {
  this.resetDropdowns();

  // Update the header label
  this.updateLabels();
  this.updateSwatches();

  // Trigger a selection event on load if necessary
  var nVariationsSelected = 0;
  for (var sVarKey in oSelectedVarValues) {
    if (oSelectedVarValues[sVarKey] != -1) {
      nVariationsSelected++;
    }
  }
  if ((nVariationsSelected > 0) || (nVariationsTotal == 1)) {
    this.triggerEvent('loadSelectedChildData');
  }
}

this.getNumberOfSelectedVariations = function() {
   var nVariationsSelected = 0;
   for (var sVarKey in oSelectedVarValues) {
      if (oSelectedVarValues[sVarKey] != -1) {
      nVariationsSelected++;
     }
   }
   return nVariationsSelected;
}

this.updateSwatches = function() {
  for (var sVarKey in oSwatchElements) {
    // Ignore fixed swatches
    if (oVariationDisplayTypes[sVarKey] == 'f') {
      continue;
    }

    // If N-1 other variations are selected, limit availability
    var sLookup = '';
    var oItems = null;
    for (var sCurVarKey in oSelectedVarValues) {
      if (sCurVarKey != sVarKey) {
        if (oHoveredVarValues[sCurVarKey] != -1) {
          sLookup += (oHoveredVarValues[sCurVarKey] + " ");
        } else if (oSelectedVarValues[sCurVarKey] != -1) {
          sLookup += (oSelectedVarValues[sCurVarKey] + " ");
        } else {
           // sLookup = null;
           // break;
           sLookup += "-1 ";
        }
      } else {
        sLookup += "* ";
      }
    }

    if (sLookup != null) {
      oItems = oSelectionItems[sLookup];
    }

    // Now go through each swatch and apply style
    for (var nVarValue in oSwatchElements[sVarKey]) {
      var sSwatchState = 'swatchAvailable';
      if (oSelectedVarValues[sVarKey] == nVarValue) {
        if (oItems && (oItems[nVarValue] == undefined)) {
          sSwatchState = 'swatchSelectGray';
        } else {
          sSwatchState = 'swatchSelect';
        }
        sSwatchState = 'swatchSelect';
      } else if (oHoveredVarValues[sVarKey] == nVarValue) {
        if (oItems && (oItems[nVarValue] == undefined)) {
          sSwatchState = 'swatchUnavailableHover';
        } else {
          sSwatchState = 'swatchHover';
        }
      } else {
        if (oItems && (oItems[nVarValue] == undefined)) {
          sSwatchState = 'swatchUnavailable';
        } else {
          sSwatchState = 'swatchAvailable';
        }
      }

      // Sync with the DOM
      if (sSwatchState != oSwatchStateCache[sVarKey][nVarValue]) {
        oSwatchElements[sVarKey][nVarValue].className = sSwatchState;
        oSwatchStateCache[sVarKey][nVarValue] = sSwatchState;
      }
    }
  }
}

this.updateDropdowns = function(sChangedVarKey) {
  for (var sVarKey in oSelectedVarValues) {
    if ((oVariationDisplayTypes[sVarKey] != 'd') ||
        (sVarKey == sChangedVarKey)) {
      continue;
    }
    var oDropdown = document.getElementById(sVarKey);

    // Compute lookup to find list of dropdown entries
    var sLookup = '';
    for (var sCurVarKey in oSelectedVarValues) {
      if (sCurVarKey != sVarKey) {
        if (oSelectedVarValues[sCurVarKey] != -1) {
          sLookup += (oSelectedVarValues[sCurVarKey] + " ");
        } else {
          // sLookup = '';
          // break;
          sLookup += "-1 ";
        }
      } else {
        sLookup += "* ";
      }
    }
    // If the lookup didn't change, then we don't need to update the dropdown
    if ((oDropdownLookupState[sVarKey] != undefined) &&
        (oDropdownLookupState[sVarKey] == sLookup)) {
        continue;
    }
    oDropdownLookupState[sVarKey] = sLookup;

    // Save the old selected value
    var nVarValueOrig = oSelectedVarValues[sVarKey];

    // Compute the available options for this dropdown
    var aOptions = new Array();
    var count = 0;
    if (sLookup != '') {
      // Lookup ok; use a limited range of values
      var oItems = oSelectionItems[sLookup];
      for (var val in goVariationValues[sVarKey]) {
	var option = { nVal: val, sVal: oVariationValues[sVarKey][val], sAvail: 0 };
        for (var nVarValue in oItems) {
          if ( goVariationValues[sVarKey][val] == oVariationValues[sVarKey][nVarValue]) {
	    option.sAvail = 1;
            break;
         }
        }
        aOptions[count] = option;
        count++;
      }
    } else {
      // Use the full range of values
      for (var nVarValue in oVariationValues[sVarKey]) {
        aOptions[count] = { nVal: nVarValue, sVal: oVariationValues[sVarKey][nVarValue] };
        count++;
      }
    }
   
    // Sort the dropdown alphabetically
    function sortDropdown(a, b) {
      return (b.sVal < a.sVal) - (a.sVal < b.sVal);
    }
    //aOptions.sort(sortDropdown);

    // Rebuild the dropdown
    oDropdown.options.length = 0;
    oDropdown.options[0] = new Option(goTwisterSwatchStrings['select'], -1, true);

    var index = 0;
    for (var i = 0; i < aOptions.length; i++) {
      if (aOptions[i].nVal == nVarValueOrig) {
        index = i + 1;
      }

      var child = new Option(aOptions[i].sVal, aOptions[i].nVal);
      child.title = aOptions[i].sVal;
      child.style.color = notAvailColor;
      child.isAvail = 0;
      if (aOptions[i].sAvail) {
	child.style.color = availColor;
	child.isAvail = 1;
      }
      oDropdown.options[i + 1] = child;
    }

    // Restore the original selection
    if (index > 0) {
      oDropdown.options[index].selected = true;
    }
  }
}

this.updateLabels = function() {
  var headerDiv = document.getElementById("swatchHeader");
  var sHeader = '';
  var bFirst = 1;
  var last, notLast, f = '';
  for (var sVarKey in oSelectedVarValues) {
    if (oSelectedVarValues[sVarKey] == -1) {
      bFirst = 0;
      notLast = last;
      last = goVariationLabels[sVarKey];
      if ( notLast) {
        sHeader += (f + notLast);
        f = ', ';
      }
    }
  }

  if (last && notLast) {
    sHeader += (' ' + goVariationStrings['and'] + ' ' + last);
  } else if (last) {
    sHeader += last;
  }

  // place variations into select string
  sHeader = goVariationStrings['select'].replace(/###/, sHeader) ;

  if (bFirst) {
    sHeader = goVariationStrings['toBuy'];
  }
  if (headerDiv!=null)
    headerDiv.innerHTML = sHeader;

  for (var sVarKey in oSelectedVarValues) {
    var labelDiv = document.getElementById("selected_" + sVarKey);
    var sHTML = '';
    if (nVariationsTotal > 1) {
	    sHTML += '<b class=variationDefault>' + oVariationLabels[sVarKey] + ': </b> ';
    } else {
	    sHTML += '<b class=variationDefault></b>';
    } 

    if ((oHoveredVarValues[sVarKey] != -1) && (oHoveredVarValues[sVarKey] != oSelectedVarValues[sVarKey])) {
      if (nVariationsTotal == 1) {
           sHTML += '<b class=variationDefault>' + oVariationLabels[sVarKey] + ': </b> ';
      }
      sHTML += '<b class=variationLabelHovered>' + oVariationValues[sVarKey][oHoveredVarValues[sVarKey]] + '</b>'; 
    } else if (oSelectedVarValues[sVarKey] != -1) {
      if (nVariationsTotal > 1) {
	      sHTML += '<b class=variationLabel>' + oVariationValues[sVarKey][oSelectedVarValues[sVarKey]] + '</b>';
     } else {
	      sHTML += '<b class=variationDefault>' + oVariationLabels[sVarKey] + ': </b> ';
	      sHTML += '<b class=variationLabel>'  + oVariationValues[sVarKey][oSelectedVarValues[sVarKey]] + '</b>';
      } 
    } else {
      sHTML += '<b class=variationDefault>&nbsp;</b>';
    }

    labelDiv.innerHTML = sHTML;
  }
}

this.onHoverOverSwatch = function(sVarKey, nVarValue) {
  oHoveredVarValues[sVarKey] = nVarValue;
  
  this.updateSwatches();
  this.updateLabels();
  this.triggerEvent('preview');
}

this.onHoverOffSwatch = function() {
  for (var sVarKey in oHoveredVarValues) {
    oHoveredVarValues[sVarKey] = -1;
  }

  this.updateSwatches();
  this.updateLabels();
  this.triggerEvent('preview');
}

this.onClickSwatch = function(sVarKey, nVarValue) {
  if (oVariationDisplayTypes[sVarKey] == 'f') { // Ignore fixed swatches
    return;
  }

  if (oSelectedVarValues[sVarKey] == nVarValue) {
    oSelectedVarValues[sVarKey] = -1;
  } else {
    // When unavailable swatch is toggled on, deselect other variations
    if (oSwatchStateCache[sVarKey][nVarValue] == 'swatchUnavailableHover') {
      for (var sCurVarKey in oSelectedVarValues) {
        if (oVariationDisplayTypes[sCurVarKey] != 'f') { // Ignore fixed swatches
          oSelectedVarValues[sCurVarKey] = -1;
        }
      }
    }
    oSelectedVarValues[sVarKey] = nVarValue;
  }

  this.updateSwatches();
  this.updateDropdowns(sVarKey);
  this.updateLabels();
  this.triggerEvent('select');
} 

this.onChangeDropdown = function(sVarKey) {
  var oDropdown = document.getElementById(sVarKey);
  var option = oDropdown.options[oDropdown.selectedIndex];
  var nVarValue = option.value;

  if (nVarValue != -1 && !option.isAvail) {
    // If user cleared the selected option, deselect other variations (helps user get reoriented)
    // Do the same when user selects unavailable option
    var numberOfDims=0;
    for (var sCurVarKey in oSelectedVarValues) { 
      if (oVariationDisplayTypes[sCurVarKey] != 'f') { // Ignore fixed swatches
        oSelectedVarValues[sCurVarKey] = -1;
	numberOfDims++;
      } 
    }
    if (!option.isAvail) {
      oSelectedVarValues[sVarKey] = nVarValue;
    }
    if (numberOfDims>1)   // Need to add this check to  fix #sev -2 0003834917
	     sVarKey='';    
  } else {
    oSelectedVarValues[sVarKey] = nVarValue;
  }

  this.updateSwatches();
  this.updateDropdowns(sVarKey);
  this.updateLabels();
  this.triggerEvent('select');
} 

var eventActionId = 0;
var lastEvent;

this.triggerEvent = function(sEventType) {
  // Compute the variation value array
  var oEventVarValues = new Array();
  var nEventVariationsSelected = 0;
  for (var sVarKey in oSelectedVarValues) {
    if ((sEventType == 'preview') && (oHoveredVarValues[sVarKey] != -1)) {
      oEventVarValues[oVariationLabels[sVarKey]] = oVariationValues[sVarKey][oHoveredVarValues[sVarKey]];
      nEventVariationsSelected++;
    } else if (oSelectedVarValues[sVarKey] != -1) {
      oEventVarValues[oVariationLabels[sVarKey]] = oVariationValues[sVarKey][oSelectedVarValues[sVarKey]];
      nEventVariationsSelected++;
    } else {
      oEventVarValues[oVariationLabels[sVarKey]] = null;
    }
  }

  // Compute buyable ASIN if all variations selected
  var sBuyableASIN = null;
  if (nEventVariationsSelected == nVariationsTotal) {
    var sLookup = '';
    for (var sVarKey in oSelectedVarValues) {
      if ((sEventType == 'preview') && (oHoveredVarValues[sVarKey] != -1)) {
        sLookup += (oHoveredVarValues[sVarKey] + " ");
      } else if (oSelectedVarValues[sVarKey] != -1) {
        sLookup += (oSelectedVarValues[sVarKey] + " ");
      } else {
        sLookup = null;
        break;
      }
    }
    if (sLookup != null) {
      var oItems = oSelectionItems[sLookup];
      if (oItems != null) {
        sBuyableASIN = oSelectionItems[sLookup][0];
      }
    }
  }

  // Compute the ASIN list (for select events only); these are all the ASINs
  // that could potentially be selected on the user's next click
  var aAsinList = new Array();
  var count = 0;
  if (sEventType == 'select' || sEventType == 'loadSelectedChildData') {
    for (var sIgnoreVarKey in oSelectedVarValues) {
      var sLookup = '';
      for (var sVarKey in oSelectedVarValues) {
        if (sVarKey != sIgnoreVarKey) {
          if ((sEventType == 'preview') && (oHoveredVarValues[sVarKey] != -1)) {
            sLookup += (oHoveredVarValues[sVarKey] + " ");
          } else if (oSelectedVarValues[sVarKey] != -1) {
            sLookup += (oSelectedVarValues[sVarKey] + " ");
          } else {
            sLookup = null;
            break;
          }
        } else {
          sLookup += "-1 ";
        }
      }
      if (sLookup != null) {
        var oItems = oSelectionItems[sLookup];
        for (var nVarValue in oItems) {
          aAsinList[count] = oItems[nVarValue];
          count++;
        }
      }
    }
  }

  // Create the event object
  var oEventData = new VariationData();
  oEventData.oSelectedVariations = oEventVarValues;
  oEventData.nVariationsTotal = nVariationsTotal;
  oEventData.nVariationsSelected = nEventVariationsSelected;
  oEventData.oVariationTypeDisplayLabels = oVariationLabels;
  oEventData.aAsinList = aAsinList;
  oEventData.sBuyableASIN = sBuyableASIN;  

  // Publish the event
  if (sEventType == 'preview') {
    // to avoid duplicate previews
    lastEvent = oEventData;
    eventActionId++;
    setTimeout('delayPreviewEvent(' + eventActionId+');', 100);
  } else if (sEventType == 'select') {
    oEventManager.publish(this, gsTwisterVariationsEventName_SelectVariations, oEventData);
  }
  else if (sEventType == 'loadSelectedChildData')
  {
    oEventData.bUpdateFeatures=	new Object();
    oEventData.bUpdateFeatures.value=false;
    oEventManager.publish(this, gsTwisterVariationsEventName_SelectVariations, oEventData);
  }
} 

delayPreviewEvent = function (action) {
  if ( action == eventActionId) {
    oEventManager.publish(goTwisterVariations, gsTwisterVariationsEventName_PreviewVariations, lastEvent);
  }
}

this.selectChild = function(oChildVariations, sObjName) {
  var time = 0;

  for (var sVarKey in oChildVariations) {
    var sVarValue = oChildVariations[sVarKey];

    var nVarValue = -1;
    for (var nCurVarValue in oVariationValues[sVarKey]) {
      if (sVarValue == oVariationValues[sVarKey][nCurVarValue]) {
        nVarValue = nCurVarValue;
        break;
      }
    }

    if (oSelectedVarValues[sVarKey] == nVarValue) {
      continue; // No change
    }

    if (oVariationDisplayTypes[sVarKey] == 's') {
      setTimeout(sObjName + ".onClickSwatch('" + sVarKey + "', " + nVarValue + ')', time * 500);
    } else if (oVariationDisplayTypes[sVarKey] == 'd') {
      var ddList = document.getElementById(sVarKey);
      for (var i = 1; ddList.options[i] != null; i++) {
        if (ddList.options[i].value == nVarValue) {
          ddList.options[i].selected = true;
          break;
        }
      }
      setTimeout(sObjName + ".onChangeDropdown('" + sVarKey + "')", time * 500);
    }

    time++; // Delay selection
  }
}

this.updateSizeChart = function(oOfferData) {
  if (!oVariationArgs['merchSizeChartLink'] || !oVariationArgs['merchSizeText'] || !oVariationArgs['divID'] ||
      !oOfferData['ASIN'] || !oOfferData['merchantID']) {
    return;
  }
  var div = document.getElementById(oVariationArgs['divID']);
  if (!div) {
    return;
  }
  var link = oVariationArgs['merchSizeChartLink'] + '?asin=' + oOfferData['ASIN'] + '&seller=' + oOfferData['merchantID'];
  var sHTML = '<a href="' + link + '" target="_blank">' + oVariationArgs['merchSizeText'] + '</a>';
  div.innerHTML = sHTML;
}

this.clearSizeChart = function() {
  if (!oVariationArgs['divID']) {
    return;
  }
  var div = document.getElementById(oVariationArgs['divID']);
  if (!div) {
    return;
  }
  div.innerHTML = oVariationArgs['twisterDefaultSizingChartLink'];
}

this.getChildCount = function() {
  if(oChildItems) {
   return (oChildItems.length);
  }
  return 0;
}

}

// VariationData object passed to the twister manager 
function VariationData() { 
  this.aAsinList = new Array();
  this.oSelectedVariations = new Array();
  this.nVariationsSelected = 0;
  this.nVariationsTotal = 0;
  this.sBuyableASIN = null;
  this.oVariationTypeDisplayLabels = new Array();
}

// Event helper functions
window.isChildElement = function(oParent, oChild) {
  var isChild = false;
  for (var i = 0; i < 4; i++) { // Going up 4 levels is all that's necessary!
    if (oChild == null) break;
    if (oChild == oParent) { isChild = true; break; }
    oChild = oChild.parentNode;
  }
  return isChild;
}

window.isMouseOver = function(oElement, e) {
  if (!e) var e = window.event;
  var tg = (window.event) ? e.srcElement : e.target;
  var reltg = (e.relatedTarget) ? e.relatedTarget : e.fromElement;

  if (isChildElement(oElement, tg) && !isChildElement(oElement, reltg)) {
    if (oElement.getAttribute("mouseOver") != "1") {
      oElement.setAttribute("mouseOver", "1");
      return 1;
    }
  }
  return 0;
}

window.isMouseOut = function(oElement, e) {
  if (!e) var e = window.event;
  var tg = (window.event) ? e.srcElement : e.target;
  var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement;

  if (isChildElement(oElement, tg) && !isChildElement(oElement, reltg)) {
    if (oElement.getAttribute("mouseOver") == "1") {
      oElement.setAttribute("mouseOver", "0");
      return 1;
    }
  }
  return 0;
}

// (FILE: /detail-page-features/twister-product-image/twister-product-image.js) 

// Twister Product Image Object
function TwisterProductImage(oStrings) {
  var oStrings = oStrings;

  var registeredImages = new Object();
  var selectedImageID = "none";

  var isPendingPreload = false;

  this.registerImage = function(id, src, imageHTML, captionHTML) {
    if (registeredImages[id] == null) {
      registeredImages[id] = new Object();
      registeredImages[id].imageHTML = imageHTML;
      registeredImages[id].captionHTML = captionHTML;
      registeredImages[id].src = src;
      registeredImages[id].hasSticker = false;
    }
  }

  this.preloadImage = function(id) {
    if (registeredImages[id] && !registeredImages[id].image) {
      registeredImages[id].image = new Image();
      registeredImages[id].image.src = registeredImages[id].src;
    }
  }

  this.displayImage = function(id) {
    this.preloadImage(id);
    this.showImage(id);
    this.hideOverlay();
  }

  this.displayNotBuyable = function(id, oSelectedVariations) {
    this.showImage(id);
    this.showNotBuyableOverlay(oSelectedVariations);
  }

  this.displayImageNotAvail = function(id, oTwisterVariationData) {
    this.showImage(id);
    this.showImageNotAvailOverlay(oTwisterVariationData);
  }

  this.showImage = function(id) {
    if (id != selectedImageID) {
      // Hide previous annotations, if present
      if (registeredImages[selectedImageID] && registeredImages[selectedImageID].ciuAnnoContainer) {
	registeredImages[selectedImageID].ciuAnnoContainer.hide();
      }
    
      selectedImageID = id;
      if (id != null) {
        document.getElementById('prodImageCell').innerHTML = registeredImages[id].imageHTML;
        document.getElementById('prodImageCaption').innerHTML = registeredImages[id].captionHTML;
      }
    }
    // Show new annotations, if present
    if (registeredImages[selectedImageID] && registeredImages[selectedImageID].ciuAnnoContainer) {
      registeredImages[selectedImageID].ciuAnnoContainer.show();
      ciuAnnotationsMouseover(selectedImageID);
    }
  }

  this.hideOverlay = function() {
    document.getElementById('prodImageOverlay').style.visibility = "hidden";
  }

  this.showOverlay = function(sHTML, sClass) {
    document.getElementById('prodImageOverlayHiddenText').innerHTML = sHTML;
    document.getElementById('prodImageOverlayVisibleText').innerHTML = sHTML;

    document.getElementById('prodImageOverlay').style.visibility = "visible";

    document.getElementById('prodImageOverlayBox').className = sClass;
    document.getElementById('prodImageOverlayVisibleText').className = sClass;
  }

  this.showNotBuyableOverlay = function(oSelectedVariations) {
    var sHTML;
    sHTML = "<b>" + oStrings['prodImageNotBuyableText'] + "<br>";
    var nKeys = 0;
    for (var sKey in oSelectedVariations) {
      if (nKeys) {
        sHTML += "<br>";
      }
      sHTML += (sKey + ": <b class='prodImageNotBuyableOverlayHighlight'>" + oSelectedVariations[sKey] + "</b>");
      nKeys++;
    }
    sHTML += "</b>";

    this.showOverlay(sHTML, "prodImageNotBuyable");
  }

  this.showImageNotAvailOverlay = function(oTwisterVariationData) {
    var sHTML;
    if (oTwisterVariationData != null) {
      var oSelectedVariations = oTwisterVariationData.oSelectedVariations;
      var oVariationLabels = oTwisterVariationData.oVariationTypeDisplayLabels;
      sHTML = oStrings['prodImageNotAvailTextColorBefore'];
      var nKeys = 0;
      for (var sKey in oVariationLabels) {
	var displayName = oVariationLabels[sKey];
	var value = oSelectedVariations[displayName];
	if (value != null && dimensionLookupHash[sKey] && dimensionLookupHash[sKey][value]) {
	  if (nKeys) {
            sHTML += "<br>";
	  }
	  sHTML += (displayName + ": <b class='prodImageNotAvailOverlayHighlight'>" + value + "</b>");
	  nKeys++;
	}
      }
      if (nKeys) {
	sHTML += oStrings['prodImageNotAvailTextColorAfter'];
      } else {
	sHTML = oStrings['prodImageNotAvailTextNoColor'];
      }
      this.showOverlay(sHTML, "prodImageNotAvail");
    }
  }

  this.updateImageSticker = function(id, stickerType, quantity) {
    if (!registeredImages[id].hasSticker) {
      var styleCode = '_PI' + stickerType + '-' + quantity + ',TopRight,0,0_AA280_SH20';
      var html = registeredImages[id].imageHTML;
      var splitPoint = html.lastIndexOf('_.');
      var first = html.substr(0, splitPoint);
      var last = html.slice(splitPoint + 1);
      registeredImages[id].imageHTML = first + styleCode + last;
      registeredImages[id].hasSticker = true;
    }
  }

  this.getRegisteredImages = function() {
    return registeredImages;
  }
}

// (FILE: /detail-page-features/twister-alt-images/twister-alt-images.js) 

// Twister Alt Images object
function TwisterAltImages(sInitialColor, nInitialNumThumbs, sLookupHash, stickerType, quantity) {
  var oImageDataSets = new Object();
  var oCustomerImageDataSet = new Array();
  var oImageStickers = new Object();
  var nImageDataSets = 0;

  var sDimensionLookup = sLookupHash;

  // "Color" now no longer means color, but a '-' separated index of
  // a variational bucket, ex: 1-2
  var sCurrentSelectedColor = sInitialColor;

  // Until we confirm that we have the images for sInitialColor, assume we
  // are only viewing the default images
  var defaultIndex = sInitialColor;
  while (defaultIndex.search(/[0-9]+/) >= 0) {
    defaultIndex = defaultIndex.replace(/[0-9]+/, 'x');
  }
  var parentIndex = defaultIndex;
  var sCurrentDisplayedColor = defaultIndex;
  var sCurrentSelectionData;

  var nMaxThumbs = 7;
  var nMinAltImages = 4;
  var nThumbs = nInitialNumThumbs;
  var nHighlightThumb = 0;
  var aImageIDs = new Array();
  var nAltImages = nInitialNumThumbs;
  var nCustImages = -1;

  var sStickerType = stickerType;
  var nStickerQuantity = quantity;

  this.getBucketArray = function(bucketId) {
    var bucketString = '' + bucketId;
    var bucketArray = bucketString.split('-');
    for (var i = 0; i < bucketArray.length; i++) {
      bucketArray[i] = parseInt(bucketArray[i]);
    }
    return bucketArray;
  }
  var sCurrentSelectedBucket = this.getBucketArray(sInitialColor);

  this.callRegJS=function(imageData) {
    goTwisterProductImage.registerImage(imageData.regImgArgs[0],imageData.regImgArgs[1],imageData.regImgArgs[2],imageData.regImgArgs[3]);
  }

  this.addCustomerImage = function(id, thumbHtml, image, html, caption) {
    var oImageData = new Object();
    oImageData.sImageID = id;
    oImageData.sImage = image;
    oImageData.sImageHTML = thumbHtml;
    oImageData.sImageCaption = caption;

    oCustomerImageDataSet[oCustomerImageDataSet.length] = oImageData;
    goTwisterProductImage.registerImage(id, image, html, caption);
  }

  this.registerCustomerImages = function (start, custImages) {
    if (start < nMaxThumbs) {
      nAltImages = start;
      nCustImages = custImages;
      for (var nThumb = 0; nThumb < custImages; nThumb++) {
	var currentThumb = nThumb + start;
	if (oCustomerImageDataSet[nThumb]) {
	  this.setThumb(currentThumb, oCustomerImageDataSet[nThumb].sImageID, oCustomerImageDataSet[nThumb].sImageHTML);
	  document.getElementById("thumb_" + currentThumb).style.display = 'inline';
	}
      }
    }
  }

  this.addImage = function(sImageID, sColor, registerJSArgs, sImageHTML) {
    var oImageData = new Object();
    oImageData.sImageID = sImageID; 
    oImageData.regImgArgs=registerJSArgs;
    oImageData.sImageHTML = sImageHTML;
    oImageData.hasSticker = false;

    if (oImageDataSets[sColor] == null) {
      oImageDataSets[sColor] = new Array();
      nImageDataSets++;
    }

    // Store this image in the right image set
    oImageDataSets[sColor][oImageDataSets[sColor].length] = oImageData;	

    // Construct image's partial indexes and store images there too
    var indexes = this.getBucketArray(sColor);
    var partialIndexes = new Array;
    this.getPartialIndexes(false, '', indexes, 0, partialIndexes);
    for (var i = 1; i < partialIndexes.length; i++) { // start index at 1 to skip all x's index
      if (!oImageDataSets[partialIndexes[i]]) {
	oImageDataSets[partialIndexes[i]] = oImageDataSets[sColor];	
      }
    }

    // Add image to twister product images
    this.callRegJS(oImageData);

    // Register the image if necessary (causes it to be loaded by the browser)
    if (sColor == sCurrentSelectedColor) { 
      // This is an image for the current color; load all of them
      aImageIDs[aImageIDs.length] = sImageID;

      // Since we are displaying these images, let's update the images with stickers if necessary
      if (sStickerType && sColor != parentIndex) {
	oImageStickers[sColor] = 1;
	goTwisterProductImage.updateImageSticker(sImageID, sStickerType, nStickerQuantity);
      }

      sCurrentDisplayedColor = sCurrentSelectedColor;
    }
  }

  this.setColor = function(sNewSelectedColor) {
    if (sNewSelectedColor != sCurrentSelectedColor) {
      sCurrentSelectedColor = sNewSelectedColor;
      if (oImageDataSets[sCurrentSelectedColor] != undefined) {
        sCurrentDisplayedColor = sCurrentSelectedColor;
      }
      var oImageDataSet;
      if (oImageDataSets[sCurrentDisplayedColor] != undefined) {
        oImageDataSet = oImageDataSets[sCurrentDisplayedColor];
      } else {
        oImageDataSet = new Array();
      }

      nAltImages = oImageDataSet.length;
      nCustImages = oCustomerImageDataSet.length
      nThumbs = nAltImages + nCustImages;
      if (nThumbs > nMaxThumbs) {
	nThumbs = nMaxThumbs;
	nAltImages = nMaxThumbs - nCustImages;
	if (nAltImages < nMinAltImages) {
	  nAltImages = nMinAltImages;
	  nCustImages = nMaxThumbs - nAltImages;
	}
      }

      for (var nThumb = nThumbs; nThumb < nMaxThumbs; nThumb++) {
        document.getElementById("thumb_" + nThumb).style.display = 'none';
      }

      document.getElementById("thumb_strip").style.width = (nThumbs * 36);

      for (var nThumb = 0; nThumb < nAltImages; nThumb++) {
        this.setThumb(nThumb, oImageDataSet[nThumb].sImageID, oImageDataSet[nThumb].sImageHTML);
        document.getElementById("thumb_" + nThumb).style.display = 'inline';
      }

      this.registerCustomerImages(nAltImages, nCustImages);

      if (nThumbs > 0) {
        this.viewThumb(0);
      }
    }
  }

  this.setThumb = function(nThumb, sImageID, sImageHTML) {
    var sInnerID = "thumb_" + nThumb + "_inner";
    document.getElementById(sInnerID).innerHTML = sImageHTML;

    aImageIDs[nThumb] = sImageID;
  }

  this.viewThumb = function(nThumb) {
    if ((nImageDataSets > 1) && (sCurrentDisplayedColor != sCurrentSelectedColor)) {
      goTwisterProductImage.displayImageNotAvail(aImageIDs[nThumb], sCurrentSelectionData);
    } else {
      goTwisterProductImage.displayImage(aImageIDs[nThumb]);
    }

    if (nThumb != nHighlightThumb) {
      var sThumbID;
      sThumbID = "thumb_" + nHighlightThumb;
      document.getElementById(sThumbID).style.border = '1px solid #999999';
      sThumbID = "thumb_" + nThumb;
      document.getElementById(sThumbID).style.border = '1px solid #990000';
      nHighlightThumb = nThumb;
    }
  }

  this.preloadThumbs = function() {
    for (var nThumb = 0; nThumb < nThumbs; nThumb++) {
      goTwisterProductImage.preloadImage(aImageIDs[nThumb]);
    }
  }

  this.onMouseOver = function(nThumb) {
    this.viewThumb(nThumb);
    this.preloadThumbs();
  }

  this.onMouseOut = function(nThumb) {
    // Check if customer image
    if (nThumb >= nAltImages) {
      var id = aImageIDs[nThumb];
      if (registeredImages && registeredImages[id] && registeredImages[id].ciuAnnoContainer) {
	ciuAnnotationsMouseout(id);
      }
    }
  }

  this.previewVariationValues = function(oTwisterVariationData) {
    sCurrentSelectionData = oTwisterVariationData;
    var oOfferData = goTwisterManager.getOfferData();
    
    this.updateCurrentSelectedBucket(oTwisterVariationData);
    var sSelectedColor = this.getBucketString(sCurrentSelectedBucket);

    var sPreviewColor;
    var bImageNotAvail = 0;
    if (nImageDataSets > 0) {
      if (sSelectedColor != undefined) {
        if (oImageDataSets[sSelectedColor] != undefined) {
          sPreviewColor = sSelectedColor;
        } else {
          sPreviewColor = sCurrentDisplayedColor;
	  if (nImageDataSets > 1) {
            bImageNotAvail = 1;
	  }
        }
      }
    } else {
      sSelectedColor = undefined;
      bImageNotAvail = 1;
    }

    var sPreviewImageID = undefined;
    if (sPreviewColor) {
      if (sPreviewColor == sCurrentDisplayedColor) {
        sPreviewImageID = aImageIDs[nHighlightThumb];
      } else {
        sPreviewImageID = oImageDataSets[sPreviewColor][0].sImageID;
      }
    }

    var bNotBuyable = ((oTwisterVariationData.nVariationsSelected == oTwisterVariationData.nVariationsTotal) && (oTwisterVariationData.sBuyableASIN == undefined))
      if (bNotBuyable) {
        goTwisterProductImage.displayNotBuyable(sPreviewImageID, oTwisterVariationData.oSelectedVariations);
      } else if (bImageNotAvail) {
        goTwisterProductImage.displayImageNotAvail(sPreviewImageID, oTwisterVariationData);
      } else {
        goTwisterProductImage.displayImage(sPreviewImageID);
      }
  }

  this.selectVariationValues = function(oTwisterVariationData) {
    this.updateCurrentSelectedBucket(oTwisterVariationData);
    this.setColor(this.getBucketString(sCurrentSelectedBucket));
  }

  this.updateCurrentSelectedBucket = function(oTwisterVariationData) {
    var oOfferData = goTwisterManager.getOfferData();
    var oSelectedVariations = oTwisterVariationData.oSelectedVariations;
    var oVariationTypeDisplayLabels = oTwisterVariationData.oVariationTypeDisplayLabels;
    var sSelectedVariationLabel  = undefined;
    var sSelectedValue;
    for (var varKey in oVariationTypeDisplayLabels) {
      if(sDimensionLookup[varKey]){
        sSelectedVariationLabel  = oVariationTypeDisplayLabels[varKey];
      	sSelectedValue = oSelectedVariations[sSelectedVariationLabel];
        if (sSelectedValue != null) { 
	  sCurrentSelectedBucket[sDimensionLookup[varKey]['::::']] = sDimensionLookup[varKey][sSelectedValue];
	} else {
	  sCurrentSelectedBucket[sDimensionLookup[varKey]['::::']] = 'x';
        }
      }
    }

    // Update images with bundle stickers if necessary
    var bundleCount;
    var packCount;
    var bucket;
    if (oOfferData[oTwisterVariationData.sBuyableASIN]) {
      bundleCount = oOfferData[oTwisterVariationData.sBuyableASIN].bundle_count;
      packCount = oOfferData[oTwisterVariationData.sBuyableASIN].pack_count;
      var bucket = this.getBucketString(sCurrentSelectedBucket);
      if ((bundleCount || packCount) && oImageDataSets[bucket] && !oImageStickers[bucket]) {
	oImageStickers[bucket] = 1; // Set this so we don't try to update the stickers again
        for (var i = 0; i < oImageDataSets[bucket].length; i++) {
          if (bundleCount && bundleCount > 1) {
            goTwisterProductImage.updateImageSticker(oImageDataSets[bucket][i].sImageID, 'bundle', bundleCount);
          } else if (packCount && packCount > 1) {
            goTwisterProductImage.updateImageSticker(oImageDataSets[bucket][i].sImageID, 'countsize', packCount);
          }
        }
      }
    }
  }

  this.getBucketString = function(bucket) {
    var myResult = '';
    if (bucket.length > 0) {
      for (var i = 0; i < bucket.length - 1; i++) {
        myResult += bucket[i] + '-';
      }
      myResult += bucket[bucket.length - 1];
      return myResult;
    }
  }

  // Get partial indexes, ie. 1-2-3 gives you 1-2-x, 1-x-3, etc...
  this.getPartialIndexes = function(hasX, current, values, index, result) {
    if (index == values.length - 1) {
      result.push(current + '-x');
      if (hasX) {
	result.push(current + '-' + values[index]);
      }
    } else {
      if (index > 0) {
	this.getPartialIndexes(true, current + '-x', values, index + 1, result);
	this.getPartialIndexes(hasX, current + '-' + values[index], values, index + 1, result);
      } else {
	this.getPartialIndexes(true, 'x', values, index + 1, result);
	this.getPartialIndexes(hasX, values[index], values, index + 1, result);
      }
    }
  }

}
  
// (FILE: /detail-page-features/twister-more-buying-choices/twister-more-buying-choices.js) 

function TwisterMoreBuyingChoices(merchID, sDivID, oMBCAjaxObj) {
  var moreOffersInfo = {};
  var sDivID = sDivID;
  var oMBCAjaxObj = oMBCAjaxObj;
  this.clear = function() {
    var div = document.getElementById(sDivID);
    if(div) {
      div.innerHTML = '';
    }
  }

  this.update = function(sASIN) {
    if(merchID) {
      return;
    }
    if(!moreOffersInfo[sASIN]) {
      var oAjaxArgs = {}
      oAjaxArgs['ASIN'] = sASIN; 
      oAjaxArgs['globalObject'] = 'goTwisterMoreBuyingChoices';
	  oAjaxArgs['inTwister'] = 1;
      oMBCAjaxObj.request(oAjaxArgs);
    } else {
      var div = document.getElementById(sDivID);
      if(div) {
        div.innerHTML = moreOffersInfo[sASIN];
      }
    }
  }
  this.setOfferInfo = function(sASIN, sInfo) {
    moreOffersInfo[sASIN] = sInfo;
    var div = document.getElementById(sDivID);
    if(div) {
      div.innerHTML = moreOffersInfo[sASIN];
    }
  }
}

// (FILE: /detail-page-features/twister-buy-box/twister-buy-box.js) 


// this is only supported in US
var subscribeAndSaveHTMLTmpl='<strong>Save  subscribe_discount%  with <br />Subscribe &amp; Save</strong>';

function TwisterBuybox(headerDivID, mainDivID, oBuyboxStrings) {
  var oStrings = oBuyboxStrings;
  var buyBoxForm;

  var oneClickDiv;
  var parentOneClickDiv;
  var parentAddressDropdown;

  this.onLoad = function() {
    var sHeaderString = this.printBuyboxHeader(null);
    document.getElementById(headerDivID).innerHTML = sHeaderString;

    this.makeButtonsInactive();
    this.handleOneClick(null);
  }

  this.update = function(sASIN, oOfferData, numVariations, totalVariations, selectedVariations, displayableNames,onlyUnqualifiedOffers) {
    
    var isSIP = 0;
    if (oOfferData && oOfferData['is_sip'] ) {
      isSIP = oOfferData['is_sip'];
    }
    
    var sTable = '<table class="twisterVariations">';
    if (isSIP) {
      sTable = '<table class="twisterVariations" align="center">';
    }
    var sHeaderString = '';
    var sCurrentString = '<div id="buyboxPriceBlock" style="padding-top: 0px;">' + sTable;

    if ( onlyUnqualifiedOffers ) {
         document.getElementById('buyboxDivId').style.display = 'none';
         if (sASIN) {
             this.makeButtonsActive();
             this.handleOneClick(oOfferData);
         } else {
              this.makeButtonsInactive();
              this.handleOneClick(oOfferData);
         }
         return;
    }

    if (sASIN) {
      sHeaderString = '<strong>' + oStrings['ReadyToBuy'] + '</strong>';

      // Price
      var sPrice;
      var sShipCost;
      if (oOfferData) {
      	if (oOfferData['sale_price']) {
          sPrice = oOfferData['sale_price'];
        } else if (oOfferData['our_price']) {
          sPrice = oOfferData['our_price'];
        } else {
          sPrice = oOfferData['list_price'];
        }
        if(isSIP && oOfferData['shipping_charge']){
          sShipCost = oOfferData['shipping_charge'];
        }
      } else {
        sPrice = oStrings['loading'];
      }

      var priceValue = oStrings['PriceLabel'] + '</b>&nbsp;<b class="price">' + sPrice;

      if (oOfferData && oOfferData['price_breaks_map_raw']) {
	priceValue = '<span class="price">' + oStrings['priceTooLow'] + '</span>';
      }

      sCurrentString +='<tr><td class="twisterProductLabel" valign="top"><b>' + priceValue + '</b>';

      var ssPrefix = '<span class="plusShippingText">&nbsp;';
      var ssSuffix = '</span>';
      var msgSuffix = '';

      // Display for SSS messaging if item is qualified/eligible for it
      if (oOfferData) {
	// If price breaks MAP, display standalone shipping msg on new line
	if (oOfferData['price_breaks_map_raw']) {
	  ssPrefix = '</tr><tr><td class="twisterProductLabel">' + ssPrefix;
	  ssSuffix += '</td>';
	  msgSuffix = '_sa';
	}
         if (isSIP) {
           if (oOfferData['prime_shipping']) {
             sCurrentString += ssPrefix + oOfferData['prime_shipping'] + ssSuffix;
           } else if (oOfferData['isEligibleForSuperSaverShipping']) {
             if (oOfferData['isEligibleForSuperSaverShipping'] == 1) {
                  sCurrentString += ssPrefix + oStrings['SSSEligible' + msgSuffix] + ssSuffix;
             }
             else {
                  sCurrentString += ssPrefix + oStrings['SSSQualifies' + msgSuffix] + ssSuffix;
             }
           }
           else if(sShipCost && !oOfferData['isFreeShipping']){
             sCurrentString += ssPrefix + '+ ' + sShipCost + ' ' + oStrings['shipping'] + ssSuffix;
           }
           else{
             sCurrentString += ssPrefix + '+&nbsp;' + oStrings['FreeShipping'] + ssSuffix;
           }
         }
         else {
           if (oOfferData['prime_shipping']) {
             sCurrentString += ssPrefix + oOfferData['prime_shipping'] + ssSuffix; 
           // We only show SSS message if Amazon and item is qualified.
           } else if (oOfferData['isEligibleForSuperSaverShipping'] && (oOfferData['merchantID'] == 'ATVPDKIKX0DER')) {
             sCurrentString += ssPrefix + oStrings['SSSMessage'] + ssSuffix; 
           }
         }
      }
     
      sCurrentString += '</td></tr>';
      
      
      // show amazon points information
      if (oOfferData && oOfferData['amazonPoints']) {
        sCurrentString +='<tr><td class="twisterProductLabel" valign="top">'+oStrings['pointsLabel']+'<span class="tiny">&nbsp;' + oOfferData['amazonPoints'] + '</span></td></tr>';
      }

      sCurrentString += this.printVariationInfo(selectedVariations);

      if (oOfferData) {
        document.getElementById("twisterBuyboxAvailabilityJS").innerHTML = this.printAvailability(oOfferData);
      } else {
        document.getElementById("twisterBuyboxAvailabilityJS").innerHTML = '';
      }
      
      // Update buybox form with buyable asin and merchant id
      if (oOfferData) {
        // document.getElementById("ASIN").value = sASIN;
        // document.getElementById("merchantID").value = oOfferData['merchantID'];
        // document.getElementById("offerListingID").value = oOfferData['offer_listing_id'];

        if (!buyBoxForm) {
          buyBoxForm = document.handleBuy;
        }
        buyBoxForm.ASIN.value = sASIN;
        buyBoxForm.merchantID.value = oOfferData['merchantID'];
        buyBoxForm.offerListingID.value = oOfferData['offer_listing_id'];

        this.makeButtonsActive();
        this.handleOneClick(oOfferData);
      } else {
        this.makeButtonsInactive();
        this.handleOneClick(oOfferData);
      }
    } else {
      sHeaderString = this.printBuyboxHeader(selectedVariations);

      // Clear the availability when we go from N selected variations to N-x selected variations
      document.getElementById("twisterBuyboxAvailabilityJS").innerHTML = '';
      this.makeButtonsInactive();
      this.handleOneClick(oOfferData);

      if (numVariations == 0) {
        sCurrentString = '';
        if (totalVariations == 0) {
          sHeaderString = '';
        }
      } else if (numVariations < totalVariations) {
        sCurrentString += this.printVariationInfo(selectedVariations);
      }
    }

    sCurrentString += '</table></div>';

    document.getElementById(headerDivID).innerHTML = sHeaderString;
    document.getElementById(mainDivID).innerHTML = sCurrentString; 

    if ( sASIN && oOfferData && (!oOfferData['avail_message'] || !oOfferData['availabilityCondition'])) {
         document.getElementById('buyboxDivId').style.display = 'none';
      this.setSubscribeDivVisibility(oOfferData);
    } 
 else {	
    document.getElementById('buyboxDivId').style.display = 'block';  
   this.setSubscribeDivVisibility(oOfferData);
 }

    // Use proper add to cart button
    var addToCart = document.getElementById('twisterAddToCartActive');
    var oneClick = document.getElementById('twisterOneClickActive');
    if (oOfferData && addToCart && goTwisterBuyboxImages) {
      if (oOfferData['is_preorder']) {
	if (goTwisterBuyboxImages['preorder']) {
	  addToCart.innerHTML = goTwisterBuyboxImages['preorder'];
	}
	if (oneClick && goTwisterBuyboxImages['oneclick_preorder']) {
	  oneClick.innerHTML = goTwisterBuyboxImages['oneclick_preorder'];
	}
      } else {
	if (goTwisterBuyboxImages['addToCart']) {
	  addToCart.innerHTML = goTwisterBuyboxImages['addToCart'];
	}
	if (oneClick && goTwisterBuyboxImages['oneclick']) {
	  oneClick.innerHTML = goTwisterBuyboxImages['oneclick'];
	}
      }
    }

  }

this.setSubscribeDivVisibility=function(oOfferData)
{
  var subDiscnt=(oOfferData==null)?null:oOfferData['subscribe_discount'];

  var subscribeDiv=document.getElementById('rcx-subs-bb-outer');

	if (subscribeDiv==null) return;
   if (subDiscnt!=null)
   {
	subscribeDiv.style.display = 'block';

   }
	else
  {
	subscribeDiv.style.display = 'none';

  }
}
this.updateSubscribeInfo=function(oOfferData)
{
   var subDiscnt=(oOfferData==null)?null:oOfferData['subscribe_discount'];
   if (subDiscnt!=null)
	{	
	 document.getElementById('subscribe_discount_div').innerHTML=formatString(subscribeAndSaveHTMLTmpl, 		{'subscribe_discount':subDiscnt});
	}
}

  this.array2String = function(arr, aStr, useAll) {
    var str = '';
    var last, notLast, f='';
    for (v in arr) {
      if ((!arr[v]) || useAll ) {
        notLast = last;
        if (useAll) {
          last = arr[v];
        } else {
          last = v;
        }

        if  ( notLast ) {
          str += (f + notLast);
          f = ', ';
        }
      }
    }

    if (str == '') {
      return last;
    }
    if (last) {
      return str + aStr + last;
    }
    return str;
  }

  this.printBuyboxHeader = function(selectedVariations) {
    var headerString = '';

    var hasVariationNames = 0;
    for (var x in goVariationLabels) {
      hasVariationNames = 1;
      break;
    }

    var strOptions = '';
    if (hasVariationNames) {
      if (selectedVariations) {
        strOptions = this.array2String(selectedVariations, ' ' +  goTwisterBuyboxStrings['and'] + ' ', false);
      } else {
        // If selectedVariations is null (eg when page first loads), we have
        // to use the global goVariationLabels to display the proper names.
        strOptions = this.array2String(goVariationLabels, ' ' +  goTwisterBuyboxStrings['and'] + ' ', true);
      }

      headerString += '<strong>' + goTwisterBuyboxStrings['toBuy'].replace(/###/, strOptions) + 
                      '</strong>' + '<br />(' + oStrings['NoVariationSubheader'] + ')';
    }

    return headerString;
  }

  this.printVariationInfo = function(selectedVariations) {
    var counter = 0;
    var variationString = '<tr><td class="twisterYourSelectionLabel">';
     if (goTwisterBuyboxStrings['Realm'] == 'JPAmazon') {
          variationString += '<span class="tiny">' 
     } else {
          variationString += '<span class="tiny">' 
     }
    for (var x in selectedVariations) {      
      if (selectedVariations[x]) {
        if (counter == 0) {
           variationString += '<span class="twisterBold">' + goTwisterBuyboxStrings['yourSelection'] + ' </span>';
           counter = 1;
        }
        variationString += selectedVariations[x] + ', ' ; 
      } 
    }
    variationString = variationString.substr(0,variationString.length - 2); 
    variationString += '</span></td></tr>';
    return variationString;
  }

  this.makeButtonsActive = function() {
    
    addOrig = document.getElementById("twisterAddToCartOrig");
    if (addOrig) { addOrig.style.display = 'none'; }
    addInactive = document.getElementById("twisterAddToCartInactive");
    if (addInactive) { addInactive.style.display = 'none'; }
    addActive = document.getElementById("twisterAddToCartActive");
    if (addActive) { addActive.style.display = 'block'; }
    if (document && document.handleBuy && document.handleBuy.quantity) { document.handleBuy.quantity.disabled = false; }
    w = document.getElementById("twisterOneClickOrig");
    if (w) { w.style.display = 'none'; } 
    z = document.getElementById("twisterShippingDropdown");
    if (z) { z.disabled = false; }
    a = document.getElementById("wishlistAddButtonActive");
    if (a) {a.style.display = 'inline';}
    b = document.getElementById("wishlistAddButtonInactive");
    if (b) {b.style.display = 'none';}
    c = document.getElementById("wishlistDownButtonActive");
    if (c) {c.style.display = 'inline';}
    d = document.getElementById("wishlistDownButtonInactive");
    if (d) {d.style.display = 'none';}
    j = document.getElementById("rslButtonOrig");
    if (j) {j.style.display = 'none';}
    e = document.getElementById("rslButtonJsInactive");
    if (e) {e.style.display = 'none';}
    f = document.getElementById("rslButtonJsActive"); 
    if (f) {f.style.display = 'block';}
    g = document.getElementById("weddingButtonInactive");
    if (g) {g.style.display = 'none';}
    h = document.getElementById("weddingButtonActive");
    if (h) {h.style.display = 'block';}
    u = document.getElementById("babyButtonActive");
    if (u) { u.style.display = 'block'; }
    v = document.getElementById("babyButtonInactive");
    if (v) { v.style.display = 'none'; }
    a = document.getElementById("wishlistButtonActive");
    if (a) {a.style.display = 'block';}
    b = document.getElementById("wishlistButtonInactive");
    if (b) {b.style.display = 'none';}


  }

  this.handleOneClick = function(oOfferData) {
    if (oneClickDiv == null || parentOneClickDiv == null) {
      oneClickDiv =  document.getElementById('oneClickDivId');
      parentOneClickDiv =  document.getElementById('parentOneClickDivId');
      if (oneClickDiv == null || parentOneClickDiv == null) { return; }
    }
    if (parentAddressDropdown == null) {
      parentAddressDropdown =  document.getElementById('buyboxAddresSelectionDropDown');
    }
    if (oOfferData) {
      if (oOfferData['prime_1click']) {
        parentOneClickDiv.style.display = 'none';
        oneClickDiv.innerHTML = oOfferData['prime_1click']; 
        oneClickDiv.style.display = 'block'; 
        // rename parent dropdown
        if (parentAddressDropdown != null) {
          parentAddressDropdown.setAttribute('name', 'parent-dropdown-selection');
        }
      } else if (oOfferData['isOneClickable']) {
        oneClickDiv.style.display = 'none'; 
        parentOneClickDiv.style.display = 'block'; 
	x = document.getElementById("twisterOneClickInactive");
	if(x) { x.style.display = 'none'; }
	y = document.getElementById("twisterOneClickActive");
	if(y) { y.style.display = 'block'; }
        // rename parent dropdown
        if (parentAddressDropdown != null) {
          parentAddressDropdown.setAttribute('name', 'dropdown-selection');
        }
      }
    } else {
      oneClickDiv.style.display = 'none';
      parentOneClickDiv.style.display = 'block';
      x = document.getElementById("twisterOneClickInactive");
     if(x) { x.style.display = 'block'; }
     y = document.getElementById("twisterOneClickActive");
     if(y) { y.style.display = 'none'; }
    }
  }

  this.makeButtonsInactive = function() {
    addOrig = document.getElementById("twisterAddToCartOrig");
    if(addOrig){ addOrig.style.display = 'none'; }
    addInactive = document.getElementById("twisterAddToCartInactive");
    if(addInactive){ addInactive.style.display = 'block'; }
    addActive = document.getElementById("twisterAddToCartActive");
    if(addActive){ addActive.style.display = 'none'; }
    if(document && document.handleBuy && document.handleBuy.quantity) { document.handleBuy.quantity.disabled = true; }
    w = document.getElementById("twisterOneClickOrig");
    if(w) { w.style.display = 'none'; }
    z = document.getElementById("twisterShippingDropdown");
    if(z) { z.disabled = true; }
    a = document.getElementById("wishlistAddButtonActive");
    if(a) {a.style.display = 'none';}
    b = document.getElementById("wishlistAddButtonInactive");
    if(b) {b.style.display = 'inline';}
    c = document.getElementById("wishlistDownButtonActive");
    if(c) {c.style.display = 'none';}
    d = document.getElementById("wishlistDownButtonInactive");
    if(d) {d.style.display = 'inline';}
    j = document.getElementById("rslButtonOrig");
    if(j) {j.style.display = 'none';}
    e = document.getElementById("rslButtonJsInactive");
    if(e) {e.style.display = 'block';}
    f = document.getElementById("rslButtonJsActive");
    if(f) {f.style.display = 'none';}
    g = document.getElementById("weddingButtonInactive");
    if(g) {g.style.display = 'block';}
    h = document.getElementById("weddingButtonActive");
    if(h) {h.style.display = 'none';}
    u = document.getElementById("babyButtonActive");
    if(u) { u.style.display = 'none'; }
    v = document.getElementById("babyButtonInactive");
    if(v) { v.style.display = 'block'; }
    a = document.getElementById("wishlistButtonActive");
    if(a) {a.style.display = 'none';}
    b = document.getElementById("wishlistButtonInactive");
    if(b) {b.style.display = 'block';}  


  }
 


  this.printAvailability = function(oOfferData) {
    var sAvail = '';
    var sMerchant = oOfferData['merchantName'];
    var sMessage = oOfferData['short_avail_message'];

    if (!sMessage) {
      return sAvail;
    }
    sAvail += sMessage;

   if (sMerchant) {
      if ( oOfferData['isSSOF'] ) {
           sAvail += ' ' + goTwisterBuyboxStrings['soldShipByAmazon'].replace("defaultMerchant", '<span class="twisterBold">' + sMerchant + '</span>');
      } else {
     	if (goTwisterBuyboxStrings['Realm'] == 'JPAmazon') {
        	  sAvail += '<span class="tiny">';
	     } else {
        	  sAvail += '<span class="tiny">';
	     }
        sAvail += ' ' + oStrings['ShipsFrom'] + ' ' + '<span class="twisterBold">' + sMerchant + '</span>';
        sAvail += '</span>';
      }
    }
    return sAvail;
  }
}

// (FILE: /detail-page-features/twister-prime/twister-prime.js) 

function TwisterPrime(sChildASIN, sDivID, sParentDivID, oTPAjaxObj) {
    var sCurrentASIN = sChildASIN;
    var oPrimeAjaxObj = oTPAjaxObj;
    var sParentHTML = '';
  
    oPrimeAjaxObj.setURL('/gp/twister/dynamic-update/prime.html');

    var oParentDiv = document.getElementById(sParentDivID);

    if (oParentDiv == null) { // current item is parent
        var oPrimeDiv =document.getElementById('prime_feature_div'); 
        sParentHTML = oPrimeDiv.innerHTML;
    }else{
        var oArgs = new Object();
        oArgs["ASIN"] = sCurrentASIN;
        oArgs["globalObject"] = 'goTwisterPrime';
        oPrimeAjaxObj.request(oArgs);
    }

    this.setChildHTML = function(sASIN, sHTML) {
      sParentHTML = sHTML;
    }

    this.getParentContent = function() {
      return sParentHTML;
    }
}

// (FILE: /detail-page-features/twister-price-block/twister-price-block.js) 


function TwisterPriceBlock(parentPriceBlockDivID, priceBlockDivID, sAnchorBlockDivID, oPriceBlockStrings, hasPromotions) {
  var sParentPriceBlockDivID = parentPriceBlockDivID;
  var sPriceBlockDivID = priceBlockDivID;
  var oStrings = oPriceBlockStrings;
  var bHasPromotions = hasPromotions;

  var oHTMLCache = new Array();
  var sCurrentASIN = '';

  var sPriceBlockLabelClass = gbEnableLarge ? 'priceBlockLabelPrice' : 'priceLabel';
  var sListPriceBlockLabelClass =  gbEnableLarge ? 'priceBlockLabel' : 'productLabel'; 
  var sOurPriceBlockLabelClass =  gbEnableLarge ? 'priceBlockLabel' : 'productLabel';
  var sPriceClass = gbEnableLarge ? 'priceLarge' : 'price';
  var sProductLabel = gbEnableLarge ? 'priceBlockLabelPrice' : 'productLabel';
  var sBoldPrice = gbEnableLarge ? '' : '<b>';
  var sBoldPriceClose = gbEnableLarge ? '' : '</b>';
  var sValignMiddle = gbEnableLarge ? '' : ' valign="middle" ';
  var sCellspacing = gbEnableLarge ? '3' : '0';

  var mapContentDiv = document.getElementById('twister_map_content');
  var priceBlockDiv = document.getElementById('priceBlock');

  this.update = function(sASIN, oOfferData,onlyUnqualifiedOffers) {

    // If offer breaks map, initialize the MAP popup
    if (oOfferData && oOfferData['price_breaks_map_raw']) {

      // Initialize if div not found
      if (mapContentDiv == null) {
	mapContentDiv = document.createElement('div');
	mapContentDiv.id = 'twister_map_content';
	if (priceBlockDiv) {
	  priceBlockDiv.appendChild(mapContentDiv);
	}

	// Initialize JSF popover
	goMAPPop_twister = new N2StaticPopover();
	goN2Events.registerFeature('mappop_twister', 'goMAPPop_twister', null, null, 'n2HotspotClickStatic');
	goMAPPop_twister.initialize('goMAPPop_twister', 'goMAPPop_twister', null, null, 'auto');
      }

      goMAPPop_twister.setTitle(oOfferData['map_popup_title']);
      mapContentDiv.innerHTML = oOfferData['map_div_content_html'];
      sPriceClass = 'price';
    } else {
      sPriceClass = gbEnableLarge ? 'priceLarge' : 'price';
    }

    if (sASIN == sCurrentASIN) {
      return;
    }
    sCurrentASIN = sASIN;

    if (sASIN == null) {
      this.clear();
      return;
    }
    if (oHTMLCache[sASIN] == null) {
      var sHTML = '';//'<div  class="buying" id="priceBlock"><table class="product" cellpadding="0" cellspacing="' + sCellspacing  +'" ><tbody>';
      if (oOfferData['avail_message'] && oOfferData['availabilityCondition'] &&
              !onlyUnqualifiedOffers) {
          if (oOfferData['promo_sticker']){
            sHTML += (oOfferData['promo_sticker']);
          }
          sHTML += '<div  class="buying" id="priceBlock"><table class="product" cellpadding="0" cellspacing="' + sCellspacing  +'" ><tbody>';
          sHTML += this.printImportListPrice(oOfferData);
          sHTML += this.printListPrice(oOfferData); 
          sHTML += this.printOurPrice(oOfferData);
          sHTML += this.printSalePrice(oOfferData);
          sHTML += this.printYouSaveRow(oOfferData);
          sHTML += this.printRebateInfo(sASIN,oOfferData);
          sHTML += this.printAmazonPoints(oOfferData);
	  sHTML += this.printSpecialOffers(oOfferData);
          sHTML += this.printPriceGuarantee(oOfferData);
          sHTML += '<tr style="height: 0px; line-height: 0px;"><td style="visibility: hidden;"></td><td style="visibility: hidden;"><span style="line-height: 0px;">o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o</span></td></tr>';
          sHTML += '</tbody></table></div>';
      }
      
      oHTMLCache[sASIN] = sHTML;
    }

    document.getElementById(sPriceBlockDivID).innerHTML = oHTMLCache[sASIN];
   
    // if child price block is bigger - resize parent
    var cPriceBlock = document.getElementById(sPriceBlockDivID);
    var aPriceBlock = document.getElementById(sAnchorBlockDivID);
    if (cPriceBlock.offsetHeight > aPriceBlock.offsetHeight) {
      aPriceBlock.style.height = cPriceBlock.offsetHeight;
    }
    this.updateSubscribeFeature(oOfferData);
  }

  this.clear = function() {
    document.getElementById(sPriceBlockDivID).innerHTML = document.getElementById(sParentPriceBlockDivID).innerHTML;
    var pPriceBlock = document.getElementById(sParentPriceBlockDivID);
    var aPriceBlock = document.getElementById(sAnchorBlockDivID);
    if (pPriceBlock.offsetHeight > aPriceBlock.offsetHeight) {
      aPriceBlock.style.height = pPriceBlock.offsetHeight;
    }
    this.updateSubscribeFeature(null);
  }

  // Get the Import List Price
  this.printImportListPrice = function(oOfferData) {
    importListPriceString = '';
    if (oOfferData['import_list_price_raw']) {
      if (oOfferData['list_price_raw'] && oOfferData['list_price']) {
        if (oOfferData['list_price_raw'] > oOfferData['our_price_raw']) {
          listPriceString += '<tr><td class="productLabel">' +  oStrings['ListPriceLabel']   
          + '</td><td><b class="listprice">' + oOfferData['list_price'] + '</b></td></tr>';
        } else {
          listPriceString += '<tr><td class="productLabel">' + oStrings['ListPriceLabel'] 
            + '</td><td><b class="price">' + oOfferData['list_price'] + '</b></td></tr>';
        }
      }
    }
    return importListPriceString;
  }

  // if price guarantee enabled, print it.
  this.printPriceGuarantee = function(oOfferData) {
   listPriceString = '';
   if (oOfferData['price_guarantee_enabled'] && oOfferData['price_guarantee_text']) {
     listPriceString += oOfferData['price_guarantee_text'];
   } 
   return listPriceString;
  }


  // Gets the List Price
  this.printListPrice = function(oOfferData) {
    listPriceString = '';

    if (!oOfferData['list_price_raw'] ) { return listPriceString; }

    if ((oOfferData['our_price_raw'] && oOfferData['list_price_raw'] <= oOfferData['our_price_raw']) ||  (oOfferData['sale_price_raw'] && oOfferData['list_price_raw'] <= oOfferData['sale_price_raw'])){
      return listPriceString;
    }

    listPriceString += '<tr><td ' + sValignMiddle + ' class="' + sListPriceBlockLabelClass + '" >' + oStrings['ListPriceLabel'] 
      + ':</td><td class="listprice">' + oOfferData['list_price'];

    if (oOfferData['list_price_with_tax']) {
      listPriceString += ' ' + oStrings['TaxIncluded'];
    }
    listPriceString += '</td></tr>';

    return listPriceString;
  }

  this.printOurPrice = function(oOfferData) {
    var ourPriceString = '';
    var sSSSMessage = '';

    // Display the 'was' price string
    if (oOfferData['was_price_raw'] && oOfferData['was_price']) {
      if(oOfferData['was_price_breaks_map_raw']) {
        ourPriceString += '<tr><td ' + sValignMiddle + 'class="' + sProductLabel + '">'+ oStrings['WasText'] +'</td><td>'
          + oStrings['BreaksMap'] +'</td></tr>';
      } else {
        ourPriceString += '<tr><td ' + sValignMiddle + 'class="' + sProductLabel + '">'+ oStrings['WasText'] +'</td><td>'
          + oOfferData['was_price'] +'</td></tr>';
      }
    }

    if (!oOfferData['our_price_raw']) { return ourPriceString; }

    if (oOfferData['sale_price_raw'] && oOfferData['sale_price_raw'] >= oOfferData['our_price_raw']) { return ourPriceString; }

    var priceLabelName = oStrings['ItemDetailPriceLabel'];
    if(oOfferData['was_price_raw']) { priceLabelName = oStrings['NowText']; }
    if(oOfferData['list_price_with_tax'] && !oOfferData['surcharge']) { priceLabelName = oStrings['OurPrice']; }

    var sOurPriceLabelClass = sProductLabel;

    if(oOfferData['sale_price_raw']){
      sOurPriceLabelClass = sOurPriceBlockLabelClass;
    }

    ourPriceString += '<tr><td class="' + sOurPriceLabelClass + '">' + sBoldPrice + priceLabelName + sBoldPriceClose + '</td>';

    if(oOfferData['sale_price_raw']) {
      ourPriceString += '<td><span class="listprice">' + oOfferData['our_price'] + '</span>'; 
      if(oOfferData['list_price_with_tax']) {
        ourPriceString += ' ' + oStrings['TaxIncluded'];
      }
    } else {
      ourPriceString += '<td>' + sBoldPrice + '<span class="' + sPriceClass + '">' + oOfferData['our_price'];
      if(oOfferData['list_price_with_tax']) {
        ourPriceString += ' ' + oStrings['TaxIncluded'];
      }
      ourPriceString += sBoldPriceClose + '</span>'; 
    }
    if (oOfferData['our_price_ppu']) {
          ourPriceString += ' ' + oOfferData['our_price_ppu'];
    }

    var ssPrefix = '&nbsp;';
    var ssSuffix = '';
    var msgSuffix = '';

    if (oOfferData['price_breaks_map_raw']) {
      ssPrefix = '</tr><tr><td /><td>';
      ssSuffix = '<td/>';
      msgSuffix = '_sa';
    }

    if (oOfferData['prime_shipping']) {
        ourPriceString += '&nbsp;' + oOfferData['prime_shipping'];
    } else {
      if (oOfferData['isFreeShipping']) {
        ourPriceString += '&nbsp;' + oStrings['freeShippingMsg'];
      } else if (oOfferData['fixed_shipping_charge']) {
	ourPriceString += '&nbsp;' + oStrings['fixedShipping'].replace('#charge#', oOfferData['fixed_shipping_charge']);
      } else if (oOfferData['shipping_surcharge']) {
	if (oOfferData['show_prime_shipping_surcharge']) {
	  ourPriceString += '&nbsp;' + oStrings['shippingSurchargePrime'];
	} else {
	  ourPriceString += '&nbsp;' + oStrings['shippingSurcharge'].replace('#charge#', oOfferData['shipping_surcharge']);
	}
      } else if (oOfferData['isEligibleForSuperSaverShipping']) {
        if (oOfferData['isEligibleForSuperSaverShipping'] == 1) {
          ourPriceString += ssPrefix + oStrings['SSSEligible' + msgSuffix] + ssSuffix;
        } else {
          ourPriceString += ssPrefix + oStrings['SSSQualifies' + msgSuffix] + ssSuffix;
        }
      }
    }
    ourPriceString += '</td></tr>';
    return ourPriceString;
  }

  this.printYouSaveRow = function(oOfferData) {
    youSaveString = '';
    if(oOfferData['price_breaks_map_raw']) { return youSaveString; }
//    if(oOfferData['always_show_list_price'] == 0) {
//      if(oOfferData['isListPriceSuppressed']){ 
//        return youSaveString; 
//      }
//    }
    if(oOfferData['you_save_percentage'] && oOfferData['you_save']) {
      youSaveString += '<tr><td ' + sValignMiddle + 'class="' + sListPriceBlockLabelClass + '">' + oStrings['PriceYouSave'] + '</td>'; 
      youSaveString += '<td><span class=price>' + oOfferData['you_save'] 
        + ' (' + oOfferData['you_save_percentage'] + '%)</span></td></tr>'; 
    }
    return youSaveString;
  }

  this.printSpecialOffers = function(oOfferData) {
    var hiddenString = '';
    if (oOfferData['promotions'] == undefined) {
      return '';
    }

    var specialOffersString = '';
    specialOffersString += '<tr><td class="productLabel">' 
      + '<span' + hiddenString + '>' + oStrings['SpecialOffersImage'] + '</span>'
      + '</td><td class="tiny">'
      + '<span' + hiddenString + '>' + oStrings['SpecialOffers'] + '</span'
      + '</td></tr>';
    return specialOffersString;
  }

  this.printSalePrice = function(oOfferData) {
    salePriceString = '';
    if (oOfferData['price_breaks_map_raw']) { return salePriceString; }
    if (oOfferData['sale_price_raw'] && oOfferData['sale_price']) {
      salePriceString = '<tr><td class="' + sProductLabel + '"><span class="price">' + sBoldPrice + oStrings['SalePriceLabel'] 
        + sBoldPriceClose  + '</span></td><td><span class="' + sPriceClass + '">' + sBoldPrice + oOfferData['sale_price'] + sBoldPriceClose + '</span></td></tr>';
      ourPriceString = '<tr><td class="' + sProductLabel + '">' + sBoldPrice + oStrings['ItemDetailPriceLabel'] 
        + sBoldPriceClose +'</td><td class="' + sPriceClass + '">' + sBoldPrice + oOfferData['sale_price'] + sBoldPriceClose +'</td></tr>';

      if (oOfferData['our_price_raw'] && oOfferData['our_price_raw'] <= oOfferData['sale_price_raw']) {
        return ourPriceString;
      }
    }
    return salePriceString;
  }

  this.printAmazonPoints = function(oOfferData) {
    if (oOfferData['amazonPoints'] == undefined) {
      return '';
    }

    var amazonPointsString = '<tr><td class="productLabel">' 
      + '<span>' + oStrings['pointsLabel'] + '</span>'
      + '</td><td class="tiny">'
      + '<span>' + oOfferData['amazonPoints'] + '</span'
      + '</td></tr>';
    return amazonPointsString;
  }
var subscribeTemplate = null;
var subscribeDiv = null;
var bSupportSandS = -1;
this.updateSubscribeFeature= function(oOfferData) {
        if (!bSupportSandS) return;

        if (bSupportSandS == -1) {
          subscribeDiv = document.getElementById('snsPB');
          if (subscribeDiv) {
            bSupportSandS = 1;
          } else {
            bSupportSandS = 0;
            return;
          }
        }
	
        var subDiscnt;
        if (oOfferData) {
          subDiscnt = oOfferData['subscribe_discount'];
        }

	if (subDiscnt==null) {
	 subscribeDiv.innerHTML='';
         return;
        }
	if (subscribeTemplate==null)
		subscribeTemplate=document.getElementById('subscribe_template_div').innerHTML;
	 subscribeDiv.innerHTML=formatString(subscribeTemplate,{
                                      'subscribe_discount':oOfferData['subscribe_discount'],
                                      'discounted_price':oOfferData['discounted_price']
                                });
	//alert('new html='+document.getElementById('subscribe_feature_div').innerHTML);
	}

 
this.printRebateInfo=function (asin,oOfferData)
	{
	var rebateAmount=oOfferData['rebate_amount'];
	var rebateHTML='';
	if (rebateAmount!=null)
	{
		var numRebates=oOfferData['num_rebates'];
		var rebateHTMLTemplate;
		if (numRebates==1)
		{
			rebateHTMLTemplate=rebateHTMLTemplateSingular;
			priceAfterRebateHTMLTemplate=priceAfterRebateHTMLTemplateSingular;
		}
		else
		{
			rebateHTMLTemplate=rebateHTMLTemplatePlural;
			priceAfterRebateHTMLTemplate=priceAfterRebateHTMLTemplatePlural;
		}
		rebateHTML= formatString(rebateHTMLTemplate,{'ASIN_VAR':asin,'REBATE_AMOUNT':rebateAmount})
			+formatString(priceAfterRebateHTMLTemplate,{'PRICE_AFTER_REBATE':oOfferData['price_after_rebate']});
	}	
	return rebateHTML;	
	}
}



// (FILE: /detail-page-features/twister-availability/twister-availability.js) 

var sFastTrackMsgDiv,sFastTrackDivSearched=false,sFastTrackOuterDivSearched=false;
var lastSelectedASIN; var isFTLoading=false;

function TwisterAvailability(parentAvailabilityDivID, 
			     availabilityDivID, 
			     hiddenAvailabilityDivID, 
			     moreBuyingChoicesDivID, 
			     scarcityDivID,oAvailabilityStrings, 
			     holidayTimeFrame, 
			     parentASIN, 
			     sessionID) {

  var sParentAvailabilityDivID = parentAvailabilityDivID;
  var sAvailabilityDivID = availabilityDivID;
  var sHiddenAvailabilityDivID = hiddenAvailabilityDivID;
  var sMoreBuyingChoicesDivID = moreBuyingChoicesDivID;
  var sScarcityDivID = scarcityDivID;
  var oStrings = oAvailabilityStrings;
  var bHolidayTimeFrame = holidayTimeFrame;
  var sParentASIN = parentASIN;
  var sSessionID = sessionID; 
  var oAvailabilityHTMLCache = new Array();
  var oMoreBuyingChoicesHTMLCache = new Array();
  var sCurrentASIN = '';
//  var sCurrentSelectedASIN;

  var sEnableLargeBR = gbEnableLarge ? '<br />' : '';

  this.getChildSelectionURLParam = function() {
    if (sCurrentASIN && sCurrentASIN != '')
      return 'childASIN=' + sCurrentASIN;
    else
      return null;
  } 

  // FMA seller messages state
  var oFmaMessageDiv;
  this.isFmaMessageLoading = false;

  this.setInitialASIN = function(asin) {
    if (!lastSelectedASIN) {
      lastSelectedASIN = asin;
    }
  }

  this.update = function(sASIN, oOfferData,onlyUnqualifiedOffers) {
    if (sASIN == sCurrentASIN) {
      return;
    }
    sCurrentASIN = sASIN;
    if (sASIN == null) {
      this.clear();
      return;
    }

    if (oAvailabilityHTMLCache[sASIN] == null) {
      oAvailabilityHTMLCache[sASIN] = this.printAvailability(oOfferData,onlyUnqualifiedOffers);
    }

    if (oMoreBuyingChoicesHTMLCache[sASIN] == null) {
      oMoreBuyingChoicesHTMLCache[sASIN] = this.printMoreBuyingChoices(oOfferData);
    }

    document.getElementById(sAvailabilityDivID).innerHTML = oAvailabilityHTMLCache[sASIN];
    document.getElementById(sMoreBuyingChoicesDivID).innerHTML = oMoreBuyingChoicesHTMLCache[sASIN];
    document.getElementById(sScarcityDivID).innerHTML = this.printScarcityMsg(oOfferData);

    // resize parent div if child div is bigger
    var cAvailBlock = document.getElementById(sAvailabilityDivID);
    var pAvailBlock = document.getElementById(sParentAvailabilityDivID);
    var hAvailBlock = document.getElementById(sHiddenAvailabilityDivID);
    if (cAvailBlock.offsetHeight > hAvailBlock.offsetHeight) {
      hAvailBlock.style.height = cAvailBlock.offsetHeight;
    }
    cAvailBlock.style.visibility = 'visible';
    pAvailBlock.style.visibility = 'hidden';

    this.handleShippingContainerMessaging(sCurrentASIN, oOfferData);
  }

  this.clear = function() {
    document.getElementById(sAvailabilityDivID).innerHTML = document.getElementById(sParentAvailabilityDivID).innerHTML;
    document.getElementById(sMoreBuyingChoicesDivID).innerHTML = '';
    document.getElementById(sScarcityDivID).innerHTML = '';
    this.onPreviewEvent();
  }

  this.printAvailability = function(oOfferData,onlyUnqualifiedOffers) {
    availString = '';
    if (onlyUnqualifiedOffers || !oOfferData['avail_message'] || !oOfferData['availabilityCondition']) {
      return availString;
    }
    merchantID = oOfferData['merchantID'];
    merchantName = oOfferData['merchantName'];
    if(!gbEnableLarge){
      availString += '<b>' + oStrings['availability'] + '</b> ';
    }
    availString += oOfferData['avail_message'] + sEnableLargeBR;
    if (gbShowProdAvailChart) {
      availString += ' ' + oStrings['see'] + ' <a href="/gp/product/product-availability/' + sParentASIN + '/ref=dp_availability_1/' + sSessionID + '?%5Fencoding=UTF8&m=' + merchantID +'" onClick="return amz_js_PopWin('+"'"+'/gp/product/product-availability/' 
        + sParentASIN + '/ref=dp_availability_1/' + sSessionID + '?%5Fencoding=UTF8&m=' + merchantID 
        + "','AmazonHelp','width=570,height=600,resizable=1,scrollbars=1,toolbar=0,status=1');"+'"'+' >' + oStrings['price_and_avail'] + sEnableLargeBR;       }

    if ( oOfferData['isSSOF'] ) {
          availString += ' ' + goTwisterBuyboxStrings['soldShipByAmazon'].replace("defaultMerchant", '<a href="/gp/help/seller/at-a-glance.html/' + sSessionID + '?%5Fencoding=UTF8&seller=' + merchantID + '">' + merchantName + '</a>');
         // availString += ' ' + 'Sold by' + ' <a href="/gp/help/seller/at-a-glance.html/' + sSessionID + '?%5Fencoding=UTF8&seller=' + merchantID + '">' + merchantName + '</a> and ships from Amazon Fulfillment.';
    } else {
         availString += ' ' + oStrings['ships_from'] + ' <a href="/gp/help/seller/at-a-glance.html/' + sSessionID + '?%5Fencoding=UTF8&seller=' + merchantID + '">' + merchantName + '</a>.';
    }

   if (bHolidayTimeFrame && (merchantName != 'Amazon.com')) {
      availString += ' Want it by Dec. 22? View this seller'+'"'+'s <a href="/gp/help/seller/shipping.html/' + sSessionID + '?ie=UTF8&seller=' + merchantID + '">shipping details</a>.';
    }
    if (oOfferData['giftWrapMessage']) {
     availString += oOfferData['giftWrapMessage'];
    }

     if (oOfferData['shipByMessage']) {
     availString += ' ' + oOfferData['shipByMessage'];
    }

     return availString;
  }

  this.printMoreBuyingChoices = function(oOfferData) {
    var sHTML = '';
    var nAvailCond = oOfferData['availabilityCondition'];
    var nUsedAndNew = oOfferData['usedAndNewCount'];

    if ((nAvailCond && nUsedAndNew <= 1) || 
        (!nAvailCond && nUsedAndNew <= 0)) {
       return sHTML;
    }

    var sPrice = oOfferData['usedAndNewLowestPrice'];
    if (sPrice) {
      sHTML += '<b><a href="/gp/offer-listing/' + oOfferData['ASIN'] + '/' + sSessionID + '">';
      sHTML += ( nAvailCond ) ? ((nUsedAndNew-1) + ' ') : ((nUsedAndNew) + ' ');
      sHTML += (nUsedAndNew >= 3) ? oStrings['more_buying_choices'] : oStrings['more_buying_choice'];
      sHTML += '</a>';
      if (!oOfferData['usedAndNewLowestPriceBreaksMAP']) { 
        sHTML += ' ';
        sHTML += (nUsedAndNew >= 3) ? oStrings['from'] : oStrings['at'];
        sHTML += ' ' + '<span class="price">' + sPrice + '</span>';
      }
      sHTML += '</b>';
    }

    return sHTML;
  }

  this.printScarcityMsg= function(oOfferData) {
    if (oOfferData['scarcityMsg']) {
      return oOfferData['scarcityMsg'];
    }
    return '';
  }
 
  this.onSelectEvent=function (currentSelectedASIN,offerDataNewASIN)
  {	
    initializeFma();

    //console.log('last sel in select='+lastSelectedASIN);
    if (lastSelectedASIN!=null && lastSelectedASIN != currentSelectedASIN)
    {//this indicates a new selection has been made and content will be fetched for fast track
      fadeFastTrack();
      isFTLoading=true;
      
      this.fadeFmaMessage();
      this.isFmaMessageLoading = true;
    }
    else
    {//this indicates this is the first time load, or an item was deselected, or fast track has already been updated
      isFTLoading=false;
      fadeFastTrack(false);
      
      this.isFmaMessageLoading = false;
      this.fadeFmaMessage(false);
    }
    lastSelectedASIN=currentSelectedASIN;
    // //console.log('select currentSelectedASIN='+currentSelectedASIN);	  
    var ftTimerDiv=document.getElementById("fast-track_feature_div");
    if (ftTimerDiv && ftTimerDiv.style)
    {
      if (currentSelectedASIN==null)
 	ftTimerDiv.style.display='none';
      else	
	ftTimerDiv.style.display='block';
    }
    
    if (oFmaMessageDiv) {
      if (currentSelectedASIN == null) {
	oFmaMessageDiv.style.display = 'none';
      } else {
	oFmaMessageDiv.style.display = 'block';
      }
    }

    this.handleShippingContainerMessaging(currentSelectedASIN,offerDataNewASIN);	
  }

 this.onPreviewEvent =function (currentSelectedASIN,offerDataNewASIN,anyVariationsSelected)
 {	//console.log('preview currentSelectedASIN='+currentSelectedASIN+' anyVariationsSelected  ='+anyVariationsSelected);	
   this.handleFastTrackMessaging(currentSelectedASIN,anyVariationsSelected);
   this.handleShippingContainerMessaging(currentSelectedASIN,offerDataNewASIN);
	
   initializeFma();
   this.fadeFmaMessage(lastSelectedASIN != currentSelectedASIN);
 }
 
 this.handleFastTrackMessaging =function (currentSelectedASIN,anyVariationsSelected)
 { 	
	
	if (!sFastTrackDivSearched)
	{
		setFastTrackDivHandle();
	 }
	if (sFastTrackMsgDiv==null || lastSelectedASIN==null || (!anyVariationsSelected && currentSelectedASIN==null))
	{
 		return;	 
	}	
	
	//console.log ('fade check :'+lastSelectedASIN+' vs '+currentSelectedASIN);
	var hoverOtherAsin=(lastSelectedASIN!=currentSelectedASIN);

	if (sFastTrackMsgDiv.style){  
			 fadeFastTrack(hoverOtherAsin);		
			}

 }
 var shippingMsgDivsSearched=false;
 var shippingCanWrapMsgDiv, shippingNoWrapMsgDiv;
 var lastShippingStat;

  this.handleShippingContainerMessaging = function(asin, offerData) {
    if (!shippingMsgDivsSearched) {
      shippingCanWrapMsgDiv = document.getElementById('overwrapContainerMsgDiv');
      shippingNoWrapMsgDiv = document.getElementById('noOverwrapContainerMsgDiv');
      shippingMsgDivsSearched = true;
    }
    if (shippingCanWrapMsgDiv == null) 
      return;

    if (asin == null || offerData == null) {
      shippingCanWrapMsgDiv.style.display = 'none';	
      shippingNoWrapMsgDiv.style.display = 'none';
      lastShippingStat = null;
      return;
    }

    var shippingStat = offerData['shipping_status'];
    if (shippingStat == lastShippingStat) {
      //do nothing
    } else if (shippingStat != null) {
      if  (shippingStat == WRAP_CONTAINER_STATUS) {
	shippingCanWrapMsgDiv.style.display = 'block';
	shippingNoWrapMsgDiv.style.display = 'none';	
      } else if (shippingStat == NO_WRAP_CONTAINER_STATUS) {
	shippingNoWrapMsgDiv.style.display = 'block';	
     	shippingCanWrapMsgDiv.style.display = 'none';		
      } else {
	shippingNoWrapMsgDiv.style.display = 'none';	
     	shippingCanWrapMsgDiv.style.display = 'none';		
      }
    } else {
      shippingCanWrapMsgDiv.style.display = 'none';	
      shippingNoWrapMsgDiv.style.display = 'none';	
    }
    lastShippingStat = shippingStat;
  }


  // Helper functions for the fma-seller-messages feature
  this.fadeFmaMessage = function(val) {
    if (this.isFmaMessageLoading) {
      return;
    } else if (oFmaMessageDiv) {
      if (val == null || val == true) {
        fadeDiv(oFmaMessageDiv, 25);
      } else {
        unfadeDiv(oFmaMessageDiv);
      }
    }
  }
  
  var initializeFma = function() {
    if (!oFmaMessageDiv) {
      oFmaMessageDiv = document.getElementById("fma-seller-messages_feature_div");
      if (oFmaMessageDiv) {
        oFmaMessageDiv.style.width = "100%";
      }
    }
  }  
}

 function setFastTrackDivHandle()
 {
	 sFastTrackMsgDiv=document.getElementById("fast-track_feature_div");
	 sFastTrackMsgDiv.style.width="100%"; //needed else opacity chanage doesn't work on IE
	 sFastTrackDivSearched=true;
 }
 
 function fadeFastTrack(val)
 {
 	if (isFTLoading)
 		return;
 	if (sFastTrackMsgDiv)
 	{
 		if (val==null || val==true)
 		{
 			//console.log('fading fast track');
 			fadeDiv(sFastTrackMsgDiv,25);
 			}
 		else if (val==false)
 		{
 			//console.log('unfading fast track');
 			unfadeDiv(sFastTrackMsgDiv);
 		}
 			
 	}
 }

  var secondsLeft=new Object();
  var secondsLeftUpdateTime=new Object();
  function onAjaxUpdate_fast_track(asin,initialLoad)
	{ 		
	var timerDiv=document.getElementById("ftMessageTimer");
	var cuttOffElems=document.getElementsByName("promise-cutoff-time."+asin);
	if (!initialLoad)
		lastSelectedASIN=asin;	
	if (cuttOffElems==null || cuttOffElems.length==0)
		return;	

        FT_CurrentDisplayMin = -1;
	if (timerDiv && timerDiv.style)
	{
		timerDiv.style.display='inline';		
		if (initialLoad==null || initialLoad==false)
			{
			timerDiv.style.margin='3px';
			}
	}
	 var cutOffTimeVal=cuttOffElems[0].value;
	var cutOffTime=parseInt(cutOffTimeVal);
	var currSecs=new Date().getTime()/1000;
	var secsLeft=(cutOffTime-currSecs);//countDn;
	secondsLeft[asin]=secsLeft;
        FT_getCountdown(secsLeft);
	secondsLeftUpdateTime[asin]=currSecs;	
	isFTLoading=false;
	fadeFastTrack(false);
	}
  function onCacheUpdate_fast_track(asin)	
	{	
	var timerDiv=document.getElementById("ftMessageTimer");
	if (timerDiv && timerDiv.style)	
	{
		timerDiv.style.display='inline';		
		timerDiv.style.margin='3px';
	}

        FT_CurrentDisplayMin = -1;
	var lastUpdTimeSecs=secondsLeftUpdateTime[asin];
	var elapsedTimeSecs=new Date().getSeconds()-lastUpdTimeSecs;
	var newSecondsLeft=secondsLeft[asin]-elapsedTimeSecs;	
	lastSelectedASIN=asin;
	isFTLoading=false;
	fadeFastTrack(false);
	}



function onAjaxUpdate_fma_seller_messages(asin, initialLoad) {
  goTwisterAvailability.isFmaMessageLoading = false;
  goTwisterAvailability.fadeFmaMessage(false);
}

function onCacheUpdate_fma_seller_messages(asin) {
  goTwisterAvailability.isFmaMessageLoading = false;
  goTwisterAvailability.fadeFmaMessage(false);
}

