var api = {
  innerholderelement : new Object(),
  addEvent: function(obj, type, fn) {
    if (obj.addEventListener) {
      obj.addEventListener(type, fn, false);
    } else if (obj.attachEvent) {
      obj["e"+type+fn] = fn;
      obj[type+fn] = function() { obj["e"+type+fn](window.event); }
      obj.attachEvent("on"+type, obj[type+fn]);
    }
  },
  stopEvent: function(event) {
    if (event.preventDefault) {
      event.preventDefault();
      event.stopPropagation();
    } else {
      event.returnValue = false;
      event.cancelBubble = true;
    }
  },
  testDOM: function() {
    return (document.getElementById ||
            document.getElementsByTagName ||
            document.createElement);
  },
  map: function(fn, elems) {
    for (var i = 0; i < elems.length; i++) {
      fn(elems[i]);
    }
  },
  clearTextNodes:function(node, recursive)
  {
    if (node.nodeType) 
    {
        if (node.nodeType == 3) 
        {
            node.parentNode.removeChild(node);
            return;
        }
    }
    if(node.type == "hidden") return;
    if (recursive) if (node.childNodes) for (nui=0;nui<node.childNodes.length;nui++) api.clearTextNodes(node.childNodes[nui], true);
  },
  clearChildNodes: function(node)
  {
    for (ccn = node.childNodes.length; ccn != 0 ; ccn--) node.removeChild(node.childNodes[ccn-1]);
  },
  getElementNodes: function(node) {
    var a = [];
    while (node) {
      if (node.nodeType == 1) {
        a.push(node);
      }
      node = node.nextSibling;
    }
    return a;
  },
  getFirstChild: function(node) {
    return (node.firstChild.nodeType == 1) ?
      node.firstChild :
      api.getNextSibling(node.firstChild);
  },
  getLastChild: function(node) {
    return (node.lastChild.nodeType == 1) ?
      node.lastChild :
      api.getPreviousSibling(node.lastChild);
  },
  getPreviousSibling: function(node) {
    while (node = node.previousSibling) {
      if (node.nodeType == 1) {
        break;
      }
    }
    return node;
  },
  getNextSibling: function(node) {
    while (node = node.nextSibling) {
      if (node.nodeType == 1) {
        break;
      }
    }
    return node;
  },
  countPreviousSiblings: function(node) {
    var i = 0;
    while (node = node.previousSibling) {
      if (node.nodeType == 1) {
        ++i;
      }
    }
    return i;
  },
  newCBR:function()
  {
        var br = document.createElement("br");
        br.setAttribute("clear", "all");
        if (arguments[0]) br.className = arguments[0];
        return br;
  }
  ,
    /**
    *Gets the dimensions of a DOM object*/
  getSize: function(obj) {
    if (obj.offsetWidth) if (obj.offsetHeight) 
        return {width: obj.offsetWidth, height: obj.offsetHeight};
    var originalVisibility = obj.style.visibility;
    var originalPosition = obj.style.position;
    obj.style.visibility = 'hidden';
    obj.style.position = 'absolute';
    obj.style.display = '';
    var originalWidth = obj.clientWidth;
    var originalHeight = obj.clientHeight;
    obj.style.display = 'none';
    obj.style.position = originalPosition;
    obj.style.visibility = originalVisibility;
    return {width: parseInt(originalWidth), height: parseInt(originalHeight)};
  },
  getOffset: function(obj) {
    var offset = {x: obj.offsetLeft, y: obj.offsetTop};
    while(obj = obj.offsetParent) 
    {
      offset.x += parseInt(obj.offsetLeft);
      offset.y += parseInt(obj.offsetTop);
    }
    if (document.all) 
    {
        offset.x += parseInt(document.body.scrollLeft);
        offset.y += parseInt(document.body.scrollTop);
    }
    return offset;
  },
  removeClassName: function(oldClass, elem) {
    var a = [];
    var classes = elem.className.split(" ");
    for (var i in classes) {
      if (classes[i] != oldClass) {
        a.push(classes[i]);
      }
    }
    elem.className = a.join(" ");
  },
  removeLastClassName: function(elem) {
    var classes = elem.className.split(" ");
    classes.pop();
    return classes.join(" ");
  },
  /*** getElementsByClassName 1.03 | Muffin Research Labs ***/
  getElementsByClassName: function(strClass, strTag, objContElm) {
    strTag = strTag || "*";
    objContElm = objContElm || document;
    var objColl = objContElm.getElementsByTagName(strTag);
    if (!objColl.length && strTag == "*" && objContElm.all) objColl = objContElm.all;
    var arr = new Array();
    var delim = strClass.indexOf("|") != -1  ? "|" : " ";
    var arrClass = strClass.split(delim);
    for (var i = 0, j = objColl.length; i < j; i++) {
      var arrObjClass = objColl[i].className.split(" ");
      if (delim == " " && arrClass.length > arrObjClass.length) continue;
      var c = 0;
      comparisonLoop:
      for (var k = 0, l = arrObjClass.length; k < l; k++) {
        for (var m = 0, n = arrClass.length; m < n; m++) {
          if (arrClass[m] == arrObjClass[k]) c++;
          if (( delim == "|" && c == 1) || (delim == " " && c == arrClass.length)) {
            arr.push(objColl[i]);
            break comparisonLoop;
          }
        }
      }
    }
    return arr;
  },
  getCursorPosition: function(event) {
    event = event || window.event;
    var coords = {x:0, y:0};
    if (event.pageX || event.pageY) {
      coords.x = event.pageX;
      coords.y = event.pageY;
    } else {
      var de = document.documentElement;
      var b = document.body;
      coords.x = event.clientX + (de.scrollLeft || b.scrollLeft) - (de.clientLeft || 0);
      coords.y = event.clientY + (de.scrollTop || b.scrollTop) - (de.clientTop || 0);
    }
    return coords;
  },
  getRelatedTarget: function(event, obj) {
    event = event || window.event;
    var relatedTarget = event.relatedTarget || event.toElement;
    while (relatedTarget && relatedTarget != obj) {
      relatedTarget = relatedTarget.parentNode;
    }
    return (relatedTarget == obj);
  },
  // ------------------------------------------------------------------------------------------------
  getViewPortSize : function()
  {
    /*var viewportwidth;
    var viewportheight;
    if (typeof window.innerWidth != 'undefined')
    {
        viewportwidth = window.innerWidth,
        viewportheight = window.innerHeight
    }
    else if (typeof document.documentElement != 'undefined'
            && typeof document.documentElement.clientWidth !=
            'undefined' && document.documentElement.clientWidth != 0)
    {
        viewportwidth = document.documentElement.clientWidth,
        viewportheight = document.documentElement.clientHeight
    }
    else
    {
        viewportwidth = document.getElementsByTagName('body')[0].clientWidth,
        viewportheight = document.getElementsByTagName('body')[0].clientHeight
    }
    return {width: viewportwidth, height: viewportheight}*/
    var x,y;
    if (self.innerHeight) // all except Explorer
    {
	    x = self.innerWidth;
	    y = self.innerHeight;
    }
    else if (document.documentElement && document.documentElement.clientHeight)
	    // Explorer 6 Strict Mode
    {
	    x = document.documentElement.clientWidth;
	    y = document.documentElement.clientHeight;
    }
    else if (document.body) // other Explorers
    {
	    x = document.body.clientWidth;
	    y = document.body.clientHeight;
    }
    if (self.screen.availHeight) if (parseInt(self.screen.availHeight) < y) y = parseInt(self.screen.availHeight);
    return {width: parseInt(x), height:parseInt(y)};
  },
  getScrollXY : function () {
        var scrOfX = 0, scrOfY = 0;
        if( typeof( window.pageYOffset ) == 'number' )
        {
            //Netscape compliant
            scrOfY = window.pageYOffset;
            scrOfX = window.pageXOffset;
        }
            else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) )
        {
            //DOM compliant
            scrOfY = document.body.scrollTop;
            scrOfX = document.body.scrollLeft;
        }
            else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) )
        {
            //IE6 standards compliant mode
            scrOfY = document.documentElement.scrollTop;
            scrOfX = document.documentElement.scrollLeft;
        }
        return {x:scrOfX, y:scrOfY};
    },
   setScrollXY : function(x, y)
   {
        if( typeof( window.pageYOffset ) == 'number' )
        {
            //Netscape compliant
            window.pageYOffset = y;
            window.pageXOffset = x;
            return;
        }
        if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) )
        {
            //DOM compliant
            document.body.scrollTop = y;
            document.body.scrollLeft = x;
            return;
        }
        if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) )
        {
            //IE6 standards compliant mode
            document.documentElement.scrollTop = y;
            document.documentElement.scrollLeft = x;
        }
   },
  
  // ------------------------------------------------------------------------------------------------
  // additions to api.classEventMap should only be done via api.setClassEventMapping() function below
  classEventMap : new Array(), 
  setClassEventMapping : function(className, behaviour, functionName)
  {
    if (api.classEventMap[className]==null) api.classEventMap[className] = new Array();
    api.classEventMap[className].push({attribute: behaviour, name: functionName});
  },
  // ------------------------------------------------------------------------------------------------
  
  
  /**
     *opens a window with no toolbars
     *
     * {url}                url to open
     * {name}               should not include spaces
     * {width}              width in pixesl
     * {height}             height in pixels
     * {options ..... , .... }         translates to point A(p,p)
   */ 
  sccWin : function() {
    
    a = api.sccWin.arguments;
    var doptions = ",resizable=no,location=no,toolbar=no,status=no,scrollbars=yes";
    var options = "";
    if (a[4])
    {
        for (k in a[4])
        {
            options += "," + k + "=" + eval("a[4]." + k);
            var re = new RegExp(",?" + k +  "=[A-Za-z0-9]+,?");
            doptions = doptions.replace(re, ",");
        }
    }
    return window.open(
        a[0],
        a[1],
        'height='+a[3]
        +',width='+a[2] + (doptions + options)
    );
  },
  // -------------------------------------------------------------------------------------------------
  /**
  * Allows you do something like:
  * 
  * function a(b,c){ alert(b+c); };
  * var params = new Array();
  * params.push(a);
  * params.push(2);
  * params.push(3);
  * api.doFunction(params); <--- alerts '5'
  */
  doFunction : function(params)
  {
    call = "params[0](";
    for(i = 1; i < params.length; i++) call += "params["+i+"]" + (i == params.length-1 ? "" : ",");
    return eval(call+")");
  },
  
  // -------------------------------------------------------------------------------------------------
  /**
  * Calls .NET's Ajax methods however adds our pre-loader to a given div;
  * 
  *  USAGE:
  *         api.callAtlas(
  *             [id of DOM element to hold the animated gif or its direct reference],
  *             [Reference to WebMethod, eg: Softchoice.Web.WebServices.Foo.Bar],
  *             {ARG1 for Bar()}, __
  *             {ARG2 for Bar()},   |
  *             ....                |---> optional
  *             {ARG# for Bar()}, __|
  *             [reference to function to call onSuccess of Bar()] or null
  *             );
  */
  callAtlas : function()
  {
    if (arguments.length < 3) return;
    var params = new Array();
    for (argi = 1; argi < arguments.length - 1; argi++) params.push(arguments[argi]);    
    if (!this.holder) this.holder = new Object();
    if (!this.holder.events) this.holder.events = new Array();
    if (!this.holder.caller) this.holder.caller = function(iinti) { this.events[iinti](); }
    var hndl = new Object();
    hndl.container = null;
    hndl.showImage = function() { }
    if (arguments[0])
    {
        if (typeof arguments[0] == "string") hndl.container = document.getElementById(arguments[0]);
        else hndl.container = arguments[0];
        hndl.showImage = function() 
        {
            if(!hndl.showImage) return;
            api.clearChildNodes(hndl.container);
            if($.browser.msie) var imgloader = new Image();
            else var imgloader = document.createElement("img");
            imgloader.src = "/img/ui/ajax-loader.gif";
            hndl.container.appendChild(imgloader);
        }
        this.holder.events.push(hndl.showImage);
    }
    hndl.history = arguments[arguments.length -1];
    hndl.onSuccess = function() 
    {
        hndl.showImage = null;
        api.clearChildNodes(hndl.container);
        var mp = new Array(); 
        if (hndl.history) mp.push(hndl.history); 
        for (thisi = 0; thisi < arguments.length; thisi++) mp.push(arguments[thisi]); 
        api.doFunction(mp); 
    }
    params.push(hndl.onSuccess);
    setTimeout('api.holder.caller('+(api.holder.events.length-1)+')', 1000);
    api.doFunction(params);
  },
  
  // -------------------------------------------------------------------------------------------------
  // Sets a given boolean for provided {id} and {idtype}, and calls 
  // {onDataRef} function after any data is retrieved via AJAX.
  //
  // id:        id of the DOM element
  // idtype:    set to "class" or "id", or whatever attribute you want
  // bool:      it is saved as the value for the given {id} and {idtype}
  //            and will be retrieved after using the fetch methods as bool
  // onDataRef:  reference to a function to call onreadystate
  rememberBool : function(id, idtype, bool, onDataRef)
  {
    Softchoice.Web.WebServices.SaveCollapsePreference.SetDomElementState(id, idtype, bool, onDataRef);
  },
  // Returns a single boolean for the given {id} and {idtype} or returns true
  // if nothing was found. {onDataRef} will be called when AJAX recieves readystate.
  //
  // id:        id of the DOM element
  // idtype:    set to "class" or "id", or whatever attribute you want
  // onDataRef:  reference to a function to call onreadystate
  fetchBool : function(id, idtype, onDataRef)
  {
    Softchoice.Web.WebServices.SaveCollapsePreference.GetDomElementState(id, idtype, onDataRef);
  },
  // Returns an array of booleans for the given {ids} and {idtypes} arrays provided, in that same order
  // of {ids}. If nothing was found at any point, you get true for it in the output array.
  // {onDataRef} will be called when AJAX recieves readystate. This function assumes
  // that {ids} and {idtypes} are of same length;
  //
  // ids:        array of string of ids of the DOM elements; ie. ['foo', 'bar' ]
  // idtypes:    array of string of idtypes as in api.fetchBool() above; i.e ['id', 'class' ]
  // onDataRef:  reference to a function to call onreadystate
  fetchBools : function(ids, idtypes, onDataRef)
  {
    Softchoice.Web.WebServices.SaveCollapsePreference.GetDomElementStates(ids, idtypes, onDataRef);
  },
  // -------------------------------------------------------------------------------------------
  requestCallback : function(email)
  {
    api.sccWin('/WindowPanels/SendRequest.aspx?' + email, 'sendrequest', 400, 200);
  },
  sendMessage : function(email, name)
  {
    api.sccWin('/WindowPanels/SendMessage.aspx?RepEmail=' + email + "&RepName=" + name, 'sendmessage', 470, 375);
  },
  sendProduct : function(productName, productUrl, displayPrice)
  {
    api.sccWin('/WindowPanels/SendProduct.aspx?pName=' + productName + "&pUrl=" + productUrl + "&pPrice=" + displayPrice, 'sendproduct', 470, 440);
  },
  
  // ****************** 
  // 1.2 - Legacy URLS
  // ******************
  legacyPopupReporting : function(url)
  {
    api.sccWin(url, 'reporting', 785, 500, {resizable :'yes'});
  },
  legacyPopupAgreements : function(url)
  {
    api.sccWin(url, 'agreements', 785, 500, {resizable :'yes'});
  },  
  legacyPopupLiveQuote : function(url)
  {
    api.sccWin(url, 'livequote', 785, 500, {resizable :'yes'});
  },  
  legacyPopupChat : function(url)
  {
    api.sccWin(url, 'chat', 512, 400);
  },  
  legacyPopupAddLocations : function(url)
  {
    api.sccWin(url, 'addlocation', 785, 500, {resizable :'yes'});
  },
  legacyPopupManageLocations : function(url)
  {
    api.sccWin(url, 'locationandcontacts', 785, 500, {resizable :'yes'});
  },
  legacyPopupMyOrders : function(url)
  {
    api.sccWin(url, 'myorders', 785, 500, {resizable :'yes'});
  },
  legacyPopupOrderStatus : function(url)
  {
    api.sccWin(url, 'orderstatus', 785, 500, {resizable :'yes'});
  },
  legacyPopupChangePassword : function(url)
  {
    api.sccWin(url, 'changepassword', 780, 350, {resizable :'yes'});
  },
  legacyPopupChangeEmail : function(url)
  {
    api.sccWin(url, 'changeemail', 780, 280, {resizable :'yes'});
  },
  // -------------------------------------------------------------------------------------------
  /*
  sets the carryover value which will persist if the page reloads and IsPostback */
  setCarryOver : function(val)
  {
    document.getElementById("ctl00_carryover").value = val;
  },
  /** returns an empty string unless there is carryover value */
  getCarryOver : function()
  {
    var hdncarfld = document.getElementById("ctl00_carryover");
    if (hdncarfld) if (hdncarfld.value) return hdncarfld.value;
    return null;
  },
  addToCart : function(dombutton, sku, quant, options)
  {
    options = options || {};
    if (dombutton.src)
    {
        dombutton.src = dombutton.src.replace(/-loading\./i, ".")
        var re = /(\.[\w\d]+)$/i;
        mymatch = re.exec(dombutton.src);
        dombutton.src = dombutton.src.replace(mymatch[0], "-loading" + mymatch[0]);
    }
    if (!(api.innerholderelement.onAddCartElements)) api.innerholderelement.onAddCartElements = new Array();
    api.innerholderelement.onAddCartElements.push(new Object());
    var myref = api.innerholderelement.onAddCartElements[api.innerholderelement.onAddCartElements.length-1];
    myref.dom = dombutton;
    myref.id = dombutton.id;
    myref.fn = function(notifications)
    {
        myref.dom.src = myref.dom.src.replace(/-loading\./i, ".")
        var clean = new Array();
        for (iclean = 0; iclean < api.innerholderelement.onAddCartElements.length; iclean++)
            if (api.innerholderelement.onAddCartElements[iclean].id != myref.id)
                clean.push(api.innerholderelement.onAddCartElements[iclean]);
        api.innerholderelement.onAddCartElements = clean;
        var notes = [];
        for (inote = 0; inote < notifications.length - 4; inote+=3)
        {
            notes.push(api.getModal(notifications[inote+1], eval ("api.modalLevels." + notifications[inote]), 
            {allowRemembrance: (notifications[inote+2] != ""), remembranceID: notifications[inote+2]}));
        }
        if (notes.length != 0) 
        {
            api.showModal(notes);
        }
        document.getElementById("cartwidget-count").innerHTML = notifications[notifications.length - 3];
        document.getElementById("cartwidget-totalcount").innerHTML = notifications[notifications.length - 2];
        document.getElementById("cartwidget-subtotal").innerHTML = notifications[notifications.length - 1];
        api.updateCartWidget( 
        notifications[notifications.length - 3],  
        notifications[notifications.length - 2],  
        notifications[notifications.length - 1]);
    }
    Softchoice.Web.WebServices.AjaxAddToCart.AddToCart(sku, quant, myref.fn);

    // Analytics (Track the click)
    pageTracker._trackPageview("/AddToCart/" + sku);
    
  },
  updateCartWidget : function (count, totalcount, total)
  {
    document.getElementById("cartwidget-count").innerHTML = count;
    document.getElementById("cartwidget-totalcount").innerHTML = totalcount;
    document.getElementById("cartwidget-subtotal").innerHTML =total;
  }
  ,
  // -------------------------------------------------------------------------------------------
  /**
  * use these similar to enums in .NET for api.getModal(...) below
  */
  modalLevels : { success: "success", warning: "warning", fatal: "fatal" },
  /*
  * Gets a template for inserting into api.showModal(..) below
  *
  * Example Usage:
  *         var successExample = api.getModal("Great Success!!", api.modalLevels.success);
  *         var fatalExample = api.getModal("Death!!", api.modalLevels.fatal);
  *         var warnExample = api.getModal("Ooopse!!", api.modalLevels.warning);
  *
  *
  * now you can do something like:
  *         api.showModal(successExample);
  *         or ....
  *         api.showModal(warnExample, successExample, fatalExample);
  *         or ....
  *         api.showModal([warnExample, successExample, fatalExample]);
  *
  *         whatever you wish!!!!!
  */
  getModal : function(msg, lvl, options)
  {
    options = options || {allowRemembrance: false, remembranceID: "" };
    var d = document.createElement("div");
    d.className = "mod-" + lvl;
    var p = document.createElement("p");
    d.appendChild(p);
    var ddd = document.createElement("span");
    ddd.innerHTML = msg;
    p.appendChild(ddd);
    if (options.allowRemembrance && options.remembranceID)
    {
        var dvrm = document.createElement("div");
        dvrm.className = "modal-remember-checkbox";
        var chkrm = document.createElement("input");
        chkrm.type = "checkbox";
        chkrm.name = chkrm.id = "rmbchk_" + options.remembranceID;
        chkrm.onclick = function ()
        {
            api.rememberBool(options.remembranceID,'id',!chkrm.checked,null);
        }
        var lbl = document.createElement($.browser.msie ? '<label for="rmbchk_' + options.remembranceID + '">' : "label");
        if(!$.browser.msie) lbl.setAttribute('for', "rmbchk_" + options.remembranceID);
        lbl.appendChild(document.createTextNode(modalDontShowMessage));
        dvrm.appendChild(chkrm);
        dvrm.appendChild(lbl);
        d.appendChild(dvrm);
    }
    return d;
  },
  /**
  * Shows the global alerts
  *
  * USAGE:          here are some valid ways to use this function
  *
  *                 api.showModal("string id of element");
  *                 api.showModal("string id of element 1", "string id of element 2");
  *                 api.showModal(refToElement);
  *                 api.showModal(domRefOne, [ domElementOne, domElementTwo, ....], "string id");
  *
  *                 as you can see you can either send single elements, arrays of strings
  *                 or array of elements or many arguments containing mix of above flavours
  *
  * EXAMPLE of USAGE on cart.js:
  *                 api.showModal( api.getModal( document.getElementById("checkouterrors").innerHTML,  api.modalLevels.fatal ) );
  */
  showModal : function()
  {
    if (arguments.length == 0) return;
    var constantid = "sccshowmodalcontainer";
    var oldone = document.getElementById(constantid);
    if(oldone) return;
    var aao = document.getElementById("modal_templateHolder_child");
    var aa = aao.cloneNode(true);
    api.innerholderelement.alertBoxRef = aa;
    aa.id = constantid;
    var lastNode;
    for (sci=0;sci<aa.childNodes.length;sci++) 
        if (aa.childNodes[sci].id) 
            if (aa.childNodes[sci].id == "sc-ok")  { lastNode = aa.childNodes[sci]; lastNode.id = "sc-ok2"; sci = aa.childNodes.length; }
    var rlcntr = document.createElement("div");
    aa.insertBefore(rlcntr,lastNode);
    var nodes = new Array();
    var counter = 0;
    for (argi = 0; argi < arguments.length; argi++)
    {
        el = arguments[argi];
        if (el.length) for (eli=0;eli<el.length;eli++) nodes.push(el[eli]);
        else if (typeof el == "string") nodes.push(getElementById(el));
        else nodes.push(el);
        counter += nodes.length;
        //var tmp fx 
        for (eli=0;eli<nodes.length;eli++)
        {
            var tmp = nodes[eli];
            if (nodes[eli].parentNode) nodes[eli].parentNode.removeChild(nodes[eli]);
            //alert("----->" + nodes.length);
            //aa.insertBefore(nodes[eli].cloneNode(true),lastNode);
            rlcntr.appendChild(nodes[eli]);
        }
    }
    var options = {};
    if (counter > 3) { options = {width:'330px'}; rlcntr.className = "modal-alertlong"; }
    $.blockUI(aa, options);
    document.getElementById('sc-ok2').onclick = function() {$.unblockUI(); api.innerholderelement.alertBoxRef.parentNode.removeChild(api.innerholderelement.alertBoxRef); api.innerholderelement.alertBoxRef = null;};
  }
}


