﻿/* 
*	ViewMnager base class
*/
function ViewManagedList() {
    this.data = null;
    this.service = null;
    this.displayArea;
    this.jDisplayElement;
    this.jResults = null;
    this.Pager = null;
    this.itemCount = 0;

    this.throbberClass = "throbber",

    this.timer = null;

    // If the service outputs a container with children, or just children.
    this.hasResultContainer = true;
    this.onComplete = null;
};

ViewManagedList.prototype.Load = function(optData) {
    // Convinence to add data on Load
    if (arguments.length > 0) {
        this.SetData(optData);
    }

    // Check we have what we need
    if (this.data == null || this.service == null) {
        alert("you must assign data and service details with SetService before loading");
        return;
    }

    // Todo: more flexible throbber, plus handle timeouts
    this.GetDisplayElement().html("<div class='" + this.throbberClass + "'><span>Loading...</span></div>");
    this.GetDisplayElement().show();

    if (this.Pager != null) {
        this.Pager.CreateLinks(this);
    }

    // Wrap the callback function to maintain scope in recieving method.
    var _this = this; // Keep scope for callback closure
    var callback = function(result) { _this.onLoadComplete(_this, result) };
    var failedCallback = function(result) { _this.onLoadFailed(_this, result) };

    // Call the View web service.
    //TODO: jquery has a "make array" or isArray thing - use that instead of == "object"

    if (typeof this.data == "object") {
        // Multiple data parameters for the service.
        this.data.push(callback, failedCallback);
        this.service.apply(this.service, this.data);
    }
    else {
        this.service.call(this.service, this.data, callback, failedCallback);
    }

};

// Parse the Web Service results for rendering
ViewManagedList.prototype.onLoadComplete = function(_this, result) {
    if (!_this.hasResultContainer) {
        result = "<div>" + result + "</div>";
    }
    // Convert to JQuery objects
    _this.jResults = $(result);

    _this.itemCount = _this.jResults.children().length;

    if (_this.Pager != null) {
        _this.Pager.totalSize = _this.itemCount;
        _this.Pager.CurrentPage = 0;
    }

    // Call the render method in the scope of the actual ViewManagerList instance.
    _this.Render.apply(_this);

    // Call callback if set
    if (_this.onComplete != null)
        _this.onComplete(_this.jResults);
};

ViewManagedList.prototype.onLoadFailed = function(_this, result) {
    //alert("Error:" + _this + "\n\n" + result);
}

// Set the Web Service details to call (hmm, also lets you set the data and display area)
ViewManagedList.prototype.SetService = function(service, data, displayArea) {
    this.service = service;
    if (arguments.length > 1) {
        this.SetData(data);
    }
    if (arguments.length > 2) {
        this.SetDisplay(displayArea);
    }
};

ViewManagedList.prototype.SetPager = function(pagingOptions) {
    this.Pager = new ListItemPager();
    this.Pager.init(pagingOptions);
};

ViewManagedList.prototype.SetData = function(data) {
    this.data = data;
}

ViewManagedList.prototype.SetDisplay = function(displayArea) {
    this.displayArea = displayArea;
}

// Update the target for the results to render in
ViewManagedList.prototype.SetDisplayElement = function(jDisplayElement) {

    // We have changed the target for the view - now we need to remove past references
    if (this.jDisplayElement != null) {
        this.jDisplayElement.empty();
    }

    // Now set the new display dom
    this.jDisplayElement = jDisplayElement;
}

ViewManagedList.prototype.GetDisplayElement = function() {
    if (this.jDisplayElement == null && this.displayArea != null) {
        this.jDisplayElement = this.displayArea.charAt(0) == "." ? $(this.displayArea) : $("#" + this.displayArea);
    }
    return this.jDisplayElement;
}

ViewManagedList.prototype.Render = function() {

    if (this.jResults == null || this.jResults.length == 0) {
        //alert("nothing to render - have you .Load yet?");
        return;
    }

    var subset = this.jResults.clone();

    if (this.Pager != null) {
        var startIndex = this.Pager.CurrentPage * this.Pager.PageSize;
        var endIndex = (startIndex + this.Pager.PageSize) - 1;

        subset.children("*:gt(" + endIndex + ")").remove();
        subset.children("*:lt(" + startIndex + ")").remove();

        this.Pager.prevLink.removeClass(this.Pager.UnavailableClassName);
        if (!this.Pager.HasPrevious()) { this.Pager.prevLink.addClass(this.Pager.UnavailableClassName) };

        this.Pager.nextLink.removeClass(this.Pager.UnavailableClassName);
        if (!this.Pager.HasNext()) { this.Pager.nextLink.addClass(this.Pager.UnavailableClassName) };
    }

    this.GetDisplayElement().html(subset).show();
    subset = null;
};



/* 
*	Paging
*/
function ListItemPager() {
    this.CurrentPage = 0;
    this.PageSize;
    this.totalSize;

    this.prevLink;
    this.nextLink;
}
ListItemPager.prototype.init = function(pagingOptions) {
    // Setup Options
    this.PageSize = pagingOptions.PageSize || 10;
    this.ClassName = pagingOptions.ClassName || "";
    this.PreviousClassName = pagingOptions.PreviousClassName || "PagingPrevious";
    this.NextClassName = pagingOptions.NextClassName || "PagingNext";
    this.PreviousHTML = pagingOptions.PreviousHTML || "Previous";
    this.NextHTML = pagingOptions.NextHTML || "Next";
    this.UnavailableClassName = pagingOptions.UnavailableClassName || "unavailable";
    this.displaySibling = pagingOptions.displaySibling;
}

// Append the NExt/Previous links for the pager
ListItemPager.prototype.CreateLinks = function(container) {
    
    // Determine where in the DOM to inject the links
    var displaySibling = this.displaySibling || container.jDisplayElement || container.displayArea;

    // If it's a string, then get the JQuery reference
    if (typeof this.displaySibling == "string") {
        displaySibling = $("#" + this.displaySibling);
    }

    // Remove the next link if it already exists, so we don't add twice.
    if (this.nextLink != null) {
        this.nextLink.parent().remove();
    }
    var boxy = $("<div class='PagingContainer' />");

    this.nextLink = $("<a href='#'>" + this.NextHTML + "</a>")
								    .addClass(this.ClassName)
								    .addClass(this.NextClassName)
								    .addClass(this.UnavailableClassName)
								    .click(function() {
								        container.Pager.MoveNext();
								        container.Render();
								        return false;
								    })
								    .appendTo(boxy);
    //  .insertAfter(displaySibling);

    // Remove the previous link if it already exists, so we don't add twice.
    /* if (this.prevLink != null) {
    this.prevLink.remove();
    }*/
    this.prevLink = $("<a href='#'>" + this.PreviousHTML + "</a>")
								    .addClass(this.ClassName)
								    .addClass(this.PreviousClassName)
								    .addClass(this.UnavailableClassName)
								    .click(function() {
								        container.Pager.MovePrevious();
								        container.Render();
								        return false;
								    })
								    .appendTo(boxy);
    //.insertAfter(displaySibling);
    boxy.insertAfter(displaySibling);


};
ListItemPager.prototype.MoveNext = function() { if (this.HasNext()) this.CurrentPage++; };
ListItemPager.prototype.MovePrevious = function() { if (this.HasPrevious()) this.CurrentPage--; };
ListItemPager.prototype.HasNext = function() { return !((this.CurrentPage + 1) * this.PageSize >= this.totalSize); };
ListItemPager.prototype.HasPrevious = function() { return this.CurrentPage != 0; };

if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();