YUI recommends YUI 3.

YUI 2 has been deprecated since 2011. This site acts as an archive for files and documentation.

YUI Library Home

YUI Library Examples: DataTable Control: Quick Edit

DataTable Control: Quick Edit

A demonstration of switching DataTable into Quick Edit mode. When the table first loads, it displays the normal way. When it switches to Quick Edit mode, the editable colums are filled with input fields. getQuickEditChanges() returns the changed values for efficiently saving the updates.

In Quick Edit mode, hold down the Control key and press the up or down arrow keys to move within a column.

To test validation, try entering John Lindal as the author, anything other than 4 digits for the date, and anything other than a positive integer for the quantity.

The Lion, the Witch and the Wardrobe
C.S. Lewis
1950
10
Prince Caspian: The Return to Narnia
C.S. Lewis
1951
5
The Voyage of the Dawn Treader
C.S. Lewis
1952
2
The Silver Chair
C.S. Lewis
1953
6
The Horse and His Boy
C.S. Lewis
1954
9

Custom CSS for this Example

1<style type="text/css"
2#quick-edit-controls 
3{ 
4    displaynone
5} 
6</style> 
view plain | print | ?

DataTable Quick Edit extension code:

Also available here.

1/* This code should not be modified */ 
2(function(){ 
3/**********
4* Quick Edit extension to YUI 2 DataTable
5* Author: lindalj@yahoo-inc.com / John Lindal
6* @submodule Quick Edit
7* @class YAHOO.widget.QuickEditDataTable
8***********/ 
9(function(){ 
10 
11    var lang = YAHOO.lang, 
12        Dom = YAHOO.util.Dom; 
13 
14    /**
15     * The QuickEditDataTable class extends the DataTable class to provide
16     * Quick Edit mode.  (It could just as easily extend
17     * ScrollingDataTable.)  QuickEdit mode allows the user to edit all the
18     * values that are visible in the table, controlled by the column
19     * configuration.  Each editable cell contains an input field.  If the
20     * user decides to save the changes, then you can extract the changes
21     * by calling <code>getQuickEditChanges()</code>.
22     * 
23     * For a column to be editable in QuickEdit mode, the column
24     * configuration must include <code>quickEdit</code>.  The contents of
25     * this object define the column's behavior in QuickEdit mode.
26     * 
27     * If a column should not be editable, but needs to be formatted
28     * differently in QuickEdit mode, then you must define qeFormatter in
29     * the column configuration. This is simply a normal cell formatter
30     * function that will be used in QuickEdit mode.  The static functions
31     * <code>readonly*QuickEditFormatter</code> provide examples.
32     * 
33     * The following configuration can be provided as part of quickEdit:
34     * 
35     * <dl>
36     * 
37     * <dt>copyDown</dt><dd>If true, the top cell in the column will have a
38     * button to copy the value down to the rest of the rows.</dd>
39     * 
40     * <dt>formatter</dt><dd>The cell formatter which will render an
41     * appropriate form field: <input type="text">, <textarea>,
42     * or <select>.</dd>
43     * 
44     * <dt>validation</dt><dd>Validation configuration for every field in
45     * the column.</dd>
46     * 
47     * </dl>
48     * 
49     * The following configuration can be provided as part of
50     * quickEdit.validation:
51     * 
52     * <dl>
53     * 
54     * <dt>css</dt><dd>CSS classes encoding basic validation rules.  Note
55     * that this will only work if you uncomment the call to
56     * <code>validateFromCSSData()</code> inside
57     * <code>_validateElements()</code>.</dd>
58     * 
59     * <dt>fn</dt><dd>A function that will be called with the DataTable as
60     * its scope and the cell's form element as the argument. Return true
61     * if the value is valid. Otherwise, call this.displayMessage(...) to
62     * display an error and return false.</dd>
63     * 
64     * <dt>msg</dt><dd>A map of types to messages that will be displayed
65     * when a basic or regex validation rule fails. Currently, the only
66     * valid type is regex.  If you copy the implementation of
67     * validateFromCSSData(), from FormManager in the YUI 3 Gallery, then
68     * you will be able to specify more types:  required, min_length,
69     * max_length, integer, and decimal.</dd>
70     * 
71     * <dt>regex</dt><dd>Regular expression that the value must satisfy in
72     * order to be considered valid.</dd>
73     * 
74     * </dl>
75     * 
76     * Custom QuickEdit Formatters
77     * 
78     * To write a custom cell formatter for QuickEdit mode, you must
79     * structure the function as follows:
80     * 
81     * function myQuickEditFormatter(el, oRecord, oColumn, oData) {
82     *   var markup =
83     *     '<input type="text" class="{yiv} yui-quick-edit yui-quick-edit-key:{key}"/>' +
84     *     YAHOO.widget.QuickEditDataTable.MARKUP_QE_ERROR_DISPLAY;
85     *     
86     *     el.innerHTML = lang.substitute(markup, {
87     *       key: oColumn.key,
88     *       yiv: oColumn.quickEdit.validation ? (oColumn.quickEdit.validation.css || '') : ''
89     *     });
90     *     
91     *     el.firstChild.value = extractMyEditableValue(oData);
92     *     
93     *     YAHOO.widget.QuickEditDataTable.copyDownFormatter.apply(this, arguments);
94     * };
95     * 
96     * You can use textarea or select instead of input, but you can only
97     * create a single field.
98     * 
99     * <code>extractMyEditableValue</code> does not have to be a separate
100     * function nor must it be limited to using only oData. The work should
101     * normally be done inline in the formatter function, but the name of
102     * the sample function makes the point clear.
103     *
104     * @module QuickEdit
105     * @namespace YAHOO.widget
106     * @class QuickEditDataTable
107     * @extends YAHOO.widget.DataTable
108     * @constructor
109     * @param elContainer {HTMLElement} Container element for the TABLE.
110     * @param aColumnDefs {Object[]} Array of object literal Column definitions.
111     * @param oDataSource {YAHOO.util.DataSource} DataSource instance.
112     * @param oConfigs {object} (optional) Object literal of configuration values.
113     */ 
114    YAHOO.widget.QuickEditDataTable = function(elContainer,aColumnDefs,oDataSource,oConfigs) 
115    { 
116        YAHOO.widget.QuickEditDataTable.superclass.constructor.call(this, elContainer,aColumnDefs,oDataSource,oConfigs);  
117 
118        this.hasQEMessages = false
119 
120    }; 
121 
122    var QEDT = YAHOO.widget.QuickEditDataTable, 
123        quick_edit_re             = /yui-quick-edit-key:([^\s]+)/, 
124        qe_row_status_even_prefix = 'yui-quick-edit-even-has'
125        qe_row_status_odd_prefix  = 'yui-quick-edit-odd-has'
126        qe_row_status_pattern     = '(?:^|\\s)(?:yui-quick-edit-(even|odd)-has([a-z]+))(?= |$)'
127        qe_row_status_re          = new RegExp(qe_row_status_pattern), 
128        qe_cell_status_prefix     = 'yui-quick-edit-has'
129        qe_cell_status_pattern    = '(?:^|\\s)(?:' + qe_cell_status_prefix + '([a-z]+))(?= |$)'
130        qe_cell_status_re         = new RegExp(qe_cell_status_pattern); 
131 
132    QEDT.status_order = 
133    [ 
134        'error'
135        'warn'
136        'success'
137        'info' 
138    ]; 
139 
140    getStatusPrecedence = function
141        /* string */    status) 
142    { 
143        for (var i=0; i<QEDT.status_order.length; i++) 
144        { 
145            if (status == QEDT.status_order[i]) 
146            { 
147                return i; 
148            } 
149        } 
150 
151        return QEDT.status_order.length; 
152    }; 
153 
154    statusTakesPrecendence = function
155        /* string */    orig_status, 
156        /* string */    new_status) 
157    { 
158        return (!orig_status || getStatusPrecedence(new_status) < getStatusPrecedence(orig_status)); 
159    }; 
160 
161    YAHOO.lang.extend(  
162        YAHOO.widget.QuickEditDataTable, 
163        YAHOO.widget.DataTable,  
164    { 
165        /**
166         * Switch to Quick Edit mode.  Columns that have quickEdit defined will
167         * be editable.
168         *
169         * @method startQuickEdit
170         */ 
171        startQuickEdit : function() { 
172 
173            this.fireEvent('clearErrorNotification'); 
174 
175            if (YAHOO.lang.isFunction(this.collapseAllRows)) { 
176                this.collapseAllRows(); 
177            } 
178 
179            var cols        = this.getColumnSet().keys; 
180            this.qeSaveSort = []; 
181            this.qeSaveEdit = {}; 
182            this.qeSaveFmt  = {}; 
183            var sortable    = false
184            for (var i=0; i<cols.length; i++) { 
185                var col  = cols[i]; 
186                sortable = sortable || col.sortable; 
187                this.qeSaveSort.push(col.sortable); 
188                col.sortable = false
189 
190                this.qeSaveEdit[ col.key ] = col.editor; 
191                col.editor                 = null
192 
193                if (!col.hidden && (col.quickEdit || col.qeFormatter)) { 
194                    var fn; 
195                    if (col.quickEdit && lang.isFunction(col.quickEdit.formatter)) { 
196                        fn = col.quickEdit.formatter; 
197                    } 
198                    else if (lang.isFunction(col.qeFormatter)) { 
199                        fn = col.qeFormatter; 
200                    } 
201                    else { 
202                        fn = QEDT.textQuickEditFormatter; 
203                    } 
204 
205                    if (fn) { 
206                        var fmt                 = this._wrapFormatter(fn, col.formatter); 
207                        this.qeSaveFmt[col.key] = col.formatter; 
208                        col.formatter           = fmt; 
209                    } 
210                } 
211            } 
212 
213            Dom.addClass(this.getContainerEl(), 'yui-dt-quick-edit'); 
214            this.subscribe('tbodyKeyEvent'this._moveFocus, nullthis); 
215 
216            var pg = this.get('paginator'); 
217            if (pg) { 
218                var c = pg.get('containers'); 
219                if (!(c instanceof Array)) { 
220                    c = [c]; 
221                } 
222                for (var i=0; i<c.length; i++) { 
223                    Dom.setStyle(c[i], 'display''none'); 
224                } 
225            } 
226 
227            if (sortable) { 
228                this._initTheadEl(); 
229            } 
230            this.render(); 
231        }, 
232 
233        _wrapFormatter : function(editFmt, origFmt) { 
234 
235            return function(el, oRecord, oColumn, oData) { 
236                if (oRecord) { 
237                    editFmt.apply(this, arguments); 
238                } 
239                else { 
240                    origFmt.apply(this, arguments); 
241                } 
242            }; 
243        }, 
244 
245        /**
246         * Switch out of Quick Edit mode.  THIS DISCARDS ALL DATA!  If you
247         * want to save the data, call getQuickEditChanges() BEFORE calling
248         * this function.
249         *
250         * @method cancelQuickEdit
251         */ 
252        cancelQuickEdit : function() { 
253 
254            this.fireEvent('clearErrorNotification'); 
255 
256            var cols     = this.getColumnSet().keys; 
257            var sortable = false
258            for (var i=0; i<cols.length; i++) { 
259                var col      = cols[i]; 
260                col.sortable = this.qeSaveSort[i]; 
261                sortable     = sortable || col.sortable; 
262                col.editor   = this.qeSaveEdit[ col.key ]; 
263            } 
264            delete this.qeSaveSort; 
265            delete this.qeSaveEdit; 
266 
267            for (var key in this.qeSaveFmt) { 
268                if (lang.hasOwnProperty(this.qeSaveFmt, key)) { 
269                    var col       = this.getColumn(key); 
270                    col.formatter = this.qeSaveFmt[key]; 
271                } 
272            } 
273            delete this.qeSaveFmt; 
274 
275            Dom.removeClass(this.getContainerEl(), 'yui-dt-quick-edit'); 
276            this.unsubscribe('tbodyKeyEvent'this._moveFocus); 
277 
278            var pg = this.get('paginator'); 
279            if (pg) { 
280                var c = pg.get('containers'); 
281                if (!(c instanceof Array)) { 
282                    c = [c]; 
283                } 
284                for (var i=0; i<c.length; i++) { 
285                    Dom.setStyle(c[i], 'display''block'); 
286                } 
287            } 
288 
289            if (sortable) { 
290                this._initTheadEl(); 
291            } 
292            this.render(); 
293        }, 
294 
295        /**
296         * Return the changed values.  For each row, an object is created
297         * with only the changed values.  The object keys are the column keys.
298         *
299         * @method getQuickEditChanges
300         * @return {mixed} array if all validation passed, false otherwise
301         */ 
302        getQuickEditChanges : function() { 
303 
304            if (!this.validateQuickEdit()) { 
305                return false
306            } 
307 
308            var changes = []; 
309 
310            var tr = this.getFirstTrEl(); 
311            while (tr) { 
312                var rec  = this.getRecord(tr); 
313                var list = Dom.getElementsByClassName(quick_edit_re, null, tr); 
314 
315                var change = {}; 
316                changes.push(change); 
317 
318                for (var i=0; i<list.length; i++) { 
319                    var m    = quick_edit_re.exec(list[i].className); 
320                    var key  = m[1]; 
321                    var col  = this.getColumn(key); 
322                    var prev = rec.getData(key); 
323 
324                    var val = list[i].value; 
325                    if (col.parser) { 
326                        val = col.parser.call(this, val); 
327                    } 
328 
329                    if (col.quickEditChanged ? col.quickEditChanged(prev, val) : 
330                            val !== (prev ? prev.toString() : '')) { 
331                        change[key] = val; 
332                    } 
333                } 
334 
335                tr = this.getNextTrEl(tr); 
336            } 
337 
338            return changes; 
339        }, 
340 
341        /**
342         * Copy value from first cell to all other cells in the column.
343         *
344         * @method _quickEditCopyDown
345         * @param e {Event} triggering event
346         * @param cell {Element} cell from which to copy
347         * @private
348         */ 
349        _quickEditCopyDown : function
350            /* event */     e, 
351            /* element */   cell) { 
352 
353            var list = Dom.getElementsByClassName(quick_edit_re, null, cell); 
354            if (!list || !list.length) { 
355                return
356            } 
357 
358            var value = list[0].value; 
359            while (1) { 
360                cell = this.getBelowTdEl(cell); 
361                if (!cell) { 
362                    break
363                } 
364 
365                list = Dom.getElementsByClassName(quick_edit_re, null, cell); 
366                if (list && list.length) { 
367                    list[0].value = value; 
368                } 
369            } 
370        }, 
371 
372        /**
373         * Validate the quick edit data.
374         *
375         * @method validateQuickEdit
376         * @return {boolean} true if all validation checks pass
377         */ 
378        validateQuickEdit : function() { 
379 
380            this.clearMessages(); 
381            var status = true
382 
383            var e1 = this.getTbodyEl().getElementsByTagName('input'); 
384            var e2 = this.getTbodyEl().getElementsByTagName('textarea'); 
385 
386            status = this._validateElements(e1) && status;  // status last to guarantee call 
387            status = this._validateElements(e2) && status; 
388 
389            if (!status) { 
390                this.fireEvent('notifyErrors'); 
391            } 
392 
393            return status; 
394        }, 
395 
396        /**
397         * Validate the given form fields.
398         *
399         * @method _validateElements
400         * @param e {Array} Array of form fields.
401         * @return {boolean} true if all validation checks pass
402         * @private
403         */ 
404        _validateElements : function
405            /* array */ e) { 
406 
407            var status = true
408            for (var i=0; i<e.length; i++) { 
409                var col = this.getColumn(e[i]); 
410                if (!col.quickEdit) { 
411                    continue
412                } 
413                var msg_list = col.quickEdit.validation ? col.quickEdit.validation.msg : null
414/*
415                // see yui3-gallery:gallery-formmgr for an example of validateFromCSSData()
416
417                var info = validateFromCSSData(e[i], msg_list);
418                if (info.error) {
419                    this.displayMessage(e[i], info.error, 'error');
420                    status = false;
421                }
422                if (!info.keepGoing) {
423                    continue;
424                }
425*/ 
426                if (col.quickEdit.validation 
427                        && col.quickEdit.validation.regex instanceof RegExp 
428                        && !col.quickEdit.validation.regex.test(e[i].value)) { 
429                    this.displayMessage(e[i], msg_list ? msg_list.regex : null'error'); 
430                    status = false
431                    continue
432                } 
433 
434                if (col.quickEdit.validation 
435                        && lang.isFunction(col.quickEdit.validation.fn) 
436                        && !col.quickEdit.validation.fn.call(this, e[i])) { 
437                    status = false
438                    continue
439                } 
440            } 
441 
442            return status; 
443        }, 
444 
445        /**
446         * Clear all validation messages in quick edit mode.
447         *
448         * @method clearMessages
449         */ 
450        clearMessages : function() { 
451 
452            this.hasQEMessages = false
453 
454            this.fireEvent('clearErrorNotification'); 
455 
456            var list = Dom.getElementsByClassName(qe_row_status_re, nullthis.getTbodyEl()); 
457            Dom.removeClass(list, qe_row_status_re); 
458 
459            list = Dom.getElementsByClassName(qe_cell_status_re, nullthis.getTbodyEl()); 
460            Dom.removeClass(list, qe_cell_status_re); 
461 
462            for (var i=0; i<list.length; i++) { 
463                var m = Dom.getElementsByClassName(QEDT.CLASS_QE_ERROR_TEXT, null, list[i]); 
464                if (m && m.length > 0) { 
465                    m[0].innerHTML = ''
466                } 
467            } 
468        }, 
469 
470        /**
471         * Display a message for a quick edit field.  If an existing message with
472         * a higher precedence is already visible, it will not be replaced.
473         *
474         * @method displayMessage
475         * @param e {Element} form field
476         * @param msg {String} message to display
477         * @param type {String} message type: error, warn, success, info
478         * @param scroll {boolean} If false, does not scroll, even if this is the first message to display.
479         */ 
480        displayMessage : function
481            /* element */   e, 
482            /* string */    msg, 
483            /* string */    type, 
484            /* boolean */   scroll) { 
485 
486            if (lang.isUndefined(scroll)) { 
487                scroll = true
488            } 
489 
490            var row = this.getTrEl(e); 
491            if (statusTakesPrecendence(this._getElementStatus(row, qe_row_status_re), type)) { 
492                if (!this.hasQEMessages && scroll) { 
493                    this.getFirstTdEl(row).scrollIntoView(); 
494                } 
495 
496                if (Dom.hasClass(row, 'yui-dt-even')) { 
497                    Dom.replaceClass(row, qe_row_status_re, qe_row_status_even_prefix + type); 
498                } 
499                else { 
500                    Dom.replaceClass(row, qe_row_status_re, qe_row_status_odd_prefix + type); 
501                } 
502                this.hasQEMessages = true
503            } 
504 
505            var cell = this.getTdEl(e); 
506            if (statusTakesPrecendence(this._getElementStatus(cell, qe_cell_status_re), type)) { 
507                if (msg) { 
508                    var m = Dom.getElementsByClassName(QEDT.CLASS_QE_ERROR_TEXT, null, cell); 
509                    if (m && m.length > 0) { 
510                        m[0].innerHTML = msg; 
511                    } 
512                } 
513 
514                Dom.replaceClass(cell, qe_cell_status_re, qe_cell_status_prefix + type); 
515                this.hasQEMessages = true
516            } 
517        }, 
518 
519        /**
520         * Return the status of the field.
521         *
522         * @method _getElementStatus
523         * @param e {Element} form field
524         * @param r {RegExp} regex to match against className
525         * @private
526         */ 
527        _getElementStatus : function
528            /* string/object */ e, 
529            /* regex */         r) { 
530 
531            var m = e.className.match(r); 
532            return ((m && m.length) ? m[1] : false); 
533        }, 
534 
535        /**
536         * Shift the focus up/down within a column.
537         *
538         * @method _moveFocus
539         * @param cssClass {String} Extra class to apply to the row.
540         * @return {Element} reference to the new row
541         * @private
542         */ 
543        _moveFocus : function(data) { 
544            var e   = data.event; 
545            var key = YAHOO.util.Event.getCharCode(e); 
546            if (e.ctrlKey && (key == 38 || key == 40)) {    // Ctrl-up/down 
547                var target = YAHOO.util.Event.getTarget(e); 
548                var cell   = (key == 38 ? this.getAboveTdEl(target) : this.getBelowTdEl(target)); 
549                if (cell) { 
550                    var input = Dom.getElementsByClassName(quick_edit_re, null, cell)[0]; 
551                    if (input) { 
552                        input.focus(); 
553                        input.select(); 
554                        YAHOO.util.Event.stopEvent(e); 
555                    } 
556                } 
557            } 
558        } 
559    }); 
560 
561    YAHOO.lang.augmentObject(YAHOO.widget.QuickEditDataTable, 
562    { 
563        CLASS_QE_ERROR_TEXT     : 'yui-quick-edit-message-text'
564        MARKUP_QE_ERROR_DISPLAY : '<div class="yui-quick-edit-message-text"></div>'
565 
566        /**
567         * Called with exactly the same arguments as any other cell
568         * formatter, this function displays an input field.
569         *
570         * @method textQuickEditFormatter
571         * @static
572         */ 
573        textQuickEditFormatter : function(el, oRecord, oColumn, oData) 
574        { 
575            var markup = 
576                '<input type="text" class="{yiv} yui-quick-edit yui-quick-edit-key:{key}"/>' + 
577                QEDT.MARKUP_QE_ERROR_DISPLAY; 
578 
579            el.innerHTML = lang.substitute(markup, 
580            { 
581                key: oColumn.key, 
582                yiv: oColumn.quickEdit.validation ? (oColumn.quickEdit.validation.css || '') : '' 
583            }); 
584 
585            el.firstChild.value = oData; 
586 
587            QEDT.copyDownFormatter.apply(this, arguments); 
588        }, 
589 
590        /**
591         * Called with exactly the same arguments as any other cell
592         * formatter, this function displays a textarea field.
593         *
594         * @method textareaQuickEditFormatter
595         * @static
596         */ 
597        textareaQuickEditFormatter : function(el, oRecord, oColumn, oData) { 
598 
599            var markup = 
600                '<textarea class="{yiv} yui-quick-edit yui-quick-edit-key:{key}"/>' + 
601                QEDT.MARKUP_QE_ERROR_DISPLAY; 
602 
603            el.innerHTML = lang.substitute(markup, 
604            { 
605                key: oColumn.key, 
606                yiv: oColumn.quickEdit.validation ? (oColumn.quickEdit.validation.css || '') : '' 
607            }); 
608 
609            el.firstChild.value = oData; 
610 
611            QEDT.copyDownFormatter.apply(this, arguments); 
612        }, 
613 
614        /**
615         * Called with exactly the same arguments as any other cell
616         * formatter, this function displays an email address without the
617         * anchor tag.  Use this as the column's qeFormatter if the column
618         * should not be editable in Quick Edit mode.
619         *
620         * @method readonlyLinkQuickEditFormatter
621         * @static
622         */ 
623        readonlyEmailQuickEditFormatter : function(el, oRecord, oColumn, oData) 
624        { 
625            el.innerHTML = (oData ? oData : ''); 
626        }, 
627 
628        /**
629         * Called with exactly the same arguments as any other cell
630         * formatter, this function displays a link without the anchor tag.
631         * Use this as the column's qeFormatter if the column should not be
632         * editable in Quick Edit mode.
633         *
634         * @method readonlyLinkQuickEditFormatter
635         * @static
636         */ 
637         readonlyLinkQuickEditFormatter : function(el, oRecord, oColumn, oData) 
638         { 
639            el.innerHTML = oData; 
640        }, 
641 
642        /**
643         * Called with exactly the same arguments as a normal cell
644         * formatter, this function inserts a "Copy down" button if the
645         * cell is in the first row of the DataTable.  Call this at the end
646         * of your QuickEdit formatter.
647         *
648         * @method copyDownFormatter
649         * @static
650         */ 
651        copyDownFormatter : function(el, oRecord, oColumn, oData) 
652        { 
653            if (oColumn.quickEdit.copyDown && 
654                this.getRecordSet().getRecordIndex(oRecord) == 
655                    this.getState().pagination.recordOffset) 
656            { 
657                var button       = document.createElement('button'); 
658                button.title     = 'Copy down'
659                button.innerHTML = '↓' 
660 
661                var msg = Dom.getElementsByClassName(QEDT.CLASS_QE_ERROR_TEXT, null, el)[0]; 
662                el.insertBefore(button, msg); 
663 
664                YAHOO.util.Event.on(button, 'click'this._quickEditCopyDown, el, this); 
665            } 
666        } 
667    }); 
668 
669})(); 
670})(); 
view plain | print | ?

