@richscripts2/richtexteditor 1.0.15 → 1.0.16

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.
@@ -1,82 +1,257 @@
1
- 
2
-
3
- RTE_DefaultConfig.plugin_inserttemplate = RTE_Plugin_InsertTemplate;
4
-
5
- function RTE_Plugin_InsertTemplate() {
6
-
7
-
8
-
9
- var obj = this;
10
-
11
- var config, editor;
12
-
13
- obj.PluginName = "InsertTemplate";
14
-
15
- obj.InitConfig = function (argconfig) {
16
- config = argconfig;
17
- }
18
- obj.InitEditor = function (argeditor) {
19
- editor = argeditor;
20
-
21
- editor.attachEvent("exec_command_inserttemplate", function (state, cmd, value) {
22
- state.returnValue = true;
23
- obj.DoInsertTemplate();
24
- });
25
-
26
-
27
- }
28
-
29
- function __Append(parent, tagname, csstext, cssclass) {
30
- var tag = parent.ownerDocument.createElement(tagname);
31
- if (csstext) tag.style.cssText = csstext;
32
- if (cssclass) tag.className = cssclass;
33
- parent.appendChild(tag);
34
- return tag;
35
- }
36
-
37
- obj.DoInsertTemplate = function () {
38
-
39
- var dialoginner = editor.createDialog(editor.getLangText("inserttemplatetitle"), "rte-dialog-inserttemplate");
40
-
41
- var scrollpanel = __Append(dialoginner, "rte-inserttemplate-scrollpanel", "overflow-y:auto;padding-bottom:32px;");
42
- var container = __Append(scrollpanel, "rte-inserttemplate-container", "display:flex;flex-wrap:wrap;");
43
-
44
- container.focus();//focus to let ESC key close dialog
45
-
46
- function CreateDiv(item) {
47
- var text = item[0];
48
- var html = item[1];
49
- console.log(item, text, html);
50
-
51
- var divitem = __Append(container, "rte-inserttemplate-image-item", "cursor:pointer;width:256px;height:256px;margin:12px;box-shadow:0 0 8px #ccc;display:flex;align-items:center;justify-content:center;")
52
- var div = __Append(divitem, "div", "max-width:90%;max-height:90%;overflow:auto;");
53
- var innerdiv = __Append(div, "div");
54
- innerdiv.innerHTML = html;
55
- div.title = text;
56
-
57
- var scale = Math.min(200 / div.scrollWidth, 200 / div.scrollHeight);
58
- if (scale < 1) {
59
-
60
- var tx, ty;
61
- tx = ty = (Math.max(div.scrollWidth, div.scrollHeight) - 200) / 2;
62
- innerdiv.style.transform = "scale(" + scale + ") translate(-" + tx + "px,-" + ty + "px)";
63
- div.style.overflow = "hidden";
64
- }
65
-
66
- divitem.onclick = function () {
67
- editor.setHTMLCode(html);
68
- dialoginner.close();
69
- }
70
- }
71
-
72
- for (var i = 0; i < config.htmlTemplates.length; i++) {
73
- var item = config.htmlTemplates[i];
74
- CreateDiv(item);
75
- }
76
-
77
- }
78
- }
79
-
80
-
81
-
82
-
1
+ RTE_DefaultConfig.plugin_inserttemplate = RTE_Plugin_InsertTemplate;
2
+
3
+ function RTE_Plugin_InsertTemplate() {
4
+ var obj = this;
5
+ var config;
6
+ var editor;
7
+
8
+ obj.PluginName = "InsertTemplate";
9
+
10
+ obj.InitConfig = function (argconfig) {
11
+ config = argconfig;
12
+ if (!config.htmlTemplates) {
13
+ config.htmlTemplates = [];
14
+ }
15
+ };
16
+
17
+ obj.InitEditor = function (argeditor) {
18
+ editor = argeditor;
19
+
20
+ editor.attachEvent("exec_command_inserttemplate", function (state) {
21
+ state.returnValue = true;
22
+ obj.DoInsertTemplate();
23
+ });
24
+ };
25
+
26
+ function append(parent, tagName, cssText, className) {
27
+ var tag = parent.ownerDocument.createElement(tagName);
28
+ if (cssText) {
29
+ tag.style.cssText = cssText;
30
+ }
31
+ if (className) {
32
+ tag.className = className;
33
+ }
34
+ parent.appendChild(tag);
35
+ return tag;
36
+ }
37
+
38
+ function clear(node) {
39
+ while (node.firstChild) {
40
+ node.removeChild(node.firstChild);
41
+ }
42
+ }
43
+
44
+ function stripHtml(html) {
45
+ var div = document.createElement("div");
46
+ div.innerHTML = html || "";
47
+ return div.innerText || div.textContent || "";
48
+ }
49
+
50
+ function normalizeTemplateItem(item, index) {
51
+ if (item instanceof Array) {
52
+ return {
53
+ id: "template-" + index,
54
+ title: item[0] || ("Template " + (index + 1)),
55
+ html: item[1] || "",
56
+ meta: item[2] || ""
57
+ };
58
+ }
59
+
60
+ if (item && typeof item === "object") {
61
+ return {
62
+ id: item.id || ("template-" + index),
63
+ title: item.title || item.name || item.text || ("Template " + (index + 1)),
64
+ html: item.html || item.content || "",
65
+ meta: item.meta || item.description || ""
66
+ };
67
+ }
68
+
69
+ if (typeof item === "string") {
70
+ return {
71
+ id: "template-" + index,
72
+ title: "Template " + (index + 1),
73
+ html: item,
74
+ meta: ""
75
+ };
76
+ }
77
+
78
+ return null;
79
+ }
80
+
81
+ function scalePreview(body, canvas) {
82
+ var maxWidth = 206;
83
+ var maxHeight = 166;
84
+ var width = Math.max(canvas.scrollWidth, 1);
85
+ var height = Math.max(canvas.scrollHeight, 1);
86
+ var scale = Math.min(1, maxWidth / width, maxHeight / height);
87
+
88
+ canvas.style.transformOrigin = "top left";
89
+ canvas.style.transform = "scale(" + scale + ")";
90
+ canvas.style.width = width + "px";
91
+ canvas.style.height = height + "px";
92
+ }
93
+
94
+ obj.DoInsertTemplate = function () {
95
+ var dialoginner = editor.createDialog(editor.getLangText("inserttemplatetitle") || "Insert template", "rte-dialog-inserttemplate");
96
+ var closeDialog = typeof dialoginner.close === "function" ? function () {
97
+ dialoginner.close();
98
+ } : function () {
99
+ editor.closeCurrentPopup();
100
+ };
101
+
102
+ var browser = append(dialoginner, "div", "", "rte-dialog-browser");
103
+ var header = append(browser, "div", "", "rte-dialog-browser-header");
104
+ var kicker = append(header, "div", "", "rte-dialog-browser-kicker");
105
+ kicker.innerText = "Content Blocks";
106
+ var title = append(header, "div", "", "rte-dialog-browser-title");
107
+ title.innerText = "Insert template";
108
+ var copy = append(header, "div", "", "rte-dialog-browser-copy");
109
+ copy.innerText = "Preview reusable layouts, search by name, and replace the current editor content with a selected template.";
110
+
111
+ var toolbar = append(browser, "div", "", "rte-dialog-browser-toolbar");
112
+ var search = append(toolbar, "input", "", "rte-dialog-browser-search");
113
+ search.type = "search";
114
+ search.placeholder = "Search templates";
115
+ var count = append(toolbar, "div", "", "rte-dialog-browser-count");
116
+
117
+ var scrollpanel = append(browser, "div", "", "rte-dialog-browser-scrollpanel");
118
+ var grid = append(scrollpanel, "div", "", "rte-dialog-browser-grid rte-template-grid");
119
+ var empty = append(scrollpanel, "div", "", "rte-dialog-browser-empty");
120
+ empty.innerText = "No templates match the current filter.";
121
+
122
+ var footer = append(browser, "div", "", "rte-gallery-browser-footer");
123
+ var footerText = append(footer, "div", "", "rte-gallery-browser-footer-text");
124
+ footerText.innerText = "Select a template to replace the current content.";
125
+
126
+ var cancelButton = append(footer, "button", "", "rte-gallery-browser-button");
127
+ cancelButton.type = "button";
128
+ cancelButton.innerText = "Cancel";
129
+
130
+ var applyButton = append(footer, "button", "", "rte-gallery-browser-button rte-gallery-browser-button-primary");
131
+ applyButton.type = "button";
132
+ applyButton.innerText = "Replace Content";
133
+ applyButton.disabled = true;
134
+
135
+ var selectedId = "";
136
+
137
+ function getTemplates() {
138
+ var list = [];
139
+ var items = config.htmlTemplates || [];
140
+ var i;
141
+ for (i = 0; i < items.length; i++) {
142
+ var normalized = normalizeTemplateItem(items[i], i);
143
+ if (normalized && normalized.html) {
144
+ list.push(normalized);
145
+ }
146
+ }
147
+ return list;
148
+ }
149
+
150
+ function getFilteredTemplates() {
151
+ var keyword = search.value.replace(/^\s+|\s+$/g, "").toLowerCase();
152
+ var items = getTemplates();
153
+ if (!keyword) {
154
+ return items;
155
+ }
156
+
157
+ return items.filter(function (item) {
158
+ var plainText = stripHtml(item.html).toLowerCase();
159
+ return item.title.toLowerCase().indexOf(keyword) >= 0
160
+ || plainText.indexOf(keyword) >= 0
161
+ || (item.meta && item.meta.toLowerCase().indexOf(keyword) >= 0);
162
+ });
163
+ }
164
+
165
+ function updateFooter(items) {
166
+ var selectedTemplate = null;
167
+ var i;
168
+ for (i = 0; i < items.length; i++) {
169
+ if (items[i].id === selectedId) {
170
+ selectedTemplate = items[i];
171
+ break;
172
+ }
173
+ }
174
+
175
+ count.innerText = items.length + " template" + (items.length === 1 ? "" : "s");
176
+ footerText.innerText = selectedTemplate
177
+ ? ("Ready to replace the editor content with " + selectedTemplate.title + ".")
178
+ : "Select a template to replace the current content.";
179
+ applyButton.disabled = !selectedTemplate;
180
+ }
181
+
182
+ function applySelected() {
183
+ var items = getTemplates();
184
+ var i;
185
+ for (i = 0; i < items.length; i++) {
186
+ if (items[i].id === selectedId) {
187
+ editor.setHTMLCode(items[i].html);
188
+ closeDialog();
189
+ editor.focus();
190
+ return;
191
+ }
192
+ }
193
+ }
194
+
195
+ function render() {
196
+ clear(grid);
197
+ var items = getFilteredTemplates();
198
+ var i;
199
+
200
+ empty.style.display = items.length ? "none" : "block";
201
+
202
+ for (i = 0; i < items.length; i++) {
203
+ (function (item) {
204
+ var card = append(grid, "button", "", "rte-dialog-browser-card");
205
+ card.type = "button";
206
+ if (item.id === selectedId) {
207
+ card.classList.add("is-selected");
208
+ }
209
+
210
+ var preview = append(card, "div", "", "rte-template-card-preview");
211
+ var previewBody = append(preview, "div", "", "rte-template-card-preview-body");
212
+ var canvas = append(previewBody, "div", "", "rte-template-card-preview-canvas");
213
+ canvas.innerHTML = item.html;
214
+ scalePreview(previewBody, canvas);
215
+
216
+ var footer = append(card, "div", "", "rte-template-card-footer");
217
+ var title = append(footer, "div", "", "rte-template-card-title");
218
+ title.innerText = item.title;
219
+ var meta = append(footer, "div", "", "rte-template-card-meta");
220
+ meta.innerText = item.meta || stripHtml(item.html).substring(0, 80) || "Reusable template";
221
+
222
+ card.onclick = function () {
223
+ selectedId = item.id;
224
+ render();
225
+ };
226
+
227
+ card.ondblclick = function () {
228
+ selectedId = item.id;
229
+ applySelected();
230
+ };
231
+ })(items[i]);
232
+ }
233
+
234
+ if (selectedId) {
235
+ var visible = false;
236
+ for (i = 0; i < items.length; i++) {
237
+ if (items[i].id === selectedId) {
238
+ visible = true;
239
+ break;
240
+ }
241
+ }
242
+ if (!visible) {
243
+ selectedId = "";
244
+ }
245
+ }
246
+
247
+ updateFooter(items);
248
+ }
249
+
250
+ search.oninput = render;
251
+ cancelButton.onclick = closeDialog;
252
+ applyButton.onclick = applySelected;
253
+
254
+ render();
255
+ search.focus();
256
+ };
257
+ }
@@ -0,0 +1,335 @@
1
+ RTE_DefaultConfig.plugin_zz_richtextbox_dialog_style = RTE_Plugin_RichTextBoxDialogStyle;
2
+
3
+ function RTE_Plugin_RichTextBoxDialogStyle() {
4
+ var obj = this;
5
+
6
+ obj.PluginName = "RichTextBoxDialogStyle";
7
+
8
+ obj.InitConfig = function (config) {
9
+ if (!config.imageItems) {
10
+ config.imageItems = [];
11
+ }
12
+ if (!config.galleryImages) {
13
+ config.galleryImages = [];
14
+ }
15
+ if (!config.htmlTemplates) {
16
+ config.htmlTemplates = [];
17
+ }
18
+ if (!config.documentItems) {
19
+ config.documentItems = [];
20
+ }
21
+ };
22
+
23
+ obj.InitEditor = function () {
24
+ };
25
+
26
+ function append(parent, tagName, cssText, className) {
27
+ var tag = parent.ownerDocument.createElement(tagName);
28
+ if (cssText) {
29
+ tag.style.cssText = cssText;
30
+ }
31
+ if (className) {
32
+ tag.className = className;
33
+ }
34
+ parent.appendChild(tag);
35
+ return tag;
36
+ }
37
+
38
+ function getUrlValue(input) {
39
+ return input && input.value ? input.value.replace(/^\s+|\s+$/g, "") : "";
40
+ }
41
+
42
+ function getUrlHost(value) {
43
+ try {
44
+ return new URL(value, window.location.href).hostname || "";
45
+ } catch (ex) {
46
+ return "";
47
+ }
48
+ }
49
+
50
+ function getUrlFileName(value) {
51
+ var clean = String(value || "").split("#")[0].split("?")[0];
52
+ var slash = clean.lastIndexOf("/");
53
+ var fileName = slash >= 0 ? clean.substring(slash + 1) : clean;
54
+ try {
55
+ fileName = decodeURIComponent(fileName);
56
+ } catch (ex) {
57
+ }
58
+ return fileName || "";
59
+ }
60
+
61
+ function getExtension(value) {
62
+ var fileName = getUrlFileName(value);
63
+ var dot = fileName.lastIndexOf(".");
64
+ if (dot < 0) {
65
+ return "LINK";
66
+ }
67
+ return fileName.substring(dot + 1).toUpperCase().substring(0, 4);
68
+ }
69
+
70
+ function ensureUploadIntro(panel, className, message) {
71
+ if (!panel || panel.querySelector("." + className)) {
72
+ return;
73
+ }
74
+ var intro = append(panel, "div", "", className);
75
+ intro.innerText = message;
76
+ }
77
+
78
+ function bindInput(input, handler, flagName) {
79
+ if (input[flagName]) {
80
+ return false;
81
+ }
82
+
83
+ if (input.addEventListener) {
84
+ input.addEventListener("input", handler);
85
+ } else {
86
+ input.onkeyup = handler;
87
+ input.onchange = handler;
88
+ input.onpaste = handler;
89
+ }
90
+
91
+ input[flagName] = true;
92
+ return true;
93
+ }
94
+
95
+ function ensureImagePreview(panel, urlLine) {
96
+ if (!panel || !urlLine) {
97
+ return;
98
+ }
99
+
100
+ var input = urlLine.querySelector("input[type='text']");
101
+ if (!input) {
102
+ return;
103
+ }
104
+
105
+ if (!input.placeholder) {
106
+ input.placeholder = "https://example.com/image.jpg";
107
+ }
108
+
109
+ var preview = panel.querySelector(".rte-insertimage-preview");
110
+ if (!preview) {
111
+ preview = append(panel, "div", "", "rte-insertimage-preview is-empty");
112
+ var image = append(preview, "img", "", "rte-insertimage-preview-image");
113
+ image.alt = "Image preview";
114
+ append(preview, "div", "", "rte-insertimage-preview-caption");
115
+ }
116
+
117
+ if (input.__rteRichTextBoxImagePreviewBound) {
118
+ return;
119
+ }
120
+
121
+ var previewImage = preview.querySelector(".rte-insertimage-preview-image");
122
+ var previewCaption = preview.querySelector(".rte-insertimage-preview-caption");
123
+
124
+ function updatePreview() {
125
+ var value = getUrlValue(input);
126
+ if (!value) {
127
+ preview.classList.add("is-empty");
128
+ preview.classList.remove("is-error");
129
+ previewImage.removeAttribute("src");
130
+ previewCaption.innerText = "Enter an image URL to preview it here.";
131
+ return;
132
+ }
133
+
134
+ preview.classList.remove("is-empty");
135
+ preview.classList.remove("is-error");
136
+ previewCaption.innerText = "Loading preview...";
137
+ previewImage.src = value;
138
+ }
139
+
140
+ previewImage.onload = function () {
141
+ preview.classList.remove("is-empty");
142
+ preview.classList.remove("is-error");
143
+ previewCaption.innerText = "Ready to insert this image.";
144
+ };
145
+
146
+ previewImage.onerror = function () {
147
+ preview.classList.remove("is-empty");
148
+ preview.classList.add("is-error");
149
+ previewCaption.innerText = "Preview unavailable for this URL.";
150
+ };
151
+
152
+ bindInput(input, updatePreview, "__rteRichTextBoxImagePreviewBound");
153
+ updatePreview();
154
+ }
155
+
156
+ function ensureDocumentPreview(panel, urlLine) {
157
+ if (!panel || !urlLine) {
158
+ return;
159
+ }
160
+
161
+ var input = urlLine.querySelector("input[type='text']");
162
+ if (!input) {
163
+ return;
164
+ }
165
+
166
+ if (!input.placeholder) {
167
+ input.placeholder = "https://example.com/files/proposal.pdf";
168
+ }
169
+
170
+ var preview = panel.querySelector(".rte-insertdocument-preview");
171
+ if (!preview) {
172
+ preview = append(panel, "div", "", "rte-insertdocument-preview is-empty");
173
+ var icon = append(preview, "div", "", "rte-insertdocument-preview-icon");
174
+ append(icon, "div", "", "rte-insertdocument-preview-ext");
175
+ var body = append(preview, "div", "", "rte-insertdocument-preview-body");
176
+ append(body, "div", "", "rte-insertdocument-preview-title");
177
+ append(body, "div", "", "rte-insertdocument-preview-meta");
178
+ }
179
+
180
+ if (input.__rteRichTextBoxDocumentPreviewBound) {
181
+ return;
182
+ }
183
+
184
+ var ext = preview.querySelector(".rte-insertdocument-preview-ext");
185
+ var title = preview.querySelector(".rte-insertdocument-preview-title");
186
+ var meta = preview.querySelector(".rte-insertdocument-preview-meta");
187
+
188
+ function updatePreview() {
189
+ var value = getUrlValue(input);
190
+ if (!value) {
191
+ preview.classList.add("is-empty");
192
+ ext.innerText = "DOC";
193
+ title.innerText = "No document selected";
194
+ meta.innerText = "Enter a document URL to preview the inserted link.";
195
+ return;
196
+ }
197
+
198
+ preview.classList.remove("is-empty");
199
+ ext.innerText = getExtension(value);
200
+ title.innerText = getUrlFileName(value) || value;
201
+
202
+ var host = getUrlHost(value);
203
+ meta.innerText = host
204
+ ? ("Source: " + host + " | The editor inserts a clickable link.")
205
+ : "The editor inserts a clickable link at the current cursor position.";
206
+ }
207
+
208
+ bindInput(input, updatePreview, "__rteRichTextBoxDocumentPreviewBound");
209
+ updatePreview();
210
+ }
211
+
212
+ function enhanceInsertImagePanels(root) {
213
+ var panels = [];
214
+ var i;
215
+
216
+ if (root.classList && root.classList.contains("rte-panel-insertimage")) {
217
+ panels.push(root);
218
+ }
219
+
220
+ if (root.querySelectorAll) {
221
+ var nested = root.querySelectorAll(".rte-panel-insertimage");
222
+ for (i = 0; i < nested.length; i++) {
223
+ panels.push(nested[i]);
224
+ }
225
+ }
226
+
227
+ for (i = 0; i < panels.length; i++) {
228
+ var panel = panels[i];
229
+ panel.classList.add("rte-richtextbox-dialog");
230
+
231
+ var uploadTab = panel.querySelector(".fileuploader-dragdrop");
232
+ if (uploadTab) {
233
+ ensureUploadIntro(uploadTab, "rte-insertimage-intro", "Drop an image here or click anywhere in this panel to browse.");
234
+ }
235
+
236
+ var urlTab = panel.querySelector(".rte_insertimage_byurl");
237
+ if (urlTab) {
238
+ ensureUploadIntro(urlTab, "rte-insertimage-intro", "Paste a hosted image URL and verify the preview before inserting.");
239
+ ensureImagePreview(urlTab, urlTab.querySelector(".rte-dialog-line-url"));
240
+ }
241
+
242
+ var actionButton = panel.querySelector(".rte-dialog-line-action .rte-dialog-button");
243
+ if (actionButton && actionButton.innerText === "Insert") {
244
+ actionButton.innerText = "Insert image";
245
+ }
246
+ }
247
+ }
248
+
249
+ function enhanceInsertDocumentPanels(root) {
250
+ var panels = [];
251
+ var i;
252
+
253
+ if (root.classList && root.classList.contains("rte-panel-insertdocument")) {
254
+ panels.push(root);
255
+ }
256
+
257
+ if (root.querySelectorAll) {
258
+ var nested = root.querySelectorAll(".rte-panel-insertdocument");
259
+ for (i = 0; i < nested.length; i++) {
260
+ panels.push(nested[i]);
261
+ }
262
+ }
263
+
264
+ for (i = 0; i < panels.length; i++) {
265
+ var panel = panels[i];
266
+ panel.classList.add("rte-richtextbox-dialog");
267
+
268
+ var uploadTab = panel.querySelector(".fileuploader-dragdrop");
269
+ if (uploadTab) {
270
+ ensureUploadIntro(uploadTab, "rte-insertdocument-intro", "Upload a local file or drag it into the dialog to create a document link.");
271
+ }
272
+
273
+ var urlTab = panel.querySelector(".rte_insertdocument_byurl");
274
+ if (urlTab) {
275
+ ensureUploadIntro(urlTab, "rte-insertdocument-intro", "Paste a hosted file URL and review the link details before inserting.");
276
+ ensureDocumentPreview(urlTab, urlTab.querySelector(".rte-dialog-line-url"));
277
+ }
278
+
279
+ var actionLine = panel.querySelector(".rte-dialog-line-action");
280
+ if (actionLine) {
281
+ actionLine.classList.add("rte-insertdocument-actions");
282
+ }
283
+
284
+ var actionButton = panel.querySelector(".rte-dialog-line-action .rte-dialog-button");
285
+ if (actionButton && actionButton.innerText === "Insert") {
286
+ actionButton.innerText = "Insert document";
287
+ }
288
+ if (actionButton && actionButton.innerText === "Update") {
289
+ actionButton.innerText = "Update document";
290
+ }
291
+ }
292
+ }
293
+
294
+ function patchTree(root) {
295
+ if (!root || root.nodeType !== 1) {
296
+ return;
297
+ }
298
+
299
+ enhanceInsertImagePanels(root);
300
+ enhanceInsertDocumentPanels(root);
301
+ }
302
+
303
+ function start() {
304
+ patchTree(document.documentElement);
305
+
306
+ if (!window.MutationObserver) {
307
+ return;
308
+ }
309
+
310
+ var observer = new MutationObserver(function (mutations) {
311
+ var i;
312
+ var j;
313
+ for (i = 0; i < mutations.length; i++) {
314
+ for (j = 0; j < mutations[i].addedNodes.length; j++) {
315
+ patchTree(mutations[i].addedNodes[j]);
316
+ }
317
+ }
318
+ });
319
+
320
+ observer.observe(document.documentElement, {
321
+ childList: true,
322
+ subtree: true
323
+ });
324
+ }
325
+
326
+ if (document.readyState === "loading") {
327
+ if (document.addEventListener) {
328
+ document.addEventListener("DOMContentLoaded", start);
329
+ } else {
330
+ window.attachEvent("onload", start);
331
+ }
332
+ } else {
333
+ start();
334
+ }
335
+ }