您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

815 行
22 KiB

  1. // Copyright (c) 2013, Web Notes Technologies Pvt. Ltd.
  2. // MIT License. See license.txt
  3. wn.ui.form.make_control = function(opts) {
  4. var control_class_name = "Control" + opts.df.fieldtype.replace(/ /g, "");
  5. if(wn.ui.form[control_class_name]) {
  6. return new wn.ui.form[control_class_name](opts);
  7. } else {
  8. console.log("Invalid Control Name: " + opts.df.fieldtype);
  9. }
  10. }
  11. // old style
  12. function make_field(docfield, doctype, parent, frm, in_grid, hide_label) { // Factory
  13. return wn.ui.form.make_control({
  14. df: docfield,
  15. doctype: doctype,
  16. parent: parent,
  17. hide_label: hide_label,
  18. frm: frm
  19. });
  20. }
  21. wn.ui.form.Control = Class.extend({
  22. init: function(opts) {
  23. $.extend(this, opts);
  24. this.make();
  25. // if developer_mode=1, show fieldname as tooltip
  26. if(wn.boot.profile && wn.boot.profile.name==="Administrator" &&
  27. wn.boot.developer_mode===1 && this.$wrapper) {
  28. this.$wrapper.attr("title", this.df.fieldname);
  29. }
  30. },
  31. make: function() {
  32. this.$wrapper = $("<div>").appendTo(this.parent);
  33. this.wrapper = this.$wrapper.get(0);
  34. },
  35. // returns "Read", "Write" or "None"
  36. // as strings based on permissions
  37. get_status: function(explain) {
  38. if(!this.doctype)
  39. return "Write";
  40. return wn.perm.get_field_display_status(this.df,
  41. locals[this.doctype][this.docname], this.perm, explain);
  42. },
  43. refresh: function() {
  44. this.disp_status = this.get_status();
  45. this.$wrapper
  46. && this.$wrapper.toggle(this.disp_status!="None")
  47. && this.$wrapper.trigger("refresh");
  48. },
  49. get_doc: function() {
  50. return this.doctype && this.docname
  51. && locals[this.doctype] && locals[this.doctype][this.docname] || {};
  52. },
  53. parse_validate_and_set_in_model: function(value) {
  54. var me = this;
  55. this.inside_change_event = true;
  56. if(this.parse) value = this.parse(value);
  57. var set = function(value) {
  58. me.set_model_value(value);
  59. me.inside_change_event = false;
  60. me.set_mandatory && me.set_mandatory(value);
  61. }
  62. this.validate ? this.validate(value, set) : set(value);
  63. },
  64. get_parsed_value: function() {
  65. return this.get_value ?
  66. (this.parse ? this.parse(this.get_value()) : this.get_value()) :
  67. undefined;
  68. },
  69. set_model_value: function(value) {
  70. if(wn.model.set_value(this.doctype, this.docname, this.df.fieldname,
  71. value, this.df.fieldtype)) {
  72. this.frm && this.frm.dirty();
  73. this.last_value = value;
  74. }
  75. },
  76. });
  77. wn.ui.form.ControlHTML = wn.ui.form.Control.extend({
  78. make: function() {
  79. this._super();
  80. var me = this;
  81. this.disp_area = this.wrapper;
  82. this.$wrapper.on("refresh", function() {
  83. if(me.df.options)
  84. me.$wrapper.html(me.df.options);
  85. })
  86. }
  87. });
  88. wn.ui.form.ControlImage = wn.ui.form.Control.extend({
  89. make: function() {
  90. this._super();
  91. var me = this;
  92. this.$wrapper.on("refresh", function() {
  93. me.$wrapper.empty();
  94. if(me.df.options && me.frm.doc[me.df.options]) {
  95. $("<img src='"+me.frm.doc[me.df.options]+"' style='max-width: 70%;'>")
  96. .appendTo(me.$wrapper);
  97. } else {
  98. $("<div class='missing-image'><i class='icon-camera'></i></div>")
  99. .appendTo(me.$wrapper)
  100. }
  101. return false;
  102. })
  103. }
  104. });
  105. wn.ui.form.ControlReadOnly = wn.ui.form.Control.extend({
  106. make: function() {
  107. this._super();
  108. var me = this;
  109. this.$wrapper.on("refresh", function() {
  110. var value = wn.model.get_value(me.doctype, me.docname, me.fieldname);
  111. me.$wrapper.html(value);
  112. })
  113. },
  114. });
  115. wn.ui.form.ControlInput = wn.ui.form.Control.extend({
  116. make: function() {
  117. // parent element
  118. this.make_wrapper();
  119. this.wrapper = this.$wrapper.get(0);
  120. this.wrapper.fieldobj = this; // reference for event handlers
  121. this.set_input_areas();
  122. // set description
  123. this.set_max_width();
  124. this.setup_update_on_refresh();
  125. },
  126. make_wrapper: function() {
  127. if(this.only_input) {
  128. this.$wrapper = $("<span>").appendTo(this.parent);
  129. } else {
  130. this.$wrapper = $('<div class="control-group">\
  131. <label class="control-label"></label>\
  132. <div class="control-input"></div>\
  133. <div class="control-value like-disabled-input" style="display: none;"></div>\
  134. <p class="help-box small text-muted">&nbsp;</p>\
  135. </div>\
  136. </div>').appendTo(this.parent);
  137. }
  138. },
  139. set_input_areas: function() {
  140. if(this.only_input) {
  141. this.input_area = this.wrapper;
  142. } else {
  143. this.label_area = this.label_span = this.$wrapper.find("label").get(0);
  144. this.input_area = this.$wrapper.find(".control-input").get(0);
  145. this.disp_area = this.$wrapper.find(".control-value").get(0);
  146. }
  147. },
  148. set_max_width: function() {
  149. if(['Code', 'Text Editor', 'Text', 'Small Text', 'Table', 'HTML']
  150. .indexOf(this.df.fieldtype)==-1) {
  151. this.$wrapper.css({"max-width": "600px"});
  152. }
  153. },
  154. // update input value, label, description
  155. // display (show/hide/read-only),
  156. // mandatory style on refresh
  157. setup_update_on_refresh: function() {
  158. var me = this;
  159. this.$wrapper.on("refresh", function() {
  160. if(me.disp_status != "None") {
  161. // refresh value
  162. if(me.doctype && me.docname) {
  163. me.value = wn.model.get_value(me.doctype, me.docname, me.df.fieldname);
  164. }
  165. if(me.disp_status=="Write") {
  166. me.disp_area && $(me.disp_area).toggle(false);
  167. $(me.input_area).toggle(true);
  168. !me.has_input && me.make_input();
  169. if(me.doctype && me.docname)
  170. me.set_input(me.value);
  171. } else {
  172. $(me.input_area).toggle(false);
  173. me.disp_area && $(me.disp_area)
  174. .toggle(true)
  175. .html(
  176. wn.format(me.value, me.df, {no_icon:true}, locals[me.doctype][me.name])
  177. );
  178. }
  179. me.set_description();
  180. me.set_label();
  181. me.set_mandatory(me.value);
  182. }
  183. return false;
  184. });
  185. },
  186. bind_change_event: function() {
  187. var me = this;
  188. this.$input && this.$input.on("change", this.change || function() {
  189. me.doctype && me.docname && me.get_value
  190. && me.parse_validate_and_set_in_model(me.get_value()); } );
  191. },
  192. bind_save_event: function() {
  193. if(this.frm && this.$input) {
  194. var me = this;
  195. this.$input.keydown("ctrl+s meta+s", function(e) {
  196. me.frm.save_or_update();
  197. return false;
  198. })
  199. }
  200. },
  201. set_label: function(label) {
  202. if(label) this.df.label = label;
  203. if(this.only_input || this.df.label==this._label)
  204. return;
  205. var icon = wn.ui.form.fieldtype_icons[this.df.fieldtype];
  206. if(this.df.fieldtype==="Link") {
  207. icon = wn.boot.doctype_icons[this.df.options];
  208. } else if(this.df.link_doctype) {
  209. icon = wn.boot.doctype_icons[this.df.link_doctype];
  210. }
  211. this.label_span.innerHTML = (icon ? '<i class="'+icon+'"></i> ' : "") +
  212. wn._(this.df.label);
  213. this._label = this.df.label;
  214. },
  215. set_description: function() {
  216. if(this.only_input || this.df.description===this._description)
  217. return;
  218. if(this.df.description) {
  219. this.$wrapper.find(".help-box").html(this.df.description);
  220. } else {
  221. this.set_empty_description();
  222. }
  223. this._description = this.df.description;
  224. },
  225. set_empty_description: function() {
  226. this.$wrapper.find(".help-box").html("&nbsp;");
  227. },
  228. set_mandatory: function(value) {
  229. this.$wrapper.toggleClass("has-error", (this.df.reqd
  230. && (value==null || value==="")) ? true : false);
  231. },
  232. });
  233. wn.ui.form.ControlData = wn.ui.form.ControlInput.extend({
  234. html_element: "input",
  235. input_type: "text",
  236. make_input: function() {
  237. this.$input = $("<"+ this.html_element +">")
  238. .attr("type", this.input_type)
  239. .addClass("col col-lg-12 input-with-feedback")
  240. .prependTo(this.input_area)
  241. this.set_input_attributes();
  242. this.input = this.$input.get(0);
  243. this.has_input = true;
  244. this.bind_change_event();
  245. this.bind_save_event();
  246. },
  247. set_input_attributes: function() {
  248. this.$input
  249. .attr("data-fieldtype", this.df.fieldtype)
  250. .attr("data-fieldname", this.df.fieldname)
  251. .attr("placeholder", this.df.placeholder || "")
  252. if(this.doctype)
  253. this.$input.attr("data-doctype", this.doctype);
  254. if(this.df.input_css)
  255. this.$input.css(this.df.input_css);
  256. },
  257. set_input: function(val) {
  258. this.$input.val(this.format_for_input(val));
  259. this.last_value = val;
  260. this.set_mandatory && this.set_mandatory(val);
  261. },
  262. get_value: function() {
  263. return this.$input ? this.$input.val() : undefined;
  264. },
  265. format_for_input: function(val) {
  266. return val==null ? "" : val;
  267. },
  268. validate: function(v, callback) {
  269. if(this.df.options == 'Phone') {
  270. if(v+''=='')return '';
  271. v1 = ''
  272. // phone may start with + and must only have numbers later, '-' and ' ' are stripped
  273. v = v.replace(/ /g, '').replace(/-/g, '').replace(/\(/g, '').replace(/\)/g, '');
  274. // allow initial +,0,00
  275. if(v && v.substr(0,1)=='+') {
  276. v1 = '+'; v = v.substr(1);
  277. }
  278. if(v && v.substr(0,2)=='00') {
  279. v1 += '00'; v = v.substr(2);
  280. }
  281. if(v && v.substr(0,1)=='0') {
  282. v1 += '0'; v = v.substr(1);
  283. }
  284. v1 += cint(v) + '';
  285. callback(v1);
  286. } else if(this.df.options == 'Email') {
  287. if(v+''=='')return '';
  288. if(!validate_email(v)) {
  289. msgprint(wn._("Invalid Email") + ": " + v);
  290. callback("");
  291. } else
  292. callback(v);
  293. } else {
  294. callback(v);
  295. }
  296. }
  297. });
  298. wn.ui.form.ControlPassword = wn.ui.form.ControlData.extend({
  299. input_type: "password"
  300. });
  301. wn.ui.form.ControlInt = wn.ui.form.ControlData.extend({
  302. make_input: function() {
  303. var me = this;
  304. this._super();
  305. this.$input
  306. .css({"text-align": "right"})
  307. .on("focus", function() {
  308. setTimeout(function() {
  309. if(!document.activeElement) return;
  310. me.validate(document.activeElement.value, function(val) {
  311. document.activeElement.value = val;
  312. });
  313. document.activeElement.select()
  314. }, 100);
  315. return false;
  316. })
  317. },
  318. validate: function(value, callback) {
  319. return callback(cint(value, null));
  320. }
  321. });
  322. wn.ui.form.ControlFloat = wn.ui.form.ControlInt.extend({
  323. validate: function(value, callback) {
  324. return callback(isNaN(parseFloat(value)) ? null : flt(value));
  325. },
  326. format_for_input: function(value) {
  327. var formatted_value = format_number(parseFloat(value),
  328. null, cint(wn.boot.sysdefaults.float_precision, null));
  329. return isNaN(parseFloat(value)) ? "" : formatted_value;
  330. }
  331. });
  332. wn.ui.form.ControlCurrency = wn.ui.form.ControlFloat.extend({
  333. format_for_input: function(value) {
  334. var formatted_value = format_number(parseFloat(value),
  335. get_number_format(this.get_currency()));
  336. return isNaN(parseFloat(value)) ? "" : formatted_value;
  337. },
  338. get_currency: function() {
  339. return wn.meta.get_field_currency(this.df, this.get_doc());
  340. }
  341. });
  342. wn.ui.form.ControlPercent = wn.ui.form.ControlFloat;
  343. wn.ui.form.ControlDate = wn.ui.form.ControlData.extend({
  344. datepicker_options: {
  345. altFormat:'yy-mm-dd',
  346. changeYear: true,
  347. yearRange: "-70Y:+10Y",
  348. },
  349. make_input: function() {
  350. this._super();
  351. this.set_datepicker();
  352. },
  353. set_datepicker: function() {
  354. this.datepicker_options.dateFormat =
  355. (wn.boot.sysdefaults.date_format || 'yy-mm-dd').replace('yyyy','yy')
  356. this.$input.datepicker(this.datepicker_options);
  357. },
  358. parse: function(value) {
  359. return value ? dateutil.user_to_str(value) : value;
  360. },
  361. format_for_input: function(value) {
  362. return value ? dateutil.str_to_user(value) : "";
  363. },
  364. validate: function(value, callback) {
  365. var value = wn.datetime.validate(value);
  366. if(!value) {
  367. msgprint (wn._("Date must be in format") + ": " + (sys_defaults.date_format || "yyyy-mm-dd"));
  368. callback("");
  369. }
  370. return callback(value);
  371. }
  372. })
  373. import_timepicker = function() {
  374. wn.require("lib/js/lib/jquery/jquery.ui.slider.min.js");
  375. wn.require("lib/js/lib/jquery/jquery.ui.sliderAccess.js");
  376. wn.require("lib/js/lib/jquery/jquery.ui.timepicker-addon.css");
  377. wn.require("lib/js/lib/jquery/jquery.ui.timepicker-addon.js");
  378. }
  379. wn.ui.form.ControlTime = wn.ui.form.ControlData.extend({
  380. make_input: function() {
  381. import_timepicker();
  382. this._super();
  383. this.$input.timepicker({
  384. timeFormat: 'hh:mm:ss',
  385. });
  386. }
  387. });
  388. wn.ui.form.ControlDatetime = wn.ui.form.ControlDate.extend({
  389. set_datepicker: function() {
  390. this.datepicker_options.dateFormat =
  391. (wn.boot.sysdefaults.date_format || 'yy-mm-dd').replace('yyyy','yy')
  392. this.datepicker_options.timeFormat = "hh:mm:ss";
  393. this.$input.datetimepicker(this.datepicker_options);
  394. },
  395. make_input: function() {
  396. import_timepicker();
  397. this._super();
  398. },
  399. });
  400. wn.ui.form.ControlText = wn.ui.form.ControlData.extend({
  401. html_element: "textarea"
  402. });
  403. wn.ui.form.ControlLongText = wn.ui.form.ControlText;
  404. wn.ui.form.ControlSmallText = wn.ui.form.ControlText;
  405. wn.ui.form.ControlCheck = wn.ui.form.ControlData.extend({
  406. input_type: "checkbox",
  407. make_wrapper: function() {
  408. this.$wrapper = $('<div class="checkbox">\
  409. <label class="input-area">\
  410. <span class="disp-area" style="display:none;"></span>\
  411. <span class="label-area"></span>\
  412. </label>\
  413. <p class="help-box small text-muted">&nbsp;</p>\
  414. </div>').appendTo(this.parent)
  415. },
  416. set_input_areas: function() {
  417. this.label_area = this.label_span = this.$wrapper.find(".label-area").get(0);
  418. this.input_area = this.$wrapper.find(".input-area").get(0);
  419. this.disp_area = this.$wrapper.find(".disp-area").get(0);
  420. },
  421. make_input: function() {
  422. this._super();
  423. this.$input.removeClass("col col-lg-12");
  424. },
  425. parse: function(value) {
  426. return this.input.checked ? 1 : 0;
  427. },
  428. validate: function(value, callback) {
  429. return callback(cint(value));
  430. },
  431. set_input: function(value) {
  432. this.input.checked = value ? 1 : 0;
  433. this.last_value = value;
  434. }
  435. });
  436. wn.ui.form.ControlButton = wn.ui.form.ControlData.extend({
  437. make_input: function() {
  438. var me = this;
  439. this.$input = $('<button class="btn btn-default">')
  440. .prependTo(me.input_area)
  441. .css({"margin-bottom": "7px"})
  442. .on("click", function() {
  443. if(me.frm && me.frm.doc && me.frm.cscript) {
  444. if(me.frm.cscript[me.df.fieldname]) {
  445. me.frm.script_manager.trigger(me.df.fieldname, me.doctype, me.docname);
  446. } else {
  447. me.frm.runscript(me.df.options, me);
  448. }
  449. }
  450. else if(me.df.click) {
  451. me.df.click();
  452. }
  453. });
  454. this.input = this.$input.get(0);
  455. this.has_input = true;
  456. },
  457. set_input_areas: function() {
  458. this._super();
  459. $(this.disp_area).removeClass();
  460. },
  461. set_empty_description: function() {
  462. this.$wrapper.find(".help-box").empty().toggle(false);
  463. },
  464. set_label: function() {
  465. this.$input && this.$input.html(this.df.label);
  466. }
  467. });
  468. wn.ui.form.ControlSelect = wn.ui.form.ControlData.extend({
  469. html_element: "select",
  470. make_input: function() {
  471. var me = this;
  472. this._super();
  473. if(this.df.options=="attach_files:") {
  474. this.setup_attachment();
  475. }
  476. this.set_options();
  477. },
  478. set_input: function(value) {
  479. // refresh options first - (new ones??)
  480. this.set_options();
  481. this._super(value);
  482. // not a possible option, repair
  483. if(this.doctype && this.docname) {
  484. // model value is not an option,
  485. // set the default option (displayed)
  486. var input_value = this.$input.val();
  487. var model_value = wn.model.get_value(this.doctype, this.docname, this.df.fieldname);
  488. if(input_value != (model_value || "")) {
  489. this.set_model_value(input_value);
  490. } else {
  491. this.last_value = value;
  492. }
  493. }
  494. },
  495. setup_attachment: function() {
  496. var me = this;
  497. $(this.input).css({"width": "70%"});
  498. this.$attach = $("<button class='btn btn-default' title='"+ wn._("Add attachment") + "'\
  499. style='margin-bottom: 9px; \
  500. padding-left: 6px; padding-right: 6px; margin-left: 6px;'>\
  501. <i class='icon-plus'></i></button>")
  502. .click(function() {
  503. me.frm.attachments.new_attachment(me.df.fieldname);
  504. })
  505. .appendTo(this.input_area);
  506. $(document).on("upload_complete", function(event, filename, file_url) {
  507. if(cur_frm === me.frm) {
  508. me.set_options();
  509. }
  510. })
  511. this.$wrapper.on("refresh", function() {
  512. me.$attach.toggle(!me.frm.doc.__islocal);
  513. });
  514. },
  515. set_options: function() {
  516. var options = this.df.options || [];
  517. if(this.df.options=="attach_files:") {
  518. options = this.get_file_attachment_list();
  519. } else if(typeof this.df.options==="string") {
  520. options = this.df.options.split("\n");
  521. }
  522. if(this.in_filter && options[0] != "") {
  523. options = add_lists([''], options);
  524. }
  525. var selected = this.$input.find(":selected").val();
  526. this.$input.empty().add_options(options || []);
  527. if(selected) this.$input.val(selected);
  528. },
  529. get_file_attachment_list: function() {
  530. if(!this.frm) return;
  531. var fl = wn.model.docinfo[this.frm.doctype][this.frm.docname];
  532. if(fl && fl.attachments) {
  533. fl = fl.attachments;
  534. this.set_description("");
  535. var options = [""];
  536. for(var fname in fl) {
  537. if(fname.substr(0,4)!="http")
  538. fname = "files/" + fname;
  539. options.push(fname);
  540. }
  541. return options;
  542. } else {
  543. this.set_description(wn._("Please attach a file first."))
  544. return [""];
  545. }
  546. }
  547. });
  548. // special features for link
  549. // buttons
  550. // autocomplete
  551. // link validation
  552. // custom queries
  553. // add_fetches
  554. wn.ui.form.ControlLink = wn.ui.form.ControlData.extend({
  555. make_input: function() {
  556. $('<div class="input-group link-field">\
  557. <input type="text" class="input-with-feedback">\
  558. <div class="input-group-btn">\
  559. <button class="btn btn-default btn-search" title="Search Link">\
  560. <i class="icon-search"></i>\
  561. </button>\
  562. <button class="btn btn-default btn-open" title="Open Link">\
  563. <i class="icon-play"></i>\
  564. </button><button class="btn btn-default btn-new" title="Make New">\
  565. <i class="icon-plus"></i>\
  566. </button>\
  567. </div>\
  568. </div>').appendTo(this.input_area);
  569. this.$input_area = $(this.input_area);
  570. this.$input = this.$input_area.find('input');
  571. this.set_input_attributes();
  572. this.input = this.$input.get(0);
  573. this.has_input = true;
  574. //this.bind_change_event();
  575. var me = this;
  576. this.$input.on("blur", function() {
  577. if(me.selected) {
  578. me.selected = false;
  579. return;
  580. }
  581. if(me.doctype && me.docname) {
  582. var value = me.get_value();
  583. if(value!==me.last_value) {
  584. me.parse_validate_and_set_in_model(value);
  585. }
  586. }});
  587. this.bind_save_event();
  588. this.setup_buttons();
  589. this.setup_autocomplete();
  590. },
  591. setup_buttons: function() {
  592. var me = this;
  593. // magnifier - search
  594. this.$input_area.find(".btn-search").on("click", function() {
  595. new wn.ui.form.LinkSelector({
  596. doctype: me.df.options,
  597. target: me,
  598. txt: me.$input.val()
  599. });
  600. });
  601. // open
  602. if(wn.model.can_read(me.df.options)) {
  603. this.$input_area.find(".btn-open").on("click", function() {
  604. var value = me.get_value();
  605. if(value && me.df.options) wn.set_route("Form", me.df.options, value);
  606. });
  607. } else {
  608. this.$input_area.find(".btn-open").remove();
  609. }
  610. // new
  611. if(wn.model.can_create(me.df.options)) {
  612. this.$input_area.find(".btn-new").on("click", function() {
  613. new_doc(me.df.options)
  614. });
  615. } else {
  616. this.$input_area.find(".btn-new").remove();
  617. }
  618. },
  619. setup_autocomplete: function() {
  620. var me = this;
  621. this.$input.autocomplete({
  622. source: function(request, response) {
  623. var args = {
  624. 'txt': request.term,
  625. 'doctype': me.df.options,
  626. };
  627. me.set_custom_query(args);
  628. return wn.call({
  629. type: "GET",
  630. method:'webnotes.widgets.search.search_link',
  631. args: args,
  632. callback: function(r) {
  633. response(r.results);
  634. },
  635. });
  636. },
  637. open: function(event, ui) {
  638. if(cur_dialog) {
  639. var zindex = cint(cur_dialog.$wrapper.css("z-index")) + 1
  640. $(this).autocomplete("widget").css("z-index", zindex);
  641. }
  642. me.autocomplete_open = true;
  643. },
  644. close: function(event, ui) {
  645. me.autocomplete_open = false;
  646. },
  647. select: function(event, ui) {
  648. me.autocomplete_open = false;
  649. if(me.frm && me.frm.doc) {
  650. me.selected = true;
  651. me.parse_validate_and_set_in_model(ui.item.value);
  652. } else {
  653. me.$input.val(ui.item.value);
  654. me.$input.trigger("change");
  655. }
  656. }
  657. }).data('uiAutocomplete')._renderItem = function(ul, item) {
  658. return $('<li></li>')
  659. .data('item.autocomplete', item)
  660. .append(repl('<a><span style="font-weight: bold;">%(label)s</span><br>\
  661. <span style="font-size:10px;">%(info)s</span></a>',
  662. item))
  663. .appendTo(ul);
  664. };
  665. // remove accessibility span (for now)
  666. this.$wrapper.find(".ui-helper-hidden-accessible").remove();
  667. },
  668. set_custom_query: function(args) {
  669. if(this.get_query || this.df.get_query) {
  670. var q = (this.get_query || this.df.get_query)(this.frm && this.frm.doc, this.doctype, this.docname);
  671. if (typeof(q)==="string") {
  672. args.query = q;
  673. } else if($.isPlainObject(q)) {
  674. if(q.filters) {
  675. $.each(q.filters, function(key, value) {
  676. if(value!==undefined) {
  677. q.filters[key] = value || null;
  678. }
  679. });
  680. }
  681. $.extend(args, q);
  682. }
  683. }
  684. },
  685. validate: function(value, callback) {
  686. // validate the value just entered
  687. var me = this;
  688. if(this.df.options=="[Select]") {
  689. callback(value);
  690. return;
  691. }
  692. this.frm.script_manager.validate_link_and_fetch(this.df, this.docname, value, callback);
  693. },
  694. });
  695. wn.ui.form.ControlCode = wn.ui.form.ControlInput.extend({
  696. editor_name: "ACE",
  697. make_input: function() {
  698. $(this.input_area).css({"min-height":"360px"});
  699. var me = this;
  700. this.editor = new wn.editors[this.editor_name]({
  701. parent: this.input_area,
  702. change: function(value) {
  703. me.parse_validate_and_set_in_model(value);
  704. },
  705. field: this
  706. });
  707. this.has_input = true;
  708. if(this.editor.$editor) {
  709. this.editor.$editor.keypress("ctrl+s meta+s", function() {
  710. me.frm.save_or_update();
  711. });
  712. }
  713. },
  714. get_value: function() {
  715. return this.editor.get_value();
  716. },
  717. set_input: function(value) {
  718. this.editor.set_input(value);
  719. this.last_value = value;
  720. }
  721. });
  722. wn.ui.form.ControlTextEditor = wn.ui.form.ControlCode.extend({
  723. editor_name: "BootstrapWYSIWYG"
  724. });
  725. wn.ui.form.ControlTable = wn.ui.form.Control.extend({
  726. make: function() {
  727. this._super();
  728. this.grid = new wn.ui.form.Grid({
  729. frm: this.frm,
  730. df: this.df,
  731. perm: this.perm,
  732. parent: this.wrapper
  733. })
  734. if(this.frm)
  735. this.frm.grids[this.frm.grids.length] = this;
  736. // description
  737. if(this.df.description) {
  738. $('<p class="text-muted small">' + this.df.description + '</p>')
  739. .appendTo(this.wrapper);
  740. }
  741. var me = this;
  742. this.$wrapper.on("refresh", function() {
  743. me.grid.refresh();
  744. return false;
  745. });
  746. }
  747. })
  748. wn.ui.form.fieldtype_icons = {
  749. "Date": "icon-calendar",
  750. "Time": "icon-time",
  751. "Datetime": "icon-time",
  752. "Code": "icon-code",
  753. "Select": "icon-flag"
  754. };