﻿/**
 * @author pop webdev [tw]
 * @version 0.1
 * @classDescription Handles Pagination of an inline collection. The collection should the form of a <ul> nested inside a master <ul>
 * @return {Object}	Returns a new  object.
 * The class depends on Prototype v1.6.
 */
var Paginator = Class.create({
    initialize: function (elMasterList, options) {
        // set options
        this.options = Object.extend({
            initialPageIndex: 0,
            itemsPerPage: 4,
            disableClassName: 'disabled',
            selectedClassName: 'selected'
        }, options || {});

        // element check
        if ($(elMasterList)) { this.masterList = $(elMasterList); } else { return; }

        // get dom references and set properties based on original list.
        // get the li count of the nested ul (performance items)
        var firstLI = this.masterList.down('li').addClassName('paginator_page').writeAttribute('id', 'paginator_page_0');
        this.items = firstLI.select('ul li');
        this.itemCount = this.items.size();

        // split first li.paginator_page ul into separeate ul's and insert into generated li.paginator_page nodes
        var aPages = this.items.eachSlice(this.options.itemsPerPage); //, function(listItem){});
        this.pageCount = aPages.size();

        if (this.pageCount > 1) {
            /* 
            for all pages except the first, create a node like
            <li class="paginator_page" id="paginator_page_i">
				<ul class="[className from original nested ul]">
					list items in aPage[i]
				</ul>
            </li>
            */
            var sInnerUlClassName = firstLI.down('ul').className; // get any css classnames from inner UL
            for (var i = 1, len = this.pageCount; i < len; ++i) {
                var elPageLi = new Element('li', { 'class': 'paginator_page', 'id': 'paginator_page_' + i });
                var elInnerUL = new Element('ul', { 'class': sInnerUlClassName });
                for (var j = 0; j < aPages[i].size(); j++) {
                    elInnerUL.insert(aPages[i][j]);
                }
                elPageLi.insert(elInnerUL);
                this.masterList.insert(elPageLi);
            }
        }
        else {
            return; // there's only one page, no pagination needed.
        }

        // add li.paginav controls via dom
        var elTopControls = new Element('li', { 'class': 'paginav', id: 'paginav_top' });
        this._addControlList(elTopControls);
        this.masterList.insert({ top: elTopControls });
        this.paginavTop = elTopControls;

        var elBottomControls = new Element('li', { 'class': 'paginav', id: 'paginav_bottom' });
        this._addControlList(elBottomControls);
        this.masterList.insert({ bottom: elBottomControls });
        this.paginavBottom = elBottomControls;

		if (this.options.initialPageIndex + 1 > this.pageCount) {
			this.options.initialPageIndex = 0;
		}
        this.viewPage(this.options.initialPageIndex);

    },

    // creates a ul filled with pagination links, 
    // attaches an event listener, 
    // and appends the node to supplied element.
    _addControlList: function (elLi) {
        var elControlList = new Element('ul');
        var elPrevNavItem = new Element('li', { 'class': 'prev' });
        var elPrevNavLink = new Element('a', { 'href': '#prev' }).update('<img src="/_img/_ui/arrow_prev.gif" alt="Previous" />');
        elPrevNavItem.insert(elPrevNavLink);
        elControlList.insert(elPrevNavItem);

        for (var i = 0; i < this.pageCount; i++) {
            //<li class="individual"><a href="#paginator_page_0">1</a></li>
            var pageNum = i + 1;
            var elPageItem = new Element('li', { 'class': 'individual' });
            var elPageLink = new Element('a', { 'href': '#paginator_page_' + i }).update(pageNum);
            elPageItem.insert(elPageLink);
            elControlList.insert(elPageItem);
        }

        var elNextNavItem = new Element('li', { 'class': 'next' });
        var elNextNavLink = new Element('a', { 'href': '#next' }).update('<img src="/_img/_ui/arrow_next.gif" alt="Next" />');
        elNextNavItem.insert(elNextNavLink);
        elControlList.insert(elNextNavItem);

        // add event handler
        elControlList.observe('click', this.__paginavListClick.bindAsEventListener(this));
        // add new nodes to provide li		
        elLi.insert(elControlList);
    },

    // calls updatePaginav on both top and bottom nav
    updatePaginavs: function () {
        this.updatePaginav(this.paginavTop);
        this.updatePaginav(this.paginavBottom);
    },

    // sets disabled and selected classes
    updatePaginav: function (elPaginav) {
        // adjust next/previous
        var elPrevNavItem = elPaginav.down('li.prev');
        (this.currentPageIndex > 0) ? elPrevNavItem.removeClassName(this.options.disableClassName) : elPrevNavItem.addClassName(this.options.disableClassName);

        var elNextNavItem = elPaginav.down('li.next');
        (this.currentPageIndex < (this.pageCount - 1)) ? elNextNavItem.removeClassName(this.options.disableClassName) : elNextNavItem.addClassName(this.options.disableClassName);

        var elNavItems = elPaginav.select('li.individual');

        //var elNavItems = elPaginav.childElements();
        for (var i = 0, len = elNavItems.size(); i < len; i++) {
            //var pageIndex = /\d+$/.exec(dest)[0];
            (i == this.currentPageIndex) ? elNavItems[i].addClassName('selected') : elNavItems[i].removeClassName('selected');
        }

    },

    __paginavListClick: function (e) {

        var el = e.element();
        var elLi, elLnk;
        if (el.nodeName == 'UL') { return; }
        e.stop();

        if (el.nodeName != 'LI') { elLi = $(el).up('li'); }
        else { elLi = $(el); }
        elLnk = elLi.down('a');

        var dest = elLnk.readAttribute('href').replace('#', '');
        //console.log(dest);
        switch (dest) {
            case 'prev':
                this.viewPreviousPage();
                break;
            case 'next':
                this.viewNextPage();
                break;
            default:
                var pageIndex = /\d+$/.exec(dest)[0];
                this.viewPage(parseInt(pageIndex));
                break;
        }
    },

    // methods
    viewPage: function (pageIndex) {
        this.currentPageIndex = pageIndex;
        // hide all but given page	
        var pageLIs = this.masterList.select('li.paginator_page');
        for (var i = 0, len = pageLIs.size(); i < len; i++) {
            // all that for this.
            (i == pageIndex) ? pageLIs[i].show() : pageLIs[i].hide();
        }
        this.updatePaginavs()
        $('top').scrollTo(); // Prevent "jump" to top per Req 4.1.1

        deephash.set('page', pageIndex + 1);
    },

    viewNextPage: function () {
        if (this.currentPageIndex < (this.pageCount - 1)) {
            this.viewPage(this.currentPageIndex + 1);
        }
    },

    viewPreviousPage: function () {
        if (this.currentPageIndex > 0) {
            this.viewPage(this.currentPageIndex - 1);
        }
    }
});

/*
document.observe('dom:loaded', function(){
	myPaginator = new Paginator($('paginator'),{initialPageIndex: 0, itemsPerPage: 4, disableClassName: 'disabled', selectedClassName: 'selected'});
});
*/

// prevent errors from console calls to browsers that don't provide firebug's debugging console.
if (!window.console || !console.firebug) {
    var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml",
    "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];

    window.console = {};
    for (var i = 0; i < names.length; ++i)
        window.console[names[i]] = function() {}
}
