447a22c15861165245f9d150ee59c071fe2f824a
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Resources / Public / JavaScript / Backend / FormEditor / ViewModel.js
1 /*
2 * This file is part of the TYPO3 CMS project.
3 *
4 * It is free software; you can redistribute it and/or modify it under
5 * the terms of the GNU General Public License, either version 2
6 * of the License, or any later version.
7 *
8 * For the full copyright and license information, please read the
9 * LICENSE.txt file that was distributed with this source code.
10 *
11 * The TYPO3 project - inspiring people to share!
12 */
13
14 /**
15 * Module: TYPO3/CMS/Form/Backend/FormEditor/ViewModel
16 */
17 define(['jquery',
18 'TYPO3/CMS/Form/Backend/FormEditor/TreeComponent',
19 'TYPO3/CMS/Form/Backend/FormEditor/ModalsComponent',
20 'TYPO3/CMS/Form/Backend/FormEditor/InspectorComponent',
21 'TYPO3/CMS/Form/Backend/FormEditor/StageComponent',
22 'TYPO3/CMS/Form/Backend/FormEditor/Helper',
23 'TYPO3/CMS/Backend/Icons',
24 'TYPO3/CMS/Backend/Notification'
25 ], function($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification) {
26 'use strict';
27
28 return (function($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification) {
29
30 /**
31 * @private
32 *
33 * @var object
34 */
35 var _configuration = {
36 domElementClassNames: {
37 formElementIsComposit: 't3-form-element-composit',
38 formElementIsTopLevel: 't3-form-element-toplevel',
39 hasError: 'has-error',
40 headerButtonBar: 'module-docheader-bar-column-left',
41 selectedCompositFormElement: 't3-form-form-composit-element-selected',
42 selectedFormElement: 't3-form-form-element-selected',
43 selectedRootFormElement: 't3-form-root-element-selected',
44 selectedStagePanel: 't3-form-form-stage-selected',
45 sortableHover: 'sortable-hover',
46 stageViewModeAbstract: 't3-form-stage-viewmode-abstract',
47 stageViewModePreview: 't3-form-stage-viewmode-preview',
48 validationErrors: 't3-form-validation-errors',
49 validationChildHasErrors: 't3-form-validation-child-has-error'
50 },
51 domElementDataAttributeNames: {
52 abstractType: 'data-element-abstract-type'
53 },
54 domElementDataAttributeValues: {
55 buttonHeaderClose: 'closeButton',
56 buttonHeaderNewPage: 'headerNewPage',
57 buttonHeaderPaginationNext: 'buttonPaginationNext',
58 buttonHeaderPaginationPrevious: 'buttonPaginationPrevious',
59 buttonHeaderRedo: 'redoButton',
60 buttonHeaderSave: 'saveButton',
61 buttonHeaderSettings: 'formSettingsButton',
62 buttonHeaderUndo: 'undoButton',
63 buttonHeaderViewModeAbstract: 'buttonViewModeAbstract',
64 buttonHeaderViewModePreview: 'buttonViewModePreview',
65 buttonStageNewElementBottom: 'stageNewElementBottom',
66 buttonStructureNewPage: 'treeNewPageBottom',
67 iconMailform: 'content-elements-mailform',
68 iconSave: 'actions-document-save',
69 iconSaveSpinner: 'spinner-circle-dark',
70 inspectorSection: 'inspectorSection',
71 moduleLoadingIndicator: 'moduleLoadingIndicator',
72 moduleWrapper: 'moduleWrapper',
73 stageArea: 'stageArea',
74 stageContainer: 'stageContainer',
75 stageContainerInner: 'stageContainerInner',
76 stageNewElementRow: 'stageNewElementRow',
77 stagePanelHeading: 'panelHeading',
78 stageSection: 'stageSection',
79 structure: 'structure-element',
80 structureSection: 'structureSection',
81 structureRootContainer: 'treeRootContainer',
82 structureRootElement: 'treeRootElement'
83 },
84 panels: {
85 structure: {
86 width: 300
87 },
88 stage: {
89 marginLeft: 300,
90 marginRight: 325,
91 marginLeftCollapsed: 0,
92 marginRightCollapsed: -25,
93 maxWidthPreview: 1000,
94 maxWidthAbstract: 800
95 },
96 inspector: {
97 width: 350
98 }
99 }
100 };
101
102 /**
103 * @private
104 *
105 * @var bool
106 */
107 var _previewMode = false;
108
109 /**
110 * @private
111 *
112 * @var object
113 */
114 var _formEditorApp = null;
115
116 /**
117 * @private
118 *
119 * @var object
120 */
121 var _structureComponent = null;
122
123 /**
124 * @private
125 *
126 * @var object
127 */
128 var _modalsComponent = null;
129
130 /**
131 * @private
132 *
133 * @var object
134 */
135 var _inspectorsComponent = null;
136
137 /**
138 * @private
139 *
140 * @var object
141 */
142 var _stageComponent = null;
143
144 /* *************************************************************
145 * Private Methodes
146 * ************************************************************/
147
148 /**
149 * @private
150 *
151 * @return object
152 */
153 function getRootFormElement() {
154 return getFormEditorApp().getRootFormElement();
155 };
156
157 /**
158 * @private
159 *
160 * @param mixed test
161 * @param string message
162 * @param int messageCode
163 * @return void
164 */
165 function assert(test, message, messageCode) {
166 return getFormEditorApp().assert(test, message, messageCode);
167 };
168
169 /**
170 * @private
171 *
172 * @return object
173 */
174 function getUtility() {
175 return getFormEditorApp().getUtility();
176 };
177
178 /**
179 * @private
180 *
181 * @return object
182 */
183 function getCurrentlySelectedFormElement() {
184 return getFormEditorApp().getCurrentlySelectedFormElement();
185 };
186
187
188 /**
189 * @private
190 *
191 * @return object
192 */
193 function getPublisherSubscriber() {
194 return getFormEditorApp().getPublisherSubscriber();
195 };
196
197 /**
198 * @private
199 *
200 * @return void
201 */
202 function _addPropertyValidators() {
203 getFormEditorApp().addPropertyValidationValidator('NotEmpty', function(formElement, propertyPath) {
204 if (formElement.get(propertyPath) === '') {
205 return getFormEditorApp().getFormElementPropertyValidatorDefinition('NotEmpty')['errorMessage'] || 'invalid value';
206 }
207 });
208
209 getFormEditorApp().addPropertyValidationValidator('Integer', function(formElement, propertyPath) {
210 if (!$.isNumeric(formElement.get(propertyPath))) {
211 return getFormEditorApp().getFormElementPropertyValidatorDefinition('Integer')['errorMessage'] || 'invalid value';
212 }
213 });
214
215 getFormEditorApp().addPropertyValidationValidator('IntegerOrEmpty', function(formElement, propertyPath) {
216 if (getUtility().isUndefinedOrNull(formElement.get(propertyPath))) {
217 return;
218 }
219 if (formElement.get(propertyPath).length > 0 && !$.isNumeric(formElement.get(propertyPath))) {
220 return getFormEditorApp().getFormElementPropertyValidatorDefinition('Integer')['errorMessage'] || 'invalid value';
221 }
222 });
223
224 getFormEditorApp().addPropertyValidationValidator('NaiveEmail', function(formElement, propertyPath) {
225 if (getUtility().isUndefinedOrNull(formElement.get(propertyPath))) {
226 return;
227 }
228 if (!formElement.get(propertyPath).match(/\S+@\S+\.\S+/)) {
229 return getFormEditorApp().getFormElementPropertyValidatorDefinition('NaiveEmail')['errorMessage'] || 'invalid value';
230 }
231 });
232
233 getFormEditorApp().addPropertyValidationValidator('NaiveEmailOrEmpty', function(formElement, propertyPath) {
234 if (getUtility().isUndefinedOrNull(formElement.get(propertyPath))) {
235 return;
236 }
237 if (formElement.get(propertyPath).length > 0 && !formElement.get(propertyPath).match(/\S+@\S+\.\S+/)) {
238 return getFormEditorApp().getFormElementPropertyValidatorDefinition('NaiveEmailOrEmpty')['errorMessage'] || 'invalid value';
239 }
240 });
241
242 getFormEditorApp().addPropertyValidationValidator('FormElementIdentifierWithinCurlyBracesInclusive', function(formElement, propertyPath) {
243 var match, regex;
244
245 if (getUtility().isUndefinedOrNull(formElement.get(propertyPath))) {
246 return;
247 }
248
249 regex = /\{([a-z0-9-_]+)?\}/gi;
250 match = regex.exec(formElement.get(propertyPath));
251 if (match && ((match[1] && !getFormEditorApp().isFormElementIdentifierUsed(match[1])) || !match[1])) {
252 return getFormEditorApp().getFormElementPropertyValidatorDefinition('FormElementIdentifierWithinCurlyBracesInclusive')['errorMessage'] || 'invalid value';
253 }
254 });
255
256 getFormEditorApp().addPropertyValidationValidator('FormElementIdentifierWithinCurlyBracesExclusive', function(formElement, propertyPath) {
257 var match, regex;
258
259 if (getUtility().isUndefinedOrNull(formElement.get(propertyPath))) {
260 return;
261 }
262
263 regex = /^\{([a-z0-9-_]+)?\}$/i;
264 match = regex.exec(formElement.get(propertyPath));
265 if (!match || ((match[1] && !getFormEditorApp().isFormElementIdentifierUsed(match[1])) || !match[1])) {
266 return getFormEditorApp().getFormElementPropertyValidatorDefinition('FormElementIdentifierWithinCurlyBracesInclusive')['errorMessage'] || 'invalid value';
267 }
268 });
269
270 getFormEditorApp().addPropertyValidationValidator('FileSize', function(formElement, propertyPath) {
271 if (getUtility().isUndefinedOrNull(formElement.get(propertyPath))) {
272 return;
273 }
274 if (!formElement.get(propertyPath).match(/^(\d*\.?\d+)(B|K|M|G)$/i)) {
275 return getFormEditorApp().getFormElementPropertyValidatorDefinition('FileSize')['errorMessage'] || 'invalid value';
276 }
277 });
278 };
279
280 /**
281 * @private
282 *
283 * @param object additionalViewModelModules
284 * @return void
285 * @publish view/ready
286 * @throws 1475425785
287 */
288 function _loadAdditionalModules(additionalViewModelModules) {
289 var additionalViewModelModulesLength, isLastElement, loadedAdditionalViewModelModules;
290
291 if ('array' !== $.type(additionalViewModelModules)) {
292 return;
293 }
294 additionalViewModelModulesLength = additionalViewModelModules.length;
295
296 if (additionalViewModelModulesLength > 0) {
297 loadedAdditionalViewModelModules = 0;
298 for (var i = 0; i < additionalViewModelModulesLength; ++i) {
299 require([additionalViewModelModules[i]], function(additionalViewModelModule) {
300 assert(
301 'function' === $.type(additionalViewModelModule.bootstrap),
302 'The module "' + additionalViewModelModules[i] + '" does not implement the method "bootstrap"',
303 1475425785
304 );
305 additionalViewModelModule.bootstrap(getFormEditorApp());
306
307 loadedAdditionalViewModelModules++;
308 if (additionalViewModelModulesLength === loadedAdditionalViewModelModules) {
309 getPublisherSubscriber().publish('view/ready');
310 }
311 });
312 }
313 } else {
314 getPublisherSubscriber().publish('view/ready');
315 }
316 };
317
318 /**
319 * @private
320 *
321 * @return void
322 * @throws 1478268638
323 */
324 function _helperSetup() {
325 assert('function' === $.type(Helper.bootstrap),
326 'The view model helper does not implement the method "bootstrap"',
327 1478268638
328 );
329
330 Helper.bootstrap(getFormEditorApp());
331 };
332
333 /**
334 * @private
335 *
336 * @return void
337 * @throws 1478268639
338 */
339 function _structureComponentSetup() {
340 assert(
341 'function' === $.type(TreeComponent.bootstrap),
342 'The structure component does not implement the method "bootstrap"',
343 1478268639
344 );
345
346 _structureComponent = TreeComponent.bootstrap(
347 getFormEditorApp(),
348 $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [
349 getHelper().getDomElementDataAttributeValue('structure')
350 ]))
351 );
352
353 $(getHelper().getDomElementDataIdentifierSelector('iconMailform'),
354 $(getHelper().getDomElementDataIdentifierSelector('structureRootContainer'))
355 ).tooltip({
356 title: 'identifier: ' + getRootFormElement().get('identifier'),
357 placement: 'right'
358 });
359 };
360
361 /**
362 * @private
363 *
364 * @return void
365 * @throws 1478895106
366 */
367 function _modalsComponentSetup() {
368 assert(
369 'function' === $.type(ModalsComponent.bootstrap),
370 'The modals component does not implement the method "bootstrap"',
371 1478895106
372 );
373 _modalsComponent = ModalsComponent.bootstrap(getFormEditorApp());
374 };
375
376 /**
377 * @private
378 *
379 * @return void
380 * @throws 1478895106
381 */
382 function _inspectorsComponentSetup() {
383 assert(
384 'function' === $.type(InspectorComponent.bootstrap),
385 'The inspector component does not implement the method "bootstrap"',
386 1478895106
387 );
388 _inspectorsComponent = InspectorComponent.bootstrap(getFormEditorApp());
389 };
390
391 /**
392 * @private
393 *
394 * @return void
395 * @throws 1478986610
396 */
397 function _stageComponentSetup() {
398 assert(
399 'function' === $.type(InspectorComponent.bootstrap),
400 'The stage component does not implement the method "bootstrap"',
401 1478986610
402 );
403 _stageComponent = StageComponent.bootstrap(
404 getFormEditorApp(),
405 $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [
406 getHelper().getDomElementDataAttributeValue('stageArea')
407 ]))
408 );
409
410 getStage().getStagePanelDomElement().on("click", function(e) {
411 if (
412 $(e.target).attr(getHelper().getDomElementDataAttribute('identifier')) === getHelper().getDomElementDataAttributeValue('stagePanelHeading')
413 || $(e.target).attr(getHelper().getDomElementDataAttribute('identifier')) === getHelper().getDomElementDataAttributeValue('stageSection')
414 || $(e.target).attr(getHelper().getDomElementDataAttribute('identifier')) === getHelper().getDomElementDataAttributeValue('stageArea')
415 ) {
416 selectPageBatch(getFormEditorApp().getCurrentlySelectedPageIndex());
417 }
418 getPublisherSubscriber().publish('view/stage/panel/clicked', []);
419 });
420 };
421
422 /**
423 * @private
424 *
425 * @return void
426 * @publish view/header/button/save/clicked
427 * @publish view/stage/abstract/button/newElement/clicked
428 * @publish view/header/button/newPage/clicked
429 * @publish view/structure/button/newPage/clicked
430 * @publish view/header/button/close/clicked
431 */
432 function _buttonsSetup() {
433 $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSave')).on("click", function(e) {
434 getPublisherSubscriber().publish('view/header/button/save/clicked', []);
435 });
436
437 $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSettings')).on('click', function(e) {
438 getPublisherSubscriber().publish('view/header/formSettings/clicked', []);
439 });
440
441 $(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')).on('click', function(e) {
442 getPublisherSubscriber().publish(
443 'view/stage/abstract/button/newElement/clicked', [
444 'view/insertElements/perform/bottom'
445 ]
446 );
447 });
448
449 $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage')).on('click', function(e) {
450 getPublisherSubscriber().publish('view/header/button/newPage/clicked', ['view/insertPages/perform']);
451 });
452
453 $(getHelper().getDomElementDataIdentifierSelector('buttonStructureNewPage')).on('click', function(e) {
454 getPublisherSubscriber().publish('view/structure/button/newPage/clicked', ['view/insertPages/perform']);
455 });
456
457 $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderClose')).on('click', function(e) {
458 if (!getFormEditorApp().getUnsavedContent()) {
459 return;
460 }
461 e.preventDefault();
462 getPublisherSubscriber().publish('view/header/button/close/clicked', []);
463 });
464
465 $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')).on('click', function(e) {
466 getPublisherSubscriber().publish('view/undoButton/clicked', []);
467 });
468
469 $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')).on('click', function(e) {
470 getPublisherSubscriber().publish('view/redoButton/clicked', []);
471 });
472
473 $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract')).on('click', function(e) {
474 getPublisherSubscriber().publish('view/viewModeButton/abstract/clicked', []);
475 });
476
477 $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModePreview')).on('click', function(e) {
478 getPublisherSubscriber().publish('view/viewModeButton/preview/clicked', []);
479 });
480
481 $(getHelper().getDomElementDataIdentifierSelector('structureRootContainer')).on("click", function(e) {
482 getPublisherSubscriber().publish('view/structure/root/selected');
483 });
484
485 $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderPaginationNext')).on('click', function(e) {
486 getPublisherSubscriber().publish('view/paginationNext/clicked', []);
487 });
488
489 $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderPaginationPrevious')).on('click', function(e) {
490 getPublisherSubscriber().publish('view/paginationPrevious/clicked', []);
491 });
492 };
493
494 /* *************************************************************
495 * Public Methodes
496 * ************************************************************/
497
498 /**
499 * @public
500 *
501 * @return object
502 */
503 function getFormEditorApp() {
504 return _formEditorApp;
505 };
506
507 /**
508 * @public
509 *
510 * @param object
511 * @return object
512 */
513 function getHelper(configuration) {
514 if (getUtility().isUndefinedOrNull(configuration)) {
515 return Helper.setConfiguration(_configuration);
516 }
517 return Helper.setConfiguration(configuration);
518 };
519
520 /**
521 * @public
522 *
523 * @param object formElement
524 * @param string formElementDefinitionKey
525 * @return mixed
526 */
527 function getFormElementDefinition(formElement, formElementDefinitionKey) {
528 return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey);
529 };
530
531 /**
532 * @public
533 *
534 * @return object (derefernced)
535 */
536 function getConfiguration() {
537 return $.extend(true, {}, _configuration);
538 };
539
540 /**
541 * @public
542 *
543 * @return int
544 */
545 function getPreviewMode() {
546 return _previewMode;
547 };
548
549 /**
550 * @public
551 *
552 * @param bool
553 * @return void
554 */
555 function setPreviewMode(previewMode) {
556 _previewMode = !!previewMode;
557 };
558
559 /* *************************************************************
560 * Structure
561 * ************************************************************/
562
563 /**
564 * @public
565 *
566 * @return object
567 */
568 function getStructure() {
569 return _structureComponent;
570 };
571
572 /**
573 * @public
574 *
575 * @return void
576 * @publish view/structure/renew/postProcess
577 */
578 function renewStructure() {
579 getStructure().renew();
580 getPublisherSubscriber().publish('view/structure/renew/postProcess');
581 };
582
583 /**
584 * @public
585 *
586 * @param object
587 * @return void
588 */
589 function addStructureSelection(formElement) {
590 getStructure().getTreeNode(formElement).addClass(getHelper().getDomElementClassName('selectedFormElement'));
591 };
592
593 /**
594 * @public
595 *
596 * @param object
597 * @return void
598 */
599 function removeStructureSelection(formElement) {
600 getStructure().getTreeNode(formElement).removeClass(getHelper().getDomElementClassName('selectedFormElement'));
601 };
602
603 /**
604 * @public
605 *
606 * @return void
607 */
608 function removeAllStructureSelections() {
609 $(getHelper().getDomElementClassName('selectedFormElement', true), getStructure().getTreeDomElement())
610 .removeClass(getHelper().getDomElementClassName('selectedFormElement'));
611 };
612
613 /**
614 * @public
615 *
616 * @return object
617 */
618 function getStructureRootElement() {
619 return $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [
620 getHelper().getDomElementDataAttributeValue('structureRootElement')
621 ]));
622 };
623
624 /**
625 * @public
626 *
627 * @return void
628 */
629 function removeStructureRootElementSelection() {
630 $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [
631 getHelper().getDomElementDataAttributeValue('structureRootContainer')
632 ])).removeClass(getHelper().getDomElementClassName('selectedRootFormElement'));
633 };
634
635 /**
636 * @public
637 *
638 * @return void
639 */
640 function addStructureRootElementSelection() {
641 $(getHelper().getDomElementDataAttribute('identifier', 'bracesWithKeyValue', [
642 getHelper().getDomElementDataAttributeValue('structureRootContainer')
643 ])).addClass(getHelper().getDomElementClassName('selectedRootFormElement'));
644 };
645
646 /**
647 * @public
648 *
649 * @param string title
650 * @return void
651 */
652 function setStructureRootElementTitle(title) {
653 if (getUtility().isUndefinedOrNull(title)) {
654 title = $('<span></span>')
655 .text((getRootFormElement().get('label') ? getRootFormElement().get('label') : getRootFormElement().get('identifier')))
656 .text();
657 }
658 getStructureRootElement().text(title);
659 };
660
661 /**
662 * @public
663 *
664 * @return void
665 */
666 function addStructureValidationResults() {
667 var validationResults;
668
669 getStructure().getAllTreeNodes()
670 .removeClass(getHelper().getDomElementClassName('validationErrors'))
671 .removeClass(getHelper().getDomElementClassName('validationChildHasErrors'));
672
673 removeElementValidationErrorClass(getStructureRootElement());
674
675 validationResults = getFormEditorApp().validateFormElementRecursive(getRootFormElement());
676 for (var i = 0, len = validationResults.length; i < len; ++i) {
677 var hasError = false, pathParts, validationElement;
678 for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) {
679 if (
680 validationResults[i]['validationResults'][j]['validationResults']
681 && validationResults[i]['validationResults'][j]['validationResults'].length > 0
682 ) {
683 hasError = true;
684 break;
685 }
686 }
687
688 if (hasError) {
689 if (i === 0) {
690 setElementValidationErrorClass(getStructureRootElement());
691 } else {
692 validationElement = getStructure().getTreeNode(validationResults[i]['formElementIdentifierPath']);
693 setElementValidationErrorClass(validationElement);
694
695 pathParts = validationResults[i]['formElementIdentifierPath'].split('/');
696 while (pathParts.pop()) {
697 validationElement = getStructure().getTreeNode(pathParts.join('/'));
698 if ('object' === $.type(validationElement)) {
699 setElementValidationErrorClass(validationElement, 'validationChildHasErrors');
700 }
701 }
702 }
703 }
704 }
705 };
706
707 /* *************************************************************
708 * Modals
709 * ************************************************************/
710
711 /**
712 * @public
713 *
714 * @return object
715 */
716 function getModals() {
717 return _modalsComponent
718 };
719
720 /**
721 * @public
722 *
723 * @param object formElement
724 * @return void
725 */
726 function showRemoveFormElementModal(formElement) {
727 if (getUtility().isUndefinedOrNull(formElement)) {
728 formElement = getCurrentlySelectedFormElement();
729 }
730 getModals().showRemoveFormElementModal(formElement);
731 };
732
733 /**
734 * @public
735 *
736 * @param string collectionElementIdentifier
737 * @param string collectionName
738 * @param object formElement
739 * @return void
740 */
741 function showRemoveCollectionElementModal(collectionElementIdentifier, collectionName, formElement) {
742 if (getUtility().isUndefinedOrNull(formElement)) {
743 formElement = getCurrentlySelectedFormElement();
744 }
745 getModals().showRemoveCollectionElementModal(collectionElementIdentifier, collectionName, formElement);
746 };
747
748 /**
749 * @public
750 *
751 * @return void
752 */
753 function showCloseConfirmationModal() {
754 getModals().showCloseConfirmationModal();
755 };
756
757 /**
758 * @public
759 *
760 * @param string targetEvent
761 * @param object configuration
762 * @return void
763 */
764 function showInsertElementsModal(targetEvent, configuration) {
765 getModals().showInsertElementsModal(targetEvent, configuration);
766 };
767
768 /**
769 * @public
770 *
771 * @param string targetEvent
772 * @return void
773 */
774 function showInsertPagesModal(targetEvent) {
775 getModals().showInsertPagesModal(targetEvent);
776 };
777
778 /**
779 * @public
780 *
781 * @param bool
782 * @return void
783 */
784 function showValidationErrorsModal() {
785 var validationResults;
786 validationResults = getFormEditorApp().validateFormElementRecursive(getRootFormElement());
787
788 getModals().showValidationErrorsModal(validationResults);
789 };
790
791 /* *************************************************************
792 * Inspector
793 * ************************************************************/
794
795 /**
796 * @public
797 *
798 * @return object
799 */
800 function getInspector() {
801 return _inspectorsComponent
802 };
803
804 /**
805 * @public
806 *
807 * @param object
808 * @param bool
809 * @return void
810 */
811 function renderInspectorEditors(formElement, useFadeEffect) {
812 var render;
813 if (getUtility().isUndefinedOrNull(useFadeEffect)) {
814 useFadeEffect = true;
815 }
816
817 /**
818 * @private
819 *
820 * @param function
821 * @return void
822 */
823 render = function(callback) {
824 getInspector().renderEditors(formElement, callback);
825 };
826
827 if (!!useFadeEffect) {
828 getInspector().getInspectorDomElement().fadeOut('fast', function() {
829 render(function() {
830 getInspector().getInspectorDomElement().fadeIn('fast');
831 });
832 });
833 } else {
834 render();
835 }
836 };
837
838 /**
839 * @public
840 *
841 * @param string
842 * @param string
843 * @return void
844 */
845 function renderInspectorCollectionElementEditors(collectionName, collectionElementIdentifier) {
846 getInspector().renderCollectionElementEditors(collectionName, collectionElementIdentifier);
847 };
848
849 /**
850 * @public
851 *
852 * @param string content
853 * @return void
854 */
855 function setInspectorFormElementHeaderEditorContent(content) {
856 getInspector().setFormElementHeaderEditorContent(content);
857 };
858
859 /* *************************************************************
860 * Stage
861 * ************************************************************/
862
863 /**
864 * @public
865 *
866 * @return object
867 */
868 function getStage() {
869 return _stageComponent;
870 };
871
872 /**
873 * @public
874 *
875 * @param string title
876 * @return void
877 */
878 function setStageHeadline(title) {
879 getStage().setStageHeadline(title);
880 };
881
882 /**
883 * @public
884 *
885 * @return void
886 */
887 function addStagePanelSelection() {
888 getStage().getStagePanelDomElement().addClass(getHelper().getDomElementClassName('selectedStagePanel'));
889 };
890
891 /**
892 * @public
893 *
894 * @return void
895 */
896 function removeStagePanelSelection() {
897 getStage().getStagePanelDomElement().removeClass(getHelper().getDomElementClassName('selectedStagePanel'));
898 };
899
900 /**
901 * @public
902 *
903 * @return void
904 */
905 function renderPagination() {
906 getStage().renderPagination();
907 };
908
909 /**
910 * @public
911 *
912 * @return void
913 */
914 function renderUndoRedo() {
915 getStage().renderUndoRedo();
916 };
917
918 /**
919 * @public
920 *
921 * @param bool
922 * @param bool
923 * @return void
924 * @publish view/stage/abstract/render/postProcess
925 * @publish view/stage/abstract/render/preProcess
926 */
927 function renderAbstractStageArea(useFadeEffect, toolbarUseFadeEffect) {
928 var render, renderPostProcess;
929
930 $(getHelper().getDomElementDataIdentifierSelector('structureSection'))
931 .animate({
932 'left': '0px'
933 }, 'slow');
934 $(getHelper().getDomElementDataIdentifierSelector('inspectorSection'))
935 .animate({
936 'right': '0px'
937 }, 'slow');
938 $(getHelper().getDomElementDataIdentifierSelector('stageContainer'))
939 .animate({
940 'margin-left': _configuration['panels']['stage']['marginLeft'] + 'px',
941 'margin-right': _configuration['panels']['stage']['marginRight'] + 'px'
942 }, 'slow');
943 $(getHelper().getDomElementDataIdentifierSelector('stageContainerInner'))
944 .animate({
945 'max-width': _configuration['panels']['stage']['maxWidthAbstract'] + 'px'
946 }, 'slow');
947 $(getHelper().getDomElementClassName('headerButtonBar', true))
948 .animate({
949 'margin-left': _configuration['panels']['structure']['width'] + 'px'
950 }, 'slow');
951
952 if (getUtility().isUndefinedOrNull(useFadeEffect)) {
953 useFadeEffect = true;
954 }
955
956 if (getUtility().isUndefinedOrNull(toolbarUseFadeEffect)) {
957 toolbarUseFadeEffect = true;
958 }
959
960 setButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract')));
961 removeButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModePreview')));
962
963 /**
964 * @private
965 *
966 * @param function
967 * @return void
968 */
969 render = function(callback) {
970 $(getHelper().getDomElementDataIdentifierSelector('stageContainer'))
971 .addClass(getHelper().getDomElementClassName('stageViewModeAbstract'))
972 .removeClass(getHelper().getDomElementClassName('stageViewModePreview'));
973
974 getStage().renderAbstractStageArea(undefined, callback);
975 };
976
977 /**
978 * @private
979 *
980 * @return void
981 */
982 renderPostProcess = function() {
983 var formElementTypeDefinition;
984
985 formElementTypeDefinition = getFormElementDefinition(getCurrentlySelectedFormElement());
986 getStage().getAllFormElementDomElements().hover(function() {
987 getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover'));
988 if (
989 $(this).parent().hasClass(getHelper().getDomElementClassName('formElementIsComposit'))
990 && !$(this).parent().hasClass(getHelper().getDomElementClassName('formElementIsTopLevel'))
991 ) {
992 $(this).parent().addClass(getHelper().getDomElementClassName('sortableHover'));
993 }
994 });
995
996 showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage')));
997 if (
998 formElementTypeDefinition['_isTopLevelFormElement']
999 && !formElementTypeDefinition['_isCompositeFormElement']
1000 && !getFormEditorApp().isRootFormElementSelected()
1001 ) {
1002 hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')));
1003 hideComponent($(getHelper().getDomElementDataIdentifierSelector('stageNewElementRow')));
1004 } else {
1005 showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')));
1006 showComponent($(getHelper().getDomElementDataIdentifierSelector('stageNewElementRow')));
1007 }
1008
1009 refreshSelectedElementItemsBatch(toolbarUseFadeEffect);
1010 getPublisherSubscriber().publish('view/stage/abstract/render/postProcess');
1011 };
1012
1013 if (useFadeEffect) {
1014 $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeOut(400, function() {
1015 render(function() {
1016 getPublisherSubscriber().publish('view/stage/abstract/render/preProcess');
1017 $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeIn(400);
1018 renderPostProcess();
1019 getPublisherSubscriber().publish('view/stage/abstract/render/postProcess');
1020 });
1021 });
1022 } else {
1023 render(function() {
1024 getPublisherSubscriber().publish('view/stage/abstract/render/preProcess');
1025 renderPostProcess();
1026 getPublisherSubscriber().publish('view/stage/abstract/render/postProcess');
1027 });
1028 }
1029 };
1030
1031 /**
1032 * @public
1033 *
1034 * @param string html
1035 * @return void
1036 * @publish view/stage/preview/render/postProcess
1037 */
1038 function renderPreviewStageArea(html) {
1039 $(getHelper().getDomElementDataIdentifierSelector('structureSection'))
1040 .animate({
1041 'left': '-=' + _configuration['panels']['structure']['width'] + 'px'
1042 }, 'slow');
1043 $(getHelper().getDomElementDataIdentifierSelector('inspectorSection'))
1044 .animate({
1045 'right': '-=' + _configuration['panels']['inspector']['width'] + 'px'
1046 }, 'slow');
1047 $(getHelper().getDomElementDataIdentifierSelector('stageContainer'))
1048 .animate({
1049 'margin-left': _configuration['panels']['stage']['marginLeftCollapsed'] + 'px',
1050 'margin-right': _configuration['panels']['stage']['marginRightCollapsed'] + 'px'
1051 }, 'slow');
1052 $(getHelper().getDomElementDataIdentifierSelector('stageContainerInner'))
1053 .animate({
1054 'max-width': _configuration['panels']['stage']['maxWidthPreview'] + 'px'
1055 }, 'slow');
1056 $(getHelper().getDomElementClassName('headerButtonBar', true))
1057 .animate({
1058 'margin-left': _configuration['panels']['stage']['marginLeftCollapsed'] + 'px'
1059 }, 'slow');
1060
1061 setButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModePreview')));
1062 removeButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract')));
1063
1064 $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeOut(400, function() {
1065 $(getHelper().getDomElementDataIdentifierSelector('stageContainer'))
1066 .addClass(getHelper().getDomElementClassName('stageViewModePreview'))
1067 .removeClass(getHelper().getDomElementClassName('stageViewModeAbstract'));
1068
1069 hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')));
1070 hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage')));
1071
1072 getStage().renderPreviewStageArea(html);
1073 $(getHelper().getDomElementDataIdentifierSelector('stageSection')).fadeIn(400);
1074 getPublisherSubscriber().publish('view/stage/preview/render/postProcess');
1075 });
1076 };
1077
1078 /**
1079 * @public
1080 *
1081 * @return void
1082 */
1083 function addAbstractViewValidationResults() {
1084 var validationResults;
1085
1086 validationResults = getFormEditorApp().validateFormElementRecursive(getRootFormElement());
1087 for (var i = 0, len = validationResults.length; i < len; ++i) {
1088 var hasError = false, validationElement;
1089 for (var j = 0, len2 = validationResults[i]['validationResults'].length; j < len2; ++j) {
1090 if (
1091 validationResults[i]['validationResults'][j]['validationResults']
1092 && validationResults[i]['validationResults'][j]['validationResults'].length > 0
1093 ) {
1094 hasError = true;
1095 break;
1096 }
1097 }
1098
1099 if (hasError) {
1100 if (i > 0) {
1101 validationElement = getStage().getAbstractViewFormElementDomElement(validationResults[i]['formElementIdentifierPath']);
1102 setElementValidationErrorClass(validationElement);
1103 }
1104 }
1105 }
1106 };
1107
1108 /* *************************************************************
1109 * Form element methods
1110 * ************************************************************/
1111
1112 /**
1113 * @public
1114 *
1115 * @param string formElementType
1116 * @param string|object referenceFormElement
1117 * @param bool
1118 * @return object
1119 * @publish view/formElement/inserted
1120 */
1121 function createAndAddFormElement(formElementType, referenceFormElement, disablePublishersOnSet) {
1122 var newFormElement;
1123
1124 newFormElement = getFormEditorApp().createAndAddFormElement(formElementType, referenceFormElement);
1125 if (!!!disablePublishersOnSet) {
1126 getPublisherSubscriber().publish('view/formElement/inserted', [newFormElement]);
1127 }
1128 return newFormElement;
1129 };
1130
1131 /**
1132 * @public
1133 *
1134 * @param string|object formElementToMove
1135 * @param string position
1136 * @param string|object referenceFormElement
1137 * @param bool
1138 * @return object
1139 * @publish view/formElement/moved
1140 */
1141 function moveFormElement(formElementToMove, position, referenceFormElement, disablePublishersOnSet) {
1142 var movedFormElement;
1143
1144 movedFormElement = getFormEditorApp().moveFormElement(formElementToMove, position, referenceFormElement, false);
1145 if (!!!disablePublishersOnSet) {
1146 getPublisherSubscriber().publish('view/formElement/moved', [movedFormElement]);
1147 }
1148 return movedFormElement;
1149 };
1150
1151 /**
1152 * @public
1153 *
1154 * @param object formElement
1155 * @param bool
1156 * @return object
1157 * @publish view/formElement/removed
1158 */
1159 function removeFormElement(formElement, disablePublishersOnSet) {
1160 var parentFormElement;
1161
1162 if (getUtility().isUndefinedOrNull(formElement)) {
1163 formElement = getCurrentlySelectedFormElement();
1164 }
1165
1166 if (
1167 getFormElementDefinition(formElement, '_isTopLevelFormElement')
1168 && getFormElementDefinition(formElement, '_isCompositeFormElement')
1169 && getRootFormElement().get('renderables').length === 1
1170 ) {
1171 Notification.error(
1172 getFormElementDefinition(getRootFormElement(), 'modalRemoveElementLastAvailablePageFlashMessageTitle'),
1173 getFormElementDefinition(getRootFormElement(), 'modalRemoveElementLastAvailablePageFlashMessageMessage'),
1174 2
1175 );
1176 } else {
1177 parentFormElement = getFormEditorApp().removeFormElement(formElement, false);
1178 if (!!!disablePublishersOnSet) {
1179 getPublisherSubscriber().publish('view/formElement/removed', [parentFormElement]);
1180 }
1181 }
1182 return parentFormElement;
1183 };
1184
1185 /**
1186 * @public
1187 *
1188 * @param string collectionElementIdentifier
1189 * @param string collectionName
1190 * @param object formElement
1191 * @param object collectionElementConfiguration
1192 * @param string referenceCollectionElementIdentifier
1193 * @param bool
1194 * @return void
1195 * @publish view/collectionElement/new/added
1196 */
1197 function createAndAddPropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, collectionElementConfiguration, referenceCollectionElementIdentifier, disablePublishersOnSet) {
1198 getFormEditorApp().createAndAddPropertyCollectionElement(
1199 collectionElementIdentifier,
1200 collectionName,
1201 formElement,
1202 collectionElementConfiguration,
1203 referenceCollectionElementIdentifier
1204 );
1205 if (!!!disablePublishersOnSet) {
1206 getPublisherSubscriber().publish('view/collectionElement/new/added', [
1207 collectionElementIdentifier,
1208 collectionName,
1209 formElement,
1210 collectionElementConfiguration,
1211 referenceCollectionElementIdentifier
1212 ]);
1213 }
1214 };
1215
1216 /**
1217 * @public
1218 *
1219 * @param string collectionElementToMove
1220 * @param string position
1221 * @param string referenceCollectionElement
1222 * @param string collectionName
1223 * @param object formElement
1224 * @param bool
1225 * @return void
1226 */
1227 function movePropertyCollectionElement(collectionElementToMove, position, referenceCollectionElement, collectionName, formElement, disablePublishersOnSet) {
1228 if (getUtility().isUndefinedOrNull(formElement)) {
1229 formElement = getCurrentlySelectedFormElement();
1230 }
1231 getFormEditorApp().movePropertyCollectionElement(
1232 collectionElementToMove,
1233 position,
1234 referenceCollectionElement,
1235 collectionName,
1236 formElement,
1237 false
1238 );
1239 if (!!!disablePublishersOnSet) {
1240 getPublisherSubscriber().publish('view/collectionElement/moved', [
1241 collectionElementToMove,
1242 position,
1243 referenceCollectionElement,
1244 collectionName,
1245 formElement]
1246 );
1247 }
1248 };
1249
1250 /**
1251 * @public
1252 *
1253 * @param string collectionElementIdentifier
1254 * @param string collectionName
1255 * @param object formElement
1256 * @param bool
1257 * @return void
1258 * @publish view/collectionElement/removed
1259 */
1260 function removePropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, disablePublishersOnSet) {
1261 var collectionElementConfiguration, propertyData, propertyPath;
1262
1263 getFormEditorApp().removePropertyCollectionElement(collectionElementIdentifier, collectionName, formElement);
1264
1265 collectionElementConfiguration = getFormEditorApp().getPropertyCollectionElementConfiguration(
1266 collectionElementIdentifier,
1267 collectionName
1268 );
1269 if ('array' === $.type(collectionElementConfiguration['editors'])) {
1270 for (var i = 0, len1 = collectionElementConfiguration['editors'].length; i < len1; ++i) {
1271 if ('array' === $.type(collectionElementConfiguration['editors'][i]['additionalElementPropertyPaths'])) {
1272 for (var j = 0, len2 = collectionElementConfiguration['editors'][i]['additionalElementPropertyPaths'].length; j < len2; ++j) {
1273 getCurrentlySelectedFormElement().unset(collectionElementConfiguration['editors'][i]['additionalElementPropertyPaths'][j], true);
1274 }
1275 } else if (collectionElementConfiguration['editors'][i]['identifier'] === 'validationErrorMessage') {
1276 propertyPath = getFormEditorApp().buildPropertyPath(
1277 collectionElementConfiguration['editors'][i]['propertyPath']
1278 );
1279 propertyData = getCurrentlySelectedFormElement().get(propertyPath);
1280 if (!getUtility().isUndefinedOrNull(propertyData)) {
1281 for (var j = 0, len2 = collectionElementConfiguration['editors'][i]['errorCodes'].length; j < len2; ++j) {
1282 for (var k = 0, len3 = propertyData.length; k < len3; ++k) {
1283 if (parseInt(collectionElementConfiguration['editors'][i]['errorCodes'][j]) === parseInt(propertyData[k]['code'])) {
1284 propertyData.splice(k, 1);
1285 --len3;
1286 }
1287 }
1288 }
1289 getCurrentlySelectedFormElement().set(propertyPath, propertyData);
1290 }
1291 }
1292 }
1293 }
1294
1295 if (!!!disablePublishersOnSet) {
1296 getPublisherSubscriber().publish('view/collectionElement/removed', [
1297 collectionElementIdentifier,
1298 collectionName,
1299 formElement]
1300 );
1301 }
1302 };
1303
1304 /* *************************************************************
1305 * Batch methodes
1306 * ************************************************************/
1307
1308 /**
1309 * @public
1310 *
1311 * @param bool
1312 * @return void
1313 */
1314 function refreshSelectedElementItemsBatch(toolbarUseFadeEffect) {
1315 var formElementTypeDefinition, selectedElement;
1316
1317 if (getUtility().isUndefinedOrNull(toolbarUseFadeEffect)) {
1318 toolbarUseFadeEffect = true;
1319 }
1320
1321 formElementTypeDefinition = getFormElementDefinition(getCurrentlySelectedFormElement());
1322
1323 getStage().removeAllStageToolbars();
1324 removeAllStageElementSelectionsBatch();
1325 removeAllStructureSelections();
1326
1327 if (!getFormEditorApp().isRootFormElementSelected()) {
1328 removeStructureRootElementSelection();
1329 addStructureSelection();
1330
1331 selectedElement = getStage().getAbstractViewFormElementDomElement();
1332
1333 if (formElementTypeDefinition['_isTopLevelFormElement']) {
1334 addStagePanelSelection();
1335 } else {
1336 selectedElement.addClass(getHelper().getDomElementClassName('selectedFormElement'));
1337 getStage().createAndAddAbstractViewFormElementToolbar(selectedElement, undefined, toolbarUseFadeEffect);
1338 }
1339
1340 getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('selectedCompositFormElement'));
1341 if (!formElementTypeDefinition['_isTopLevelFormElement'] && formElementTypeDefinition['_isCompositeFormElement']) {
1342 selectedElement.parent().addClass(getHelper().getDomElementClassName('selectedCompositFormElement'));
1343 }
1344 }
1345 };
1346
1347 /**
1348 * @public
1349 *
1350 * @param int
1351 * @return void
1352 * @throws 1478651732
1353 * @throws 1478651733
1354 * @throws 1478651734
1355 */
1356 function selectPageBatch(pageIndex) {
1357 assert('number' === $.type(pageIndex), 'Invalid parameter "pageIndex"', 1478651732);
1358 assert(pageIndex >= 0, 'Invalid parameter "pageIndex"', 1478651733);
1359 assert(pageIndex < getRootFormElement().get('renderables').length, 'Invalid parameter "pageIndex"', 1478651734);
1360
1361 getFormEditorApp().setCurrentlySelectedFormElement(getRootFormElement().get('renderables')[pageIndex]);
1362 renewStructure();
1363 renderPagination()
1364 refreshSelectedElementItemsBatch();
1365 renderInspectorEditors();
1366 };
1367
1368 /**
1369 * @public
1370 *
1371 * @return void
1372 */
1373 function removeAllStageElementSelectionsBatch() {
1374 getStage().getAllFormElementDomElements().removeClass(getHelper().getDomElementClassName('selectedFormElement'));
1375 removeStagePanelSelection();
1376 getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover'));
1377 };
1378
1379 /**
1380 * @public
1381 *
1382 * @return void
1383 */
1384 function onViewReadyBatch() {
1385 $(getHelper().getDomElementDataIdentifierSelector('structureSection'))
1386 .css({
1387 width: _configuration['panels']['structure']['width'] + 'px',
1388 left: '-=' + _configuration['panels']['structure']['width'] + 'px'
1389 });
1390 $(getHelper().getDomElementDataIdentifierSelector('inspectorSection'))
1391 .css({
1392 width: _configuration['panels']['inspector']['width'] + 'px',
1393 right: '-=' + _configuration['panels']['inspector']['width'] + 'px'
1394 });
1395
1396 $(getHelper().getDomElementClassName('headerButtonBar', true))
1397 .css({
1398 'margin-left': _configuration['panels']['structure']['width'] + 'px'
1399 });
1400
1401 $(getHelper().getDomElementDataIdentifierSelector('stageContainer'))
1402 .css({
1403 'margin-left': _configuration['panels']['stage']['marginLeft'] + 'px',
1404 'margin-right': _configuration['panels']['stage']['marginRight'] + 'px'
1405 });
1406
1407 hideComponent($(getHelper().getDomElementDataIdentifierSelector('buttonStageNewElementBottom')));
1408 hideComponent($(getHelper().getDomElementDataIdentifierSelector('stageNewElementRow')));
1409
1410 setStageHeadline();
1411 setStructureRootElementTitle();
1412 renderAbstractStageArea(false);
1413 renewStructure();
1414 addStructureRootElementSelection();
1415 renderInspectorEditors();
1416 renderPagination();
1417
1418 hideComponent($(getHelper().getDomElementDataIdentifierSelector('moduleLoadingIndicator')));
1419 showComponent($(getHelper().getDomElementDataIdentifierSelector('moduleWrapper')));
1420 showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSave')));
1421 showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderSettings')));
1422 showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderClose')));
1423 showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderNewPage')));
1424 showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderUndo')));
1425 showComponent($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderRedo')));
1426 setButtonActive($(getHelper().getDomElementDataIdentifierSelector('buttonHeaderViewModeAbstract')));
1427 };
1428
1429 /**
1430 * @public
1431 *
1432 * @param object
1433 * @param object
1434 * @return void
1435 */
1436 function onAbstractViewDndStartBatch(draggedFormElementDomElement, draggedFormPlaceholderDomElement) {
1437 draggedFormPlaceholderDomElement.removeClass(getHelper().getDomElementClassName('sortableHover'));
1438 };
1439
1440 /**
1441 * @public
1442 *
1443 * @param object
1444 * @param string
1445 * @param object
1446 * @return void
1447 */
1448 function onAbstractViewDndChangeBatch(placeholderDomElement, parentFormElementIdentifierPath, enclosingCompositeFormElement) {
1449 getStage().getAllFormElementDomElements().parent().removeClass(getHelper().getDomElementClassName('sortableHover'));
1450 if (enclosingCompositeFormElement) {
1451 getStage().getAbstractViewParentFormElementWithinDomElement(placeholderDomElement).parent().addClass(getHelper().getDomElementClassName('sortableHover'));
1452 }
1453 };
1454
1455 /**
1456 * @public
1457 *
1458 * @param object
1459 * @param string
1460 * @param string
1461 * @param string
1462 * @return void
1463 * @throws 1472502237
1464 */
1465 function onAbstractViewDndUpdateBatch(movedDomElement, movedFormElementIdentifierPath, previousFormElementIdentifierPath, nextFormElementIdentifierPath) {
1466 var movedFormElement, parentFormElementIdentifierPath;
1467 if (nextFormElementIdentifierPath) {
1468 movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'before', nextFormElementIdentifierPath);
1469 } else if (previousFormElementIdentifierPath) {
1470 movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'after', previousFormElementIdentifierPath);
1471 } else {
1472 parentFormElementIdentifierPath = getStage().getAbstractViewParentFormElementIdentifierPathWithinDomElement(movedDomElement);
1473 if (parentFormElementIdentifierPath) {
1474 movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'inside', parentFormElementIdentifierPath);
1475 } else {
1476 assert(false, 'Next element, previous or parent element need to be set.', 1472502237);
1477 }
1478 }
1479
1480 getStage()
1481 .getAbstractViewFormElementWithinDomElement(movedDomElement)
1482 .attr(
1483 getHelper().getDomElementDataAttribute('elementIdentifier'),
1484 movedFormElement.get('__identifierPath')
1485 );
1486 };
1487
1488 /**
1489 * @public
1490 *
1491 * @param object
1492 * @param string
1493 * @param object
1494 * @return void
1495 */
1496 function onStructureDndChangeBatch(placeholderDomElement, parentFormElementIdentifierPath, enclosingCompositeFormElement) {
1497 getStructure()
1498 .getAllTreeNodes()
1499 .parent()
1500 .removeClass(getHelper().getDomElementClassName('sortableHover'));
1501
1502 getStage()
1503 .getAllFormElementDomElements()
1504 .parent()
1505 .removeClass(getHelper().getDomElementClassName('sortableHover'));
1506
1507 if (enclosingCompositeFormElement) {
1508 getStructure()
1509 .getParentTreeNodeWithinDomElement(placeholderDomElement)
1510 .parent()
1511 .addClass(getHelper().getDomElementClassName('sortableHover'));
1512
1513 getStage()
1514 .getAbstractViewFormElementDomElement(enclosingCompositeFormElement)
1515 .parent()
1516 .addClass(getHelper().getDomElementClassName('sortableHover'));
1517 }
1518 };
1519
1520 /**
1521 * @public
1522 *
1523 * @param object
1524 * @param string
1525 * @param string
1526 * @param string
1527 * @return void
1528 * @throws 1479048646
1529 */
1530 function onStructureDndUpdateBatch(movedDomElement, movedFormElementIdentifierPath, previousFormElementIdentifierPath, nextFormElementIdentifierPath) {
1531 var movedFormElement, parentFormElementIdentifierPath;
1532 if (nextFormElementIdentifierPath) {
1533 movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'before', nextFormElementIdentifierPath);
1534 } else if (previousFormElementIdentifierPath) {
1535 movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'after', previousFormElementIdentifierPath);
1536 } else {
1537 parentFormElementIdentifierPath = getStructure().getParentTreeNodeIdentifierPathWithinDomElement(movedDomElement);
1538 if (parentFormElementIdentifierPath) {
1539 movedFormElement = moveFormElement(movedFormElementIdentifierPath, 'inside', parentFormElementIdentifierPath);
1540 } else {
1541 getFormEditorApp().assert(false, 'Next element, previous or parent element need to be set.', 1479048646);
1542 }
1543 }
1544
1545 getStructure()
1546 .getTreeNodeWithinDomElement(movedDomElement)
1547 .attr(
1548 getHelper().getDomElementDataAttribute('elementIdentifier'),
1549 movedFormElement.get('__identifierPath')
1550 );
1551 };
1552
1553 /* *************************************************************
1554 * Misc
1555 * ************************************************************/
1556
1557 /**
1558 * @public
1559 *
1560 * @return void
1561 */
1562 function closeEditor() {
1563 document.location.href = $(getHelper().getDomElementDataIdentifierSelector('buttonHeaderClose')).prop('href');
1564 };
1565
1566 /**
1567 * @public
1568 *
1569 * @param object
1570 * @param string
1571 * @return void
1572 */
1573 function setElementValidationErrorClass(element, classIdentifier) {
1574 if (getFormEditorApp().getUtility().isUndefinedOrNull(classIdentifier)) {
1575 element.addClass(getHelper().getDomElementClassName('validationErrors'));
1576 } else {
1577 element.addClass(getHelper().getDomElementClassName(classIdentifier));
1578 }
1579 };
1580
1581 /**
1582 * @public
1583 *
1584 * @param object
1585 * @param string
1586 * @return void
1587 */
1588 function removeElementValidationErrorClass(element, classIdentifier) {
1589 if (getFormEditorApp().getUtility().isUndefinedOrNull(classIdentifier)) {
1590 element.removeClass(getHelper().getDomElementClassName('validationErrors'));
1591 } else {
1592 element.removeClass(getHelper().getDomElementClassName(classIdentifier));
1593 }
1594 };
1595
1596 /**
1597 * @public
1598 *
1599 * @param object
1600 * @return void
1601 */
1602 function showComponent(element) {
1603 element.removeClass(getHelper().getDomElementClassName('hidden')).show();
1604 };
1605
1606 /**
1607 * @public
1608 *
1609 * @param object
1610 * @return void
1611 */
1612 function hideComponent(element) {
1613 element.addClass(getHelper().getDomElementClassName('hidden')).hide();
1614 };
1615
1616 /**
1617 * @public
1618 *
1619 * @param object
1620 * @return void
1621 */
1622 function enableButton(buttonElement) {
1623 buttonElement.prop('disabled', false).removeClass(getHelper().getDomElementClassName('disabled'));
1624 };
1625
1626 /**
1627 * @public
1628 *
1629 * @param object
1630 * @return void
1631 */
1632 function disableButton(buttonElement) {
1633 buttonElement.prop('disabled', 'disabled').addClass(getHelper().getDomElementClassName('disabled'));
1634 };
1635
1636 /**
1637 * @public
1638 *
1639 * @param object
1640 * @return void
1641 */
1642 function setButtonActive(buttonElement) {
1643 buttonElement.addClass(getHelper().getDomElementClassName('active'));
1644 };
1645
1646 /**
1647 * @public
1648 *
1649 * @param object
1650 * @return void
1651 */
1652 function removeButtonActive(buttonElement) {
1653 buttonElement.removeClass(getHelper().getDomElementClassName('active'));
1654 };
1655
1656 /**
1657 * @public
1658 *
1659 * @return void
1660 */
1661 function showSaveButtonSpinnerIcon() {
1662 Icons.getIcon(getHelper().getDomElementDataAttributeValue('iconSaveSpinner'), Icons.sizes.small).done(function(markup) {
1663 $(getHelper().getDomElementDataIdentifierSelector('iconSave')).replaceWith($(markup));
1664 });
1665 };
1666
1667 /**
1668 * @public
1669 *
1670 * @return void
1671 */
1672 function showSaveButtonSaveIcon() {
1673 Icons.getIcon(getHelper().getDomElementDataAttributeValue('iconSave'), Icons.sizes.small).done(function(markup) {
1674 $(getHelper().getDomElementDataIdentifierSelector('iconSaveSpinner')).replaceWith($(markup));
1675 });
1676 };
1677
1678 /**
1679 * @public
1680 *
1681 * @return void
1682 */
1683 function showSaveSuccessMessage() {
1684 Notification.success(
1685 getFormElementDefinition(getRootFormElement(), 'saveSuccessFlashMessageTitle'),
1686 getFormElementDefinition(getRootFormElement(), 'saveSuccessFlashMessageMessage'),
1687 2
1688 );
1689 };
1690
1691 /**
1692 * @public
1693 *
1694 * @return void
1695 */
1696 function showSaveErrorMessage(response) {
1697 Notification.error(
1698 getFormElementDefinition(getRootFormElement(), 'saveErrorFlashMessageTitle'),
1699 getFormElementDefinition(getRootFormElement(), 'saveErrorFlashMessageMessage') +
1700 " " +
1701 response.message
1702 );
1703 };
1704
1705 /**
1706 * @public
1707 *
1708 * @param string
1709 * @param string
1710 * @return void
1711 */
1712 function showErrorFlashMessage(title, message) {
1713 Notification.error(title, message, 2);
1714 };
1715
1716 /**
1717 * @public
1718 *
1719 * @param object formEditorApp
1720 * @param object additionalViewModelModules
1721 * @return void
1722 */
1723 function bootstrap(formEditorApp, additionalViewModelModules) {
1724 _formEditorApp = formEditorApp;
1725
1726 _helperSetup();
1727 _structureComponentSetup();
1728 _modalsComponentSetup();
1729 _inspectorsComponentSetup();
1730 _stageComponentSetup();
1731 _buttonsSetup();
1732 _addPropertyValidators();
1733 _loadAdditionalModules(additionalViewModelModules);
1734 };
1735
1736 /**
1737 * Publish the public methods.
1738 * Implements the "Revealing Module Pattern".
1739 */
1740 return {
1741 addAbstractViewValidationResults: addAbstractViewValidationResults,
1742 addStagePanelSelection: addStagePanelSelection,
1743 addStructureRootElementSelection: addStructureRootElementSelection,
1744 addStructureSelection: addStructureSelection,
1745 addStructureValidationResults: addStructureValidationResults,
1746 bootstrap: bootstrap,
1747 closeEditor: closeEditor,
1748 createAndAddFormElement: createAndAddFormElement,
1749 createAndAddPropertyCollectionElement: createAndAddPropertyCollectionElement,
1750 disableButton: disableButton,
1751 enableButton: enableButton,
1752 getConfiguration: getConfiguration,
1753 getFormEditorApp: getFormEditorApp,
1754 getFormElementDefinition: getFormElementDefinition,
1755 getHelper: getHelper,
1756 getInspector: getInspector,
1757 getModals: getModals,
1758 getPreviewMode: getPreviewMode,
1759 getStage: getStage,
1760 getStructure: getStructure,
1761 getStructureRootElement: getStructureRootElement,
1762 hideComponent: hideComponent,
1763 moveFormElement: moveFormElement,
1764 movePropertyCollectionElement: movePropertyCollectionElement,
1765 onAbstractViewDndChangeBatch: onAbstractViewDndChangeBatch,
1766 onAbstractViewDndStartBatch: onAbstractViewDndStartBatch,
1767 onAbstractViewDndUpdateBatch: onAbstractViewDndUpdateBatch,
1768 onStructureDndChangeBatch: onStructureDndChangeBatch,
1769 onStructureDndUpdateBatch: onStructureDndUpdateBatch,
1770 onViewReadyBatch: onViewReadyBatch,
1771 refreshSelectedElementItemsBatch: refreshSelectedElementItemsBatch,
1772 removeAllStageElementSelectionsBatch: removeAllStageElementSelectionsBatch,
1773 removeAllStructureSelections: removeAllStructureSelections,
1774 removeButtonActive: removeButtonActive,
1775 removeElementValidationErrorClass: removeElementValidationErrorClass,
1776 removeFormElement: removeFormElement,
1777 removePropertyCollectionElement: removePropertyCollectionElement,
1778 removeStagePanelSelection: removeStagePanelSelection,
1779 removeStructureRootElementSelection: removeStructureRootElementSelection,
1780 removeStructureSelection: removeStructureSelection,
1781 renderAbstractStageArea: renderAbstractStageArea,
1782 renderInspectorEditors: renderInspectorEditors,
1783 renderInspectorCollectionElementEditors: renderInspectorCollectionElementEditors,
1784 renderPagination: renderPagination,
1785 renderPreviewStageArea: renderPreviewStageArea,
1786 renewStructure: renewStructure,
1787 renderUndoRedo: renderUndoRedo,
1788 selectPageBatch: selectPageBatch,
1789 setButtonActive: setButtonActive,
1790 setElementValidationErrorClass: setElementValidationErrorClass,
1791 setInspectorFormElementHeaderEditorContent: setInspectorFormElementHeaderEditorContent,
1792 setPreviewMode: setPreviewMode,
1793 setStageHeadline: setStageHeadline,
1794 setStructureRootElementTitle: setStructureRootElementTitle,
1795 showCloseConfirmationModal: showCloseConfirmationModal,
1796 showComponent: showComponent,
1797 showErrorFlashMessage: showErrorFlashMessage,
1798 showInsertElementsModal: showInsertElementsModal,
1799 showInsertPagesModal: showInsertPagesModal,
1800 showRemoveFormElementModal: showRemoveFormElementModal,
1801 showRemoveCollectionElementModal: showRemoveCollectionElementModal,
1802 showSaveButtonSaveIcon: showSaveButtonSaveIcon,
1803 showSaveButtonSpinnerIcon: showSaveButtonSpinnerIcon,
1804 showSaveSuccessMessage: showSaveSuccessMessage,
1805 showSaveErrorMessage: showSaveErrorMessage,
1806 showValidationErrorsModal: showValidationErrorsModal
1807 };
1808 })($, TreeComponent, ModalsComponent, InspectorComponent, StageComponent, Helper, Icons, Notification);
1809 });