mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-09-06 16:07:03 +03:00
Extract WYSIWYG code from Html.js into HtmlEditor.js
This commit is contained in:
parent
2084913a4d
commit
809fca73a0
5 changed files with 168 additions and 165 deletions
|
|
@ -721,168 +721,7 @@ export const
|
||||||
.replace(/\n/g, '<br>');
|
.replace(/\n/g, '<br>');
|
||||||
blockquoteSwitcher();
|
blockquoteSwitcher();
|
||||||
return tmpl.innerHTML.trim();
|
return tmpl.innerHTML.trim();
|
||||||
},
|
};
|
||||||
|
|
||||||
WYSIWYGS = ko.observableArray();
|
|
||||||
|
|
||||||
WYSIWYGS.push({
|
|
||||||
name: 'Squire',
|
|
||||||
construct: (owner, container, onReady) => onReady(new SquireUI(container))
|
|
||||||
});
|
|
||||||
|
|
||||||
rl.registerWYSIWYG = (name, construct) => WYSIWYGS.push({name, construct});
|
|
||||||
|
|
||||||
export class HtmlEditor {
|
|
||||||
/**
|
|
||||||
* @param {Object} element
|
|
||||||
* @param {Function=} onBlur
|
|
||||||
* @param {Function=} onReady
|
|
||||||
* @param {Function=} onModeChange
|
|
||||||
*/
|
|
||||||
constructor(element, onReady = null, onModeChange = null, onBlur = null) {
|
|
||||||
this.blurTimer = 0;
|
|
||||||
|
|
||||||
this.onBlur = onBlur;
|
|
||||||
this.onModeChange = onModeChange;
|
|
||||||
|
|
||||||
if (element) {
|
|
||||||
onReady = onReady ? [onReady] : [];
|
|
||||||
this.onReady = fn => onReady.push(fn);
|
|
||||||
// TODO: make 'which' user configurable
|
|
||||||
const which = SettingsUserStore.editorWysiwyg(),
|
|
||||||
wysiwyg = WYSIWYGS.find(item => which == item.name) || WYSIWYGS.find(item => 'Squire' == item.name);
|
|
||||||
// const wysiwyg = WYSIWYGS.find(item => 'Squire' == item.name);
|
|
||||||
wysiwyg.construct(this, element, editor => setTimeout(()=>{
|
|
||||||
this.editor = editor;
|
|
||||||
editor.on('blur', () => this.blurTrigger());
|
|
||||||
editor.on('focus', () => clearTimeout(this.blurTimer));
|
|
||||||
editor.on('mode', () => {
|
|
||||||
this.blurTrigger();
|
|
||||||
this.onModeChange?.(!this.isPlain());
|
|
||||||
});
|
|
||||||
this.onReady = fn => fn();
|
|
||||||
onReady.forEach(fn => fn());
|
|
||||||
},1));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
blurTrigger() {
|
|
||||||
if (this.onBlur) {
|
|
||||||
clearTimeout(this.blurTimer);
|
|
||||||
this.blurTimer = setTimeout(() => this.onBlur?.(), 200);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
isHtml() {
|
|
||||||
return this.editor ? !this.isPlain() : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
isPlain() {
|
|
||||||
return this.editor ? 'plain' === this.editor.mode : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
clearCachedSignature() {
|
|
||||||
this.onReady(() => this.editor.execCommand('insertSignature', {
|
|
||||||
clearCache: true
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} signature
|
|
||||||
* @param {bool} html
|
|
||||||
* @param {bool} insertBefore
|
|
||||||
* @returns {void}
|
|
||||||
*/
|
|
||||||
setSignature(signature, html, insertBefore = false) {
|
|
||||||
this.onReady(() => this.editor.execCommand('insertSignature', {
|
|
||||||
isHtml: html,
|
|
||||||
insertBefore: insertBefore,
|
|
||||||
signature: signature
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {boolean=} wrapIsHtml = false
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
getData() {
|
|
||||||
let result = '';
|
|
||||||
if (this.editor) {
|
|
||||||
try {
|
|
||||||
if (this.isPlain()) {
|
|
||||||
result = this.editor.getPlainData();
|
|
||||||
} else {
|
|
||||||
result = this.editor.getData();
|
|
||||||
}
|
|
||||||
} catch (e) {} // eslint-disable-line no-empty
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
getDataWithHtmlMark() {
|
|
||||||
return (this.isHtml() ? ':HTML:' : '') + this.getData();
|
|
||||||
}
|
|
||||||
|
|
||||||
modeWysiwyg() {
|
|
||||||
this.onReady(() => this.editor.setMode('wysiwyg'));
|
|
||||||
}
|
|
||||||
modePlain() {
|
|
||||||
this.onReady(() => this.editor.setMode('plain'));
|
|
||||||
}
|
|
||||||
|
|
||||||
setHtmlOrPlain(text) {
|
|
||||||
text.startsWith(':HTML:')
|
|
||||||
? this.setHtml(text.slice(6))
|
|
||||||
: this.setPlain(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
setData(mode, data) {
|
|
||||||
this.onReady(() => {
|
|
||||||
const editor = this.editor;
|
|
||||||
this.clearCachedSignature();
|
|
||||||
try {
|
|
||||||
editor.setMode(mode);
|
|
||||||
if (this.isPlain()) {
|
|
||||||
editor.setPlainData(data);
|
|
||||||
} else {
|
|
||||||
editor.setData(data);
|
|
||||||
}
|
|
||||||
} catch (e) { console.error(e); }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
setHtml(html) {
|
|
||||||
this.setData('wysiwyg', html/*.replace(/<p[^>]*><\/p>/gi, '')*/);
|
|
||||||
}
|
|
||||||
|
|
||||||
setPlain(txt) {
|
|
||||||
this.setData('plain', txt);
|
|
||||||
}
|
|
||||||
|
|
||||||
focus() {
|
|
||||||
this.onReady(() => this.editor.focus());
|
|
||||||
}
|
|
||||||
|
|
||||||
blur() {
|
|
||||||
this.onReady(() => this.editor.blur());
|
|
||||||
}
|
|
||||||
|
|
||||||
clear() {
|
|
||||||
this.onReady(() => this.isPlain() ? this.setPlain('') : this.setHtml(''));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rl.Utils = {
|
rl.Utils = {
|
||||||
htmlToPlain: htmlToPlain,
|
htmlToPlain: htmlToPlain,
|
||||||
|
|
|
||||||
163
dev/Common/HtmlEditor.js
Normal file
163
dev/Common/HtmlEditor.js
Normal file
|
|
@ -0,0 +1,163 @@
|
||||||
|
import { SettingsUserStore } from 'Stores/User/Settings';
|
||||||
|
|
||||||
|
export const
|
||||||
|
WYSIWYGS = ko.observableArray();
|
||||||
|
|
||||||
|
WYSIWYGS.push({
|
||||||
|
name: 'Squire',
|
||||||
|
construct: (owner, container, onReady) => onReady(new SquireUI(container))
|
||||||
|
});
|
||||||
|
|
||||||
|
rl.registerWYSIWYG = (name, construct) => WYSIWYGS.push({name, construct});
|
||||||
|
|
||||||
|
export class HtmlEditor {
|
||||||
|
/**
|
||||||
|
* @param {Object} element
|
||||||
|
* @param {Function=} onBlur
|
||||||
|
* @param {Function=} onReady
|
||||||
|
* @param {Function=} onModeChange
|
||||||
|
*/
|
||||||
|
constructor(element, onReady = null, onModeChange = null, onBlur = null) {
|
||||||
|
this.blurTimer = 0;
|
||||||
|
|
||||||
|
this.onBlur = onBlur;
|
||||||
|
this.onModeChange = onModeChange;
|
||||||
|
|
||||||
|
if (element) {
|
||||||
|
onReady = onReady ? [onReady] : [];
|
||||||
|
this.onReady = fn => onReady.push(fn);
|
||||||
|
// TODO: make 'which' user configurable
|
||||||
|
const which = SettingsUserStore.editorWysiwyg(),
|
||||||
|
wysiwyg = WYSIWYGS.find(item => which == item.name) || WYSIWYGS.find(item => 'Squire' == item.name);
|
||||||
|
// const wysiwyg = WYSIWYGS.find(item => 'Squire' == item.name);
|
||||||
|
wysiwyg.construct(this, element, editor => setTimeout(()=>{
|
||||||
|
this.editor = editor;
|
||||||
|
editor.on('blur', () => this.blurTrigger());
|
||||||
|
editor.on('focus', () => clearTimeout(this.blurTimer));
|
||||||
|
editor.on('mode', () => {
|
||||||
|
this.blurTrigger();
|
||||||
|
this.onModeChange?.(!this.isPlain());
|
||||||
|
});
|
||||||
|
this.onReady = fn => fn();
|
||||||
|
onReady.forEach(fn => fn());
|
||||||
|
},1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blurTrigger() {
|
||||||
|
if (this.onBlur) {
|
||||||
|
clearTimeout(this.blurTimer);
|
||||||
|
this.blurTimer = setTimeout(() => this.onBlur?.(), 200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isHtml() {
|
||||||
|
return this.editor ? !this.isPlain() : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
isPlain() {
|
||||||
|
return this.editor ? 'plain' === this.editor.mode : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
clearCachedSignature() {
|
||||||
|
this.onReady(() => this.editor.execCommand('insertSignature', {
|
||||||
|
clearCache: true
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} signature
|
||||||
|
* @param {bool} html
|
||||||
|
* @param {bool} insertBefore
|
||||||
|
* @returns {void}
|
||||||
|
*/
|
||||||
|
setSignature(signature, html, insertBefore = false) {
|
||||||
|
this.onReady(() => this.editor.execCommand('insertSignature', {
|
||||||
|
isHtml: html,
|
||||||
|
insertBefore: insertBefore,
|
||||||
|
signature: signature
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {boolean=} wrapIsHtml = false
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
getData() {
|
||||||
|
let result = '';
|
||||||
|
if (this.editor) {
|
||||||
|
try {
|
||||||
|
if (this.isPlain()) {
|
||||||
|
result = this.editor.getPlainData();
|
||||||
|
} else {
|
||||||
|
result = this.editor.getData();
|
||||||
|
}
|
||||||
|
} catch (e) {} // eslint-disable-line no-empty
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
getDataWithHtmlMark() {
|
||||||
|
return (this.isHtml() ? ':HTML:' : '') + this.getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
modeWysiwyg() {
|
||||||
|
this.onReady(() => this.editor.setMode('wysiwyg'));
|
||||||
|
}
|
||||||
|
modePlain() {
|
||||||
|
this.onReady(() => this.editor.setMode('plain'));
|
||||||
|
}
|
||||||
|
|
||||||
|
setHtmlOrPlain(text) {
|
||||||
|
text.startsWith(':HTML:')
|
||||||
|
? this.setHtml(text.slice(6))
|
||||||
|
: this.setPlain(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
setData(mode, data) {
|
||||||
|
this.onReady(() => {
|
||||||
|
const editor = this.editor;
|
||||||
|
this.clearCachedSignature();
|
||||||
|
try {
|
||||||
|
editor.setMode(mode);
|
||||||
|
if (this.isPlain()) {
|
||||||
|
editor.setPlainData(data);
|
||||||
|
} else {
|
||||||
|
editor.setData(data);
|
||||||
|
}
|
||||||
|
} catch (e) { console.error(e); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setHtml(html) {
|
||||||
|
this.setData('wysiwyg', html/*.replace(/<p[^>]*><\/p>/gi, '')*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
setPlain(txt) {
|
||||||
|
this.setData('plain', txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
focus() {
|
||||||
|
this.onReady(() => this.editor.focus());
|
||||||
|
}
|
||||||
|
|
||||||
|
blur() {
|
||||||
|
this.onReady(() => this.editor.blur());
|
||||||
|
}
|
||||||
|
|
||||||
|
clear() {
|
||||||
|
this.onReady(() => this.isPlain() ? this.setPlain('') : this.setHtml(''));
|
||||||
|
}
|
||||||
|
}
|
||||||
2
dev/External/User/ko.js
vendored
2
dev/External/User/ko.js
vendored
|
|
@ -1,7 +1,7 @@
|
||||||
import 'External/ko';
|
import 'External/ko';
|
||||||
import ko from 'ko';
|
import ko from 'ko';
|
||||||
import { RFC822 } from 'Common/File';
|
import { RFC822 } from 'Common/File';
|
||||||
import { HtmlEditor } from 'Common/Html';
|
import { HtmlEditor } from 'Common/HtmlEditor';
|
||||||
import { timeToNode } from 'Common/Translator';
|
import { timeToNode } from 'Common/Translator';
|
||||||
import { doc, elementById, addEventsListeners, dropdowns, leftPanelDisabled } from 'Common/Globals';
|
import { doc, elementById, addEventsListeners, dropdowns, leftPanelDisabled } from 'Common/Globals';
|
||||||
import { EmailAddressesComponent } from 'Component/EmailAddresses';
|
import { EmailAddressesComponent } from 'Component/EmailAddresses';
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import { SaveSettingStatus } from 'Common/Enums';
|
||||||
import { LayoutSideView, LayoutBottomView } from 'Common/EnumsUser';
|
import { LayoutSideView, LayoutBottomView } from 'Common/EnumsUser';
|
||||||
import { setRefreshFoldersInterval } from 'Common/Folders';
|
import { setRefreshFoldersInterval } from 'Common/Folders';
|
||||||
import { Settings, SettingsGet } from 'Common/Globals';
|
import { Settings, SettingsGet } from 'Common/Globals';
|
||||||
import { WYSIWYGS } from 'Common/Html';
|
import { WYSIWYGS } from 'Common/HtmlEditor';
|
||||||
import { isArray } from 'Common/Utils';
|
import { isArray } from 'Common/Utils';
|
||||||
import { addSubscribablesTo, addComputablesTo } from 'External/ko';
|
import { addSubscribablesTo, addComputablesTo } from 'External/ko';
|
||||||
import { i18n, translateTrigger, translatorReload, convertLangName } from 'Common/Translator';
|
import { i18n, translateTrigger, translatorReload, convertLangName } from 'Common/Translator';
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@ import {
|
||||||
} from 'Common/EnumsUser';
|
} from 'Common/EnumsUser';
|
||||||
|
|
||||||
import { pInt, isArray, arrayLength, b64Encode } from 'Common/Utils';
|
import { pInt, isArray, arrayLength, b64Encode } from 'Common/Utils';
|
||||||
import { encodeHtml, HtmlEditor, htmlToPlain } from 'Common/Html';
|
import { encodeHtml, htmlToPlain } from 'Common/Html';
|
||||||
|
import { HtmlEditor } from 'Common/HtmlEditor';
|
||||||
import { koArrayWithDestroy, addObservablesTo, addComputablesTo, addSubscribablesTo } from 'External/ko';
|
import { koArrayWithDestroy, addObservablesTo, addComputablesTo, addSubscribablesTo } from 'External/ko';
|
||||||
|
|
||||||
import { UNUSED_OPTION_VALUE } from 'Common/Consts';
|
import { UNUSED_OPTION_VALUE } from 'Common/Consts';
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue