NOBUG: Fixed file access permissions
[moodle.git] / lib / yuilib / 3.13.0 / datatable-paginator / datatable-paginator.js
blob62dbcabbb3bc03a7b3c5b9da8ee3b1ff8731426d
1 /*
2 YUI 3.13.0 (build 508226d)
3 Copyright 2013 Yahoo! Inc. All rights reserved.
4 Licensed under the BSD License.
5 http://yuilibrary.com/license/
6 */
8 YUI.add('datatable-paginator', function (Y, NAME) {
10 /**
11  Adds support for paging through data in the DataTable.
13  @module datatable
14  @submodule datatable-paginator
15  @since 3.11.0
16  */
18 var Model,
19     View,
20     PaginatorTemplates = Y.DataTable.Templates.Paginator,
21     sub = Y.Lang.sub,
22     getClassName = Y.ClassNameManager.getClassName,
23     CLASS_DISABLED = getClassName(NAME, 'control-disabled'),
24     EVENT_UI = 'paginator:ui';
27 /**
28  @class DataTable.Paginator.Model
29  @extends Model
30  @since 3.11.0
31  */
32 Model = Y.Base.create('dt-pg-model', Y.Model, [Y.Paginator.Core]),
34 /**
35  @class DataTable.Paginator.View
36  @extends View
37  @since 3.11.0
38  */
39 View = Y.Base.create('dt-pg-view', Y.View, [], {
40     /**
41      Array of event handles to keep track of what should be destroyed later
42      @protected
43      @property _eventHandles
44      @type {Array}
45      @since 3.11.0
46      */
47     _eventHandles: [],
49     /**
50      Template for this view's container.
51      @property containerTemplate
52      @type {String}
53      @default '<div class="yui3-datatable-paginator"/>'
54      @since 3.11.0
55      */
56     containerTemplate: '<div class="{paginator}"/>',
58     /**
59      Template for content. Helps maintain order of controls.
60      @property contentTemplate
61      @type {String}
62      @default '{buttons}{goto}{perPage}'
63      @since 3.11.0
64      */
65     contentTemplate: '{buttons}{goto}{perPage}',
67     /**
68      Disables ad-hoc ATTRS for our view.
69      @protected
70      @property _allowAdHocAttrs
71      @type {Boolean}
72      @default false
73      @since 3.11.0
74      */
75     _allowAdHocAttrs: false,
77     /**
78      Sets classnames on the templates and bind events
79      @method initializer
80      @since 3.11.0
81      */
82     initializer: function () {
83         this.containerTemplate = sub(this.containerTemplate, {
84             paginator: getClassName(NAME)
85         });
87         this._initStrings();
88         this._initClassNames();
90         this.attachEvents();
91     },
93     /**
94      @method render
95      @chainable
96      @since 3.11.0
97      */
98     render: function () {
99         var model = this.get('model'),
100             content = sub(this.contentTemplate, {
101                 'buttons': this._buildButtonsGroup(),
102                 'goto': this._buildGotoGroup(),
103                 'perPage': this._buildPerPageGroup()
104             });
106         this.get('container').append(content);
107         this.attachEvents();
109         this._rendered = true;
111         this._updateControlsUI(model.get('page'));
112         this._updateItemsPerPageUI(model.get('itemsPerPage'));
114         return this;
115     },
117     /**
118      @method attachEvents
119      @since 3.11.0
120      */
121     attachEvents: function () {
122         View.superclass.attachEvents.apply(this, arguments);
124         var container = this.get('container');
126         if (!this.classNames) {
127             this._initClassNames();
128         }
130         this._attachedViewEvents.push(
131             container.delegate('click', this._controlClick, '.' + this.classNames.control, this),
132             this.get('model').after('change', this._modelChange, this)
133         );
135         container.all('form').each(Y.bind(function (frm) {
136             this._attachedViewEvents.push(
137                 frm.after('submit', this._controlSubmit, this)
138             );
139         }, this));
141         container.all('select').each(Y.bind(function (sel) {
142             this._attachedViewEvents.push(
143                 sel.after('change', this._controlChange, this)
144             );
145         }, this));
147     },
149     /**
150      Returns a string built from the button and buttons templates.
151      @protected
152      @method _buildButtonsGroup
153      @return {String}
154      @since 3.11.0
155      */
156     _buildButtonsGroup: function () {
157         var strings = this.get('strings'),
158             classNames = this.classNames,
159             buttons;
161         buttons = PaginatorTemplates.button({
162                     type: 'first', label: strings.first, classNames: classNames
163                 }) +
164                 PaginatorTemplates.button({
165                     type: 'prev',  label: strings.prev,  classNames: classNames
166                 }) +
167                 PaginatorTemplates.button({
168                     type: 'next',  label: strings.next,  classNames: classNames
169                 }) +
170                 PaginatorTemplates.button({
171                     type: 'last',  label: strings.last,  classNames: classNames
172                 });
174         return PaginatorTemplates.buttons({
175             classNames: classNames,
176             buttons: buttons
177         });
179     },
181     /**
182      Returns a string built from the gotoPage template.
183      @protected
184      @method _buildGotoGroup
185      @return {String}
186      @since 3.11.0
187      */
188     _buildGotoGroup: function () {
190         return PaginatorTemplates.gotoPage({
191             classNames: this.classNames,
192             strings: this.get('strings'),
193             page: this.get('model').get('page')
194         });
195     },
197     /**
198      Returns a string built from the perPage template
199      @protected
200      @method _buildPerPageGroup
201      @return {String}
202      @since 3.11.0
203      */
204     _buildPerPageGroup: function () {
205         var options = this.get('pageSizes'),
206             rowsPerPage = this.get('model').get('rowsPerPage'),
207             option,
208             len,
209             i;
211         for (i = 0, len = options.length; i < len; i++ ) {
212             option = options[i];
214             if (typeof option !== 'object') {
215                 option = {
216                     value: option,
217                     label: option
218                 };
219             }
220             option.selected = (option.value === rowsPerPage) ? ' selected' : '';
221         }
223         return PaginatorTemplates.perPage({
224             classNames: this.classNames,
225             strings: this.get('strings'),
226             options: this.get('pageSizes')
227         });
229     },
231     /**
232      Update the UI after the model has changed.
233      @protected
234      @method _modelChange
235      @param {EventFacade} e
236      @since 3.11.0
237      */
238     _modelChange: function (e) {
239         var changed = e.changed,
240             page = (changed && changed.page),
241             itemsPerPage = (changed && changed.itemsPerPage);
243         if (page) {
244             this._updateControlsUI(page.newVal);
245         }
246         if (itemsPerPage) {
247             this._updateItemsPerPageUI(itemsPerPage.newVal);
248             if (!page) {
249                 this._updateControlsUI(e.target.get('page'));
250             }
251         }
253     },
255     /**
256      Updates the button controls and the gotoPage form
257      @protected
258      @method _updateControlsUI
259      @param {Number} val Page number to set the UI input to
260      @since 3.11.0
261      */
262     _updateControlsUI: function (val) {
263         if (!this._rendered) {
264             return;
265         }
267         var model = this.get('model'),
268             controlClass = '.' + this.classNames.control,
269             container = this.get('container'),
270             hasPrev = model.hasPrevPage(),
271             hasNext = model.hasNextPage();
273         container.one(controlClass + '-first')
274                  .toggleClass(CLASS_DISABLED, !hasPrev)
275                  .set('disabled', !hasPrev);
277         container.one(controlClass + '-prev')
278                  .toggleClass(CLASS_DISABLED, !hasPrev)
279                  .set('disabled', !hasPrev);
281         container.one(controlClass + '-next')
282                  .toggleClass(CLASS_DISABLED, !hasNext)
283                  .set('disabled', !hasNext);
285         container.one(controlClass + '-last')
286                  .toggleClass(CLASS_DISABLED, !hasNext)
287                  .set('disabled', !hasNext);
289         container.one('form input').set('value', val);
290     },
292     /**
293      Updates the drop down select for items per page
294      @protected
295      @method _updateItemsPerPageUI
296      @param {Number} val Number of items to display per page
297      @since 3.11.0
298      */
299     _updateItemsPerPageUI: function (val) {
300         if (!this._rendered) {
301             return;
302         }
304         this.get('container').one('select').set('value', val);
305     },
307     /**
308      Fire EVENT_UI when an enabled control button is clicked
309      @protected
310      @method _controlClick
311      @param {EventFacade} e
312      @since 3.11.0
313      */
314     _controlClick: function (e) { // buttons
315         e.preventDefault();
316         var control = e.currentTarget;
317         // register click events from the four control buttons
318         if (control.hasClass(CLASS_DISABLED)) {
319             return;
320         }
321         this.fire(EVENT_UI, {
322             type: control.getData('type'),
323             val: control.getData('page') || null
324         });
325     },
327     /**
328      Fire EVENT_UI with `type:perPage` after the select drop down changes
329      @protected
330      @method _controlChange
331      @param {EventFacade} e
332      @since 3.11.0
333      */
334     _controlChange: function (e) {
336         // register change events from the perPage select
337         if ( e.target.hasClass(CLASS_DISABLED) ) {
338             return;
339         }
341         val = e.target.get('value');
342         this.fire(EVENT_UI, { type: 'perPage', val: parseInt(val, 10) });
343     },
345     /**
346      Fire EVENT_UI with `type:page` after form is submitted
347      @protected
348      @method _controlSubmit
349      @param {EventFacade} e
350      @since 3.11.0
351      */
352     _controlSubmit: function (e) {
353         if ( e.target.hasClass(CLASS_DISABLED) ) {
354             return;
355         }
357         // the only form we have is the go to page form
358         e.preventDefault();
360         input = e.target.one('input');
361         this.fire(EVENT_UI, { type: 'page', val: input.get('value') });
362     },
364     /**
365      Initializes classnames to be used with the templates
366      @protected
367      @method _initClassNames
368      @since 3.11.0
369      */
370     _initClassNames: function () {
371         this.classNames = {
372             control: getClassName(NAME, 'control'),
373             controls: getClassName(NAME, 'controls'),
374             group: getClassName(NAME, 'group'),
375             perPage: getClassName(NAME, 'per-page')
376         };
377     },
379     /**
380      Initializes strings used for internationalization
381      @protected
382      @method _initStrings
383      @since 3.11.0
384      */
385     _initStrings: function () {
386         // Not a valueFn because other class extensions may want to add to it
387         this.set('strings', Y.mix((this.get('strings') || {}),
388             Y.Intl.get('datatable-paginator')));
389     },
392     /**
393      Returns an Array with default values for the Rows Per Page select option.
394      We had to use a valueFn to enable language string replacement.
396      @protected
397      @method _defPageSizeVal
398      @since 3.13.0
399      */
400     _defPageSizeVal: function () {
401         this._initStrings();
403         var str = this.get('strings');
405         return [10, 50, 100, { label: str.showAll, value: -1 }]
406     }
408 }, {
409     ATTRS: {
410         /**
411          Array of values used to populate the drop down for items per page
412          @attribute pageSizes
413          @type {Array}
414          @default [ 10, 50, 100, { label: 'Show All', value: -1 } ]
415          @since 3.11.0
416          */
417         pageSizes: {
418             valueFn: '_defPageSizeVal'
419         },
421         /**
422          Model used for this view
423          @attribute model
424          @type {Y.Model}
425          @default null
426          @since 3.11.0
427          */
428         model: {}
429     }
433  @class DataTable.Paginator
434  @since 3.11.0
435  */
436 function Controller () {}
438 Controller.ATTRS = {
439     /**
440      A model instance or a configuration object for the Model.
441      @attribute paginatorModel
442      @type {Y.Model | Object}
443      @default null
444      @since 3.11.0
445      */
446     paginatorModel: {
447         setter: '_setPaginatorModel',
448         value: null,
449         writeOnce: 'initOnly'
450     },
452     /**
453      A pointer to a Model object to be instantiated, or a String off of the
454      `Y` namespace.
456      This is only used if the `paginatorModel` is a configuration object or
457      is null.
458      @attribute paginatorModelType
459      @type {Y.Model | String}
460      @default 'DataTable.Paginator.Model'
461      @since 3.11.0
462      */
463     paginatorModelType: {
464         getter: '_getConstructor',
465         value: 'DataTable.Paginator.Model',
466         writeOnce: 'initOnly'
467     },
469     /**
470      A pointer to a `Y.View` object to be instantiated. A new view will be
471      created for each location provided. Each view created will be given the
472      same model instance.
473      @attribute paginatorView
474      @type {Y.View | String}
475      @default 'DataTable.Paginator.View'
476      @since 3.11.0
477      */
478     paginatorView: {
479         getter: '_getConstructor',
480         value: 'DataTable.Paginator.View',
481         writeOnce: 'initOnly'
482     },
484     // PAGINATOR CONFIGS
485     /**
486      Array of values used to populate the values in the Paginator UI allowing
487      the end user to select the number of items to display per page.
488      @attribute pageSizes
489      @type {Array}
490      @default [10, 50, 100, { label: 'Show All', value: -1 }]
491      @since 3.11.0
492      */
493     pageSizes: {
494         setter: '_setPageSizesFn',
495         valueFn: '_defPageSizeVal'
496     },
498     paginatorStrings: {},
500     /**
501      Number of rows to display per page. As the UI changes the number of pages
502      to display, this will update to reflect the value selected in the UI
503      @attribute rowsPerPage
504      @type {Number | null}
505      @default null
506      @since 3.11.0
507      */
508     rowsPerPage: {
509         value: null
510     },
512     /**
513      String of `footer` or `header`, a Y.Node, or an Array or any combination
514      of those values.
515      @attribute paginatorLocation
516      @type {String | Array | Y.Node}
517      @default footer
518      @since 3.11.0
519      */
520     paginatorLocation: {
521         value: 'footer'
522     }
525 Y.mix(Controller.prototype, {
526     /**
527      Sets the `paginatorModel` to the first page.
528      @method firstPage
529      @chainable
530      @since 3.11.0
531      */
532     firstPage: function () {
533         this.get('paginatorModel').set('page', 1);
534         return this;
535     },
537     /**
538      Sets the `paginatorModel` to the last page.
539      @method lastPage
540      @chainable
541      @since 3.11.0
542      */
543     lastPage: function () {
544         var model = this.get('paginatorModel');
545         model.set('page', model.get('totalPages'));
546         return this;
547     },
549     /**
550      Sets the `paginatorModel` to the previous page.
551      @method previousPage
552      @chainable
553      @since 3.11.0
554      */
555     previousPage: function () {
556         this.get('paginatorModel').prevPage();
557         return this;
558     },
560     /**
561      Sets the `paginatorModel` to the next page.
562      @method nextPage
563      @chainable
564      @since 3.11.0
565      */
566     nextPage: function () {
567         this.get('paginatorModel').nextPage();
568         return this;
569     },
572     /// Init and protected
573     /**
574      Constructor logic
575      @protected
576      @method initializer
577      @since 3.11.0
578      */
579     initializer: function () {
580         // allow DT to use paged data
581         this._initPaginatorStrings();
582         this._augmentData();
584         if (!this._eventHandles.paginatorRender) {
585             this._eventHandles.paginatorRender = Y.Do.after(this._paginatorRender, this, 'render');
586         }
587     },
589     /**
590      Renders the paginator into locations and attaches events.
591      @protected
592      @method _paginatorRender
593      @since 3.11.0
594      */
595     _paginatorRender: function () {
596         var model = this.get('paginatorModel');
598         this._paginatorRenderUI();
599         model.after('change', this._afterPaginatorModelChange, this);
600         this.after('dataChange', this._afterDataChangeWithPaginator, this);
601         this.after('rowsPerPageChange', this._afterRowsPerPageChange, this);
602         this.data.after(['add', 'remove', 'change'], this._afterDataUpdatesWithPaginator, this);
604         // ensure our model has the correct totalItems set
605         model.set('itemsPerPage', this.get('rowsPerPage'));
606         model.set('totalItems', this.get('data').size());
607     },
609     /**
610      After the data changes, we ensure we are on the first page and the data
611      is augmented
612      @protected
613      @method _afterDataChangeWithPaginator
614      @since 3.11.0
615      */
616     _afterDataChangeWithPaginator: function () {
617         var data = this.get('data'),
618             model = this.get('paginatorModel');
620         model.set('totalItems', data.size());
622         if (model.get('page') !== 1) {
623             this.firstPage();
624         } else {
625             this._augmentData();
627             data.fire.call(data, 'reset', {
628                 src: 'reset',
629                 models: data._items.concat()
630             });
631         }
632     },
634     /**
635      After data has changed due to a model being added, removed, or changed,
636      update paginator model totalItems to reflect the changes.
637      @protected
638      @method _afterDataUpdatesWithPaginator
639      @param {EventFacade} e
640      @since 3.13.0
641     */
642     _afterDataUpdatesWithPaginator: function () {
643         var model = this.get('paginatorModel'),
644             data = this.get('data');
646         model.set('totalItems', data.size());
647     },
649     /**
650      After the rowsPerPage changes, update the UI to reflect the new number of
651      rows to be displayed. If the new value is `null`, destroy all instances
652      of the paginators.
653      @protected
654      @method _afterRowsPerPageChange
655      @param {EventFacade} e
656      @since 3.11.0
657      */
658     _afterRowsPerPageChange: function (e) {
659         var data = this.get('data'),
660             model = this.get('paginatorModel'),
661             view;
663         if (e.newVal !== null) {
664             // turning on
665             this._paginatorRenderUI();
667             if (!(data._paged)) {
668                 this._augmentData();
669             }
671             data._paged.index = (model.get('page') - 1) * model.get('itemsPerPage');
672             data._paged.length = model.get('itemsPerPage');
674         } else { // e.newVal === null
675             // destroy!
676             while(this._pgViews.length) {
677                 view = this._pgViews.shift();
678                 view.destroy({ remove: true });
679                 view._rendered = null;
680             }
682             data._paged.index = 0;
683             data._paged.length = null;
684         }
686         this.get('paginatorModel').set('itemsPerPage', parseInt(e.newVal, 10));
687     },
689     /**
690      Parse each location and render a new view into each area.
691      @protected
692      @method _paginatorRenderUI
693      @since 3.11.0
694      */
695     _paginatorRenderUI: function () {
696         if (!this.get('rowsPerPage')) {
697             return;
698         }
699         var views = this._pgViews,
700             ViewClass = this.get('paginatorView'),
701             viewConfig = {
702                 pageSizes: this.get('pageSizes'),
703                 model: this.get('paginatorModel')
704             },
705             locations = this.get('paginatorLocation');
707         if (!Y.Lang.isArray(locations)) {
708             locations = [locations];
709         }
711         if (!views) { // set up initial rendering of views
712             views = this._pgViews = [];
713         }
715         // for each placement area, push to views
716         Y.Array.each(locations, function (location) {
717             var view = new ViewClass(viewConfig),
718                 container = view.render().get('container'),
719                 row;
721             view.after('*:ui', this._uiPgHandler, this);
722             views.push(view);
724             if (location._node) { // assume Y.Node
725                 location.append(container);
726                 // remove this container row if the view is ever destroyed
727                 this.after('destroy', function (/* e */) {
728                     view.destroy({ remove: true });
729                 });
730             } else if (location === 'footer') { // DT Footer
731                 // Render a table footer if there isn't one
732                 if (!this.foot) {
733                     this.foot = new Y.DataTable.FooterView({ host: this });
734                     this.foot.render();
735                     this.fire('renderFooter', { view: this.foot });
736                 }
738                 // create a row for the paginator to sit in
739                 row = Y.Node.create(PaginatorTemplates.rowWrapper({
740                     wrapperClass: getClassName(NAME, 'wrapper'),
741                     numOfCols: this.get('columns').length
742                 }));
744                 row.one('td').append(container);
745                 this.foot.tfootNode.append(row);
747                 // remove this container row if the view is ever destroyed
748                 view.after('destroy', function (/* e */) {
749                     row.remove(true);
750                 });
751             } else if (location === 'header') {
752                 // 'header' means insert before the table
753                 // placement with the caption may need to be addressed
754                 if (this.view && this.view.tableNode) {
755                     this.view.tableNode.insert(container, 'before');
756                 } else {
757                     this.get('contentBox').prepend(container);
758                 }
759             }
760         }, this);
762     },
764     /**
765      Handles the paginator's UI event into a single location. Updates the
766      `paginatorModel` according to what type is provided.
767      @protected
768      @method _uiPgHandler
769      @param {EventFacade} e
770      @since 3.11.0
771      */
772     _uiPgHandler: function (e) {
773         // e.type = control type (first|prev|next|last|page|perPage)
774         // e.val = value based on the control type to pass to the model
775         var model = this.get('paginatorModel');
777         switch (e.type) {
778             case 'first':
779                 model.set('page', 1);
780                 break;
781             case 'last':
782                 model.set('page', model.get('totalPages'));
783                 break;
784             case 'prev':
785             case 'next': // overflow intentional
786                 model[e.type + 'Page']();
787                 break;
788             case 'page':
789                 model.set('page', e.val);
790                 break;
791             case 'perPage':
792                 model.set('itemsPerPage', e.val);
793                 model.set('page', 1);
794                 break;
795         }
796     },
798     /**
799      Augments the model list with a paged structure, or updates the paged
800      data. Then fires reset on the model list.
801      @protected
802      @method _afterPaginatorModelChange
803      @param {EventFacade} [e]
804      @since 3.11.0
805      */
806     _afterPaginatorModelChange: function () {
807         var model = this.get('paginatorModel'),
808             data = this.get('data');
810         if (!data._paged) {
811             this._augmentData();
812         } else {
813             data._paged.index = (model.get('page') - 1) * model.get('itemsPerPage');
814             data._paged.length = model.get('itemsPerPage');
815         }
817         data.fire.call(data, 'reset', {
818             src: 'reset',
819             models: data._items.concat()
820         });
821     },
823     /**
824      Augments the model list data structure with paged implementations.
826      The model list will contain a method for `getPage` that will return the
827      given number of items listed within the range.
829      `each` will also loop over the items in the page
830      @protected
831      @method _augmentData
832      @since 3.11.0
833      */
834     _augmentData: function () {
835         var model = this.get('paginatorModel');
837         if (this.get('rowsPerPage') === null) {
838             return;
839         }
841         Y.mix(this.get('data'), {
843             _paged: {
844                 index: (model.get('page') - 1) * model.get('itemsPerPage'),
845                 length: model.get('itemsPerPage')
846             },
848             getPage: function () {
849                 var _pg = this._paged,
850                     min = _pg.index;
852                 // IE LTE 8 doesn't allow "undefined" as a second param - gh890
853                 return (_pg.length >= 0) ?
854                         this._items.slice(min, min + _pg.length) :
855                         this._items.slice(min);
856             },
858             size: function (paged) {
859                 return (paged && this._paged.length >=0 ) ?
860                     this._paged.length :
861                     this._items.length;
862             },
864             each: function () {
865                 var args = Array.prototype.slice.call(arguments);
866                 args.unshift(this.getPage());
868                 Y.Array.each.apply(null, args);
870                 return this;
871             }
872         }, true);
873     },
875     /**
876      Ensures `pageSizes` value is an array of objects to be used in the
877      paginator view.
878      @protected
879      @method _setPageSizesFn
880      @param {Array} val
881      @return Array
882      @since 3.11.0
883      */
884     _setPageSizesFn: function (val) {
885         var i,
886             len = val.length,
887             label,
888             value;
890         if (!Y.Lang.isArray(val)) {
891             val = [val];
892             len = val.length;
893         }
895         for ( i = 0; i < len; i++ ) {
896             if (typeof val[i] !== 'object') {
897                 label = val[i];
898                 value = val[i];
900                 // We want to check to see if we have a number or a string
901                 // of a number. If we do not, we want the value to be -1 to
902                 // indicate "all rows"
903                 /*jshint eqeqeq:false */
904                 if (parseInt(value, 10) != value) {
905                     value = -1;
906                 }
907                 /*jshint eqeqeq:true */
908                 val[i] = { label: label, value: value };
909             }
910         }
912         return val;
913     },
915     /**
916      Ensures the object provided is an instance of a `Y.Model`. If it is not,
917      it assumes it is the configuration of a model, and gets the new model
918      type from `paginatorModelType`.
919      @protected
920      @method _setPaginatorModel
921      @param {Y.Model | Object} model
922      @return Y.Model instance
923      @since 3.11.0
924      */
925     _setPaginatorModel: function (model) {
926         if (!(model && model._isYUIModel)) {
927             var ModelConstructor = this.get('paginatorModelType');
928             model = new ModelConstructor(model);
929         }
931         return model;
932     },
934     /**
935      Returns a pointer to an object to be instantiated if the provided type is
936      a string
937      @protected
938      @method _getConstructor
939      @param {Object | String} type Type of Object to contruct. If `type` is a
940        String, we assume it is a namespace off the Y object
941      @return
942      @since 3.11.0
943      */
944     _getConstructor: function (type) {
945         return typeof type === 'string' ?
946             Y.Object.getValue(Y, type.split('.')) :
947             type;
948     },
950     /**
951      Initializes paginatorStrings used for internationalization
952      @protected
953      @method _initPaginatorStrings
954      @since 3.13.0
955      */
956     _initPaginatorStrings: function () {
957         // Not a valueFn because other class extensions may want to add to it
958         this.set('paginatorStrings', Y.mix((this.get('paginatorStrings') || {}),
959             Y.Intl.get('datatable-paginator')));
960     },
962     /**
963      Returns an Array with default values for the Rows Per Page select option.
964      We had to use a valueFn to enable language string replacement.
966      @protected
967      @method _defPageSizeVal
968      @since 3.13.0
969      */
970     _defPageSizeVal: function () {
971         this._initPaginatorStrings();
973         var str = this.get('paginatorStrings');
975         return [10, 50, 100, { label: str.showAll, value: -1 }]
976     }
977 }, true);
980 Y.DataTable.Paginator = Controller;
981 Y.DataTable.Paginator.Model = Model;
982 Y.DataTable.Paginator.View = View;
984 Y.Base.mix(Y.DataTable, [Y.DataTable.Paginator]);
987 }, '3.13.0', {
988     "requires": [
989         "model",
990         "view",
991         "paginator-core",
992         "datatable-foot",
993         "datatable-paginator-templates"
994     ],
995     "lang": [
996         "en",
997         "fr"
998     ],
999     "skinnable": true