function TourLiveAtComponent(_id, _properties) {
    var lastUpdateDataId;
    var data;
    var id;
    var dataUrl;
    var flForceUpdate;
    var fullLeaderboardURL;
    var userInterface;
    
    init();
    
    function init() {
        setId(_id);
        flForceUpdate = false;
        if (_properties) {	
            if (_properties.full_leaderboard_url) {
                setFullLeaderboardURL(_properties.full_leaderboard_url);
            }
            if (_properties.user_interface) {
                setUserInterface(_properties.user_interface);
            }
        }
    }
    
    function setId(_id) {
        id = _id;
    }
    
    function isForceUpdateEnabled() {
        return flForceUpdate;
    }
    
    function setData(_data) {
        data = _data;
    }
    
    function setFullLeaderboardURL(_url) {
        fullLeaderboardURL = _url;
    }
    
    function setUserInterface(_userInterface) {
        try {
            userInterface = document.getElementById(_userInterface);
        } catch(e) { 
        userInterface = null; 
    }
}

this.enableForceUpdate = function(_forceUpdate) {
    flForceUpdate = _forceUpdate;
}

this.getData = function() {
    return data;
}

this.getId = function() {
    return id;
}

this.notify = function(_dataId, _dataObjId, _data, _code) {
    if (isForceUpdateEnabled() || lastUpdateDataId != _dataId) {
        setData(_data);
        lastUpdateDataId = _dataId;
        eval('setTimeout("tlac.updateComponent(' + this.getId() + ')", 1)'); // Threaded model
    }
}

this.render = function() {
    alert("...Must be overridden by subclasses...");
}

this.getFullLeaderboardURL = function() {
    return fullLeaderboardURL;
}

this.getUserInterface = function() {
    return userInterface;
}
}

TourLiveAtComponent.prototype.NO_VALUE_INDICATOR = "--";
TourLiveAtComponent.prototype.BACK_NINE_START_INDICATOR = "*";
TourLiveAtComponent.prototype.getNodeValue = function(_node) {
    return (_node && _node.hasChildNodes())? _node.childNodes[0].nodeValue : this.NO_VALUE_INDICATOR; 	
}

function LeaderBoardComponent(_id, _properties) {
    TourLiveAtComponent.call(this, _id, _properties);
    
    this.render = function() {
        var oPlayers = new Object();
        oPlayers.stats = [ ];
        
        var playerXml = this.getData().getElementsByTagName("player");
        var nameValue;
        var positionValue;
        var starthole;
        var thruValue;
        var todayValue;
        var totalValue;
        var thruValueNode
        var className = "tourLbRow";
        
        
        for (var i=0; i<playerXml.length; i++) {
            nameValue = this.getNodeValue(playerXml[i].getElementsByTagName("name")[0]);
            positionValue = this.getNodeValue(playerXml[i].getElementsByTagName("position")[0]);
            thruValueNode = playerXml[i].getElementsByTagName("thru")[0];
            thruValue = this.getNodeValue(thruValueNode);
            if (this.NO_VALUE_INDICATOR != thruValue) {
                if (thruValueNode.getAttribute("starthole") != null && parseInt(thruValueNode.getAttribute("starthole")) != 1) {
                    thruValue += this.BACK_NINE_START_INDICATOR;
                }
            }
            
            todayValue = this.getNodeValue(playerXml[i].getElementsByTagName("currentscore")[0]);            
            if (this.NO_VALUE_INDICATOR == todayValue) { todayValue = this.getNodeValue(playerXml[i].getElementsByTagName("teetime")[0]); }
            totalValue = this.getNodeValue(playerXml[i].getElementsByTagName("totalscore")[0]);
            var classNameWithRowID = className + (i + 1);
            oPlayers.stats.push({name: nameValue, position: positionValue, thru: thruValue, today: todayValue, total: totalValue, cssClassName:classNameWithRowID});
        }
        
        var tableTemplate = new Template(
            '<div class="#{cssClassName}">' +
            '<div class="tourLbCol tourLbCol1">#{position}</div>' +
            '<div class="tourLbCol tourLbCol2">#{name}</div>' +
            '<div class="tourLbCol tourLbCol3">#{today}</div>' +
            '<div class="tourLbCol tourLbCol4">#{thru}</div>' +
            '<div class="tourLbCol tourLbCol5">#{total}</div>' +
            '</div>'
        );
        
        var outHTML_ = "";
        
        for (var i = 0; i < playerXml.length; i++) {
            var str = oPlayers.stats[i];
            outHTML_ += tableTemplate.evaluate(str) + '\n';
        }
        
        outHTML_ += '<div class="tourLeaderboardLink">' +
                         '<a href="#" onclick="tourAction(' + "'newWindow', '" + this.getFullLeaderboardURL() + "'" + '); return false;">Full Leaderboard&nbsp;<img src="/.element/img/3.0/sect/liveat/white_arrow.gif" widht="4" height="7" alt="" /></a></div>';
        
        this.getUserInterface().innerHTML = outHTML_;
        tourAction('showLeaderboard');
        
        
    }
}
LeaderBoardComponent.prototype = new TourLiveAtComponent();
LeaderBoardComponent.prototype.constructor = LeaderBoardComponent;
LeaderBoardComponent.prototype.baseClass = TourLiveAtComponent.prototype.constructor;

