// JavaScript Browser Sniffer
// Eric Krok, Andy King, Michel Plungjan Jan. 31, 2002
// see http://www.webreference.com/ for more information
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
//  (at your option) any later version.
//
// please send any improvements to aking@internet.com and we'll
// roll the best ones in
//
// adapted from Netscape's Ultimate client-side JavaScript client sniffer
// and andy king's sniffer
// Revised May 7 99 to add is.nav5up and is.ie5up (see below). (see below).
// Revised June 11 99 to add additional props, checks
// Revised June 23 99 added screen props - gecko m6 doesn't support yet - abk
//                    converted to var is_ from is object to work everywhere
// 990624 - added cookie forms links frames checks - abk
// 001031 - ie4 mod 5.0 -> 5. (ie5.5 mididentified - abk)
//          is_ie4 mod tp work with ie6+ - abk
// 001120 - ns6 released, document.layers false, put back in
//        - is_nav6 test added - abk
// 001121 - ns6+ added, used document.getElementById, better test, dom-compl
// 010117 - actual version for ie3-5.5 by Michel Plungjan
// 010118 - actual version for ns6 by Michel Plungjan
// 010217 - netscape 6/mz 6 ie5.5 onload defer bug docs - abk
// 011107 - added is_ie6 and is_ie6up variables - dmr
// 020128 - added link to netscape's sniffer, on which this is based - abk
//          updated sniffer for aol4-6, ie5mac = js1.4, TVNavigator, AOLTV,
//          hotjava
// 020131 - cleaned up links, added more links to example object detection
// 020131 - a couple small problems with Opera detection. First, when Opera
//          is set to be compatible with other browsers it will contain their
//          information in the userAgent strings. Thus, to be sure we have
//          Opera we should check for it before checking for the other bigs.
//          (And make sure the others are !opera.) Also corrected a minor
//          bug in the is_opera6up assignment.
// 020214 - Added link for Opera/JS compatibility; added improvements for
//          windows xp/2000 id in opera and aol 7 id (thanks to Les
//          Hill, Les.Hill@getronics.com, for the suggestion).
// 020531 - Added N6/7 and moz identifiers.
// 020605 - Added mozilla guessing, Netscape 7 identification, and cleaner
//          identification for Netscape 6. (this comment added after code
//          changes)
// 020725 - Added is_gecko. -- dmr
// 021205 - Added is_Flash and is_FlashVersion, based on Doc JavaScript code.
//          Added Opera 7 variables. -- dmr
// 021209 - Added aol8. -- dmr
// 030110 - Added is_safari, added 1.5 js designation for Opera 7. --dmr
// 030128 - Added is_konq, per user suggestion (thanks to Sam Vilain).
//          Removed duplicate Opera checks left over after last revision. - dmr
// 031124 - Added is_fb and version. We report this right after the is_moz
//          report. - dmr
// 040325 - Added is_fx and version. We report this right after the is_moz
//          report. - dmr
// 040421 - Added Debian check to is_moz. Thanks to Patrice Bridoux for
//          reporting this.
// 040517 - Added is_fb/is_fx to plugins based flash detection. Thanks to
//          Martin Bischoff for pointing out this omission.
// 040617 - On Mac IE, appVersion differs from the version in the ua,
//          with the UA appearing to be more accurate. As an experiment,
//          for Mac we'll pull is_minor from the ua instead.
// 040831 - Fixed Opera bug in flash detection logic; when Opera has
//          "enable plugins" unchecked in preferences, the "plugin"
//          variable is still true, but the "description" property
//          belonging to it is undefined.
//
// Everything you always wanted to know about your JavaScript client
// but were afraid to ask. Creates "is_" variables indicating:
// (1) browser vendor:
//     is_nav, is_ie, is_opera
// (2) browser version number:
//     is_major (integer indicating major version number: 2, 3, 4 ...)
//     is_minor (float   indicating full  version number: 2.02, 3.01, 4.04 ...)
// (3) browser vendor AND major version number
//     is_nav2, is_nav3, is_nav4, is_nav4up, is_nav5, is_nav5up,
//     is_nav6, is_nav6up, is_ie3, is_ie4, is_ie4up, is_ie5up, is_ie6...
// (4) JavaScript version number:
//     is_js (float indicating full JavaScript version number: 1, 1.1, 1.2 ...)
// (5) OS platform and version:
//     is_win, is_win16, is_win32, is_win31, is_win95, is_winnt, is_win98
//     is_os2
//     is_mac, is_mac68k, is_macppc
//     is_unix
//        is_sun, is_sun4, is_sun5, is_suni86
//        is_irix, is_irix5, is_irix6
//        is_hpux, is_hpux9, is_hpux10
//        is_aix, is_aix1, is_aix2, is_aix3, is_aix4
//        is_linux, is_sco, is_unixware, is_mpras, is_reliant
//        is_dec, is_sinix, is_freebsd, is_bsd
//     is_vms
//
// based in part on
// http://www.mozilla.org/docs/web-developer/sniffer/browser_type.html
// The Ultimate JavaScript Client Sniffer
// and Andy King's object detection sniffer
//
// Note: you don't want your Nav4 or IE4 code to "turn off" or
// stop working when Nav5 and IE5 (or later) are released, so
// in conditional code forks, use is_nav4up ("Nav4 or greater")
// and is_ie4up ("IE4 or greater") instead of is_nav4 or is_ie4
// to check version in code which you want to work on future
// versions. For DOM tests scripters commonly used the
// is_getElementById test, but make sure you test your code as
// filter non-compliant browsers (Opera 5-6 for example) as some
// browsers return true for this test, and don't fully support
// the W3C's DOM1.
//

    // convert all characters to lowercase to simplify testing
    var agt=navigator.userAgent.toLowerCase();
    var appVer = navigator.appVersion.toLowerCase();

    // *** BROWSER VERSION ***

    var is_minor = parseFloat(appVer);
    var is_major = parseInt(is_minor);

    var is_opera = (agt.indexOf("opera") != -1);
    var is_opera2 = (agt.indexOf("opera 2") != -1 || agt.indexOf("opera/2") != -1);
    var is_opera3 = (agt.indexOf("opera 3") != -1 || agt.indexOf("opera/3") != -1);
    var is_opera4 = (agt.indexOf("opera 4") != -1 || agt.indexOf("opera/4") != -1);
    var is_opera5 = (agt.indexOf("opera 5") != -1 || agt.indexOf("opera/5") != -1);
    var is_opera6 = (agt.indexOf("opera 6") != -1 || agt.indexOf("opera/6") != -1); // new 020128- abk
    var is_opera7 = (agt.indexOf("opera 7") != -1 || agt.indexOf("opera/7") != -1); // new 021205- dmr
    var is_opera5up = (is_opera && !is_opera2 && !is_opera3 && !is_opera4);
    var is_opera6up = (is_opera && !is_opera2 && !is_opera3 && !is_opera4 && !is_opera5); // new020128
    var is_opera7up = (is_opera && !is_opera2 && !is_opera3 && !is_opera4 && !is_opera5 && !is_opera6); // new021205 -- dmr

    // Note: On IE, start of appVersion return 3 or 4
    // which supposedly is the version of Netscape it is compatible with.
    // So we look for the real version further on in the string
    // And on Mac IE5+, we look for is_minor in the ua; since
    // it appears to be more accurate than appVersion - 06/17/2004

    var is_mac = (agt.indexOf("mac")!=-1);
    var iePos  = appVer.indexOf('msie');
    if (iePos !=-1) {
       if(is_mac) {
           var iePos = agt.indexOf('msie');
           is_minor = parseFloat(agt.substring(iePos+5,agt.indexOf(';',iePos)));
       }
       else is_minor = parseFloat(appVer.substring(iePos+5,appVer.indexOf(';',iePos)));
       is_major = parseInt(is_minor);
    }

    // ditto Konqueror

    var is_konq = false;
    var kqPos   = agt.indexOf('konqueror');
    if (kqPos !=-1) {
       is_konq  = true;
       is_minor = parseFloat(agt.substring(kqPos+10,agt.indexOf(';',kqPos)));
       is_major = parseInt(is_minor);
    }

    var is_getElementById   = (document.getElementById) ? "true" : "false"; // 001121-abk
    var is_getElementsByTagName = (document.getElementsByTagName) ? "true" : "false"; // 001127-abk
    var is_documentElement = (document.documentElement) ? "true" : "false"; // 001121-abk

    var is_safari = ((agt.indexOf('safari')!=-1)&&(agt.indexOf('mac')!=-1))?true:false;
    var is_khtml  = (is_safari || is_konq);

    var is_gecko = ((!is_khtml)&&(navigator.product)&&(navigator.product.toLowerCase()=="gecko"))?true:false;
    var is_gver  = 0;
    if (is_gecko) is_gver=navigator.productSub;

    var is_moz   = ((agt.indexOf('mozilla/5')!=-1) && (agt.indexOf('spoofer')==-1) &&
                    (agt.indexOf('compatible')==-1) && (agt.indexOf('opera')==-1)  &&
                    (agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1)     &&
                    (is_gecko) &&
                    ((navigator.vendor=="")||(navigator.vendor=="Mozilla")||(navigator.vendor=="Debian")));
    var is_fb = ((agt.indexOf('mozilla/5')!=-1) && (agt.indexOf('spoofer')==-1) &&
                 (agt.indexOf('compatible')==-1) && (agt.indexOf('opera')==-1)  &&
                 (agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1)     &&
                 (is_gecko) && (navigator.vendor=="Firebird"));
    var is_fx = ((agt.indexOf('mozilla/5')!=-1) && (agt.indexOf('spoofer')==-1) &&
                 (agt.indexOf('compatible')==-1) && (agt.indexOf('opera')==-1)  &&
                 (agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1)     &&
                 (is_gecko) && (navigator.vendor=="Firefox"));
    if ((is_moz)||(is_fb)||(is_fx)) {  // 032504 - dmr
       var is_moz_ver = (navigator.vendorSub)?navigator.vendorSub:0;
       if(!(is_moz_ver)) {
           is_moz_ver = agt.indexOf('rv:');
           is_moz_ver = agt.substring(is_moz_ver+3);
           is_paren   = is_moz_ver.indexOf(')');
           is_moz_ver = is_moz_ver.substring(0,is_paren);
       }
       is_minor = is_moz_ver;
       is_major = parseInt(is_moz_ver);
    }
   var is_fb_ver = is_moz_ver;
   var is_fx_ver = is_moz_ver;

    var is_nav  = ((agt.indexOf('mozilla')!=-1) && (agt.indexOf('spoofer')==-1)
                && (agt.indexOf('compatible') == -1) && (agt.indexOf('opera')==-1)
                && (agt.indexOf('webtv')==-1) && (agt.indexOf('hotjava')==-1)
                && (!is_khtml) && (!(is_moz)) && (!is_fb) && (!is_fx));

    // Netscape6 is mozilla/5 + Netscape6/6.0!!!
    // Mozilla/5.0 (Windows; U; Win98; en-US; m18) Gecko/20001108 Netscape6/6.0
    // Changed this to use navigator.vendor/vendorSub - dmr 060502
    // var nav6Pos = agt.indexOf('netscape6');
    // if (nav6Pos !=-1) {
    if ((navigator.vendor)&&
        ((navigator.vendor=="Netscape6")||(navigator.vendor=="Netscape"))&&
        (is_nav)) {
       is_major = parseInt(navigator.vendorSub);
       // here we need is_minor as a valid float for testing. We'll
       // revert to the actual content before printing the result.
       is_minor = parseFloat(navigator.vendorSub);
    }

    var is_nav2 = (is_nav && (is_major == 2));
    var is_nav3 = (is_nav && (is_major == 3));
    var is_nav4 = (is_nav && (is_major == 4));
    var is_nav4up = (is_nav && is_minor >= 4);  // changed to is_minor for
                                                // consistency - dmr, 011001
    var is_navonly      = (is_nav && ((agt.indexOf(";nav") != -1) ||
                          (agt.indexOf("; nav") != -1)) );

    var is_nav6   = (is_nav && is_major==6);    // new 010118 mhp
    var is_nav6up = (is_nav && is_minor >= 6); // new 010118 mhp

    var is_nav5   = (is_nav && is_major == 5 && !is_nav6); // checked for ns6
    var is_nav5up = (is_nav && is_minor >= 5);

    var is_nav7   = (is_nav && is_major == 7);
    var is_nav7up = (is_nav && is_minor >= 7);

    var is_ie   = ((iePos!=-1) && (!is_opera) && (!is_khtml));
    var is_ie3  = (is_ie && (is_major < 4));

    var is_ie4   = (is_ie && is_major == 4);
    var is_ie4up = (is_ie && is_minor >= 4);
    var is_ie5   = (is_ie && is_major == 5);
    var is_ie5up = (is_ie && is_minor >= 5);

    var is_ie5_5  = (is_ie && (agt.indexOf("msie 5.5") !=-1)); // 020128 new - abk
    var is_ie5_5up =(is_ie && is_minor >= 5.5);                // 020128 new - abk

    var is_ie6   = (is_ie && is_major == 6);
    var is_ie6up = (is_ie && is_minor >= 6);


    // *** JAVASCRIPT VERSION CHECK ***
    // Useful to workaround Nav3 bug in which Nav3
    // loads <SCRIPT LANGUAGE="JavaScript1.2">
    // updated 020131 by dragle
    var is_js;
    if (is_nav2 || is_ie3) is_js = 1.0;
    else if (is_nav3) is_js = 1.1;
    else if ((is_opera5)||(is_opera6)) is_js = 1.3; // 020214 - dmr
    else if (is_opera7up) is_js = 1.5; // 031010 - dmr
    else if (is_khtml) is_js = 1.5;   // 030110 - dmr
    else if (is_opera) is_js = 1.1;
    else if ((is_nav4 && (is_minor <= 4.05)) || is_ie4) is_js = 1.2;
    else if ((is_nav4 && (is_minor > 4.05)) || is_ie5) is_js = 1.3;
    else if (is_nav5 && !(is_nav6)) is_js = 1.4;
    else if (is_nav6up) is_js = 1.5;

    // NOTE: In the future, update this code when newer versions of JS
    // are released. For now, we try to provide some upward compatibility
    // so that future versions of Nav and IE will show they are at
    // *least* JS 1.x capable. Always check for JS version compatibility
    // with > or >=.

    else if (is_nav && (is_major > 5)) is_js = 1.4;
    else if (is_ie && (is_major > 5)) is_js = 1.3;
    else if (is_moz) is_js = 1.5;
    else if (is_fb||is_fx) is_js = 1.5; // 032504 - dmr

    // what about ie6 and ie6up for js version? abk

    // HACK: no idea for other browsers; always check for JS version
    // with > or >=
    else is_js = 0.0;
    // HACK FOR IE5 MAC = js vers = 1.4 (if put inside if/else jumps out at 1.3)
    if ((agt.indexOf("mac")!=-1) && is_ie5up) is_js = 1.4; // 020128 - abk

    // Done with is_minor testing; revert to real for N6/7
    if (is_nav6up) {
       is_minor = navigator.vendorSub;
    }


