YUI recommends YUI 3.
YUI 2 has been deprecated since 2011. This site acts as an archive for files and documentation.
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.
1 | <style type="text/css"> |
2 | #quick-edit-controls |
3 | { |
4 | display: none; |
5 | } |
6 | </style> |
view plain | print | ? |
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, null, this); |
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, null, this.getTbodyEl()); |
457 | Dom.removeClass(list, qe_row_status_re); |
458 | |
459 | list = Dom.getElementsByClassName(qe_cell_status_re, null, this.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 | ? |
1 | /* Modify as needed */ |
2 | YAHOO.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 | ? |
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.
Note: Logging and debugging is currently turned off for this example.
Copyright © 2011 Yahoo! Inc. All rights reserved.
Privacy Policy - Terms of Service - Copyright Policy - Job Openings