function FedExCupComponent(_id, _properties) {
    TourLiveAtComponent.call(this, _id, _properties);
    
    this.render = function() {						
        var oFedExCupPlayers = new Object();
        oFedExCupPlayers.stats = [ ];
        
        var fedExCupPlayerXML = this.getData().getElementsByTagName("player");
        var nameValue;
        var rankValue;
        var pointsValue;
        var className = "tourLbRow";		
        
        for (var i=0; i<fedExCupPlayerXML.length; i++) {
            nameValue = this.getNodeValue(fedExCupPlayerXML[i].getElementsByTagName("name")[0]);
            rankValue = this.getNodeValue(fedExCupPlayerXML[i].getElementsByTagName("position")[0]);
            pointsValue = this.getNodeValue(fedExCupPlayerXML[i].getElementsByTagName("points")[0]);
            
            var classNameWithRowID = className + (i + 1);
            oFedExCupPlayers.stats.push({name:nameValue, blank:'--', rank:rankValue, points:pointsValue, cssClassName:classNameWithRowID});
        }
        
        var tableTemplate = new Template(
            '<div class="#{cssClassName}">' +
            '<div class="tourLbCol tourLbCol1Fc">#{rank}</div>' +
            '<div class="tourLbCol tourLbCol2Fc">#{name}</div>' +
            '<div class="tourLbCol tourLbCol3Fc">#{points}</div>' +
            '</div>'
        );
        
        var fedExCupHTML_ = "";
        
        for (var i = 0; i < fedExCupPlayerXML.length; i++) {
            var str = oFedExCupPlayers.stats[i];
            fedExCupHTML_ += tableTemplate.evaluate(str) + '\n';
        }
		
		fedExCupHTML_ += '<div class="tourLeaderboardLink">' +
                            'Projected FEC Standings<!--a href="#" onclick="tourAction(' + "'newWindow', '" + this.getFullLeaderboardURL() + "'" + '); return false;">FC Projected Points&nbsp;<img src="/.element/img/3.0/sect/liveat/white_arrow.gif" widht="4" height="7" alt="" /></a--></div>';
        
        this.getUserInterface().innerHTML = fedExCupHTML_;
    }
}
FedExCupComponent.prototype = new TourLiveAtComponent();
FedExCupComponent.prototype.constructor = FedExCupComponent;
FedExCupComponent.prototype.baseClass = TourLiveAtComponent.prototype.constructor;

function HoleStatsComponent(_id, _properties) {
    TourLiveAtComponent.call(this, _id, _properties);
    
    var that = this;
    var holeImageBaseURL;
    var holeDisplay;
    var liveatHole;
    var currentHoleIndex;
    var holeList;
    var holeIdFromInitProperty;
    var holeDottedStr = { 
        aces:"..................................",  
        eagles:"................................",
        birdies:"..............................",
        pars:"...................................",
        bogeys:"..............................",
        others:"................"
    }
    
    init();
    
    function init() {
        currentHoleIndex = -1;
        liveatHole = null;
        holeImageBaseURL = _properties.data.hole_graphic_url;
        holeIdFromInitProperty = _properties.data.hole_id;
        holeDisplay = _properties.data.hole_display;
    }
    
    function setHoleList() {
        holeList = that.getData().getElementsByTagName("hole");
    }
    
    function isCurrentHoleValid() {
        var currentHoleValid_ = true;
        
        if (currentHoleIndex == -1 || holeList[currentHoleIndex].getAttribute("onliveat") == "false") {
            currentHoleValid_ = false;
        }
        return currentHoleValid_;
    }
    
    function setLiveatHole() {
        var holeListLength = holeList.length;
        
        for (var i=0; i < holeListLength; i++) {
            if (holeList[i].getAttribute("onliveat") == "true") {
                currentHoleIndex = i;
                liveatHole = holeList[i];
                break;
            }
        }
        
        if (liveatHole == null) { 
            var liveatHoleId = holeIdFromInitProperty;
            for (var j=0; j < holeListLength; j++) {
                if (holeList[j].getAttribute("id") == liveatHoleId) {
                    liveatHole = holeList[j];
                    currentHoleIndex = j;
                    break;
                }
            }
        }
        
    }
    
    function getFirstChild(n) {
        var nodeRef = n.firstChild;
        while (nodeRef && nodeRef.nodeType != 1) {
            nodeRef = nodeRef.nextSibling;
        }
        
        return nodeRef;
    }
    
    function configHolePane() {
        var holeId;
        var holeImageURL;
        var holeRef;
        
        holeId = liveatHole.getAttribute("id");
        holeImageURL = holeImageBaseURL + holeId + ".jpg";
        try {
            holeRef = document.getElementById(holeDisplay);
            oldImageNode = getFirstChild(holeRef);
            imageNode = document.createElement("img");
            with (imageNode) {
                setAttribute("src", holeImageURL);
                setAttribute("alt", holeId);
                setAttribute("title", "");
            }
            
            if (oldImageNode) { 
                holeRef.replaceChild(imageNode, oldImageNode);
            }
            else {
                holeRef.appendChild(imageNode);
            }
        }
        catch (e) {} // need a default hole graphic/message;
        tour.writeLIVEatTab(holeId);
    }
    
    function updateHoleData() {
        liveatHole = holeList[currentHoleIndex];
    }
    
    this.render = function() {
        var holeMapString;
        var oHole;
        var oCurrentHoleStats;
        var outHTML_;
        
        setHoleList();
        if (isCurrentHoleValid() == false) {
            setLiveatHole();
            configHolePane();
        }
        else {
            updateHoleData();
        }
        
        outHTML_ = '<div class="tourHoleStatsTable"><table border="0" cellspacing="0" cellpadding="0">';
        oHole = new Object();
        oHole.stats = [ ];
        
        oCurrentHoleStats = liveatHole.getElementsByTagName("stats")[0];
        
        for (var i=0; i<oCurrentHoleStats.childNodes.length; i++) {
            if (oCurrentHoleStats.childNodes[i].nodeType == 1) {
                holeNodeValue = (oCurrentHoleStats.childNodes[i].hasChildNodes())? oCurrentHoleStats.childNodes[i].childNodes[0].nodeValue : 0;
                holeNodeName = oCurrentHoleStats.childNodes[i].nodeName;
                var tmpstr = "holeDottedStr." + holeNodeName;
                holeDots = eval(tmpstr);
                
                // Change Hole Name to display format
                if (holeNodeName == "others") { holeNodeName = "Double Bogey/+"; }
                else { // Capitalize the first letter of the Hole Name;
                    holeNodeName = holeNodeName.charAt(0).toUpperCase() + holeNodeName.substring(1);
                }
                
                oHole.stats.push({name:holeNodeName, count:holeNodeValue, dots:holeDots});
            }
        }
        
        var tableTemplate = new Template(
            '<tr>' +
            '<td><span class="white">#{name}</span><span class="blue">#{dots}</span></td>' + 
            '<td><span class="blue">#{count}</span></td>' +
            '</tr>');
        
        
        
        for (var i = 0; i < oHole.stats.length; i++) {
            var str = oHole.stats[i];
            outHTML_ += tableTemplate.evaluate(str) + '\n';
        }
        
        outHTML_ += "</table></div>";
        
        this.getUserInterface().innerHTML = outHTML_;
    }
}
HoleStatsComponent.prototype = new TourLiveAtComponent();
HoleStatsComponent.prototype.constructor = HoleStatsComponent;
HoleStatsComponent.prototype.baseClass = TourLiveAtComponent.prototype.constructor;