//end browser sniffer


/////////////////////////////////////////////////////////////////////////////////
//  Variables instantiated here
/////////////////////////////////////////////////////////////////////////////////

//this is in here for killing the shadow in mac os9 ie
if (!is_ie6up) {
    SHADOW = DONOTHING;
}
//these must correspond to the style sheets available for users to set their
//font prefs. These style sheets must be named txt<Name> where name is an entry in the array below
var txtSizes = new Array ("Tiny","Small","Medium","Large");

//this variable is used to show popups when objects are moused over (uses the overlib libraries)
var showPopUps = true;
//get the cookie for this on startup

if (readCookie('showPopUps')) {
    showPopUps = readCookie ('showPopUps');
}

/////////////////////////////////////////////////////////////////////////////////
//  Site Wide Functions
/////////////////////////////////////////////////////////////////////////////////

//set a preference. pass in:
// pref - the name of the cookie (preference) to save
// value - the value to save
function setPref (pref, value) {
    var cookie = readCookie(pref);
    if (cookie == null || cookie != value) {
        createCookie(pref, value, 365);
    }
    //refresh all preferences
    getPrefs();
}

// getPrefs - gets all prefs from the user's browser. Should be run at load time.
function getPrefs() {
    //get popup prefs
    var cookie = readCookie("showPopUps");
    if (cookie) {
        showPopUps = cookie;
    }
    if (typeof chartsSections !== "undefined"){
        cookie = readCookie(chartsSections);
        selectTab(chartsSections, cookie);
				changeClass('topdlmore','hidden');
				changeClass(cookie+'more','visible');
    }
    if (typeof featuredGenres !== "undefined"){
        cookie = readCookie(featuredGenres);
        selectFeaturedTab(featuredGenres, cookie);
    }
    return true;
    //this function should expand as we add more preferences.
}
// this calls the drop down box when the user clicks the prefs button
function showPrefs() {
    //here's the body of the box with the text size and popup details
    var body = "<div id=\"prefsWindowClose\"><span><a href=\"javascript:nd();definePrefs();\">What do these do?</a></span><a href=\"javascript:nd();void(0);\">close</a></div><div class=\"clearAll\"></div><div id=\"prefsWindow\"><form name=\"prefs\"><div class=\"textSize\"><img src=\"/i/mdl/global/font_prefs.gif\" width=\"14\" height=\"13\" alt=\"font prefs\" border=\"0\" align=\"absmiddle\"/>text size:<select align=\"absmiddle\" onchange=\"setPref('style','txt' + txtSizes[this.selectedIndex]);changeTxtSize('txt' + txtSizes[this.selectedIndex]);\">";
    //get the current user pref (if any)
    var fontPref = readCookie("style");
    //if it's not set, use the default
    if (fontPref == null) {
        fontPref = "txtSmall";
    }
    //loop through the available sizes; see array instantiated at top of this js file.
    for (i = 0; i < txtSizes.length; i++) {
        if (fontPref == "txt" + txtSizes[i]) {
            body += "<option selected=\"true\">" + txtSizes[i] + "</option>";
        } else {
            body += "<option>" + txtSizes[i] + "</option>";
        }
    }
    //more html, related to the details popups
    body += "</select><div class=\"clearAll\"></div></div><div class=\"popDetails\"><img src=\"/i/mdl/global/popup_prefs.gif\" width=\"45\" height=\"34\" alt=\"show popup details\" border=\"0\" />Show popup details?<br />yes <input type=\"radio\" name=\"showPops\" value=\"true\"";
    if (showPopUps == "true" || showPopUps == true) {
        body += "checked=\"true\"";
    }
    body += "onMouseDown=\"setPref('showPopUps','true');showPopUps='true';\"/>&nbsp;&nbsp; no <input type=\"radio\" name=\"showPops\" value=\"false\"";
    if (showPopUps == "false" || showPopUps == false) {
        body += "checked=\"true\"";
    }
    body += "onMouseDown=\"setPref('showPopUps','false');showPopUps='false';\"/><div class=\"clearAll\"></div></div></form><div class=\"newsletter\"><form action=\"http://nl.com.com/mini_form.ss\" method=\"post\" name=\"newsletterPrefForm\"><input type=\"hidden\" name=\"brand\" value=\"download\" /><input type=\"hidden\" name=\"subs_channel\" value=\"cn_download.com\" /><input type=\"hidden\" name=\"partner_id\" value=\"CNET_Download\" /><input type=\"hidden\" name=\"tag\" value=\"mf.but.download\" /><input type=\"hidden\" name=\"list_id\" value=\"e718\" /><a href=\"javascript:document.newsletterPrefForm.submit();\"><img src=\"/i/mdl/global/email_prefs.gif\" width=\"17\" height=\"14\" alt=\"manage newsletters\" border=\"0\">Manage your newsletter subscriptions.</a></form><div class=\"clearAll\"></div></div></div>";
    //call overlib
    return overlib(body, REF, 'prefs_icon', REFP, 'BR', REFY, 30, REFX, -75, TEXTSIZE, '10px', TEXTCOLOR,'#000000', BGCOLOR, '#000000', FGCOLOR, '#505050', BORDER, 2, SHADOW, SHADOWCOLOR, '#333333', WIDTH, 180, TEXTPADDING, 0);
}

