﻿/// <reference name="MicrosoftAjax.js"/>
/****************************************************************************

AUTHOR:				MRM Worldwide (v-jgriff)
DATE:				20090106

DESCRIPTION:
------------
Provides client side data binding using the Microsoft AJAX JavaScript library
Implements the asynchronous callback Web methods to interact with Handler.aspx
The requests are HTTP form based and responses are in JSON.

MAINTENANCE LOG:

REVISION	DATE		EMAIL		DESCRIPTION
--------	----		-----		-----------
1.0			20090106	v-jgriff	Initial creation, separated from base Web Form.
****************************************************************************/

Sys.Application.add_init(function() {
});

/****************************************************************************

Basic HTML Extension functions.

****************************************************************************/

/// <summary>
/// Gets an array of product ids associated with selected products in the given Product Group.
/// </summary>
function getSelected(productGroupID)
{
    var result = new Array();
    var control = $get(productGroupID);
    
    // iterate the childNodes and populate the result with value of each checked checkbox
    for (var i = 0; i < control.childNodes.length; ++i)
    {
        var child = control.childNodes[i].firstChild;
        
        if (child != null && child.type == 'checkbox')
        {
            if (child.checked)
            {
                result.push(child.value);
            }
        }
    }

    return result;
}

/// <summary>
/// Gets number of products for the given Product Group.
/// </summary>
function getProductCount(productGroupID)
{
    var control = $get(productGroupID);
    var productCount = 0;
    
    // iterate the childNodes and populate the result with value of each checked checkbox
    for (var i = 0; i < control.childNodes.length; ++i)
    {
        var child = control.childNodes[i].firstChild;
        
        if (child != null && child.type == 'checkbox')
        {
            productCount++;
        }
    }
    return productCount;
}

/// <summary>
/// Create a new table cell.
/// </summary>
/// <param name="content">The content of the cell.</param>
/// <returns>A checkbox element</returns>
function addCell(content, style)
{
    var td = document.createElement('td'); // create new element
    if (style == '')
    {
    }
    else
    {
        td.className = style;
    }
    td.innerHTML = content; // set the content of the cell
    
    // return the element
    return td;
}

/// <summary>
/// Opens a pop-up window in the center of the screen and loads the document specified by a given URL.
/// </summary>
/// <param name="url">The URL of the document to display.</param>
/// <param name="width">The width of the pop-up window.</param>
/// <param name="height">The height of the pop-up window.</param>
function openPopupWindow(url, width, height) {
    var left = parseInt((screen.availWidth/2) - (width/2));
    var top = parseInt((screen.availHeight/2) - (height/2));
    var windowFeatures = "width=" + width + ",height=" + height + ",status,resizable,left=" + left + ",top=" + top + "screenX=" + left + ",screenY=" + top;
    var myWindow = window.open(url, "subWind", windowFeatures);
    myWindow.focus();
}

/// <summary>
/// Removes all childNodes for an element.
/// </summary>
/// <param name="element">The element to clear.</param>
function removeChildNodes(element)
{
    // check the element has children
    if (element.childNodes.length > 0)
    {
        // remove the first child until there are no children.
        while (element.firstChild)
        {
            element.removeChild(element.firstChild);
        }
    }
}

function CheckEnter()
{
    if(event.keyCode==13) 
        document.getElementById('lnkSearch').click();
}  

/****************************************************************************

Resource functions.

****************************************************************************/

