瀏覽代碼

[form] [controls] wip rewriting fields js

version-14
Rushabh Mehta 12 年之前
父節點
當前提交
10bc9e36c5
共有 18 個檔案被更改,包括 709 行新增664 行删除
  1. +1
    -0
      public/build.json
  2. +0
    -10
      public/css/legacy/fields.css
  3. +0
    -4
      public/css/legacy/forms.css
  4. +23
    -0
      public/css/ui/common.css
  5. 二進制
      public/images/ui/cancelled.png
  6. 二進制
      public/images/ui/submitted.png
  7. +8
    -4
      public/js/legacy/utils/datatype.js
  8. +16
    -554
      public/js/legacy/widgets/form/fields.js
  9. +1
    -2
      public/js/legacy/widgets/form/form.js
  10. +0
    -78
      public/js/legacy/widgets/form/form_comments.js
  11. +1
    -1
      public/js/wn/dom.js
  12. +114
    -0
      public/js/wn/form/comments.js
  13. +431
    -0
      public/js/wn/form/control.js
  14. +72
    -0
      public/js/wn/form/footer.js
  15. +3
    -5
      public/js/wn/form/formatters.js
  16. +1
    -1
      public/js/wn/form/layout.js
  17. +30
    -2
      public/js/wn/model/model.js
  18. +8
    -3
      public/js/wn/ui/appframe.js

+ 1
- 0
public/build.json 查看文件

@@ -152,6 +152,7 @@

"lib/public/js/wn/form/toolbar.js",
"lib/public/js/wn/form/layout.js",
"lib/public/js/wn/form/control.js",
"lib/public/js/wn/form/editors.js",
"lib/public/js/wn/form/grid.js",
"lib/public/js/wn/form/attachments.js",


+ 0
- 10
public/css/legacy/fields.css 查看文件

@@ -18,13 +18,3 @@
padding-left: 6px;
padding-right: 6px;
}

.disp-area {
background-color: #eee;
padding: 6px;
margin-bottom: 7px;
border-radius: 3px;
}
.disp-area-no-val {
height: 30px;
}

+ 0
- 4
public/css/legacy/forms.css 查看文件

@@ -56,10 +56,6 @@ div.dialog_frm {
margin: 10px;
}



/*------------------*/

.top_cell {
height: 50px;
}


+ 23
- 0
public/css/ui/common.css 查看文件

@@ -152,6 +152,21 @@ a {
outline: none;
}

/* appframe header */

.appframe-header {
background-color: #eee;
padding-bottom: 10px;
margin-bottom: 15px;
border-bottom: 1px solid #ddd;
}

/* form */

textarea[data-fieldtype="Small Text"] {
height: 60px;
}

/* form grid */

.rows .grid-row .divider {
@@ -179,4 +194,12 @@ a {
border: 1px dashed #ddd;
padding: 15px;
padding-top: 0px;
}

.like-disabled-input {
background-color: #eee;
padding: 6px;
margin-bottom: 7px;
border-radius: 3px;
min-height: 30px;
}

二進制
public/images/ui/cancelled.png 查看文件

Before After
Width: 305  |  Height: 86  |  Size: 3.2 KiB

二進制
public/images/ui/submitted.png 查看文件

Before After
Width: 305  |  Height: 86  |  Size: 3.6 KiB

+ 8
- 4
public/js/legacy/utils/datatype.js 查看文件

@@ -69,12 +69,16 @@ function replace_newlines(t) {
}

function cint(v, def) {
if(v===true) return 1;
v=v+'';
if(v===true)
return 1;
if(v===false)
return 0;
v=v+'';
v=lstrip(v, ['0']);
v=parseInt(v);
if(isNaN(v))v=def?def:0;
return v;
return isNaN(v) ?
(def ? def : 0) :
v
}
function validate_email(txt) {
return wn.utils.validate_type(txt, "email");


+ 16
- 554
public/js/legacy/widgets/form/fields.js 查看文件

@@ -38,11 +38,9 @@ function Field() {
this.with_label = 1;
}

Field.prototype.make_body = function() {
var ischk = (this.df.fieldtype=='Check' ? 1 : 0);
Field.prototype.make_body = function() {
// parent element
this.$wrapper = $('<div class="control-group">\
this.$wrapper = $('<div class="control-group" style="max-width: 600px;">\
<label class="control-label"></label>\
<div class="controls">\
<div class="control-input"></div>\
@@ -244,35 +242,6 @@ Field.prototype.get_input = function() {
}


// 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;
@@ -354,11 +323,6 @@ DataField.prototype.validate = function(v) {

// ======================================================================================

function ReadOnlyField() { }
ReadOnlyField.prototype = new Field();

// ======================================================================================

function HTMLField() {
var me = this;
this.make_body = function() {
@@ -377,75 +341,6 @@ function HTMLField() {
}
}

// ======================================================================================

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 = $("<input type='text' data-fieldtype='Date'>")
.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() {
@@ -735,464 +630,29 @@ LinkField.prototype.set_disp = function(val) {
this.set_disp_html(t);
}

// ======================================================================================

function IntField() { } IntField.prototype = new DataField();
IntField.prototype.validate = function(v) {
if(isNaN(parseInt(v)))return null;
return cint(v);
};
IntField.prototype.format_input = function() {
if(this.input.value==null) this.input.value='';
}

// ======================================================================================

function FloatField() { } FloatField.prototype = new DataField();
FloatField.prototype.validate = function(v) {
if(isNaN(parseFloat(v)))
return null;
else
v = flt(v);
return v;
};
FloatField.prototype.format_input = function() {
if(this.input.value==null || this.input.value=='')
this.input.value='';
else {
var format;
if(this.get_field_currency) {
format = get_number_format(this.get_field_currency());
this.input.value =
format_number(parseFloat(this.input.value), format);
} else {
var decimals = wn.boot.sysdefaults.float_precision ?
parseInt(wn.boot.sysdefaults.float_precision) : null;
this.input.value = format_number(parseFloat(this.input.value), null, decimals);
}
}
}
FloatField.prototype.onmake_input = function() {
if(!this.input) return;
this.input.onfocus = function() {
this.select();
}
}
FloatField.prototype.set_disp = function(val) {
this.set_disp_html(wn.format(val, this.df, null, locals[this.doctype][this.name]));
}

function PercentField() { } PercentField.prototype = new FloatField();
PercentField.prototype.set_disp = function(val) {
this.set_disp_html(wn.format(val, this.df));
}

function CurrencyField() { } CurrencyField.prototype = new FloatField();

CurrencyField.prototype.validate = function(v) {
if(v==null || v=='')
return 0;
return flt(v, null, get_number_format(this.get_field_currency()));
}

CurrencyField.prototype.get_field_currency = function() {
var doc = null;
if(this.doctype && this.docname && locals[this.doctype])
doc = locals[this.doctype][this.docname];
return wn.meta.get_field_currency(this.df, doc);
};

CurrencyField.prototype.get_formatted = function(val) {
if(this.not_in_form)
return val;
return format_currency(val, this.get_field_currency());
}
CurrencyField.prototype.set_disp = function(val) {
this.set_disp_html(this.get_formatted(val));
}

function CheckField() { } CheckField.prototype = new Field();
CheckField.prototype.validate = function(v) {
return cint(v);
};
CheckField.prototype.onmake = function() {
this.checkimg = $("<i class='icon-check'></i>").appendTo(this.disp_area);
}

CheckField.prototype.make_input = function() { var me = this;
this.input = $("<input type='checkbox'>")
.appendTo(this.input_area)
.get(0);
$(this.input).change(function() {
me.set(this.checked ? 1 : 0);
me.run_trigger();
})
this.input.set_input = function(v) {
me.input.checked = cint(v) ? true : false;
}

this.get_value= function() {
return this.input.checked ? 1 : 0;
}

}
CheckField.prototype.set_disp = function(val) {
this.checkimg.toggle(cint(val) ? true : false);
}


function TextField() { } TextField.prototype = new Field();
TextField.prototype.set_disp = function(val) {
this.disp_area.innerHTML = replace_newlines(val);
}
TextField.prototype.make_input = function() {
var me = this;
if(this.in_grid)
return; // do nothing, text dialog will take over
this.input = $a(this.input_area, 'textarea');

if(this.df.fieldtype=='Small Text') {
$(this.input).css({height: "60px"});
} else if(this.df.width) {
$(this.input).css({height: cint(this.df.width) + "px"});
} else {
$(this.input).css({height: "60px"});
}
this.input.set_input = function(v) {
me.input.value = (v==null ? "" : v);
}
this.input.onchange = function() {
me.set(me.input.value);
me.run_trigger();
}
this.get_value= function() {
return this.input.value;
}
}

// text dialog
var text_dialog;
function make_text_dialog() {
var d = new Dialog(520,410,'Edit Text');
d.make_body([
['Text', 'Enter Text'],
['HTML', 'Description'],
['Button', 'Update']
]);
d.widgets['Update'].onclick = function() {
var t = this.dialog;
t.field.set(t.widgets['Enter Text'].value);
t.hide();
}
d.onshow = function() {
this.widgets['Enter Text'].style.height = '300px';
var v = _f.get_value(this.field.doctype,this.field.docname,this.field.df.fieldname);
this.widgets['Enter Text'].value = v==null?'':v;
this.widgets['Enter Text'].focus();
this.widgets['Description'].innerHTML = ''
if(this.field.df.description)
$a(this.widgets['Description'], 'div', 'help small', '', this.field.df.description);
}
d.onhide = function() {
if(_f.cur_grid_cell)
_f.cur_grid_cell.grid.cell_deselect();
}
text_dialog = d;
}

TextField.prototype.table_refresh = function() {
if(!this.text_dialog)
make_text_dialog();
text_dialog.set_title(wn._('Enter text for')+': "'+ wn._(this.df.label) +'"');
text_dialog.field = this;
text_dialog.show();
}


// Select
// ======================================================================================

function SelectField() { } SelectField.prototype = new Field();
SelectField.prototype.make_input = function() {
var me = this;
var opt=[];
if(this.in_filter && (!this.df.single_select)) {
// multiple select
this.input = $a(this.input_area, 'select');
this.input.multiple = true;
this.input.style.height = '4em';
this.input.lab = $a(this.input_area, 'div', {fontSize:'9px',color:'#999'});
this.input.lab.innerHTML = '(Use Ctrl+Click to select multiple or de-select)'
} else {

// Single select
this.input = $a(this.input_area, 'select');
this.input.onchange = function() {
if(me.validate)
me.validate();
me.set(sel_val(this));
me.run_trigger();
}
if(this.df.options == 'attach_files:') {
this.attach_files = true;
$(this.input).css({"width": "70%"});
$("<button class='btn' title='Add attachment'\
style='margin-bottom: 9px; \
padding-left: 6px; padding-right: 6px; margin-left: 6px;'>\
<i class='icon-plus'></i></button>")
.click(function() {
cur_frm.attachments.new_attachment();
})
.appendTo(this.input_area);
}
}

// set as single (to be called from report builder)
this.set_as_single = function() {
var i = this.input;
i.multiple = false;
i.style.height = null;
if(i.lab)$dh(i.lab)
}
// refresh options list
this.refresh_options = function(options) {
if(options)
me.df.options = options;

if(this.attach_files)
this.set_attach_options();
if(typeof me.df.options=="object")
me.options_list = me.df.options || [""];
else
me.options_list = me.df.options?me.df.options.split('\n'):[''];

// add options
if(me.in_filter && me.options_list[0]!='') {
me.options_list = add_lists([''], me.options_list);
}
$(this.input).empty().add_options(me.options_list);
}
// refresh options
this.onrefresh = function() {
this.refresh_options();

if(this.not_in_form) {
this.input.value = '';
return;
}
if(_f.get_value)
var v = _f.get_value(this.doctype,this.docname,this.df.fieldname);
else {
if(this.options_list && this.options_list.length)
var v = this.options_list[0];
else
var v = null;
}
this.input.set_input(v);
}
var _set_value = function(value) {
// use option's value if dict, else use string for comparison and setting
for(var i in (me.options_list || [""])) {
var option = me.options_list[i];
if($.isPlainObject(option)){
option = option.value;
}
if(option === value) {
me.input.value = value;
break;
}
}
}
this.input.set_input=function(v) {
if(!v) {
if(!me.input.multiple) {
if(me.docname) { // if called from onload without docname being set on fields
_set_value(v);
me.set(me.get_value());
}
}
} else {
if(me.options_list) {
if(me.input.multiple) {
for(var i=0; i<me.input.options.length; i++) {
me.input.options[i].selected = 0;
if(me.input.options[i].value && inList(typeof(v)=='string'?v.split(","):v, me.input.options[i].value))
me.input.options[i].selected = 1;
}
} else {
_set_value(v);
}
}
}
}
this.get_value= function() {
if(me.input.multiple) {
var l = [];
for(var i=0;i<me.input.options.length; i++ ) {
if(me.input.options[i].selected)l[l.length] = me.input.options[i].value;
}
return l;
} else {
if(me.input.options) {
var val = sel_val(me.input);
if(!val && !me.input.selectedIndex)
val = me.input.options[0].value;
return val;
}
return me.input.value;
}
}
this.set_attach_options = function() {
if(!cur_frm) return;
var fl = cur_frm.doc.file_list;
if(fl) {
fl = JSON.parse(fl);
this.df.options = '';

for(var fname in fl) {
if(fname.substr(0,4)!="http")
fname = "files/" + fname;
this.df.options += '\n' + fname;
}

this.set_description("");
} else {
this.df.options = ''
this.set_description(wn._("Please attach a file first."))
}
}
this.refresh();
}

function TimeField() { } TimeField.prototype = new DataField();

function import_timepicker() {
wn.require("lib/js/lib/jquery/jquery.ui.slider.min.js");
wn.require("lib/js/lib/jquery/jquery.ui.sliderAccess.js");
wn.require("lib/js/lib/jquery/jquery.ui.timepicker-addon.css");
wn.require("lib/js/lib/jquery/jquery.ui.timepicker-addon.js");
}

TimeField.prototype.make_input = function() {
import_timepicker();
var me = this;
this.input = $('<input type="text">')
.appendTo(this.input_area)
.timepicker({
timeFormat: 'hh:mm:ss',
}).get(0);
this.input.set_input = function(v) {
$(me.input).val(v);
};
this.input.onchange = function() {
if(!this.not_in_form)
me.set(me.input.value);
me.run_trigger();
};
}

function DateTimeField() { } DateTimeField.prototype = new DateField();

DateTimeField.prototype.make_input = function() {
import_timepicker();
var me = this;

args = get_datepicker_options();
args.timeFormat = "hh:mm:ss";

this.input = $('<input type="text" data-fieldtype="Datetime">')
.appendTo(this.input_area)
.datetimepicker(args).get(0);
this.setup_input();
}

var tmpid = 0;

_f.ButtonField = function() { };
_f.ButtonField.prototype = new Field();
_f.ButtonField.prototype.set_label = function(label) { };
_f.ButtonField.prototype.make_input = function() { var me = this;

// make a button area for one button
if(!this.button_area)
this.button_area = $a(this.input_area, 'div','',{
marginBottom:'4px'});
// make the input
this.input = $btn(this.button_area,
me.df.label, null,
{fontWeight:'bold'}, null, 1)

$(this.input).click(function() {
if(me.not_in_form) return;
if(cur_frm.cscript[me.df.fieldname] && (!me.in_filter)) {
cur_frm.runclientscript(me.df.fieldname, me.doctype, me.docname);
} else {
cur_frm.runscript(me.df.options, me);
}
});
}

_f.ButtonField.prototype.hide = function() {
$dh(this.button_area);
};

_f.ButtonField.prototype.show = function() {
$ds(this.button_area);
};


_f.ButtonField.prototype.set = function(v) { }; // No Setter
_f.ButtonField.prototype.set_disp = function(val) { } // No Disp on readonly

function make_field(docfield, doctype, parent, frm, in_grid, hide_label) { // Factory
if(["Data", "Int", "Float", "Currency", "HTML", "Date", "Time", "DateTime",
"Text", "Small Text", "Long Text", "Check", "Button", "Select",
"Password", "Read Only"].indexOf(docfield.fieldtype)!=-1) {
return new wn.ui.form.make_control({
df: docfield,
doctype: doctype,
parent: parent,
hide_label: hide_label,
frm: frm
});
}

switch(docfield.fieldtype.toLowerCase()) {
// general fields
case 'data':var f = new DataField(); break;
case 'password':var f = new DataField(); break;
case 'int':var f = new IntField(); break;
case 'float':var f = new FloatField(); break;
case 'currency':var f = new CurrencyField(); break;
case 'percent':var f = new PercentField(); break;
case 'read only':var f = new ReadOnlyField(); break;
case 'link':var f = new LinkField(); break;
case 'long text': var f = new TextField(); break;
case 'date':var f = new DateField(); break;
case 'datetime':var f = new DateTimeField(); break;
case 'time':var f = new TimeField(); break;
case 'html':var f = new HTMLField(); break;
case 'check':var f = new CheckField(); break;
case 'text':var f = new TextField(); break;
case 'small text':var f = new TextField(); break;
case 'select':var f = new SelectField(); break;
case 'button':var f = new _f.ButtonField(); break;
// form fields
case 'code':var f = new _f.CodeField(); break;
@@ -1200,6 +660,8 @@ function make_field(docfield, doctype, parent, frm, in_grid, hide_label) { // Fa
case 'table':var f = new _f.TableField(); break;
case 'image':var f= new _f.ImageField(); break;
}
if(!f) console.log(docfield.fieldtype)

f.parent = parent;
f.doctype = doctype;


+ 1
- 2
public/js/legacy/widgets/form/form.js 查看文件

@@ -139,11 +139,10 @@ _f.Frm.prototype.setup = function() {
_f.Frm.prototype.setup_print_layout = function() {
var me = this;
this.print_wrapper = $('<div>\
<form class="form-inline">\
<form class="form-inline" style="margin-bottom: 10px;">\
<select class="col-span-2 preview-select"></select> \
<button class="btn btn-edit btn-info"><i class="icon-edit"></i> Edit</button>\
</form>\
<hr>\
<div class="print-format-area clear-fix" style="min-height: 400px;"></div>\
</div>').appendTo(this.layout_main).get(0);


+ 0
- 78
public/js/legacy/widgets/form/form_comments.js 查看文件

@@ -1,78 +0,0 @@
// 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.
//

wn.widgets.form.comments = {
n_comments: {},
comment_list: {},
sync: function(dt, dn, r) {
var f = wn.widgets.form.comments;

f.n_comments[dn] = r.n_comments;
f.comment_list[dn] = r.comment_list;
},
add: function(input, dt, dn, callback) {
$c('webnotes.widgets.form.comments.add_comment', wn.widgets.form.comments.get_args(input, dt, dn),
function(r,rt) {
// update the comments
wn.widgets.form.comments.update_comment_list(input, dt, dn);
// clean up the text area
input.value = '';
callback(input, dt, dn);
}
);
},
remove: function(dt, dn, comment_id, callback) {
$c('webnotes.widgets.form.comments.remove_comment',{
id:comment_id,
dt:dt,
dn:dn
}, callback
);
},
get_args: function(input, dt, dn) {
return {
comment: input.value,
comment_by: user,
comment_by_fullname: user_fullname,
comment_doctype: dt,
comment_docname: dn
}
},
update_comment_list: function(input, dt, dn) {
var f = wn.widgets.form.comments;
// update no of comments
f.n_comments[dn] = cint(f.n_comments[dn]) + 1;
// update comment list
f.comment_list[dn] = add_lists(
[f.get_args(input, dt, dn)],
f.comment_list[dn]
);
}
}

+ 1
- 1
public/js/wn/dom.js 查看文件

@@ -224,7 +224,7 @@ wn.dom.set_box_shadow = function(ele, spread) {
ele.loading_img = $('<img src="lib/images/ui/button-load.gif" \
style="margin-left: 4px; margin-bottom: -2px; display: inline;" />')
.insertAfter(ele);
}
}
}
$.fn.done_working = function() {
var ele = this.get(0);


+ 114
- 0
public/js/wn/form/comments.js 查看文件

@@ -0,0 +1,114 @@
wn.ui.form.Comments = Class.extend({
init: function(opts) {
$.extend(this, opts);
this.make();
},
make: function() {
var me = this;
this.wrapper =this.parent;
this.row = $("<div class='row'>").appendTo(this.parent);
this.input = $('<div class="col-span-10">\
<textarea rows="3"></textarea></div>')
.appendTo(this.row)
.find("textarea");
this.button = $('<div class="col-span-1">\
<button class="btn btn-go" class="col-span-1">\
<i class="icon-ok"></i></button>\
</div>')
.appendTo(this.row)
.find("button")
.click(function() {
me.add_comment();
});
this.list = $('<div class="comments" style="margin-top: 15px;"></div>')
.appendTo(this.parent);
},
refresh: function() {
var me = this;
if(this.frm.doc.__islocal) {
this.wrapper.toggle(false);
return;
}
this.wrapper.toggle(true);
this.list.empty();
var comments = JSON.parse(this.frm.doc.__comments || "[]");
$.each(comments, function(i, c) {
if(c.comment_by==user) {
c["delete"] = '<a class="close" href="#">&times;</a>';
}
c.image = wn.user_info(c.comment_by).image;
c.comment_on = dateutil.comment_when(c.creation);
c.fullname = wn.user_info(c.comment_by).fullname;
$(repl('<div class="comment alert col-span-10" data-name="%(name)s">\
<div class="row">\
<div class="col-span-1">\
<span class="avatar avatar-small"><img src="%(image)s"></span>\
</div>\
<div class="col-span-11">\
%(comment)s%(delete)s<br>\
<span class="small text-muted">%(fullname)s / %(comment_on)s</span>\
</div>\
</div>\
</div>', c))
.appendTo(me.list)
.on("click", ".close", function() {
var name = $(this).parent().attr("data-name");
me.delete_comment(name);
return false;
})
});
},
add_comment: function() {
var me = this,
txt = me.input.val();
if(txt) {
var comment = {
doctype: "Comment",
comment_doctype: me.frm.doctype,
comment_docname: me.frm.docname,
comment: txt,
comment_by: user
};
wn.call({
method: "webnotes.client.insert",
args: {
doclist:[comment]
},
callback: function(r) {
if(!r.exc) {
var comments = JSON.parse(me.frm.doc.__comments || "[]");
me.frm.doc.__comments = JSON.stringify(r.message.concat(comments));
me.input.val("");
me.refresh();
}
}
});
}
},
delete_comment: function(name) {
var me = this;
wn.call({
method: "webnotes.client.delete",
args: {
doctype: "Comment",
name: name
},
callback: function(r) {
if(!r.exc) {
me.frm.doc.__comments = JSON.stringify(
$.map(JSON.parse(me.frm.doc.__comments || "[]"),
function(v) {
if(v.name==name) return null;
else return v;
}
)
);
me.refresh();
}
}
});
}
})

+ 431
- 0
public/js/wn/form/control.js 查看文件

@@ -0,0 +1,431 @@
wn.ui.form.make_control = function(opts) {
var control_class_name = "Control" + opts.df.fieldtype.replace(/ /g, "");
if(wn.ui.form[control_class_name]) {
return new wn.ui.form[control_class_name](opts);
} else {
console.log("Invalid Control Name: " + opts.df.fieldtype);
}
}

wn.ui.form.Control = Class.extend({
init: function(opts) {
$.extend(this, opts);
this.make();
},
make: function() {
this.$wrapper = $("<div>").appendTo(this.parent);
this.wrapper = this.$wrapper.get(0);
},
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);
},
refresh: function() {
this.disp_status = this.get_status();
this.$wrapper && this.$wrapper.toggle(this.disp_status!="None");
this.$wrapper && this.$wrapper.trigger("refresh");
},
get_doc: function() {
return this.doctype && this.docname
&& locals[this.doctype] && locals[this.doctype][this.docname] || {};
}
});

wn.ui.form.ControlHTML = wn.ui.form.Control.extend({
make: function() {
this._super();
var me = this;
this.$wrapper.on("refresh", function() {
if(me.df.options)
me.$wrapper.html(me.df.options);
})
}
});

wn.ui.form.ControlReadOnly = wn.ui.form.Control.extend({
make: function() {
this._super();
var me = this;
this.$wrapper.on("refresh", function() {
var value = wn.model.get_value(me.doctype, me.docname, me.fieldname);
me.$wrapper.html(value);
})
}
});

wn.ui.form.ControlInput = wn.ui.form.Control.extend({
make: function() {
// parent element
this.$wrapper = $('<div class="control-group">\
<label class="control-label"></label>\
<div class="controls">\
<div class="control-input"></div>\
<div class="control-value like-disabled-input" style="display: none;"></div>\
</div>\
</div>').appendTo(this.parent);
this.wrapper = this.$wrapper.get(0);
this.wrapper.fieldobj = this; // reference for event handlers

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_max_width();
this.setup_update_on_refresh();
},
set_max_width: function() {
if(['Code', 'Text Editor', 'Text', 'Small Text', 'Table', 'HTML']
.indexOf(this.df.fieldtype)==-1) {
this.$wrapper.css({"max-width": "600px"});
}
},
// update input value, label, description
// display (show/hide/read-only),
// mandatory style on refresh
setup_update_on_refresh: function() {
var me = this;
this.$wrapper.on("refresh", function() {
if(me.disp_status != "None") {
// refresh value
if(me.docname && me.set_input) {
me.value = wn.model.get_value(me.doctype, me.docname, me.df.fieldname);

if(me.disp_status=="Write") {
$(me.disp_area).toggle(false);
$(me.input_area).toggle(true);
!me.has_input && me.make_input();
me.set_input(me.value);
} else {
$(me.input_area).toggle(false);
me.disp_area && $(me.disp_area)
.toggle(true)
.html(
wn.format(me.value, me.df, null, locals[me.doctype][me.name])
);
}
}

me.set_description();
me.set_label();
me.set_mandatory();
}
})
},
set_label: function() {
if(this.df.label==this._description)
return;
this.label_span.innerHTML = wn._(this.df.label);
this._label = this.df.label;
},
set_description: function() {
if(this.df.description==this._description) return;
if(this.df.description) {
if(!this.$wrapper.find(".help-box").length) {
$('<p class="help-box small text-muted"></p>').appendTo(this.input_area);
}
this.$wrapper.find(".help-box").html(this.df.description);
} else {
this.$wrapper.find(".help-box").empty().toggle(false);
}
this._description = this.df.description;
},
set_mandatory: function() {
this.$wrapper.toggleClass("has-error", (this.df.reqd
&& (this.value==null || this.value=="")) ? true : false);
},
set_model_value: function(value) {
wn.model.set_value(this.doctype, this.docname, this.df.fieldname, value);
this.frm && this.frm.dirty();
}
});

wn.ui.form.ControlData = wn.ui.form.ControlInput.extend({
html_element: "input",
input_type: "text",
make_input: function() {
this.$input = $("<"+ this.html_element +">")
.attr("type", this.input_type)
.attr("placeholder", this.df.placeholder || "")
.attr("data-fieldtype", this.df.fieldtype)
.addClass("col-span-12")
.prependTo(this.input_area)
this.input = this.$input.get(0);
this.has_input = true;
this.bind_change_event();
},
bind_change_event: function() {
var me = this;
this.$input.on("change", this.change || function() {
if(me.doctype && me.docname && me.get_value) {
var value = me.parse ?
me.parse(me.get_value()) :
me.get_value();

me.validate ?
me.validate(value, function() { me.set_model_value(value); }) :
me.set_model_value(value);
}
});
},
set_input: function(val) {
this.$input.val(this.format_for_input(val));
},
get_value: function() {
return this.$input.val();
},
format_for_input: function(val) {
return val==null ? "" : val;
},
validate: function(v, callback) {
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) + '';
callback(v1);
} else if(this.df.options == 'Email') {
if(v+''=='')return '';
if(!validate_email(v)) {
msgprint(wn._("Invalid Email") + ": " + v);
callback("");
} else
callback(v);
} else {
callback(v);
}
}
});

wn.ui.form.ControlPassword = wn.ui.form.ControlData.extend({
input_type: "password"
});

wn.ui.form.ControlInt = wn.ui.form.ControlData.extend({
make_input: function() {
this._super();
this.$input.css({"text-align": "right"})
},
validate: function(value, callback) {
return callback(cint(value, null));
}
});

wn.ui.form.ControlFloat = wn.ui.form.ControlInt.extend({
validate: function(value, callback) {
return callback(isNaN(parseFloat(value)) ? null : flt(value));
},
format_for_input: function(value) {
value = format_number(parseFloat(value),
null, cint(wn.boot.sysdefaults.float_precision, null));
return isNaN(value) ? "" : value;
}
});

wn.ui.form.ControlCurrency = wn.ui.form.ControlFloat.extend({
format_for_input: function(value) {
value = format_number(parseFloat(value),
get_number_format(this.get_currency()));
return isNaN(value) ? "" : value;
},
get_currency: function() {
return wn.meta.get_field_currency(this.df, this.get_doc());
}
});

wn.ui.form.ControlPercent = wn.ui.form.ControlFloat;

wn.ui.form.ControlDate = wn.ui.form.ControlData.extend({
datepicker_options: {
altFormat:'yy-mm-dd',
changeYear: true,
yearRange: "-70Y:+10Y",
},
make_input: function() {
this._super();
this.set_datepicker();
},
set_datepicker: function() {
this.datepicker_options.dateFormat =
(wn.boot.sysdefaults.date_format || 'yy-mm-dd').replace('yyyy','yy')
this.$input.datepicker(this.datepicker_options);
},
parse: function(value) {
return dateutil.user_to_str(value);
},
format_for_input: function(value) {
return dateutil.str_to_user(value);
},
validate: function(value, callback) {
var value = wn.datetime.validate(value);
if(!value) {
msgprint (wn._("Date must be in format") + ": " + (sys_defaults.date_format || "yyyy-mm-dd"));
callback("");
}
return callback(value);
}
})

import_timepicker = function() {
wn.require("lib/js/lib/jquery/jquery.ui.slider.min.js");
wn.require("lib/js/lib/jquery/jquery.ui.sliderAccess.js");
wn.require("lib/js/lib/jquery/jquery.ui.timepicker-addon.css");
wn.require("lib/js/lib/jquery/jquery.ui.timepicker-addon.js");
}

wn.ui.form.ControlTime = wn.ui.form.ControlData.extend({
make_input: function() {
import_timepicker();
this._super();
this.$input.timepicker({
timeFormat: 'hh:mm:ss',
});
}
});

wn.ui.form.ControlDateTime = wn.ui.form.ControlDate.extend({
set_datepicker: function() {
this.datepicker_options.dateFormat =
(wn.boot.sysdefaults.date_format || 'yy-mm-dd').replace('yyyy','yy')
this.datepicker_options.timeFormat = "hh:mm:ss";

this.$input.datetimepicker(this.datepicker_options);
},
make_input: function() {
import_timepicker();
this._super();
},
});

wn.ui.form.ControlText = wn.ui.form.ControlData.extend({
html_element: "textarea"
});

wn.ui.form.ControlLongText = wn.ui.form.ControlData.extend({
html_element: "textarea"
});

wn.ui.form.ControlSmallText = wn.ui.form.ControlText.extend({
html_element: "textarea"
});

wn.ui.form.ControlCheck = wn.ui.form.ControlData.extend({
input_type: "checkbox",
parse: function(value) {
return this.input.checked ? 1 : 0;
},
validate: function(value, callback) {
return callback(cint(value));
},
set_input: function(value) {
this.input.checked = value ? 1 : 0;
}
});

wn.ui.form.ControlButton = wn.ui.form.ControlData.extend({
make_input: function() {
var me = this;
this.$input = $('<button class="btn">')
.prependTo(me.input_area)
.on("click", function() {
if(me.frm && me.frm.cscript) {
if(me.frm.cscript[me.df.fieldname]) {
me.frm.runclientscript(me.df.fieldname, me.doctype, me.docname);
} else {
me.frm.runscript(me.df.options, me);
}
}
});
this.input = this.$input.get(0);
this.has_input = true;
},
set_label: function() {
this.$input && this.$input.html(this.df.label);
}
});

wn.ui.form.ControlSelect = wn.ui.form.ControlData.extend({
html_element: "select",
make_input: function() {
var me = this;
this._super();
if(this.df.options=="attach_files:") {
this.setup_attachment();
}
this.set_options();
this.$wrapper.on("refresh", function() {
me.set_options();
var value = wn.model.get_value(me.doctype, me.docname, me.fieldname);
if(me.doctype && me.docname) {
// model value is not an option,
// set the default option (displayed)
if(me.$input.val() != value) {
me.set_model_value(me.$input.val());
}
}
})
},
setup_attachment: function() {
var me = this;
$(this.input).css({"width": "70%"});
$("<button class='btn' title='"+ wn._("Add attachment") + "'\
style='margin-bottom: 9px; \
padding-left: 6px; padding-right: 6px; margin-left: 6px;'>\
<i class='icon-plus'></i></button>")
.click(function() {
me.frm.attachments.new_attachment();
})
.appendTo(this.input_area);
},
set_options: function() {
var options = this.df.options || [];
if(this.df.options=="attach_files:") {
options = this.get_file_attachment_list();
} else if(typeof this.df.options==="string") {
options = this.df.options.split("\n");
}
if(this.in_filter && options[0] != "") {
options = add_lists([''], options);
}

this.$input.empty().add_options(options || []);
},
get_file_attachment_list: function() {
if(!this.frm) return;
var fl = this.frm.doc.file_list;
if(fl) {
this.set_description("");
var fl = JSON.parse(fl),
options = [];
for(var fname in fl) {
if(fname.substr(0,4)!="http")
fname = "files/" + fname;
options.push(fname);
}
return options;
} else {
this.set_description(wn._("Please attach a file first."))
return [""];
}
}
});

+ 72
- 0
public/js/wn/form/footer.js 查看文件

@@ -0,0 +1,72 @@
wn.ui.form.Footer = Class.extend({
init: function(opts) {
var me = this;
$.extend(this, opts);
this.make();
this.make_attachments();
this.make_comments();
// render-complete
$(this.frm.wrapper).on("render_complete", function() {
me.refresh();
})
},
make: function() {
this.wrapper = $('<div class="form-footer row">\
<!--i class="icon-cut" style="margin-top: -23px; margin-bottom: 23px; \
display: block; margin-left: 15px; color: #888;"></i-->\
<div class="col-span-12">\
<div class="save-area">\
<button class="btn btn-save btn-primary">\
<i class="icon-save"></i> Save</button>\
</div>\
</div>\
<div class="col-span-8">\
<div class="form-comments">\
<h4><i class="icon-comments"></i> Comments</h4>\
</div>\
</div>\
<div class="col-span-4">\
<div class="form-attachments">\
<h5><i class="icon-paper-clip"></i> Attachments</h5>\
</div>\
</div>\
</div>')
.appendTo(this.parent);
this.wrapper.find(".btn-save").click(function() {
me.frm.save('Save', null, this);
})
},
make_attachments: function() {
this.frm.attachments = new wn.ui.form.Attachments({
parent: this.wrapper.find(".form-attachments"),
frm: this.frm
});
},
make_comments: function() {
this.frm.comments = new wn.ui.form.Comments({
parent: this.wrapper.find(".form-comments"),
frm: this.frm
})
},
show_save: function() {
this.wrapper.find(".save-area").toggle(true);
},
hide_save: function() {
this.wrapper.find(".save-area").toggle(false);
},
refresh: function() {
this.toggle_save();
this.frm.attachments.refresh();
this.frm.comments.refresh();
// show save?
},
toggle_save: function() {
if(this.frm_head && this.appframe.toolbar
&& this.appframe.buttons.Save && !this.save_disabled
&& (this.fields && this.fields.length > 7)) {
this.show_save();
} else {
this.hide_save();
}
}
});

+ 3
- 5
public/js/wn/form/formatters.js 查看文件

@@ -7,11 +7,9 @@ wn.form.formatters = {
return value==null ? "" : value
},
Float: function(value, docfield) {
var decimals = wn.boot.sysdefaults.float_precision ?
parseInt(wn.boot.sysdefaults.float_precision) : null;

return "<div style='text-align: right'>" +
format_number(value, null, decimals) + "</div>";
var decimals = cint(wn.boot.sysdefaults.float_precision, null);
return "<div style='text-align: right'>" + format_number(value, null, decimals)
+ "</div>";
},
Int: function(value) {
return cint(value);


+ 1
- 1
public/js/wn/form/layout.js 查看文件

@@ -64,7 +64,7 @@ wn.ui.form.Layout = Class.extend({
},
make_section: function(df) {
if(this.section) {
$("<hr>").appendTo(this.wrapper);
//$("<hr>").appendTo(this.wrapper);
}
this.section = $('<div class="row">').appendTo(this.wrapper);
this.frm.sections.push(this.section);


+ 30
- 2
public/js/wn/model/model.js 查看文件

@@ -45,6 +45,7 @@ $.extend(wn.model, {
],

new_names: {},
events: {},

get_std_field: function(fieldname) {
var docfield = $.map([].concat(wn.model.std_fields).concat(wn.model.std_fields_table),
@@ -179,8 +180,35 @@ $.extend(wn.model, {
},
get_value: function(doctype, filters, fieldname) {
var l = wn.model.get(doctype, filters);
return (l.length && l[0]) ? l[0][fieldname] : null;
if(typeof filters==="string") {
return locals[doctype] && locals[doctype][filters]
&& locals[doctype][filters][fieldname];
} else {
var l = wn.model.get(doctype, filters);
return (l.length && l[0]) ? l[0][fieldname] : null;
}
},
set_value: function(doctype, name, fieldname, value) {
var doc = locals[doctype] && locals[doctype][name];
if(doc) {
doc[fieldname] = value;
wn.model.trigger(doctype, name, fieldname, value);
}
},
on: function(doctype, name, fieldname, fn) {
wn.provide("locals." + doctype + "." + name + "." + fieldname);
locals[doctype][name][fieldname] = fn;
},
trigger: function(doctype, name, fieldname, value) {
if(wn.model.events[doctype] && wn.model.events[doctype][name]) {
var ev = wn.model.events[doctype][name];
ev[fieldname] && ev[fieldname](value, doctype, name, fieldname);
ev["*"] && ev["*"](value, doctype, name, fieldname);
}
},
get_doc: function(doctype, name) {


+ 8
- 3
public/js/wn/ui/appframe.js 查看文件

@@ -7,8 +7,14 @@ wn.ui.AppFrame = Class.extend({
init: function(parent, title, module) {
this.set_document_title = true;
this.buttons = {};
this.$w = $('<div class="col-span-12"></div>').prependTo(parent);
this.$w = $('<div class="col-span-12">\
<div class="row appframe-header">\
<div class="col-span-12"></div>\
</div>\
</div>')
.prependTo(parent)
.find(".appframe-header div");

$('<!-- div>\
<ul class="breadcrumb" style="height: 32px;">\
<span class="appframe-right pull-right">\
@@ -26,7 +32,6 @@ wn.ui.AppFrame = Class.extend({
style="margin-top: -10px;"></div>\
<div class="btn-group appframe-toolbar" \
style="display: none; margin-top: 15px;"></div>\
<hr>\
').appendTo(this.$w);
this.$w.find('.close').click(function() {


Loading…
取消
儲存