//this function displays details about what each preference does
function definePrefs () {
    var definition = "<div id=\"prefsDetailsClose\"><span><a href=\"javascript:nd();showPrefs();\"><b>&laquo;</b> Back to preferences</a></span><a href=\"javascript:nd();void(0);\">close</a></div><div class=\"clearAll\"></div>";
    definition += "<div id=\"prefsDetails\"><b>What do these preferences do?</b><dl><dt>Text size:</dt><dd>Changes the size of the fonts on Download.com Music. Note that your browser settings may affect this.</dd><dt>Popup details:</dt><dd>Shows more detail when you mouse over certain items on our site. Currently the only items with popup information are the \"Suggestions From The Editors\" on every artist page.</dd><dt>Newsletter subscriptions:</dt><dd>Use this to subscribe or unsubscribe to our weekly music update, or to change your email address.</dd></dl></div>";
    return overlib(definition, REF, 'prefs_icon', REFP, 'BR', REFY, 30, REFX, -125, TEXTSIZE, '10px', TEXTCOLOR,'#000000', BGCOLOR, '#000000', FGCOLOR, '#505050', BORDER, 2, SHADOW, SHADOWCOLOR, '#333333', WIDTH, 250, HEIGHT, 250, TEXTPADDING, 0);
}


// changeNavTab: toggles navigation between genre and location browsing
// type - either "genre" or "location"
function changeNavTab (type) {
    //this is a bit of a hack to get around an NS7 display bug.
    hideSection ('genreNav');
    hideSection ('locationNav');
    //depending on the type, change the tab itself to be selected
    if (type == "genre") {
        showSection ('genreNav');
        document.getElementById("genreTab").src="/i/mdl/global/genres_tab_on.gif";
        document.getElementById("locationTab").src="/i/mdl/global/location_tab_off.gif";
    } else {
        showSection ('locationNav');
        document.getElementById("genreTab").src="/i/mdl/global/genres_tab_off.gif";
        document.getElementById("locationTab").src="/i/mdl/global/location_tab_on.gif";
    }
}

