﻿/// <reference name="MicrosoftAjax.js"/>
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  IController.js
*
*      Declares the initial call pattern for controllers.
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("SiteCommon");

SiteCommon.IController = function() { }

SiteCommon.IController.prototype = {
    initializeRequest: function() {
        /// <summary>
        ///     initializeRequest is called to initialize the ajax data request needed by
        ///     this controller, as well as any additional requirements.
        /// </summary>
    }
}
SiteCommon.IController.registerInterface('SiteCommon.IController');


/// <reference name="MicrosoftAjax.js"/>
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  IView.js
*
*      Declares the general view abstract routines.
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("UserPCSite");

SiteCommon.IView = function(element) {
    SiteCommon.IView.initializeBase(this, [element]);
}

SiteCommon.IView.prototype = {
    initialize: function() {
        /// <summary>
        ///     initialize the main control, and setup the static UI content.
        /// </summary>
    },
    _setupRender: function() {
        /// <summary>
        ///     Sets up the dom element structure which doesn't require queried data.
        /// </summary>
    },
    dataRender: function() {
        /// <summary>
        ///     Update the UI with main data components from controller.
        /// </summary>
    }
}

SiteCommon.IView.registerInterface('SiteCommon.IView');


/// <reference name="MicrosoftAjax.js"/>
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  InteractiveBaseView.js
*
*      Declares common view behaviour.
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("SiteCommon");

SiteCommon.InteractiveBaseView = function(element) {
    /// <summary>
    ///     Constructor.  DO NOT CALL DIRECTLY, USE $CREATE.
    /// </summary>
    /// <param name="element">HTML DomElement to associate.</param>
    /// <returns>
    ///     A newly created object.
    /// </returns>
    SiteCommon.InteractiveBaseView.initializeBase(this, [element]);

    this._clickDelegate = null;
    this._hoverDelegate = null;
    this._unhoverDelegate = null;
    this._controller = null;
    this._eventTargets = new Array();
    for (eventType in SiteCommon.InteractiveBaseView.eventTypes) {
        this._eventTargets[this._eventTargets.length] = new Array();
    }
}

SiteCommon.InteractiveBaseView.prototype = {
    initialize: function() {
        /// <summary>
        ///     Initialize.  DO NOT CALL DIRECTLY, USE $CREATE.
        ///     
        ///     Initializes the view.
        /// </summary>

        if (SiteCommon.Utils.isNullOrUndefined(this.get_id())) {
            throw "ID must be defined during $create.";
        }

        var element = this.get_element();

        // Setup the click event
        if (this._clickDelegate === null) {
            this._clickDelegate = Function.createDelegate(this, this._clickHandler);
        }
        Sys.UI.DomEvent.addHandler(element, 'click', this._clickDelegate);

        // Setup the hover event
        if (this._hoverDelegate === null) {
            this._hoverDelegate = Function.createDelegate(this, this._hoverHandler);
        }
        Sys.UI.DomEvent.addHandler(element, 'mouseover', this._hoverDelegate);
        Sys.UI.DomEvent.addHandler(element, 'focus', this._hoverDelegate);

        // Setup the unhover event
        if (this._unhoverDelegate === null) {
            this._unhoverDelegate = Function.createDelegate(this, this._unhoverHandler);
        }
        Sys.UI.DomEvent.addHandler(element, 'mouseout', this._unhoverDelegate);
        Sys.UI.DomEvent.addHandler(element, 'blur', this._unhoverDelegate);

        // Initialize the base class
        SiteCommon.InteractiveBaseView.callBaseMethod(this, 'initialize');

        // Call render on the subclass
        this._setupRender();
    },
    add_click: function(handler) {
        /// <summary>
        ///     Adds a click event handler.
        /// </summary>
        /// <param name="handler">Reference to the handler to call.</param>
        this.get_events().addHandler('click', handler);
    },
    remove_click: function(handler) {
        /// <summary>
        ///     Removes a click event handler.
        /// </summary>
        /// <param name="handler">Reference to the handler.</param>
        this.get_events().removeHandler('click', handler);
    },
    add_hover: function(handler) {
        /// <summary>
        ///     Adds a hover event handler.
        /// </summary>
        /// <param name="handler">Reference to the handler to call.</param>
        this.get_events().addHandler('hover', handler);
    },
    remove_hover: function(handler) {
        /// <summary>
        ///     Removes a hover event handler.
        /// </summary>
        /// <param name="handler">Reference to the handler.</param>
        this.get_events().removeHandler('hover', handler);
    },
    add_unhover: function(handler) {
        /// <summary>
        ///     Adds an unhover event handler.
        /// </summary>
        /// <param name="handler">Reference to the handler to call.</param>
        this.get_events().addHandler('unhover', handler);
    },
    remove_unhover: function(handler) {
        /// <summary>
        ///     Removes an unhover event handler.
        /// </summary>
        /// <param name="handler">Reference to the handler.</param>
        this.get_events().removeHandler('unhover', handler);
    },
    get_controller: function() {
        /// <summary>
        ///     Get a reference to the controller.
        /// </summary>
        return this._controller;
    },
    set_controller: function(controller) {
        /// <summary>
        ///     Sets a reference to the controller to use.
        /// </summary>
        /// <param name="controller">Reference to the controller.</param>
        this._controller = controller;
    },
    addEventTarget: function(eventType, targetID, contextData) {
        /// <summary>
        ///     Adds an event target using the provided ID and the given contextData, which will be
        ///     returned as 'args' to the handler when the event is fired.
        /// </summary>
        /// <param name="eventType">A SiteCommon.InteractiveBaseView.eventTypes value referring to the event type.</param>
        /// <param name="targetID">The string targetID of the sub-element to catch.</param>
        /// <param name="contextData">The context data to return to the handler as args.</param>
        this._eventTargets[eventType][targetID] = contextData;
    },
    removeEventTarget: function(eventType, targetID) {
        /// <summary>
        ///     Removes an event target using the provided ID
        /// </summary>
        /// <param name="eventType">A SiteCommon.InteractiveBaseView.eventTypes value referring to the event type.</param>
        /// <param name="targetID">The string targetID of the sub-element to catch.</param>
        this._eventTargets[eventType][targetID] = undefined;
    },
    dispose: function() {
        /// <summary>
        ///     Called to dispose of this objects resources.
        /// </summary>

        var element = this.get_element();

        // Remove the click handler
        if (this._clickDelegate) {
            Sys.UI.DomEvent.removeHandler(element, 'click', this._clickDelegate);
            delete this._clickDelegate;
        }

        // Remove the hover handler
        if (this._hoverDelegate) {
            Sys.UI.DomEvent.removeHandler(element, 'focus', this._hoverDelegate);
            Sys.UI.DomEvent.removeHandler(element, 'mouseover', this._hoverDelegate);
            delete this._hoverDelegate;
        }

        // Remove the unhover handler
        if (this._unhoverDelegate) {
            Sys.UI.DomEvent.removeHandler(element, 'blur', this._unhoverDelegate);
            Sys.UI.DomEvent.removeHandler(element, 'mouseout', this._unhoverDelegate);
            delete this._unhoverDelegate;
        }

        SiteCommon.InteractiveBaseView.callBaseMethod(this, 'dispose');
    },
    _clickHandler: function(event) {
        /// <summary>
        ///     Resends the click event to the handler.
        /// </summary>
        /// <param name="event">Event reference.</param>
        this.launchEventHandler('click', SiteCommon.InteractiveBaseView.eventTypes.click, event);
    },
    _hoverHandler: function(event) {
        /// <summary>
        ///     Resends the click event to the handler.
        /// </summary>
        /// <param name="event">Event reference.</param>
        this.launchEventHandler('hover', SiteCommon.InteractiveBaseView.eventTypes.hover, event);
    },
    _unhoverHandler: function(event) {
        /// <summary>
        ///     Resends the click event to the handler.
        /// </summary>
        /// <param name="event">Event reference.</param>
        this.launchEventHandler('unhover', SiteCommon.InteractiveBaseView.eventTypes.unhover, event);
    },
    launchEventHandler: function(eventName, eventType, event) {
        /// <summary>
        ///     Adds any required data (EventHandlerArgs) to the event and passes it on to the
        ///     handler, if one was registered.
        /// </summary>
        /// <param name="eventName">Name of the event raised.</param>
        /// <param name="eventType">A SiteCommon.InteractiveBaseView.eventTypes value referring to the event type.</param>
        /// <param name="event">The event object fired by the system, containing the target element.</param>
        var handler = this.get_events().getHandler(eventName);
        if (handler) {
            handler(this, this.getEventHandlerArg(eventType, event));
        }
    },
    getEventHandlerArg: function(eventType, eventObj) {
        /// <summary>
        ///     Checks if a contextData element exists for the provided eventType and eventObj's target ID.
        /// </summary>
        /// <param name="eventType">A SiteCommon.InteractiveBaseView.eventTypes value referring to the event type.</param>
        /// <param name="eventObj">The event object fired by the system, containing the target element.</param>

        if (!SiteCommon.Utils.isNullOrUndefined(eventObj)
            && !SiteCommon.Utils.isNullOrUndefined(eventObj.target)
            && !SiteCommon.Utils.isNullOrUndefined(eventObj.target.id)) {
            eventObj.customData = this._eventTargets[eventType][eventObj.target.id];
        }
        return eventObj;
    }
}
SiteCommon.InteractiveBaseView.eventTypes = { 'click': 0, 'hover': 1, 'unhover': 2 };
/// <field name="eventType">A static list of possible event handler types.</field>

SiteCommon.InteractiveBaseView.registerClass('SiteCommon.InteractiveBaseView', Sys.UI.Control, SiteCommon.IView);


/// <reference name="MicrosoftAjax.js"/>
/// <reference name="~/Common/AjaxControls/Utils.js"/>

Type.registerNamespace("DevPortal");

DevPortal.Utils = function() { }

DevPortal.Utils.displayPopup = function(isError, showXClose, textNodeHeader, divContent) {
    /// <summary>
    ///     Displays a modal popup to the user.
    /// </summary>
    /// <param name="isError">Display normal or error dialog.</param>
    /// <param name="showXClose">Determines if a close button in the corner should be displayed.</param>
    /// <param name="textNodeHeader">The dialog header text node.</param>
    /// <param name="divContent">The main dialog contents to use.</param>
    SiteCommon.Utils.displayPopup(isError, showXClose, textNodeHeader, divContent);
}

DevPortal.Utils.displayErrorPopup = function(textNodeHeader, response) {
    /// <summary>
    ///     Displays a modal error dialog to the user.
    /// </summary>
    /// <param name="textNodeHeader">The dialog header text node.</param>
    /// <param name="response">The server response to display.</param>

    var divContent = SiteCommon.Utils.generateErrorDiv(response);

    // Launch the dialog.
    DevPortal.Utils.displayPopup(true, true, textNodeHeader, divContent);
}

DevPortal.Utils.createLoadingDiv = function(loadingMsg) {
    /// <summary>
    ///     Create the UI for a loading message.
    /// </summary>
    /// <returns>
    ///     A dom element to use as a loading message.
    /// </returns>
    return SiteCommon.Utils.createLoadingDiv(loadingMsg);
}

DevPortal.Utils.createReloadDiv = function(parentId, refreshMsg, busyMsg) {
    /// <summary>
    ///     Create the UI for a reload message.
    /// </summary>
    /// <param name="parentId">Id of the parent view.</param>
    /// <returns>
    ///     An object with two properties:
    ///         object.reloadButton: A reference to the actual reload button DOM element.
    ///         object.div: The main div of the UI element.
    /// </returns>
    return SiteCommon.Utils.createReloadDiv(parentId, refreshMsg, busyMsg);
}

DevPortal.Utils.DisplayConfirmationDialog = function(textTitle, textContent, textHeader, textOk,
                                                textCancel, okClickHandler) {
    /// <summary>
    ///     Create the UI for a loading message.
    /// </summary>
    /// <returns>
    ///     A dom element to use as a loading message.
    /// </returns>

    SiteCommon.Utils.DisplayConfirmationDialog(textTitle, textContent, textHeader, textOk,
                                                textCancel, okClickHandler);
}

DevPortal.Utils.ActionConfirmationHandler = function(
            sender, itemGuid, actionId,
            Loc, message, cancel, ok, args) {
    /// <summary>
    ///     Handle the action by displaying a confirmation modal popup,
    ///     or redirect the user to appropriate page with querystring params.
    /// </summary>
    /// <param name="sender">Event sender object</param>
    /// <param name="itemGuid">Sku Guid</param>
    /// <param name="actionId">Action ID of the action to be taken</param>
    /// <param name="title">Title of the confirmation modal popup</param>
    /// <param name="message">Message displayed on the confirmation modal popup</param>
    /// <param name="cancel">Cancel button text</param>
    /// <param name="ok">Ok button text</param>
    /// <param name="args">args for SubmitToCatalog action</param>        
    /// <returns>false</returns> 
    switch (actionId) {
        case this.Actions.EditProductDetails:
            DevPortal.Utils.SetDefaultTab(1);
            window.location.search = "?pageid=1&appsku=" + itemGuid;
            return false;
            break;

        case this.Actions.ViewProductDetails:
            DevPortal.Utils.SetDefaultTab(1);
            window.location.search = "?prodid=" + itemGuid;
            return false;
            break;

        case this.Actions.SubmitForCertification:
            //Show confirmation message
            DevPortal.Utils.DisplayConfirmationDialog(Loc.Submission_Title, Loc.Submission_Body,
                Loc.Submission_Header, ok, cancel,
                'DevPortal.Utils.SubmitSku(\'' + itemGuid + '\', ' + actionId + ');');
            return false;
            break;

        case this.Actions.SubmitAdditionalMarket:
            //Show confirmation message
            DevPortal.Utils.DisplayConfirmationDialog(Loc.Market_Title, Loc.Market_Body,
                Loc.Market_Header, ok, cancel,
                'DevPortal.Utils.SubmitMarket(\'' + itemGuid + '\');');
            return false;
            break;

        case this.Actions.ViewTestResults:
            window.open("FileVendor.aspx?type=testresultfile&sku=" + itemGuid);
            return false;
            break;

        case this.Actions.SubmitToCatalog:
            if (args.hasDefaultMarketPrice) {
                DevPortal.Utils.DisplayConfirmationDialog(Loc.Catalog_Title, Loc.Catalog_Body,
                Loc.Catalog_Header, ok, cancel,
                'DevPortal.Utils.SubmitSku(\'' + itemGuid + '\', ' + actionId + ');');
            }
            else {
                SiteCommon.Utils.displayErrorMessagePopup(
                    SiteCommon.Utils.toUIString(Loc.Missing_Information_Title),
                    SiteCommon.Utils.toUIString(Loc.DefaultMarketPriceNotFound));
            }
            return false;
            break;

        case this.Actions.SubmitForSigning:
            //Action removed from Specs
            //Should not be invoked, so do nothing
            return false;
            break;

        case this.Actions.SubmitProductUpdate:
            DevPortal.Utils.SetDefaultTab(1);
            window.location.search = "?pageid=1&type=update&appsku=" + itemGuid;
            return false;
            break;

        case this.Actions.SubmitProductUpgrade:
            DevPortal.Utils.SetDefaultTab(1);
            window.location.search = "?pageid=1&type=upgrade&appsku=" + itemGuid;
            return false;
            break;

        case this.Actions.ContactSupport:
            window.open("http://go.microsoft.com/?linkid=9670342");
            return false;
            break;

        case this.Actions.RemoveFromCatalog:
            //Show confirmation message
            DevPortal.Utils.DisplayConfirmationDialog(Loc.Remove_Title, Loc.Remove_Body,
                Loc.Remove_Header, ok, cancel,
                'DevPortal.Utils.RemoveSku(\'' + itemGuid + '\', ' + actionId + ');');
            return false;
            break;
        case this.Actions.DeleteApplication:
            //Show confirmation message
            DevPortal.Utils.DisplayConfirmationDialog(Loc.Delete_Title, Loc.Delete_Body,
                Loc.Delete_Header, ok, cancel,
                'DevPortal.Utils.DeleteSku(\'' + itemGuid + '\', ' + actionId + ');');
            return false;
            break;

        default:
            return false;
    }
}

DevPortal.Utils.SubmitMarket = function(guid) {
    /// <summary>
    ///     Opens a new page/tab to allow the user to pay for and then submit  a 
    ///     new market for the specified SKU.
    /// </summary>
    /// <param name="guid">GUID of the product (SKU).</param>
    /// <param name="actionId">Action to be performed on the SKU</param>

    SiteCommon.Utils.closePopup();
    DevPortal.Utils.SetDefaultTab(1);
    window.location.search = "?pageid=1&type=market&appsku=" + guid;
    return false;
}

DevPortal.Utils.SubmitSku = function(guid, actionId) {
    /// <summary>
    ///     Opens a new page/tab to allow the user to pay for and then submit the 
    ///     SKU for certification/signing/ingestion into catalog.
    /// </summary>
    /// <param name="guid">GUID of the product (SKU).</param>
    /// <param name="actionId">Action to be performed on the SKU</param>

    SiteCommon.Utils.closePopup();
    if (actionId == this.Actions.SubmitToCatalog) {
        window.location.search = "?catalog=1&appsku=" + guid;
    }
    else {
        DevPortal.Utils.SetDefaultTab(2);
        window.location.search = "?submit=1&appsku=" + guid;
    }
    return;
}

DevPortal.Utils.RemoveSku = function(guid, actionId) {
    /// <summary>
    ///     Opens a new page/tab to confirm removal of App
    /// </summary>
    /// <param name="guid">GUID of the product (SKU).</param>
    /// <param name="actionId">Action to be performed on the SKU</param>

    SiteCommon.Utils.closePopup();
    if (actionId == this.Actions.RemoveFromCatalog) {
        window.location.search = "?catalog=2&appsku=" + guid;
    }
    return false;
}
DevPortal.Utils.DeleteSku = function(guid, actionId) {
    /// <summary>
    ///     Opens a new page/tab to to confirm deletion of App
    /// </summary>
    /// <param name="guid">GUID of the product (SKU).</param>
    /// <param name="actionId">Action to be performed on the SKU</param>

    SiteCommon.Utils.closePopup();
    if (actionId == this.Actions.DeleteApplication) {
        window.location.search = "?catalog=3&appsku=" + guid;
    }
    return false;
}
DevPortal.Utils.SwitchTab = function(tabControl, tabId) {
    /// <summary>
    ///     Switches the active tab on the tabControl to the specified tab number.
    /// </summary>
    /// <returns>
    ///     success=true/failure=false
    /// </returns>
    var tab = $find(tabControl);
    if (null == tab) // sometimes the control isn't available b/c framework hasn't loaded it yet.
        return false;

    var totalTabs = tab.get_tabs().length;
    if (tabId >= totalTabs || tabId < 0 || typeof (tabId) != 'number' || isNaN(tabId)) {
        throw ("Invalid tabId");
        return false;
    }
    else {
        // change the active tab, if we're not already on tabId. 
        // This check is necessary to prevent an infinite loop. We call DefaultSwitchTab from onNavigate, 
        // and for some odd reason the AJAX framework triggers a new onNavigate event whenever the tab 
        // container changes state (not just when the url/hash changes) so the set_activeTabIndex will trigger
        // an additional onNavigate.
        var currentTab = tab.get_activeTabIndex();
        if (currentTab != tabId) {
            tab.set_activeTabIndex(tabId);
        }
    }
}
DevPortal.Utils.DefaultSwitchTab = function(tabId) {
    /// <summary>
    ///     Switches the active tab on the default tabControl to the specified tab number.
    /// </summary>
    /// <returns>
    ///     success=true/failure=false
    /// </returns>
    tabControl = 'ctl00_ctl00_ctl00_placeholderPage_placeholderContent_pageContentPlaceholder_HeroPageTabControl';
    DevPortal.Utils.SwitchTab(tabControl, tabId);
}
DevPortal.Utils.SetDefaultTab = function(tabId) {
    /// <summary>
    ///     Sets a new tab id in the hash. Note this will trigger an onNavigate and our handler for that 
    ///     will handle calling DefaultSwitchTab to switch to the new tab.
    /// </summary>

    window.location.hash = "#tab=" + tabId;
}
DevPortal.Utils.CreateDiv = function(parent, id, cssClass, appendChild) {
    ///<summary>
    ///     Creates a new div element
    ///</summary>
    /// <param name="parent">Parent div to add new div element to.</param>
    /// <param name="id">ID of the new div element.</param>
    /// <param name="cssClass">Css Class to add to the new div element.</param>
    /// <param name="appendChild">First child element to add to the new element.</param>

    return SiteCommon.Utils.CreateDiv(parent, id, cssClass, appendChild);
}
DevPortal.Utils.CreateImg = function(parent, id, cssClass, url, text) {
    ///<summary>
    ///     Creates a new image element
    ///</summary>
    /// <param name="parent">Parent div to add new div element to.</param>
    /// <param name="id">ID of the new div element.</param>
    /// <param name="cssClass">Css Class to add to the new div element.</param>
    /// <param name="url">URL to the image.</param>


    return SiteCommon.Utils.CreateImg(parent, id, cssClass, url, text);
}

DevPortal.Utils.CreateSpan = function(parent, id, cssClass, appendChild) {
    ///<summary>
    ///     Creates a new span element
    ///</summary>
    /// <param name="parent">Parent div to add new span element to.</param>
    /// <param name="id">ID of the new span element.</param>
    /// <param name="cssClass">Css Class to add to the new span element.</param>
    /// <param name="appendChild">First child element to add to the new span element.</param>

    return SiteCommon.Utils.CreateSpan(parent, id, cssClass, appendChild);
}
DevPortal.Utils.CreateLink = function(parent, id, cssClass, appendChild, onClick, href) {
    ///<summary>
    ///     Creates a new link element
    ///</summary>
    /// <param name="parent">Parent div to add new link element to.</param>
    /// <param name="id">ID of the new link element.</param>
    /// <param name="cssClass">Css Class to add to the new link element.</param>
    /// <param name="appendChild">First child element to add to the new link element.</param>
    /// <param name="onClick">OnClick event handler (optional)</param>
    /// <param name="href">href link</param>

    return SiteCommon.Utils.CreateLink(parent, id, cssClass, appendChild, onClick, href);
}
DevPortal.Utils.CreateButton = function(text, id, cssClassBase, onClick) {
    /// <summary>
    ///     Create a button and returns the wrapping Div DOM element.
    /// </summary>
    /// <param name="text">Text to use as button value.</param>
    /// <param name="id">DOM ID to attach to the resulting elements.</param>
    /// <returns>
    ///     A reference the wrapping DOM element.
    /// </returns>

    return SiteCommon.Utils.CreateButton(text, id, cssClassBase, onClick);
}

DevPortal.Utils.DashboardTabSwitchHandler = function(sender, args) {
    ///<summary>
    ///     Function to retain state on postback
    ///</summary>
    /// <param name="sender">Element that triggered the function.</param>
    /// <param name="args">Arguments.</param>

    DevPortal.Utils.SaveState(sender);

    var idxTab = sender.get_activeTabIndex();
    Sys.Application.addHistoryPoint({ tab: idxTab });
}
DevPortal.Utils.SaveState = function(sender) {
    ///<summary>
    ///     Function to retain state on postback
    ///</summary>
    /// <param name="sender">Element that triggered the function.</param>
    sender.get_clientStateField().value = sender.saveClientState();
}


DevPortal.Utils.Actions = {
    EditProductDetails: 1,
    ViewProductDetails: 2,
    SubmitForCertification: 3,
    SubmitAdditionalMarket: 4,
    ViewTestResults: 5,
    SubmitToCatalog: 6,
    SubmitForSigning: 7,
    SubmitProductUpdate: 8,
    SubmitProductUpgrade: 9,
    ContactSupport: 10,
    RemoveFromCatalog: 11,
    DeleteApplication: 12
};
/// <field name="Actions">An enum of possible actions operable upon SKU items.</field>

DevPortal.Utils.SubmissionStatus = {
    SubmissionCreated: 1,
    ReadyForCertificationTest: 2,
    PendingCertificationTest: 3,
    CertificationTestFailed: 4,
    CertificationTestCompleted: 5,
    TestSigningFailed: 6,
    SigningFailed: 7,
    SigningRequestDenied: 8,
    PendingSigning: 9,
    PublishedToCatalog: 10,
    SubmissionCancelled: 11,
    PendingQueueingToWorkflow: 12,
    PendingPaymentProcess: 13,
    StartingWorkflow: 14,
    ReadyToPublish: 15,
    CabCrackingFailed: 16,
    Deleted: 17
};
/// <field name="SubmissionStatus">An enum of submission status values for SKU items.</field>

