grid.common.js 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843
  1. /**
  2. * jqGrid common function
  3. * Tony Tomov tony@trirand.com, http://trirand.com/blog/
  4. * Changed by Oleg Kiriljuk, oleg.kiriljuk@ok-soft-gmbh.com
  5. * Dual licensed under the MIT and GPL licenses:
  6. * http://www.opensource.org/licenses/mit-license.php
  7. * http://www.gnu.org/licenses/gpl-2.0.html
  8. */
  9. /*jshint eqeqeq:false */
  10. /*global jQuery, define, HTMLElement, exports, module, require */
  11. /*jslint browser: true, eqeq: true, plusplus: true, unparam: true, white: true, vars: true */
  12. (function (global, factory) {
  13. "use strict";
  14. if (typeof define === "function" && define.amd) {
  15. // AMD. Register as an anonymous module.
  16. //console.log("grid.common AMD");
  17. define([
  18. "jquery",
  19. "./grid.base",
  20. "./jqdnr",
  21. "./jqmodal"
  22. ], function ($) {
  23. //console.log("grid.common AMD: define callback");
  24. return factory($, global.document);
  25. });
  26. } else if (typeof module === "object" && module.exports) {
  27. // Node/CommonJS
  28. //console.log("grid.common CommonJS");
  29. module.exports = function (root, $) {
  30. //console.log("grid.common CommonJS: in module.exports");
  31. if (!root) {
  32. root = window;
  33. }
  34. //console.log("grid.common CommonJS: before require('jquery')");
  35. if ($ === undefined) {
  36. // require("jquery") returns a factory that requires window to
  37. // build a jQuery instance, we normalize how we use modules
  38. // that require this pattern but the window provided is a noop
  39. // if it's defined (how jquery works)
  40. $ = typeof window !== "undefined" ?
  41. require("jquery") :
  42. require("jquery")(root);
  43. }
  44. //console.log("grid.common CommonJS: before require('./grid.base')");
  45. require("./grid.base");
  46. //console.log("grid.common CommonJS: before require('./jqdnr')");
  47. require("./jqdnr");
  48. //console.log("grid.common CommonJS: before require('./jqmodal')");
  49. require("./jqmodal");
  50. factory($, root.document);
  51. return $;
  52. };
  53. } else {
  54. // Browser globals
  55. //console.log("grid.common Browser: before factory");
  56. factory(jQuery, global.document);
  57. }
  58. }(typeof window !== "undefined" ? window : this, function ($, document) {
  59. "use strict";
  60. var jgrid = $.jgrid, base = $.fn.jqGrid;
  61. // begin module grid.common
  62. var getGuiStyles = base.getGuiStyles, getGridRes = base.getGridRes;
  63. jgrid.jqModal = jgrid.jqModal || {};
  64. $.extend(true, jgrid.jqModal, { toTop: true });
  65. $.extend(jgrid, {
  66. // Modal functions
  67. // The methods showModal and closeModal will be used as callback of $.jqm jQuery plugin defined in jqModal.js
  68. // The modul can support multiple modal dialods. It hold the information about evety active modules in internal array of "hashes".
  69. // The modal dialogs as hidden typically. Before the dialog will be visible onShow callback (showModal) will be called.
  70. //
  71. // Every eleement contains "hash object" which have 4 properties:
  72. // w: (jQuery object) The modal element, represent the outer div of the modal dialog
  73. // o: (jQuery object) The overlay element. It will be assigned on the first opening of the modal
  74. // c: (object) The modal's options object. The options used durin creating the modal.
  75. // One can use global $.jgrid.jqModal or gris specifif p.jqModal to specify defaults of the options.
  76. // t: (DOM object) The triggering element.
  77. // s: numeric part of "id" used for modal dialog. The modal dialog have class "jqmID" + s.
  78. // a: Boolean. It's false initially. It will be set to true during opening and will set to false on closing.
  79. showModal: function (h) {
  80. // w: (jQuery object) The modal element
  81. h.w.show();
  82. },
  83. closeModal: function (h) {
  84. // w: (jQuery object) The modal element
  85. // o: (jQuery object) The overlay element
  86. // c: (object) The modal's options object
  87. h.w.hide().attr("aria-hidden", "true");
  88. if (h.o) {
  89. h.o.remove();
  90. }
  91. },
  92. hideModal: function (selector, o) {
  93. o = $.extend({ jqm: true, gb: "", removemodal: false }, o || {});
  94. var thisgrid = o.gb && typeof o.gb === "string" && o.gb.substr(0, 6) === "#gbox_" ? $("#" + o.gb.substr(6))[0] : false,
  95. $selector = $(selector);
  96. if (o.onClose) {
  97. var oncret = thisgrid ? o.onClose.call(thisgrid, selector) : o.onClose(selector);
  98. if (typeof oncret === "boolean" && !oncret) { return; }
  99. }
  100. if ($.fn.jqm && o.jqm === true) {
  101. $selector.attr("aria-hidden", "true").jqmHide();
  102. } else {
  103. if (o.gb !== "") {
  104. try { $(">.jqgrid-overlay", o.gb).first().hide(); } catch (ignore) { }
  105. }
  106. $selector.hide().attr("aria-hidden", "true");
  107. }
  108. if (o.removemodal) {
  109. $selector.remove();
  110. }
  111. },
  112. //Helper functions
  113. createModal: function (aIDs, content, o, insertSelector, posSelector, appendsel, css) {
  114. var jqID = jgrid.jqID, p = this.p;
  115. o = $.extend(true, {
  116. resizingRightBottomIcon: base.getIconRes.call(this, "form.resizableLtr")
  117. }, jgrid.jqModal || {},
  118. p != null ? p.jqModal || {} : {},
  119. o);
  120. // create main window "div.ui-jqdialog", which will contains other components of the modal window:
  121. // "div.ui-jqdialog-titlebar", "div.ui-jqdialog-content" and optionally resizer like "div.jqResize"
  122. var mw = document.createElement("div"), themodalSelector = "#" + jqID(aIDs.themodal),
  123. rtlsup = $(o.gbox).attr("dir") === "rtl" ? true : false,
  124. resizeAlso = aIDs.resizeAlso ? "#" + jqID(aIDs.resizeAlso) : false;
  125. css = $.extend({}, css || {});
  126. mw.className = getGuiStyles.call(this, "dialog.window", "ui-jqdialog");
  127. mw.id = aIDs.themodal;
  128. mw.dir = rtlsup ? "rtl" : "ltr";
  129. var mdoc = document.createElement("div");
  130. mdoc.className = getGuiStyles.call(this, "dialog.document");
  131. $(mdoc).attr("role", "document");
  132. var msubdoc = document.createElement("div");
  133. msubdoc.className = getGuiStyles.call(this, "dialog.subdocument");
  134. mdoc.appendChild(msubdoc);
  135. mw.appendChild(mdoc);
  136. // create the title "div.ui-jqdialog-titlebar", which contains:
  137. // "span.ui-jqdialog-title" with the title text and "a.ui-jqdialog-titlebar-close" with the closing button
  138. var mh = document.createElement("div");
  139. mh.className = getGuiStyles.call(this,
  140. "dialog.header",
  141. "ui-jqdialog-titlebar " + (rtlsup ? "ui-jqdialog-titlebar-rtl" : "ui-jqdialog-titlebar-ltr"));
  142. mh.id = aIDs.modalhead;
  143. $(mh).append("<span class='ui-jqdialog-title'>" + o.caption + "</span>");
  144. var hoverClasses = getGuiStyles.call(this, "states.hover"),
  145. ahr = $("<a aria-label='Close' class='" + getGuiStyles.call(this, "dialog.closeButton", "ui-jqdialog-titlebar-close") + "'></a>")
  146. .hover(function () { ahr.addClass(hoverClasses); },
  147. function () { ahr.removeClass(hoverClasses); })
  148. .append("<span class='" + base.getIconRes.call(this, "form.close") + "'></span>");
  149. $(mh).append(ahr);
  150. // create "div.ui-jqdialog-content" which hold some HTML content (see input parameter)
  151. var mc = document.createElement("div");
  152. $(mc).addClass(getGuiStyles.call(this, "dialog.content", "ui-jqdialog-content"))
  153. .attr("id", aIDs.modalcontent);
  154. $(mc).append(content);
  155. // place "div.ui-jqdialog-content" and "div.ui-jqdialog-titlebar" in main window "div.ui-jqdialog"
  156. msubdoc.appendChild(mc);
  157. $(msubdoc).prepend(mh);
  158. // appendsel and insertSelector specifies where the dialog should be placed on the HTML page
  159. if (appendsel === true) {
  160. $("body").append(mw); //append as first child in body -for alert dialog
  161. } else if (typeof appendsel === "string") {
  162. $(appendsel).append(mw);
  163. } else { $(mw).insertBefore(insertSelector); }
  164. $(mw).css(css);
  165. if (o.jqModal === undefined) { o.jqModal = true; } // internal use
  166. var coord = {};
  167. if ($.fn.jqm && o.jqModal === true) {
  168. if (o.left === 0 && o.top === 0 && o.overlay) {
  169. o = $(posSelector).offset();
  170. o.left += 4;
  171. o.top += 4;
  172. }
  173. coord.top = o.top + "px";
  174. coord.left = o.left;
  175. } else if (o.left !== 0 || o.top !== 0) {
  176. coord.left = o.left;
  177. coord.top = o.top + "px";
  178. }
  179. $("a.ui-jqdialog-titlebar-close", mh).click(function () {
  180. var oncm = $(themodalSelector).data("onClose") || o.onClose;
  181. var gboxclose = $(themodalSelector).data("gbox") || o.gbox;
  182. jgrid.hideModal(themodalSelector, {
  183. gb: gboxclose,
  184. jqm: o.jqModal,
  185. onClose: oncm,
  186. removemodal: o.removemodal || false
  187. });
  188. return false;
  189. });
  190. if (o.width === 0 || !o.width) { o.width = 300; }
  191. if (o.height === 0 || !o.height) { o.height = 200; }
  192. if (!o.zIndex) {
  193. var parentZ = $(insertSelector).parents("*[role=dialog]").first().css("z-index");
  194. if (parentZ) {
  195. o.zIndex = parseInt(parentZ, 10) + 2;
  196. o.toTop = true;
  197. } else {
  198. o.zIndex = 950;
  199. }
  200. }
  201. // ONE NEEDS correction of left position in case of RTL, but the current code places
  202. // modal dialog OUT OF visible part of/ the window if <body dir="rtl">.
  203. // Thus first of all the lines are commented. Later the FIXED code below will be included.
  204. /*var rtlt = 0;
  205. if( rtlsup && coord.left && !appendsel) {
  206. rtlt = $(o.gbox).width()- (!isNaN(o.width) ? parseInt(o.width,10) :0) - 8; // to do
  207. // just in case
  208. coord.left = parseInt(coord.left,10) + parseInt(rtlt,10);
  209. }*/
  210. if (coord.left) { coord.left += "px"; }
  211. $(mw).css($.extend({
  212. width: isNaN(o.width) ? "auto" : o.width + "px",
  213. height: isNaN(o.height) ? "auto" : o.height + "px",
  214. zIndex: o.zIndex
  215. }, coord))
  216. .attr({ tabIndex: "-1", "role": "dialog", "aria-labelledby": aIDs.modalhead, "aria-hidden": "true" });
  217. if (o.drag === undefined) { o.drag = true; }
  218. if (o.resize === undefined) { o.resize = true; }
  219. if (o.drag) {
  220. if ($.fn.jqDrag) {
  221. // .ui-draggable .ui-dialog-titlebar {cursor: move}
  222. //$(mw).addClass("ui-draggable"); //css("cursor", "move");
  223. $(mh).css("cursor", "move");
  224. $(mw).jqDrag(mh);
  225. } else {
  226. try {
  227. $(mw).draggable({ handle: $("#" + jqID(mh.id)) });
  228. } catch (ignore) { }
  229. }
  230. }
  231. if (o.resize) {
  232. if ($.fn.jqResize) {
  233. $(mc).append("<div class='jqResize ui-resizable-handle ui-resizable-se " + o.resizingRightBottomIcon + "'></div>");
  234. $(themodalSelector).jqResize(".jqResize", resizeAlso);
  235. } else {
  236. try {
  237. $(mw).resizable({ handles: "se, sw", alsoResize: resizeAlso });
  238. } catch (ignore) { }
  239. }
  240. }
  241. if (o.closeOnEscape === true) {
  242. $(mw).keydown(function (e) {
  243. if (e.which === 27) {
  244. var cone = $(themodalSelector).data("onClose") || o.onClose;
  245. jgrid.hideModal(themodalSelector, { gb: o.gbox, jqm: o.jqModal, onClose: cone, removemodal: o.removemodal || false, formprop: !o.recreateForm || false, form: o.form || "" });
  246. }
  247. });
  248. }
  249. },
  250. viewModal: function (selector, o) {
  251. o = $.extend(true, {
  252. //toTop: false,
  253. overlay: 30,
  254. modal: false,
  255. overlayClass: getGuiStyles.call(this, "overlay"), // "ui-widget-overlay"
  256. onShow: jgrid.showModal,
  257. onHide: jgrid.closeModal,
  258. gbox: "",
  259. jqm: true,
  260. jqM: true
  261. }, jgrid.jqModal || {}, o || {});
  262. if ($.fn.jqm && o.jqm === true) {
  263. if (o.jqM) {
  264. $(selector).attr("aria-hidden", "false").jqm(o).jqmShow();
  265. } else {
  266. $(selector).attr("aria-hidden", "false").jqmShow();
  267. }
  268. } else {
  269. if (o.gbox !== "") {
  270. $(">.jqgrid-overlay", o.gbox).first().show();
  271. $(selector).data("gbox", o.gbox);
  272. }
  273. $(selector).show().attr("aria-hidden", "false");
  274. try { $(":input:visible", selector)[0].focus(); } catch (ignore) { }
  275. }
  276. },
  277. info_dialog: function (caption, content, closeButtonText, modalopt) {
  278. var $t = this, p = $t.p,
  279. mopt = $.extend(true,
  280. {
  281. width: 290,
  282. height: "auto",
  283. dataheight: "auto",
  284. drag: true,
  285. resize: false,
  286. left: 250,
  287. top: 170,
  288. zIndex: 1000,
  289. jqModal: true,
  290. modal: false,
  291. closeOnEscape: true,
  292. align: "center",
  293. buttonalign: "center",
  294. buttons: []
  295. // {text:"textbutt", id:"buttid", onClick : function(){...}}
  296. // if the id is not provided we set it like info_button_+ the index in the array - i.e info_button_0,info_button_1...
  297. },
  298. jgrid.jqModal || {},
  299. p != null ? p.jqModal || {} : {},
  300. { caption: "<b>" + caption + "</b>" },
  301. modalopt || {}),
  302. jm = mopt.jqModal;
  303. if ($.fn.jqm && !jm) { jm = false; }
  304. // in case there is no jqModal
  305. var buttstr = "", i, hoverClasses = getGuiStyles.call($t, "states.hover");
  306. if (mopt.buttons.length > 0) {
  307. for (i = 0; i < mopt.buttons.length; i++) {
  308. if (mopt.buttons[i].id === undefined) { mopt.buttons[i].id = "info_button_" + i; }
  309. buttstr += jgrid.builderFmButon.call($t, mopt.buttons[i].id, mopt.buttons[i].text);
  310. }
  311. }
  312. var dh = isNaN(mopt.dataheight) ? mopt.dataheight : mopt.dataheight + "px",
  313. cn = "text-align:" + mopt.align + ";",
  314. $dlg = $("#info_dialog"),
  315. cnt = "<div id='info_id'>";
  316. cnt += "<div id='infocnt' style='margin:0px;padding-bottom:1em;width:100%;overflow:auto;position:relative;height:" + dh + ";" + cn + "'>" + content + "</div>";
  317. if (closeButtonText || buttstr !== "") {
  318. cnt += "<hr class='" + getGuiStyles.call($t, "dialog.hr") + "' style='margin:1px'/><div style='text-align:" + mopt.buttonalign +
  319. ";padding:.8em 0 .5em 0;background-image:none;border-width: 1px 0 0 0;'>" +
  320. (closeButtonText ? jgrid.builderFmButon.call($t, "closedialog", closeButtonText) : "") + buttstr + "</div>";
  321. }
  322. cnt += "</div>";
  323. try {
  324. if ($dlg.attr("aria-hidden") === "false") {
  325. jgrid.hideModal("#info_dialog", { jqm: jm });
  326. }
  327. $dlg.remove();
  328. } catch (ignore) { }
  329. jgrid.createModal.call($t,
  330. {
  331. themodal: "info_dialog",
  332. modalhead: "info_head",
  333. modalcontent: "info_content",
  334. resizeAlso: "infocnt"
  335. },
  336. cnt,
  337. mopt,
  338. "", "", true);
  339. // attach onclick after inserting into the dom
  340. $dlg = $("#info_dialog");
  341. if (buttstr) {
  342. $.each(mopt.buttons, function () {
  343. $("#" + jgrid.jqID(this.id), "#info_id")
  344. .on("click",
  345. { click: this.onClick },
  346. function (e) {
  347. if ($.isFunction(e.data.click)) {
  348. e.data.click.call($t, e, $dlg);
  349. }
  350. return false;
  351. });
  352. });
  353. }
  354. $("#closedialog", "#info_id").click(function () {
  355. jgrid.hideModal("#info_dialog", {
  356. jqm: jm,
  357. onClose: $dlg.data("onClose") || mopt.onClose,
  358. gb: $dlg.data("gbox") || mopt.gbox
  359. });
  360. return false;
  361. });
  362. $(".fm-button", "#info_dialog").hover(
  363. function () { $(this).addClass(hoverClasses); },
  364. function () { $(this).removeClass(hoverClasses); }
  365. );
  366. if ($.isFunction(mopt.beforeOpen)) { mopt.beforeOpen(); }
  367. jgrid.viewModal.call($t, "#info_dialog", {
  368. onHide: function (h) {
  369. h.w.hide().remove();
  370. if (h.o) { h.o.remove(); }
  371. },
  372. modal: mopt.modal,
  373. jqm: jm
  374. });
  375. if ($.isFunction(mopt.afterOpen)) { mopt.afterOpen(); }
  376. try { $dlg.focus(); } catch (ignore) { }
  377. },
  378. bindEv: function (el, opt) {
  379. var $t = this, p = $t.p;
  380. if ($.isFunction(opt.dataInit)) {
  381. opt.dataInit.call($t, el, opt);
  382. }
  383. if (opt.dataEvents) {
  384. $.each(opt.dataEvents, function () {
  385. var data = this.data === undefined ?
  386. $.extend({ gridId: p.id, gridIdSel: p.idSel }, opt) :
  387. (typeof this.data === "object" && this.data !== null ?
  388. $.extend(true, { gridId: p.id, gridIdSel: p.idSel }, opt, this.data) :
  389. this.data);
  390. $(el).on(this.type, data, this.fn);
  391. });
  392. }
  393. },
  394. // Form Functions
  395. createEl: function (eltype, options, vl, autowidth, ajaxso) {
  396. var elem = "", $t = this, p = $t.p, infoDialog = jgrid.info_dialog,
  397. getRes = function (path) { return getGridRes.call($($t), path); },
  398. errcap = getRes("errors.errcap"), edit = getRes("edit"), editMsg = edit.msg, bClose = edit.bClose;
  399. function setAttributes(elm, atr, exl) {
  400. var exclude = [
  401. "dataInit",
  402. "dataEvents",
  403. "dataUrl",
  404. "buildSelect",
  405. "sopt",
  406. "searchhidden",
  407. "defaultValue",
  408. "attr",
  409. "custom_element",
  410. "custom_value",
  411. "generateValue",
  412. "postData",
  413. "selectFilled",
  414. "rowId",
  415. "column",
  416. "mode",
  417. "cm",
  418. "iCol"
  419. ];
  420. if (exl !== undefined && $.isArray(exl)) {
  421. $.merge(exclude, exl);
  422. }
  423. $.each(atr, function (attrName, value) {
  424. if ($.inArray(attrName, exclude) === -1) {
  425. $(elm).attr(attrName, value);
  426. }
  427. });
  428. if (!atr.hasOwnProperty("id")) {
  429. $(elm).attr("id", jgrid.randId());
  430. }
  431. }
  432. if (options == null) { return ""; }
  433. switch (eltype) {
  434. case "textarea":
  435. elem = document.createElement("textarea");
  436. if (autowidth) {
  437. if (!options.cols) { $(elem).css({ width: "100%", "box-sizing": "border-box" }); }
  438. } else if (!options.cols) { options.cols = 19; }
  439. if (!options.rows) { options.rows = 2; }
  440. if (vl === "&nbsp;" || vl === "&#160;" || (vl.length === 1 && vl.charCodeAt(0) === 160)) { vl = ""; }
  441. elem.value = vl;
  442. setAttributes(elem, options);
  443. $(elem).attr({ role: "textbox" }); // , "multiline": "true"
  444. break;
  445. case "checkbox": //what code for simple checkbox
  446. elem = document.createElement("input");
  447. elem.type = "checkbox";
  448. if (vl === "" || vl == null) {
  449. vl = !options.hasOwnProperty("defaultValue") ?
  450. "false" :
  451. $.isFunction(options.defaultValue) ?
  452. options.defaultValue.call($t, {
  453. cellValue: vl,
  454. options: options
  455. }) :
  456. options.defaultValue;
  457. }
  458. if (!options.value) {
  459. var vl1 = String(vl).toLowerCase();
  460. if (vl1.search(/(false|f|0|no|n|off|undefined)/i) < 0 && vl1 !== "") {
  461. elem.checked = true;
  462. elem.defaultChecked = true;
  463. elem.value = vl;
  464. } else {
  465. elem.value = "on";
  466. }
  467. $(elem).data("offval", "off");
  468. } else {
  469. var cbval = options.value.split(":");
  470. if (vl === cbval[0]) {
  471. elem.checked = true;
  472. elem.defaultChecked = true;
  473. }
  474. elem.value = vl;
  475. $(elem).data("offval", cbval[1]);
  476. }
  477. setAttributes(elem, options, ["value"]);
  478. $(elem).attr({ role: "checkbox", "aria-checked": elem.checked ? "true" : "false" });
  479. break;
  480. case "select":
  481. elem = document.createElement("select");
  482. //var msl, ovm = [], isSelected, rowid = null;
  483. var msl, ovm = [], rowid = null;
  484. if (options.multiple === true || options.multiple === "multiple") {
  485. msl = true;
  486. elem.multiple = "multiple";
  487. $(elem).attr("aria-multiselectable", "true");
  488. ovm = vl.split(",");
  489. ovm = $.map(ovm, function (n) { return $.trim(n); });
  490. } else {
  491. msl = false;
  492. ovm[0] = $.trim(vl);
  493. }
  494. if (options.size === undefined) {
  495. options.size = msl ? 3 : 1;
  496. }
  497. try {
  498. rowid = options.rowId;
  499. } catch (ignore) { }
  500. if (p && p.idPrefix) {
  501. rowid = jgrid.stripPref(p.idPrefix, rowid);
  502. }
  503. if (options.dataUrl === undefined && options.generateValue && p.indexByColumnData[options.cm.name] != null) {
  504. options.value = $t.generateValueFromColumnIndex(options.cm.name, options.separator, options.delimiter);
  505. }
  506. if (options.dataUrl !== undefined) {
  507. var postData = options.postData || ajaxso.postData,
  508. ajaxContext = {
  509. elem: elem,
  510. options: options,
  511. cm: options.cm,
  512. mode: options.mode,
  513. rowid: rowid,
  514. iCol: options.iCol,
  515. ovm: ovm
  516. };
  517. setAttributes(elem, options, postData ? ["postData"] : undefined);
  518. $.ajax($.extend({
  519. url: $.isFunction(options.dataUrl) ? options.dataUrl.call($t, rowid, vl, String(options.name), ajaxContext) : options.dataUrl,
  520. type: "GET",
  521. dataType: "html",
  522. data: $.isFunction(postData) ? postData.call($t, rowid, vl, String(options.name)) : postData,
  523. context: ajaxContext,
  524. success: function (data, textStatus, jqXHR) {
  525. var ovm1 = this.ovm, elem1 = this.elem, cm1 = this.cm, iCol1 = this.iCol,
  526. options1 = $.extend({}, this.options), rowid1 = this.rowid, mode1 = this.mode,
  527. a = $.isFunction(options1.buildSelect) ? options1.buildSelect.call($t, data, jqXHR, cm1, iCol1) : data;
  528. if (typeof a === "string") {
  529. a = $($.trim(a)).html();
  530. }
  531. if (a) {
  532. //$(elem1).empty(); // ???
  533. $(elem1).append(a);
  534. setTimeout(function () {
  535. var isSelected1; // undefined
  536. $("option", elem1).each(function (iOpt) {
  537. //if(i===0) { this.selected = false; }
  538. // fix IE8/IE7 problem with selecting of the first item on multiple=true
  539. if (iOpt === 0 && elem1.multiple) { this.selected = false; }
  540. if ($.inArray($.trim($(this).val()), ovm1) > -1) {
  541. // this.setAttribute("selected", "selected");
  542. this.selected = true;
  543. isSelected1 = true;
  544. }
  545. });
  546. if (!isSelected1) {
  547. $("option", elem1).each(function () {
  548. if ($.inArray($.trim($(this).text()), ovm1) > -1) {
  549. // this.setAttribute("selected", "selected");
  550. this.selected = true;
  551. }
  552. });
  553. }
  554. //$(elem1).change();
  555. jgrid.fullBoolFeedback.call($t, options1.selectFilled, "jqGridSelectFilled", {
  556. elem: elem1,
  557. options: options1,
  558. cm: cm1,
  559. rowid: rowid1,
  560. mode: mode1,
  561. cmName: cm1 != null ? cm1.name : options1.name,
  562. iCol: iCol1
  563. });
  564. }, 0);
  565. }
  566. }
  567. }, ajaxso || {}));
  568. } else if (options.value) {
  569. jgrid.fillSelectOptions(
  570. elem,
  571. options.value,
  572. options.separator === undefined ? ":" : options.separator,
  573. options.delimiter === undefined ? ";" : options.delimiter,
  574. msl,
  575. vl
  576. );
  577. setAttributes(elem, options, ["value"]);
  578. jgrid.fullBoolFeedback.call($t, options.selectFilled, "jqGridSelectFilled", {
  579. elem: elem,
  580. options: options,
  581. cm: options.cm,
  582. rowid: rowid,
  583. mode: options.mode,
  584. cmName: options.cm != null ? options.cm.name : options.name,
  585. iCol: options.iCol
  586. });
  587. }
  588. break;
  589. case "text":
  590. case "password":
  591. case "button":
  592. var role;
  593. if (eltype === "button") {
  594. role = "button";
  595. } else {
  596. role = "textbox";
  597. }
  598. elem = document.createElement("input");
  599. elem.type = eltype;
  600. setAttributes(elem, options);
  601. elem.value = vl;
  602. if (eltype !== "button") {
  603. if (autowidth) {
  604. if (!options.size) { $(elem).css({ width: "100%", "box-sizing": "border-box" }); }
  605. } else if (!options.size) {
  606. options.size = 20;
  607. }
  608. }
  609. $(elem).attr("role", role);
  610. break;
  611. case "image":
  612. case "file":
  613. elem = document.createElement("input");
  614. elem.type = eltype;
  615. setAttributes(elem, options);
  616. break;
  617. case "custom":
  618. elem = document.createElement("span");
  619. try {
  620. if ($.isFunction(options.custom_element)) {
  621. var celm = options.custom_element.call($t, vl, options);
  622. if (celm instanceof jQuery || jgrid.isHTMLElement(celm) || typeof celm === "string") {
  623. celm = $(celm).addClass("customelement").attr({ id: options.id, name: options.name });
  624. $(elem).empty().append(celm);
  625. } else {
  626. throw "editoptions.custom_element returns value of a wrong type";
  627. }
  628. } else {
  629. throw "editoptions.custom_element is not a function";
  630. }
  631. } catch (e) {
  632. if (e === "e1") {
  633. infoDialog.call($t, errcap, "function 'custom_element' " + editMsg.nodefined, bClose);
  634. }
  635. if (e === "e2") {
  636. infoDialog.call($t, errcap, "function 'custom_element' " + editMsg.novalue, bClose);
  637. } else {
  638. infoDialog.call($t, errcap, typeof e === "string" ? e : e.message, bClose);
  639. }
  640. }
  641. break;
  642. }
  643. return elem;
  644. },
  645. // Date Validation Javascript
  646. checkDate: function (format, date) {
  647. var daysInFebruary = function (year) {
  648. // February has 29 days in any year evenly divisible by four,
  649. // EXCEPT for centurial years which are not also divisible by 400.
  650. return (((year % 4 === 0) && (year % 100 !== 0 || (year % 400 === 0))) ? 29 : 28);
  651. },
  652. tsp = {},
  653. sep;
  654. format = format.toLowerCase();
  655. //we search for /,-,. for the date separator
  656. if (format.indexOf("/") !== -1) {
  657. sep = "/";
  658. } else if (format.indexOf("-") !== -1) {
  659. sep = "-";
  660. } else if (format.indexOf(".") !== -1) {
  661. sep = ".";
  662. } else {
  663. sep = "/";
  664. }
  665. format = format.split(sep);
  666. date = date.split(sep);
  667. if (date.length !== 3) { return false; }
  668. var j = -1, yln, dln = -1, mln = -1, i, dv;
  669. for (i = 0; i < format.length; i++) {
  670. dv = isNaN(date[i]) ? 0 : parseInt(date[i], 10);
  671. tsp[format[i]] = dv;
  672. yln = format[i];
  673. if (yln.indexOf("y") !== -1) { j = i; }
  674. if (yln.indexOf("m") !== -1) { mln = i; }
  675. if (yln.indexOf("d") !== -1) { dln = i; }
  676. }
  677. if (format[j] === "y" || format[j] === "yyyy") {
  678. yln = 4;
  679. } else if (format[j] === "yy") {
  680. yln = 2;
  681. } else {
  682. yln = -1;
  683. }
  684. var strDate, daysInMonth = [0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
  685. if (j === -1) {
  686. return false;
  687. }
  688. strDate = tsp[format[j]].toString();
  689. if (yln === 2 && strDate.length === 1) { yln = 1; }
  690. if (strDate.length !== yln || (tsp[format[j]] === 0 && date[j] !== "00")) {
  691. return false;
  692. }
  693. if (mln === -1) {
  694. return false;
  695. }
  696. strDate = tsp[format[mln]].toString();
  697. if (strDate.length < 1 || tsp[format[mln]] < 1 || tsp[format[mln]] > 12) {
  698. return false;
  699. }
  700. if (dln === -1) {
  701. return false;
  702. }
  703. strDate = tsp[format[dln]].toString();
  704. if (strDate.length < 1 || tsp[format[dln]] < 1 || tsp[format[dln]] > 31 || (tsp[format[mln]] === 2 && tsp[format[dln]] > daysInFebruary(tsp[format[j]])) || tsp[format[dln]] > daysInMonth[tsp[format[mln]]]) {
  705. return false;
  706. }
  707. return true;
  708. },
  709. isEmpty: function (val) {
  710. if (val.match(/^\s+$/) || val === "") {
  711. return true;
  712. }
  713. return false;
  714. },
  715. checkTime: function (time) {
  716. // checks only hh:ss (and optional am/pm)
  717. var re = /^(\d{1,2}):(\d{2})([apAP][Mm])?$/, regs;
  718. if (!jgrid.isEmpty(time)) {
  719. regs = time.match(re);
  720. if (regs) {
  721. if (regs[3]) {
  722. if (regs[1] < 1 || regs[1] > 12) { return false; }
  723. } else {
  724. if (regs[1] > 23) { return false; }
  725. }
  726. if (regs[2] > 59) {
  727. return false;
  728. }
  729. } else {
  730. return false;
  731. }
  732. }
  733. return true;
  734. },
  735. checkValues: function (val, iCol, customobject, nam, options) {
  736. var edtrul, nm, dft, g = this, p = g.p, colModel = p.colModel, cm, isEmpty = jgrid.isEmpty,
  737. editMsg = getGridRes.call($(g), "edit.msg"), ret,
  738. getPropertyValue = function (propertyName) {
  739. var propValue = edtrul[propertyName];
  740. return $.isFunction(propValue) ? propValue.call(g, options) : propValue;
  741. },
  742. dateMasks = getGridRes.call($(g), "formatter.date.masks");
  743. if (customobject === undefined) {
  744. if (typeof iCol === "string") {
  745. iCol = p.iColByName[iCol];
  746. }
  747. if (iCol === undefined || iCol < 0) {
  748. return [true, "", ""];
  749. }
  750. cm = colModel[iCol];
  751. edtrul = cm.editrules;
  752. if (cm.formoptions != null) { nm = cm.formoptions.label; }
  753. } else {
  754. edtrul = customobject;
  755. nm = nam === undefined ? "_" : nam;
  756. cm = colModel[iCol];
  757. }
  758. if (edtrul) {
  759. if (!nm) { nm = p.colNames != null ? p.colNames[iCol] : cm.label; }
  760. if (getPropertyValue("required") === true) {
  761. if (isEmpty(val)) { return [false, nm + ": " + editMsg.required, ""]; }
  762. }
  763. // force required
  764. var rqfield = getPropertyValue("required") === false ? false : true;
  765. if (getPropertyValue("number") === true) {
  766. if (!(rqfield === false && isEmpty(val))) {
  767. if (isNaN(val)) { return [false, nm + ": " + editMsg.number, ""]; }
  768. }
  769. }
  770. if (edtrul.minValue !== undefined && !isNaN(edtrul.minValue)) {
  771. if (parseFloat(val) < parseFloat(edtrul.minValue)) { return [false, nm + ": " + editMsg.minValue + " " + edtrul.minValue, ""]; }
  772. }
  773. if (edtrul.maxValue !== undefined && !isNaN(edtrul.maxValue)) {
  774. if (parseFloat(val) > parseFloat(edtrul.maxValue)) { return [false, nm + ": " + editMsg.maxValue + " " + edtrul.maxValue, ""]; }
  775. }
  776. var filter;
  777. if (getPropertyValue("email") === true) {
  778. if (!(rqfield === false && isEmpty(val))) {
  779. // taken from $ Validate plugin
  780. filter = /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i;
  781. if (!filter.test(val)) { return [false, nm + ": " + editMsg.email, ""]; }
  782. }
  783. }
  784. if (getPropertyValue("integer") === true) {
  785. if (!(rqfield === false && isEmpty(val))) {
  786. if (isNaN(val)) { return [false, nm + ": " + editMsg.integer, ""]; }
  787. if ((val % 1 !== 0) || (val.indexOf(".") !== -1)) { return [false, nm + ": " + editMsg.integer, ""]; }
  788. }
  789. }
  790. if (getPropertyValue("date") === true) {
  791. if (!(rqfield === false && isEmpty(val))) {
  792. if (cm.formatoptions && cm.formatoptions.newformat) {
  793. dft = cm.formatoptions.newformat;
  794. if (dateMasks.hasOwnProperty(dft)) {
  795. dft = dateMasks[dft];
  796. }
  797. } else {
  798. dft = colModel[iCol].datefmt || "Y-m-d";
  799. }
  800. if (!jgrid.checkDate(dft, val)) { return [false, nm + ": " + editMsg.date + " - " + dft, ""]; }
  801. }
  802. }
  803. if (getPropertyValue("time") === true) {
  804. if (!(rqfield === false && isEmpty(val))) {
  805. if (!jgrid.checkTime(val)) { return [false, nm + ": " + editMsg.date + " - hh:mm (am/pm)", ""]; }
  806. }
  807. }
  808. if (getPropertyValue("url") === true) {
  809. if (!(rqfield === false && isEmpty(val))) {
  810. filter = /^(((https?)|(ftp)):\/\/([\-\w]+\.)+\w{2,3}(\/[%\-\w]+(\.\w{2,})?)*(([\w\-\.\?\\\/+@&#;`~=%!]*)(\.\w{2,})?)*\/?)/i;
  811. if (!filter.test(val)) { return [false, nm + ": " + editMsg.url, ""]; }
  812. }
  813. }
  814. if (edtrul.custom === true) {
  815. if (!(rqfield === false && isEmpty(val))) {
  816. if ($.isFunction(edtrul.custom_func)) {
  817. ret = edtrul.custom_func.call(g, val, nm, iCol);
  818. return $.isArray(ret) ? ret : [false, editMsg.customarray, ""];
  819. }
  820. return [false, editMsg.customfcheck, ""];
  821. }
  822. } else if ($.isFunction(edtrul.custom)) {
  823. if (!(rqfield === false && isEmpty(val))) {
  824. ret = edtrul.custom.call(g, options);
  825. return $.isArray(ret) ? ret : [false, editMsg.customarray, ""];
  826. }
  827. }
  828. }
  829. return [true, "", ""];
  830. }
  831. });
  832. // end module grid.common
  833. }));