// Copyright (c) 2012 Web Notes Technologies Pvt Ltd (http://erpnext.com) // // MIT License (MIT) // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the "Software"), // to deal in the Software without restriction, including without limitation // the rights to use, copy, modify, merge, publish, distribute, sublicense, // and/or sell copies of the Software, and to permit persons to whom the // Software is furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // fields.js // // Fields are divided into 2 types // 1. Standard fields are loaded with the libarary // 2. Special fields are loaded with form.compressed.js // // // + wrapper // + input_area // + display_area // ====================================================================================== var no_value_fields = ['Section Break', 'Column Break', 'HTML', 'Table', 'FlexTable', 'Button', 'Image']; var codeid=0; var code_editors={}; function Field() { this.with_label = 1; } Field.prototype.make_body = function() { var ischk = (this.df.fieldtype=='Check' ? 1 : 0); // parent element this.$wrapper = $('
\ \
\
\
\
\
').appendTo(this.parent); this.wrapper = this.$wrapper.get(0); this.label_area = this.label_span = this.$wrapper.find(".control-label").get(0); this.input_area = this.$wrapper.find(".control-input").get(0); this.disp_area = this.$wrapper.find(".control-value").get(0); // set description this.set_description(); if(this.onmake)this.onmake(); } Field.prototype.set_max_width = function() { var no_max = ['Code', 'Text Editor', 'Text', 'Small Text', 'Table', 'HTML'] if(this.wrapper && this.layout_cell && this.layout_cell.parentNode.cells && this.layout_cell.parentNode.cells.length==1 && !in_list(no_max, this.df.fieldtype)) { $y(this.wrapper, {paddingRight:'50%'}); } } Field.prototype.set_label = function(label) { this.label_span.innerHTML = wn._(label || this.df.label); } Field.prototype.set_description = function(txt) { if(txt) { if(!this.$wrapper.find(".help-box").length) { $('

