﻿//http://www.jibbering.com/faq/faq_notes/type_convert.html
// <0 - this first
// =0 - same
// >0 - s first

/* Global Variables */
var EQUALTO = 0, GT = 1, LT = 2;

function CSStrCompareTo(s) {
    var sThis = this.toLowerCase();
    s = s.toString().toLowerCase();
    if (sThis === s)
        return EQUALTO;
    else if (sThis < s)
        return LT;

    return GT;
}

function CSNumCompareTo(s) {
    s = s - 0;
    if (this == s)
        return EQUALTO;
    else if (this < s)
        return LT;

    return GT;
}

function CSDateCompareTo(s) {
    var dtThis = Date.parse(this);
    s = Date.parse(s)
    if (dtThis == s)
        return EQUALTO;
    else if (dtThis < s)
        return LT;

    return GT;
}

/*
false = 0
true = 1
so, 
false < true
true > false
*/
function CSBooleanCompareTo(s) {
    s = Boolean(s);
    if (this == s)
        return EQUALTO;
    else if (this < s)
        return LT;

    return GT;
}

/*
* All types share same interface and interface is assigned to different function.
*/
String.prototype.CSCompareTo = CSStrCompareTo;
Number.prototype.CSCompareTo = CSNumCompareTo;
Date.prototype.CSCompareTo = CSDateCompareTo;
Boolean.prototype.CSCompareTo = CSBooleanCompareTo;

/* Trim by myself!?! - I hate .js */
String.prototype.trim = function() {
    return this.replace(/^\s+|\s+$/g, "");
}
String.prototype.ltrim = function() {
    return this.replace(/^\s+/, "");
}
String.prototype.rtrim = function() {
    return this.replace(/\s+$/, "");
}

/*
* This utility function is used to create a consistent Year Make Model SubModel text.
* 
* Parameters:
*   year            - Item is used to create YMMMS String 
*    mk              - Item is used to create YMMMS String 
*   mdl             - Item is used to create YMMMS String 
*   dflt            - Item is used to indicate if it has YMMS created or not 
*/
function YMMSText(year, mk, mdl, smdl, dflt) {
    var sYMMS = "";
    if (year && year > 0) sYMMS = " " + year.toString();
    if (mk && mk.length > 0) sYMMS += " " + mk;
    if (mdl && mdl.length > 0) sYMMS += " " + mdl;
    if (smdl && smdl.length > 0) sYMMS += " " + smdl;
    if (sYMMS.length == 0) return dflt;
    return sYMMS.trim();
}

/*
* This utility function is used to create a consistent Year Make Model SubModel text
*   with a maximum character count.
* 
* Parameters:
*   year            - Item is used to create YMMMS String 
*    mk             - Item is used to create YMMMS String 
*   mdl             - Item is used to create YMMMS String 
*   dflt            - Item is used to indicate if it has YMMS created or not
*   maxChars        - Max length of the YMMS text
*/
function YMMSTextMax(year, mk, mdl, smdl, dflt, maxChars) {
    
    //Year Make Model SubModel
    var sYMMS = YMMSText(year, mk, mdl, smdl, dflt);
    if (sYMMS.length <= maxChars) return sYMMS;

    //Year Make Model
    sYMMS = YMMSText(year, mk, mdl, null, dflt);
    if (sYMMS.length <= maxChars) return sYMMS;

    //Make Model
    sYMMS = YMMSText(null, mk, mdl, null, dflt);
    if (sYMMS.length <= maxChars) return sYMMS;

    //Year Model
    sYMMS = YMMSText(year, null, mdl, null, dflt);
    if (sYMMS.length <= maxChars) return sYMMS;

    //Model
    if (mdl && mdl.length <= maxChars) return mdl;    
    
    return dflt;
}

