﻿function FDCPClient() {
    this.cpHost = "cache-01.cleanprint.net";
    this.divid = "2435";
    this.refid = "2361";
    this.rt = "i";
    this.cpstatus = false;
    this.ptstatus = "y";
    this.printSpecId = 0;
    this.outputFormat = "text/html";
    this.fdDebug = false;
    this.cpc = null;
    this.blkwidth = 0;
    this.xpathLib = "";
    this.shost = "formatdyn.hs.llnwd.net/e1";
    this.hosted = "customer";
    this.blockThreshold = 5000;
    this.trackerHost = "cleanprint.net";

    this.modes = { unset: 0, printLink: 1, filePrint: 2, printerFriendlyViewer: 3 };
    this.mode = 0; //modes.unset
    this.resetMode = function () { this.mode = this.modes.unset; };
    this.cookie_flags = "pv";
    this.category = "UNKNOWN";
    this.site = "UNKNOWN";

    // moved from the printtracker FormatDynamicsPT object
    this.pthosts = "formatdynamics.com,cleanprint.net,formatdyn.hs.llnwd.net";
    this.autoRefreshCSS = "true";
    this.autoRefreshTime = "30000";

    // quantcast tracking: n => turn off qc tracking, anything else leaves it on
    this.enableQC = "y";

    // templatetest var to pull templates from a directory
    this.templateTest = true;

    // 's' for standalone and 'c' for combined.  A standalone install turns off registration for
    // PrintTracker events
    this.insType = "c";

    this.colre = new RegExp(":", "g");
    this.comre = new RegExp(",", "g");

    this.isPtCss = function (content) {
        var phosts = this.pthosts.split(',');
        for (var i = 0; i < phosts.length; i++) {
            if (content.indexOf(phosts[i]) != -1)
                return true;
        }
        return false;
    }

    // templatetest var to pull templates from a directory
    this.templateTest = false;

    // 's' for standalone and 'c' for combined.  A standalone install turns off registration for
    // PrintTracker events
    this.insType = "c";

    this.escCom = function (st) {
        st = new st.constructor(st);
        st = st.replace(this.colre, "::");
        st = st.replace(this.comre, ":,");
        return st;
    }

    this.getSegment = function () {
        var seg1 = "Other";
        var seg2 = "Other";
        try {
            var s = document.getElementsByTagName("script");
            var r1 = new RegExp("cnn_money_position=728x90.*cnn_money_rollup=([^&]*)");
            var r2 = new RegExp("cnn_money_position=970x418.*cnn_money_rollup=([^&]*)");
            for (var i = 0; i < s.length; i++) {
                if (s[i].innerHTML.indexOf("cnnad_createAd") >= 0) {
                    var h = s[i].innerHTML;
                    if (h.match(r1)) {
                        var res = r1.exec(h);
                        seg1 = res[1];
                        break;
                    }
                    else if (h.match(r2)) {
                        var res = r2.exec(h);
                        seg1 = res[1];
                        break;
                    }
                }
            }
        } catch (e) {
        }
        var allATags = document.getElementsByTagName("a");
        for (var i = 0; i < allATags.length; i++) {
            var anATag = allATags[i];
            if (anATag.innerHTML == "Print" || anATag.innerHTML == "PRINT") {
                if (window.addEventListener) {
                    anATag.addEventListener("click", function () {
                        formatDynamicsPT.pf = "&p=1";
                        formatDynamicsPT.qstr = formatDynamicsPT.div + formatDynamicsPT.ua + formatDynamicsPT.seg + formatDynamicsPT.ustr + formatDynamicsPT.pf + formatDynamicsPT.version;
                        formatDynamicsPT.turl = formatDynamicsPT.pcol + formatDynamicsPT.cstr + formatDynamicsPT.dtstr + "?" + formatDynamicsPT.qstr;
                        formatDynamicsPT.getFDImage();
                    }, true);
                } else if (window.attachEvent) {
                    anATag.attachEvent("onclick", function () {
                        formatDynamicsPT.pf = "&p=1";
                        formatDynamicsPT.qstr = formatDynamicsPT.div + formatDynamicsPT.ua + formatDynamicsPT.seg + formatDynamicsPT.ustr + formatDynamicsPT.pf + formatDynamicsPT.version;
                        formatDynamicsPT.turl = formatDynamicsPT.pcol + formatDynamicsPT.cstr + formatDynamicsPT.dtstr + "?" + formatDynamicsPT.qstr;
                        formatDynamicsPT.getFDImage();
                    });
                }
            }
        }
        return seg1 + "," + seg2;
    }
    this.getCPViewerId = function () {

    }
    this.getPFF = function () {
        return "0";
    }

    this.getVR = function () {
        var rollupRegex = new RegExp("cnn_money_rollup=([^&]*)");
        var sectionRegex = new RegExp("cnn_money_section=([^&]*)");
        var subsectionRegex = new RegExp("cnn_money_subsection=([^&]*)");
        var rollup = "";
        var section = "";
        var subsection = "";
        var iframes = document.getElementsByTagName("iframe");
        for (var i = 0; i < iframes.length; i++) {
            if (iframes[i].src.indexOf("728x90") > 0 || iframes[i].src.indexOf("336x280") > 0) {
                if (iframes[i].src.indexOf("cnn_money_rollup") > 0) {
                    var rslt = iframes[i].src.match(rollupRegex);
                    if (rslt != null) {
                        rollup = rslt[1];
                    }
                }
                if (iframes[i].src.indexOf("cnn_money_section") > 0) {
                    var rslt = iframes[i].src.match(sectionRegex);
                    if (rslt != null) {
                        section = rslt[1];
                    }
                }
                if (iframes[i].src.indexOf("cnn_money_subsection") > 0) {
                    var rslt = iframes[i].src.match(subsectionRegex);
                    if (rslt != null) {
                        subsection = rslt[1];
                    }
                }
            }
            return { rollup: rollup, section: section, subsection: subsection };
        }
        for (var i = 0; i < iframes.length; i++) {
            if (iframes[i].src.indexOf("cnn_money_rollup") > 0) {
                var rslt = iframes[i].src.match(rollupRegex);
                if (rslt != null) {
                    rollup = rslt[1];
                }
            }
            if (iframes[i].src.indexOf("cnn_money_section") > 0) {
                var rslt = iframes[i].src.match(sectionRegex);
                if (rslt != null) {
                    section = rslt[1];
                }
            }
            if (iframes[i].src.indexOf("cnn_money_subsection") > 0) {
                var rslt = iframes[i].src.match(subsectionRegex);
                if (rslt != null) {
                    subsection = rslt[1];
                }
            }
            if (rollup.length > 0 || section.length > 0 || subsection.length > 0) {
                return { rollup: rollup, section: section, subsection: subsection };
            }
        }
    }

    this.onPrint = function (cpdata) {
        if (window.location.href.indexOf("snapshots") > 0) {
            if (document.getElementById("magFeatSnapImg") == null) {
                cpdata.template = "7802";
                return;
            }
            if (document.getElementById("magFeatSnapImg") != null) {
                for (var i = 0; i < document.getElementById("magFeatSnapImg").childNodes.length; i++) {
                    if (document.getElementById("magFeatSnapImg").childNodes[i].nodeType == 1 && document.getElementById("magFeatSnapImg").childNodes[i].className == "snapImg") {
                        return;
                    }
                }
            }
            cpdata.template = "7802";
            return;
        }
        try {
            if (typeof cpProxyUrl != 'undefined') {
                if (cpProxyUrl.substring(0, 5) == "index") {
                    cpProxyUrl = window.location.protocol + "//" + window.location.hostname + "/index.php?plugin=cleanprint-lt&print=1";
                    FDCPLoader.FDCPClient.cpc.tPath = cpProxyUrl;
                    fdcp.tstr = cpProxyUrl;
                }
            }
        } catch (e) { }
    }

    this.getBlockThreshold = function () {
        return this.getCfg('blockThreshold', this.blockThreshold);
    }

    this.getCfg = function (ckey, cdef) {
        if (this.cpc != null && typeof this.cpc[ckey] != 'undefined')
            return this.cpc[ckey];
        return cdef;
    }

    this.getTHost = function () {
        if (this.shost.length > 0 && document.location.protocol == "https:")
            return this.shost;
        else
            return this.cpHost;
    }
    this.getTrackerHost = function () {
        return this.trackerHost;
    }
    this.getcpStat = function () { return this.getCfg('cpStatus', this.cpstatus); }
    this.getptStat = function () { return this.getCfg('ptStatus', this.ptstatus); }
    this.getDiv = function () { return this.getCfg('divisionId', this.divid); }
    this.getOutputFormat = function () { return this.getCfg('mimeType', this.outputFormat); }
    this.getTmpl = function () { return this.getCfg('templateId', null); }
    this.getRfmt = function () { return this.getCfg('templateId', this.refid); }
    this.getTPath = function () { return this.getCfg('tPath', null); }
    this.getLPath = function () { return this.getCfg('lPath', null); }
    this.getTO = function () { return this.getCfg('timeout', 10000); }
    this.getTemplateTest = function () { return this.getCfg('templateTest', this.templateTest); }
    this.getXpathLib = function () { return this.getCfg('xpathLib', this.xpathLib); }

    this.getAutoRefreshCSS = function () { return this.getCfg('autoRefreshCSS', this.autoRefreshCSS); }
    this.getAutoRefreshTime = function () { return this.getCfg('autoRefreshTime', this.autoRefreshTime); }
    this.getPtHosts = function () { return this.getCfg('pthosts', this.pthosts); }
    this.getFDDebug = function () { return this.getCfg('fdDebug', this.fdDebug); }

    this.getRType = function () {
        return this.rt;
    }

    this.getIframeUrls = function () {

    }

    this.onCpLoad = function () {
        try {
            if (window.navigator.userAgent.indexOf("MSIE") > 0 || window.navigator.userAgent.indexOf("Firefox") > 0) {
                var formatdynamics_dl_load = document.createElement('script');
                formatdynamics_dl_load.setAttribute('type', 'text/javascript');
                formatdynamics_dl_load.setAttribute('charset', 'utf-8');
                var st = 'http://cleanprint.net/cs/dl/script.jsp?unique=' + (new Date()).getTime();
                formatdynamics_dl_load.setAttribute('src', st);
                document.getElementsByTagName('body').item(0).appendChild(formatdynamics_dl_load);
            }
        } catch (e) { }
    }

    this.cpServletPath = document.location.protocol + "//" + this.getTHost() + "/cp/psj";
    this.logUrl = document.location.protocol + "//" + this.getTHost() + "/cp/l";

    this.getCalculatedPrintSpecId = function () {
        var pathname = window.location.pathname;
        if (window.location.href.indexOf("ttoam.com") > 0) {
            return false;
        }
        if (pathname.indexOf("bplive") >= 0) {
            return "390";
        }
        else if (pathname.indexOf("galleries") >= 0) {
            return "484";
        }
        else if (window.location.href.indexOf("stanleybing") > 0) {
            return "649";
        }
        else if (window.location.href.indexOf("blogs") > 0 || document.getElementById("cnnblogPage") != null) {
            return "427";
        }
        else if (pathname.indexOf("snapshots") > 0) {
            return "439";
        }
        else if (pathname.indexOf("/quote/") >= 0) {
            return "430";
        }
        else {
            if (typeof document.body.className == "undefined" || document.body.className == null || document.body.className.length == 0) {
                return "389";
            }
            else if (document.body.className == "cnnStoryPage") {
                return "477";
            }
            return "389";
        }
    }
    this.onBeforeContentSerialization = function () {

    }
    this.onAfterContentSerialization = function () {

    }
    this.onPrintSpecLoad = function () {

    }
    this.onBeforeCleanPrint = function (data) {
        try {
            if (window.location.href.indexOf("blogs") > 0 && data.indexOf("<!DOCTYPE") > 0) {
                data = data.substring(0, data.indexOf("<!DOCTYPE"));
            }
        }
        catch (e) {
        }
        return data;
    }
    this.calculateCacheKey = function () {
        return cacheKey;
    }

    this.onAfterCleanPrint = function () {

        // standard behavior
        if (this.enableQC == 'y')
            this.appendQC();

        // customizations

    }

    this.appendQC = function () {
    }

    this.getRequestObject = function () {
        var act = "Unknown";
        if (this.mode == this.modes.filePrint) {
            act = "Chrome";
        } else if (this.mode == this.modes.printLink
                || this.mode == this.modes.printerFriendlyViewer) {
            act = "Link";
        }

        var logdata = {
            d: this.getDiv(),
            a: navigator.appName + " " + navigator.userAgent,
            s: this.getSegment(),
            u: window.location.href,
            p: this.getPFF(),
            r: this.getRfmt(),
            q: "1.0",
            template: this.getTmpl(),
            act: act
        };
        return logdata;
    }
}

function FormatDynamicsPT(client) {
    this.clnt = client;
    this.pcol = document.location.protocol + "//";
    this.cstr = client.getTrackerHost() + "/pt/t/";
    this.div = "d=" + this.clnt.getDiv();
    this.ua = "&a=" + escape(navigator.appName + " " + navigator.userAgent);
    this.seg = "&s=" + escape(this.clnt.getSegment());
    this.ustr = "&u=" + escape(window.location.href);
    this.pf = "&p=" + this.clnt.getPFF();
    this.version = "&q=1.1";
    this.rtype = "&rt=" + this.clnt.getRType();
    this.qstr = this.div + this.ua + this.seg + this.ustr + this.pf + this.version;
    this.pthosts = this.clnt.getPtHosts();
    this.autoRefreshCSS = this.clnt.getAutoRefreshCSS();
    this.autoRefreshTime = this.clnt.getAutoRefreshTime();
    this.cssRefreshInterval = null;
    this.rcount = 0;
    this.ptssfound = false;

    this.getTURL = function () {
        return this.pcol + this.cstr + (new Date()).getTime() + '?' + this.qstr;
    }

    this.isPtCss = function (content) {
        var phosts = this.pthosts.split(',');
        for (var i = 0; i < phosts.length; i++) {
            if (content.indexOf(phosts[i]) != -1)
                return true;
        }
        return false;
    }

    this.changePrintStyleSheet = function () {

        this.rcount++;

        // Change fdprint stylesheet if found
        for (i = 0; i < document.styleSheets.length; i++) {
            try {
                var sheet = document.styleSheets[i];
                var agent = navigator.userAgent.toLowerCase();

                if ((navigator.appName.indexOf("Netscape") != -1 || agent.indexOf("firefox") != -1 || agent.indexOf("safari") != -1) && this.isPtCss(sheet.cssRules[0].style.content)) {
                    sheet.cssRules[0].style.content = "url(" + this.getTURL() + ")";
                    return;
                }
                else {
                    if (this.isPtCss(sheet.cssRules[0].style.getPropertyValue('content'))) {
                        if (navigator.appName.indexOf("Opera") != -1) {
                            sheet.deleteRule(0);
                        }
                        else if (navigator.appName.indexOf("Konqueror") == -1) {
                            sheet.cssRules[0].style.setProperty('content', 'url(' + this.getTURL() + ')', null);
                        }
                        return;
                    }
                }
            }
            catch (err) { }
        }

        // otherwise insert the stylesheet
        if (this.rcount == 1) {
            try {
                var agent = navigator.userAgent.toLowerCase();
                if ((navigator.appName.indexOf("Netscape") != -1 || agent.indexOf("firefox") != -1 || agent.indexOf("safari") != -1)) {
                    var s = document.createElement("style");
                    s.type = "text/css";
                    s.rel = "stylesheet";
                    s.media = "print";
                    s.appendChild(document.createTextNode("body:after {content: url(" + this.getTURL() + ")};"));
                    document.getElementsByTagName("head")[0].appendChild(s);
                }
            }
            catch (err) { }
        }
        else {
            formatDynamicsPT.autoRefreshCSS = "false";
        }
    }

    this.getFDImage = function () {

        // rtype of 's' is a script-based load and 'i' is an image-based load
        if (this.clnt.getRType() == 's') {
            var hs = document.documentElement.getElementsByTagName("head");
            var h = null;

            if (hs && hs.length > 0) {
                h = hs[0];
                var script = document.createElement("script");
                script.type = 'text/javascript';
                script.src = this.getTURL() + '&rnd=' + Math.random();
            }
        }
        else {
            var fdloader = new Image();
            fdloader.src = this.getTURL();
        }
    }

    this.initIE = function () {
        try {
            if (navigator.appName.indexOf("Microsoft") != -1 && parseInt(navigator.appVersion) >= 4 && navigator.userAgent.indexOf("Windows") != -1)
                window.attachEvent("onbeforeprint", function () { formatDynamicsPT.getFDImage(); });
        }
        catch (e)
        { }
    }

    this.initX = function () {
        try {
            if (navigator.appName.indexOf("Konqueror") != -1) {
                formatDynamicsPT.changePrintStyleSheet();
            }
            else if (navigator.appName.indexOf("Microsoft") == -1) {
                formatDynamicsPT.changePrintStyleSheet();
                formatDynamicsPT.cssRefreshInterval = setInterval("formatDynamicsPT.refreshCSS()", formatDynamicsPT.autoRefreshTime);
            }
        }
        catch (e)
        { }
    }

    this.initAll = function () {
        try {
            this.initIE();
            this.initX();
        }
        catch (e)
        { }
    }

    this.refreshCSS = function () {
        if (formatDynamicsPT.autoRefreshCSS == "true")
            formatDynamicsPT.changePrintStyleSheet();
        else
            clearInterval(formatDynamicsPT.cssRefreshInterval);
    }
}
// TODO: add 'script' mode back. also add 'auto' mode to load everything without waiting
// TODO: run through rhino
// TODO: in the print spec js, we use '1' and '0', 'y' and 'n' and true and false for boolean values. clean this up.
var FDCPLoader = {

    count: 0,
    tint: 500,
    tmax: 10000,
    tagg: 0,
    incyc: false,
    loaded: false, // TODO: rename to printSpecLoaded?
    divId: 0, // TODO: redundant
    printSpecId: 0, // TODO: have a PrintSpec class? In any case, isn't needed as an instance var
    cpDef: {}, // TODO: can print spec come back as a JSON object?
    FDCPClient: new FDCPClient(),
    printPreviewWindow: null, // TODO: remove
    printPreviewWindowOpen: false, // TODO: remove
    tester: false, // TODO: still used?
    slre: new RegExp("[^/]*$"),

    // TODO: this should go away
    getCfg: function (ckey, cdef) {
        if (this.cpc != null && typeof this.cpc[ckey] != 'undefined')
            return this.cpc[ckey];
        return cdef;
    },

    loadcp: function () {

        if (typeof FDCPLoader.FDCPClient.onPrintSpecLoad != "undefined") {
            FDCPLoader.FDCPClient.onPrintSpecLoad();
        }

        // TODO: this is stupid
        this.cpc = FDCPLoader.FDCPClient.cpc;

        if (this.cpc.cpStatus == 'n') {
            FDCPLoader.tagg = FDCPLoader.tmax + 1;
            return;
        }

        var jsloc = this.FDCPClient.cpc.codeBase;

        if (jsloc == null || jsloc.length == 0) {
            jsloc = document.location.protocol + '//' + this.FDCPClient.trackerHost + '/cpjs';

            jsloc += "?d=" + FDCPLoader.FDCPClient.divid +
                "&bn=" + FDCPLoader.browserDetect.browser +
                "&bv=" + FDCPLoader.browserDetect.version +
                "&fs=" + (FDCPLoader.hasFlash() ? "true" : "false") +
                "&rp=" + FDCPLoader.FDCPClient.cpc.rpOk
        }

        var e = document.createElement('script');

        // TODO: assume a good codeBase value and get rid of this call
        e.src = this.validatePath(jsloc, "cp.js");
        e.type = 'text/javascript';
        document.getElementsByTagName("head")[0].appendChild(e);

        this.loadXPathLib();
    },

    loadFFjs: function () {

        if (FDCPLoader.FDCPClient.cpc.cpStatus == 'n') {
            FDCPLoader.tagg = FDCPLoader.tmax + 1;
            return;
        }

        var jsloc = this.getCfg('codeBase', null);
        jsloc = this.removeFileFromPath(jsloc, "cp.js");

        var e = document.createElement('script');
        e.src = this.validatePath(jsloc, "FDFF.js");
        e.type = 'text/javascript';
        document.getElementsByTagName("head")[0].appendChild(e);

        setTimeout(function (thisObj) { thisObj.checkFFjs(false); }, 2000, this);
    },

    checkFFjs: function (expire) {

        if (expire)
            return false;

        if (typeof FDFF == 'undefined')
            setTimeout(function (thisObj) { thisObj.checkFFjs(true); }, 2000, this);
        else
            FDFF.load();
    },

    // TODO: needs cleanup
    loadXPathLib: function () {

        if (navigator.appName == "Microsoft Internet Explorer") {
            var xpathUrl = null;

            if (typeof this.FDCPClient.xpathLib == "undefined" || this.FDCPClient.xpathLib == null || this.FDCPClient.xpathLib == "") {
                // TODO: xpath.js never used in cpc, get rid of this call
                xpathUrl = this.getCfg('xpathLib', null);

                if (xpathUrl == null) {
                    xpathUrl = this.getCfg('codeBase', null);
                    xpathUrl = this.removeFileFromPath(xpathUrl, "cp.js");
                }
            }
            else
                xpathUrl = this.FDCPClient.xpathLib;

            var e = document.createElement('script');

            e.src = this.validatePath(xpathUrl, "xpath.js");
            e.type = 'text/javascript';
            document.getElementsByTagName("head")[0].appendChild(e);
        }
        else {
            if (navigator.userAgent.indexOf("Firefox") != -1) {
                //FDCPLoader.loadFFjs();
            }
        }
    },

    removeFileFromPath: function (path, file) {

        if (path.indexOf(file) > 1) {
            var lastSlashIndex = path.search(this.slre);
            return path.substr(0, lastSlashIndex);
        }
        else {
            return path;
        }
    },

    getPDScriptUrl: function () {

        var snodes = document.getElementsByName('cleanprintloader');
        var url = "";

        if (snodes.length > 0) {
            url = snodes[0].src;
        }
        else {

            snodes = document.getElementsByTagName('SCRIPT');

            for (var i = 0; i < snodes.length; i++) {
                if (snodes[i].name == 'cleanprintloader') {
                    url = snodes[i].src;
                    break;
                }
            }
        }

        return url;
    },


    loadPrintSpec: function () {

        try {
            formatDynamicsPT = new FormatDynamicsPT(new FDCPClient());
            formatDynamicsPT.initX();

            var psfailed = false;

            if (!this.loaded) {
                this.loaded = true; // TODO: shouldn't we set this after a successful load?
                var pdSrc = this.getPDScriptUrl();

                // TODO: is this still necessary?
                if (this.FDCPClient.hosted == "fd" && pdSrc.length > 0)
                    this.divId = this.getDivisionId(pdSrc);
                else
                    this.divId = this.FDCPClient.divid;

                // TODO: get this from the client now
                this.printSpecId = this.getPrintSpecId(pdSrc);

                var url = this.FDCPClient.cpServletPath;
                url += "?useCache=false";
                url += "&divId=" + this.divId;

                var psid = null;

                // TODO: this function is now required. clean up this logic accordingly
                if (typeof this.FDCPClient.getCalculatedPrintSpecId != "undefined" && this.tester == false) {
                    try {
                        psid = this.FDCPClient.getCalculatedPrintSpecId();

                        if (psid == false) {
                            psfailed = true;
                        }
                    }
                    catch (err) {
                        psfailed = true;
                    }
                }

                if (psfailed) {
                    // TODO: can we always register the PT handler, and disable by setting a flag on fdcp or something? then we don't need to mess with this logic on all cp load failures
                    formatDynamicsPT.initIE();
                }
                else {
                    url += "&printSpecId=" + ((typeof psid == 'undefined' || psid == null) ? this.printSpecId : psid);

                    var cpDefScript = document.createElement('script');
                    cpDefScript.src = url;
                    cpDefScript.type = 'text/javascript';
                    document.getElementsByTagName("head")[0].appendChild(cpDefScript);
                }
            }
        }
        catch (e) {
            // TODO: something. anything. 
        }
    },

    // TODO: get rid of this
    validatePath: function (path, jsFile) {
        if (path.indexOf(jsFile) > 1)
            return path;
        else {
            if (path.charAt(path.length - 1) == "/")
                return path + jsFile;
            else
                return path + "/" + jsFile;
        }
    },

    // TODO: get rid of this?
    getPrintSpecId: function (pdSrc) {
        var pdre = new RegExp("^[^?]+\\??");
        var queryString = pdSrc.replace(pdre, '');

        var params = this.parseQuery(queryString);

        return params['ps'];

    },

    // TODO: get rid of this
    getDivisionId: function (pdSrc) {
        var tmpUrl = pdSrc.replace(this.slre, "");
        var lastSlashIndex = tmpUrl.search(this.slre);
        var divId = tmpUrl.substr(0, lastSlashIndex - 1);
        lastSlashIndex = divId.search(this.slre);
        divId = divId.substr(lastSlashIndex, divId.length);

        return divId;
    },

    // TODO: get rid of this if you get rid of getPrintSpecId
    parseQuery: function (query) {
        var Params = new Object();
        if (!query) return Params; // return empty object
        var pre = new RegExp("[;&]");
        var plusre = new RegExp("\\+", "g");
        var Pairs = query.split(pre);
        for (var i = 0; i < Pairs.length; i++) {
            var KeyVal = Pairs[i].split('=');
            if (!KeyVal || KeyVal.length != 2) continue;
            var key = unescape(KeyVal[0]);
            var val = unescape(KeyVal[1]);
            val = val.replace(plusre, ' ');
            Params[key] = val;
        }
        return Params;
    },

    cpJsLoaded: false,
    xpathJsLoaded: navigator.appName != "Microsoft Internet Explorer",
    registerModuleLoaded: function (moduleName) {
        if (moduleName == "cp.js") {
            this.cpJsLoaded = true;
        }
        else if (moduleName == "xpath.js") {
            this.xpathJsLoaded = true;
        }
        if (this.xpathJsLoaded && this.cpJsLoaded) {
            fdcp.replacePrintLinks();
        }
    },

    fdPrintWrapper: function (theContext) {
        theContext = typeof theContext == "undefined" ? window : theContext;
        theContext.print();
    },

    // TODO: still used?
    ptFailover: function () {
        formatDynamicsPT = new FormatDynamicsPT(new FDCPClient());
        formatDynamicsPT.initAll();
    },

    hasFlash: function () {

        // Flash Player Version Detection - Rev 1.6
        // Detect Client Browser type
        // Copyright(c) 2005-2006 Adobe Macromedia Software, LLC. All rights reserved.
        var nn = navigator;
        var np = nn.plugins;
        var isIE = (nn.appVersion.indexOf("MSIE") != -1) ? true : false;
        var isWin = (nn.appVersion.toLowerCase().indexOf("win") != -1) ? true : false;
        var isOpera = (nn.userAgent.indexOf("Opera") != -1) ? true : false;

        // NS/Opera version >= 3 check for Flash plugin in plugin array
        var flashVer;

        if (nn.plugins != null && np.length > 0) {
            if (np["Shockwave Flash 2.0"] || np["Shockwave Flash"]) {
                var swVer2 = np["Shockwave Flash 2.0"] ? " 2.0" : "";
                var descArray = np["Shockwave Flash" + swVer2].description.split(" ");
                var tempArrayMajor = descArray[2].split(".");
                flashVer = tempArrayMajor[0] > 5 ? tempArrayMajor[0] : -1;
            }
        }
        else if (isIE && isWin && !isOpera) {
            var axo;
            var e;

            // NOTE : new ActiveXObject(strFoo) throws an exception if strFoo isn't in the registry
            try {
                // version will be set for 7.X or greater players
                axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");
                flashVer = axo.GetVariable("$version");
            } catch (e) {
            }

            if (!flashVer) {
                try {
                    // version will be set for 6.X players only
                    axo = new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");
                    flashVer = "6";
                } catch (e) {
                }
            }
        }

        return flashVer && flashVer > 0;
    },

    browserDetect: {
        init: function () {
            this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
            this.version = this.searchVersion(navigator.userAgent)
                    || this.searchVersion(navigator.appVersion)
                    || "an unknown version";
            this.OS = this.searchString(this.dataOS) || "an unknown OS";
        },
        searchString: function (data) {
            for (var i = 0; i < data.length; i++) {
                var dataString = data[i].string;
                var dataProp = data[i].prop;
                this.versionSearchString = data[i].versionSearch || data[i].identity;
                if (dataString) {
                    if (dataString.indexOf(data[i].subString) != -1)
                        return data[i].identity;
                }
                else if (dataProp)
                    return data[i].identity;
            }
        },
        searchVersion: function (dataString) {
            var index = dataString.indexOf(this.versionSearchString);
            if (index == -1) return;
            return parseFloat(dataString.substring(index + this.versionSearchString.length + 1));
        },
        dataBrowser: [
                {
                    string: navigator.userAgent,
                    subString: "Chrome",
                    identity: "Chrome"
                },
                { string: navigator.userAgent,
                    subString: "OmniWeb",
                    versionSearch: "OmniWeb/",
                    identity: "OmniWeb"
                },
                {
                    string: navigator.vendor,
                    subString: "Apple",
                    identity: "Safari",
                    versionSearch: "Version"
                },
                {
                    prop: window.opera,
                    identity: "Opera"
                },
                {
                    string: navigator.vendor,
                    subString: "iCab",
                    identity: "iCab"
                },
                {
                    string: navigator.vendor,
                    subString: "KDE",
                    identity: "Konqueror"
                },
                {
                    string: navigator.userAgent,
                    subString: "Firefox",
                    identity: "Firefox"
                },
                {
                    string: navigator.vendor,
                    subString: "Camino",
                    identity: "Camino"
                },
                {       // for newer Netscapes (6+)
                    string: navigator.userAgent,
                    subString: "Netscape",
                    identity: "Netscape"
                },
                {
                    string: navigator.userAgent,
                    subString: "MSIE",
                    identity: "Explorer",
                    versionSearch: "MSIE"
                },
                {
                    string: navigator.userAgent,
                    subString: "Gecko",
                    identity: "Mozilla",
                    versionSearch: "rv"
                },
                {       // for older Netscapes (4-)
                    string: navigator.userAgent,
                    subString: "Mozilla",
                    identity: "Netscape",
                    versionSearch: "Mozilla"
                }
            ],
        dataOS: [
                {
                    string: navigator.platform,
                    subString: "Win",
                    identity: "Windows"
                },
                {
                    string: navigator.platform,
                    subString: "Mac",
                    identity: "Mac"
                },
                {
                    string: navigator.userAgent,
                    subString: "iPhone",
                    identity: "iPhone/iPod"
                },
                {
                    string: navigator.platform,
                    subString: "Linux",
                    identity: "Linux"
                }
            ]

    }
}

