@firestitch/html-editor 9.4.4 → 9.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/app/classes/plugin.d.ts +7 -7
  2. package/app/components/html-editor/html-editor.component.d.ts +51 -51
  3. package/app/components/html-renderer/html-renderer.component.d.ts +9 -9
  4. package/app/consts/paragraph-buttons.const.d.ts +1 -1
  5. package/app/consts/rich-buttons.const.d.ts +1 -1
  6. package/app/consts/text-buttons.const.d.ts +1 -1
  7. package/app/enums/default-plugin.enum.d.ts +14 -13
  8. package/app/fs-html-editor.module.d.ts +25 -25
  9. package/app/injects/config.inject.d.ts +3 -3
  10. package/app/interfaces/html-editor-config.d.ts +25 -25
  11. package/app/interfaces/plugin-button.d.ts +12 -12
  12. package/app/interfaces/plugin-config.d.ts +5 -5
  13. package/app/plugins/checklist.plugin.d.ts +7 -7
  14. package/app/plugins/code.plugin.d.ts +9 -9
  15. package/app/plugins/configs/mention-plugin.config.d.ts +12 -12
  16. package/app/plugins/configs/screen-record-plugin.config.d.ts +7 -7
  17. package/app/plugins/mention.plugin.d.ts +12 -12
  18. package/app/plugins/screen-record.plugin.d.ts +11 -11
  19. package/app/services/froala-loader.service.d.ts +17 -17
  20. package/app/utils/loader.d.ts +7 -7
  21. package/bundles/firestitch-html-editor.umd.js +990 -988
  22. package/bundles/firestitch-html-editor.umd.js.map +1 -1
  23. package/bundles/firestitch-html-editor.umd.min.js +1 -1
  24. package/bundles/firestitch-html-editor.umd.min.js.map +1 -1
  25. package/esm2015/app/classes/plugin.js +4 -4
  26. package/esm2015/app/components/html-editor/html-editor.component.js +422 -422
  27. package/esm2015/app/components/html-renderer/html-renderer.component.js +33 -33
  28. package/esm2015/app/consts/paragraph-buttons.const.js +8 -8
  29. package/esm2015/app/consts/rich-buttons.const.js +6 -6
  30. package/esm2015/app/consts/text-buttons.const.js +18 -18
  31. package/esm2015/app/enums/default-plugin.enum.js +1 -1
  32. package/esm2015/app/fs-html-editor.module.js +57 -56
  33. package/esm2015/app/injects/config.inject.js +3 -3
  34. package/esm2015/app/plugins/checklist.plugin.js +34 -34
  35. package/esm2015/app/plugins/code.plugin.js +62 -62
  36. package/esm2015/app/plugins/mention.plugin.js +72 -72
  37. package/esm2015/app/plugins/screen-record.plugin.js +91 -91
  38. package/esm2015/app/services/froala-loader.service.js +80 -80
  39. package/esm2015/app/utils/loader.js +83 -82
  40. package/esm2015/firestitch-html-editor.js +8 -8
  41. package/esm2015/public_api.js +11 -11
  42. package/esm5/app/classes/plugin.js +8 -8
  43. package/esm5/app/components/html-editor/html-editor.component.js +445 -445
  44. package/esm5/app/components/html-renderer/html-renderer.component.js +38 -38
  45. package/esm5/app/consts/paragraph-buttons.const.js +8 -8
  46. package/esm5/app/consts/rich-buttons.const.js +6 -6
  47. package/esm5/app/consts/text-buttons.const.js +18 -18
  48. package/esm5/app/enums/default-plugin.enum.js +1 -1
  49. package/esm5/app/fs-html-editor.module.js +62 -61
  50. package/esm5/app/injects/config.inject.js +3 -3
  51. package/esm5/app/plugins/checklist.plugin.js +40 -40
  52. package/esm5/app/plugins/code.plugin.js +69 -69
  53. package/esm5/app/plugins/mention.plugin.js +78 -78
  54. package/esm5/app/plugins/screen-record.plugin.js +105 -105
  55. package/esm5/app/services/froala-loader.service.js +95 -95
  56. package/esm5/app/utils/loader.js +83 -82
  57. package/esm5/firestitch-html-editor.js +8 -8
  58. package/esm5/public_api.js +11 -11
  59. package/fesm2015/firestitch-html-editor.js +915 -913
  60. package/fesm2015/firestitch-html-editor.js.map +1 -1
  61. package/fesm5/firestitch-html-editor.js +992 -990
  62. package/fesm5/firestitch-html-editor.js.map +1 -1
  63. package/firestitch-html-editor.d.ts +9 -9
  64. package/firestitch-html-editor.metadata.json +1 -1
  65. package/package.json +1 -1
  66. package/public_api.d.ts +16 -16
@@ -9,949 +9,951 @@ import { merge, debounce } from 'lodash-es';
9
9
  import { DomSanitizer } from '@angular/platform-browser';
10
10
  import Tribute from 'tributejs';
11
11
 
12
- const RichButtons = [
13
- 'insertTable',
14
- 'insertImage',
15
- 'insertLink',
16
- 'insertVideo',
12
+ const RichButtons = [
13
+ 'insertTable',
14
+ 'insertImage',
15
+ 'insertLink',
16
+ 'insertVideo',
17
17
  ];
18
18
 
19
- const TextButtons = [
20
- 'paragraphFormat',
21
- 'code',
22
- 'bold',
23
- 'italic',
24
- 'underline',
25
- 'strikeThrough',
26
- 'subscript',
27
- 'superscript',
28
- 'fontFamily',
29
- 'fontSize',
30
- 'textColor',
31
- 'backgroundColor',
32
- 'inlineClass',
33
- 'inlineStyle',
34
- 'clearFormatting',
35
- 'quote',
19
+ const TextButtons = [
20
+ 'paragraphFormat',
21
+ 'code',
22
+ 'bold',
23
+ 'italic',
24
+ 'underline',
25
+ 'strikeThrough',
26
+ 'subscript',
27
+ 'superscript',
28
+ 'fontFamily',
29
+ 'fontSize',
30
+ 'textColor',
31
+ 'backgroundColor',
32
+ 'inlineClass',
33
+ 'inlineStyle',
34
+ 'clearFormatting',
35
+ 'quote',
36
36
  ];
37
37
 
38
- const ParagraphButtons = [
39
- 'align',
40
- 'formatOL',
41
- 'formatUL',
42
- 'checklist',
43
- 'indent',
44
- 'outdent',
38
+ const ParagraphButtons = [
39
+ 'align',
40
+ 'formatOL',
41
+ 'formatUL',
42
+ 'checklist',
43
+ 'indent',
44
+ 'outdent',
45
45
  ];
46
46
 
47
- const FS_HTML_EDITOR_DEFAULT_CONFIG = new InjectionToken('fs-html-editor.default-config');
47
+ const FS_HTML_EDITOR_DEFAULT_CONFIG = new InjectionToken('fs-html-editor.default-config');
48
48
  const FS_HTML_EDITOR_CONFIG = new InjectionToken('fs-html-editor.config');
49
49
 
50
- function resourceLoaderFactory() {
51
- let resourceBase = '/assets/js/froala/';
52
- let stylesBase = '/assets/css/';
53
- const head = document.getElementsByTagName('head')[0];
54
- const files = new Map();
55
- const resourcePaths = {
56
- froala: 'froala_editor.min.js',
57
- align: 'plugins/align.min.js',
58
- colors: 'plugins/colors.min.js',
59
- image: 'plugins/image.min.js',
60
- link: 'plugins/link.min.js',
61
- lists: 'plugins/lists.min.js',
62
- paragraph_format: 'plugins/paragraph_format.min.js',
63
- table: 'plugins/table.min.js',
64
- url: 'plugins/url.min.js',
65
- video: 'plugins/video.min.js',
66
- quote: 'plugins/quote.min.js',
67
- draggable: 'plugins/draggable.min.js',
68
- };
69
- const stylesPaths = {
70
- froala: 'froala_editor.pkgd.min.css',
71
- };
72
- const loadResource = function (scriptPath) {
73
- if (!files.has(scriptPath)) {
74
- const obs$ = new Observable((obs) => {
75
- const script = document.createElement('script');
76
- script.src = scriptPath;
77
- head.appendChild(script);
78
- script.onload = () => {
79
- obs.next();
80
- obs.complete();
81
- };
82
- script.onerror = (err) => {
83
- obs.error(err);
84
- };
85
- })
86
- .pipe(shareReplay(1));
87
- files.set(scriptPath, obs$);
88
- }
89
- return files.get(scriptPath);
90
- };
91
- const loadStyles = function (stylePath) {
92
- if (!files.has(stylePath)) {
93
- const obs$ = new Observable((obs) => {
94
- const style = document.createElement('link');
95
- style.id = stylePath;
96
- style.rel = 'stylesheet';
97
- style.href = `${stylePath}`;
98
- head.appendChild(style);
99
- style.onload = () => {
100
- obs.next();
101
- obs.complete();
102
- };
103
- style.onerror = (err) => {
104
- obs.error(err);
105
- };
106
- });
107
- files.set(stylePath, obs$);
108
- }
109
- return files.get(stylePath);
110
- };
111
- return {
112
- setResourceBase: (path) => {
113
- resourceBase = path;
114
- },
115
- setStylesBase: (path) => {
116
- stylesBase = path;
117
- },
118
- loadResource: (resourceName) => {
119
- const path = resourcePaths[resourceName] || resourceName;
120
- return loadResource(resourceBase + path);
121
- },
122
- loadStyles: (resourceName) => {
123
- const path = stylesPaths[resourceName] || resourceName;
124
- return loadStyles(stylesBase + path);
125
- }
126
- };
127
- }
50
+ function resourceLoaderFactory() {
51
+ let resourceBase = '/assets/js/froala/';
52
+ let stylesBase = '/assets/css/';
53
+ const head = document.getElementsByTagName('head')[0];
54
+ const files = new Map();
55
+ const resourcePaths = {
56
+ froala: 'froala_editor.min.js',
57
+ align: 'plugins/align.min.js',
58
+ colors: 'plugins/colors.min.js',
59
+ image: 'plugins/image.min.js',
60
+ link: 'plugins/link.min.js',
61
+ lists: 'plugins/lists.min.js',
62
+ paragraph_format: 'plugins/paragraph_format.min.js',
63
+ table: 'plugins/table.min.js',
64
+ url: 'plugins/url.min.js',
65
+ video: 'plugins/video.min.js',
66
+ quote: 'plugins/quote.min.js',
67
+ draggable: 'plugins/draggable.min.js',
68
+ font_size: 'plugins/font_size.min.js',
69
+ };
70
+ const stylesPaths = {
71
+ froala: 'froala_editor.pkgd.min.css',
72
+ };
73
+ const loadResource = function (scriptPath) {
74
+ if (!files.has(scriptPath)) {
75
+ const obs$ = new Observable((obs) => {
76
+ const script = document.createElement('script');
77
+ script.src = scriptPath;
78
+ head.appendChild(script);
79
+ script.onload = () => {
80
+ obs.next();
81
+ obs.complete();
82
+ };
83
+ script.onerror = (err) => {
84
+ obs.error(err);
85
+ };
86
+ })
87
+ .pipe(shareReplay(1));
88
+ files.set(scriptPath, obs$);
89
+ }
90
+ return files.get(scriptPath);
91
+ };
92
+ const loadStyles = function (stylePath) {
93
+ if (!files.has(stylePath)) {
94
+ const obs$ = new Observable((obs) => {
95
+ const style = document.createElement('link');
96
+ style.id = stylePath;
97
+ style.rel = 'stylesheet';
98
+ style.href = `${stylePath}`;
99
+ head.appendChild(style);
100
+ style.onload = () => {
101
+ obs.next();
102
+ obs.complete();
103
+ };
104
+ style.onerror = (err) => {
105
+ obs.error(err);
106
+ };
107
+ });
108
+ files.set(stylePath, obs$);
109
+ }
110
+ return files.get(stylePath);
111
+ };
112
+ return {
113
+ setResourceBase: (path) => {
114
+ resourceBase = path;
115
+ },
116
+ setStylesBase: (path) => {
117
+ stylesBase = path;
118
+ },
119
+ loadResource: (resourceName) => {
120
+ const path = resourcePaths[resourceName] || resourceName;
121
+ return loadResource(resourceBase + path);
122
+ },
123
+ loadStyles: (resourceName) => {
124
+ const path = stylesPaths[resourceName] || resourceName;
125
+ return loadStyles(stylesBase + path);
126
+ }
127
+ };
128
+ }
128
129
  const ResourceLoader = resourceLoaderFactory();
129
130
 
130
- let FsFroalaLoaderService = class FsFroalaLoaderService {
131
- constructor(_defaultConfig) {
132
- this._defaultConfig = _defaultConfig;
133
- this._froalaLoaded = new BehaviorSubject(false);
134
- this._defaultPluginsLoaded = new BehaviorSubject(false);
135
- this._ready$ = combineLatest([this._froalaLoaded, this._defaultPluginsLoaded])
136
- .pipe(map(([FroalaReady, pluginsRead]) => {
137
- return pluginsRead && FroalaReady;
138
- }), shareReplay(1));
139
- if (this._defaultConfig) {
140
- if (this._defaultConfig.assetsJSPath) {
141
- ResourceLoader.setResourceBase(this._defaultConfig.assetsJSPath);
142
- }
143
- if (this._defaultConfig.assetsCSSPath) {
144
- ResourceLoader.setStylesBase(this._defaultConfig.assetsCSSPath);
145
- }
146
- }
147
- this._load();
148
- }
149
- get ready$() {
150
- return this._ready$;
151
- }
152
- get ready() {
153
- return this._froalaLoaded.getValue() && this._defaultPluginsLoaded.getValue();
154
- }
155
- get FroalaEditor() {
156
- return this._FroalaEditor;
157
- }
158
- _load() {
159
- combineLatest([
160
- ResourceLoader.loadResource('froala'),
161
- ResourceLoader.loadStyles('froala')
162
- ])
163
- .pipe(tap(() => {
164
- this._FroalaEditor = window.FroalaEditor;
165
- this._froalaDone();
166
- }), concatMap(() => {
167
- return this._loadPlugins();
168
- }), tap(() => {
169
- this._defaultPluginsDone();
170
- }))
171
- .subscribe();
172
- }
173
- _loadPlugins() {
174
- const imports = this._defaultConfig
175
- .defaultPlugins
176
- .reduce((acc, pluginName) => {
177
- const import$ = ResourceLoader.loadResource(pluginName);
178
- acc.push(import$);
179
- return acc;
180
- }, []);
181
- return combineLatest(imports);
182
- }
183
- _froalaDone() {
184
- this._froalaLoaded.next(true);
185
- }
186
- _defaultPluginsDone() {
187
- this._defaultPluginsLoaded.next(true);
188
- }
189
- };
190
- FsFroalaLoaderService.ctorParameters = () => [
191
- { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [FS_HTML_EDITOR_CONFIG,] }] }
192
- ];
193
- FsFroalaLoaderService.ɵprov = ɵɵdefineInjectable({ factory: function FsFroalaLoaderService_Factory() { return new FsFroalaLoaderService(ɵɵinject(FS_HTML_EDITOR_CONFIG, 8)); }, token: FsFroalaLoaderService, providedIn: "root" });
194
- FsFroalaLoaderService = __decorate([
195
- Injectable({
196
- providedIn: 'root',
197
- }),
198
- __param(0, Optional()), __param(0, Inject(FS_HTML_EDITOR_CONFIG)),
199
- __metadata("design:paramtypes", [Object])
131
+ let FsFroalaLoaderService = class FsFroalaLoaderService {
132
+ constructor(_defaultConfig) {
133
+ this._defaultConfig = _defaultConfig;
134
+ this._froalaLoaded = new BehaviorSubject(false);
135
+ this._defaultPluginsLoaded = new BehaviorSubject(false);
136
+ this._ready$ = combineLatest([this._froalaLoaded, this._defaultPluginsLoaded])
137
+ .pipe(map(([FroalaReady, pluginsRead]) => {
138
+ return pluginsRead && FroalaReady;
139
+ }), shareReplay(1));
140
+ if (this._defaultConfig) {
141
+ if (this._defaultConfig.assetsJSPath) {
142
+ ResourceLoader.setResourceBase(this._defaultConfig.assetsJSPath);
143
+ }
144
+ if (this._defaultConfig.assetsCSSPath) {
145
+ ResourceLoader.setStylesBase(this._defaultConfig.assetsCSSPath);
146
+ }
147
+ }
148
+ this._load();
149
+ }
150
+ get ready$() {
151
+ return this._ready$;
152
+ }
153
+ get ready() {
154
+ return this._froalaLoaded.getValue() && this._defaultPluginsLoaded.getValue();
155
+ }
156
+ get FroalaEditor() {
157
+ return this._FroalaEditor;
158
+ }
159
+ _load() {
160
+ combineLatest([
161
+ ResourceLoader.loadResource('froala'),
162
+ ResourceLoader.loadStyles('froala')
163
+ ])
164
+ .pipe(tap(() => {
165
+ this._FroalaEditor = window.FroalaEditor;
166
+ this._froalaDone();
167
+ }), concatMap(() => {
168
+ return this._loadPlugins();
169
+ }), tap(() => {
170
+ this._defaultPluginsDone();
171
+ }))
172
+ .subscribe();
173
+ }
174
+ _loadPlugins() {
175
+ const imports = this._defaultConfig
176
+ .defaultPlugins
177
+ .reduce((acc, pluginName) => {
178
+ const import$ = ResourceLoader.loadResource(pluginName);
179
+ acc.push(import$);
180
+ return acc;
181
+ }, []);
182
+ return combineLatest(imports);
183
+ }
184
+ _froalaDone() {
185
+ this._froalaLoaded.next(true);
186
+ }
187
+ _defaultPluginsDone() {
188
+ this._defaultPluginsLoaded.next(true);
189
+ }
190
+ };
191
+ FsFroalaLoaderService.ctorParameters = () => [
192
+ { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [FS_HTML_EDITOR_CONFIG,] }] }
193
+ ];
194
+ FsFroalaLoaderService.ɵprov = ɵɵdefineInjectable({ factory: function FsFroalaLoaderService_Factory() { return new FsFroalaLoaderService(ɵɵinject(FS_HTML_EDITOR_CONFIG, 8)); }, token: FsFroalaLoaderService, providedIn: "root" });
195
+ FsFroalaLoaderService = __decorate([
196
+ Injectable({
197
+ providedIn: 'root',
198
+ }),
199
+ __param(0, Optional()), __param(0, Inject(FS_HTML_EDITOR_CONFIG)),
200
+ __metadata("design:paramtypes", [Object])
200
201
  ], FsFroalaLoaderService);
201
202
 
202
- var FsHtmlEditorComponent_1;
203
- let FsHtmlEditorComponent = FsHtmlEditorComponent_1 = class FsHtmlEditorComponent {
204
- constructor(_defaultConfig, _cdRef, _fr) {
205
- this._defaultConfig = _defaultConfig;
206
- this._cdRef = _cdRef;
207
- this._fr = _fr;
208
- this.classFocused = false;
209
- this.classDisabled = false;
210
- this.config = {};
211
- this.initialized = false;
212
- this._initialize$ = new ReplaySubject();
213
- this._destroy$ = new Subject();
214
- this.onChange = (data) => { };
215
- this.onTouched = () => { };
216
- }
217
- get el() {
218
- return this.elRef.nativeElement;
219
- }
220
- get html() {
221
- return this._html;
222
- }
223
- get editor() {
224
- return this._editor;
225
- }
226
- get froalaReady$() {
227
- return this._fr.ready$;
228
- }
229
- ngOnInit() {
230
- this.config = this.config || {};
231
- this.config.autofocus = this.config.autofocus !== false && !this.config.disabled;
232
- this.initialized = !this.config.initOnClick;
233
- this._listenLazyInit();
234
- }
235
- ngAfterViewInit() {
236
- if (!this.config.initOnClick || !this.hasContent()) {
237
- this.initialized = true;
238
- this._initialize$.next();
239
- }
240
- }
241
- hasContent() {
242
- const el = document.createElement('div');
243
- if (el.querySelector('img')) {
244
- return true;
245
- }
246
- el.innerHTML = this._html;
247
- return !!el.innerText.length;
248
- }
249
- initialize(options = {}) {
250
- const config = this._createConfig();
251
- this._initPlugins(config);
252
- this.el.innerHTML = this._html;
253
- this._editor = new this._fr.FroalaEditor(this.el, this._createOptions(), () => {
254
- this._cdRef.markForCheck();
255
- if (config.disabled) {
256
- this.disable();
257
- }
258
- if (config.froalaConfig.events) {
259
- if (config.froalaConfig.events.initialized) {
260
- config.froalaConfig.events.initialized();
261
- }
262
- }
263
- this._editor.events.on('focus', () => {
264
- this.classFocused = true;
265
- this._cdRef.markForCheck();
266
- });
267
- this._editor.events.on('blur', () => {
268
- this.classFocused = false;
269
- this._cdRef.markForCheck();
270
- });
271
- this._editor.events.on('contentChanged', () => {
272
- const editorHTML = this._editor.html.get();
273
- if (this.html !== editorHTML) {
274
- this._change(editorHTML);
275
- }
276
- });
277
- this._editor.events.on('paste.afterCleanup', (html) => {
278
- var div = document.createElement('div');
279
- div.innerHTML = html;
280
- div.querySelectorAll('*')
281
- .forEach((el) => {
282
- for (var i = 0; i < el.attributes.length; i++) {
283
- const name = el.attributes[0].name;
284
- if (name !== 'href') {
285
- el.removeAttribute(name);
286
- }
287
- }
288
- });
289
- return div.innerHTML;
290
- });
291
- this._editor.events.on('keydown', () => {
292
- this.onTouched();
293
- });
294
- if (this.config.image && this.config.image.upload) {
295
- this._editor.events.on('image.beforePasteUpload', (image) => {
296
- fetch(image.getAttribute('src'))
297
- .then((res) => {
298
- res.blob()
299
- .then((blob) => {
300
- this._processImageUpload(blob)
301
- .subscribe((url) => {
302
- image.setAttribute('src', url);
303
- image.removeAttribute('data-fr-image-pasted');
304
- });
305
- });
306
- });
307
- return false;
308
- });
309
- this._editor.events.on('image.beforeUpload', (blobs) => {
310
- this._processImageUpload(blobs[0]).subscribe((url) => {
311
- this.editor.image.insert(url, null, null, this.editor.image.get());
312
- });
313
- return false;
314
- });
315
- }
316
- if (this.el.querySelector('.fr-second-toolbar')) {
317
- this.el.querySelector('.fr-second-toolbar').remove();
318
- }
319
- const selection = options.selection;
320
- if (selection) {
321
- const node = Array.from(this.el.querySelectorAll('.fr-element *')).find((node) => {
322
- return selection.node === node.textContent;
323
- });
324
- if (node) {
325
- const range = document.createRange();
326
- const sel = window.getSelection();
327
- range.setStart(this._getTextNode(node), selection.offset);
328
- range.collapse(true);
329
- sel.removeAllRanges();
330
- sel.addRange(range);
331
- }
332
- else if (this.config.autofocus) {
333
- this.focus();
334
- }
335
- }
336
- else if (this.config.autofocus) {
337
- this.focus();
338
- }
339
- });
340
- }
341
- _processImageUpload(blob) {
342
- return this.config.image.upload(blob)
343
- .pipe(takeUntil(this._destroy$));
344
- }
345
- _getTextNode(node) {
346
- if (node) {
347
- if (node.nodeType === Node.TEXT_NODE) {
348
- return node;
349
- }
350
- if (node.childNodes) {
351
- return this._getTextNode(node.childNodes[0]);
352
- }
353
- }
354
- }
355
- uninitializedClick(event) {
356
- if (!event.defaultPrevented) {
357
- const target = event.target;
358
- if (target && target.nodeName === 'A' && target.getAttribute('href')) {
359
- const targetTarget = target.getAttribute('target');
360
- target.setAttribute('target', '_blank');
361
- setTimeout(() => {
362
- if (targetTarget) {
363
- target.setAttribute('target', targetTarget);
364
- }
365
- else {
366
- target.removeAttribute('target');
367
- }
368
- });
369
- }
370
- else {
371
- if (this.config.initClick) {
372
- this.config.initClick(event);
373
- }
374
- this._initialize$.next();
375
- this.initialized = true;
376
- }
377
- }
378
- }
379
- updateSize() {
380
- // Hack: To trigger the toolbar button size modes
381
- window.dispatchEvent(new Event('resize'));
382
- }
383
- validate(control) {
384
- const err = {};
385
- if (this.config.maxLength && this._html) {
386
- const maxLength = this.config.maxLength;
387
- const length = this._html.length;
388
- if (length > maxLength) {
389
- err.maxLengthError = `Must be ${maxLength} characters or fewer. You entered ${length} characters.`;
390
- }
391
- }
392
- return Object.keys(err).length ? err : null;
393
- }
394
- focus(options) {
395
- options = options ? options : {};
396
- if (options.cursorPosition === 'end') {
397
- this.editor.selection.setAtEnd(this.editor.$el.get(0));
398
- }
399
- else {
400
- this.editor.selection.setAtStart(this.editor.$el.get(0));
401
- }
402
- this.editor.selection.restore();
403
- const elSelection = this.editor.selection.element();
404
- if (elSelection) {
405
- elSelection.scrollIntoView({ block: 'center' });
406
- }
407
- }
408
- clear() {
409
- this.writeValue('');
410
- }
411
- disable() {
412
- this.classDisabled = true;
413
- }
414
- setHtml(html) {
415
- this.writeValue(html);
416
- }
417
- writeValue(html) {
418
- this._html = html || '';
419
- this._cdRef.markForCheck();
420
- // SP-T2298 timeout needed for the case, when froala was already initated and
421
- // second instance opened in dialog/drawer. In this case init step pass much faster, writeValue trigger
422
- // after init and froala ignore new html. At the same time froala was initied but editor not yet, and next
423
- // code doesn't work without timeout. We've got time range when too late for initiate value, and to early
424
- // for change event.
425
- setTimeout(() => {
426
- if (this.editor && this.editor.html) {
427
- try {
428
- this.editor.html.set(this._html);
429
- }
430
- catch (e) {
431
- }
432
- }
433
- });
434
- }
435
- registerOnChange(fn) {
436
- this.onChange = fn;
437
- }
438
- registerOnTouched(fn) {
439
- this.onTouched = fn;
440
- }
441
- ngOnDestroy() {
442
- this._initialize$.complete();
443
- this._destroy$.next();
444
- this._destroy$.complete();
445
- this.destroy();
446
- }
447
- destroy() {
448
- if (this.editor) {
449
- this.editor.destroy();
450
- }
451
- this.initialized = false;
452
- this._cdRef.markForCheck();
453
- this.el.innerHTML = '';
454
- }
455
- _createConfig() {
456
- return merge({ froalaConfig: {} }, this._defaultConfig, this.config);
457
- }
458
- _change(html) {
459
- this._html = html;
460
- this.onChange(html);
461
- }
462
- _initPlugins(config) {
463
- (config.plugins || []).forEach((plugin) => {
464
- this._fr.FroalaEditor.PLUGINS[plugin.config.name] = function (editor) {
465
- plugin.editor = editor;
466
- plugin.initialize();
467
- return plugin;
468
- };
469
- (plugin.config.buttons || []).forEach((button) => {
470
- this._fr.FroalaEditor.DefineIcon(button.name, {
471
- NAME: button.name,
472
- PATH: button.svgPath,
473
- });
474
- this._fr.FroalaEditor.RegisterCommand(button.name, {
475
- icon: button.name,
476
- title: button.tooltip,
477
- undo: button.undo,
478
- focus: button.focus,
479
- showOnMobile: button.showOnMobile,
480
- refreshAfterCallback: button.refreshAfterCallback,
481
- callback: function () {
482
- if (button.click) {
483
- button.click(this);
484
- }
485
- },
486
- refresh: function (button) {
487
- if (button.refresh) {
488
- button.refresh(this, button);
489
- }
490
- }
491
- });
492
- });
493
- });
494
- }
495
- _createOptions() {
496
- const config = this._createConfig();
497
- return merge(
498
- // For some reason editor store somewhere pointer on default config object and dublicate options each time on init
499
- // Extra merge level fixed this problem and allow to init config properly without legacy data
500
- {}, {
501
- key: config.activationKey,
502
- placeholderText: config.placeholder,
503
- linkAlwaysBlank: true,
504
- tabSpaces: 2,
505
- typingTimer: 250,
506
- tooltips: false,
507
- wordPasteModal: false,
508
- imageDefaultWidth: 0,
509
- imageDefaultAlign: 'left',
510
- quickInsertEnabled: false,
511
- paragraphDefaultSelection: 'Format',
512
- videoUpload: false,
513
- paragraphFormat: {
514
- N: 'Normal',
515
- H1: 'Heading 1',
516
- H2: 'Heading 2',
517
- H3: 'Heading 3',
518
- H4: 'Heading 4',
519
- BLOCKQUOTE: 'Quote',
520
- },
521
- paragraphFormatSelection: true,
522
- toolbarButtonsXS: {
523
- moreText: {
524
- buttons: TextButtons,
525
- buttonsVisible: 1,
526
- },
527
- moreParagraph: {
528
- buttons: ParagraphButtons,
529
- buttonsVisible: 2,
530
- },
531
- moreRich: {
532
- buttons: RichButtons,
533
- buttonsVisible: 0,
534
- },
535
- },
536
- toolbarButtons: {
537
- moreText: {
538
- buttons: TextButtons,
539
- buttonsVisible: 3,
540
- },
541
- moreParagraph: {
542
- buttons: ParagraphButtons,
543
- buttonsVisible: 5,
544
- },
545
- moreRich: {
546
- buttons: RichButtons,
547
- buttonsVisible: 3,
548
- },
549
- },
550
- }, config.froalaConfig);
551
- }
552
- _listenLazyInit() {
553
- this.froalaReady$
554
- .pipe(filter((ready) => ready), switchMap(() => this._initialize$))
555
- .subscribe(() => {
556
- const selection = window.getSelection();
557
- const options = {};
558
- if (selection.baseNode) {
559
- options.selection = {
560
- node: selection.baseNode.nodeValue,
561
- offset: selection.baseOffset,
562
- };
563
- }
564
- this.initialize(options);
565
- });
566
- }
567
- };
568
- FsHtmlEditorComponent.ctorParameters = () => [
569
- { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [FS_HTML_EDITOR_CONFIG,] }] },
570
- { type: ChangeDetectorRef },
571
- { type: FsFroalaLoaderService }
572
- ];
573
- __decorate([
574
- HostBinding('class.focused'),
575
- __metadata("design:type", Object)
576
- ], FsHtmlEditorComponent.prototype, "classFocused", void 0);
577
- __decorate([
578
- HostBinding('class.disabled'),
579
- __metadata("design:type", Object)
580
- ], FsHtmlEditorComponent.prototype, "classDisabled", void 0);
581
- __decorate([
582
- ViewChild('elRef'),
583
- __metadata("design:type", ElementRef)
584
- ], FsHtmlEditorComponent.prototype, "elRef", void 0);
585
- __decorate([
586
- Input(),
587
- __metadata("design:type", Object)
588
- ], FsHtmlEditorComponent.prototype, "config", void 0);
589
- FsHtmlEditorComponent = FsHtmlEditorComponent_1 = __decorate([
590
- Component({
591
- selector: 'fs-html-editor',
592
- template: "<div class=\"fs-html-editor-default\">\n <ng-container *ngIf=\"initialized\">\n <ng-container *fsSkeleton=\"(froalaReady$ | async) !== false\">\n </ng-container>\n </ng-container>\n\n <div #elRef></div>\n\n <div class=\"bottom-line\"></div>\n <div class=\"disabled-line\"></div>\n <fs-html-renderer\n *ngIf=\"!initialized\"\n [html]=\"html\"\n (click)=\"uninitializedClick($event)\">\n </fs-html-renderer>\n</div>\n",
593
- providers: [
594
- {
595
- provide: NG_VALUE_ACCESSOR,
596
- useExisting: forwardRef(() => FsHtmlEditorComponent_1),
597
- multi: true
598
- },
599
- {
600
- provide: NG_VALIDATORS,
601
- useExisting: forwardRef(() => FsHtmlEditorComponent_1),
602
- multi: true
603
- },
604
- ],
605
- changeDetection: ChangeDetectionStrategy.OnPush,
606
- styles: [":host ::ng-deep .fr-box.fr-basic .fr-wrapper{border:0;border-bottom:1px solid #949494;margin-bottom:1px;background-color:transparent}:host ::ng-deep .fr-box.fr-basic .fr-element{padding:0;font-family:inherit;color:inherit;font-size:inherit;line-height:inherit;min-height:auto}:host ::ng-deep .fr-dropdown-menu .fr-dropdown-wrapper,:host ::ng-deep .fr-dropdown:after,:host ::ng-deep .fr-more-toolbar,:host ::ng-deep .fr-toolbar{transition:none!important}:host ::ng-deep .fr-toolbar{position:-webkit-sticky;position:sticky;z-index:2;border-radius:0;background-color:transparent}:host ::ng-deep .fr-toolbar .fr-btn-grp{margin:0 20px 0 0;position:relative}:host ::ng-deep .fr-toolbar .fr-btn-grp:nth-child(1):after,:host ::ng-deep .fr-toolbar .fr-btn-grp:nth-child(2):after{content:\"\";position:absolute;top:9px;height:30px;border-left:1px solid #e5e5e5;margin-left:10px}:host ::ng-deep .fr-toolbar div:first-of-type:before{border:none}:host ::ng-deep .fr-toolbar.fr-toolbar-open .fr-newline{height:auto}:host ::ng-deep .fr-toolbar .fr-btn-grp:first-child{margin-left:0}:host ::ng-deep .fr-toolbar.fr-top{border:0}:host ::ng-deep .fr-toolbar .fr-newline{margin:0}:host ::ng-deep .fr-toolbar .fr-more-toolbar{z-index:auto}:host ::ng-deep .fr-toolbar .fr-command.fr-btn{z-index:auto}:host ::ng-deep .fr-toolbar .fr-command.fr-btn.fr-dropdown:after{right:3px}:host ::ng-deep .fr-toolbar .fr-command.fr-btn.fr-dropdown.fr-selection:after{right:10px}:host ::ng-deep .fr-toolbar .fr-command.fr-btn.fr-dropdown.fr-selection span{margin-right:24px}:host ::ng-deep .fr-toolbar .fr-command.fr-btn.fr-open{border-radius:4px;margin:4px 2px}:host ::ng-deep .fr-view ol,:host ::ng-deep .fr-view ul{list-style-position:unset}:host.disabled ::ng-deep .fr-box.fr-basic{opacity:.5;pointer-events:none}:host.disabled ::ng-deep .fr-box.fr-basic .fr-wrapper{border:none}:host.disabled ::ng-deep .disabled-line{display:block}::ng-deep .fr-popup{z-index:1001!important}::ng-deep .fr-video-by-url-layer .fr-checkbox-line{display:none}.disabled-line{display:none;position:absolute;bottom:-1px;z-index:1;background-image:linear-gradient(90deg,rgba(0,0,0,.42) 0,rgba(0,0,0,.42) 33%,transparent 0);background-size:4px 100%;background-repeat:repeat-x;height:1px;width:100%}.bottom-line{opacity:0;transform-origin:50%;transform:scaleX(.5);transition:background-color .3s cubic-bezier(.55,0,.55,.2);width:100%;border-bottom:2px solid #949494;position:absolute;bottom:-1px;z-index:1}:host{position:relative;display:block}:host.focused .bottom-line{opacity:1;display:block;transform:scaleX(1);transition:transform .3s cubic-bezier(.25,.8,.25,1),opacity .1s cubic-bezier(.25,.8,.25,1),background-color .3s cubic-bezier(.25,.8,.25,1)}::ng-deep .fs-html-editor-mention-container{position:absolute;top:0;left:0;height:auto;max-height:300px;max-width:500px;overflow:auto;display:block;z-index:999999;box-shadow:0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12);border-bottom-left-radius:4px;border-bottom-right-radius:4px;background:#fff}::ng-deep .fs-html-editor-mention-container ul{margin:0;padding:0;list-style:none}::ng-deep .fs-html-editor-mention-container li{padding:0 16px;cursor:pointer;line-height:48px}::ng-deep .fs-html-editor-mention-container li.highlight,::ng-deep .fs-html-editor-mention-container li:hover{background:#f5f5f5}::ng-deep .fs-html-editor-mention-container li.no-match{cursor:default}"]
607
- }),
608
- __param(0, Optional()), __param(0, Inject(FS_HTML_EDITOR_CONFIG)),
609
- __metadata("design:paramtypes", [Object, ChangeDetectorRef,
610
- FsFroalaLoaderService])
203
+ var FsHtmlEditorComponent_1;
204
+ let FsHtmlEditorComponent = FsHtmlEditorComponent_1 = class FsHtmlEditorComponent {
205
+ constructor(_defaultConfig, _cdRef, _fr) {
206
+ this._defaultConfig = _defaultConfig;
207
+ this._cdRef = _cdRef;
208
+ this._fr = _fr;
209
+ this.classFocused = false;
210
+ this.classDisabled = false;
211
+ this.config = {};
212
+ this.initialized = false;
213
+ this._initialize$ = new ReplaySubject();
214
+ this._destroy$ = new Subject();
215
+ this.onChange = (data) => { };
216
+ this.onTouched = () => { };
217
+ }
218
+ get el() {
219
+ return this.elRef.nativeElement;
220
+ }
221
+ get html() {
222
+ return this._html;
223
+ }
224
+ get editor() {
225
+ return this._editor;
226
+ }
227
+ get froalaReady$() {
228
+ return this._fr.ready$;
229
+ }
230
+ ngOnInit() {
231
+ this.config = this.config || {};
232
+ this.config.autofocus = this.config.autofocus !== false && !this.config.disabled;
233
+ this.initialized = !this.config.initOnClick;
234
+ this._listenLazyInit();
235
+ }
236
+ ngAfterViewInit() {
237
+ if (!this.config.initOnClick || !this.hasContent()) {
238
+ this.initialized = true;
239
+ this._initialize$.next();
240
+ }
241
+ }
242
+ hasContent() {
243
+ const el = document.createElement('div');
244
+ if (el.querySelector('img')) {
245
+ return true;
246
+ }
247
+ el.innerHTML = this._html;
248
+ return !!el.innerText.length;
249
+ }
250
+ initialize(options = {}) {
251
+ const config = this._createConfig();
252
+ this._initPlugins(config);
253
+ this.el.innerHTML = this._html;
254
+ this._editor = new this._fr.FroalaEditor(this.el, this._createOptions(), () => {
255
+ this._cdRef.markForCheck();
256
+ if (config.disabled) {
257
+ this.disable();
258
+ }
259
+ if (config.froalaConfig.events) {
260
+ if (config.froalaConfig.events.initialized) {
261
+ config.froalaConfig.events.initialized();
262
+ }
263
+ }
264
+ this._editor.events.on('focus', () => {
265
+ this.classFocused = true;
266
+ this._cdRef.markForCheck();
267
+ });
268
+ this._editor.events.on('blur', () => {
269
+ this.classFocused = false;
270
+ this._cdRef.markForCheck();
271
+ });
272
+ this._editor.events.on('contentChanged', () => {
273
+ const editorHTML = this._editor.html.get();
274
+ if (this.html !== editorHTML) {
275
+ this._change(editorHTML);
276
+ }
277
+ });
278
+ this._editor.events.on('paste.afterCleanup', (html) => {
279
+ var div = document.createElement('div');
280
+ div.innerHTML = html;
281
+ div.querySelectorAll('*')
282
+ .forEach((el) => {
283
+ for (var i = 0; i < el.attributes.length; i++) {
284
+ const name = el.attributes[0].name;
285
+ if (name !== 'href') {
286
+ el.removeAttribute(name);
287
+ }
288
+ }
289
+ });
290
+ return div.innerHTML;
291
+ });
292
+ this._editor.events.on('keydown', () => {
293
+ this.onTouched();
294
+ });
295
+ if (this.config.image && this.config.image.upload) {
296
+ this._editor.events.on('image.beforePasteUpload', (image) => {
297
+ fetch(image.getAttribute('src'))
298
+ .then((res) => {
299
+ res.blob()
300
+ .then((blob) => {
301
+ this._processImageUpload(blob)
302
+ .subscribe((url) => {
303
+ image.setAttribute('src', url);
304
+ image.removeAttribute('data-fr-image-pasted');
305
+ });
306
+ });
307
+ });
308
+ return false;
309
+ });
310
+ this._editor.events.on('image.beforeUpload', (blobs) => {
311
+ this._processImageUpload(blobs[0]).subscribe((url) => {
312
+ this.editor.image.insert(url, null, null, this.editor.image.get());
313
+ });
314
+ return false;
315
+ });
316
+ }
317
+ if (this.el.querySelector('.fr-second-toolbar')) {
318
+ this.el.querySelector('.fr-second-toolbar').remove();
319
+ }
320
+ const selection = options.selection;
321
+ if (selection) {
322
+ const node = Array.from(this.el.querySelectorAll('.fr-element *')).find((node) => {
323
+ return selection.node === node.textContent;
324
+ });
325
+ if (node) {
326
+ const range = document.createRange();
327
+ const sel = window.getSelection();
328
+ range.setStart(this._getTextNode(node), selection.offset);
329
+ range.collapse(true);
330
+ sel.removeAllRanges();
331
+ sel.addRange(range);
332
+ }
333
+ else if (this.config.autofocus) {
334
+ this.focus();
335
+ }
336
+ }
337
+ else if (this.config.autofocus) {
338
+ this.focus();
339
+ }
340
+ });
341
+ }
342
+ _processImageUpload(blob) {
343
+ return this.config.image.upload(blob)
344
+ .pipe(takeUntil(this._destroy$));
345
+ }
346
+ _getTextNode(node) {
347
+ if (node) {
348
+ if (node.nodeType === Node.TEXT_NODE) {
349
+ return node;
350
+ }
351
+ if (node.childNodes) {
352
+ return this._getTextNode(node.childNodes[0]);
353
+ }
354
+ }
355
+ }
356
+ uninitializedClick(event) {
357
+ if (!event.defaultPrevented) {
358
+ const target = event.target;
359
+ if (target && target.nodeName === 'A' && target.getAttribute('href')) {
360
+ const targetTarget = target.getAttribute('target');
361
+ target.setAttribute('target', '_blank');
362
+ setTimeout(() => {
363
+ if (targetTarget) {
364
+ target.setAttribute('target', targetTarget);
365
+ }
366
+ else {
367
+ target.removeAttribute('target');
368
+ }
369
+ });
370
+ }
371
+ else {
372
+ if (this.config.initClick) {
373
+ this.config.initClick(event);
374
+ }
375
+ this._initialize$.next();
376
+ this.initialized = true;
377
+ }
378
+ }
379
+ }
380
+ updateSize() {
381
+ // Hack: To trigger the toolbar button size modes
382
+ window.dispatchEvent(new Event('resize'));
383
+ }
384
+ validate(control) {
385
+ const err = {};
386
+ if (this.config.maxLength && this._html) {
387
+ const maxLength = this.config.maxLength;
388
+ const length = this._html.length;
389
+ if (length > maxLength) {
390
+ err.maxLengthError = `Must be ${maxLength} characters or fewer. You entered ${length} characters.`;
391
+ }
392
+ }
393
+ return Object.keys(err).length ? err : null;
394
+ }
395
+ focus(options) {
396
+ options = options ? options : {};
397
+ if (options.cursorPosition === 'end') {
398
+ this.editor.selection.setAtEnd(this.editor.$el.get(0));
399
+ }
400
+ else {
401
+ this.editor.selection.setAtStart(this.editor.$el.get(0));
402
+ }
403
+ this.editor.selection.restore();
404
+ const elSelection = this.editor.selection.element();
405
+ if (elSelection) {
406
+ elSelection.scrollIntoView({ block: 'center' });
407
+ }
408
+ }
409
+ clear() {
410
+ this.writeValue('');
411
+ }
412
+ disable() {
413
+ this.classDisabled = true;
414
+ }
415
+ setHtml(html) {
416
+ this.writeValue(html);
417
+ }
418
+ writeValue(html) {
419
+ this._html = html || '';
420
+ this._cdRef.markForCheck();
421
+ // SP-T2298 timeout needed for the case, when froala was already initated and
422
+ // second instance opened in dialog/drawer. In this case init step pass much faster, writeValue trigger
423
+ // after init and froala ignore new html. At the same time froala was initied but editor not yet, and next
424
+ // code doesn't work without timeout. We've got time range when too late for initiate value, and to early
425
+ // for change event.
426
+ setTimeout(() => {
427
+ if (this.editor && this.editor.html) {
428
+ try {
429
+ this.editor.html.set(this._html);
430
+ }
431
+ catch (e) {
432
+ }
433
+ }
434
+ });
435
+ }
436
+ registerOnChange(fn) {
437
+ this.onChange = fn;
438
+ }
439
+ registerOnTouched(fn) {
440
+ this.onTouched = fn;
441
+ }
442
+ ngOnDestroy() {
443
+ this._initialize$.complete();
444
+ this._destroy$.next();
445
+ this._destroy$.complete();
446
+ this.destroy();
447
+ }
448
+ destroy() {
449
+ if (this.editor) {
450
+ this.editor.destroy();
451
+ }
452
+ this.initialized = false;
453
+ this._cdRef.markForCheck();
454
+ this.el.innerHTML = '';
455
+ }
456
+ _createConfig() {
457
+ return merge({ froalaConfig: {} }, this._defaultConfig, this.config);
458
+ }
459
+ _change(html) {
460
+ this._html = html;
461
+ this.onChange(html);
462
+ }
463
+ _initPlugins(config) {
464
+ (config.plugins || []).forEach((plugin) => {
465
+ this._fr.FroalaEditor.PLUGINS[plugin.config.name] = function (editor) {
466
+ plugin.editor = editor;
467
+ plugin.initialize();
468
+ return plugin;
469
+ };
470
+ (plugin.config.buttons || []).forEach((button) => {
471
+ this._fr.FroalaEditor.DefineIcon(button.name, {
472
+ NAME: button.name,
473
+ PATH: button.svgPath,
474
+ });
475
+ this._fr.FroalaEditor.RegisterCommand(button.name, {
476
+ icon: button.name,
477
+ title: button.tooltip,
478
+ undo: button.undo,
479
+ focus: button.focus,
480
+ showOnMobile: button.showOnMobile,
481
+ refreshAfterCallback: button.refreshAfterCallback,
482
+ callback: function () {
483
+ if (button.click) {
484
+ button.click(this);
485
+ }
486
+ },
487
+ refresh: function (button) {
488
+ if (button.refresh) {
489
+ button.refresh(this, button);
490
+ }
491
+ }
492
+ });
493
+ });
494
+ });
495
+ }
496
+ _createOptions() {
497
+ const config = this._createConfig();
498
+ return merge(
499
+ // For some reason editor store somewhere pointer on default config object and dublicate options each time on init
500
+ // Extra merge level fixed this problem and allow to init config properly without legacy data
501
+ {}, {
502
+ key: config.activationKey,
503
+ placeholderText: config.placeholder,
504
+ linkAlwaysBlank: true,
505
+ tabSpaces: 2,
506
+ typingTimer: 250,
507
+ tooltips: false,
508
+ wordPasteModal: false,
509
+ imageDefaultWidth: 0,
510
+ imageDefaultAlign: 'left',
511
+ quickInsertEnabled: false,
512
+ paragraphDefaultSelection: 'Format',
513
+ videoUpload: false,
514
+ paragraphFormat: {
515
+ N: 'Normal',
516
+ H1: 'Heading 1',
517
+ H2: 'Heading 2',
518
+ H3: 'Heading 3',
519
+ H4: 'Heading 4',
520
+ BLOCKQUOTE: 'Quote',
521
+ },
522
+ paragraphFormatSelection: true,
523
+ toolbarButtonsXS: {
524
+ moreText: {
525
+ buttons: TextButtons,
526
+ buttonsVisible: 1,
527
+ },
528
+ moreParagraph: {
529
+ buttons: ParagraphButtons,
530
+ buttonsVisible: 2,
531
+ },
532
+ moreRich: {
533
+ buttons: RichButtons,
534
+ buttonsVisible: 0,
535
+ },
536
+ },
537
+ toolbarButtons: {
538
+ moreText: {
539
+ buttons: TextButtons,
540
+ buttonsVisible: 3,
541
+ },
542
+ moreParagraph: {
543
+ buttons: ParagraphButtons,
544
+ buttonsVisible: 5,
545
+ },
546
+ moreRich: {
547
+ buttons: RichButtons,
548
+ buttonsVisible: 3,
549
+ },
550
+ },
551
+ }, config.froalaConfig);
552
+ }
553
+ _listenLazyInit() {
554
+ this.froalaReady$
555
+ .pipe(filter((ready) => ready), switchMap(() => this._initialize$))
556
+ .subscribe(() => {
557
+ const selection = window.getSelection();
558
+ const options = {};
559
+ if (selection.baseNode) {
560
+ options.selection = {
561
+ node: selection.baseNode.nodeValue,
562
+ offset: selection.baseOffset,
563
+ };
564
+ }
565
+ this.initialize(options);
566
+ });
567
+ }
568
+ };
569
+ FsHtmlEditorComponent.ctorParameters = () => [
570
+ { type: undefined, decorators: [{ type: Optional }, { type: Inject, args: [FS_HTML_EDITOR_CONFIG,] }] },
571
+ { type: ChangeDetectorRef },
572
+ { type: FsFroalaLoaderService }
573
+ ];
574
+ __decorate([
575
+ HostBinding('class.focused'),
576
+ __metadata("design:type", Object)
577
+ ], FsHtmlEditorComponent.prototype, "classFocused", void 0);
578
+ __decorate([
579
+ HostBinding('class.disabled'),
580
+ __metadata("design:type", Object)
581
+ ], FsHtmlEditorComponent.prototype, "classDisabled", void 0);
582
+ __decorate([
583
+ ViewChild('elRef'),
584
+ __metadata("design:type", ElementRef)
585
+ ], FsHtmlEditorComponent.prototype, "elRef", void 0);
586
+ __decorate([
587
+ Input(),
588
+ __metadata("design:type", Object)
589
+ ], FsHtmlEditorComponent.prototype, "config", void 0);
590
+ FsHtmlEditorComponent = FsHtmlEditorComponent_1 = __decorate([
591
+ Component({
592
+ selector: 'fs-html-editor',
593
+ template: "<div class=\"fs-html-editor-default\">\n <ng-container *ngIf=\"initialized\">\n <ng-container *fsSkeleton=\"(froalaReady$ | async) !== false\">\n </ng-container>\n </ng-container>\n\n <div #elRef></div>\n\n <div class=\"bottom-line\"></div>\n <div class=\"disabled-line\"></div>\n <fs-html-renderer\n *ngIf=\"!initialized\"\n [html]=\"html\"\n (click)=\"uninitializedClick($event)\">\n </fs-html-renderer>\n</div>\n",
594
+ providers: [
595
+ {
596
+ provide: NG_VALUE_ACCESSOR,
597
+ useExisting: forwardRef(() => FsHtmlEditorComponent_1),
598
+ multi: true
599
+ },
600
+ {
601
+ provide: NG_VALIDATORS,
602
+ useExisting: forwardRef(() => FsHtmlEditorComponent_1),
603
+ multi: true
604
+ },
605
+ ],
606
+ changeDetection: ChangeDetectionStrategy.OnPush,
607
+ styles: [":host ::ng-deep .fr-box.fr-basic .fr-wrapper{border:0;border-bottom:1px solid #949494;margin-bottom:1px;background-color:transparent}:host ::ng-deep .fr-box.fr-basic .fr-element{padding:0;font-family:inherit;color:inherit;font-size:inherit;line-height:inherit;min-height:auto}:host ::ng-deep .fr-dropdown-menu .fr-dropdown-wrapper,:host ::ng-deep .fr-dropdown:after,:host ::ng-deep .fr-more-toolbar,:host ::ng-deep .fr-toolbar{transition:none!important}:host ::ng-deep .fr-toolbar{position:-webkit-sticky;position:sticky;z-index:2;border-radius:0;background-color:transparent}:host ::ng-deep .fr-toolbar .fr-btn-grp{margin:0 20px 0 0;position:relative}:host ::ng-deep .fr-toolbar .fr-btn-grp:nth-child(1):after,:host ::ng-deep .fr-toolbar .fr-btn-grp:nth-child(2):after{content:\"\";position:absolute;top:9px;height:30px;border-left:1px solid #e5e5e5;margin-left:10px}:host ::ng-deep .fr-toolbar div:first-of-type:before{border:none}:host ::ng-deep .fr-toolbar.fr-toolbar-open .fr-newline{height:auto}:host ::ng-deep .fr-toolbar .fr-btn-grp:first-child{margin-left:0}:host ::ng-deep .fr-toolbar.fr-top{border:0}:host ::ng-deep .fr-toolbar .fr-newline{margin:0}:host ::ng-deep .fr-toolbar .fr-more-toolbar{z-index:auto}:host ::ng-deep .fr-toolbar .fr-command.fr-btn{z-index:auto}:host ::ng-deep .fr-toolbar .fr-command.fr-btn.fr-dropdown:after{right:3px}:host ::ng-deep .fr-toolbar .fr-command.fr-btn.fr-dropdown.fr-selection span{margin-right:24px}:host ::ng-deep .fr-toolbar .fr-command.fr-btn.fr-open{border-radius:4px;margin:4px 2px}:host ::ng-deep .fr-view ol,:host ::ng-deep .fr-view ul{list-style-position:unset}:host.disabled ::ng-deep .fr-box.fr-basic{opacity:.5;pointer-events:none}:host.disabled ::ng-deep .fr-box.fr-basic .fr-wrapper{border:none}:host.disabled ::ng-deep .disabled-line{display:block}::ng-deep .fr-popup{z-index:1001!important}::ng-deep .fr-video-by-url-layer .fr-checkbox-line{display:none}.disabled-line{display:none;position:absolute;bottom:-1px;z-index:1;background-image:linear-gradient(90deg,rgba(0,0,0,.42) 0,rgba(0,0,0,.42) 33%,transparent 0);background-size:4px 100%;background-repeat:repeat-x;height:1px;width:100%}.bottom-line{opacity:0;transform-origin:50%;transform:scaleX(.5);transition:background-color .3s cubic-bezier(.55,0,.55,.2);width:100%;border-bottom:2px solid #949494;position:absolute;bottom:-1px;z-index:1}:host{position:relative;display:block}:host.focused .bottom-line{opacity:1;display:block;transform:scaleX(1);transition:transform .3s cubic-bezier(.25,.8,.25,1),opacity .1s cubic-bezier(.25,.8,.25,1),background-color .3s cubic-bezier(.25,.8,.25,1)}::ng-deep .fs-html-editor-mention-container{position:absolute;top:0;left:0;height:auto;max-height:300px;max-width:500px;overflow:auto;display:block;z-index:999999;box-shadow:0 2px 4px -1px rgba(0,0,0,.2),0 4px 5px 0 rgba(0,0,0,.14),0 1px 10px 0 rgba(0,0,0,.12);border-bottom-left-radius:4px;border-bottom-right-radius:4px;background:#fff}::ng-deep .fs-html-editor-mention-container ul{margin:0;padding:0;list-style:none}::ng-deep .fs-html-editor-mention-container li{padding:0 16px;cursor:pointer;line-height:48px}::ng-deep .fs-html-editor-mention-container li.highlight,::ng-deep .fs-html-editor-mention-container li:hover{background:#f5f5f5}::ng-deep .fs-html-editor-mention-container li.no-match{cursor:default}"]
608
+ }),
609
+ __param(0, Optional()), __param(0, Inject(FS_HTML_EDITOR_CONFIG)),
610
+ __metadata("design:paramtypes", [Object, ChangeDetectorRef,
611
+ FsFroalaLoaderService])
611
612
  ], FsHtmlEditorComponent);
612
613
 
613
- let FsHtmlRendererComponent = class FsHtmlRendererComponent {
614
- constructor(sanitized, _cdRef) {
615
- this.sanitized = sanitized;
616
- this._cdRef = _cdRef;
617
- }
618
- set setHtml(html) {
619
- this.trustedHtml = this.sanitized.bypassSecurityTrustHtml(html);
620
- this._cdRef.markForCheck();
621
- }
622
- };
623
- FsHtmlRendererComponent.ctorParameters = () => [
624
- { type: DomSanitizer },
625
- { type: ChangeDetectorRef }
626
- ];
627
- __decorate([
628
- Input('html'),
629
- __metadata("design:type", Object),
630
- __metadata("design:paramtypes", [Object])
631
- ], FsHtmlRendererComponent.prototype, "setHtml", null);
632
- FsHtmlRendererComponent = __decorate([
633
- Component({
634
- selector: 'fs-html-renderer',
635
- template: "<div class=\"fr-view fs-html-editor-default\" [innerHtml]=\"trustedHtml\"></div>\n",
636
- changeDetection: ChangeDetectionStrategy.OnPush,
637
- styles: [""]
638
- }),
639
- __metadata("design:paramtypes", [DomSanitizer,
640
- ChangeDetectorRef])
614
+ let FsHtmlRendererComponent = class FsHtmlRendererComponent {
615
+ constructor(sanitized, _cdRef) {
616
+ this.sanitized = sanitized;
617
+ this._cdRef = _cdRef;
618
+ }
619
+ set setHtml(html) {
620
+ this.trustedHtml = this.sanitized.bypassSecurityTrustHtml(html);
621
+ this._cdRef.markForCheck();
622
+ }
623
+ };
624
+ FsHtmlRendererComponent.ctorParameters = () => [
625
+ { type: DomSanitizer },
626
+ { type: ChangeDetectorRef }
627
+ ];
628
+ __decorate([
629
+ Input('html'),
630
+ __metadata("design:type", Object),
631
+ __metadata("design:paramtypes", [Object])
632
+ ], FsHtmlRendererComponent.prototype, "setHtml", null);
633
+ FsHtmlRendererComponent = __decorate([
634
+ Component({
635
+ selector: 'fs-html-renderer',
636
+ template: "<div class=\"fr-view fs-html-editor-default\" [innerHtml]=\"trustedHtml\"></div>\n",
637
+ changeDetection: ChangeDetectionStrategy.OnPush,
638
+ styles: [""]
639
+ }),
640
+ __metadata("design:paramtypes", [DomSanitizer,
641
+ ChangeDetectorRef])
641
642
  ], FsHtmlRendererComponent);
642
643
 
643
- var FsHtmlEditorModule_1;
644
- let FsHtmlEditorModule = FsHtmlEditorModule_1 = class FsHtmlEditorModule {
645
- static forRoot(config = {}) {
646
- return {
647
- ngModule: FsHtmlEditorModule_1,
648
- providers: [
649
- { provide: FS_HTML_EDITOR_DEFAULT_CONFIG, useValue: config },
650
- {
651
- provide: FS_HTML_EDITOR_CONFIG,
652
- useFactory: FsHtmlEditorConfigFactory,
653
- deps: [FS_HTML_EDITOR_DEFAULT_CONFIG]
654
- }
655
- ]
656
- };
657
- }
658
- };
659
- FsHtmlEditorModule = FsHtmlEditorModule_1 = __decorate([
660
- NgModule({
661
- imports: [
662
- CommonModule,
663
- FsSkeletonModule,
664
- ],
665
- exports: [
666
- FsHtmlEditorComponent,
667
- FsHtmlRendererComponent,
668
- ],
669
- declarations: [
670
- FsHtmlEditorComponent,
671
- FsHtmlRendererComponent,
672
- ],
673
- })
674
- ], FsHtmlEditorModule);
675
- function FsHtmlEditorConfigFactory(config) {
676
- return Object.assign({ defaultPlugins: [
677
- "align" /* Align */,
678
- "colors" /* Colors */,
679
- "image" /* Image */,
680
- "link" /* Link */,
681
- "lists" /* Lists */,
682
- "paragraph_format" /* ParagraphFormat */,
683
- "quote" /* Quote */,
684
- "table" /* Table */,
685
- "url" /* Url */,
686
- "video" /* Video */,
687
- "draggable" /* Draggable */,
688
- ] }, config);
644
+ var FsHtmlEditorModule_1;
645
+ let FsHtmlEditorModule = FsHtmlEditorModule_1 = class FsHtmlEditorModule {
646
+ static forRoot(config = {}) {
647
+ return {
648
+ ngModule: FsHtmlEditorModule_1,
649
+ providers: [
650
+ { provide: FS_HTML_EDITOR_DEFAULT_CONFIG, useValue: config },
651
+ {
652
+ provide: FS_HTML_EDITOR_CONFIG,
653
+ useFactory: FsHtmlEditorConfigFactory,
654
+ deps: [FS_HTML_EDITOR_DEFAULT_CONFIG]
655
+ }
656
+ ]
657
+ };
658
+ }
659
+ };
660
+ FsHtmlEditorModule = FsHtmlEditorModule_1 = __decorate([
661
+ NgModule({
662
+ imports: [
663
+ CommonModule,
664
+ FsSkeletonModule,
665
+ ],
666
+ exports: [
667
+ FsHtmlEditorComponent,
668
+ FsHtmlRendererComponent,
669
+ ],
670
+ declarations: [
671
+ FsHtmlEditorComponent,
672
+ FsHtmlRendererComponent,
673
+ ],
674
+ })
675
+ ], FsHtmlEditorModule);
676
+ function FsHtmlEditorConfigFactory(config) {
677
+ return Object.assign({ defaultPlugins: [
678
+ "align" /* Align */,
679
+ "colors" /* Colors */,
680
+ "image" /* Image */,
681
+ "link" /* Link */,
682
+ "lists" /* Lists */,
683
+ "paragraph_format" /* ParagraphFormat */,
684
+ "quote" /* Quote */,
685
+ "table" /* Table */,
686
+ "url" /* Url */,
687
+ "video" /* Video */,
688
+ "draggable" /* Draggable */,
689
+ "font_size" /* FontSize */,
690
+ ] }, config);
689
691
  }
690
692
 
691
- class Plugin {
692
- initialize() { }
693
- destroy() { }
693
+ class Plugin {
694
+ initialize() { }
695
+ destroy() { }
694
696
  }
695
697
 
696
- class MentionPlugin extends Plugin {
697
- constructor(config) {
698
- super();
699
- this.config = config;
700
- this.config = Object.assign(Object.assign({}, config), { buttons: [
701
- {
702
- name: config.name,
703
- tooltip: config.tooltip,
704
- svgPath: config.iconPath,
705
- click: (editor) => {
706
- this._closeAll();
707
- this._tribute.showMenuForCollection(editor.el);
708
- }
709
- }
710
- ] });
711
- this._tribute = new Tribute({
712
- values: debounce(this._loadValues.bind(this), 200),
713
- searchOpts: {
714
- pre: '',
715
- post: '',
716
- skip: true
717
- },
718
- containerClass: `fs-html-editor-mention-container ${this.config.containerClass || ''}`,
719
- itemClass: `fs-html-editor-mention-menu-item ${this.config.menuItemClass || ''}`,
720
- trigger: this.config.trigger,
721
- allowSpaces: true,
722
- menuItemTemplate: (item) => {
723
- return this.config.menuItemTemplate(item.original);
724
- },
725
- selectTemplate: (item) => {
726
- const template = this.config.selectedTemplate(item.original);
727
- let p = document.createElement('p');
728
- p.innerHTML = template;
729
- let node = p.firstElementChild;
730
- if (!node) {
731
- node = document.createElement('span');
732
- node.innerHTML = template;
733
- }
734
- node.setAttribute('contenteditable', 'false');
735
- node.classList.add('fr-deletable');
736
- return node.outerHTML;
737
- },
738
- });
739
- MentionPlugin._tributes.push(this._tribute);
740
- }
741
- initialize() {
742
- this._tribute.attach(this.editor.el);
743
- this.editor.events.on('keydown', (e) => {
744
- if (e.key === 'Enter' && this._tribute.isActive) {
745
- return false;
746
- }
747
- }, true);
748
- }
749
- destroy() { }
750
- _closeAll() {
751
- MentionPlugin._tributes.forEach((tribute) => {
752
- if (tribute.menu) {
753
- tribute.hideMenu();
754
- }
755
- });
756
- }
757
- _loadValues(keyword, cb) {
758
- return this.config.fetch(keyword)
759
- .subscribe((data) => {
760
- cb(data);
761
- });
762
- }
763
- }
698
+ class MentionPlugin extends Plugin {
699
+ constructor(config) {
700
+ super();
701
+ this.config = config;
702
+ this.config = Object.assign(Object.assign({}, config), { buttons: [
703
+ {
704
+ name: config.name,
705
+ tooltip: config.tooltip,
706
+ svgPath: config.iconPath,
707
+ click: (editor) => {
708
+ this._closeAll();
709
+ this._tribute.showMenuForCollection(editor.el);
710
+ }
711
+ }
712
+ ] });
713
+ this._tribute = new Tribute({
714
+ values: debounce(this._loadValues.bind(this), 200),
715
+ searchOpts: {
716
+ pre: '',
717
+ post: '',
718
+ skip: true
719
+ },
720
+ containerClass: `fs-html-editor-mention-container ${this.config.containerClass || ''}`,
721
+ itemClass: `fs-html-editor-mention-menu-item ${this.config.menuItemClass || ''}`,
722
+ trigger: this.config.trigger,
723
+ allowSpaces: true,
724
+ menuItemTemplate: (item) => {
725
+ return this.config.menuItemTemplate(item.original);
726
+ },
727
+ selectTemplate: (item) => {
728
+ const template = this.config.selectedTemplate(item.original);
729
+ let p = document.createElement('p');
730
+ p.innerHTML = template;
731
+ let node = p.firstElementChild;
732
+ if (!node) {
733
+ node = document.createElement('span');
734
+ node.innerHTML = template;
735
+ }
736
+ node.setAttribute('contenteditable', 'false');
737
+ node.classList.add('fr-deletable');
738
+ return node.outerHTML;
739
+ },
740
+ });
741
+ MentionPlugin._tributes.push(this._tribute);
742
+ }
743
+ initialize() {
744
+ this._tribute.attach(this.editor.el);
745
+ this.editor.events.on('keydown', (e) => {
746
+ if (e.key === 'Enter' && this._tribute.isActive) {
747
+ return false;
748
+ }
749
+ }, true);
750
+ }
751
+ destroy() { }
752
+ _closeAll() {
753
+ MentionPlugin._tributes.forEach((tribute) => {
754
+ if (tribute.menu) {
755
+ tribute.hideMenu();
756
+ }
757
+ });
758
+ }
759
+ _loadValues(keyword, cb) {
760
+ return this.config.fetch(keyword)
761
+ .subscribe((data) => {
762
+ cb(data);
763
+ });
764
+ }
765
+ }
764
766
  MentionPlugin._tributes = [];
765
767
 
766
- class ChecklistPlugin extends Plugin {
767
- constructor(config = { name: 'checklist' }) {
768
- super();
769
- this.config = config;
770
- this.config = Object.assign(Object.assign({}, config), { name: 'checklist', buttons: [
771
- {
772
- name: 'checklist',
773
- svgPath: 'M8.4,10.3l-1.2,1.2l4,4L20,6.7l-1.2-1.2l-7.6,7.6L8.4,10.3z M18.2,18.2H5.8V5.8h8.9V4H5.8C4.8,4,4,4.8,4,5.8v12.4c0,1,0.8,1.8,1.8,1.8h12.4c1,0,1.8-0.8,1.8-1.8v-7.1h-1.8V18.2z',
774
- click: (editor) => {
775
- editor.html.insert('<ul class="checklist"><li></li></ul>');
776
- }
777
- }
778
- ] });
779
- }
780
- initialize() {
781
- this.editor.events.on('click', (e) => {
782
- const li = e.target;
783
- if (li.nodeName === 'LI' && e.offsetX < 0) {
784
- const items = [li, ...li.querySelectorAll('li')];
785
- if (li.classList.contains('checked')) {
786
- items.forEach((item) => {
787
- item.classList.remove('checked');
788
- });
789
- }
790
- else {
791
- items.forEach((item) => {
792
- item.classList.add('checked');
793
- });
794
- }
795
- }
796
- }, false);
797
- }
768
+ class ChecklistPlugin extends Plugin {
769
+ constructor(config = { name: 'checklist' }) {
770
+ super();
771
+ this.config = config;
772
+ this.config = Object.assign(Object.assign({}, config), { name: 'checklist', buttons: [
773
+ {
774
+ name: 'checklist',
775
+ svgPath: 'M8.4,10.3l-1.2,1.2l4,4L20,6.7l-1.2-1.2l-7.6,7.6L8.4,10.3z M18.2,18.2H5.8V5.8h8.9V4H5.8C4.8,4,4,4.8,4,5.8v12.4c0,1,0.8,1.8,1.8,1.8h12.4c1,0,1.8-0.8,1.8-1.8v-7.1h-1.8V18.2z',
776
+ click: (editor) => {
777
+ editor.html.insert('<ul class="checklist"><li></li></ul>');
778
+ }
779
+ }
780
+ ] });
781
+ }
782
+ initialize() {
783
+ this.editor.events.on('click', (e) => {
784
+ const li = e.target;
785
+ if (li.nodeName === 'LI' && e.offsetX < 0) {
786
+ const items = [li, ...li.querySelectorAll('li')];
787
+ if (li.classList.contains('checked')) {
788
+ items.forEach((item) => {
789
+ item.classList.remove('checked');
790
+ });
791
+ }
792
+ else {
793
+ items.forEach((item) => {
794
+ item.classList.add('checked');
795
+ });
796
+ }
797
+ }
798
+ }, false);
799
+ }
798
800
  }
799
801
 
800
- class CodePlugin extends Plugin {
801
- constructor(config = { name: 'code' }) {
802
- super();
803
- this.config = config;
804
- this.config = Object.assign(Object.assign({}, config), { name: 'code', buttons: [
805
- {
806
- name: 'code',
807
- svgPath: 'M8.9,7.3L4.2,12l4.7,4.7l1.1-1.1L6.4,12L10,8.4L8.9,7.3z M15.1,7.3L14,8.4l3.6,3.6L14,15.6l1.1,1.1l4.7-4.7L15.1,7.3z',
808
- click: (editor) => {
809
- const node = editor.selection.get();
810
- const codeEl = this._getCodeEl(node.baseNode);
811
- if (codeEl) {
812
- codeEl.classList.remove('code');
813
- }
814
- else {
815
- editor.html.insert('<p class="code">' + editor.selection.get().toString().replace(/\n{1,}/g, '<br>') + '</p>');
816
- }
817
- }
818
- }
819
- ] });
820
- }
821
- initialize() {
822
- this.editor.events.on('keydown', (e) => {
823
- if (e.keyCode === 13) {
824
- const selection = this.editor.selection.get();
825
- if (selection && this._getCodeEl(selection.baseNode)) {
826
- e.preventDefault();
827
- e.stopPropagation();
828
- e.stopImmediatePropagation();
829
- let br = '<br>';
830
- const base = selection.baseNode;
831
- if (base.nodeName === '#text' && selection.baseOffset === base.length) {
832
- if (!(base.nextSibling && base.nextSibling.nodeName === 'BR')) {
833
- br += '<br>';
834
- }
835
- }
836
- else {
837
- const el = Array.from(base.childNodes).splice(selection.baseOffset - 1, 1).pop();
838
- if (el && el.nodeName !== 'BR') {
839
- br += '<br>';
840
- }
841
- }
842
- this.editor.html.insert(br);
843
- return false;
844
- }
845
- }
846
- }, true);
847
- }
848
- destroy() { }
849
- _getCodeEl(el) {
850
- if (el) {
851
- if (el.classList && el.classList.contains('code')) {
852
- return el;
853
- }
854
- if (el.parentElement) {
855
- return this._getCodeEl(el.parentElement);
856
- }
857
- }
858
- return null;
859
- }
802
+ class CodePlugin extends Plugin {
803
+ constructor(config = { name: 'code' }) {
804
+ super();
805
+ this.config = config;
806
+ this.config = Object.assign(Object.assign({}, config), { name: 'code', buttons: [
807
+ {
808
+ name: 'code',
809
+ svgPath: 'M8.9,7.3L4.2,12l4.7,4.7l1.1-1.1L6.4,12L10,8.4L8.9,7.3z M15.1,7.3L14,8.4l3.6,3.6L14,15.6l1.1,1.1l4.7-4.7L15.1,7.3z',
810
+ click: (editor) => {
811
+ const node = editor.selection.get();
812
+ const codeEl = this._getCodeEl(node.baseNode);
813
+ if (codeEl) {
814
+ codeEl.classList.remove('code');
815
+ }
816
+ else {
817
+ editor.html.insert('<p class="code">' + editor.selection.get().toString().replace(/\n{1,}/g, '<br>') + '</p>');
818
+ }
819
+ }
820
+ }
821
+ ] });
822
+ }
823
+ initialize() {
824
+ this.editor.events.on('keydown', (e) => {
825
+ if (e.keyCode === 13) {
826
+ const selection = this.editor.selection.get();
827
+ if (selection && this._getCodeEl(selection.baseNode)) {
828
+ e.preventDefault();
829
+ e.stopPropagation();
830
+ e.stopImmediatePropagation();
831
+ let br = '<br>';
832
+ const base = selection.baseNode;
833
+ if (base.nodeName === '#text' && selection.baseOffset === base.length) {
834
+ if (!(base.nextSibling && base.nextSibling.nodeName === 'BR')) {
835
+ br += '<br>';
836
+ }
837
+ }
838
+ else {
839
+ const el = Array.from(base.childNodes).splice(selection.baseOffset - 1, 1).pop();
840
+ if (el && el.nodeName !== 'BR') {
841
+ br += '<br>';
842
+ }
843
+ }
844
+ this.editor.html.insert(br);
845
+ return false;
846
+ }
847
+ }
848
+ }, true);
849
+ }
850
+ destroy() { }
851
+ _getCodeEl(el) {
852
+ if (el) {
853
+ if (el.classList && el.classList.contains('code')) {
854
+ return el;
855
+ }
856
+ if (el.parentElement) {
857
+ return this._getCodeEl(el.parentElement);
858
+ }
859
+ }
860
+ return null;
861
+ }
860
862
  }
861
863
 
862
- class ScreenRecordPlugin extends Plugin {
863
- constructor(config = {}) {
864
- super();
865
- this.config = config;
866
- this.config = Object.assign(Object.assign({}, config), { name: config.name || 'screenRecord', buttons: [
867
- {
868
- name: 'screenRecord',
864
+ class ScreenRecordPlugin extends Plugin {
865
+ constructor(config = {}) {
866
+ super();
867
+ this.config = config;
868
+ this.config = Object.assign(Object.assign({}, config), { name: config.name || 'screenRecord', buttons: [
869
+ {
870
+ name: 'screenRecord',
869
871
  svgPath: `M14.7,7.7v6.1H7.1V7.7H14.7 M16.3,9.6V6.9c0-0.4-0.3-0.8-0.8-0.8H6.4c-0.4,0-0.8,0.3-0.8,0.8v7.6c0,0.4,0.3,0.8,0.8,0.8h9.1c0.4,0,0.8-0.3,0.8-0.8v-2.7l1.7,1.7c0.3,0.3,0.8,0.3,1.1,0c0.1-0.1,0.2-0.3,0.2-0.5V8.4c0-0.4-0.3-0.8-0.8-0.8
870
872
  c-0.2,0-0.4,0.1-0.5,0.2L16.3,9.6z M21.5,1.6H2.9c-0.7,0-1.3,0.7-1.3,1.6v14.6c0,0.9,0.6,1.6,1.3,1.6h7.6v1.1l-5,1c-0.2,0-0.4,0.3-0.4,0.6c0,0.3,0.2,0.4,0.4,0.4c0,0,0,0,0.1,0l5.3-1h2.6l5.3,1c0,0,0,0,0.1,0c0.2,0,0.4-0.2,0.4-0.4
871
- c0-0.3-0.1-0.6-0.4-0.6l-5-1v-1.1h7.6c0.7,0,1.3-0.7,1.3-1.6V3.2C22.9,2.3,22.3,1.6,21.5,1.6z M21.1,17.3H3.3V3.7h17.8L21.1,17.3L21.1,17.3z`,
872
- tooltip: 'Screen Record',
873
- click: (editor) => {
874
- navigator.mediaDevices.getDisplayMedia({ video: true })
875
- .then((stream) => {
876
- const chunks = [];
877
- const options = { mimeType: 'video/webm; codecs=vp9' };
878
- let mediaRecorder = new MediaRecorder(stream, options);
879
- stream.addEventListener('inactive', (e) => {
880
- mediaRecorder.stop();
881
- mediaRecorder = null;
882
- stream.getTracks().forEach((track) => track.stop());
883
- stream = null;
884
- const blob = new Blob(chunks, { type: 'video/webm' });
885
- config.upload(blob)
886
- .subscribe((url) => {
887
- editor.html.insert(`<span class="fr-screen-record fr-deletable fr-draggable"><video controls style="max-width:${config.maxWidth}"><source src="${url}" type="video/webm"></video></span>`);
888
- });
889
- });
890
- mediaRecorder.addEventListener('dataavailable', (event) => {
891
- if (event.data && event.data.size > 0) {
892
- chunks.push(event.data);
893
- }
894
- });
895
- mediaRecorder.start(10);
896
- })
897
- .catch((e) => { });
898
- }
899
- }
900
- ] });
901
- }
902
- initialize() {
903
- return __awaiter(this, void 0, void 0, function* () {
904
- yield ResourceLoader.loadStyles('froala')
905
- .toPromise();
906
- const FroalaEditor = window.FroalaEditor;
907
- this.editor.events.on('mouseup', (e) => {
908
- const el = this._getEl(e.target);
909
- if (el) {
910
- this.editor.popups.hideAll();
911
- this._activeEl = el;
912
- this._showPopup(el);
913
- }
914
- });
915
- FroalaEditor.POPUP_TEMPLATES["screenRecordPlugin.popup"] = '[_BUTTONS_]';
916
- FroalaEditor.DefineIcon('popupClose', { NAME: 'trash', SVG_KEY: 'remove' });
917
- FroalaEditor.RegisterCommand('popupClose', {
918
- title: 'Remove',
919
- undo: false,
920
- focus: false,
921
- callback: () => {
922
- if (this._activeEl) {
923
- this._activeEl.remove();
924
- }
925
- }
926
- });
927
- });
928
- }
929
- _createPopup() {
930
- const template = {
931
- buttons: `<div class="fr-buttons">${this.editor.button.buildList(['popupClose'])}</div>`,
932
- };
933
- return this.editor.popups.create('screenRecordPlugin.popup', template);
934
- }
935
- _showPopup(el) {
936
- var $popup = this.editor.popups.get('screenRecordPlugin.popup');
937
- if (!$popup) {
938
- $popup = this._createPopup();
939
- }
940
- this.editor.popups.setContainer('screenRecordPlugin.popup', this.editor.$(el));
941
- const left = el.offsetLeft + el.offsetWidth / 2;
942
- this.editor.popups.show('screenRecordPlugin.popup', left, null);
943
- }
944
- _getEl(el) {
945
- if (el && el.classList) {
946
- if (el.classList.contains('fr-screen-record'))
947
- return el;
948
- return this._getEl(el.parentNode);
949
- }
950
- }
873
+ c0-0.3-0.1-0.6-0.4-0.6l-5-1v-1.1h7.6c0.7,0,1.3-0.7,1.3-1.6V3.2C22.9,2.3,22.3,1.6,21.5,1.6z M21.1,17.3H3.3V3.7h17.8L21.1,17.3L21.1,17.3z`,
874
+ tooltip: 'Screen Record',
875
+ click: (editor) => {
876
+ navigator.mediaDevices.getDisplayMedia({ video: true })
877
+ .then((stream) => {
878
+ const chunks = [];
879
+ const options = { mimeType: 'video/webm; codecs=vp9' };
880
+ let mediaRecorder = new MediaRecorder(stream, options);
881
+ stream.addEventListener('inactive', (e) => {
882
+ mediaRecorder.stop();
883
+ mediaRecorder = null;
884
+ stream.getTracks().forEach((track) => track.stop());
885
+ stream = null;
886
+ const blob = new Blob(chunks, { type: 'video/webm' });
887
+ config.upload(blob)
888
+ .subscribe((url) => {
889
+ editor.html.insert(`<span class="fr-screen-record fr-deletable fr-draggable"><video controls style="max-width:${config.maxWidth}"><source src="${url}" type="video/webm"></video></span>`);
890
+ });
891
+ });
892
+ mediaRecorder.addEventListener('dataavailable', (event) => {
893
+ if (event.data && event.data.size > 0) {
894
+ chunks.push(event.data);
895
+ }
896
+ });
897
+ mediaRecorder.start(10);
898
+ })
899
+ .catch((e) => { });
900
+ }
901
+ }
902
+ ] });
903
+ }
904
+ initialize() {
905
+ return __awaiter(this, void 0, void 0, function* () {
906
+ yield ResourceLoader.loadStyles('froala')
907
+ .toPromise();
908
+ const FroalaEditor = window.FroalaEditor;
909
+ this.editor.events.on('mouseup', (e) => {
910
+ const el = this._getEl(e.target);
911
+ if (el) {
912
+ this.editor.popups.hideAll();
913
+ this._activeEl = el;
914
+ this._showPopup(el);
915
+ }
916
+ });
917
+ FroalaEditor.POPUP_TEMPLATES["screenRecordPlugin.popup"] = '[_BUTTONS_]';
918
+ FroalaEditor.DefineIcon('popupClose', { NAME: 'trash', SVG_KEY: 'remove' });
919
+ FroalaEditor.RegisterCommand('popupClose', {
920
+ title: 'Remove',
921
+ undo: false,
922
+ focus: false,
923
+ callback: () => {
924
+ if (this._activeEl) {
925
+ this._activeEl.remove();
926
+ }
927
+ }
928
+ });
929
+ });
930
+ }
931
+ _createPopup() {
932
+ const template = {
933
+ buttons: `<div class="fr-buttons">${this.editor.button.buildList(['popupClose'])}</div>`,
934
+ };
935
+ return this.editor.popups.create('screenRecordPlugin.popup', template);
936
+ }
937
+ _showPopup(el) {
938
+ var $popup = this.editor.popups.get('screenRecordPlugin.popup');
939
+ if (!$popup) {
940
+ $popup = this._createPopup();
941
+ }
942
+ this.editor.popups.setContainer('screenRecordPlugin.popup', this.editor.$(el));
943
+ const left = el.offsetLeft + el.offsetWidth / 2;
944
+ this.editor.popups.show('screenRecordPlugin.popup', left, null);
945
+ }
946
+ _getEl(el) {
947
+ if (el && el.classList) {
948
+ if (el.classList.contains('fr-screen-record'))
949
+ return el;
950
+ return this._getEl(el.parentNode);
951
+ }
952
+ }
951
953
  }
952
954
 
953
- /**
954
- * Generated bundle index. Do not edit.
955
+ /**
956
+ * Generated bundle index. Do not edit.
955
957
  */
956
958
 
957
959
  export { ChecklistPlugin, CodePlugin, FS_HTML_EDITOR_CONFIG, FsHtmlEditorComponent, FsHtmlEditorModule, FsHtmlRendererComponent, MentionPlugin, ParagraphButtons, RichButtons, ScreenRecordPlugin, TextButtons, FsHtmlEditorConfigFactory as ɵa, FS_HTML_EDITOR_DEFAULT_CONFIG as ɵb, FsFroalaLoaderService as ɵc, Plugin as ɵe };