ui.form.js 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982
  1. /**
  2. * DevExtreme (ui/form/ui.form.js)
  3. * Version: 19.1.16
  4. * Build date: Tue Oct 18 2022
  5. *
  6. * Copyright (c) 2012 - 2022 Developer Express Inc. ALL RIGHTS RESERVED
  7. * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
  8. */
  9. "use strict";
  10. var _renderer = require("../../core/renderer");
  11. var _renderer2 = _interopRequireDefault(_renderer);
  12. var _events_engine = require("../../events/core/events_engine");
  13. var _events_engine2 = _interopRequireDefault(_events_engine);
  14. var _component_registrator = require("../../core/component_registrator");
  15. var _component_registrator2 = _interopRequireDefault(_component_registrator);
  16. var _guid = require("../../core/guid");
  17. var _guid2 = _interopRequireDefault(_guid);
  18. var _common = require("../../core/utils/common");
  19. var _type = require("../../core/utils/type");
  20. var _iterator = require("../../core/utils/iterator");
  21. var _array = require("../../core/utils/array");
  22. var _extend = require("../../core/utils/extend");
  23. var _string = require("../../core/utils/string");
  24. var _browser = require("../../core/utils/browser");
  25. var _browser2 = _interopRequireDefault(_browser);
  26. var _dom = require("../../core/utils/dom");
  27. var _message = require("../../localization/message");
  28. var _message2 = _interopRequireDefault(_message);
  29. var _ui = require("../widget/ui.widget");
  30. var _ui2 = _interopRequireDefault(_ui);
  31. var _window = require("../../core/utils/window");
  32. var _validation_engine = require("../validation_engine");
  33. var _validation_engine2 = _interopRequireDefault(_validation_engine);
  34. var _uiForm = require("./ui.form.layout_manager");
  35. var _uiForm2 = _interopRequireDefault(_uiForm);
  36. var _uiForm3 = require("./ui.form.items_runtime_info");
  37. var _uiForm4 = _interopRequireDefault(_uiForm3);
  38. var _tab_panel = require("../tab_panel");
  39. var _tab_panel2 = _interopRequireDefault(_tab_panel);
  40. var _ui3 = require("../scroll_view/ui.scrollable");
  41. var _ui4 = _interopRequireDefault(_ui3);
  42. var _deferred = require("../../core/utils/deferred");
  43. var _themes = require("../themes");
  44. var _themes2 = _interopRequireDefault(_themes);
  45. var _uiForm5 = require("./ui.form.item_options_actions");
  46. var _uiForm6 = _interopRequireDefault(_uiForm5);
  47. require("../validation_summary");
  48. require("../validation_group");
  49. function _interopRequireDefault(obj) {
  50. return obj && obj.__esModule ? obj : {
  51. "default": obj
  52. }
  53. }
  54. var FORM_CLASS = "dx-form";
  55. var FIELD_ITEM_CLASS = "dx-field-item";
  56. var FIELD_ITEM_LABEL_TEXT_CLASS = "dx-field-item-label-text";
  57. var FORM_GROUP_CLASS = "dx-form-group";
  58. var FORM_GROUP_CONTENT_CLASS = "dx-form-group-content";
  59. var FORM_GROUP_WITH_CAPTION_CLASS = "dx-form-group-with-caption";
  60. var FORM_GROUP_CAPTION_CLASS = "dx-form-group-caption";
  61. var HIDDEN_LABEL_CLASS = "dx-layout-manager-hidden-label";
  62. var FIELD_ITEM_LABEL_CLASS = "dx-field-item-label";
  63. var FIELD_ITEM_LABEL_CONTENT_CLASS = "dx-field-item-label-content";
  64. var FIELD_ITEM_TAB_CLASS = "dx-field-item-tab";
  65. var FORM_FIELD_ITEM_COL_CLASS = "dx-col-";
  66. var GROUP_COL_COUNT_CLASS = "dx-group-colcount-";
  67. var FIELD_ITEM_CONTENT_CLASS = "dx-field-item-content";
  68. var FORM_VALIDATION_SUMMARY = "dx-form-validation-summary";
  69. var WIDGET_CLASS = "dx-widget";
  70. var FOCUSED_STATE_CLASS = "dx-state-focused";
  71. var Form = _ui2.default.inherit({
  72. _init: function() {
  73. this.callBase();
  74. this._cachedColCountOptions = [];
  75. this._itemsRunTimeInfo = new _uiForm4.default;
  76. this._groupsColCount = [];
  77. this._attachSyncSubscriptions()
  78. },
  79. _initOptions: function(options) {
  80. if (!("screenByWidth" in options)) {
  81. options.screenByWidth = _window.defaultScreenFactorFunc
  82. }
  83. this.callBase(options)
  84. },
  85. _getDefaultOptions: function() {
  86. return (0, _extend.extend)(this.callBase(), {
  87. formID: "dx-" + new _guid2.default,
  88. formData: {},
  89. colCount: 1,
  90. screenByWidth: null,
  91. colCountByScreen: void 0,
  92. labelLocation: "left",
  93. readOnly: false,
  94. onFieldDataChanged: null,
  95. customizeItem: null,
  96. onEditorEnterKey: null,
  97. minColWidth: 200,
  98. alignItemLabels: true,
  99. alignItemLabelsInAllGroups: true,
  100. showColonAfterLabel: true,
  101. showRequiredMark: true,
  102. showOptionalMark: false,
  103. requiredMark: "*",
  104. optionalMark: _message2.default.format("dxForm-optionalMark"),
  105. requiredMessage: _message2.default.getFormatter("dxForm-requiredMessage"),
  106. showValidationSummary: false,
  107. items: void 0,
  108. scrollingEnabled: false,
  109. validationGroup: void 0,
  110. stylingMode: void 0
  111. })
  112. },
  113. _defaultOptionsRules: function() {
  114. return this.callBase().concat([{
  115. device: function() {
  116. return _themes2.default.isMaterial()
  117. },
  118. options: {
  119. showColonAfterLabel: false,
  120. labelLocation: "top"
  121. }
  122. }])
  123. },
  124. _setOptionsByReference: function() {
  125. this.callBase();
  126. (0, _extend.extend)(this._optionsByReference, {
  127. formData: true,
  128. validationGroup: true
  129. })
  130. },
  131. _getColCount: function($element) {
  132. var index = 0;
  133. var isColsExist = true;
  134. var $cols;
  135. while (isColsExist) {
  136. $cols = $element.find("." + FORM_FIELD_ITEM_COL_CLASS + index);
  137. if (!$cols.length) {
  138. isColsExist = false
  139. } else {
  140. index++
  141. }
  142. }
  143. return index
  144. },
  145. _createHiddenElement: function(rootLayoutManager) {
  146. this._$hiddenElement = (0, _renderer2.default)("<div>").addClass(WIDGET_CLASS).addClass(HIDDEN_LABEL_CLASS).appendTo("body");
  147. var $hiddenLabel = rootLayoutManager._renderLabel({
  148. text: " ",
  149. location: this.option("labelLocation")
  150. }).appendTo(this._$hiddenElement);
  151. this._hiddenLabelText = $hiddenLabel.find("." + FIELD_ITEM_LABEL_TEXT_CLASS)[0]
  152. },
  153. _removeHiddenElement: function() {
  154. this._$hiddenElement.remove();
  155. this._hiddenLabelText = null
  156. },
  157. _getLabelWidthByText: function(text) {
  158. this._hiddenLabelText.innerHTML = text;
  159. return this._hiddenLabelText.offsetWidth
  160. },
  161. _getLabelsSelectorByCol: function(index, options) {
  162. options = options || {};
  163. var fieldItemClass = options.inOneColumn ? FIELD_ITEM_CLASS : FORM_FIELD_ITEM_COL_CLASS + index;
  164. var cssExcludeTabbedSelector = options.excludeTabbed ? ":not(." + FIELD_ITEM_TAB_CLASS + ")" : "";
  165. var childLabelContentSelector = "> ." + FIELD_ITEM_LABEL_CLASS + " > ." + FIELD_ITEM_LABEL_CONTENT_CLASS;
  166. return "." + fieldItemClass + cssExcludeTabbedSelector + childLabelContentSelector
  167. },
  168. _getLabelText: function(labelText) {
  169. var length = labelText.children.length;
  170. var result = "";
  171. for (var i = 0; i < length; i++) {
  172. var child = labelText.children[i];
  173. result += !(0, _string.isEmpty)(child.innerText) ? child.innerText : child.innerHTML
  174. }
  175. return result
  176. },
  177. _applyLabelsWidthByCol: function($container, index, options) {
  178. var $labelTexts = $container.find(this._getLabelsSelectorByCol(index, options));
  179. var $labelTextsLength = $labelTexts.length;
  180. var i;
  181. var maxWidth = 0;
  182. for (i = 0; i < $labelTextsLength; i++) {
  183. var labelWidth = this._getLabelWidthByText(this._getLabelText($labelTexts[i]));
  184. if (labelWidth > maxWidth) {
  185. maxWidth = labelWidth
  186. }
  187. }
  188. for (i = 0; i < $labelTextsLength; i++) {
  189. $labelTexts[i].style.width = maxWidth + "px"
  190. }
  191. },
  192. _applyLabelsWidth: function($container, excludeTabbed, inOneColumn, colCount) {
  193. colCount = inOneColumn ? 1 : colCount || this._getColCount($container);
  194. var applyLabelsOptions = {
  195. excludeTabbed: excludeTabbed,
  196. inOneColumn: inOneColumn
  197. };
  198. for (var i = 0; i < colCount; i++) {
  199. this._applyLabelsWidthByCol($container, i, applyLabelsOptions)
  200. }
  201. },
  202. _getGroupElementsInColumn: function($container, columnIndex, colCount) {
  203. var cssColCountSelector = (0, _type.isDefined)(colCount) ? "." + GROUP_COL_COUNT_CLASS + colCount : "";
  204. var groupSelector = "." + FORM_FIELD_ITEM_COL_CLASS + columnIndex + " > ." + FIELD_ITEM_CONTENT_CLASS + " > ." + FORM_GROUP_CLASS + cssColCountSelector;
  205. return $container.find(groupSelector)
  206. },
  207. _applyLabelsWidthWithGroups: function($container, colCount, excludeTabbed) {
  208. var alignItemLabelsInAllGroups = this.option("alignItemLabelsInAllGroups");
  209. if (alignItemLabelsInAllGroups) {
  210. this._applyLabelsWidthWithNestedGroups($container, colCount, excludeTabbed)
  211. } else {
  212. var $groups = this.$element().find("." + FORM_GROUP_CLASS);
  213. for (var i = 0; i < $groups.length; i++) {
  214. this._applyLabelsWidth($groups.eq(i), excludeTabbed)
  215. }
  216. }
  217. },
  218. _applyLabelsWidthWithNestedGroups: function($container, colCount, excludeTabbed) {
  219. var applyLabelsOptions = {
  220. excludeTabbed: excludeTabbed
  221. };
  222. var $groupsByCol;
  223. for (var colIndex = 0; colIndex < colCount; colIndex++) {
  224. $groupsByCol = this._getGroupElementsInColumn($container, colIndex);
  225. this._applyLabelsWidthByCol($groupsByCol, 0, applyLabelsOptions);
  226. for (var groupsColIndex = 0; groupsColIndex < this._groupsColCount.length; groupsColIndex++) {
  227. $groupsByCol = this._getGroupElementsInColumn($container, colIndex, this._groupsColCount[groupsColIndex]);
  228. var groupColCount = this._getColCount($groupsByCol);
  229. for (var groupColIndex = 1; groupColIndex < groupColCount; groupColIndex++) {
  230. this._applyLabelsWidthByCol($groupsByCol, groupColIndex, applyLabelsOptions)
  231. }
  232. }
  233. }
  234. },
  235. _alignLabelsInColumn: function(options) {
  236. if (!(0, _window.hasWindow)()) {
  237. return
  238. }
  239. this._createHiddenElement(options.layoutManager);
  240. if (options.inOneColumn) {
  241. this._applyLabelsWidth(options.$container, options.excludeTabbed, true)
  242. } else {
  243. if (this._checkGrouping(options.items)) {
  244. this._applyLabelsWidthWithGroups(options.$container, options.layoutManager._getColCount(), options.excludeTabbed)
  245. } else {
  246. this._applyLabelsWidth(options.$container, options.excludeTabbed, false, options.layoutManager._getColCount())
  247. }
  248. }
  249. this._removeHiddenElement()
  250. },
  251. _prepareFormData: function() {
  252. if (!(0, _type.isDefined)(this.option("formData"))) {
  253. this.option("formData", {})
  254. }
  255. },
  256. _initMarkup: function() {
  257. _validation_engine2.default.addGroup(this._getValidationGroup());
  258. this._clearCachedInstances();
  259. this._prepareFormData();
  260. this.$element().addClass(FORM_CLASS);
  261. this.callBase();
  262. this.setAria("role", "form", this.$element());
  263. if (this.option("scrollingEnabled")) {
  264. this._renderScrollable()
  265. }
  266. this._renderLayout();
  267. this._renderValidationSummary();
  268. this._lastMarkupScreenFactor = this._targetScreenFactor || this._getCurrentScreenFactor()
  269. },
  270. _getCurrentScreenFactor: function() {
  271. return (0, _window.hasWindow)() ? (0, _window.getCurrentScreenFactor)(this.option("screenByWidth")) : "lg"
  272. },
  273. _clearCachedInstances: function() {
  274. this._itemsRunTimeInfo.clear();
  275. this._cachedLayoutManagers = []
  276. },
  277. _alignLabels: function(layoutManager, inOneColumn) {
  278. this._alignLabelsInColumn({
  279. $container: this.$element(),
  280. layoutManager: layoutManager,
  281. excludeTabbed: true,
  282. items: this.option("items"),
  283. inOneColumn: inOneColumn
  284. })
  285. },
  286. _clean: function() {
  287. this.callBase();
  288. this._groupsColCount = [];
  289. this._cachedColCountOptions = [];
  290. this._lastMarkupScreenFactor = void 0
  291. },
  292. _renderScrollable: function() {
  293. var useNativeScrolling = this.option("useNativeScrolling");
  294. this._scrollable = new _ui4.default(this.$element(), {
  295. useNative: !!useNativeScrolling,
  296. useSimulatedScrollbar: !useNativeScrolling,
  297. useKeyboard: false,
  298. direction: "both",
  299. bounceEnabled: false
  300. })
  301. },
  302. _getContent: function() {
  303. return this.option("scrollingEnabled") ? this._scrollable.$content() : this.$element()
  304. },
  305. _renderValidationSummary: function() {
  306. var $validationSummary = this.$element().find("." + FORM_VALIDATION_SUMMARY);
  307. if ($validationSummary.length > 0) {
  308. $validationSummary.remove()
  309. }
  310. if (this.option("showValidationSummary")) {
  311. (0, _renderer2.default)("<div>").addClass(FORM_VALIDATION_SUMMARY).dxValidationSummary({
  312. validationGroup: this._getValidationGroup()
  313. }).appendTo(this._getContent())
  314. }
  315. },
  316. _prepareItems: function(items, parentIsTabbedItem) {
  317. if (items) {
  318. var result = [];
  319. for (var i = 0; i < items.length; i++) {
  320. var item = items[i];
  321. var guid = this._itemsRunTimeInfo.add({
  322. item: item,
  323. itemIndex: i
  324. });
  325. if ((0, _type.isObject)(item)) {
  326. var itemCopy = (0, _extend.extend)({}, item);
  327. itemCopy.guid = guid;
  328. this._tryPrepareGroupItem(itemCopy);
  329. this._tryPrepareTabbedItem(itemCopy);
  330. this._tryPrepareItemTemplate(itemCopy);
  331. if (parentIsTabbedItem) {
  332. itemCopy.cssItemClass = FIELD_ITEM_TAB_CLASS
  333. }
  334. if (itemCopy.items) {
  335. itemCopy.items = this._prepareItems(itemCopy.items, parentIsTabbedItem)
  336. }
  337. result.push(itemCopy)
  338. } else {
  339. result.push(item)
  340. }
  341. }
  342. return result
  343. }
  344. },
  345. _tryPrepareGroupItem: function(item) {
  346. if ("group" === item.itemType) {
  347. item.alignItemLabels = (0, _common.ensureDefined)(item.alignItemLabels, true);
  348. if (item.template) {
  349. item.groupContentTemplate = this._getTemplate(item.template)
  350. }
  351. item.template = this._itemGroupTemplate.bind(this, item)
  352. }
  353. },
  354. _tryPrepareTabbedItem: function(item) {
  355. if ("tabbed" === item.itemType) {
  356. item.template = this._itemTabbedTemplate.bind(this, item);
  357. item.tabs = this._prepareItems(item.tabs, true)
  358. }
  359. },
  360. _tryPrepareItemTemplate: function(item) {
  361. if (item.template) {
  362. item.template = this._getTemplate(item.template)
  363. }
  364. },
  365. _checkGrouping: function(items) {
  366. if (items) {
  367. for (var i = 0; i < items.length; i++) {
  368. var item = items[i];
  369. if ("group" === item.itemType) {
  370. return true
  371. }
  372. }
  373. }
  374. },
  375. _renderLayout: function() {
  376. var that = this;
  377. var items = that.option("items");
  378. var $content = that._getContent();
  379. items = that._prepareItems(items);
  380. that._rootLayoutManager = that._renderLayoutManager(items, $content, {
  381. colCount: that.option("colCount"),
  382. alignItemLabels: that.option("alignItemLabels"),
  383. screenByWidth: this.option("screenByWidth"),
  384. colCountByScreen: this.option("colCountByScreen"),
  385. onLayoutChanged: function(inOneColumn) {
  386. that._alignLabels.bind(that)(that._rootLayoutManager, inOneColumn)
  387. },
  388. onContentReady: function(e) {
  389. that._alignLabels(e.component, e.component.isSingleColumnMode())
  390. }
  391. })
  392. },
  393. _tryGetItemsForTemplate: function(item) {
  394. return item.items || []
  395. },
  396. _itemTabbedTemplate: function(item, e, $container) {
  397. var _this = this;
  398. var that = this;
  399. var $tabPanel = (0, _renderer2.default)("<div>").appendTo($container);
  400. var tabPanelOptions = (0, _extend.extend)({}, item.tabPanelOptions, {
  401. dataSource: item.tabs,
  402. onItemRendered: function(args) {
  403. (0, _dom.triggerShownEvent)(args.itemElement)
  404. },
  405. itemTemplate: function(itemData, e, container) {
  406. var $container = (0, _renderer2.default)(container);
  407. var alignItemLabels = (0, _common.ensureDefined)(itemData.alignItemLabels, true);
  408. var layoutManager = that._renderLayoutManager(that._tryGetItemsForTemplate(itemData), $container, {
  409. colCount: itemData.colCount,
  410. alignItemLabels: alignItemLabels,
  411. screenByWidth: this.option("screenByWidth"),
  412. colCountByScreen: itemData.colCountByScreen,
  413. cssItemClass: itemData.cssItemClass,
  414. onLayoutChanged: function(inOneColumn) {
  415. that._alignLabelsInColumn.bind(that)({
  416. $container: $container,
  417. layoutManager: layoutManager,
  418. items: itemData.items,
  419. inOneColumn: inOneColumn
  420. })
  421. }
  422. });
  423. if (alignItemLabels) {
  424. that._alignLabelsInColumn.bind(that)({
  425. $container: $container,
  426. layoutManager: layoutManager,
  427. items: itemData.items,
  428. inOneColumn: layoutManager.isSingleColumnMode()
  429. })
  430. }
  431. }
  432. });
  433. that._createComponent($tabPanel, _tab_panel2.default, tabPanelOptions);
  434. var tabPanel = this._createComponent($tabPanel, _tab_panel2.default, tabPanelOptions);
  435. if (item.tabs) {
  436. item.tabs.forEach(function(tab) {
  437. return _this._itemsRunTimeInfo.extendRunTimeItemInfoByKey(tab.guid, {
  438. widgetInstance: tabPanel
  439. })
  440. })
  441. }
  442. },
  443. _itemGroupTemplate: function(item, e, $container) {
  444. var $group = (0, _renderer2.default)("<div>").toggleClass(FORM_GROUP_WITH_CAPTION_CLASS, (0, _type.isDefined)(item.caption) && item.caption.length).addClass(FORM_GROUP_CLASS).appendTo($container);
  445. if (item.caption) {
  446. (0, _renderer2.default)("<span>").addClass(FORM_GROUP_CAPTION_CLASS).text(item.caption).appendTo($group)
  447. }
  448. var $groupContent = (0, _renderer2.default)("<div>").addClass(FORM_GROUP_CONTENT_CLASS).appendTo($group);
  449. if (item.groupContentTemplate) {
  450. var data = {
  451. formData: this.option("formData"),
  452. component: this
  453. };
  454. item.groupContentTemplate.render({
  455. model: data,
  456. container: (0, _dom.getPublicElement)($groupContent)
  457. })
  458. } else {
  459. var layoutManager = this._renderLayoutManager(this._tryGetItemsForTemplate(item), $groupContent, {
  460. colCount: item.colCount,
  461. colCountByScreen: item.colCountByScreen,
  462. alignItemLabels: item.alignItemLabels,
  463. cssItemClass: item.cssItemClass
  464. });
  465. var colCount = layoutManager._getColCount();
  466. if ((0, _array.inArray)(colCount, this._groupsColCount) === -1) {
  467. this._groupsColCount.push(colCount)
  468. }
  469. $group.addClass(GROUP_COL_COUNT_CLASS + colCount)
  470. }
  471. },
  472. _renderLayoutManager: function(items, $rootElement, options) {
  473. var $element = (0, _renderer2.default)("<div>");
  474. var that = this;
  475. var config = that._getLayoutManagerConfig(items, options);
  476. var baseColCountByScreen = {
  477. lg: options.colCount,
  478. md: options.colCount,
  479. sm: options.colCount,
  480. xs: 1
  481. };
  482. that._cachedColCountOptions.push({
  483. colCountByScreen: (0, _extend.extend)(baseColCountByScreen, options.colCountByScreen)
  484. });
  485. $element.appendTo($rootElement);
  486. var instance = that._createComponent($element, "dxLayoutManager", config);
  487. instance.on("autoColCountChanged", function() {
  488. that._refresh()
  489. });
  490. that._cachedLayoutManagers.push(instance);
  491. return instance
  492. },
  493. _getValidationGroup: function() {
  494. return this.option("validationGroup") || this
  495. },
  496. _getLayoutManagerConfig: function(items, options) {
  497. var that = this;
  498. var baseConfig = {
  499. form: that,
  500. validationGroup: that._getValidationGroup(),
  501. showRequiredMark: that.option("showRequiredMark"),
  502. showOptionalMark: that.option("showOptionalMark"),
  503. requiredMark: that.option("requiredMark"),
  504. optionalMark: that.option("optionalMark"),
  505. requiredMessage: that.option("requiredMessage"),
  506. screenByWidth: that.option("screenByWidth"),
  507. layoutData: that.option("formData"),
  508. labelLocation: that.option("labelLocation"),
  509. customizeItem: that.option("customizeItem"),
  510. minColWidth: that.option("minColWidth"),
  511. showColonAfterLabel: that.option("showColonAfterLabel"),
  512. onEditorEnterKey: that.option("onEditorEnterKey"),
  513. onFieldDataChanged: function(args) {
  514. if (!that._isDataUpdating) {
  515. that._triggerOnFieldDataChanged(args)
  516. }
  517. },
  518. validationBoundary: that.option("scrollingEnabled") ? that.$element() : void 0
  519. };
  520. return (0, _extend.extend)(baseConfig, {
  521. items: items,
  522. onContentReady: function(args) {
  523. that._itemsRunTimeInfo.addItemsOrExtendFrom(args.component._itemsRunTimeInfo);
  524. options.onContentReady && options.onContentReady(args)
  525. },
  526. colCount: options.colCount,
  527. alignItemLabels: options.alignItemLabels,
  528. cssItemClass: options.cssItemClass,
  529. colCountByScreen: options.colCountByScreen,
  530. onLayoutChanged: options.onLayoutChanged,
  531. width: options.width
  532. })
  533. },
  534. _createComponent: function($element, type, config) {
  535. var that = this;
  536. config = config || {};
  537. that._extendConfig(config, {
  538. readOnly: that.option("readOnly")
  539. });
  540. return that.callBase($element, type, config)
  541. },
  542. _attachSyncSubscriptions: function() {
  543. var that = this;
  544. that.on("optionChanged", function(args) {
  545. var optionFullName = args.fullName;
  546. if ("formData" === optionFullName) {
  547. if (!(0, _type.isDefined)(args.value)) {
  548. that._options.formData = args.value = {}
  549. }
  550. that._triggerOnFieldDataChangedByDataSet(args.value)
  551. }
  552. if (that._cachedLayoutManagers.length) {
  553. (0, _iterator.each)(that._cachedLayoutManagers, function(index, layoutManager) {
  554. if ("formData" === optionFullName) {
  555. that._isDataUpdating = true;
  556. layoutManager.option("layoutData", args.value);
  557. that._isDataUpdating = false
  558. }
  559. if ("readOnly" === args.name || "disabled" === args.name) {
  560. layoutManager.option(optionFullName, args.value)
  561. }
  562. })
  563. }
  564. })
  565. },
  566. _optionChanged: function(args) {
  567. var rootNameOfComplexOption = this._getRootLevelOfExpectedComplexOption(args.fullName, ["formData", "items"]);
  568. if (rootNameOfComplexOption) {
  569. this._customHandlerOfComplexOption(args, rootNameOfComplexOption);
  570. return
  571. }
  572. switch (args.name) {
  573. case "formData":
  574. if (!this.option("items")) {
  575. this._invalidate()
  576. } else {
  577. if ((0, _type.isEmptyObject)(args.value)) {
  578. this._resetValues()
  579. }
  580. }
  581. break;
  582. case "items":
  583. case "colCount":
  584. case "onFieldDataChanged":
  585. case "onEditorEnterKey":
  586. case "labelLocation":
  587. case "alignItemLabels":
  588. case "showColonAfterLabel":
  589. case "customizeItem":
  590. case "alignItemLabelsInAllGroups":
  591. case "showRequiredMark":
  592. case "showOptionalMark":
  593. case "requiredMark":
  594. case "optionalMark":
  595. case "requiredMessage":
  596. case "scrollingEnabled":
  597. case "formID":
  598. case "colCountByScreen":
  599. case "screenByWidth":
  600. case "stylingMode":
  601. this._invalidate();
  602. break;
  603. case "showValidationSummary":
  604. this._renderValidationSummary();
  605. break;
  606. case "minColWidth":
  607. if ("auto" === this.option("colCount")) {
  608. this._invalidate()
  609. }
  610. break;
  611. case "readOnly":
  612. break;
  613. case "width":
  614. this.callBase(args);
  615. this._rootLayoutManager.option(args.name, args.value);
  616. this._alignLabels(this._rootLayoutManager, this._rootLayoutManager.isSingleColumnMode());
  617. break;
  618. case "visible":
  619. this.callBase(args);
  620. if (args.value) {
  621. (0, _dom.triggerShownEvent)(this.$element())
  622. }
  623. break;
  624. case "validationGroup":
  625. _validation_engine2.default.removeGroup(args.previousValue || this);
  626. this._invalidate();
  627. break;
  628. default:
  629. this.callBase(args)
  630. }
  631. },
  632. _getRootLevelOfExpectedComplexOption: function(fullOptionName, expectedRootNames) {
  633. var splitFullName = fullOptionName.split(".");
  634. var result;
  635. if (splitFullName.length > 1) {
  636. var rootOptionName = splitFullName[0];
  637. for (var i = 0; i < expectedRootNames.length; i++) {
  638. if (rootOptionName.search(expectedRootNames[i]) !== -1) {
  639. result = expectedRootNames[i]
  640. }
  641. }
  642. }
  643. return result
  644. },
  645. _tryCreateItemOptionAction: function(optionName, item, value, previousValue) {
  646. return (0, _uiForm6.default)(optionName, {
  647. item: item,
  648. value: value,
  649. previousValue: previousValue,
  650. itemsRunTimeInfo: this._itemsRunTimeInfo
  651. })
  652. },
  653. _tryExecuteItemOptionAction: function(action) {
  654. return action && action.tryExecute()
  655. },
  656. _customHandlerOfComplexOption: function(args, rootOptionName) {
  657. var nameParts = args.fullName.split(".");
  658. var value = args.value;
  659. if ("items" === rootOptionName) {
  660. var itemPath = this._getItemPath(nameParts);
  661. var item = this.option(itemPath);
  662. var optionNameWithoutPath = args.fullName.replace(itemPath + ".", "");
  663. var simpleOptionName = optionNameWithoutPath.split(".")[0].replace(/\[\d+]/, "");
  664. var itemAction = this._tryCreateItemOptionAction(simpleOptionName, item, item[simpleOptionName], args.previousValue);
  665. if (!this._tryExecuteItemOptionAction(itemAction) && item) {
  666. this._changeItemOption(item, optionNameWithoutPath, value);
  667. var items = this._generateItemsFromData(this.option("items"));
  668. this.option("items", items)
  669. }
  670. }
  671. if ("formData" === rootOptionName) {
  672. var dataField = nameParts.slice(1).join(".");
  673. var editor = this.getEditor(dataField);
  674. if (editor) {
  675. editor.option("value", value)
  676. } else {
  677. this._triggerOnFieldDataChanged({
  678. dataField: dataField,
  679. value: value
  680. })
  681. }
  682. }
  683. },
  684. _getItemPath: function(nameParts) {
  685. var itemPath = nameParts[0];
  686. for (var i = 1; i < nameParts.length; i++) {
  687. if (nameParts[i].search("items|tabs") !== -1) {
  688. itemPath += "." + nameParts[i]
  689. } else {
  690. break
  691. }
  692. }
  693. return itemPath
  694. },
  695. _triggerOnFieldDataChanged: function(args) {
  696. this._createActionByOption("onFieldDataChanged")(args)
  697. },
  698. _triggerOnFieldDataChangedByDataSet: function(data) {
  699. var that = this;
  700. if (data && (0, _type.isObject)(data)) {
  701. (0, _iterator.each)(data, function(dataField, value) {
  702. that._triggerOnFieldDataChanged({
  703. dataField: dataField,
  704. value: value
  705. })
  706. })
  707. }
  708. },
  709. _updateFieldValue: function(dataField, value) {
  710. if ((0, _type.isDefined)(this.option("formData"))) {
  711. var editor = this.getEditor(dataField);
  712. this.option("formData." + dataField, value);
  713. if (editor) {
  714. var editorValue = editor.option("value");
  715. if (editorValue !== value) {
  716. editor.option("value", value)
  717. }
  718. }
  719. }
  720. },
  721. _generateItemsFromData: function(items) {
  722. var formData = this.option("formData");
  723. var result = [];
  724. if (!items && (0, _type.isDefined)(formData)) {
  725. (0, _iterator.each)(formData, function(dataField) {
  726. result.push({
  727. dataField: dataField
  728. })
  729. })
  730. }
  731. if (items) {
  732. (0, _iterator.each)(items, function(index, item) {
  733. if ((0, _type.isObject)(item)) {
  734. result.push(item)
  735. } else {
  736. result.push({
  737. dataField: item
  738. })
  739. }
  740. })
  741. }
  742. return result
  743. },
  744. _getItemByField: function(field, items) {
  745. var that = this;
  746. var fieldParts = (0, _type.isObject)(field) ? field : that._getFieldParts(field);
  747. var fieldName = fieldParts.fieldName;
  748. var fieldPath = fieldParts.fieldPath;
  749. var resultItem;
  750. if (items.length) {
  751. (0, _iterator.each)(items, function(index, item) {
  752. var itemType = item.itemType;
  753. if (fieldPath.length) {
  754. var path = fieldPath.slice();
  755. item = that._getItemByFieldPath(path, fieldName, item)
  756. } else {
  757. if ("group" === itemType && !(item.caption || item.name) || "tabbed" === itemType && !item.name) {
  758. var subItemsField = that._getSubItemField(itemType);
  759. item.items = that._generateItemsFromData(item.items);
  760. item = that._getItemByField({
  761. fieldName: fieldName,
  762. fieldPath: fieldPath
  763. }, item[subItemsField])
  764. }
  765. }
  766. if (that._isExpectedItem(item, fieldName)) {
  767. resultItem = item;
  768. return false
  769. }
  770. })
  771. }
  772. return resultItem
  773. },
  774. _getFieldParts: function(field) {
  775. var fieldSeparator = ".";
  776. var fieldName = field;
  777. var separatorIndex = fieldName.indexOf(fieldSeparator);
  778. var resultPath = [];
  779. while (separatorIndex !== -1) {
  780. resultPath.push(fieldName.substr(0, separatorIndex));
  781. fieldName = fieldName.substr(separatorIndex + 1);
  782. separatorIndex = fieldName.indexOf(fieldSeparator)
  783. }
  784. return {
  785. fieldName: fieldName,
  786. fieldPath: resultPath.reverse()
  787. }
  788. },
  789. _getItemByFieldPath: function(path, fieldName, item) {
  790. var that = this;
  791. var itemType = item.itemType;
  792. var subItemsField = that._getSubItemField(itemType);
  793. var isItemWithSubItems = "group" === itemType || "tabbed" === itemType || item.title;
  794. var result;
  795. do {
  796. if (isItemWithSubItems) {
  797. var name = item.name || item.caption || item.title;
  798. var isGroupWithName = (0, _type.isDefined)(name);
  799. var nameWithoutSpaces = that._getTextWithoutSpaces(name);
  800. var pathNode;
  801. item[subItemsField] = that._generateItemsFromData(item[subItemsField]);
  802. if (isGroupWithName) {
  803. pathNode = path.pop()
  804. }
  805. if (!path.length) {
  806. result = that._getItemByField(fieldName, item[subItemsField]);
  807. if (result) {
  808. break
  809. }
  810. }
  811. if (!isGroupWithName || isGroupWithName && nameWithoutSpaces === pathNode) {
  812. if (path.length) {
  813. result = that._searchItemInEverySubItem(path, fieldName, item[subItemsField])
  814. }
  815. }
  816. } else {
  817. break
  818. }
  819. } while (path.length && !(0, _type.isDefined)(result));
  820. return result
  821. },
  822. _getSubItemField: function(itemType) {
  823. return "tabbed" === itemType ? "tabs" : "items"
  824. },
  825. _searchItemInEverySubItem: function(path, fieldName, items) {
  826. var that = this;
  827. var result;
  828. (0, _iterator.each)(items, function(index, groupItem) {
  829. result = that._getItemByFieldPath(path.slice(), fieldName, groupItem);
  830. if (result) {
  831. return false
  832. }
  833. });
  834. if (!result) {
  835. result = false
  836. }
  837. return result
  838. },
  839. _getTextWithoutSpaces: function(text) {
  840. return text ? text.replace(/\s/g, "") : void 0
  841. },
  842. _isExpectedItem: function(item, fieldName) {
  843. return item && (item.dataField === fieldName || item.name === fieldName || this._getTextWithoutSpaces(item.title) === fieldName || "group" === item.itemType && this._getTextWithoutSpaces(item.caption) === fieldName)
  844. },
  845. _changeItemOption: function(item, option, value) {
  846. if ((0, _type.isObject)(item)) {
  847. item[option] = value
  848. }
  849. },
  850. _dimensionChanged: function() {
  851. var currentScreenFactor = this._getCurrentScreenFactor();
  852. if (this._lastMarkupScreenFactor !== currentScreenFactor) {
  853. if (this._isColCountChanged(this._lastMarkupScreenFactor, currentScreenFactor)) {
  854. this._targetScreenFactor = currentScreenFactor;
  855. this._refresh();
  856. this._targetScreenFactor = void 0
  857. }
  858. this._lastMarkupScreenFactor = currentScreenFactor
  859. }
  860. },
  861. _isColCountChanged: function(oldScreenSize, newScreenSize) {
  862. var isChanged = false;
  863. (0, _iterator.each)(this._cachedColCountOptions, function(index, item) {
  864. if (item.colCountByScreen[oldScreenSize] !== item.colCountByScreen[newScreenSize]) {
  865. isChanged = true;
  866. return false
  867. }
  868. });
  869. return isChanged
  870. },
  871. _refresh: function() {
  872. var editorSelector = "." + FOCUSED_STATE_CLASS + " input, ." + FOCUSED_STATE_CLASS + " textarea";
  873. _events_engine2.default.trigger(this.$element().find(editorSelector), "change");
  874. this.callBase()
  875. },
  876. _resetValues: function() {
  877. this._itemsRunTimeInfo.each(function(_, itemRunTimeInfo) {
  878. if ((0, _type.isDefined)(itemRunTimeInfo.widgetInstance) && (0, _type.isDefined)(itemRunTimeInfo.item) && "button" !== itemRunTimeInfo.item.itemType) {
  879. itemRunTimeInfo.widgetInstance.reset();
  880. itemRunTimeInfo.widgetInstance.option("isValid", true)
  881. }
  882. });
  883. _validation_engine2.default.resetGroup(this._getValidationGroup())
  884. },
  885. _updateData: function(data, value, isComplexData) {
  886. var that = this;
  887. var _data = isComplexData ? value : data;
  888. if ((0, _type.isObject)(_data)) {
  889. (0, _iterator.each)(_data, function(dataField, fieldValue) {
  890. that._updateData(isComplexData ? data + "." + dataField : dataField, fieldValue, (0, _type.isObject)(fieldValue))
  891. })
  892. } else {
  893. if ((0, _type.isString)(data)) {
  894. that._updateFieldValue(data, value)
  895. }
  896. }
  897. },
  898. registerKeyHandler: function(key, handler) {
  899. this.callBase(key, handler);
  900. this._itemsRunTimeInfo.each(function(_, itemRunTimeInfo) {
  901. if ((0, _type.isDefined)(itemRunTimeInfo.widgetInstance)) {
  902. itemRunTimeInfo.widgetInstance.registerKeyHandler(key, handler)
  903. }
  904. })
  905. },
  906. _focusTarget: function() {
  907. return this.$element().find("." + FIELD_ITEM_CONTENT_CLASS + " [tabindex]").first()
  908. },
  909. _visibilityChanged: function(visible) {
  910. if (visible && _browser2.default.msie) {
  911. this._refresh()
  912. }
  913. },
  914. _dispose: function() {
  915. _validation_engine2.default.removeGroup(this._getValidationGroup());
  916. this.callBase()
  917. },
  918. resetValues: function() {
  919. this._resetValues()
  920. },
  921. updateData: function(data, value) {
  922. this._updateData(data, value)
  923. },
  924. getEditor: function(dataField) {
  925. return this._itemsRunTimeInfo.findWidgetInstanceByDataField(dataField) || this._itemsRunTimeInfo.findWidgetInstanceByName(dataField)
  926. },
  927. getButton: function(name) {
  928. return this._itemsRunTimeInfo.findWidgetInstanceByName(name)
  929. },
  930. updateDimensions: function() {
  931. var that = this;
  932. var deferred = new _deferred.Deferred;
  933. if (that._scrollable) {
  934. that._scrollable.update().done(function() {
  935. deferred.resolveWith(that)
  936. })
  937. } else {
  938. deferred.resolveWith(that)
  939. }
  940. return deferred.promise()
  941. },
  942. itemOption: function(id, option, value) {
  943. var _this2 = this;
  944. var items = this._generateItemsFromData(this.option("items"));
  945. var item = this._getItemByField(id, items);
  946. switch (arguments.length) {
  947. case 1:
  948. return item;
  949. case 3:
  950. var itemAction = this._tryCreateItemOptionAction(option, item, value, item[option]);
  951. this._changeItemOption(item, option, value);
  952. if (!this._tryExecuteItemOptionAction(itemAction)) {
  953. this.option("items", items)
  954. }
  955. break;
  956. default:
  957. if ((0, _type.isObject)(option)) {
  958. var allowUpdateItems;
  959. (0, _iterator.each)(option, function(optionName, optionValue) {
  960. var itemAction = _this2._tryCreateItemOptionAction(optionName, item, optionValue, item[optionName]);
  961. _this2._changeItemOption(item, optionName, optionValue);
  962. if (!allowUpdateItems && !_this2._tryExecuteItemOptionAction(itemAction)) {
  963. allowUpdateItems = true
  964. }
  965. });
  966. allowUpdateItems && this.option("items", items)
  967. }
  968. }
  969. },
  970. validate: function() {
  971. return _validation_engine2.default.validateGroup(this._getValidationGroup())
  972. },
  973. getItemID: function(name) {
  974. return "dx_" + this.option("formID") + "_" + (name || new _guid2.default)
  975. },
  976. getTargetScreenFactor: function() {
  977. return this._targetScreenFactor
  978. }
  979. });
  980. (0, _component_registrator2.default)("dxForm", Form);
  981. module.exports = Form;