@skyux/text-editor 5.0.3 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -1
- package/bundles/skyux-text-editor.umd.js +39 -39
- package/documentation.json +61 -14
- package/esm2015/index.js +15 -0
- package/esm2015/index.js.map +1 -0
- package/esm2015/lib/modules/rich-text-display/rich-text-display.component.js +39 -0
- package/esm2015/lib/modules/rich-text-display/rich-text-display.component.js.map +1 -0
- package/esm2015/lib/modules/rich-text-display/rich-text-display.module.js +18 -0
- package/esm2015/lib/modules/rich-text-display/rich-text-display.module.js.map +1 -0
- package/esm2015/lib/modules/shared/forms-utility.js +10 -0
- package/esm2015/lib/modules/shared/forms-utility.js.map +1 -0
- package/esm2015/lib/modules/shared/sky-text-editor-resources.module.js +106 -0
- package/esm2015/lib/modules/shared/sky-text-editor-resources.module.js.map +1 -0
- package/esm2015/lib/modules/text-editor/defaults/font-list-defaults.js +42 -0
- package/esm2015/lib/modules/text-editor/defaults/font-list-defaults.js.map +1 -0
- package/esm2015/lib/modules/text-editor/defaults/font-size-list-defaults.js +7 -0
- package/esm2015/lib/modules/text-editor/defaults/font-size-list-defaults.js.map +1 -0
- package/esm2015/lib/modules/text-editor/defaults/menu-defaults.js +5 -0
- package/esm2015/lib/modules/text-editor/defaults/menu-defaults.js.map +1 -0
- package/esm2015/lib/modules/text-editor/defaults/style-state-defaults.js +15 -0
- package/esm2015/lib/modules/text-editor/defaults/style-state-defaults.js.map +1 -0
- package/esm2015/lib/modules/text-editor/defaults/toolbar-action-defaults.js +12 -0
- package/esm2015/lib/modules/text-editor/defaults/toolbar-action-defaults.js.map +1 -0
- package/esm2015/lib/modules/text-editor/menubar/text-editor-menubar.component.js +196 -0
- package/esm2015/lib/modules/text-editor/menubar/text-editor-menubar.component.js.map +1 -0
- package/esm2015/lib/modules/text-editor/services/text-editor-adapter.service.js +473 -0
- package/esm2015/lib/modules/text-editor/services/text-editor-adapter.service.js.map +1 -0
- package/esm2015/lib/modules/text-editor/services/text-editor-selection.service.js +80 -0
- package/esm2015/lib/modules/text-editor/services/text-editor-selection.service.js.map +1 -0
- package/esm2015/lib/modules/text-editor/services/text-editor.service.js +61 -0
- package/esm2015/lib/modules/text-editor/services/text-editor.service.js.map +1 -0
- package/esm2015/lib/modules/text-editor/services/text-sanitization.service.js +38 -0
- package/esm2015/lib/modules/text-editor/services/text-sanitization.service.js.map +1 -0
- package/esm2015/lib/modules/text-editor/text-editor.component.js +322 -0
- package/esm2015/lib/modules/text-editor/text-editor.component.js.map +1 -0
- package/esm2015/lib/modules/text-editor/text-editor.module.js +99 -0
- package/esm2015/lib/modules/text-editor/text-editor.module.js.map +1 -0
- package/esm2015/lib/modules/text-editor/toolbar/text-editor-toolbar.component.js +175 -0
- package/esm2015/lib/modules/text-editor/toolbar/text-editor-toolbar.component.js.map +1 -0
- package/esm2015/lib/modules/text-editor/types/editor-command.js +2 -0
- package/esm2015/lib/modules/text-editor/types/editor-command.js.map +1 -0
- package/esm2015/lib/modules/text-editor/types/editor-setting.js +2 -0
- package/esm2015/lib/modules/text-editor/types/editor-setting.js.map +1 -0
- package/esm2015/lib/modules/text-editor/types/font-state.js +2 -0
- package/esm2015/lib/modules/text-editor/types/font-state.js.map +1 -0
- package/esm2015/lib/modules/text-editor/types/menu-type.js +2 -0
- package/esm2015/lib/modules/text-editor/types/menu-type.js.map +1 -0
- package/esm2015/lib/modules/text-editor/types/style-state.js +2 -0
- package/esm2015/lib/modules/text-editor/types/style-state.js.map +1 -0
- package/esm2015/lib/modules/text-editor/types/text-editor-merge-field.js +2 -0
- package/esm2015/lib/modules/text-editor/types/text-editor-merge-field.js.map +1 -0
- package/esm2015/lib/modules/text-editor/types/toolbar-action-type.js +2 -0
- package/esm2015/lib/modules/text-editor/types/toolbar-action-type.js.map +1 -0
- package/esm2015/lib/modules/text-editor/url-modal/text-editor-url-modal-context.js +6 -0
- package/esm2015/lib/modules/text-editor/url-modal/text-editor-url-modal-context.js.map +1 -0
- package/esm2015/lib/modules/text-editor/url-modal/text-editor-url-modal-result.js +2 -0
- package/esm2015/lib/modules/text-editor/url-modal/text-editor-url-modal-result.js.map +1 -0
- package/esm2015/lib/modules/text-editor/url-modal/text-editor-url-modal.component.js +121 -0
- package/esm2015/lib/modules/text-editor/url-modal/text-editor-url-modal.component.js.map +1 -0
- package/esm2015/lib/modules/text-editor/url-modal/text-editor-url-target.js +9 -0
- package/esm2015/lib/modules/text-editor/url-modal/text-editor-url-target.js.map +1 -0
- package/esm2015/skyux-text-editor.js +2 -2
- package/esm2015/skyux-text-editor.js.map +1 -0
- package/fesm2015/skyux-text-editor.js +105 -105
- package/fesm2015/skyux-text-editor.js.map +1 -1
- package/index.d.ts +12 -0
- package/{modules → lib/modules}/rich-text-display/rich-text-display.component.d.ts +0 -0
- package/{modules → lib/modules}/rich-text-display/rich-text-display.module.d.ts +0 -0
- package/{modules → lib/modules}/shared/forms-utility.d.ts +0 -0
- package/{modules → lib/modules}/shared/sky-text-editor-resources.module.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/defaults/font-list-defaults.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/defaults/font-size-list-defaults.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/defaults/menu-defaults.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/defaults/style-state-defaults.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/defaults/toolbar-action-defaults.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/menubar/text-editor-menubar.component.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/services/text-editor-adapter.service.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/services/text-editor-selection.service.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/services/text-editor.service.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/services/text-sanitization.service.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/text-editor.component.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/text-editor.module.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/toolbar/text-editor-toolbar.component.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/types/editor-command.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/types/editor-setting.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/types/font-state.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/types/menu-type.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/types/style-state.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/types/text-editor-merge-field.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/types/toolbar-action-type.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/url-modal/text-editor-url-modal-context.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/url-modal/text-editor-url-modal-result.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/url-modal/text-editor-url-modal.component.d.ts +0 -0
- package/{modules → lib/modules}/text-editor/url-modal/text-editor-url-target.d.ts +0 -0
- package/package.json +27 -13
- package/skyux-text-editor.d.ts +1 -1
- package/LICENSE +0 -21
- package/bundles/skyux-text-editor.umd.js.map +0 -1
- package/esm2015/modules/rich-text-display/rich-text-display.component.js +0 -37
- package/esm2015/modules/rich-text-display/rich-text-display.module.js +0 -18
- package/esm2015/modules/shared/forms-utility.js +0 -10
- package/esm2015/modules/shared/sky-text-editor-resources.module.js +0 -106
- package/esm2015/modules/text-editor/defaults/font-list-defaults.js +0 -42
- package/esm2015/modules/text-editor/defaults/font-size-list-defaults.js +0 -7
- package/esm2015/modules/text-editor/defaults/menu-defaults.js +0 -5
- package/esm2015/modules/text-editor/defaults/style-state-defaults.js +0 -15
- package/esm2015/modules/text-editor/defaults/toolbar-action-defaults.js +0 -12
- package/esm2015/modules/text-editor/menubar/text-editor-menubar.component.js +0 -194
- package/esm2015/modules/text-editor/services/text-editor-adapter.service.js +0 -470
- package/esm2015/modules/text-editor/services/text-editor-selection.service.js +0 -80
- package/esm2015/modules/text-editor/services/text-editor.service.js +0 -61
- package/esm2015/modules/text-editor/services/text-sanitization.service.js +0 -38
- package/esm2015/modules/text-editor/text-editor.component.js +0 -317
- package/esm2015/modules/text-editor/text-editor.module.js +0 -99
- package/esm2015/modules/text-editor/toolbar/text-editor-toolbar.component.js +0 -173
- package/esm2015/modules/text-editor/types/editor-command.js +0 -2
- package/esm2015/modules/text-editor/types/editor-setting.js +0 -2
- package/esm2015/modules/text-editor/types/font-state.js +0 -2
- package/esm2015/modules/text-editor/types/menu-type.js +0 -2
- package/esm2015/modules/text-editor/types/style-state.js +0 -2
- package/esm2015/modules/text-editor/types/text-editor-merge-field.js +0 -2
- package/esm2015/modules/text-editor/types/toolbar-action-type.js +0 -2
- package/esm2015/modules/text-editor/url-modal/text-editor-url-modal-context.js +0 -6
- package/esm2015/modules/text-editor/url-modal/text-editor-url-modal-result.js +0 -2
- package/esm2015/modules/text-editor/url-modal/text-editor-url-modal.component.js +0 -119
- package/esm2015/modules/text-editor/url-modal/text-editor-url-target.js +0 -9
- package/esm2015/public-api.js +0 -15
- package/public-api.d.ts +0 -12
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import { SkyAppWindowRef } from '@skyux/core';
|
|
3
|
+
import { Subject } from 'rxjs';
|
|
4
|
+
import { STYLE_STATE_DEFAULTS } from '../defaults/style-state-defaults';
|
|
5
|
+
import { UrlTarget } from '../url-modal/text-editor-url-target';
|
|
6
|
+
import { SkyTextEditorService } from './text-editor.service';
|
|
7
|
+
import { SkyTextEditorSelectionService } from './text-editor-selection.service';
|
|
8
|
+
import * as i0 from "@angular/core";
|
|
9
|
+
import * as i1 from "./text-editor-selection.service";
|
|
10
|
+
import * as i2 from "./text-editor.service";
|
|
11
|
+
import * as i3 from "@skyux/core";
|
|
12
|
+
/**
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export class SkyTextEditorAdapterService {
|
|
16
|
+
constructor(selectionService, textEditorService, windowService) {
|
|
17
|
+
this.selectionService = selectionService;
|
|
18
|
+
this.textEditorService = textEditorService;
|
|
19
|
+
this.windowService = windowService;
|
|
20
|
+
}
|
|
21
|
+
get editors() {
|
|
22
|
+
return this.textEditorService.editors;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Creates a text editor inside the supplied iframe element.
|
|
26
|
+
*/
|
|
27
|
+
addEditor(id, iframeElement, styleState, placeholder) {
|
|
28
|
+
/* istanbul ignore else */
|
|
29
|
+
if (!(id in this.editors)) {
|
|
30
|
+
this.editors[id] = this.createObservers(id, iframeElement);
|
|
31
|
+
const documentEl = this.getIframeDocumentEl(id);
|
|
32
|
+
const styleEl = documentEl.createElement('style');
|
|
33
|
+
styleEl.innerHTML = `.editor:empty:before {
|
|
34
|
+
content: attr(data-placeholder);
|
|
35
|
+
font-family: "Blackbaud Sans", Arial, sans-serif;
|
|
36
|
+
color: #686c73;
|
|
37
|
+
font-weight: 400;
|
|
38
|
+
font-size: 15px;
|
|
39
|
+
font-style: italic;
|
|
40
|
+
}`;
|
|
41
|
+
documentEl.head.appendChild(styleEl);
|
|
42
|
+
const style = Object.assign(Object.assign({}, STYLE_STATE_DEFAULTS), styleState);
|
|
43
|
+
const bodyStyle = `background-color: ${style.backColor};
|
|
44
|
+
color: ${style.fontColor};
|
|
45
|
+
font-family: ${style.font};
|
|
46
|
+
font-size: ${style.fontSize}px`;
|
|
47
|
+
documentEl.querySelector('html').setAttribute('lang', 'en');
|
|
48
|
+
documentEl.body.setAttribute('contenteditable', 'true');
|
|
49
|
+
documentEl.body.setAttribute('id', id);
|
|
50
|
+
documentEl.body.setAttribute('role', 'main');
|
|
51
|
+
documentEl.body.setAttribute('class', 'editor');
|
|
52
|
+
documentEl.body.setAttribute('style', bodyStyle);
|
|
53
|
+
documentEl.body.setAttribute('data-placeholder', placeholder || '');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
disableEditor(id, focusableChildren, textEditorNativeElement) {
|
|
57
|
+
this.setEditorDisabled(id, focusableChildren, textEditorNativeElement, true);
|
|
58
|
+
}
|
|
59
|
+
enableEditor(id, focusableChildren, textEditorNativeElement) {
|
|
60
|
+
this.setEditorDisabled(id, focusableChildren, textEditorNativeElement, false);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Executes a command on the text editor with the corresponding id.
|
|
64
|
+
*/
|
|
65
|
+
execCommand(id, editorCommand) {
|
|
66
|
+
/* istanbul ignore else */
|
|
67
|
+
if (id in this.editors) {
|
|
68
|
+
const documentEl = this.getIframeDocumentEl(id);
|
|
69
|
+
/* istanbul ignore else */
|
|
70
|
+
if (this.editorSelected(id)) {
|
|
71
|
+
const commandIsSupportedAndEnabled = documentEl.execCommand(editorCommand.command, false, editorCommand.value);
|
|
72
|
+
// IE11 doesn't support insertHTML
|
|
73
|
+
/* istanbul ignore next */
|
|
74
|
+
if (editorCommand.command.toLowerCase() === 'inserthtml' &&
|
|
75
|
+
!commandIsSupportedAndEnabled) {
|
|
76
|
+
this.insertHtmlInIE11(id, editorCommand.value);
|
|
77
|
+
}
|
|
78
|
+
this.focusEditor(id);
|
|
79
|
+
this.editors[id].commandChangeObservable.next();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
getCurrentSelection(id) {
|
|
84
|
+
return this.selectionService.getCurrentSelection(this.getIframeDocumentEl(id));
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Returns a data URI using the provided text string.
|
|
88
|
+
* Used to display a merge field inside a string of text.
|
|
89
|
+
*/
|
|
90
|
+
getMergeFieldDataURI(text) {
|
|
91
|
+
const documentEl = this.windowService.nativeWindow.document;
|
|
92
|
+
let textToUse = text;
|
|
93
|
+
if (text.length > 18) {
|
|
94
|
+
textToUse = text.substr(0, 15) + '...';
|
|
95
|
+
}
|
|
96
|
+
const canvasElement = documentEl.createElement('canvas');
|
|
97
|
+
canvasElement.setAttribute('height', '20');
|
|
98
|
+
canvasElement.setAttribute('width', '100');
|
|
99
|
+
canvasElement.style.backgroundColor = 'tan';
|
|
100
|
+
canvasElement.style.border = '1px solid #000000';
|
|
101
|
+
canvasElement.style.borderRadius = '5px';
|
|
102
|
+
const context = canvasElement.getContext('2d');
|
|
103
|
+
context.font = '12px Arial';
|
|
104
|
+
context.textAlign = 'center';
|
|
105
|
+
context.fillText(textToUse, 50, 15);
|
|
106
|
+
context.globalCompositeOperation = 'destination-over';
|
|
107
|
+
context.fillStyle = '#00FFFF';
|
|
108
|
+
context.fillRect(0, 0, 100, 20);
|
|
109
|
+
context.globalCompositeOperation = 'source-over';
|
|
110
|
+
context.lineWidth = 2;
|
|
111
|
+
context.strokeStyle = '#FF0000';
|
|
112
|
+
context.strokeRect(0, 0, 100, 20);
|
|
113
|
+
const result = canvasElement.toDataURL('image/png', 1.0);
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
116
|
+
getStyleState(id) {
|
|
117
|
+
const documentEl = this.getIframeDocumentEl(id);
|
|
118
|
+
/* istanbul ignore else */
|
|
119
|
+
if (this.editorSelected(id)) {
|
|
120
|
+
return {
|
|
121
|
+
backColor: this.getColor(documentEl, 'BackColor'),
|
|
122
|
+
fontColor: this.getColor(documentEl, 'ForeColor'),
|
|
123
|
+
fontSize: parseInt(this.getFontSize(id), undefined),
|
|
124
|
+
font: documentEl.queryCommandValue('fontname'),
|
|
125
|
+
boldState: documentEl.queryCommandState('Bold'),
|
|
126
|
+
italicState: documentEl.queryCommandState('Italic'),
|
|
127
|
+
underlineState: documentEl.queryCommandState('Underline'),
|
|
128
|
+
linkState: this.hasLink(id),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/* istanbul ignore next */
|
|
132
|
+
return {};
|
|
133
|
+
}
|
|
134
|
+
getEditorInnerHtml(id) {
|
|
135
|
+
const documentEl = this.getIframeDocumentEl(id);
|
|
136
|
+
if (documentEl) {
|
|
137
|
+
return this.replaceHtmlCodes(documentEl.body.innerHTML);
|
|
138
|
+
}
|
|
139
|
+
return '';
|
|
140
|
+
}
|
|
141
|
+
setEditorInnerHtml(id, value) {
|
|
142
|
+
const documentEl = this.getIframeDocumentEl(id);
|
|
143
|
+
const editorContent = documentEl.body;
|
|
144
|
+
/* istanbul ignore else */
|
|
145
|
+
if (editorContent.innerHTML !== value) {
|
|
146
|
+
editorContent.innerHTML = value;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
focusEditor(id) {
|
|
150
|
+
/* istanbul ignore else */
|
|
151
|
+
if (id in this.editors) {
|
|
152
|
+
const windowEl = this.getContentWindowEl(id);
|
|
153
|
+
const iframeDocumentEl = this.getIframeDocumentEl(id);
|
|
154
|
+
const currentSelection = this.selectionService.getCurrentSelectionRange(iframeDocumentEl, windowEl);
|
|
155
|
+
const cursorIsNotActiveAndHasReset = currentSelection &&
|
|
156
|
+
currentSelection.startOffset === 0 &&
|
|
157
|
+
currentSelection.endOffset === 0;
|
|
158
|
+
if (!this.editorSelected(id) || cursorIsNotActiveAndHasReset) {
|
|
159
|
+
// focus the end of the editor
|
|
160
|
+
const documentEl = this.windowService.nativeWindow.document;
|
|
161
|
+
const editor = iframeDocumentEl.body;
|
|
162
|
+
const range = documentEl.createRange();
|
|
163
|
+
this.editors[id].iframeElementRef.focus();
|
|
164
|
+
editor.focus();
|
|
165
|
+
/* istanbul ignore else */
|
|
166
|
+
if (windowEl.getSelection && documentEl.createRange) {
|
|
167
|
+
range.selectNodeContents(editor);
|
|
168
|
+
range.collapse(false);
|
|
169
|
+
const sel = windowEl.getSelection();
|
|
170
|
+
sel.removeAllRanges();
|
|
171
|
+
sel.addRange(range);
|
|
172
|
+
}
|
|
173
|
+
else {
|
|
174
|
+
// IE only
|
|
175
|
+
const textRange = editor.createTextRange();
|
|
176
|
+
textRange.moveToElementText(editor);
|
|
177
|
+
textRange.collapse(false);
|
|
178
|
+
textRange.select();
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
// Cursor may not be active, restore it
|
|
183
|
+
this.editors[id].iframeElementRef.focus();
|
|
184
|
+
iframeDocumentEl.body.focus();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
getLink(editorId) {
|
|
189
|
+
let link = undefined;
|
|
190
|
+
const anchorEl = this.getSelectedAnchorTag(editorId);
|
|
191
|
+
if (anchorEl && anchorEl.href) {
|
|
192
|
+
link = {
|
|
193
|
+
target: anchorEl.getAttribute('target') === '_blank'
|
|
194
|
+
? UrlTarget.NewWindow
|
|
195
|
+
: UrlTarget.None,
|
|
196
|
+
url: anchorEl.href,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
return link;
|
|
200
|
+
}
|
|
201
|
+
getSelectedAnchorTag(editorId) {
|
|
202
|
+
const selectedEl = this.getCurrentSelectionParentElement(editorId);
|
|
203
|
+
return this.getParent(selectedEl, 'a');
|
|
204
|
+
}
|
|
205
|
+
saveSelection(id) {
|
|
206
|
+
return this.selectionService.getCurrentSelectionRange(this.getIframeDocumentEl(id), this.getContentWindowEl(id));
|
|
207
|
+
}
|
|
208
|
+
selectElement(id, element) {
|
|
209
|
+
this.selectionService.selectElement(this.getIframeDocumentEl(id), this.getContentWindowEl(id), element);
|
|
210
|
+
}
|
|
211
|
+
setPlaceholder(id, placeholder) {
|
|
212
|
+
const documentEl = this.getIframeDocumentEl(id);
|
|
213
|
+
documentEl.body.setAttribute('data-placeholder', placeholder || '');
|
|
214
|
+
}
|
|
215
|
+
setFontSize(id, fontSize) {
|
|
216
|
+
const doc = this.getIframeDocumentEl(id);
|
|
217
|
+
this.execCommand(id, { command: 'fontSize', value: 1 });
|
|
218
|
+
const fontElements = Array.from(doc.querySelectorAll('font[size="1"]'));
|
|
219
|
+
for (let element of fontElements) {
|
|
220
|
+
element.removeAttribute('size');
|
|
221
|
+
element.style.fontSize = fontSize + 'px';
|
|
222
|
+
}
|
|
223
|
+
this.cleanUpBlankStyleTags(doc);
|
|
224
|
+
this.focusEditor(id);
|
|
225
|
+
this.editors[id].commandChangeObservable.next();
|
|
226
|
+
}
|
|
227
|
+
removeObservers(setting) {
|
|
228
|
+
/* istanbul ignore next */
|
|
229
|
+
const documentEl = setting.iframeElementRef.contentWindow
|
|
230
|
+
? setting.iframeElementRef.contentWindow.document
|
|
231
|
+
: setting.iframeElementRef.contentDocument;
|
|
232
|
+
setting.selectionChangeObservable.complete();
|
|
233
|
+
setting.clickObservable.complete();
|
|
234
|
+
setting.commandChangeObservable.complete();
|
|
235
|
+
documentEl.removeEventListener('selectionchange', setting.selectionListener);
|
|
236
|
+
documentEl.removeEventListener('input', setting.selectionListener);
|
|
237
|
+
documentEl.removeEventListener('mousedown', setting.clickListener);
|
|
238
|
+
documentEl.body.removeEventListener('paste', setting.pasteListener);
|
|
239
|
+
}
|
|
240
|
+
getContentWindowEl(id) {
|
|
241
|
+
return this.editors[id].iframeElementRef.contentWindow;
|
|
242
|
+
}
|
|
243
|
+
getChildSelectedAnchorTags(editorId) {
|
|
244
|
+
const selectedRange = this.getCurrentSelection(editorId).getRangeAt(0);
|
|
245
|
+
if (selectedRange.toString().length <= 0) {
|
|
246
|
+
return [];
|
|
247
|
+
}
|
|
248
|
+
const parentElement = this.getCurrentSelectionParentElement(editorId);
|
|
249
|
+
let childElements = [];
|
|
250
|
+
/* istanbul ignore else */
|
|
251
|
+
if (parentElement) {
|
|
252
|
+
childElements = Array.from(parentElement.querySelectorAll('a'));
|
|
253
|
+
}
|
|
254
|
+
/* istanbul ignore next */
|
|
255
|
+
return childElements.filter((element) => {
|
|
256
|
+
// IE specific
|
|
257
|
+
if (!selectedRange.intersectsNode) {
|
|
258
|
+
if (!element || !element.href) {
|
|
259
|
+
return false;
|
|
260
|
+
}
|
|
261
|
+
const tempRange = document.createRange();
|
|
262
|
+
tempRange.selectNodeContents(element);
|
|
263
|
+
return ((selectedRange.compareBoundaryPoints(Range.START_TO_START, tempRange) !== -1 &&
|
|
264
|
+
selectedRange.compareBoundaryPoints(Range.START_TO_END, tempRange) !== 1) ||
|
|
265
|
+
(selectedRange.compareBoundaryPoints(Range.END_TO_START, tempRange) !== -1 &&
|
|
266
|
+
selectedRange.compareBoundaryPoints(Range.END_TO_END, tempRange) !==
|
|
267
|
+
1));
|
|
268
|
+
}
|
|
269
|
+
// Normal non-IE
|
|
270
|
+
return (!!element && !!element.href && selectedRange.intersectsNode(element));
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
getIframeDocumentEl(id) {
|
|
274
|
+
/* istanbul ignore next */
|
|
275
|
+
if (!(id in this.editors)) {
|
|
276
|
+
return undefined;
|
|
277
|
+
}
|
|
278
|
+
const contentWindowEl = this.getContentWindowEl(id);
|
|
279
|
+
/* istanbul ignore else */
|
|
280
|
+
if (contentWindowEl) {
|
|
281
|
+
return contentWindowEl.document;
|
|
282
|
+
}
|
|
283
|
+
/* istanbul ignore next */
|
|
284
|
+
return this.editors[id].iframeElementRef.contentDocument;
|
|
285
|
+
}
|
|
286
|
+
getFontSize(id) {
|
|
287
|
+
let fontSize = STYLE_STATE_DEFAULTS.fontSize.toString();
|
|
288
|
+
const selection = this.getCurrentSelection(id);
|
|
289
|
+
/* istanbul ignore else */
|
|
290
|
+
if (selection &&
|
|
291
|
+
selection.anchorNode &&
|
|
292
|
+
selection.anchorNode.parentElement) {
|
|
293
|
+
let element = selection.anchorNode;
|
|
294
|
+
if (element.nodeType !== 1) {
|
|
295
|
+
element = element.parentElement;
|
|
296
|
+
}
|
|
297
|
+
const computedStyle = window.getComputedStyle(element);
|
|
298
|
+
/* istanbul ignore else */
|
|
299
|
+
if (computedStyle) {
|
|
300
|
+
fontSize = computedStyle.getPropertyValue('font-size');
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
return fontSize;
|
|
304
|
+
}
|
|
305
|
+
createObservers(id, element) {
|
|
306
|
+
/* istanbul ignore next */
|
|
307
|
+
const documentEl = element.contentWindow
|
|
308
|
+
? element.contentWindow.document
|
|
309
|
+
: element.contentDocument;
|
|
310
|
+
// Firefox bug where we need to open/close to cancel load so it doesn't overwrite attrs
|
|
311
|
+
documentEl.open();
|
|
312
|
+
documentEl.close();
|
|
313
|
+
const selectionObservable = new Subject();
|
|
314
|
+
const selectionListener = () => selectionObservable.next();
|
|
315
|
+
const clickObservable = new Subject();
|
|
316
|
+
const clickListener = () => clickObservable.next();
|
|
317
|
+
const pasteListener = this.getPasteOverride(id);
|
|
318
|
+
const blurObservable = new Subject();
|
|
319
|
+
const blurListener = () => blurObservable.next();
|
|
320
|
+
const inputObservable = new Subject();
|
|
321
|
+
const inputListener = () => inputObservable.next();
|
|
322
|
+
documentEl.addEventListener('selectionchange', selectionListener);
|
|
323
|
+
documentEl.addEventListener('input', inputListener);
|
|
324
|
+
documentEl.addEventListener('mousedown', clickListener);
|
|
325
|
+
documentEl.body.addEventListener('paste', pasteListener);
|
|
326
|
+
documentEl.body.addEventListener('blur', blurListener);
|
|
327
|
+
return {
|
|
328
|
+
blurObservable: blurObservable,
|
|
329
|
+
clickObservable: clickObservable,
|
|
330
|
+
commandChangeObservable: new Subject(),
|
|
331
|
+
iframeElementRef: element,
|
|
332
|
+
inputObservable: inputObservable,
|
|
333
|
+
selectionChangeObservable: selectionObservable,
|
|
334
|
+
blurListener: blurListener,
|
|
335
|
+
clickListener: clickListener,
|
|
336
|
+
inputListener: inputListener,
|
|
337
|
+
pasteListener: pasteListener,
|
|
338
|
+
selectionListener: selectionListener,
|
|
339
|
+
};
|
|
340
|
+
}
|
|
341
|
+
/* istanbul ignore next */
|
|
342
|
+
getPasteOverride(id) {
|
|
343
|
+
return (e) => {
|
|
344
|
+
e.preventDefault();
|
|
345
|
+
const text = e.clipboardData.getData('text/plain');
|
|
346
|
+
this.execCommand(id, { command: 'insertHTML', value: text });
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
getCurrentSelectionParentElement(id) {
|
|
350
|
+
return this.selectionService.getCurrentSelectionParentElement(this.getIframeDocumentEl(id));
|
|
351
|
+
}
|
|
352
|
+
getColor(documentEl, selector) {
|
|
353
|
+
const commandValue = documentEl.queryCommandValue(selector);
|
|
354
|
+
// Edge is weird and returns numbers
|
|
355
|
+
/* istanbul ignore if */
|
|
356
|
+
if (typeof commandValue === 'number') {
|
|
357
|
+
/* istanbul ignore next */
|
|
358
|
+
// tslint:disable-next-line: no-bitwise
|
|
359
|
+
return ('rgb(' +
|
|
360
|
+
(commandValue & 0xff) +
|
|
361
|
+
', ' +
|
|
362
|
+
// tslint:disable-next-line: no-bitwise
|
|
363
|
+
((commandValue & 0xff00) >> 8) +
|
|
364
|
+
', ' +
|
|
365
|
+
// tslint:disable-next-line: no-bitwise
|
|
366
|
+
((commandValue & 0xff0000) >> 16) +
|
|
367
|
+
')');
|
|
368
|
+
}
|
|
369
|
+
// Firefox uses 'Transparent' instead of a color value
|
|
370
|
+
/* istanbul ignore next */
|
|
371
|
+
if (commandValue.toString().toLowerCase() === 'transparent') {
|
|
372
|
+
return STYLE_STATE_DEFAULTS.backColor;
|
|
373
|
+
}
|
|
374
|
+
return commandValue;
|
|
375
|
+
}
|
|
376
|
+
hasLink(editorId) {
|
|
377
|
+
const anchorEl = this.getSelectedAnchorTag(editorId);
|
|
378
|
+
const childAnchorEls = this.getChildSelectedAnchorTags(editorId);
|
|
379
|
+
/* istanbul ignore next */
|
|
380
|
+
return childAnchorEls.length > 0 || (!!anchorEl && !!anchorEl.href);
|
|
381
|
+
}
|
|
382
|
+
getParent(element, tag) {
|
|
383
|
+
let currentNode = element;
|
|
384
|
+
while (currentNode && currentNode.tagName.toUpperCase() !== 'BODY') {
|
|
385
|
+
if (currentNode.tagName.toUpperCase() === tag.toUpperCase()) {
|
|
386
|
+
return currentNode;
|
|
387
|
+
}
|
|
388
|
+
currentNode = currentNode.parentElement;
|
|
389
|
+
}
|
|
390
|
+
return undefined;
|
|
391
|
+
}
|
|
392
|
+
editorSelected(id) {
|
|
393
|
+
const documentEl = this.getIframeDocumentEl(id);
|
|
394
|
+
return this.selectionService.isElementSelected(documentEl, documentEl.body);
|
|
395
|
+
}
|
|
396
|
+
/* istanbul ignore next */
|
|
397
|
+
insertHtmlInIE11(id, html) {
|
|
398
|
+
const documentEl = this.getIframeDocumentEl(id);
|
|
399
|
+
const windowEl = this.getContentWindowEl(id);
|
|
400
|
+
const sel = windowEl.getSelection();
|
|
401
|
+
if (sel.getRangeAt && sel.rangeCount) {
|
|
402
|
+
let range = sel.getRangeAt(0);
|
|
403
|
+
range.deleteContents();
|
|
404
|
+
const el = documentEl.createElement('div');
|
|
405
|
+
el.innerHTML = html;
|
|
406
|
+
let frag = documentEl.createDocumentFragment(), node, lastNode;
|
|
407
|
+
while (el.firstChild) {
|
|
408
|
+
node = el.firstChild;
|
|
409
|
+
lastNode = frag.appendChild(node);
|
|
410
|
+
}
|
|
411
|
+
range.insertNode(frag);
|
|
412
|
+
// Preserve the selection
|
|
413
|
+
if (lastNode) {
|
|
414
|
+
range = range.cloneRange();
|
|
415
|
+
range.setStartAfter(lastNode);
|
|
416
|
+
range.collapse(true);
|
|
417
|
+
sel.removeAllRanges();
|
|
418
|
+
sel.addRange(range);
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
cleanUpBlankStyleTags(doc) {
|
|
423
|
+
const orphanElements = Array.from(doc.querySelectorAll('font,span,*[style=""]'));
|
|
424
|
+
for (let element of orphanElements) {
|
|
425
|
+
if (!element.getAttribute('style')) {
|
|
426
|
+
element.removeAttribute('style');
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
const removableElements = orphanElements.filter((element) => {
|
|
430
|
+
const tagName = element.tagName.toUpperCase();
|
|
431
|
+
return ((tagName === 'FONT' || tagName === 'SPAN') &&
|
|
432
|
+
(element.attributes.length === 0 || !element.hasChildNodes));
|
|
433
|
+
});
|
|
434
|
+
for (let element of removableElements) {
|
|
435
|
+
const parent = element.parentNode;
|
|
436
|
+
/* istanbul ignore else */
|
|
437
|
+
if (parent) {
|
|
438
|
+
while (element.firstChild) {
|
|
439
|
+
parent.insertBefore(element.firstChild, element);
|
|
440
|
+
}
|
|
441
|
+
parent.removeChild(element);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
// Certain values are encoded in html and need to be decoded
|
|
446
|
+
replaceHtmlCodes(str) {
|
|
447
|
+
return str
|
|
448
|
+
.replace(/ /, String.fromCharCode(160))
|
|
449
|
+
.replace(/</g, '<')
|
|
450
|
+
.replace(/>/g, '>')
|
|
451
|
+
.replace(/&/g, '&');
|
|
452
|
+
}
|
|
453
|
+
setEditorDisabled(id, focusableChildren, textEditorNativeElement, disabled) {
|
|
454
|
+
textEditorNativeElement.style.pointerEvents = disabled ? 'none' : 'auto';
|
|
455
|
+
textEditorNativeElement.setAttribute('aria-disabled', disabled ? 'true' : 'false');
|
|
456
|
+
/* istanbul ignore else */
|
|
457
|
+
if (focusableChildren.length > 0) {
|
|
458
|
+
focusableChildren.forEach((aFocusableChild) => {
|
|
459
|
+
aFocusableChild.tabIndex = disabled ? -1 : 0;
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
this.getIframeDocumentEl(id).body.setAttribute('contenteditable', disabled ? 'false' : 'true');
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
SkyTextEditorAdapterService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyTextEditorAdapterService, deps: [{ token: i1.SkyTextEditorSelectionService }, { token: i2.SkyTextEditorService }, { token: i3.SkyAppWindowRef }], target: i0.ɵɵFactoryTarget.Injectable });
|
|
466
|
+
SkyTextEditorAdapterService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyTextEditorAdapterService, providedIn: 'root' });
|
|
467
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyTextEditorAdapterService, decorators: [{
|
|
468
|
+
type: Injectable,
|
|
469
|
+
args: [{
|
|
470
|
+
providedIn: 'root',
|
|
471
|
+
}]
|
|
472
|
+
}], ctorParameters: function () { return [{ type: i1.SkyTextEditorSelectionService }, { type: i2.SkyTextEditorService }, { type: i3.SkyAppWindowRef }]; } });
|
|
473
|
+
//# sourceMappingURL=text-editor-adapter.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-editor-adapter.service.js","sourceRoot":"","sources":["../../../../../../../../../libs/components/text-editor/src/lib/modules/text-editor/services/text-editor-adapter.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from '@angular/core';\n\nimport { SkyAppWindowRef } from '@skyux/core';\n\nimport { Subject } from 'rxjs';\n\nimport { STYLE_STATE_DEFAULTS } from '../defaults/style-state-defaults';\n\nimport { EditorCommand } from '../types/editor-command';\n\nimport { EditorSetting } from '../types/editor-setting';\n\nimport { SkyTextEditorStyleState } from '../types/style-state';\n\nimport { UrlModalResult } from '../url-modal/text-editor-url-modal-result';\n\nimport { UrlTarget } from '../url-modal/text-editor-url-target';\n\nimport { SkyTextEditorService } from './text-editor.service';\n\nimport { SkyTextEditorSelectionService } from './text-editor-selection.service';\n\n/**\n * @internal\n */\n@Injectable({\n providedIn: 'root',\n})\nexport class SkyTextEditorAdapterService {\n private get editors(): { [key: string]: EditorSetting } {\n return this.textEditorService.editors;\n }\n\n constructor(\n private selectionService: SkyTextEditorSelectionService,\n private textEditorService: SkyTextEditorService,\n private windowService: SkyAppWindowRef\n ) {}\n\n /**\n * Creates a text editor inside the supplied iframe element.\n */\n public addEditor(\n id: string,\n iframeElement: HTMLIFrameElement,\n styleState: SkyTextEditorStyleState,\n placeholder?: string\n ): void {\n /* istanbul ignore else */\n if (!(id in this.editors)) {\n this.editors[id] = this.createObservers(id, iframeElement);\n\n const documentEl = this.getIframeDocumentEl(id);\n\n const styleEl = documentEl.createElement('style');\n styleEl.innerHTML = `.editor:empty:before {\n content: attr(data-placeholder);\n font-family: \"Blackbaud Sans\", Arial, sans-serif;\n color: #686c73;\n font-weight: 400;\n font-size: 15px;\n font-style: italic;\n }`;\n documentEl.head.appendChild(styleEl);\n\n const style: SkyTextEditorStyleState = {\n ...STYLE_STATE_DEFAULTS,\n ...styleState,\n };\n const bodyStyle = `background-color: ${style.backColor};\n color: ${style.fontColor};\n font-family: ${style.font};\n font-size: ${style.fontSize}px`;\n documentEl.querySelector('html').setAttribute('lang', 'en');\n documentEl.body.setAttribute('contenteditable', 'true');\n documentEl.body.setAttribute('id', id);\n documentEl.body.setAttribute('role', 'main');\n documentEl.body.setAttribute('class', 'editor');\n documentEl.body.setAttribute('style', bodyStyle);\n documentEl.body.setAttribute('data-placeholder', placeholder || '');\n }\n }\n\n public disableEditor(\n id: string,\n focusableChildren: HTMLElement[],\n textEditorNativeElement: any\n ): void {\n this.setEditorDisabled(\n id,\n focusableChildren,\n textEditorNativeElement,\n true\n );\n }\n\n public enableEditor(\n id: string,\n focusableChildren: HTMLElement[],\n textEditorNativeElement: any\n ): void {\n this.setEditorDisabled(\n id,\n focusableChildren,\n textEditorNativeElement,\n false\n );\n }\n\n /**\n * Executes a command on the text editor with the corresponding id.\n */\n public execCommand(id: string, editorCommand: EditorCommand): void {\n /* istanbul ignore else */\n if (id in this.editors) {\n const documentEl = this.getIframeDocumentEl(id);\n\n /* istanbul ignore else */\n if (this.editorSelected(id)) {\n const commandIsSupportedAndEnabled = documentEl.execCommand(\n editorCommand.command,\n false,\n editorCommand.value\n );\n\n // IE11 doesn't support insertHTML\n /* istanbul ignore next */\n if (\n editorCommand.command.toLowerCase() === 'inserthtml' &&\n !commandIsSupportedAndEnabled\n ) {\n this.insertHtmlInIE11(id, editorCommand.value);\n }\n\n this.focusEditor(id);\n this.editors[id].commandChangeObservable.next();\n }\n }\n }\n\n public getCurrentSelection(id: string): Selection {\n return this.selectionService.getCurrentSelection(\n this.getIframeDocumentEl(id)\n );\n }\n\n /**\n * Returns a data URI using the provided text string.\n * Used to display a merge field inside a string of text.\n */\n public getMergeFieldDataURI(text: string): string {\n const documentEl = this.windowService.nativeWindow.document;\n let textToUse = text;\n if (text.length > 18) {\n textToUse = text.substr(0, 15) + '...';\n }\n\n const canvasElement = documentEl.createElement('canvas');\n canvasElement.setAttribute('height', '20');\n canvasElement.setAttribute('width', '100');\n canvasElement.style.backgroundColor = 'tan';\n canvasElement.style.border = '1px solid #000000';\n canvasElement.style.borderRadius = '5px';\n\n const context = canvasElement.getContext('2d');\n context.font = '12px Arial';\n context.textAlign = 'center';\n context.fillText(textToUse, 50, 15);\n\n context.globalCompositeOperation = 'destination-over';\n context.fillStyle = '#00FFFF';\n context.fillRect(0, 0, 100, 20);\n\n context.globalCompositeOperation = 'source-over';\n context.lineWidth = 2;\n context.strokeStyle = '#FF0000';\n context.strokeRect(0, 0, 100, 20);\n\n const result = canvasElement.toDataURL('image/png', 1.0);\n return result;\n }\n\n public getStyleState(id: string): Partial<SkyTextEditorStyleState> {\n const documentEl = this.getIframeDocumentEl(id);\n\n /* istanbul ignore else */\n if (this.editorSelected(id)) {\n return {\n backColor: this.getColor(documentEl, 'BackColor'),\n fontColor: this.getColor(documentEl, 'ForeColor'),\n fontSize: parseInt(this.getFontSize(id), undefined),\n font: documentEl.queryCommandValue('fontname'),\n boldState: documentEl.queryCommandState('Bold'),\n italicState: documentEl.queryCommandState('Italic'),\n underlineState: documentEl.queryCommandState('Underline'),\n linkState: this.hasLink(id),\n };\n }\n\n /* istanbul ignore next */\n return {};\n }\n\n public getEditorInnerHtml(id: string): string {\n const documentEl = this.getIframeDocumentEl(id);\n if (documentEl) {\n return this.replaceHtmlCodes(documentEl.body.innerHTML);\n }\n return '';\n }\n\n public setEditorInnerHtml(id: string, value: string): void {\n const documentEl = this.getIframeDocumentEl(id);\n const editorContent = documentEl.body;\n /* istanbul ignore else */\n if (editorContent.innerHTML !== value) {\n editorContent.innerHTML = value;\n }\n }\n\n public focusEditor(id: string): void {\n /* istanbul ignore else */\n if (id in this.editors) {\n const windowEl = this.getContentWindowEl(id);\n const iframeDocumentEl = this.getIframeDocumentEl(id);\n const currentSelection = this.selectionService.getCurrentSelectionRange(\n iframeDocumentEl,\n windowEl\n );\n const cursorIsNotActiveAndHasReset =\n currentSelection &&\n currentSelection.startOffset === 0 &&\n currentSelection.endOffset === 0;\n\n if (!this.editorSelected(id) || cursorIsNotActiveAndHasReset) {\n // focus the end of the editor\n const documentEl = this.windowService.nativeWindow.document;\n const editor: any = iframeDocumentEl.body;\n const range = documentEl.createRange();\n\n this.editors[id].iframeElementRef.focus();\n editor.focus();\n /* istanbul ignore else */\n if (windowEl.getSelection && documentEl.createRange) {\n range.selectNodeContents(editor);\n range.collapse(false);\n const sel = windowEl.getSelection();\n sel.removeAllRanges();\n sel.addRange(range);\n } else {\n // IE only\n const textRange = editor.createTextRange();\n textRange.moveToElementText(editor);\n textRange.collapse(false);\n textRange.select();\n }\n } else {\n // Cursor may not be active, restore it\n this.editors[id].iframeElementRef.focus();\n iframeDocumentEl.body.focus();\n }\n }\n }\n\n public getLink(editorId: string): UrlModalResult {\n let link: UrlModalResult = undefined;\n const anchorEl = this.getSelectedAnchorTag(editorId);\n if (anchorEl && anchorEl.href) {\n link = {\n target:\n anchorEl.getAttribute('target') === '_blank'\n ? UrlTarget.NewWindow\n : UrlTarget.None,\n url: anchorEl.href,\n };\n }\n\n return link;\n }\n\n public getSelectedAnchorTag(editorId: string): HTMLAnchorElement {\n const selectedEl = this.getCurrentSelectionParentElement(editorId);\n\n return this.getParent(selectedEl, 'a') as HTMLAnchorElement;\n }\n\n public saveSelection(id: string): Range {\n return this.selectionService.getCurrentSelectionRange(\n this.getIframeDocumentEl(id),\n this.getContentWindowEl(id)\n );\n }\n\n public selectElement(id: string, element: HTMLElement): void {\n this.selectionService.selectElement(\n this.getIframeDocumentEl(id),\n this.getContentWindowEl(id),\n element\n );\n }\n\n public setPlaceholder(id: string, placeholder?: string): void {\n const documentEl = this.getIframeDocumentEl(id);\n documentEl.body.setAttribute('data-placeholder', placeholder || '');\n }\n\n public setFontSize(id: string, fontSize: number): void {\n const doc = this.getIframeDocumentEl(id);\n this.execCommand(id, { command: 'fontSize', value: 1 });\n const fontElements: HTMLElement[] = Array.from(\n doc.querySelectorAll('font[size=\"1\"]')\n );\n for (let element of fontElements) {\n element.removeAttribute('size');\n element.style.fontSize = fontSize + 'px';\n }\n this.cleanUpBlankStyleTags(doc);\n\n this.focusEditor(id);\n this.editors[id].commandChangeObservable.next();\n }\n\n public removeObservers(setting: EditorSetting): void {\n /* istanbul ignore next */\n const documentEl = setting.iframeElementRef.contentWindow\n ? setting.iframeElementRef.contentWindow.document\n : setting.iframeElementRef.contentDocument;\n setting.selectionChangeObservable.complete();\n setting.clickObservable.complete();\n setting.commandChangeObservable.complete();\n documentEl.removeEventListener(\n 'selectionchange',\n setting.selectionListener\n );\n documentEl.removeEventListener('input', setting.selectionListener);\n documentEl.removeEventListener('mousedown', setting.clickListener);\n documentEl.body.removeEventListener('paste', setting.pasteListener);\n }\n\n private getContentWindowEl(id: string): Window {\n return this.editors[id].iframeElementRef.contentWindow;\n }\n\n private getChildSelectedAnchorTags(editorId: string): Element[] {\n const selectedRange = this.getCurrentSelection(editorId).getRangeAt(0);\n if (selectedRange.toString().length <= 0) {\n return [];\n }\n\n const parentElement = this.getCurrentSelectionParentElement(editorId);\n\n let childElements = [];\n /* istanbul ignore else */\n if (parentElement) {\n childElements = Array.from(parentElement.querySelectorAll('a'));\n }\n\n /* istanbul ignore next */\n return childElements.filter((element) => {\n // IE specific\n if (!selectedRange.intersectsNode) {\n if (!element || !element.href) {\n return false;\n }\n const tempRange = document.createRange();\n tempRange.selectNodeContents(element);\n return (\n (selectedRange.compareBoundaryPoints(\n Range.START_TO_START,\n tempRange\n ) !== -1 &&\n selectedRange.compareBoundaryPoints(\n Range.START_TO_END,\n tempRange\n ) !== 1) ||\n (selectedRange.compareBoundaryPoints(\n Range.END_TO_START,\n tempRange\n ) !== -1 &&\n selectedRange.compareBoundaryPoints(Range.END_TO_END, tempRange) !==\n 1)\n );\n }\n\n // Normal non-IE\n return (\n !!element && !!element.href && selectedRange.intersectsNode(element)\n );\n });\n }\n\n private getIframeDocumentEl(id: string): Document {\n /* istanbul ignore next */\n if (!(id in this.editors)) {\n return undefined;\n }\n\n const contentWindowEl = this.getContentWindowEl(id);\n /* istanbul ignore else */\n if (contentWindowEl) {\n return contentWindowEl.document;\n }\n\n /* istanbul ignore next */\n return this.editors[id].iframeElementRef.contentDocument;\n }\n\n private getFontSize(id: string): string {\n let fontSize = STYLE_STATE_DEFAULTS.fontSize.toString();\n const selection = this.getCurrentSelection(id);\n /* istanbul ignore else */\n if (\n selection &&\n selection.anchorNode &&\n selection.anchorNode.parentElement\n ) {\n let element = selection.anchorNode;\n if (element.nodeType !== 1) {\n element = element.parentElement;\n }\n const computedStyle = window.getComputedStyle(element as Element);\n /* istanbul ignore else */\n if (computedStyle) {\n fontSize = computedStyle.getPropertyValue('font-size');\n }\n }\n return fontSize;\n }\n\n private createObservers(\n id: string,\n element: HTMLIFrameElement\n ): EditorSetting {\n /* istanbul ignore next */\n const documentEl = element.contentWindow\n ? element.contentWindow.document\n : element.contentDocument;\n\n // Firefox bug where we need to open/close to cancel load so it doesn't overwrite attrs\n documentEl.open();\n documentEl.close();\n\n const selectionObservable = new Subject();\n const selectionListener = () => selectionObservable.next();\n const clickObservable = new Subject();\n const clickListener = () => clickObservable.next();\n const pasteListener = this.getPasteOverride(id);\n const blurObservable = new Subject();\n const blurListener = () => blurObservable.next();\n const inputObservable = new Subject();\n const inputListener = () => inputObservable.next();\n\n documentEl.addEventListener('selectionchange', selectionListener);\n documentEl.addEventListener('input', inputListener);\n documentEl.addEventListener('mousedown', clickListener);\n documentEl.body.addEventListener('paste', pasteListener);\n documentEl.body.addEventListener('blur', blurListener);\n return {\n blurObservable: blurObservable,\n clickObservable: clickObservable,\n commandChangeObservable: new Subject(),\n iframeElementRef: element,\n inputObservable: inputObservable,\n selectionChangeObservable: selectionObservable,\n blurListener: blurListener,\n clickListener: clickListener,\n inputListener: inputListener,\n pasteListener: pasteListener,\n selectionListener: selectionListener,\n };\n }\n\n /* istanbul ignore next */\n private getPasteOverride(id: string): (e: ClipboardEvent) => void {\n return (e: ClipboardEvent): void => {\n e.preventDefault();\n const text = e.clipboardData.getData('text/plain');\n this.execCommand(id, { command: 'insertHTML', value: text });\n };\n }\n\n private getCurrentSelectionParentElement(id: string): Element {\n return this.selectionService.getCurrentSelectionParentElement(\n this.getIframeDocumentEl(id)\n );\n }\n\n private getColor(documentEl: Document, selector: string): string {\n const commandValue = documentEl.queryCommandValue(selector);\n\n // Edge is weird and returns numbers\n /* istanbul ignore if */\n if (typeof commandValue === 'number') {\n /* istanbul ignore next */\n // tslint:disable-next-line: no-bitwise\n return (\n 'rgb(' +\n (commandValue & 0xff) +\n ', ' +\n // tslint:disable-next-line: no-bitwise\n ((commandValue & 0xff00) >> 8) +\n ', ' +\n // tslint:disable-next-line: no-bitwise\n ((commandValue & 0xff0000) >> 16) +\n ')'\n );\n }\n\n // Firefox uses 'Transparent' instead of a color value\n /* istanbul ignore next */\n if (commandValue.toString().toLowerCase() === 'transparent') {\n return STYLE_STATE_DEFAULTS.backColor;\n }\n return commandValue;\n }\n\n private hasLink(editorId: string): boolean {\n const anchorEl = this.getSelectedAnchorTag(editorId);\n const childAnchorEls = this.getChildSelectedAnchorTags(editorId);\n /* istanbul ignore next */\n return childAnchorEls.length > 0 || (!!anchorEl && !!anchorEl.href);\n }\n\n private getParent(element: Element, tag: string): Element {\n let currentNode = element;\n while (currentNode && currentNode.tagName.toUpperCase() !== 'BODY') {\n if (currentNode.tagName.toUpperCase() === tag.toUpperCase()) {\n return currentNode;\n }\n currentNode = currentNode.parentElement;\n }\n return undefined;\n }\n\n private editorSelected(id: string): boolean {\n const documentEl = this.getIframeDocumentEl(id);\n return this.selectionService.isElementSelected(documentEl, documentEl.body);\n }\n\n /* istanbul ignore next */\n private insertHtmlInIE11(id: string, html: string): void {\n const documentEl = this.getIframeDocumentEl(id);\n const windowEl = this.getContentWindowEl(id);\n const sel = windowEl.getSelection();\n if (sel.getRangeAt && sel.rangeCount) {\n let range = sel.getRangeAt(0);\n range.deleteContents();\n\n const el = documentEl.createElement('div');\n el.innerHTML = html;\n let frag = documentEl.createDocumentFragment(),\n node,\n lastNode;\n while (el.firstChild) {\n node = el.firstChild;\n lastNode = frag.appendChild(node);\n }\n range.insertNode(frag);\n\n // Preserve the selection\n if (lastNode) {\n range = range.cloneRange();\n range.setStartAfter(lastNode);\n range.collapse(true);\n sel.removeAllRanges();\n sel.addRange(range);\n }\n }\n }\n\n private cleanUpBlankStyleTags(doc: Document): void {\n const orphanElements: HTMLElement[] = Array.from(\n doc.querySelectorAll('font,span,*[style=\"\"]')\n );\n for (let element of orphanElements) {\n if (!element.getAttribute('style')) {\n element.removeAttribute('style');\n }\n }\n const removableElements = orphanElements.filter((element) => {\n const tagName = element.tagName.toUpperCase();\n return (\n (tagName === 'FONT' || tagName === 'SPAN') &&\n (element.attributes.length === 0 || !element.hasChildNodes)\n );\n });\n for (let element of removableElements) {\n const parent = element.parentNode;\n /* istanbul ignore else */\n if (parent) {\n while (element.firstChild) {\n parent.insertBefore(element.firstChild, element);\n }\n parent.removeChild(element);\n }\n }\n }\n\n // Certain values are encoded in html and need to be decoded\n private replaceHtmlCodes(str: string): string {\n return str\n .replace(/ /, String.fromCharCode(160))\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/&/g, '&');\n }\n\n private setEditorDisabled(\n id: string,\n focusableChildren: HTMLElement[],\n textEditorNativeElement: any,\n disabled: boolean\n ): void {\n textEditorNativeElement.style.pointerEvents = disabled ? 'none' : 'auto';\n textEditorNativeElement.setAttribute(\n 'aria-disabled',\n disabled ? 'true' : 'false'\n );\n /* istanbul ignore else */\n if (focusableChildren.length > 0) {\n focusableChildren.forEach((aFocusableChild) => {\n aFocusableChild.tabIndex = disabled ? -1 : 0;\n });\n }\n this.getIframeDocumentEl(id).body.setAttribute(\n 'contenteditable',\n disabled ? 'false' : 'true'\n );\n }\n}\n"]}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { Injectable } from '@angular/core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
/**
|
|
4
|
+
* @internal
|
|
5
|
+
*/
|
|
6
|
+
export class SkyTextEditorSelectionService {
|
|
7
|
+
isElementSelected(documentEl, element) {
|
|
8
|
+
const selectedNode = this.getCurrentSelection(documentEl)
|
|
9
|
+
.anchorNode;
|
|
10
|
+
/* istanbul ignore next */
|
|
11
|
+
return (selectedNode &&
|
|
12
|
+
(element.contains(selectedNode) ||
|
|
13
|
+
(selectedNode.parentNode && element.contains(selectedNode.parentNode))));
|
|
14
|
+
}
|
|
15
|
+
getCurrentSelection(documentEl) {
|
|
16
|
+
return documentEl.getSelection();
|
|
17
|
+
}
|
|
18
|
+
getCurrentSelectionParentElement(documentEl) {
|
|
19
|
+
const selection = this.getCurrentSelection(documentEl);
|
|
20
|
+
let selectedEl;
|
|
21
|
+
/* istanbul ignore else */
|
|
22
|
+
if (selection &&
|
|
23
|
+
selection.getRangeAt &&
|
|
24
|
+
selection.getRangeAt(0).commonAncestorContainer) {
|
|
25
|
+
selectedEl = selection.getRangeAt(0).commonAncestorContainer;
|
|
26
|
+
selectedEl =
|
|
27
|
+
selectedEl.nodeType !== 1 ? selectedEl.parentElement : selectedEl;
|
|
28
|
+
}
|
|
29
|
+
else if (selection && selection.type !== 'Control') {
|
|
30
|
+
selectedEl = selection.createRange().parentElement();
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
return selectedEl;
|
|
36
|
+
}
|
|
37
|
+
getCurrentSelectionRange(documentEl, windowEl) {
|
|
38
|
+
/* istanbul ignore else */
|
|
39
|
+
if (windowEl.getSelection) {
|
|
40
|
+
const sel = windowEl.getSelection();
|
|
41
|
+
/* istanbul ignore else */
|
|
42
|
+
if (sel.getRangeAt && sel.rangeCount) {
|
|
43
|
+
return sel.getRangeAt(0);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else if (documentEl.getSelection() &&
|
|
47
|
+
documentEl.getSelection().getRangeAt) {
|
|
48
|
+
return documentEl.getSelection().getRangeAt(0);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
selectElement(documentEl, windowEl, element) {
|
|
52
|
+
/* istanbul ignore else */
|
|
53
|
+
if (element) {
|
|
54
|
+
/* istanbul ignore else */
|
|
55
|
+
if (windowEl.getSelection) {
|
|
56
|
+
const sel = windowEl.getSelection();
|
|
57
|
+
sel.removeAllRanges();
|
|
58
|
+
const range = documentEl.createRange();
|
|
59
|
+
range.selectNodeContents(element);
|
|
60
|
+
sel.addRange(range);
|
|
61
|
+
}
|
|
62
|
+
else if (documentEl.getSelection) {
|
|
63
|
+
const sel = documentEl.getSelection();
|
|
64
|
+
sel.removeAllRanges();
|
|
65
|
+
const range = documentEl.createRange();
|
|
66
|
+
range.selectNodeContents(element);
|
|
67
|
+
sel.addRange(range);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
SkyTextEditorSelectionService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyTextEditorSelectionService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
73
|
+
SkyTextEditorSelectionService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyTextEditorSelectionService, providedIn: 'root' });
|
|
74
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.16", ngImport: i0, type: SkyTextEditorSelectionService, decorators: [{
|
|
75
|
+
type: Injectable,
|
|
76
|
+
args: [{
|
|
77
|
+
providedIn: 'root',
|
|
78
|
+
}]
|
|
79
|
+
}] });
|
|
80
|
+
//# sourceMappingURL=text-editor-selection.service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-editor-selection.service.js","sourceRoot":"","sources":["../../../../../../../../../libs/components/text-editor/src/lib/modules/text-editor/services/text-editor-selection.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;;AAE3C;;GAEG;AAIH,MAAM,OAAO,6BAA6B;IACjC,iBAAiB,CAAC,UAAoB,EAAE,OAAoB;QACjE,MAAM,YAAY,GAAG,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC;aACtD,UAAyB,CAAC;QAC7B,0BAA0B;QAC1B,OAAO,CACL,YAAY;YACZ,CAAC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC;gBAC7B,CAAC,YAAY,CAAC,UAAU,IAAI,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAC1E,CAAC;IACJ,CAAC;IAEM,mBAAmB,CAAC,UAAoB;QAC7C,OAAO,UAAU,CAAC,YAAY,EAAE,CAAC;IACnC,CAAC;IAEM,gCAAgC,CAAC,UAAoB;QAC1D,MAAM,SAAS,GAAG,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC;QACvD,IAAI,UAAmB,CAAC;QACxB,0BAA0B;QAC1B,IACE,SAAS;YACT,SAAS,CAAC,UAAU;YACpB,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,uBAAuB,EAC/C;YACA,UAAU,GAAG,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,uBAAkC,CAAC;YACxE,UAAU;gBACR,UAAU,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,CAAC,UAAU,CAAC;SACrE;aAAM,IAAI,SAAS,IAAI,SAAS,CAAC,IAAI,KAAK,SAAS,EAAE;YACpD,UAAU,GAAI,SAAiB,CAAC,WAAW,EAAE,CAAC,aAAa,EAAE,CAAC;SAC/D;aAAM;YACL,OAAO,SAAS,CAAC;SAClB;QACD,OAAO,UAAU,CAAC;IACpB,CAAC;IAEM,wBAAwB,CAC7B,UAAoB,EACpB,QAAgB;QAEhB,0BAA0B;QAC1B,IAAI,QAAQ,CAAC,YAAY,EAAE;YACzB,MAAM,GAAG,GAAG,QAAQ,CAAC,YAAY,EAAE,CAAC;YACpC,0BAA0B;YAC1B,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,UAAU,EAAE;gBACpC,OAAO,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;aAC1B;SACF;aAAM,IACL,UAAU,CAAC,YAAY,EAAE;YACzB,UAAU,CAAC,YAAY,EAAE,CAAC,UAAU,EACpC;YACA,OAAO,UAAU,CAAC,YAAY,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;SAChD;IACH,CAAC;IAEM,aAAa,CAClB,UAAoB,EACpB,QAAgB,EAChB,OAAoB;QAEpB,0BAA0B;QAC1B,IAAI,OAAO,EAAE;YACX,0BAA0B;YAC1B,IAAI,QAAQ,CAAC,YAAY,EAAE;gBACzB,MAAM,GAAG,GAAG,QAAQ,CAAC,YAAY,EAAE,CAAC;gBACpC,GAAG,CAAC,eAAe,EAAE,CAAC;gBACtB,MAAM,KAAK,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;gBACvC,KAAK,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;gBAClC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;aACrB;iBAAM,IAAI,UAAU,CAAC,YAAY,EAAE;gBAClC,MAAM,GAAG,GAAG,UAAU,CAAC,YAAY,EAAE,CAAC;gBACtC,GAAG,CAAC,eAAe,EAAE,CAAC;gBACtB,MAAM,KAAK,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;gBACvC,KAAK,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC;gBAClC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;aACrB;SACF;IACH,CAAC;;2HA7EU,6BAA6B;+HAA7B,6BAA6B,cAF5B,MAAM;4FAEP,6BAA6B;kBAHzC,UAAU;mBAAC;oBACV,UAAU,EAAE,MAAM;iBACnB","sourcesContent":["import { Injectable } from '@angular/core';\n\n/**\n * @internal\n */\n@Injectable({\n providedIn: 'root',\n})\nexport class SkyTextEditorSelectionService {\n public isElementSelected(documentEl: Document, element: HTMLElement) {\n const selectedNode = this.getCurrentSelection(documentEl)\n .anchorNode as HTMLElement;\n /* istanbul ignore next */\n return (\n selectedNode &&\n (element.contains(selectedNode) ||\n (selectedNode.parentNode && element.contains(selectedNode.parentNode)))\n );\n }\n\n public getCurrentSelection(documentEl: Document): Selection {\n return documentEl.getSelection();\n }\n\n public getCurrentSelectionParentElement(documentEl: Document): Element {\n const selection = this.getCurrentSelection(documentEl);\n let selectedEl: Element;\n /* istanbul ignore else */\n if (\n selection &&\n selection.getRangeAt &&\n selection.getRangeAt(0).commonAncestorContainer\n ) {\n selectedEl = selection.getRangeAt(0).commonAncestorContainer as Element;\n selectedEl =\n selectedEl.nodeType !== 1 ? selectedEl.parentElement : selectedEl;\n } else if (selection && selection.type !== 'Control') {\n selectedEl = (selection as any).createRange().parentElement();\n } else {\n return undefined;\n }\n return selectedEl;\n }\n\n public getCurrentSelectionRange(\n documentEl: Document,\n windowEl: Window\n ): Range {\n /* istanbul ignore else */\n if (windowEl.getSelection) {\n const sel = windowEl.getSelection();\n /* istanbul ignore else */\n if (sel.getRangeAt && sel.rangeCount) {\n return sel.getRangeAt(0);\n }\n } else if (\n documentEl.getSelection() &&\n documentEl.getSelection().getRangeAt\n ) {\n return documentEl.getSelection().getRangeAt(0);\n }\n }\n\n public selectElement(\n documentEl: Document,\n windowEl: Window,\n element: HTMLElement\n ): void {\n /* istanbul ignore else */\n if (element) {\n /* istanbul ignore else */\n if (windowEl.getSelection) {\n const sel = windowEl.getSelection();\n sel.removeAllRanges();\n const range = documentEl.createRange();\n range.selectNodeContents(element);\n sel.addRange(range);\n } else if (documentEl.getSelection) {\n const sel = documentEl.getSelection();\n sel.removeAllRanges();\n const range = documentEl.createRange();\n range.selectNodeContents(element);\n sel.addRange(range);\n }\n }\n }\n}\n"]}
|