'use strict';
/**
* Licensed Materials - Property of IBM
* IBM Cognos Products: BI Dashboard
* (C) Copyright IBM Corp. 2017, 2021
* US Government Users Restricted Rights - Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
define(['underscore', '../../lib/@waca/core-client/js/core-client/utils/BrowserUtils', '../../lib/@waca/core-client/js/core-client/ui/core/Class', '../../lib/@waca/core-client/js/core-client/utils/Utils', '../../lib/@waca/textwidget/dist/summernote', '../../lib/@waca/dashboard-common/dist/utils/HtmlXSSUtils', '../widgets/staticwidget/text/ContentEditableSelectionManager', '../../lib/@waca/dashboard-common/dist/ui/dialogs/TextToolbarCompactDialog', '../../lib/@waca/dashboard-common/dist/ui/AuthoringToolbar', '../../app/nls/StringResources', '../widgets/PropertiesUtil', 'jquery', './TextFitUtil', '../../lib/@waca/textwidget/src/js/base/core/agent'], function (_, BrowserUtils, Class, Utils, Summernote, HtmlCleanser, ContentEditableSelectionManager, TextToolbar, Toolbar, resources, PropertiesUtil, $, TextFitUtil, agent) {
var F12 = 123;
var ENTER_KEY = 13;
var WHITELISTED_ELEMENTS = ['
', '
', '', '', '', '', '
', '', '', '', '', '', '- '];
// Summernote attributes that are used in Properties Pane
var WHITELISTED_PROPERTIES = ['color', 'font-bold', 'font-family', 'font-italic', 'font-size', 'font-strikethrough', 'font-subscript', 'font-superscript', 'font-underline', 'insertOrderedList', 'insertUnorderedList', 'text-align', 'text-format'];
var cleanContentElements = function cleanContentElements(content) {
return HtmlCleanser.cleanseContentElements(content, WHITELISTED_ELEMENTS, true);
};
var getTextHTML = function getTextHTML(options) {
var initialPlaceholder = options.text ? '' + _.escape(options.text) + '' : '
';
return '' + initialPlaceholder + '
';
};
var TextEditor = Class.extend({
SUMMERNOTE_CLASS: '.summernote',
EDITING_AREA: '.note-editable',
TEXT_FITTED: '.textFitted',
savedSel: null,
isResponsive: false,
autoSaveInterval: 2000,
isBold: false,
/**
* Initialize Text editor with the eleemnt where you wanna have text editing capabilities, and a reference to the widget.
*
* @param {Jquery element} options.node The element where we want to initialize summernote
* @param {Jquery element} options.container Element that contains the node.
* @param {Jquery element} options.toolbarNode Element that the toolbar will use to place itself
* @param {Object} options.fonts Object to override the default font properties
* @param {Object} options.fontSizes Object to override the default font sizes
* @param {Object} options.widget A reference to the widget where we want text editing capabilities.
*/
init: function init(options) {
this.node = options.node;
this.isResponsive = options.isResponsive;
// TODO: The initSummernote will update the text content and cleanse it again. Should be consolidated with above code in one place.
this.initSummernote();
this.getEditingArea().attr('contenteditable', false);
this.container = options.container;
this.widget = options.widget;
this.colorsService = this.widget.getDashboardApi().getFeature('Colors');
var customFonts = this.widget.getDashboardApi().getFeature('DashboardSettings').get('fonts');
var fonts = Array.isArray(customFonts) ? customFonts.concat(TextEditor.FONTFAMILY_CHOICES) : TextEditor.FONTFAMILY_CHOICES;
this._toolbarDock = this.widget.getDashboardApi().getFeature('ToolbarDock');
this._contentActions = this.widget.getDashboardApi().getFeature('ContentActions');
this._dashboardState = this.widget.getDashboardApi().getFeature('DashboardState');
this._icons = this.widget.getDashboardApi().getFeature('Icons');
this.toolbarNode = options.toolbarNode;
//TODO: options is kept for backward compatibility; it may be removed eventually
this._fontFamilyChoices = options.fonts || fonts;
this._fontSizeChoices = options.fontSizes || TextEditor.FONTSIZE_CHOICES;
this.shouldResizeViz = options.shouldResizeViz;
this.supportsLists = options.supportsLists;
this.numberOfLines = 1;
this.toolbar = new Toolbar({
container: $('body'),
placement: 'top',
noFocus: true
});
var supportsTextWrap = false;
this._ext = options.extension || {};
if (this._ext.isTextWrapOn) {
supportsTextWrap = true;
}
this.textToolbar = new TextToolbar({
onStateChange: this.onToolbarStateChange.bind(this),
textNode: this.getEditingArea(),
properties: this.getToolbarProperties(),
initialState: options.initialState,
supportsLists: options.supportsLists,
supportsTextWrap: supportsTextWrap
});
this.fillText();
var onInit = this._ext.onInit;
onInit && onInit(this);
// Save the content so that we can check if the content has changed.
this.lastSavedData = this.getContent();
this.toolbar.on('toolbar:hide', this.hideTextToolbar, this);
this.widget.eventRouter.on('textToolbar:hide', this.hideTextToolbar, this);
this.widget.eventRouter.on('widget:hideToolbar', this.hideTextToolbar, this);
},
/**
* Initialize summernote in the node given
*/
initSummernote: function initSummernote() {
var $summerNote = this.node.children(this.SUMMERNOTE_CLASS);
var preDefinedHtml;
if (!$summerNote.length) {
if (this.node.children().length) {
preDefinedHtml = this.node.html();
this.node.children().remove();
}
$summerNote = this.node.append('').children('.summernote');
}
var isAlreadyInitialized = !!$summerNote.data('summernote');
if (!isAlreadyInitialized) {
preDefinedHtml = preDefinedHtml || this.getEditingArea().remove().html();
this.node.find('.note-editor').remove();
$summerNote.summernote({
airMode: true,
popover: {}, //disable the popover
disableDragAndDrop: true,
lineWrapping: true,
keyMap: this._getSummernoteShortcuts()
});
if (preDefinedHtml && HtmlCleanser.isValidHtmlContent(preDefinedHtml)) {
var $editingArea = this.getEditingArea();
$editingArea.html(HtmlCleanser.cleanseContentElements(preDefinedHtml, WHITELISTED_ELEMENTS, true));
// clear old saved jquery textfill font-size value
$editingArea.find('>p').css('font-size', '');
}
}
},
/**
* gets the default font
* @return {Object} font default font properties
* @returns {string} font.id id of the font
*/
getDefaultFont: function getDefaultFont() {
var id = '';
this._fontFamilyChoices.forEach(function (font) {
if (font.default === true) {
id += font.value;
}
});
return { id: id };
},
_getSummernoteShortcuts: function _getSummernoteShortcuts() {
return {
pc: {
'ENTER': 'insertParagraph',
'CTRL+Z': 'undo',
'CTRL+Y': 'redo',
'TAB': '', /* tabbing is handled in onKeyDown */
'SHIFT+TAB': '',
'CTRL+B': 'bold',
'CTRL+I': 'italic',
'CTRL+U': 'underline',
'CTRL+SHIFT+L': 'justifyLeft',
'CTRL+SHIFT+E': 'justifyCenter',
'CTRL+SHIFT+R': 'justifyRight',
'CTRL+SHIFT+NUM7': '', /* inserting lists is handled in onKeyDown */
'CTRL+SHIFT+NUM8': ''
},
mac: {
'ENTER': 'insertParagraph',
'CMD+Z': 'undo',
'CMD+SHIFT+Z': 'redo',
'TAB': '', /* tabbing is handled in onKeyDown */
'SHIFT+TAB': '',
'CMD+B': 'bold',
'CMD+I': 'italic',
'CMD+U': 'underline',
'CMD+SHIFT+L': 'justifyLeft',
'CMD+SHIFT+E': 'justifyCenter',
'CMD+SHIFT+R': 'justifyRight',
'CMD+SHIFT+NUM7': '', /* inserting lists is handled in onKeyDown */
'CMD+SHIFT+NUM8': ''
}
};
},
destroy: function destroy() {
if (this.toolbar) {
this.toolbar.remove();
this.toolbar = null;
}
if (this.textToolbar) {
this.textToolbar.remove();
this.textToolbar = null;
}
this.selectionManager = null;
this._getSummerNote().summernote('destroy');
},
/**
* Initialize ContentEditableSelectionManager in the element matched by the selector.
*
* @param {String} selector Selector of the element
*/
initContentEditable: function initContentEditable(selector) {
this.selectionManager = new ContentEditableSelectionManager(this.node, selector);
},
/**
* insert a text to the editor
* @param {String} text - string text to insert to the editor
*/
setText: function setText(text) {
this.getEditingArea().html(HtmlCleanser.cleanseContentElements(text, WHITELISTED_ELEMENTS, true));
this.editingAreaHeight = this._getHeight();
var onSetText = this._ext.onSetText;
onSetText && onSetText(this);
},
getNode: function getNode() {
return this.node;
},
/**
* Defect 230351: Put back focus on text when the focus is stolen by the ODT
*/
_putBackFocusOnText: function _putBackFocusOnText() {
this.setFocus();
this.widget.eventRouter.off('widget:hideToolbar:done');
},
setFocus: function setFocus() {
this._getSummerNote().summernote('focus');
},
/*
* Helpers.
*/
selectionBindNodeEvents: function selectionBindNodeEvents() {
this.fnSelectionOnKeyDown = this.selectionOnKeyDown.bind(this);
this.node.on('keydown', this.fnSelectionOnKeyDown);
},
selectionUnbindNodeEvents: function selectionUnbindNodeEvents() {
if (this.fnSelectionOnKeyDown) {
this.node.off('keydown', this.fnSelectionOnKeyDown);
this.fnSelectionOnKeyDown = null;
}
},
selectionOnKeyDown: function selectionOnKeyDown(event) {
this.selectionManager.filterKeypress(event);
},
addEditingEvents: function addEditingEvents(options) {
// Detach the enter editing mode gestures.
this.detachEnterEditEvents();
this.bindNodeEvents();
this._startAutoSaver(options);
//SMEditTest
var onEditStart = this._ext.onEditStart;
onEditStart && onEditStart(this);
//SMEditTest
},
removeEditingEvents: function removeEditingEvents(options) {
this.unbindNodeEvents();
this._stopAutoSaver(options);
// Allow the user to enter editing mode again through gestures.
this.attachEnterEditEvents();
var onEditEnd = this._ext.onEditEnd;
onEditEnd && onEditEnd(this);
},
/*
* Event related
*/
onInitialTouchDown: function onInitialTouchDown() {
this.hasInitiallyTouchedDown = true;
},
onInitialTouchUp: function onInitialTouchUp() {
if (this.hasInitiallyTouchedDown) {
this.hasInitiallyTouchedDown = false;
//Hide contextual toolbar
this.widget.eventRouter.trigger('widget:hideToolbar');
/**
* Even tough toolbar is hidden, it can sometimes be rendered and focused because of the timer set with the SetTimout
* Defect 230351 fix: Put back focus on text when the focus is stolen by the ODT
*/
this.widget.eventRouter.on('widget:hideToolbar:done', this._putBackFocusOnText, this);
this.toggleEditing(true);
} else {
this.widget.eventRouter.off('widget:hideToolbar:done');
}
},
attachEnterEditEvents: function attachEnterEditEvents() {
if (!this.fnTouchDown && this.widget.isAuthoringMode && this.widget.chromeSelected) {
this.fnTouchDown = this.onInitialTouchDown.bind(this);
this.fnTouchUp = this.onInitialTouchUp.bind(this);
this.node.on('touchstart', this.fnTouchDown).on('touchend', this.fnTouchUp).on('mousedown', this.fnTouchDown).on('mouseup', this.fnTouchUp);
}
},
detachEnterEditEvents: function detachEnterEditEvents() {
if (this.fnTouchDown) {
this.node.off('touchstart', this.fnTouchDown).off('touchend', this.fnTouchUp).off('mousedown', this.fnTouchDown).off('mouseup', this.fnTouchUp);
this.fnTouchDown = null;
this.fnTouchUp = null;
}
},
save: function save(options) {
var _this = this;
var data = this.getContent();
var lastSavedData = this.lastSavedData;
if (this.isResponsive) {
// The auto font-size is screen-size specific, and so does not need to be
// persisted. We remove it from the string compare to avoid triggering
// undesired or unnecessary events.
var _clearFontSize = function _clearFontSize(html) {
var $el = $('' + html + '
');
$el.find(_this.TEXT_FITTED).css('font-size', '');
return $el.html();
};
data = _clearFontSize(data);
lastSavedData = _clearFontSize(lastSavedData);
}
//truncate style does not need to be persisted
data = this._clearTruncateStyle(data);
lastSavedData = this._clearTruncateStyle(lastSavedData);
// Only update if the value has changed.
if (data !== lastSavedData) {
if (!options) {
var transactionId = _.uniqueId('_text_');
this.widget.onPropertyUpdate({
category: 'saveTitle',
transactionId: transactionId
});
} else {
options.category = 'saveTitle';
this.widget.onPropertyUpdate(options);
}
this.fillText();
}
},
setTruncateOn: function setTruncateOn() {
this.getEditingArea().find(this.TEXT_FITTED).addClass('truncateTextOn');
this.getEditingArea().find('p').addClass('truncateText');
},
setTruncateOff: function setTruncateOff() {
this.getEditingArea().find(this.TEXT_FITTED).removeClass('truncateTextOn');
this.getEditingArea().find('p').removeClass('truncateText');
},
updateLastSavedText: function updateLastSavedText(value) {
if (this.lastSavedData !== value) {
this.lastSavedData = value;
}
},
_clearTruncateStyle: function _clearTruncateStyle(html) {
var $el = $('' + html + '
');
$el.find('p').removeClass('truncateText');
return $el.html();
},
updateCssOnParagraphs: function updateCssOnParagraphs(addedClass, removedClass) {
this.getEditingArea().find('p').removeClass(removedClass);
this.getEditingArea().find('p').addClass(addedClass);
},
_startAutoSaver: function _startAutoSaver(options) {
if (!this.autoSaverInterval) {
//Save then start autosaver
this.save(options);
this.autoSaverInterval = setInterval(this.save.bind(this), this.autoSaveInterval);
}
},
_stopAutoSaver: function _stopAutoSaver(options) {
if (this.autoSaverInterval) {
this.save(options);
clearInterval(this.autoSaverInterval);
this.autoSaverInterval = null;
}
},
/**
* Returns whether the event is for the modifier key (cmd on Mac, ctrl on other platforms).
*/
_isModifierKey: function _isModifierKey(event) {
return event.ctrlKey || event.metaKey;
},
onKeyDown: function onKeyDown(event) {
var _this2 = this;
// Prevent arrow keys from moving widget around while editing text.
event.stopPropagation();
// TODO backspace will delete the editor, this fix can prevent that, but a better solution needs to be found
if (this.textIsEmpty() && (event.which === 8 || event.which === 46)) {
event.preventDefault();
}
if (event.which === ENTER_KEY) {
this._resizeViz();
}
// handle tabbing and indenting
if (event.which === 9) {
var maxNestingLevelReached = false;
var listItemStartSelected = false;
var listItems = this.getSelectedListItems();
var selRange = this._getRefinedSelectionRange();
listItems.forEach(function (li) {
var $li = $(li);
if (!maxNestingLevelReached && $li.parentsUntil(_this2.EDITING_AREA, 'ul, ol').length > 3) {
maxNestingLevelReached = true;
}
if (!listItemStartSelected && _this2._isNodeStartSelected(li, selRange)) {
listItemStartSelected = true;
}
});
if (listItems.length && listItemStartSelected) {
if (event.shiftKey) {
this._getSummerNote().summernote('outdent');
} else if (!maxNestingLevelReached) {
this._getSummerNote().summernote('indent');
}
} else {
if (event.shiftKey) {
this._focusToolbar();
} else {
this._getSummerNote().summernote('tab');
}
}
event.preventDefault();
this.fillText();
this.save();
}
if (this.supportsLists && (event.which === 55 || event.which === 56) && this._isModifierKey(event) && event.shiftKey) {
this.modifyList(event.which === 55 ? 'insertUnorderedList' : 'insertOrderedList');
this.fillText();
this.save();
this.updatePropertiesIfNecessary();
}
this.selectionOnKeyDown(event);
},
_focusToolbar: function _focusToolbar() {
if (this._toolbarDock && this._toolbarDock.isContentToolbarDocked()) {
this._toolbarDock.focusODT();
} else {
this.toolbar.focus();
}
},
_isToolbarOpened: function _isToolbarOpened() {
return this.toolbar && this.toolbar.isOpened;
},
hideTextToolbar: function hideTextToolbar() {
if (this._isToolbarOpened()) {
this.toolbar.remove();
}
},
show: function show(immediateEditing) {
this.node.show();
this.fillText();
if (immediateEditing) {
this.toggleEditing(true);
}
},
hide: function hide() {
this.toggleEditing(false);
this.node.hide();
},
_getNumberOfLines: function _getNumberOfLines() {
return this.getEditingArea().find('p').length;
},
_getHeight: function _getHeight() {
return this.getEditingArea().height();
},
_resizeVizIfHeightChanged: function _resizeVizIfHeightChanged() {
if (this._getHeight() !== this.editingAreaHeight) {
this._resizeViz();
this.editingAreaHeight = this._getHeight();
}
},
_resizeViz: function _resizeViz() {
var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {
hideToolbar: false
};
if (this.shouldResizeViz) {
this.widget.widgetChromeEventRouter.trigger('title:resizeViz', options);
}
},
/*onKeyUp - Checking for the shift F12 event so that we can exit the textwidget.
* - Prevent fn-backspace or delete from deleting the widget while editing text.
*/
onKeyUp: function onKeyUp(event) {
if (event.which === 27 && this._isToolbarOpened()) {
this.hideTextToolbar();
this.node.focus();
} else if (event.which === 27 || event.which === F12 && event.shiftKey) {
event.stopPropagation();
this.toggleEditing(false);
this.container.focus();
} else if (event.which === 8 || event.which === 46) {
// delete or fn-backspace
event.stopPropagation();
}
this._resizeVizIfHeightChanged();
this.numberOfLines = this._getNumberOfLines();
this.fillText();
// TODO: The updatePropertiesIfNecessary was added to help offset missing functionality from the
// TextSelectionNormalizer class. The TextSelectionNormalizer class mimics events (selectionchange) that some browsers
// don't handle (like older firefox 45). This line can be removed once TextSelectionNormalizer has been
// restored.
this.updatePropertiesIfNecessary();
},
/**
* prevent moving the widget in authoring mode when we highlight text using the mouse
*/
onMouseMove: function onMouseMove(event) {
if (this.hasMouseDownInside) {
event.stopPropagation();
}
},
onMouseUp: function onMouseUp(event) {
if (this.hasMouseDownInside) {
this.hasMouseDownInside = false;
event.stopPropagation();
if (this.fnMouseMove) {
$(document).off('mousemove', this.fnMouseMove);
this.fnMouseMove = null;
}
if (this.fnMouseUp) {
$(document).off('mouseup', this.fnMouseUp);
this.fnMouseUp = null;
}
}
},
onMouseDown: function onMouseDown(event) {
var target = event.target;
if (target.tagName !== 'SELECT' && target.tagName !== 'INPUT' && target.tagName !== 'TEXTAREA' && !target.isContentEditable) {
event.preventDefault();
}
},
onBlur: function onBlur() {
this.selection = this.saveSelection();
},
onMouseDownInside: function onMouseDownInside(event) {
event.stopPropagation();
this.hasMouseDownInside = true;
// Add mouse move and up events. Only start listening for them now so that we aren't continuously
// tracking the mouse movements.
this.fnMouseMove = this.onMouseMove.bind(this);
this.fnMouseUp = this.onMouseUp.bind(this);
$(document).on('mousemove', this.fnMouseMove).on('mouseup', this.fnMouseUp);
},
onTouchStart: function onTouchStart(event) {
// Prevent the move widget handler from taking over.
event.stopPropagation();
},
keepTextSelected: function keepTextSelected() {
if (Utils.isIpad()) {
this.savedSel = this.saveSelection();
}
},
onTextSelected: function onTextSelected() {
var _this3 = this;
if (!this.getEditingArea().is(document.activeElement)) {
// if the selection changes because the user
// clicked elsewhere, we don't care.
return Promise.resolve();
}
// Instantiate this.selection to prepare for new text selection
if (this.selection) {
this.selection = null;
}
var currentSelection = this._getSummerNote().summernote('createRange').toString();
if (!currentSelection || currentSelection !== this.lastSelection) {
return this.showTextToolbar().then(function () {
// Throttle the properties page update
if (_this3.delayedPropertyUpdate) {
clearTimeout(_this3.delayedPropertyUpdate);
}
_this3.delayedPropertyUpdate = setTimeout(function () {
if (!(Utils.isIpad() && $('SELECT:focus').length > 0)) {
this.delayedPropertyUpdate = null;
this.updatePropertiesIfNecessary();
}
}.bind(_this3), 500);
_this3.lastSelection = currentSelection;
if (Utils.isIpad()) {
_this3.savedSel = _this3.saveSelection();
}
});
}
},
bindNodeEvents: function bindNodeEvents() {
this.fnOnKeyDown = this.onKeyDown.bind(this);
this.fnOnKeyUp = this.onKeyUp.bind(this);
this.fnOnPaste = this.onPaste.bind(this);
// Need to keep these events on the div since they won't fire on the inner span
this.node.on('keydown', this.fnOnKeyDown).on('keyup', this.fnOnKeyUp).on('paste', this.fnOnPaste);
this.fnOnMouseDownInside = this.onMouseDownInside.bind(this);
this.fnOnBlur = this.onBlur.bind(this);
this.fnOnTouchStart = this.onTouchStart.bind(this);
this.fnkeepTextSelected = this.keepTextSelected.bind(this);
// Special handlers for when we click/touch on the text to prevent some of the widget default behavior (i.e. widget move)
this.getEditingArea().on('mousedown', this.fnOnMouseDownInside).on('blur', this.fnOnBlur).on('touchstart', this.fnOnTouchStart).on('focusout', this.fnkeepTextSelected);
this.fnMouseDown = this.onMouseDown.bind(this);
this.fnSelectionChange = this.onTextSelected.bind(this);
$(document).on('mousedown', this.fnMouseDown).on('selectionchange', this.fnSelectionChange);
},
unbindNodeEvents: function unbindNodeEvents() {
this.node.off('keydown', this.fnOnKeyDown).off('keyup', this.fnOnKeyUp).off('paste', this.fnOnPaste);
this.getEditingArea().off('mousedown', this.fnOnMouseDownInside).off('touchstart', this.fnOnTouchStart).off('blur', this.fnOnBlur).off('focusout', this.fnkeepTextSelected);
if (this.fnSelectionChange) {
$(document).off('selectionchange', this.fnSelectionChange);
this.fnSelectionChange = null;
}
if (this.fnMouseDown) {
$(document).off('mousedown', this.fnMouseDown);
this.fnMouseDown = null;
}
},
_replaceContent: function _replaceContent(options) {
var currentContent = this.node.find(this.EDITING_AREA);
var prevContent = $(options.value).find(this.EDITING_AREA);
currentContent.html(prevContent.html());
this._resizeVizIfHeightChanged();
},
_didContentChange: function _didContentChange(value) {
if (value) {
var prevContent = $(value).find(this.EDITING_AREA).html();
var currentContent = this.getContent();
return prevContent && currentContent && prevContent !== currentContent;
} else {
return false;
}
},
applyContent: function applyContent(options) {
//Reinitialize summernote if necessary after undo/redo
this.initSummernote();
if (this._didContentChange(options.value)) {
this._replaceContent(options);
if (options.sender === 'TranslationService') {
this.fillText();
}
// We need to update the last saved data here, before replacing content with placeholder. See Defect 254590.
this.lastSavedData = this.getContent();
// update placeholder on undo / redo
if (options.sender === 'UndoRedoController' && this.widget.placeholder) {
this.widget.updatePlaceholder();
}
} else {
this.lastSavedData = this.getContent();
}
},
onPaste: function onPaste(event) {
this._pasteTextExtractedFromHTML(event);
this.fillText();
},
/** put window behind an accessor to make it possible to unit test. */
_getWindow: function _getWindow() {
return window;
},
/** Gets the paste data from the paste event, extracts the text out of whatever else is there,
* and then inserts it where ever the caret is.
*/
_pasteTextExtractedFromHTML: function _pasteTextExtractedFromHTML(event) {
var pastedData;
// Stop data actually being pasted into the element. preventDefault() prevents the
// text from being 'pasted twice', once with the formatting and the second time without it (here).
event.preventDefault();
// Get pasted data via clipboard API and insert it where the cursor is.
// This version is apparently more efficient than the alternative (below).
if (event.originalEvent.clipboardData) {
pastedData = event.originalEvent.clipboardData.getData('Text');
this._getWindow().document.execCommand('insertText', false, pastedData);
} else {
// Special case for IE
pastedData = this._getWindow().clipboardData.getData('Text');
var selected = this._getWindow().getSelection().getRangeAt(0);
selected.deleteContents();
selected.insertNode(this._getWindow().document.createTextNode(pastedData));
}
},
isEditing: function isEditing() {
return this.container.hasClass('editing');
},
onToolbarStateChange: function onToolbarStateChange(changedState, options) {
var restoreDefaults = options && options.restoreDefaults;
if (restoreDefaults) {
// 1. The summernote api for bold, italic and underline only offers toggles.
// 2. The current text selection may have mixed styles. (e.g: only some letters of a word are bold)
// ** Therefore, removing all formatting before restoring default styles
this._getSummerNote().summernote('removeFormat');
}
for (var propChanged in changedState) {
if (propChanged === 'underline' || propChanged === 'bold' || propChanged === 'italic') {
var value = changedState[propChanged];
if (!restoreDefaults || value) {
this.modifyTextFormat(propChanged, options);
}
} else if (propChanged === 'fontSize') {
this.onFontSizeUpdate(propChanged, changedState.fontSize);
} else if (propChanged === 'font') {
this.onFontFamilyUpdate('fontFamily', changedState.font);
} else if (propChanged === 'color') {
if (this._isHexColor(changedState.color)) {
this.modifyTextColor(this._findColorIdFromHex(changedState.color));
} else {
// For incoming non-hex colors, we directly set the class on the node, and then update properties to let the toolbar pick up the hexcode for the new color
this.modifyTextColor(changedState.color);
}
} else if (propChanged === 'justifyLeft' || propChanged === 'justifyRight' || propChanged === 'justifyCenter') {
if (changedState[propChanged]) {
this.modifyTextAlignment(propChanged);
}
} else if (propChanged === 'insertUnorderedList' || propChanged === 'insertOrderedList') {
this.modifyList(propChanged, changedState[propChanged]);
} else if (propChanged === 'textWrap') {
this._ext.onTextWrapChanged(changedState[propChanged]);
}
}
this.updatePropertiesIfNecessary();
if (!options || !options.silent) {
this.lastActiveStyles = this.getActiveStyles();
this.fillText();
this.save();
this.widget.refreshPropertiesPane();
}
},
_findColorHexFromId: function _findColorHexFromId(colorId) {
var colorPalette = this._getTextColorChoices();
var found = _.find(colorPalette, function (color) {
return color.id === colorId;
});
if (!found && this.colorsService.isCustomColor(colorId)) {
return this.colorsService.getHexColorFromClassName(colorId);
}
return found ? found.hexValue : found;
},
_findColorIdFromHex: function _findColorIdFromHex(colorValue) {
var colorPalette = this._getTextColorChoices();
var found = _.find(colorPalette, function (color) {
return color.hexValue.toUpperCase() === colorValue.toUpperCase();
});
if (!found) {
return this.colorsService.getColorClassName(colorValue);
}
return found ? found.id : found;
},
convertStyleToToolbarState: function convertStyleToToolbarState(styles) {
var state = {};
if (styles['font-size']) {
state.fontSize = styles['font-size'] + '';
}
if (styles.color) {
state.color = this._findColorHexFromId(styles.color);
}
if (styles['font-family']) {
state.font = this._convertCssToFontId(styles['font-family'])[0];
}
if (styles['text-align']) {
state[styles['text-align']] = true;
}
state.insertUnorderedList = styles.insertUnorderedList;
state.insertOrderedList = styles.insertOrderedList;
//Set the text format applied to true (underline,bold,italic);
state.bold = state.underline = state.italic = false;
_.each(styles['text-format'], function (format) {
state[format] = true;
});
return state;
},
showTextToolbar: function showTextToolbar() {
var _this4 = this;
if (this._toolbarDock && this._toolbarDock.isContentToolbarDocked()) {
if (!this.textToolbar.isRendered) {
var toolbarState = this.convertStyleToToolbarState(this.getActiveStyles());
// refresh the properties options before re-render the text toolbar
this.textToolbar.properties = this.getToolbarProperties();
this._setTextWrapState(toolbarState);
this.textToolbar.setState(toolbarState);
this._toolbarDock.updateODTState([{
type: 'SubView',
responsive: true,
editable: false,
changedAction: null,
subView: this.textToolbar,
removeThenApplyAction: true,
action: function action() {}
}, {
name: 'textToolbarDock',
type: 'Button',
label: resources.get('undockToolbar'),
icon: this._icons.getIcon('undock-icon').id,
disabled: function disabled() {
return _this4._dashboardState.getUiState().focus;
},
actions: {
apply: function () {
this._toolbarDock.disableDockedODT();
this.showTextToolbar();
}.bind(this)
}
}]);
}
return Promise.resolve();
} else {
if (this._isToolbarOpened()) {
return Promise.resolve();
} else {
// unmount react component before clear items
this.textToolbar.remove();
this.toolbar.clearItems();
var _toolbarState = this.convertStyleToToolbarState(this.getActiveStyles());
// refresh the properties options before re-render the text toolbar
this.textToolbar.properties = this.getToolbarProperties();
this._setTextWrapState(_toolbarState);
this.textToolbar.setState(_toolbarState);
var useMoveHandle = this.toolbarNode[0] === this.container[0] || $.contains(this.toolbarNode[0], this.container[0]);
var $moveHandle = this.toolbarNode.find('.moveHandle');
var selectionContext = useMoveHandle && $moveHandle.length ? $moveHandle[0] : this.container[0];
this.toolbar.setSelectionContext([selectionContext]);
return this.toolbar.addItems([{
type: 'SubView',
responsive: true,
editable: false,
changedAction: null,
subView: this.textToolbar, //Here the toolkit toolbar is rendered but not visible. Returns a promise.
removeThenApplyAction: true,
action: function action() {}
}, {
name: 'textToolbarDock',
type: 'Button',
label: resources.get('dockToolbar'),
icon: this._icons.getIcon('dock-icon').id,
actions: {
apply: function () {
this._toolbarDock.enableDockedODT();
this.textToolbar.remove();
this.toolbar.remove();
this.showTextToolbar();
}.bind(this)
}
}]).then(function () {
return _this4.toolbar.show();
});
}
}
},
_setTextWrapState: function _setTextWrapState(toolbarState) {
if (this._ext && this._ext.isTextWrapOn) {
toolbarState.textWrap = this._ext.isTextWrapOn();
}
},
_selectContent: function _selectContent() {
var range = document.createRange();
var isMissingParagraphElement = this.getEditingArea().find('p').length === 0;
// FIXME: The paragraph element shouldn't be getting deleted at all, but our current implementation with IE 11 allows this to happen
var nodeContents = isMissingParagraphElement ? this.getEditingArea().get(0) : this.getEditingArea().find('p').get(0);
range.selectNodeContents(nodeContents);
var sel = window.getSelection();
this._clearSelection(sel);
sel.addRange(range);
},
_focusOnText: function _focusOnText() {
var _this5 = this;
this._selectContent();
this.getEditingArea().focus();
return this.showTextToolbar().then(function () {
_this5._selectContent();
_this5.getEditingArea().focus(); // Required for Firefox, Defect 202868 fix
_this5.widget.refreshPropertiesPane({
'selectedTab': resources.get('propText')
});
});
},
toggleEditing: function toggleEditing(editing, options) {
var wasEditing = this.isEditing(this.container);
var toggle = editing === undefined ? !wasEditing : editing;
this.container.toggleClass('editing', toggle);
this.getEditingArea().attr('contenteditable', toggle);
if (toggle !== wasEditing) {
this._resizeViz();
}
if (toggle) {
if (!wasEditing) {
this.addEditingEvents(options);
}
this._focusOnText();
} else if (wasEditing && !toggle) {
this._clearSelection(window.getSelection());
this.removeEditingEvents(options);
if (this._toolbarDock && this._toolbarDock.isContentToolbarDocked()) {
var currentSelection = this.widget.getDashboardApi().getCanvas().getSelectedContentList();
var selectedIds = currentSelection.map(function (content) {
return content.getId();
});
this._toolbarDock.updateODTState(this._contentActions.getContentActionList(selectedIds), selectedIds);
} else {
this.hideTextToolbar();
}
//when toggle is off, remove the text details tab from the property panel by refreshing the property panel
this.widget.refreshPropertiesPane();
}
},
_removeClassFromSelection: function _removeClassFromSelection(command) {
var map = {
'fontSize': /rt_fontSize(\d+|\w+)/g,
'fontFamily': /rt_fontFamily\w+(-\w+)?/g,
'textColor': /customColor.+|color\d+|grayShade\d+|responsiveColor/g
};
if (command && map[command]) {
return function (index, cls) {
return (cls.match(map[command]) || []).join(' ');
};
}
},
_addClassToSelection: function _addClassToSelection(command, value) {
var map = {
'fontSize': 'rt_fontSize',
'fontFamily': '',
'textColor': ''
};
return map[command] + value;
},
getToolbarProperties: function getToolbarProperties() {
var colorPalette = this._getTextColorChoices();
var colorValues = [];
_.each(colorPalette, function (color) {
colorValues.push(color.hexValue);
});
return {
'fonts': this._fontFamilyChoices,
'fontSizes': this._fontSizeChoices,
'colors': colorValues
};
},
/**
* livewidget_cleanup: [todo] we might need to move this to a proper place..
* Implementation of {@link PropertiesProviderAPI#getPropertyLayoutList}
*/
getPropertyLayoutList: function getPropertyLayoutList() {
if (!this.isEditing()) {
return [];
}
var layoutList = [{
id: 'textDetail',
type: 'Group',
label: resources.get('tabName_textDetails'),
position: 1
}, {
id: 'fontFamily',
type: 'Section',
collapsible: false,
label: resources.get('textFontFamily'),
position: 1
}, {
id: 'fontFamilyLine',
type: 'SingleLineLinks',
items: [{
id: 'left',
align: 'left',
items: []
}, {
id: 'right',
align: 'right',
items: []
}]
}].concat(this.getPropertyLayoutControlList());
return layoutList;
},
getPropertyList: function getPropertyList() {
return [];
},
getPropertyLayoutControlList: function getPropertyLayoutControlList() {
if (!this.isEditing()) {
return [];
}
var layoutControlList = [];
this.lastActiveStyles = this.getActiveStyles();
layoutControlList.push.apply(layoutControlList, this._getFontFamilyProperties());
layoutControlList.push(this._getFontSizeProperty());
layoutControlList.push(this._getTextColorProperty());
layoutControlList.push(this._getFontWeightProperty());
layoutControlList.push(this._getTextAlignmentProperty());
if (this.supportsLists) {
layoutControlList.push(this._getListProperty());
}
return layoutControlList;
},
_getFontFamilyProperties: function _getFontFamilyProperties() {
var activeStyle = this.lastActiveStyles['font-family'];
var selected = activeStyle ? this._convertCssToFontId(activeStyle) : [];
var cssClass = this._findFontFamilyItemFromValue(selected[0], this._fontFamilyChoices);
if (!cssClass) {
selected = [this.getDefaultFont().id];
cssClass = this._findFontFamilyItemFromValue(selected[0], this._fontFamilyChoices);
}
var subCssClass = _.find(cssClass.subCssClasses, function (subCssClass) {
return subCssClass.cssClass === cssClass.cssClass;
});
return [{
id: 'fontFamily',
editor: {
sectionId: 'textDetail.fontFamily.fontFamilyLine.left',
position: 1,
uiControl: {
type: 'DropDown',
ariaDescribedby: resources.get('textFontFamily'),
options: this._fontFamilyChoices,
responsive: false,
style: 'width: 156px;',
value: selected[0],
onChange: this.onFontFamilyUpdate.bind(this)
}
}
}, {
id: 'fontFamilySubClass',
editor: {
sectionId: 'textDetail.fontFamily.fontFamilyLine.left',
position: 2,
hidden: !cssClass || !cssClass.subCssClasses || cssClass.subCssClasses.length === 0,
uiControl: {
type: 'DropDown',
ariaDescribedby: resources.get('textFontFamily'),
options: cssClass && cssClass.subCssClasses,
value: subCssClass && subCssClass.value,
onChange: this.onFontFamilyUpdate.bind(this),
style: 'width:80px;',
responsive: false
}
}
}];
},
_getFontSizeProperty: function _getFontSizeProperty() {
return {
id: 'fontSize',
editor: {
sectionId: 'textDetail',
position: 2,
uiControl: {
type: 'DropDown',
label: resources.get('textFontSize'),
options: this._fontSizeChoices,
onChange: this.onFontSizeUpdate.bind(this),
value: this.isResponsive ? 'auto' : this.lastActiveStyles['font-size'] + ''
}
}
};
},
_getTextColorProperty: function _getTextColorProperty() {
var _this6 = this;
var paletteItems = this._getTextColorChoices();
var selected = _.find(paletteItems, function (palette) {
return palette.id === _this6.lastActiveStyles.color;
}) || {
name: this.lastActiveStyles.color,
value: ''
};
return {
id: 'textColor',
editor: {
sectionId: 'textDetail',
position: 3,
uiControl: {
paletteType: 'DashboardColorSet',
type: 'ColorPicker',
showHexValue: true,
addButton: true,
label: resources.get('propTextColor'),
open: false,
ariaLabel: resources.get('propTextColor'),
items: paletteItems,
allowSameSelection: true,
selectedName: selected ? selected.name : '',
value: selected ? selected.value : '',
onChange: this.onTextColorUpdate.bind(this)
}
}
};
},
getCustomColorList: function getCustomColorList() {
var colorList = [];
var classNames = [];
var allSpans = this.getEditingArea().find('span');
allSpans.each(function (index, span) {
classNames.push(span.className);
});
var allClassNames = classNames.join(' ');
var customColors = this.colorsService.getCustomColorSet();
customColors.forEach(function (customColor) {
if (allClassNames.indexOf(customColor.id) !== -1) {
colorList.push(customColor.hexValue);
}
});
return colorList;
},
_getFontWeightProperty: function _getFontWeightProperty() {
return {
id: 'textFormat',
editor: {
sectionId: 'textDetail',
position: 4,
uiControl: {
type: 'IconPicker',
label: resources.get('textStyle'),
useToggling: true,
allowMultiple: true,
items: [{
name: 'bold',
label: resources.get('propToolbarPickBold'),
value: 'common-text-bold'
}, {
name: 'italic',
label: resources.get('propToolbarPickItalic'),
value: 'common-text-italic'
}, {
name: 'underline',
label: resources.get('propToolbarPickUnderline'),
value: 'common-text-underline'
}],
values: this.lastActiveStyles['text-format'],
onChange: this.onTextFormatUpdate.bind(this)
}
}
};
},
_getTextAlignmentProperty: function _getTextAlignmentProperty() {
return {
id: 'alignmentPicker',
editor: {
sectionId: 'textDetail',
position: 5,
uiControl: {
type: 'IconPicker',
label: resources.get('propAlignPicker'),
items: [{
name: 'justifyLeft',
label: resources.get('propAlignPickLeft'),
value: 'common-left-align'
}, {
name: 'justifyCenter',
label: resources.get('propAlignPickCenter'),
value: 'common-center-align'
}, {
name: 'justifyRight',
label: resources.get('propAlignPickRight'),
value: 'common-right-align'
}],
values: this.lastActiveStyles['text-align'],
onChange: this.onTextAlignmentUpdate.bind(this)
}
}
};
},
_getListProperty: function _getListProperty() {
var selected = void 0;
if (this.lastActiveStyles['insertUnorderedList']) {
selected = 'insertUnorderedList';
} else if (this.lastActiveStyles['insertOrderedList']) {
selected = 'insertOrderedList';
}
return {
id: 'listPicker',
editor: {
sectionId: 'textDetail',
position: 6,
uiControl: {
type: 'IconPicker',
label: resources.get('propList'),
useToggling: true,
items: [{
name: 'insertUnorderedList',
label: resources.get('propUnorderedList'),
value: this._icons.getIcon('bullet-list').id
}, {
name: 'insertOrderedList',
label: resources.get('propOrderedList'),
value: this._icons.getIcon('number-list').id
}],
values: selected,
onChange: this.onListUpdate.bind(this)
}
}
};
},
updateTextToolbar: function updateTextToolbar(activeStyles) {
var styles = activeStyles ? activeStyles : this.getActiveStyles();
var states = this.convertStyleToToolbarState(styles);
// refresh the properties options before re-render the text toolbar
this.textToolbar.properties = this.getToolbarProperties();
this._setTextWrapState(states);
this.textToolbar.setState(states);
},
updatePropertiesIfNecessary: function updatePropertiesIfNecessary() {
if (this.isEditing()) {
var activeStyles = this.getActiveStyles();
var filteredActiveStyles = _.pick(activeStyles, WHITELISTED_PROPERTIES);
var filteredLastActiveStyles = _.pick(this.lastActiveStyles || {}, WHITELISTED_PROPERTIES);
if (!_.isEqual(filteredActiveStyles, filteredLastActiveStyles)) {
this.lastActiveStyles = activeStyles;
this.updateTextToolbar(activeStyles);
this.widget.refreshPropertiesPane();
}
}
},
_convertCssToFontId: function _convertCssToFontId(fontCss) {
var fontId;
fontId = fontCss.replace(/["\s]+/g, '');
fontId = fontId.toLowerCase().split(',');
fontId = fontId.length ? fontId[0].split('-') : null;
return fontId;
},
getFontFamilySubClassSpec: function getFontFamilySubClassSpec(cssItem, defaultValue) {
if (!cssItem) {
return [];
}
if (!defaultValue && cssItem.subCssClasses) {
for (var i = 0; i < cssItem.subCssClasses.length; i++) {
if (cssItem.subCssClasses[i].cssClass === cssItem.cssClass) {
defaultValue = cssItem.subCssClasses[i].value;
break;
}
}
}
var property = {
'type': 'DropDown',
'name': 'fontFamilySubClass',
'id': 'fontFamilyGroup',
'ariaDescribedby': resources.get('textFontFamily'),
'defaultValue': defaultValue,
'options': cssItem.subCssClasses,
'onChange': this.onFontFamilyUpdate.bind(this),
'style': 'width:80px;',
'responsive': false
};
if (!cssItem.subCssClasses || cssItem.subCssClasses.length === 0) {
property.hidden = true;
}
return property;
},
modifyTextFormat: function modifyTextFormat(value) {
if (!this.isEditing()) {
return;
}
if (agent.isFF && (value == 'bold' || value == 'underline')) {
// [201576] Patch for bold + underline props not showing up in FF
this.patchUnderline(value);
} else if (value) {
this._getSummerNote().summernote(value);
}
this.fillText();
},
onListUpdate: function onListUpdate(propertyName, propertyValue) {
if (propertyValue && propertyValue[0] && propertyValue[0].name) {
this.modifyList(propertyValue[0].name);
} else {
var activeList = this.getActiveStyles()['insertUnorderedList'] ? 'insertUnorderedList' : 'insertOrderedList';
this.modifyList(activeList);
}
this.fillText();
this.save();
this.updateTextToolbar();
},
modifyList: function modifyList(propertyName, propertyValue) {
if (!this.isEditing() || this.getActiveStyles()[propertyName] === propertyValue) {
return;
}
this._getSummerNote().summernote(propertyName);
this._styleListItems();
},
/**
* Patch for firefox, applying underline after bold would break
* Works fine when we have , fails spectacularly when we have , i.e. underline then bold works, bold then underline fails.
* @param value {String} bold or underline
*/
patchUnderline: function patchUnderline(value) {
if (value == 'bold') {
this.isBold = !this.isBold;
this._getSummerNote().summernote(value);
} else if (value == 'underline') {
if (this.isBold) {
// remove bold and reapply after underline so we always have , never since that breaks in FF
this._getSummerNote().summernote('bold');
this._getSummerNote().summernote('underline');
this._getSummerNote().summernote('bold');
} else {
this._getSummerNote().summernote('underline');
}
}
},
/*
* Modify the font family: Anton, Roboto, etc.
*/
modifyFontFamily: function modifyFontFamily(cssClass) {
if (!this.isEditing()) {
return;
}
var removedClass = this._removeClassFromSelection('fontFamily');
var addedClass = this._addClassToSelection('fontFamily', cssClass);
this._getSummerNote().summernote('updateClassToSelection', {
remove: removedClass,
add: addedClass
});
this._styleListItems();
this.getEditingArea().focus();
this.fillText();
},
_findFontFamilyItemFromValue: function _findFontFamilyItemFromValue(value, items) {
var current = void 0;
for (var i = 0; i < items.length; i++) {
if (items[i].value === value) {
return items[i];
} else if (this.lastActiveStyles && this.lastActiveStyles['font-family'] && items[i].value === this._convertCssToFontId(this.lastActiveStyles['font-family'])[0]) {
current = items[i];
}
}
if (current) {
var subCssClassMatch = this._findFontFamilyItemFromValue(value, current.subCssClasses || []);
if (subCssClassMatch) {
return subCssClassMatch;
}
}
return null;
},
_cleanInlineStyle: function _cleanInlineStyle() {
this.getEditingArea().find('span, li').css('font-size', '');
},
/*
* Modify the font size.
*/
modifyFontSize: function modifyFontSize(value) {
if (!this.isEditing()) {
return;
}
this.isResponsive = value === 'auto';
var removeClass = this._removeClassFromSelection('fontSize');
if (!this.isResponsive) {
this.unFillText();
this._getSummerNote().summernote('fontSize', parseInt(value));
this._styleListItems();
} else {
this._cleanInlineStyle();
}
this._getSummerNote().summernote('updateClassToSelection', {
remove: removeClass
});
this.fillText();
this.getEditingArea().focus();
this._resizeViz();
},
_isHexColor: function _isHexColor(val) {
return val.indexOf('#') === 0 && val.length === 7;
},
/*
* Modify the text color.
*/
modifyTextColor: function modifyTextColor(value) {
if (!this.isEditing()) {
return;
}
var addedClass = void 0;
var removedClass = this._removeClassFromSelection('textColor');
// Check for the transparent color.
if (value !== 'transparent') {
addedClass = this._addClassToSelection('textColor', value);
}
this._getSummerNote().summernote('updateClassToSelection', {
remove: removedClass,
add: addedClass
});
this._styleListItems();
this.getEditingArea().focus();
},
onTextFormatUpdate: function onTextFormatUpdate(propertyName, propertyPayload) {
var formatStyles = ['bold', 'underline', 'italic'];
var selected = this.getActiveStyles()['text-format'];
formatStyles.forEach(function (format) {
var styleApplied = [];
if (propertyPayload) {
styleApplied = $.grep(propertyPayload, function (property) {
return property.name === format;
});
}
if (styleApplied.length > 0 && selected.indexOf(format) === -1 || styleApplied.length === 0 && selected.indexOf(format) > -1) {
this.modifyTextFormat(format);
}
}.bind(this));
this.fillText();
this.save();
this.updateTextToolbar();
},
onTextAlignmentUpdate: function onTextAlignmentUpdate(propertyName, propertyPayload) {
if (propertyPayload && propertyPayload[0] && propertyPayload[0].name) {
this.modifyTextAlignment(propertyPayload[0].name);
}
this.fillText();
this.save();
this.updateTextToolbar();
},
modifyTextAlignment: function modifyTextAlignment(value) {
if (!this.isEditing()) {
return;
}
var alignment = value.replace('justify', '');
var selectedTextNodes = this.getSelectedParagraphs();
for (var _iterator = selectedTextNodes, _isArray = Array.isArray(_iterator), _i = 0, _iterator = _isArray ? _iterator : _iterator[Symbol.iterator]();;) {
var _ref;
if (_isArray) {
if (_i >= _iterator.length) break;
_ref = _iterator[_i++];
} else {
_i = _iterator.next();
if (_i.done) break;
_ref = _i.value;
}
var node = _ref;
node.style.textAlign = alignment;
}
//Changing the text alignment loses focus on the text
this.getEditingArea().focus();
},
onFontSizeUpdate: function onFontSizeUpdate(propertyName, value) {
this.modifyFontSize(value);
this.fillText();
if (Utils.isIpad()) {
this.restoreSelection();
}
this.getEditingArea().focus();
this.updateTextToolbar();
},
onFontFamilyUpdate: function onFontFamilyUpdate(propertyName, value) {
if (value) {
var styleItem = this._findFontFamilyItemFromValue(value, this._fontFamilyChoices);
if (!styleItem) {
return;
}
this.modifyFontFamily(styleItem.cssClass);
if (propertyName === 'fontFamily') {
this.widget.triggerExternalEvent('properties:refreshProperty', {
'sender': this.widget.model.id,
'propertySpec': this.getFontFamilySubClassSpec(styleItem, null),
'removeProperty': !styleItem.subCssClasses
});
}
//Force auto-resize of text because some fonts are different default sizes
this.fillTextAfterDelay(500);
if (Utils.isIpad()) {
this.restoreSelection();
}
this.getEditingArea().focus();
this.updateTextToolbar();
}
},
onTextColorUpdate: function onTextColorUpdate(propertyName, propertyValueInfo) {
if (this.selection) {
this.restoreSelection(this.selection);
this.selection = null;
}
this.modifyTextColor(propertyValueInfo.name);
this.fillText();
this.updateTextToolbar();
},
textIsEmpty: function textIsEmpty() {
return this._getSummerNote().summernote('isEmpty') ||
/*Firefox*/this.getEditingArea().get(0).textContent.length === 0 && this.numberOfLines == 1;
},
getEditingArea: function getEditingArea() {
return this.node.find(this.EDITING_AREA);
},
_getSummerNote: function _getSummerNote() {
this.initSummernote();
return this.node.children(this.SUMMERNOTE_CLASS);
},
getContent: function getContent() {
return this.getEditingArea().html();
},
getTitleFromHtml: function getTitleFromHtml(html) {
var titleHtml = html;
var title = '';
$(titleHtml).find('p, li').each(function (index, el) {
title = title + ' ' + el.textContent;
});
return title.trim();
},
fillText: function fillText() {
if (!this.node.is(':visible')) {
return;
}
if (this.isResponsive) {
this.node.addClass('textFillNoScroll');
this.node.find(this.TEXT_FITTED).css('word-wrap', 'normal');
var savedLineAlignment = [];
if (BrowserUtils.isIE()) {
// Texfit fails in IE and Edge if the text is aligned right (related MS issue 30900154)
// Scrollwidth erroneously 1px smaller than actual fools the size acceptance test
this.getEditingArea().find('p, li').each(function (index, el) {
savedLineAlignment.push(el.style.textAlign);
el.style.textAlign = 'left';
});
}
var options = {
maxFontSize: Math.ceil(this.node.height()),
minFontSize: 1,
multiLine: true,
detectMultiLine: false
};
TextFitUtil.fillText(this.getEditingArea()[0], options);
if (savedLineAlignment.length) {
this.getEditingArea().find('p, li').each(function (index, el) {
el.style.textAlign = savedLineAlignment[index];
});
}
}
},
fillTextAfterDelay: function fillTextAfterDelay(delay) {
setTimeout(this.fillText.bind(this), delay);
},
unFillText: function unFillText() {
this.node.find(this.TEXT_FITTED).css({
'font-size': '',
'word-wrap': ''
});
this.node.removeClass('textFillNoScroll');
},
/**
* Styling related function
*/
getActiveStyles: function getActiveStyles() {
var styles = this._getSummerNote().summernote('currentStyle');
this._getActiveTextFormat(styles);
this._getActiveTextAlignment(styles);
this._getActiveTextColor(styles);
this._getActiveFontSize(styles);
this._getActiveLists(styles);
return styles;
},
_getActiveLists: function _getActiveLists(context) {
context.insertUnorderedList = context['list-style'] === 'unordered';
context.insertOrderedList = context['list-style'] === 'ordered';
},
_getActiveTextFormat: function _getActiveTextFormat(context) {
var obj = context['text-format'];
if (!obj) {
context['text-format'] = obj = [];
}
if (context['font-bold'] === 'bold') {
obj.push('bold');
}
if (context['font-underline'] === 'underline') {
obj.push('underline');
}
if (context['font-italic'] === 'italic') {
obj.push('italic');
}
},
_getActiveTextAlignment: function _getActiveTextAlignment(context) {
var selectedTextNodes = this.getSelectedParagraphs();
// If multiple lines have different text alignments
// will not highlight an alignment in the property panel
if (selectedTextNodes && selectedTextNodes.length > 0) {
var style = selectedTextNodes[0].style.textAlign;
for (var _iterator2 = selectedTextNodes, _isArray2 = Array.isArray(_iterator2), _i2 = 0, _iterator2 = _isArray2 ? _iterator2 : _iterator2[Symbol.iterator]();;) {
var _ref2;
if (_isArray2) {
if (_i2 >= _iterator2.length) break;
_ref2 = _iterator2[_i2++];
} else {
_i2 = _iterator2.next();
if (_i2.done) break;
_ref2 = _i2.value;
}
var node = _ref2;
if (node.style.textAlign !== style) {
context['text-align'] = '';
return;
}
}
switch (style) {
case 'center':
context['text-align'] = 'justifyCenter';
break;
case 'right':
context['text-align'] = 'justifyRight';
break;
default:
context['text-align'] = 'justifyLeft';
}
}
},
_getActiveTextColor: function _getActiveTextColor(context) {
if (!context.color) {
return;
}
var match = this._getActiveTextColor_Checker(context.color);
if (match) {
context.color = match;
}
},
_getActiveTextColor_Checker: function _getActiveTextColor_Checker(rgbColor) {
var match = null;
if (rgbColor) {
var colors = this._getTextColorChoices();
var hex = this._rgbToHex(rgbColor);
for (var _iterator3 = colors, _isArray3 = Array.isArray(_iterator3), _i3 = 0, _iterator3 = _isArray3 ? _iterator3 : _iterator3[Symbol.iterator]();;) {
var _ref3;
if (_isArray3) {
if (_i3 >= _iterator3.length) break;
_ref3 = _iterator3[_i3++];
} else {
_i3 = _iterator3.next();
if (_i3.done) break;
_ref3 = _i3.value;
}
var color = _ref3;
// Find key corresponding to the node's color value.
if (hex && hex === color.hexValue) {
match = color.id;
break;
}
}
//If the color is not found then it is a customColor
if (!match && hex) {
match = this.colorsService.getColorClassName(hex);
}
}
return match;
},
_getActiveFontSize: function _getActiveFontSize(context) {
if (!context['font-size']) {
return;
}
if (this.isResponsive) {
context['font-size'] = 'auto';
}
},
_rgbToHex: function _rgbToHex(rgb) {
rgb = rgb.match(/^rgba?[\s+]?\([\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?,[\s+]?(\d+)[\s+]?/i);
return rgb && rgb.length === 4 ? '#' + ('0' + parseInt(rgb[1], 10).toString(16)).slice(-2) + ('0' + parseInt(rgb[2], 10).toString(16)).slice(-2) + ('0' + parseInt(rgb[3], 10).toString(16)).slice(-2) : '';
},
_getTextColorChoices: function _getTextColorChoices() {
return this.colorsService.getDashboardColorSet().filter(function (item) {
return item.id !== 'transparent';
});
},
_copyTextStyles: function _copyTextStyles($from, $to) {
var hexColor = this._rgbToHex($from.css('color'));
var fontId = this._convertCssToFontId($from.css('font-family'))[0];
$to.removeClass();
var colorClass = this._findColorIdFromHex(hexColor);
if (colorClass) {
$to.addClass(colorClass);
}
var fontFamilyItem = this._findFontFamilyItemFromValue(fontId, this._fontFamilyChoices);
if (fontFamilyItem && fontFamilyItem.cssClass) {
$to.addClass(fontFamilyItem.cssClass);
}
if (!this.isResponsive) {
$to.css({
'font-size': $from.css('font-size')
});
}
},
/**
* Returns a refined clone of the current selection range.
* Useful for Range.compareBoundaryPoints calls.
*/
_getRefinedSelectionRange: function _getRefinedSelectionRange() {
var selRange = window.getSelection().getRangeAt(0).cloneRange();
var selStartEl = selRange.startContainer;
var selStartOffset = selStartEl.firstChild ? 0 : selRange.startOffset;
while (selStartEl.firstChild) {
selStartEl = selStartEl.firstChild;
}
// Summernote has a patch that inserts bogus chars when styling with no selection
// Range.compareBoundaryPoints will produce unexpected results if there is more than one of them on a boundary.
// Logged https://github.com/summernote/summernote/issues/3035, this is a workaround for now.
var ZERO_WIDTH_SPACE = '\uFEFF';
if (selStartOffset > 0 && selStartEl.textContent[selStartOffset - 1] === ZERO_WIDTH_SPACE) {
selStartOffset -= 1;
if (selStartOffset === 0) {
var textNodeWalker = document.createTreeWalker($(selStartEl).closest('p, li')[0], window.NodeFilter.SHOW_TEXT);
while (selStartEl !== textNodeWalker.nextNode()) {}
var previousTextNode = textNodeWalker.previousNode();
while (previousTextNode && previousTextNode.textContent[previousTextNode.textContent.length - 1] === ZERO_WIDTH_SPACE) {
previousTextNode.textContent = previousTextNode.textContent.slice(0, -1);
if (previousTextNode.parentNode.innerText === '') {
var toRemove = previousTextNode.parentNode;
previousTextNode = textNodeWalker.previousNode();
toRemove.remove();
}
}
}
}
selRange.setStart(selStartEl, selStartOffset);
return selRange;
},
_isNodeStartSelected: function _isNodeStartSelected(node, selRange) {
while (node.firstChild) {
node = node.firstChild;
}
var paragraphRange = document.createRange();
paragraphRange.setStart(node, 0);
return selRange.compareBoundaryPoints(window.Range.START_TO_START, paragraphRange) !== 1;
},
_styleListItems: function _styleListItems() {
var _this7 = this;
var listItems = this.getSelectedListItems();
if (listItems.length) {
var selRange = this._getRefinedSelectionRange();
listItems.forEach(function (node) {
var $node = $(node);
if (_this7._isNodeStartSelected(node, selRange)) {
// The li will be styled; Protect li children against li styles before applying them.
$node.contents().each(function (index, childNode) {
var $childNode = $(childNode);
if (childNode.nodeType === window.Node.TEXT_NODE) {
var $span = $('');
_this7._copyTextStyles($node, $span);
$childNode.wrap($span);
} else {
_this7._copyTextStyles($childNode, $childNode);
}
});
while (node.firstChild) {
node = node.firstChild;
}
_this7._copyTextStyles($(node.parentNode), $node);
}
});
}
},
getSelectedListItems: function getSelectedListItems() {
return this.getSelectedParagraphs().filter(function (node) {
return node.nodeName === 'LI';
});
},
getSelectedParagraphs: function getSelectedParagraphs() {
var selection = window.getSelection();
if (!selection.rangeCount) {
return [];
}
var range = selection.getRangeAt(0);
if (range.startContainer === this.getEditingArea()[0]) {
// Happens on IE if selection was made with ctrl + a (select all)
return this.getEditingArea().find('p, li').toArray();
}
var start = $(range.startContainer).closest('p, li').get(0);
var end = $(range.endContainer).closest('p, li').get(0);
if (start === end) {
return start ? [start] : [];
}
var nodes = [];
var inRange = false;
$(range.commonAncestorContainer).find('p, li').each(function () {
if (this === start) {
inRange = true;
}
if (inRange) {
nodes.push(this);
}
if (this === end) {
inRange = false;
}
});
return nodes;
},
saveSelection: function saveSelection() {
if (window.getSelection) {
var sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
return sel.getRangeAt(0);
}
} else if (document.selection && document.selection.createRange) {
return document.selection.createRange();
}
return null;
},
// IE11 throws error 800a025e on removeAllRanges in certain cases
_clearSelection: function _clearSelection(selection) {
if (!BrowserUtils.isIE11() || selection.rangeCount > 0 && selection.getRangeAt(0).getClientRects().length > 0) {
selection.removeAllRanges();
}
},
restoreSelection: function restoreSelection(range) {
if (range) {
if (window.getSelection) {
var sel = window.getSelection();
this._clearSelection(sel);
sel.addRange(range);
} else if (document.selection && range.select) {
range.select();
}
}
},
hasContent: function hasContent() {
var $editingArea = this.getEditingArea();
return !!$editingArea.text().length || !!$editingArea.find('li').length;
},
hasText: function hasText() {
return !!this.getEditingArea().text().length;
}
});
TextEditor.cleanContentElements = cleanContentElements;
TextEditor.getTextHTML = getTextHTML;
//Make sure that the ID here matches css class name.
TextEditor.FONTFAMILY_CHOICES = [{
'value': 'anton',
'label': 'Anton',
'cssClass': 'rt_fontFamilyAnton'
}, {
'value': 'cherrycreamsoda',
'label': 'Cherry Cream Soda',
'cssClass': 'rt_fontFamilyCherryCreamSoda'
}, {
'value': 'condiment',
'label': 'Condiment',
'cssClass': 'rt_fontFamilyCondiment-Regular'
}, {
'value': 'didactgothic',
'label': 'Didact Gothic',
'cssClass': 'rt_fontFamilyDidactGothic'
}, {
'value': 'euphoriascript',
'label': 'Euphoria Script',
'cssClass': 'rt_fontFamilyEuphoriaScript-Regular'
}, {
'value': 'helveticaneueforibm',
'label': 'Helvetica Neue',
'cssClass': 'rt_fontFamilyHelvNeueforIBM-Regular',
'subCssClasses': [{
'value': 'light',
'label': resources.get('textFontFamilySubClassLight'),
'cssClass': 'rt_fontFamilyHelvNeueforIBM-Light'
}, {
'value': 'lightitalic',
'label': resources.get('textFontFamilySubClassLightItalic'),
'cssClass': 'rt_fontFamilyHelvNeueforIBM-LightItalic'
}, {
'value': 'regular',
'label': resources.get('textFontFamilySubClassRegular'),
'cssClass': 'rt_fontFamilyHelvNeueforIBM-Regular'
}, {
'value': 'italic',
'label': resources.get('textFontFamilySubClassItalic'),
'cssClass': 'rt_fontFamilyHelvNeueforIBM-Italic'
}, {
'value': 'medium',
'label': resources.get('textFontFamilySubClassMedium'),
'cssClass': 'rt_fontFamilyHelvNeueforIBM-Medium'
}, {
'value': 'mediumitalic',
'label': resources.get('textFontFamilySubClassMediumItalic'),
'cssClass': 'rt_fontFamilyHelvNeueforIBM-MediumItalic'
}, {
'value': 'bold',
'label': resources.get('textFontFamilySubClassBold'),
'cssClass': 'rt_fontFamilyHelvNeueforIBM-Bold'
}, {
'value': 'bolditalic',
'label': resources.get('textFontFamilySubClassBoldItalic'),
'cssClass': 'rt_fontFamilyHelvNeueforIBM-BoldItalic'
}]
}, {
'value': 'kaushanscript',
'label': 'Kaushan Script',
'cssClass': 'rt_fontFamilyKaushanScript-Regular'
}, {
'value': 'lobster',
'label': 'Lobster',
'cssClass': 'rt_fontFamilyLobster'
}, {
'value': 'merriweather',
'label': 'Merriweather',
'cssClass': 'rt_fontFamilyMerriweather-Regular',
'subCssClasses': [{
'value': 'italic',
'label': resources.get('textFontFamilySubClassItalic'),
'cssClass': 'rt_fontFamilyMerriweather-Italic'
}, {
'value': 'light',
'label': resources.get('textFontFamilySubClassLight'),
'cssClass': 'rt_fontFamilyMerriweather-Light'
}, {
'value': 'regular',
'label': resources.get('textFontFamilySubClassRegular'),
'cssClass': 'rt_fontFamilyMerriweather-Regular'
}, {
'value': 'bold',
'label': resources.get('textFontFamilySubClassBold'),
'cssClass': 'rt_fontFamilyMerriweather-Bold'
}, {
'value': 'bolditalic',
'label': resources.get('textFontFamilySubClassBoldItalic'),
'cssClass': 'rt_fontFamilyMerriweather-BoldItalic'
}, {
'value': 'black',
'label': resources.get('textFontFamilySubClassBlack'),
'cssClass': 'rt_fontFamilyMerriweather-Black'
}, {
'value': 'lightitalic',
'label': resources.get('textFontFamilySubClassLightItalic'),
'cssClass': 'rt_fontFamilyMerriweather-LightItalic'
}, {
'value': 'heavyitalic',
'label': resources.get('textFontFamilySubClassHeavyItalic'),
'cssClass': 'rt_fontFamilyMerriweather-HeavyItalic'
}]
}, {
'value': 'merriweathersans',
'label': 'Merriweather Sans',
'cssClass': 'rt_fontFamilyMerriweatherSans-Regular',
'subCssClasses': [{
'value': 'italic',
'label': resources.get('textFontFamilySubClassItalic'),
'cssClass': 'rt_fontFamilyMerriweatherSans-Italic'
}, {
'value': 'light',
'label': resources.get('textFontFamilySubClassLight'),
'cssClass': 'rt_fontFamilyMerriweatherSans-Light'
}, {
'value': 'lightitalic',
'label': resources.get('textFontFamilySubClassLightItalic'),
'cssClass': 'rt_fontFamilyMerriweatherSans-LightItalic'
}, {
'value': 'regular',
'label': resources.get('textFontFamilySubClassRegular'),
'cssClass': 'rt_fontFamilyMerriweatherSans-Regular'
}, {
'value': 'bold',
'label': resources.get('textFontFamilySubClassBold'),
'cssClass': 'rt_fontFamilyMerriweatherSans-Bold'
}, {
'value': 'bolditalic',
'label': resources.get('textFontFamilySubClassBoldItalic'),
'cssClass': 'rt_fontFamilyMerriweatherSans-BoldItalic'
}, {
'value': 'extrabold',
'label': resources.get('textFontFamilySubClassExtraBold'),
'cssClass': 'rt_fontFamilyMerriweatherSans-ExtraBold'
}, {
'value': 'extrabolditalic',
'label': resources.get('textFontFamilySubClassExtraBoldItalic'),
'cssClass': 'rt_fontFamilyMerriweatherSans-ExtraBoldItalic'
}]
}, {
'value': 'monoton',
'label': 'Monoton',
'cssClass': 'rt_fontFamilyMonoton-Regular'
}, {
'value': 'montserrat',
'label': 'Montserrat',
'cssClass': 'rt_fontFamilyMontserrat-Regular',
'subCssClasses': [{
'value': 'hairline',
'label': resources.get('textFontFamilySubClassHairline'),
'cssClass': 'rt_fontFamilyMontserrat-Hairline'
}, {
'value': 'light',
'label': resources.get('textFontFamilySubClassLight'),
'cssClass': 'rt_fontFamilyMontserrat-Light'
}, {
'value': 'regular',
'label': resources.get('textFontFamilySubClassRegular'),
'cssClass': 'rt_fontFamilyMontserrat-Regular'
}, {
'value': 'bold',
'label': resources.get('textFontFamilySubClassBold'),
'cssClass': 'rt_fontFamilyMontserrat-Bold'
}, {
'value': 'black',
'label': resources.get('textFontFamilySubClassBlack'),
'cssClass': 'rt_fontFamilyMontserrat-Black'
}]
}, {
'value': 'opensanscondensed',
'label': 'Open Sans Condensed',
'cssClass': 'rt_fontFamilyOpenSansCondensed-Light',
'subCssClasses': [{
'value': 'light',
'label': resources.get('textFontFamilySubClassLight'),
'cssClass': 'rt_fontFamilyOpenSansCondensed-Light'
}, {
'value': 'lightitalic',
'label': resources.get('textFontFamilySubClassLightItalic'),
'cssClass': 'rt_fontFamilyOpenSansCondensed-LightItalic'
}, {
'value': 'bold',
'label': resources.get('textFontFamilySubClassBold'),
'cssClass': 'rt_fontFamilyOpenSansCondensed-Bold'
}]
}, {
'value': 'oswald',
'label': 'Oswald',
'cssClass': 'rt_fontFamilyOswald-Regular',
'subCssClasses': [{
'value': 'extralight',
'label': resources.get('textFontFamilySubClassExtraLight'),
'cssClass': 'rt_fontFamilyOswald-ExtraLight'
}, {
'value': 'extralightitalic',
'label': resources.get('textFontFamilySubClassExtraLightItalic'),
'cssClass': 'rt_fontFamilyOswald-ExtraLightItalic'
}, {
'value': 'light',
'label': resources.get('textFontFamilySubClassLight'),
'cssClass': 'rt_fontFamilyOswald-Light'
}, {
'value': 'lightitalic',
'label': resources.get('textFontFamilySubClassLightItalic'),
'cssClass': 'rt_fontFamilyOswald-LightItalic'
}, {
'value': 'regular',
'label': resources.get('textFontFamilySubClassRegular'),
'cssClass': 'rt_fontFamilyOswald-Regular'
}, {
'value': 'regularitalic',
'label': resources.get('textFontFamilySubClassRegularItalic'),
'cssClass': 'rt_fontFamilyOswald-RegularItalic'
}, {
'value': 'medium',
'label': resources.get('textFontFamilySubClassMedium'),
'cssClass': 'rt_fontFamilyOswald-Medium'
}, {
'value': 'mediumitalic',
'label': resources.get('textFontFamilySubClassMediumItalic'),
'cssClass': 'rt_fontFamilyOswald-MediumItalic'
}, {
'value': 'demibold',
'label': resources.get('textFontFamilySubClassDemiBold'),
'cssClass': 'rt_fontFamilyOswald-DemiBold'
}, {
'value': 'demibolditalic',
'label': resources.get('textFontFamilySubClassDemiBoldItalic'),
'cssClass': 'rt_fontFamilyOswald-DemiBoldItalic'
}, {
'value': 'bold',
'label': resources.get('textFontFamilySubClassBold'),
'cssClass': 'rt_fontFamilyOswald-Bold'
}, {
'value': 'bolditalic',
'label': resources.get('textFontFamilySubClassBoldItalic'),
'cssClass': 'rt_fontFamilyOswald-BoldItalic'
}, {
'value': 'heavy',
'label': resources.get('textFontFamilySubClassHeavy'),
'cssClass': 'rt_fontFamilyOswald-Heavy'
}, {
'value': 'heavyitalic',
'label': resources.get('textFontFamilySubClassHeavyItalic'),
'cssClass': 'rt_fontFamilyOswald-HeavyItalic'
}, {
'value': 'stencil',
'label': resources.get('textFontFamilySubClassStencil'),
'cssClass': 'rt_fontFamilyOswald-Stencil'
}]
}, {
'value': 'playball',
'label': 'Playball',
'cssClass': 'rt_fontFamilyPlayball'
}, {
'value': 'ibmplexsans',
'label': 'IBM Plex',
default: true,
'cssClass': 'rt_fontFamilyPlex-Regular',
'subCssClasses': [{
'value': 'light',
'label': resources.get('textFontFamilySubClassLight'),
'cssClass': 'rt_fontFamilyPlex-Light'
}, {
'value': 'lightitalic',
'label': resources.get('textFontFamilySubClassLightItalic'),
'cssClass': 'rt_fontFamilyPlex-LightItalic'
}, {
'value': 'regular',
'label': resources.get('textFontFamilySubClassRegular'),
'cssClass': 'rt_fontFamilyPlex-Regular'
}, {
'value': 'italic',
'label': resources.get('textFontFamilySubClassItalic'),
'cssClass': 'rt_fontFamilyPlex-Italic'
}, {
'value': 'medium',
'label': resources.get('textFontFamilySubClassMedium'),
'cssClass': 'rt_fontFamilyPlex-Medium'
}, {
'value': 'mediumitalic',
'label': resources.get('textFontFamilySubClassMediumItalic'),
'cssClass': 'rt_fontFamilyPlex-MediumItalic'
}, {
'value': 'bold',
'label': resources.get('textFontFamilySubClassBold'),
'cssClass': 'rt_fontFamilyPlex-Bold'
}, {
'value': 'bolditalic',
'label': resources.get('textFontFamilySubClassBoldItalic'),
'cssClass': 'rt_fontFamilyPlex-BoldItalic'
}]
}, {
'value': 'roboto',
'label': 'Roboto',
'cssClass': 'rt_fontFamilyRoboto-Regular',
'subCssClasses': [{
'value': 'thin',
'label': resources.get('textFontFamilySubClassThin'),
'cssClass': 'rt_fontFamilyRoboto-Thin'
}, {
'value': 'thinitalic',
'label': resources.get('textFontFamilySubClassThinItalic'),
'cssClass': 'rt_fontFamilyRoboto-ThinItalic'
}, {
'value': 'light',
'label': resources.get('textFontFamilySubClassLight'),
'cssClass': 'rt_fontFamilyRoboto-Light'
}, {
'value': 'lightitalic',
'label': resources.get('textFontFamilySubClassLightItalic'),
'cssClass': 'rt_fontFamilyRoboto-LightItalic'
}, {
'value': 'regular',
'label': resources.get('textFontFamilySubClassRegular'),
'cssClass': 'rt_fontFamilyRoboto-Regular'
}, {
'value': 'italic',
'label': resources.get('textFontFamilySubClassItalic'),
'cssClass': 'rt_fontFamilyRoboto-Italic'
}, {
'value': 'medium',
'label': resources.get('textFontFamilySubClassMedium'),
'cssClass': 'rt_fontFamilyRoboto-Medium'
}, {
'value': 'mediumitalic',
'label': resources.get('textFontFamilySubClassMediumItalic'),
'cssClass': 'rt_fontFamilyRoboto-MediumItalic'
}, {
'value': 'bold',
'label': resources.get('textFontFamilySubClassBold'),
'cssClass': 'rt_fontFamilyRoboto-Bold'
}, {
'value': 'bolditalic',
'label': resources.get('textFontFamilySubClassBoldItalic'),
'cssClass': 'rt_fontFamilyRoboto-BoldItalic'
}, {
'value': 'black',
'label': resources.get('textFontFamilySubClassBlack'),
'cssClass': 'rt_fontFamilyRoboto-Black'
}, {
'value': 'blackitalic',
'label': resources.get('textFontFamilySubClassBlackItalic'),
'cssClass': 'rt_fontFamilyRoboto-BlackItalic'
}]
}, {
'value': 'sortsmillgoudy',
'label': 'Sorts Mill Goudy',
'cssClass': 'rt_fontFamilySortsMillGoudy-Regular',
'subCssClasses': [{
'value': 'regular',
'label': resources.get('textFontFamilySubClassRegular'),
'cssClass': 'rt_fontFamilySortsMillGoudy-Regular'
}, {
'value': 'italic',
'label': resources.get('textFontFamilySubClassItalic'),
'cssClass': 'rt_fontFamilySortsMillGoudy-Italic'
}]
}, {
'value': 'specialelite',
'label': 'Special Elite',
'cssClass': 'rt_fontFamilySpecialElite'
}];
TextEditor.INT_FONTSIZE_CHOICES = [{
'value': '8',
'label': '8'
}, {
'value': '9',
'label': '9'
}, {
'value': '10',
'label': '10'
}, {
'value': '11',
'label': '11'
}, {
'value': '12',
'label': '12'
}, {
'value': '14',
'label': '14'
}, {
'value': '16',
'label': '16'
}, {
'value': '18',
'label': '18'
}, {
'value': '20',
'label': '20'
}, {
'value': '22',
'label': '22'
}, {
'value': '24',
'label': '24'
}, {
'value': '26',
'label': '26'
}, {
'value': '28',
'label': '28'
}, {
'value': '30',
'label': '30'
}, {
'value': '36',
'label': '36'
}, {
'value': '48',
'label': '48'
}, {
'value': '60',
'label': '60'
}, {
'value': '72',
'label': '72'
}, {
'value': '96',
'label': '96'
}, {
'value': '120',
'label': '120'
}, {
'value': '170',
'label': '170'
}, {
'value': '230',
'label': '230'
}];
TextEditor.FONTSIZE_CHOICES = [{
'value': 'auto',
'label': resources.get('textAutoFontSize')
}].concat(TextEditor.INT_FONTSIZE_CHOICES);
return TextEditor;
});
//# sourceMappingURL=TextEditor.js.map