/*
*This utility function is used to sort and merge Arrary. 
* Parameters:
* CarList         - The List need to be sorted 
* sSortItem       - sorting will be based on this item 
* sortFlags       - All the items can be used as sSortItem 
*/
function MergeSort(CarList, sSortItem, sortFlags) {
    var left = new Array();
    var right = new Array();

    var len = CarList.length;

    if (len <= 1) return CarList;

    var middle = Math.floor(len / 2);
    for (var i = 0; i < middle; i++) left.push(CarList[i]);
    for (var i = middle; i < len; i++) right.push(CarList[i]);

    left = MergeSort(left, sSortItem, sortFlags);
    right = MergeSort(right, sSortItem, sortFlags);

    return Merge(left, right, sSortItem, sortFlags);
}
/*
*This utility function is used to combine two arrays. 
* Parameters:
* left            - left half CarList 
* right           - right half CarList 
* sSortItem       - sorting will be based on this item 
* sortFlags       - All the items can be used as sSortItem 
*/
function Merge(left, right, sSortItem, sortFlags) {
    var retval = new Array();
    while (left.length > 0 && right.length > 0) {
        for (var j = 0; j < sortFlags.length; j++) {
            if (sortFlags[j].key == sSortItem) {
                if (!sortFlags[j].value) {
                    if (left[0][sSortItem].CSCompareTo(right[0][sSortItem]) == 0 || left[0][sSortItem].CSCompareTo(right[0][sSortItem]) == 2) retval.push(left.shift());
                    else retval.push(right.shift());
                }
                else {
                    if (left[0][sSortItem].CSCompareTo(right[0][sSortItem]) == 0 || left[0][sSortItem].CSCompareTo(right[0][sSortItem]) == 1) retval.push(left.shift());
                    else retval.push(right.shift());
                }
            }
        }
    }
    if (left.length > 0) return retval.concat(left);
    if (right.length > 0) return retval.concat(right);
}

/*
*This utility function is used to make money more readable. 
* Parameters:
* sValueToBeautify     - Make Price more readable with $ sign 
*/
function Convert2PrettyString(sValueToBeautify) {

    var oRegExp = /(^[-]?\d+$)|(^[-]?\d*[\.]\d{1,2}$)/; //find if it is any integer or float(2 precision) like 0.12, .12, or 12.23
    if (!oRegExp.test(sValueToBeautify)) return "";
    oRegExp = /(-?[0-9]+)([0-9]{3})/;
    while (oRegExp.test(sValueToBeautify)) {
        //replace original string with first group match,a comma, then second group match
        sValueToBeautify = sValueToBeautify.replace(oRegExp, '$1,$2');
    }
    return '$' + sValueToBeautify;
}

/*
*This utility function is used to parse moneny into normal number. 
* Parameters:
* sDollarNumb     - it probably contain $ or , 
*/
function Currency2Numb(sDollarNumb) {
    var iNumber = sDollarNumb.replace(/(\$|,)/gi, '');
    //check if iNumber is integer or float
    if (!(/(^[-]?\d+$)|(^[-]?\d*[\.]\d{1,2}$)/).test(iNumber))
        iNumber = 0;
    return iNumber;
}

/*
*This utility function is used to decode paramValue. 
* Parameters:
* paramName        - As a new key for new querystring
* paramKey         - key in querystring
* isSimple         - decide whether or not to call GetDecodedParamValue
*/
function GetParam(paramName, paramKey, isSimple) {
    var sParamValue = null;
    if (isSimple) {
        sParamValue = YAHOO.util.History.getQueryStringParameter(paramKey);
    }
    else {
        sParamValue = GetDecodedParamValue(YAHOO.util.History.getQueryStringParameter(paramKey));
        if (!YAHOO.lang.isNull(sParamValue))
            sParamValue = "\"" + escape(sParamValue) + "\"";
    }
    return paramName + "=" + sParamValue + "&";
}

/*
*This utility function is used to decode paramValue. 
* Parameters:
* paramValue        - Value has encoded value and junk sign '+'
*/
function GetDecodedParamValue(paramValue) {
    if (YAHOO.lang.isNull(paramValue)) return paramValue;
    return unescape(paramValue.replace(/[+]/g, " "));
}

/*
*This utility function is used to encode query string.
*escape function does not properly encode the '+' and '/' character 
*these characters need to be converted manually
http://www.permadi.com/tutorial/urlEncoding/
*/
EncodeString = function(sEncoding) {

    var sEncoded = escape(sEncoding);
    if (sEncoded.indexOf('+') > -1)
        sEncoded = sEncoded.replace(/[+]/, "%2B");

    if (sEncoded.indexOf('/') > -1)
        sEncoded = sEncoded.replace(/[\/]/g, "%2F");
    return sEncoded;
}

/* 
* Decodes the URL string 
*/
DecodeURL = function(sURL) {
    return unescape(sURL).replace(/[+]/g, " ");
}

/*
* Description: Adds a last child to the element referenced by elem2OpenWthn.
*   Adds any type of html element that has a separate closing tag.
*   <See AddSameCloseElem for elements like img or br>
* 
* Returns: Reference to the new element that is good until any siblings
*   of the newly created element (i.e. more children of elem2OpenWthn) are
*   added.  TODO: Fix that 
* 
* Parameters:
*   elem2OpenWthn       - Element that we are adding a last child to - not an ID
*   eId                 - ID of the ew element, will be generated if empty or null
*   eClass              - Class to add to the new element
*   eStyle              - Style(s) to add to the new element
*/
function AddClassStyle(elem2OpenWthn, eId, eClass, eStyle) {
    var oElem = YAHOO.util.Selector.query("#" + eId, elem2OpenWthn, true);
    if (eClass && eClass.length > 0) YAHOO.util.Dom.addClass(oElem, eClass);
    if (eStyle && eStyle.length > 0) oElem.style = eStyle;
    return oElem;
}

/*
* Description: Adds a last child to the element referenced by elem2OpenWthn.
*   Adds any type of html element that has a separate closing tag.
*   <See AddSameCloseElem for elements like img or br>
* 
* Returns: Reference to the new element that is good until any siblings
*   of the newly created element (i.e. more children of elem2OpenWthn) are
*   added.  TODO: Fix that 
* 
* Parameters:
*   elem2OpenWthn       - Element that we are adding a last child to - not an ID
*   eTag                - Type of ew element we are creating, e.g. div, p, a
*   eId                 - ID of the ew element, will be generated if empty or null
*   eClass              - Class to add to the new element
*   eStyle              - Style(s) to add to the new element
*/
function AddSepCloseElem(elem2OpenWthn, eTag, eId, eClass, eStyle) {
    if (!eId || eId.length == 0) eId = YAHOO.util.Dom.generateId(null, eTag);
    elem2OpenWthn.innerHTML += "<" + eTag + " id=\"" + eId + "\"></" + eTag + ">";
    return AddClassStyle(elem2OpenWthn, eId, eClass, eStyle);
}

/*
* Description: Adds a last child to the element referenced by elem2OpenWthn.
*   Adds any type of html element that has a self-closing tag.
*   <See AddSepCloseElem for elements like div or table>
* 
* Returns: Reference to the new element that is good until any siblings
*   of the newly created element (i.e. more children of elem2OpenWthn) are
*   added.  TODO: Fix that 
* 
* Parameters:
*   elem2OpenWthn       - Element that we are adding a last child to - not an ID
*   eTag                - Type of ew element we are creating, e.g. div, p, a
*   eId                 - ID of the ew element, will be generated if empty or null
*   eClass              - Class to add to the new element
*   eStyle              - Style(s) to add to the new element
*/
function AddSameCloseElem(elem2OpenWthn, eTag, eId, eClass, eStyle) {
    if (!eId || eId.length == 0) eId = YAHOO.util.Dom.generateId(null, eTag);
    elem2OpenWthn.innerHTML += "<" + eTag + " id=\"" + eId + "\" />";
    //elem2OpenWthn.innerHTML = elem2OpenWthn.innerHTML.concat("<", eTag, " id=\"", eId, "\" />");
    return AddClassStyle(elem2OpenWthn, eId, eClass, eStyle);
}

