function Shoptivate(endfn) {
  var imgstem='';
  var detailMode = false;
  var divwd=ShSettings.lbItemWidth;
  var areawd=0, areaht=0, shdheight=0, shdwidth=0;
  var o=DOMhelp.createElement;
  var shdetail=o('div#shdetail');
  var shdettitle=o('div#shdettitle', o('div#shclose', {onclick: endDetailMode}));
  var shcartmsg=o('div#shcartmsg');
  var helpimg=o('div#helpimg');
  var carthldr=o('div');
  var cartstatus=o('div#cartstat');
  var scripthldr=o('div');
  var lbox=new Listbox();
  var schobj=new ShSearch(lbox, scripthldr);
  var skuCartURL='';
  var wishURL='';
  var disp_sku='';
  var received_details=false;
  var secret=0;
  var dbid=0;
  var shcartfade= new YAHOO.util.Anim(shcartmsg, {opacity: {from: 1, to: 0}}, 2, YAHOO.util.Easing.easeIn);
  shcartfade.onComplete.subscribe(function() {shcartmsg.style.display='none';});
  var cartstatusfade= new YAHOO.util.Anim(cartstatus, {opacity: {from: 0, to: 1}}, 2, YAHOO.util.Easing.easeIn);

  function detailScroll(e) {
      if (e.detail && e.stopPropagation)
        if ((e.detail<0 && shdetail.scrollTop>0) ||
            (e.detail>0 && shdetail.scrollTop+shdetail.offsetHeight<shdetail.scrollHeight+2))
          e.stopPropagation();
  //  var newTop=shdetail.scrollTop+((e.detail && e.detail<0) ? -40 : 40);
  //  newTop=Math.min(newTop, shdetail.scrollHeight+2-shdetail.offsetHeight);
  //  shdetail.scrollTop=Math.max(newTop,0);
  }
  function detailScrollIE() {
    if (window.event && window.event.wheelDelta && shdetail.doScroll)
      shdetail.doScroll(window.event.wheelDelta<0 ? "scrollbarDown" : "scrollbarUp");
  } 
  if (shdetail.addEventListener)
    shdetail.addEventListener("DOMMouseScroll", detailScroll, false);
  else
    shdetail.onmousewheel=detailScrollIE;

  function dismissWaiting(popmsg, statdom) {
    shcartmsg.style.left=(areawd/2-150)+"px";
    shcartmsg.style.top=(areaht/2-26)+"px";
    DOMhelp.replaceContent(shcartmsg, o('div', popmsg));
    if (shcartfade.isAnimated()) {
      shcartfade.stop();
    }
    YAHOO.util.Dom.setStyle(shcartmsg, 'opacity', 1);
    shcartmsg.style.display='block';

    shcartfade.animate();
    YAHOO.util.Dom.setStyle(cartstatus, 'opacity', 0);
    if (statdom) {
      DOMhelp.replaceContent(cartstatus, statdom);
    }
    cartstatus.style.display='block';
    cartstatusfade.animate();
    carthldr.innerHTML="";
  }
  function waitingPopup(s) {
    cartstatus.style.display='none';
    DOMhelp.replaceContent(shcartmsg, o('div', o('img.shwait', {'src':'/images/waiting.gif'}), s));
    shcartmsg.style.left=(areawd/2-150)+"px";
    shcartmsg.style.top=(areaht/2-26)+"px";
    YAHOO.util.Dom.setStyle(shcartmsg, 'opacity', 1);
    shcartmsg.style.display='block';
  }
  window.wishlist_success=function(k) {
    if (k==secret) {
      dismissWaiting('Item added to wishlist.',
        ['Item added - ', o('a', {'href':ShSettings.wishURL()}, 'View wishlist')]);
    }
  };
  window.wishlist_failure=function(k) {
    if (k==secret) {
      dismissWaiting('Add to wishlist failed.',
        ['Add to wishlist failed - ', o('a', {'href':ShSettings.wishURL()}, 'View wishlist')]);
    }
  };
  window.wishlist_nologin=function(k) {
    if (k==secret) {
      dismissWaiting('Not logged in.',
        ['Please ', o('a', {'href':ShSettings.wishURL()}, 'login'), ' to use the wishlist.']);
    }
  };
  window.product_detail=function(sku, data) {
    if (sku==disp_sku && detailMode) {
      received_details=true;
      var image = data[4] ? o('img.shdprim', {'src':unstem(data[4]), 'width':data[5], 'height':data[6]}) : [];
      DOMhelp.replaceContent(shdetail,
        o('div.prodcont',
          image,
          o('div.shdtitle', data[0], o('br'),
            o('a.shprpglk', {'href':ShSettings.productURL(sku)}, 'View product page')),
          o('span', {'innerHTML':data[1]}),
          o('div',
            o('a.shdaction', {'href':'#', 'onclick':function() {addItemToProdlist(data[0], sku); return false;}},
              o('img', {'src':'/images/smcart.gif'})))));
    }
  };
  window.product_detail_error=function(sku) {};
  window.cartmsg=function(n) {
    args=n.split(',');
    if (args[0]==secret) {
      if (args.length>=3 && args[1]=='ok') {
        dismissWaiting('Item added to cart.',
          ['Item added - Total: $'+args[2]+' - ', o('a', {'href':ShSettings.cartURL()}, 'View cart')]);
      } else if (args.length>=3 && args[1]=='out') {
        dismissWaiting('Item out of stock.',
          ['Out of stock - Total: $'+args[2]+' - ', o('a', {'href':ShSettings.cartURL()}, 'View cart')]);
      } else {
        dismissWaiting('Error adding item.');
      }
    }
  }
  function qtyString() {
    var qtyelt=document.getElementById('shqty');
    if (qtyelt && qtyelt.value && qtyelt.value.match(/^\d+$/) && qtyelt.value>1)
      return '&vwquantity='+qtyelt.value;
    return '';
  }
  function addToCart() {
    secret=Math.floor(Math.random()*0x7fffffff);
    var url=skuCartURL+qtyString();
    var framename="shcart_"+secret;

    var hn=window.location.hostname;
    var hnlen=hn.length;
    if (hnlen>14 && hn.substring(hnlen-13)=='scrapbook.com') {
      framename+="_"+hn.substring(0, hnlen-13);
    }

    carthldr.innerHTML="<iframe name='"+framename+"' style='display:none;' src='"+url+"'></iframe>";
    waitingPopup("Adding to cart...");
    return false;
  }
  function addToWish() {
    secret=Math.floor(Math.random()*0x7fffffff);
    var url=wishURL+"&key="+secret+qtyString();
    DOMhelp.replaceContent(carthldr, o('script', {'src':url}));
    waitingPopup("Adding to wishlist...");
    return false;
  }
  function unstem(s) {
    if (s=='' || s.substring(0,7)=='http://')
      return s;
    return imgstem+s;
  }
  function stopProp(e) {
    if (!e) e=window.event;
    if (e.stopPropagation) {
      e.stopPropagation();
    } else {
      e.cancelBubble=true;
    }
  }
  schobj.setItemInCB(function(item, num, elt) {
    var img = item[0] ? o('img', {'src':unstem(item[0])}) : [];
    DOMhelp.replaceContent(elt, o('a.prodlink', {'href':item[3], 'target':'_top'}, img, o('div.title', item[1])));
  });
  schobj.setInitCB(function(count, istem, databaseid) {
    imgstem = istem;
    dbid = databaseid;
    schobj.setQuerySuffix('&D='+databaseid);
  });
  function itemDetails(sku) {
    var url='http://search.scrapbook.com/detail.php?sku='+sku+'&db='+dbid;
    disp_sku = sku;
    received_details = false;
    DOMhelp.replaceContent(carthldr, o('script', {'src':url}));
    setTimeout(function() {if (!received_details)
        DOMhelp.replaceContent(shdetail, o('div.prodcont', o('b', "Getting product information...")));}, 300);
  }
  this.outerDOMelements=function() {
    return [o('div#schtermbox', o('input#schterm'))];
  }
  this.DOMelements=function() {
    schobj.setHelpImg(helpimg);
    return [schobj.DOMelements(),
            lbox.DOMelements(),
            helpimg,
            shdettitle,
            shdetail,
            o('a', {'href':'http://www.shoptivate.com'},
              o('img#shlogo', {'src':'/images/shlogo.bmp'})),
            carthldr,
            scripthldr,
            cartstatus,
            shcartmsg];
  }
  this.resizeNotify=function(ht, wd) {
    if (ht!=areaht) {
      shdheight = ht-(window.ieLT7 ? 20 : 22);
      if (detailMode)
        shdetail.style.height=shdheight+"px";
      lbox.setHeight(ht+1);
      areaht=ht;
    }
    if (wd!=areawd) {
      shdwidth = wd-divwd-16;
      if (detailMode) {
        shdetail.style.width=shdwidth+"px";
        shdettitle.style.width=shdwidth+(window.ieLT7 ? 0 : 2)+"px";
      } else
        lbox.setWidth(wd, -1);
      areawd=wd;
    }
  }
  this.turnOn=function() {
    lbox.turnOn();
    if (detailMode)
      shdetail.style.display=shdettitle.style.display='block';
  }
  this.turnOff=function() {
    lbox.turnOff();
    shdetail.style.display=shdettitle.style.display='none';
  }
  function addItemToProdlist(title, sku) {
    addProduct(title, sku);
    dismissWaiting('Item added to list', 
      ['Item added to list - ',
        o('a', {'href':'#', 'onclick':function() {endSchMode(); return false;}}, 'Back to upload page')]);
  }
  function startDetailMode(n) {
    if (!detailMode) {
      lbox.setWidth(divwd+6, n);
      
      shdetail.style.left=shdettitle.style.left=(divwd+26)+"px";
      shdetail.style.height=shdheight+"px";
      shdetail.style.width=shdwidth+"px";
      shdetail.style.display=shdettitle.style.display='block';
      shdettitle.style.width=shdwidth+(window.ieLT7 ? 0 : 2)+"px";
      detailMode=true;
    }
    var item=schobj.getItem(n);
    if (item) {
      itemDetails(item[4]);
      lbox.highlight(n);
      shdetail.scrollTop=0;
    } else
      DOMhelp.replaceContent(shdetail);
  }
  function endDetailMode() {
    if (detailMode) {
      lbox.setWidth(areawd, -1);
      shdetail.style.display=shdettitle.style.display='none';
      DOMhelp.replaceContent(shdetail);
      detailMode=false;
      lbox.highlight(-1);
    }
  }
  lbox.setKeyCB(function(k) {
    if (k==27) endfn();
    return (k!=13);
  });
  schobj.setClearDataCB(endDetailMode);
  this.txtupdate=schobj.txtupdate;
}