// hideSection - an explicit javascript css change. Normally, I use changeClass,
//           but there seems to be a bug with NS7 when hiding and unhiding things
//           so we do it explicitely here.
function hideSection(id) {
    var thisLevel = document.getElementById( id );
    if (thisLevel != null){
    	thisLevel.style.display = "none";
    }
}
//the counterpart to the above function.
function showSection(id) {
    var thisLevel = document.getElementById( id );
    if (thisLevel != null){
        thisLevel.style.display = "block";
    }
}

// changeClass - changes the class of an element
// id - the id of the object
// newClass - the destination class
function changeClass(id, newClass) {
    if (document.getElementById(id)) {
        var identity=document.getElementById(id);
        if (identity.className != newClass) {
            identity.className=newClass;
        }
    } else {
        /*alert ('id not found: ' + id);*/
    }
}

//toggleSelection - toggles an element from one class to the other
// id - the id of the element
// onClass - the 'on' state class
// offClass - the 'off' state
function toggleSection (id,onClass,offClass) {
    var styleObject = document.getElementById(id);
    var currentClass = styleObject.className;
    if (styleObject) {
        if (currentClass != offClass) {
            changeClass(id, offClass);
        } else {
            changeClass(id, onClass);
        }
        return true;
    } else {
        return false;
    }
}