DevPortal.Utils.StatusActionsList = [
    [//0: [
        ],
    [//SubmissionCreated: [
        DevPortal.Utils.Actions.EditProductDetails,
        DevPortal.Utils.Actions.ViewProductDetails,
        DevPortal.Utils.Actions.DeleteApplication
        ],
    [//ReadyForCertificationTest: [
        DevPortal.Utils.Actions.SubmitForCertification,
        DevPortal.Utils.Actions.EditProductDetails,
        DevPortal.Utils.Actions.ViewProductDetails,
        DevPortal.Utils.Actions.DeleteApplication
        ],
    [//PendingCertificationTest: [
        DevPortal.Utils.Actions.ViewProductDetails
        ],
    [//CertificationTestFailed: [
        DevPortal.Utils.Actions.ViewTestResults,
        DevPortal.Utils.Actions.EditProductDetails,
        DevPortal.Utils.Actions.ViewProductDetails,
        DevPortal.Utils.Actions.DeleteApplication
        ],
    [//CertificationTestCompleted: [        
        DevPortal.Utils.Actions.ViewProductDetails
        ],
    [//TestSigningFailed: [
        DevPortal.Utils.Actions.SubmitForCertification,
        DevPortal.Utils.Actions.EditProductDetails,
        DevPortal.Utils.Actions.ViewProductDetails,
        DevPortal.Utils.Actions.DeleteApplication
        ],
    [//SigningFailed: [
        DevPortal.Utils.Actions.ContactSupport,
        DevPortal.Utils.Actions.ViewProductDetails,
        DevPortal.Utils.Actions.DeleteApplication
        ],
    [//SigningRequestDenied: [
        DevPortal.Utils.Actions.SubmitProductUpdate,
        DevPortal.Utils.Actions.EditProductDetails,
        DevPortal.Utils.Actions.ViewProductDetails,
        DevPortal.Utils.Actions.DeleteApplication
        ],
    [//PendingSigning: [
        DevPortal.Utils.Actions.ViewProductDetails
        ],
    [//PublishedToCatalog: [
        DevPortal.Utils.Actions.ViewProductDetails,
        DevPortal.Utils.Actions.EditProductDetails,
        DevPortal.Utils.Actions.RemoveFromCatalog,
        DevPortal.Utils.Actions.SubmitProductUpdate,
        DevPortal.Utils.Actions.SubmitAdditionalMarket
        ],
    [//SubmissionCancelled: [
            DevPortal.Utils.Actions.DeleteApplication
        ],
    [//PendingQueueingToWorkflow: 12,
        DevPortal.Utils.Actions.SubmitForCertification,
        DevPortal.Utils.Actions.ViewProductDetails
        ],
    [//PendingPaymentProcess: 13,
        DevPortal.Utils.Actions.ViewProductDetails
        ],
    [//StartingWorkflow: 14,
        DevPortal.Utils.Actions.ViewProductDetails,
        ],
    [//ReadyToBePublished: 15,
        DevPortal.Utils.Actions.SubmitToCatalog,
        DevPortal.Utils.Actions.DeleteApplication,
        DevPortal.Utils.Actions.SubmitAdditionalMarket,
        DevPortal.Utils.Actions.EditProductDetails,
        DevPortal.Utils.Actions.ViewProductDetails
        ],
    [//CabCrackingFailed: 16
        DevPortal.Utils.Actions.ContactSupport,
        DevPortal.Utils.Actions.ViewProductDetails,
        DevPortal.Utils.Actions.DeleteApplication
        ]
];
/// <field name="StatusActionsList">An 2D array of Actions available for the actions available for SKU items.</field>



DevPortal.Utils.registerClass('DevPortal.Utils', Sys.Component);

/// <reference name="MicrosoftAjax.js"/>
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  Utils.js
*
*      General utilities
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("SiteCommon");

SiteCommon.Utils = function() { }

SiteCommon.Utils.boldFirstWord = function(textNode, additionalBoldCss) {
    /// <summary>
    ///     Bolds the first word of a string of text
    /// </summary>
    /// <param name="textNode">textNode to style</param>
    /// <param name="additionalBoldCss">An optional css class to apply to the resulting textnode.</param>
    /// <returns>
    ///     domElement of the provided text.
    /// </returns>
    var boldText = "";
    var normalText = "";
    var text = textNode.data;

    var index = text.indexOf(' ');
    if (index >= 0) {
        boldText = text.substring(0, index);
        normalText = text.substring(index);
    }
    else {
        boldText = text;
    }
    // Create bold element.
    var boldSpan = document.createElement('span');
    Sys.UI.DomElement.addCssClass(boldSpan, 'BoldFirstWord');
    if (!SiteCommon.Utils.isNullOrUndefined(additionalBoldCss)) {
        Sys.UI.DomElement.addCssClass(boldSpan, additionalBoldCss);
    }
    boldSpan.appendChild(document.createTextNode(boldText));
    // Create main span container.
    var outerSpan = document.createElement('span');
    outerSpan.appendChild(boldSpan);
    outerSpan.appendChild(document.createTextNode(normalText));
    return outerSpan;
}

SiteCommon.Utils.setOpacity = function(domElement, value) {
    /// <summary>
    ///     Sets the opacity of the provided domElement to the provided value.
    /// </summary>
    /// <param name="domElement">A reference to the domElement to change.</param>
    /// <param name="value">A value (0-10) of the desired opacity.</param>
    domElement.style.opacity = value / 10;
    domElement.style.filter = 'alpha(opacity=' + value * 10 + ')';
}

SiteCommon.Utils.markEventHandled = function(event) {
    /// <summary>
    ///     Marks the provided event as handled in the system, to avoid it bubbling (or cascading) anymore.
    /// </summary>
    /// <param name="event">The event to handle.</param>

    event.cancelBubble = true;
    if (event.stopPropagation) event.stopPropagation();
}

SiteCommon.Utils.toUIString = function(value) {
    /// <summary>
    ///     Converts the value string object to a proper UI textnode (empty strings for null or undefined objects).
    /// </summary>
    /// <param name="value">Text string to check.</param>
    /// <returns>
    ///     The resulting textnode.
    /// </returns>
    var newString = SiteCommon.Utils.isNullOrUndefined(value) ? "" : value;

    return document.createTextNode(newString);
}

SiteCommon.Utils.isNullOrUndefined = function(value) {
    /// <summary>
    ///     Determines if the provided value is null or undefined.
    /// </summary>
    /// <param name="value">The object to check.</param>
    /// <returns>
    ///     A bool value, true if value is null or undefined, false otherwise.
    /// </returns>
    return (value == null || value == undefined);
},

SiteCommon.Utils.displayPopup = function(isError, showXClose, textNodeHeader, divContent) {
    /// <summary>
    ///     Displays a modal popup to the user.
    /// </summary>
    /// <param name="isError">Display normal or error dialog.</param>
    /// <param name="showXClose">Determines if a close button in the corner should be displayed.</param>
    /// <param name="textNodeHeader">The dialog header text node.</param>
    /// <param name="divContent">The main dialog contents to use.</param>


    var upperLeft = $get('ModalPopup_header_upperleft');
    var top = $get('ModalPopup_header_top');
    var topContent = $get('ModalPopup_header_content');
    var upperRight = $get('ModalPopup_header_upperright');
    var content = $get('ModalPopupContent');
    var xClose = $get('ModalPopup_xClose');

    // Skin the top of the dialog with either the normal or error UI
    var styleString = (isError) ? "error" : "normal";
    var styleStringOpposite = (!isError) ? "error" : "normal";
    upperLeft.innerHTML = "<div class='popup-" + styleString + "-upperleft' />";
    Sys.UI.DomElement.removeCssClass(top, 'ModalPopup-' + styleStringOpposite + '-top');
    Sys.UI.DomElement.addCssClass(top, 'ModalPopup-' + styleString + '-top');
    upperRight.innerHTML = "<div class='popup-" + styleString + "-upperright"
                                + (showXClose ? "-close" : "") + "' />";

    // Toggle the visible state of the XClose Button
    if (showXClose) {
        Sys.UI.DomElement.removeCssClass(xClose, 'Hidden');
    }
    else {
        Sys.UI.DomElement.addCssClass(xClose, 'Hidden');
    }

    // Reset the dialog contents
    content.innerHTML = "";
    content.appendChild(divContent);
    topContent.innerHTML = "";
    topContent.appendChild(SiteCommon.Utils.boldFirstWord(textNodeHeader, 'ModalPopup_header_content_bold'));

    var popup = $find('ModalPopupBehaviorID');
    if (!SiteCommon.Utils.isNullOrUndefined(popup)) {
        popup.show();
    }
}

SiteCommon.Utils.generateErrorDiv = function(response) {
    /// <summary>
    ///     Creates a Div containing the error details as specified in the response parameter.
    /// </summary>
    /// <param name="response">The server response to display.</param>
    // Initialize data values.
    var statusCode = SiteCommon.Utils.isNullOrUndefined(response._statusCode) ? "" : response._statusCode;
    var exceptionType = SiteCommon.Utils.isNullOrUndefined(response._exceptionType) ? "" : response._exceptionType;
    var message = SiteCommon.Utils.isNullOrUndefined(response._message) ? "" : response._message;
    var stackTrace = SiteCommon.Utils.isNullOrUndefined(response._stackTrace) ? "" : response._stackTrace;
    var responseCode = SiteCommon.Utils.isNullOrUndefined(response.ResponseCode) ? "" : response.ResponseCode;
    var responseMessage = SiteCommon.Utils.isNullOrUndefined(response.ResponseMessage) ? "" : response.ResponseMessage;

    // Construct main dialog wrapper.
    var divContent = document.createElement('div');
    Sys.UI.DomElement.addCssClass(divContent, 'PopupDialogContent');

    // Display the error status code
    var p = document.createElement('p');
    p.appendChild(document.createTextNode('Error Encountered (' + response._statusCode + '): ' + exceptionType));
    divContent.appendChild(p);

    // If a ResponseCode was found, display it and the response message.
    if (responseCode != "") {
        p = document.createElement('p');
        p.appendChild(document.createTextNode("ResponseMessage (" + responseCode + "): " + responseMessage));
        divContent.appendChild(p);
    }

    // Add a corresponding error message
    p = document.createElement('p');
    p.appendChild(document.createTextNode(message));
    divContent.appendChild(p);

    // Add the callstack if it is included.
    p = document.createElement('p');
    Sys.UI.DomElement.addCssClass(p, 'PopupErrorContent_stack');

    // Replace any newlines in the stack with <br/>'s
    var index = 0;
    while ((index = stackTrace.indexOf('\n', 0)) >= 0) {
        p.appendChild(document.createTextNode(stackTrace.substring(0, index)));
        p.innerHTML += "<br/>";
        if (index + 1 < stackTrace.length) {
            stackTrace = stackTrace.substring(index + 1);
        }
        else {
            stackTrace = "";
        }
    }
    divContent.appendChild(p);

    return divContent;
}

SiteCommon.Utils.displayErrorMessagePopup = function(textNodeHeader, textNodeMessage) {
    /// <summary>
    ///     Displays a modal error dialog to the user.
    /// </summary>
    /// <param name="textNodeHeader">The dialog header text node.</param>
    /// <param name="textNodeMessage">The message to display.</param>
    var divContent = document.createElement('div');
    Sys.UI.DomElement.addCssClass(divContent, 'PopupErrorDialogContent');
    
    // Display the error message
    var p = document.createElement('p');
    p.appendChild(textNodeMessage);
    divContent.appendChild(p);

    // Launch the dialog.
    SiteCommon.Utils.displayPopup(true, true, textNodeHeader, divContent);
}

SiteCommon.Utils.displayErrorPopup = function(textNodeHeader, response) {
    /// <summary>
    ///     Displays a modal error dialog to the user.
    /// </summary>
    /// <param name="textNodeHeader">The dialog header text node.</param>
    /// <param name="response">The server response to display.</param>

    var divContent = SiteCommon.Utils.generateErrorDiv(response);

    // Launch the dialog.
    SiteCommon.Utils.displayPopup(true, true, textNodeHeader, divContent);
}

SiteCommon.Utils.closePopup = function() {
    /// <summary>
    ///     Displays a modal popup to the user.
    ///
    ///     Currently only implemented for the download confirmation dialog.
    /// </summary>
    var buttonLabel = $get('ModalPopupButtonLabel');
    var closeButton = $get(buttonLabel.innerHTML);
    closeButton.click();
}

SiteCommon.Utils.isSuccessResponse = function(response) {
    /// <summary>
    ///     Validates the provided JSON encoded server response doesn't contain a non-succesful StatusCode or ResponseCode.
    /// </summary>
    /// <param name="response">The server response to check.</param>
    /// <returns>
    ///     A bool value, true if the codes weren't error conditions, false otherwise.
    /// </returns>
    var isSuccess = false;
    // We assume non-error unless one is detected (due to JSON allowing values to be undefined)
    var isStatusCodeSuccess = true;
    var isResponseCodeSuccess = true;

    if (!SiteCommon.Utils.isNullOrUndefined(response)) {
        // If a statusCode is defined, then validate it.
        if (!SiteCommon.Utils.isNullOrUndefined(response._statusCode)) {
            isStatusCodeSuccess = (response._statusCode == 200);
        }

        // If a responseCode is defined, then validate it.
        if (!SiteCommon.Utils.isNullOrUndefined(response.ResponseCode)) {
            isResponseCodeSuccess = (response.ResponseCode == "0x00000000");
        }

        isSuccess = (isStatusCodeSuccess && isResponseCodeSuccess);
    }

    return isSuccess;
}

SiteCommon.Utils.simpleXAnimation = function(hostingObject, domElement, startX, endX, stepCount, interval, onCompletedHandler) {
    /// <summary>
    ///     Animations a provided object over the x-axis based on the input parameters.
    /// </summary>
    /// <param name="hostingObject">The hosting UI object of the animation.</param>
    /// <param name="domElement">The dom object to animation.</param>
    /// <param name="startX">The x position to start the animation.</param>
    /// <param name="endX">The x position to end the animation.</param>
    /// <param name="stepCount">The number of steps for the animation.</param>
    /// <param name="interval">The time to wait between steps.</param>
    /// <param name="onCompletedHandler">The animation completed handler to call.</param>
    var delta = (endX - startX) / stepCount;
    var currentX = 0;
    var currentStep = 1;
    hostingObject._animationInterval = window.setInterval(function() {
        currentX = startX + parseInt(delta * currentStep + 0.5);
        Sys.UI.DomElement.setLocation(domElement, currentX, 0);
        currentStep++;
        if (currentStep > stepCount) {
            window.clearInterval(hostingObject._animationInterval);
            if (!SiteCommon.Utils.isNullOrUndefined(onCompletedHandler)) {
                onCompletedHandler(hostingObject);
            }
        }
    }, interval);
}

SiteCommon.Utils.createLoadingDiv = function(loadingMsg) {
    /// <summary>
    ///     Create the UI for a loading message.
    /// </summary>
    /// <returns>
    ///     A dom element to use as a loading message.
    /// </returns>
    var div = document.createElement('div');
    Sys.UI.DomElement.addCssClass(div, 'LoadingMessage');

    var p = document.createElement('p');
    p.appendChild(document.createTextNode(loadingMsg));
    div.appendChild(p);

    var divImg = document.createElement('div');
    Sys.UI.DomElement.addCssClass(divImg, 'LoadingMessage_image');
    div.appendChild(divImg);

    return div;
}

SiteCommon.Utils.createReloadDiv = function(parentId, refreshMsg, busyMsg) {
    /// <summary>
    ///     Create the UI for a reload message.
    /// </summary>
    /// <param name="parentId">Id of the parent view.</param>
    /// <returns>
    ///     An object with two properties:
    ///         object.reloadButton: A reference to the actual reload button DOM element.
    ///         object.div: The main div of the UI element.
    /// </returns>
    var returnObj = new Object();

    var div = document.createElement('div');
    Sys.UI.DomElement.addCssClass(div, 'LoadingMessage');

    var p = document.createElement('p');
    p.appendChild(document.createTextNode(busyMsg));
    div.appendChild(p);

    var divImg = document.createElement('div');
    Sys.UI.DomElement.addCssClass(divImg, 'LoadingMessage_image');
    div.appendChild(divImg);

    var divReload = document.createElement('div');
    divReload.setAttribute('id', parentId + "_reload");
    returnObj.reloadButton = divReload;
    divReload.appendChild(document.createTextNode(refreshMsg));
    Sys.UI.DomElement.addCssClass(divReload, 'ReloadMessage_button CursorHand');
    div.appendChild(divReload);

    returnObj.div = div;

    return returnObj;
}
SiteCommon.Utils.createElement = function(type, parent, id, cssClass, appendChild) {
    ///<summary>
    ///     Creates a new element
    ///</summary>
    /// <param name="type">Type of the new element.</param>    
    /// <param name="parent">Parent div to add new element to.</param>
    /// <param name="id">ID of the new element.</param>
    /// <param name="cssClass">Css Class to add to the new element.</param>
    /// <param name="appendChild">First child element to add to the new element.</param>

    var divName = document.createElement(type);

    if (!SiteCommon.Utils.isNullOrUndefined(id)) {
        divName.setAttribute('id', id);
    }
    if (!SiteCommon.Utils.isNullOrUndefined(parent)) {
        parent.appendChild(divName);
    }

    if (!SiteCommon.Utils.isNullOrUndefined(cssClass)) {
        Sys.UI.DomElement.addCssClass(divName, cssClass);
    }
    if (!SiteCommon.Utils.isNullOrUndefined(appendChild)) {
        divName.appendChild(appendChild);
    }
    return divName;
}

SiteCommon.Utils.DisplayConfirmationDialog = function(textTitle, textContent, textHeader, textOk,
                                                textCancel, okClickHandler) {
    /// <summary>
    ///     Create the UI for a loading message.
    /// </summary>
    /// <returns>
    ///     A dom element to use as a loading message.
    /// </returns>
    var headerUI = SiteCommon.Utils.toUIString(textTitle);
    var contentHeaderUI = SiteCommon.Utils.createElement('h2', null,
                            'ConfirmHeader', 'Confirmation_Content_Header',
                            SiteCommon.Utils.toUIString(textHeader));
    var contentUI = SiteCommon.Utils.toUIString(textContent);
    var okUI = SiteCommon.Utils.toUIString(textOk);
    var cancelUI = SiteCommon.Utils.toUIString(textCancel);

    var contentDiv = SiteCommon.Utils.CreateDiv(null, 'Confirmation_Content',
                        null, null);

    //Add text as a div                        
    var contentUIDiv = SiteCommon.Utils.CreateDiv(contentDiv, 'Confirmation_Content_Text',
                        null, contentHeaderUI);
    contentUIDiv.appendChild(contentUI);

    //Add clear:both div
    SiteCommon.Utils.CreateDiv(contentDiv, 'Confirmation_Content_Clear',
                              'clear', null);

    //Add OK & Cancel buttons
    var btn_cancel = SiteCommon.Utils.CreateButton(textCancel, 'Confirmation_Cancel',
                    'WhiteButton', 'SiteCommon.Utils.closePopup();');
    contentDiv.appendChild(btn_cancel);

    var btn_ok = SiteCommon.Utils.CreateButton(textOk, 'Confirmation_Ok',
                                'OrangeButton', okClickHandler);
    contentDiv.appendChild(btn_ok);

    //Show the popup
    SiteCommon.Utils.displayPopup(false, true, headerUI, contentDiv);
}

SiteCommon.Utils.getShowPurchaseConfirmation = function() {
    ///<summary>
    ///     Check whether or not to show the purchase confirmation dialog
    ///     by reading the 'BypassPurchaseConf' cookie value
    ///</summary>
    ///<return>
    /// true or false
    ///</return>    
    var bypassPurchaseConf = SiteCommon.Utils.readCookie('BypassPurchaseConf');
    if (SiteCommon.Utils.isNullOrUndefined(bypassPurchaseConf)) {
        return true;
    } else {
        return false;
    }
}

SiteCommon.Utils.setShowPurchaseConfirmation = function(checkBoxId) {
    ///<summary>
    ///     Set the 'BypassPurchaseConf' cookie value to bypass showing the 
    ///     purchase confirmation dialog
    ///</summary>

    var checkBox = document.getElementById(checkBoxId);

    if (!SiteCommon.Utils.isNullOrUndefined(checkBox) && checkBox.checked) {
        SiteCommon.Utils.createCookie('BypassPurchaseConf', '1', 14);
    }
}

SiteCommon.Utils.createCookie = function(name, value, days) {
    ///<summary>
    /// create cookie
    ///</summary>
    ///<param name="name">cookie name</param>
    ///<param name="value">cookie value</param>
    ///<param name="days">Pass in zero - cookie will expire when close browser</param>
    if (days) {
        var date = new Date();
        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
        var expires = "; expires=" + date.toGMTString();
    }
    else var expires = "";
    document.cookie = name + "=" + value + expires + "; path=/";
}

SiteCommon.Utils.readCookie = function(name) {
    ///<summary>
    ///     Read cookie
    ///</summary>
    ///<param name="name">cookie name</param>
    ///<returns>
    ///     return cookie value
    ///</return>
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') c = c.substring(1, c.length);
        if (c.indexOf(nameEQ) == 0) {
            return c.substring(nameEQ.length, c.length);
        }
    }
    return null;
}

SiteCommon.Utils.extractValueFromACookie = function(CookieName, KeyName) {
    ///<summary>
    ///     Extract a specific value from a cookie
    ///</summary>
    ///<param name="name">Key name</param>
    ///<returns>
    ///     return value of the Key/Value pair
    ///</return>
    var sCookieValues = SiteCommon.Utils.readCookie(CookieName);
    var nameEQ = KeyName + "=";
    var ca = sCookieValues.split('&');
    for (var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') c = c.substring(1, c.length);
        if (c.indexOf(nameEQ) == 0) {
            return c.substring(nameEQ.length, c.length);
        }
    }
    return null;
}

SiteCommon.Utils.eraseCookie = function(name) {
    ///<summary>
    ///     Delete existing cookie
    ///</summary>
    ///<param name="name">cookie name</param>
    createCookie(name, "", -1);
}


SiteCommon.Utils.CreateDiv = function(parent, id, cssClass, appendChild) {
    ///<summary>
    ///     Creates a new div element
    ///</summary>
    /// <param name="parent">Parent div to add new div element to.</param>
    /// <param name="id">ID of the new div element.</param>
    /// <param name="cssClass">Css Class to add to the new div element.</param>
    /// <param name="appendChild">First child element to add to the new element.</param>

    return SiteCommon.Utils.createElement(SiteCommon.Utils.elementTypes.div, parent, id, cssClass, appendChild);
}
SiteCommon.Utils.CreateImg = function(parent, id, cssClass, url, text) {
    ///<summary>
    ///     Creates a new image element
    ///</summary>
    /// <param name="parent">Parent div to add new div element to.</param>
    /// <param name="id">ID of the new div element.</param>
    /// <param name="cssClass">Css Class to add to the new div element.</param>
    /// <param name="url">URL to the image.</param>

    var img = SiteCommon.Utils.createElement(SiteCommon.Utils.elementTypes.img, parent, id, cssClass, null);
    img.setAttribute('src', url);
    img.setAttribute('alt', text);
    return img;
}

SiteCommon.Utils.CreateSpan = function(parent, id, cssClass, appendChild) {
    ///<summary>
    ///     Creates a new span element
    ///</summary>
    /// <param name="parent">Parent div to add new span element to.</param>
    /// <param name="id">ID of the new span element.</param>
    /// <param name="cssClass">Css Class to add to the new span element.</param>
    /// <param name="appendChild">First child element to add to the new span element.</param>

    return SiteCommon.Utils.createElement(SiteCommon.Utils.elementTypes.span, parent, id, cssClass, appendChild);
}

SiteCommon.Utils.CreatePara = function(parent, id, cssClass, appendChild) {
    ///<summary>
    ///     Creates a new Para element
    ///</summary>
    /// <param name="parent">Parent div to add new para element to.</param>
    /// <param name="id">ID of the new span element.</param>
    /// <param name="cssClass">Css Class to add to the new para element.</param>
    /// <param name="appendChild">First child element to add to the new para element.</param>

    return SiteCommon.Utils.createElement(SiteCommon.Utils.elementTypes.p, parent, id, cssClass, appendChild);
}

SiteCommon.Utils.CreateLink = function(parent, id, cssClass, appendChild, onClick, href) {
    ///<summary>
    ///     Creates a new link element
    ///</summary>
    /// <param name="parent">Parent div to add new link element to.</param>
    /// <param name="id">ID of the new link element.</param>
    /// <param name="cssClass">Css Class to add to the new link element.</param>
    /// <param name="appendChild">First child element to add to the new link element.</param>
    /// <param name="onClick">OnClick event to add to the new link element.</param>
    /// <param name="href">Href element to add to the new link element.</param>

    var link = SiteCommon.Utils.createElement(SiteCommon.Utils.elementTypes.a, parent, id, cssClass, appendChild);
    if (!SiteCommon.Utils.isNullOrUndefined(onClick)) {
        link.setAttribute('href', 'javascript:' + onClick);
    }
    else if (!SiteCommon.Utils.isNullOrUndefined(href)) {
        link.setAttribute('href', href);
    }
    else {
        link.setAttribute('href', '#');
    }

    return link;
}

SiteCommon.Utils.CreateTable = function(parent, id, cssClass, appendChild) {
    ///<summary>
    ///     Creates a new Table element
    ///</summary>
    /// <param name="parent">Parent div to add new Table element to.</param>
    /// <param name="id">ID of the new Table element.</param>
    /// <param name="cssClass">Css Class to add to the new Table element.</param>
    /// <param name="appendChild">First child element to add to the new Table element.</param>

    return SiteCommon.Utils.createElement(SiteCommon.Utils.elementTypes.table, parent, id, cssClass, appendChild);
}

SiteCommon.Utils.CreateTableRow = function(parent, id, cssClass, appendChild, colspan) {
    ///<summary>
    ///     Creates a new Table Row element
    ///</summary>
    /// <param name="parent">Parent div to add new Table Row element to.</param>
    /// <param name="id">ID of the new Table Row element.</param>
    /// <param name="cssClass">Css Class to add to the new Table Row element.</param>
    /// <param name="appendChild">First child element to add to the new Table Row element.</param>

    var row = SiteCommon.Utils.createElement(SiteCommon.Utils.elementTypes.row, parent, id, cssClass, appendChild);
    if (!SiteCommon.Utils.isNullOrUndefined(colspan)) {
        row.setAttribute('colspan', colspan);
    }
    return row;
}

SiteCommon.Utils.CreateTableColumn = function(parent, id, cssClass, appendChild, rowspan) {
    ///<summary>
    ///     Creates a new Table Column element
    ///</summary>
    /// <param name="parent">Parent div to add new Table Column element to.</param>
    /// <param name="id">ID of the new Table Column element.</param>
    /// <param name="cssClass">Css Class to add to the new Table Column element.</param>
    /// <param name="appendChild">First child element to add to the new Table Column element.</param>

    var col = SiteCommon.Utils.createElement(SiteCommon.Utils.elementTypes.column, parent, id, cssClass, appendChild);
    if (!SiteCommon.Utils.isNullOrUndefined(rowspan)) {
        col.setAttribute('rowspan', rowspan);
    }
    return col;
}

