@sapui5/sap.ui.richtexteditor 1.99.1 → 1.102.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/package.json +1 -1
  2. package/src/sap/ui/richtexteditor/.library +1 -1
  3. package/src/sap/ui/richtexteditor/RTESplitButton.js +1 -1
  4. package/src/sap/ui/richtexteditor/RichTextEditor.js +143 -67
  5. package/src/sap/ui/richtexteditor/RichTextEditorRenderer.js +1 -2
  6. package/src/sap/ui/richtexteditor/ToolbarWrapper.js +508 -297
  7. package/src/sap/ui/richtexteditor/ToolbarWrapperRenderer.js +1 -2
  8. package/src/sap/ui/richtexteditor/library.js +59 -30
  9. package/src/sap/ui/richtexteditor/messagebundle_ru.properties +1 -1
  10. package/src/sap/ui/richtexteditor/themes/base/RichTextEditor.less +9 -48
  11. package/src/sap/ui/richtexteditor/themes/sap_belize/RichTextEditor.less +29 -0
  12. package/src/sap/ui/richtexteditor/themes/sap_belize/library.source.less +3 -1
  13. package/src/sap/ui/richtexteditor/themes/sap_belize_hcb/RichTextEditor.less +29 -0
  14. package/src/sap/ui/richtexteditor/themes/sap_belize_hcb/library.source.less +2 -0
  15. package/src/sap/ui/richtexteditor/themes/sap_belize_hcw/RichTextEditor.less +30 -0
  16. package/src/sap/ui/richtexteditor/themes/sap_belize_hcw/library.source.less +2 -0
  17. package/src/sap/ui/richtexteditor/themes/sap_fiori_3/RichTextEditor.less +4 -5
  18. package/src/sap/ui/richtexteditor/themes/sap_fiori_3_dark/RichTextEditor.less +4 -5
  19. package/src/sap/ui/richtexteditor/themes/sap_fiori_3_hcb/RichTextEditor.less +4 -5
  20. package/src/sap/ui/richtexteditor/themes/sap_fiori_3_hcw/RichTextEditor.less +4 -5
  21. package/src/sap/ui/richtexteditor/themes/sap_horizon/RichTextEditor.less +15 -30
  22. package/src/sap/ui/richtexteditor/themes/sap_horizon_dark/RichTextEditor.less +30 -0
  23. package/src/sap/ui/richtexteditor/themes/sap_horizon_dark/library.source.less +10 -0
  24. package/src/sap/ui/richtexteditor/themes/sap_horizon_hcb/RichTextEditor.less +15 -0
  25. package/src/sap/ui/richtexteditor/themes/sap_horizon_hcb/library.source.less +10 -0
  26. package/src/sap/ui/richtexteditor/themes/sap_horizon_hcw/RichTextEditor.less +15 -0
  27. package/src/sap/ui/richtexteditor/themes/sap_horizon_hcw/library.source.less +10 -0