//callNd() kills an overlib window if we are showing popups
function callNd() {
    if (showPopUps && (showPopUps=="true" || showPopUps==true)) {
        nd(200);
    }
}

/*startList = function() {
    if (document.all&&document.getElementById) {
        var items = new Array(document.getElementById("genreNav"), document.getElementById("locationNav"));
        for (list=0; list < items.length; list++) {
            for (i=0; i<items[list].childNodes.length; i++) {
                node = items[list].childNodes[i];
                if (node.nodeName=="DIV" || node.nodeName=="div") {
                    node.onmouseover=function() {
                        this.className+="Over";
                }
                node.onmouseout=function() {
                    this.className=this.className.replace("Over", "");
                }
            }
            }
        }
    }
}
window.onload=startList;*/




//this empty variable (loadFunctions) is a list of functions
//that is filled by the document as it prints. when the window is loaded, it calls these functions
var loadFunctions = new Array();
//it can include documents that must be called on submit.
function callLoadFunctions()
{
    //loop through all the entries in the loadFunctions Array
    for ( numfunctions=0; numfunctions < loadFunctions.length; numfunctions++ )
    {
        //if this funciton, when called, fails, return false
        loadFunctions[numfunctions]();
    }
    //else, all functions ran, return true
    return true;
}

//getStyleObject - get the style of a particular object so that you can change it
//id - the id of the object
function getStyleObject(id) {
    // checkW3C DOM, then MSIE 4, then NN 4.
    //
    if(document.getElementById && document.getElementById(id)) {
        return document.getElementById(id).style;
    }
    else if (document.all && document.all(id)) {
        return document.all(id).style;
    }
    else if (document.layers && document.layers[id]) {
        return document.layers[id];
    } else {
        return false;
    }
}

function toggle(elm) {
    var newDisplay = "none";
    var e = elm.nextSibling;
    while (e != null) {
        if (e.tagName == "div" || e.tagName == "DIV") {
            if (e.style.display == "none") {
                newDisplay = "block";
            }
            break;
        }
        e = e.nextSibling;
    }
    while (e != null) {
        if (e.tagName == "div" || e.tagName == "DIV") {
            e.style.display = newDisplay;
        }
        return true;
    }
}

function collapseAll() {
    var locationNav = document.getElementById('locationNav');
    var tags = locationNav.childNodes;
    for (var n = 0; n < tags.length; n++) {
        if (tags[n].className == "top"){
            var navElements = tags[n].childNodes;
            for (var i = 0; i < navElements.length; i++) {
                if (navElements[i].tagName != "a" && (navElements[i].tagName == "div" || navElements[i].tagName == "DIV")) {
                    navElements[i].style.display = "none";
                    var newDisplay = "none";
                    var e = navElements[i].nextSibling;
                    while (e != null) {
                        if (e.tagName == "div" || e.tagName == "DIV") {
                            newDisplay = "none";
                            break;
                        }
                        e = e.nextSibling;
                    }
                    while (e != null) {
                        if (e.tagName == "div" || e.tagName == "DIV") e.style.display = "none";
                        e = e.nextSibling;
                    }
                }
            }
        }
    }
}

function toggleNav(cont,id,onClass,offClass) {
    for (var i = 0; i < cont.length; i++) {
        var styleObject = document.getElementById(id);
        var currentClass = styleObject.className;
        if (cont[i] == id) {
            if (styleObject) {
                if (currentClass != offClass) {
                    changeClass(cont[i], offClass);
                } else {
                    changeClass(cont[i], onClass);
                }
            }
        } else {
            changeClass(cont[i], offClass);
        }
    }
}


