📄 form.js.svn-base
字号:
/*Class: FlashSYS.Form Dynamic form generatorCopyright: Copyright (C) 2008 OpenRB.comArguments: container - (element or id) form will be placed inside this container options - (object)Returns: class instanceOptions: module - (string) form module id, required for proper window closing saveModule - (string) module name for submit event (defaults to 'module' option) saveAction - (string) action name for submit event (defaults to 'save') reload - (string or null) module name to reload after form is saved params - (object) extra parameters for submit event function prefix - (string) id prefix, defaults to 'fsform_' trPrefix - (string) translation key prefix submit - (function) executed on form submit submitParam - (mixed) second parameter for submit function submitEl - (element or null) container for submit button elements - (array) form elements and their options classPrefix - (string) form css class prefix postAll - (boolean) post either all visible form values or only changed ones (enabled by default) forceReload - (boolean) forces from reload (cache is not used) NOT IMPLEMENTED tabs - (array or null) split form by tabs using array of tab names reboot - (boolean) 'apply changes' will required system reboot if any data has changed addChange - (boolean) do 'apply changes' if any part of the form has changed iframe - (boolean) if set to true, iframe will be used instead of Ajax request, used for file uploads callback - (function) used only when iframe is enabled, iframe JSON-decoded key 'params' will be passed to it cbParam - (mixed) extra parameter for callback changeModule - (string or null) module name for 'apply changes', form module will be used if not specified changeAction - (string or null) action name for 'apply changes' changeNoId - (boolean) pass id to FlashSYS.addChange or not, should be used if the whole module needs to be restarted validate - (boolean) use validation or not (enabled by default) skipAutoSize - (boolean) skip auto form size or not (not skipped by default)Properties: blocks - (object) form block cache elements - (object) form element cache labels - (object) form label cache elemWraps - (object) form element wrap cache (used in validation) elemTabs - (object) form element tab number cache (used in validation) selectBlocks - (object) block cache for select element show/hide feature elemTypes - (object) cache elem types for faster check when loading initial values tab - (null or element) current output tab block - (null or element) current output block initial - (object) initial form values after loadValues call changes - (object) cache of elements that have addChange property set errors - (object) contains error messages per element when validation is used validation - (object) per item validation table activeTab - (integer) current active output tab, -1 specifies that tabs are not used*/FlashSYS.Form = new Class({ Implements: [Options], blocks: {}, elements: {}, labels: {}, elemWraps: {}, elemTabs: {}, selectBlocks: {}, callbacks: {}, elemTypes: {}, tab: null, block: null, initial: {}, changes: {}, errors: {}, validation: {}, activeTab: -1, options: { module: '', saveModule: null, saveAction: 'save', reload: null, params: {}, trPrefix: '', prefix: '', submit: null, submitParam: null, submitEl: null, elements: [], classPrefix: 'FSForm', postAll: true, forceReload: false, tabs: false, reboot: false, addChange: false, iframe: false, callback: $empty, cbParam: null, changeModule: null, changeAction: null, changeNoId: false, validate: true, skipAutoSize: false }, initialize: function(container, options) { this.container = $(container); this.setOptions(options); // set form id this.formId = (this.options.prefix ? this.options.prefix + '_' : 'fsform_') + FlashSYS.idCounter.toString(); FlashSYS.idCounter++; var containerSize = this.container.getSize(); var formOptions = { 'id': this.formId, 'method': 'post', 'events': { 'submit': this.formSubmit.bind(this) } }; if (!this.options.skipAutoSize) { formOptions.styles = { 'width': containerSize.x - this.container.getStyle('padding-left').toInt() - this.container.getStyle('padding-right').toInt(), 'height': containerSize.y - this.container.getStyle('padding-top').toInt() - this.container.getStyle('padding-bottom').toInt() }; } // add extra form parameters when using file upload / iframe if (this.options.iframe) { formOptions.enctype = 'multipart/form-data'; formOptions.action = FlashSYS.requestUrl({ 'module': (this.options.saveModule || this.options.module), 'action': this.options.saveAction }); formOptions.target = this.formId + '_iframe'; this.iframe = new FSFrame({ 'id': formOptions.target, 'name': formOptions.target, 'class': 'Hidden', 'load': this.iframeLoaded.bind(this) }).inject(document.body); } this.hint = new Element('div', { 'id': this.formId + '_hint', 'class': this.options.classPrefix + 'ErrorHint' }).inject(document.body); this.form = new Element('form', formOptions).inject(this.container, 'top'); /* // cache form for later re-use if (!this.options.forceReload) { FlashSYS.formInstances[ this.formId ] = this.form; } */ // default submit container if not specified if (!this.options.submitEl) { this.options.submitEl = this.form; } // default container - form itself this.injectTo = this.form; this.initTabs(); // add new elements and submit button this.options.elements.each(this.addElement, this); this.addSubmit(); this.showAllBlocks(); return this; }, /* Function: serialize Saves form values in an object Returns: Object with form field values */ serialize: function() { var formValues = {}; for (var name in this.elements) { var value = null, type = '', elem = this.elements[ name ]; switch ($type(elem)) { // direct element pointer case 'element': if (elem.type) { type = elem.type.toLowerCase(); value = this.getElemValue(elem, type); } break; // array of radio buttons case 'array': elem.each(function(radioElem){ type = radioElem.type.toLowerCase(); value = $pick(value, this.getElemValue(radioElem, type)); }, this); break; } if (value !== null) { formValues[ name ] = (type == 'password' ? value : value.toString().trim()); } } return formValues; }, /* Function: getElement Gets element element reference based on element's id Arguments: elemName - (string) element's id Returns: Element or undefined if element with gived id does not exist */ getElement: function(elemName) { return this.elements[ elemName ]; }, /* Function: getElemValue Gets element value taking care of block visibility Arguments: elem - (element) to get value from type - (string) element type Returns: Element value or null if element is not visible (block is hidden) or not found */ getElemValue: function(elem, type) { var value = Element.get(elem, 'value'); if (value === false || !elem.name || (type == 'radio' && !elem.checked)) { return null; } // empty checkboxes should be posted aswell if (type == 'checkbox' && !elem.checked) { value = elem.retrieve('falseValue', ''); } // check block visibility var block = elem.retrieve('block'); return block === null || !(block.getStyle('display') == 'none' || block.hasClass('Hidden')) ? value : null; }, /* Function: addElement Adds an element to the form depending on its type Arguments: elem - (string or object) new element properties */ addElement: function(elem) { var fn = '_'; if ($type(elem) == 'string') { fn += elem; } else { this.elemTypes[ elem.name ] = elem.type; fn += elem.type; if (elem.addChange !== undefined) { this.changes[ elem.name ] = elem.addChange; } } if (elem.validate) { this.validation[ elem.name ] = elem.validate; this.elemTabs[ elem.name ] = this.activeTab; } this[fn](elem); }, /* Function: cacheElement Caches element and it's block if specified Arguments: name - (string) element's name (used in id generation also) elem - (string or object) element properties */ cacheElement: function(name, elem) { if (this.block) { $splat(elem).each(function(subElem){ subElem.store('block', this.block); }, this); } this.elements[ name ] = elem; }, /* Function: initTabs Initializes tabs if they were specified in options */ initTabs: function() { if ($type(this.options.tabs) == 'array') { this.tabs = new FlashSYS.Tabs(this.form, { 'trPrefix': this.options.trPrefix + 'tab_', 'tabs': this.options.tabs }); // switch to first tab for output this.tab = this.tabs.getPanelByIndex(0); this.injectTo = this.tab; this.activeTab = 0; } }, /* Function: loadValues Load values for corresponding form elems, take care of hiding blocks depending on select elements' value Arguments: values - (object) corresponding element values params - (object) optional form params to be passed on submit event Returns: class instance */ loadValues: function(values, params) { if (params) { this.options.params = $merge(this.options.params, params); } $each(values || {}, function(value, name){ var elem = this.elements[ name ]; if (!elem || value == undefined) { return; } value = value.toString(); switch ($type(elem)) { // direct element pointer case 'element': var elemTag = elem.get('tag'); var curValue = elem.get('value'); // plain text element if (elemTag == 'span') { elem.set('text', value); } // checkbox have constant value, set checked attribute instead else if (elem.type == 'checkbox') { elem.checked = curValue == value; } // non-checkbox elements else if (curValue != value) { elem.set('value', value); } // check block visibility for select element if (elemTag == 'select') { this.selectChange(name); } break; // array of radio buttons case 'array': var checked = false; elem.each(function(radioElem){ if (checked) return; checked = radioElem.get('value') == value; radioElem.checked = checked; }, this); // check first radio button if given value differs from any radio button if (!checked && elem[0]) { elem[0].checked = true; } break; default: return; } }, this); this.initial = this.serialize(); return this; }, /* Function: elemWrap Creates element wrapper and label Arguments: wrapOptions - (object) new wrapper element options Returns: Container element */ elemWrap: function(wrapOptions) { var elemName = wrapOptions.name; // create wrap var wrap = new Element('div', { 'class': this.options.classPrefix + 'ElemWrap' }).inject(this.injectTo); this.elemWraps[ elemName ] = wrap; if (wrapOptions.wrapCls) { wrap.addClass(wrapOptions.wrapCls); } if (!wrapOptions.skipLabel) { var title = wrapOptions.title || elemName; // create label this.labels[ elemName ] = new Element('label', { 'for': this.formId + '_elem_' + elemName, 'class': this.options.classPrefix + 'Label', 'text': wrapOptions.noTranslate ? title : FlashSYS.translate(this.options.trPrefix + title), 'events': { 'mouseover': this.showHint.bind(this, elemName), 'mouseout': this.hideHint.bind(this) } }).inject(wrap); } // return container element return new Element('div', { 'class': this.options.classPrefix + 'Container' }).inject(wrap); }, /* Function: showHint Executed when mouse pointer is over form label, show hint / error message when required Arguments: elemName - (string) name of the label / element that caused this event */ showHint: function(elemName) { var label = this.labels[ elemName ], errors = this.errors[ elemName ]; if (!label || !errors) { return; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -