📄 zpgrid-editable.js
字号:
/** * @fileoverview Zapatec Editable Grid widget extension. * * <pre> * Copyright (c) 2004-2007 by Zapatec, Inc. * http://www.zapatec.com * 1700 MLK Way, Berkeley, California, * 94709, U.S.A. * All rights reserved. * </pre> *//* $Id: zpgrid-editable.js 7597 2007-07-25 08:32:55Z alex $ */// Emulate window.event in Mozilla for keydown eventZapatec.Utils.emulateWindowEvent(['keydown']);/** * Editable Grid extension. * * <pre> * Note: zpgrid-core.js must be included before this module. If plugin modules * like zpgrid-xml.js are used, they must be included before this module as * well. * * <strong>Input data formats differences form Zapatec.Grid:</strong> * * <strong>JSON:</strong> * * "noedit: true" property in field definition makes column not editable. * * "list: true" property in field definition means that cells in the column will * not be edited directly. Instead there will appear selectbox with the list of * possible values for the cell. Cell "v" property should contain select * element: * <xmp> * <select> * <option>value1</option> * <option selected>value2</option> * ... * </select> * </xmp> * * Alternatively (deprecated) cell definition may contain "values" * property with all possible values: * values: ["value1", "value2", ...] * "v" property should contain default (selected) value in this case. * * <strong>HTML:</strong> * * Special "zpGridTypeNoedit" class makes column not editable. * * Special "zpGridTypeList" class means that cells in the column will not be * edited directly. Instead there will appear selectbox with the list of * possible values for the cell. Cell definition should contain select element: * <xmp> * <select> * <option>value1</option> * <option selected>value2</option> * ... * </select> * </xmp> * Special field types can be used alone or in conjunction with other field * types, e.g. class="zpGridTypeInt zpGridTypeNoedit" or * class="zpGridTypeFloat zpGridTypeList". * * <strong>XML:</strong> * * "noedit=true" attribute in field definition makes column not editable. * * "list=true" attribute in field definition means that cells in the column will * not be edited directly. Instead there will appear selectbox with the list of * possible values for the cell. Cell definition should contain select element: * <xmp> * <select> * <option>value1</option> * <option selected>value2</option> * ... * </select> * </xmp> * * <strong>In addition to config options defined in base Zapatec.Widget class * and Zapatec.Grid class provides following config options:</strong> * * <b>callbackCellEdit</b> [function] Callback function to call before grid cell * is turned into editable state. Receives Zapatec.EditableGrid and cell object. * Return false to stop editing using standard grid editor. * * <b>callbackCellReadOnly</b> [function] Callback function to call when grid * cell is turned into read-only state. Receives Zapatec.EditableGrid and cell * object. * * <b>externalEditors</b> [object] Array with external editors to use instead of * standard editors in following format: * [ * { * column: [number, optional] column number, * editor: [object, optional] widget object used as external editor, * callback: [function, optional] callback function to pass value for * editing * }, * ... * ] * If "column" property is not set, this editor is used for all columns and the * rest of the array members are ignored. If "callback" property is specified, * "editor" property is ignored. * * <b>autoSaveCell</b> [string] URL of server side script that is used for * checking and saving of individual cell. * * <b>callbackAutoSaveCell</b> [function] Callback function that is used for * checking of server side script response. It receives following object: * { * response: [object] XMLHttpRequest object * } * If cell was saved successfully, callback function must return true. * * <strong>In addition to events fired from base Zapatec.Grid class fires * following events:</strong> * * <b>gridCellEdit</b> before grid cell is turned into editable state and after * calling of callbackCellEdit. Event listener receives cell object that is * being modified. * * <b>gridCellSaved</b> when HTTP success response is received from the server * and callbackAutoSaveCell config option is not defined or callback function * returns true. Event listener receives following object as argument: * { * cell: [object] cell object, * request: [object] XMLHttpRequest object (see * {@link Zapatec.Transport#fetch} for details) * } * * <b>gridCellNotSaved</b> when HTTP error response is received from the server * or callbackAutoSaveCell config option is defined and callback function * doesn't return true. Event listener receives following object as argument: * { * cell: [object] cell object, * error: [object] error object (see {@link Zapatec.Transport#fetch} for * details) * } * * <b>gridCellEdited</b> before turning cell into read-only state if it was * changed. Event listener receives following object: * { * cell: [object] edited cell, * previousState: [object] cell before editing * } * * <b>gridEdited</b> when grid cell is turned into read-only state and after * calling of callbackCellReadOnly. Event listener receives edited cell object * as argument. * </pre> * * @constructor * @extends Zapatec.Grid * @param {object} oArg User configuration */Zapatec.EditableGrid = function(oArg) { // Call constructor of superclass Zapatec.EditableGrid.SUPERconstructor.call(this, oArg);};// Inherit GridZapatec.inherit(Zapatec.EditableGrid, Zapatec.Grid);/** * Configures editable grid. Extends parent method. * * @private * @param {object} oArg User configuration */Zapatec.EditableGrid.prototype.configure = function(oArg) { // Define config options this.defineConfigOption('callbackCellEdit'); this.defineConfigOption('callbackCellReadOnly'); this.defineConfigOption('externalEditors', []); this.defineConfigOption('autoSaveCell'); this.defineConfigOption('callbackAutoSaveCell'); // Call parent method Zapatec.EditableGrid.SUPERclass.configure.call(this, oArg); // Setup autosaving var oConfig = this.config; if (oConfig.autoSaveCell) { this.addEventListener('gridCellEdited', this.saveCell); if (typeof this.visualizeCellSaved == 'function') { this.addEventListener('gridCellSaved', this.visualizeCellSaved); } if (typeof this.visualizeCellNotSaved == 'function') { this.addEventListener('gridCellNotSaved', this.visualizeCellNotSaved); } }};/** * Extends parent method. * * @private * @param {objcet} oCell Cell object * @return Converted cell object * @type object */Zapatec.EditableGrid.prototype.convertCell = function(oCell) { var oField = this.getFieldByCell(oCell); if (oField && oField.list && !oCell.innerHTML) { // Parse HTML fragment var oTmpContr = Zapatec.Transport.parseHtml(oCell.v); if (oTmpContr.firstChild) { if (oTmpContr.firstChild.nodeType == 1 && oTmpContr.firstChild.nodeName.toLowerCase() == 'select') { // Save original select tag oCell.innerHTML = oCell.v; // Remove old value var undef; oCell.v = undef; // Value to display var sVal; // Iterate over values var oOption = oTmpContr.firstChild.firstChild; while (oOption) { if (oOption.nodeType == 1 && oOption.nodeName.toLowerCase() == 'option') { // Opera doesn't set selected property correctly if (oOption.selected || oOption.getAttribute('selected') || typeof oCell.v == 'undefined') { // Set selected value if (oOption.value.length) { oCell.v = oOption.value; // Check if value attribute is the same as displayed text if (oCell.v != oOption.innerHTML) { sVal = oOption.innerHTML; } } else { oCell.v = oOption.innerHTML; } } } // Next value oOption = oOption.nextSibling; } // Modify value to display if (typeof sVal != 'undefined') { oCell = Zapatec.EditableGrid.SUPERclass.convertCell.call(this, oCell); oCell.v = sVal; return oCell; } } else if ((oCell.values instanceof Array) && oCell.values.length) { // For backward compatibility var aHtml = []; aHtml.push('<select>'); for (var iVal = 0; iVal < oCell.values.length; iVal++) { var sVal = oCell.values[iVal]; aHtml.push('<option'); if (sVal == oCell.v) { aHtml.push(' selected'); } aHtml.push('>'); aHtml.push(sVal); aHtml.push('</option>'); } aHtml.push('</select>'); oCell.innerHTML = aHtml.join(''); } else { // Single value oCell.innerHTML = '<select><option selected>' + oCell.v + '</option></select>'; } } } return Zapatec.EditableGrid.SUPERclass.convertCell.call(this, oCell);};// Check if zpgrid-html.js is loadedif (Zapatec.Grid.prototype.newFieldHtml) { /** * Extends parent method. * * @private * @param {object} oCell Element object * @return Field object * @type object */ Zapatec.EditableGrid.prototype.newFieldHtml = function(oCell) { // Call parent method var oField = Zapatec.EditableGrid.SUPERclass.newFieldHtml.call(this, oCell); // Set noedit flag if (oCell.className.indexOf('zpGridTypeNoedit') >= 0) { oField.noedit = true; } // Set list flag if (oCell.className.indexOf('zpGridTypeList') >= 0) { oField.list = true; } return oField; };}// Check if zpgrid-xml.js is loadedif (Zapatec.Grid.prototype.newFieldXml) { /** * Extends parent method. * * @private * @param {object} oCell Source object * @return Field object * @type object */ Zapatec.EditableGrid.prototype.newFieldXml = function(oCell) { // Call parent method var oField = Zapatec.EditableGrid.SUPERclass.newFieldXml.call(this, oCell); // Set noedit flag if (oCell.getAttribute('noedit') == 'true') { oField.noedit = true; } // Set list flag if (oCell.getAttribute('list') == 'true') { oField.list = true; } return oField; };}/** * Keydown event handler in editable mode. * * @private * @param {number} iRowId Row id * @param {number} iCellId Cell id */Zapatec.EditableGrid.prototype.inputKeyDown = function(iRowId, iCellId) { // Get Event object if (!window.event) { return; } // Skip Shift, Ctrl and Alt buttons because they are used only as modifiers if (window.event.keyCode >= 16 && window.event.keyCode <= 18) { return true; } // Get target element var oElement = window.event.srcElement || window.event.target; if (!oElement) { return; } // Get row object var oRow = this.getRowById(iRowId); if (!oRow) { return; } // Get field object var oField = this.getFieldById(iCellId); if (!oField) { return; } // Get cell object var oCell = this.getCellById(iRowId, iCellId); if (!oCell) { return; } // Process key switch (window.event.keyCode) { case 27: // Esc return this.inputButtonEsc(oCell, window.event, oElement); case 13: // Enter return this.inputButtonEnter(oCell, window.event, oElement); case 0: // Shift+Tab in Safari only if (/Safari/i.test(navigator.userAgent)) { return this.inputButtonTab(oCell, window.event, oElement); } break; case 9: // Tab return this.inputButtonTab(oCell, window.event, oElement); }};/** * Focus lost event handler for edited cell. * * @private * @param {number} iRowId Row id
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -