/* Source: topspin_purchase.js, as of Mon Oct 26 14:15:37 -0700 2009 */

TSConfig = {
    CDN_URL: "http://cdn.topspin.net/",
    APP_URL: "http://app.topspin.net/",
    SSL_APP_URL: "https://app.topspin.net/",
    BEACON_URL: "http://px.topspin.net/px/"
};


/* Source: /var/www/apps/topspin/releases/20091026183912/public/javascripts/TSPurchase.js, last modified at Mon Oct 26 11:40:28 -0700 2009 */
// Do not execute the contents of this file if TSPurchase has already been
// initialized; this is done to prevent redundant processing when this file
// has been included more than once on the same page.
if (!window.TSPurchase) {

/* SWFOBJECT */
/*
 * SWFObject v2.0 <http://code.google.com/p/swfobject/>
 * Copyright (c) 2007 Geoff Stearns, Michael Williams, and Bobby van der Sluis
 * This software is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
 */
var swfobject=function(){var Z="undefined",P="object",B="Shockwave Flash",h="ShockwaveFlash.ShockwaveFlash",W="application/x-shockwave-flash",K="SWFObjectExprInst",G=window,g=document,N=navigator,f=[],H=[],Q=null,L=null,T=null,S=false,C=false;var a=function(){var l=typeof g.getElementById!=Z&&typeof g.getElementsByTagName!=Z&&typeof g.createElement!=Z&&typeof g.appendChild!=Z&&typeof g.replaceChild!=Z&&typeof g.removeChild!=Z&&typeof g.cloneNode!=Z,t=[0,0,0],n=null;if(typeof N.plugins!=Z&&typeof N.plugins[B]==P){n=N.plugins[B].description;if(n){n=n.replace(/^.*\s+(\S+\s+\S+$)/,"$1");t[0]=parseInt(n.replace(/^(.*)\..*$/,"$1"),10);t[1]=parseInt(n.replace(/^.*\.(.*)\s.*$/,"$1"),10);t[2]=/r/.test(n)?parseInt(n.replace(/^.*r(.*)$/,"$1"),10):0}}else{if(typeof G.ActiveXObject!=Z){var o=null,s=false;try{o=new ActiveXObject(h+".7")}catch(k){try{o=new ActiveXObject(h+".6");t=[6,0,21];o.AllowScriptAccess="always"}catch(k){if(t[0]==6){s=true}}if(!s){try{o=new ActiveXObject(h)}catch(k){}}}if(!s&&o){try{n=o.GetVariable("$version");if(n){n=n.split(" ")[1].split(",");t=[parseInt(n[0],10),parseInt(n[1],10),parseInt(n[2],10)]}}catch(k){}}}}var v=N.userAgent.toLowerCase(),j=N.platform.toLowerCase(),r=/webkit/.test(v)?parseFloat(v.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,i=false,q=j?/win/.test(j):/win/.test(v),m=j?/mac/.test(j):/mac/.test(v);/*@cc_on i=true;@if(@_win32)q=true;@elif(@_mac)m=true;@end@*/return{w3cdom:l,pv:t,webkit:r,ie:i,win:q,mac:m}}();var e=function(){if(!a.w3cdom){return }J(I);if(a.ie&&a.win){try{g.write("<script id=__ie_ondomload defer=true src=//:><\/script>");var i=c("__ie_ondomload");if(i){i.onreadystatechange=function(){if(this.readyState=="complete"){this.parentNode.removeChild(this);V()}}}}catch(j){}}if(a.webkit&&typeof g.readyState!=Z){Q=setInterval(function(){if(/loaded|complete/.test(g.readyState)){V()}},10)}if(typeof g.addEventListener!=Z){g.addEventListener("DOMContentLoaded",V,null)}M(V)}();function V(){if(S){return }if(a.ie&&a.win){var m=Y("span");try{var l=g.getElementsByTagName("body")[0].appendChild(m);l.parentNode.removeChild(l)}catch(n){return }}S=true;if(Q){clearInterval(Q);Q=null}var j=f.length;for(var k=0;k<j;k++){f[k]()}}function J(i){if(S){i()}else{f[f.length]=i}}function M(j){if(typeof G.addEventListener!=Z){G.addEventListener("load",j,false)}else{if(typeof g.addEventListener!=Z){g.addEventListener("load",j,false)}else{if(typeof G.attachEvent!=Z){G.attachEvent("onload",j)}else{if(typeof G.onload=="function"){var i=G.onload;G.onload=function(){i();j()}}else{G.onload=j}}}}}function I(){var l=H.length;for(var j=0;j<l;j++){var m=H[j].id;if(a.pv[0]>0){var k=c(m);if(k){H[j].width=k.getAttribute("width")?k.getAttribute("width"):"0";H[j].height=k.getAttribute("height")?k.getAttribute("height"):"0";if(O(H[j].swfVersion)){if(a.webkit&&a.webkit<312){U(k)}X(m,true)}else{if(H[j].expressInstall&&!C&&O("6.0.65")&&(a.win||a.mac)){D(H[j])}else{d(k)}}}}else{X(m,true)}}}function U(m){var k=m.getElementsByTagName(P)[0];if(k){var p=Y("embed"),r=k.attributes;if(r){var o=r.length;for(var n=0;n<o;n++){if(r[n].nodeName.toLowerCase()=="data"){p.setAttribute("src",r[n].nodeValue)}else{p.setAttribute(r[n].nodeName,r[n].nodeValue)}}}var q=k.childNodes;if(q){var s=q.length;for(var l=0;l<s;l++){if(q[l].nodeType==1&&q[l].nodeName.toLowerCase()=="param"){p.setAttribute(q[l].getAttribute("name"),q[l].getAttribute("value"))}}}m.parentNode.replaceChild(p,m)}}function F(i){if(a.ie&&a.win&&O("8.0.0")){G.attachEvent("onunload",function(){var k=c(i);if(k){for(var j in k){if(typeof k[j]=="function"){k[j]=function(){}}}k.parentNode.removeChild(k)}})}}function D(j){C=true;var o=c(j.id);if(o){if(j.altContentId){var l=c(j.altContentId);if(l){L=l;T=j.altContentId}}else{L=b(o)}if(!(/%$/.test(j.width))&&parseInt(j.width,10)<310){j.width="310"}if(!(/%$/.test(j.height))&&parseInt(j.height,10)<137){j.height="137"}g.title=g.title.slice(0,47)+" - Flash Player Installation";var n=a.ie&&a.win?"ActiveX":"PlugIn",k=g.title,m="MMredirectURL="+G.location+"&MMplayerType="+n+"&MMdoctitle="+k,p=j.id;if(a.ie&&a.win&&o.readyState!=4){var i=Y("div");p+="SWFObjectNew";i.setAttribute("id",p);o.parentNode.insertBefore(i,o);o.style.display="none";G.attachEvent("onload",function(){o.parentNode.removeChild(o)})}R({data:j.expressInstall,id:K,width:j.width,height:j.height},{flashvars:m},p)}}function d(j){if(a.ie&&a.win&&j.readyState!=4){var i=Y("div");j.parentNode.insertBefore(i,j);i.parentNode.replaceChild(b(j),i);j.style.display="none";G.attachEvent("onload",function(){j.parentNode.removeChild(j)})}else{j.parentNode.replaceChild(b(j),j)}}function b(n){var m=Y("div");if(a.win&&a.ie){m.innerHTML=n.innerHTML}else{var k=n.getElementsByTagName(P)[0];if(k){var o=k.childNodes;if(o){var j=o.length;for(var l=0;l<j;l++){if(!(o[l].nodeType==1&&o[l].nodeName.toLowerCase()=="param")&&!(o[l].nodeType==8)){m.appendChild(o[l].cloneNode(true))}}}}}return m}function R(AE,AC,q){var p,t=c(q);if(typeof AE.id==Z){AE.id=q}if(a.ie&&a.win){var AD="";for(var z in AE){if(AE[z]!=Object.prototype[z]){if(z=="data"){AC.movie=AE[z]}else{if(z.toLowerCase()=="styleclass"){AD+=' class="'+AE[z]+'"'}else{if(z!="classid"){AD+=" "+z+'="'+AE[z]+'"'}}}}}var AB="";for(var y in AC){if(AC[y]!=Object.prototype[y]){AB+='<param name="'+y+'" value="'+AC[y]+'" />'}}t.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+AD+">"+AB+"</object>";F(AE.id);p=c(AE.id)}else{if(a.webkit&&a.webkit<312){var AA=Y("embed");AA.setAttribute("type",W);for(var x in AE){if(AE[x]!=Object.prototype[x]){if(x=="data"){AA.setAttribute("src",AE[x])}else{if(x.toLowerCase()=="styleclass"){AA.setAttribute("class",AE[x])}else{if(x!="classid"){AA.setAttribute(x,AE[x])}}}}}for(var w in AC){if(AC[w]!=Object.prototype[w]){if(w!="movie"){AA.setAttribute(w,AC[w])}}}t.parentNode.replaceChild(AA,t);p=AA}else{var s=Y(P);s.setAttribute("type",W);for(var v in AE){if(AE[v]!=Object.prototype[v]){if(v.toLowerCase()=="styleclass"){s.setAttribute("class",AE[v])}else{if(v!="classid"){s.setAttribute(v,AE[v])}}}}for(var u in AC){if(AC[u]!=Object.prototype[u]&&u!="movie"){E(s,u,AC[u])}}t.parentNode.replaceChild(s,t);p=s}}return p}function E(k,i,j){var l=Y("param");l.setAttribute("name",i);l.setAttribute("value",j);k.appendChild(l)}function c(i){return g.getElementById(i)}function Y(i){return g.createElement(i)}function O(k){var j=a.pv,i=k.split(".");i[0]=parseInt(i[0],10);i[1]=parseInt(i[1],10);i[2]=parseInt(i[2],10);return(j[0]>i[0]||(j[0]==i[0]&&j[1]>i[1])||(j[0]==i[0]&&j[1]==i[1]&&j[2]>=i[2]))?true:false}function A(m,j){if(a.ie&&a.mac){return }var l=g.getElementsByTagName("head")[0],k=Y("style");k.setAttribute("type","text/css");k.setAttribute("media","screen");if(!(a.ie&&a.win)&&typeof g.createTextNode!=Z){k.appendChild(g.createTextNode(m+" {"+j+"}"))}l.appendChild(k);if(a.ie&&a.win&&typeof g.styleSheets!=Z&&g.styleSheets.length>0){var i=g.styleSheets[g.styleSheets.length-1];if(typeof i.addRule==P){i.addRule(m,j)}}}function X(k,i){var j=i?"visible":"hidden";if(S){c(k).style.visibility=j}else{A("#"+k,"visibility:"+j)}}return{registerObject:function(l,i,k){if(!a.w3cdom||!l||!i){return }var j={};j.id=l;j.swfVersion=i;j.expressInstall=k?k:false;H[H.length]=j;X(l,false)},getObjectById:function(l){var i=null;if(a.w3cdom&&S){var j=c(l);if(j){var k=j.getElementsByTagName(P)[0];if(!k||(k&&typeof j.SetVariable!=Z)){i=j}else{if(typeof k.SetVariable!=Z){i=k}}}}return i},embedSWF:function(n,u,r,t,j,m,k,p,s){if(!a.w3cdom||!n||!u||!r||!t||!j){return }r+="";t+="";if(O(j)){X(u,false);var q=(typeof s==P)?s:{};q.data=n;q.width=r;q.height=t;var o=(typeof p==P)?p:{};if(typeof k==P){for(var l in k){if(k[l]!=Object.prototype[l]){if(typeof o.flashvars!=Z){o.flashvars+="&"+l+"="+k[l]}else{o.flashvars=l+"="+k[l]}}}}J(function(){R(q,o,u);if(q.id==u){X(u,true)}})}else{if(m&&!C&&O("6.0.65")&&(a.win||a.mac)){X(u,false);J(function(){var i={};i.id=i.altContentId=u;i.width=r;i.height=t;i.expressInstall=m;D(i)})}}},getFlashPlayerVersion:function(){return{major:a.pv[0],minor:a.pv[1],release:a.pv[2]}},hasFlashPlayerVersion:O,createSWF:function(k,j,i){if(a.w3cdom&&S){return R(k,j,i)}else{return undefined}},createCSS:function(j,i){if(a.w3cdom){A(j,i)}},addDomLoadEvent:J,addLoadEvent:M,getQueryParamValue:function(m){var l=g.location.search||g.location.hash;if(m==null){return l}if(l){var k=l.substring(1).split("&");for(var j=0;j<k.length;j++){if(k[j].substring(0,k[j].indexOf("="))==m){return k[j].substring((k[j].indexOf("=")+1))}}}return""},expressInstallCallback:function(){if(C&&L){var i=c(K);if(i){i.parentNode.replaceChild(L,i);if(T){X(T,true);if(a.ie&&a.win){L.style.display="block"}}L=null;T=null;C=false}}}}}();
/* END SWFOBJECT */

/* TSFLASH */
/**
 * Functions for embedding Flash elements on the page.
 * Flash movies currently in use must be recompiled to use the Flash methods.
 * Uses swfobject 2.0.
 */
TSFlash = {
    /**
     * Embeds a flash movie on the page. Requires a full path to the SWF, a container element,
     * and an options object. At a minimum, you need to pass options.width, options.height,
     * options.instance (a unique ID for the movie). If options.facing is not supplied, this
     * defaults to 'fan' facing, using fan redirects & min version standards. The other valid
     * option is currently 'artist'. Other optional params include options.redirectURL -- a custom
     * URL to redirect to that doesn't correspond to the stock fan- or artist- facing URL;
     * options.redirectParams -- appended to the end of the redirect URL.
     * If params are not supplied we will supply a high quality
     *
     * @param    swfName   the full path to the swf file to be embedded.
     * @param    container the element that the Flash movie will be embedded in.
     * @param    options   an object with options. Minimum requirement is width, height,
     *                     instanceName and loadParams.
     * @requires swfbject  swfobject 2.0 is required for embeds.
     */
    embed: function(swfName, container, options) {
        if (!options) {
            return;
        }
        if (typeof(options.params) == "undefined") {
		    options.params = {
		        quality: "high",
		        wmode: TSFlash.isLinux() ? "" : "transparent",
		        allowscriptaccess: "always",
		        menu: false
		    };
        }
        // redirect, etc have been pulled as swfobject 2.0 does not currently support it.
        // Variables should still be passed in but it's pulledfor lightness of code.
        swfobject.embedSWF(swfName, container, options.width, options.height, TSFlash.minVersion[options.facing], null, options.variables, options.params);
    },
    /**
     * Allows flash to call out to resize its parent container
     *
     * @param target        the id of element to be redimensioned
     * @param height        the new desired height
     * @param jsIdentifier  JS Identifier for widget making call
     */
    redimensionMovie: function(target, height, jsIdentifier){
        // TODO: convert to a JSON model of CSS atribs & values & change that way
        var elem = document.getElementById(target);
        height = parseInt(height) + 23;
        elem.style.height = height + "px";
        elem.parentNode.style.height = height + "px";
    },
    /**
     * Checks to see if minimum version of flash player is present for the supplied facing.
     * Assumes "fan" if no facing is supplied.
     *
     * @param  facing   the facing that needs to be checked for min flash version.
     * @return boolean  true if sufficient flash player version exists, false if not.
     */
    checkMinVersion: function(facing) {
        if (typeof(facing) == 'undefined') {
            facing = 'fan';
        }
        var version = swfobject.getFlashPlayerVersion();
        var reqVersions = TSFlash.minVersion[facing].split('.');
        var compatibleVersion = false;
        if (parseInt(version.major) > parseInt(reqVersions[0])) {
            // MAJ > MAJ -- compat
            compatibleVersion = true;
        } else {
            // check the minor version
            if (parseInt(version.minor) > parseInt(reqVersions[1]) && parseInt(version.major) == parseInt(reqVersions[0])) {
                // MAJ == MAJ; MIN > MIN -- compat
                compatibleVersion = true;
            } else {
                // check the revision
                if (parseInt(version.release) >= parseInt(reqVersions[2]) && parseInt(version.minor) == parseInt(reqVersions[1])) {
                    // MAJ == MAJ, MIN == MIN, REV > REV -- compat
                    compatibleVersion = true;
                }
            }
        }
        return compatibleVersion;
    },
    /**
     * Minimum flash versions needed for different areas of the site.
     */
    minVersion: {
        artist:"9.0.115",
        fan:"9.0.115"
    },
    isLinux: function() {
        var exp = /Linux/;
        return (exp.exec(navigator.platform));
    },
    /**
     * Javascript functions used by Flash players to transact. This may be moved to Widgets
     * eventually.
     */
    PlayerHooks: {
        /**
         * Transact is the primary player hook for flash and kicks off the purchase flow.
         *
         * @param JSONData  JSON string containing transactionMode (share or download),
         *                  event info, and APIDs to transact upon.
         */
        transact: function(JSONData) {
            var jsonObj = eval( "(" + JSONData + ")");
            (!jsonObj.jsIdentifier) ? ts_load_purch_flow(jsonObj.purchases, jsonObj.transactionMode) : ts_load_purch_flow(jsonObj.purchases, jsonObj.transactionMode, jsonObj.jsIdentifier);
        }
    }
};
/* END TSFLASH */
/* WIDGETS.JS */
/*
TODO: make getElementsByClassName faster
TODO: clean up error overlay
*/


/**
 * Namespace that wraps all widget code.
 */
var TSWidget = {
    /**
     * The Util namespace encompasses static utility functions that are either dependencies of
     * other classes, or are commonly used by the individual or general widget code.
     * Util encompasses DOM manipulation, logging and debugging, URL parsing, String manipulation
     * functions, and the like. In general most of this functionality has been developed elsewhere
     * and collected here.
     * It borrows heavily from the Prototype library and Peter Michaux's Fork library.
     */
    Util: {},
    /**
     * The Widgets namespace is used to declare functions and variables related
     * to displaying and managing widgets
     */
    Widgets: {},
    /**
     * The Config namespace is used to declare configuration variables.
     * These variables can be modified by widget users.
     * Any variables that are modified by deploy scripts should be declared here.
     */
    Config: {}
};


/**
 * This function adds the fields (and corresponding values) of the source to the destination.
 * It has many uses, like merging associative arrays, extending classes with new functionality,
 * and overwriting methods.
 * It is taken wholesale from the Prototype library (Object.extend).
 *
 * @param {Object} destination The object to be extended.
 * @param {Object} source The object whose fields are to be copied.
 * @return {Object} The destination object after extension.
 */
TSWidget.Util.extend = function(destination, source) {
    for (var property in source) {
        destination[property] = source[property];
    }
    return destination;
};


/* =====      TSWidget.Util      ===== */
TSWidget.Util.extend(TSWidget.Util, {

    getOverlayDimensions: function() {
        var windowWidth;
        var windowHeight;
        if (window.innerWidth) {
            // Not IE
            windowWidth = window.innerWidth;
            windowHeight = window.innerHeight;
        } else if (document.documentElement && document.documentElement.clientWidth) {
            // IE Strict Mode
            windowWidth = document.documentElement.clientWidth;
		    windowHeight = document.documentElement.clientHeight;
        } else {
            // Everyone else
            windowWidth = document.body.clientWidth;
            windowHeight = document.body.clientHeight;
        }

        var bodyWidth;
        var bodyHeight;
        if (window.innerHeight && window.scrollMaxY) {
            // Not IE
            bodyWidth = window.innerWidth + window.scrollMaxX;
            bodyHeight = window.innerHeight + window.scrollMaxY;
        } else if (document.body.scrollHeight > document.body.offsetHeight) {
            // All but IE mac
            bodyWidth = document.body.scrollWidth;
            bodyHeight = document.body.scrollHeight;
        } else {
            // Everyone else
            bodyWidth = document.body.offsetWidth;
            bodyHeight = document.body.offsetHeight;
        }

        var overlayWidth  = (windowWidth  > bodyWidth)  ? windowWidth  : bodyWidth;
        var overlayHeight = (windowHeight > bodyHeight) ? windowHeight : bodyHeight;

        /*
         * Returns the largest element on the page (in terms of pixel height)
         * regardless of display, position, or visibility CSS style settings
         */
        function getMaxElementHeight() {
            var arr = document.getElementsByTagName("*");
        	var max = 0;

        	function getDimensions(element) {
        	    var display = element.style.display;
        	    if (display != 'none' && display != null) { // Safari bug
        	        return {width: element.offsetWidth, height: element.offsetHeight};
                }
                // All *Width and *Height properties give 0 on elements with display none,
        	    // so enable the element temporarily
        	    var els = element.style;
                var originalVisibility = els.visibility;
        	    var originalPosition = els.position;
        	    var originalDisplay = els.display;
        	    els.visibility = 'hidden';
        	    els.position = 'absolute';
        	    els.display = 'block';
        	    var originalWidth = element.clientWidth;
        	    var originalHeight = element.clientHeight;
        	    els.display = originalDisplay;
        	    els.position = originalPosition;
        	    els.visibility = originalVisibility;
        	    return { width: originalWidth, height: originalHeight };
        	};

        	for (var i=0; i < arr.length; i++) {
        		var h = getDimensions(arr[i]).height;
        		if (h > max) { max = h; }
        	}

            return max;
        };

        if (bodyHeight == 0 || bodyHeight == windowHeight) {
            overlayHeight = getMaxElementHeight();
        }

        var overlayDimensions = {
            width: overlayWidth,
            height: overlayHeight
        };
        return overlayDimensions;
    },
    redimensionOverlay: function() {
        var overlay = document.getElementById('TSOverlayBGDiv');
        var overlayDims = TSWidget.Util.getOverlayDimensions();
        overlay.style.height = overlayDims.height + "px";
        overlay.style.width = overlayDims.width + "px";
    },
    showFlash: function() {
        var flashNodes = document.getElementsByTagName('object');
        for (var i=0;i<flashNodes.length;i++) {
            flashNodes[i].parentNode.style.textIndent = "0px";
            if (flashNodes[i].style.visibility == "hidden") {
                flashNodes[i].style.visibility = "visible";
            }
        }
    },
    hideFlash: function() {
        var flashNodes = document.getElementsByTagName('object');
        for (var i=0;i<flashNodes.length;i++) {
            var flashNode = flashNodes[i];
            if (flashNode.style.visibility != "hidden" && flashNode.id != "pf_alt_1") {
                flashNode.style.visibility = "hidden";
                flashNode.parentNode.style.textIndent = "-9999px";
            }
        }
    },
    showOverlay: function() {
        TSWidget.Util.hideFlash();

        var overlay = document.getElementById('TSOverlayBGDiv');

        if (!overlay) {
            overlay = document.createElement('div');
            overlay.id = "TSOverlayBGDiv";
            overlay.innerHTML = "&nbsp;";

            var dBody = document.getElementsByTagName('body')[0];
            dBody.appendChild(overlay, dBody);
        }

        // NOTE: Setting the dimensions for the overlay is primarily for < IE6;
        //       this step should not be required for browsers that support
        //       fixed positioned elements.
        TSWidget.Util.redimensionOverlay();

        overlay.style.display = "block";
    },
    hideOverlay: function() {
        var overlay = document.getElementById('TSOverlayBGDiv');
        if (overlay) {
            overlay.style.display = "none";
        }
        TSWidget.Util.showFlash();
    },
    errorMessage: function(message, actionLink, jsIdentifier) {
        var pFlow = document.getElementById('ts_ol_pflow');
        if (typeof(pFlow) != 'undefined') {
            var newDiv = document.createElement('div');
            newDiv.innerHTML = "blah";
            pFlow.style.display = "none";
        }
        var ua = new String(navigator.userAgent);
        var errorPane = document.createElement('div');
        errorPane.id = "tsUsrErrMsgLbox";
        errorPane.style.background = "url('"+ TSConfig.CDN_URL + "images/widgetSupport/errorPane/errorIcon.jpg') no-repeat 25px 30px #000000";

        if (ua.indexOf("MSIE") > -1) {
            var pageHeight;
            var pageWidth;
            if (document.documentElement && document.documentElement.clientWidth) {
                pageHeight = document.documentElement.scrollTop;
                pageWidth = document.documentElement.clientWidth;
            } else {
                pageHeight = document.body.clientHeight;
                pageWidth = document.body.clientWidth;
            }
            errorPane.style.top = 120 + parseInt(pageHeight) + "px";
            errorPane.style.left = parseInt(pageWidth)/2 - 347 + "px";
        } else {
            //errorPane.style.top = parseInt(window.pageYOffset) + 120 + "px";
            errorPane.style.left = parseInt(window.innerWidth)/2 - 347 + "px";
        }

        var errorHeadline = document.createElement('h3');
        var errorMessage = document.createElement('div');
        var errorAction = document.createElement('a');
        var errorClose = document.createElement('a');

        errorPane.appendChild(errorHeadline);
        errorPane.appendChild(errorMessage);
        errorPane.appendChild(errorAction);
        errorPane.appendChild(errorClose);

        var dBody = document.getElementsByTagName('body')[0];
        dBody.insertBefore(errorPane, dBody.firstChild);
        setTimeout("TSWidget.Util.paneScroll('tsUsrErrMsgLbox', 120)",2);

        errorHeadline.innerHTML = message.headline;
        errorMessage.innerHTML = message.text;
        errorAction.innerHTML = "&raquo; " + actionLink.text;
        errorAction.href = actionLink.href;
        errorAction.onclick = actionLink.onclick;
        errorAction.setAttribute("onclick", actionLink.onclick);
        errorAction.className = "tsErrActionLink";

        errorClose.innerHTML = "Cancel and Go Back";
        errorClose.href = "javascript:void(0);";
        errorClose.onclick = "javascript:TSWidget.Util.closeError('"+errorPane.id+"')";
        errorClose.setAttribute("onclick","javascript:TSWidget.Util.closeError('"+errorPane.id+"')");

        errorPane.innerHTML = errorPane.innerHTML; // IE
        TSPurchFlowResizeHandler = function () {
            TSWidget.Util.centerPane('tsUsrErrMsgLbox', 350);
            TSWidget.Util.redimensionOverlay();
        };
        TSPurchFlowScrollHandler = function () {
            TSWidget.Util.paneScroll('tsUsrErrMsgLbox', 120);
        };
        TSWidget.Util.DOM.addEventHandler(window, "resize", TSPurchFlowResizeHandler);
        TSWidget.Util.DOM.addEventHandler(window, "scroll", TSPurchFlowScrollHandler);
        return;
    },
    closeError : function(paneId) {
       var ePane = document.getElementById(paneId);
       ePane.parentNode.removeChild(ePane);
       TSWidget.Util.hideOverlay();
       //document.onscroll = "";
       TSWidget.Util.DOM.removeEventHandler(window, "resize", TSPurchFlowResizeHandler);
       TSPurchFlowResizeHandler = null;
       TSWidget.Util.DOM.removeEventHandler(window, "scroll", TSPurchFlowScrollHandler);
       //TSWidget.Util.DOM.removeEventHandler(document.documentElement, "scroll", TSPurchFlowScrollHandler);
       TSPurchFlowScrollHandler = null;
    },
    centerPane : function(elementId, offset) {
        var ePane = document.getElementById(elementId);
        var val = (parseInt(document.body.clientWidth))/2 - offset + "px";
        ePane.style.left = val;
    },
    paneScroll: function(elementId, offset) {
        var ePane = document.getElementById(elementId);
        var ua = new String(navigator.userAgent);
        var rawVal;
        if (ua.indexOf("MSIE") > -1) {
            rawVal = parseInt(document.documentElement.scrollTop);
        } else {
            rawVal = parseInt(window.pageYOffset);
        }
        var val = offset + rawVal + "px";
        ePane.style.top = val;
    },
    /**
     * The DOM namespace covers basic DOM manipulation functions such as insertions and search functions.
     */
    DOM: {
        /**
         * Adds an event handler function as an event listener to a DOM element
         *
         * @param element  DOM element to which the event handler should be added
         * @param eventType  Event type excluding "on" prefix
         * @param handler  Event handler function
         */
        addEventHandler: function (element, eventType, handler) {
            if (typeof element.addEventListener != "undefined") {
                element.addEventListener(eventType, handler, false); // DOM2
            } else if (typeof element.attachEvent != "undefined") {
                element.attachEvent("on"+eventType, handler); // IE
            }
        },
        /**
         * Removes an event handler function from a DOM element
         *
         * @param element  DOM element from which the event handler should be removed
         * @param eventType  Event type excluding "on" prefix
         * @param handler  Event handler function
         */
        removeEventHandler: function (element, eventType, handler) {
            if (typeof element.removeEventListener != "undefined") {
                element.removeEventListener(eventType, handler, false); // DOM2
            } else if (typeof element.detachEvent != "undefined") {
                element.detachEvent("on"+eventType, handler); // IE
            }
        }
    }
});

/* END WIDGETS.JS */
/* WIDGET POPULATORS */

TSWidget.Util.extend(TSWidget.Widgets, {
    FlashHooks:{
		purchaseFlowPath: "widgets/purchase/TSPF4.swf",

        /**
         * @deprecated  Use TSWidget.Widgets.Helpers.closeLightBox instead -- needs to be changed in flash
         */
        downloadFormCancel: function (jsIdentifier){
            TSWidget.Widgets.Helpers.closeLightBox(jsIdentifier);
        },
        paypalPurchase: function (paypalURL, jsIdentifier){
            var WindowObjectReference = window.open(paypalURL,'targetURL');
            if (!WindowObjectReference) {
                var message = {
                    headline: "Sorry",
                    text: "Your browser has prevented a pop-up window from opening.<br/><br/>"
                };
                message.text += "You may wish to disable pop-up blocking to make the download process a little easier. Otherwise, you can still continue by opening this link in a new window.";
                var actionLink = {
                    href:"javascript:void(0);",
                    text:"Go to PayPal in a New Window",
                    onclick:"javascript:window.open('"+paypalURL+"');TSWidget.Util.closeError('ts_usrErrMsg_lbox');"
                };
                TSWidget.Util.errorMessage(message, actionLink, jsIdentifier);
            }
        },
        openURLFromFlash: function(targetURL, jsIdentifier) {
            var windowObjectReference;
            var isIE = (navigator.userAgent.toString().indexOf("MSIE") > -1);
            if (!isIE) {
                windowObjectReference = window.open(targetURL, '_self');
            }
            if (!windowObjectReference || isIE) {
                var message = {
                    headline: "Sorry",
                    text: "Your browser has prevented a pop-up window from opening.<br/><br/>"
                };
                message.text += "You may wish to disable pop-up blocking to make the process a little easier. Otherwise, you can still continue by opening this link in a new window. ";
                var actionLink = {
                    href:"javascript:void(0);",
                    text:"Open Link in a New Window",
                    onclick:"javascript:window.open('"+targetURL+"');TSWidget.Util.closeError('ts_usrErrMsg_box');"
                };
                TSWidget.Util.errorMessage(message, actionLink, jsIdentifier);
            }
        },
        refreshPage: function (jsIdentifier) {
            window.location = window.location;
        },
        loadPurchaseFlow: function (productList, mode, widgetId, width, campaignId, persistVal, artistIdVal, theme) {
            var lightBox = TSWidget.Widgets.Helpers.renderLightBox(widgetId);
            var lightBoxWrapper = lightBox.parentNode;
            persistVal = (typeof(persistVal) == 'undefined' || persistVal == null) ? true : persistVal;
            theme = (typeof(theme) == 'undefined' || theme == null) ? "black" : theme;
            var key = "";
            // TODO: Need to determine where to get the subject from. Global data object is not the right place.
            //var emailSubject = (typeof(data.subject) != 'undefined') ? data.subject : "";
            var emailSubject = "";

            campaignId = campaignId || "";
            mode = mode || "download";
            // width = width || 435;
            // var height = 529;
            width = 480;
            var height = 570;
		    var flashURL = TSConfig.CDN_URL + TSWidget.Widgets.FlashHooks.purchaseFlowPath;

            if (mode == "share") {
                lightBoxWrapper.className += " share";
                width = 400;
                height = 334;
                flashURL = TSConfig.SSL_APP_URL + "flash/share/TSShareFlow.swf";
            }
            var paypalReturnURLBase = TSConfig.SSL_APP_URL + "purchase";
            var options = {
                facing: 'fan',
                variables: {
                    persist: persistVal,
                    baseUrl: TSConfig.SSL_APP_URL.replace(/\/$/,''),
                    cdnUrl: TSConfig.CDN_URL.replace(/\/$/,''),
                    ppUrl: paypalReturnURLBase,
                    shareSubj: emailSubject,
                    divW: width,
                    artistId: artistIdVal,
                    pList: productList,
                    key: key,
                    campaignId: campaignId,
                    jsIdentifier: widgetId,
                    theme : theme,
                    movieId: lightBox.id
                },
                params: {
                    quality: "high",
                    allowscriptaccess: "always",
                    menu: "false",
                    bgcolor: "#000000"
                },
                width: width,
                height: height,
                instance: lightBox.id
            };

            TSFlash.embed(flashURL, lightBox.id, options);

            function adblockCheck() {
                var abCheck = lightBoxWrapper.getElementsByTagName('a');
                var hideFlag = false;
                for (var i=0;i<abCheck.length;i++) {
                    if (abCheck[i].className.indexOf('abp-obj') >= 0) {
                        hideFlag = true;
                    }
                }
                if (hideFlag) {
                    for (var i=0;i<abCheck.length;i++) {
                        if (hideFlag && abCheck[i].className.indexOf('abp-obj') == -1) {
                            abCheck[i].style.left = "0px";
                            abCheck[i].style.cssFloat = "left";
                            abCheck[i].style.textAlign = "left";
                            abCheck[i].parentNode.style.textAlign = "left";
                        }
                    }
                }
            };
            setTimeout(adblockCheck, 100);
        }
    },
    Helpers: {
        /**
         * Renders empty modal light box
         *
         * @param id  The identifier used to create the light box media container
         * @return The light box media container element
         */
        renderLightBox: function (id) {
            TSWidget.Util.showOverlay();

            var wrapper = document.getElementById('ts_ol_pflow');
            if (wrapper != null) {
                wrapper.parentNode.removeChild(wrapper);
            }
            wrapper = document.createElement('div');
            wrapper.id = "ts_ol_pflow";
            wrapper.className = "ts_download_form";

            var tBar = document.createElement('div');
            tBar.id = "ts_pflow_control";
            var tBarLink = document.createElement('a');
            tBarLink.href = "javascript:void(0);";
            var closeURL = TSConfig.CDN_URL + "images/widgetSupport/purchFlow/close.gif";
            tBarLink.innerHTML = "<img src='"+closeURL+"' border='0' alt='Close'/>";
            TSWidget.Util.DOM.addEventHandler(tBarLink, "click", TSWidget.Widgets.Helpers.closeLightBox);
            tBar.appendChild(tBarLink);

            var contentBox = document.createElement('span');
            contentBox.id = "pf_alt_" + id;
            contentBox.className = "TSFlash_alt";
            contentBox.style.display = "block";
            contentBox.style.position = "absolute";
            contentBox.style.fontSize = "12px";
            contentBox.style.fontFamily = "Verdana, Arial, Helvetica";
            contentBox.style.backgroundColor = "transparent";
            contentBox.style.width = "100%";
            contentBox.style.border = "none";
            contentBox.style.color = "#ffffff";
            contentBox.innerHTML = "You do not have the required minimum version of<br/>Adobe Flash&reg;.<br/><br/> <a href='http://www.adobe.com/shockwave/download/download.cgi?P1_Prod_Version=ShockwaveFlash' target='_blank' style='color:#01cdff;font-weight:bold;'>Click here to upgrade</a>.<br/><br/><a href='#' style='color:#01cdff' onclick='javascript:TSWidget.Widgets.Helpers.closeLightBox();'>Cancel</a>";

            wrapper.appendChild(tBar);
            wrapper.appendChild(contentBox);

            var yOffset;
            if (window.pageYOffset) {
                // Not IE
                yOffset = window.pageYOffset;
            } else if (document.documentElement && document.documentElement.scrollTop) {
                // IE strict mode
                yOffset = document.documentElement.scrollTop;
            } else {
                // IE other
                yOffset = document.body.scrollTop;
            }
            wrapper.style.top = 80 + parseInt(yOffset) + "px";
            wrapper.style.left = (document.body.clientWidth)/2 - 212 + "px";

            var bodyNode = document.getElementsByTagName('body')[0];
            bodyNode.insertBefore(wrapper, bodyNode.firstChild.nextSibling);

            // Declare event handlers within global scope so they can be referenced when removing
            TSLightBoxResizeHandler = function () {
                TSWidget.Util.centerPane("ts_ol_pflow", 212);
                TSWidget.Util.redimensionOverlay();
            };
            TSWidget.Util.DOM.addEventHandler(window, "resize", TSLightBoxResizeHandler);

            return contentBox;
        },
        /**
         * Closes a modal light box
         *
         * @param id  The identifier used to create the light box media container
         */
        closeLightBox: function (id) {
            /// THIS TOOK JSIDENTIFIER... NEEDS TO ACTUALLY TAKE ID NOW
            var pf = document.getElementById('ts_ol_pflow');
            //pf.innerHTML = "";

            TSWidget.Util.DOM.removeEventHandler(window, "resize", TSLightBoxResizeHandler);
            TSLightBoxResizeHandler = null;

            TSWidget.Util.hideOverlay();
            pf.style.display = "none";
            //pf.parentNode.removeChild(pf);
        }
    }
});

/* END WIDGET POPULATORS */
/* TSPURCHASE */

TSPurchase = (function () {
    /**
     * Handles initial set up for TSPurchase related elements included on the page
     */
    function init() {
        if (!document.getElementById('topspin_style_addition')) {
            var styleTag = document.createElement('link');
            styleTag.media = 'screen';
            styleTag.rel = 'stylesheet';
            styleTag.type = 'text/css';
            styleTag.id = 'topspin_style_addition';
            styleTag.href = TSConfig.CDN_URL + "stylesheets/widget.css";
            var headNode = document.getElementsByTagName('head')[0];
            var headChild = headNode.firstChild;
            headNode.insertBefore(styleTag, headChild);

            var genericImageTag = document.createElement('img');
            genericImageTag.className = "invisible_image";

            var bodyNode = document.getElementsByTagName('body')[0];

            var allAnchors = document.getElementsByTagName('a');
            var anchorLength = allAnchors.length;

            // CHECK: Is this still necessary?
            for (var i=0;i<anchorLength;i++) {
                var anchor = allAnchors[i];
                if (anchor.href.indexOf('https://app.topspin.net/purchase/') >= 0) {
                    var urlArr = anchor.href.split('/');
                    var artistID = urlArr[5];
                    var campaignID = urlArr[6];
                    anchor.href = "javascript:void(0);";
                    anchor.onclick = "TSPurchase.load({aId:"+artistID+",bId:22737,cId:"+campaignID+",persist:true});";
                }
            }

            for (i=0;i<anchorLength;i++) {
                var clickStr = new String(allAnchors[i].onclick);
                if (clickStr.indexOf('TSPurchase.load') >= 0) {
                    var data = eval(clickStr.substring(clickStr.indexOf('TSPurchase.load') + 'TSPurchase.load'.length, clickStr.length-1));
                    var beaconImageTag = genericImageTag.cloneNode(true);
                    beaconImageTag.src = TSConfig.BEACON_URL +
                                         "?ec=18&es=2&ref_url=" + encodeURIComponent(window.location.href.toString()) +
                                         "&campaign_id=" + data['cId'] + "&timestamp=" + new Date().getTime();
                    bodyNode.appendChild(beaconImageTag);
                }
            }
        }
    }

    return {
        initialize: init,

        load: function(params) {
           TSWidget.Widgets.FlashHooks.loadPurchaseFlow(params.bId, null, 1, 435, params.cId, params.persist, params.aId, params.theme);
        }
    };
})();

TSWidget.Util.DOM.addEventHandler(window, "load", TSPurchase.initialize);

/* END TSPURCHASE */


} // End wrapping TSPurchase initialization check