/////////////////////////////////////////////////////////////////////////////////
//  home page/door page specific functions
/////////////////////////////////////////////////////////////////////////////////


//selectTab changes between sections in a tab layout. pass in:
// array - an array of tabs. Each section must correspond to the
//         names in the array. Each tab's id must be the same name
//         plus " Tab"
// tab - the tab that is selected - the name of it.
function selectTab(array, tab) {
    //save the array and the selection as a cookie for prefs.
    createCookie (array,tab,365);
    //array = array of tab names in selection
    //tab = name of tab selected
    for (i = 0; i < array.length; i++ ){
        //NS7 display hack
        showSection (array[i]);
        hideSection (array[i]);
        //change the tabs
        if (tab != null && tab != "null") {
            if (array[i] == tab) {
                showSection (array[i]);
                changeClass(array[i] + "_tab", "highlight");
            } else {
                if (i == array.length -1) {
                    changeClass(array[i] + "_tab", "lastTab");
                } else {
                    changeClass(array[i] + "_tab", "no-highlight");
                }
            }
        } else {
            showSection (array[0]);
            changeClass(array[0] + "_tab", "highlight");
        }
    }
}

function selectFeaturedTab(array, tab, ifId, path) {
    if (null == tab || 'null' == tab) {
        tab = '7975';
    }
    if (null != ifId && 'null' != ifId) {
        var iframe = document.getElementById(ifId);
    } else {
        var iframe = document.getElementById('featArtistsFrame');
    }
    if (null != path && 'null' != path) {
        iframe.src = path;
    } else {
        iframe.src = '/3629-' + tab + '-0-2.html?tag=FA_iframe';
    }
    var tabLabel = 'genre_' + tab;

    //save the array and the selection as a cookie for prefs.
    createCookie (array,tab,365);
    for (i = 0; i < array.length; i++ ){
        //change the tabs
        if (tab != null && tab != "null") {
            if (array[i] == tabLabel) {
                changeClass(array[i] + "_tab", "highlight");
            } else {
                if (i == array.length -1) {
                    changeClass(array[i] + "_tab", "lastTab");
                } else {
                    changeClass(array[i] + "_tab", "no-highlight");
                }
            }
        } else {
            changeClass(array[0] + "_tab", "highlight");
        }
    }
}

//highlight - changes featured artist as one mouses over elements
// array - an array of artist data containing the following elements:
//         img: the url to a 100x100 image
//         url: the url to this artist
// id - the id of the artist to highlight relative to the array passed in.
// offset - the offset of this artist id: the array should include ALL artists
//          for the section, of which only a portion are visible at any time.
//          which artists are visible are defined by the totalVisible variable.
//          the offset + the total visible gives you the visible set
//          so if there are 30 artists in the array, and the offset is 20, and
//          totalVisible = 5, then we know we are showing elements 20-24 of 30.
//          the id of the highlighted element should be within this range
function highlight(array, id, offset, totalVisible) {
    // get the top boundary of the set
    var set = offset + totalVisible;
    //set up the crossfade filter and change the image
    crossfade('FA_ImgTag',array[id]["img"], 2)
    //change the link around the image
    document.getElementById('FA_ImgLink').href = array[id]["url"];
    //loop through the set, showing and hiding the relevent info
    for (i = offset; i < set; i++) {
        if (i == id) {
            changeClass('FA_' + i, 'artistName');
            changeClass('FADesc_' + i, '');
            changeClass('FAFiledUnder_' + i, 'visible');
            changeClass('FALocation_' + i, 'visible');
            changeClass('FA_Rating_' + i, 'artistRating');
            changeClass('artist_' + i, 'highlight');
        } else {
            changeClass('FA_' + i, 'hidden');
            changeClass('FADesc_' + i, 'hidden');
            changeClass('FAFiledUnder_' + i, 'hidden');
            changeClass('FALocation_' + i, 'hidden');
            changeClass('FA_Rating_' + i, 'hidden')
            changeClass('artist_' + i, 'artist');
        }
    }
}

//highlight - changes featured artist as one mouses over elements
// array - an array of artist data containing the following elements:
//         img: the url to a 100x100 image
//         url: the url to this artist
// id - the id of the artist to highlight relative to the array passed in.
// offset - the offset of this artist id: the array should include ALL artists
//          for the section, of which only a portion are visible at any time.
//          which artists are visible are defined by the totalVisible variable.
//          the offset + the total visible gives you the visible set
//          so if there are 30 artists in the array, and the offset is 20, and
//          totalVisible = 5, then we know we are showing elements 20-24 of 30.
//          the id of the highlighted element should be within this range
function highlightWithNode(array, id, offset, totalVisible, nodeId) {
    // get the top boundary of the set
    var set = offset + totalVisible;
    //set up the crossfade filter and change the image
    crossfade('FA_ImgTag_' + nodeId,array[id]["img"], 2)
    //change the link around the image
    document.getElementById('FA_ImgLink_' + nodeId).href = array[id]["url"];
    //loop through the set, showing and hiding the relevent info
    for (i = offset; i < set; i++) {
        if (i == id) {
            changeClass('FA_' + nodeId + '_' + i, 'artistName');
            changeClass('FADesc_' + nodeId + '_' + i, '');
            changeClass('FAFiledUnder_' + nodeId + '_' + i, 'visible');
            changeClass('FALocation_' + nodeId + '_' + i, 'visible');
            //changeClass('FA_Rating_' + nodeId + '_' + i, 'artistRating');
            changeClass('artist_' + nodeId + '_' + i, 'highlight');
        } else {
            changeClass('FA_' + nodeId + '_' + i, 'hidden');
            changeClass('FADesc_' + nodeId + '_' + i, 'hidden');
            changeClass('FAFiledUnder_' + nodeId + '_' + i, 'hidden');
            changeClass('FALocation_' + nodeId + '_' + i, 'hidden');
            //changeClass('FA_Rating_' + i, 'hidden')
            changeClass('artist_' + nodeId + '_' + i, 'artist');
        }
    }
}