/// <summary>
/// Displays the details of a ResourceResult object returned from the database.
/// </summary>
/// <param name="resourceResult">A ResourceResult object to display.</param>
/// <param name="position">The ordinal position of the ResourceResult.</param>
function addResourceItem(resourceResult, position)
{
    var daysWhileNew = 30; // initialise the number of days that indicate if a Resource is new
    var tr = document.createElement('tr'); // create a new tr element
    tr.className = position % 2 == 0 ? 'even' : 'odd';

    if (resourceResult == null)
    {
    }
    else
    {
        // create a new date and set it to Now - daysWhileNew      
        var newResourceDate = new Date;
        newResourceDate = newResourceDate.setDate(newResourceDate.getDate() - daysWhileNew);
        var modified = Date.parseInvariant(resourceResult.Modified, 'dd/MM/yyyy'); // parse the modified string into a date object

        var content = new Sys.StringBuilder(); // initialise a new StringBinder object
        
        // Resource Cell
        content.append('<h2>');
        
        if (resourceResult.SourceType == 'Website')
        {// set the operation to "Open" and the target to a new window
            content.append(String.format('<a href="Handler.aspx?operation=Open&resource={0}" target="_blank" title="Open website in a new window">{1}</a>', resourceResult.ID, resourceResult.Name));
        }
        else
        {
            content.append(String.format('<a href="Handler.aspx?operation=Download&resource={0}" title="Download and save resource">{1}</a>', resourceResult.ID, resourceResult.Name));
        }
        if (modified > newResourceDate)
        {// the resource was modified in the last daysWhileNew days so show the new image
            content.append('<img src="images/results/icon-new.gif" alt="New" class="icn-new" /> ');
        }
        content.append('</h2>');
        content.append(String.format('<p>{0}</p>', resourceResult.Description));
        content.append(String.format('<p class="info"><strong>Categories:</strong> {0}</p>', resourceResult.CategoryText));
        content.append(String.format('<p class="info"><strong>Products:</strong> {0}</p>', resourceResult.ProductText));
        if(typeof(getEditButtonHtml)=="function") 
            content.append(getEditButtonHtml(resourceResult.ID));
        
        tr.appendChild(addCell(content.toString(), 'info'));
        content.clear();

        var fileTypeImage = String.format('<img class="icon-type" src="images/results/icon-{0}.gif" alt="{1} (.{0})" align="absmiddle" border="0" />', resourceResult.Extension, resourceResult.ResourceType);
                
        content.append(String.format('<dt><strong>Popularity:</strong> <img class="popularity" src="images/popularity/bar-{0}.gif" /></dt>', resourceResult.Popularity));
        content.append(String.format('<dt><strong>Date added:</strong> {0}</dt>', resourceResult.Modified));
        content.append(String.format('<dt><strong>Downloads:</strong> {0}</dt>', resourceResult.Downloads));
        content.append(String.format('<dt><strong>Size:</strong> {0}</dt>', resourceResult.SizeText));
        content.append(String.format('<dt><strong>Type:</strong> {0}\n{1}</dt>', fileTypeImage, resourceResult.ResourceType));

        tr.appendChild(addCell(content.toString(), 'details')); // add a new cell to the element
        
    }
    
    // return the element
    return tr;
}

/// <summary>
/// Renders the no ResourceResult content.
/// Writes a hyperlink
/// </summary>
/// <param name="sortOrder">Determines whether to display the newest or most popular link.</param>
/// <param name="text">Link text.</param>
function addResourceLinkEmpty(sortOrder, text)
{
    var link = String.format('<a href="?searchText=&category=&products=&pageIndex=0&pageSize=5&sortID={0}">{1}</a>', sortOrder, text);
    // return the element
    return link;
}

/// <summary>
/// Renders the no ResourceResult content.
/// Writes a string in a table row.
/// </summary>
/// <param name="text">Link text.</param>
function addResourceStringEmpty(text) {
    var tr = document.createElement('tr'); // create a new tr element

    var td = document.createElement('td'); // create a new td element
    td.className = 'noItems';
    var para = document.createElement('p'); // create a new a element
    para.innerHTML = text;

    td.appendChild(para); // add the href to the cell
    tr.appendChild(td); // add the cell to the row

    // return the element
    return tr;
}

/// <summary>
/// Renders the no ResourceResult content.
/// Writes a List in a table row.
/// </summary>
/// <param name="listHeading">list heading text</param>
/// <param name="listType">Type of list.</param>
/// <param name="listText">Array of list text.</param>
function addResourceListEmpty(listHeading,listType,listText) {
    if (listType.toLowerCase() == 'ordered') {
        listType = 'ol';
    }else{
        listType = 'ul';
    }
    
    
    var tr = document.createElement('tr'); // create a new tr element

    var td = document.createElement('td'); // create a new td element
    td.className = 'noItems';
    if (listHeading != '') {
        var heading = document.createElement('h3'); // create a new h3 element
        heading.innerHTML = listHeading;
        td.appendChild(heading); // add the heading to the cell
    }
    
    
    var list = document.createElement(listType); // create a new ol/ul element
    var listitem = '';
    var para = '';
    for (var cc = 0; cc < listText.length; cc++) {
        listItem = document.createElement('li'); // create a new li element
        para = document.createElement('p'); // create a new a element
        para.innerHTML = listText[cc];
        listItem.appendChild(para); // add the para to the li
        list.appendChild(listItem); // add the li to the list
    }
    
    td.appendChild(list); // add the href to the cell
    tr.appendChild(td); // add the cell to the row

    // return the element
    return tr;
}


/****************************************************************************

Data Binding functions.

****************************************************************************/
function searchCriteriaToString()
{
    var body = new Sys.StringBuilder('searchText=');
    body.append(_searchCriteria.SearchText);
    body.append('&category=');
    body.append(_searchCriteria.Category);
    body.append('&products=');
    body.append(_searchCriteria.Products);
    body.append('&pageIndex=');
    body.append(_searchCriteria.PageIndex);
    body.append('&pageSize=');
    body.append(_searchCriteria.PageSize);
    body.append('&sortID=');
    body.append(_searchCriteria.SortID);
    return body.toString()
}

