e6ba2da4f9ebc10b2b3b8cfb03b43b80f3838b82
[Packages/TYPO3.CMS.git] / typo3 / sysext / form / Resources / Public / JavaScript / Backend / FormEditor / InspectorComponent.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/InspectorComponent
16 */
17
18 /**
19 * Add legacy functions to be accessible in the global scope.
20 * This is needed by TYPO3/CMS/Recordlist/ElementBrowser
21 */
22 var setFormValueFromBrowseWin;
23
24 define(['jquery',
25 'TYPO3/CMS/Form/Backend/FormEditor/Helper',
26 'TYPO3/CMS/Backend/Icons',
27 'TYPO3/CMS/Backend/Notification',
28 'TYPO3/CMS/Backend/Modal',
29 'TYPO3/CMS/Form/Backend/Contrib/jquery.mjs.nestedSortable'
30 ], function($, Helper, Icons, Notification, Modal) {
31 'use strict';
32
33 return (function($, Helper, Icons, Notification) {
34
35 /**
36 * @private
37 *
38 * @var object
39 */
40 var _configuration = null;
41
42 /**
43 * @private
44 *
45 * @var object
46 */
47 var _defaultConfiguration = {
48 domElementClassNames: {
49 buttonFormElementRemove: 't3-form-remove-element-button',
50 collectionElement: 't3-form-collection-element',
51 finisherEditorPrefix: 't3-form-inspector-finishers-editor-',
52 inspectorEditor: 'form-editor',
53 inspectorInputGroup: 'input-group',
54 validatorEditorPrefix: 't3-form-inspector-validators-editor-'
55 },
56 domElementDataAttributeNames: {
57 contentElementSelectorTarget: 'data-insert-target',
58 finisher: 'data-finisher-identifier',
59 validator: 'data-validator-identifier',
60 randomId: 'data-random-id',
61 randomIdTarget: 'data-random-id-attribute',
62 randomIdIndex: 'data-random-id-number'
63 },
64 domElementDataAttributeValues: {
65 collapse: 'actions-view-table-expand',
66 editorControlsInputGroup: 'inspectorEditorControlsGroup',
67 editorWrapper: 'editorWrapper',
68 editorControlsWrapper: 'inspectorEditorControlsWrapper',
69 formElementHeaderEditor: 'inspectorFormElementHeaderEditor',
70 formElementSelectorControlsWrapper: 'inspectorEditorFormElementSelectorControlsWrapper',
71 formElementSelectorSplitButtonContainer: 'inspectorEditorFormElementSelectorSplitButtonContainer',
72 formElementSelectorSplitButtonListContainer: 'inspectorEditorFormElementSelectorSplitButtonListContainer',
73 iconNotAvailable: 'actions-close',
74 iconPage: 'apps-pagetree-page-default',
75 iconTtContent: 'mimetypes-x-content-text',
76 inspector: 'inspector',
77 'Inspector-CheckboxEditor': 'Inspector-CheckboxEditor',
78 'Inspector-CollectionElementHeaderEditor': 'Inspector-CollectionElementHeaderEditor',
79 'Inspector-FinishersEditor': 'Inspector-FinishersEditor',
80 'Inspector-FormElementHeaderEditor': 'Inspector-FormElementHeaderEditor',
81 'Inspector-PropertyGridEditor': 'Inspector-PropertyGridEditor',
82 'Inspector-RemoveElementEditor': 'Inspector-RemoveElementEditor',
83 'Inspector-RequiredValidatorEditor': 'Inspector-RequiredValidatorEditor',
84 'Inspector-SingleSelectEditor': 'Inspector-SingleSelectEditor',
85 'Inspector-MultiSelectEditor': 'Inspector-MultiSelectEditor',
86 'Inspector-GridColumnViewPortConfigurationEditor': 'Inspector-GridColumnViewPortConfigurationEditor',
87 'Inspector-TextareaEditor': 'Inspector-TextareaEditor',
88 'Inspector-TextEditor': 'Inspector-TextEditor',
89 'Inspector-Typo3WinBrowserEditor': 'Inspector-Typo3WinBrowserEditor',
90 'Inspector-ValidatorsEditor': 'Inspector-ValidatorsEditor',
91 'Inspector-ValidationErrorMessageEditor': 'Inspector-ValidationErrorMessageEditor',
92
93 inspectorFinishers: 'inspectorFinishers',
94 inspectorValidators: 'inspectorValidators',
95 propertyGridEditorAddRow: 'addRow',
96 propertyGridEditorAddRowItem: 'addRowItem',
97 propertyGridEditorContainer: 'propertyGridContainer',
98 propertyGridEditorDeleteRow: 'deleteRow',
99 propertyGridEditorLabel: 'label',
100 propertyGridEditorRowItem: 'rowItem',
101 propertyGridEditorSelectValue: 'selectValue',
102 propertyGridEditorSortRow: 'sortRow',
103 propertyGridEditorValue: 'value',
104 viewportButton: 'viewportButton'
105 },
106 domElementIdNames: {
107 finisherPrefix: 't3-form-inspector-finishers-',
108 validatorPrefix: 't3-form-inspector-validators-'
109 },
110 isSortable: true
111 };
112
113 /**
114 * @private
115 *
116 * @var object
117 */
118 var _formEditorApp = null;
119
120 /* *************************************************************
121 * Private Methodes
122 * ************************************************************/
123
124 /**
125 * @private
126 *
127 * @return void
128 * @throws 1478268638
129 */
130 function _helperSetup() {
131 assert('function' === $.type(Helper.bootstrap),
132 'The view model helper does not implement the method "bootstrap"',
133 1478268638
134 );
135 Helper.bootstrap(getFormEditorApp());
136 };
137
138 /**
139 * @private
140 *
141 * @return object
142 */
143 function getFormEditorApp() {
144 return _formEditorApp;
145 };
146
147 /**
148 * @private
149 *
150 * @return object
151 */
152 function getViewModel() {
153 return getFormEditorApp().getViewModel();
154 };
155
156 /**
157 * @private
158 *
159 * @param object
160 * @return object
161 */
162 function getHelper(configuration) {
163 if (getUtility().isUndefinedOrNull(configuration)) {
164 return Helper.setConfiguration(_configuration);
165 }
166 return Helper.setConfiguration(configuration);
167 };
168
169 /**
170 * @private
171 *
172 * @return object
173 */
174 function getUtility() {
175 return getFormEditorApp().getUtility();
176 };
177
178 /**
179 * @private
180 *
181 * @param mixed test
182 * @param string message
183 * @param int messageCode
184 * @return void
185 */
186 function assert(test, message, messageCode) {
187 return getFormEditorApp().assert(test, message, messageCode);
188 };
189
190 /**
191 * @private
192 *
193 * @return object
194 */
195 function getCurrentlySelectedFormElement() {
196 return getFormEditorApp().getCurrentlySelectedFormElement();
197 };
198
199 /**
200 * @private
201 *
202 * @return object
203 */
204 function getRootFormElement() {
205 return getFormEditorApp().getRootFormElement();
206 };
207
208 /**
209 * @private
210 *
211 * @return object
212 */
213 function getPublisherSubscriber() {
214 return getFormEditorApp().getPublisherSubscriber();
215 };
216
217 /**
218 * @private
219 *
220 * @param object
221 * @param string
222 * @return mixed
223 */
224 function getFormElementDefinition(formElement, formElementDefinitionKey) {
225 return getFormEditorApp().getFormElementDefinition(formElement, formElementDefinitionKey);
226 };
227
228 /**
229 * @private
230 *
231 * @param object
232 * @param object
233 * @param string
234 * @param string
235 * @return void
236 * @publish view/inspector/editor/insert/perform
237 */
238 function _renderEditorDispatcher(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
239 switch (editorConfiguration['templateName']) {
240 case 'Inspector-FormElementHeaderEditor':
241 renderFormElementHeaderEditor(
242 editorConfiguration,
243 editorHtml,
244 collectionElementIdentifier,
245 collectionName
246 );
247 break;
248 case 'Inspector-CollectionElementHeaderEditor':
249 renderCollectionElementHeaderEditor(
250 editorConfiguration,
251 editorHtml,
252 collectionElementIdentifier,
253 collectionName
254 );
255 break;
256 case 'Inspector-TextEditor':
257 renderTextEditor(
258 editorConfiguration,
259 editorHtml,
260 collectionElementIdentifier,
261 collectionName
262 );
263 break;
264 case 'Inspector-FinishersEditor':
265 renderCollectionElementSelectionEditor(
266 'finishers',
267 editorConfiguration,
268 editorHtml,
269 collectionElementIdentifier,
270 collectionName
271 );
272 break;
273 case 'Inspector-ValidatorsEditor':
274 renderCollectionElementSelectionEditor(
275 'validators',
276 editorConfiguration,
277 editorHtml,
278 collectionElementIdentifier,
279 collectionName
280 );
281 break;
282 case 'Inspector-ValidationErrorMessageEditor':
283 renderValidationErrorMessageEditor(
284 editorConfiguration,
285 editorHtml,
286 collectionElementIdentifier,
287 collectionName
288 );
289 break;
290 case 'Inspector-RemoveElementEditor':
291 renderRemoveElementEditor(
292 editorConfiguration,
293 editorHtml,
294 collectionElementIdentifier,
295 collectionName
296 );
297 break;
298 case 'Inspector-RequiredValidatorEditor':
299 renderRequiredValidatorEditor(
300 editorConfiguration,
301 editorHtml,
302 collectionElementIdentifier,
303 collectionName
304 );
305 break;
306 case 'Inspector-CheckboxEditor':
307 renderCheckboxEditor(
308 editorConfiguration,
309 editorHtml,
310 collectionElementIdentifier,
311 collectionName
312 );
313 break;
314 case 'Inspector-SingleSelectEditor':
315 renderSingleSelectEditor(
316 editorConfiguration,
317 editorHtml,
318 collectionElementIdentifier,
319 collectionName
320 );
321 break;
322 case 'Inspector-MultiSelectEditor':
323 renderMultiSelectEditor(
324 editorConfiguration,
325 editorHtml,
326 collectionElementIdentifier,
327 collectionName
328 );
329 break;
330 case 'Inspector-GridColumnViewPortConfigurationEditor':
331 renderGridColumnViewPortConfigurationEditor(
332 editorConfiguration,
333 editorHtml,
334 collectionElementIdentifier,
335 collectionName
336 );
337 break;
338 case 'Inspector-PropertyGridEditor':
339 renderPropertyGridEditor(
340 editorConfiguration,
341 editorHtml,
342 collectionElementIdentifier,
343 collectionName
344 );
345 break;
346 case 'Inspector-TextareaEditor':
347 renderTextareaEditor(
348 editorConfiguration,
349 editorHtml,
350 collectionElementIdentifier,
351 collectionName
352 );
353 break;
354 case 'Inspector-Typo3WinBrowserEditor':
355 renderTypo3WinBrowserEditor(
356 editorConfiguration,
357 editorHtml,
358 collectionElementIdentifier,
359 collectionName
360 );
361 break;
362 }
363 getPublisherSubscriber().publish('view/inspector/editor/insert/perform', [
364 editorConfiguration, editorHtml, collectionElementIdentifier, collectionName
365 ]);
366 };
367
368 /**
369 * @private
370 *
371 * opens a popup window with the element browser
372 *
373 * @param string mode
374 * @param string params
375 */
376 function _openTypo3WinBrowser(mode, params) {
377 Modal.advanced({
378 type: Modal.types.iframe,
379 content: TYPO3.settings.FormEditor.typo3WinBrowserUrl + '&mode=' + mode + '&bparams=' + params,
380 size: Modal.sizes.large
381 });
382 };
383
384 /**
385 * @private
386 *
387 * @param string
388 * @param string
389 * @return object
390 */
391 function _getCollectionElementClass(collectionName, collectionElementIdentifier) {
392 if (collectionName === 'finishers') {
393 return getHelper()
394 .getDomElementClassName('finisherEditorPrefix') + collectionElementIdentifier;
395 } else {
396 return getHelper()
397 .getDomElementClassName('validatorEditorPrefix') + collectionElementIdentifier;
398 }
399 };
400
401 /**
402 * @private
403 *
404 * @param string
405 * @param string
406 * @param bool
407 * @return object
408 */
409 function _getCollectionElementId(collectionName, collectionElementIdentifier, asSelector) {
410 if (collectionName === 'finishers') {
411 return getHelper()
412 .getDomElementIdName('finisherPrefix', asSelector) + collectionElementIdentifier;
413 } else {
414 return getHelper()
415 .getDomElementIdName('validatorPrefix', asSelector) + collectionElementIdentifier;
416 }
417 };
418
419 /**
420 * @private
421 *
422 * @param object
423 * @param string
424 * @return void
425 */
426 function _addSortableCollectionElementsEvents(sortableDomElement, collectionName) {
427 sortableDomElement.addClass(getHelper().getDomElementClassName('sortable')).sortable({
428 revert: 'true',
429 items: getHelper().getDomElementClassName('collectionElement', true),
430 cancel: getHelper().getDomElementClassName('jQueryUiStateDisabled', true) + ',input,textarea,select',
431 delay: 200,
432 update: function(e, o) {
433 var dataAttributeName, nextCollectionElementIdentifier, movedCollectionElementIdentifier,
434 previousCollectionElementIdentifier;
435
436 if (collectionName === 'finishers') {
437 dataAttributeName = getHelper().getDomElementDataAttribute('finisher');
438 } else {
439 dataAttributeName = getHelper().getDomElementDataAttribute('validator');
440 }
441
442 movedCollectionElementIdentifier = $(o.item).attr(dataAttributeName);
443 previousCollectionElementIdentifier = $(o.item)
444 .prevAll(getHelper().getDomElementClassName('collectionElement', true))
445 .first()
446 .attr(dataAttributeName);
447 nextCollectionElementIdentifier = $(o.item)
448 .nextAll(getHelper().getDomElementClassName('collectionElement', true))
449 .first()
450 .attr(dataAttributeName);
451
452 getPublisherSubscriber().publish('view/inspector/collectionElements/dnd/update', [
453 movedCollectionElementIdentifier,
454 previousCollectionElementIdentifier,
455 nextCollectionElementIdentifier,
456 collectionName
457 ]);
458 }
459 });
460 };
461
462 /**
463 * @private
464 *
465 * @param object editorHtml
466 * @param bool multiSelection
467 * @param string propertyPath
468 * @param string propertyPathPrefix
469 * @return void
470 */
471 function _setPropertyGridData(editorHtml, multiSelection, propertyPath, propertyPathPrefix) {
472 var defaultValue, newPropertyData;
473
474 if (multiSelection) {
475 defaultValue = [];
476
477 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' +
478 getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked',
479 $(editorHtml)
480 ).each(function(i) {
481 defaultValue.push(
482 $(this)
483 .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'))
484 .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'))
485 .val()
486 );
487 });
488 getCurrentlySelectedFormElement().set(propertyPathPrefix + 'defaultValue', defaultValue);
489 } else {
490 getCurrentlySelectedFormElement().set(
491 propertyPathPrefix + 'defaultValue',
492 $(
493 getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' +
494 getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked',
495 $(editorHtml)
496 ).first()
497 .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'))
498 .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'))
499 .val(),
500 true
501 );
502 }
503
504 newPropertyData = [];
505 $(
506 getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer') + ' ' +
507 getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'),
508 $(editorHtml)
509 ).each(function(i) {
510 var value, label, tmpObject;
511
512 value = $(this)
513 .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'))
514 .val();
515 label = $(this)
516 .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'))
517 .val();
518
519 if ('' === value) {
520 value = label;
521 }
522
523 tmpObject = {};
524 tmpObject[value] = label;
525 newPropertyData.push({
526 _label: label,
527 _value: value
528 });
529 });
530
531 getCurrentlySelectedFormElement().set(propertyPathPrefix + propertyPath, newPropertyData);
532 };
533
534 /**
535 * @private
536 *
537 * @param object
538 * @return object
539 */
540 function _getEditorWrapperDomElement(editorDomElement) {
541 return $(getHelper().getDomElementDataIdentifierSelector('editorWrapper'), $(editorDomElement));
542 };
543
544 /**
545 * @private
546 *
547 * @param object
548 * @return object
549 */
550 function _getEditorControlsWrapperDomElement(editorDomElement) {
551 return $(getHelper().getDomElementDataIdentifierSelector('editorControlsWrapper'), $(editorDomElement));
552 };
553
554 /**
555 * @private
556 *
557 * @param string
558 * @param object
559 * @return void
560 */
561 function _validateCollectionElement(propertyPath, editorHtml) {
562 var hasError, propertyPrefix, validationResults;
563
564 validationResults = getFormEditorApp().validateCurrentlySelectedFormElementProperty(propertyPath);
565
566 if (validationResults.length > 0) {
567 getHelper()
568 .getTemplatePropertyDomElement('validationErrors', editorHtml)
569 .text(validationResults[0]);
570 getViewModel().setElementValidationErrorClass(
571 getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml)
572 );
573 getViewModel().setElementValidationErrorClass(
574 _getEditorControlsWrapperDomElement(editorHtml),
575 'hasError'
576 );
577 } else {
578 getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml).text('');
579 getViewModel().removeElementValidationErrorClass(
580 getHelper().getTemplatePropertyDomElement('validationErrors', editorHtml)
581 );
582 getViewModel().removeElementValidationErrorClass(
583 _getEditorControlsWrapperDomElement(editorHtml),
584 'hasError'
585 );
586 }
587
588 validationResults = getFormEditorApp().validateFormElement(getCurrentlySelectedFormElement());
589 propertyPrefix = propertyPath.split('.');
590 propertyPrefix = propertyPrefix[0] + '.' + propertyPrefix[1];
591
592 hasError = false;
593 for (var i = 0, len = validationResults.length; i < len; ++i) {
594 if (
595 validationResults[i]['propertyPath'].indexOf(propertyPrefix, 0) === 0
596 && validationResults[i]['validationResults']
597 && validationResults[i]['validationResults'].length > 0
598 ) {
599 hasError = true;
600 break;
601 }
602 }
603
604 if (hasError) {
605 getViewModel().setElementValidationErrorClass(
606 _getEditorControlsWrapperDomElement(editorHtml).closest(getHelper().getDomElementClassName('collectionElement', true))
607 );
608 } else {
609 getViewModel().removeElementValidationErrorClass(
610 _getEditorControlsWrapperDomElement(editorHtml).closest(getHelper().getDomElementClassName('collectionElement', true))
611 );
612 }
613 };
614
615 /**
616 * @private
617 *
618 * @param object
619 * @param object
620 * @return null|string
621 * @throws 1489932939
622 * @throws 1489932940
623 */
624 function _getFirstAvailableValidationErrorMessage(errorCodes, propertyData) {
625 assert(
626 'array' === $.type(errorCodes),
627 'Invalid configuration "errorCodes"',
628 1489932939
629 );
630 assert(
631 'array' === $.type(propertyData),
632 'Invalid configuration "propertyData"',
633 1489932940
634 );
635
636 for (var i = 0, len1 = errorCodes.length; i < len1; ++i) {
637 for (var j = 0, len2 = propertyData.length; j < len2; ++j) {
638 if (parseInt(errorCodes[i]) === parseInt(propertyData[j]['code'])) {
639 if (getUtility().isNonEmptyString(propertyData[j]['message'])) {
640 return propertyData[j]['message'];
641 }
642 }
643 }
644 }
645
646 return null;
647 };
648
649 /**
650 * @private
651 *
652 * @param object
653 * @param object
654 * @param string
655 * @return object
656 * @throws 1489932942
657 */
658 function _renewValidationErrorMessages(errorCodes, propertyData, value) {
659 var errorCodeSubset;
660
661 assert(
662 'array' === $.type(propertyData),
663 'Invalid configuration "propertyData"',
664 1489932942
665 );
666
667 if (
668 !getUtility().isUndefinedOrNull(errorCodes)
669 && 'array' === $.type(errorCodes)
670 ) {
671 errorCodeSubset = [];
672 for (var i = 0, len1 = errorCodes.length; i < len1; ++i) {
673 var errorCodeFound = false;
674
675 for (var j = 0, len2 = propertyData.length; j < len2; ++j) {
676 if (parseInt(errorCodes[i]) === parseInt(propertyData[j]['code'])) {
677 errorCodeFound = true;
678 if (getUtility().isNonEmptyString(value)) {
679 // error code exists and should be updated because message is not empty
680 propertyData[j]['message'] = value;
681 } else {
682 // error code exists but should be removed because message is empty
683 propertyData.splice(j, 1);
684 --len2;
685 }
686 }
687 }
688
689 if (!errorCodeFound) {
690 // add new codes because message is not empty
691 if (getUtility().isNonEmptyString(value)) {
692 errorCodeSubset.push({
693 code: errorCodes[i],
694 message: value
695 });
696 }
697 }
698 }
699
700 propertyData = propertyData.concat(errorCodeSubset);
701 }
702
703 return propertyData;
704 };
705
706 /**
707 * @private
708 *
709 * @param object
710 * @throws 1523904699
711 */
712 function _setRandomIds(html) {
713 assert(
714 'object' === $.type(html),
715 'Invalid input "html"',
716 1523904699
717 );
718
719 $(getHelper().getDomElementClassName('inspectorEditor', true)).each(function(e) {
720 var $parent = $(this),
721 idReplacements = {};
722
723 $(getHelper().getDomElementDataAttribute('randomId', 'bracesWithKey'), $parent).each(function(e) {
724 var $element = $(this),
725 targetAttribute = $element.attr(getHelper().getDomElementDataAttribute('randomIdTarget')),
726 randomIdIndex = $element.attr(getHelper().getDomElementDataAttribute('randomIdIndex'));
727
728 if ($element.is('[' + targetAttribute + ']')) {
729 return true;
730 }
731
732 if (!idReplacements.hasOwnProperty(randomIdIndex)) {
733 idReplacements[randomIdIndex] = 'fe' + Math.floor(Math.random() * 42) + Date.now();
734 }
735 $element.attr(targetAttribute, idReplacements[randomIdIndex]);
736 });
737 });
738 };
739
740 /* *************************************************************
741 * Public Methodes
742 * ************************************************************/
743
744 /**
745 * @public
746 *
747 * callback from TYPO3/CMS/Recordlist/ElementBrowser
748 *
749 * @param string fieldReference
750 * @param string elValue
751 * @param string elName
752 * @return void
753 */
754 setFormValueFromBrowseWin = function(fieldReference, elValue, elName) {
755 var result;
756 result = elValue.split('_');
757
758 $(getHelper().getDomElementDataAttribute('contentElementSelectorTarget', 'bracesWithKeyValue', [fieldReference]))
759 .val(result.pop())
760 .trigger('paste');
761 };
762
763 /**
764 * @public
765 *
766 * @return object
767 */
768 function getInspectorDomElement() {
769 return $(getHelper().getDomElementDataIdentifierSelector('inspector'));
770 };
771
772 /**
773 * @public
774 *
775 * @return object
776 */
777 function getFinishersContainerDomElement() {
778 return $(getHelper().getDomElementDataIdentifierSelector('inspectorFinishers'), getInspectorDomElement());
779 };
780
781 /**
782 * @public
783 *
784 * @return object
785 */
786 function getValidatorsContainerDomElement() {
787 return $(getHelper().getDomElementDataIdentifierSelector('inspectorValidators'), getInspectorDomElement());
788 };
789
790 /**
791 * @public
792 *
793 * @param string
794 * @param string
795 * @return object
796 */
797 function getCollectionElementDomElement(collectionName, collectionElementIdentifier) {
798 if (collectionName === 'finishers') {
799 return $(getHelper().getDomElementDataAttribute(
800 'finisher',
801 'bracesWithKeyValue',
802 [collectionElementIdentifier]
803 ), getFinishersContainerDomElement());
804 } else {
805 return $(getHelper().getDomElementDataAttribute(
806 'validator',
807 'bracesWithKeyValue',
808 [collectionElementIdentifier]
809 ), getValidatorsContainerDomElement());
810 }
811 };
812
813 /**
814 * @public
815 *
816 * @param object
817 * @param function
818 * @return void
819 */
820 function renderEditors(formElement, callback) {
821 var formElementTypeDefinition;
822 if (getUtility().isUndefinedOrNull(formElement)) {
823 formElement = getCurrentlySelectedFormElement();
824 }
825
826 getInspectorDomElement().off().empty();
827
828 formElementTypeDefinition = getFormElementDefinition(formElement);
829 if ('array' !== $.type(formElementTypeDefinition['editors'])) {
830 return;
831 }
832
833 for (var i = 0, len = formElementTypeDefinition['editors'].length; i < len; ++i) {
834 var html, template;
835
836 template = getHelper()
837 .getTemplate(formElementTypeDefinition['editors'][i]['templateName'])
838 .clone();
839 if (!template.length) {
840 continue;
841 }
842 html = $(template.html());
843
844 $(html)
845 .first()
846 .addClass(getHelper().getDomElementClassName('inspectorEditor'));
847 getInspectorDomElement().append($(html));
848
849 _setRandomIds(html);
850 _renderEditorDispatcher(formElementTypeDefinition['editors'][i], html);
851 }
852
853 if ('function' === $.type(callback)) {
854 callback();
855 }
856 };
857
858 /**
859 * @public
860 *
861 * @param string collectionName
862 * @param string collectionElementIdentifier
863 * @return void
864 * @publish view/inspector/collectionElements/dnd/update
865 * @throws 1478354853
866 * @throws 1478354854
867 */
868 function renderCollectionElementEditors(collectionName, collectionElementIdentifier) {
869 var collapseWrapper, collectionContainer, collectionContainerElementWrapper,
870 collectionElementConfiguration, collectionElementEditorsLength;
871
872 assert(
873 getUtility().isNonEmptyString(collectionName),
874 'Invalid parameter "collectionName"',
875 1478354853
876 );
877 assert(
878 getUtility().isNonEmptyString(collectionElementIdentifier),
879 'Invalid parameter "collectionElementIdentifier"',
880 1478354854
881 );
882
883 collectionElementConfiguration = getFormEditorApp().getPropertyCollectionElementConfiguration(
884 collectionElementIdentifier,
885 collectionName
886 );
887 if ('array' !== $.type(collectionElementConfiguration['editors'])) {
888 return;
889 }
890
891 collectionContainerElementWrapper = $('<div></div>').addClass(getHelper().getDomElementClassName('collectionElement'));
892 if (collectionName === 'finishers') {
893 collectionContainer = getFinishersContainerDomElement();
894 collectionContainerElementWrapper
895 .attr(getHelper().getDomElementDataAttribute('finisher'), collectionElementIdentifier);
896 } else {
897 collectionContainer = getValidatorsContainerDomElement();
898 collectionContainerElementWrapper
899 .attr(getHelper().getDomElementDataAttribute('validator'), collectionElementIdentifier);
900 }
901 collectionContainer.append(collectionContainerElementWrapper);
902
903 collectionElementEditorsLength = collectionElementConfiguration['editors'].length;
904 if (
905 collectionElementEditorsLength > 0
906 && collectionElementConfiguration['editors'][0]['identifier'] === 'header'
907 ) {
908 collapseWrapper = $('<div role="tabpanel"></div>')
909 .addClass('panel-collapse collapse')
910 .prop('id', _getCollectionElementId(
911 collectionName,
912 collectionElementIdentifier
913 ));
914 }
915
916 for (var i = 0; i < collectionElementEditorsLength; ++i) {
917 var html, template;
918
919 template = getHelper()
920 .getTemplate(collectionElementConfiguration['editors'][i]['templateName'])
921 .clone();
922 if (!template.length) {
923 continue;
924 }
925 html = $(template.html());
926
927 $(html).first()
928 .addClass(_getCollectionElementClass(
929 collectionName,
930 collectionElementConfiguration['editors'][i]['identifier']
931 ))
932 .addClass(getHelper().getDomElementClassName('inspectorEditor'));
933
934 if (i === 0 && collapseWrapper) {
935 getCollectionElementDomElement(collectionName, collectionElementIdentifier)
936 .append(html)
937 .append(collapseWrapper);
938 } else if (
939 i === (collectionElementEditorsLength - 1)
940 && collapseWrapper
941 && collectionElementConfiguration['editors'][i]['identifier'] === 'removeButton'
942 ) {
943 getCollectionElementDomElement(collectionName, collectionElementIdentifier).append(html);
944 } else if (i > 0 && collapseWrapper) {
945 collapseWrapper.append(html);
946 } else {
947 getCollectionElementDomElement(collectionName, collectionElementIdentifier).append(html);
948 }
949
950 _setRandomIds(html);
951 _renderEditorDispatcher(
952 collectionElementConfiguration['editors'][i],
953 html,
954 collectionElementIdentifier,
955 collectionName
956 );
957 }
958
959 if (
960 (
961 collectionElementEditorsLength === 2
962 && collectionElementConfiguration['editors'][0]['identifier'] === 'header'
963 && collectionElementConfiguration['editors'][1]['identifier'] === 'removeButton'
964 ) || (
965 collectionElementEditorsLength === 1
966 && collectionElementConfiguration['editors'][0]['identifier'] === 'header'
967 )
968 ) {
969 $(getHelper().getDomElementDataIdentifierSelector('collapse'), collectionContainerElementWrapper).remove();
970 }
971
972 if (_configuration['isSortable']) {
973 _addSortableCollectionElementsEvents(collectionContainer, collectionName);
974 }
975 };
976
977 /**
978 * @public
979 *
980 * @string collectionName
981 * @param object editorConfiguration
982 * @param object editorHtml
983 * @return void
984 * @publish view/inspector/collectionElement/existing/selected
985 * @publish view/inspector/collectionElement/new/selected
986 * @throws 1475423098
987 * @throws 1475423099
988 * @throws 1475423100
989 * @throws 1475423101
990 * @throws 1478362968
991 */
992 function renderCollectionElementSelectionEditor(collectionName, editorConfiguration, editorHtml) {
993 var alreadySelectedCollectionElements, selectElement, collectionContainer,
994 removeSelectElement;
995 assert(
996 getUtility().isNonEmptyString(collectionName),
997 'Invalid configuration "collectionName"',
998 1478362968
999 );
1000 assert(
1001 'object' === $.type(editorConfiguration),
1002 'Invalid parameter "editorConfiguration"',
1003 1475423098
1004 );
1005 assert(
1006 'object' === $.type(editorHtml),
1007 'Invalid parameter "editorHtml"',
1008 1475423099
1009 );
1010 assert(
1011 getUtility().isNonEmptyString(editorConfiguration['label']),
1012 'Invalid configuration "label"',
1013 1475423100
1014 );
1015 assert(
1016 'array' === $.type(editorConfiguration['selectOptions']),
1017 'Invalid configuration "selectOptions"',
1018 1475423101
1019 );
1020
1021 if (collectionName === 'finishers') {
1022 collectionContainer = getFinishersContainerDomElement();
1023 alreadySelectedCollectionElements = getRootFormElement().get(collectionName);
1024 } else {
1025 collectionContainer = getValidatorsContainerDomElement();
1026 alreadySelectedCollectionElements = getCurrentlySelectedFormElement().get(collectionName);
1027 }
1028
1029 collectionContainer.off().empty();
1030
1031 getHelper().getTemplatePropertyDomElement('label', editorHtml).text(editorConfiguration['label']);
1032 selectElement = getHelper().getTemplatePropertyDomElement('selectOptions', editorHtml);
1033
1034 if (!getUtility().isUndefinedOrNull(alreadySelectedCollectionElements)) {
1035 for (var i = 0, len = alreadySelectedCollectionElements.length; i < len; ++i) {
1036 getPublisherSubscriber().publish('view/inspector/collectionElement/existing/selected', [
1037 alreadySelectedCollectionElements[i]['identifier'],
1038 collectionName
1039 ]);
1040 }
1041 }
1042
1043 removeSelectElement = true;
1044 for (var i = 0, len1 = editorConfiguration['selectOptions'].length; i < len1; ++i) {
1045 var appendOption = true;
1046 if (!getUtility().isUndefinedOrNull(alreadySelectedCollectionElements)) {
1047 for (var j = 0, len2 = alreadySelectedCollectionElements.length; j < len2; ++j) {
1048 if (alreadySelectedCollectionElements[j]['identifier'] === editorConfiguration['selectOptions'][i]['value']) {
1049 appendOption = false;
1050 break;
1051 }
1052 }
1053 }
1054 if (appendOption) {
1055 selectElement.append(new Option(
1056 editorConfiguration['selectOptions'][i]['label'],
1057 editorConfiguration['selectOptions'][i]['value']
1058 ));
1059 if (editorConfiguration['selectOptions'][i]['value'] !== '') {
1060 removeSelectElement = false;
1061 }
1062 }
1063 }
1064
1065 if (removeSelectElement) {
1066 selectElement.off().empty().remove();
1067 }
1068
1069 selectElement.on('change', function() {
1070 if ($(this).val() !== '') {
1071 var value = $(this).val();
1072 $('option[value="' + value + '"]', $(this)).remove();
1073
1074 getFormEditorApp().getPublisherSubscriber().publish(
1075 'view/inspector/collectionElement/new/selected',
1076 [value, collectionName]
1077 );
1078 }
1079 });
1080 };
1081
1082 /**
1083 * @public
1084 *
1085 * @param object editorConfiguration
1086 * @param object editorHtml
1087 * @param string collectionElementIdentifier
1088 * @param string collectionName
1089 * @return void
1090 * @throws 1475421525
1091 * @throws 1475421526
1092 * @throws 1475421527
1093 * @throws 1475421528
1094 */
1095 function renderFormElementHeaderEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
1096 assert('object' === $.type(editorConfiguration), 'Invalid parameter "editorConfiguration"', 1475421525);
1097 assert('object' === $.type(editorHtml), 'Invalid parameter "editorHtml"', 1475421526);
1098
1099 Icons.getIcon(
1100 getFormElementDefinition(getCurrentlySelectedFormElement(), 'iconIdentifier'),
1101 Icons.sizes.small,
1102 null,
1103 Icons.states.default
1104 ).done(function(icon) {
1105 getHelper().getTemplatePropertyDomElement('header-label', editorHtml)
1106 .append($(icon).addClass(getHelper().getDomElementClassName('icon')))
1107 .append(buildTitleByFormElement());
1108 });
1109 };
1110
1111 /**
1112 * @public
1113 *
1114 * @param object editorConfiguration
1115 * @param object editorHtml
1116 * @param string collectionElementIdentifier
1117 * @param string collectionName
1118 * @return void
1119 * @throws 1475421257
1120 * @throws 1475421258
1121 * @throws 1475421259
1122 */
1123 function renderCollectionElementHeaderEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
1124 var collectionElementConfiguration, setData;
1125
1126 assert(
1127 'object' === $.type(editorConfiguration),
1128 'Invalid parameter "editorConfiguration"',
1129 1475421258
1130 );
1131 assert(
1132 getUtility().isNonEmptyString(editorConfiguration['label']),
1133 'Invalid configuration "label"',
1134 1475421257
1135 );
1136 assert(
1137 'object' === $.type(editorHtml),
1138 'Invalid parameter "editorHtml"',
1139 1475421259
1140 );
1141
1142 setData = function(icon) {
1143 getHelper()
1144 .getTemplatePropertyDomElement('header-label', editorHtml)
1145 .prepend($(icon));
1146
1147 Icons.getIcon(
1148 getHelper().getDomElementDataAttributeValue('collapse'),
1149 Icons.sizes.small,
1150 null,
1151 Icons.states.default,
1152 Icons.markupIdentifiers.inline
1153 ).done(function(icon) {
1154 var iconWrap;
1155 iconWrap = $('<a></a>')
1156 .attr('href', _getCollectionElementId(collectionName, collectionElementIdentifier, true))
1157 .attr('data-toggle', 'collapse')
1158 .attr('aria-expanded', 'true')
1159 .attr('aria-controls', _getCollectionElementId(collectionName, collectionElementIdentifier))
1160 .addClass('collapsed')
1161 .append($(icon));
1162
1163 getHelper()
1164 .getTemplatePropertyDomElement('header-label', editorHtml)
1165 .prepend(iconWrap);
1166 });
1167 };
1168
1169 collectionElementConfiguration = getFormEditorApp().getFormEditorDefinition(collectionName, collectionElementIdentifier);
1170 if (collectionName === 'validators') {
1171 Icons.getIcon(
1172 collectionElementConfiguration['iconIdentifier'],
1173 Icons.sizes.small,
1174 null,
1175 Icons.states.default
1176 ).done(function(icon) {
1177 setData(icon);
1178 });
1179 } else {
1180 Icons.getIcon(
1181 collectionElementConfiguration['iconIdentifier'],
1182 Icons.sizes.small,
1183 null,
1184 Icons.states.default
1185 ).done(function(icon) {
1186 setData(icon);
1187 });
1188 }
1189
1190 if (editorConfiguration['label']) {
1191 getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']);
1192 }
1193 };
1194
1195 /**
1196 * @public
1197 *
1198 * @param object editorConfiguration
1199 * @param object editorHtml
1200 * @param string collectionElementIdentifier
1201 * @param string collectionName
1202 * @return void
1203 * @throws 1475421053
1204 * @throws 1475421054
1205 * @throws 1475421055
1206 * @throws 1475421056
1207 */
1208 function renderTextEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
1209 var propertyData, propertyPath;
1210 assert(
1211 'object' === $.type(editorConfiguration),
1212 'Invalid parameter "editorConfiguration"',
1213 1475421053
1214 );
1215 assert(
1216 'object' === $.type(editorHtml),
1217 'Invalid parameter "editorHtml"',
1218 1475421054
1219 );
1220 assert(
1221 getUtility().isNonEmptyString(editorConfiguration['label']),
1222 'Invalid configuration "label"',
1223 1475421055
1224 );
1225 assert(
1226 getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
1227 'Invalid configuration "propertyPath"',
1228 1475421056
1229 );
1230
1231 getHelper()
1232 .getTemplatePropertyDomElement('label', editorHtml)
1233 .append(editorConfiguration['label']);
1234 if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) {
1235 getHelper()
1236 .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
1237 .text(editorConfiguration['fieldExplanationText']);
1238 } else {
1239 getHelper()
1240 .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
1241 .remove();
1242 }
1243
1244 if (getUtility().isNonEmptyString(editorConfiguration['placeholder'])) {
1245 getHelper()
1246 .getTemplatePropertyDomElement('propertyPath', editorHtml)
1247 .attr('placeholder', editorConfiguration['placeholder']);
1248 }
1249
1250 propertyPath = getFormEditorApp().buildPropertyPath(
1251 editorConfiguration['propertyPath'],
1252 collectionElementIdentifier,
1253 collectionName
1254 );
1255 propertyData = getCurrentlySelectedFormElement().get(propertyPath);
1256
1257 _validateCollectionElement(propertyPath, editorHtml);
1258
1259 getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).val(propertyData);
1260
1261 renderFormElementSelectorEditorAddition(editorConfiguration, editorHtml, propertyPath);
1262
1263 getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function() {
1264 if (
1265 !!editorConfiguration['doNotSetIfPropertyValueIsEmpty']
1266 && !getUtility().isNonEmptyString($(this).val())
1267 ) {
1268 getCurrentlySelectedFormElement().unset(propertyPath);
1269 } else {
1270 getCurrentlySelectedFormElement().set(propertyPath, $(this).val());
1271 }
1272 _validateCollectionElement(propertyPath, editorHtml);
1273 if (
1274 !getUtility().isUndefinedOrNull(editorConfiguration['additionalElementPropertyPaths'])
1275 && 'array' === $.type(editorConfiguration['additionalElementPropertyPaths'])
1276 ) {
1277 for (var i = 0, len = editorConfiguration['additionalElementPropertyPaths'].length; i < len; ++i) {
1278 if (
1279 !!editorConfiguration['doNotSetIfPropertyValueIsEmpty']
1280 && !getUtility().isNonEmptyString($(this).val())
1281 ) {
1282 getCurrentlySelectedFormElement().unset(editorConfiguration['additionalElementPropertyPaths'][i]);
1283 } else {
1284 getCurrentlySelectedFormElement().set(editorConfiguration['additionalElementPropertyPaths'][i], $(this).val());
1285 }
1286 }
1287 }
1288 });
1289 };
1290
1291 /**
1292 * @public
1293 *
1294 * @param object editorConfiguration
1295 * @param object editorHtml
1296 * @param string collectionElementIdentifier
1297 * @param string collectionName
1298 * @return void
1299 * @throws 1489874120
1300 * @throws 1489874121
1301 * @throws 1489874122
1302 * @throws 1489874123
1303 */
1304 function renderValidationErrorMessageEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
1305 var propertyData, propertyPath, validationErrorMessage;
1306 assert(
1307 'object' === $.type(editorConfiguration),
1308 'Invalid parameter "editorConfiguration"',
1309 1489874121
1310 );
1311 assert(
1312 'object' === $.type(editorHtml),
1313 'Invalid parameter "editorHtml"',
1314 1489874122
1315 );
1316 assert(
1317 getUtility().isNonEmptyString(editorConfiguration['label']),
1318 'Invalid configuration "label"',
1319 1489874123
1320 );
1321 assert(
1322 getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
1323 'Invalid configuration "propertyPath"',
1324 1489874124
1325 );
1326
1327 getHelper()
1328 .getTemplatePropertyDomElement('label', editorHtml)
1329 .append(editorConfiguration['label']);
1330 if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) {
1331 getHelper()
1332 .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
1333 .text(editorConfiguration['fieldExplanationText']);
1334 } else {
1335 getHelper()
1336 .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
1337 .remove();
1338 }
1339
1340 propertyPath = getFormEditorApp().buildPropertyPath(
1341 editorConfiguration['propertyPath']
1342 );
1343
1344 propertyData = getCurrentlySelectedFormElement().get(propertyPath);
1345
1346 if (
1347 !getUtility().isUndefinedOrNull(propertyData)
1348 && 'array' === $.type(propertyData)
1349 ) {
1350 validationErrorMessage = _getFirstAvailableValidationErrorMessage(editorConfiguration['errorCodes'], propertyData);
1351
1352 if (!getUtility().isUndefinedOrNull(validationErrorMessage)) {
1353 getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).val(validationErrorMessage);
1354 }
1355 }
1356
1357 getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function() {
1358 propertyData = getCurrentlySelectedFormElement().get(propertyPath);
1359 if (getUtility().isUndefinedOrNull(propertyData)) {
1360 propertyData = [];
1361 }
1362 getCurrentlySelectedFormElement().set(propertyPath, _renewValidationErrorMessages(
1363 editorConfiguration['errorCodes'],
1364 propertyData,
1365 $(this).val()
1366 ));
1367 });
1368 };
1369
1370 /**
1371 * @public
1372 *
1373 * @param object editorConfiguration
1374 * @param object editorHtml
1375 * @param string collectionElementIdentifier
1376 * @param string collectionName
1377 * @return void
1378 * @throws 1475421048
1379 * @throws 1475421049
1380 * @throws 1475421050
1381 * @throws 1475421051
1382 * @throws 1475421052
1383 */
1384 function renderSingleSelectEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
1385 var propertyData, propertyPath, selectElement;
1386 assert(
1387 'object' === $.type(editorConfiguration),
1388 'Invalid parameter "editorConfiguration"',
1389 1475421048
1390 );
1391 assert(
1392 'object' === $.type(editorHtml),
1393 'Invalid parameter "editorHtml"',
1394 1475421049
1395 );
1396 assert(
1397 getUtility().isNonEmptyString(editorConfiguration['label']),
1398 'Invalid configuration "label"',
1399 1475421050
1400 );
1401 assert(
1402 getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
1403 'Invalid configuration "propertyPath"',
1404 1475421051
1405 );
1406 assert(
1407 'array' === $.type(editorConfiguration['selectOptions']),
1408 'Invalid configuration "selectOptions"',
1409 1475421052
1410 );
1411
1412 propertyPath = getFormEditorApp().buildPropertyPath(
1413 editorConfiguration['propertyPath'],
1414 collectionElementIdentifier,
1415 collectionName
1416 );
1417
1418 getHelper()
1419 .getTemplatePropertyDomElement('label', editorHtml)
1420 .append(editorConfiguration['label']);
1421
1422 selectElement = getHelper()
1423 .getTemplatePropertyDomElement('selectOptions', editorHtml);
1424
1425 propertyData = getCurrentlySelectedFormElement().get(propertyPath);
1426
1427 for (var i = 0, len = editorConfiguration['selectOptions'].length; i < len; ++i) {
1428 var option;
1429
1430 if (editorConfiguration['selectOptions'][i]['value'] === propertyData) {
1431 option = new Option(editorConfiguration['selectOptions'][i]['label'], i, false, true);
1432 } else {
1433 option = new Option(editorConfiguration['selectOptions'][i]['label'], i);
1434 }
1435 $(option).data({value: editorConfiguration['selectOptions'][i]['value']});
1436 selectElement.append(option);
1437 }
1438
1439 selectElement.on('change', function() {
1440 getCurrentlySelectedFormElement().set(propertyPath, $('option:selected', $(this)).data('value'));
1441 });
1442 };
1443
1444 /**
1445 * @public
1446 *
1447 * @param object editorConfiguration
1448 * @param object editorHtml
1449 * @param string collectionElementIdentifier
1450 * @param string collectionName
1451 * @return void
1452 * @throws 1485712399
1453 * @throws 1485712400
1454 * @throws 1485712401
1455 * @throws 1485712402
1456 * @throws 1485712403
1457 */
1458 function renderMultiSelectEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
1459 var propertyData, propertyPath, selectElement;
1460 assert(
1461 'object' === $.type(editorConfiguration),
1462 'Invalid parameter "editorConfiguration"',
1463 1485712399
1464 );
1465 assert(
1466 'object' === $.type(editorHtml),
1467 'Invalid parameter "editorHtml"',
1468 1485712400
1469 );
1470 assert(
1471 getUtility().isNonEmptyString(editorConfiguration['label']),
1472 'Invalid configuration "label"',
1473 1485712401
1474 );
1475 assert(
1476 getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
1477 'Invalid configuration "propertyPath"',
1478 1485712402
1479 );
1480 assert(
1481 'array' === $.type(editorConfiguration['selectOptions']),
1482 'Invalid configuration "selectOptions"',
1483 1485712403
1484 );
1485
1486 propertyPath = getFormEditorApp().buildPropertyPath(
1487 editorConfiguration['propertyPath'],
1488 collectionElementIdentifier,
1489 collectionName
1490 );
1491
1492 getHelper()
1493 .getTemplatePropertyDomElement('label', editorHtml)
1494 .append(editorConfiguration['label']);
1495
1496 selectElement = getHelper()
1497 .getTemplatePropertyDomElement('selectOptions', editorHtml);
1498
1499 propertyData = getCurrentlySelectedFormElement().get(propertyPath);
1500
1501 for (var i = 0, len1 = editorConfiguration['selectOptions'].length; i < len1; ++i) {
1502 var option, value;
1503
1504 option = null;
1505 for (var propertyDataKey in propertyData) {
1506 if (!propertyData.hasOwnProperty(propertyDataKey)) {
1507 continue;
1508 }
1509 if (editorConfiguration['selectOptions'][i]['value'] === propertyData[propertyDataKey]) {
1510 option = new Option(editorConfiguration['selectOptions'][i]['label'], i, false, true);
1511 break;
1512 }
1513 }
1514
1515 if (!option) {
1516 option = new Option(editorConfiguration['selectOptions'][i]['label'], i);
1517 }
1518
1519 $(option).data({value: editorConfiguration['selectOptions'][i]['value']});
1520
1521 selectElement.append(option);
1522 }
1523
1524 selectElement.on('change', function() {
1525 var selectValues = [];
1526 $('option:selected', $(this)).each(function(i) {
1527 selectValues.push($(this).data('value'));
1528 });
1529
1530 getCurrentlySelectedFormElement().set(propertyPath, selectValues);
1531 });
1532 };
1533
1534 /**
1535 * @public
1536 *
1537 * @param object editorConfiguration
1538 * @param object editorHtml
1539 * @param string collectionElementIdentifier
1540 * @param string collectionName
1541 * @return void
1542 * @throws 1489528242
1543 * @throws 1489528243
1544 * @throws 1489528244
1545 * @throws 1489528245
1546 * @throws 1489528246
1547 * @throws 1489528247
1548 */
1549 function renderGridColumnViewPortConfigurationEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
1550 var editorControlsWrapper, initNumbersOfColumnsField, numbersOfColumnsTemplate, selectElement,
1551 viewportButtonTemplate;
1552 assert(
1553 'object' === $.type(editorConfiguration),
1554 'Invalid parameter "editorConfiguration"',
1555 1489528242
1556 );
1557 assert(
1558 'object' === $.type(editorHtml),
1559 'Invalid parameter "editorHtml"',
1560 1489528243
1561 );
1562 assert(
1563 getUtility().isNonEmptyString(editorConfiguration['label']),
1564 'Invalid configuration "label"',
1565 1489528244
1566 );
1567 assert(
1568 'array' === $.type(editorConfiguration['configurationOptions']['viewPorts']),
1569 'Invalid configurationOptions "viewPorts"',
1570 1489528245
1571 );
1572 assert(
1573 !getUtility().isUndefinedOrNull(editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['label']),
1574 'Invalid configurationOptions "numbersOfColumnsToUse"',
1575 1489528246
1576 );
1577 assert(
1578 !getUtility().isUndefinedOrNull(editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['propertyPath']),
1579 'Invalid configuration "selectOptions"',
1580 1489528247
1581 );
1582
1583 if (!getFormElementDefinition(getCurrentlySelectedFormElement().get('__parentRenderable'), '_isGridRowFormElement')) {
1584 editorHtml.remove();
1585 return;
1586 }
1587
1588 getHelper()
1589 .getTemplatePropertyDomElement('label', editorHtml)
1590 .append(editorConfiguration['label']);
1591
1592
1593 viewportButtonTemplate = $(getHelper()
1594 .getDomElementDataIdentifierSelector('viewportButton'), $(editorHtml))
1595 .clone();
1596
1597 $(getHelper()
1598 .getDomElementDataIdentifierSelector('viewportButton'), $(editorHtml))
1599 .remove();
1600
1601 numbersOfColumnsTemplate = getHelper()
1602 .getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml))
1603 .clone();
1604
1605 getHelper()
1606 .getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml))
1607 .remove();
1608
1609 editorControlsWrapper = _getEditorControlsWrapperDomElement(editorHtml);
1610
1611 initNumbersOfColumnsField = function(element) {
1612 var numbersOfColumnsTemplateClone, propertyPath;
1613
1614 getHelper().getTemplatePropertyDomElement('numbersOfColumnsToUse', $(editorHtml))
1615 .off()
1616 .empty()
1617 .remove();
1618
1619 numbersOfColumnsTemplateClone = $(numbersOfColumnsTemplate).clone(true, true);
1620 _getEditorWrapperDomElement(editorHtml).after(numbersOfColumnsTemplateClone);
1621
1622 $('input', numbersOfColumnsTemplateClone).focus();
1623
1624 getHelper()
1625 .getTemplatePropertyDomElement('numbersOfColumnsToUse-label', numbersOfColumnsTemplateClone)
1626 .append(
1627 editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['label']
1628 .replace('{@viewPortLabel}', element.data('viewPortLabel'))
1629 );
1630
1631 getHelper()
1632 .getTemplatePropertyDomElement('numbersOfColumnsToUse-fieldExplanationText', numbersOfColumnsTemplateClone)
1633 .append(editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['fieldExplanationText']);
1634
1635 propertyPath = editorConfiguration['configurationOptions']['numbersOfColumnsToUse']['propertyPath']
1636 .replace('{@viewPortIdentifier}', element.data('viewPortIdentifier'));
1637
1638 getHelper()
1639 .getTemplatePropertyDomElement('numbersOfColumnsToUse-propertyPath', numbersOfColumnsTemplateClone)
1640 .val(getCurrentlySelectedFormElement().get(propertyPath));
1641
1642 getHelper().getTemplatePropertyDomElement('numbersOfColumnsToUse-propertyPath', numbersOfColumnsTemplateClone).on('keyup paste change', function() {
1643 var that = $(this);
1644 if (!$.isNumeric(that.val())) {
1645 that.val('');
1646 }
1647 getCurrentlySelectedFormElement().set(propertyPath, that.val());
1648 });
1649 };
1650
1651 for (var i = 0, len = editorConfiguration['configurationOptions']['viewPorts'].length; i < len; ++i) {
1652 var numbersOfColumnsTemplateClone, viewportButtonTemplateClone, viewPortIdentifier,
1653 viewPortLabel;
1654
1655 viewPortIdentifier = editorConfiguration['configurationOptions']['viewPorts'][i]['viewPortIdentifier'];
1656 viewPortLabel = editorConfiguration['configurationOptions']['viewPorts'][i]['label'];
1657
1658 viewportButtonTemplateClone = $(viewportButtonTemplate).clone(true, true);
1659 viewportButtonTemplateClone.text(viewPortLabel);
1660 viewportButtonTemplateClone.data('viewPortIdentifier', viewPortIdentifier);
1661 viewportButtonTemplateClone.data('viewPortLabel', viewPortLabel);
1662 editorControlsWrapper.append(viewportButtonTemplateClone);
1663
1664 if (i === (len - 1)) {
1665 numbersOfColumnsTemplateClone = $(numbersOfColumnsTemplate).clone(true, true);
1666 _getEditorWrapperDomElement(editorHtml).after(numbersOfColumnsTemplateClone);
1667 initNumbersOfColumnsField(viewportButtonTemplateClone);
1668 viewportButtonTemplateClone.addClass(getHelper().getDomElementClassName('active'));
1669 }
1670
1671 $('button', editorControlsWrapper).on('click', function() {
1672 var that = $(this);
1673
1674 $('button', editorControlsWrapper).removeClass(getHelper().getDomElementClassName('active'));
1675 that.addClass(getHelper().getDomElementClassName('active'));
1676
1677 initNumbersOfColumnsField(that);
1678 });
1679 }
1680 };
1681
1682 /**
1683 * @public
1684 *
1685 * @param object editorConfiguration
1686 * @param object editorHtml
1687 * @param string collectionElementIdentifier
1688 * @param string collectionName
1689 * @return void
1690 * @throws 1475419226
1691 * @throws 1475419227
1692 * @throws 1475419228
1693 * @throws 1475419229
1694 * @throws 1475419230
1695 * @throws 1475419231
1696 * @throws 1475419232
1697 */
1698 function renderPropertyGridEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
1699 var addRowTemplate, defaultValue, multiSelection, propertyData, propertyPathPrefix,
1700 rowItemTemplate, setData;
1701 assert(
1702 'object' === $.type(editorConfiguration),
1703 'Invalid parameter "editorConfiguration"',
1704 1475419226
1705 );
1706 assert(
1707 'object' === $.type(editorHtml),
1708 'Invalid parameter "editorHtml"',
1709 1475419227
1710 );
1711 assert(
1712 'boolean' === $.type(editorConfiguration['enableAddRow']),
1713 'Invalid configuration "enableAddRow"',
1714 1475419228
1715 );
1716 assert(
1717 'boolean' === $.type(editorConfiguration['enableDeleteRow']),
1718 'Invalid configuration "enableDeleteRow"',
1719 1475419230
1720 );
1721 assert(
1722 'boolean' === $.type(editorConfiguration['isSortable']),
1723 'Invalid configuration "isSortable"',
1724 1475419229
1725 );
1726 assert(
1727 getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
1728 'Invalid configuration "propertyPath"',
1729 1475419231
1730 );
1731 assert(
1732 getUtility().isNonEmptyString(editorConfiguration['label']),
1733 'Invalid configuration "label"',
1734 1475419232
1735 );
1736
1737 getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']);
1738 propertyPathPrefix = getFormEditorApp().buildPropertyPath(
1739 undefined,
1740 collectionElementIdentifier,
1741 collectionName,
1742 undefined,
1743 true
1744 );
1745 if (getUtility().isNonEmptyString(propertyPathPrefix)) {
1746 propertyPathPrefix = propertyPathPrefix + '.';
1747 }
1748
1749 if (getUtility().isUndefinedOrNull(editorConfiguration['multiSelection'])) {
1750 multiSelection = false;
1751 } else {
1752 multiSelection = !!editorConfiguration['multiSelection'];
1753 }
1754
1755 rowItemTemplate = $(
1756 getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'),
1757 $(editorHtml)
1758 ).clone();
1759 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), $(editorHtml)).remove();
1760
1761 if (!!editorConfiguration['enableDeleteRow']) {
1762 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorDeleteRow'),
1763 $(rowItemTemplate)
1764 ).on('click', function() {
1765 if ($(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'), $(editorHtml)).length > 1) {
1766 $(this)
1767 .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'))
1768 .off()
1769 .empty()
1770 .remove();
1771
1772 _setPropertyGridData(
1773 $(editorHtml),
1774 multiSelection,
1775 editorConfiguration['propertyPath'],
1776 propertyPathPrefix
1777 );
1778 } else {
1779 Notification.error(
1780 editorConfiguration['removeLastAvailableRowFlashMessageTitle'],
1781 editorConfiguration['removeLastAvailableRowFlashMessageMessage'],
1782 2
1783 );
1784 }
1785 });
1786 } else {
1787 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorDeleteRow'), $(rowItemTemplate))
1788 .parent()
1789 .off()
1790 .empty();
1791 }
1792
1793 if (!!editorConfiguration['isSortable']) {
1794 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml))
1795 .addClass(getHelper().getDomElementClassName('sortable'))
1796 .sortable({
1797 revert: 'true',
1798 items: getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'),
1799 update: function(e, o) {
1800 _setPropertyGridData($(editorHtml), multiSelection, editorConfiguration['propertyPath'], propertyPathPrefix);
1801 }
1802 });
1803 } else {
1804 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSortRow'), $(rowItemTemplate))
1805 .parent()
1806 .off()
1807 .empty();
1808 }
1809
1810 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue'),
1811 $(rowItemTemplate)
1812 ).on('change', function() {
1813 if (!multiSelection) {
1814 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue') + ':checked', $(editorHtml))
1815 .not($(this))
1816 .prop('checked', false);
1817 }
1818 _setPropertyGridData($(editorHtml), multiSelection, editorConfiguration['propertyPath'], propertyPathPrefix);
1819 });
1820
1821 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel') + ',' +
1822 getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'),
1823 $(rowItemTemplate)
1824 ).on('keyup paste', function() {
1825 _setPropertyGridData($(editorHtml), multiSelection, editorConfiguration['propertyPath'], propertyPathPrefix);
1826 });
1827
1828 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'),
1829 $(rowItemTemplate)
1830 ).on('focusout', function() {
1831 if ('' === $(this)
1832 .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'))
1833 .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'))
1834 .val()
1835 ) {
1836 $(this)
1837 .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorRowItem'))
1838 .find(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'))
1839 .val($(this).val());
1840 }
1841 });
1842
1843 if (!!editorConfiguration['enableAddRow']) {
1844 addRowTemplate = $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).clone();
1845 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).remove();
1846
1847 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRow'), $(addRowTemplate)).on('click', function() {
1848 $(this)
1849 .closest(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'))
1850 .before($(rowItemTemplate).clone(true, true));
1851 });
1852 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml))
1853 .prepend($(addRowTemplate).clone(true, true));
1854 } else {
1855 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml)).remove();
1856 }
1857
1858 defaultValue = {};
1859 if (multiSelection) {
1860 if (!getUtility().isUndefinedOrNull(getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'))) {
1861 defaultValue = getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue');
1862 }
1863 } else {
1864 if (!getUtility().isUndefinedOrNull(getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue'))) {
1865 defaultValue = {0: getCurrentlySelectedFormElement().get(propertyPathPrefix + 'defaultValue')};
1866 }
1867 }
1868 propertyData = getCurrentlySelectedFormElement().get(propertyPathPrefix + editorConfiguration['propertyPath']) || {};
1869
1870 setData = function(label, value) {
1871 var isPreselected, newRowTemplate;
1872
1873 isPreselected = false;
1874 newRowTemplate = $(rowItemTemplate).clone(true, true);
1875
1876 for (var defaultValueKey in defaultValue) {
1877 if (!defaultValue.hasOwnProperty(defaultValueKey)) {
1878 continue;
1879 }
1880 if (defaultValue[defaultValueKey] === value) {
1881 isPreselected = true;
1882 break;
1883 }
1884 }
1885
1886 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorLabel'), $(newRowTemplate)).val(label);
1887 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorValue'), $(newRowTemplate)).val(value);
1888 if (isPreselected) {
1889 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorSelectValue'), $(newRowTemplate))
1890 .prop('checked', true);
1891 }
1892
1893 if (!!editorConfiguration['enableAddRow']) {
1894 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorAddRowItem'), $(editorHtml))
1895 .before($(newRowTemplate));
1896 } else {
1897 $(getHelper().getDomElementDataIdentifierSelector('propertyGridEditorContainer'), $(editorHtml))
1898 .prepend($(newRowTemplate));
1899 }
1900 };
1901
1902 if ('object' === $.type(propertyData)) {
1903 for (var propertyDataKey in propertyData) {
1904 if (!propertyData.hasOwnProperty(propertyDataKey)) {
1905 continue;
1906 }
1907 setData(propertyData[propertyDataKey], propertyDataKey);
1908 }
1909 } else if ('array' === $.type(propertyData)) {
1910 for (var propertyDataKey in propertyData) {
1911 if (!propertyData.hasOwnProperty(propertyDataKey)) {
1912 continue;
1913 }
1914 if (getUtility().isUndefinedOrNull(propertyData[propertyDataKey]['_label'])) {
1915 setData(propertyData[propertyDataKey], propertyDataKey);
1916 } else {
1917 setData(propertyData[propertyDataKey]['_label'], propertyData[propertyDataKey]['_value']);
1918 }
1919 }
1920 }
1921 };
1922
1923 /**
1924 * @public
1925 *
1926 * @param object editorConfiguration
1927 * @param object editorHtml
1928 * @param string collectionElementIdentifier
1929 * @param string collectionName
1930 * @return void
1931 * @publish view/inspector/collectionElement/new/selected
1932 * @publish view/inspector/removeCollectionElement/perform
1933 * @throws 1475417093
1934 * @throws 1475417094
1935 * @throws 1475417095
1936 * @throws 1475417096
1937 */
1938 function renderRequiredValidatorEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
1939 var propertyData, propertyPath, propertyValue, showValidationErrorMessage, validationErrorMessage, validationErrorMessagePropertyPath, validationErrorMessageTemplate, validationErrorMessageTemplateClone, validatorIdentifier;
1940 assert(
1941 'object' === $.type(editorConfiguration),
1942 'Invalid parameter "editorConfiguration"',
1943 1475417093
1944 );
1945 assert(
1946 'object' === $.type(editorHtml),
1947 'Invalid parameter "editorHtml"',
1948 1475417094
1949 );
1950 assert(
1951 getUtility().isNonEmptyString(editorConfiguration['validatorIdentifier']),
1952 'Invalid configuration "validatorIdentifier"',
1953 1475417095
1954 );
1955 assert(
1956 getUtility().isNonEmptyString(editorConfiguration['label']),
1957 'Invalid configuration "label"',
1958 1475417096
1959 );
1960
1961 validatorIdentifier = editorConfiguration['validatorIdentifier'];
1962 getHelper().getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']);
1963
1964 if (getUtility().isNonEmptyString(editorConfiguration['propertyPath'])) {
1965 propertyPath = getFormEditorApp()
1966 .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName);
1967 }
1968 if (getUtility().isNonEmptyString(editorConfiguration['propertyValue'])) {
1969 propertyValue = editorConfiguration['propertyValue'];
1970 } else {
1971 propertyValue = '';
1972 }
1973
1974 validationErrorMessagePropertyPath = getFormEditorApp()
1975 .buildPropertyPath(editorConfiguration['configurationOptions']['validationErrorMessage']['propertyPath']);
1976
1977 validationErrorMessageTemplate = getHelper()
1978 .getTemplatePropertyDomElement('validationErrorMessage', $(editorHtml))
1979 .clone();
1980
1981 getHelper()
1982 .getTemplatePropertyDomElement('validationErrorMessage', $(editorHtml))
1983 .remove();
1984
1985 showValidationErrorMessage = function() {
1986 validationErrorMessageTemplateClone = $(validationErrorMessageTemplate).clone(true, true);
1987 _getEditorWrapperDomElement(editorHtml).after(validationErrorMessageTemplateClone);
1988
1989 getHelper()
1990 .getTemplatePropertyDomElement('validationErrorMessage-label', validationErrorMessageTemplateClone)
1991 .append(editorConfiguration['configurationOptions']['validationErrorMessage']['label']);
1992
1993 getHelper()
1994 .getTemplatePropertyDomElement('validationErrorMessage-fieldExplanationText', validationErrorMessageTemplateClone)
1995 .append(editorConfiguration['configurationOptions']['validationErrorMessage']['fieldExplanationText']);
1996
1997 propertyData = getCurrentlySelectedFormElement().get(validationErrorMessagePropertyPath);
1998 if (getUtility().isUndefinedOrNull(propertyData)) {
1999 propertyData = [];
2000 }
2001
2002 validationErrorMessage = _getFirstAvailableValidationErrorMessage(
2003 editorConfiguration['configurationOptions']['validationErrorMessage']['errorCodes'],
2004 propertyData
2005 );
2006 if (!getUtility().isUndefinedOrNull(validationErrorMessage)) {
2007 getHelper()
2008 .getTemplatePropertyDomElement('validationErrorMessage-propertyPath', validationErrorMessageTemplateClone)
2009 .val(validationErrorMessage);
2010 }
2011
2012 getHelper().getTemplatePropertyDomElement('validationErrorMessage-propertyPath', validationErrorMessageTemplateClone).on('keyup paste', function() {
2013 propertyData = getCurrentlySelectedFormElement().get(validationErrorMessagePropertyPath);
2014 if (getUtility().isUndefinedOrNull(propertyData)) {
2015 propertyData = [];
2016 }
2017
2018 getCurrentlySelectedFormElement().set(validationErrorMessagePropertyPath, _renewValidationErrorMessages(
2019 editorConfiguration['configurationOptions']['validationErrorMessage']['errorCodes'],
2020 propertyData,
2021 $(this).val()
2022 ));
2023 });
2024 }
2025
2026 if (-1 !== getFormEditorApp().getIndexFromPropertyCollectionElement(validatorIdentifier, 'validators')) {
2027 $('input[type="checkbox"]', $(editorHtml)).prop('checked', true);
2028 if (getUtility().isNonEmptyString(propertyPath)) {
2029 getCurrentlySelectedFormElement().set(propertyPath, propertyValue);
2030 }
2031 showValidationErrorMessage();
2032 }
2033
2034 $('input[type="checkbox"]', $(editorHtml)).on('change', function() {
2035 getHelper().getTemplatePropertyDomElement('validationErrorMessage', $(editorHtml))
2036 .off()
2037 .empty()
2038 .remove();
2039
2040 if ($(this).is(":checked")) {
2041 showValidationErrorMessage();
2042 getPublisherSubscriber().publish(
2043 'view/inspector/collectionElement/new/selected',
2044 [validatorIdentifier, 'validators']
2045 );
2046
2047 if (getUtility().isNonEmptyString(propertyPath)) {
2048 getCurrentlySelectedFormElement().set(propertyPath, propertyValue);
2049 }
2050 } else {
2051 getPublisherSubscriber().publish(
2052 'view/inspector/removeCollectionElement/perform',
2053 [validatorIdentifier, 'validators']
2054 );
2055 if (getUtility().isNonEmptyString(propertyPath)) {
2056 getCurrentlySelectedFormElement().unset(propertyPath);
2057 }
2058
2059 propertyData = getCurrentlySelectedFormElement().get(validationErrorMessagePropertyPath);
2060 if (getUtility().isUndefinedOrNull(propertyData)) {
2061 propertyData = [];
2062 }
2063
2064 getCurrentlySelectedFormElement().set(validationErrorMessagePropertyPath, _renewValidationErrorMessages(
2065 editorConfiguration['configurationOptions']['validationErrorMessage']['errorCodes'],
2066 propertyData,
2067 ''
2068 ));
2069 }
2070 });
2071 };
2072
2073 /**
2074 * @public
2075 *
2076 * @param object editorConfiguration
2077 * @param object editorHtml
2078 * @param string collectionElementIdentifier
2079 * @param string collectionName
2080 * @return void
2081 * @throws 1476218671
2082 * @throws 1476218672
2083 * @throws 1476218673
2084 * @throws 1476218674
2085 */
2086 function renderCheckboxEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
2087 var propertyData, propertyPath;
2088 assert(
2089 'object' === $.type(editorConfiguration),
2090 'Invalid parameter "editorConfiguration"',
2091 1476218671
2092 );
2093 assert(
2094 'object' === $.type(editorHtml),
2095 'Invalid parameter "editorHtml"',
2096 1476218672
2097 );
2098 assert(
2099 getUtility().isNonEmptyString(editorConfiguration['label']),
2100 'Invalid configuration "label"',
2101 1476218673
2102 );
2103 assert(
2104 getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
2105 'Invalid configuration "propertyPath"',
2106 1476218674
2107 );
2108
2109 getHelper()
2110 .getTemplatePropertyDomElement('label', editorHtml)
2111 .append(editorConfiguration['label']);
2112
2113 propertyPath = getFormEditorApp()
2114 .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName);
2115 propertyData = getCurrentlySelectedFormElement().get(propertyPath);
2116
2117 if (
2118 ('boolean' === $.type(propertyData) && propertyData)
2119 || propertyData === 'true'
2120 || propertyData === 1
2121 || propertyData === "1"
2122 ) {
2123 $('input[type="checkbox"]', $(editorHtml)).prop('checked', true);
2124 }
2125
2126 $('input[type="checkbox"]', $(editorHtml)).on('change', function() {
2127 if ($(this).is(":checked")) {
2128 getCurrentlySelectedFormElement().set(propertyPath, true);
2129 } else {
2130 getCurrentlySelectedFormElement().set(propertyPath, false);
2131 }
2132 });
2133 };
2134
2135 /**
2136 * @public
2137 *
2138 * @param object editorConfiguration
2139 * @param object editorHtml
2140 * @param string collectionElementIdentifier
2141 * @param string collectionName
2142 * @return void
2143 * @throws 1475412567
2144 * @throws 1475412568
2145 * @throws 1475416098
2146 * @throws 1475416099
2147 */
2148 function renderTextareaEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
2149 var propertyPath, propertyData;
2150 assert(
2151 'object' === $.type(editorConfiguration),
2152 'Invalid parameter "editorConfiguration"',
2153 1475412567
2154 );
2155 assert(
2156 'object' === $.type(editorHtml),
2157 'Invalid parameter "editorHtml"',
2158 1475412568
2159 );
2160 assert(
2161 getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
2162 'Invalid configuration "propertyPath"',
2163 1475416098
2164 );
2165 assert(
2166 getUtility().isNonEmptyString(editorConfiguration['label']),
2167 'Invalid configuration "label"',
2168 1475416099
2169 );
2170
2171 propertyPath = getFormEditorApp()
2172 .buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName);
2173
2174 getHelper()
2175 .getTemplatePropertyDomElement('label', editorHtml).append(editorConfiguration['label']);
2176
2177 if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) {
2178 getHelper()
2179 .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
2180 .text(editorConfiguration['fieldExplanationText']);
2181 } else {
2182 getHelper()
2183 .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
2184 .remove();
2185 }
2186
2187 propertyData = getCurrentlySelectedFormElement().get(propertyPath);
2188 $('textarea', $(editorHtml)).val(propertyData);
2189
2190 $('textarea', $(editorHtml)).on('keyup paste', function() {
2191 getCurrentlySelectedFormElement().set(propertyPath, $(this).val());
2192 });
2193 };
2194
2195 /**
2196 * @public
2197 *
2198 * @param object editorConfiguration
2199 * @param object editorHtml
2200 * @param string collectionElementIdentifier
2201 * @param string collectionName
2202 * @return void
2203 * @throws 1477300587
2204 * @throws 1477300588
2205 * @throws 1477300589
2206 * @throws 1477300590
2207 * @throws 1477318981
2208 * @throws 1477319859
2209 */
2210 function renderTypo3WinBrowserEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
2211 var iconType, propertyPath, propertyData;
2212 assert(
2213 'object' === $.type(editorConfiguration),
2214 'Invalid parameter "editorConfiguration"',
2215 1477300587
2216 );
2217 assert(
2218 'object' === $.type(editorHtml),
2219 'Invalid parameter "editorHtml"',
2220 1477300588
2221 );
2222 assert(
2223 getUtility().isNonEmptyString(editorConfiguration['label']),
2224 'Invalid configuration "label"',
2225 1477300589
2226 );
2227 assert(
2228 getUtility().isNonEmptyString(editorConfiguration['buttonLabel']),
2229 'Invalid configuration "buttonLabel"',
2230 1477318981
2231 );
2232 assert(
2233 getUtility().isNonEmptyString(editorConfiguration['propertyPath']),
2234 'Invalid configuration "propertyPath"',
2235 1477300590
2236 );
2237 assert(
2238 'tt_content' === editorConfiguration['browsableType'] || 'pages' === editorConfiguration['browsableType'],
2239 'Invalid configuration "browsableType"',
2240 1477319859
2241 );
2242
2243 getHelper()
2244 .getTemplatePropertyDomElement('label', editorHtml)
2245 .append(editorConfiguration['label']);
2246 getHelper()
2247 .getTemplatePropertyDomElement('buttonLabel', editorHtml)
2248 .append(editorConfiguration['buttonLabel']);
2249
2250 if (getUtility().isNonEmptyString(editorConfiguration['fieldExplanationText'])) {
2251 getHelper()
2252 .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
2253 .text(editorConfiguration['fieldExplanationText']);
2254 } else {
2255 getHelper()
2256 .getTemplatePropertyDomElement('fieldExplanationText', editorHtml)
2257 .remove();
2258 }
2259
2260 $('form', $(editorHtml)).prop('name', editorConfiguration['propertyPath']);
2261
2262 iconType = ('tt_content' === editorConfiguration['browsableType'])
2263 ? getHelper().getDomElementDataAttributeValue('iconTtContent')
2264 : getHelper().getDomElementDataAttributeValue('iconPage');
2265 Icons.getIcon(iconType, Icons.sizes.small).done(function(icon) {
2266 getHelper().getTemplatePropertyDomElement('image', editorHtml).append($(icon));
2267 });
2268
2269 getHelper().getTemplatePropertyDomElement('onclick', editorHtml).on('click', function() {
2270 var insertTarget, randomIdentifier;
2271
2272 randomIdentifier = Math.floor((Math.random() * 100000) + 1);
2273 insertTarget = $(this)
2274 .closest(getHelper().getDomElementDataIdentifierSelector('editorControlsWrapper'))
2275 .find(getHelper().getDomElementDataAttribute('contentElementSelectorTarget', 'bracesWithKey'));
2276
2277 insertTarget.attr(getHelper().getDomElementDataAttribute('contentElementSelectorTarget'), randomIdentifier);
2278 _openTypo3WinBrowser('db', randomIdentifier + '|||' + editorConfiguration['browsableType']);
2279 });
2280
2281 propertyPath = getFormEditorApp().buildPropertyPath(editorConfiguration['propertyPath'], collectionElementIdentifier, collectionName);
2282 propertyData = getCurrentlySelectedFormElement().get(propertyPath);
2283
2284 _validateCollectionElement(propertyPath, editorHtml);
2285 getHelper()
2286 .getTemplatePropertyDomElement('propertyPath', editorHtml)
2287 .val(propertyData);
2288
2289 getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).on('keyup paste', function() {
2290 getCurrentlySelectedFormElement().set(propertyPath, $(this).val());
2291 _validateCollectionElement(propertyPath, editorHtml);
2292 });
2293 };
2294
2295 /**
2296 * @public
2297 *
2298 * @param object editorConfiguration
2299 * @param object editorHtml
2300 * @param string collectionElementIdentifier
2301 * @param string collectionName
2302 * @return void
2303 * @throws 1475412563
2304 * @throws 1475412564
2305 */
2306 function renderRemoveElementEditor(editorConfiguration, editorHtml, collectionElementIdentifier, collectionName) {
2307 assert('object' === $.type(editorConfiguration), 'Invalid parameter "editorConfiguration"', 1475412563);
2308 assert('object' === $.type(editorHtml), 'Invalid parameter "editorHtml"', 1475412564);
2309
2310 if (getUtility().isUndefinedOrNull(collectionElementIdentifier)) {
2311
2312 $('button', $(editorHtml))
2313 .addClass(
2314 getHelper().getDomElementClassName('buttonFormElementRemove') + ' ' +
2315 getHelper().getDomElementClassName('buttonFormEditor')
2316 );
2317 } else {
2318 $('button', $(editorHtml)).addClass(
2319 getHelper().getDomElementClassName('buttonCollectionElementRemove')
2320 );
2321 }
2322
2323 $('button', $(editorHtml)).on('click', function(e) {
2324 if (getUtility().isUndefinedOrNull(collectionElementIdentifier)) {
2325 getViewModel().showRemoveFormElementModal();
2326 } else {
2327 getViewModel().showRemoveCollectionElementModal(collectionElementIdentifier, collectionName);
2328 }
2329 });
2330 };
2331
2332 /**
2333 * @public
2334 *
2335 * @param object editorConfiguration
2336 * @param object editorHtml
2337 * @param string propertyPath
2338 * @return void
2339 * @throws 1484574704
2340 * @throws 1484574705
2341 * @throws 1484574706
2342 */
2343 function renderFormElementSelectorEditorAddition(editorConfiguration, editorHtml, propertyPath) {
2344 var nonCompositeNonToplevelFormElements, formElementSelectorControlsWrapper,
2345 formElementSelectorSplitButtonListContainer, itemTemplate;
2346
2347 assert(
2348 'object' === $.type(editorConfiguration),
2349 'Invalid parameter "editorConfiguration"',
2350 1484574704
2351 );
2352 assert(
2353 'object' === $.type(editorHtml),
2354 'Invalid parameter "editorHtml"',
2355 1484574705
2356 );
2357 assert(
2358 getUtility().isNonEmptyString(propertyPath),
2359 'Invalid parameter "propertyPath"',
2360 1484574706
2361 );
2362
2363 formElementSelectorControlsWrapper = $(
2364 getHelper().getDomElementDataIdentifierSelector('formElementSelectorControlsWrapper'), editorHtml
2365 );
2366
2367 if (editorConfiguration['enableFormelementSelectionButton'] === true) {
2368 if (formElementSelectorControlsWrapper.length === 0) {
2369 return;
2370 }
2371
2372 formElementSelectorSplitButtonListContainer = $(
2373 getHelper().getDomElementDataIdentifierSelector('formElementSelectorSplitButtonListContainer'), editorHtml
2374 );
2375
2376 formElementSelectorSplitButtonListContainer.off().empty();
2377 nonCompositeNonToplevelFormElements = getFormEditorApp().getNonCompositeNonToplevelFormElements();
2378
2379 if (nonCompositeNonToplevelFormElements.length === 0) {
2380 Icons.getIcon(
2381 getHelper().getDomElementDataAttributeValue('iconNotAvailable'),
2382 Icons.sizes.small,
2383 null,
2384 Icons.states.default
2385 ).done(function(icon) {
2386 itemTemplate = $('<li data-no-sorting>'
2387 + '<a href="#"></a>'
2388 + '</li>');
2389
2390 itemTemplate
2391 .append($(icon))
2392 .append(' ' + getFormElementDefinition(getRootFormElement(), 'inspectorEditorFormElementSelectorNoElements'));
2393 formElementSelectorSplitButtonListContainer.append(itemTemplate);
2394 });
2395 } else {
2396 for (var i = 0, len = nonCompositeNonToplevelFormElements.length; i < len; ++i) {
2397 var nonCompositeNonToplevelFormElement;
2398
2399 nonCompositeNonToplevelFormElement = nonCompositeNonToplevelFormElements[i];
2400 Icons.getIcon(
2401 getFormElementDefinition(nonCompositeNonToplevelFormElement, 'iconIdentifier'),
2402 Icons.sizes.small,
2403 null,
2404 Icons.states.default
2405 ).done(function(icon) {
2406 itemTemplate = $('<li data-no-sorting>'
2407 + '<a href="#" data-formelement-identifier="' + nonCompositeNonToplevelFormElement.get('identifier') + '">'
2408 + '</a>'
2409 + '</li>');
2410
2411 $('[data-formelement-identifier="' + nonCompositeNonToplevelFormElement.get('identifier') + '"]', itemTemplate)
2412 .append($(icon))
2413 .append(' ' + nonCompositeNonToplevelFormElement.get('label'));
2414
2415 $('a', itemTemplate).on('click', function() {
2416 var propertyData;
2417
2418 propertyData = getCurrentlySelectedFormElement().get(propertyPath);
2419
2420 if (propertyData.length === 0) {
2421 propertyData = '{' + $(this).attr('data-formelement-identifier') + '}';
2422 } else {
2423 propertyData = propertyData + ' ' + '{' + $(this).attr('data-formelement-identifier') + '}';
2424 }
2425
2426 getCurrentlySelectedFormElement().set(propertyPath, propertyData);
2427 getHelper().getTemplatePropertyDomElement('propertyPath', editorHtml).val(propertyData);
2428 _validateCollectionElement(propertyPath, editorHtml);
2429 });
2430
2431 formElementSelectorSplitButtonListContainer.append(itemTemplate);
2432 });
2433 }
2434 }
2435 } else {
2436 $(getHelper().getDomElementDataIdentifierSelector('editorControlsInputGroup'), editorHtml)
2437 .removeClass(getHelper().getDomElementClassName('inspectorInputGroup'));
2438 formElementSelectorControlsWrapper.off().empty().remove();
2439 }
2440 }
2441
2442 /**
2443 * @public
2444 *
2445 * @param string content
2446 * @return void
2447 */
2448 function setFormElementHeaderEditorContent(content) {
2449 if (getFormEditorApp().getUtility().isUndefinedOrNull(content)) {
2450 content = buildTitleByFormElement();
2451 }
2452
2453 $(getHelper()
2454 .getDomElementDataIdentifierSelector('formElementHeaderEditor'), getInspectorDomElement())
2455 .html(content);
2456 };
2457
2458 /**
2459 * @public
2460 *
2461 * @param object
2462 * @return object
2463 * @throws 1478967319
2464 */
2465 function buildTitleByFormElement(formElement) {
2466 var label;
2467 if (getUtility().isUndefinedOrNull(formElement)) {
2468 formElement = getCurrentlySelectedFormElement();
2469 }
2470 assert('object' === $.type(formElement), 'Invalid parameter "formElement"', 1478967319);
2471
2472 return $('<span></span>').text((formElement.get('label')
2473 ? formElement.get('label')
2474 : formElement.get('identifier')));
2475 };
2476
2477 /**
2478 * @public
2479 *
2480 * @param object
2481 * @param object
2482 * @return this
2483 */
2484 function bootstrap(formEditorApp, configuration) {
2485 _formEditorApp = formEditorApp;
2486 _configuration = $.extend(true, _defaultConfiguration, configuration || {});
2487 _helperSetup();
2488 return this;
2489 };
2490
2491 /**
2492 * Publish the public methods.
2493 * Implements the "Revealing Module Pattern".
2494 */
2495 return {
2496 bootstrap: bootstrap,
2497 buildTitleByFormElement: buildTitleByFormElement,
2498 getCollectionElementDomElement: getCollectionElementDomElement,
2499 getFinishersContainerDomElement: getFinishersContainerDomElement,
2500 getInspectorDomElement: getInspectorDomElement,
2501 getValidatorsContainerDomElement: getValidatorsContainerDomElement,
2502 renderCheckboxEditor: renderCheckboxEditor,
2503 renderCollectionElementEditors: renderCollectionElementEditors,
2504 renderCollectionElementHeaderEditor: renderCollectionElementHeaderEditor,
2505 renderCollectionElementSelectionEditor: renderCollectionElementSelectionEditor,
2506 renderEditors: renderEditors,
2507 renderFormElementHeaderEditor: renderFormElementHeaderEditor,
2508 renderFormElementSelectorEditorAddition: renderFormElementSelectorEditorAddition,
2509 renderPropertyGridEditor: renderPropertyGridEditor,
2510 renderRemoveElementEditor: renderRemoveElementEditor,
2511 renderRequiredValidatorEditor: renderRequiredValidatorEditor,
2512 renderSingleSelectEditor: renderSingleSelectEditor,
2513 renderMultiSelectEditor: renderMultiSelectEditor,
2514 renderTextareaEditor: renderTextareaEditor,
2515 renderTextEditor: renderTextEditor,
2516 renderTypo3WinBrowserEditor: renderTypo3WinBrowserEditor,
2517 setFormElementHeaderEditorContent: setFormElementHeaderEditorContent
2518 };
2519 })($, Helper, Icons, Notification);
2520 });