	
	function Paginator( sDomElement, oOptions, oRequestParams ) {
        var isCacheProvide = true;
        if ( this === window ) {
            // Paginator Must invoked with 'new' operator
	        return;
	    }
	    if ( !sDomElement ) {
	        return;
	    }
	    if ( typeof oOptions.sOrigElem === 'undefined' ) {
	        isCacheProvide = false;
	    }
	    this.oRequestParams = oRequestParams;
	    
	    var defaults = {
	        sOrigElem : 'KMPCache',
	        sPagiElem : 'KMPagination',
	        sItemWrapper : 'li',
	        iItemsPerPage : 10,
	        sCurrentPage : 'KMPCurrent',
	        sFormAction : 'javascript:void(0);',
	        totalPages : 1,
	        iNowPage : 1
	    };
	    $.extend(this, defaults, oOptions || {});
	
	    this.$DestElem = $( sDomElement );
	    if ( isCacheProvide ) {
	        this.$OrigElem = $(this.sOrigElem);
	    } else {
	        this.$OrigElem = $('<div class="' + this.sOrigElem + '"></div>');
	        this.$OrigElem.insertAfter( this.$DestElem );
	    }
	    this.isDetailPage = false ;
	    this.$PagiElem = $(this.sPagiElem);
	    if ( this.sFormAction === 'javascript:void(0);' ) {
	    	this.isDetailPage = true ;
	    	this.items = this.$OrigElem.find(this.sItemWrapper);
	    	this.totalItems = this.items.length;
	    	if ( this.totalItems === 0 ){
	    		return;
	    	}
	    	this.totalPages = Math.ceil( this.totalItems / this.iItemsPerPage );
	    } 
	    this.oData = {};
	    $.extend( this.oData, this.oRequestParams );
	    this.params = '';
	    var self = this;
	    $.each(	this.oData, function( name, value ){
	    	self.params += '&' + name + '=' + value;
	    } );
	    this.init();
	}
	
	Paginator.prototype.init = function() {
		if( this.$DestElem.length > 0 ) {
			this.showPages( this.iNowPage );
			if( this.isDetailPage ) {
				this.PageEventRegister();
			}
		}
	};
	
	Paginator.prototype.EnterPress = function( evt ){
		evt = (evt) ? evt : ((window.event) ? window.event : "");
		keyCode = evt.keyCode ? evt.keyCode : (evt.which ? evt.which : evt.charCode);
		if (keyCode == 13) {
			this.checkTopage();
			return false;
		}
	}
	
	Paginator.prototype.checkTopage = function( sTopage ) {
		var $ToPage = $(sTopage);
		var topage = $ToPage[0].value;
		re1 = new RegExp("^[0-9]+$");
		re2 = new RegExp("^[a-z,A-Z]+$");
		if( !re1.test( topage ) || topage * 1 == 0 ) {
			topage = 1;
			$ToPage[0].value = topage;
		} else if(topage * 1 > this.totalPages) {
			topage = this.totalPages;
			$ToPage[0].value = topage;
		}
		this.turnPages( parseInt( topage ) );
		return true;
	}
	
	Paginator.prototype.turnPages = function( iipage ) {
		if( this.isDetailPage ) {
			this.gotoPage( iipage );
			this.showPages( iipage );
			this.PageEventRegister();
		}
	}
	
	Paginator.prototype.showPages = function( page ) {
		var self = this,
			sType = 'num';
			
		if( this.totalPages <= 1 ) {
			return;
		}
	   	this.$PagiElem.empty();
	   	
        if ( this.totalPages  <= 9 ) {
	        for ( var i = 1; i <= this.totalPages; i++ ) {
               generateHelper( page, i, sType );
	        }
        }else{
	        var aPages = this.generatePages( page );
	        for ( var i = 0; i < aPages.length; i++ ) {
	            sType = ( aPages[i] == '...' ) ? '...' : 'num';
		        generateHelper( page, aPages[i], sType );
	        }
	        generateInlinePage( page - 1 ,'上一页');
	        generateInlinePage( page + 1 ,'下一页' );
			
			this.$PagiElem.append( $('<span class="page-count mr05">共 ' + this.totalPages + ' 页</span>') );
			var sTopage = '<span>  到 <input type="text" id="topage" name="page" value="" /> 页 <input class="paginatorSubmit" type="submit" value="确定" /> </span>';
		    $.each(	this.oData, function( name, value ){
		    	sTopage += '<input name="' + name + '" type="hidden" value=' + value + ' /> ';
		    } );
			var $form = $('<form action=' + this.sFormAction + ' onsubmit="return false">' + sTopage + '</form>');
			$form.css('display','inline');
			$form.submit( function(event) { event.preventDefault();self.checkTopage('#topage');event.target.submit(); } );
			this.$PagiElem.append( $form );
			this.$PagiElem.find('a').attr('hideFocus', true);
	    }
        
	   	function generateInlinePage( ipage , text ){
	   		if( ipage >= 1 && ipage <= self.totalPages ) {
	   			var appendText = $('<a class="mr05">' + text + '</a>');
	   			if( self.isDetailPage ) {
	   				appendText.bind( 'click', function(){ self.turnPages( ipage ) } );
   				}else {
   					var sHref = self.sFormAction + '?page=' + ipage + self.params;
   					appendText.attr( 'href', sHref );
	   			}
	   			self.$PagiElem.append( appendText );
	   		}
	   	}
	   	
	   	function generateHelper( CurrentPage, iPage, type ){
            var sTag = 'a',
                sClassOfLink = '',
                oElem = '';

            sClassOfLink = ( iPage == CurrentPage ) ? 'mr05 ' + self.sCurrentPage : 'mr05';
            if ( type === 'num') {
                sClassOfLink += ' pagination-page ';
            } else {
                sClassOfLink += ' page-break';
                sTag = 'span';
            }
            oElem = $('<' + sTag + '/>');
            oElem.addClass(sClassOfLink).attr('hideFocus', true);
            if( !self.isDetailPage ) {
            	var sHref = '';
            	sHref = self.sFormAction + '?page=' + iPage + self.params;
            	sTag === 'a' ? oElem.attr('href', sHref) : '';
            }
            oElem.text( iPage );
            self.$PagiElem.append( oElem );
        }
	   	
	};
	
	Paginator.prototype.generatePages = function(ipage){
		var pages = [];
		var len = 9,
			flag = '',
			middle = Math.ceil( len / 2);
		
		for ( var i = 0 , j = 1; i < len; i++ , j++ ) {
			flag = '' + j;
			if( ( i == 1 && ipage > middle ) || ( i == 7 && ipage <= this.totalPages - middle ) ) {
				flag = '...';
			} else if ( i == 2 && ipage > this.totalPages - middle ){
				j = this.totalPages -  middle - 1;
				flag = '' + j;
			} else if ( i == 2 && ipage <= this.totalPages - middle && ipage > middle ) {
				j = ipage - 2;
				flag = '' + j;
			} else if ( i == len - 1 ) {
				flag = '' + this.totalPages;
			}
			pages[i] = flag;
		}
		return pages;
	}
	
	Paginator.prototype.PageEventRegister = function() {
	    var self = this;
	
	    this.$PagiElem.find('a.pagination-page').click(function(){
	        var iCursor = self.$PagiElem.find('a.pagination-page').index( $(this) );
	        var cursorPage = 1;
	        if( self.$PagiElem.find('a.pagination-page').length > 0){
	       		cursorPage = parseInt(  self.$PagiElem.find('a.pagination-page')[iCursor].innerHTML );
	        }
	        self.turnPages( cursorPage );
	        return false;
	    });
	}
	
	Paginator.prototype.gotoPage = function(i) {
	    //this.getItemsFromVisible();
	    this.clearVisible();
	    //this.putItemsIntoCache();
	    this.putItemsIntoVisible(i);
	    $('html, body').animate({
	        scrollTop : this.$DestElem.parent().offset().top
	    }, 300);
	};
	
	Paginator.prototype.getItemsFromVisible = function() {
	    return this.$DestElem.find(this.sItemWrapper);
	};
	
	Paginator.prototype.clearVisible = function() {
	    this.$DestElem.find(this.sItemWrapper).detach();
	};
	
	Paginator.prototype.putItemsIntoCache = function() {
	    var iCursor = this.$PagiElem.find('a').index( $( '.' + this.sCurrentPage) ),
	        iIndex = iCursor * this.iItemsPerPage,
	        $visibleItems = this.getItemsFromVisible();
	    if( iIndex === 0 ){
	        $visibleItems.prependTo( this.$OrigElem );
	        return;
	    }
	    $visibleItems.insertAfter( this.$OrigElem[iIndex] );
	};
	
	Paginator.prototype.putItemsIntoVisible = function(page) {
	   	var iIndex = ( page - 1 )* this.iItemsPerPage,
	        len = iIndex + this.iItemsPerPage,
	        aItems = this.$OrigElem.find(this.sItemWrapper);
	    for( iIndex; iIndex < len && iIndex < this.totalItems; iIndex++ ) {
	    	var perPage = aItems[iIndex];
	        this.$DestElem.append( $(perPage).clone() );
	    }
	};
	

