be985682c5ded7eada488772c34226006419499a
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Resources / Public / JavaScript / Backend / FormEditor.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
16 */
17 define(['jquery',
18 'TYPO3/CMS/Form/Backend/FormEditor/Core'
19 ], function($, core) {
20 'use strict';
21
22 /**
23 * Return a static method named "getInstance".
24 * Use this method to create the formeditor app.
25 */
26 return (function(_core) {
27
28 /**
29 * @private
30 *
31 * Hold the instance (Singleton Pattern)
32 */
33 var _formEditorInstance = null;
34
35 /**
36 * @public
37 *
38 * @param object _configuration
39 * @param object _mediator
40 * @param object _viewModel
41 * @return object
42 */
43 function FormEditor(_configuration, _mediator, _viewModel) {
44
45 /**
46 * @private
47 *
48 * @var bool
49 */
50 var _isRunning = false;
51
52 /**
53 * @private
54 *
55 * @var bool
56 */
57 var _unsavedContent = false;
58
59 /**
60 * @private
61 *
62 * @var bool
63 */
64 var _previewMode = false;
65
66 /**
67 * @public
68 *
69 * @return object
70 */
71 function getPublisherSubscriber() {
72 return _core.getPublisherSubscriber();
73 };
74
75 /**
76 * @public
77 *
78 * @return void
79 */
80 function _saveApplicationState() {
81
82 _getApplicationStateStack().addAndReset({
83 formDefinition: _getApplicationStateStack().getCurrentState('formDefinition').clone(),
84 currentlySelectedPageIndex: _getApplicationStateStack().getCurrentState('currentlySelectedPageIndex'),
85 currentlySelectedFormElementIdentifierPath: _getApplicationStateStack().getCurrentState('currentlySelectedFormElementIdentifierPath')
86 });
87 };
88
89 /**
90 * @public
91 *
92 * @return void
93 */
94 function undoApplicationState() {
95 _getApplicationStateStack().incrementCurrentStackPointer();
96 };
97
98 /**
99 * @public
100 *
101 * @return void
102 */
103 function redoApplicationState() {
104 _getApplicationStateStack().decrementCurrentStackPointer();
105 };
106
107 /**
108 * @public
109 *
110 * @return int
111 */
112 function getMaximalApplicationStates() {
113 return _getApplicationStateStack().getMaximalStackSize();
114 };
115
116 /**
117 * @public
118 *
119 * @return int
120 */
121 function getCurrentApplicationStates() {
122 return _getApplicationStateStack().getCurrentStackSize();
123 };
124
125 /**
126 * @public
127 *
128 * @return int
129 */
130 function getCurrentApplicationStatePosition() {
131 return _getApplicationStateStack().getCurrentStackPointer();
132 };
133
134 /**
135 * @public
136 *
137 * @param string type
138 * @return object
139 * @throws 1475378543
140 */
141 function getRunningAjaxRequest(type) {
142 assert(getUtility().isNonEmptyString(type), 'Invalid parameter "type"', 1475378543);
143 return _core.getRunningAjaxRequest(type);
144 };
145
146 /**
147 * @public
148 *
149 * @return object
150 */
151 function getUtility() {
152 return _core.getUtility();
153 };
154
155 /**
156 * @public
157 *
158 * @param mixed test
159 * @param string message
160 * @param int messageCode
161 * @return void
162 */
163 function assert(test, message, messageCode) {
164 getUtility().assert(test, message, messageCode);
165 };
166
167 /**
168 * @public
169 *
170 * @param string propertyPath
171 * @param string collectionElementIdentifier
172 * @param string collectionName
173 * @param object formElement
174 * @param boolean allowEmptyReturnValue
175 * @return string
176 */
177 function buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement, allowEmptyReturnValue) {
178 if (getUtility().isUndefinedOrNull(formElement)) {
179 formElement = getCurrentlySelectedFormElement();
180 }
181 formElement = _getRepository().findFormElement(formElement);
182 return getUtility().buildPropertyPath(propertyPath, collectionElementIdentifier, collectionName, formElement, allowEmptyReturnValue);
183 };
184
185 /**
186 * @public
187 *
188 * @param string validatorIdentifier
189 * @param function func
190 * @return void
191 */
192 function addPropertyValidationValidator(validatorIdentifier, func) {
193 _getPropertyValidationService().addValidator(validatorIdentifier, func);
194 };
195
196 /**
197 * @public
198 *
199 * @param string propertyPath
200 * @return object
201 */
202 function validateCurrentlySelectedFormElementProperty(propertyPath) {
203 return validateFormElementProperty(
204 getCurrentlySelectedFormElement(),
205 propertyPath
206 );
207 };
208
209 /**
210 * @public
211 *
212 * @param object formElement
213 * @param string propertyPath
214 * @return object
215 */
216 function validateFormElementProperty(formElement, propertyPath) {
217 formElement = _getRepository().findFormElement(formElement);
218 return _getPropertyValidationService().validateFormElementProperty(formElement, propertyPath);
219 };
220
221 /**
222 * @public
223 *
224 * @param object formElement
225 * @return object
226 */
227 function validateFormElement(formElement) {
228 formElement = _getRepository().findFormElement(formElement);
229 return _getPropertyValidationService().validateFormElement(formElement);
230 };
231
232 /**
233 * @public
234 *
235 * @param object validationResults
236 * @return boolean
237 */
238 function validationResultsHasErrors(validationResults) {
239 return _getPropertyValidationService().validationResultsHasErrors(validationResults);
240 };
241
242 /**
243 * @public
244 *
245 * @param object formElement
246 * @param boolean returnAfterFirstMatch
247 * @return object
248 */
249 function validateFormElementRecursive(formElement, returnAfterFirstMatch) {
250 formElement = _getRepository().findFormElement(formElement);
251 return _getPropertyValidationService().validateFormElementRecursive(formElement, returnAfterFirstMatch);
252 };
253
254 /**
255 * @public
256 *
257 * @param bool unsavedContent
258 * @return void
259 * @throws 1475378544
260 */
261 function setUnsavedContent(unsavedContent) {
262 assert('boolean' === $.type(unsavedContent), 'Invalid parameter "unsavedContent"', 1475378544);
263 _unsavedContent = unsavedContent;
264 };
265
266 /**
267 * @public
268 *
269 * @return boolean
270 */
271 function getUnsavedContent() {
272 return _unsavedContent;
273 };
274
275 /**
276 * @public
277 *
278 * @return object
279 */
280 function getRootFormElement() {
281 return _getRepository().getRootFormElement();
282 };
283
284 /**
285 * @public
286 *
287 * @return string
288 */
289 function getCurrentlySelectedFormElement() {
290 return _getRepository().findFormElementByIdentifierPath(_getApplicationStateStack().getCurrentState('currentlySelectedFormElementIdentifierPath'));
291 };
292
293 /**
294 * @public
295 *
296 * @param string|object formElement
297 * @param boolean doNotRefreshCurrentlySelectedPageIndex
298 * @return void
299 * @publish core/currentlySelectedFormElementChanged
300 */
301 function setCurrentlySelectedFormElement(formElement, doNotRefreshCurrentlySelectedPageIndex) {
302 doNotRefreshCurrentlySelectedPageIndex = !!doNotRefreshCurrentlySelectedPageIndex;
303
304 formElement = _getRepository().findFormElement(formElement);
305 _getApplicationStateStack().setCurrentState('currentlySelectedFormElementIdentifierPath', formElement.get('__identifierPath'));
306
307 if (!doNotRefreshCurrentlySelectedPageIndex) {
308 refreshCurrentlySelectedPageIndex();
309 }
310 getPublisherSubscriber().publish('core/currentlySelectedFormElementChanged', [formElement]);
311 };
312
313 /**
314 * @public
315 *
316 * @param string identifierPath
317 * @return object
318 * @throws 1475378545
319 */
320 function getFormElementByIdentifierPath(identifierPath) {
321 assert(getUtility().isNonEmptyString(identifierPath), 'Invalid parameter "identifierPath"', 1475378545);
322 return _getRepository().findFormElementByIdentifierPath(identifierPath);
323 };
324
325 /**
326 * @public
327 *
328 * @param string identifierPath
329 * @return bool
330 */
331 function isFormElementIdentifierUsed(formElementIdentifier) {
332 return _getRepository().isFormElementIdentifierUsed(formElementIdentifier);
333 }
334
335 /**
336 * @public
337 *
338 * @param string formElementType
339 * @param string|object referenceFormElement
340 * @param boolean disablePublishersOnSet
341 * @return object
342 */
343 function createAndAddFormElement(formElementType, referenceFormElement, disablePublishersOnSet) {
344 var formElement;
345 formElement = addFormElement(createFormElement(formElementType, disablePublishersOnSet), referenceFormElement, disablePublishersOnSet);
346 formElement.set('renderables', formElement.get('renderables'));
347 return formElement;
348 };
349
350 /**
351 * @public
352 *
353 * @param object formElement
354 * @param string|object referenceFormElement
355 * @param boolean disablePublishersOnSet
356 * @return object
357 * @throws 1475434337
358 */
359 function addFormElement(formElement, referenceFormElement, disablePublishersOnSet) {
360 _saveApplicationState();
361
362 if (getUtility().isUndefinedOrNull(referenceFormElement)) {
363 referenceFormElement = getCurrentlySelectedFormElement();
364 }
365 referenceFormElement = _getRepository().findFormElement(referenceFormElement);
366 assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1475434337);
367 return _getRepository().addFormElement(formElement, referenceFormElement, true, disablePublishersOnSet);
368 };
369
370 /**
371 * @public
372 *
373 * @param string formElementType
374 * @param boolean disablePublishersOnSet
375 * @return object
376 * @throws 1475434336
377 * @throws 1475435857
378 */
379 function createFormElement(formElementType, disablePublishersOnSet) {
380 var formElementDefinition, identifier;
381 assert(getUtility().isNonEmptyString(formElementType), 'Invalid parameter "formElementType"', 1475434336);
382
383 identifier = _getRepository().getNextFreeFormElementIdentifier(formElementType);
384 formElementDefinition = getFormElementDefinitionByType(formElementType);
385 return _getFactory().createFormElement({
386 type: formElementType,
387 identifier: identifier,
388 label: formElementDefinition['label'] || formElementType
389 }, undefined, undefined, undefined, disablePublishersOnSet);
390 };
391
392 /**
393 * @public
394 *
395 * @param string|object formElementToRemove
396 * @param boolean disablePublishersOnSet
397 * @return object
398 */
399 function removeFormElement(formElementToRemove, disablePublishersOnSet) {
400 var parentFormElement;
401 _saveApplicationState();
402
403 formElementToRemove = _getRepository().findFormElement(formElementToRemove);
404 parentFormElement = formElementToRemove.get('__parentRenderable');
405 _getRepository().removeFormElement(formElementToRemove, true, disablePublishersOnSet);
406 return parentFormElement;
407 };
408
409 /**
410 * @public
411 *
412 * @param string|object formElementToMove
413 * @param string position
414 * @param string|object referenceFormElement
415 * @param boolean disablePublishersOnSet
416 * @return string
417 * @throws 1475378551
418 */
419 function moveFormElement(formElementToMove, position, referenceFormElement, disablePublishersOnSet) {
420 _saveApplicationState();
421
422 formElementToMove = _getRepository().findFormElement(formElementToMove);
423 referenceFormElement = _getRepository().findFormElement(referenceFormElement);
424
425 assert('after' === position || 'before' === position || 'inside' === position, 'Invalid position "' + position + '"', 1475378551);
426
427 formElementToMove = _getRepository().moveFormElement(formElementToMove, position, referenceFormElement, true);
428 disablePublishersOnSet = !!disablePublishersOnSet;
429 if (!disablePublishersOnSet) {
430 formElementToMove.get('__parentRenderable').set('renderables', formElementToMove.get('__parentRenderable').get('renderables'));
431 }
432 return formElementToMove;
433 };
434
435 /**
436 * @public
437 *
438 * @param string collectionElementIdentifier
439 * @param string collectionName
440 * @param string formElement
441 * @return object (dereferenced)
442 * @throws 1475378555
443 * @throws 1475378556
444 * @throws 1475446108
445 */
446 function getPropertyCollectionElementConfiguration(collectionElementIdentifier, collectionName, formElement) {
447 var collection, collectionElement, formElementDefinition;
448 if (getUtility().isUndefinedOrNull(formElement)) {
449 formElement = getCurrentlySelectedFormElement();
450 }
451 formElement = _getRepository().findFormElement(formElement);
452
453 assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378555);
454 assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378556);
455
456 formElementDefinition = getFormElementDefinitionByType(formElement.get('type'));
457 if (!getUtility().isUndefinedOrNull(formElementDefinition['propertyCollections'])) {
458 collection = formElementDefinition['propertyCollections'][collectionName];
459 assert(!getUtility().isUndefinedOrNull(collection), 'Invalid collection name "' + collectionName + '"', 1475446108);
460 collectionElement = _getRepository().findCollectionElementByIdentifierPath(collectionElementIdentifier, collection);
461 return $.extend(true, {}, collectionElement);
462 } else {
463 return {};
464 }
465 };
466
467 /**
468 * @public
469 *
470 * @param string collectionElementIdentifier
471 * @param string collectionName
472 * @param string formElement
473 * @return int
474 * @throws 1475378557
475 * @throws 1475378558
476 */
477 function getIndexFromPropertyCollectionElement(collectionElementIdentifier, collectionName, formElement) {
478 var indexFromPropertyCollectionElement;
479 if (getUtility().isUndefinedOrNull(formElement)) {
480 formElement = getCurrentlySelectedFormElement();
481 }
482 formElement = _getRepository().findFormElement(formElement);
483
484 assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378557);
485 assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378558);
486
487 indexFromPropertyCollectionElement = _getRepository().getIndexFromPropertyCollectionElementByIdentifier(
488 collectionElementIdentifier,
489 collectionName,
490 formElement
491 );
492
493 return indexFromPropertyCollectionElement;
494 };
495
496 /**
497 * @public
498 *
499 * @param string collectionElementIdentifier
500 * @param string collectionName
501 * @param object formElement
502 * @param object collectionElementConfiguration
503 * @param string referenceCollectionElementIdentifier
504 * @return object
505 */
506 function createAndAddPropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, collectionElementConfiguration, referenceCollectionElementIdentifier) {
507 return addPropertyCollectionElement(createPropertyCollectionElement(collectionElementIdentifier, collectionName, collectionElementConfiguration), collectionName, formElement, referenceCollectionElementIdentifier);
508 };
509
510 /**
511 * @public
512 *
513 * @param object collectionElement
514 * @param string collectionName
515 * @param string|object formElement
516 * @param string referenceCollectionElementIdentifier
517 * @return object
518 * @throws 1475443300
519 * @throws 1475443301
520 */
521 function addPropertyCollectionElement(collectionElement, collectionName, formElement, referenceCollectionElementIdentifier) {
522 var collection;
523 _saveApplicationState();
524
525 if (getUtility().isUndefinedOrNull(formElement)) {
526 formElement = getCurrentlySelectedFormElement();
527 }
528 formElement = _getRepository().findFormElement(formElement);
529
530 assert('object' === $.type(collectionElement), 'Invalid parameter "collectionElement"', 1475443301);
531 assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475443300);
532
533 if (getUtility().isUndefinedOrNull(referenceCollectionElementIdentifier)) {
534 collection = formElement.get(collectionName);
535 if ('array' === $.type(collection) && collection.length > 0) {
536 referenceCollectionElementIdentifier = collection[collection.length - 1]['identifier'];
537 }
538 }
539
540 return _getRepository().addPropertyCollectionElement(
541 collectionElement,
542 collectionName,
543 formElement,
544 referenceCollectionElementIdentifier,
545 false
546 );
547 };
548
549 /**
550 * @public
551 *
552 * @param string collectionElementIdentifier
553 * @param string collectionName
554 * @param object collectionElementConfiguration
555 * @return void
556 * @throws 1475378559
557 * @throws 1475378560
558 */
559 function createPropertyCollectionElement(collectionElementIdentifier, collectionName, collectionElementConfiguration) {
560 assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378559);
561 assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378560);
562 if ('object' !== $.type(collectionElementConfiguration)) {
563 collectionElementConfiguration = {};
564 }
565
566 return _getFactory().createPropertyCollectionElement(collectionElementIdentifier, collectionElementConfiguration, collectionName);
567 };
568
569 /**
570 * @public
571 *
572 * @param string collectionElementIdentifier
573 * @param string collectionName
574 * @param string formElement
575 * @param bool disablePublishersOnSet
576 * @return void
577 * @throws 1475378561
578 * @throws 1475378562
579 */
580 function removePropertyCollectionElement(collectionElementIdentifier, collectionName, formElement, disablePublishersOnSet) {
581 _saveApplicationState();
582
583 if (getUtility().isUndefinedOrNull(formElement)) {
584 formElement = getCurrentlySelectedFormElement();
585 }
586 formElement = _getRepository().findFormElement(formElement);
587
588 assert(getUtility().isNonEmptyString(collectionElementIdentifier), 'Invalid parameter "collectionElementIdentifier"', 1475378561);
589 assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1475378562);
590
591 _getRepository().removePropertyCollectionElementByIdentifier(
592 formElement,
593 collectionElementIdentifier,
594 collectionName,
595 true
596 );
597
598 disablePublishersOnSet = !!disablePublishersOnSet;
599 if (!disablePublishersOnSet) {
600 getPublisherSubscriber().publish('core/formElement/somePropertyChanged', ['__fakeProperty']);
601 }
602 };
603
604 /**
605 * @public
606 *
607 * @param string collectionElementToMove
608 * @param string position
609 * @param string referenceCollectionElement
610 * @param string collectionName
611 * @param object formElement
612 * @param boolean disablePublishersOnSet
613 * @return string
614 * @throws 1477404352
615 * @throws 1477404353
616 * @throws 1477404354
617 * @throws 1477404355
618 */
619 function movePropertyCollectionElement(collectionElementToMove, position, referenceCollectionElement, collectionName, formElement, disablePublishersOnSet) {
620 _saveApplicationState();
621
622 formElement = _getRepository().findFormElement(formElement);
623
624 assert('string' === $.type(collectionElementToMove), 'Invalid parameter "collectionElementToMove"', 1477404352);
625 assert('string' === $.type(referenceCollectionElement), 'Invalid parameter "referenceCollectionElement"', 1477404353);
626 assert('after' === position || 'before' === position, 'Invalid position "' + position + '"', 1477404354);
627 assert(getUtility().isNonEmptyString(collectionName), 'Invalid parameter "collectionName"', 1477404355);
628
629 return _getRepository().movePropertyCollectionElement(collectionElementToMove, position, referenceCollectionElement, collectionName, formElement, disablePublishersOnSet);
630 };
631
632 /**
633 * @public
634 *
635 * @param string elementType
636 * @param string formElementDefinitionKey
637 * @returnmixed
638 * @throws 1475378563
639 */
640 function getFormElementDefinitionByType(elementType, formElementDefinitionKey) {
641 var formElementDefinition;
642 assert(getUtility().isNonEmptyString(elementType), 'Invalid parameter "elementType"', 1475378563);
643
644 formElementDefinition = _getRepository().getFormEditorDefinition('formElements', elementType);
645
646 if (!getUtility().isUndefinedOrNull(formElementDefinitionKey)) {
647 formElementDefinition = formElementDefinition[formElementDefinitionKey];
648 }
649
650 if ('object' === $.type(formElementDefinition) || 'array' === $.type(formElementDefinition)) {
651 return $.extend(true, {}, formElementDefinition);
652 } else {
653 return formElementDefinition;
654 }
655 };
656
657 /**
658 * @public
659 *
660 * @param object formElement
661 * @param string formElementDefinitionKey
662 * @return mixed
663 */
664 function getFormElementDefinition(formElement, formElementDefinitionKey) {
665 formElement = _getRepository().findFormElement(formElement);
666 return getFormElementDefinitionByType(formElement.get('type'), formElementDefinitionKey);
667 };
668
669 /**
670 * @public
671 *
672 * @param string collectionName
673 * @param string collectionElementIdentifier
674 * @return mixed
675 */
676 function getFormEditorDefinition(definitionName, subject) {
677 return _getRepository().getFormEditorDefinition(definitionName, subject);
678 };
679
680 /**
681 * @public
682 *
683 * @param string validatorIdentifier
684 * @return object (dereferenced)
685 * @throws 1475672362
686 */
687 function getFormElementPropertyValidatorDefinition(validatorIdentifier) {
688 var validatorDefinition;
689 assert(getUtility().isNonEmptyString(validatorIdentifier), 'Invalid parameter "validatorIdentifier"', 1475672362);
690
691 validatorDefinition = _getRepository().getFormEditorDefinition('formElementPropertyValidators', validatorIdentifier);
692 return $.extend(true, {}, validatorDefinition);
693 };
694
695 /**
696 * @public
697 *
698 * @return int
699 */
700 function getCurrentlySelectedPageIndex() {
701 return _getApplicationStateStack().getCurrentState('currentlySelectedPageIndex');
702 };
703
704 /**
705 * @public
706 *
707 * @return void
708 */
709 function refreshCurrentlySelectedPageIndex() {
710 _getApplicationStateStack().setCurrentState('currentlySelectedPageIndex', getPageIndexFromFormElement(getCurrentlySelectedFormElement()));
711 };
712
713 /**
714 * @public
715 *
716 * @return object
717 * @throws 1477786068
718 */
719 function getCurrentlySelectedPage() {
720 var currentPage;
721
722 currentPage = _getRepository().getRootFormElement().get('renderables')[getCurrentlySelectedPageIndex()];
723 assert('object' === $.type(currentPage), 'No page found', 1477786068);
724 return currentPage;
725 };
726
727 /**
728 * @public
729 *
730 * @return object
731 */
732 function getLastTopLevelElementOnCurrentPage() {
733 var lastRenderable, renderables;
734
735 renderables = getCurrentlySelectedPage().get('renderables');
736 if (getUtility().isUndefinedOrNull(renderables)) {
737 return undefined;
738 }
739 lastRenderable = renderables[renderables.length - 1];
740 return lastRenderable;
741 };
742
743 /**
744 * @public
745 *
746 * @param object
747 * @return object
748 */
749 function getLastFormElementWithinParentFormElement(formElement) {
750 var lastElement;
751
752 formElement = _getRepository().findFormElement(formElement);
753 if (formElement.get('__identifierPath') === getRootFormElement().get('__identifierPath')) {
754 return formElement;
755 }
756 return formElement.get('__parentRenderable').get('renderables')[formElement.get('__parentRenderable').get('renderables').length - 1];
757 };
758
759 /**
760 * @public
761 *
762 * @param object
763 * @return int
764 */
765 function getPageIndexFromFormElement(formElement) {
766 formElement = _getRepository().findFormElement(formElement);
767
768 return _getRepository().getIndexForEnclosingCompositeFormElementWhichIsOnTopLevelForFormElement(
769 formElement
770 );
771 };
772
773 /**
774 * @public
775 *
776 * @return void
777 */
778 function renderCurrentFormPage() {
779 renderFormPage(getCurrentlySelectedPageIndex());
780 };
781
782 /**
783 * @public
784 *
785 * @param int pageIndex
786 * @return void
787 * @throws 1475446442
788 */
789 function renderFormPage(pageIndex) {
790 assert('number' === $.type(pageIndex), 'Invalid parameter "pageIndex"', 1475446442);
791 _getDataBackend().renderFormDefinitionPage(pageIndex);
792 };
793
794 /**
795 * @public
796 *
797 * @param object formElement
798 * @return object|null
799 */
800 function findEnclosingCompositeFormElementWhichIsNotOnTopLevel(formElement) {
801 return _getRepository().findEnclosingCompositeFormElementWhichIsNotOnTopLevel(
802 _getRepository().findFormElement(formElement)
803 );
804 };
805
806 /**
807 * @public
808 *
809 * @param object formElement
810 * @return object|null
811 */
812 function findEnclosingGridContainerFormElement(formElement) {
813 return _getRepository().findEnclosingGridContainerFormElement(
814 _getRepository().findFormElement(formElement)
815 );
816 };
817
818 /**
819 * @public
820 *
821 * @param object formElement
822 * @return object|null
823 */
824 function findEnclosingGridRowFormElement(formElement) {
825 return _getRepository().findEnclosingGridRowFormElement(
826 _getRepository().findFormElement(formElement)
827 );
828 };
829
830 /**
831 * @public
832 *
833 * @return object
834 */
835 function getNonCompositeNonToplevelFormElements() {
836 return _getRepository().getNonCompositeNonToplevelFormElements();
837 };
838
839 /**
840 * @public
841 *
842 * @return boolean
843 */
844 function isRootFormElementSelected() {
845 return (getCurrentlySelectedFormElement().get('__identifierPath') === getRootFormElement().get('__identifierPath'));
846 };
847
848 /**
849 * @public
850 *
851 * @return object
852 */
853 function getViewModel() {
854 return _viewModel;
855 };
856
857 /**
858 * @public
859 *
860 * @return void
861 */
862 function saveFormDefinition() {
863 _getDataBackend().saveFormDefinition();
864 };
865
866 /**
867 * @private
868 *
869 * @return object
870 */
871 function _getDataBackend() {
872 return _core.getDataBackend();
873 };
874
875 /**
876 * @private
877 *
878 * @return object
879 */
880 function _getFactory() {
881 return _core.getFactory();
882 };
883
884 /**
885 * @private
886 *
887 * @return object
888 */
889 function _getRepository() {
890 return _core.getRepository();
891 };
892
893 /**
894 * @private
895 *
896 * @return object
897 */
898 function _getPropertyValidationService() {
899 return _core.getPropertyValidationService();
900 };
901
902 /**
903 * @public
904 *
905 * @return object
906 */
907 function _getApplicationStateStack() {
908 return _core.getApplicationStateStack();
909 };
910
911 /**
912 * @private
913 *
914 * @return void
915 * @publish ajax/beforeSend
916 * @publish ajax/complete
917 */
918 function _ajaxSetup() {
919 $.ajaxSetup({
920 beforeSend: function() {
921 getPublisherSubscriber().publish('ajax/beforeSend');
922 },
923 complete: function() {
924 getPublisherSubscriber().publish('ajax/complete');
925 }
926 });
927 };
928
929 /**
930 * @private
931 *
932 * @param object endpoints
933 * @param string prototypeName
934 * @param string formPersistenceIdentifier
935 * @return void
936 * @throws 1475379748
937 * @throws 1475379749
938 * @throws 1475927876
939 */
940 function _dataBackendSetup(endpoints, prototypeName, formPersistenceIdentifier) {
941 assert('object' === $.type(endpoints), 'Invalid parameter "endpoints"', 1475379748);
942 assert(getUtility().isNonEmptyString(prototypeName), 'Invalid parameter "prototypeName"', 1475927876);
943 assert(getUtility().isNonEmptyString(formPersistenceIdentifier), 'Invalid parameter "formPersistenceIdentifier"', 1475379749);
944
945 _core.getDataBackend().setEndpoints(endpoints);
946 _core.getDataBackend().setPrototypeName(prototypeName);
947 _core.getDataBackend().setPersistenceIdentifier(formPersistenceIdentifier);
948 };
949
950 /**
951 * @private
952 *
953 * @param object formEditorDefinitions
954 * @return void
955 * @throws 1475379750
956 */
957 function _repositorySetup(formEditorDefinitions) {
958 assert('object' === $.type(formEditorDefinitions), 'Invalid parameter "formEditorDefinitions"', 1475379750);
959
960 _getRepository().setFormEditorDefinitions(formEditorDefinitions);
961 }
962
963 /**
964 * @private
965 *
966 * @param object additionalViewModelModules
967 * @return void
968 * @throws 1475379752
969 * @throws 1475492374
970 */
971 function _viewSetup(additionalViewModelModules) {
972 assert('function' === $.type(_viewModel.bootstrap), 'The view model does not implement the method "bootstrap"', 1475492374);
973
974 if (!getUtility().isUndefinedOrNull(additionalViewModelModules)) {
975 assert('array' === $.type(additionalViewModelModules), 'Invalid parameter "additionalViewModelModules"', 1475379752);
976 } else {
977 additionalViewModelModules = [];
978 }
979 _viewModel.bootstrap(_formEditorInstance, additionalViewModelModules);
980 };
981
982 /**
983 * @private
984 *
985 * @return void
986 * @throws 1475492032
987 */
988 function _mediatorSetup() {
989 assert('function' === $.type(_mediator.bootstrap), 'The mediator does not implement the method "bootstrap"', 1475492032);
990 _mediator.bootstrap(_formEditorInstance, _viewModel);
991 };
992
993 /**
994 * @private
995 *
996 * @param object rootFormElement
997 * @param int maximumUndoSteps
998 * @return void
999 * @throws 1475379751
1000 */
1001 function _applicationStateStackSetup(rootFormElement, maximumUndoSteps) {
1002 assert('object' === $.type(rootFormElement), 'Invalid parameter "rootFormElement"', 1475379751);
1003
1004 if ('number' !== $.type(maximumUndoSteps)) {
1005 maximumUndoSteps = 10;
1006 }
1007 _getApplicationStateStack().setMaximalStackSize(maximumUndoSteps);
1008
1009 _getApplicationStateStack().addAndReset({
1010 currentlySelectedPageIndex: 0,
1011 currentlySelectedFormElementIdentifierPath: rootFormElement['identifier']
1012 }, true);
1013
1014 _getApplicationStateStack().setCurrentState('formDefinition', _getFactory().createFormElement(rootFormElement, undefined, undefined, true));
1015 };
1016
1017 /**
1018 * @private
1019 *
1020 * @return void
1021 */
1022 function _bootstrap() {
1023 _configuration = _configuration || {};
1024
1025 _mediatorSetup();
1026 _ajaxSetup();
1027 _dataBackendSetup(_configuration['endpoints'], _configuration['prototypeName'], _configuration['formPersistenceIdentifier']);
1028 _repositorySetup(_configuration['formEditorDefinitions']);
1029 _applicationStateStackSetup(_configuration['formDefinition'], _configuration['maximumUndoSteps']);
1030 setCurrentlySelectedFormElement(_getRepository().getRootFormElement());
1031
1032 _viewSetup(_configuration['additionalViewModelModules']);
1033 };
1034
1035 /**
1036 * @public
1037 *
1038 * @return TYPO3/CMS/Form/Backend/FormEditor
1039 * @throws 1473200696
1040 */
1041 function run() {
1042 if (_isRunning) {
1043 throw 'You can not run the app twice (1473200696)';
1044 }
1045
1046 _bootstrap();
1047 _isRunning = true;
1048 return this;
1049 };
1050
1051 /**
1052 * Publish the public methods.
1053 * Implements the "Revealing Module Pattern".
1054 */
1055 return {
1056 getRootFormElement: getRootFormElement,
1057
1058 createAndAddFormElement: createAndAddFormElement,
1059 createFormElement: createFormElement,
1060 addFormElement: addFormElement,
1061 moveFormElement: moveFormElement,
1062 removeFormElement: removeFormElement,
1063
1064 getCurrentlySelectedFormElement: getCurrentlySelectedFormElement,
1065 setCurrentlySelectedFormElement: setCurrentlySelectedFormElement,
1066
1067 getFormElementByIdentifierPath: getFormElementByIdentifierPath,
1068 isFormElementIdentifierUsed: isFormElementIdentifierUsed,
1069
1070 createAndAddPropertyCollectionElement: createAndAddPropertyCollectionElement,
1071 createPropertyCollectionElement: createPropertyCollectionElement,
1072 addPropertyCollectionElement: addPropertyCollectionElement,
1073 removePropertyCollectionElement: removePropertyCollectionElement,
1074 movePropertyCollectionElement: movePropertyCollectionElement,
1075 getIndexFromPropertyCollectionElement: getIndexFromPropertyCollectionElement,
1076 getPropertyCollectionElementConfiguration: getPropertyCollectionElementConfiguration,
1077
1078 saveFormDefinition: saveFormDefinition,
1079 renderCurrentFormPage: renderCurrentFormPage,
1080 renderFormPage: renderFormPage,
1081
1082 getCurrentlySelectedPageIndex: getCurrentlySelectedPageIndex,
1083 refreshCurrentlySelectedPageIndex: refreshCurrentlySelectedPageIndex,
1084 getPageIndexFromFormElement: getPageIndexFromFormElement,
1085 getCurrentlySelectedPage: getCurrentlySelectedPage,
1086 getLastTopLevelElementOnCurrentPage: getLastTopLevelElementOnCurrentPage,
1087 findEnclosingCompositeFormElementWhichIsNotOnTopLevel: findEnclosingCompositeFormElementWhichIsNotOnTopLevel,
1088 findEnclosingGridContainerFormElement: findEnclosingGridContainerFormElement,
1089 findEnclosingGridRowFormElement: findEnclosingGridRowFormElement,
1090 isRootFormElementSelected: isRootFormElementSelected,
1091 getLastFormElementWithinParentFormElement: getLastFormElementWithinParentFormElement,
1092 getNonCompositeNonToplevelFormElements: getNonCompositeNonToplevelFormElements,
1093
1094 getFormElementDefinitionByType: getFormElementDefinitionByType,
1095 getFormElementDefinition: getFormElementDefinition,
1096 getFormElementPropertyValidatorDefinition: getFormElementPropertyValidatorDefinition,
1097 getFormEditorDefinition: getFormEditorDefinition,
1098
1099 getPublisherSubscriber: getPublisherSubscriber,
1100 getRunningAjaxRequest: getRunningAjaxRequest,
1101
1102 setUnsavedContent: setUnsavedContent,
1103 getUnsavedContent: getUnsavedContent,
1104
1105 addPropertyValidationValidator: addPropertyValidationValidator,
1106 validateFormElementProperty: validateFormElementProperty,
1107 validateCurrentlySelectedFormElementProperty: validateCurrentlySelectedFormElementProperty,
1108 validateFormElement: validateFormElement,
1109 validateFormElementRecursive: validateFormElementRecursive,
1110 validationResultsHasErrors: validationResultsHasErrors,
1111
1112 getUtility: getUtility,
1113 assert: assert,
1114 buildPropertyPath: buildPropertyPath,
1115
1116 getViewModel: getViewModel,
1117 undoApplicationState: undoApplicationState,
1118 redoApplicationState: redoApplicationState,
1119 getMaximalApplicationStates: getMaximalApplicationStates,
1120 getCurrentApplicationStates: getCurrentApplicationStates,
1121 getCurrentApplicationStatePosition: getCurrentApplicationStatePosition,
1122
1123 run: run
1124 };
1125 };
1126
1127 /**
1128 * Emulation of static methods
1129 */
1130 return {
1131 /**
1132 * @public
1133 * @static
1134 *
1135 * Implement the "Singleton Pattern".
1136 *
1137 * Return a singleton instance of a
1138 * "FormEditor" object.
1139 *
1140 * @param object configuration
1141 * @param object mediator
1142 * @param object viewModel
1143 * @return object
1144 */
1145 getInstance: function(configuration, mediator, viewModel) {
1146 if (_formEditorInstance === null) {
1147 _formEditorInstance = new FormEditor(configuration, mediator, viewModel);
1148 }
1149 return _formEditorInstance;
1150 }
1151 };
1152 })(core);
1153 });