123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394 |
- /*
- Copyright (c) 2009, Yahoo! Inc. All rights reserved.
- Code licensed under the BSD License:
- http://developer.yahoo.net/yui/license.txt
- version: 2.8.0r4
- */
- (function () {
- /**
- * The Paginator widget provides a set of controls to navigate through paged
- * data.
- *
- * @module paginator
- * @uses YAHOO.util.EventProvider
- * @uses YAHOO.util.AttributeProvider
- */
- var Dom = YAHOO.util.Dom,
- lang = YAHOO.lang,
- isObject = lang.isObject,
- isFunction = lang.isFunction,
- isArray = lang.isArray,
- isString = lang.isString;
- /**
- * Instantiate a Paginator, passing a configuration object to the contructor.
- * The configuration object should contain the following properties:
- * <ul>
- * <li>rowsPerPage : <em>n</em> (int)</li>
- * <li>totalRecords : <em>n</em> (int or Paginator.VALUE_UNLIMITED)</li>
- * <li>containers : <em>id | el | arr</em> (HTMLElement reference, its id, or an array of either)</li>
- * </ul>
- *
- * @namespace YAHOO.widget
- * @class Paginator
- * @constructor
- * @param config {Object} Object literal to set instance and ui component
- * configuration.
- */
- function Paginator(config) {
- var UNLIMITED = Paginator.VALUE_UNLIMITED,
- attrib, initialPage, records, perPage, startIndex;
- config = isObject(config) ? config : {};
- this.initConfig();
- this.initEvents();
- // Set the basic config keys first
- this.set('rowsPerPage',config.rowsPerPage,true);
- if (Paginator.isNumeric(config.totalRecords)) {
- this.set('totalRecords',config.totalRecords,true);
- }
-
- this.initUIComponents();
- // Update the other config values
- for (attrib in config) {
- if (config.hasOwnProperty(attrib)) {
- this.set(attrib,config[attrib],true);
- }
- }
- // Calculate the initial record offset
- initialPage = this.get('initialPage');
- records = this.get('totalRecords');
- perPage = this.get('rowsPerPage');
- if (initialPage > 1 && perPage !== UNLIMITED) {
- startIndex = (initialPage - 1) * perPage;
- if (records === UNLIMITED || startIndex < records) {
- this.set('recordOffset',startIndex,true);
- }
- }
- }
- // Static members
- lang.augmentObject(Paginator, {
- /**
- * Incrementing index used to give instances unique ids.
- * @static
- * @property Paginator.id
- * @type number
- * @private
- */
- id : 0,
- /**
- * Base of id strings used for ui components.
- * @static
- * @property Paginator.ID_BASE
- * @type string
- * @private
- */
- ID_BASE : 'yui-pg',
- /**
- * Used to identify unset, optional configurations, or used explicitly in
- * the case of totalRecords to indicate unlimited pagination.
- * @static
- * @property Paginator.VALUE_UNLIMITED
- * @type number
- * @final
- */
- VALUE_UNLIMITED : -1,
- /**
- * Default template used by Paginator instances. Update this if you want
- * all new Paginators to use a different default template.
- * @static
- * @property Paginator.TEMPLATE_DEFAULT
- * @type string
- */
- TEMPLATE_DEFAULT : "{FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink}",
- /**
- * Common alternate pagination format, including page links, links for
- * previous, next, first and last pages as well as a rows-per-page
- * dropdown. Offered as a convenience.
- * @static
- * @property Paginator.TEMPLATE_ROWS_PER_PAGE
- * @type string
- */
- TEMPLATE_ROWS_PER_PAGE : "{FirstPageLink} {PreviousPageLink} {PageLinks} {NextPageLink} {LastPageLink} {RowsPerPageDropdown}",
- /**
- * Storage object for UI Components
- * @static
- * @property Paginator.ui
- */
- ui : {},
- /**
- * Similar to YAHOO.lang.isNumber, but allows numeric strings. This is
- * is used for attribute validation in conjunction with getters that return
- * numbers.
- *
- * @method Paginator.isNumeric
- * @param v {Number|String} value to be checked for number or numeric string
- * @returns {Boolean} true if the input is coercable into a finite number
- * @static
- */
- isNumeric : function (v) {
- return isFinite(+v);
- },
- /**
- * Return a number or null from input
- *
- * @method Paginator.toNumber
- * @param n {Number|String} a number or numeric string
- * @return Number
- * @static
- */
- toNumber : function (n) {
- return isFinite(+n) ? +n : null;
- }
- },true);
- // Instance members and methods
- Paginator.prototype = {
- // Instance members
- /**
- * Array of nodes in which to render pagination controls. This is set via
- * the "containers" attribute.
- * @property _containers
- * @type Array(HTMLElement)
- * @private
- */
- _containers : [],
- /**
- * Flag used to indicate multiple attributes are being updated via setState
- * @property _batch
- * @type boolean
- * @protected
- */
- _batch : false,
- /**
- * Used by setState to indicate when a page change has occurred
- * @property _pageChanged
- * @type boolean
- * @protected
- */
- _pageChanged : false,
- /**
- * Temporary state cache used by setState to keep track of the previous
- * state for eventual pageChange event firing
- * @property _state
- * @type Object
- * @protected
- */
- _state : null,
- // Instance methods
- /**
- * Initialize the Paginator's attributes (see YAHOO.util.Element class
- * AttributeProvider).
- * @method initConfig
- * @private
- */
- initConfig : function () {
- var UNLIMITED = Paginator.VALUE_UNLIMITED;
- /**
- * REQUIRED. Number of records constituting a "page"
- * @attribute rowsPerPage
- * @type integer
- */
- this.setAttributeConfig('rowsPerPage', {
- value : 0,
- validator : Paginator.isNumeric,
- setter : Paginator.toNumber
- });
- /**
- * REQUIRED. Node references or ids of nodes in which to render the
- * pagination controls.
- * @attribute containers
- * @type {string|HTMLElement|Array(string|HTMLElement)}
- */
- this.setAttributeConfig('containers', {
- value : null,
- validator : function (val) {
- if (!isArray(val)) {
- val = [val];
- }
- for (var i = 0, len = val.length; i < len; ++i) {
- if (isString(val[i]) ||
- (isObject(val[i]) && val[i].nodeType === 1)) {
- continue;
- }
- return false;
- }
- return true;
- },
- method : function (val) {
- val = Dom.get(val);
- if (!isArray(val)) {
- val = [val];
- }
- this._containers = val;
- }
- });
- /**
- * Total number of records to paginate through
- * @attribute totalRecords
- * @type integer
- * @default 0
- */
- this.setAttributeConfig('totalRecords', {
- value : 0,
- validator : Paginator.isNumeric,
- setter : Paginator.toNumber
- });
- /**
- * Zero based index of the record considered first on the current page.
- * For page based interactions, don't modify this attribute directly;
- * use setPage(n).
- * @attribute recordOffset
- * @type integer
- * @default 0
- */
- this.setAttributeConfig('recordOffset', {
- value : 0,
- validator : function (val) {
- var total = this.get('totalRecords');
- if (Paginator.isNumeric(val)) {
- val = +val;
- return total === UNLIMITED || total > val ||
- (total === 0 && val === 0);
- }
- return false;
- },
- setter : Paginator.toNumber
- });
- /**
- * Page to display on initial paint
- * @attribute initialPage
- * @type integer
- * @default 1
- */
- this.setAttributeConfig('initialPage', {
- value : 1,
- validator : Paginator.isNumeric,
- setter : Paginator.toNumber
- });
- /**
- * Template used to render controls. The string will be used as
- * innerHTML on all specified container nodes. Bracketed keys
- * (e.g. {pageLinks}) in the string will be replaced with an instance
- * of the so named ui component.
- * @see Paginator.TEMPLATE_DEFAULT
- * @see Paginator.TEMPLATE_ROWS_PER_PAGE
- * @attribute template
- * @type string
- */
- this.setAttributeConfig('template', {
- value : Paginator.TEMPLATE_DEFAULT,
- validator : isString
- });
- /**
- * Class assigned to the element(s) containing pagination controls.
- * @attribute containerClass
- * @type string
- * @default 'yui-pg-container'
- */
- this.setAttributeConfig('containerClass', {
- value : 'yui-pg-container',
- validator : isString
- });
- /**
- * Display pagination controls even when there is only one page. Set
- * to false to forgo rendering and/or hide the containers when there
- * is only one page of data. Note if you are using the rowsPerPage
- * dropdown ui component, visibility will be maintained as long as the
- * number of records exceeds the smallest page size.
- * @attribute alwaysVisible
- * @type boolean
- * @default true
- */
- this.setAttributeConfig('alwaysVisible', {
- value : true,
- validator : lang.isBoolean
- });
- /**
- * Update the UI immediately upon interaction. If false, changeRequest
- * subscribers or other external code will need to explicitly set the
- * new values in the paginator to trigger repaint.
- * @attribute updateOnChange
- * @type boolean
- * @default false
- * @deprecated use changeRequest listener that calls setState
- */
- this.setAttributeConfig('updateOnChange', {
- value : false,
- validator : lang.isBoolean
- });
- // Read only attributes
- /**
- * Unique id assigned to this instance
- * @attribute id
- * @type integer
- * @final
- */
- this.setAttributeConfig('id', {
- value : Paginator.id++,
- readOnly : true
- });
- /**
- * Indicator of whether the DOM nodes have been initially created
- * @attribute rendered
- * @type boolean
- * @final
- */
- this.setAttributeConfig('rendered', {
- value : false,
- readOnly : true
- });
- },
- /**
- * Initialize registered ui components onto this instance.
- * @method initUIComponents
- * @private
- */
- initUIComponents : function () {
- var ui = Paginator.ui,
- name,UIComp;
- for (name in ui) {
- if (ui.hasOwnProperty(name)) {
- UIComp = ui[name];
- if (isObject(UIComp) && isFunction(UIComp.init)) {
- UIComp.init(this);
- }
- }
- }
- },
- /**
- * Initialize this instance's CustomEvents.
- * @method initEvents
- * @private
- */
- initEvents : function () {
- /**
- * Event fired when the Paginator is initially rendered
- * @event render
- */
- this.createEvent('render');
- /**
- * Event fired when the Paginator is initially rendered
- * @event rendered
- * @deprecated use render event
- */
- this.createEvent('rendered'); // backward compatibility
- /**
- * Event fired when a change in pagination values is requested,
- * either by interacting with the various ui components or via the
- * setStartIndex(n) etc APIs.
- * Subscribers will receive the proposed state as the first parameter.
- * The proposed state object will contain the following keys:
- * <ul>
- * <li>paginator - the Paginator instance</li>
- * <li>page</li>
- * <li>totalRecords</li>
- * <li>recordOffset - index of the first record on the new page</li>
- * <li>rowsPerPage</li>
- * <li>records - array containing [start index, end index] for the records on the new page</li>
- * <li>before - object literal with all these keys for the current state</li>
- * </ul>
- * @event changeRequest
- */
- this.createEvent('changeRequest');
- /**
- * Event fired when attribute changes have resulted in the calculated
- * current page changing.
- * @event pageChange
- */
- this.createEvent('pageChange');
- /**
- * Event that fires before the destroy event.
- * @event beforeDestroy
- */
- this.createEvent('beforeDestroy');
- /**
- * Event used to trigger cleanup of ui components
- * @event destroy
- */
- this.createEvent('destroy');
- this._selfSubscribe();
- },
- /**
- * Subscribes to instance attribute change events to automate certain
- * behaviors.
- * @method _selfSubscribe
- * @protected
- */
- _selfSubscribe : function () {
- // Listen for changes to totalRecords and alwaysVisible
- this.subscribe('totalRecordsChange',this.updateVisibility,this,true);
- this.subscribe('alwaysVisibleChange',this.updateVisibility,this,true);
- // Fire the pageChange event when appropriate
- this.subscribe('totalRecordsChange',this._handleStateChange,this,true);
- this.subscribe('recordOffsetChange',this._handleStateChange,this,true);
- this.subscribe('rowsPerPageChange',this._handleStateChange,this,true);
- // Update recordOffset when totalRecords is reduced below
- this.subscribe('totalRecordsChange',this._syncRecordOffset,this,true);
- },
- /**
- * Sets recordOffset to the starting index of the previous page when
- * totalRecords is reduced below the current recordOffset.
- * @method _syncRecordOffset
- * @param e {Event} totalRecordsChange event
- * @protected
- */
- _syncRecordOffset : function (e) {
- var v = e.newValue,rpp,state;
- if (e.prevValue !== v) {
- if (v !== Paginator.VALUE_UNLIMITED) {
- rpp = this.get('rowsPerPage');
- if (rpp && this.get('recordOffset') >= v) {
- state = this.getState({
- totalRecords : e.prevValue,
- recordOffset : this.get('recordOffset')
- });
- this.set('recordOffset', state.before.recordOffset);
- this._firePageChange(state);
- }
- }
- }
- },
- /**
- * Fires the pageChange event when the state attributes have changed in
- * such a way as to locate the current recordOffset on a new page.
- * @method _handleStateChange
- * @param e {Event} the attribute change event
- * @protected
- */
- _handleStateChange : function (e) {
- if (e.prevValue !== e.newValue) {
- var change = this._state || {},
- state;
- change[e.type.replace(/Change$/,'')] = e.prevValue;
- state = this.getState(change);
- if (state.page !== state.before.page) {
- if (this._batch) {
- this._pageChanged = true;
- } else {
- this._firePageChange(state);
- }
- }
- }
- },
- /**
- * Fires a pageChange event in the form of a standard attribute change
- * event with additional properties prevState and newState.
- * @method _firePageChange
- * @param state {Object} the result of getState(oldState)
- * @protected
- */
- _firePageChange : function (state) {
- if (isObject(state)) {
- var current = state.before;
- delete state.before;
- this.fireEvent('pageChange',{
- type : 'pageChange',
- prevValue : state.page,
- newValue : current.page,
- prevState : state,
- newState : current
- });
- }
- },
- /**
- * Render the pagination controls per the format attribute into the
- * specified container nodes.
- * @method render
- * @return the Paginator instance
- * @chainable
- */
- render : function () {
- if (this.get('rendered')) {
- return this;
- }
- var template = this.get('template'),
- state = this.getState(),
- // ex. yui-pg0-1 (first paginator, second container)
- id_base = Paginator.ID_BASE + this.get('id') + '-',
- i, len;
- // Assemble the containers, keeping them hidden
- for (i = 0, len = this._containers.length; i < len; ++i) {
- this._renderTemplate(this._containers[i],template,id_base+i,true);
- }
- // Show the containers if appropriate
- this.updateVisibility();
- // Set render attribute manually to support its readOnly contract
- if (this._containers.length) {
- this.setAttributeConfig('rendered', { value: true });
- this.fireEvent('render', state);
- // For backward compatibility
- this.fireEvent('rendered', state);
- }
- return this;
- },
- /**
- * Creates the individual ui components and renders them into a container.
- *
- * @method _renderTemplate
- * @param container {HTMLElement} where to add the ui components
- * @param template {String} the template to use as a guide for rendering
- * @param id_base {String} id base for the container's ui components
- * @param hide {Boolean} leave the container hidden after assembly
- * @protected
- */
- _renderTemplate : function (container, template, id_base, hide) {
- var containerClass = this.get('containerClass'),
- markers, i, len;
- if (!container) {
- return;
- }
- // Hide the container while its contents are rendered
- Dom.setStyle(container,'display','none');
- Dom.addClass(container, containerClass);
- // Place the template innerHTML, adding marker spans to the template
- // html to indicate drop zones for ui components
- container.innerHTML = template.replace(/\{([a-z0-9_ \-]+)\}/gi,
- '<span class="yui-pg-ui yui-pg-ui-$1"></span>');
- // Replace each marker with the ui component's render() output
- markers = Dom.getElementsByClassName('yui-pg-ui','span',container);
- for (i = 0, len = markers.length; i < len; ++i) {
- this.renderUIComponent(markers[i], id_base);
- }
- if (!hide) {
- // Show the container allowing page reflow
- Dom.setStyle(container,'display','');
- }
- },
- /**
- * Replaces a marker node with a rendered UI component, determined by the
- * yui-pg-ui-(UI component class name) in the marker's className. e.g.
- * yui-pg-ui-PageLinks => new YAHOO.widget.Paginator.ui.PageLinks(this)
- *
- * @method renderUIComponent
- * @param marker {HTMLElement} the marker node to replace
- * @param id_base {String} string base the component's generated id
- */
- renderUIComponent : function (marker, id_base) {
- var par = marker.parentNode,
- name = /yui-pg-ui-(\w+)/.exec(marker.className),
- UIComp = name && Paginator.ui[name[1]],
- comp;
- if (isFunction(UIComp)) {
- comp = new UIComp(this);
- if (isFunction(comp.render)) {
- par.replaceChild(comp.render(id_base),marker);
- }
- }
- },
- /**
- * Removes controls from the page and unhooks events.
- * @method destroy
- */
- destroy : function () {
- this.fireEvent('beforeDestroy');
- this.fireEvent('destroy');
- this.setAttributeConfig('rendered',{value:false});
- this.unsubscribeAll();
- },
- /**
- * Hides the containers if there is only one page of data and attribute
- * alwaysVisible is false. Conversely, it displays the containers if either
- * there is more than one page worth of data or alwaysVisible is turned on.
- * @method updateVisibility
- */
- updateVisibility : function (e) {
- var alwaysVisible = this.get('alwaysVisible'),
- totalRecords,visible,rpp,rppOptions,i,len;
- if (!e || e.type === 'alwaysVisibleChange' || !alwaysVisible) {
- totalRecords = this.get('totalRecords');
- visible = true;
- rpp = this.get('rowsPerPage');
- rppOptions = this.get('rowsPerPageOptions');
- if (isArray(rppOptions)) {
- for (i = 0, len = rppOptions.length; i < len; ++i) {
- rpp = Math.min(rpp,rppOptions[i]);
- }
- }
- if (totalRecords !== Paginator.VALUE_UNLIMITED &&
- totalRecords <= rpp) {
- visible = false;
- }
- visible = visible || alwaysVisible;
- for (i = 0, len = this._containers.length; i < len; ++i) {
- Dom.setStyle(this._containers[i],'display',
- visible ? '' : 'none');
- }
- }
- },
- /**
- * Get the configured container nodes
- * @method getContainerNodes
- * @return {Array} array of HTMLElement nodes
- */
- getContainerNodes : function () {
- return this._containers;
- },
- /**
- * Get the total number of pages in the data set according to the current
- * rowsPerPage and totalRecords values. If totalRecords is not set, or
- * set to YAHOO.widget.Paginator.VALUE_UNLIMITED, returns
- * YAHOO.widget.Paginator.VALUE_UNLIMITED.
- * @method getTotalPages
- * @return {number}
- */
- getTotalPages : function () {
- var records = this.get('totalRecords'),
- perPage = this.get('rowsPerPage');
- // rowsPerPage not set. Can't calculate
- if (!perPage) {
- return null;
- }
- if (records === Paginator.VALUE_UNLIMITED) {
- return Paginator.VALUE_UNLIMITED;
- }
- return Math.ceil(records/perPage);
- },
- /**
- * Does the requested page have any records?
- * @method hasPage
- * @param page {number} the page in question
- * @return {boolean}
- */
- hasPage : function (page) {
- if (!lang.isNumber(page) || page < 1) {
- return false;
- }
- var totalPages = this.getTotalPages();
- return (totalPages === Paginator.VALUE_UNLIMITED || totalPages >= page);
- },
- /**
- * Get the page number corresponding to the current record offset.
- * @method getCurrentPage
- * @return {number}
- */
- getCurrentPage : function () {
- var perPage = this.get('rowsPerPage');
- if (!perPage || !this.get('totalRecords')) {
- return 0;
- }
- return Math.floor(this.get('recordOffset') / perPage) + 1;
- },
- /**
- * Are there records on the next page?
- * @method hasNextPage
- * @return {boolean}
- */
- hasNextPage : function () {
- var currentPage = this.getCurrentPage(),
- totalPages = this.getTotalPages();
- return currentPage && (totalPages === Paginator.VALUE_UNLIMITED || currentPage < totalPages);
- },
- /**
- * Get the page number of the next page, or null if the current page is the
- * last page.
- * @method getNextPage
- * @return {number}
- */
- getNextPage : function () {
- return this.hasNextPage() ? this.getCurrentPage() + 1 : null;
- },
- /**
- * Is there a page before the current page?
- * @method hasPreviousPage
- * @return {boolean}
- */
- hasPreviousPage : function () {
- return (this.getCurrentPage() > 1);
- },
- /**
- * Get the page number of the previous page, or null if the current page
- * is the first page.
- * @method getPreviousPage
- * @return {number}
- */
- getPreviousPage : function () {
- return (this.hasPreviousPage() ? this.getCurrentPage() - 1 : 1);
- },
- /**
- * Get the start and end record indexes of the specified page.
- * @method getPageRecords
- * @param page {number} (optional) The page (current page if not specified)
- * @return {Array} [start_index, end_index]
- */
- getPageRecords : function (page) {
- if (!lang.isNumber(page)) {
- page = this.getCurrentPage();
- }
- var perPage = this.get('rowsPerPage'),
- records = this.get('totalRecords'),
- start, end;
- if (!page || !perPage) {
- return null;
- }
- start = (page - 1) * perPage;
- if (records !== Paginator.VALUE_UNLIMITED) {
- if (start >= records) {
- return null;
- }
- end = Math.min(start + perPage, records) - 1;
- } else {
- end = start + perPage - 1;
- }
- return [start,end];
- },
- /**
- * Set the current page to the provided page number if possible.
- * @method setPage
- * @param newPage {number} the new page number
- * @param silent {boolean} whether to forcibly avoid firing the
- * changeRequest event
- */
- setPage : function (page,silent) {
- if (this.hasPage(page) && page !== this.getCurrentPage()) {
- if (this.get('updateOnChange') || silent) {
- this.set('recordOffset', (page - 1) * this.get('rowsPerPage'));
- } else {
- this.fireEvent('changeRequest',this.getState({'page':page}));
- }
- }
- },
- /**
- * Get the number of rows per page.
- * @method getRowsPerPage
- * @return {number} the current setting of the rowsPerPage attribute
- */
- getRowsPerPage : function () {
- return this.get('rowsPerPage');
- },
- /**
- * Set the number of rows per page.
- * @method setRowsPerPage
- * @param rpp {number} the new number of rows per page
- * @param silent {boolean} whether to forcibly avoid firing the
- * changeRequest event
- */
- setRowsPerPage : function (rpp,silent) {
- if (Paginator.isNumeric(rpp) && +rpp > 0 &&
- +rpp !== this.get('rowsPerPage')) {
- if (this.get('updateOnChange') || silent) {
- this.set('rowsPerPage',rpp);
- } else {
- this.fireEvent('changeRequest',
- this.getState({'rowsPerPage':+rpp}));
- }
- }
- },
- /**
- * Get the total number of records.
- * @method getTotalRecords
- * @return {number} the current setting of totalRecords attribute
- */
- getTotalRecords : function () {
- return this.get('totalRecords');
- },
- /**
- * Set the total number of records.
- * @method setTotalRecords
- * @param total {number} the new total number of records
- * @param silent {boolean} whether to forcibly avoid firing the changeRequest event
- */
- setTotalRecords : function (total,silent) {
- if (Paginator.isNumeric(total) && +total >= 0 &&
- +total !== this.get('totalRecords')) {
- if (this.get('updateOnChange') || silent) {
- this.set('totalRecords',total);
- } else {
- this.fireEvent('changeRequest',
- this.getState({'totalRecords':+total}));
- }
- }
- },
- /**
- * Get the index of the first record on the current page
- * @method getStartIndex
- * @return {number} the index of the first record on the current page
- */
- getStartIndex : function () {
- return this.get('recordOffset');
- },
- /**
- * Move the record offset to a new starting index. This will likely cause
- * the calculated current page to change. You should probably use setPage.
- * @method setStartIndex
- * @param offset {number} the new record offset
- * @param silent {boolean} whether to forcibly avoid firing the changeRequest event
- */
- setStartIndex : function (offset,silent) {
- if (Paginator.isNumeric(offset) && +offset >= 0 &&
- +offset !== this.get('recordOffset')) {
- if (this.get('updateOnChange') || silent) {
- this.set('recordOffset',offset);
- } else {
- this.fireEvent('changeRequest',
- this.getState({'recordOffset':+offset}));
- }
- }
- },
- /**
- * Get an object literal describing the current state of the paginator. If
- * an object literal of proposed values is passed, the proposed state will
- * be returned as an object literal with the following keys:
- * <ul>
- * <li>paginator - instance of the Paginator</li>
- * <li>page - number</li>
- * <li>totalRecords - number</li>
- * <li>recordOffset - number</li>
- * <li>rowsPerPage - number</li>
- * <li>records - [ start_index, end_index ]</li>
- * <li>before - (OPTIONAL) { state object literal for current state }</li>
- * </ul>
- * @method getState
- * @return {object}
- * @param changes {object} OPTIONAL object literal with proposed values
- * Supported change keys include:
- * <ul>
- * <li>rowsPerPage</li>
- * <li>totalRecords</li>
- * <li>recordOffset OR</li>
- * <li>page</li>
- * </ul>
- */
- getState : function (changes) {
- var UNLIMITED = Paginator.VALUE_UNLIMITED,
- M = Math, max = M.max, ceil = M.ceil,
- currentState, state, offset;
- function normalizeOffset(offset,total,rpp) {
- if (offset <= 0 || total === 0) {
- return 0;
- }
- if (total === UNLIMITED || total > offset) {
- return offset - (offset % rpp);
- }
- return total - (total % rpp || rpp);
- }
- currentState = {
- paginator : this,
- totalRecords : this.get('totalRecords'),
- rowsPerPage : this.get('rowsPerPage'),
- records : this.getPageRecords()
- };
- currentState.recordOffset = normalizeOffset(
- this.get('recordOffset'),
- currentState.totalRecords,
- currentState.rowsPerPage);
- currentState.page = ceil(currentState.recordOffset /
- currentState.rowsPerPage) + 1;
- if (!changes) {
- return currentState;
- }
- state = {
- paginator : this,
- before : currentState,
- rowsPerPage : changes.rowsPerPage || currentState.rowsPerPage,
- totalRecords : (Paginator.isNumeric(changes.totalRecords) ?
- max(changes.totalRecords,UNLIMITED) :
- +currentState.totalRecords)
- };
- if (state.totalRecords === 0) {
- state.recordOffset =
- state.page = 0;
- } else {
- offset = Paginator.isNumeric(changes.page) ?
- (changes.page - 1) * state.rowsPerPage :
- Paginator.isNumeric(changes.recordOffset) ?
- +changes.recordOffset :
- currentState.recordOffset;
- state.recordOffset = normalizeOffset(offset,
- state.totalRecords,
- state.rowsPerPage);
- state.page = ceil(state.recordOffset / state.rowsPerPage) + 1;
- }
- state.records = [ state.recordOffset,
- state.recordOffset + state.rowsPerPage - 1 ];
- // limit upper index to totalRecords - 1
- if (state.totalRecords !== UNLIMITED &&
- state.recordOffset < state.totalRecords && state.records &&
- state.records[1] > state.totalRecords - 1) {
- state.records[1] = state.totalRecords - 1;
- }
- return state;
- },
- /**
- * Convenience method to facilitate setting state attributes rowsPerPage,
- * totalRecords, recordOffset in batch. Also supports calculating
- * recordOffset from state.page if state.recordOffset is not provided.
- * Fires only a single pageChange event, if appropriate.
- * This will not fire a changeRequest event.
- * @method setState
- * @param state {Object} Object literal of attribute:value pairs to set
- */
- setState : function (state) {
- if (isObject(state)) {
- // get flux state based on current state with before state as well
- this._state = this.getState({});
- // use just the state props from the input obj
- state = {
- page : state.page,
- rowsPerPage : state.rowsPerPage,
- totalRecords : state.totalRecords,
- recordOffset : state.recordOffset
- };
- // calculate recordOffset from page if recordOffset not specified.
- // not using lang.isNumber for support of numeric strings
- if (state.page && state.recordOffset === undefined) {
- state.recordOffset = (state.page - 1) *
- (state.rowsPerPage || this.get('rowsPerPage'));
- }
- this._batch = true;
- this._pageChanged = false;
- for (var k in state) {
- if (state.hasOwnProperty(k) && this._configs.hasOwnProperty(k)) {
- this.set(k,state[k]);
- }
- }
- this._batch = false;
-
- if (this._pageChanged) {
- this._pageChanged = false;
- this._firePageChange(this.getState(this._state));
- }
- }
- }
- };
- lang.augmentProto(Paginator, YAHOO.util.AttributeProvider);
- YAHOO.widget.Paginator = Paginator;
- })();
- (function () {
- var Paginator = YAHOO.widget.Paginator,
- l = YAHOO.lang;
- /**
- * ui Component to generate the textual report of current pagination status.
- * E.g. "Now viewing page 1 of 13".
- *
- * @namespace YAHOO.widget.Paginator.ui
- * @class CurrentPageReport
- * @for YAHOO.widget.Paginator
- *
- * @constructor
- * @param p {Pagintor} Paginator instance to attach to
- */
- Paginator.ui.CurrentPageReport = function (p) {
- this.paginator = p;
- p.subscribe('recordOffsetChange', this.update,this,true);
- p.subscribe('rowsPerPageChange', this.update,this,true);
- p.subscribe('totalRecordsChange',this.update,this,true);
- p.subscribe('pageReportTemplateChange', this.update,this,true);
- p.subscribe('destroy',this.destroy,this,true);
- //TODO: make this work
- p.subscribe('pageReportClassChange', this.update,this,true);
- };
- /**
- * Decorates Paginator instances with new attributes. Called during
- * Paginator instantiation.
- * @method init
- * @param p {Paginator} Paginator instance to decorate
- * @static
- */
- Paginator.ui.CurrentPageReport.init = function (p) {
- /**
- * CSS class assigned to the span containing the info.
- * @attribute pageReportClass
- * @default 'yui-pg-current'
- */
- p.setAttributeConfig('pageReportClass', {
- value : 'yui-pg-current',
- validator : l.isString
- });
- /**
- * Used as innerHTML for the span. Place holders in the form of {name}
- * will be replaced with the so named value from the key:value map
- * generated by the function held in the pageReportValueGenerator attribute.
- * @attribute pageReportTemplate
- * @default '({currentPage} of {totalPages})'
- * @see pageReportValueGenerator attribute
- */
- p.setAttributeConfig('pageReportTemplate', {
- value : '({currentPage} of {totalPages})',
- validator : l.isString
- });
- /**
- * Function to generate the value map used to populate the
- * pageReportTemplate. The function is passed the Paginator instance as a
- * parameter. The default function returns a map with the following keys:
- * <ul>
- * <li>currentPage</li>
- * <li>totalPages</li>
- * <li>startIndex</li>
- * <li>endIndex</li>
- * <li>startRecord</li>
- * <li>endRecord</li>
- * <li>totalRecords</li>
- * </ul>
- * @attribute pageReportValueGenarator
- */
- p.setAttributeConfig('pageReportValueGenerator', {
- value : function (paginator) {
- var curPage = paginator.getCurrentPage(),
- records = paginator.getPageRecords();
- return {
- 'currentPage' : records ? curPage : 0,
- 'totalPages' : paginator.getTotalPages(),
- 'startIndex' : records ? records[0] : 0,
- 'endIndex' : records ? records[1] : 0,
- 'startRecord' : records ? records[0] + 1 : 0,
- 'endRecord' : records ? records[1] + 1 : 0,
- 'totalRecords': paginator.get('totalRecords')
- };
- },
- validator : l.isFunction
- });
- };
- /**
- * Replace place holders in a string with the named values found in an
- * object literal.
- * @static
- * @method sprintf
- * @param template {string} The content string containing place holders
- * @param values {object} The key:value pairs used to replace the place holders
- * @return {string}
- */
- Paginator.ui.CurrentPageReport.sprintf = function (template, values) {
- return template.replace(/\{([\w\s\-]+)\}/g, function (x,key) {
- return (key in values) ? values[key] : '';
- });
- };
- Paginator.ui.CurrentPageReport.prototype = {
- /**
- * Span node containing the formatted info
- * @property span
- * @type HTMLElement
- * @private
- */
- span : null,
- /**
- * Generate the span containing info formatted per the pageReportTemplate
- * attribute.
- * @method render
- * @param id_base {string} used to create unique ids for generated nodes
- * @return {HTMLElement}
- */
- render : function (id_base) {
- this.span = document.createElement('span');
- this.span.id = id_base + '-page-report';
- this.span.className = this.paginator.get('pageReportClass');
- this.update();
-
- return this.span;
- },
-
- /**
- * Regenerate the content of the span if appropriate. Calls
- * CurrentPageReport.sprintf with the value of the pageReportTemplate
- * attribute and the value map returned from pageReportValueGenerator
- * function.
- * @method update
- * @param e {CustomEvent} The calling change event
- */
- update : function (e) {
- if (e && e.prevValue === e.newValue) {
- return;
- }
- this.span.innerHTML = Paginator.ui.CurrentPageReport.sprintf(
- this.paginator.get('pageReportTemplate'),
- this.paginator.get('pageReportValueGenerator')(this.paginator));
- },
- /**
- * Removes the link/span node and clears event listeners
- * removal.
- * @method destroy
- * @private
- */
- destroy : function () {
- this.span.parentNode.removeChild(this.span);
- this.span = null;
- }
- };
- })();
- (function () {
- var Paginator = YAHOO.widget.Paginator,
- l = YAHOO.lang;
- /**
- * ui Component to generate the page links
- *
- * @namespace YAHOO.widget.Paginator.ui
- * @class PageLinks
- * @for YAHOO.widget.Paginator
- *
- * @constructor
- * @param p {Pagintor} Paginator instance to attach to
- */
- Paginator.ui.PageLinks = function (p) {
- this.paginator = p;
- p.subscribe('recordOffsetChange',this.update,this,true);
- p.subscribe('rowsPerPageChange',this.update,this,true);
- p.subscribe('totalRecordsChange',this.update,this,true);
- p.subscribe('pageLinksChange', this.rebuild,this,true);
- p.subscribe('pageLinkClassChange', this.rebuild,this,true);
- p.subscribe('currentPageClassChange', this.rebuild,this,true);
- p.subscribe('destroy',this.destroy,this,true);
- //TODO: Make this work
- p.subscribe('pageLinksContainerClassChange', this.rebuild,this,true);
- };
- /**
- * Decorates Paginator instances with new attributes. Called during
- * Paginator instantiation.
- * @method init
- * @param p {Paginator} Paginator instance to decorate
- * @static
- */
- Paginator.ui.PageLinks.init = function (p) {
- /**
- * CSS class assigned to each page link/span.
- * @attribute pageLinkClass
- * @default 'yui-pg-page'
- */
- p.setAttributeConfig('pageLinkClass', {
- value : 'yui-pg-page',
- validator : l.isString
- });
- /**
- * CSS class assigned to the current page span.
- * @attribute currentPageClass
- * @default 'yui-pg-current-page'
- */
- p.setAttributeConfig('currentPageClass', {
- value : 'yui-pg-current-page',
- validator : l.isString
- });
- /**
- * CSS class assigned to the span containing the page links.
- * @attribute pageLinksContainerClass
- * @default 'yui-pg-pages'
- */
- p.setAttributeConfig('pageLinksContainerClass', {
- value : 'yui-pg-pages',
- validator : l.isString
- });
- /**
- * Maximum number of page links to display at one time.
- * @attribute pageLinks
- * @default 10
- */
- p.setAttributeConfig('pageLinks', {
- value : 10,
- validator : Paginator.isNumeric
- });
- /**
- * Function used generate the innerHTML for each page link/span. The
- * function receives as parameters the page number and a reference to the
- * paginator object.
- * @attribute pageLabelBuilder
- * @default function (page, paginator) { return page; }
- */
- p.setAttributeConfig('pageLabelBuilder', {
- value : function (page, paginator) { return page; },
- validator : l.isFunction
- });
- };
- /**
- * Calculates start and end page numbers given a current page, attempting
- * to keep the current page in the middle
- * @static
- * @method calculateRange
- * @param {int} currentPage The current page
- * @param {int} totalPages (optional) Maximum number of pages
- * @param {int} numPages (optional) Preferred number of pages in range
- * @return {Array} [start_page_number, end_page_number]
- */
- Paginator.ui.PageLinks.calculateRange = function (currentPage,totalPages,numPages) {
- var UNLIMITED = Paginator.VALUE_UNLIMITED,
- start, end, delta;
- // Either has no pages, or unlimited pages. Show none.
- if (!currentPage || numPages === 0 || totalPages === 0 ||
- (totalPages === UNLIMITED && numPages === UNLIMITED)) {
- return [0,-1];
- }
- // Limit requested pageLinks if there are fewer totalPages
- if (totalPages !== UNLIMITED) {
- numPages = numPages === UNLIMITED ?
- totalPages :
- Math.min(numPages,totalPages);
- }
- // Determine start and end, trying to keep current in the middle
- start = Math.max(1,Math.ceil(currentPage - (numPages/2)));
- if (totalPages === UNLIMITED) {
- end = start + numPages - 1;
- } else {
- end = Math.min(totalPages, start + numPages - 1);
- }
- // Adjust the start index when approaching the last page
- delta = numPages - (end - start + 1);
- start = Math.max(1, start - delta);
- return [start,end];
- };
- Paginator.ui.PageLinks.prototype = {
- /**
- * Current page
- * @property current
- * @type number
- * @private
- */
- current : 0,
- /**
- * Span node containing the page links
- * @property container
- * @type HTMLElement
- * @private
- */
- container : null,
- /**
- * Generate the nodes and return the container node containing page links
- * appropriate to the current pagination state.
- * @method render
- * @param id_base {string} used to create unique ids for generated nodes
- * @return {HTMLElement}
- */
- render : function (id_base) {
- var p = this.paginator;
- // Set up container
- this.container = document.createElement('span');
- this.container.id = id_base + '-pages';
- this.container.className = p.get('pageLinksContainerClass');
- YAHOO.util.Event.on(this.container,'click',this.onClick,this,true);
- // Call update, flagging a need to rebuild
- this.update({newValue : null, rebuild : true});
- return this.container;
- },
- /**
- * Update the links if appropriate
- * @method update
- * @param e {CustomEvent} The calling change event
- */
- update : function (e) {
- if (e && e.prevValue === e.newValue) {
- return;
- }
- var p = this.paginator,
- currentPage = p.getCurrentPage();
- // Replace content if there's been a change
- if (this.current !== currentPage || !currentPage || e.rebuild) {
- var labelBuilder = p.get('pageLabelBuilder'),
- range = Paginator.ui.PageLinks.calculateRange(
- currentPage,
- p.getTotalPages(),
- p.get('pageLinks')),
- start = range[0],
- end = range[1],
- content = '',
- linkTemplate,i;
- linkTemplate = '<a href="#" class="' + p.get('pageLinkClass') +
- '" page="';
- for (i = start; i <= end; ++i) {
- if (i === currentPage) {
- content +=
- '<span class="' + p.get('currentPageClass') + ' ' +
- p.get('pageLinkClass') + '">' +
- labelBuilder(i,p) + '</span>';
- } else {
- content +=
- linkTemplate + i + '">' + labelBuilder(i,p) + '</a>';
- }
- }
- this.container.innerHTML = content;
- }
- },
- /**
- * Force a rebuild of the page links.
- * @method rebuild
- * @param e {CustomEvent} The calling change event
- */
- rebuild : function (e) {
- e.rebuild = true;
- this.update(e);
- },
- /**
- * Removes the page links container node and clears event listeners
- * @method destroy
- * @private
- */
- destroy : function () {
- YAHOO.util.Event.purgeElement(this.container,true);
- this.container.parentNode.removeChild(this.container);
- this.container = null;
- },
- /**
- * Listener for the container's onclick event. Looks for qualifying link
- * clicks, and pulls the page number from the link's page attribute.
- * Sends link's page attribute to the Paginator's setPage method.
- * @method onClick
- * @param e {DOMEvent} The click event
- */
- onClick : function (e) {
- var t = YAHOO.util.Event.getTarget(e);
- if (t && YAHOO.util.Dom.hasClass(t,
- this.paginator.get('pageLinkClass'))) {
- YAHOO.util.Event.stopEvent(e);
- this.paginator.setPage(parseInt(t.getAttribute('page'),10));
- }
- }
- };
- })();
- (function () {
- var Paginator = YAHOO.widget.Paginator,
- l = YAHOO.lang;
- /**
- * ui Component to generate the link to jump to the first page.
- *
- * @namespace YAHOO.widget.Paginator.ui
- * @class FirstPageLink
- * @for YAHOO.widget.Paginator
- *
- * @constructor
- * @param p {Pagintor} Paginator instance to attach to
- */
- Paginator.ui.FirstPageLink = function (p) {
- this.paginator = p;
- p.subscribe('recordOffsetChange',this.update,this,true);
- p.subscribe('rowsPerPageChange',this.update,this,true);
- p.subscribe('totalRecordsChange',this.update,this,true);
- p.subscribe('destroy',this.destroy,this,true);
- // TODO: make this work
- p.subscribe('firstPageLinkLabelChange',this.update,this,true);
- p.subscribe('firstPageLinkClassChange',this.update,this,true);
- };
- /**
- * Decorates Paginator instances with new attributes. Called during
- * Paginator instantiation.
- * @method init
- * @param p {Paginator} Paginator instance to decorate
- * @static
- */
- Paginator.ui.FirstPageLink.init = function (p) {
- /**
- * Used as innerHTML for the first page link/span.
- * @attribute firstPageLinkLabel
- * @default '<< first'
- */
- p.setAttributeConfig('firstPageLinkLabel', {
- value : '<< first',
- validator : l.isString
- });
- /**
- * CSS class assigned to the link/span
- * @attribute firstPageLinkClass
- * @default 'yui-pg-first'
- */
- p.setAttributeConfig('firstPageLinkClass', {
- value : 'yui-pg-first',
- validator : l.isString
- });
- };
- // Instance members and methods
- Paginator.ui.FirstPageLink.prototype = {
- /**
- * The currently placed HTMLElement node
- * @property current
- * @type HTMLElement
- * @private
- */
- current : null,
- /**
- * Link node
- * @property link
- * @type HTMLElement
- * @private
- */
- link : null,
- /**
- * Span node (inactive link)
- * @property span
- * @type HTMLElement
- * @private
- */
- span : null,
- /**
- * Generate the nodes and return the appropriate node given the current
- * pagination state.
- * @method render
- * @param id_base {string} used to create unique ids for generated nodes
- * @return {HTMLElement}
- */
- render : function (id_base) {
- var p = this.paginator,
- c = p.get('firstPageLinkClass'),
- label = p.get('firstPageLinkLabel');
- this.link = document.createElement('a');
- this.span = document.createElement('span');
- this.link.id = id_base + '-first-link';
- this.link.href = '#';
- this.link.className = c;
- this.link.innerHTML = label;
- YAHOO.util.Event.on(this.link,'click',this.onClick,this,true);
- this.span.id = id_base + '-first-span';
- this.span.className = c;
- this.span.innerHTML = label;
- this.current = p.getCurrentPage() > 1 ? this.link : this.span;
- return this.current;
- },
- /**
- * Swap the link and span nodes if appropriate.
- * @method update
- * @param e {CustomEvent} The calling change event
- */
- update : function (e) {
- if (e && e.prevValue === e.newValue) {
- return;
- }
- var par = this.current ? this.current.parentNode : null;
- if (this.paginator.getCurrentPage() > 1) {
- if (par && this.current === this.span) {
- par.replaceChild(this.link,this.current);
- this.current = this.link;
- }
- } else {
- if (par && this.current === this.link) {
- par.replaceChild(this.span,this.current);
- this.current = this.span;
- }
- }
- },
- /**
- * Removes the link/span node and clears event listeners
- * removal.
- * @method destroy
- * @private
- */
- destroy : function () {
- YAHOO.util.Event.purgeElement(this.link);
- this.current.parentNode.removeChild(this.current);
- this.link = this.span = null;
- },
- /**
- * Listener for the link's onclick event. Pass new value to setPage method.
- * @method onClick
- * @param e {DOMEvent} The click event
- */
- onClick : function (e) {
- YAHOO.util.Event.stopEvent(e);
- this.paginator.setPage(1);
- }
- };
- })();
- (function () {
- var Paginator = YAHOO.widget.Paginator,
- l = YAHOO.lang;
- /**
- * ui Component to generate the link to jump to the last page.
- *
- * @namespace YAHOO.widget.Paginator.ui
- * @class LastPageLink
- * @for YAHOO.widget.Paginator
- *
- * @constructor
- * @param p {Pagintor} Paginator instance to attach to
- */
- Paginator.ui.LastPageLink = function (p) {
- this.paginator = p;
- p.subscribe('recordOffsetChange',this.update,this,true);
- p.subscribe('rowsPerPageChange',this.update,this,true);
- p.subscribe('totalRecordsChange',this.update,this,true);
- p.subscribe('destroy',this.destroy,this,true);
- // TODO: make this work
- p.subscribe('lastPageLinkLabelChange',this.update,this,true);
- p.subscribe('lastPageLinkClassChange', this.update,this,true);
- };
- /**
- * Decorates Paginator instances with new attributes. Called during
- * Paginator instantiation.
- * @method init
- * @param paginator {Paginator} Paginator instance to decorate
- * @static
- */
- Paginator.ui.LastPageLink.init = function (p) {
- /**
- * Used as innerHTML for the last page link/span.
- * @attribute lastPageLinkLabel
- * @default 'last >>'
- */
- p.setAttributeConfig('lastPageLinkLabel', {
- value : 'last >>',
- validator : l.isString
- });
- /**
- * CSS class assigned to the link/span
- * @attribute lastPageLinkClass
- * @default 'yui-pg-last'
- */
- p.setAttributeConfig('lastPageLinkClass', {
- value : 'yui-pg-last',
- validator : l.isString
- });
- };
- Paginator.ui.LastPageLink.prototype = {
- /**
- * Currently placed HTMLElement node
- * @property current
- * @type HTMLElement
- * @private
- */
- current : null,
- /**
- * Link HTMLElement node
- * @property link
- * @type HTMLElement
- * @private
- */
- link : null,
- /**
- * Span node (inactive link)
- * @property span
- * @type HTMLElement
- * @private
- */
- span : null,
- /**
- * Empty place holder node for when the last page link is inappropriate to
- * display in any form (unlimited paging).
- * @property na
- * @type HTMLElement
- * @private
- */
- na : null,
- /**
- * Generate the nodes and return the appropriate node given the current
- * pagination state.
- * @method render
- * @param id_base {string} used to create unique ids for generated nodes
- * @return {HTMLElement}
- */
- render : function (id_base) {
- var p = this.paginator,
- c = p.get('lastPageLinkClass'),
- label = p.get('lastPageLinkLabel'),
- last = p.getTotalPages();
- this.link = document.createElement('a');
- this.span = document.createElement('span');
- this.na = this.span.cloneNode(false);
- this.link.id = id_base + '-last-link';
- this.link.href = '#';
- this.link.className = c;
- this.link.innerHTML = label;
- YAHOO.util.Event.on(this.link,'click',this.onClick,this,true);
- this.span.id = id_base + '-last-span';
- this.span.className = c;
- this.span.innerHTML = label;
- this.na.id = id_base + '-last-na';
- switch (last) {
- case Paginator.VALUE_UNLIMITED :
- this.current = this.na; break;
- case p.getCurrentPage() :
- this.current = this.span; break;
- default :
- this.current = this.link;
- }
- return this.current;
- },
- /**
- * Swap the link, span, and na nodes if appropriate.
- * @method update
- * @param e {CustomEvent} The calling change event (ignored)
- */
- update : function (e) {
- if (e && e.prevValue === e.newValue) {
- return;
- }
- var par = this.current ? this.current.parentNode : null,
- after = this.link;
- if (par) {
- switch (this.paginator.getTotalPages()) {
- case Paginator.VALUE_UNLIMITED :
- after = this.na; break;
- case this.paginator.getCurrentPage() :
- after = this.span; break;
- }
- if (this.current !== after) {
- par.replaceChild(after,this.current);
- this.current = after;
- }
- }
- },
- /**
- * Removes the link/span node and clears event listeners
- * @method destroy
- * @private
- */
- destroy : function () {
- YAHOO.util.Event.purgeElement(this.link);
- this.current.parentNode.removeChild(this.current);
- this.link = this.span = null;
- },
- /**
- * Listener for the link's onclick event. Passes to setPage method.
- * @method onClick
- * @param e {DOMEvent} The click event
- */
- onClick : function (e) {
- YAHOO.util.Event.stopEvent(e);
- this.paginator.setPage(this.paginator.getTotalPages());
- }
- };
- })();
- (function () {
- var Paginator = YAHOO.widget.Paginator,
- l = YAHOO.lang;
- /**
- * ui Component to generate the link to jump to the next page.
- *
- * @namespace YAHOO.widget.Paginator.ui
- * @class NextPageLink
- * @for YAHOO.widget.Paginator
- *
- * @constructor
- * @param p {Pagintor} Paginator instance to attach to
- */
- Paginator.ui.NextPageLink = function (p) {
- this.paginator = p;
- p.subscribe('recordOffsetChange', this.update,this,true);
- p.subscribe('rowsPerPageChange', this.update,this,true);
- p.subscribe('totalRecordsChange', this.update,this,true);
- p.subscribe('destroy',this.destroy,this,true);
- // TODO: make this work
- p.subscribe('nextPageLinkLabelChange', this.update,this,true);
- p.subscribe('nextPageLinkClassChange', this.update,this,true);
- };
- /**
- * Decorates Paginator instances with new attributes. Called during
- * Paginator instantiation.
- * @method init
- * @param p {Paginator} Paginator instance to decorate
- * @static
- */
- Paginator.ui.NextPageLink.init = function (p) {
- /**
- * Used as innerHTML for the next page link/span.
- * @attribute nextPageLinkLabel
- * @default 'next >'
- */
- p.setAttributeConfig('nextPageLinkLabel', {
- value : 'next >',
- validator : l.isString
- });
- /**
- * CSS class assigned to the link/span
- * @attribute nextPageLinkClass
- * @default 'yui-pg-next'
- */
- p.setAttributeConfig('nextPageLinkClass', {
- value : 'yui-pg-next',
- validator : l.isString
- });
- };
- Paginator.ui.NextPageLink.prototype = {
- /**
- * Currently placed HTMLElement node
- * @property current
- * @type HTMLElement
- * @private
- */
- current : null,
- /**
- * Link node
- * @property link
- * @type HTMLElement
- * @private
- */
- link : null,
- /**
- * Span node (inactive link)
- * @property span
- * @type HTMLElement
- * @private
- */
- span : null,
- /**
- * Generate the nodes and return the appropriate node given the current
- * pagination state.
- * @method render
- * @param id_base {string} used to create unique ids for generated nodes
- * @return {HTMLElement}
- */
- render : function (id_base) {
- var p = this.paginator,
- c = p.get('nextPageLinkClass'),
- label = p.get('nextPageLinkLabel'),
- last = p.getTotalPages();
- this.link = document.createElement('a');
- this.span = document.createElement('span');
- this.link.id = id_base + '-next-link';
- this.link.href = '#';
- this.link.className = c;
- this.link.innerHTML = label;
- YAHOO.util.Event.on(this.link,'click',this.onClick,this,true);
- this.span.id = id_base + '-next-span';
- this.span.className = c;
- this.span.innerHTML = label;
- this.current = p.getCurrentPage() === last ? this.span : this.link;
- return this.current;
- },
- /**
- * Swap the link and span nodes if appropriate.
- * @method update
- * @param e {CustomEvent} The calling change event
- */
- update : function (e) {
- if (e && e.prevValue === e.newValue) {
- return;
- }
- var last = this.paginator.getTotalPages(),
- par = this.current ? this.current.parentNode : null;
- if (this.paginator.getCurrentPage() !== last) {
- if (par && this.current === this.span) {
- par.replaceChild(this.link,this.current);
- this.current = this.link;
- }
- } else if (this.current === this.link) {
- if (par) {
- par.replaceChild(this.span,this.current);
- this.current = this.span;
- }
- }
- },
- /**
- * Removes the link/span node and clears event listeners
- * @method destroy
- * @private
- */
- destroy : function () {
- YAHOO.util.Event.purgeElement(this.link);
- this.current.parentNode.removeChild(this.current);
- this.link = this.span = null;
- },
- /**
- * Listener for the link's onclick event. Passes to setPage method.
- * @method onClick
- * @param e {DOMEvent} The click event
- */
- onClick : function (e) {
- YAHOO.util.Event.stopEvent(e);
- this.paginator.setPage(this.paginator.getNextPage());
- }
- };
- })();
- (function () {
- var Paginator = YAHOO.widget.Paginator,
- l = YAHOO.lang;
- /**
- * ui Component to generate the link to jump to the previous page.
- *
- * @namespace YAHOO.widget.Paginator.ui
- * @class PreviousPageLink
- * @for YAHOO.widget.Paginator
- *
- * @constructor
- * @param p {Pagintor} Paginator instance to attach to
- */
- Paginator.ui.PreviousPageLink = function (p) {
- this.paginator = p;
- p.subscribe('recordOffsetChange',this.update,this,true);
- p.subscribe('rowsPerPageChange',this.update,this,true);
- p.subscribe('totalRecordsChange',this.update,this,true);
- p.subscribe('destroy',this.destroy,this,true);
- // TODO: make this work
- p.subscribe('previousPageLinkLabelChange',this.update,this,true);
- p.subscribe('previousPageLinkClassChange',this.update,this,true);
- };
- /**
- * Decorates Paginator instances with new attributes. Called during
- * Paginator instantiation.
- * @method init
- * @param p {Paginator} Paginator instance to decorate
- * @static
- */
- Paginator.ui.PreviousPageLink.init = function (p) {
- /**
- * Used as innerHTML for the previous page link/span.
- * @attribute previousPageLinkLabel
- * @default '< prev'
- */
- p.setAttributeConfig('previousPageLinkLabel', {
- value : '< prev',
- validator : l.isString
- });
- /**
- * CSS class assigned to the link/span
- * @attribute previousPageLinkClass
- * @default 'yui-pg-previous'
- */
- p.setAttributeConfig('previousPageLinkClass', {
- value : 'yui-pg-previous',
- validator : l.isString
- });
- };
- Paginator.ui.PreviousPageLink.prototype = {
- /**
- * Currently placed HTMLElement node
- * @property current
- * @type HTMLElement
- * @private
- */
- current : null,
- /**
- * Link node
- * @property link
- * @type HTMLElement
- * @private
- */
- link : null,
- /**
- * Span node (inactive link)
- * @property span
- * @type HTMLElement
- * @private
- */
- span : null,
- /**
- * Generate the nodes and return the appropriate node given the current
- * pagination state.
- * @method render
- * @param id_base {string} used to create unique ids for generated nodes
- * @return {HTMLElement}
- */
- render : function (id_base) {
- var p = this.paginator,
- c = p.get('previousPageLinkClass'),
- label = p.get('previousPageLinkLabel');
- this.link = document.createElement('a');
- this.span = document.createElement('span');
- this.link.id = id_base + '-prev-link';
- this.link.href = '#';
- this.link.className = c;
- this.link.innerHTML = label;
- YAHOO.util.Event.on(this.link,'click',this.onClick,this,true);
- this.span.id = id_base + '-prev-span';
- this.span.className = c;
- this.span.innerHTML = label;
- this.current = p.getCurrentPage() > 1 ? this.link : this.span;
- return this.current;
- },
- /**
- * Swap the link and span nodes if appropriate.
- * @method update
- * @param e {CustomEvent} The calling change event
- */
- update : function (e) {
- if (e && e.prevValue === e.newValue) {
- return;
- }
- var par = this.current ? this.current.parentNode : null;
- if (this.paginator.getCurrentPage() > 1) {
- if (par && this.current === this.span) {
- par.replaceChild(this.link,this.current);
- this.current = this.link;
- }
- } else {
- if (par && this.current === this.link) {
- par.replaceChild(this.span,this.current);
- this.current = this.span;
- }
- }
- },
- /**
- * Removes the link/span node and clears event listeners
- * @method destroy
- * @private
- */
- destroy : function () {
- YAHOO.util.Event.purgeElement(this.link);
- this.current.parentNode.removeChild(this.current);
- this.link = this.span = null;
- },
- /**
- * Listener for the link's onclick event. Passes to setPage method.
- * @method onClick
- * @param e {DOMEvent} The click event
- */
- onClick : function (e) {
- YAHOO.util.Event.stopEvent(e);
- this.paginator.setPage(this.paginator.getPreviousPage());
- }
- };
- })();
- (function () {
- var Paginator = YAHOO.widget.Paginator,
- l = YAHOO.lang;
- /**
- * ui Component to generate the rows-per-page dropdown
- *
- * @namespace YAHOO.widget.Paginator.ui
- * @class RowsPerPageDropdown
- * @for YAHOO.widget.Paginator
- *
- * @constructor
- * @param p {Pagintor} Paginator instance to attach to
- */
- Paginator.ui.RowsPerPageDropdown = function (p) {
- this.paginator = p;
- p.subscribe('rowsPerPageChange',this.update,this,true);
- p.subscribe('rowsPerPageOptionsChange',this.rebuild,this,true);
- p.subscribe('totalRecordsChange',this._handleTotalRecordsChange,this,true);
- p.subscribe('destroy',this.destroy,this,true);
- // TODO: make this work
- p.subscribe('rowsPerPageDropdownClassChange',this.rebuild,this,true);
- };
- /**
- * Decorates Paginator instances with new attributes. Called during
- * Paginator instantiation.
- * @method init
- * @param p {Paginator} Paginator instance to decorate
- * @static
- */
- Paginator.ui.RowsPerPageDropdown.init = function (p) {
- /**
- * Array of available rows-per-page sizes. Converted into select options.
- * Array values may be positive integers or object literals in the form<br>
- * { value : NUMBER, text : STRING }
- * @attribute rowsPerPageOptions
- * @default []
- */
- p.setAttributeConfig('rowsPerPageOptions', {
- value : [],
- validator : l.isArray
- });
- /**
- * CSS class assigned to the select node
- * @attribute rowsPerPageDropdownClass
- * @default 'yui-pg-rpp-options'
- */
- p.setAttributeConfig('rowsPerPageDropdownClass', {
- value : 'yui-pg-rpp-options',
- validator : l.isString
- });
- };
- Paginator.ui.RowsPerPageDropdown.prototype = {
- /**
- * select node
- * @property select
- * @type HTMLElement
- * @private
- */
- select : null,
- /**
- * option node for the optional All value
- *
- * @property all
- * @type HTMLElement
- * @protected
- */
- all : null,
- /**
- * Generate the select and option nodes and returns the select node.
- * @method render
- * @param id_base {string} used to create unique ids for generated nodes
- * @return {HTMLElement}
- */
- render : function (id_base) {
- this.select = document.createElement('select');
- this.select.id = id_base + '-rpp';
- this.select.className = this.paginator.get('rowsPerPageDropdownClass');
- this.select.title = 'Rows per page';
- YAHOO.util.Event.on(this.select,'change',this.onChange,this,true);
- this.rebuild();
- return this.select;
- },
- /**
- * (Re)generate the select options.
- * @method rebuild
- */
- rebuild : function (e) {
- var p = this.paginator,
- sel = this.select,
- options = p.get('rowsPerPageOptions'),
- opt,cfg,val,i,len;
- this.all = null;
- for (i = 0, len = options.length; i < len; ++i) {
- cfg = options[i];
- opt = sel.options[i] ||
- sel.appendChild(document.createElement('option'));
- val = l.isValue(cfg.value) ? cfg.value : cfg;
- opt.innerHTML = l.isValue(cfg.text) ? cfg.text : cfg;
- if (l.isString(val) && val.toLowerCase() === 'all') {
- this.all = opt;
- opt.value = p.get('totalRecords');
- } else{
- opt.value = val;
- }
- }
- while (sel.options.length > options.length) {
- sel.removeChild(sel.firstChild);
- }
- this.update();
- },
- /**
- * Select the appropriate option if changed.
- * @method update
- * @param e {CustomEvent} The calling change event
- */
- update : function (e) {
- if (e && e.prevValue === e.newValue) {
- return;
- }
- var rpp = this.paginator.get('rowsPerPage')+'',
- options = this.select.options,
- i,len;
- for (i = 0, len = options.length; i < len; ++i) {
- if (options[i].value === rpp) {
- options[i].selected = true;
- break;
- }
- }
- },
- /**
- * Listener for the select's onchange event. Sent to setRowsPerPage method.
- * @method onChange
- * @param e {DOMEvent} The change event
- */
- onChange : function (e) {
- this.paginator.setRowsPerPage(
- parseInt(this.select.options[this.select.selectedIndex].value,10));
- },
- /**
- * Updates the all option value (and Paginator's rowsPerPage attribute if
- * necessary) in response to a change in the Paginator's totalRecords.
- *
- * @method _handleTotalRecordsChange
- * @param e {Event} attribute change event
- * @protected
- */
- _handleTotalRecordsChange : function (e) {
- if (!this.all || (e && e.prevValue === e.newValue)) {
- return;
- }
- this.all.value = e.newValue;
- if (this.all.selected) {
- this.paginator.set('rowsPerPage',e.newValue);
- }
- },
- /**
- * Removes the select node and clears event listeners
- * @method destroy
- * @private
- */
- destroy : function () {
- YAHOO.util.Event.purgeElement(this.select);
- this.select.parentNode.removeChild(this.select);
- this.select = null;
- }
- };
- })();
- YAHOO.register("paginator", YAHOO.widget.Paginator, {version: "2.8.0r4", build: "2449"});
|