@@ -16,9 +16,22 @@ sap.ui.define([
16
16
  "sap/base/Log",
17
17
  "./ToolbarWrapperRenderer" // Control renderer
18
18
  ],
19
- function(jQuery, Control, library, IconPool, Item, Core, RTESplitButton, URLListValidator, Log) {
19
+ function(
20
+ jQuery,
21
+ Control,
22
+ library,
23
+ IconPool,
24
+ Item,
25
+ Core,
26
+ RTESplitButton,
27
+ URLListValidator,
28
+ Log
29
+ ) {
20
30
  "use strict";
21
31
 
32
+ var ButtonGroups = library.ButtonGroups,
33
+ EditorCommands = library.EditorCommands,
34
+ ButtonsToCommandsMap = library.ButtonsToCommandsMap;
22
35
 
23
36
  /**
24
37
  * Constructor for a new RichTextEditor's Custom Toolbar.
@@ -85,8 +98,8 @@ sap.ui.define([
85
98
  this._helper = library.RichTextEditorHelper;
86
99
  this._oResourceBundle = Core.getLibraryResourceBundle("sap.ui.richtexteditor");
87
100
  this._oAccessibilityTexts = {};
88
- this._sTextColor = library.EditorCommands.TextColor.defaultValue;
89
- this._sBackgroundColor = library.EditorCommands.BackgroundColor.defaultValue;
101
+ this._sTextColor = EditorCommands.TextColor.defaultValue;
102
+ this._sBackgroundColor = EditorCommands.BackgroundColor.defaultValue;
90
103
  };
91
104
 
92
105
  ToolbarWrapper.prototype.onBeforeRendering = function () {
@@ -116,12 +129,12 @@ sap.ui.define([
116
129
 
117
130
  ToolbarWrapper.prototype.onAfterRendering = function () {
118
131
  var oEditor = this.getEditor();
119
- // create an array of deep copies with the initia setupof the button groups
132
+ // create an array of deep copies with the initial setup of the button groups
120
133
  this._initialButtonGroupsState = oEditor && oEditor.getButtonGroups().map(function(oObject){
121
134
  return jQuery.extend(true, {}, oObject);
122
135
  });
123
136
 
124
- this._syncPopoverOpeningArrows();
137
+ this._modifyPopoverOpeningArrowHandlers(true);
125
138
  this._syncColors("TextColor", this._sTextColor);
126
139
  this._syncColors("BackgroundColor", this._sBackgroundColor);
127
140
  };
@@ -134,25 +147,78 @@ sap.ui.define([
134
147
 
135
148
  this._customButtons = null;
136
149
  this._oAccessibilityTexts = null;
150
+ this._helper = null;
151
+ this._oResourceBundle = null;
152
+ this._sTextColor = null;
153
+ this._sBackgroundColor = null;
137
154
  };
138
155
 
139
156
  /**
140
- * Helper function for synchronising the arrow button of the color selection SplitButtons
157
+ * Helper function for attaching / detaching the synchronization handlers of the color selection SplitButton arrow buttons
141
158
  * The arrow button should be displayed as active, while the corresponding color popover is open
142
159
  *
160
+ * @param {boolean} bAttach Will attach the handlers if true
143
161
  * @private
144
162
  */
145
- ToolbarWrapper.prototype._syncPopoverOpeningArrows = function () {
146
- var aFontButtons = this._findGroupedControls("font"),
147
- oTextColorArrowButton = aFontButtons[2] && aFontButtons[2]._getArrowButton(),
148
- oBackgroundColorArrowButton = aFontButtons[3] && aFontButtons[3]._getArrowButton();
163
+ ToolbarWrapper.prototype._modifyPopoverOpeningArrowHandlers = function (bAttach) {
164
+ var oTextColorButton = this._findButtonById("TextColor"),
165
+ oTextColorArrowButton = oTextColorButton && oTextColorButton._getArrowButton(),
166
+ oBackgroundColorButton = this._findButtonById("BackgroundColor"),
167
+ oBackgroundColorArrowButton = oBackgroundColorButton && oBackgroundColorButton._getArrowButton();
168
+
169
+ // Attaching handlers
170
+ // As this method is called each time after rendering, we need to ensure that we attach
171
+ // the necessary handlers only once. That is why two properties were introduced:
172
+ // _bTextColorSyncHandlersAttached
173
+ // _bBackgroundColorSyncHandlersAttached
174
+ if (bAttach && oTextColorArrowButton && !this._bTextColorSyncHandlersAttached) {
175
+ this.getAggregation("_customTextColorDialog")._ensurePopover()
176
+ .attachAfterOpen(oTextColorArrowButton, this._customColorDialogAfterOpen, this)
177
+ .attachAfterClose(oTextColorArrowButton, this._customColorDialogAfterClose, this);
178
+ this._bTextColorSyncHandlersAttached = true;
179
+ }
180
+ if (bAttach && oBackgroundColorArrowButton && !this._bBackgroundColorSyncHandlersAttached) {
181
+ this.getAggregation("_customBackgroundColorDialog")._ensurePopover()
182
+ .attachAfterOpen(oBackgroundColorArrowButton, this._customColorDialogAfterOpen, this)
183
+ .attachAfterClose(oBackgroundColorArrowButton, this._customColorDialogAfterClose, this);
184
+ this._bBackgroundColorSyncHandlersAttached = true;
185
+ }
186
+
187
+ // Detaching handlers
188
+ if (!bAttach && oTextColorArrowButton && this._bTextColorSyncHandlersAttached) {
189
+ this.getAggregation("_customTextColorDialog")._ensurePopover()
190
+ .detachAfterOpen(this._customColorDialogAfterOpen, this)
191
+ .detachAfterClose(this._customColorDialogAfterClose, this);
192
+ this._bTextColorSyncHandlersAttached = null;
193
+ }
194
+ if (!bAttach && oBackgroundColorArrowButton && this._bBackgroundColorSyncHandlersAttached) {
195
+ this.getAggregation("_customBackgroundColorDialog")._ensurePopover()
196
+ .detachAfterOpen(this._customColorDialogAfterOpen, this)
197
+ .detachAfterClose(this._customColorDialogAfterClose, this);
198
+ this._bBackgroundColorSyncHandlersAttached = null;
199
+ }
200
+ };
201
+
202
+ /**
203
+ * Synchronization handler called after opening of the text / background color picker dialog
204
+ *
205
+ * @param {object} oEvent The event object
206
+ * @param {object} oButton The color button
207
+ * @private
208
+ */
209
+ ToolbarWrapper.prototype._customColorDialogAfterOpen = function (oEvent, oButton) {
210
+ oButton && oButton._activeButton();
211
+ };
149
212
 
150
- this.getAggregation("_customTextColorDialog")._ensurePopover()
151
- .attachAfterOpen(function () { oTextColorArrowButton._activeButton();})
152
- .attachAfterClose(function () { oTextColorArrowButton._inactiveButton();});
153
- this.getAggregation("_customBackgroundColorDialog")._ensurePopover()
154
- .attachAfterOpen(function () { oBackgroundColorArrowButton._activeButton();})
155
- .attachAfterClose(function () { oBackgroundColorArrowButton._inactiveButton();});
213
+ /**
214
+ * Synchronization handler called after closing of the text / background color picker dialog
215
+ *
216
+ * @param {object} oEvent The event object
217
+ * @param {object} oButton The color button
218
+ * @private
219
+ */
220
+ ToolbarWrapper.prototype._customColorDialogAfterClose = function (oEvent, oButton) {
221
+ oButton && oButton._inactiveButton();
156
222
  };
157
223
 
158
224
  /**
@@ -197,7 +263,7 @@ sap.ui.define([
197
263
  * @public
198
264
  */
199
265
  ToolbarWrapper.prototype.modifyRTEToolbarConfig = function (oConfig) {
200
- var oToolbar = this;
266
+ var that = this;
201
267
 
202
268
  // Remove the native toolbar. From now on the sap.ui.richtexteditor.ToolbarWrapper will be used
203
269
  oConfig.toolbar = false;
@@ -206,7 +272,7 @@ sap.ui.define([
206
272
 
207
273
  // Sync sap.ui.richtexteditor.ToolbarWrapper buttons with the editor
208
274
  editor.on('NodeChange', function () {
209
- oToolbar._syncToolbarStates(this);
275
+ that._syncToolbarStates(this);
210
276
  });
211
277
  };
212
278
 
@@ -236,20 +302,20 @@ sap.ui.define([
236
302
  * @private
237
303
  */
238
304
  ToolbarWrapper.prototype._syncColors = function (sCommand, sColor) {
239
- var aControls = this._findGroupedControls("font"),
240
- oTextButtonIcon;
305
+ var oColorButton = this._findButtonById(sCommand),
306
+ oColorButtonIcon;
241
307
 
242
308
  if (!sColor) {
243
309
  return;
244
310
  }
245
- switch (sCommand) {
246
- case "TextColor":
247
- aControls[2] && aControls[2].setIconColor(sColor);
248
- break;
249
- case "BackgroundColor":
250
- oTextButtonIcon = aControls[3] && aControls[3]._getTextButton().getDomRef("img");
251
- oTextButtonIcon && Core.byId(oTextButtonIcon.id).setColor(sColor);
252
- break;
311
+
312
+ if (sCommand === "TextColor") {
313
+ oColorButton && oColorButton.setIconColor(sColor);
314
+ }
315
+
316
+ if (sCommand === "BackgroundColor") {
317
+ oColorButtonIcon = oColorButton && oColorButton._getTextButton().getDomRef("img");
318
+ oColorButtonIcon && Core.byId(oColorButtonIcon.id).setColor(sColor);
253
319
  }
254
320
  };
255
321
  /**
@@ -259,7 +325,6 @@ sap.ui.define([
259
325
  */
260
326
  ToolbarWrapper.prototype._syncToolbarStates = function (oNativeEditor) {
261
327
  var oEditorCommand, oControl, sEditorCommand,
262
- oEditorCommands = library.EditorCommands,
263
328
  oFormatter = oNativeEditor.formatter,
264
329
  oResourceBundle = this._oResourceBundle,
265
330
  _syncTextAlign = function (oTextAlignCommand, oEditorFormatter, oControl) {
@@ -343,12 +408,12 @@ sap.ui.define([
343
408
  }
344
409
  };
345
410
 
346
- for (sEditorCommand in oEditorCommands) {
347
- if (!oEditorCommands.hasOwnProperty(sEditorCommand)) {
411
+ for (sEditorCommand in EditorCommands) {
412
+ if (!EditorCommands.hasOwnProperty(sEditorCommand)) {
348
413
  continue;
349
414
  }
350
415
 
351
- oEditorCommand = oEditorCommands[sEditorCommand];
416
+ oEditorCommand = EditorCommands[sEditorCommand];
352
417
  // TODO: Probably there's a better way to handle this
353
418
  oControl = Core.byId(this._getId(sEditorCommand));
354
419
 
@@ -402,11 +467,9 @@ sap.ui.define([
402
467
  * @private
403
468
  */
404
469
  ToolbarWrapper.prototype._createButtonConfig = function (sCommand) {
405
- var oEditorCommands = library.EditorCommands,
406
- oCommand = oEditorCommands[sCommand],
470
+ var oCommand = EditorCommands[sCommand],
407
471
  oRTE = this.getEditor();
408
472
 
409
-
410
473
  return {
411
474
  id: this._getId(sCommand),
412
475
  icon: IconPool.getIconURI(oCommand.icon),
@@ -431,17 +494,16 @@ sap.ui.define([
431
494
  */
432
495
  ToolbarWrapper.prototype._createMenuButtonItems = function (sCommand) {
433
496
  var oEditorHelper = this._helper,
434
- oEditorCommands = library.EditorCommands,
435
497
  aItems = [],
436
498
  sItemText,
437
499
  oCommand;
438
500
 
439
- for (var sEditorCommand in oEditorCommands[sCommand]) {
501
+ for (var sEditorCommand in EditorCommands[sCommand]) {
440
502
  if (sEditorCommand === 'bundleKey') {
441
503
  continue;
442
504
  }
443
505
 
444
- oCommand = oEditorCommands[sCommand][sEditorCommand];
506
+ oCommand = EditorCommands[sCommand][sEditorCommand];
445
507
  sItemText = this._oResourceBundle.getText(oCommand.bundleKey) || oCommand.text;
446
508
  aItems.push(oEditorHelper.createMenuItem(this._getId(sCommand + sEditorCommand), sItemText, IconPool.getIconURI(oCommand.icon)));
447
509
  }
@@ -457,7 +519,7 @@ sap.ui.define([
457
519
  * @private
458
520
  */
459
521
  ToolbarWrapper.prototype._findTextAlignCommandByIcon = function (sIconUri) {
460
- var oEditorCommands = library.EditorCommands['TextAlign'],
522
+ var oEditorCommands = EditorCommands['TextAlign'],
461
523
  sCommandIconUri, sCommand;
462
524
 
463
525
  Object.keys(oEditorCommands)
@@ -479,8 +541,7 @@ sap.ui.define([
479
541
  * @private
480
542
  */
481
543
  ToolbarWrapper.prototype._createFontStyleSelectItems = function () {
482
- var oEditorCommands = library.EditorCommands,
483
- oFontFamilies = oEditorCommands["FontFamily"],
544
+ var oFontFamilies = EditorCommands["FontFamily"],
484
545
  aItems = [],
485
546
  oItem;
486
547
 
@@ -504,8 +565,7 @@ sap.ui.define([
504
565
  * @private
505
566
  */
506
567
  ToolbarWrapper.prototype._getFontStyleCommand = function (sItemText) {
507
- var oEditorCommands = library.EditorCommands,
508
- oFontFamilies = oEditorCommands["FontFamily"];
568
+ var oFontFamilies = EditorCommands["FontFamily"];
509
569
 
510
570
  for (var sFontStyle in oFontFamilies) {
511
571
  if (oFontFamilies.hasOwnProperty(sFontStyle) && oFontFamilies[sFontStyle].text === sItemText) {
@@ -522,8 +582,7 @@ sap.ui.define([
522
582
  * @private
523
583
  */
524
584
  ToolbarWrapper.prototype._getFormatBlockCommand = function (sItemText) {
525
- var oEditorCommands = library.EditorCommands,
526
- oFormat = oEditorCommands["FormatBlock"];
585
+ var oFormat = EditorCommands["FormatBlock"];
527
586
 
528
587
  for (var sFormat in oFormat) {
529
588
  if (oFormat.hasOwnProperty(sFormat) && this._oResourceBundle.getText(oFormat[sFormat].bundleKey) === sItemText) {
@@ -541,10 +600,9 @@ sap.ui.define([
541
600
  ToolbarWrapper.prototype._createFontSizeSelectItems = function () {
542
601
  var aItems = [],
543
602
  number = 1, //TinyMCE command values for font sizes have a value from 1 to 7
544
- oItem,
545
- oEditorCommands = library.EditorCommands;
603
+ oItem;
546
604
 
547
- oEditorCommands["FontSize"].forEach(function (item) {
605
+ EditorCommands["FontSize"].forEach(function (item) {
548
606
  oItem = {
549
607
  id: this._getId("FontSize" + number),
550
608
  text: item + " pt"
@@ -562,8 +620,7 @@ sap.ui.define([
562
620
  * @private
563
621
  */
564
622
  ToolbarWrapper.prototype._createFormatBlockItems = function () {
565
- var oEditorCommands = library.EditorCommands,
566
- oFormatBlock = oEditorCommands["FormatBlock"],
623
+ var oFormatBlock = EditorCommands["FormatBlock"],
567
624
  aItems = [],
568
625
  oItem;
569
626
 
@@ -588,7 +645,7 @@ sap.ui.define([
588
645
  */
589
646
  ToolbarWrapper.prototype._getColor = function (sCommand) {
590
647
  var oRTE = this.getEditor(),
591
- oCommandStyle = library.EditorCommands[sCommand].style,
648
+ oCommandStyle = EditorCommands[sCommand].style,
592
649
  oNode = oRTE.getNativeApi().selection.getNode(),
593
650
  aNodes = oRTE.getNativeApi().dom.getParents(oNode),
594
651
  i, aCurrentNode, sColor;
@@ -603,7 +660,7 @@ sap.ui.define([
603
660
  }
604
661
 
605
662
  // If there is no color style found, return the default color
606
- return library.EditorCommands[sCommand].defaultValue;
663
+ return EditorCommands[sCommand].defaultValue;
607
664
  };
608
665
 
609
666
 
@@ -612,32 +669,30 @@ sap.ui.define([
612
669
  *
613
670
  * @private
614
671
  * @param {string} [sCommand] Editor Command
615
- * @returns {object} The configuration object for the toolbar SplitButton which opens a command specific popover
672
+ * @returns {object|null} The configuration object for the toolbar SplitButton which opens a command specific popover or null
616
673
  */
617
674
  ToolbarWrapper.prototype._createSplitButtonForDialog = function (sCommand) {
618
- var oCommand = library.EditorCommands[sCommand],
619
- oToolbar = this,
675
+ var oCommand = EditorCommands[sCommand],
676
+ that = this,
620
677
  oDialog, oResultConfig;
621
678
 
622
679
  if (!oCommand) {
623
- return;
680
+ return null;
624
681
  }
625
682
 
626
683
  oResultConfig = {
627
684
  id: this._getId(sCommand),
628
685
  tooltip: this._oResourceBundle.getText(oCommand.bundleKey),
629
686
  press: function () {
630
- switch (sCommand) {
631
- case "TextColor":
632
- oToolbar._applyColor(sCommand, oCommand.command, oToolbar._sTextColor);
633
- break;
634
- case "BackgroundColor":
635
- oToolbar._applyColor(sCommand, oCommand.command, oToolbar._sBackgroundColor);
636
- break;
687
+ if (sCommand === "TextColor") {
688
+ that._applyColor(sCommand, oCommand.command, that._sTextColor);
689
+ }
690
+ if (sCommand === "BackgroundColor") {
691
+ that._applyColor(sCommand, oCommand.command, that._sBackgroundColor);
637
692
  }
638
693
  },
639
694
  arrowPress: function () {
640
- oDialog = oToolbar.getAggregation("_custom" + sCommand + "Dialog");
695
+ oDialog = that.getAggregation("_custom" + sCommand + "Dialog");
641
696
 
642
697
  this._getArrowButton()._activeButton();
643
698
  if (!oDialog) {
@@ -657,19 +712,19 @@ sap.ui.define([
657
712
 
658
713
 
659
714
  /**
660
- * Helper function for creating Button Control configuration for opening dialogs
715
+ * Helper function for creating Button Control configuration for opening dialogs.
661
716
  *
662
717
  * @private
663
718
  * @param {string} [sCommand] Editor Command
664
- * @returns {object} The configuration object for the toolbar button which opens a command specific dialog
719
+ * @returns {object|null} The configuration object for the toolbar button which opens a command specific dialog or null.
665
720
  */
666
721
  ToolbarWrapper.prototype._createButtonForDialog = function (sCommand) {
667
- var oCommand = library.EditorCommands[sCommand],
668
- oToolbar = this,
722
+ var oCommand = EditorCommands[sCommand],
723
+ that = this,
669
724
  oDialog;
670
725
 
671
726
  if (!oCommand) {
672
- return;
727
+ return null;
673
728
  }
674
729
 
675
730
  return {
@@ -678,7 +733,7 @@ sap.ui.define([
678
733
  tooltip: this._oResourceBundle.getText(oCommand.bundleKey),
679
734
  text: this._oResourceBundle.getText(oCommand.bundleKey),
680
735
  press: function () {
681
- oDialog = oToolbar.getAggregation("_custom" + sCommand + "Dialog");
736
+ oDialog = that.getAggregation("_custom" + sCommand + "Dialog");
682
737
 
683
738
  if (!oDialog) {
684
739
  return;
@@ -687,13 +742,16 @@ sap.ui.define([
687
742
  switch (sCommand) {
688
743
  case "InsertImage":
689
744
  this.setPressed(true);
690
- oToolbar._syncImageDialogData(oDialog);
745
+ that._syncImageDialogData(oDialog);
691
746
  break;
692
747
  case "InsertLink":
693
- oToolbar._syncLinkDialogData(oDialog);
748
+ that._syncLinkDialogData(oDialog);
694
749
  break;
695
750
  case "InsertTable":
696
- oToolbar._resetDialogContent(oDialog);
751
+ that._resetDialogContent(oDialog);
752
+ break;
753
+ default:
754
+ break;
697
755
  }
698
756
  oDialog.open();
699
757
  }
@@ -840,25 +898,22 @@ sap.ui.define([
840
898
  * @private
841
899
  */
842
900
  ToolbarWrapper.prototype._createColorPalettePopoverConfig = function(sType) {
843
- var oCommand = library.EditorCommands[sType],
901
+ var oCommand = EditorCommands[sType],
844
902
  sColor = oCommand.defaultValue,
845
- oToolbar = this;
903
+ that = this;
846
904
 
847
905
  return {
848
906
  defaultColor: sColor,
849
907
  colorSelect: function (oEvent) {
850
908
  var sColor = oEvent.getParameters().value;
851
- oToolbar._applyColor(sType, oCommand.command, sColor, oEvent.getParameter("defaultAction"));
852
-
853
- switch (sType) {
854
- case "TextColor":
855
- oToolbar._sTextColor = sColor;
856
- oToolbar._syncColors("TextColor", sColor);
857
- break;
858
- case "BackgroundColor":
859
- oToolbar._sBackgroundColor = sColor;
860
- oToolbar._syncColors("BackgroundColor", sColor);
861
- break;
909
+ that._applyColor(sType, oCommand.command, sColor, oEvent.getParameter("defaultAction"));
910
+ if (sType === "TextColor") {
911
+ that._sTextColor = sColor;
912
+ that._syncColors("TextColor", sColor);
913
+ }
914
+ if (sType === "BackgroundColor") {
915
+ that._sBackgroundColor = sColor;
916
+ that._syncColors("BackgroundColor", sColor);
862
917
  }
863
918
  }
864
919
  };
@@ -894,7 +949,7 @@ sap.ui.define([
894
949
  */
895
950
  ToolbarWrapper.prototype._createInsertImageConfig = function() {
896
951
  var iRationCoeff,
897
- oTitleBundleText = this._oResourceBundle.getText(sap.ui.richtexteditor.EditorCommands["InsertImage"].bundleKey),
952
+ oTitleBundleText = this._oResourceBundle.getText(EditorCommands["InsertImage"].bundleKey),
898
953
  oURLInput = this._helper.createInput(),
899
954
  oURLLabel = this._helper.createLabel({
900
955
  text: this._oResourceBundle.getText("INSERT_IMAGE_URL"),
@@ -978,7 +1033,7 @@ sap.ui.define([
978
1033
  oDimensionHeightInput.setValue(fWidthInputValue / iRationCoeff);
979
1034
  }
980
1035
  },
981
- oToolbar = this,
1036
+ that = this,
982
1037
  aButtons = [];
983
1038
 
984
1039
  oDimensionsLabel.setLabelFor(oDimensionWidthInput);
@@ -988,13 +1043,13 @@ sap.ui.define([
988
1043
  text: this._oResourceBundle.getText("DIALOG_OK_BUTTON"),
989
1044
  press: function () {
990
1045
  oRTE.getNativeApi()
991
- .insertContent(oToolbar._generateImageHTML(oURLInput.getValue(),
1046
+ .insertContent(that._generateImageHTML(oURLInput.getValue(),
992
1047
  oTextInput.getValue(),
993
1048
  oDimensionHeightInput.getValue(),
994
1049
  oDimensionWidthInput.getValue(),
995
1050
  oRatioCheckBox.getSelected()));
996
- oToolbar.getAggregation("_customInsertImageDialog").close();
997
- oToolbar._syncToolbarStates(oRTE.getNativeApi());
1051
+ that.getAggregation("_customInsertImageDialog").close();
1052
+ that._syncToolbarStates(oRTE.getNativeApi());
998
1053
  }
999
1054
  }));
1000
1055
 
@@ -1002,8 +1057,8 @@ sap.ui.define([
1002
1057
  id: this._getId("CancelInsertImageButton"),
1003
1058
  text: this._oResourceBundle.getText("DIALOG_CANCEL_BUTTON"),
1004
1059
  press: function () {
1005
- oToolbar.getAggregation("_customInsertImageDialog").close();
1006
- oToolbar._syncToolbarStates(oRTE.getNativeApi());
1060
+ that.getAggregation("_customInsertImageDialog").close();
1061
+ that._syncToolbarStates(oRTE.getNativeApi());
1007
1062
  }
1008
1063
  }));
1009
1064
 
@@ -1050,10 +1105,9 @@ sap.ui.define([
1050
1105
  * Helper function for generating link HTML content
1051
1106
  *
1052
1107
  * @param {string} [sURL] The URL of the HTML link tag
1053
- * @param {string} [sText] The text of the HTML link tag
1054
1108
  * @param {string} [sTitle] The title of the HTML link tag
1055
1109
  * @param {boolean} [bTarget] True if the provided link should be opened in a new window
1056
- * @returns {string} String representing HTML tag with the provided parameters
1110
+ * @param {string} [sText] The text of the HTML link tag
1057
1111
  * @private
1058
1112
  */
1059
1113
  ToolbarWrapper.prototype._generateLinkHTML = function (sURL, sTitle, bTarget, sText) {
@@ -1128,7 +1182,7 @@ sap.ui.define([
1128
1182
  * @private
1129
1183
  */
1130
1184
  ToolbarWrapper.prototype._createInsertLinkConfig = function() {
1131
- var oTitleBundleText = this._oResourceBundle.getText(sap.ui.richtexteditor.EditorCommands["InsertLink"].bundleKey),
1185
+ var oTitleBundleText = this._oResourceBundle.getText(EditorCommands["InsertLink"].bundleKey),
1132
1186
  oURLInput = this._helper.createInput(),
1133
1187
  oURLLabel = this._helper.createLabel({
1134
1188
  text: this._oResourceBundle.getText("INSERT_LINK_URL"),
@@ -1168,7 +1222,7 @@ sap.ui.define([
1168
1222
  oTargetSelect]
1169
1223
  }),
1170
1224
  oRTE = this.getEditor(),
1171
- oToolbar = this,
1225
+ that = this,
1172
1226
  aButtons = [];
1173
1227
 
1174
1228
  aButtons.push(this._helper.createButton({
@@ -1176,12 +1230,12 @@ sap.ui.define([
1176
1230
  text: this._oResourceBundle.getText("DIALOG_OK_BUTTON"),
1177
1231
  press: function () {
1178
1232
  var bTarget = (oTargetSelect.getSelectedItem() === oTargetSelect.getItems()[1]);
1179
- oToolbar._generateLinkHTML(oURLInput.getValue(),
1233
+ that._generateLinkHTML(oURLInput.getValue(),
1180
1234
  oTitleInput.getValue(),
1181
1235
  bTarget,
1182
1236
  oTextInput.getValue());
1183
- oToolbar.getAggregation("_customInsertLinkDialog").close();
1184
- oToolbar._syncToolbarStates(oRTE.getNativeApi());
1237
+ that.getAggregation("_customInsertLinkDialog").close();
1238
+ that._syncToolbarStates(oRTE.getNativeApi());
1185
1239
  }
1186
1240
  }));
1187
1241
 
@@ -1189,8 +1243,8 @@ sap.ui.define([
1189
1243
  id: this._getId("CancelInsertLinkButton"),
1190
1244
  text: this._oResourceBundle.getText("DIALOG_CANCEL_BUTTON"),
1191
1245
  press: function () {
1192
- oToolbar.getAggregation("_customInsertLinkDialog").close();
1193
- oToolbar._syncToolbarStates(oRTE.getNativeApi());
1246
+ that.getAggregation("_customInsertLinkDialog").close();
1247
+ that._syncToolbarStates(oRTE.getNativeApi());
1194
1248
  }
1195
1249
  }));
1196
1250
 
@@ -1217,7 +1271,7 @@ sap.ui.define([
1217
1271
  * @private
1218
1272
  */
1219
1273
  ToolbarWrapper.prototype._createInsertTableConfig = function() {
1220
- var oTitleBundleText = this._oResourceBundle.getText(sap.ui.richtexteditor.EditorCommands["InsertTable"].bundleKey),
1274
+ var oTitleBundleText = this._oResourceBundle.getText(EditorCommands["InsertTable"].bundleKey),
1221
1275
  oRowsInput = this._helper.createStepInput({
1222
1276
  value: 2,
1223
1277
  min: 0,
@@ -1265,7 +1319,7 @@ sap.ui.define([
1265
1319
  oDimensionWidthInput]
1266
1320
  }),
1267
1321
  oRTE = this.getEditor(),
1268
- oToolbar = this,
1322
+ that = this,
1269
1323
  aButtons = [];
1270
1324
 
1271
1325
  aButtons.push(this._helper.createButton({
@@ -1279,7 +1333,7 @@ sap.ui.define([
1279
1333
  dom.setStyle(tableElm, 'width', oDimensionWidthInput.getValue() + "px");
1280
1334
  dom.setStyle(tableElm, 'height', oDimensionHeightInput.getValue() + "px");
1281
1335
 
1282
- oToolbar.getAggregation("_customInsertTableDialog").close();
1336
+ that.getAggregation("_customInsertTableDialog").close();
1283
1337
  }
1284
1338
  }));
1285
1339
 
@@ -1287,7 +1341,7 @@ sap.ui.define([
1287
1341
  id: this._getId("CancelInsertTableButton"),
1288
1342
  text: this._oResourceBundle.getText("DIALOG_CANCEL_BUTTON"),
1289
1343
  press: function () {
1290
- oToolbar.getAggregation("_customInsertTableDialog").close();
1344
+ that.getAggregation("_customInsertTableDialog").close();
1291
1345
  }
1292
1346
  }));
1293
1347
 
@@ -1316,8 +1370,7 @@ sap.ui.define([
1316
1370
  ToolbarWrapper.prototype._createCustomToolbar = function () {
1317
1371
  var oEditorHelper = this._helper,
1318
1372
  aContent = [],
1319
- oButtonGroups = library.ButtonGroups,
1320
- aGroupNames = Object.keys(oButtonGroups),
1373
+ aGroupNames = Object.keys(ButtonGroups),
1321
1374
  aGroups = [],
1322
1375
  aGroupObjects = this.getEditor() ? this.getEditor().getButtonGroups() : [];
1323
1376
 
@@ -1334,7 +1387,7 @@ sap.ui.define([
1334
1387
  aGroups = this._sortToolbarContent(aGroups);
1335
1388
 
1336
1389
  aGroups.forEach(function(oGroup){
1337
- aContent = aContent.concat(this.addButtonGroup(oGroup.name));
1390
+ aContent = aContent.concat(this._createButtonGroup(oGroup));
1338
1391
  }.bind(this));
1339
1392
 
1340
1393
  return oEditorHelper.createOverflowToolbar(this._getId(), aContent);
@@ -1374,195 +1427,326 @@ sap.ui.define([
1374
1427
  };
1375
1428
 
1376
1429
  /**
1377
- * Adds a Button Group to the Custom Toolbar
1430
+ * Maps the native TinyMCE style button names to ones supported by the toolbar wrapper.
1378
1431
  *
1379
- * @param {string} [sGroupName] Group name
1432
+ * @param {string} sGroupName Name of the group
1433
+ * @param {string[]} aNativeButtons Array of native TinyMCE style button names.
1434
+ * @returns {string[]} Array of supported button names (commands).
1435
+ * @private
1436
+ */
1437
+ ToolbarWrapper.prototype._mapNativeButtonsToCommands = function (sGroupName, aNativeButtons) {
1438
+ var oRTE = this.getEditor();
1439
+ var aCommandsToCreate = [];
1440
+ var aSupportedButtonGroup = ButtonGroups[sGroupName];
1441
+
1442
+ if (!Array.isArray(aSupportedButtonGroup) || aNativeButtons && !aNativeButtons.length) {
1443
+ return [];
1444
+ }
1445
+
1446
+ // There are some special groups which do not map 1 to 1 with the native button types
1447
+ // Those groups require some special attention as they might render all buttons as single menu one
1448
+ // or create select type controls.
1449
+ switch (sGroupName) {
1450
+ case "text-align":
1451
+ aCommandsToCreate.push("TextAlign");
1452
+ break;
1453
+ case "formatselect":
1454
+ case "styleselect":
1455
+ aCommandsToCreate.push("FormatBlock");
1456
+ break;
1457
+ case "insert":
1458
+ aCommandsToCreate.push("InsertImage");
1459
+ break;
1460
+ default:
1461
+ // Check the provided buttons in the group against the supported ones for this particular group from the library.
1462
+ aNativeButtons.forEach(function (sNativeButtonName) {
1463
+ var sCustomCommandName = ButtonsToCommandsMap[sNativeButtonName];
1464
+ if (aSupportedButtonGroup.indexOf(sCustomCommandName) > -1) {
1465
+ // The button is supported in the custom toolbar and can be added
1466
+ aCommandsToCreate.push(sCustomCommandName);
1467
+ } else {
1468
+ // For unsupported buttons - log warning and do not do anything
1469
+ Log.warning("Unsupported button for the custom toolbar found: " + sNativeButtonName + ", for group: " + sGroupName + ".", oRTE);
1470
+ }
1471
+ });
1472
+ break;
1473
+ }
1474
+
1475
+ return aCommandsToCreate;
1476
+ };
1477
+
1478
+ ToolbarWrapper.prototype._createFontToolbarContent = function (aButtonsToCreate, bVisible) {
1479
+ // All buttons in this group should be handled case by case as they are not of the same type.
1480
+ var aToolbarContent = [];
1481
+ var oAccessibilityKeys = library.Accessibility;
1482
+ var oRTE = this.getEditor();
1483
+ var that = this;
1484
+
1485
+ // --- Font Family ---
1486
+ if (aButtonsToCreate.indexOf("FontFamily") !== -1) {
1487
+ var oInvisibleTextFontFamily = this._helper.createInvisibleText({
1488
+ text: this._oResourceBundle.getText(oAccessibilityKeys["FontFamily"])
1489
+ }).toStatic();
1490
+ this._registerAssociatedInvisibleTexts("font", oInvisibleTextFontFamily.getId());
1491
+
1492
+ aToolbarContent.push(
1493
+ this._helper.createSelect({
1494
+ id: this._getId("FontFamily"),
1495
+ ariaLabelledBy: oInvisibleTextFontFamily,
1496
+ selectedItemId: this._getId("FontFamilyVerdana"),
1497
+ items: this._createFontStyleSelectItems(),
1498
+ change: function (oEvent) {
1499
+ var oItem;
1500
+
1501
+ if (oRTE) {
1502
+ oItem = oEvent.getSource().getSelectedItem();
1503
+ oRTE.getNativeApi().execCommand('FontName', false, that._getFontStyleCommand(oItem.getText()));
1504
+ } else {
1505
+ Log.warning("Cannot execute native command: " + 'FontName');
1506
+ }
1507
+ }
1508
+ }).setVisible(bVisible)
1509
+ );
1510
+ }
1511
+
1512
+ // --- Font Size ---
1513
+ if (aButtonsToCreate.indexOf("FontSize") !== -1) {
1514
+ var oInvisibleTextFontSize = this._helper.createInvisibleText({
1515
+ text: this._oResourceBundle.getText(oAccessibilityKeys["FontSize"])
1516
+ }).toStatic();
1517
+ this._registerAssociatedInvisibleTexts("font", oInvisibleTextFontSize.getId());
1518
+
1519
+ aToolbarContent.push(
1520
+ this._helper.createSelect({
1521
+ id: this._getId("FontSize"),
1522
+ ariaLabelledBy: oInvisibleTextFontSize,
1523
+ selectedItemId: this._getId("FontSize2"),
1524
+ items: this._createFontSizeSelectItems(),
1525
+ change: function (oEvent) {
1526
+ var oItem;
1527
+
1528
+ if (oRTE) {
1529
+ oItem = oEvent.getSource().getSelectedItem();
1530
+ oRTE.getNativeApi().execCommand('FontSize', false, oItem.getText().replace(/\s/g, ""));
1531
+ } else {
1532
+ Log.warning("Cannot execute native command: " + 'FontSize');
1533
+ }
1534
+ }
1535
+ }).setVisible(bVisible)
1536
+ );
1537
+ }
1538
+
1539
+ // --- Font Color ---
1540
+ if (aButtonsToCreate.indexOf("TextColor") !== -1) {
1541
+ var oInvisibleTextFontColor = this._helper.createInvisibleText({
1542
+ text: this._oResourceBundle.getText(oAccessibilityKeys["FontColor"])
1543
+ }).toStatic();
1544
+
1545
+ var oRTESplitButton = new RTESplitButton(this._createSplitButtonForDialog("TextColor")).setVisible(bVisible);
1546
+ oRTESplitButton._getTextButton().addAriaLabelledBy(oInvisibleTextFontColor);
1547
+
1548
+ aToolbarContent.push(oRTESplitButton);
1549
+ }
1550
+
1551
+ // --- Background Color ---
1552
+ if (aButtonsToCreate.indexOf("BackgroundColor") !== -1) {
1553
+ var oInvisibleTextBackgroundColor = this._helper.createInvisibleText({
1554
+ text: this._oResourceBundle.getText(oAccessibilityKeys["BackgroundColor"])
1555
+ }).toStatic();
1556
+
1557
+ var oBackgroundColorButton = this._helper.createSplitButton(this._createSplitButtonForDialog("BackgroundColor")).setVisible(bVisible);
1558
+ oBackgroundColorButton._getTextButton().addAriaLabelledBy(oInvisibleTextBackgroundColor);
1559
+ aToolbarContent.push(oBackgroundColorButton);
1560
+ }
1561
+
1562
+ return aToolbarContent;
1563
+ };
1564
+
1565
+ ToolbarWrapper.prototype._createTextAlignToolbarContent = function (bVisible) {
1566
+ var oRTE = this.getEditor();
1567
+ var bGroupVisible = oRTE ? oRTE.getShowGroupFontStyle() || bVisible : false;
1568
+ var that = this;
1569
+ var bTextAlignLRight = oRTE._getTextDirection() === "rtl";
1570
+ var iDefaultItemIndex = bTextAlignLRight ? 2 : 0;
1571
+ var aMenuItems = this._createMenuButtonItems("TextAlign");
1572
+
1573
+ return [
1574
+ this._helper.createMenuButton(
1575
+ this._getId("TextAlign"),
1576
+ aMenuItems,
1577
+ function (oEvent) {
1578
+ var oSelectedItem, oEditor, oSelectedItemIcon;
1579
+
1580
+ if (oRTE) {
1581
+ oSelectedItem = oEvent.getParameter("item");
1582
+ oEditor = oRTE.getNativeApi();
1583
+ oSelectedItemIcon = oSelectedItem.getIcon();
1584
+ if (oSelectedItemIcon === this.getParent().getIcon()) {
1585
+ var sTextAlign = bTextAlignLRight ? "JustifyRight" : "JustifyLeft";
1586
+ // Text Align commands in TinyMCE have a toggle behavior when you set a
1587
+ // certain command twice the default command (text-align-left) will be applied
1588
+ oEditor.execCommand(sTextAlign);
1589
+ } else {
1590
+ oEditor.execCommand('Justify' + that._findTextAlignCommandByIcon(oSelectedItemIcon));
1591
+ }
1592
+ } else {
1593
+ Log.warning("Cannot execute native command: " + 'Justify');
1594
+ }
1595
+ },
1596
+ aMenuItems[iDefaultItemIndex].getIcon(),
1597
+ this._oResourceBundle.getText(EditorCommands["TextAlign"].bundleKey)
1598
+ ).setVisible(bGroupVisible)
1599
+ ];
1600
+ };
1601
+
1602
+ ToolbarWrapper.prototype._createFormatSelectToolbarContent = function (bVisible) {
1603
+ var oRTE = this.getEditor();
1604
+ var oAccessibilityKeys = library.Accessibility;
1605
+ var oInvisibleTextFormatBlock = this._helper.createInvisibleText({
1606
+ text: this._oResourceBundle.getText(oAccessibilityKeys["FormatBlock"])
1607
+ }).toStatic();
1608
+
1609
+ this._registerAssociatedInvisibleTexts("formatselect", oInvisibleTextFormatBlock.getId());
1610
+
1611
+ return [
1612
+ this._helper.createSelect({
1613
+ id: this._getId("FormatBlock"),
1614
+ ariaLabelledBy: oInvisibleTextFormatBlock,
1615
+ items: this._createFormatBlockItems(),
1616
+ change: function (oEvent) {
1617
+ var oSelectedItem;
1618
+ if (oRTE) {
1619
+ oSelectedItem = oEvent.getSource().getSelectedItem();
1620
+ if (oSelectedItem) {
1621
+ var currentFormatterCommand = oRTE.getAggregation("_toolbarWrapper")._getFormatBlockCommand(oSelectedItem.getText());
1622
+ oRTE.getNativeApi().execCommand('FormatBlock', false, currentFormatterCommand);
1623
+ }
1624
+ } else {
1625
+ Log.warning("Cannot execute native command: " + 'FormatBlock');
1626
+ }
1627
+ }
1628
+ }).setVisible(bVisible)
1629
+ ];
1630
+ };
1631
+
1632
+ ToolbarWrapper.prototype._createFontStyleToolbarContent = function (aButtonsToCreate, bVisible) {
1633
+ var aToolbarContent = [];
1634
+
1635
+ aButtonsToCreate.forEach(function (oCommand) {
1636
+ aToolbarContent.push(this._helper.createOverflowToolbarToggleButton(this._createButtonConfig(oCommand)).setVisible(bVisible));
1637
+ }, this);
1638
+
1639
+ return aToolbarContent;
1640
+ };
1641
+
1642
+ ToolbarWrapper.prototype._createInsertToolbarContent = function (bVisible) {
1643
+ return [this._helper.createOverflowToolbarToggleButton(this._createButtonForDialog("InsertImage")).setVisible(bVisible)];
1644
+ };
1645
+
1646
+ ToolbarWrapper.prototype._createLinkToolbarContent = function (aButtonsToCreate, bVisible) {
1647
+ var aToolbarContent = [];
1648
+
1649
+ // All buttons in this group should be handled case by case as they are not of the same type.
1650
+ if (aButtonsToCreate.indexOf("InsertLink") !== -1) {
1651
+ aToolbarContent.push(this._helper.createOverflowToolbarToggleButton(this._createButtonForDialog("InsertLink")).setVisible(bVisible));
1652
+ }
1653
+ if (aButtonsToCreate.indexOf("Unlink") !== -1) {
1654
+ aToolbarContent.push(this._helper.createOverflowToolbarButton(this._createButtonConfig("Unlink")).setVisible(bVisible));
1655
+ }
1656
+
1657
+ return aToolbarContent;
1658
+ };
1659
+
1660
+ ToolbarWrapper.prototype._createStructureToolbarContent = function (aButtonsToCreate, bVisible) {
1661
+ var aToolbarContent = [];
1662
+
1663
+ aButtonsToCreate.forEach(function (oCommand) {
1664
+ aToolbarContent.push(this._helper.createOverflowToolbarButton(this._createButtonConfig(oCommand)).setVisible(bVisible));
1665
+ }, this);
1666
+
1667
+ return aToolbarContent;
1668
+ };
1669
+
1670
+ ToolbarWrapper.prototype._createClipboardToolbarContent = function (aButtonsToCreate, bVisible) {
1671
+ var aToolbarContent = [];
1672
+
1673
+ aButtonsToCreate.forEach(function (oCommand) {
1674
+ aToolbarContent.push(this._helper.createOverflowToolbarButton(this._createButtonConfig(oCommand)).setVisible(bVisible));
1675
+ }, this);
1676
+
1677
+ return aToolbarContent;
1678
+ };
1679
+
1680
+ ToolbarWrapper.prototype._createUndoToolbarContent = function (aButtonsToCreate, bVisible) {
1681
+ var aToolbarContent = [];
1682
+
1683
+ aButtonsToCreate.forEach(function (oCommand) {
1684
+ aToolbarContent.push(this._helper.createOverflowToolbarButton(this._createButtonConfig(oCommand)).setVisible(bVisible));
1685
+ }, this);
1686
+
1687
+ return aToolbarContent;
1688
+ };
1689
+
1690
+ /**
1691
+ * Creates a Button Group for the Custom Toolbar
1692
+ *
1693
+ * @param {string} [mGroup] Object map containing group information.
1694
+ * @param {string[]} [mGroup.buttons] Array of name/IDs of the buttons in the group
1695
+ * @param {string} [mGroup.name] Name/ID of the group.
1696
+ * @param {boolean} [mGroup.visible=true] (optional) The priority of the button group. Lower priorities are added first.
1697
+ * @param {int} [mGroup.row=0] (optional) Row number in which the button should be
1698
+ * @param {int} [mGroup.priority=10] (optional) The priority of the button group. Lower priorities are added first.
1699
+ * @param {int} [mGroup.customToolbarPriority] (optional) The priority of the button group in the custom toolbar. Each default group in the custom toolbar has a predefined <code>customToolbarPriority</code>. Lower priorities are added in first.
1380
1700
  * @returns {Array} An array containing the buttons in the group that should be added to the Custom Toolbar's content
1381
- * @public
1701
+ * @private
1382
1702
  */
1383
- ToolbarWrapper.prototype.addButtonGroup = function (sGroupName) {
1703
+ ToolbarWrapper.prototype._createButtonGroup = function (mGroup) {
1384
1704
  var oRTE = this.getEditor(),
1385
1705
  oEditorHelper = this._helper,
1386
1706
  aContent = [],
1387
- oButtonGroups = library.ButtonGroups,
1388
- oCommands = library.EditorCommands,
1389
- oAccessibilityKeys = library.Accessibility,
1390
- bVisibleGroupClipboard,
1391
- bVisibleGroupStructure,
1392
- bVisibleGroupFont,
1393
- bVisibleGroupFontStyle,
1394
- bVisibleGroupUndo,
1395
- bVisibleGroupTextAlign,
1396
- bVisibleGroupFormatBlock,
1397
- bVisibleGroupLink,
1398
- bVisibleGroupInsert,
1399
- oToolbar = this;
1707
+ aToolbarButtonsToCreate = [];
1400
1708
 
1709
+ if (!oRTE) {
1710
+ return [];
1711
+ }
1401
1712
 
1402
- switch (sGroupName) {
1403
- case "font-style":
1404
- bVisibleGroupFontStyle = oRTE ? oRTE.getShowGroupFontStyle() : false;
1713
+ // Map native tinyMCE style button names (e.g. "bold", "forecolor") to supported by the custom toolbar button commands (e.g. "Bold", "TextColor").
1714
+ // If the group does not have "buttons" property, the default configuration for this particular group will be used.
1715
+ aToolbarButtonsToCreate = this._mapNativeButtonsToCommands(mGroup.name, mGroup.buttons);
1405
1716
 
1406
- oButtonGroups["font-style"].forEach(function (oCommand) {
1407
- aContent.push(oEditorHelper.createOverflowToolbarToggleButton(this._createButtonConfig(oCommand)).setVisible(bVisibleGroupFontStyle));
1408
- }, this);
1717
+ switch (mGroup.name) {
1718
+ case "font-style":
1719
+ aContent = this._createFontStyleToolbarContent(aToolbarButtonsToCreate, mGroup.visible);
1409
1720
  break;
1410
1721
  case "font":
1411
- bVisibleGroupFont = oRTE ? oRTE.getShowGroupFont() : false;
1412
-
1413
- var oInvisibleTextFontFamily = oEditorHelper.createInvisibleText({
1414
- text: this._oResourceBundle.getText(oAccessibilityKeys["FontFamily"])
1415
- }).toStatic(),
1416
- oInvisibleTextFontSize = oEditorHelper.createInvisibleText({
1417
- text: this._oResourceBundle.getText(oAccessibilityKeys["FontSize"])
1418
- }).toStatic(),
1419
- oInvisibleTextFontColor = oEditorHelper.createInvisibleText({
1420
- text: this._oResourceBundle.getText(oAccessibilityKeys["FontColor"])
1421
- }).toStatic(),
1422
- oInvisibleTextBackgroundColor = oEditorHelper.createInvisibleText({
1423
- text: this._oResourceBundle.getText(oAccessibilityKeys["BackgroundColor"])
1424
- }).toStatic();
1425
- this._registerAssociatedInvisibleTexts("font", oInvisibleTextFontFamily.getId());
1426
- this._registerAssociatedInvisibleTexts("font", oInvisibleTextFontSize.getId());
1427
-
1428
- aContent.push(
1429
- oEditorHelper.createSelect({
1430
- id: this._getId("FontFamily"),
1431
- ariaLabelledBy: oInvisibleTextFontFamily,
1432
- selectedItemId: this._getId("FontFamilyVerdana"),
1433
- items: this._createFontStyleSelectItems(),
1434
- change: function (oEvent) {
1435
- var oItem;
1436
-
1437
- if (oRTE) {
1438
- oItem = oEvent.getSource().getSelectedItem();
1439
- oRTE.getNativeApi().execCommand('FontName', false, this._getFontStyleCommand(oItem.getText()));
1440
- } else {
1441
- Log.warning("Cannot execute native command: " + 'FontName');
1442
- }
1443
- }.bind(this)
1444
- }).setVisible(bVisibleGroupFont)
1445
- );
1446
-
1447
- aContent.push(
1448
- oEditorHelper.createSelect({
1449
- id: this._getId("FontSize"),
1450
- ariaLabelledBy: oInvisibleTextFontSize,
1451
- selectedItemId: this._getId("FontSize2"),
1452
- items: this._createFontSizeSelectItems(),
1453
- change: function (oEvent) {
1454
- var oItem;
1455
-
1456
- if (oRTE) {
1457
- oItem = oEvent.getSource().getSelectedItem();
1458
- oRTE.getNativeApi().execCommand('FontSize', false, oItem.getText().replace(/\s/g, ""));
1459
- } else {
1460
- Log.warning("Cannot execute native command: " + 'FontSize');
1461
- }
1462
- }
1463
- }).setVisible(bVisibleGroupFont)
1464
- );
1465
- var oRTESplitButton = new RTESplitButton(this._createSplitButtonForDialog("TextColor")).setVisible(bVisibleGroupFont),
1466
- oBackgroundColorButton = oEditorHelper.createSplitButton(this._createSplitButtonForDialog("BackgroundColor")).setVisible(bVisibleGroupFont);
1467
-
1468
- oRTESplitButton._getTextButton().addAriaLabelledBy(oInvisibleTextFontColor);
1469
- aContent.push(oRTESplitButton);
1470
-
1471
- oBackgroundColorButton._getTextButton().addAriaLabelledBy(oInvisibleTextBackgroundColor);
1472
- aContent.push(oBackgroundColorButton);
1722
+ aContent = this._createFontToolbarContent(aToolbarButtonsToCreate, mGroup.visible);
1473
1723
  break;
1474
1724
  case "text-align":
1475
- bVisibleGroupTextAlign = oRTE ? oRTE.getShowGroupTextAlign() : false;
1476
- var bTextAlignLRight = oRTE._getTextDirection() === "rtl";
1477
- var iDefaultItemIndex = bTextAlignLRight ? 2 : 0;
1478
- var aMenuItems = this._createMenuButtonItems("TextAlign");
1479
- aContent.push(
1480
- oEditorHelper.createMenuButton(
1481
- this._getId("TextAlign"),
1482
- aMenuItems,
1483
- function (oEvent) {
1484
- var oSelectedItem, oEditor, oSelectedItemIcon;
1485
-
1486
- if (oRTE) {
1487
- oSelectedItem = oEvent.getParameter("item");
1488
- oEditor = oRTE.getNativeApi();
1489
- oSelectedItemIcon = oSelectedItem.getIcon();
1490
- if (oSelectedItemIcon === this.getParent().getIcon()) {
1491
- var sTextAlign = bTextAlignLRight ? "JustifyRight" : "JustifyLeft";
1492
- // Text Align commands in TinyMCE have a toggle behavior when you set a
1493
- // certain command twice the default command (text-align-left) will be applied
1494
- oEditor.execCommand(sTextAlign);
1495
- } else {
1496
- oEditor.execCommand('Justify' + oToolbar._findTextAlignCommandByIcon(oSelectedItemIcon));
1497
- }
1498
- } else {
1499
- Log.warning("Cannot execute native command: " + 'Justify');
1500
- }
1501
- },
1502
- aMenuItems[iDefaultItemIndex].getIcon(),
1503
- this._oResourceBundle.getText(oCommands["TextAlign"].bundleKey)
1504
- ).setVisible(bVisibleGroupTextAlign)
1505
- );
1725
+ aContent = this._createTextAlignToolbarContent(mGroup.visible);
1506
1726
  break;
1727
+ case "styleselect":
1507
1728
  case "formatselect":
1508
- bVisibleGroupFormatBlock = oRTE ? (this._isButtonGroupAdded("styleselect") || this._isButtonGroupAdded("formatselect")) : false;
1509
-
1510
- if (bVisibleGroupFormatBlock) {
1511
- var oInvisibleTextFormatBlock = oEditorHelper.createInvisibleText({
1512
- text: this._oResourceBundle.getText(oAccessibilityKeys["FormatBlock"])
1513
- }).toStatic();
1514
- this._registerAssociatedInvisibleTexts("formatselect", oInvisibleTextFormatBlock.getId());
1515
- aContent.push(
1516
- oEditorHelper.createSelect({
1517
- id: this._getId("FormatBlock"),
1518
- ariaLabelledBy: oInvisibleTextFormatBlock,
1519
- items: this._createFormatBlockItems(),
1520
- change: function (oEvent) {
1521
- var oSelectedItem;
1522
- if (oRTE) {
1523
- oSelectedItem = oEvent.getSource().getSelectedItem();
1524
- if (oSelectedItem) {
1525
- var currentFormatterCommand = oRTE.getAggregation("_toolbarWrapper")._getFormatBlockCommand(oSelectedItem.getText());
1526
- oRTE.getNativeApi().execCommand('FormatBlock', false, currentFormatterCommand);
1527
- }
1528
- } else {
1529
- Log.warning("Cannot execute native command: " + 'FormatBlock');
1530
- }
1531
- }
1532
- }).setVisible(bVisibleGroupFormatBlock)
1533
- );
1534
- }
1729
+ aContent = this._createFormatSelectToolbarContent(this._isButtonGroupAdded("styleselect") || this._isButtonGroupAdded("formatselect"));
1535
1730
  break;
1536
1731
  case "structure":
1537
- bVisibleGroupStructure = oRTE ? oRTE.getShowGroupStructure() : false;
1538
- oButtonGroups["structure"].forEach(function (oCommand) {
1539
- aContent.push(oEditorHelper.createOverflowToolbarButton(this._createButtonConfig(oCommand)).setVisible(bVisibleGroupStructure));
1540
- }, this);
1732
+ aContent = this._createStructureToolbarContent(aToolbarButtonsToCreate, mGroup.visible);
1541
1733
  break;
1542
1734
  case "clipboard":
1543
- bVisibleGroupClipboard = oRTE ? oRTE.getShowGroupClipboard() : false;
1544
- oButtonGroups["clipboard"].forEach(function (oCommand) {
1545
- aContent.push(oEditorHelper.createOverflowToolbarButton(this._createButtonConfig(oCommand)).setVisible(bVisibleGroupClipboard));
1546
- }, this);
1735
+ aContent = this._createClipboardToolbarContent(aToolbarButtonsToCreate, mGroup.visible);
1547
1736
  break;
1548
1737
  case "undo":
1549
- bVisibleGroupUndo = oRTE ? oRTE.getShowGroupUndo() : false;
1550
- oButtonGroups["undo"].forEach(function (oCommand) {
1551
- aContent.push(oEditorHelper.createOverflowToolbarButton(this._createButtonConfig(oCommand)).setVisible(bVisibleGroupUndo));
1552
- }, this);
1738
+ aContent = this._createUndoToolbarContent(aToolbarButtonsToCreate, mGroup.visible);
1553
1739
  break;
1554
1740
  case "insert":
1555
- bVisibleGroupInsert = oRTE ? oRTE.getShowGroupInsert() : false;
1556
- aContent.push(oEditorHelper.createOverflowToolbarToggleButton(this._createButtonForDialog("InsertImage")).setVisible(bVisibleGroupInsert));
1741
+ aContent = this._createInsertToolbarContent(mGroup.visible);
1557
1742
  break;
1558
1743
  case "link":
1559
- bVisibleGroupLink = oRTE ? oRTE.getShowGroupLink() : false;
1560
- aContent.push(oEditorHelper.createOverflowToolbarToggleButton(this._createButtonForDialog("InsertLink")).setVisible(bVisibleGroupLink));
1561
- aContent.push(oEditorHelper.createOverflowToolbarButton(this._createButtonConfig("Unlink")).setVisible(bVisibleGroupLink));
1744
+ aContent = this._createLinkToolbarContent(aToolbarButtonsToCreate, mGroup.visible);
1562
1745
  break;
1563
1746
  case "table":
1564
- aContent.push(oEditorHelper.createOverflowToolbarButton(this._createButtonForDialog("InsertTable")));
1747
+ aContent.push(oEditorHelper.createOverflowToolbarButton(this._createButtonForDialog("InsertTable")).setVisible(mGroup.visible));
1565
1748
  break;
1749
+ default: break;
1566
1750
  }
1567
1751
 
1568
1752
  return aContent;
@@ -1572,36 +1756,28 @@ sap.ui.define([
1572
1756
  * Adds a Button Group to an existing Toolbar
1573
1757
  *
1574
1758
  * @param {map} [mGroup] Group object
1575
- * @param {boolean} [bFullGroup] If false, the group is generated from a group name
1576
1759
  * @returns {object} this for method chaining
1577
1760
  * @public
1578
1761
  */
1579
- ToolbarWrapper.prototype.addButtonGroupToContent = function (mGroup, bFullGroup) {
1762
+ ToolbarWrapper.prototype.addButtonGroupToContent = function (mGroup) {
1580
1763
  var sGroupName;
1581
1764
  // if the group is generated add it to the button groups object
1582
1765
  // as a custom group (if it contains supported group buttons - ex."table")
1583
- if (!bFullGroup && mGroup.buttons[0] === "table") {
1584
- sGroupName = mGroup.buttons[0];
1585
- sap.ui.richtexteditor.ButtonGroups.custom[mGroup.name] = {
1586
- name: mGroup.buttons[0],
1587
- controls: ["InsertTable"]
1588
- };
1589
- }
1590
1766
 
1591
1767
  // if the group is supported (ex. "table") add it to the button groups object
1592
- if (bFullGroup && mGroup.name === "table") {
1768
+ if (mGroup.name === "table") {
1593
1769
  sGroupName = mGroup.name;
1594
- sap.ui.richtexteditor.ButtonGroups[mGroup.name] = ["InsertTable"];
1770
+ ButtonGroups[mGroup.name] = ["InsertTable"];
1595
1771
  }
1596
1772
 
1597
1773
  // if the group is supported (ex. "formatselect") add it to the button groups object
1598
- if (bFullGroup && (mGroup.name === "formatselect" || mGroup.name === "styleselect")) {
1774
+ if (mGroup.name === "formatselect" || mGroup.name === "styleselect") {
1599
1775
  sGroupName = "formatselect";
1600
- sap.ui.richtexteditor.ButtonGroups[mGroup.name] = ["FormatBlock"];
1776
+ ButtonGroups[mGroup.name] = ["FormatBlock"];
1601
1777
  }
1602
1778
 
1603
1779
  // if not supported return and do not add content
1604
- if (!sap.ui.richtexteditor.ButtonGroups[mGroup.name] && !sap.ui.richtexteditor.ButtonGroups.custom[mGroup.name]) {
1780
+ if (!ButtonGroups[mGroup.name] && !ButtonGroups.custom[mGroup.name]) {
1605
1781
  return this;
1606
1782
  }
1607
1783
 
@@ -1612,7 +1788,7 @@ sap.ui.define([
1612
1788
  }
1613
1789
 
1614
1790
  var oToolbar = this.getAggregation("_toolbar"),
1615
- aContent = this.addButtonGroup(sGroupName),
1791
+ aContent = this._createButtonGroup(mGroup),
1616
1792
  iContentSize = aContent.length,
1617
1793
  i, iStartIndex;
1618
1794
 
@@ -1647,7 +1823,6 @@ sap.ui.define([
1647
1823
  */
1648
1824
  ToolbarWrapper.prototype._findGroupPriorityPosition = function (mGroup) {
1649
1825
  var aGroups = this.getEditor().getButtonGroups(),
1650
- aCustomToolbarGroups = library.ButtonGroups,
1651
1826
  iStartIndex = 0;
1652
1827
 
1653
1828
  // place groups without predefined customToolbarPriority at the end
@@ -1658,10 +1833,23 @@ sap.ui.define([
1658
1833
  // sort groups according to customToolbarPriority
1659
1834
  aGroups = this._sortToolbarContent(aGroups);
1660
1835
 
1661
- aGroups.forEach(function (oGroup) {
1662
- if (oGroup.customToolbarPriority < mGroup.customToolbarPriority && oGroup.name !== mGroup.name) {
1836
+ aGroups
1837
+ // Map all groups to supported buttons that can be created in the custom toolbar
1838
+ // based on the current group configuration
1839
+ .map(function (oGroup) {
1840
+ // We need new object that maps buttons to commands, as they do not map directly and some of the configurations
1841
+ // may have many buttons, which is then translated to single control in the custom toolbar.
1842
+ return {
1843
+ name: oGroup.name,
1844
+ iButtonsCount: this._mapNativeButtonsToCommands(oGroup.name, oGroup.buttons).length,
1845
+ customToolbarPriority: oGroup.customToolbarPriority
1846
+ };
1847
+ }.bind(this))
1848
+ // Find the correct starting index for this group, based on the customToolbarPriority group property
1849
+ .forEach(function (oMappedGroup) {
1850
+ if (oMappedGroup.customToolbarPriority < mGroup.customToolbarPriority && oMappedGroup.name !== mGroup.name) {
1663
1851
  // if the group exist for the customToolbar, add its button count to the startIndex
1664
- iStartIndex += aCustomToolbarGroups[oGroup.name] ? aCustomToolbarGroups[oGroup.name].length : 0;
1852
+ iStartIndex += ButtonGroups[oMappedGroup.name] ? oMappedGroup.iButtonsCount : 0;
1665
1853
  }
1666
1854
  });
1667
1855
 
@@ -1671,8 +1859,8 @@ sap.ui.define([
1671
1859
  /**
1672
1860
  * Helper function for finding the priority of the last group in the toolbar
1673
1861
  *
1674
- * @param {Array} [oGroups] Group name
1675
- * @returns {Number} The priority of the last group in the toolbar
1862
+ * @param {Array} [aGroups] Group name
1863
+ * @returns {number} The priority of the last group in the toolbar
1676
1864
  * @private
1677
1865
  */
1678
1866
  ToolbarWrapper.prototype._getLastGroupPriority = function (aGroups) {
@@ -1692,6 +1880,11 @@ sap.ui.define([
1692
1880
  ToolbarWrapper.prototype.removeButtonGroup = function (sGroupName) {
1693
1881
  var aObjects = this._findGroupedControls(sGroupName);
1694
1882
 
1883
+ // Detach handlers from color picker dialogs if the font group is removed
1884
+ if (sGroupName === "font") {
1885
+ this._modifyPopoverOpeningArrowHandlers(false);
1886
+ }
1887
+
1695
1888
  // destroys associated InvisibleTexts for the group
1696
1889
  this._destroyAssociatedInvisibleTexts(sGroupName);
1697
1890
 
@@ -1819,18 +2012,17 @@ sap.ui.define([
1819
2012
  * @private
1820
2013
  */
1821
2014
  ToolbarWrapper.prototype._findGroupedControls = function (sGroupName) {
1822
- var oButtonGroups = library.ButtonGroups,
1823
- oToolbar = this.getAggregation("_toolbar"),
2015
+ var oToolbar = this.getAggregation("_toolbar"),
1824
2016
  aControls = [];
1825
2017
 
1826
2018
  if (!oToolbar) {
1827
2019
  return [];
1828
2020
  }
1829
2021
 
1830
- if (oButtonGroups[sGroupName]) {
1831
- aControls = oButtonGroups[sGroupName];
1832
- } else if (oButtonGroups.custom[sGroupName]) {
1833
- aControls = oButtonGroups.custom[sGroupName].controls;
2022
+ if (ButtonGroups[sGroupName]) {
2023
+ aControls = ButtonGroups[sGroupName];
2024
+ } else if (ButtonGroups.custom[sGroupName]) {
2025
+ aControls = ButtonGroups.custom[sGroupName].controls;
1834
2026
  }
1835
2027
 
1836
2028
  var aIds = aControls.map(function (sName) {
@@ -1890,6 +2082,9 @@ sap.ui.define([
1890
2082
  case "remove":
1891
2083
  vResult = this._proxyToolbarRemove.apply(this, args);
1892
2084
  break;
2085
+
2086
+ default:
2087
+ break;
1893
2088
  }
1894
2089
 
1895
2090
  return vResult;
@@ -2017,6 +2212,8 @@ sap.ui.define([
2017
2212
  case "number":
2018
2213
  sId = this._customButtons[vItem];
2019
2214
  break;
2215
+ default:
2216
+ break;
2020
2217
  }
2021
2218
 
2022
2219
  vResult = oToolbar.removeContent(sId);
@@ -2028,5 +2225,19 @@ sap.ui.define([
2028
2225
  return vResult;
2029
2226
  };
2030
2227
 
2228
+ /**
2229
+ * Helper function for finding controls in the Toolbar by their corresponding names.
2230
+ *
2231
+ * @param {string} sButtonName Custom toolbar button name (Bold, TextAlign, Italic, TextColor, etc...)
2232
+ * @returns {sap.ui.core.Control|null} The control with the corresponding name or null.
2233
+ */
2234
+ ToolbarWrapper.prototype._findButtonById = function (sButtonName) {
2235
+ var oRTE = this.getEditor();
2236
+ if (!oRTE) {
2237
+ return null;
2238
+ }
2239
+ return Core.byId(oRTE.getId() + this.getId() + "-" + sButtonName);
2240
+ };
2241
+
2031
2242
  return ToolbarWrapper;
2032
2243
  });