JavaScript to run this example

1/* Modify as needed */ 
2YAHOO.util.Event.onDOMReady( function() { 
3 
4    YAHOO.example.Data = { 
5        bookorders: [ 
6            {author:"C.S. Lewis", year:1950, quantity:10, title:"The Lion, the Witch and the Wardrobe"}, 
7            {author:"C.S. Lewis", year:1951, quantity:5, title:"Prince Caspian: The Return to Narnia"}, 
8            {author:"C.S. Lewis", year:1952, quantity:2, title:"The Voyage of the Dawn Treader"}, 
9            {author:"C.S. Lewis", year:1953, quantity:6, title:"The Silver Chair"}, 
10            {author:"C.S. Lewis", year:1954, quantity:9, title:"The Horse and His Boy"}, 
11            {author:"C.S. Lewis", year:1955, quantity:4, title:"The Magician's Nephew"}, 
12            {author:"C.S. Lewis", year:1956, quantity:8, title:"The Last Battle"}, 
13            {author:"C.S. Lewis", year:1938, quantity:10, title:"Out of the Silent Planet"}, 
14            {author:"C.S. Lewis", year:1943, quantity:5, title:"Perelandra"}, 
15            {author:"C.S. Lewis", year:1945, quantity:2, title:"That Hideous Strength"}, 
16            {author:"Philip Pullman", year:1995, quantity:7, title:"Northern Lights"}, 
17            {author:"Philip Pullman", year:1997, quantity:5, title:"The Subtle Knife"}, 
18            {author:"Philip Pullman", year:2000, quantity:8, title:"The Amber Spyglass"}, 
19            {author:"J. R. R. Tolkien", year:1937, quantity:5, title:"The Hobbit"}, 
20            {author:"J. R. R. Tolkien", year:1955, quantity:12, title:"The Fellowship of the Ring"}, 
21            {author:"J. R. R. Tolkien", year:1955, quantity:0, title:"The Two Towers"}, 
22            {author:"J. R. R. Tolkien", year:1955, quantity:8, title:"The Return of the King"}, 
23            {author:"Philip K. Dick", year:1966, quantity:5, title:"Do Androids Dream of Electric Sheep?"}, 
24            {author:"Robert A. Heinlein", year:1959, quantity:4, title:"Starship Troopers"}, 
25            {author:"Robert A. Heinlein", year:1961, quantity:7, title:"Stranger in a Strange Land"}, 
26            {author:"Robert A. Heinlein", year:1966, quantity:3, title:"The Moon Is a Harsh Mistress"}, 
27            {author:"A. E. van Vogt", year:1946, quantity:3, title:"Slan"}, 
28            {author:"A. E. van Vogt", year:1950, quantity:5, title:"The Voyage of the Space Beagle"}, 
29            {author:"A. E. van Vogt", year:1970, quantity:8, title:"Quest for the Future"
30        ] 
31    }; 
32 
33    /**
34    *
35    * Create a YUI DataSource instance. This will create an XHR datasource and will use YQL 
36    * to query the Flickr web service.
37    *
38    **/ 
39    var myDataSource = new YAHOO.util.DataSource(YAHOO.example.Data.bookorders, { 
40 
41        responseType: YAHOO.util.DataSource.TYPE_JSARRAY, 
42        responseSchema: { 
43            fields: [ 'author''year''quantity''title' ] 
44        } 
45    }); 
46 
47    /**
48    *
49    * Create a YUI DataTable instance.
50    *
51    **/ 
52    var myDataTable = new YAHOO.widget.QuickEditDataTable( 
53        "quickedit_table"
54        [ 
55            { 
56                key:"title"
57                label:"Title"
58                resizeable: true
59                sortable: true 
60            }, 
61            { 
62                key:"author"
63                label:"Author"
64                resizeable: true
65                sortable: true
66                quickEdit: { 
67                    validation: { 
68                        fn: function(e) { 
69                            if (e.value == "John Lindal") { 
70                                this.displayMessage(e, 'He has never been published!''error'); 
71                                return false
72                            } 
73                            else { 
74                                return true
75                            } 
76                        } 
77                    } 
78                } 
79            }, 
80            { 
81                key:"year"
82                label:"Publication Date"
83                resizeable: true
84                sortable: true
85                quickEdit: { 
86                    validation: { 
87                        regex: /^[0-9]{4}$/, 
88                        msg: { 
89                            regex: 'Please enter a four digit year.' 
90                        } 
91                    } 
92                } 
93            }, 
94            { 
95                key:"quantity"
96                label:"Quantity"
97                resizeable: true
98                sortable: true
99                quickEdit: { 
100                    copyDown: true
101                    validation: { 
102//                          css: "yiv-integer:[0,]" 
103                        regex: /^[0-9]+$/, 
104                        msg: { 
105                            regex: 'Please enter a positive integer.' 
106                        } 
107                    } 
108                } 
109            }, 
110        ], 
111        myDataSource, 
112        {  
113            paginator: new YAHOO.widget.Paginator({ 
114                rowsPerPage:5, 
115                containers:'pagination' 
116            }) 
117        } 
118    ); 
119 
120    /**
121    * Quick Edit controls
122    **/ 
123    YAHOO.util.Event.on('start-quick-edit''click'function() 
124    { 
125        document.getElementById('start-quick-edit').disabled = true
126        YAHOO.util.Dom.setStyle('quick-edit-controls''display''inline'); 
127        myDataTable.startQuickEdit(); 
128    }); 
129 
130    YAHOO.util.Event.on('save-quick-edit''click'function() 
131    { 
132        stopQuickEdit(true); 
133    }); 
134 
135    YAHOO.util.Event.on('cancel-quick-edit''click'function() 
136    { 
137        stopQuickEdit(false); 
138    }); 
139 
140    function stopQuickEdit(save) 
141    { 
142        if (save) 
143        { 
144            var changes = myDataTable.getQuickEditChanges(); 
145            if (changes === false
146            { 
147                return false
148            } 
149 
150            var offset = myDataTable.get('paginator').getStartIndex(); 
151            for (var i=0; i<changes.length; i++) 
152            { 
153                var j = i + offset; 
154                for (var key in changes[i]) 
155                { 
156                    if (YAHOO.lang.hasOwnProperty(changes[i], key)) 
157                    { 
158                        myDataTable.getRecord(j).setData(key, changes[i][key]); 
159                    } 
160                } 
161            } 
162        } 
163 
164        document.getElementById('start-quick-edit').disabled = false
165        YAHOO.util.Dom.setStyle('quick-edit-controls''display''none'); 
166        myDataTable.cancelQuickEdit(); 
167        return true
168    } 
169}); 
view plain | print | ?

Configuration for This Example

You can load the necessary JavaScript and CSS for this example from Yahoo's servers. Click here to load the YUI Dependency Configurator with all of this example's dependencies preconfigured.

Copyright © 2011 Yahoo! Inc. All rights reserved.

Privacy Policy - Terms of Service - Copyright Policy - Job Openings