').appendTo(this.input_area); } this.$wrapper.find(".help-box").html(txt); } else { this.$wrapper.find(".help-box").empty().toggle(false); } } Field.prototype.get_status = function(explain) { if(!this.doctype) return "Write"; return wn.perm.get_field_display_status(this.df, locals[this.doctype][this.docname], this.perm, explain) } Field.prototype.refresh_mandatory = function() { if(this.in_filter)return; //this.$wrapper.toggleClass("has-warning", cint(this.df.reqd) ? true : false); this.refresh_label_icon() } Field.prototype.refresh_display = function() { // from permission if(!this.current_status || this.current_status!=this.disp_status) { // status changed if(this.disp_status=='Write') { // write if(this.make_input&&(!this.input)) { // make input if reqd this.make_input(); if(this.txt || this.input) $(this.txt || this.input).addClass("mousetrap"); if(this.onmake_input) this.onmake_input(); } if(this.show) this.show() else { $ds(this.wrapper); } // input or content if(this.input) { // if there, show it! $ds(this.input_area); $dh(this.disp_area); if(this.input.refresh) this.input.refresh(); } else { // no widget $dh(this.input_area); $ds(this.disp_area); } } else if(this.disp_status=='Read') { // read if(this.show) this.show() else { $ds(this.wrapper); } $dh(this.input_area); $ds(this.disp_area); } else { // None - hide all if(this.hide) this.hide(); else $dh(this.wrapper); } this.current_status = this.disp_status; } } Field.prototype.refresh = function() { // get status this.disp_status = this.get_status(); // if there is a special refresh in case of table, then this is not valid if(this.in_grid && this.table_refresh && this.disp_status == 'Write') { this.table_refresh(); return; } this.set_label(); this.refresh_display(); if(this.input) { if(this.input.refresh) this.input.refresh(this.df); } // further refresh if(this.onrefresh) this.onrefresh(); // called by various fields if(this.wrapper) { this.wrapper.fieldobj = this; $(this.wrapper).trigger('refresh'); } if(!this.not_in_form) this.set_input(_f.get_value(this.doctype,this.docname,this.df.fieldname)); this.refresh_mandatory(); this.set_max_width(); } Field.prototype.refresh_label_icon = function() { // mandatory var to_update = false; if(this.df.reqd && this.get_value && is_null(this.get_value())) to_update = true; this.$wrapper.toggleClass("has-error", to_update); } Field.prototype.set = function(val) { // not in form if(this.not_in_form) return; if((!this.docname) && this.grid) { this.docname = this.grid.add_newrow(); // new row } if(this.validate) val = this.validate(val); cur_frm.set_value_in_locals(this.doctype, this.docname, this.df.fieldname, val); this.value = val; // for return } Field.prototype.set_input = function(val) { this.value = val; if(this.input && this.input.set_input) { this.input.set_input(val); // in widget } var disp_val = val; if(val==null) disp_val = ''; this.set_disp(disp_val); // text } Field.prototype.run_trigger = function() { // update mandatory icon this.refresh_label_icon(); if(this.not_in_form) { return; } if(cur_frm.cscript[this.df.fieldname]) cur_frm.runclientscript(this.df.fieldname, this.doctype, this.docname); cur_frm.refresh_dependency(); } Field.prototype.set_disp_html = function(t) { if(this.disp_area){ $(this.disp_area).addClass('disp-area'); this.disp_area.innerHTML = (t==null ? '' : t); if(!t) $(this.disp_area).addClass('disp-area-no-val'); } } Field.prototype.set_disp = function(val) { this.set_disp_html(val); } Field.prototype.get_input = function() { return this.txt || this.input; } // for grids (activate against a particular record in the table Field.prototype.activate = function(docname) { this.docname = docname; this.refresh(); if(this.input) { var v = _f.get_value(this.doctype, this.docname, this.df.fieldname); this.last_value=v; // set input value if(this.input.onchange && this.input.get_value && this.input.get_value() !=v) { if(this.validate) this.input.set_value(this.validate(v)); else this.input.set_value((v==null)?'':v); if(this.format_input) this.format_input(); } if(this.input.focus){ try{this.input.focus();} catch(e){} // IE Fix - Unexpected call??? } } if(this.txt) { try{this.txt.focus();} catch(e){} // IE Fix - Unexpected call??? this.txt.field_object = this; } } function DataField() { } DataField.prototype = new Field(); DataField.prototype.make_input = function() { var me = this; this.input = $a_input(this.input_area, this.df.fieldtype=='Password' ? 'password' : 'text'); if(this.df.placeholder) $(this.input).attr("placeholder", this.df.placeholder); this.get_value= function() { var v = this.input.value; if(this.validate) v = this.validate(v); return v; } this.input.name = this.df.fieldname; $(this.input).blur(function() { me.set_value(me.get_value ? me.get_value() : $(this).val()); }); this.set_value = function(val) { if(!me.last_value) me.last_value=undefined; if(me.validate) { val = me.validate(val); if(me.last_value === val) return; me.input.value = (val==undefined) ? '' : val; } else if(me.last_value === val) { return; } me.set(val); if(me.format_input) me.format_input(); if(in_list(['Currency','Float','Int'], me.df.fieldtype)) { if(flt(me.last_value)==flt(val)) { me.last_value = val; return; // do not run trigger } } me.last_value = val; me.run_trigger(); } this.input.set_input = function(val) { if(val==null)val=''; me.input.value = val; if(me.format_input)me.format_input(); } } DataField.prototype.validate = function(v) { if(this.df.options == 'Phone') { if(v+''=='')return ''; v1 = '' // phone may start with + and must only have numbers later, '-' and ' ' are stripped v = v.replace(/ /g, '').replace(/-/g, '').replace(/\(/g, '').replace(/\)/g, ''); // allow initial +,0,00 if(v && v.substr(0,1)=='+') { v1 = '+'; v = v.substr(1); } if(v && v.substr(0,2)=='00') { v1 += '00'; v = v.substr(2); } if(v && v.substr(0,1)=='0') { v1 += '0'; v = v.substr(1); } v1 += cint(v) + ''; return v1; } else if(this.df.options == 'Email') { if(v+''=='')return ''; if(!validate_email(v)) { msgprint(this.df.label + ': ' + v + ' is not a valid email id'); return ''; } else return v; } else { return v; } } // ====================================================================================== function ReadOnlyField() { } ReadOnlyField.prototype = new Field(); // ====================================================================================== function HTMLField() { var me = this; this.make_body = function() { me.wrapper = $("
").appendTo(me.parent); } this.set_disp = function(val) { if(val) $(me.wrapper).html(val); } this.set_input = function(val) { me.set_disp(val); } this.refresh = function() { if(me.df.options) me.set_disp(me.df.options); } } // ====================================================================================== var datepicker_active = 0; function get_datepicker_options() { var datepicker_options = { dateFormat: (sys_defaults.date_format || 'yy-mm-dd').replace('yyyy','yy'), altFormat:'yy-mm-dd', changeYear: true, yearRange: "-70Y:+10Y", beforeShow: function(input, inst) { datepicker_active = 1 }, onClose: function(dateText, inst) { datepicker_active = 0; if(_f.cur_grid_cell) _f.cur_grid_cell.grid.cell_deselect(); }, } return datepicker_options; } function DateField() { } DateField.prototype = new Field(); DateField.prototype.make_input = function() { var me = this; this.input = $("") .appendTo(this.input_area).get(0); $(this.input).datepicker(get_datepicker_options()); this.setup_input(); } DateField.prototype.setup_input = function() { var me = this; me.input.onchange = function() { // input as dd-mm-yyyy if(this.value==null)this.value=''; if(!this.not_in_form) me.set(dateutil.user_to_str(me.input.value)); me.run_trigger(); } me.input.set_input = function(val) { if(val==null)val=''; else val=dateutil.str_to_user(val); me.input.value = val; } me.get_value = function() { if(me.input.value) return dateutil.user_to_str(me.input.value); } } DateField.prototype.set_disp = function(val) { var v = dateutil.str_to_user(val); if(v==null)v = ''; this.set_disp_html(v); } DateField.prototype.validate = function(v) { var v = wn.datetime.validate(v); if(!v) { msgprint (wn._("Date must be in format") + ": " + (sys_defaults.date_format || "yyyy-mm-dd")); this.input.set_input(''); return ''; } return v; }; // reference when a new record is created via link function LinkField() { } LinkField.prototype = new Field(); LinkField.prototype.make_input = function() { var me = this; if(me.df.no_buttons) { this.txt = $("") .appendTo(this.input_area).get(0); this.input = this.txt; } else { me.input = me.input_area; me.input_group = $('