function CustomLBComponent(_id, _properties) {
    TourLiveAtComponent.call(this, _id, _properties);
    var that = this;	
    var cPlayers;
    var controlObjRef;
    var dataObjId;
    var defaultDocElement = "tourLiveAtLeaderBoardContentDefault";
    var that = this;
    var defaultState;
    
    this.config = function(_dataObjId, _controlObjRef) {
        var tourCustomLBCookieData;
        
        controlObjRef = _controlObjRef;
        dataObjId = _dataObjId;
        // Check for preexisting LB Customization;
        tourCustomLBCookieData = readCookie(controlObjRef.CUSTOM_PLAYER_COOKIE_NAME); //"1|2|3|4|5"; // getCookie("tourCustomLBCookie"); // check for cookie
        
        if (tourCustomLBCookieData != null && tourCustomLBCookieData != "") {
            //  Configure Custom Player Environment
            cPlayers = tourCustomLBCookieData.split("|"); // Setup Custom Player Leaderboard array
            controlObjRef.setAutoPopulateMode("on", dataObjId);
        }
        else {
            controlObjRef.setAutoPopulateMode("off", dataObjId);
            controlObjRef.retrieveData(_dataObjId);
            //showDefault();
            return; // No further configuration necessary.
        }
    }
    
    function updatePlayerIds(_cPlayers) {
        cPlayers = _cPlayers;
    }
    
    function showDefault() {
        that.getUserInterface().innerHTML = document.getElementById(defaultDocElement).innerHTML;
        defaultState = true;
    }
    
    function match(_playerId1, _playerId2) {
        for (var i=0; i<cPlayers.length; i++) {
            if (cPlayers[i] == _playerId) { return true; }
        }
        
        return false;
    }
    
    this.render = function() {
        controlObjRef.transformLBXmlToJson(this.getData());
        
        if (cPlayers != null) { paint(this.getData()); }
        else {
            showDefault();
        }
    }
    
    function orderPlayers(_listPlayers) {
        var listPlayersOrdered_;
        var playerID;
        var intListIndex;
        var intCustomPlayers;
        var intListPlayers;
        
        listPlayersOrdered_ = new Array();
        intCustomPlayers = cPlayers.length;
        intListPlayers = _listPlayers.length;
        for (var i=0; i < intCustomPlayers; i++) {
            for (var k=0; k < intListPlayers; k++) {
                if (_listPlayers[k].getAttribute("id") == cPlayers[i]) {
                    try {
                        intListIndex = parseInt(_listPlayers[k].getElementsByTagName("position")[0].getAttribute("id"));
                        listPlayersOrdered_[intListIndex] = _listPlayers[k];
                    } catch (e) {
                    listPlayersOrdered_[intListPlayers+k] = _listPlayers[k];
                }
                break;
            }
        }
    }
    
    return trimList(listPlayersOrdered_);
}

function trimList(_list) {
    var list_;
    var intListIndex;
    var intListItems
    
    list_ = new Array();
    intListIndex = 0;
    intListItems = _list.length;
    for (var i=0; i < intListItems; i++) {
        if (_list[i] != null) {
            list_[intListIndex++] = _list[i];
        }
    }
    
    return list_;
}

function paint(_data) {
    var oPlayers = new Object();
    oPlayers.stats = [ ];
    
    var listPlayersXML; // = _data.getElementsByTagName("player");	
    var listCustomPlayersXML;
    var intCustomPlayers;
    var nameValue;
    var positionValue;
    var starthole;
    var thruValue;
    var todayValue;
    var totalValue;		
    var numOfCustomPlayers = 0;
    var maxNumOfCustomPlayers = 5;
    var playerId;
    var orderedCustPlayers;
    var thruValueNode;
    var className = "tourLbRow";
    
    
    // Get the latest SERVER XML for players
    listPlayersXML = _data.getElementsByTagName("player");
    // Order custom Players by current position
    listCustomPlayersXML = orderPlayers(listPlayersXML);
    intCustomPlayers = listCustomPlayersXML.length;
    
    for (var k=0; k<intCustomPlayers; k++) { 
        
        nameValue = that.getNodeValue(listCustomPlayersXML[k].getElementsByTagName("name")[0]);
        positionValue = that.getNodeValue(listCustomPlayersXML[k].getElementsByTagName("position")[0]);
        thruValueNode = listCustomPlayersXML[k].getElementsByTagName("thru")[0];
        thruValue = that.getNodeValue(thruValueNode);
        if (that.NO_VALUE_INDICATOR != thruValue) {
            if (thruValueNode.getAttribute("starthole") != null && parseInt(thruValueNode.getAttribute("starthole")) != 1) {
                thruValue += that.BACK_NINE_START_INDICATOR;
            }
        }
        todayValue = that.getNodeValue(listCustomPlayersXML[k].getElementsByTagName("currentscore")[0]);
        if (that.NO_VALUE_INDICATOR == todayValue) { todayValue = that.getNodeValue(listCustomPlayersXML[k].getElementsByTagName("teetime")[0]); }
        totalValue = that.getNodeValue(listCustomPlayersXML[k].getElementsByTagName("totalscore")[0]);
        var classNameWithRowID = className + (k + 1);			
        oPlayers.stats.push({name:nameValue, position:positionValue, thru:thruValue, today:todayValue, total:totalValue, cssClassName:classNameWithRowID});		
        
    }
    
    var tableTemplate = new Template(
        '<div class="#{cssClassName}">' +
        '<div class="tourLbCol tourLbCol1">#{position}</div>' +
        '<div class="tourLbCol tourLbCol2">#{name}</div>' +
        '<div class="tourLbCol tourLbCol3">#{today}</div>' +
        '<div class="tourLbCol tourLbCol4">#{thru}</div>' +
        '<div class="tourLbCol tourLbCol5">#{total}</div>' +
        '</div>'
    );
    
    var outHTML_ = "";    
    for (var i = 0; i < intCustomPlayers; i++) {
        var str = oPlayers.stats[i];
        outHTML_ += tableTemplate.evaluate(str) + '\n';
    }
    
    outHTML_ += '<div class="tourLeaderboardLink">' +
                         '<a href="#" onclick="tourAction(' + "'newWindow', '" + that.getFullLeaderboardURL() + "'" + '); return false;">Full Leaderboard&nbsp;<img src="/.element/img/3.0/sect/liveat/white_arrow.gif" widht="4" height="7" alt="" /></a></div>';
        
    that.getUserInterface().innerHTML = outHTML_;
}

this.update = function(_cPlayers) {
    updatePlayerIds(_cPlayers);
    if (_cPlayers.length == 0) {
        showDefault();
        controlObjRef.setAutoPopulateMode("off", dataObjId);
    }
    else {
        controlObjRef.setAutoPopulateMode("on", dataObjId);
        paint(this.getData());
    }
}
}
CustomLBComponent.prototype = new TourLiveAtComponent();
CustomLBComponent.prototype.constructor = CustomLBComponent;
CustomLBComponent.prototype.baseClass = TourLiveAtComponent.prototype.constructor;