FDCPLoader.browserDetect.init();

function FDCPUrl(pfLink, isViewer) {

    try {
        isViewer = typeof isViewer == "undefined" ? false : isViewer;

        if (isViewer && (typeof pfLink == "undefined" || pfLink == null || pfLink == '')) {

            // TODO: shouldn't this just do a window.print()?
            return false;
        }

        if (typeof fdcp == 'undefined') {

            // TODO: what if incyc is already true?
            if (FDCPLoader.incyc == false)
                FDCPLoader.incyc = true;

            if (FDCPLoader.tagg > FDCPLoader.tmax) {

                FDCPLoader.incyc = false;
                FDCPLoader.fdPrintWrapper();
                FDCPLoader.tagg = 0;
                return false;
            }

            FDCPLoader.tagg += FDCPLoader.tint;

            setTimeout("FDCPUrl('" + pfLink + "', " + isViewer + ")", FDCPLoader.tint);

            return false;
        }
        else
            FDCPLoader.incyc = false;

        if (isViewer) {
            var continueCp = FDCPLoader.browserDetect.browser == "Firefox" || FDCPLoader.browserDetect.browser == "Explorer" || (FDCPLoader.browserDetect.browser == "Safari" && FDCPLoader.browserDetect.OS == "Mac");

            if (!continueCp) {
                window.open(pfLink, "pf", "");
                return false;
            }
        }

        fdcp.clt.mode = isViewer ? fdcp.clt.modes.printerFriendlyViewer : fdcp.clt.modes.printLink;
        fdcp.linkPrintHandler(pfLink);

        // TODO: why not use the browserDetect object?
        if (navigator.appName != "Microsoft Internet Explorer") {
            fdcp.clt.resetMode();
        }

        return false;
    }
    catch (e)
    { }
}

// a simple ajax object getter
function fdGetAjaxObj() {
    if (window.XMLHttpRequest) {
        return new XMLHttpRequest(); //Not IE
    } else if (window.ActiveXObject) {
        return new ActiveXObject("Microsoft.XMLHTTP"); //IE
    } else {
        // TODO: check to see if there are others we need to support
        return null;
    }
}

if (window.addEventListener) {
    window.addEventListener("load", function () { FDCPLoader.loadPrintSpec(); }, true);
}
else if (window.attachEvent) {
    window.attachEvent("onload", function () { FDCPLoader.loadPrintSpec(); });
}