SiteCommon.Utils.CreateButton = function(text, id, cssClassBase, onClick) {
    /// <summary>
    ///     Create a button and returns the wrapping Div DOM element.
    /// </summary>
    /// <param name="text">Text to use as button value.</param>
    /// <param name="id">DOM ID to attach to the resulting elements.</param>
    /// <returns>
    ///     A reference the wrapping DOM element.
    /// </returns>

    var div = document.createElement('div');
    div.setAttribute('id', id + '_wrapper');
    Sys.UI.DomElement.addCssClass(div, cssClassBase);

    var button = document.createElement('a');
    button.setAttribute('id', id + '_button');
    button.appendChild(SiteCommon.Utils.toUIString(text));
    Sys.UI.DomElement.addCssClass(button, cssClassBase + 'Text');
    button.setAttribute('href', 'javascript:' + onClick);
    var divRight = document.createElement('div');
    divRight.setAttribute('id', id + '_right');
    Sys.UI.DomElement.addCssClass(divRight, cssClassBase + 'Div');

    div.appendChild(button);
    div.appendChild(divRight);

    return div;
}
SiteCommon.Utils.CreateRadioButton = function(id, name, value, onClick, isChecked) {
    /// <summary>
    ///     Create a radio button that will work for both IE and FireFox. 
    /// </summary>
    /// <param name="id">id attribute of radio button</param>
    /// <param name="name">name required attribute to group radio button</param>
    /// <param name="value">value of the radio button</param>
    /// <param name="onClick">String representation of javascript call</param>
    /// <param name="isChecked">default is fault</param>
    /// <returns>
    ///     A reference of a radiobutton.
    /// </returns>
    //This to handle IE createElement bug that prevents radio button to be selectable
    var radiobutton = null;
    var html = '';
    if (SiteCommon.Utils.isNullOrUndefined(isChecked)) {
        isChecked = false;
    }

    try {
        if (!SiteCommon.Utils.isNullOrUndefined(onClick)) {
            html = '<input type="radio" id="' + id + '" name="' + name + '" value="' + value + '" onClick="' + onClick + '" ';
        } else {
            html = '<input type="radio" id="' + id + '" name="' + name + '" value="' + value + '"';
        }

        if (isChecked) {
            html += 'checked="checked">';
        } else {
            html += '>';
        }
        radiobutton = document.createElement(html);
    } catch (e) {
        //do nothing
    }

    //if FireFox/Netscape checkbox will be null.
    if (SiteCommon.Utils.isNullOrUndefined(radiobutton)) {
        radiobutton = document.createElement('input');
        radiobutton.setAttribute('type', 'radio');
        radiobutton.setAttribute('id', id);
        radiobutton.setAttribute('name', name);
        radiobutton.setAttribute('value', value);
        if (!SiteCommon.Utils.isNullOrUndefined(onClick)) {
            radiobutton.setAttribute('onclick', onClick);
        }
        if (isChecked) {
            radiobutton.setAttribute('checked', 'checked');
        }
    }
    return radiobutton;
}
SiteCommon.Utils.CreateCheckBox = function(id, isChecked) {
    /// <summary>
    ///     Create a checkbox that will with in both IE and FireFox
    /// </summary>
    /// <param name="id">ID that will be assigned to the checkbox ID attribute</param>
    /// <param name="isChecked">default to false unless pass in true</param>
    /// <returns>
    ///     A checkbox reference.
    /// </returns>
    var checkbox = null;
    try {
        if (isChecked) {
            checkbox = document.createElement('<input type="checkbox" id="' + id + '" checked=checked />');
        } else {
            checkbox = document.createElement('<input type="checkbox" id="' + id + '" />');
        }
    } catch (e) {
        //do nothing
    }

    //if FireFox/Netscape checkbox will be null.
    if ((checkbox == null || checkbox == undefined)) {
        checkbox = document.createElement('input');
        checkbox.setAttribute('type', 'checkbox');
        checkbox.setAttribute('id', id);
        checkbox.checked = isChecked;
    }

    return checkbox;

}

SiteCommon.Utils.CreateRatings = function(parent, id, cssClass, rating) {
    ///<summary>
    ///     Creates a new ratings div containing star icons
    ///</summary>
    /// <param name="parent">Parent div to add new element to.</param>
    /// <param name="id">ID of the new element.</param>
    /// <param name="cssClass">Css Class to add to the new element.</param>
    /// <param name="rating">Rating number to specify the number of active stars.</param>

    var mainDiv = SiteCommon.Utils.CreateDiv(parent, id, cssClass, null);
    for (var i = 0; i < 5; i++) {
        if (i < rating) {
            //Add active star
            var star = SiteCommon.Utils.CreateDiv(mainDiv, id + i,
                            'sprite ProductRatingStar', null);
        }
        else {
            //Add empty star
            star = SiteCommon.Utils.CreateDiv(mainDiv, id + i,
                            'sprite ProductRatingStarEmpty', null);
        }
    }
    return mainDiv;
}

SiteCommon.Utils.TriggerEvent = function(ElementID, TargetID, RedirectURL) {
    /// <summary>
    ///     Trigger and event based on ElementID
    /// </summary>
    /// <param name="ElementID">ID of an object to trigger and event from</param>
    /// <param name="TargetID">Name of sender that call this function</param>
    /// <param name="RedirectURL">Optional - URL to redirect to appropriate page if needed.</param>

    var controller = $find(ElementID);
    controller.handleEvent(TargetID, RedirectURL);
}

SiteCommon.Utils.JsonParser = function(json) {
    ///<summary>
    ///     Creates a Json parsed object from a string
    ///</summary>
    /// <param name="json">String containing data in Json format.</param>
    /// <returns>    Json Object
    /// </returns>
    return eval(json)[0];
}

SiteCommon.Utils.QueryString = function(key) {
    ///<summary>
    ///     Gets the specified key value from the querystring
    ///</summary>
    /// <param name="key">key to look for</param>
    /// <returns>    value for the key in the current querystring
    /// </returns>
    return SiteCommon.Utils.QueryStringInUrl(key, window.location.href);
}

SiteCommon.Utils.QueryStringInUrl = function(key, url) {
    ///<summary>
    ///     Gets the specified key value from the querystring
    ///</summary>
    /// <param name="key">key to look for</param>
    /// <param name="url">url to look into</param>
    /// <returns>    value for the key in the given url
    /// </returns>
    key = key.replace(/[\[]/, "\\\[").replace(/[\]]/, "\\\]");
    var regex = new RegExp("[\\?&]" + key + "=([^&#]*)");
    var qs = regex.exec(url);
    if (qs == null) {
        return null;
    }
    else {
        return qs[1];
    }
}

SiteCommon.Utils.FixUrlProtocol = function(url) {
    ///<summary>
    ///     Modifies the url to fix the protocol in the url
    ///     using the current window's protocol
    ///</summary>
    /// <param name="url">url to look into</param>
    /// <returns>    updated url
    /// </returns>

    if (SiteCommon.Utils.isNullOrUndefined(url)) {
        return url;
    }

    var prot = window.location.protocol.toLowerCase();
    if (url.toLowerCase().substr(0, prot.length) == prot) {
        return url;
    }
    else {
        var index = url.toString().indexOf(':', 0)
        return prot + url.substring(index + 1, url.length);
    }
}

SiteCommon.Utils.AddEllipses = function(s, n) {
    ///<summary> 
    /// Trims the string to the desired length
    /// and adds ellipses only if the string is longer 
    /// than this specified length
    ///</summary>
    /// <param name="s">string to chop</param>
    /// <param name="n">number of chars to cut string</param>
    if (!SiteCommon.Utils.isNullOrUndefined(s)
        && s.length > n) {
        return s.substr(0, n).trimEnd() + '...';
    }
    return s;
}

SiteCommon.Utils.OpenNewWindow = function(url) {
    var wMax, hMax

    try {
        if (screen.width > 0 && screen.height > 0) {
            wMax = screen.width;
            hMax = screen.height;
        } else if (window.outerWidth > 0 && window.outerHeight > 0) {
            wMax = window.outerWidth;
            hMax = window.outerHeight;
        } else {
            wMax = 1280;
            hMax = 960;
        }
    } catch (e) {
        wMax = 1280;
        hMax = 960;
    }

    var d = url; if (!d) return;
    var w = wMax / 2;
    var h = hMax / 2;

    try {
        if (xwin && !xwin.closed) xwin.close();
    } catch (e) { };

    xwin = window.open(d, 'mywindow', 'height=' + h + ',width=' + w + ',top=' + (hMax - h) / 2 + ',left=' + (wMax - w) / 2 + ',resizable=1,scrollbars=1');
    setTimeout('xwin.location=\'' + d + '\';xwin.focus()', 1500);
}

SiteCommon.Utils.OmnitureTrackPurchase = function(pageName, channel, appSku, productName, cost) {
    s.pageName = pageName;
    s.channel = channel;
    s.events = "purchase";
    s.products = "CC;" + productName + ";1;" + cost;
    SiteCommon.Utils.OmnitureSubmit();
}

SiteCommon.Utils.OmnitureTrackThumbnailClick = function(thumbnailNumber) {
    s.prop18 = "Slot " + thumbnailNumber;
    SiteCommon.Utils.OmnitureSubmit();
}

SiteCommon.Utils.OmnitureTrackThumbnailPage = function(thumbnailPage) {
    s.prop18 = "Page " + thumbnailPage;
    SiteCommon.Utils.OmnitureSubmit();
}

SiteCommon.Utils.OmnitureTrackSearch = function(searchQuery) {
    s.prop32 = searchQuery;
    SiteCommon.Utils.OmnitureSubmit();
}

SiteCommon.Utils.OmnitureSubmit = function() {
    var s_code = s.t(); if (s_code) document.write(s_code);
}

SiteCommon.Utils.elementTypes = { div: 'div', span: 'span', a: 'a', img: 'img',
    p: 'p', table: 'table', row: 'tr', column: 'td'
};
/// <field name="elementTypes">An enum of possible element types used in the function SiteCommon.Utils.createElement.</field>

SiteCommon.Utils.chartIds = { 'popular': 'popular', 'whatshot': 'whatshot', 'whatsnew': 'whatsnew' };
/// <field name="chartIds">A static list of possible chart types.</field>

SiteCommon.Utils.registerClass('SiteCommon.Utils', Sys.Component);


/// ***************************************************************************************************************
///
///     This function has been taken from MicrosoftAjax.js, and is used to complete the response codes sent
///     back to the callback once a proper WCF call has taken place.  It has been copied here to allow a single
///     line change (highlighted in place) to support REST calls.  The problem is that when an HTTP errorcode
///     (or rather an non-200 response) is enountered this library throws away the server response and only
///     returns a chunk of generic information.  This does not support REST api's that should allow additional
///     (partial) data to be returned along with the StatusCode.
///
///     The single change below ensures that the original server response is passed through, unless it is
///     of type HTML.  This allows any of our REST overloaded responses to make it through, but html errors
///     (server errors before out code, some LiveID errors, etc) will be passed through in the original
///     format.
///
///     The entire function is defined here, as it is the only way to modify the line in question, and due
///     to JSON, we can just redefine a function at any time and it will be used instead of the original.
///
/// ***************************************************************************************************************
Sys.Net.WebServiceProxy.invoke = function Sys$Net$WebServiceProxy$invoke(servicePath, methodName, useGet, params, onSuccess, onFailure, userContext, timeout) {
    /// <summary locid="M:J#Sys.Net.WebServiceProxy.invoke" />
    /// <param name="servicePath" type="String"></param>
    /// <param name="methodName" type="String"></param>
    /// <param name="useGet" type="Boolean" optional="true"></param>
    /// <param name="params" mayBeNull="true" optional="true"></param>
    /// <param name="onSuccess" type="Function" mayBeNull="true" optional="true"></param>
    /// <param name="onFailure" type="Function" mayBeNull="true" optional="true"></param>
    /// <param name="userContext" mayBeNull="true" optional="true"></param>
    /// <param name="timeout" type="Number" optional="true"></param>
    /// <returns type="Sys.Net.WebRequest"></returns>
    var e = Function._validateParams(arguments, [
        { name: "servicePath", type: String },
        { name: "methodName", type: String },
        { name: "useGet", type: Boolean, optional: true },
        { name: "params", mayBeNull: true, optional: true },
        { name: "onSuccess", type: Function, mayBeNull: true, optional: true },
        { name: "onFailure", type: Function, mayBeNull: true, optional: true },
        { name: "userContext", mayBeNull: true, optional: true },
        { name: "timeout", type: Number, optional: true }
    ]);
    if (e) throw e;
    var request = new Sys.Net.WebRequest();
    request.get_headers()['Content-Type'] = 'application/json; charset=utf-8';
    if (!params) params = {};
    var urlParams = params;
    if (!useGet || !urlParams) urlParams = {};
    request.set_url(Sys.Net.WebRequest._createUrl(servicePath + "/" + encodeURIComponent(methodName), urlParams));
    var body = null;
    if (!useGet) {
        body = Sys.Serialization.JavaScriptSerializer.serialize(params);
        if (body === "{}") body = "";
    }
    request.set_body(body);
    request.add_completed(onComplete);
    if (timeout && timeout > 0) request.set_timeout(timeout);
    request.invoke();
    function onComplete(response, eventArgs) {
        if (response.get_responseAvailable()) {
            var statusCode = response.get_statusCode();
            var result = null;

            try {
                var contentType = response.getResponseHeader("Content-Type");
                if (contentType.startsWith("application/json")) {
                    result = response.get_object();
                }
                else if (contentType.startsWith("text/xml")) {
                    result = response.get_xml();
                }
                else {
                    result = response.get_responseData();
                }
            } catch (ex) {
            }
            var error = response.getResponseHeader("jsonerror");
            var errorObj = (error === "true");
            if (errorObj) {
                if (result) {
                    result = new Sys.Net.WebServiceError(false, result.Message, result.StackTrace, result.ExceptionType);
                }
            }
            else if (contentType.startsWith("application/json")) {
                if (!result || typeof (result.d) === "undefined") {
                    throw Sys.Net.WebServiceProxy._createFailedError(methodName, String.format(Sys.Res.webServiceInvalidJsonWrapper, methodName));
                }
                result = result.d;
            }
            if (((statusCode < 200) || (statusCode >= 300)) || errorObj) {
                if (onFailure) {
                    // **************************************************************************************
                    // Changed this line to only clobber result here if an html response has been found.
                    if (contentType.startsWith("text/html")) {
                        // **************************************************************************************
                        result = new Sys.Net.WebServiceError(false, String.format(Sys.Res.webServiceFailedNoMsg, methodName), "", "");
                    }
                    result._statusCode = statusCode;
                    onFailure(result, userContext, methodName);
                }
                else {
                    var error;
                    if (result && errorObj) {
                        error = result.get_exceptionType() + "-- " + result.get_message();
                    }
                    else {
                        error = response.get_responseData();
                    }
                    throw Sys.Net.WebServiceProxy._createFailedError(methodName, String.format(Sys.Res.webServiceFailed, methodName, error));
                }
            }
            else if (onSuccess) {
                onSuccess(result, userContext, methodName);
            }
        }
        else {
            var msg;
            if (response.get_timedOut()) {
                msg = String.format(Sys.Res.webServiceTimedOut, methodName);
            }
            else {
                msg = String.format(Sys.Res.webServiceFailedNoMsg, methodName)
            }
            if (onFailure) {
                onFailure(new Sys.Net.WebServiceError(response.get_timedOut(), msg, "", ""), userContext, methodName);
            }
            else {
                throw Sys.Net.WebServiceProxy._createFailedError(methodName, msg);
            }
        }
    }
    return request;
}

/// <reference name="MicrosoftAjax.js"/>
/// <reference path="~/AjaxControls/InteractiveBaseControl.js" />
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  ContentSliderView.js
*
*      Displays the details of an Application.
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("DevPortal");

DevPortal.ContentSliderView = function(element) {
    /// <summary>
    ///     ContentSliderView Constructor.  DO NOT CALL DIRECTLY, USE $CREATE.
    /// </summary>
    /// <param name="element">HTML DomElement to associate.</param>
    /// <returns>
    ///     A newly created ContentSliderView object.
    /// </returns>
    DevPortal.ContentSliderView.initializeBase(this, [element]);
}

DevPortal.ContentSliderView.prototype = {
    initialize: function() {
        /// <summary>
        ///     Initialize.  DO NOT CALL DIRECTLY, USE $CREATE.
        ///     
        ///     Initializes the view.
        /// </summary>

        DevPortal.ContentSliderView.callBaseMethod(this, 'initialize');

        this._listSlides = new Array();
        this.add_click(this._onClick);
        this._curIndex = 0;
        this._newIndex = -1;
        this._handlingSlide = false;
        // Length of time to aim for full animation.
        this._slideTime = 400;
        // Amount of time to wait between calls
        this._slideWait = this._slideTime / 30; // (30 ~= 30fps, where 1000/30 => 33.333 ms and some time for processing.)
    },
    _setupRender: function() {
        /// <summary>
        ///     Sets up the slider main element.
        /// </summary>

        // Set the main CSS style for the element
        Sys.UI.DomElement.addCssClass(this.get_element(), 'ContentSlider ContentSlider_' + this.sliderType);

        // Create a table for the slide elements
        this._slidesTable = document.createElement('table');
        this.get_element().appendChild(this._slidesTable);
        var tbody = document.createElement('tbody');
        tbody.setAttribute('vAlign', 'top');
        this._slidesTable.appendChild(tbody);
        this._slidesTR = document.createElement('tr');
        tbody.appendChild(this._slidesTR);

        // Create a table for the buttons
        var table = document.createElement('table');
        this.get_element().appendChild(table);
        Sys.UI.DomElement.addCssClass(table, 'ContentSlider_buttonBar ContentSlider_' + this.sliderType + '_buttonBar'); // absolutely position, high z-order
        var tbody = document.createElement('tbody');
        table.appendChild(tbody);
        var tr = document.createElement('tr');
        tbody.appendChild(tr);
        var td = document.createElement('td');
        tr.appendChild(td);

        // Create the left button
        var leftButton = document.createElement('div');
        var buttonName = this.get_id() + '_left';
        leftButton.setAttribute('id', buttonName);
        Sys.UI.DomElement.addCssClass(leftButton, 'CursorHand ContentSlider_buttonBar_left');
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click, buttonName, { 'button': 'left' });
        td.appendChild(leftButton);
        var td = document.createElement('td');
        tr.appendChild(td);

        // Create the right button
        var rightButton = document.createElement('div');
        buttonName = this.get_id() + '_right';
        rightButton.setAttribute('id', buttonName);
        Sys.UI.DomElement.addCssClass(rightButton, 'CursorHand ContentSlider_buttonBar_right');
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click, buttonName, { 'button': 'right' });
        td.appendChild(rightButton);
    },
    dataRender: function() {
        /* Declared for interface */
    },
    addSlide: function(domElement) {
        /// <summary>
        ///     Called to add a element to the slide deck.
        /// </summary>
        /// <param name="domElement">HTML DOM element to add as member of the slide.</param>

        var index = this._listSlides.length;
        this._listSlides[index] = domElement;
        domElement.setAttribute('id', this.get_id() + '_' + index);

        Sys.UI.DomElement.addCssClass(domElement, 'ContentSlider_slideItem');
        var td = document.createElement('td');
        td.appendChild(domElement);
        this._slidesTR.appendChild(td);
    },
    setSlide: function(index, animate) {
        /// <summary>
        ///     Show a particular slide from the deck.
        /// </summary>
        /// <param name="index">Index of the slide to navigate to.</param>
        if ((index > this._listSlides.length - 1) || (index < 0)) {
            throw "Content Slider index is out of range.";
        }

        // Check non-animated, then assign the new location directly.
        if (!animate) {
            this._curIndex = index;
            Sys.UI.DomElement.setLocation(this._slidesTable, -(this.slideWidth * index), 0);
        }
        else {
            // Animate the element change, based on the setup parameters.
            this._newIndex = index;
            var slideSteps = Math.ceil(this._slideTime / this._slideWait);

            SiteCommon.Utils.simpleXAnimation(this,                                 // owning object
                                              this._slidesTable,                    // domElement to slide
                                              -this.slideWidth * this._curIndex,    // current X location
                                              -this.slideWidth * this._newIndex,    // current Y location
                                              slideSteps,                           // number of steps to take
                                              this._slideWait,                      // delay between animation steps
                                              this._slideComplete);                 // animation completed callback.
        }

    },
    _slideComplete: function(context) {
        /// <summary>
        ///     Notification of animation completion.
        /// </summary>
        /// <param name="context">ContentSliderView object that was animating.</param>
        context._handlingSlide = false;
        // Call non-animated setSlide to ensure no animation rounding affects layout, and to update the current index.
        context.setSlide(context._newIndex, false);
    },
    dispose: function() {
        /// <summary>
        ///     Called to dispose of this objects resources.
        /// </summary>

        DevPortal.ContentSliderView.callBaseMethod(this, 'dispose');
    },
    _onClick: function(sender, args) {
        /// <summary>
        ///     Click event handler for the subcategoryname.
        /// </summary>
        /// <param name="sender">CategoryListView object that is hovered.</param>
        /// <param name="args">Event args.</param>

        var handled = false;

        if (!sender._handlingSlide) {
            // Notify the controller that a category was clicked.
            if (!SiteCommon.Utils.isNullOrUndefined(args.customData)) {
                var newIndex = -1;
                if (args.customData.button == 'right') {
                    var newIndex = (sender._curIndex == sender._listSlides.length - 1) ? 0 : sender._curIndex + 1;
                    var handled = true;
                }
                else if (args.customData.button == 'left') {
                    var newIndex = (sender._curIndex == 0) ? sender._listSlides.length - 1 : sender._curIndex - 1;
                    var handled = true;
                }
                if ((newIndex != sender._curIndex) && (newIndex >= 0) && (newIndex < sender._listSlides.length)) {
                    sender._handlingSlide = true;
                    sender.setSlide(newIndex, true);
                }
            }
        }
        if (handled) {
            // Mark the event as handled to avoid refiring.
            SiteCommon.Utils.markEventHandled(event);
        }
    }
}

DevPortal.ContentSliderView.prototype.sliderType = "";
/// <field name="sliderType">The slider Type for css display.</field>
DevPortal.ContentSliderView.prototype.slideWidth = 0;
/// <field name="slideWidth">The width of the slider window to view (used for sliding to next element).</field>

DevPortal.ContentSliderView.registerClass('DevPortal.ContentSliderView', SiteCommon.InteractiveBaseView);


/// <reference name="MicrosoftAjax.js"/>

Type.registerNamespace("DashboardUtils");

DashboardUtils = function() { }

DashboardUtils.showAddMenu = function(sender, args) {
    ShowPop("MenuProd", "block")
}
DashboardUtils.hideAddMenu = function(sender, args) {
    ShowPop("MenuProd", "none")
}
DashboardUtils.AddApp = function() {
    DevPortal.Utils.SetDefaultTab(1); // must come before location.search change for FF.
    window.location.search = "?skutype=app&pageid=1";
}
DashboardUtils.AddWidget = function() {
    DevPortal.Utils.SetDefaultTab(1); // must come before location.search change for FF.
    window.location.search = "?skutype=widget&pageid=1";
}
DashboardUtils.addHoverHandler = function(element, handler) {
    if (!SiteCommon.Utils.isNullOrUndefined(element)) {
        Sys.UI.DomEvent.addHandler(element, "mouseover", handler);
        Sys.UI.DomEvent.addHandler(element, "focus", handler);
    }
}
DashboardUtils.addClickHandler = function(element, handler) {
    if (!SiteCommon.Utils.isNullOrUndefined(element)) {
        Sys.UI.DomEvent.addHandler(element, "click", handler);
    }
}
DashboardUtils.addUnHoverHandler = function(element, handler) {
    if (!SiteCommon.Utils.isNullOrUndefined(element)) {
        Sys.UI.DomEvent.addHandler(element, "mouseout", handler);
        Sys.UI.DomEvent.addHandler(element, "blur", handler);
    }
}
DashboardUtils.load = function() {
    var btn = document.getElementById("AddProd");
    
    //Check if button exists on the page
    if (!SiteCommon.Utils.isNullOrUndefined(btn)) {
        DashboardUtils.addHoverHandler(btn, DashboardUtils.showAddMenu);
        DashboardUtils.addUnHoverHandler(btn, DashboardUtils.hideAddMenu);

        var menu = document.getElementById("MenuProd");
        if (!SiteCommon.Utils.isNullOrUndefined(menu)) {
            Sys.UI.DomElement.setVisibilityMode(menu, Sys.UI.VisibilityMode.collapse);
            DashboardUtils.addHoverHandler(menu, DashboardUtils.showAddMenu);
            DashboardUtils.addUnHoverHandler(menu, DashboardUtils.hideAddMenu);
        }

        DashboardUtils.addClickHandler(document.getElementById("AddApp"), DashboardUtils.AddApp);
        DashboardUtils.addClickHandler(document.getElementById("AddWidget"), DashboardUtils.AddWidget);

        DashboardUtils.addHoverHandler(document.getElementById("AddApp"), DashboardUtils.showAddMenu);
        DashboardUtils.addHoverHandler(document.getElementById("AddWidget"), DashboardUtils.showAddMenu);
    }
}

// Update the dashboard tab selection if a 'tab=%d' is present in hash.
DashboardUtils.UpdateTab = function() {
    var tabIdx = 0; // default if hash indicator is not present
    if (window.location.hash) {
        var params = window.location.hash.substring(1).split('&'); // skip the # at beginning and split on &
        for (var i = 0; i < params.length; i++) {
            var keyvalue = params[i].split('=');
            if (keyvalue.length == 2 && keyvalue[0] == "tab") {
                tabIdx = parseInt(keyvalue[1]);
                break;
            }
        }
    }
    DevPortal.Utils.DefaultSwitchTab(tabIdx);
}

function pageLoad(sender, args)  
{  
    Sys.Application.add_navigate(onNavigate);  
}  
function onNavigate(sender, e)   
{  
    // update the tab index (if present in the hash) when navigate occurs. 
    // This makes back navigation work properly with the AJAX control.
    DashboardUtils.UpdateTab();
}   

DashboardUtils.load();
/// <reference name="MicrosoftAjax.js"/>
/// <reference path="~/Common/AjaxControls/InteractiveBaseControl.js" />
/// <reference path="~/scripts/utils.js" />
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  ProductStatusView.js
*
*      Displays the list of subcategories.
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("DevPortal");

DevPortal.ProductStatusView = function(element) {
    /// <summary>
    ///     CategoryListView Constructor.  DO NOT CALL DIRECTLY, USE $CREATE.
    /// </summary>
    /// <param name="element">HTML DomElement to associate.</param>
    /// <returns>
    ///     A newly created CategoryListView object.
    /// </returns>
    DevPortal.ProductStatusView.initializeBase(this, [element]);
}