function ScorecardComponent(_id, _properties) {
    TourLiveAtComponent.call(this, _id, _properties);
    var that = this;
    var controlObjRef;
    var dataObjId;
    var baseDataUrl;
    var classNameBase;
    var defaultDocElement;
    
    function buildPlayerDataUrl(_playerId) {
        return baseDataUrl + _playerId + ".xml";
    }
    
    function generateNullTableRow() {
        var tRow_;
    }
    
    this.config = function(_dataObjId, _controlObjRef, _docElement, _baseDataUrl) {
        controlObjRef = _controlObjRef;
        dataObjId = _dataObjId;
        baseDataUrl = _baseDataUrl;
        controlObjRef.setAutoPopulateMode("off", dataObjId);
        this.enableForceUpdate(true);
        classNameBase = "tourKeyColor"; // hardcoded. :(
    }
    
    this.showDefaultDocElement = function() {
        tourAction('showScorecardDefault');
        controlObjRef.setAutoPopulateMode("off", dataObjId);
    }	
    
    this.render = function() {
        var scoreCardData;
        var cRowData;
        var oParRow = new Object;
        var currentRound = 0;
        var cssAttribute = "shotstyle-";
        var shotCSSdefaultPrefix = " shotstyle-";
        var cssAltRowStyle = cssAttribute + " AltRowStyle";
        var cssAxisLblStyle = " axisLblStyle";
        var scorecardHTML_ = "";
        var NO_VALUE_INDICATOR = "--";
        var roundStatus;
        var LINE_BREAK_CODE = "\n";
        var lengNodes;
        var parFrontNine;
        var scoreFrontNine;
        var statusFrontNine;
        var scoreFrontNine;
        var scoreBackNine;
        var statusBackNine;
        
        try {
            scoreCardData = this.getData();
            currentRound = scoreCardData.getElementsByTagName("tournament")[0].getAttribute("currentRound");
        } catch (e) {
            tourAction("showScorecardDefault");
            return;
        }
        
        var roundNodes = scoreCardData.getElementsByTagName("scorecard");
        var activeScoreCard;        
        for (var i=0; i<roundNodes.length; i++) {
            if (roundNodes[i].getAttribute("round") == currentRound) {
                activeScoreCard = roundNodes[i];
                break;
            } 
        }
        
        scorecardHTML_ += '<div class="tourScHeader">' +
                            '<div class="tourScHeaderItem1">Hole</div>'+
                            '<div class="tourScHeaderItem2">Par</div>' +
                            '<div class="tourScHeaderItem3">Rnd' + currentRound + '</div>' +
                            '<div class="tourScHeaderItem4">Status</div>' +
                          '</div>' + LINE_BREAK_CODE;
        
        scorecardHTML_ += '<div class="tourScTitle">';
        
        var rowTmplCode = new Template('<div class="tourScCol#{css}">#{value}</div>');
        
        // hole row;
        var oHoleRow = new Object();
        var index;
        oHoleRow.items = [ ];
        lengNodes = 18;
        for (var i = 0; i < lengNodes; i++) {
            index = i + 1;
            oHoleRow.items.push({value:index});
            if (i == 8) { oHoleRow.items.push({value:"OUT"}); }
            if ((i+1) == lengNodes) { 
                oHoleRow.items.push({value:"IN"}); 
                oHoleRow.items.push({value:"TOT"});
            }
        }
        
        for (var i = 0; i < oHoleRow.items.length; i++) {
            var data = oHoleRow.items[i];
            scorecardHTML_ += rowTmplCode.evaluate(data) + LINE_BREAK_CODE;
        }
        scorecardHTML_ += "</div>"+ LINE_BREAK_CODE;
        
        //par row;
        oParRow.items = [];
        var parSum = 0;
        var halfsum = 0;
        var oParHoleNodes;
        var parValue;
        
        oParHoleNodes = (activeScoreCard == null)? new Array(18) : activeScoreCard.getElementsByTagName("hole");        
        lengNodes = oParHoleNodes.length;
        for (var i = 0; i < lengNodes; i++) {
            if (oParHoleNodes[i] != null) {
                parValue =  oParHoleNodes[i].getAttribute("shotsToPar");
                parSum += parseInt(parValue);
                halfsum += parseInt(parValue);
            }
            else { parValue = NO_VALUE_INDICATOR; }
            
            oParRow.items.push({value:parValue});
            
            if (i == 8) { 
                parFrontNine = halfsum;
                if (halfsum == 0) { halfsum = NO_VALUE_INDICATOR; }	
                oParRow.items.push({value:halfsum});
                halfsum = 0;
            }
            if ((i+1) == lengNodes) { 
                parBackNine = halfsum;
                if (halfsum == 0) { halfsum = NO_VALUE_INDICATOR; }
                if (parSum == 0) { parSum = NO_VALUE_INDICATOR; }
                oParRow.items.push({value:halfsum}); 
                oParRow.items.push({value:parSum});
            }
        }
        
        scorecardHTML_ += '<div class="tourScRow1">';
        for (var i=0; i<oParRow.items.length; i++) {
            var data = oParRow.items[i];
            scorecardHTML_ += rowTmplCode.evaluate(data) + LINE_BREAK_CODE;
        }        
        scorecardHTML_ += "</div>" + LINE_BREAK_CODE;
        
        
        // Score		
        var cScoreNodes;
        var cScoreRelNodes;		
        var scoreValue;
        var scoreRelValue;        
        var cScore = new Array();		
        var oScoreRow = new Object();
        
        oScoreRow.items = [ ];cScoreNodes = (activeScoreCard == null)? new Array(18) : activeScoreCard.getElementsByTagName("score");
        cScoreRelNodes = (activeScoreCard == null)? new Array(18) : activeScoreCard.getElementsByTagName("scoreRelToPar");
        lengNodes = cScoreNodes.length;
        
        var sum = 0;
        halfsum = 0;
        for (var i = 0; i < lengNodes; i++) {
            if (cScoreNodes[i] != null && cScoreNodes[i].hasChildNodes()) {
                scoreValue = cScoreNodes[i].childNodes[0].nodeValue;
                sum += parseInt(scoreValue);
                halfsum += parseInt(scoreValue);
            } 
            else { scoreValue = NO_VALUE_INDICATOR; }
            
            shotCSSclass = shotCSSdefaultPrefix;
            if (cScoreRelNodes[i] != null && cScoreRelNodes[i].hasChildNodes()) {
                scoreRelValue = cScoreRelNodes[i].childNodes[0].nodeValue;
                if (scoreRelValue != "par") {
                    shotCSSclass +=  scoreRelValue;
                }
            }
            oScoreRow.items.push({value:scoreValue, css:shotCSSclass});
            
            if (i == 8) { 
                scoreFrontNine = halfsum;
                if (halfsum == 0) { 
                    halfsum = NO_VALUE_INDICATOR;                    
                }
                oScoreRow.items.push({value:halfsum}); 
                halfsum = 0;
            }
            if ((i+1) == lengNodes) { 
                scoreBackNine = halfsum;
                if (halfsum == 0) { halfsum = NO_VALUE_INDICATOR; }
                if (sum == 0) { sum = NO_VALUE_INDICATOR; }
                oScoreRow.items.push({value:halfsum});
                oScoreRow.items.push({value:sum});
            }
        }
        
        // APPEND SCORE OUTPUT TO scorecardHTML_
        scorecardHTML_ += '<div class="tourScRow2">';
        for (var i = 0; i < oScoreRow.items.length; i++) {
            var data = oScoreRow.items[i];
            scorecardHTML_ += rowTmplCode.evaluate(data) + LINE_BREAK_CODE;
        }
        scorecardHTML_ += "</div>" + LINE_BREAK_CODE;
        
        
        // Status
        var cStatusNodes;
        var statusValue;
        var cStatus = new Array();
        var oStatusRow = new Object();
        var statusSum = 0;
        var roundStatus;
        oStatusRow.items = [ ];
        
        if (activeScoreCard == null) {
            cStatusNodes = new Array(18);
            roundStatus = NO_VALUE_INDICATOR;
        }
        else {
            cStatusNodes = activeScoreCard.getElementsByTagName("status");
            roundStatus = (activeScoreCard.getElementsByTagName("round-status")[0].hasChildNodes())? activeScoreCard.getElementsByTagName("round-status")[0].childNodes[0].nodeValue : NO_VALUE_INDICATOR;
        }
        
        lengNodes = cStatusNodes.length;
        for (var i = 0; i < lengNodes; i++) {
            if (cStatusNodes[i] != null && cStatusNodes[i].hasChildNodes()) {
                statusValue = cStatusNodes[i].childNodes[0].nodeValue;
            } 
            else { statusValue = NO_VALUE_INDICATOR; }
            
            oStatusRow.items.push({value:statusValue});
            
            if (i == 8) { 
                if (parFrontNine == 0 || scoreFrontNine == 0) {
                    statusFrontNine = NO_VALUE_INDICATOR;
                }
                else {
                    relScore = scoreFrontNine - parFrontNine;
                    statusFrontNine = (relScore > 0)? "+" + relScore : relScore;
                }
                
                oStatusRow.items.push({value:NO_VALUE_INDICATOR}); 
            }
            
            if ((i+1) == lengNodes) {
                shotCSSclass = shotCSSdefaultPrefix + "total";
                
                if (parBackNine == 0 || scoreBackNine == 0) {
                    statusBackNine = NO_VALUE_INDICATOR;
                }
                else {
                    relScore = scoreBackNine - parBackNine;
                    statusBackNine = (relScore > 0)? "+" + relScore : relScore;
                }
                
                oStatusRow.items.push({value:NO_VALUE_INDICATOR});
                oStatusRow.items.push({value:roundStatus, css:shotCSSclass});
            }
        }
        
        scorecardHTML_ += '<div class="tourScRow3">';
        for (var i=0; i <oStatusRow.items.length; i++) {
            var data = oStatusRow.items[i];
            scorecardHTML_ += rowTmplCode.evaluate(data) + LINE_BREAK_CODE;
        }
        scorecardHTML_ += "</div>" + LINE_BREAK_CODE;
        
        this.getUserInterface().innerHTML = scorecardHTML_;
    }
    
    this.retrieve = function(_playerId) {
        controlObjRef.setDataObjUrl(buildPlayerDataUrl(_playerId), dataObjId);
        controlObjRef.retrieveData(dataObjId);
        controlObjRef.setAutoPopulateMode("on", dataObjId);
    }
    
}
ScorecardComponent.prototype = new TourLiveAtComponent();
ScorecardComponent.prototype.constructor = ScorecardComponent;
ScorecardComponent.prototype.baseClass = TourLiveAtComponent.prototype.constructor;


