/*
 * catalogPagination.js ---
 *
 * <pre>
 * Author: Sucheela Nanekrangsan
 * Created: Tue Jun 10, 2008
 *
 * Commentary:
 * Usage:
 *
 * HTML example:
 *
 * <div id="unique-1" onclick="someFunction(this)">product HTML content</div>
 * <ul id="pagination-default">
 *   <li><a href="javascript:void(0)" onclick="cp.previousPage()">Previous</a></li>
 *   <li><a href="javascript:void(0)" onclick="cp.changePage(1)">1</a></li>
 *   <li><a href="javascript:void(0)" onclick="cp.nextPage()">Next</a></li>
 * </ul>
 *
 * Limitation: Can't pass any parameters other than itself to the main DIV's onclick handler
 *
 * JavaScript example:
 *
 * var cp = new CatalogPagination(20, 5, json_encoded_product_array);
 * cp.setDivIdToReplace('unique-#idx#');
 * cp.setIndexString('#idx#');
 * cp.setProductHtml('product HTML with replacement strings such as #product# #publication_id#');
 * cp.setReplacementArray('#product#', 'productName'); // where productName is a column name in json_encoded_product_array
 * cp.setReplacementArray('#publication_id#', 'publicationId');
 * cp.setMaxCharLength(30); // if you want to limit char length to display
 *
 * </pre>
 */

/**
 * Constructor
 * @param Integer maxNumProducts The number of products to be displayed
 *                on one page.
 * @param Integer maxNumPages The number of pages to be displayed in the
 *                page navigation bar.
 */  
function CatalogPagination(maxNumProducts, maxNumPages, products) {
    
    this.currPage = 1;
    this.maxNumProducts = maxNumProducts;
    this.maxNumPages = maxNumPages;
    this.products = eval(products);

    this.totalPages = Math.ceil(this.products.length/this.maxNumProducts);

    this.replacementArray = new Array();

    this.maxCharLength = 0;
} // CatalogPagination

/**
 * Tell the object which div we are working with
 * @param String id Unique ID of the div we are working with.
 */  
CatalogPagination.prototype.setDivIdToReplace = function(id){
    this.divId = id;
} // setDivIdToReplace

/**
 * HTML that we want to display with in the DIV
 * @param String html
 */  
CatalogPagination.prototype.setProductHtml = function(html){
    this.productHtml = html;
} // setProductHtml

/**
 * Marked string to be replaced with index count
 * @param String indexString
 */  
CatalogPagination.prototype.setIndexString = function(indexString){
    this.indexString = indexString;
} // setIndexString

/**
 * Marked string in productHtml and handlerString to be replaced 
 * with values from replacementColName in this.products 
 * @param String searchString
 * @param String replacementColName
 */  
CatalogPagination.prototype.setReplacementArray = function(searchString, replacementColumnName){
    this.replacementArray[this.replacementArray.length]
        = new Array(searchString, replacementColumnName);
} // setReplacementArray

/**
 * Set maximum number of characters to display
 * @param Integer length
 */
CatalogPagination.prototype.setMaxCharLength = function(length){
    this.maxCharLength = length;
} // setMaxCharLength

/**
 * Move next 
 */  
CatalogPagination.prototype.nextPage = function(){
    if (this.currPage < this.totalPages){
        this.currPage++;
    }
    this.writeCatalog();
    this.writePageNav();
} // nextPage

/**
 * Move previous 
 */  
CatalogPagination.prototype.previousPage = function(){
    if (this.currPage > 1){
        this.currPage--;
    }   
    this.writeCatalog();
    this.writePageNav();
} // previousPage

/**
 * Go to page
 * @param Integer pageNum
 */  
CatalogPagination.prototype.changePage = function(pageNum){
    if (pageNum >= 1 && pageNum <= this.totalPages){
        this.currPage = pageNum;
    }
    this.writeCatalog();
    this.writePageNav();
} // changePage

/**
 * Replace content of identified DIV with replacements from this.products
 * and this.replacementArray
 */  
CatalogPagination.prototype.writeCatalog = function(){
    var firstItem = (this.currPage-1) * this.maxNumProducts;
    for (var i=0; i<this.maxNumProducts; i++){
    
        var productIndex = firstItem + i;
        
        // get the div element
        var idReg = new RegExp(this.indexString, 'g');
        var id = this.divId.replace(idReg, i);
        var el = document.getElementById(id);
    
        if (productIndex < this.products.length){
            // get the product we want to display
            var product = this.products[productIndex];
    
            // prepare the html
            var html = this.productHtml;

            // replace element ID
            html = html.replace(idReg, i);

            // replace other string
            for (var j=0; j<this.replacementArray.length; j++){
                var searchString = new RegExp(this.replacementArray[j][0], 'g');
                var replaceString = product[this.replacementArray[j][1]];
                // truncate string if maxCharLength is set
                if (this.maxCharLength > 0 && replaceString.length > this.maxCharLength){
                    replaceString = replaceString.substring(0, this.maxCharLength);
                    replaceString = replaceString + '...';
                }
                html = html.replace(searchString, replaceString);
            }

            el.style.visibility = 'visible';
            el.innerHTML = html;
        } else {
            // this is the last page - and we can't fill it up
            // so just hide the leftover spaces
            el.style.visibility = 'hidden';            
        }
    }
} // writeCatalog

CatalogPagination.prototype.writePageNav = function(){
    // get UL containing page nav
    var nav = document.getElementById('pagination-default');
    
    // remove all existing paginations
    for (var i=nav.childNodes.length-1; i>=0; i--){
        nav.removeChild(nav.childNodes[i]);
    }

    // previous link
    var prev = document.createElement('li');
    if (this.currPage > 1){
        prev.innerHTML = '<a href="javascript:void(0)" onclick="cp.previousPage()">&laquo; Previous</a>';
        prev.className = 'previous';
    } else {
        prev.innerHTML = '&laquo; Previous';
        prev.className = 'previous-off';
    }

    nav.appendChild(prev);

    // figure out what pages to display
    var pageOffset = Math.floor(this.maxNumPages/2);

    var firstPage = this.currPage - pageOffset;
    if (firstPage < 1){
        firstPage = 1;
    }
    if (this.totalPages <= this.maxNumPages){
        firstPage = 1;
    }

    for (var i=0; i<this.maxNumPages; i++){
        var pageNum = firstPage + i;

        if (pageNum > this.totalPages){
            break;
        }

        var page = document.createElement('li');
        if (pageNum == this.currPage){
            page.innerHTML = pageNum;
            page.className = 'active';
        } else {
            page.innerHTML = '<a href="javascript:void(0)" onclick="cp.changePage(' + pageNum + ')">' + pageNum + '</a>';
        }
        nav.appendChild(page);
    }

    // next link
    var next = document.createElement('li');
    if (this.currPage < this.totalPages){
        next.innerHTML = '<a href="javascript:void(0)" onclick="cp.nextPage()">Next &raquo;</a>';
        next.className = 'next';
    } else {
        next.innerHTML = 'Next &raquo;';
        next.className = 'next-off';
    }
    nav.appendChild(next);
    
} // writePageNav