DevPortal.ProductStatusView.prototype = {
    initialize: function() {
        /// <summary>
        ///     Initialize.  DO NOT CALL DIRECTLY, USE $CREATE.
        ///     
        ///     Initializes the view.
        /// </summary>

        this._groupItems = new Array();
        this.add_click(this._onClick);
        this._numberOfGroups = 3;

        this._Loc = SiteCommon.Utils.JsonParser(this.get_controller().locDict);

        // Do local initialization (needed for_setupRender before calling base class, as it will call _setupRender).
        DevPortal.ProductStatusView.callBaseMethod(this, 'initialize');
    },
    _setupGroup: function(i) {
        /// <summary>
        ///     Sets up the Severity Group dom elements.
        /// </summary>

        this._divGroup[i] = DevPortal.Utils.CreateDiv(this.get_element(),
                            this.get_id() + '_Group' + i, 'ProductStatusGroupBox', null);
        Sys.UI.DomElement.setVisibilityMode(this._divGroup[i], Sys.UI.VisibilityMode.collapse);

        this._divGroupHeader[i] = DevPortal.Utils.CreateDiv(this._divGroup[i],
                            this._divGroup[i].getAttribute('id') + '_Header' + i, 'ProductStatusGroupHeader', null);
        Sys.UI.DomElement.setVisibilityMode(this._divGroupHeader[i], Sys.UI.VisibilityMode.collapse);

        this._divGroupTitle[i] = DevPortal.Utils.CreateDiv(this._divGroupHeader[i],
                            this._divGroup[i].getAttribute('id') + '_Title', 'ProductStatusGroupTitle', null);

        this._divGroupCount[i] = DevPortal.Utils.CreateDiv(this._divGroupHeader[i],
                            this._divGroup[i].getAttribute('id') + '_Count', 'ProductStatusGroupCount',
                            SiteCommon.Utils.toUIString('(0)'));

        var buttonId = this._divGroup[i].getAttribute('id') + '_button';
        var button = this._createButton(this._Loc.ViewAll, buttonId, i);
        var buttonWrapper = DevPortal.Utils.CreateDiv(this._divGroupHeader[i],
                            buttonId + '_container', 'ProductStatusButtonContainer',
                            button);

        //Add clear:both div
        DevPortal.Utils.CreateDiv(this._divGroupHeader[i],
                            this._divGroup[i].getAttribute('id') + '_Clear' + i,
                            'clear', null);

        this._groupCounter[i] = 0;
    },
    _setupRender: function() {
        /// <summary>
        ///     Sets up the panel dom element.
        /// </summary>

        // Set the main CSS style for the element
        Sys.UI.DomElement.addCssClass(this.get_element(), 'ProductStatusBox');

        // Create a div for the Status Panel header
        this._divHeaderBar = DevPortal.Utils.CreateDiv(this.get_element(), this.get_id() + '_Header', 'DashboardHeader', null);
        Sys.UI.DomElement.setVisibilityMode(this._divHeaderBar, Sys.UI.VisibilityMode.collapse);

        //Add column headings
        DevPortal.Utils.CreateDiv(this._divHeaderBar, this._divHeaderBar.getAttribute('id') + '_date',
                        'ProductStatusHeading ProductStatusDateWidth', SiteCommon.Utils.toUIString(this._Loc.Header_Update));
        DevPortal.Utils.CreateDiv(this._divHeaderBar, this._divHeaderBar.getAttribute('id') + '_title',
                        'ProductStatusHeading ProductStatusTitleWidth', SiteCommon.Utils.toUIString(this._Loc.Header_Title));
        DevPortal.Utils.CreateDiv(this._divHeaderBar, this._divHeaderBar.getAttribute('id') + '_status',
                        'ProductStatusHeading ProductStatusSubmissionWidth', SiteCommon.Utils.toUIString(this._Loc.Header_Status));
        DevPortal.Utils.CreateDiv(this._divHeaderBar, this._divHeaderBar.getAttribute('id') + '_platform',
                        'ProductStatusHeading ProductStatusPlatformWidth', SiteCommon.Utils.toUIString(this._Loc.Header_Platform));
        DevPortal.Utils.CreateDiv(this._divHeaderBar, this._divHeaderBar.getAttribute('id') + '_market',
                        'ProductStatusHeading ProductStatusMarketWidth', SiteCommon.Utils.toUIString(this._Loc.Header_Market));
        DevPortal.Utils.CreateDiv(this._divHeaderBar, this._divHeaderBar.getAttribute('id') + '_action',
                        'ProductStatusHeading ProductStatusActionWidth', SiteCommon.Utils.toUIString(this._Loc.Header_Action));

        //Start adding groupings
        this._divGroup = new Array(this._numberOfGroups);
        this._divGroupHeader = new Array(this._numberOfGroups);
        this._divGroupTitle = new Array(this._numberOfGroups);
        this._divGroupCount = new Array(this._numberOfGroups);
        this._groupCounter = new Array(this._numberOfGroups);
        this._groupItems = new Array();

        for (var i = 0; i < this._numberOfGroups; i++) {
            this._setupGroup(i);
        }

        this._divGroupTitle[0].appendChild(SiteCommon.Utils.toUIString(this._Loc.Group_0));
        this._divGroupTitle[1].appendChild(SiteCommon.Utils.toUIString(this._Loc.Group_1));
        this._divGroupTitle[2].appendChild(SiteCommon.Utils.toUIString(this._Loc.Group_2));

        //End adding groupings

        // Create EmptyPanel
        var emptyPanelId = this.get_id() + '_Empty';
        this._divEmptyPanel = DevPortal.Utils.CreateDiv(this.get_element(),
                        emptyPanelId, 'ProductStatusEmptyBox', null);
        Sys.UI.DomElement.setVisibilityMode(this._divEmptyPanel, Sys.UI.VisibilityMode.collapse);

        //Add user message to the empty panel
        DevPortal.Utils.CreateDiv(this._divEmptyPanel, emptyPanelId + '_NoApps',
                        'ProductStatusEmptyBoxTitle', SiteCommon.Utils.toUIString(this._Loc.NoApps));
        DevPortal.Utils.CreateDiv(this._divEmptyPanel, emptyPanelId + '_body',
                        'ProductStatusEmptyBoxBody', SiteCommon.Utils.toUIString(this._Loc.FirstRun_1));
        var footer = DevPortal.Utils.CreateDiv(this._divEmptyPanel, emptyPanelId + '_footer',
                        'ProductStatusEmptyBoxFooter', SiteCommon.Utils.toUIString(this._Loc.FirstRun_3));
        DevPortal.Utils.CreateLink(footer, emptyPanelId + '_footer_Link1', null,
                        SiteCommon.Utils.toUIString(this._Loc.FirstRun_4),
                        'DevPortal.Utils.SwitchTab(\'' + this.get_controller().tabControlId + '\', 4)');
        footer.appendChild(SiteCommon.Utils.toUIString(this._Loc.FirstRun_5));
        DevPortal.Utils.CreateLink(footer, emptyPanelId + '_footer_Link2', null,
                        SiteCommon.Utils.toUIString(this._Loc.FirstRun_6),
                        null, this._Loc.AppSubGuidelines);

        //Hide the panels
        this.showEmptyPanel(false);
        this.showStatusPanel(false);

        // Create a div for status information (loading, failed, no results, etc)
        this._divStatusInfo = document.createElement('div');
        Sys.UI.DomElement.setVisibilityMode(this._divStatusInfo, Sys.UI.VisibilityMode.collapse);
        this.get_element().appendChild(this._divStatusInfo);

        //Show the loading panel
        this.displayLoading();

    },
    dataRender: function() {
        /// <summary>
        ///     Update the UI with main data components from controller.
        /// </summary>

        // update the tab here as well in case the pageLoaded event didn't catch it 
        // (sometimes the AJAX framework still hasn't loaded the control by then - only seen this problem in IE)
        DashboardUtils.UpdateTab();

        // Hide the status UI
        Sys.UI.DomElement.setVisible(this._divStatusInfo, false);

        var data = this.get_controller().get_data();

        for (var i = 0; i < this._numberOfGroups; i++) {
            if (data != null) {
                this._divGroupCount[i].removeChild(this._divGroupCount[i].firstChild);
                this._divGroupCount[i].appendChild(SiteCommon.Utils.toUIString('(' + data.getGroupItemTotalCount(i) + ')'));
            }
        }
    },
    showStatusPanel: function(Show) {
        /// <summary>
        ///     Shows/Hides the Status panel
        /// </summary>
        /// <param name="Show">True: shows the EmptyPanel and hide the Product Status panel and vice-versa.</param>

        //header bar
        Sys.UI.DomElement.setVisible(this._divHeaderBar, Show);

        var data = this.get_controller().get_data();

        //Hide product list
        for (var i = 0; i < this._numberOfGroups; i++) {

            //Show this group if hiding empty panel
            var showGroup = Show;

            //If no data to display in the group, and we are trying to show all groups 
            //(in other words, hide empty panel)
            if (data != null && data.getGroupItemLength(i) == 0 && Show) {
                //then hide this group
                showGroup = false;
            }
            Sys.UI.DomElement.setVisible(this._divGroup[i], showGroup);
            Sys.UI.DomElement.setVisible(this._divGroupHeader[i], showGroup);
        }
    },
    showEmptyPanel: function(Show) {
        /// <summary>
        ///     Shows/Hides the EmptyPanel
        /// </summary>
        /// <param name="Show">True: shows the EmptyPanel and hide the Product Status panel and vice-versa.</param>

        //Show Empty panel
        Sys.UI.DomElement.setVisible(this._divEmptyPanel, Show);
    },
    resetRender: function() {
        /// <summary>
        ///     Reset the UI to initial state.
        /// </summary>

        for (var i = 0; i < this._numberOfGroups; i++) {
            Sys.UI.DomElement.setVisible(this._divGroup[i], false);
            Sys.UI.DomElement.setVisible(this._divGroupHeader[i], false);

            this._divGroupCount[i].appendChild(SiteCommon.Utils.toUIString('(0)'));
            this._groupCounter[i] = 0;
        }

        this.showEmptyPanel(false);
        this.showStatusPanel(false);

        delete this._groupItems;
        this._groupItems = new Array();
    },
    displayLoading: function() {
        /// <summary>
        ///     Displays loading message.
        /// </summary>

        this._divStatusInfo.innerHTML = "";
        var div = DevPortal.Utils.createLoadingDiv(this._Loc.Loading);
        this._divStatusInfo.appendChild(div);
        Sys.UI.DomElement.setVisible(this._divStatusInfo, true);
    },
    displayFailed: function() {
        /// <summary>
        ///     Displays failure message.
        /// </summary>
        this._divStatusInfo.innerHTML = "";
        var reloadObj = DevPortal.Utils.createReloadDiv(this.get_id(), this._Loc.Refresh,
                            this._Loc.ServerBusy);
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click,
                                reloadObj.reloadButton.getAttribute('id'),
                                { 'isReload': true });
        this._divStatusInfo.appendChild(reloadObj.div);
        Sys.UI.DomElement.setVisible(this._divStatusInfo, true);

        this.showEmptyPanel(false);
        this.showStatusPanel(false);
    },
    addProduct: function(group, dataContext) {
        /// <summary>
        ///     Add a Product to the navigation list.
        /// </summary>
        /// <param name="group">Severity group to refer to the data elements.</param>    
        /// <param name="dataContext">Data context to refer to the data elements.</param>

        var index = this._groupItems.length;

        // Create the list item     
        var divId = this._divGroup[group].getAttribute('id') + '_' + dataContext;
        var div = this._createRowItem(divId, group, dataContext);
        this._groupItems[index] = div;
        this._divGroup[group].appendChild(div);
    },
    dispose: function() {
        /// <summary>
        ///     Called to dispose of this objects resources.
        /// </summary>
        DevPortal.ProductStatusView.callBaseMethod(this, 'dispose');
    },
    _createRowItem: function(id, group, dataContext) {
        /// <summary>
        ///     Create a list item and returns the wrapping Div DOM element.
        /// </summary>
        /// <param name="id">DOM ID to attach to the resulting elements.</param>
        /// <param name="group">Severity group to refer to the data elements.</param>  
        /// <param name="dataContext">Data context to refer to the data elements.</param>
        /// <returns>
        ///     A reference the wrapping DOM element.
        /// </returns>

        var data = this.get_controller().get_data();

        // Create the item wrapper.
        var div = document.createElement('div');
        div.setAttribute('id', id);
        Sys.UI.DomElement.addCssClass(div, 'ProductRow');
        if (dataContext + 1 < data.getGroupItemLength(group)) {
            Sys.UI.DomElement.addCssClass(div, 'ProductRowNoBorder');
        }

        var lastUpdated = DevPortal.Utils.CreateSpan(div, id + '_LastUpdated',
                                'ProductStatusDateWidth ProductStatusDateWidthData',
                                data.getLastUpdatedUI(group, dataContext, this._Loc.UserMarketDateFormat));

        // Create the span contents for the item name.
        var spanName = document.createElement('span');
        var spanNameId = id + '_title';
        spanName.setAttribute('id', spanNameId);
        Sys.UI.DomElement.addCssClass(spanName, 'ProductStatusTitleWidth');
        div.appendChild(spanName);

        var link = DevPortal.Utils.CreateLink(spanName, spanNameId + '_link', 'CursorHand',
                        data.getTitleUI(group, dataContext));
        link.appendChild(SiteCommon.Utils.toUIString(this._Loc.version + data.getVersion(group, dataContext)));
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click,
                                spanNameId + '_link',
                                { 'eventType': 'productDetails',
                                    'skuGuid': data.getSubmissionGuid(group, dataContext)
                                });

        var status = DevPortal.Utils.CreateSpan(div, id + '_Status',
                        'ProductStatusSubmissionWidth',
                        SiteCommon.Utils.toUIString(this._Loc['Sub_' + data.getStatus(group, dataContext)]));
        if (group == 2) {
            Sys.UI.DomElement.addCssClass(status, 'DashboardGreenStatus');
        }
        else if (group == 0) {
            Sys.UI.DomElement.addCssClass(status, 'DashboardRedStatus');
        }

        var platform = DevPortal.Utils.CreateSpan(div, id + '_Platform',
                       'ProductStatusPlatformWidth',
                       SiteCommon.Utils.toUIString(this._Loc[data.getPlatform(group, dataContext)]));

        var market = DevPortal.Utils.CreateSpan(div, id + '_Market',
                       'ProductStatusMarketWidth', data.getMarketUI(group, dataContext));

        var action = this._getDefaultActionUI(div, id + '_Action',
                        'ProductStatusActionWidth ProductStatusActionWidthData',
                        data.getSubmissionGuid(group, dataContext),
                        group, dataContext, data);

        return div;
    },
    _createButton: function(text, id, buttonNumber) {
        /// <summary>
        ///     Create a button and returns the wrapping Div DOM element.
        /// </summary>
        /// <param name="text">Text to use as button value.</param>
        /// <param name="id">DOM ID to attach to the resulting elements.</param>
        /// <returns>
        ///     A reference the wrapping DOM element.
        /// </returns>

        var div = document.createElement('div');
        div.setAttribute('id', id + '_wrapper');
        Sys.UI.DomElement.addCssClass(div, 'WhiteRectButton CursorHand');
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click,
                                id + '_wrapper',
                                { 'eventType': 'viewAll',
                                    'severity': buttonNumber + 1
                                });

        var button = DevPortal.Utils.CreateDiv(div, id + '_button',
                    'WhiteRectButtonText CursorHand', SiteCommon.Utils.toUIString(text));
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click,
                                id + '_button',
                                { 'eventType': 'viewAll',
                                    'severity': buttonNumber + 1
                                });

        var divRight = document.createElement('div');
        divRight.setAttribute('id', id + '_right');
        Sys.UI.DomElement.addCssClass(divRight, 'WhiteRectButtonDiv CursorHand');
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click,
                                id + '_right',
                                { 'eventType': 'viewAll',
                                    'severity': buttonNumber + 1
                                });

        div.appendChild(divRight);

        return div;
    },
    _onClick: function(sender, args) {
        /// <summary>
        ///     Click event handler for the items.
        /// </summary>
        /// <param name="sender">ProductStatusView object that was clicked on.</param>
        /// <param name="args">Event args.</param>
        if (args.customData != null) {
            if (args.customData.eventType == 'productDetails') {
                //Handle item title click
                sender.get_controller().handleTitleClick(args.customData.skuGuid);
            }
            else if (args.customData.eventType == 'action') {
                //Handle action link click
                DevPortal.Utils.ActionConfirmationHandler(
                    sender, args.customData.skuGuid, args.customData.actionId,
                    sender._Loc,
                    sender._getActionString(args.customData.actionId),
                    sender._Loc.btn_cancel, sender._Loc.btn_ok,
                    args.customData.params
                );
            }
            else if (args.customData.eventType == 'viewAll') {

                sender.get_controller().showSeverityGroupInProductList(args.customData.severity);
            }
            else if (args.customData.isReload) {
                sender.get_controller().reloadClicked();
            }
        }
    },
    _getDefaultActionUI: function(parent, id, cssClass, subGuid, group, dataContext, data) {
        /// <summary>
        ///     Create & return a span element to show the default action for the given
        ///     status ID
        /// </summary>
        /// <param name="parent">Parent DOM element.</param>
        /// <param name="id">DOM ID to attach to the resulting elements.</param>
        /// <param name="cssClass">CSS class to attach to the resulting elements.</param>
        /// <param name="statusId">Status ID of the product item</param>
        /// <param name="subGuid">Product item's guid to pass to the action handlers.</param>
        /// <returns>
        ///     A reference the wrapping DOM element.
        /// </returns>
        var actionText;
        var statusId = data.getStatusId(group, dataContext);
        var defaultMarketPriceFlag = data.getDefaultMarketPriceFlag(group, dataContext);

        //If no actions available, return empty string
        if (statusId == 0 || statusId == this.SubmissionStatus.SubmissionCancelled) {
            return SiteCommon.Utils.toUIString("");
        }

        //Get default action ID based on status ID
        var actionId = this.StatusActionsList[statusId][0];

        if (actionId == DevPortal.Utils.Actions.SubmitAdditionalMarket
            && !data.isAddNewMarketAvailable(group, dataContext)) {
            actionId = this.StatusActionsList[statusId][1];
        }

        //Get action text to display
        actionText = SiteCommon.Utils.toUIString(this._getActionString(actionId));

        //Get function to call when action-link clicked on
        var span = DevPortal.Utils.CreateSpan(parent, id + 'container', cssClass, null);
        if (actionId != DevPortal.Utils.Actions.EditProductDetails) {
            DevPortal.Utils.CreateLink(span, id, 'CursorHand', actionText);
        } else {
            DevPortal.Utils.CreateLink(span, id, 'CursorHand', actionText, null, "javascript:return false;");
        }
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click,
                                id,
                                { 'eventType': 'action',
                                    'skuGuid': subGuid,
                                    'actionId': actionId,
                                    'params': { 'hasDefaultMarketPrice': defaultMarketPriceFlag }
                                });


        //Generate action-link
        return span;
    },
    _getActionString: function(actionId) {
        /// <summary>
        ///     Returns the localized string for the specified product item action
        /// </summary>
        /// <param name="parent">Localized string.</param>
        switch (actionId) {
            case this.Actions.EditProductDetails:
                return this._Loc.Action_Edit;
                break;

            case this.Actions.ViewProductDetails:
                return this._Loc.Action_View;
                break;

            case this.Actions.SubmitForCertification:
                return this._Loc.Action_Cert;
                break;

            case this.Actions.SubmitAdditionalMarket:
                return this._Loc.Action_Market;
                break;

            case this.Actions.ViewTestResults:
                return this._Loc.Action_Results;
                break;

            case this.Actions.SubmitToCatalog:
                return this._Loc.Action_Catalog;
                break;

            case this.Actions.SubmitForSigning:
                return this._Loc.Action_Signing;
                break;

            case this.Actions.SubmitProductUpdate:
                return this._Loc.Action_Update;
                break;

            case this.Actions.SubmitProductUpgrade:
                return this._Loc.Action_Upgrade;
                break;

            case this.Actions.ContactSupport:
                return this._Loc.Action_Contact;
                break;

            case this.Actions.RemoveFromCatalog:
                return this._Loc.Action_Remove;
                break;
            case this.Actions.DeleteApplication:
                return this._Loc.Action_Delete;
                break;

            default:
                return "";
        }
    }
}

DevPortal.ProductStatusView.prototype.Actions = DevPortal.Utils.Actions;
/// <field name="Actions">An enum of possible actions operable upon SKU items.</field>

DevPortal.ProductStatusView.prototype.SubmissionStatus = DevPortal.Utils.SubmissionStatus;
/// <field name="SubmissionStatus">An enum of submission status values for SKU items.</field>

DevPortal.ProductStatusView.prototype.StatusActionsList = DevPortal.Utils.StatusActionsList;
/// <field name="StatusActionsList">An 2D array of Actions available for the actions available for SKU items.</field>

DevPortal.ProductStatusView.registerClass('DevPortal.ProductStatusView', SiteCommon.InteractiveBaseView);

/// <reference name="MicrosoftAjax.js"/>
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  ProductStatusData.js
*
*      Processes the app data, abstracting it from the UI.
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("DevPortal");

DevPortal.ProductStatusData = function() {
    DevPortal.ProductStatusData.initializeBase(this);
}

DevPortal.ProductStatusData.prototype = {
    initialize: function() {
        /// <summary>
        ///     Constructor.  DO NOT CALL DIRECTLY, USE $CREATE.
        /// </summary>
        /// <returns>
        ///     A newly created data object.
        /// </returns>
        DevPortal.ProductStatusData.callBaseMethod(this, 'initialize');
    },
    getGroupLength: function() {
        /// <summary>
        ///     Gets the number of groups currently acquired.
        /// </summary>
        /// <returns>Count of groups acquired.</returns>
        var length = 0;
        if (!((this._json == null) && (this._json.Entity == null) && (this._json.Entity.NumItems == null))) {
            length = this._json.Entity.NumItems;
        }
        return length;
    },
    _getGroup: function(group) {
        /// <summary>
        ///     Gets the group specified by the group index.
        /// </summary>
        /// <param name="group">Index of the group</param>  
        /// <returns>Group acquired.</returns>
        var g;
        try {
            g = this._json.Entity.SeverityGroups[group];
        }
        catch (exception) {
            throw ("Product Group Index is Out of Range.");
        }
        return g;
    },
    getGroupItemTotalCount: function(group) {
        /// <summary>
        ///     Gets the total number of items in the group.
        /// </summary>
        /// <param name="group">Index of the group</param>  
        /// <returns>Count of items acquired in the group.</returns>
        var length = 0;
        var g = this._getGroup(group);
        if (!((g == null) && (g.NumItems == null))) {
            length = g.TotalSkuCount;
        }
        return length;
    },
    getGroupItemLength: function(group) {
        /// <summary>
        ///     Gets the number of items currently acquired in the group.
        /// </summary>
        /// <param name="group">Index of the group</param>  
        /// <returns>Count of items acquired in the group.</returns>
        var length = 0;
        var g = this._getGroup(group);
        if (!((g == null) && (g.NumItems == null))) {
            length = g.NumItems;
        }
        return length;
    },
    _getGroupItem: function(group, index) {
        /// <summary>
        ///     Get the item referenced by index in the group specified
        /// </summary>  
        /// <param name="group">Index of the referenced severity group</param>
        /// <param name="index">Index of the referenced Product item</param>  
        /// <returns>Product Item at the specified index.</returns>
        var value = null;
        try {
            value = this._getGroup(group).List[index];
        }
        catch (exception) {
            throw ("Product Data Index is Out of Range.");
        }
        return value;
    },
    getLastUpdated: function(group, index, format) {
        /// <summary>
        ///     Get the last updated date of the item
        /// </summary>  
        /// <param name="group">Index of the referenced severity group</param>
        /// <param name="index">Index of the referenced Product item</param>
        /// <returns>Product Item's Last Updated date.</returns>
        if (format != null) {
            return (new Date(this._getGroupItem(group, index).SubmissionInfo.LastUpdatedDate)).format(format);
        }
        else {
            return (new Date(this._getGroupItem(group, index).SubmissionInfo.LastUpdatedDate)).localeFormat("d");
        }
    },
    getLastUpdatedUI: function(group, index, format) {
        /// <summary>
        ///     Get the last updated date  of a Product Item.
        /// </summary>
        /// <param name="group">Index of the referenced severity group</param>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>last updated date  value of the Item.</returns>
        return SiteCommon.Utils.toUIString(this.getLastUpdated(group, index, format));
    },
    getTitleUI: function(group, index) {
        /// <summary>
        ///     Get the Title of a Product Item.
        /// </summary>
        /// <param name="group">Index of the referenced severity group</param>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Title value of the Item.</returns>
        return SiteCommon.Utils.toUIString(this._getGroupItem(group, index).SkuInfo.CatalogItemName);
    },
    getVersion: function(group, index) {
        /// <summary>
        ///     Get the Title of a Product Item.
        /// </summary>
        /// <param name="group">Index of the referenced severity group</param>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Title value of the Item.</returns>
        return this._getGroupItem(group, index).SkuInfo.Version;
    },
    getStatus: function(group, index) {
        /// <summary>
        ///     Get the Status name  of a Product Item.
        /// </summary>
        /// <param name="group">Index of the referenced severity group</param>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Status name value of the Item.</returns>
        return this._getGroupItem(group, index).SubmissionInfo.SubmissionStatusName;
    },
    getDefaultMarketPriceFlag: function(group, index) {
        /// <summary>
        ///     get default market price flag
        /// </summary>
        /// <param name="group">Index of the referenced severity group</param>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>true if price is set for the market the app was created for</returns>
        return this._getGroupItem(group, index).HasDefaultMarketPrice;
    },
    getStatusId: function(group, index) {
        /// <summary>
        ///     Get the Status ID of a Product Item.
        /// </summary>
        /// <param name="group">Index of the referenced severity group</param>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Status ID value of the Item.</returns>
        return this._getGroupItem(group, index).SubmissionInfo.SubmissionStatus;
    },
    isAddNewMarketAvailable: function(group, index) {
        /// <summary>
        ///     Get if the parent of a Product Item is in a completed status or no parent.
        /// </summary>
        /// <param name="group">Index of the referenced severity group</param>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>True if Parent submission complete or no parent.</returns>
        return (this._getGroupItem(group, index).SubmissionInfo.BaseSkuId == null ||
                this._getGroupItem(group, index).SubmissionInfo.IsParentSubmissionComplete);
    },
    getPlatform: function(group, index) {
        /// <summary>
        ///     Get the Platform of a Product Item.
        /// </summary>
        /// <param name="group">Index of the referenced severity group</param>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Platform value of the Item.</returns>
        return this._getGroupItem(group, index).SkuInfo.PlatformTypeName;
    },
    getMarketUI: function(group, index) {
        /// <summary>
        ///     Get the Market of a Product Item.
        /// </summary>
        /// <param name="group">Index of the referenced severity group</param>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Market value of the Item.</returns>
        var market = this._getGroupItem(group, index).SkuInfo.MarketLocale;
        if (!SiteCommon.Utils.isNullOrUndefined(market) && market != "") {
            market = market.toUpperCase();
        }
        return SiteCommon.Utils.toUIString(market);
    },
    getSubmissionGuid: function(group, index) {
        /// <summary>
        ///     Get the Title of a Product Item.
        /// </summary>
        /// <param name="group">Index of the referenced severity group</param>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Title value of the Item.</returns>
        return this._getGroupItem(group, index).Id;
    },
    dispose: function() {
        /// <summary>
        ///     Dispose of any local resources.
        /// </summary>
        DevPortal.ProductStatusData.callBaseMethod(this, 'dispose');
    }
}
DevPortal.ProductStatusData.prototype.get_json = function() { return this._json; };
DevPortal.ProductStatusData.prototype.set_json = function(json) { this._json = json; }
/// <field name="json">The source data element to use.</field>