function TabGroupComponent(_id, _properties) {
    TourLiveAtComponent.call(this, _id, _properties);
    
    var that = this;
    var cPlayers;
    var dataObjId;
    var controlObjRef;
    var oScoreCardRef;
    var flDrawn;
    var docElement;
    var tabDefaultDocElement;
    var activeTab;
    
    function setDrawn(_state) {
        flDrawn = _state;
    }
    
    function isDrawn() {
        return flDrawn;
    }
    
    function getDocElement() {
        return docElement;
    }
    
    function getPlayerIdFromTab(_tab) {
        return cPlayers[_tab];
    }
    
    function getPlayerShortName(_playerId, _data) {
        var playerNodeRefs;
        var playerName;
        var playerShortName;
        
        playerNodeRefs = _data.getElementsByTagName("player");
        for (var i=0; i<playerNodeRefs.length; i++) {
            if (playerNodeRefs[i].getAttribute("id") == _playerId) {
                var spaceindex;
                
                playerName = playerNodeRefs[i].getElementsByTagName("name")[0].childNodes[0].nodeValue;
                spaceindex = playerName.indexOf(" ");
                playerShortName = playerName.charAt(0).toUpperCase() + ". " + playerName.substring(spaceindex);
                break;
            }
        }
        
        return playerShortName;
    }
    
    function getPlayerName(_playerId, _data) {
        var playerNodeRefs;
        
        playerNodeRefs = _data.getElementsByTagName("player");
        for (var i=0; i<playerNodeRefs.length; i++) {
            if (playerNodeRefs[i].getAttribute("id") == _playerId) {
                return playerNodeRefs[i].getElementsByTagName("name")[0].childNodes[0].nodeValue;
            }
        }
        
        return "";
    }
    
    function getActiveTab() {
        return activeTab;
    }
    
    function setActiveTab(_tab) {
        activeTab = _tab;
    }
    
    function updateScorecard(_tab) {
        if (_tab == -1) {
            // oScoreCardRef.showDefaultDocElement();
            tourAction('showScorecardDefault');
        }
        else {
             tourAction("showScorecard");
            try {
                oScoreCardRef.retrieve(getPlayerIdFromTab(_tab));
            } catch (e) {}
        }		
    }
    
    function getActiveCss(_tab) {
        var tabPosition = _tab;
        var numOfTabs = cPlayers.length;
        var tabmod = tabPosition % numOfTabs;
        var cssActive_ = "active";
        
        switch (tabmod) {
            case 0: 
            return cssActive_ += (tabPosition == 1)? "L" : "R";
            case 1:
            return cssActive_ += "L";
            default:
            return cssActive_ += "C";
        }
    }
    
    /**
    * Draws the TabGroup Control Buttons for the UI
    */
    function paint(_data) {
        var tabHtmlTemplateCode;
        var oTabs;
        var contentId;
        var parentId;
        var menuId;
        var scoreTabID;
        var modindex;
        var tabId;
        var css = "";
        var classTagActive = "class='active'";
        var playerShortName;
        var tabGroupHTML_;
        
        if (_data == null) {
            setDrawn(false);
            return;
        }
        
        oTabs = new Object;
        oTabs.items = [ ];
        
        tabHtmlTemplateCode = new Template(
            '<a id="#{menu}" #{css} #{onclick}>#{playername}</a>'
        );
        
        onclickHTMLtmplCode = new Template(
            'href="#" onclick="' +
            "tlac.HandleUserInterface_OnClick(#{component}, '#{tab}'); tourAction('#{scoretab}'); return false;" + '"'
        );
        var onclickStr;
        // build tab array.
        for (var i=0; i<5; i++) {
            modindex = i+1;
            contentId = "tourScorecard1";
            menuId = "scTab" + modindex;
            scoreTabID = "scoreTab" + modindex;
            tabId = i;
            parentId = "tourScorecardMenu";
            playerName = "";
            onclickStr = "";
            css = "";
            
            if (i < cPlayers.length) {
                if (i == getActiveTab(modindex)) { css = classTagActive; }            
                playerName = getPlayerName(cPlayers[i], _data);
                onclickData = {tab:tabId, component:4, scoretab:scoreTabID};
                onclickStr = onclickHTMLtmplCode.evaluate(onclickData);
            } 
            
            oTabs.items.push({menu:menuId, onclick:onclickStr, playername:playerName, css:css});
        }
        
        tabGroupHTML_ = "";
        for (var i=0; i <oTabs.items.length; i++) {
            var tabdata = oTabs.items[i];
            tabGroupHTML_ += tabHtmlTemplateCode.evaluate(tabdata) + '\n';
        }
        
        // output the data
        that.getUserInterface().innerHTML = tabGroupHTML_;
    }
    
    this.config = function(_dataObjId, _controlObjRef, _docElement) {
        var tourCustomLBCookieData;
        
        dataObjId = _dataObjId;
        controlObjRef = _controlObjRef;
        oScoreCardRef = controlObjRef.initializeComponent(null, "Scorecard");
        // Check for preexisting LB Customization;
        tourCustomLBCookieData = readCookie(controlObjRef.CUSTOM_PLAYER_COOKIE_NAME);
        if (tourCustomLBCookieData != null && tourCustomLBCookieData != "") {		
            this.updatePlayers(tourCustomLBCookieData.split("|"));
            tourAction("showScorecard");
        }
        else { updateScorecard(-1); }
    }
    
    this.render = function() {
        if (isDrawn() == false) {
            paint(this.getData());
            setDrawn(true);
        }		
        if (cPlayers == null) { updateScorecard(-1); }		
    }
    
    this.updatePlayers = function(_playerIds) {
        var tabIndex;
        
        cPlayers = _playerIds;
        tabIndex = (_playerIds.length == 0)? -1 : 0;
        setActiveTab(0);
        paint(this.getData());
        updateScorecard(tabIndex);
    }
    
    this.HandleUserInterface_OnClick = function(_tab) {
        setActiveTab(_tab);
        updateScorecard(_tab);
    }
}
TabGroupComponent.prototype = new TourLiveAtComponent();
TabGroupComponent.prototype.constructor = TabGroupComponent;
TabGroupComponent.prototype.baseClass = TourLiveAtComponent.prototype.constructor;


