$.fn.dataTableExt.oPagination.mosaic_pagination = {
    center_align: true,
	/*
	 * Function: oPagination.four_button.fnInit
	 * Purpose:  Initalise dom elements required for pagination with a list of the pages
	 * Returns:  -
	 * Inputs:   object:oSettings - dataTables settings object
	 *           node:nPaging - the DIV which contains this pagination control
	 *           function:fnCallbackDraw - draw function which must be called on update
	 */
	"fnInit": function ( oSettings, nPaging, fnCallbackDraw )
	{
		nFirst = document.createElement( 'span' );
		nPrevious = document.createElement( 'span' );
		nNext = document.createElement( 'span' );
		nLast = document.createElement( 'span' );
        nList = document.createElement( 'span' );
		
		nFirst.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sFirst ) );
		nPrevious.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sPrevious ) );
		nNext.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sNext ) );
		nLast.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sLast ) );
		
		nFirst.className = "paginate_button first";
		nPrevious.className = "paginate_button previous";
		nNext.className="paginate_button next";
		nLast.className = "paginate_button last";
		
		nPaging.appendChild( nFirst );
		nPaging.appendChild( nPrevious );
        nPaging.appendChild( nList );
		nPaging.appendChild( nNext );
		nPaging.appendChild( nLast );
		
		$(nFirst).click( function () {
			oSettings.oApi._fnPageChange( oSettings, "first" );
			fnCallbackDraw( oSettings );
		} );
		
		$(nPrevious).click( function() {
			oSettings.oApi._fnPageChange( oSettings, "previous" );
			fnCallbackDraw( oSettings );
		} );
		
		$(nNext).click( function() {
			oSettings.oApi._fnPageChange( oSettings, "next" );
			fnCallbackDraw( oSettings );
		} );
		
		$(nLast).click( function() {
			oSettings.oApi._fnPageChange( oSettings, "last" );
			fnCallbackDraw( oSettings );
		} );
		
		/* Take the brutal approach to cancelling text selection */
        $('span', nPaging)
            .bind( 'mousedown', function () { return false; } )
            .bind( 'selectstart', function () { return false; } );
	},
	
	/*
	 * Function: oPagination.four_button.fnUpdate
	 * Purpose:  Update the list of page buttons shows
	 * Returns:  -
	 * Inputs:   object:oSettings - dataTables settings object
	 *           function:fnCallbackDraw - draw function which must be called on update
	 */
	"fnUpdate": function ( oSettings, fnCallbackDraw )
	{
		if ( !oSettings.aanFeatures.p )
		{
			return;
		}
        var iPageCount = $.fn.dataTableExt.oPagination.iFullNumbersShowPages;
        var iPageCountHalf = Math.floor(iPageCount / 2);
        var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength);
        var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1;
        var sList = "";
        var iStartButton, iEndButton, i, iLen;
        var oClasses = oSettings.oClasses;
		
		/* Pages calculation */
        if (iPages < iPageCount)
        {
            iStartButton = 1;
            iEndButton = iPages;
        }
        else
        {
            if (iCurrentPage <= iPageCountHalf)
            {
                iStartButton = 1;
                iEndButton = iPageCount;
            }
            else
            {
                if (iCurrentPage >= (iPages - iPageCountHalf))
                {
                    iStartButton = iPages - iPageCount + 1;
                    iEndButton = iPages;
                }
                else
                {
                    iStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1;
                    iEndButton = iStartButton + iPageCount - 1;
                }
            }
        }

        /* Build the dynamic list */
        if(iPages > iPageCount && iStartButton > 1) {
            sList += '<span class="' + oClasses.sPageButton + ' first_number">1...</span>';
        }
        for ( i=iStartButton ; i<=iEndButton ; i++ )
        {
            if ( iCurrentPage != i )
            {
                sList += '<span class="'+oClasses.sPageButton+'">'+i+'</span>';
            }
            else
            {
                sList += '<span class="'+oClasses.sPageButtonActive+'">'+i+'</span>';
            }
        }
        if(iPages > iPageCount && iEndButton < iPages) {
            sList += '<span class="' + oClasses.sPageButton + ' last_number">...' + iPages + '</span>';
        }

        /* Loop over each instance of the pager */
        var an = oSettings.aanFeatures.p;
        var anButtons, anStatic, nPaginateList;
        var fnClick = function() {
            /* Use the information in the element to jump to the required page */
            var html = this.innerHTML.replace('...', '');
            var iTarget = (html * 1) - 1;
            oSettings._iDisplayStart = iTarget * oSettings._iDisplayLength;
            fnCallbackDraw( oSettings );
            return false;
        };
        var fnFalse = function () { return false; };

        for ( i=0, iLen=an.length ; i<iLen ; i++ )
        {
            if ( an[i].childNodes.length === 0 )
            {
                continue;
            }

            /* Build up the dynamic list forst - html and listeners */
            var qjPaginateList = $('span:eq(2)', an[i]);
            qjPaginateList.html( sList );
            $('span', qjPaginateList).click( fnClick ).bind( 'mousedown', fnFalse )
                .bind( 'selectstart', fnFalse );

            /* Update the 'premanent botton's classes */
            anButtons = an[i].getElementsByTagName('span');
            anStatic = [
                anButtons[0], anButtons[1], 
                anButtons[anButtons.length-2], anButtons[anButtons.length-1]
            ];
            $(anStatic).removeClass( oClasses.sPageButton+" "+oClasses.sPageButtonActive+" "+oClasses.sPageButtonStaticDisabled );
            if ( iCurrentPage == 1 )
            {
                anStatic[0].className += " "+oClasses.sPageButtonStaticDisabled;
                anStatic[1].className += " "+oClasses.sPageButtonStaticDisabled;
            }
            else
            {
                anStatic[0].className += " "+oClasses.sPageButton;
                anStatic[1].className += " "+oClasses.sPageButton;
            }

            if ( iPages === 0 || iCurrentPage == iPages || oSettings._iDisplayLength == -1 )
            {
                anStatic[2].className += " "+oClasses.sPageButtonStaticDisabled;
                anStatic[3].className += " "+oClasses.sPageButtonStaticDisabled;
            }
            else
            {
                anStatic[2].className += " "+oClasses.sPageButton;
                anStatic[3].className += " "+oClasses.sPageButton;
            }
        }
        
        if(true === this.center_align) {
            $('.dataTables_paginate').each(function(){
                if(true !== $(this).data('wrapped')) {
                    $(this).data('wrapped', true);
                    $('<div/>', {
                        'class': 'dataTables_paginate_wrapper',
                        text: ''
                    }).insertBefore($(this)).append($(this));
                }
                $(this).width('');
                $(this).css('display', 'inline');
                $(this).width($(this).width() + 5);
                $(this).css('display', 'block');
            });
        }
	}
};