DevPortal.ProductStatusData.registerClass('DevPortal.ProductStatusData', Sys.Component);

/// <reference name="MicrosoftAjax.js"/>
/// <reference path="~/Services/Catalog/Catalog.svc"/>
/// <reference path="~/Services/DashboardService.svc"/>
/// <reference path="~/Common/AjaxControls/IController.js"/>
/// <reference path="~/AjaxControls/ProductStatusData.js"/>
/// <reference path="~/AjaxControls/ProductStatusView.js"/>
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  ProductStatusController.js
*
*       This class is used to drive the product status pane.  It sets up
*       the data class, and initializes the UI classes.
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("DevPortal");

DevPortal.ProductStatusController = function(element) {
    /// <summary>
    ///     ProductStatusController Constructor.  DO NOT CALL DIRECTLY, USE $CREATE.
    /// </summary>
    /// <param name="element">HTML DomElement to associate.</param>
    /// <returns>
    ///     A newly created ProductStatusController.
    /// </returns>
    DevPortal.ProductStatusController.initializeBase(this, [element]);
}

DevPortal.ProductStatusController.prototype = {
    initialize: function() {
        /// <summary>
        ///     Initialize.  DO NOT CALL DIRECTLY, USE $CREATE.
        ///     
        ///     Initializes the controller.
        /// </summary>
        DevPortal.ProductStatusController.callBaseMethod(this, 'initialize');
    },
    initializeRequest: function() {
        /// <summary>
        ///     initializeRequest is called to initialize the ajax data request needed by
        ///     this controller, as well as any additional requirements.
        /// </summary>


        // Create a div to contain the view
        var div = document.createElement('div');
        div.setAttribute('id', this.get_id() + '_view');
        this.get_element().appendChild(div);
        // Create the panel view element
        this._view = $create(DevPortal.ProductStatusView,
                                 { 'controller': this
                                 },
                                 {},
                                 {},
                                 div);
        this.makeRequest();
    },
    makeRequest: function() {
        /// <summary>
        ///     Issue the actual ajax request.
        /// </summary>

        this._view.displayLoading();

        // Get a reference to the catalog service, and issue a data call
        var service = new DevPortal.DashboardService();
        service.GetApplicationSkuSummarySeverityGroups(this.successfulResponse, this.failureResponse, this);
    },
    successfulResponse: function(response, context) {
        /// <summary>
        ///     Called when a data query has successfully completed.
        /// </summary>
        /// <param name="response">A JSON encoded object representing the data acquired.</param>
        /// <param name="context">A reference to the controller that issued the request</param>

        // Create the data object with the response object
        context._data = $create(DevPortal.ProductStatusData,
                                 { 'json': response
                                 },
                                 {},
                                 {},
                                 null);

        // Setup the main UI components.
        context._view.dataRender();
        var count = 0;

        context._searchResults = $find("searchResults");

        for (var g = 0; g < context._data.getGroupLength(); g++) {
            // Add items to the group view for each data element.
            for (var i = 0; i < context._data.getGroupItemLength(g); i++) {
                context._view.addProduct(g, i);
                count++;
            }
        }

        if (count == 0) {
            context._view.showEmptyPanel(true);
            context._view.showStatusPanel(false);
        }
        else {
            context._view.showEmptyPanel(false);
            context._view.showStatusPanel(true);
        }
    },
    failureResponse: function(response, context) {
        /// <summary>
        ///     Called when a data query has failed.
        /// </summary>
        /// <param name="response">A string representing the failure information.</param>
        /// <param name="context">A reference to the controller that issued the request</param>
        context._view.displayFailed();
    },
    reloadClicked: function() {
        /// <summary>
        ///     Called when the view should be reloaded.
        /// </summary>

        // Reset the view to an initial state.
        this._view.resetRender();

        // Issue the actual request.
        this.makeRequest();
    },
    dispose: function() {
        /// <summary>
        ///     Dispose any local resources.
        /// </summary>
        DevPortal.ProductStatusController.callBaseMethod(this, 'dispose');
    },
    handleTitleClick: function(skuGuid) {
        /// <summary>
        ///     Handle click title click event, redirect user to product details page
        /// </summary>
        /// <param name="skuGuid">Sku GUID for the product details page</param>
        DevPortal.Utils.DefaultSwitchTab(1);
        window.location.search = '?prodid=' + skuGuid;
    },
    showSeverityGroupInProductList: function(severity) {
        if (this._searchResults != null) {
            DevPortal.Utils.DefaultSwitchTab(1);
            this._searchResults.showSeverityGroup(severity);
        }
        else {
            DevPortal.Utils.DefaultSwitchTab(1);
            window.location.search = "?group=" + severity;
        }
    }
}

DevPortal.ProductStatusController.prototype.locDict = null;
/// <field name="locDict">The dictionary to receive localized strings.</field>

DevPortal.ProductStatusController.prototype.tabControlId = null;
/// <field name="tabControlId">The id of the dashboard tabControl.</field>

DevPortal.ProductStatusController.prototype.get_data = function() { return this._data; };
/// <field name="data">Get the data element.</field>

DevPortal.ProductStatusController.prototype._searchResults = null;

DevPortal.ProductStatusController.registerClass('DevPortal.ProductStatusController', Sys.UI.Control, SiteCommon.IController);

/// <reference name="MicrosoftAjax.js"/>
/// <reference path="~/Common/AjaxControls/InteractiveBaseControl.js" />
/// <reference path="~/AjaxControls/ProductListController.js" />
/// <reference path="~/AjaxControls/ProductListData.js" />
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  ProductListView.js
*
*      Displays the list of products.
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("DevPortal");

DevPortal.ProductListView = function(element) {
    /// <summary>
    ///     CategoryListView Constructor.  DO NOT CALL DIRECTLY, USE $CREATE.
    /// </summary>
    /// <param name="element">HTML DomElement to associate.</param>
    /// <returns>
    ///     A newly created ProductListView object.
    /// </returns>
    DevPortal.ProductListView.initializeBase(this, [element]);
}

DevPortal.ProductListView.prototype = {
    initialize: function() {
        /// <summary>
        ///     Initialize.  DO NOT CALL DIRECTLY, USE $CREATE.
        ///     
        ///     Initializes the view.
        /// </summary>

        this._listItems = new Array();
        this.add_click(this._onClick);
        this.add_hover(this._onHover);
        this.add_unhover(this._onUnHover);

        this._Loc = SiteCommon.Utils.JsonParser(this.get_controller().locDict);

        // Do local initialization (needed for_setupRender before calling base class, as it will call _setupRender).
        DevPortal.ProductListView.callBaseMethod(this, 'initialize');
    },
    _createResultsText: function(id) {
        /// <summary>
        ///     Creates the Results text div element.
        /// </summary>
        /// <param name="id">Id to assign to the results text div.</param>
        /// <returns>
        ///     A newly created Results text div element.
        /// </returns>

        //Panel to hold the result string
        var divResultText = document.createElement('div');
        divResultText.setAttribute('id', id);
        Sys.UI.DomElement.addCssClass(divResultText, 'ProductStatusResults');
        Sys.UI.DomElement.setVisibilityMode(divResultText, Sys.UI.VisibilityMode.hide);

        // Add text as pieces to compose:
        //Showing 1-20 of 200 Results for "Sudoku"
        var divTemp = DevPortal.Utils.CreateSpan(divResultText, divResultText.getAttribute('id')
                        + '_text1', 'ProductStatusHeading', SiteCommon.Utils.toUIString(this._Loc.Label_Showing + ' '));

        this._divStart = DevPortal.Utils.CreateSpan(divResultText, divResultText.getAttribute('id')
                        + '_Start', 'ProductStatusHeading', SiteCommon.Utils.toUIString('0'));

        divTemp = DevPortal.Utils.CreateSpan(divResultText, divResultText.getAttribute('id')
                        + '_text2', 'ProductStatusHeading', SiteCommon.Utils.toUIString('-'));

        this._divEnd = DevPortal.Utils.CreateSpan(divResultText, divResultText.getAttribute('id')
                        + '_End', 'ProductStatusHeading', SiteCommon.Utils.toUIString('0'));

        divTemp = DevPortal.Utils.CreateSpan(divResultText, divResultText.getAttribute('id')
                        + '_text3', 'ProductStatusHeading', SiteCommon.Utils.toUIString(' ' + this._Loc.Label_of + ' '));

        this._divTotal = DevPortal.Utils.CreateSpan(divResultText, divResultText.getAttribute('id')
                        + '_Total', 'ProductStatusHeading', SiteCommon.Utils.toUIString('0'));

        return divResultText;
    },
    _setupRender: function() {
        /// <summary>
        ///     Sets up the panel dom element.
        /// </summary>

        // Set the main CSS style for the element
        Sys.UI.DomElement.addCssClass(this.get_element(), 'ProductStatusBox');

        //Construct the back link
        this._backMsg = DevPortal.Utils.CreateDiv(this.get_element(),
                                this.get_id() + '_Back', 'BackToProductListLink', null);
        DevPortal.Utils.CreateDiv(this._backMsg,
                                this.get_id() + '_Back_Icon', 'sprite reloadSmall', null);
        var backLink = DevPortal.Utils.CreateLink(this._backMsg, this.get_id() + '_Back_Link',
                        null, SiteCommon.Utils.toUIString(this._Loc.BackToProductList), null);
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click,
                                this.get_id() + '_Back_Link',
                                { 'eventType': 'showall'
                                });
        Sys.UI.DomElement.setVisibilityMode(this._backMsg, Sys.UI.VisibilityMode.collapse);
        Sys.UI.DomElement.setVisible(this._backMsg, false);

        // Create a div for the Panel header
        this._divHeaderBar = DevPortal.Utils.CreateDiv(this.get_element(),
                                this.get_id() + '_Header', 'DashboardHeader', null);

        // Create a div for the Results Text
        this._divResultText = this._createResultsText(this.get_id() + '_ResultText');
        this._divHeaderBar.appendChild(this._divResultText);

        // Create an array to hold the list items
        this._listItems = new Array();

        // Create a div for status information (loading, failed, no results, etc)
        this._divStatusInfo = document.createElement('div');
        Sys.UI.DomElement.setVisibilityMode(this._divStatusInfo, Sys.UI.VisibilityMode.collapse);
        this.get_element().appendChild(this._divStatusInfo);
        this.displayLoading();
    },
    dataRender: function() {
        /// <summary>
        ///     Update the UI with main data components from controller.
        /// </summary>

        // Hide the status UI
        Sys.UI.DomElement.setVisible(this._divStatusInfo, false);

        // Clear the start/end/total divs
        this._divStart.removeChild(this._divStart.firstChild);
        this._divEnd.removeChild(this._divEnd.firstChild);
        this._divTotal.removeChild(this._divTotal.firstChild);

        var data = this.get_controller().get_data();

        // Add new values retrieved from the response data into the start/end/total divs
        this._divStart.appendChild(this.get_controller().getStartUI());
        this._divEnd.appendChild(this.get_controller().getEndUI());
        this._divTotal.appendChild(data.getLengthUI());

        //Set visibility of back link
        Sys.UI.DomElement.setVisible(this._backMsg, (this.get_controller()._displayedGroup != null));


        if (data.getLength() == 0) {

            // add the empty list message
            this._emptyDiv = document.createElement('div');
            Sys.UI.DomElement.addCssClass(this._emptyDiv, 'ProductItemBox');

            DevPortal.Utils.CreateDiv(this._emptyDiv, '', 'ProductStatusEmptyBoxTitle', SiteCommon.Utils.toUIString(this._Loc.NoProducts_1));
            DevPortal.Utils.CreateDiv(this._emptyDiv, '', 'ProductStatusEmptyBoxBody', SiteCommon.Utils.toUIString(this._Loc.NoProducts_2));

            this.get_element().appendChild(this._emptyDiv);
        }

        //Show/Hide header string
        Sys.UI.DomElement.setVisible(this._divResultText, (data.getLength() != 0));
    },
    resetRender: function() {
        /// <summary>
        ///     Reset the UI to initial state.
        /// </summary>

        // Clear the start/end/total divs
        this._divStart.removeChild(this._divStart.firstChild);
        this._divEnd.removeChild(this._divEnd.firstChild);
        this._divTotal.removeChild(this._divTotal.firstChild);

        // Set the start/end/total divs to default values
        this._divStart.appendChild(SiteCommon.Utils.toUIString('0'));
        this._divEnd.appendChild(SiteCommon.Utils.toUIString('0'));
        this._divTotal.appendChild(SiteCommon.Utils.toUIString('0'));

        if (this._emptyDiv != null) {
            this.get_element().removeChild(this._emptyDiv);
            this._emptyDiv = null;
        }

        //Hide the back link
        Sys.UI.DomElement.setVisible(this._backMsg, false);

        // Clear the list of items
        for (var i = 0; i < this._listItems.length; i++) {
            this.get_element().removeChild(this._listItems[i]);
        }
        delete this._listItems;
        this._listItems = new Array();
    },
    displayLoading: function() {
        /// <summary>
        ///     Displays loading message.
        /// </summary>

        this._divStatusInfo.innerHTML = "";
        var div = DevPortal.Utils.createLoadingDiv(this._Loc.Loading);
        this._divStatusInfo.appendChild(div);
        Sys.UI.DomElement.setVisible(this._divStatusInfo, true);
    },
    displayFailed: function() {
        /// <summary>
        ///     Displays failure message.
        /// </summary>
        this._divStatusInfo.innerHTML = "";
        var reloadObj = DevPortal.Utils.createReloadDiv(this.get_id(), this._Loc.Refresh,
                            this._Loc.ServerBusy);
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click,
                                reloadObj.reloadButton.getAttribute('id'),
                                { 'isReload': true });
        this._divStatusInfo.appendChild(reloadObj.div);
        Sys.UI.DomElement.setVisible(this._divStatusInfo, true);
    },
    addProduct: function(dataContext) {
        /// <summary>
        ///     Add a product to the navigation list.
        /// </summary>
        /// <param name="dataContext">Data context to refer to the data elements.</param>

        var index = this._listItems.length;

        // Create the list item
        var div = this._createRowItem(this.get_id(), dataContext);
        this._listItems[index] = div;
        this.get_element().appendChild(div);
    },
    dispose: function() {
        /// <summary>
        ///     Called to dispose of this objects resources.
        /// </summary>
        DevPortal.ProductListView.callBaseMethod(this, 'dispose');
    },
    _createRatings: function(parent, id, cssClass, appendChild, rating) {
        ///<summary>
        ///     Creates a new ratings div containing star icons
        ///</summary>
        /// <param name="parent">Parent div to add new span element to.</param>
        /// <param name="id">ID of the new span element.</param>
        /// <param name="cssClass">Css Class to add to the new span element.</param>
        /// <param name="appendChild">First child element to add to the new span element.</param>    
        /// <param name="rating">Rating number to specify the number of active stars.</param>

        var mainDiv = DevPortal.Utils.CreateDiv(parent, id, cssClass, null);
        DevPortal.Utils.CreateDiv(mainDiv, id + '_rating', 'FloatLeft', appendChild);
        for (var i = 0; i < 5; i++) {
            if (i < rating) {
                //Add active star
                var star = DevPortal.Utils.CreateDiv(mainDiv, id + i,
                                'sprite ProductRatingStar', null);
            }
            else {
                //Add empty star
                star = DevPortal.Utils.CreateDiv(mainDiv, id + i,
                                'sprite ProductRatingStarEmpty', null);
            }
        }
        return mainDiv;
    },
    _getActionString: function(actionId) {
        /// <summary>
        ///     Returns the localized string for the specified product item action
        /// </summary>
        /// <param name="parent">Localized string.</param>
        switch (actionId) {
            case this.Actions.EditProductDetails:
                return this._Loc.Action_Edit;
                break;

            case this.Actions.ViewProductDetails:
                return this._Loc.Action_View;
                break;

            case this.Actions.SubmitForCertification:
                return this._Loc.Action_Cert;
                break;

            case this.Actions.SubmitAdditionalMarket:
                return this._Loc.Action_Market;
                break;

            case this.Actions.ViewTestResults:
                return this._Loc.Action_Results;
                break;

            case this.Actions.SubmitToCatalog:
                return this._Loc.Action_Catalog;
                break;

            case this.Actions.SubmitForSigning:
                return this._Loc.Action_Signing;
                break;

            case this.Actions.SubmitProductUpdate:
                return this._Loc.Action_Update;
                break;

            case this.Actions.SubmitProductUpgrade:
                return this._Loc.Action_Upgrade;
                break;

            case this.Actions.ContactSupport:
                return this._Loc.Action_Contact;
                break;

            case this.Actions.RemoveFromCatalog:
                return this._Loc.Action_Remove;
                break;

            case this.Actions.DeleteApplication:
                return this._Loc.Action_Delete;
                break;

            default:
                return "";
        }
    },
    _getActionUI: function(parent, id, cssClass, subGuid, dataContext, data, actionIndex) {
        /// <summary>
        ///     Create & return a span element to show the default action for the given
        ///     status ID
        /// </summary>
        /// <param name="parent">Parent DOM element.</param>
        /// <param name="id">DOM ID to attach to the resulting elements.</param>
        /// <param name="cssClass">CSS class to attach to the resulting elements.</param>
        /// <param name="statusId">Status ID of the product item</param>
        /// <param name="subGuid">Product item's guid to pass to the action handlers.</param>
        /// <returns>
        ///     A reference the wrapping DOM element.
        /// </returns>
        var actionText;
        var statusId = data.getStatusId(dataContext);
        var defaultMarketPriceFlag = data.getDefaultMarketPriceFlag(dataContext);

        //If no actions available, return empty string
        if (statusId == 0 || statusId == this.SubmissionStatus.SubmissionCancelled)
            return DevPortal.Utils.CreateDiv(parent, id, cssClass, SiteCommon.Utils.toUIString(this._Loc.noItems));

        //Get default action ID based on status ID
        var actionId = this.StatusActionsList[statusId][actionIndex];

        if (actionId == DevPortal.Utils.Actions.SubmitAdditionalMarket
            && !data.isAddNewMarketAvailable(dataContext)) {
            return null;
        }

        //Get action text to display
        actionText = SiteCommon.Utils.toUIString(this._getActionString(actionId));

        var div;

        //Get function to call when action-link clicked on
        div = DevPortal.Utils.CreateDiv(parent, id, cssClass, null);
        DevPortal.Utils.CreateLink(div, id, 'CursorHand', actionText);
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click,
                                id,
                                { 'eventType': 'action',
                                    'skuGuid': subGuid,
                                    'actionId': actionId,
                                    'params': { 'hasDefaultMarketPrice': defaultMarketPriceFlag }
                                });

        //Generate action-link
        return div;
    },
    _getActionCountForDataItem: function(data, dataContext) {
        //Get Status Id of product
        var statusId = data.getStatusId(dataContext);

        //Get number of elements in the array for the given statusId
        return this.StatusActionsList[statusId].length;
    },
    _setupActionMenu: function(data, parentDiv, dataContext, menuId) {
        /// <summary>
        ///     Setup the action menu and return the DOM element.
        /// </summary>
        /// <param name="data">data object.</param>
        /// <param name="parentDiv">DOM element to add the menu to.</param>
        /// <param name="dataContext">datacontext for the menu to read from.</param>
        /// <param name="menuId">Id for the menu's DOM element.</param>
        var menu = DevPortal.Utils.CreateDiv(parentDiv, menuId, 'ProductItemButtonPopup', null);
        Sys.UI.DomElement.setVisibilityMode(menu, Sys.UI.VisibilityMode.collapse);
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.hover,
                                menuId,
                                { 'eventType': 'productActionShow',
                                    'skuGuid': data.getSubmissionGuid(dataContext),
                                    'menuId': menuId
                                });
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.unhover,
                                menuId,
                                { 'eventType': 'productActionHide',
                                    'skuGuid': data.getSubmissionGuid(dataContext),
                                    'menuId': menuId
                                });

        for (var i = 0; i < this._getActionCountForDataItem(data, dataContext); i++) {
            var actionDivId = menuId + '_action' + i;
            var actionUI = this._getActionUI(menu, actionDivId, 'ProductItemButtonPopupItem', data.getSkuId(dataContext), dataContext, data, i);

            if (actionUI != null) {
                //Add hover event to the div, so that the menu doesn't go away when an action is hovered over
                this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.hover,
                                actionDivId,
                                { 'eventType': 'productActionShow',
                                    'skuGuid': data.getSubmissionGuid(dataContext),
                                    'menuId': menuId
                                });
                this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.unhover,
                                actionDivId,
                                { 'eventType': 'productActionHide',
                                    'skuGuid': data.getSubmissionGuid(dataContext),
                                    'menuId': menuId
                                });
            }
        }

        if (this._getActionCountForDataItem(data, dataContext) == 0) {
            var actionDivId = menuId + '_noaction';
            this._getActionUI(menu, actionDivId, 'ProductItemButtonPopupItem', data.getSubmissionGuid(dataContext), dataContext, data, 0);
        }

        //Add clear:both div
        DevPortal.Utils.CreateDiv(menu, menuId + '_Clear', 'clear', null);
    },
    _createRowItem: function(id, dataContext) {
        /// <summary>
        ///     Create a list item and returns the wrapping Div DOM element.
        /// </summary>
        /// <param name="id">DOM ID to prefix to the resulting elements' IDs.</param>
        /// <param name="dataContext">Data context to refer to the data elements.</param>
        /// <returns>
        ///     A reference the wrapping DOM element.
        /// </returns>

        var data = this.get_controller().get_data();


        // Create the item wrapper.
        var div = document.createElement('div');
        div.setAttribute('id', id + '_' + dataContext);
        Sys.UI.DomElement.addCssClass(div, 'ProductItemBox');

        // set the z-index dynamically because each subsequent row item must have a z-index one lower than the one above it.
        // This is due to IE which establishes a new stacking context with z-index:1 for all positioned elements regardless of whether they have a z-index.
        // And we must have ProductItemBox be relative positioned because the button popup menu positions itself relative to the ProductItemBox boundaries.
        // We start the z-index at 99 because it must be lower than ProductItemButtonPopup which is 100.
        // dataContext = 0, 1, 2, ...
        // dataContext can be bigger than 99 so we need to get z-index based on relative position within the current page
        div.style.cssText = 'z-index:' + (99 - (dataContext % this.get_controller().maxPageLength));

        var icon = DevPortal.Utils.CreateImg(div, id + '_icon', 'ProductItemIcon',
                        this.get_controller().getImageUrl(dataContext),
                        data.getTitle(dataContext));
        var title = DevPortal.Utils.CreateDiv(div, id + '_title', 'ProductItemName',
                        data.getTitleUI(dataContext));
        title.appendChild(SiteCommon.Utils.toUIString(this._Loc.version + data.getVersion(dataContext)));
        var market = DevPortal.Utils.CreateDiv(div, id + '_marketLabel',
                        'ProductItemMarketCell', SiteCommon.Utils.toUIString(this._Loc.Label_Market + ': '));
        DevPortal.Utils.CreateSpan(market, id + '_market', 'ProductItemValues',
                        data.getMarketUI(dataContext));
        var rating = this._createRatings(div, id + '_ratingLabel', 'ProductItemRatingCell',
                        SiteCommon.Utils.toUIString(this._Loc.Label_Rating + ': '), data.getRating(dataContext));

        var menuId = id + '_menu' + dataContext;
        var buttonId = id + '_action' + dataContext;

        //Create hover button for actions menu
        var action = DevPortal.Utils.CreateDiv(div, buttonId, 'sprite ProductItemButtonCell', null);
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.hover,
                                buttonId,
                                { 'eventType': 'productActionShow',
                                    'skuGuid': data.getSubmissionGuid(dataContext),
                                    'menuId': menuId
                                });
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.unhover,
                                buttonId,
                                { 'eventType': 'productActionHide',
                                    'skuGuid': data.getSubmissionGuid(dataContext),
                                    'menuId': menuId
                                });

        //Create actions menu
        this._setupActionMenu(data, div, dataContext, menuId);

        var category = DevPortal.Utils.CreateDiv(div, id + '_category',
                        'ProductItemCategoryCell', data.getCategoryUI(dataContext));
        var platform = DevPortal.Utils.CreateDiv(div, id + '_platformLabel',
                        'ProductItemDeviceCell', SiteCommon.Utils.toUIString(this._Loc.Label_Device + ': '));
        DevPortal.Utils.CreateSpan(platform, id + '_platform', 'ProductItemValues',
                        SiteCommon.Utils.toUIString(this._Loc[data.getPlatform(dataContext)]));
        var downloadsLabel = '';
        var downloadsCountStr = '';
        if (data.getDownloads(dataContext) >= 0) {
            downloadsLabel = this._Loc.Label_Downloads + ': ';
            downloadsCountStr = data.getDownloads(dataContext);
        }
        var downloads = DevPortal.Utils.CreateDiv(div, id + '_downloadsLabel',
                        'ProductItemDownloadsCell', SiteCommon.Utils.toUIString(downloadsLabel));
        DevPortal.Utils.CreateSpan(downloads, id + '_downloads', 'ProductItemValues',
                        SiteCommon.Utils.toUIString(downloadsCountStr));
        var status = DevPortal.Utils.CreateDiv(div, id + '_status', 'ProductItemStatusCell',
                        SiteCommon.Utils.toUIString(this._Loc['Sub_' + data.getStatus(dataContext)]));

        return div;
    },
    _onClick: function(sender, args) {
        /// <summary>
        ///     Click event handler for the list items.
        /// </summary>
        /// <param name="sender">ProductListView object that is clicked on.</param>
        /// <param name="args">Event args.</param>

        // TODO: CURRENTLY UNUSED
        if (args.customData != null) {
            if (args.customData.eventType == 'productDetails') {
                //Handle item title click
                sender.get_controller().handleTitleClick(args.customData.skuGuid);
            }
            else if (args.customData.eventType == 'action') {
                //Handle action link click
                DevPortal.Utils.ActionConfirmationHandler(
                    sender, args.customData.skuGuid, args.customData.actionId,
                    sender._Loc,
                    sender._getActionString(args.customData.actionId),
                    sender._Loc.btn_cancel, sender._Loc.btn_ok,
                    args.customData.params
                );
            }
            else if (args.customData.eventType == 'pagination') {
                sender.get_controller().handlePagination(args.customData.page);
            }
            else if (args.customData.eventType == 'showall') {
                sender.get_controller().showSeverityGroup(null);
            }
            else if (args.customData.isReload) {
                sender.get_controller().reloadClicked();
            }
        }
    },
    _onHover: function(sender, args) {
        /// <summary>
        ///     Hover event handler for the list items.
        /// </summary>
        /// <param name="sender">ProductListView object that is hovered on.</param>
        /// <param name="args">Event args.</param>
        if (args.customData != null) {
            if (args.customData.eventType == 'productActionShow') {
                ShowPop(args.customData.menuId, 'block');
            }
        }
    },
    _onUnHover: function(sender, args) {
        /// <summary>
        ///     Hover event handler for the list items.
        /// </summary>
        /// <param name="sender">ProductListView object that is hovered on.</param>
        /// <param name="args">Event args.</param>
        if (args.customData != null) {
            if (args.customData.eventType == 'productActionHide') {
                ShowPop(args.customData.menuId, 'none');
            }
        }
    },
    drawPagination: function(pageStart, pageEnd, pageSelected) {
        var parent = this.get_element();
        var id = parent.getAttribute('id') + '_pagination';

        //Remove old pagination div from the view
        if (this._paginationDiv != null) {
            parent.removeChild(this._paginationDiv);
            delete this._paginationDiv;
        }

        this._paginationDiv = DevPortal.Utils.CreateDiv(parent, id, 'PaginationContainer', null);

        var prevCss = 'sprite PaginationPreviousIcon FloatLeft';
        if (pageStart < pageSelected)
            prevCss += ' CursorHand PaginationPreviousIcon-active';
        DevPortal.Utils.CreateDiv(this._paginationDiv, id + '_previous', prevCss, null);
        if (pageStart < pageSelected) {
            this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click,
                                id + '_previous',
                                { 'eventType': 'pagination',
                                    'page': (pageSelected - 1)
                                });
        }

        for (var i = pageStart; i <= pageEnd; i++) {
            if (pageSelected == i) {
                DevPortal.Utils.CreateDiv(this._paginationDiv, id + i,
                        'PaginationEntry PaginationEntrySelected FloatLeft',
                        SiteCommon.Utils.toUIString(i));
            }
            else {
                DevPortal.Utils.CreateDiv(this._paginationDiv, id + i,
                        'PaginationEntry CursorHand FloatLeft',
                        SiteCommon.Utils.toUIString(i));
                this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click,
                                id + i,
                                { 'eventType': 'pagination',
                                    'page': i
                                });
            }
        }

        var nextCss = 'sprite PaginationNextIcon FloatLeft';
        if (pageSelected < pageEnd)
            nextCss += ' CursorHand PaginationNextIcon-active';
        DevPortal.Utils.CreateDiv(this._paginationDiv, id + '_next', nextCss, null);
        if (pageSelected < pageEnd) {
            this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click,
                                id + '_next',
                                { 'eventType': 'pagination',
                                    'page': (pageSelected + 1)
                                });
        }

        //Add clear:both div
        DevPortal.Utils.CreateDiv(this._paginationDiv, id + '_Clear', 'clear', null);

        return this._paginationDiv;
    }
}

DevPortal.ProductListView.prototype.Actions = DevPortal.Utils.Actions;
/// <field name="Actions">An enum of possible actions operable upon SKU items.</field>

DevPortal.ProductListView.prototype.SubmissionStatus = DevPortal.Utils.SubmissionStatus;
/// <field name="SubmissionStatus">An enum of submission status values for SKU items.</field>

DevPortal.ProductListView.prototype.StatusActionsList = DevPortal.Utils.StatusActionsList;
/// <field name="StatusActionsList">An 2D array of Actions available for the actions available for SKU items.</field>


DevPortal.ProductListView.registerClass('DevPortal.ProductListView', SiteCommon.InteractiveBaseView);

/// <reference name="MicrosoftAjax.js"/>
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  CategoryListData.js
*
*      Processes the app data, abstracting it from the UI.
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("DevPortal");

DevPortal.ProductListData = function() {
    DevPortal.ProductListData.initializeBase(this);
}

DevPortal.ProductListData.prototype = {
    initialize: function() {
        /// <summary>
        ///     Constructor.  DO NOT CALL DIRECTLY, USE $CREATE.
        /// </summary>
        /// <returns>
        ///     A newly created data object.
        /// </returns>
        DevPortal.ProductListData.callBaseMethod(this, 'initialize');
    },
    _getGroup: function() {
        /// <summary>
        ///     Gets the list of data
        /// </summary>
        /// <returns>Group acquired.</returns>
        var g;
        try {
            g = this._json.ItemList;
        }
        catch (exception) {
            throw ("Product List structure invalid.");
        }
        return g;
    },
    getLength: function() {
        /// <summary>
        ///     Gets the number of items currently acquired in the group.
        /// </summary>
        /// <returns>Count of items acquired in the group.</returns>
        var length = 0;
        var g = this._getGroup();
        if (!((g == null) && (g.NumItems == null))) {
            length = g.NumItems;
        }
        return length;
    },
    getLengthUI: function() {
        /// <summary>
        ///     Gets UIString for the number of items currently acquired.
        /// </summary>
        /// <returns>UIString Count of items acquired.</returns>
        return SiteCommon.Utils.toUIString(this.getLength());
    },
    _getItem: function(index) {
        /// <summary>
        ///     Get the item referenced by index in the group specified
        /// </summary>  
        /// <param name="index">Index of the referenced Product item</param>  
        /// <returns>Product Item at the specified index.</returns>
        var value = null;
        try {
            value = this._getGroup().List[index];
        }
        catch (exception) {
            throw ("Product Data Index is Out of Range.");
        }
        return value;
    },

    getLastUpdated: function(index, format) {
        /// <summary>
        ///     Get the last updated date of the item
        /// </summary>  
        /// <param name="index">Index of the referenced Product item</param>  
        /// <returns>Product Item's Last Updated date.</returns>
        /// <returns>Product Item's Last Updated date.</returns>
        if (format != null) {
            return (new Date(this._getItem(index).SubmissionInfo.LastUpdatedDate)).format(format);
        }
        else {
            return (new Date(this._getItem(index).SubmissionInfo.LastUpdatedDate)).localeFormat("d");
        }
    },
    getLastUpdatedUI: function(index, format) {
        /// <summary>
        ///     Get the last updated date  of a Product Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>last updated date  value of the Item.</returns>
        return SiteCommon.Utils.toUIString(this.getLastUpdated(index, format));
    },
    getTitle: function(index) {
        /// <summary>
        ///     Get the title of a Product Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Title value of the Item.</returns>
        return this._getItem(index).SkuInfo.CatalogItemName;
    },
    getTitleUI: function(index) {
        /// <summary>
        ///     Get the Title of a Product Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Title value of the Item.</returns>
        return SiteCommon.Utils.toUIString(this.getTitle(index));
    },
    getVersion: function(index) {
        /// <summary>
        ///     Get the title of a Product Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Title value of the Item.</returns>
        return this._getItem(index).SkuInfo.Version;
    },
    getSubmissionGuid: function(index) {
        /// <summary>
        ///     Get the Title of a Product Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Title value of the Item.</returns>
        return this._getItem(index).SubmissionInfo.SubmissionGuid;
    },
    getRatingUI: function(index) {
        /// <summary>
        ///     Get the UIString Rating of a Product Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>UIString Rating Element of the Item.</returns>
        return SiteCommon.Utils.toUIString(this._getItem(index).Rating);
    },
    getRating: function(index) {
        /// <summary>
        ///     Get the Rating of a Product Item.
        ///     Services ratings scale 1-500.
        ///     UI displays 1-5 stars.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Rating value of the Item.</returns>
        return this._getItem(index).Rating/100;
    },
    getCategory: function(index) {
        /// <summary>
        ///     Get the Category name of a Product Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Category name of the Item.</returns>
        return this._getItem(index).CategoryName;
    },
    getCategoryUI: function(index) {
        /// <summary>
        ///     Get the UIString Category of a Product Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>UIString Category Element of the Item.</returns>
        return SiteCommon.Utils.toUIString(this.getCategory(index));
    },
    getPlatform: function(index) {
        /// <summary>
        ///     Get the Platform of a Product Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Platform value of the Item.</returns>
        return this._getItem(index).SkuInfo.PlatformTypeName;
    },
    getPlatformUI: function(index) {
        /// <summary>
        ///     Get the UIString Platform of a Product Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>UIString Platform Element of the Item.</returns>
        return SiteCommon.Utils.toUIString(this.getPlatform(index));
    },
    getDownloads: function(index) {
        /// <summary>
        ///     Get the number of downloads of a Product Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Platform value of the Item.</returns>
        return this._getItem(index).Downloads;
    },
    getDownloadsUI: function(index) {
        /// <summary>
        ///     Get the UIString Downloads of a Product Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>UIString Downloads Element of the Item.</returns>
        return SiteCommon.Utils.toUIString(this.getDownloads(index));
    },
    getStatus: function(index) {
        /// <summary>
        ///     Get the Status name  of a Product Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Status name value of the Item.</returns>
        return this._getItem(index).SubmissionInfo.SubmissionStatusName;
    },
    getStatusId: function(index) {
        /// <summary>
        ///     Get the Status ID of a Product Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Status ID value of the Item.</returns>
        return this._getItem(index).SubmissionInfo.SubmissionStatus;
    },
    getDefaultMarketPriceFlag: function(index) {
        /// <summary>
        ///     get default market price flag
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>true if price is set for the market the app was created for</returns>
        return this._getItem(index).HasDefaultMarketPrice;
    },
    isAddNewMarketAvailable: function(index) {
        /// <summary>
        ///     Get if the parent of a Product Item is in a completed status or no parent.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>True if Parent submission complete or no parent.</returns>
        return (this._getItem(index).SubmissionInfo.BaseSkuId == null ||
                this._getItem(index).SubmissionInfo.IsParentSubmissionComplete);
    },
    getStatusUI: function(index) {
        /// <summary>
        ///     Get the UIString Status of a Product Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>UIString Status Element of the Item.</returns>
        return SiteCommon.Utils.toUIString(this.getStatus(index));
    },
    getStatusIdUI: function(index) {
        /// <summary>
        ///     Get the UIString StatusId of a Product Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>UIString StatusId Element of the Item.</returns>
        return SiteCommon.Utils.toUIString(this.getStatusId(index));
    },
    getMarketUI: function(index) {
        /// <summary>
        ///     Get the Market of a Product Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Market value of the Item.</returns>
        var market = this._getItem(index).SkuInfo.MarketLocale;
        if (!SiteCommon.Utils.isNullOrUndefined(market) && market != "") {
            market = market.toUpperCase();
        }
        return SiteCommon.Utils.toUIString(market);
    },
    getSkuId: function(index) {
        /// <summary>
        ///     Get the sku ID of the item referenced by index.
        /// </summary>
        /// <param name="index">Index of the referenced Product item</param>
        /// <returns>Sku ID as GUID string.</returns>
        return this._getItem(index).Id;
    },
    dispose: function() {
        /// <summary>
        ///     Dispose of any local resources.
        /// </summary>
        DevPortal.ProductListData.callBaseMethod(this, 'dispose');
    }
}
DevPortal.ProductListData.prototype.get_json = function() { return this._json; };
DevPortal.ProductListData.prototype.set_json = function(json) { this._json = json; }
/// <field name="json">The source data element to use.</field>

DevPortal.ProductListData.registerClass('DevPortal.ProductListData', Sys.Component);

/// <reference name="MicrosoftAjax.js"/>
/// <reference path="~/Services/DashboardService.svc"/>
/// <reference path="~/Common/AjaxControls/IController.js"/>
/// <reference path="~/AjaxControls/ProductListData.js"/>
/// <reference path="~/AjaxControls/ProductListView.js"/>
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  ProductListController.js
*
*       This class is used to drive the product list panel.  It sets up
*       the data class, and initializes the UI classes.
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("DevPortal");

DevPortal.ProductListController = function(element) {
    /// <summary>
    ///     ProductListController Constructor.  DO NOT CALL DIRECTLY, USE $CREATE.
    /// </summary>
    /// <param name="element">HTML DomElement to associate.</param>
    /// <returns>
    ///     A newly created ProductListController.
    /// </returns>
    DevPortal.ProductListController.initializeBase(this, [element]);
}

DevPortal.ProductListController.prototype = {
    initialize: function() {
        /// <summary>
        ///     Initialize.  DO NOT CALL DIRECTLY, USE $CREATE.
        ///     
        ///     Initializes the controller.
        /// </summary>
        DevPortal.ProductListController.callBaseMethod(this, 'initialize');
    },
    initializeRequest: function() {
        /// <summary>
        ///     initializeRequest is called to initialize the ajax data request needed by
        ///     this controller, as well as any additional requirements.
        /// </summary>


        // Create a div to contain the view
        var div = document.createElement('div');
        div.setAttribute('id', this.get_id() + '_view');
        this.get_element().appendChild(div);
        // Create the panel view element
        this._view = $create(DevPortal.ProductListView,
                                 { 'controller': this
                                 },
                                 {},
                                 {},
                                 div);
        this.makeRequest();
    },
    makeRequest: function(group) {
        /// <summary>
        ///     Issue the actual ajax request.
        /// </summary>
        /// <param name="group">Optional parameter to only display items belonging to the specified
        /// severity group</param>

        this._view.displayLoading();

        // Get a reference to the dashboard service, and issue a data call
        var service = new DevPortal.DashboardService();

        //If server side asks us to switch to a specified group, then we do so and clear this stored value
        if (group == null && this.groupId != null) {
            group = this.groupId;
            this.groupId = null;
        }

        if (group == null) {
            //Get all SKUs for the company
            service.GetApplicationSkuSummary(this.successfulResponse, this.failureResponse, this);
        }
        else {
            service.GetApplicationSkuSummaryBySeverity(group, this.successfulResponse, this.failureResponse, this);
        }

        this._displayedGroup = group;
    },
    successfulResponse: function(response, context) {
        /// <summary>
        ///     Called when a data query has successfully completed.
        /// </summary>
        /// <param name="response">A JSON encoded object representing the data acquired.</param>
        /// <param name="context">A reference to the controller that issued the request</param>

        // Create the data object with the response object
        context._data = $create(DevPortal.ProductListData,
                                 { 'json': response
                                 },
                                 {},
                                 {},
                                 null);

        // Setup the main UI components.
        context._view.dataRender();

        context.handlePagination(1);
    },
    calculateNumPages: function() {
        /// <summary>
        ///     Calculate the number of pages based on the number of items and page size
        /// </summary>
        return Math.ceil(this._data.getLength() / this.maxPageLength);
    },
    displayData: function(page) {
        /// <summary>
        ///     Display the product list for the specified page number
        /// </summary>
        /// <param name="page">Page number to display.</param>
        if (this._data.getLength() > 0) {
            this._view.resetRender(page);
            this._view.dataRender();
            // Add items to the view for each data element.
            for (var i = this.getStart(page);
                    (i <= this.getEnd(page));
                    i++) {
                this._view.addProduct(i);
            }
        }
    },
    getImageUrl: function(dataContext) {
        /// <summary>
        ///     calculate the image url for the given datacontext
        /// </summary>
        /// <param name="dataContext">Data context to refer to the data elements.</param>
        return "FileVendor.aspx?type=smallwebicon&sku=" + this._data.getSkuId(dataContext);
    },
    handlePagination: function(page) {
        /// <summary>
        ///     Handle the pagination of the product list for the specified page number
        /// </summary>
        /// <param name="page">Page number to display.</param>
        var numPages = this.calculateNumPages();
        if (1 <= page && page <= numPages) {
            this._page = page;
            this.displayData(page);
            this._view.drawPagination(1, numPages, page);
        }
    },
    showSeverityGroup: function(group) {
        /// <summary>
        ///     Called by other controls to force a refresh on this control
        ///     and to display the product list items for the specified page number
        /// </summary>
        /// <param name="page">Page number to display.</param>
        this._view.resetRender();
        this._view.displayLoading();
        this.makeRequest(group);
    },
    handleTitleClick: function(skuGuid) {
        /// <summary>
        ///     Handle click title click event, redirect user to product details page
        /// </summary>
        /// <param name="skuGuid">Sku GUID for the product details page</param>
        window.location.search = '?prodid=' + skuGuid;
    },
    failureResponse: function(response, context) {
        /// <summary>
        ///     Called when a data query has failed.
        /// </summary>
        /// <param name="response">A string representing the failure information.</param>
        /// <param name="context">A reference to the controller that issued the request</param>
        context._view.displayFailed();
    },
    reloadClicked: function() {
        /// <summary>
        ///     Called when the view should be reloaded.
        /// </summary>

        // Reset the view to an initial state.
        this._view.resetRender();

        // Issue the actual request.
        this.makeRequest(this._displayedGroup);
    },
    getStart: function(page) {
        /// <summary>
        ///     Gets the Start index of items currently acquired.
        /// </summary>
        /// <returns>Start index of items acquired. -1 in case of error</returns>
        if (page == null
             && this._page != null) {
            page = this._page;
        }
        else if (this._page == null) {
            return -1;
        }
        return (page - 1) * this.maxPageLength;
    },
    getStartUI: function() {
        /// <summary>
        ///     Gets UIString for the Start Index of items currently acquired.
        /// </summary>
        /// <returns>UIString Start Index of items acquired.</returns>
        return SiteCommon.Utils.toUIString(this.getStart() + 1);
    },
    getEnd: function(page) {
        /// <summary>
        ///     Gets the End index of items currently acquired.
        /// </summary>
        /// <returns>End index of items acquired. -1 in case of error</returns>
        if (page == null
             && this._page != null) {
            page = this._page;
        }
        else if (this._page == null) {
            return -1;
        }
        var end = page * this.maxPageLength;
        if (end > this._data.getLength())
            return this._data.getLength() - 1;
        return end - 1;
    },
    getEndUI: function() {
        /// <summary>
        ///     Gets UIString for the End Index of items currently acquired.
        /// </summary>
        /// <returns>UIString End Index of items acquired.</returns>
        return SiteCommon.Utils.toUIString(this.getEnd() + 1);
    },
    dispose: function() {
        /// <summary>
        ///     Dispose any local resources.
        /// </summary>
        DevPortal.ProductListController.callBaseMethod(this, 'dispose');
    }
}
DevPortal.ProductListController.prototype.groupId = null;
/// <field name="groupId">The severity group to display.</field>

DevPortal.ProductListController.prototype.locDict = null;
/// <field name="locDict">The dictionary to receive localized strings.</field>

DevPortal.ProductListController.prototype.tabControlId = null;
/// <field name="tabControlId">The id of the dashboard tabControl.</field>

DevPortal.ProductListController.prototype.get_data = function() { return this._data; };
/// <field name="data">Get the data element.</field>

DevPortal.ProductListController.prototype.maxPageLength = 5;
/// <field name="data">Number of data elements to show on each page.</field>

DevPortal.ProductListController.registerClass('DevPortal.ProductListController', Sys.UI.Control, SiteCommon.IController);

/// <reference name="MicrosoftAjax.js"/>
/// <reference path="~/Common/AjaxControls/InteractiveBaseControl.js" />
/// <reference path="~/scripts/utils.js" />
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  ReportsListView.js
*
*      Displays the list of subcategories.
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("DevPortal");

DevPortal.ReportsListView = function(element) {
    /// <summary>
    ///     CategoryListView Constructor.  DO NOT CALL DIRECTLY, USE $CREATE.
    /// </summary>
    /// <param name="element">HTML DomElement to associate.</param>
    /// <returns>
    ///     A newly created CategoryListView object.
    /// </returns>
    DevPortal.ReportsListView.initializeBase(this, [element]);
}

