function Shoveler(shovelerName, refTag, shvlAsins, allAsins, backendHandler, shvlBatchSize, images, minNumCell, maxNumCell, maxPages, cellWidth, buttonWidth) {
this.id = Shoveler.Instances.length;
Shoveler.Instances[this.id] = this;
this.name = shovelerName;
this.refTag = refTag;
this.tagAsins = Array();
this.curLevel = 0;    
this.asins = Array();    
this.delayTime = 75;
this.count = 0;
this.requests = 0;
this.timer;
this.maxLevel;
this.newPx;
this.backendHandler = backendHandler;
this.backendBatchSize = shvlBatchSize;
this.asinList = shvlAsins;
this.allAsins = allAsins;
this.minNumCell = minNumCell;
this.maxNumCell = maxNumCell;
this.maxPages = maxPages;
this.cellWidth = cellWidth+10;
this.buttonWidth = buttonWidth;
this.buyBoxIntersect = 0;    
this.buyBoxWidth = 0;
this.oldMaxCell = this.maxNumCell;
this.qaAjaxCount = 0;
this.defaultImage = new Image();
this.defaultImage.src = images[0];
this.imgGradClick = new Image();
this.imgGradClick.src = images[1];
this.loadingImage = new Image();
this.loadingImage.src = images[2];
}
if (typeof Shoveler.Instances == 'undefined') {
Shoveler.Instances = new Array();
}
if (typeof shvlAsinCache == 'undefined') {
shvlAsinCache = new Array();
aShvlContent = new Array();
}
Shoveler.prototype.buyBoxDetect = function () {
var buyBox = goN2U.getElement('wishlist_btn_div_js');
var padding = 80;
if (!buyBox) {
buyBox = goN2U.getElement('SDPBlock');
padding = 90;
}
var topPos = goN2U.getPageElementTop(buyBox);
topPos = topPos + padding; 
var shvlWidget = goN2U.getElement(this.name+'ShvlPage');
shvlWidget.style.display = "";
var shvlTopPos = goN2U.getPageElementTop(goN2U.getElement(this.name+'Anchor'));
if (topPos >= shvlTopPos) {
this.buyBoxIntersect = 1;
} else {
this.buyBoxIntersect = 0;
}
if (!this.buyBoxWidth) {
var buyBoxDiv = goN2U.getElement('buyboxDivId');
this.buyBoxWidth = buyBoxDiv ? goN2U.getElementWidth(buyBoxDiv) : 300;
}
}
Shoveler.prototype.adjustWindowWidth = function () {
var width = goN2U.getInsideWindowWidth();
if (this.buyBoxIntersect == 1) {
width = width - (this.buyBoxWidth + this.buttonWidth);
this.newPx = width;
goN2U.getElement(this.name+"Shvl").style.width = width;
if (width > 500) { goN2U.getElement(this.name+"ShvlPage").style.width = width; } else { goN2U.getElement(this.name+"ShvlPage").style.width=500; }
goN2U.getElement(this.name+"ShvlLoad").style.width = width;
goN2U.getElement(this.name+"BuyBoxClear").style.clear = "left";
goN2U.undisplay(this.name+"Anchor");
} else {
goN2U.getElement(this.name+"Shvl").style.width = '';
goN2U.getElement(this.name+"ShvlPage").style.width = '';
goN2U.getElement(this.name+"ShvlLoad").style.width = '';
}
if (width < this.cellWidth * this.minNumCell + 2 * this.buttonWidth) {
this.maxCell = this.minNumCell;
} else {
var newMaxCell = parseInt((width - (2*this.buttonWidth)) / this.cellWidth);
if (newMaxCell > this.maxNumCell) {
this.maxCell = this.maxNumCell;
} else {
this.maxCell = newMaxCell;
}
}
}
Shoveler.prototype.setAsins = function(asins, resetLevel) {
this.asins = Array();
this.asinList = asins;
var level = 0;
this.count = this.allAsins.length;
if (goN2U.getElement(this.name + "Shvl")) {
if (this.allAsins.length == 0 && this.requests == 0) {
goN2U.undisplay(this.name + "ShvlLoad");
goN2U.getElement(this.name + "ShvlNoData").style.display = "";
goN2U.undisplay(this.name + "Shvl");
}
else if (!goN2U.isDisplayed(this.name + "shvlNJS")) {
goN2U.getElement(this.name + "ShvlLoad").style.display = "";
goN2U.undisplay(this.name + "ShvlNoData");
goN2U.undisplay(this.name + "Shvl");
}
if (this.allAsins.length <= this.maxCell) {
goN2U.undisplay(this.name + "ShvlButtonPrev");
goN2U.undisplay(this.name + "ShvlButtonNext");
}
else {
goN2U.getElement(this.name + "ShvlButtonPrev").style.display = "";
goN2U.getElement(this.name + "ShvlButtonNext").style.display = "";
}
}
for(var i = 0; i < this.allAsins.length; i++) {
if (i % this.maxCell == 0) { 
this.asins[level] = Array();
this.maxLevel = level;
}
this.asins[level][i % this.maxCell] = this.allAsins[i];
if (i % this.maxCell == this.maxCell - 1) { level++; }
}
if (resetLevel == 1) {
this.curLevel = 0;
} else if (resetLevel == 2) {
this.curLevel = parseInt (this.oldMaxCell * this.curLevel / this.maxCell);
}
for(var j=0;j<this.maxPages;j++) {
if (j > this.maxLevel) {
this.setPageHTML(j,"clear");
}
else if (j != this.curLevel) {
this.setPageHTML(j,"off");
}
else {
this.setPageHTML(j,"on");
}
}
var blank = goN2U.getElement(this.name+"Blank");
if (blank) {
if (this.maxLevel == 0) {
blank.style.display = "";
this.setPageHTML(0,"clear");
} else {
blank.style.display = "none";
}
}
}
Shoveler.prototype.setPageHTML  = function(level,state) {
var page = goN2U.getElement(this.name + "Page" + (level+1));
if (page) {
if (state == "clear") {
page.style.display = "none";
}
else if (state == "on") {
page.style.display = "";
this.changePage(level + 1) 
}
else {
page.style.display = "";
}
}
}
Shoveler.prototype.updateCell = function(asin,cell)  {
var cellLink = goN2U.getElement(this.name + "ShvlLink" + cell);
var cellTitle = goN2U.getElement(this.name + "ShvlTitle" + cell);
var cellImage = goN2U.getElement(this.name + "ShvlImg" + cell);
var cellRatings = goN2U.getElement(this.name + "ShvlRatings" + cell);
var cellPrice = goN2U.getElement(this.name + "ShvlPrice" + cell);
var asinObj = shvlAsinCache[asin];
var newLink = '';
var newLinkName = '';
var newTitle = '';
var newImageSrc = asin ? this.loadingImage.src : this.defaultImage.src;
var newRatings = '';
var newPrice = '';
var newLongTitle = '';
if (goN2U.isSafari()) {
newTitle = '<a style="text-decoration:none;" href="javascript:return false;">';
for (var i=0; i<5;i++) {
for (var j=0; j<180; j++) {
newTitle += '&nbsp;';
}
newTitle += ' ';
}
newTitle += '</a>';
}
var pos = this.curLevel*this.maxCell + cell + 1;
if (asinObj) {
newLink = asinObj.link;
newLinkName = asinObj.linkName;
newTitle = asinObj.title;
newImageSrc = asinObj.img ? asinObj.img.src : this.loadingImage.src;
newRatings = asinObj.ratingsHTML;
newPrice = asinObj.price;
newLongTitle = asinObj.longTitle;
var origRefTag = asinObj.refTag;
newLink = newLink.replace(origRefTag,this.refTag);
newTitle = newTitle.replace(origRefTag,this.refTag);
newPrice = newPrice.replace(origRefTag,this.refTag);
}
if (cellLink) {
cellLink.href = newLink.replace(/\/ref=([\w_]+)\//,"/ref=$1"+"_"+pos+"/");
cellLink.name = newLinkName;
}
if (cellTitle) {
cellTitle.innerHTML = newTitle.replace(/\/ref=([\w_]+)\//,"/ref=$1"+"_"+pos+"/");
while (newLongTitle.indexOf('&#39;') >= 0) {
newLongTitle = newLongTitle.replace(/&#39;/,"'");        
}
cellTitle.title = newLongTitle;
if (goN2U.isSafari()) {
if (asinObj) {
cellTitle.style.cursor = "";
} else {
cellTitle.style.cursor = "default";
}
}
}
if (cellImage) {
cellImage.src = newImageSrc;
if (cellImage.src == this.defaultImage.src) {
cellImage.style.display = "none";
if (goN2U.isSafari()) {
cellImage.style.display = "";
cellLink.href="javascript:return false;";
cellLink.style.cursor="default";
}
} else {
cellImage.style.display = "";
if (goN2U.isSafari()) {
cellLink.style.cursor="";
}
}
}
if (cellRatings) {
if (newRatings == '') {
if (!(goN2U.isSafari())) {
cellRatings.style.display = "none";
}
} else {
cellRatings.style.display = "";
}
cellRatings.innerHTML = newRatings; 
}
if (cellPrice) {
cellPrice.innerHTML = newPrice.replace(/\/ref=([\w_]+)\//,"/ref=$1"+"_"+pos+"/");
if (goN2U.isSafari()) {
cellPrice.innerHTML += '<br/><a style="text-decoration:none;" href="javascript: return false;">&nbsp;</a>';
}
}
}
Shoveler.prototype.nextItems = function() {
this.curCell = this.maxCell - 1;
var lastLevel = this.curLevel;
if (this.asins[this.curLevel+1]) { this.curLevel = this.curLevel+1; }
else { this.curLevel = 0; }
this.setPageHTML(lastLevel,"off");
this.setPageHTML(this.curLevel,"on");
if (this.nexttimer) clearInterval(this.nexttimer);
this.nexttimer = setInterval('Shoveler.Instances['+this.id+'].animateNext()', this.delayTime);
}
Shoveler.prototype.prevItems = function() {
this.curCell = 0;
var lastLevel = this.curLevel;
if (this.asins[this.curLevel-1]) { this.curLevel = this.curLevel -1; }   
else { this.curLevel = this.maxLevel; }   
this.setPageHTML(lastLevel,"off");
this.setPageHTML(this.curLevel,"on");
if (this.nexttimer) clearInterval(this.nexttimer);
this.nexttimer = setInterval('Shoveler.Instances['+this.id+'].animatePrev()', this.delayTime);
}
Shoveler.prototype.togglePage = function(level) {
this.setPageHTML(this.curLevel,"off");
this.setPageHTML(level-1,"on");
this.curLevel = level-1;
var totalUncached = this.getUncachedAsinsNumber (this.allAsins);
if (totalUncached > 0) {
this.preloadShvlLoader(this.allAsins);
}
this.changePage(level);
this.curCell = this.maxCell - 1;
if (this.pagetimer) clearInterval(this.pagetimer);
this.pagetimer = setInterval('Shoveler.Instances['+this.id+'].animatePage()', this.delayTime);
}   
Shoveler.prototype.changePage = function(level) {
var name = this.name + "Page" + level; 
for(var n = 1; n <= this.maxPages; n++) {
if (name == this.name + "Page" + n) {
goN2U.getElement(name).className = 'active';
}
else {
goN2U.getElement(this.name + "Page" + n).className = '';
}
}
}
Shoveler.prototype.animatePage = function() {
if (this.curCell == -1) {
clearInterval(this.pagetimer);
this.curCell = this.maxCell - 1;
}
else {
var nextAsin = this.asins[this.curLevel][this.curCell];
this.updateCell(nextAsin,this.curCell);
this.curCell = this.curCell - 1;
}
}
Shoveler.prototype.animateNext = function() {
if (this.curCell == -1) {
clearInterval(this.nexttimer);
this.curCell = this.maxCell - 1;
}
else {
var nextAsin = this.asins[this.curLevel][this.curCell];
this.updateCell(nextAsin,this.curCell);
this.curCell = this.curCell - 1;
}
}
Shoveler.prototype.animatePrev = function() {
if (this.curCell == this.maxCell) {
clearInterval(this.nexttimer);
this.curCell = 0;
}
else {
var nextAsin = this.asins[this.curLevel][this.curCell];
this.updateCell(nextAsin,this.curCell);
this.curCell = this.curCell + 1;
}
}
Shoveler.prototype.loadShovelerContent = function(resetLevel) {
clearInterval(this.timer);
this.setAsins (this.asinList, resetLevel);
for(var k = 0; k < this.maxCell; k++) {
if (this.asins[this.curLevel]) {
var asin = this.asins[this.curLevel][k];
this.updateCell(asin,k);
}
}
goN2U.getElement(this.name + "Shvl").style.display = "";
goN2U.getElement(this.name + "ShvlLoad").style.display = "none";
goN2U.getElement(this.name + "ShvlNoData").style.display = "none";
goN2U.undisplay(this.name + "shvlNJS");
}
Shoveler.prototype.shovelResize = function() {
this.preloadShvlLoader (this.asinList);
if (this.maxCell) { this.oldMaxCell = this.maxCell; }
this.adjustWindowWidth();
this.curCell = this.maxCell - 1;
if (this.maxCell > this.oldMaxCell) {
for(var l = this.oldMaxCell; l < this.maxCell; l++) {
if (goN2U.getElement(this.name + "ShvlCell" + l)) {
goN2U.getElement(this.name + "ShvlCell" + l).style.display = "";
}
} 
} else if (this.maxCell < this.oldMaxCell) {
for(var l = this.oldMaxCell-1; l > this.maxCell-1; l--) {
if (goN2U.getElement(this.name + "ShvlCell" + l)) {
goN2U.undisplay(this.name + "ShvlCell" + l);
}
} 
}
if (goN2U.getElement(this.name+"ShvlPage")) {
goN2U.getElement(this.name+"ShvlPage").style.display = "";
}
this.loadShovelerContent(2);
}
Shoveler.prototype.preloadShvlLoader = function(asinList) {
var shvlLoader = new N2DynUpObject();
var tmpShvl = this;
shvlLoader.onRequestSuccess = function (aHTML,aJSFunctions,nStatus,sRequestID) {
tmpShvl.requests--;
for(var i = 0; i < aHTML.length; i++) {
try { eval(aJSFunctions[i]); } 
catch(e) {} 
}
tmpShvl.asinList = asinList;
tmpShvl.loadShovelerContent(0);
tmpShvl.shvlOnDemandLoadCallback('success');
}
shvlLoader.onRequestFailure = function (sMessage,nStatus,sRequestID) {
tmpShvl.requests--;
if (this.count == 0 && this.requests == 0) {
tmpShvl.loadShovelerContent(0);
}                
tmpShvl.shvlOnDemandLoadCallback('fail');
}
shvlLoader.setHandler(this.backendHandler,'xd');
shvlLoader.cacheResponses(false);
shvlLoader.setLoadingMessage("Loading ...");
var oParams = {};
var reqCount = 0;
var batchSize = 0;
var batchArray = new Array();
var hasUpdated = 0;
for(var index in asinList) {
var re = /function/;
if (re.test(asinList[index])) { continue; }
var asinObj = shvlAsinCache[asinList[index]];
if (!asinObj) {
if (batchSize == 0) {
batchArray[batchSize] = asinList[index];
batchSize++;
hasUpdated = 0;
} else {
batchArray[batchSize] = asinList[index];
batchSize++;
hasUpdated = 0;
}
if (batchSize == this.backendBatchSize) {
batchArray[batchSize] = this.refTag;
var batchString = batchArray.join(",");
shvlLoader.requestUpdate ("shvlLoad",batchString,"a",oParams);
batchSize = 0;
batchArray = new Array();
reqCount++;
this.qaAjaxCount++;
hasUpdated = 1;
}
}
}
if ((hasUpdated == 0) && (batchSize != 0)) {
batchArray[batchSize] = this.refTag;
var batchString = batchArray.join(",");
shvlLoader.requestUpdate ("shvlLoad",batchString,"a",oParams);
reqCount++;
this.qaAjaxCount++;
}
this.requests = reqCount;
}
Shoveler.prototype.pageDown = function(id) {
goN2U.getElement(id).style.backgroundColor = '#c60';
goN2U.getElement(id).style.color = '#fff';
goN2U.getElement(id).style.backgroundImage = 'url('+this.imgGradClick.src+')';
goN2U.getElement(id).style.backgroundPosition = 'bottom';
}   
Shoveler.prototype.pageUp = function(id) {
goN2U.getElement(id).blur();
goN2U.getElement(id).style.backgroundColor = '';
goN2U.getElement(id).style.color = '';
goN2U.getElement(id).style.backgroundImage = '';
goN2U.getElement(id).style.backgroundPosition = 'top';
}   
Shoveler.prototype.leftShovelButtonDown = function(e) {
goN2U.getElement(this.name + 'ShvlButtonPrev').getElementsByTagName('a')[0].className = 'down';
}   
Shoveler.prototype.rightShovelButtonDown = function(e) {
goN2U.getElement(this.name + 'ShvlButtonNext').getElementsByTagName('a')[0].className = 'down';
}   
Shoveler.prototype.leftShovelButtonUp = function(e) {
goN2U.getElement(this.name + 'ShvlButtonPrev').getElementsByTagName('a')[0].className = '';
this.asinList = this.allAsins;
var totalUncached = this.getUncachedAsinsNumber (this.allAsins);
if (totalUncached > 0) {
this.preloadShvlLoader(this.allAsins);
}
this.prevItems();
}   
Shoveler.prototype.rightShovelButtonUp = function(e) {
goN2U.getElement(this.name + 'ShvlButtonNext').getElementsByTagName('a')[0].className = '';
this.asinList = this.allAsins;
var totalUncached = this.getUncachedAsinsNumber (this.allAsins);
if (totalUncached > 0) {
this.preloadShvlLoader(this.allAsins);
}
this.nextItems();
}   
Shoveler.prototype.getUncachedAsinsNumber = function (asinList) {
var totalUncached = 0;
for(var a in asinList) {
var asinObj = shvlAsinCache[asinList[a]];
if (!asinObj) {
totalUncached += 1;
}
}
return (totalUncached);
}
Shoveler.prototype.shvlOnDemandLoadCallback = function () {} // No arg needed
function shvlCacheLoad (link, linkName, asin, title, imgSrc, imgId, ratingsHTML, price, longTitle, refTag) {
var asinObj = new Object();
asinObj.link = link;
asinObj.linkName = linkName;
asinObj.title = title;
var img = new Image();
img.src = imgSrc;
img.id = imgId;
asinObj.img = img;
asinObj.ratingsHTML = ratingsHTML;
asinObj.price = price;
asinObj.longTitle = longTitle;
asinObj.refTag = refTag;
shvlAsinCache[asin] = asinObj;
}