function HighlightVideoComponent(_id, _properties) {
    TourLiveAtComponent.call(this, _id, _properties);
    
    this.render = function() {
        var idotServerURL;
        var oMovies;
        var moviesCollectionXml;
        var movieId;
        var descriptionValue;
        var lengthValue;
        var imageValue;
        var className;
        var DEFAULT_DESCRIPTION_STRING = "A PGA Learning Center video";
        var DEFAULT_THUMBNAIL_URL = "http://i.cdn.turner.com/pgatour/.element/img/1.0/video/video_default_tn.jpg";
        var highlightHTML_;
        var highlightHTMLtmpl;
        var metadata;
        
        idotServerURL = "http://i.cdn.turner.com/pgatour";
        highlightHTMLtmpl = new Template('<div class="#{cssClassName}">' +
            '<div class="tourVideoListImg"><a onclick="tour.play(\'#{id}\'); return false;" style="cursor:pointer"><img class="tourHighlightsBorder" src="#{image}" width="88" height="49" alt=""/></a></div>' +
            '<div class="tourVideoListText"><a onclick="tour.play(\'#{id}\'); return false;" style="cursor:pointer">#{description}</a> #{length}</div>' +
            '</div>'
        );
        
        oMovies = new Object();
        oMovies.metadata = [];
        moviesCollectionXml =  this.getData().getElementsByTagName("video");
        
        for (var i=0; i<moviesCollectionXml.length; i++) {
            movieURL = this.getNodeValue(moviesCollectionXml[i].getElementsByTagName("url")[0]);
            if (movieURL == this.NO_VALUE_INDICATOR) { continue; }			
            
            descriptionValue = this.getNodeValue(moviesCollectionXml[i].getElementsByTagName("headline")[0]);
            if (descriptionValue == this.NO_VALUE_INDICATOR) { descriptionValue = DEFAULT_DESCRIPTION_STRING; }
            
            lengthValue = "(" + this.getNodeValue(moviesCollectionXml[i].getElementsByTagName("length")[0]) + ")";
            if (lengthValue.indexOf(this.NO_VALUE_INDICATOR) != -1) { lengthValue = ""; }
            
            imageValue = this.getNodeValue(moviesCollectionXml[i].getElementsByTagName("image")[0]);
            if (imageValue == this.NO_VALUE_INDICATOR) { imageValue = DEFAULT_THUMBNAIL_URL; }
            else if (imageValue.indexOf('http://') == -1) {
                imageValue = idotServerURL + imageValue;
            }
            
            className = ((i % 2) == 0)? "tourVideoListAlt" : "tourVideoList";
            oMovies.metadata.push({id:movieURL, description:descriptionValue, length:lengthValue, image:imageValue, cssClassName:className});
        }
        
        highlightHTML_ = '';
        
        for (var i=0; i<oMovies.metadata.length; i++) {
            metadata = oMovies.metadata[i];
            highlightHTML_ += highlightHTMLtmpl.evaluate(metadata) + '\n';
        }
        
        this.getUserInterface().innerHTML = highlightHTML_;
    }
}
HighlightVideoComponent.prototype = new TourLiveAtComponent();
HighlightVideoComponent.prototype.constructor = HighlightVideoComponent;
HighlightVideoComponent.prototype.baseClass = TourLiveAtComponent.prototype.constructor;