function highlightWithNode2(array, id, offset, totalVisible, nodeId) {
     // get the top boundary of the set
     var set = offset + totalVisible;
     //set up the crossfade filter and change the image
     crossfade('FA_ImgTag_' + nodeId,array[id]["img"], 2)
     //change the link around the image
     document.getElementById('FA_ImgLink_' + nodeId).href = array[id]["url"];
     //change the playback link
     // commenting this for now
     // document.getElementById('FA_SampLink_' + nodeId).href = 'javascript:redirectUser(\'mdl_streaming_bandwidth,mdl_streaming_explicit\',\',\',\'3632-5_32-0.html\',false,\'playList\',\'artist-'+array[id]["artId"]+'\');void(0);';
     //loop through the set, showing and hiding the relevent info
     for (i = offset; i < set; i++) {
         if (i == id) {
             changeClass('FA_' + nodeId + '_' + i, 'artistName');
             changeClass('FADesc_' + nodeId + '_' + i, '');
             changeClass('FAFiledUnder_' + nodeId + '_' + i, 'visible');
             changeClass('FALocation_' + nodeId + '_' + i, 'visible');
             //changeClass('FA_Rating_' + nodeId + '_' + i,'artistRating');
             changeClass('artist_' + nodeId + '_' + i, 'highlight');
         } else {
             changeClass('FA_' + nodeId + '_' + i, 'hidden');
             changeClass('FADesc_' + nodeId + '_' + i, 'hidden');
             changeClass('FAFiledUnder_' + nodeId + '_' + i, 'hidden');
             changeClass('FALocation_' + nodeId + '_' + i, 'hidden');
             //changeClass('FA_Rating_' + i, 'hidden')
             changeClass('artist_' + nodeId + '_' + i, 'artist');
         }
     }
 }



// crossfade changes an image from one file to another
// if the user is using IE, it will "fade" from one to the other
// oldObj - id of the img tag to change
// newObj - the url to the new image
// speed - milliseconds to run the transition
// see: http://msdn.microsoft.com/library/default.asp?url=/workshop/author/filter/reference/filters/blendtrans.asp
function crossfade(oldObj, newObj, speed) {
    var image = document.getElementById(oldObj);
    // if we're using IE...
    if (document.all) {
        //set the filter
        image.style.filter="blendTrans(duration=" + speed + ")";
        image.filters.blendTrans.Apply();
    }
    //change the image - works in all modern browsers
    image.src = newObj;
    if (document.all) {
        //if IE, run the filter
        image.filters.blendTrans.Play();
    }
}


/////////////////////////////////////////////////////////////////////////////////
//  artist page specific functions
/////////////////////////////////////////////////////////////////////////////////



//resizeText - resizes a block object
//id - the id of the object
//h - the new height
//w - the new width
// hack - this is a safari hack. pass in a number and the height of the object will get this added to it
//    pass in zero for w or h to only resize the other value
function toggleText (id, h, w, hack) {
    var styleObject = getStyleObject(id);
    if (styleObject) {
        if (h > 0) {
            styleObject.height = h + "px";
        }
        if (w > 0) {
            styleObject.width = w + "px";
        }
    }
    if (hack != null) {
        var h = styleObject.height;
        if (h == null || h == "") {
            h = 200;
        }
        styleObject.height = h + hack + "px";
    }
}


///////////////////////////////////
//  song specific functions
///////////////////////////////////
function toggleSongsArea(expand, numSongs) {
    if (expand == "true") {
        changeClass('songsExpand', 'hidden');
        changeClass('songsCollapse', 'visible');
        for (i = 0; i < numSongs; i++) {
            toggleSong(i,'true','true');
        }
    } else {
        changeClass('songsExpand', 'visible');
        changeClass('songsCollapse', 'hidden');
        for (i = 0; i < numSongs; i++) {
            toggleSong(i,'false','false');
        }
    }
}
function toggleSong (id, expand, expandAll) {
    if (expand == "true") {
        changeClass('song' + id + 'Expand','hidden');
        if (expandAll != "true") {
            changeClass('song' + id + 'Collapse','visible');
        } else {
            changeClass('song' + id + 'Collapse','hidden');
        }
        changeClass('song' + id + 'extended','extended');
    } else {
        changeClass('song' + id + 'Expand','visible');
        changeClass('song' + id + 'Collapse','hidden');
        changeClass('song' + id + 'extended','hidden');
    }
}

///////////////////////////////////
//  artist page specific functions
///////////////////////////////////

