/home/ivoiecob/email.hirewise-va.com/modules/MailWebclient/js/views/CHtmlEditorView.js
'use strict'
const _ = require('underscore'),
$ = require('jquery'),
ko = require('knockout')
const AddressUtils = require('%PathToCoreWebclientModule%/js/utils/Address.js'),
TextUtils = require('%PathToCoreWebclientModule%/js/utils/Text.js'),
Types = require('%PathToCoreWebclientModule%/js/utils/Types.js')
const App = require('%PathToCoreWebclientModule%/js/App.js'),
Browser = require('%PathToCoreWebclientModule%/js/Browser.js'),
CJua = require('%PathToCoreWebclientModule%/js/CJua.js'),
UserSettings = require('%PathToCoreWebclientModule%/js/Settings.js')
const Popups = require('%PathToCoreWebclientModule%/js/Popups.js'),
AlertPopup = require('%PathToCoreWebclientModule%/js/popups/AlertPopup.js'),
ConfirmPopup = require('%PathToCoreWebclientModule%/js/popups/ConfirmPopup.js')
const CAttachmentModel = require('modules/%ModuleName%/js/models/CAttachmentModel.js'),
CColorPickerView = require('modules/%ModuleName%/js/views/CColorPickerView.js'),
CCrea = require('modules/%ModuleName%/js/CCrea.js'),
MailCache = require('modules/%ModuleName%/js/Cache.js'),
Settings = require('modules/%ModuleName%/js/Settings.js'),
TemplatesUtils = require('modules/%ModuleName%/js/utils/Templates.js'),
sourceEditor = require('modules/%ModuleName%/js/views/html-editor/SourceEditor.js')
/**
* @constructor
* @param {boolean} bInsertImageAsBase64
* @param {boolean} bAllowComposePlainText
* @param {Object=} oParent
*/
function CHtmlEditorView(bInsertImageAsBase64, bAllowComposePlainText, oParent) {
this.oParent = oParent
this.creaId = 'creaId' + Math.random().toString().replace('.', '')
this.textFocused = ko.observable(false)
this.workareaDom = ko.observable()
this.plaintextDom = ko.observable()
this.uploaderAreaDom = ko.observable()
this.editorUploaderBodyDragOver = ko.observable(false)
this.htmlEditorDom = ko.observable()
this.toolbarDom = ko.observable()
this.colorPickerDropdownDom = ko.observable()
this.insertLinkDropdownDom = ko.observable()
this.insertImageDropdownDom = ko.observable()
this.isFWBold = ko.observable(false)
this.isFSItalic = ko.observable(false)
this.isTDUnderline = ko.observable(false)
this.isTDStrikeThrough = ko.observable(false)
this.isEnumeration = ko.observable(false)
this.isBullets = ko.observable(false)
this.isEnable = ko.observable(true)
this.isEnable.subscribe(function () {
if (this.oCrea) {
this.oCrea.setEditable(this.isEnable())
}
}, this)
this.bInsertImageAsBase64 = bInsertImageAsBase64
this.bAllowFileUpload = !(bInsertImageAsBase64 && window.File === undefined)
this.bAllowInsertImage = Settings.AllowInsertImage
this.bAllowHorizontalLineButton = Settings.AllowHorizontalLineButton
this.bAllowComposePlainText = bAllowComposePlainText
this.plainTextMode = ko.observable(false)
this.changeTextModeTitle = ko.computed(function () {
return this.plainTextMode()
? TextUtils.i18n('%MODULENAME%/LINK_TURNOFF_PLAINTEXT')
: TextUtils.i18n('%MODULENAME%/LINK_TURNON_PLAINTEXT')
}, this)
this.bAllowEditHtmlSource = Settings.AllowEditHtmlSource
this.editSourceMode = ko.observable(false)
this.htmlSourceDom = ko.observable()
this.htmlSourceDom.subscribe(() => {
sourceEditor.setHtmlSourceDom(this.htmlSourceDom())
})
this.sourceCodeButtonText = ko.computed(() => {
return this.editSourceMode()
? TextUtils.i18n('%MODULENAME%/ACTION_EDIT_HTML_PREVIEW')
: TextUtils.i18n('%MODULENAME%/ACTION_EDIT_HTML_SOURCE_CODE')
})
this.lockFontSubscribing = ko.observable(false)
this.bAllowImageDragAndDrop = !Browser.ie10AndAbove
this.aFonts = ['Arial', 'Arial Black', 'Courier New', 'Tahoma', 'Times New Roman', 'Verdana']
this.sDefaultFont = Settings.DefaultFontName
this.correctFontFromSettings()
this.selectedFont = ko.observable('')
this.selectedFont.subscribe(function () {
if (this.oCrea && !this.lockFontSubscribing() && !this.inactive()) {
this.oCrea.fontName(this.selectedFont())
}
}, this)
this.iDefaultSize = Settings.DefaultFontSize
this.selectedSize = ko.observable(0)
this.selectedSize.subscribe(function () {
if (this.oCrea && !this.lockFontSubscribing() && !this.inactive()) {
this.oCrea.fontSize(this.selectedSize())
}
}, this)
this.visibleInsertLinkPopup = ko.observable(false)
this.linkForInsert = ko.observable('')
this.linkFocused = ko.observable(false)
this.visibleLinkPopup = ko.observable(false)
this.linkPopupDom = ko.observable(null)
this.linkHrefDom = ko.observable(null)
this.linkHref = ko.observable('')
this.visibleLinkHref = ko.observable(false)
this.visibleImagePopup = ko.observable(false)
this.visibleImagePopup.subscribe(function () {
this.onImageOut()
}, this)
this.imagePopupTop = ko.observable(0)
this.imagePopupLeft = ko.observable(0)
this.imageSelected = ko.observable(false)
this.tooltipText = ko.observable('')
this.tooltipPopupTop = ko.observable(0)
this.tooltipPopupLeft = ko.observable(0)
this.visibleInsertImagePopup = ko.observable(false)
this.imageUploaderButton = ko.observable(null)
this.aUploadedImagesData = []
this.imagePathFromWeb = ko.observable('')
this.visibleTemplatePopup = ko.observable(false)
this.visibleFontColorPopup = ko.observable(false)
this.oFontColorPickerView = new CColorPickerView(
TextUtils.i18n('%MODULENAME%/LABEL_TEXT_COLOR'),
this.setTextColorFromPopup,
this
)
this.oBackColorPickerView = new CColorPickerView(
TextUtils.i18n('%MODULENAME%/LABEL_BACKGROUND_COLOR'),
this.setBackColorFromPopup,
this
)
this.inactive = ko.observable(false)
this.sPlaceholderText = ''
this.bAllowChangeInputDirection = UserSettings.IsRTL || Settings.AllowChangeInputDirection
this.disableEdit = ko.observable(false)
this.textChanged = ko.observable(false)
this.actualTextChanged = ko.observable(false)
this.templates = ko.observableArray([])
TemplatesUtils.initTemplatesSubscription(this.templates)
this.imageResizeOptions = []
_.each(Settings.ImageResizerOptions, (value, label) => {
this.imageResizeOptions.push({
label: TextUtils.i18n(label),
value: value,
})
})
}
CHtmlEditorView.prototype.ViewTemplate = '%ModuleName%_HtmlEditorView'
CHtmlEditorView.prototype.setInactive = function (bInactive) {
this.inactive(bInactive)
if (this.inactive()) {
if (this.editSourceMode()) {
this.toggleSourceEdit()
}
this.setPlaceholder()
} else {
this.removePlaceholder()
}
}
CHtmlEditorView.prototype.setPlaceholder = function () {
var sText = this.removeAllTags(this.getText())
if (sText === '' || sText === ' ') {
this.setText('<span>' + this.sPlaceholderText + '</span>')
if (this.oCrea) {
this.oCrea.setBlur()
}
}
}
CHtmlEditorView.prototype.removePlaceholder = function () {
var sText = this.oCrea ? this.removeAllTags(this.oCrea.getText(false)) : ''
if (sText === this.sPlaceholderText) {
this.setText('')
if (this.oCrea) {
this.oCrea.setFocus(true)
}
}
}
CHtmlEditorView.prototype.hasOpenedPopup = function () {
return (
this.visibleInsertLinkPopup() ||
this.visibleLinkPopup() ||
this.visibleImagePopup() ||
this.visibleInsertImagePopup() ||
this.visibleFontColorPopup() ||
this.visibleTemplatePopup()
)
}
CHtmlEditorView.prototype.setDisableEdit = function (bDisableEdit) {
this.disableEdit(!!bDisableEdit)
}
CHtmlEditorView.prototype.correctFontFromSettings = function () {
var sDefaultFont = this.sDefaultFont,
bFound = false
_.each(this.aFonts, function (sFont) {
if (sFont.toLowerCase() === sDefaultFont.toLowerCase()) {
sDefaultFont = sFont
bFound = true
}
})
if (bFound) {
this.sDefaultFont = sDefaultFont
} else {
this.aFonts.push(sDefaultFont)
}
}
/**
* @param {Object} $link
*/
CHtmlEditorView.prototype.showLinkPopup = function ($link) {
var $workarea = $(this.workareaDom()),
$composePopup = $workarea.closest('.panel.compose'),
oWorkareaPos = $workarea.position(),
oPos = $link.position(),
iHeight = $link.height(),
iLeft = Math.round(oPos.left + oWorkareaPos.left),
iTop = Math.round(oPos.top + iHeight + oWorkareaPos.top)
this.linkHref($link.attr('href') || $link.text())
$(this.linkPopupDom()).css({
left: iLeft,
top: iTop,
})
$(this.linkHrefDom()).css({
left: iLeft,
top: iTop,
})
if (!Browser.firefox && $composePopup.length === 1) {
$(this.linkPopupDom()).css({
'max-width': $composePopup.width() - iLeft - 40 + 'px',
'white-space': 'pre-line',
'word-wrap': 'break-word',
})
}
this.visibleLinkPopup(true)
}
CHtmlEditorView.prototype.hideLinkPopup = function () {
this.visibleLinkPopup(false)
}
CHtmlEditorView.prototype.showChangeLink = function () {
this.visibleLinkHref(true)
this.hideLinkPopup()
}
CHtmlEditorView.prototype.changeLink = function () {
this.oCrea.changeLink(this.linkHref())
this.hideChangeLink()
}
CHtmlEditorView.prototype.hideChangeLink = function () {
this.visibleLinkHref(false)
}
/**
* @param {jQuery} $image
* @param {Object} oEvent
*/
CHtmlEditorView.prototype.showImagePopup = function ($image, oEvent) {
var $workarea = $(this.workareaDom()),
oWorkareaPos = $workarea.position(),
oWorkareaOffset = $workarea.offset()
this.imagePopupLeft(Math.round(oEvent.pageX + oWorkareaPos.left - oWorkareaOffset.left))
this.imagePopupTop(Math.round(oEvent.pageY + oWorkareaPos.top - oWorkareaOffset.top))
this.visibleImagePopup(true)
}
CHtmlEditorView.prototype.hideImagePopup = function () {
this.visibleImagePopup(false)
}
CHtmlEditorView.prototype.resizeImage = function (sSize) {
var oParams = {
width: 'auto',
height: 'auto',
}
if (sSize) {
oParams.width = sSize
}
this.oCrea.changeCurrentImage(oParams)
this.visibleImagePopup(false)
}
CHtmlEditorView.prototype.onImageOver = function (oEvent) {
if (oEvent.target.nodeName === 'IMG' && !this.visibleImagePopup()) {
this.imageSelected(true)
this.tooltipText(TextUtils.i18n('%MODULENAME%/ACTION_CLICK_TO_EDIT_IMAGE'))
var self = this,
$workarea = $(this.workareaDom())
$workarea.bind('mousemove.image', function (oEvent) {
var oWorkareaPos = $workarea.position(),
oWorkareaOffset = $workarea.offset()
self.tooltipPopupTop(Math.round(oEvent.pageY + oWorkareaPos.top - oWorkareaOffset.top))
self.tooltipPopupLeft(Math.round(oEvent.pageX + oWorkareaPos.left - oWorkareaOffset.left))
})
}
return true
}
CHtmlEditorView.prototype.onImageOut = function (oEvent) {
if (this.imageSelected()) {
this.imageSelected(false)
var $workarea = $(this.workareaDom())
$workarea.unbind('mousemove.image')
}
return true
}
CHtmlEditorView.prototype.commit = function () {
this.textChanged(false)
}
/**
* @param {string} sText
* @param {boolean} bPlain
* @param {string} sTabIndex
* @param {string} sPlaceholderText
*/
CHtmlEditorView.prototype.init = function (sText, bPlain, sTabIndex, sPlaceholderText) {
this.sPlaceholderText = sPlaceholderText || ''
if (this.oCrea) {
this.oCrea.$container = $('#' + this.oCrea.oOptions.creaId)
// in case if knockoutjs destroyed dom element with html editor
if (this.oCrea.$container.children().length === 0) {
this.oCrea.start(this.isEnable())
// this.editorUploader must be re-initialized because compose popup is destroyed after it is closed
this.initEditorUploader()
}
} else {
$(document.body).on(
'click',
_.bind(function (oEvent) {
var oParent = $(oEvent.target).parents('span.dropdown_helper')
if (oParent.length === 0) {
this.closeAllPopups(true)
}
}, this)
)
this.initEditorUploader()
this.oCrea = new CCrea({
creaId: this.creaId,
fontNameArray: this.aFonts,
defaultFontName: this.sDefaultFont,
defaultFontSize: this.iDefaultSize,
alwaysTryUseImageWhilePasting: Settings.AlwaysTryUseImageWhilePasting,
isRtl: UserSettings.IsRTL,
enableDrop: false,
onChange: _.bind(function () {
this.textChanged(true)
this.actualTextChanged.valueHasMutated()
}, this),
onCursorMove: _.bind(this.setFontValuesFromText, this),
onFocus: _.bind(this.onCreaFocus, this),
onBlur: _.bind(this.onCreaBlur, this),
onUrlIn: _.bind(this.showLinkPopup, this),
onUrlOut: _.bind(this.hideLinkPopup, this),
onImageSelect: _.bind(this.showImagePopup, this),
onImageBlur: _.bind(this.hideImagePopup, this),
onItemOver: Browser.mobileDevice || App.isMobile() ? null : _.bind(this.onImageOver, this),
onItemOut: Browser.mobileDevice || App.isMobile() ? null : _.bind(this.onImageOut, this),
openInsertLinkDialog: _.bind(this.insertLink, this),
onUrlClicked: true,
})
this.oCrea.start(this.isEnable())
sourceEditor.setOnChangeHandler(() => {
this.textChanged(true)
this.actualTextChanged.valueHasMutated()
})
}
if (this.plaintextDom()) {
this.plaintextDom().on('keyup paste', () => {
this.textChanged(true)
this.actualTextChanged.valueHasMutated()
})
}
this.oCrea.setTabIndex(sTabIndex)
this.clearUndoRedo()
this.editSourceMode(false)
sourceEditor.clear()
this.setText(sText, bPlain)
this.setFontValuesFromText()
this.aUploadedImagesData = []
this.selectedFont(this.sDefaultFont)
this.selectedSize(this.iDefaultSize)
TemplatesUtils.fillTemplatesOptions(this.templates)
}
CHtmlEditorView.prototype.toggleTemplatePopup = function (oViewModel, oEvent) {
if (this.visibleTemplatePopup()) {
this.visibleTemplatePopup(false)
} else {
oEvent.stopPropagation()
this.closeAllPopups()
this.visibleTemplatePopup(true)
}
}
CHtmlEditorView.prototype.insertTemplate = function (sHtml, oEvent) {
oEvent.stopPropagation()
this.insertHtml(sHtml)
}
CHtmlEditorView.prototype.isInitialized = function () {
return !!this.oCrea
}
CHtmlEditorView.prototype.setFocus = function () {
if (this.oCrea) {
this.oCrea.setFocus(false)
}
}
/**
* @param {string} sNewSignatureContent
* @param {string} sOldSignatureContent
*/
CHtmlEditorView.prototype.changeSignatureContent = function (sNewSignatureContent, sOldSignatureContent) {
if (this.oCrea && !this.disableEdit()) {
this.oCrea.changeSignatureContent(sNewSignatureContent, sOldSignatureContent)
}
}
CHtmlEditorView.prototype.setFontValuesFromText = function () {
this.lockFontSubscribing(true)
this.isFWBold(this.oCrea.getIsBold())
this.isFSItalic(this.oCrea.getIsItalic())
this.isTDUnderline(this.oCrea.getIsUnderline())
this.isTDStrikeThrough(this.oCrea.getIsStrikeThrough())
this.isEnumeration(this.oCrea.getIsEnumeration())
this.isBullets(this.oCrea.getIsBullets())
this.selectedFont(this.oCrea.getFontName())
this.selectedSize(this.oCrea.getFontSizeInNumber().toString())
this.lockFontSubscribing(false)
}
CHtmlEditorView.prototype.isUndoAvailable = function () {
if (this.oCrea) {
return this.oCrea.isUndoAvailable()
}
return false
}
CHtmlEditorView.prototype.getPlainText = function () {
if (this.oCrea) {
return this.oCrea.getPlainText()
}
return ''
}
/**
* @param {boolean=} bRemoveSignatureAnchor = false
*/
CHtmlEditorView.prototype.getText = function (bRemoveSignatureAnchor) {
if (this.plainTextMode()) {
return this.plaintextDom() ? this.plaintextDom().val() : ''
}
if (this.editSourceMode() && sourceEditor.isInitialized()) {
return sourceEditor.getText()
}
const sText = this.oCrea ? this.oCrea.getText(bRemoveSignatureAnchor) : ''
return this.sPlaceholderText !== '' && this.removeAllTags(sText) === this.sPlaceholderText ? '' : sText
}
CHtmlEditorView.prototype.getEditableArea = function () {
return this.oCrea.$editableArea
}
/**
* @param {string} sText
* @param {boolean} bPlain
*/
CHtmlEditorView.prototype.setText = function (sText, bPlain = null) {
if (this.oCrea && !this.disableEdit()) {
if (bPlain !== null) {
this.plainTextMode(!!bPlain)
}
if (this.plainTextMode()) {
if (TextUtils.isHtml(sText)) {
sText = TextUtils.htmlToPlain(sText)
}
this.plaintextDom().val(sText)
} else {
if (!TextUtils.isHtml(sText)) {
sText = TextUtils.plainToHtml(sText)
}
this.oCrea.setText(sText)
}
if (this.inactive() && sText === '') {
this.setPlaceholder()
}
}
}
CHtmlEditorView.prototype.undoAndClearRedo = function () {
if (this.oCrea) {
this.oCrea.undo()
this.oCrea.clearRedo()
}
}
CHtmlEditorView.prototype.clearUndoRedo = function () {
if (this.oCrea) {
this.oCrea.clearUndoRedo()
}
}
/**
* @param {string} sText
*/
CHtmlEditorView.prototype.removeAllTags = function (sText) {
return sText.replace(/<style>.*<\/style>/g, '').replace(/<[^>]*>/g, '')
}
CHtmlEditorView.prototype.onCreaFocus = function () {
if (this.oCrea) {
this.closeAllPopups()
this.textFocused(true)
}
}
CHtmlEditorView.prototype.onCreaBlur = function () {
if (this.oCrea) {
this.textFocused(false)
}
}
CHtmlEditorView.prototype.onEscHandler = function () {
if (!Popups.hasOpenedMaximizedPopups()) {
this.closeAllPopups()
}
}
/**
* @param {boolean} bWithoutLinkPopup
*/
CHtmlEditorView.prototype.closeAllPopups = function (bWithoutLinkPopup) {
bWithoutLinkPopup = !!bWithoutLinkPopup
if (!bWithoutLinkPopup) {
this.visibleLinkPopup(false)
}
this.visibleInsertLinkPopup(false)
this.visibleImagePopup(false)
this.visibleInsertImagePopup(false)
this.visibleFontColorPopup(false)
this.visibleTemplatePopup(false)
}
/**
* @param {string} sHtml
*/
CHtmlEditorView.prototype.insertHtml = function (sHtml) {
if (this.oCrea) {
if (!this.oCrea.isFocused()) {
this.oCrea.setFocus(true)
}
this.oCrea.insertHtml(sHtml, false)
}
}
/**
* @param {Object} oViewModel
* @param {Object} oEvent
*/
CHtmlEditorView.prototype.insertLink = function (oViewModel, oEvent) {
if (!this.inactive() && !this.visibleInsertLinkPopup()) {
if (oEvent && _.isFunction(oEvent.stopPropagation)) {
oEvent.stopPropagation()
}
this.linkForInsert(this.oCrea.getSelectedText())
this.closeAllPopups()
this.visibleInsertLinkPopup(true)
this.linkFocused(true)
}
}
/**
* @param {Object} oCurrentViewModel
* @param {Object} event
*/
CHtmlEditorView.prototype.insertLinkFromPopup = function (oCurrentViewModel, event) {
if (this.linkForInsert().length > 0) {
if (AddressUtils.isCorrectEmail(this.linkForInsert())) {
this.oCrea.insertEmailLink(this.linkForInsert())
} else {
this.oCrea.insertLink(this.linkForInsert())
}
}
this.closeInsertLinkPopup(oCurrentViewModel, event)
return false
}
/**
* @param {Object} oCurrentViewModel
* @param {Object} event
*/
CHtmlEditorView.prototype.closeInsertLinkPopup = function (oCurrentViewModel, event) {
this.visibleInsertLinkPopup(false)
if (event) {
event.stopPropagation()
}
}
CHtmlEditorView.prototype.textColor = function (oViewModel, oEvent) {
if (!this.inactive()) {
this.closeAllPopups()
if (!this.visibleFontColorPopup()) {
oEvent.stopPropagation()
this.visibleFontColorPopup(true)
this.oFontColorPickerView.onShow()
this.oBackColorPickerView.onShow()
}
}
}
/**
* @param {string} sColor
* @return string
*/
CHtmlEditorView.prototype.colorToHex = function (sColor) {
if (sColor.substr(0, 1) === '#') {
return sColor
}
/*jslint bitwise: true*/
var aDigits = /(.*?)rgb\((\d+), (\d+), (\d+)\)/.exec(sColor),
iRed = Types.pInt(aDigits[2]),
iGreen = Types.pInt(aDigits[3]),
iBlue = Types.pInt(aDigits[4]),
iRgb = iBlue | (iGreen << 8) | (iRed << 16),
sRgb = iRgb.toString(16)
/*jslint bitwise: false*/
while (sRgb.length < 6) {
sRgb = '0' + sRgb
}
return aDigits[1] + '#' + sRgb
}
/**
* @param {string} sColor
*/
CHtmlEditorView.prototype.setTextColorFromPopup = function (sColor) {
this.oCrea.textColor(this.colorToHex(sColor))
this.closeAllPopups()
}
/**
* @param {string} sColor
*/
CHtmlEditorView.prototype.setBackColorFromPopup = function (sColor) {
this.oCrea.backgroundColor(this.colorToHex(sColor))
this.closeAllPopups()
}
CHtmlEditorView.prototype.insertImage = function (oViewModel, oEvent) {
if (!this.inactive() && Settings.AllowInsertImage && !this.visibleInsertImagePopup()) {
oEvent.stopPropagation()
this.imagePathFromWeb('')
this.closeAllPopups()
this.visibleInsertImagePopup(true)
this.initUploader()
}
return true
}
/**
* @param {Object} oCurrentViewModel
* @param {Object} event
*/
CHtmlEditorView.prototype.insertWebImageFromPopup = function (oCurrentViewModel, event) {
if (Settings.AllowInsertImage && this.imagePathFromWeb().length > 0) {
this.oCrea.insertImage(this.imagePathFromWeb())
}
this.closeInsertImagePopup(oCurrentViewModel, event)
}
/**
* @param {string} sUid
* @param oAttachmentData
*/
CHtmlEditorView.prototype.insertComputerImageFromPopup = function (sUid, oAttachmentData) {
var iAccountId = _.isFunction(this.oParent && this.oParent.senderAccountId)
? this.oParent.senderAccountId()
: MailCache.currentAccountId(),
oAttachment = new CAttachmentModel(iAccountId),
sViewLink = '',
bResult = false
oAttachment.parse(oAttachmentData)
sViewLink = oAttachment.getActionUrl('view')
if (Settings.AllowInsertImage && sViewLink.length > 0) {
bResult = this.oCrea.insertImage(sViewLink)
if (bResult) {
$(this.oCrea.$editableArea)
.find('img[src="' + sViewLink + '"]')
.attr('data-x-src-cid', sUid)
oAttachmentData.CID = sUid
this.aUploadedImagesData.push(oAttachmentData)
}
}
this.closeInsertImagePopup()
}
CHtmlEditorView.prototype.getUploadedImagesData = function () {
return this.aUploadedImagesData
}
/**
* @param {?=} oCurrentViewModel
* @param {?=} event
*/
CHtmlEditorView.prototype.closeInsertImagePopup = function (oCurrentViewModel, event) {
this.visibleInsertImagePopup(false)
if (event) {
event.stopPropagation()
}
}
/**
* Initializes file uploader.
*/
CHtmlEditorView.prototype.initUploader = function () {
// this.oJua must be re-initialized because compose popup is destroyed after it is closed
if (this.imageUploaderButton()) {
this.oJua = new CJua({
action: '?/Api/',
name: 'jua-uploader',
queueSize: 2,
clickElement: this.imageUploaderButton(),
hiddenElementsPosition: UserSettings.IsRTL ? 'right' : 'left',
disableMultiple: true,
disableAjaxUpload: false,
disableDragAndDrop: true,
hidden: _.extendOwn(
{
Module: Settings.ServerModuleName,
Method: 'UploadAttachment',
Parameters: function () {
return JSON.stringify({
AccountID: MailCache.currentAccountId(),
})
},
},
App.getCommonRequestParameters()
),
})
if (this.bInsertImageAsBase64) {
this.oJua.on('onSelect', _.bind(this.onEditorDrop, this))
} else {
this.oJua
.on('onSelect', _.bind(this.onFileUploadSelect, this))
.on('onComplete', _.bind(this.onFileUploadComplete, this))
}
}
}
/**
* Initializes file uploader for editor.
*/
CHtmlEditorView.prototype.initEditorUploader = function () {
// this.editorUploader must be re-initialized because compose popup is destroyed after it is closed
if (Settings.AllowInsertImage && this.uploaderAreaDom()) {
var fBodyDragEnter = null,
fBodyDragOver = null
if (
this.oParent &&
this.oParent.composeUploaderDragOver &&
this.oParent.onFileUploadProgress &&
this.oParent.onFileUploadStart &&
this.oParent.onFileUploadComplete
) {
fBodyDragEnter = _.bind(function () {
this.editorUploaderBodyDragOver(true)
this.oParent.composeUploaderDragOver(true)
}, this)
fBodyDragOver = _.bind(function () {
this.editorUploaderBodyDragOver(false)
this.oParent.composeUploaderDragOver(false)
}, this)
this.editorUploader = new CJua({
action: '?/Api/',
name: 'jua-uploader',
queueSize: 1,
dragAndDropElement: this.bAllowImageDragAndDrop ? this.uploaderAreaDom() : null,
disableMultiple: true,
disableAjaxUpload: false,
disableDragAndDrop: !this.bAllowImageDragAndDrop,
hidden: _.extendOwn(
{
Module: Settings.ServerModuleName,
Method: 'UploadAttachment',
Parameters: function () {
return JSON.stringify({
AccountID: MailCache.currentAccountId(),
})
},
},
App.getCommonRequestParameters()
),
})
this.editorUploader
.on('onDragEnter', _.bind(this.oParent.composeUploaderDragOver, this.oParent, true))
.on('onDragLeave', _.bind(this.oParent.composeUploaderDragOver, this.oParent, false))
.on('onBodyDragEnter', fBodyDragEnter)
.on('onBodyDragLeave', fBodyDragOver)
.on('onProgress', _.bind(this.oParent.onFileUploadProgress, this.oParent))
.on('onSelect', _.bind(this.onEditorDrop, this))
.on('onStart', _.bind(this.oParent.onFileUploadStart, this.oParent))
.on('onComplete', _.bind(this.oParent.onFileUploadComplete, this.oParent))
} else {
fBodyDragEnter = _.bind(this.editorUploaderBodyDragOver, this, true)
fBodyDragOver = _.bind(this.editorUploaderBodyDragOver, this, false)
this.editorUploader = new CJua({
queueSize: 1,
dragAndDropElement: this.bAllowImageDragAndDrop ? this.uploaderAreaDom() : null,
disableMultiple: true,
disableAjaxUpload: false,
disableDragAndDrop: !this.bAllowImageDragAndDrop,
})
this.editorUploader
.on('onBodyDragEnter', fBodyDragEnter)
.on('onBodyDragLeave', fBodyDragOver)
.on('onSelect', _.bind(this.onEditorDrop, this))
}
}
}
CHtmlEditorView.prototype.isDragAndDropSupported = function () {
return this.editorUploader ? this.editorUploader.isDragAndDropSupported() : false
}
CHtmlEditorView.prototype.onEditorDrop = function (sUid, oData) {
var oReader = null,
oFile = null,
self = this,
bCreaFocused = false,
hash = Math.random().toString(),
sId = ''
if (oData && oData.File && typeof oData.File.type === 'string') {
if (Settings.AllowInsertImage && 0 === oData.File.type.indexOf('image/')) {
oFile = oData.File
if (Settings.ImageUploadSizeLimit > 0 && oFile.size > Settings.ImageUploadSizeLimit) {
Popups.showPopup(AlertPopup, [TextUtils.i18n('COREWEBCLIENT/ERROR_UPLOAD_SIZE')])
} else {
oReader = new window.FileReader()
bCreaFocused = this.oCrea.isFocused()
if (!bCreaFocused) {
this.oCrea.setFocus(true)
}
sId = oFile.name + '_' + hash
this.oCrea.insertHtml('<img id="' + sId + '" src="./static/styles/images/wait.gif" />', true)
if (!bCreaFocused) {
this.oCrea.fixFirefoxCursorBug()
}
oReader.onload = function (oEvent) {
self.oCrea.changeImageSource(sId, oEvent.target.result)
}
oReader.readAsDataURL(oFile)
}
} else {
if (this.oParent && this.oParent.onFileUploadSelect) {
this.oParent.onFileUploadSelect(sUid, oData)
return true
} else if (!Browser.ie10AndAbove) {
Popups.showPopup(AlertPopup, [TextUtils.i18n('%MODULENAME%/ERROR_NOT_IMAGE_CHOOSEN')])
}
}
}
return false
}
/**
* @param {Object} oFile
*/
CHtmlEditorView.prototype.isFileImage = function (oFile) {
if (typeof oFile.Type === 'string') {
return -1 !== oFile.Type.indexOf('image')
} else {
var iDotPos = oFile.FileName.lastIndexOf('.'),
sExt = oFile.FileName.substr(iDotPos + 1),
aImageExt = ['jpg', 'jpeg', 'gif', 'tif', 'tiff', 'png']
return -1 !== $.inArray(sExt, aImageExt)
}
}
/**
* @param {string} sUid
* @param {Object} oFile
*/
CHtmlEditorView.prototype.onFileUploadSelect = function (sUid, oFile) {
if (!this.isFileImage(oFile)) {
Popups.showPopup(AlertPopup, [TextUtils.i18n('%MODULENAME%/ERROR_NOT_IMAGE_CHOOSEN')])
return false
}
this.closeInsertImagePopup()
return true
}
/**
* @param {string} sUid
* @param {boolean} bResponseReceived
* @param {Object} oData
*/
CHtmlEditorView.prototype.onFileUploadComplete = function (sUid, bResponseReceived, oData) {
var sError = ''
if (oData && oData.Result) {
if (oData.Result.Error) {
sError =
oData.Result.Error === 'size'
? TextUtils.i18n('COREWEBCLIENT/ERROR_UPLOAD_SIZE')
: TextUtils.i18n('COREWEBCLIENT/ERROR_UPLOAD_UNKNOWN')
Popups.showPopup(AlertPopup, [sError])
} else {
this.oCrea.setFocus(true)
this.insertComputerImageFromPopup(sUid, oData.Result.Attachment)
}
} else {
Popups.showPopup(AlertPopup, [TextUtils.i18n('COREWEBCLIENT/ERROR_UPLOAD_UNKNOWN')])
}
}
CHtmlEditorView.prototype.undo = function () {
if (!this.inactive()) {
this.oCrea.undo()
}
return false
}
CHtmlEditorView.prototype.redo = function () {
if (!this.inactive()) {
this.oCrea.redo()
}
return false
}
CHtmlEditorView.prototype.bold = function () {
if (!this.inactive()) {
this.oCrea.bold()
this.isFWBold(!this.isFWBold())
}
return false
}
CHtmlEditorView.prototype.italic = function () {
if (!this.inactive()) {
this.oCrea.italic()
this.isFSItalic(!this.isFSItalic())
}
return false
}
CHtmlEditorView.prototype.underline = function () {
if (!this.inactive()) {
this.oCrea.underline()
this.isTDUnderline(!this.isTDUnderline())
}
return false
}
CHtmlEditorView.prototype.strikeThrough = function () {
if (!this.inactive()) {
this.oCrea.strikeThrough()
this.isTDStrikeThrough(!this.isTDStrikeThrough())
}
return false
}
CHtmlEditorView.prototype.numbering = function () {
if (!this.inactive()) {
this.oCrea.numbering()
this.isBullets(false)
this.isEnumeration(!this.isEnumeration())
}
return false
}
CHtmlEditorView.prototype.bullets = function () {
if (!this.inactive()) {
this.oCrea.bullets()
this.isEnumeration(false)
this.isBullets(!this.isBullets())
}
return false
}
CHtmlEditorView.prototype.insertHorizontalLine = function () {
if (!this.inactive()) {
this.oCrea.insertHorizontalLine()
}
return false
}
CHtmlEditorView.prototype.blockquote = function () {
if (!this.inactive()) {
this.oCrea.blockquote()
}
return false
}
CHtmlEditorView.prototype.removeFormat = function () {
if (!this.inactive()) {
this.oCrea.removeFormat()
}
return false
}
CHtmlEditorView.prototype.setRtlDirection = function () {
if (!this.inactive()) {
this.oCrea.setRtlDirection()
}
return false
}
CHtmlEditorView.prototype.setLtrDirection = function () {
if (!this.inactive()) {
this.oCrea.setLtrDirection()
}
return false
}
/**
* Changes text mode - html or plain text.
*/
CHtmlEditorView.prototype.changeTextMode = function () {
const changeTextModeHandler = () => {
if (this.plainTextMode()) {
const plainText = '<div>' + TextUtils.plainToHtml(this.getText()) + '</div>'
this.setText(plainText, false)
} else {
this.setText(this.getPlainText(), true)
}
}
if (this.plainTextMode()) {
changeTextModeHandler()
} else {
const confirmText = TextUtils.i18n('%MODULENAME%/CONFIRM_HTML_TO_PLAIN_FORMATTING')
Popups.showPopup(ConfirmPopup, [
confirmText,
function (changeConfirmed) {
if (changeConfirmed) {
changeTextModeHandler()
}
},
])
}
}
/**
* Turns on/off plain text mode.
* @param {boolean} bPlainTextMode
*/
CHtmlEditorView.prototype.setPlainTextMode = function (bPlainTextMode) {
this.plainTextMode(bPlainTextMode)
}
CHtmlEditorView.prototype.toggleSourceEdit = function () {
if (this.editSourceMode()) {
this.setText(sourceEditor.getText())
this.editSourceMode(false)
} else {
sourceEditor.setText(this.getText())
this.editSourceMode(true)
}
}
CHtmlEditorView.prototype.getHotKeysDescriptions = function () {
return [
{ value: 'Ctrl+Z', action: TextUtils.i18n('%MODULENAME%/LABEL_UNDO_HOTKEY'), visible: ko.observable(true) },
{ value: 'Ctrl+Y', action: TextUtils.i18n('%MODULENAME%/LABEL_REDO_HOTKEY'), visible: ko.observable(true) },
{ value: 'Ctrl+K', action: TextUtils.i18n('%MODULENAME%/LABEL_LINK_HOTKEY'), visible: ko.observable(true) },
{ value: 'Ctrl+B', action: TextUtils.i18n('%MODULENAME%/LABEL_BOLD_HOTKEY'), visible: ko.observable(true) },
{ value: 'Ctrl+I', action: TextUtils.i18n('%MODULENAME%/LABEL_ITALIC_HOTKEY'), visible: ko.observable(true) },
{ value: 'Ctrl+U', action: TextUtils.i18n('%MODULENAME%/LABEL_UNDERLINE_HOTKEY'), visible: ko.observable(true) },
]
}
module.exports = CHtmlEditorView