/*
* Description: Adds a last child to the element referenced by elem2OpenWthn.
*   Adds any type of html element that has a self-closing tag.
*   <See AddSepCloseElem for elements like div or table>
* 
* Returns: Reference to the new image that is good until any siblings
*   of the newly created element (i.e. more children of elem2OpenWthn) are
*   added.  TODO: Fix that 
* 
* Parameters:
*   elem2OpenWthn       - Element that we are adding a last child to - not an ID
*   eTag                - Type of ew element we are creating, e.g. div, p, a
*   eId                 - ID of the ew element, will be generated if empty or null
*   eClass              - Class to add to the new element
*   eStyle              - Style(s) to add to the new element
*   eSrc                - URL of the image
*   eAlt                - alt text of the image
*/
function AddImg(elem2OpenWthn, eTag, eId, eClass, eStyle, eSrc, eAlt) {
    var oElem = AddSameCloseElem(elem2OpenWthn, eTag, eId, eClass, eStyle)
    oElem.src = eSrc;
    if (eAlt && eAlt.length > 0) oElem.alt = eAlt;
    return oElem;
}

/*
* Description: Assumes that in the current operating context, 
*   the keyword this is a reference to a yi-menu object.  This function
*   preprends our CSHd and appends our CSFt divs as CSS hooks
*   *if* this menu is not scrolled.  If it is, we do not.
*
*   In the case where we are scrolled, we replace the reserved CSS hook
*   classes with "XXX".
* 
* Returns: 
*   n/a
* 
* Parameters:
*   eventType   - Name of the event that triggered this callback
*   eventArgs   - Event arguments (empty in at least beforeShow and show
*/
var MenuCSHdrFtr = function(eventType, eventArgs) {
    var menuID = this.id, menuBD = null;
    try { menuBD = YAHOO.util.Dom.getElementsByClassName("bd", "div", menuID)[0]; } catch (err) { }
    if (!menuBD) return;


    //Remove CS curvy corners holder if this is scrolled
    if (YAHOO.util.Dom.hasClass(menuBD, "yui-menu-body-scrolled")) {

        try { YAHOO.util.Dom.replaceClass(YAHOO.util.Dom.getElementsByClassName("CShd", "div", menuID)[0], "CShd", "XXX"); }
        catch (err) { alert("CShd " + err); }
        try { YAHOO.util.Dom.replaceClass(YAHOO.util.Dom.getElementsByClassName("CSft", "div", menuID)[0], "CSft", "XXX"); }
        catch (err) { alert("CSft " + err); }
        return;
    }

    //Create/insert CShd
    var oCssHook = YAHOO.util.Dom.getElementsByClassName("CShd", "div", menuID)[0];
    if (!oCssHook) oCssHook = YAHOO.util.Dom.getElementsByClassName("XXX", "div", menuID)[0];
    if (!oCssHook) {
        oDiv = document.createElement("div");
        sDivID = YAHOO.util.Dom.generateId(oDiv, "Hdr");
        oDiv.id = sDivID;
        oDiv.className = "CShd";
        YAHOO.util.Dom.insertBefore(oDiv, menuBD);
    }
    else { YAHOO.util.Dom.replaceClass(oCssHook, "XXX", "CShd"); }

    //Create/insert CSft
    oCssHook = YAHOO.util.Dom.getElementsByClassName("CSft", "div", menuID)[0];
    if (!oCssHook) oCssHook = YAHOO.util.Dom.getElementsByClassName("XXX", "div", menuID)[0];
    if (!oCssHook) {
        oDiv = document.createElement("div");
        sDivID = YAHOO.util.Dom.generateId(oDiv, "Ftr");
        oDiv.id = sDivID;
        oDiv.className = "CSft";
        YAHOO.util.Dom.insertAfter(oDiv, menuBD);
    }
    else { YAHOO.util.Dom.replaceClass(oCssHook, "XXX", "CSft"); }
}

/*
* Description: Creates a menu and subscribes to its events.
* 
* Returns: 
*   n/a
* 
* Parameters:
*   menuID   - ID of the menu that needs to be rendered
*/
function CSCreateMainNavMenu(menuID) {
    var oMenu = new YAHOO.widget.MenuBar(menuID, { autosubmenudisplay: true, keepopen: true });

    //Stay visible after clicking on the menu bar root element
    oMenu.subscribe("click", function(eventType, eventArgs) {
        var oSubMenu = eventArgs[1].cfg.getProperty("submenu");
        if (oSubMenu && !oSubMenu.cfg.getProperty("visible"))
            oSubMenu.show();
    });

    //CSS Hooks
    oMenu.subscribe("beforeShow", MenuCSHdrFtr);
    oMenu.render();
}