// <summary>
/// Calls the FilterResource method asynchronously from the Handler
/// and binds results to the parts of the screen containing dynamic content.
/// </summary>
function bindResources()
{
    // create the body of the request
    var body = 'operation=FilterResource&' + searchCriteriaToString();
    
    var loader = document.createElement('tr');
    var td = document.createElement('td');
    td.colSpan = 2;
	td.className = "loading";
    var img = document.createElement('img');
    img.alt = 'loading...';
    img.src = 'images/results/icon-loader-large.gif';
    img.className = 'btn-loader';
    td.appendChild(img);
    loader.appendChild(td);

    dataBind(this._resourceList, body, OnBindResourcesWebRequestCompleted, loader); // perform the data bind.
}

/// <summary>
/// Invokes an asynchronous XHttp request, clears the containing element
/// and displays a loader element. Sets the call back method that will
/// handle the response from the request.
/// </summary>
/// <param name="element">The container element that will display the data.</param>
/// <param name="body">The Request POST body.</param>
/// <param name="callBack">The call back method to handle the Asynchronous response.</param>
/// <param name="loader">The loader element to display while processing the request.</param>
function dataBind(element, body, callBack, loader)
{
    if (element == null)
    {
    }
    else
    {
        removeChildNodes(element); // clear the element
        element.appendChild(loader); // display the loader element

        // Instantiate the WebRequest object.
        var request =  new Sys.Net.WebRequest();

        // Set the request Url.  
        request.set_url (this._service); 

        // Set the request verb.
        request.set_httpVerb ("POST");

        // set the body of the request.
        request.set_body (body);
        request.get_headers ()["Content-Length"] = body.length;

        // Set the web request completed event handler,
        // for processing return data.
        request.add_completed(callBack);

        // Execute the request.
        request.invoke();
    }
}

/// <summary>
/// Asyncronous XHttp Response handler for the Resource DataBind event.
/// </summar
function OnBindResourcesWebRequestCompleted(executor, eventArgs)
{
    if (executor.get_responseAvailable()) 
    {
        // deserialize the JSON response
        var results = Sys.Serialization.JavaScriptSerializer.deserialize(executor.get_responseData(), true);
        var resourceItems = $get('resourceItems');
        
        //refresh GUI
        removeChildNodes(resourceItems); // remove the loader element
        
        _categoryTabs.innerHTML = results.CategoryTabsHtml;
        _topPager.innerHTML = results.PagerHtml;
        _bottomPager.innerHTML = results.PagerHtml;
        _topPageSize.innerHTML = results.PageSizeHtml;
        _bottomPageSize.innerHTML = results.PageSizeHtml;

        tabPanel.resizeTabs();
        $get('bookmarkResults').href = results.BookmarkLinkUrl;

        if (results.Resources.length == 0)
        {
            // add the links to newest and most popular resources
            resourceItems.appendChild(addResourceStringEmpty('Sorry, there are no results for your search. Please try one of the following:'));
            resourceItems.appendChild(addResourceListEmpty('', 'unordered', ['Try a different keyword (see our guidelines on how to use full text search', 'Tick the boxes to browse resources for the products you\'re interested in', 'Select \'See all resources\', below, to start a new search.']));
            resourceItems.appendChild(addResourceStringEmpty(addResourceLinkEmpty('0', 'See all resources.')));
            resourceItems.appendChild(addResourceStringEmpty(addResourceLinkEmpty('2', 'See newest resources.')));
            resourceItems.appendChild(addResourceStringEmpty(addResourceLinkEmpty('0', 'See most popular resources.')+'<!--br/><br/-->'));
            resourceItems.appendChild(addResourceListEmpty('How to use full text search:', 'unordered', ['Enter a word or words, without commas for results which contain all the entered words.', 'Enter a phrase, in quotes, to search for that exact phrase, e.g. "virtualisation presentation". (Results containing the separate words virtualisation or presentation will not be returned.)', 'Don\'t use brackets, conjunctions (AND, OR, NOT,) and special characters (apart from quotes, as above).']));
        }
        else
        {
            // add the Resource objects to the Resource results table
            for (i = 0; i < results.Resources.length; ++i)
            {
                resourceItems.appendChild(addResourceItem(results.Resources[i], i));
            }
        }
    }
    else
    {
        if (executor.get_timedOut())
            alert("Timed Out");
        else
            if (executor.get_aborted())
                alert ("Aborted");
    }
}  

/****************************************************************************
GUI event handler functions
****************************************************************************/
function search()
{
    _searchCriteria.SearchText = _searchText.value.trim();
    _searchCriteria.PageIndex = 0;
    bindResources();
}

function setCategory(category)
{
    _searchCriteria.Category = category;
    _searchCriteria.PageIndex = 0;
    bindResources();
}

function setPageIndex(pageIndex)
{
    _searchCriteria.PageIndex = pageIndex;
    bindResources();
}

