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