DevPortal.ReportsListView.prototype = {
    initialize: function() {
        /// <summary>
        ///     Initialize.  DO NOT CALL DIRECTLY, USE $CREATE.
        ///     
        ///     Initializes the view.
        /// </summary>

        this._listItems = new Array();
        this._numberOfGroups = this.isFullVersion ? 2 : 1;
        this.add_click(this._onClick);

        this._Loc = SiteCommon.Utils.JsonParser(this.get_controller().locDict);

        // Do local initialization (needed for_setupRender before calling base class, as it will call _setupRender).
        DevPortal.ReportsListView.callBaseMethod(this, 'initialize');
    },
    _setupRender: function() {
        /// <summary>
        ///     Sets up the panel dom element.
        /// </summary>

        // Set the main CSS style for the element
        Sys.UI.DomElement.addCssClass(this.get_element(), 'ProductStatusBox');

        // Create a div for the Status Panel header
        this._divHeaderBar = DevPortal.Utils.CreateDiv(this.get_element(), this.get_id() + '_Header', 'DashboardHeader', null);
        Sys.UI.DomElement.setVisibilityMode(this._divHeaderBar, Sys.UI.VisibilityMode.collapse);

        //Add column headings
        DevPortal.Utils.CreateDiv(this._divHeaderBar, this._divHeaderBar.getAttribute('id') + '_date',
                        'ProductStatusHeading ReportsListDateWidth', SiteCommon.Utils.toUIString(this._Loc.Header_Date));
        DevPortal.Utils.CreateDiv(this._divHeaderBar, this._divHeaderBar.getAttribute('id') + '_title',
                        'ProductStatusHeading ReportsListTypeNameWidth', SiteCommon.Utils.toUIString(this._Loc.Header_ReportType));
        if (this.isFullVersion) {
            DevPortal.Utils.CreateDiv(this._divHeaderBar, this._divHeaderBar.getAttribute('id') + '_platform',
                        'ProductStatusHeading ReportsListPlatformWidth', SiteCommon.Utils.toUIString(this._Loc.Header_Platform));
            DevPortal.Utils.CreateDiv(this._divHeaderBar, this._divHeaderBar.getAttribute('id') + '_market',
                        'ProductStatusHeading ReportsListMarketWidth', SiteCommon.Utils.toUIString(this._Loc.Header_Market));
            DevPortal.Utils.CreateDiv(this._divHeaderBar, this._divHeaderBar.getAttribute('id') + '_os',
                        'ProductStatusHeading ReportsListOSWidth', SiteCommon.Utils.toUIString(this._Loc.Header_OS));
        }
        DevPortal.Utils.CreateDiv(this._divHeaderBar, this._divHeaderBar.getAttribute('id') + '_datePeriod',
                        'ProductStatusHeading ReportsListDatePeriodWidth', SiteCommon.Utils.toUIString(this._Loc.Header_DatePeriod));

        //Start adding groupings
        this._divGroup = new Array(this._numberOfGroups);
        this._divGroupHeader = new Array(this._numberOfGroups);
        this._divGroupTitle = new Array(this._numberOfGroups);
        this._divGroupCount = new Array(this._numberOfGroups);
        this._groupCounter = new Array(this._numberOfGroups);
        this._listItems = new Array();

        for (var i = 0; i < this._numberOfGroups; i++) {
            this._setupGroup(i);
        }

        if (this.isFullVersion) {
            this._divGroupTitle[this._getGroupIndex(DevPortal.ReportsListData.reportStatus.Pending)].appendChild(
                                                        SiteCommon.Utils.toUIString(this._Loc.ReportsSubheadPending));
            this._divGroupTitle[this._getGroupIndex(DevPortal.ReportsListData.reportStatus.Complete)].appendChild(
                                                        SiteCommon.Utils.toUIString(this._Loc.ReportsSubheadDownload));
        }
        else {
            this._divGroupTitle[this._getGroupIndex(DevPortal.ReportsListData.reportStatus.Complete)].appendChild(
                                                        SiteCommon.Utils.toUIString(this._Loc.ReportsSubheadDownload));
        }
        //End adding groupings

        // Create EmptyPanel
        var emptyPanelId = this.get_id() + '_Empty';
        this._divEmptyPanel = DevPortal.Utils.CreateDiv(this.get_element(),
                        emptyPanelId, 'ProductStatusEmptyBox', null);
        Sys.UI.DomElement.setVisibilityMode(this._divEmptyPanel, Sys.UI.VisibilityMode.collapse);

        //Add user message to the empty panel
        DevPortal.Utils.CreateDiv(this._divEmptyPanel, emptyPanelId + '_NoApps',
                        'ProductStatusEmptyBoxBody', SiteCommon.Utils.toUIString(this._Loc.NoReports));

        //Hide the panels
        this.showEmptyPanel(false);
        this.showStatusPanel(false);

        // Create a div for status information (loading, failed, no results, etc)
        this._divStatusInfo = document.createElement('div');
        Sys.UI.DomElement.setVisibilityMode(this._divStatusInfo, Sys.UI.VisibilityMode.collapse);
        this.get_element().appendChild(this._divStatusInfo);

        //Show the loading panel
        this.displayLoading();
    },
    _setupGroup: function(i) {
        /// <summary>
        ///     Sets up the group elements.
        /// </summary>

        this._divGroup[i] = DevPortal.Utils.CreateDiv(this.get_element(),
                            this.get_id() + '_Group' + i, 'ProductStatusGroupBox', null);
        Sys.UI.DomElement.setVisibilityMode(this._divGroup[i], Sys.UI.VisibilityMode.collapse);

        this._divGroupHeader[i] = DevPortal.Utils.CreateDiv(this._divGroup[i],
                            this._divGroup[i].getAttribute('id') + '_Header' + i, 'ProductStatusGroupHeader', null);
        Sys.UI.DomElement.setVisibilityMode(this._divGroupHeader[i], Sys.UI.VisibilityMode.collapse);

        this._divGroupTitle[i] = DevPortal.Utils.CreateDiv(this._divGroupHeader[i],
                            this._divGroup[i].getAttribute('id') + '_Title', 'ProductStatusGroupTitle', null);

        this._divGroupCount[i] = DevPortal.Utils.CreateDiv(this._divGroupHeader[i],
                            this._divGroup[i].getAttribute('id') + '_Count', 'ProductStatusGroupCount',
                            SiteCommon.Utils.toUIString('(0)'));

        if (!(this.isFullVersion)) {
            var buttonId = this._divGroup[i].getAttribute('id') + '_button';
            var button = this._createButton(this._Loc.ViewAll, buttonId, i);
            var buttonWrapper = DevPortal.Utils.CreateDiv(this._divGroupHeader[i],
                            buttonId + '_container', 'ProductStatusButtonContainer',
                            button);
        }

        //Add clear:both div
        DevPortal.Utils.CreateDiv(this._divGroupHeader[i],
                            this._divGroup[i].getAttribute('id') + '_Clear' + i,
                            'clear', null);

        this._groupCounter[i] = 0;
    },
    dataRender: function() {
        /// <summary>
        ///     Update the UI with main data components from controller.
        /// </summary>

        // update the tab here as well in case the pageLoaded event didn't catch it 
        // (sometimes the AJAX framework still hasn't loaded the control by then - only seen this problem in IE)
        DashboardUtils.UpdateTab();

        // Hide the status UI
        Sys.UI.DomElement.setVisible(this._divStatusInfo, false);

        var data = this.get_controller().get_data();

        for (var i = 0; i < this._numberOfGroups; i++) {
            var status = this._getStatus(i);
            if (data != null) {
                this._divGroupCount[i].removeChild(this._divGroupCount[i].firstChild);
                this._divGroupCount[i].appendChild(SiteCommon.Utils.toUIString('(' + data.getLength(status) + ')'));
            }
        }
    },
    showStatusPanel: function(Show) {
        /// <summary>
        ///     Shows/Hides the Status panel
        /// </summary>
        /// <param name="Show">True: shows the EmptyPanel and hide the Product Status panel and vice-versa.</param>

        //header bar
        Sys.UI.DomElement.setVisible(this._divHeaderBar, Show);

        var data = this.get_controller().get_data();

        //Hide product list
        for (var i = 0; i < this._numberOfGroups; i++) {
            var status = this._getStatus(i);

            //Show this group if hiding empty panel
            var showGroup = Show;

            //If no data to display in the group, and we are trying to show all groups 
            //(in other words, hide empty panel)
            if (data != null && data.getLength(status) == 0 && Show) {
                //then hide this group
                showGroup = false;
            }
            Sys.UI.DomElement.setVisible(this._divGroup[i], showGroup);
            Sys.UI.DomElement.setVisible(this._divGroupHeader[i], showGroup);
        }
    },
    showEmptyPanel: function(Show) {
        /// <summary>
        ///     Shows/Hides the EmptyPanel
        /// </summary>
        /// <param name="Show">True: shows the EmptyPanel and hide the Product Status panel and vice-versa.</param>

        //Show Empty panel
        Sys.UI.DomElement.setVisible(this._divEmptyPanel, Show);
    },
    resetRender: function() {
        /// <summary>
        ///     Reset the UI to initial state.
        /// </summary>

        for (var i = 0; i < this._numberOfGroups; i++) {
            Sys.UI.DomElement.setVisible(this._divGroup[i], false);
            Sys.UI.DomElement.setVisible(this._divGroupHeader[i], false);

            this._divGroupCount[i].appendChild(SiteCommon.Utils.toUIString('(0)'));
            this._groupCounter[i] = 0;
        }

        this.showEmptyPanel(false);
        this.showStatusPanel(false);

        delete this._listItems;
        this._listItems = new Array();
    },
    displayLoading: function() {
        /// <summary>
        ///     Displays loading message.
        /// </summary>

        this._divStatusInfo.innerHTML = "";
        var div = DevPortal.Utils.createLoadingDiv(this._Loc.Loading);
        this._divStatusInfo.appendChild(div);
        Sys.UI.DomElement.setVisible(this._divStatusInfo, true);
    },
    displayFailed: function() {
        /// <summary>
        ///     Displays failure message.
        /// </summary>
        this._divStatusInfo.innerHTML = "";
        var reloadObj = DevPortal.Utils.createReloadDiv(this.get_id(), this._Loc.Refresh,
                            this._Loc.ServerBusy);
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click,
                                reloadObj.reloadButton.getAttribute('id'),
                                { 'isReload': true });
        this._divStatusInfo.appendChild(reloadObj.div);
        Sys.UI.DomElement.setVisible(this._divStatusInfo, true);

        this.showEmptyPanel(false);
        this.showStatusPanel(false);
    },
    addRow: function(status, dataContext) {
        /// <summary>
        ///     Add a row to the list.
        /// </summary>
        /// <param name="dataContext">Data context to refer to the data elements.</param>

        var index = this._listItems.length;
        var groupIndex = this._getGroupIndex(status);

        // Create the list item
        var divId = this._divGroup[groupIndex].getAttribute('id') + '_' + status + dataContext;
        var div = this._createRowItem(divId, status, dataContext);
        this._listItems[index] = div;
        this._divGroup[groupIndex].appendChild(div);
    },
    dispose: function() {
        /// <summary>
        ///     Called to dispose of this objects resources.
        /// </summary>
        DevPortal.ReportsListView.callBaseMethod(this, 'dispose');
    },
    _getStatus: function(index) {
        /// <summary>
        ///     Get the desired status enum based on the provided index.
        /// </summary>
        /// <param name="index">group index value.</param>
        /// <returns>
        ///     An status enum based on the provided index
        /// </returns>
        var status = DevPortal.ReportsListData.reportStatus.Complete;
        if ((this.isFullVersion) && (index == 0)) {
            status = DevPortal.ReportsListData.reportStatus.Pending;
        }
        return status;
    },
    _getGroupIndex: function(status) {
        /// <summary>
        ///     Get the desired group index from the provided status.
        /// </summary>
        /// <param name="index">group index value.</param>
        /// <returns>
        ///     An status enum based on the provided index
        /// </returns>
        var index = 0;
        if ((this.isFullVersion) && (status == DevPortal.ReportsListData.reportStatus.Complete)) {
            index = 1;
        }
        return index;
    },
    _createRowItem: function(id, status, dataContext) {
        /// <summary>
        ///     Create a list item and returns the wrapping Div DOM element.
        /// </summary>
        /// <param name="id">DOM ID to attach to the resulting elements.</param>
        /// <param name="dataContext">Data context to refer to the data elements.</param>
        /// <returns>
        ///     A reference the wrapping DOM element.
        /// </returns>

        var data = this.get_controller().get_data();

        var downloadUrl = 'FileVendor.aspx?type=report&id=' + data.getId(status, dataContext);

        // Create the item wrapper.
        var div = document.createElement('div');
        div.setAttribute('id', id);
        Sys.UI.DomElement.addCssClass(div, 'ReportsListRow');
        // Don't show a grid line in the smaller version of the app, or the bottom entry
        // of a full version display
        if ((!this.isFullVersion) || (dataContext + 1 == data.getLength(status))) {
            Sys.UI.DomElement.addCssClass(div, 'ReportsListRowNoBorder');
        }
        var lastUpdated = DevPortal.Utils.CreateSpan(div, id + '_LastUpdated',
                                'ReportsListDataCell ReportsListDateWidth',
                                data.getDateUI(status, dataContext, this._Loc.UserMarketDateFormat));

        // Create the span contents for the item name.
        var spanName = document.createElement('span');
        var spanNameId = id + '_TypeName';
        spanName.setAttribute('id', spanNameId);
        Sys.UI.DomElement.addCssClass(spanName, 'ReportsListDataCell ReportsListTypeNameWidth');
        div.appendChild(spanName);

        // Display as a link if ready for download
        if (status == DevPortal.ReportsListData.reportStatus.Complete) {
            DevPortal.Utils.CreateLink(spanName, spanNameId + '_link', 'CursorHand',
                       data.getTypeNameUI(this._Loc, status, dataContext), null, downloadUrl);
        }
        else {
            DevPortal.Utils.CreateSpan(spanName, spanNameId + '_text', '',
                       data.getTypeNameUI(this._Loc, status, dataContext));
        }

        if (this.isFullVersion) {
            var platform = DevPortal.Utils.CreateSpan(div, id + '_Platform',
                                'ReportsListDataCell ReportsListPlatformWidth',
                                data.getPlatformUI(this._Loc, status, dataContext));

            var market = DevPortal.Utils.CreateSpan(div, id + '_Market',
                                'ReportsListDataCell ReportsListMarketWidth',
                                data.getMarketUI(this._Loc, status, dataContext));

            var os = DevPortal.Utils.CreateSpan(div, id + '_OS',
                                'ReportsListDataCell ReportsListOSWidth',
                                data.getOSUI(this._Loc, status, dataContext));
        }

        // create date range
        DevPortal.Utils.CreateSpan(div, id + '_DateRange', 'ReportsListDataCell ReportsListDatePeriodWidth',
                       data.getDatePeriodUI(status, dataContext, this._Loc.UserMarketDateFormat));

        if (status == DevPortal.ReportsListData.reportStatus.Complete) {
            // Create the download link.
            var spanLink = document.createElement('span');
            Sys.UI.DomElement.addCssClass(spanLink, 'ReportsListDataCell ReportsListActionWidth');
            DevPortal.Utils.CreateLink(spanLink, null, 'CursorHand',
                       SiteCommon.Utils.toUIString(this._Loc.Download), null, downloadUrl);
            div.appendChild(spanLink);
        }

        return div;
    },
    _createButton: function(text, id, buttonNumber) {
        /// <summary>
        ///     Create a button and returns the wrapping Div DOM element.
        /// </summary>
        /// <param name="text">Text to use as button value.</param>
        /// <param name="id">DOM ID to attach to the resulting elements.</param>
        /// <returns>
        ///     A reference the wrapping DOM element.
        /// </returns>

        var div = document.createElement('div');
        div.setAttribute('id', id + '_wrapper');
        Sys.UI.DomElement.addCssClass(div, 'WhiteRectButton CursorHand');
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click,
                                id + '_wrapper',
                                { 'eventType': 'viewAll'
                                });

        var button = DevPortal.Utils.CreateDiv(div, id + '_button',
                    'WhiteRectButtonText CursorHand', SiteCommon.Utils.toUIString(text));
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click,
                                id + '_button',
                                { 'eventType': 'viewAll'
                                });

        var divRight = document.createElement('div');
        divRight.setAttribute('id', id + '_right');
        Sys.UI.DomElement.addCssClass(divRight, 'WhiteRectButtonDiv CursorHand');
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click,
                                id + '_right',
                                { 'eventType': 'viewAll'
                                });

        div.appendChild(divRight);

        return div;
    },
    _onClick: function(sender, args) {
        /// <summary>
        ///     Click event handler for the items.
        /// </summary>
        /// <param name="sender">ReportsListView object that was clicked on.</param>
        /// <param name="args">Event args.</param>
        if (args.customData != null) {
            if (args.customData.eventType == 'viewAll') {
                sender.get_controller().viewall();
            }
        }
    }
}

DevPortal.ReportsListView.prototype.isFullVersion = false;
/// <field name="isFullVersion">Indicates if this should be a full reports list or a small version.</field>

DevPortal.ReportsListView.registerClass('DevPortal.ReportsListView', SiteCommon.InteractiveBaseView);

/// <reference name="MicrosoftAjax.js"/>
/// <reference path="~/AjaxControls/ReportsListController.js"/>
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  ReportsListData.js
*
*      Processes the reports data, abstracting it from the UI.
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("DevPortal");

DevPortal.ReportsListData = function() {
    DevPortal.ReportsListData.initializeBase(this);
}

DevPortal.ReportsListData.prototype = {
    initialize: function() {
        /// <summary>
        ///     Constructor.  DO NOT CALL DIRECTLY, USE $CREATE.
        /// </summary>
        /// <returns>
        ///     A newly created data object.
        /// </returns>
        DevPortal.ReportsListData.callBaseMethod(this, 'initialize');

        // Initialize the ReadyForDownload and Pending report lists depending on the data case
        if (!this.isFullVersion) {
            this._downloadData = this._json.Entity.ItemList;
            this._pendingData = null;
        }
        else {
            this._downloadData = null;
            this._pendingData = null;

            for (var i = 0; i < this._json.Entity.NumItems; i++) {
                var itemList = this._json.Entity.SeverityGroups[i];
                if (itemList.NumItems > 0) {
                    if (itemList.List[0].ReportStatusSeverityName == "Pending") {
                        this._pendingData = itemList;
                    }
                    else {
                        this._downloadData = itemList;
                    }
                }
            }
        }
    },
    _getItemList: function(reportStatus) {
        /// <summary>
        ///     Gets the desired item list
        /// </summary>
        /// <param name="reportStatus">Type of list desired</param>  
        /// <returns>A reference to the items list.</returns>
        var itemList = (reportStatus == DevPortal.ReportsListData.reportStatus.Complete)
                                        ? this._downloadData : this._pendingData;
        return itemList;
    },
    getLength: function(reportStatus) {
        /// <summary>
        ///     Gets the number of items 
        /// </summary>
        /// <param name="reportStatus">Type of list desired</param>
        /// <returns>Count of items in the list.</returns>
        var length = 0;
        if (!SiteCommon.Utils.isNullOrUndefined(this._getItemList(reportStatus))) {
            length = this._getItemList(reportStatus).NumItems;
        }
        return length;
    },
    _getItem: function(reportStatus, index) {
        /// <summary>
        ///     Get the item referenced by index
        /// </summary>
        /// <param name="reportStatus">Type of list desired</param>  
        /// <param name="index">Index of the referenced Product item</param>  
        /// <returns>Reports Item at the specified index.</returns>
        var value = null;
        try {
            value = this._getItemList(reportStatus).List[index];
        }
        catch (exception) {
            throw ("Index is Out of Range.");
        }
        return value;
    },
    getDateUI: function(reportStatus, index, format) {
        /// <summary>
        ///     Get the generated date of the report
        /// </summary>
        /// <param name="reportStatus">Type of list desired</param>  
        /// <param name="index">Index of the referenced Item</param>
        /// <param name="format">desired date format</param>  
        /// <returns>GeneratedDate value of the Item.</returns>
        var genDate = this._getItem(reportStatus, index).GeneratedDate;
        var genDateString = "";
        if (!SiteCommon.Utils.isNullOrUndefined(genDate) && genDate != "") {
            genDateString = genDate.format(format);
        }
        return SiteCommon.Utils.toUIString(genDateString);
    },
    getTypeNameUI: function(loc, reportStatus, index) {
        /// <summary>
        ///     Get the title (report type) of the report
        /// </summary>
        /// <param name="loc">A reference to the current localizer object</param>  
        /// <param name="reportStatus">Type of list desired</param>  
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>report type of the Item.</returns>
        return SiteCommon.Utils.toUIString(
                    loc[this._getItem(reportStatus, index).ReportTypeName]);
    },
    getPlatformUI: function(loc, reportStatus, index) {
        /// <summary>
        ///     Get the platform of the report item
        /// </summary>
        /// <param name="loc">A reference to the current localizer object</param>  
        /// <param name="reportStatus">Type of list desired</param>  
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>PlatformTypeName</returns>
        var platformEnum = this._getItem(reportStatus, index).PlatformTypeName;
        var platformString = loc["PlatformAll"];
        if (!SiteCommon.Utils.isNullOrUndefined(platformEnum) && platformEnum != "") {
            platformString = loc[platformEnum];
        }
        return SiteCommon.Utils.toUIString(platformString);
    },
    getMarketUI: function(loc, reportStatus, index) {
        /// <summary>
        ///     Get the market of the report item
        /// </summary>
        /// <param name="loc">A reference to the current localizer object</param>  
        /// <param name="reportStatus">Type of list desired</param>  
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>MarketLocale</returns>
        var market = this._getItem(reportStatus, index).MarketLocale;
        if (SiteCommon.Utils.isNullOrUndefined(market) || market == "") {
            market = loc["MarketAll"];
        }
        else {
            market = market.toUpperCase();
        }
        return SiteCommon.Utils.toUIString(market);
    },
    getOSUI: function(loc, reportStatus, index) {
        /// <summary>
        ///     Get the OS of the report item
        /// </summary>
        /// <param name="loc">A reference to the current localizer object</param>  
        /// <param name="reportStatus">Type of list desired</param>  
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>OsVersion</returns>
        var osVersion = this._getItem(reportStatus, index).OsVersion;
        if (SiteCommon.Utils.isNullOrUndefined(osVersion) || osVersion == "") {
            osVersion = loc["OSAll"];
        }
        return SiteCommon.Utils.toUIString(osVersion);
    },
    getDatePeriodUI: function(reportStatus, index, format) {
        /// <summary>
        ///     Get the date range of the report item
        /// </summary>
        /// <param name="loc">A reference to the current localizer object</param>  
        /// <param name="reportStatus">Type of list desired</param>  
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>DatePeriodName</returns>
        return SiteCommon.Utils.toUIString(
            this._getItem(reportStatus, index).ReportStartDate.format(format)
            + " - "
            + this._getItem(reportStatus, index).ReportEndDate.format(format));
    },
    getId: function(reportStatus, index) {
        /// <summary>
        ///     Get the id (guid) of the report item
        /// </summary>
        /// <param name="reportStatus">Type of list desired</param>  
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Id of the Item.</returns>
        return this._getItem(reportStatus, index).ID;
    },
    dispose: function() {
        /// <summary>
        ///     Dispose of any local resources.
        /// </summary>
        DevPortal.ReportsListData.callBaseMethod(this, 'dispose');
    }
}
DevPortal.ReportsListData.prototype.get_json = function() { return this._json; };
DevPortal.ReportsListData.prototype.set_json = function(json) { this._json = json; }
/// <field name="json">The source data element to use.</field>

DevPortal.ReportsListData.prototype.isFullVersion = false;
/// <field name="isFullVersion">Indicates if this should be a full reports list or a small version.</field>

DevPortal.ReportsListData.reportStatus = { Complete: 'Complete', Pending: 'Pending' };
/// <field name="elementTypes">An enum of possible element types used in the function SiteCommon.Utils.createElement.</field>

DevPortal.ReportsListData.registerClass('DevPortal.ReportsListData', Sys.Component);

/// <reference name="MicrosoftAjax.js"/>
/// <reference path="~/Services/DashboardService.svc"/>
/// <reference path="~/Common/AjaxControls/IController.js"/>
/// <reference path="~/AjaxControls/ReportsListData.js"/>
/// <reference path="~/AjaxControls/ReportsListView.js"/>
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  ReportsListController.js
*
*       This class is used to drive the reports list on dashboard.  It sets up
*       the data class, and initializes the UI classes.
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("DevPortal");

DevPortal.ReportsListController = function(element) {
    /// <summary>
    ///     ReportsListController Constructor.  DO NOT CALL DIRECTLY, USE $CREATE.
    /// </summary>
    /// <param name="element">HTML DomElement to associate.</param>
    /// <returns>
    ///     A newly created ReportsListController.
    /// </returns>
    DevPortal.ReportsListController.initializeBase(this, [element]);
}

DevPortal.ReportsListController.prototype = {
    initialize: function() {
        /// <summary>
        ///     Initialize.  DO NOT CALL DIRECTLY, USE $CREATE.
        ///     
        ///     Initializes the controller.
        /// </summary>
        DevPortal.ReportsListController.callBaseMethod(this, 'initialize');
    },
    initializeRequest: function() {
        /// <summary>
        ///     initializeRequest is called to initialize the ajax data request needed by
        ///     this controller, as well as any additional requirements.
        /// </summary>


        // Create a div to contain the view
        var div = document.createElement('div');
        div.setAttribute('id', this.get_id() + '_view');
        this.get_element().appendChild(div);
        // Create the panel view element
        this._view = $create(DevPortal.ReportsListView,
                                 { 'controller': this,
                                     'isFullVersion': this.isFullVersion
                                 },
                                 {},
                                 {},
                                 div);
        this.makeRequest();
    },
    makeRequest: function() {
        /// <summary>
        ///     Issue the actual ajax request.
        /// </summary>

        this._view.displayLoading();

        // Get a reference to the catalog service, and issue a data call
        var service = new DevPortal.DashboardService();

        if (this.isFullVersion) {
            service.GetReportsBySeverityGroups(this.successfulResponse, this.failureResponse, this);
        }
        else {
            service.GetCompletedReports(true, // last modified first
                                        10, // Chunk size
                                        0, // Offset, only first 10 shown
                                        this.successfulResponse, this.failureResponse, this);
        }
    },
    successfulResponse: function(response, context) {
        /// <summary>
        ///     Called when a data query has successfully completed.
        /// </summary>
        /// <param name="response">A JSON encoded object representing the data acquired.</param>
        /// <param name="context">A reference to the controller that issued the request</param>

        // Create the data object with the response object
        context._data = $create(DevPortal.ReportsListData,
                                 { 'json': response,
                                     'isFullVersion': context.isFullVersion
                                 },
                                 {},
                                 {},
                                 null);

        // Setup the main UI components.
        context._view.dataRender();

        // Add pending orders
        var status = DevPortal.ReportsListData.reportStatus.Pending;
        var pendingLength = context._data.getLength(status);
        if (context.isFullVersion) {
            for (var i = 0; i < pendingLength; i++) {
                context._view.addRow(status, i);
            }
        }

        // Add completed orders
        var status = DevPortal.ReportsListData.reportStatus.Complete;
        var completeLength = context._data.getLength(status);
        for (var i = 0; i < completeLength; i++) {
            context._view.addRow(status, i);
        }

        if ((pendingLength == 0) && (completeLength == 0)) {
            context._view.showEmptyPanel(true);
            context._view.showStatusPanel(false);
        }
        else {
            context._view.showEmptyPanel(false);
            context._view.showStatusPanel(true);
        }
    },
    failureResponse: function(response, context) {
        /// <summary>
        ///     Called when a data query has failed.
        /// </summary>
        /// <param name="response">A string representing the failure information.</param>
        /// <param name="context">A reference to the controller that issued the request</param>
        context._view.displayFailed();
    },
    reloadClicked: function() {
        /// <summary>
        ///     Called when the view should be reloaded.
        /// </summary>

        // Reset the view to an initial state.
        this._view.resetRender();

        // Issue the actual request.
        this.makeRequest();
    },
    dispose: function() {
        /// <summary>
        ///     Dispose any local resources.
        /// </summary>
        DevPortal.ReportsListController.callBaseMethod(this, 'dispose');
    },
    viewall: function() {
        DevPortal.Utils.DefaultSwitchTab(DevPortal.ReportsListController.reportsTabIndex);
    }
}

DevPortal.ReportsListController.prototype.locDict = null;
/// <field name="locDict">The dictionary to receive localized strings.</field>

DevPortal.ReportsListController.prototype.tabControlId = null;
/// <field name="tabControlId">The id of the dashboard tabControl.</field>

DevPortal.ReportsListController.prototype.isFullVersion = false;
/// <field name="isFullVersion">Indicates if this should be a full reports list or a small version.</field>

DevPortal.ReportsListController.prototype.get_data = function() { return this._data; };
/// <field name="data">Get the data element.</field>

DevPortal.ReportsListController.reportsTabIndex = 3;
/// <field name="reportsTabIndex">Get the index of the reports tab.</field>

DevPortal.ReportsListController.registerClass('DevPortal.ReportsListController', Sys.UI.Control, SiteCommon.IController);

/// <reference name="MicrosoftAjax.js"/>
/// <reference path="~/AjaxControls/InteractiveBaseControl.js" />
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  ContentSliderView.js
*
*      Displays the details of an Application.
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("DevPortal");

DevPortal.HeroView = function(element) {
    /// <summary>
    ///     ContentSliderView Constructor.  DO NOT CALL DIRECTLY, USE $CREATE.
    /// </summary>
    /// <param name="element">HTML DomElement to associate.</param>
    /// <returns>
    ///     A newly created ContentSliderView object.
    /// </returns>
    DevPortal.HeroView.initializeBase(this, [element]);
}

DevPortal.HeroView.prototype = {
    initialize: function() {
        /// <summary>
        ///     Initialize.  DO NOT CALL DIRECTLY, USE $CREATE.
        ///     
        ///     Initializes the view.
        /// </summary>
        DevPortal.HeroView.callBaseMethod(this, 'initialize');
    },
    _setupRender: function() {
        /// <summary>
        ///     Sets up the Hero dom element.
        /// </summary>
        var a = document.createElement('a');

        if (this.imgLink != '') {
            a.setAttribute('href', this.imgLink);
            a.setAttribute('target', '_blank');
        }

        this.get_element().appendChild(a);
        var img = document.createElement('img');
        Sys.UI.DomElement.addCssClass(img, 'HeroView_base_image');
        img.setAttribute('src', this.imgSrc);
        img.setAttribute('title', this.altText);
        a.appendChild(img);

    },
    dispose: function() {
        /// <summary>
        ///     Called to dispose of this objects resources.
        /// </summary>    
        DevPortal.HeroView.callBaseMethod(this, 'dispose');
    }
}

DevPortal.HeroView.prototype.imgLink = "";
/// <field name="imgLink">The slider Type for css display.</field>
DevPortal.HeroView.prototype.altText = "";
/// <field name="altText">The slider Type for css display.</field>
DevPortal.HeroView.prototype.imgSrc = "";
/// <field name="imgSrc">The slider Type for css display.</field>
DevPortal.HeroView.prototype.imgId = 0;
/// <field name="imgId">The slider Type for css display.</field>

DevPortal.HeroView.registerClass('DevPortal.HeroView', SiteCommon.InteractiveBaseView);


/// <reference name="MicrosoftAjax.js"/>
/// <reference path="~/Services/Catalog/Catalog.svc"/>
/// <reference path="~/AjaxControls/IController.js"/>
/// <reference path="~/AjaxControls/ContentSliderView.js"/>
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  HeroController.js
*
*       This class is used to drive the entire app details page.  It sets up
*       the data class, and initializes the UI classes.
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("DevPortal");

DevPortal.HeroController = function(element) {
    /// <summary>
    ///     HeroController Constructor.  DO NOT CALL DIRECTLY, USE $CREATE.
    /// </summary>
    /// <param name="element">HTML DomElement to associate.</param>
    /// <returns>
    ///     A newly created HeroController.
    /// </returns>
    DevPortal.HeroController.initializeBase(this, [element]);
}

DevPortal.HeroController.prototype = {
    initialize: function() {
        /// <summary>
        ///     Initialize.  DO NOT CALL DIRECTLY, USE $CREATE.
        ///     
        ///     Initializes the controller.
        /// </summary>
        DevPortal.HeroController.callBaseMethod(this, 'initialize');
    },
    initializeRequest: function() {
        /// <summary>
        ///     initializeRequest is called to initialize the ajax data request needed by
        ///     this controller, as well as any additional requirements.
        /// </summary>

        // Create a div to contain the view
        var mainDiv = document.createElement('div');
        this.get_element().appendChild(mainDiv);

        var div = document.createElement('div');
        div.setAttribute('id', this.get_id() + '_view');
        mainDiv.appendChild(div);


        // Create the Slider view
        this._view = $create(DevPortal.ContentSliderView,
                                 { 'controller': this,
                                     'sliderType': "hero",
                                     'slideWidth': 442
                                 },
                                 {},
                                 {},
                                 div);

        // Create slides using straight data here.  In the future hook in data object.
        this._slideElements = new Array();
        for (var i = 0; i < this.get_heroData().length; i++) {
            var div = document.createElement('div');

            this._slideElements[this._slideElements.length] = $create(DevPortal.HeroView,
                                                                    { 'altText': this.get_heroData()[i].AltText,
                                                                        'imgSrc': this.get_heroData()[i].Source,
                                                                        'imgLink': this.get_heroData()[i].Link,
                                                                        'imgId': i
                                                                    },
                                                                    {},
                                                                    {},
                                                                    div);

            this._view.addSlide(div);

        }
    },
    dispose: function() {
        //Add custom dispose actions here
        DevPortal.HeroController.callBaseMethod(this, 'dispose');
    }
}
DevPortal.HeroController.prototype.set_heroData = function(heroData) { this._heroData = heroData; }
DevPortal.HeroController.prototype.get_heroData = function() { return this._heroData; }
/// <field name="heroData">JSON encoded hero control data from the ascx control.</field>

DevPortal.HeroController.registerClass('DevPortal.HeroController', Sys.UI.Control, SiteCommon.IController);



/// <reference name="MicrosoftAjax.js"/>
/// <reference path="~/Services/DeviceRegistration/WindowsPhoneRegistration.svc"/>
/// <reference path="~/Common/AjaxControls/IController.js"/>
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  DeviceListController.js
*
*       This class is used to drive the device list pane.  It sets up
*       the data class, and initializes the UI classes.
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("DevPortal");

DevPortal.DeviceListController = function(element) {
    /// <summary>
    ///     DeviceListController Constructor.  DO NOT CALL DIRECTLY, USE $CREATE.
    /// </summary>
    /// <param name="element">HTML DomElement to associate.</param>
    /// <returns>
    ///     A newly created DeviceListController.
    /// </returns>
    DevPortal.DeviceListController.initializeBase(this, [element]);
}

DevPortal.DeviceListController.prototype = {
    initialize: function() {
        /// <summary>
        ///     Initialize.  DO NOT CALL DIRECTLY, USE $CREATE.
        ///     
        ///     Initializes the controller.
        /// </summary>
        DevPortal.DeviceListController.callBaseMethod(this, 'initialize');
        _removeItemId = null;
    },
    initializeRequest: function() {
        /// <summary>
        ///     initializeRequest is called to initialize the ajax data request needed by
        ///     this controller, as well as any additional requirements.
        /// </summary>


        // Create a div to contain the view
        var div = document.createElement('div');
        div.setAttribute('id', this.get_id() + '_view');
        this.get_element().appendChild(div);
        // Create the panel view element
        this._view = $create(DevPortal.DeviceListView,
                                 { 'controller': this
                                 },
                                 {},
                                 {},
                                 div);
        this.makeRequest();
    },
    makeRequest: function() {
        /// <summary>
        ///     Issue the actual ajax request.
        /// </summary>

        this._view.displayLoading();

        // Get a reference to the registration service, and issue a data call
        var service = new DevPortal.WindowsPhoneRegistrationService();
        service.GetRegisteredDevices(this.successfulResponse, this.failureResponse, this);
    },
    successfulResponse: function(response, context) {
        /// <summary>
        ///     Called when a data query has successfully completed.
        /// </summary>
        /// <param name="response">A JSON encoded object representing the data acquired.</param>
        /// <param name="context">A reference to the controller that issued the request</param>

        // Create the data object with the response object
        context._data = $create(DevPortal.DeviceListData,
                                 { 'json': response
                                 },
                                 {},
                                 {},
                                 null);


        // Setup the main UI components.
        context._view.dataRender();
        
        for (var i = 0; i < context._data.getLength(); i++) {
            context._view.addDevice(i);
        }

        context._view._createFooter();
        context._view.showStatusPanel(true);
    },
    failureResponse: function(response, context) {
        /// <summary>
        ///     Called when a data query has failed.
        /// </summary>
        /// <param name="response">A string representing the failure information.</param>
        /// <param name="context">A reference to the controller that issued the request</param>

        context._view.displayFailed();
    },

    removeDevice: function(deviceId, listItem) {
        /// <summary>
        ///     Issue the remove request.
        /// </summary>
        if (_removeItemId == null) {
            _removeItemId = listItem;
            // Get a reference to the registration service, and issue a data call
            var service = new DevPortal.WindowsPhoneRegistrationService();
            service.UnregisterDevice(deviceId, this.successfulRemoveResponse, this.failureRemoveResponse, this);
        }
    },
    successfulRemoveResponse: function(response, context) {
        /// <summary>
        ///     Called when a data query has successfully completed.
        /// </summary>
        /// <param name="response">A JSON encoded object representing the data acquired.</param>
        /// <param name="context">A reference to the controller that issued the request</param>

        // Create the data object with the response object
        context._view._onRemoveCallback(_removeItemId, SiteCommon.Utils.isSuccessResponse(response));
        _removeItemId = null;
    },
    failureRemoveResponse: function(response, context) {
        /// <summary>
        ///     Called when a data query has failed.
        /// </summary>
        /// <param name="response">A string representing the failure information.</param>
        /// <param name="context">A reference to the controller that issued the request</param>

        context._view._onRemoveCallback(_removeItemId, false);
        _removeItemId = null;
    },
    dispose: function() {
        /// <summary>
        ///     Dispose any local resources.
        /// </summary>
        DevPortal.DeviceListController.callBaseMethod(this, 'dispose');
    }
}

DevPortal.DeviceListController.prototype.locDict = null;
/// <field name="locDict">The dictionary to receive localized strings.</field>

DevPortal.DeviceListController.prototype.tabControlId = null;
/// <field name="tabControlId">The id of the dashboard tabControl.</field>

DevPortal.DeviceListController.prototype.get_data = function() { return this._data; };
/// <field name="data">Get the data element.</field>

DevPortal.DeviceListController.registerClass('DevPortal.DeviceListController', Sys.UI.Control, SiteCommon.IController);
/// <reference name="MicrosoftAjax.js"/>
/// <reference path="~/Common/AjaxControls/InteractiveBaseControl.js" />
/// <reference path="~/scripts/utils.js" />
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  DeviceListView.js
*
*      Displays the list of subcategories.
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("DevPortal");

DevPortal.DeviceListView = function(element) {
    /// <summary>
    ///     DeviceListView Constructor.  DO NOT CALL DIRECTLY, USE $CREATE.
    /// </summary>
    /// <param name="element">HTML DomElement to associate.</param>
    /// <returns>
    ///     A newly created DeviceListView object.
    /// </returns>
    DevPortal.DeviceListView.initializeBase(this, [element]);
}

DevPortal.DeviceListView.prototype = {
    initialize: function() {
        /// <summary>
        ///     Initialize.  DO NOT CALL DIRECTLY, USE $CREATE.
        ///     
        ///     Initializes the view.
        /// </summary>

        this._deviceCount = 0;

        this._listItems = new Array();
        this.add_click(this._onClick);
        this._numberOfGroups = 1;

        this._Loc = SiteCommon.Utils.JsonParser(this.get_controller().locDict);

        // Do local initialization (needed for_setupRender before calling base class, as it will call _setupRender).
        DevPortal.DeviceListView.callBaseMethod(this, 'initialize');
    },
    _setupGroup: function(i) {
        /// <summary>
        ///     Sets up the (for now just one) Group dom elements.
        /// </summary>

        this._divGroup[i] = DevPortal.Utils.CreateDiv(this.get_element(),
                            this.get_id() + '_Group' + i, 'ProductStatusGroupBox', null);

        this._divGroupHeader[i] = DevPortal.Utils.CreateDiv(this._divGroup[i],
                            this._divGroup[i].getAttribute('id') + '_Header' + i, 'ProductStatusGroupHeader', null);

        this._divGroupTitle[i] = DevPortal.Utils.CreateDiv(this._divGroupHeader[i],
                            this._divGroup[i].getAttribute('id') + '_Title', 'ProductStatusGroupTitle', null);

        this._divGroupCount[i] = DevPortal.Utils.CreateDiv(this._divGroupHeader[i],
                            this._divGroup[i].getAttribute('id') + '_Count', 'ProductStatusGroupCount',
                            SiteCommon.Utils.toUIString('(0)'));


        //Add clear:both div
        DevPortal.Utils.CreateDiv(this._divGroupHeader[i],
                            this._divGroup[i].getAttribute('id') + '_Clear' + i,
                            'clear', null);

        this._groupCounter[i] = 0;
    },
    _setupRender: function() {
        /// <summary>
        ///     Sets up the panel dom element.
        /// </summary>
        // Set the main CSS style for the element
        Sys.UI.DomElement.addCssClass(this.get_element(), 'ProductStatusBox');

        // Create a div for the Status Panel header
        this._divHeaderBar = DevPortal.Utils.CreateDiv(this.get_element(), this.get_id() + '_Header', 'DashboardHeader', null);
        Sys.UI.DomElement.setVisibilityMode(this._divHeaderBar, Sys.UI.VisibilityMode.collapse);

        // Create a div for the Column headers
        DevPortal.Utils.CreateDiv(this._divHeaderBar, this._divHeaderBar.getAttribute('id') + '_title',
                        'ProductStatusHeading DeviceStatusTitleWidth', SiteCommon.Utils.toUIString(this._Loc.DeviceName));
        DevPortal.Utils.CreateDiv(this._divHeaderBar, this._divHeaderBar.getAttribute('id') + '_date',
                        'ProductStatusHeading DeviceStatusDateWidth', SiteCommon.Utils.toUIString(this._Loc.UnlockDate));
        DevPortal.Utils.CreateDiv(this._divHeaderBar, this._divHeaderBar.getAttribute('id') + '_action',
                        'ProductStatusHeading DeviceStatusActionWidth', SiteCommon.Utils.toUIString(this._Loc.Action));

        //Start adding groupings
        this._divGroup = new Array(this._numberOfGroups);
        this._divGroupHeader = new Array(this._numberOfGroups);
        this._divGroupTitle = new Array(this._numberOfGroups);
        this._divGroupCount = new Array(this._numberOfGroups);
        this._groupCounter = new Array(this._numberOfGroups);

        for (var i = 0; i < this._numberOfGroups; i++) {
            this._setupGroup(i);
        }

        this._divGroupTitle[0].appendChild(SiteCommon.Utils.toUIString(this._Loc.UnlockedDevices));

        //End adding groupings

        // Create EmptyPanel
        this._divEmptyPanel = DevPortal.Utils.CreateDiv(this._divGroup[0],
                        this.get_id() + '_Empty', 'DeviceStatusEmptyBox', null);
        Sys.UI.DomElement.setVisibilityMode(this._divEmptyPanel, Sys.UI.VisibilityMode.collapse);

        //Add user message to the empty panel
        DevPortal.Utils.CreateDiv(this._divEmptyPanel, this._divEmptyPanel.getAttribute('id') + '_body',
                        'DeviceStatusEmptyBoxBody', SiteCommon.Utils.toUIString(this._Loc.DeviceEmpty));

        //Hide the panels
        this.showEmptyPanel(false);
        this.showStatusPanel(false);

        // Create an array to hold the list items
        this._listItems = new Array();

        // Create a div for status information (loading, failed, no results, etc)
        this._divStatusInfo = document.createElement('div');
        Sys.UI.DomElement.setVisibilityMode(this._divStatusInfo, Sys.UI.VisibilityMode.collapse);
        this._divGroup[0].appendChild(this._divStatusInfo);

        //Show the loading panel
        this.displayLoading();
    },
    dataRender: function() {
        /// <summary>
        ///     Update the UI with main data components from controller.
        /// </summary>
        
        // Hide the status UI
        Sys.UI.DomElement.setVisible(this._divStatusInfo, false);

        var data = this.get_controller().get_data();

        if (data != null) {
            this._divGroupCount[0].removeChild(this._divGroupCount[0].firstChild);
            this._divGroupCount[0].appendChild(SiteCommon.Utils.toUIString('(' + data.getLength() + ')'));
        }
        else {
            this._divGroupCount[0].removeChild(this._divGroupCount[0].firstChild);
            this._divGroupCount[0].appendChild(SiteCommon.Utils.toUIString('(0)'));
        }
    },
    showStatusPanel: function(Show) {
        /// <summary>
        ///     Shows/Hides the Status panel
        /// </summary>
        /// <param name="Show">True: shows the Status Panel and hide the Empty Status panel and vice-versa.</param>

        //header bar
        Sys.UI.DomElement.setVisible(this._divHeaderBar, Show);
        Sys.UI.DomElement.setVisible(this._divFooterBar, Show);

        var data = this.get_controller().get_data();

        //Show product list
        for (var i = 0; i < this._numberOfGroups; i++) {
            Sys.UI.DomElement.setVisible(this._divGroup[i], Show);
            Sys.UI.DomElement.setVisible(this._divGroupHeader[i], Show);

            //If no data to display in the group, and we are trying to show all groups 
            //(in other words, show empty panel)
            if (data != null && data.getLength() == 0 && Show) {
                Sys.UI.DomElement.setVisible(this._divEmptyPanel, Show);
            }
        }
    },
    showDeviceRemoveUIProcessing: function(showProcessing, index) {
     /// <summary>
     ///     Shows/Hides the Remove link
     /// </summary>
     var removeLink = document.getElementById(this._divGroup[0].getAttribute('id') + '_' + index + '_remove');
     var processingText = document.getElementById(this._divGroup[0].getAttribute('id') + '_' + index + '_processing');
           
     Sys.UI.DomElement.setVisibilityMode(removeLink, Sys.UI.VisibilityMode.collapse);
     Sys.UI.DomElement.setVisibilityMode(processingText, Sys.UI.VisibilityMode.collapse);
     Sys.UI.DomElement.setVisible(removeLink, !showProcessing);
     Sys.UI.DomElement.setVisible(processingText, showProcessing);
    },
    showEmptyPanel: function(Show) {
        /// <summary>
        ///     Shows/Hides the EmptyPanel
        /// </summary>
        /// <param name="Show">True: shows the EmptyPanel and hide the Product Status panel and vice-versa.</param>
        //Show Empty panel

        //header bar
        Sys.UI.DomElement.setVisible(this._divHeaderBar, Show);
        Sys.UI.DomElement.setVisible(this._divFooterBar, Show);
        Sys.UI.DomElement.setVisible(this._divEmptyPanel, Show);
    },
    displayLoading: function() {
        /// <summary>
        ///     Displays loading message.
        /// </summary>
        this._divStatusInfo.innerHTML = "";
        var div = DevPortal.Utils.createLoadingDiv(this._Loc.Loading);
        this._divStatusInfo.appendChild(div);
        Sys.UI.DomElement.setVisible(this._divStatusInfo, true);
    },
    displayFailed: function() {
        /// <summary>
        ///     Displays failure message.
        /// </summary>
        this._divStatusInfo.innerHTML = "";
        var reloadObj = DevPortal.Utils.createReloadDiv(this.get_id(), this._Loc.Refresh,
                            this._Loc.ServerBusy);
        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click,
                                reloadObj.reloadButton.getAttribute('id'),
                                { 'isReload': true });
        this._divStatusInfo.appendChild(reloadObj.div);
        Sys.UI.DomElement.setVisible(this._divStatusInfo, true);

        //        this.showEmptyPanel(false);
        this.showStatusPanel(false);
    },
    addDevice: function(dataContext) {
        /// <summary>
        ///     Add a device to the navigation list.
        /// </summary>
        /// <param name="dataContext">Data context to refer to the data elements.</param>
        var index = this._listItems.length;
        this._deviceCount++;
        var divId = this._divGroup[0].getAttribute('id') + '_' + dataContext;
        // Create the list item
        var div = this._deviceCreateRowItem(divId, dataContext);
        this._listItems[index] = div;
        this._divGroup[0].appendChild(div);
    },
    dispose: function() {
        /// <summary>
        ///     Called to dispose of this objects resources.
        /// </summary>
        DevPortal.DeviceListView.callBaseMethod(this, 'dispose');
    },
    _createFooter: function() {
      /// <summary>
        ///     Called to create the footer text div.
        /// </summary>
        this._divFoot = DevPortal.Utils.CreateDiv(this._divGroup[0], this.get_id() + '_Foot', 'DeviceStatusFooter', null);
        DevPortal.Utils.CreateDiv(this._divFoot, this._divFoot.getAttribute('id') + '_text',
                        'DeviceFooterRow', SiteCommon.Utils.toUIString(this._Loc.UnlockMaxText));
    },
    _deviceCreateRowItem: function(id, dataContext) {
        /// <summary>
        ///     Create a list item and returns the wrapping Div DOM element.
        /// </summary>
        /// <param name="id">DOM ID to attach to the resulting elements.</param>
        /// <param name="group">Severity group to refer to the data elements.</param>  
        /// <param name="dataContext">Data context to refer to the data elements.</param>
        /// <returns>
        ///     A reference the wrapping DOM element.
        /// </returns>
        var data = this.get_controller().get_data();

        // Create the item wrapper.
        var div = document.createElement('div');
        Sys.UI.DomElement.addCssClass(div, 'ProductRow ProductRowNoBorder');
        div.setAttribute('id', id);

        DevPortal.Utils.CreateSpan(div, id + '_title', 'DeviceStatusTitleWidth',
                               data.getTitleUI(dataContext));
        DevPortal.Utils.CreateSpan(div, id + '_date', 'ProductStatusDateWidthData DeviceStatusDateWidth',
                                data.getExpirationDateUI(dataContext));
        var removelink = DevPortal.Utils.CreateLink(div, id + '_remove', 'ProductStatusActionWidthData DeviceStatusActionWidth',
                        SiteCommon.Utils.toUIString(this._Loc.UnlockRemove), null, "javascript:return false;");

        this.addEventTarget(SiteCommon.InteractiveBaseView.eventTypes.click,
                                id + '_remove',
                                { 'eventType': 'removeDevice',
                                    'deviceId': data.getId(dataContext),
                                    'listItem': dataContext
                                });
        
        var processing = DevPortal.Utils.CreateSpan(div, id + '_processing', 'ProductStatusDateWidthData DeviceStatusDateWidth',
                                SiteCommon.Utils.toUIString(this._Loc.UnlockProcessing));
        Sys.UI.DomElement.setVisible(processing, false);

        return div;
    },
    _onClick: function(sender, args) {
        /// <summary>
        ///     Click event handler for the items.
        /// </summary>
        /// <param name="sender">DeviceListView object that was clicked on.</param>
        /// <param name="args">Event args.</param>
        if (args.customData != null) {
           if (args.customData.eventType == 'removeDevice') {
                sender.showDeviceRemoveUIProcessing(true, args.customData.listItem);
                sender.get_controller().removeDevice(args.customData.deviceId, args.customData.listItem);
            }
        }
    },
    _onRemoveCallback: function(dataContext, isSuccess) {
        /// <summary>
        ///     On remove execution, deal with the UI.
        /// </summary>
        /// <param name="dataContext">index.</param>
        /// <param name="isSuccess">successful?</param>
        
        var link = document.getElementById(this._divGroup[0].getAttribute('id') + '_' + dataContext);

        if (isSuccess) {
            this._deviceCount--;
            this._divGroup[0].removeChild(link);
            this._divGroupCount[0].removeChild(this._divGroupCount[0].firstChild);
            this._divGroupCount[0].appendChild(SiteCommon.Utils.toUIString('(' + this._deviceCount + ')'));
        } else {
            this.showDeviceRemoveUIProcessing(false, dataContext);
        }

        if (this._deviceCount == 0) {
            this.showEmptyPanel(true);
        }
    }
}

DevPortal.DeviceListView.prototype.Actions = DevPortal.Utils.Actions;
/// <field name="Actions">An enum of possible actions operable upon SKU items.</field>

DevPortal.DeviceListView.prototype.SubmissionStatus = DevPortal.Utils.SubmissionStatus;
/// <field name="SubmissionStatus">An enum of submission status values for SKU items.</field>

DevPortal.DeviceListView.prototype.StatusActionsList = DevPortal.Utils.StatusActionsList;
/// <field name="StatusActionsList">An 2D array of Actions available for the actions available for SKU items.</field>

DevPortal.DeviceListView.registerClass('DevPortal.DeviceListView', SiteCommon.InteractiveBaseView);
/// <reference name="MicrosoftAjax.js"/>
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft
// premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license
// agreement, you are not authorized to use this source code.
// For the terms of the license, please see the license agreement
// signed by you and Microsoft.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES OR INDEMNITIES.
//

/*********************************************************************************************
*
*  DeviceListData.js
*
*      Processes the app data, abstracting it from the UI.
*
*  Copyright Microsoft Corporation, All Rights reserved.
*
*********************************************************************************************/

Type.registerNamespace("DevPortal");

DevPortal.DeviceListData = function() {
    DevPortal.DeviceListData.initializeBase(this);
}

DevPortal.DeviceListData.prototype = {
    initialize: function() {
        /// <summary>
        ///     Constructor.  DO NOT CALL DIRECTLY, USE $CREATE.
        /// </summary>
        /// <returns>
        ///     A newly created data object.
        /// </returns>
        DevPortal.DeviceListData.callBaseMethod(this, 'initialize');
    },
    _getGroup: function() {
        /// <summary>
        ///     Gets the list of data
        /// </summary>
        /// <returns>Group acquired.</returns>
        var g;
        try {
            g = this._json.ItemList;
        }
        catch (exception) {
            throw ("Device List structure invalid.");
        }
        return g;
    },
    getLength: function() {
        /// <summary>
        ///     Gets the number of items currently acquired in the group.
        /// </summary>
        /// <returns>Count of items acquired in the group.</returns>
        var length = 0;
        var g = this._getGroup();
        if (!((g == null) && (g.NumItems == null))) {
            length = g.NumItems;
        }
        return length;
    },
    getLengthUI: function() {
        /// <summary>
        ///     Gets UIString for the number of items currently acquired.
        /// </summary>
        /// <returns>UIString Count of items acquired.</returns>
        return SiteCommon.Utils.toUIString(this.getLength());
    },
    _deviceGetItem: function(index) {
        /// <summary>
        ///     Get the item referenced by index in the group specified
        /// </summary>  
        /// <param name="index">Index of the referenced Device item</param>  
        /// <returns>Device Item at the specified index.</returns>
        var value = null;
        try {
            value = this._getGroup().List[index];
        }
        catch (exception) {
            throw ("Device Data Index is Out of Range.");
        }
        return value;
    },
    getExpirationDate: function(index, format) {
        /// <summary>
        ///     Get the last updated date of the item
        /// </summary>  
        /// <param name="index">Index of the referenced Device item</param>  
        /// <returns>Device Item's Last Updated date.</returns>
        /// <returns>Device Item's Last Updated date.</returns>
        if (format != null) {
            return (new Date(this._deviceGetItem(index).ExpirationDate)).format(format);
        }
        else {
            return (new Date(this._deviceGetItem(index).ExpirationDate)).localeFormat("d");
        }
    },
    getExpirationDateUI: function(index, format) {
        /// <summary>
        ///     Get the last updated date  of a Device Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>last updated date  value of the Item.</returns>
        return SiteCommon.Utils.toUIString(this.getExpirationDate(index, format));
    },
    getTitle: function(index) {
        /// <summary>
        ///     Get the title of a Device Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Title value of the Item.</returns>
        return this._deviceGetItem(index).FriendlyName;
    },
    getTitleUI: function(index) {
        /// <summary>
        ///     Get the Title of a Device Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Title value of the Item.</returns>
        return SiteCommon.Utils.toUIString(this.getTitle(index));
    },
    getId: function(index) {
        /// <summary>
        ///     Get the title of a Device Item.
        /// </summary>
        /// <param name="index">Index of the referenced Item</param>
        /// <returns>Title value of the Item.</returns>
        return this._deviceGetItem(index).DeviceId;
    },

    dispose: function() {
        /// <summary>
        ///     Dispose of any local resources.
        /// </summary>
        DevPortal.DeviceListData.callBaseMethod(this, 'dispose');
    }
}
DevPortal.DeviceListData.prototype.get_json = function() { return this._json; };
DevPortal.DeviceListData.prototype.set_json = function(json) { this._json = json; }
/// <field name="json">The source data element to use.</field>

DevPortal.DeviceListData.registerClass('DevPortal.DeviceListData', Sys.Component);



if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();