function setPageSize(pageSize)
{
    _searchCriteria.PageSize = pageSize;
    _searchCriteria.PageIndex = 0;
    bindResources();
}

function setSortOrder(sortID)
{
    _searchCriteria.SortID = sortID;
    _searchCriteria.PageIndex = 0;
    bindResources();
}

function setProduct(productGroupControl, pgIndex)
{
    var productGroupChkbox = $get(productGroupControl)
    //update the state of the parent product group checkbox
    productGroupChkbox.checked = getSelected("productGroup_" + pgIndex).length == getProductCount("productGroup_" + pgIndex);
    //refresh list of resources
    bindProducts();
}

function setProductGroup(productGroupID, checked)
{
    var control = $get(productGroupID);
    // iterate the childNodes and populate the result with value of each checked checkbox
    for (var i = 0; i < control.childNodes.length; ++i)
    {
        var child = control.childNodes[i].firstChild;
        
        if (child != null && child.type == 'checkbox')
        {
            child.checked = checked;
        }
    }
    bindProducts();
}

function bindProducts()
{
    var productFilter = new Array();

    //get product ids from all product groups
    var i=0;
    while($get("productGroup_" + i) != null)
    {
        productFilter = productFilter.concat(getSelected("productGroup_" + i));
        i++;
    }

    var productCount = productFilter.length;
    
    // only add the filter if not all products are selected
    if (productCount != 0 && productCount != _totalProductCount)
        _searchCriteria.Products = productFilter.join(',');
    else
        _searchCriteria.Products = "";

    _searchCriteria.PageIndex = 0;
    bindResources();
}

/****************************************************************************
psat Tabs object, methods and properties
****************************************************************************/
function psatTabs(_settings) {
    this.settings = _settings;
    this.resizeTabs = resizeTabs;
    this.overideHeight = overideHeight;

    this.getData = getData;
    this.setData = setData;

    init(_settings);

    function init(userData) {
        _settings = userData;
        if (!_settings.containerId) {
            _settings.containerId = 'mainTabContainer';
        }
        if (!_settings.tabTag) {
            _settings.tabTag = 'a';
        }
        if (!_settings.overideMaxHeight) {
            _settings.overideMaxHeight = false;
        }
    }

    /* Public Methods */
    function resizeTabs() {
        var tabs = getTabsObj();
        if (tabsHavaData(tabs)) {
            if (this.settings.overideMaxHeight == false) {
                this.settings.maxHeight = getMaxHeight(tabs) - paddingAdjust(tabs[0]);
            }
            setMaxHeight(tabs, this.settings.maxHeight);
        }
    }
    
    function overideHeight(height) {
        if (height > 0) {
            this.setData('overideMaxHeight', true);
            this.setData('maxHeight', height);
        } else {
            this.setData('overideMaxHeight', false);
            this.setData('maxHeight', 0);
        }
    }

    function getData(which) {
        if (this.settings[which]) {
            return this.settings[which];
        } else {
            return null;
        }
    }

    function setData(name, data) {
        this.settings[name] = data;
    }

    /* Private Methods */
    function getTabsObj() {
        var tabContainer = document.getElementById(_settings.containerId);
        if (tabContainer) {
            var tabSet = tabContainer.getElementsByTagName(_settings.tabTag);
            return tabSet;
        } else {
            return {};
        }
    }

    function tabsHavaData(elements) {
        if (elements.length > 0) {
            return true;
        } else {
            return false;
        }
    }

    function getMaxHeight(elements) {
        var maxHeight = 0;
        for (var currentTab = 0; currentTab < elements.length; currentTab++) {
            if (elements[currentTab].className.indexOf('tab') != -1) {
                if (elements[currentTab].offsetHeight > maxHeight) { maxHeight = elements[currentTab].offsetHeight; }
            }
        }
        return maxHeight;
    }

    function setMaxHeight(elements, maxHeight) {
        for (var currentTab = 0; currentTab < elements.length; currentTab++) {
            if (elements[currentTab].className.indexOf('tab') != -1) {
                elements[currentTab].style.height = maxHeight + 'px';
            }
        }
    }

    function paddingAdjust(element) {
        var paddingAdjust = 0;
        if (element.currentStyle) {
            paddingAdjust = parseInt(element.currentStyle.paddingTop) + parseInt(element.currentStyle.paddingBottom);
        } else if (window.getComputedStyle) {
            paddingAdjust = parseInt(document.defaultView.getComputedStyle(element, null).getPropertyValue('padding-top')) + parseInt(document.defaultView.getComputedStyle(element, null).getPropertyValue('padding-bottom'));
        }
        return paddingAdjust;
    }

}

var tabPanel = new psatTabs({ 'containerId': 'mainTabContainer', 'tabTag': 'a', 'tabDivider': 'tabDivider' });