// artistOver - mouse-over highlight on artist page
// array - an array of arrays for each artist in the section.
// id - the id of the object highlighted within that array
// refObj - make this box show up relative to another object
// each array should contain the following name-value pairs:
// - desc - the artist short desc
// - name - the artist name
// - img - the artist's 75x75 image
// - edDesc - true/false value; if the desc. passed in is an editor's pick, true
function artistOver(array, id, refObj, refObjNewClass) {
    var body = "<div id=\"overArtist\"><div class=\"overArtistName\">" + array[id]["name"] + "</div>";
    body += "<div class=\"overArtistDesc\"><div class=\"source\">";
    if (array[id]["edDesc"] != null && array[id]["edDesc"] == "true") {
        body += "<img src=\"/i/mdl/global/e_bug.gif\" width=\"12\" height=\"12\" class=\"eIcon\"><b>EDITOR'S REVIEW:</b> ";
    } else {
        body += "<b>FROM THE ARTIST:</b> ";
    }
    body += "</div><img src=\"" + array[id]["img"] + "\" width=\"75\" height=\"75\" class=\"thumb\">";
    body += array[id]["desc"];
        body += "<div class=\"clearAll\"></div></div></div>";
    if (showPopUps != null && (showPopUps=="true" || showPopUps==true)) {
        for (i = 0; i < array.length; i++) {
            if (i == id) {
                changeClass('esa' + i,'edSugArtistOver');
            } else {
                changeClass('esa' + i,'edSugArtist');
            }
        }
    }
	if (refObj) {
		if (showPopUps != null && (showPopUps=="true" || showPopUps==true)) {
			return overlib(body, REF, refObj, REFP, 'UR', REFY, -5, REFX, -23, TEXTSIZE, '10px', TEXTCOLOR,'#000000', BGCOLOR, '#000000', FGCOLOR, '#EEEEEE', SHADOW, WIDTH, 250, BORDER, 0, TEXTPADDING, 0);
		}
	} else {
		if (showPopUps != null && (showPopUps=="true" || showPopUps==true)) {
			return overlib(body, VAUTO, HAUTO, OFFSETX, 22, TEXTSIZE, '10px', TEXTCOLOR,'#000000', BGCOLOR, '#000000', FGCOLOR, '#EEEEEE', SHADOW, WIDTH, 250, BORDER, 0);
		}
	}
}

function artistOut(id) {
        //setTimeout("changeClass('esa" + id + "','edSugArtist');", 200);
}

function toggleDesc (type) {
    if (type == "edRev") {
        changeClass('secondDescTab', 'tabNoSelect');
        changeClass('firstDescTab', 'tabSelect');
        changeClass('edRev', 'visible');
        changeClass('artistDesc', 'hidden');
        if (is_safari) {
            toggleText('descBody', 0, 0, -1);
        }
    } else if (type == "artBio") {
        changeClass('secondDescTab', 'tabSelect');
        changeClass('firstDescTab', 'tabNoSelect');
        changeClass('edRev', 'hidden');
        changeClass('artistDesc', 'visible');
        if (is_safari) {
            toggleText('descBody', 0, 0, 1);
        }
    }
}

function bookmarkThis(url, title) {
    var IE = navigator.appName.match(/(Microsoft Internet Explorer)/gi),
        NS = navigator.appName.match(/(Netscape)/gi),
        OP = navigator.appName.match(/(Opera)/gi);
    if(IE) {
        var url = location.href;
        var end = '.html';
        window.external.AddFavorite(url.substring(0,url.indexOf(end) + end.length) + '?tag=bookmark',document.title);
    } else if (OP || IE && !document.uniqueID) {
        alert('Your '+RegExp.$1+' browser requires that you\nPress Ctrl & T to Bookmark this page.');
    } else if(NS) {
        alert('Your '+RegExp.$1+' browser requires that you\nPress Ctrl & D to Bookmark this page.');
    } else {
       alert('Your browser doesn\'t allow bookmarks from a link.\nYou\'ll have to use your browser\'s own bookmark function.');
    }
}



function iframePopup (url, w, h, ref, center) {
    var body = "<div id=\"iframePopup\"><div id=\"popupWindowClose\"><a href=\"javascript:nd();void(0);\">close</a></div><div class=\"clearAll\"></div>";

    body += '<iframe src="' + url + '" name="iframePopupBody" id="iframePopupBody" width="' + w + '" height="' + h + '" frameborder="0"></iframe></div>';
    if (center != null && center == true) {
    return overlib(body, MIDX,0,MIDY,10, TEXTSIZE, '10px', TEXTCOLOR,'#000000', BGCOLOR, '#000000', FGCOLOR, '#505050', BORDER, 2, SHADOW, SHADOWCOLOR, '#333333', WIDTH, w, TEXTPADDING, 0);
    } else {
    return overlib(body, REF, ref, REFC,'UR', REFP, 'UR', REFY, 10, REFX, -20, TEXTSIZE, '10px', TEXTCOLOR,'#000000', BGCOLOR, '#000000', FGCOLOR, '#505050', BORDER, 2, SHADOW, SHADOWCOLOR, '#333333', WIDTH, w, TEXTPADDING, 0);
    }
}

	function popupNote (msg) {
		if (showPopUps && (showPopUps=="true" || showPopUps==true)) {
			overlib("<div class='NMS_message'>" + msg + "</div>", VCENTER, RIGHT, TEXTSIZE, "10px", SHADOW, DELAY, 500, WIDTH, "5", DELAY, 500);
		}
	}
	
	
//this next bit adds a call to the page to check wether or not this is a 404 redirect. if so, it throws up a warning
loadFunctions[loadFunctions.length] = new Function ("var loc = window.location; if(String(loc).indexOf('404=true')>0) {;var popupWarning = '<div id=\"popupWarning\"><a href=\"javascript:nd();void(0);\">close</a></div><a href=\"javascript:nd();void(0);\"><img src=\"http://music.download.com/i/mdl/global/timeout_warning.gif\" width=\"402\" height=\"74\" border=\"0\" style=\"border:3px solid #009\"></a>';overlib(popupWarning,MIDX,0,MIDY,0,TIMEOUT,6000,SHADOW);}");
