@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,4 +1,4 @@
1
- 
1
+
2
2
 
3
3
  if (!RTE_DefaultConfig.svgCode_html2pdf) {
4
4
  RTE_DefaultConfig.svgCode_html2pdf = '<svg viewBox="-2 -2 36 36" fill="#5F6368"><polygon points="30 11 30 9 22 9 22 23 24 23 24 17 29 17 29 15 24 15 24 11 30 11"></polygon><path d="M8,9H2V23H4V18H8a2,2,0,0,0,2-2V11A2,2,0,0,0,8,9Zm0,7H4V11H8Z"></path><path d="M16,23H12V9h4a4,4,0,0,1,4,4v6A4,4,0,0,1,16,23Zm-2-2h2a2,2,0,0,0,2-2V13a2,2,0,0,0-2-2H14Z"></path><title>PDF</title></svg>'
@@ -161,7 +161,9 @@ function RTE_Plugin_Html2PDF() {
161
161
 
162
162
 
163
163
 
164
- 
164
+
165
+
166
+
165
167
 
166
168
  if (!RTE_DefaultConfig.svgCode_imageeditor) {
167
169
  RTE_DefaultConfig.svgCode_imageeditor = '<svg viewBox="-2 -2 20 20" fill="#5F6368"><style>.st0{fill:#f6f6f6}.st1{fill:#424242}.st2{fill:none}.st3{fill:#f0eff1}</style><path class="st0" d="M1 0v6H0v10h10v-1h6V0z" id="outline"/><g id="icon_x5F_bg"><path class="st1" d="M2 5h1v1H2zM2 3h1v1H2zM2 1h1v1H2zM4 1h1.001v1H4zM6 1h1v1H6zM8 1h1v1H8zM10 1h1v1h-1zM12 1h1v1h-1zM14 1h1v1h-1zM14 3h1v1h-1zM14 5h1v1h-1zM14 7h1v1h-1zM14 9h1v1h-1zM14 10.999h1V12h-1zM14 13h1v1h-1zM12 13h1v1h-1zM11 11V5H5v1H4V4h8v7z"/><circle class="st1" cx="6.192" cy="9.807" r=".807"/><path class="st1" d="M1 7v8h8V7H1zm1 7.001v-.28l2.537-1.463L7.554 14l.001.001H2zm6-.93l-3.463-1.982L2 12.491v-4.49h6v5.07zM10 13h1v1h-1z"/></g><g id="icon_x5F_fg"><path class="st2" d="M2 14h5.554v.001H2z"/><path class="st3" d="M11 5v6h-1V6H5V5z"/><path class="st3" d="M2 12.491l2.537-1.402L8 13.071v-5.07H2v4.49zM6.192 9a.807.807 0 1 1 .001 1.615A.807.807 0 0 1 6.192 9z"/><path class="st3" d="M2 13.721V14h5.554l-3.017-1.742z"/></g></svg>';
@@ -321,7 +323,9 @@ function RTE_Plugin_ImageEditor() {
321
323
 
322
324
 
323
325
 
324
- 
326
+
327
+
328
+
325
329
  if (!RTE_DefaultConfig.svgCode_insertcode) {
326
330
  RTE_DefaultConfig.svgCode_insertcode = '<svg viewBox="-2 -2 20 20" fill="#5F6368"><path fill-rule="evenodd" d="M4 1h8a2 2 0 012 2v10a2 2 0 01-2 2H4a2 2 0 01-2-2V3a2 2 0 012-2zm0 1a1 1 0 00-1 1v10a1 1 0 001 1h8a1 1 0 001-1V3a1 1 0 00-1-1H4z" clip-rule="evenodd"/><path fill-rule="evenodd" d="M8.646 5.646a.5.5 0 01.708 0l2 2a.5.5 0 010 .708l-2 2a.5.5 0 01-.708-.708L10.293 8 8.646 6.354a.5.5 0 010-.708zm-1.292 0a.5.5 0 00-.708 0l-2 2a.5.5 0 000 .708l2 2a.5.5 0 00.708-.708L5.707 8l1.647-1.646a.5.5 0 000-.708z" clip-rule="evenodd"/></svg>';
327
331
  }
@@ -637,7 +641,9 @@ function RTE_Plugin_InsertCode() {
637
641
 
638
642
 
639
643
 
640
- 
644
+
645
+
646
+
641
647
  RTE_DefaultConfig.plugin_insertemoji = RTE_Plugin_InsertEmoji;
642
648
 
643
649
  function RTE_Plugin_InsertEmoji() {
@@ -895,168 +901,960 @@ function RTE_Plugin_InsertEmoji() {
895
901
 
896
902
 
897
903
 
898
- 
899
-
900
- RTE_DefaultConfig.plugin_insertgallery = RTE_Plugin_InsertGallery;
901
-
902
- function RTE_Plugin_InsertGallery() {
903
-
904
-
905
-
906
- var obj = this;
907
-
908
- var config, editor;
909
-
910
- obj.PluginName = "InsertGallery";
911
-
912
- obj.InitConfig = function (argconfig) {
913
- config = argconfig;
914
- }
915
- obj.InitEditor = function (argeditor) {
916
- editor = argeditor;
917
-
918
- editor.attachEvent("exec_command_insertgallery", function (state, cmd, value) {
919
- state.returnValue = true;
920
- obj.DoInsertGallery();
921
- });
922
-
923
-
924
- }
925
-
926
- function __Append(parent, tagname, csstext, cssclass) {
927
- var tag = parent.ownerDocument.createElement(tagname);
928
- if (csstext) tag.style.cssText = csstext;
929
- if (cssclass) tag.className = cssclass;
930
- parent.appendChild(tag);
931
- return tag;
932
- }
933
-
934
- obj.DoInsertGallery = function () {
935
-
936
- var dialoginner = editor.createDialog(editor.getLangText("insertgallerytitle"), "rte-dialog-insertgallery");
937
-
938
- var scrollpanel = __Append(dialoginner, "rte-insertgallery-scrollpanel", "overflow-y:auto;padding-bottom:32px;");
939
- var container = __Append(scrollpanel, "rte-insertgallery-container", "display:flex;flex-wrap:wrap;");
940
-
941
- container.focus();//focus to let ESC key close dialog
942
-
943
- function CreateDiv(item) {
944
- var url, text;
945
- if (typeof (item) == "string") {
946
- url = item;
947
- } else if (item instanceof Array) {
948
- url = item[0];
949
- text = item[1];
950
- }
951
- else if (item && item.url) {
952
- url = item.url;
953
- text = item.text;
954
- }
955
- else {
956
- return;
957
- }
958
-
959
- var divitem = __Append(container, "rte-insertgallery-image-item", "cursor:pointer;width:128px;height:128px;margin:12px;box-shadow:0 0 8px #ccc;display:flex;align-items:center;justify-content:center;")
960
- var img = __Append(divitem, "img", "max-width:90%;max-height:90%;");
961
- img.src = url;
962
-
963
- divitem.onclick = function () {
964
- editor.insertImageByUrl(url);
965
- dialoginner.close();
966
- }
967
- }
968
-
969
- for (var i = 0; i < config.galleryImages.length; i++) {
970
- var item = config.galleryImages[i];
971
- CreateDiv(item);
972
- }
973
-
974
- }
975
- }
976
-
977
-
978
-
979
-
980
- 
981
-
982
- RTE_DefaultConfig.plugin_inserttemplate = RTE_Plugin_InsertTemplate;
983
-
984
- function RTE_Plugin_InsertTemplate() {
985
-
986
-
987
-
988
- var obj = this;
989
-
990
- var config, editor;
991
-
992
- obj.PluginName = "InsertTemplate";
993
-
994
- obj.InitConfig = function (argconfig) {
995
- config = argconfig;
996
- }
997
- obj.InitEditor = function (argeditor) {
998
- editor = argeditor;
999
-
1000
- editor.attachEvent("exec_command_inserttemplate", function (state, cmd, value) {
1001
- state.returnValue = true;
1002
- obj.DoInsertTemplate();
1003
- });
1004
-
1005
-
1006
- }
1007
-
1008
- function __Append(parent, tagname, csstext, cssclass) {
1009
- var tag = parent.ownerDocument.createElement(tagname);
1010
- if (csstext) tag.style.cssText = csstext;
1011
- if (cssclass) tag.className = cssclass;
1012
- parent.appendChild(tag);
1013
- return tag;
1014
- }
1015
-
1016
- obj.DoInsertTemplate = function () {
1017
-
1018
- var dialoginner = editor.createDialog(editor.getLangText("inserttemplatetitle"), "rte-dialog-inserttemplate");
1019
-
1020
- var scrollpanel = __Append(dialoginner, "rte-inserttemplate-scrollpanel", "overflow-y:auto;padding-bottom:32px;");
1021
- var container = __Append(scrollpanel, "rte-inserttemplate-container", "display:flex;flex-wrap:wrap;");
1022
-
1023
- container.focus();//focus to let ESC key close dialog
1024
-
1025
- function CreateDiv(item) {
1026
- var text = item[0];
1027
- var html = item[1];
1028
- console.log(item, text, html);
1029
-
1030
- 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;")
1031
- var div = __Append(divitem, "div", "max-width:90%;max-height:90%;overflow:auto;");
1032
- var innerdiv = __Append(div, "div");
1033
- innerdiv.innerHTML = html;
1034
- div.title = text;
1035
-
1036
- var scale = Math.min(200 / div.scrollWidth, 200 / div.scrollHeight);
1037
- if (scale < 1) {
1038
-
1039
- var tx, ty;
1040
- tx = ty = (Math.max(div.scrollWidth, div.scrollHeight) - 200) / 2;
1041
- innerdiv.style.transform = "scale(" + scale + ") translate(-" + tx + "px,-" + ty + "px)";
1042
- div.style.overflow = "hidden";
1043
- }
1044
-
1045
- divitem.onclick = function () {
1046
- editor.setHTMLCode(html);
1047
- dialoginner.close();
1048
- }
1049
- }
1050
-
1051
- for (var i = 0; i < config.htmlTemplates.length; i++) {
1052
- var item = config.htmlTemplates[i];
1053
- CreateDiv(item);
1054
- }
1055
-
1056
- }
1057
- }
1058
904
 
1059
905
 
906
+ RTE_DefaultConfig.plugin_insertgallery = RTE_Plugin_InsertGallery;
907
+
908
+ function RTE_Plugin_InsertGallery() {
909
+ var obj = this;
910
+ var config;
911
+ var editor;
912
+
913
+ obj.PluginName = "InsertGallery";
914
+
915
+ obj.InitConfig = function (argconfig) {
916
+ config = argconfig;
917
+ if (!config.galleryImages) {
918
+ config.galleryImages = [];
919
+ }
920
+ };
921
+
922
+ obj.InitEditor = function (argeditor) {
923
+ editor = argeditor;
924
+
925
+ editor.attachEvent("exec_command_insertgallery", function (state) {
926
+ state.returnValue = true;
927
+ obj.DoInsertGallery();
928
+ });
929
+ };
930
+
931
+ function append(parent, tagName, cssText, className) {
932
+ var tag = parent.ownerDocument.createElement(tagName);
933
+ if (cssText) {
934
+ tag.style.cssText = cssText;
935
+ }
936
+ if (className) {
937
+ tag.className = className;
938
+ }
939
+ parent.appendChild(tag);
940
+ return tag;
941
+ }
942
+
943
+ function clear(node) {
944
+ while (node.firstChild) {
945
+ node.removeChild(node.firstChild);
946
+ }
947
+ }
948
+
949
+ function getFileName(url) {
950
+ var value = String(url || "").split("#")[0].split("?")[0];
951
+ var lastSlash = value.lastIndexOf("/");
952
+ var name = lastSlash >= 0 ? value.substring(lastSlash + 1) : value;
953
+ try {
954
+ name = decodeURIComponent(name);
955
+ } catch (ex) {
956
+ }
957
+ return name || "Image";
958
+ }
959
+
960
+ function getMetaText(item) {
961
+ if (item.meta) {
962
+ return item.meta;
963
+ }
964
+ if (item.alt) {
965
+ return item.alt;
966
+ }
967
+ return item.url;
968
+ }
969
+
970
+ function normalizeGalleryItem(item) {
971
+ var normalized = null;
972
+
973
+ if (typeof item === "string") {
974
+ normalized = {
975
+ url: item,
976
+ thumbnail: item,
977
+ name: getFileName(item)
978
+ };
979
+ } else if (item instanceof Array) {
980
+ normalized = {
981
+ url: item[0],
982
+ thumbnail: item[0],
983
+ name: item[1] || getFileName(item[0]),
984
+ meta: item[2] || ""
985
+ };
986
+ } else if (item && typeof item === "object") {
987
+ var url = item.url || item.src || item.href;
988
+ if (!url) {
989
+ return null;
990
+ }
991
+
992
+ normalized = {
993
+ url: url,
994
+ thumbnail: item.thumbnail || item.thumb || item.preview || url,
995
+ name: item.name || item.text || item.title || getFileName(url),
996
+ meta: item.meta || item.description || item.alt || ""
997
+ };
998
+ }
999
+
1000
+ if (!normalized || !normalized.url) {
1001
+ return null;
1002
+ }
1003
+
1004
+ if (!normalized.thumbnail) {
1005
+ normalized.thumbnail = normalized.url;
1006
+ }
1007
+
1008
+ if (!normalized.name) {
1009
+ normalized.name = getFileName(normalized.url);
1010
+ }
1011
+
1012
+ return normalized;
1013
+ }
1014
+
1015
+ function uploadFiles(fileList, onUploaded, onFinished, onFailed) {
1016
+ var files = [];
1017
+ var handler = window.rte_file_upload_handler;
1018
+ var i;
1019
+
1020
+ for (i = 0; i < fileList.length; i++) {
1021
+ files.push(fileList[i]);
1022
+ }
1023
+
1024
+ if (!files.length) {
1025
+ onFinished();
1026
+ return;
1027
+ }
1028
+
1029
+ if (typeof handler !== "function") {
1030
+ if (onFailed) {
1031
+ onFailed("Upload handler is not configured.");
1032
+ }
1033
+ onFinished();
1034
+ return;
1035
+ }
1036
+
1037
+ var index = 0;
1038
+
1039
+ function next() {
1040
+ if (index >= files.length) {
1041
+ onFinished();
1042
+ return;
1043
+ }
1044
+
1045
+ var file = files[index];
1046
+ handler(file, function (url, error) {
1047
+ if (url) {
1048
+ onUploaded(url, file, index, files);
1049
+ } else if (onFailed) {
1050
+ onFailed(error || ("Upload failed for " + file.name), file);
1051
+ }
1052
+
1053
+ index++;
1054
+ next();
1055
+ }, index, files);
1056
+ }
1057
+
1058
+ next();
1059
+ }
1060
+
1061
+ obj.DoInsertGallery = function () {
1062
+ var dialoginner = editor.createDialog(editor.getLangText("insertgallerytitle") || "Image gallery", "rte-dialog-insertgallery");
1063
+ var closeDialog = typeof dialoginner.close === "function" ? function () {
1064
+ dialoginner.close();
1065
+ } : function () {
1066
+ editor.closeCurrentPopup();
1067
+ };
1068
+
1069
+ var browser = append(dialoginner, "div", "", "rte-gallery-browser");
1070
+ var header = append(browser, "div", "", "rte-dialog-browser-header");
1071
+ var kicker = append(header, "div", "", "rte-dialog-browser-kicker");
1072
+ kicker.innerText = "Media Library";
1073
+ var title = append(header, "div", "", "rte-dialog-browser-title");
1074
+ title.innerText = "Image gallery";
1075
+ var copy = append(header, "div", "", "rte-dialog-browser-copy");
1076
+ copy.innerText = "Browse uploaded assets, filter by name, and insert the selected image into the editor.";
1077
+
1078
+ var toolbar = append(browser, "div", "", "rte-gallery-browser-toolbar");
1079
+ var path = append(toolbar, "div", "", "rte-gallery-browser-path");
1080
+ path.innerText = "/";
1081
+ var type = append(toolbar, "div", "", "rte-gallery-browser-type");
1082
+ type.innerText = "Image Files";
1083
+
1084
+ var uploadButton = append(toolbar, "button", "", "rte-gallery-browser-button");
1085
+ uploadButton.type = "button";
1086
+ uploadButton.innerText = "Upload";
1087
+
1088
+ var refreshButton = append(toolbar, "button", "", "rte-gallery-browser-button");
1089
+ refreshButton.type = "button";
1090
+ refreshButton.innerText = "Refresh";
1091
+
1092
+ var search = append(toolbar, "input", "", "rte-gallery-browser-search");
1093
+ search.type = "search";
1094
+ search.placeholder = "Search images";
1095
+
1096
+ var fileInput = append(toolbar, "input", "display:none;");
1097
+ fileInput.type = "file";
1098
+ fileInput.accept = "image/*,.jpg,.jpeg,.png,.gif,.bmp,.webp,.svg";
1099
+ fileInput.multiple = true;
1100
+
1101
+ var status = append(browser, "div", "", "rte-gallery-browser-status");
1102
+ var surface = append(browser, "div", "", "rte-gallery-browser-surface");
1103
+ var grid = append(surface, "div", "", "rte-gallery-browser-grid");
1104
+ var empty = append(surface, "div", "", "rte-gallery-browser-empty");
1105
+ empty.innerText = "No images match this search. Upload a file or adjust the filter.";
1106
+
1107
+ var footer = append(browser, "div", "", "rte-gallery-browser-footer");
1108
+ var footerText = append(footer, "div", "", "rte-gallery-browser-footer-text");
1109
+ footerText.innerText = "Choose an image to enable insert.";
1110
+
1111
+ var cancelButton = append(footer, "button", "", "rte-gallery-browser-button");
1112
+ cancelButton.type = "button";
1113
+ cancelButton.innerText = "Cancel";
1114
+
1115
+ var insertButton = append(footer, "button", "", "rte-gallery-browser-button rte-gallery-browser-button-primary");
1116
+ insertButton.type = "button";
1117
+ insertButton.innerText = "Insert";
1118
+ insertButton.disabled = true;
1119
+
1120
+ var selectedUrl = "";
1121
+
1122
+ function getNormalizedItems() {
1123
+ var list = [];
1124
+ var items = config.galleryImages || [];
1125
+ var i;
1126
+ for (i = 0; i < items.length; i++) {
1127
+ var normalized = normalizeGalleryItem(items[i]);
1128
+ if (normalized) {
1129
+ list.push(normalized);
1130
+ }
1131
+ }
1132
+ return list;
1133
+ }
1134
+
1135
+ function getFilteredItems() {
1136
+ var keyword = search.value.replace(/^\s+|\s+$/g, "").toLowerCase();
1137
+ var items = getNormalizedItems();
1138
+ if (!keyword) {
1139
+ return items;
1140
+ }
1141
+
1142
+ return items.filter(function (item) {
1143
+ return (item.name && item.name.toLowerCase().indexOf(keyword) >= 0)
1144
+ || (item.meta && item.meta.toLowerCase().indexOf(keyword) >= 0)
1145
+ || (item.url && item.url.toLowerCase().indexOf(keyword) >= 0);
1146
+ });
1147
+ }
1148
+
1149
+ function updateStatus(items) {
1150
+ var selectedName = "";
1151
+ var i;
1152
+ for (i = 0; i < items.length; i++) {
1153
+ if (items[i].url === selectedUrl) {
1154
+ selectedName = items[i].name;
1155
+ break;
1156
+ }
1157
+ }
1158
+
1159
+ status.innerText = items.length + " item" + (items.length === 1 ? "" : "s") + " available."
1160
+ + (selectedName ? " " + selectedName + " selected." : " No image selected.");
1161
+ footerText.innerText = selectedName ? ("Ready to insert " + selectedName + ".") : "Choose an image to enable insert.";
1162
+ insertButton.disabled = !selectedName;
1163
+ }
1164
+
1165
+ function insertSelected() {
1166
+ if (!selectedUrl) {
1167
+ return;
1168
+ }
1169
+ editor.insertImageByUrl(selectedUrl);
1170
+ closeDialog();
1171
+ editor.focus();
1172
+ }
1173
+
1174
+ function render() {
1175
+ clear(grid);
1176
+ var items = getFilteredItems();
1177
+ var i;
1178
+
1179
+ empty.style.display = items.length ? "none" : "block";
1180
+
1181
+ for (i = 0; i < items.length; i++) {
1182
+ (function (item) {
1183
+ var card = append(grid, "button", "", "rte-gallery-browser-card");
1184
+ card.type = "button";
1185
+ if (item.url === selectedUrl) {
1186
+ card.classList.add("is-selected");
1187
+ }
1188
+
1189
+ var selection = append(card, "div", "", "rte-gallery-browser-selection");
1190
+ selection.innerText = item.url === selectedUrl ? "Selected" : "";
1191
+
1192
+ var thumb = append(card, "div", "", "rte-gallery-browser-thumbnail");
1193
+ var image = append(thumb, "img", "", "rte-gallery-browser-thumbnail-image");
1194
+ image.src = item.thumbnail;
1195
+ image.alt = item.name;
1196
+
1197
+ var name = append(card, "div", "", "rte-gallery-browser-name");
1198
+ name.innerText = item.name;
1199
+
1200
+ var meta = append(card, "div", "", "rte-gallery-browser-meta");
1201
+ meta.innerText = getMetaText(item);
1202
+
1203
+ card.onclick = function () {
1204
+ selectedUrl = item.url;
1205
+ render();
1206
+ };
1207
+
1208
+ card.ondblclick = function () {
1209
+ selectedUrl = item.url;
1210
+ insertSelected();
1211
+ };
1212
+ })(items[i]);
1213
+ }
1214
+
1215
+ if (selectedUrl) {
1216
+ var stillVisible = false;
1217
+ for (i = 0; i < items.length; i++) {
1218
+ if (items[i].url === selectedUrl) {
1219
+ stillVisible = true;
1220
+ break;
1221
+ }
1222
+ }
1223
+ if (!stillVisible) {
1224
+ selectedUrl = "";
1225
+ }
1226
+ }
1227
+
1228
+ updateStatus(items);
1229
+ }
1230
+
1231
+ uploadButton.onclick = function () {
1232
+ fileInput.click();
1233
+ };
1234
+
1235
+ fileInput.onchange = function () {
1236
+ var lastUploaded = "";
1237
+ status.innerText = "Uploading images...";
1238
+
1239
+ uploadFiles(fileInput.files, function (url) {
1240
+ lastUploaded = url;
1241
+ config.galleryImages.unshift(url);
1242
+ }, function () {
1243
+ if (lastUploaded) {
1244
+ selectedUrl = lastUploaded;
1245
+ }
1246
+ fileInput.value = "";
1247
+ render();
1248
+ }, function (error) {
1249
+ status.innerText = error || "Upload failed.";
1250
+ });
1251
+ };
1252
+
1253
+ refreshButton.onclick = render;
1254
+ search.oninput = render;
1255
+ cancelButton.onclick = closeDialog;
1256
+ insertButton.onclick = insertSelected;
1257
+
1258
+ render();
1259
+ search.focus();
1260
+ };
1261
+ }
1262
+
1263
+
1264
+ RTE_DefaultConfig.plugin_inserttemplate = RTE_Plugin_InsertTemplate;
1265
+
1266
+ function RTE_Plugin_InsertTemplate() {
1267
+ var obj = this;
1268
+ var config;
1269
+ var editor;
1270
+
1271
+ obj.PluginName = "InsertTemplate";
1272
+
1273
+ obj.InitConfig = function (argconfig) {
1274
+ config = argconfig;
1275
+ if (!config.htmlTemplates) {
1276
+ config.htmlTemplates = [];
1277
+ }
1278
+ };
1279
+
1280
+ obj.InitEditor = function (argeditor) {
1281
+ editor = argeditor;
1282
+
1283
+ editor.attachEvent("exec_command_inserttemplate", function (state) {
1284
+ state.returnValue = true;
1285
+ obj.DoInsertTemplate();
1286
+ });
1287
+ };
1288
+
1289
+ function append(parent, tagName, cssText, className) {
1290
+ var tag = parent.ownerDocument.createElement(tagName);
1291
+ if (cssText) {
1292
+ tag.style.cssText = cssText;
1293
+ }
1294
+ if (className) {
1295
+ tag.className = className;
1296
+ }
1297
+ parent.appendChild(tag);
1298
+ return tag;
1299
+ }
1300
+
1301
+ function clear(node) {
1302
+ while (node.firstChild) {
1303
+ node.removeChild(node.firstChild);
1304
+ }
1305
+ }
1306
+
1307
+ function stripHtml(html) {
1308
+ var div = document.createElement("div");
1309
+ div.innerHTML = html || "";
1310
+ return div.innerText || div.textContent || "";
1311
+ }
1312
+
1313
+ function normalizeTemplateItem(item, index) {
1314
+ if (item instanceof Array) {
1315
+ return {
1316
+ id: "template-" + index,
1317
+ title: item[0] || ("Template " + (index + 1)),
1318
+ html: item[1] || "",
1319
+ meta: item[2] || ""
1320
+ };
1321
+ }
1322
+
1323
+ if (item && typeof item === "object") {
1324
+ return {
1325
+ id: item.id || ("template-" + index),
1326
+ title: item.title || item.name || item.text || ("Template " + (index + 1)),
1327
+ html: item.html || item.content || "",
1328
+ meta: item.meta || item.description || ""
1329
+ };
1330
+ }
1331
+
1332
+ if (typeof item === "string") {
1333
+ return {
1334
+ id: "template-" + index,
1335
+ title: "Template " + (index + 1),
1336
+ html: item,
1337
+ meta: ""
1338
+ };
1339
+ }
1340
+
1341
+ return null;
1342
+ }
1343
+
1344
+ function scalePreview(body, canvas) {
1345
+ var maxWidth = 206;
1346
+ var maxHeight = 166;
1347
+ var width = Math.max(canvas.scrollWidth, 1);
1348
+ var height = Math.max(canvas.scrollHeight, 1);
1349
+ var scale = Math.min(1, maxWidth / width, maxHeight / height);
1350
+
1351
+ canvas.style.transformOrigin = "top left";
1352
+ canvas.style.transform = "scale(" + scale + ")";
1353
+ canvas.style.width = width + "px";
1354
+ canvas.style.height = height + "px";
1355
+ }
1356
+
1357
+ obj.DoInsertTemplate = function () {
1358
+ var dialoginner = editor.createDialog(editor.getLangText("inserttemplatetitle") || "Insert template", "rte-dialog-inserttemplate");
1359
+ var closeDialog = typeof dialoginner.close === "function" ? function () {
1360
+ dialoginner.close();
1361
+ } : function () {
1362
+ editor.closeCurrentPopup();
1363
+ };
1364
+
1365
+ var browser = append(dialoginner, "div", "", "rte-dialog-browser");
1366
+ var header = append(browser, "div", "", "rte-dialog-browser-header");
1367
+ var kicker = append(header, "div", "", "rte-dialog-browser-kicker");
1368
+ kicker.innerText = "Content Blocks";
1369
+ var title = append(header, "div", "", "rte-dialog-browser-title");
1370
+ title.innerText = "Insert template";
1371
+ var copy = append(header, "div", "", "rte-dialog-browser-copy");
1372
+ copy.innerText = "Preview reusable layouts, search by name, and replace the current editor content with a selected template.";
1373
+
1374
+ var toolbar = append(browser, "div", "", "rte-dialog-browser-toolbar");
1375
+ var search = append(toolbar, "input", "", "rte-dialog-browser-search");
1376
+ search.type = "search";
1377
+ search.placeholder = "Search templates";
1378
+ var count = append(toolbar, "div", "", "rte-dialog-browser-count");
1379
+
1380
+ var scrollpanel = append(browser, "div", "", "rte-dialog-browser-scrollpanel");
1381
+ var grid = append(scrollpanel, "div", "", "rte-dialog-browser-grid rte-template-grid");
1382
+ var empty = append(scrollpanel, "div", "", "rte-dialog-browser-empty");
1383
+ empty.innerText = "No templates match the current filter.";
1384
+
1385
+ var footer = append(browser, "div", "", "rte-gallery-browser-footer");
1386
+ var footerText = append(footer, "div", "", "rte-gallery-browser-footer-text");
1387
+ footerText.innerText = "Select a template to replace the current content.";
1388
+
1389
+ var cancelButton = append(footer, "button", "", "rte-gallery-browser-button");
1390
+ cancelButton.type = "button";
1391
+ cancelButton.innerText = "Cancel";
1392
+
1393
+ var applyButton = append(footer, "button", "", "rte-gallery-browser-button rte-gallery-browser-button-primary");
1394
+ applyButton.type = "button";
1395
+ applyButton.innerText = "Replace Content";
1396
+ applyButton.disabled = true;
1397
+
1398
+ var selectedId = "";
1399
+
1400
+ function getTemplates() {
1401
+ var list = [];
1402
+ var items = config.htmlTemplates || [];
1403
+ var i;
1404
+ for (i = 0; i < items.length; i++) {
1405
+ var normalized = normalizeTemplateItem(items[i], i);
1406
+ if (normalized && normalized.html) {
1407
+ list.push(normalized);
1408
+ }
1409
+ }
1410
+ return list;
1411
+ }
1412
+
1413
+ function getFilteredTemplates() {
1414
+ var keyword = search.value.replace(/^\s+|\s+$/g, "").toLowerCase();
1415
+ var items = getTemplates();
1416
+ if (!keyword) {
1417
+ return items;
1418
+ }
1419
+
1420
+ return items.filter(function (item) {
1421
+ var plainText = stripHtml(item.html).toLowerCase();
1422
+ return item.title.toLowerCase().indexOf(keyword) >= 0
1423
+ || plainText.indexOf(keyword) >= 0
1424
+ || (item.meta && item.meta.toLowerCase().indexOf(keyword) >= 0);
1425
+ });
1426
+ }
1427
+
1428
+ function updateFooter(items) {
1429
+ var selectedTemplate = null;
1430
+ var i;
1431
+ for (i = 0; i < items.length; i++) {
1432
+ if (items[i].id === selectedId) {
1433
+ selectedTemplate = items[i];
1434
+ break;
1435
+ }
1436
+ }
1437
+
1438
+ count.innerText = items.length + " template" + (items.length === 1 ? "" : "s");
1439
+ footerText.innerText = selectedTemplate
1440
+ ? ("Ready to replace the editor content with " + selectedTemplate.title + ".")
1441
+ : "Select a template to replace the current content.";
1442
+ applyButton.disabled = !selectedTemplate;
1443
+ }
1444
+
1445
+ function applySelected() {
1446
+ var items = getTemplates();
1447
+ var i;
1448
+ for (i = 0; i < items.length; i++) {
1449
+ if (items[i].id === selectedId) {
1450
+ editor.setHTMLCode(items[i].html);
1451
+ closeDialog();
1452
+ editor.focus();
1453
+ return;
1454
+ }
1455
+ }
1456
+ }
1457
+
1458
+ function render() {
1459
+ clear(grid);
1460
+ var items = getFilteredTemplates();
1461
+ var i;
1462
+
1463
+ empty.style.display = items.length ? "none" : "block";
1464
+
1465
+ for (i = 0; i < items.length; i++) {
1466
+ (function (item) {
1467
+ var card = append(grid, "button", "", "rte-dialog-browser-card");
1468
+ card.type = "button";
1469
+ if (item.id === selectedId) {
1470
+ card.classList.add("is-selected");
1471
+ }
1472
+
1473
+ var preview = append(card, "div", "", "rte-template-card-preview");
1474
+ var previewBody = append(preview, "div", "", "rte-template-card-preview-body");
1475
+ var canvas = append(previewBody, "div", "", "rte-template-card-preview-canvas");
1476
+ canvas.innerHTML = item.html;
1477
+ scalePreview(previewBody, canvas);
1478
+
1479
+ var footer = append(card, "div", "", "rte-template-card-footer");
1480
+ var title = append(footer, "div", "", "rte-template-card-title");
1481
+ title.innerText = item.title;
1482
+ var meta = append(footer, "div", "", "rte-template-card-meta");
1483
+ meta.innerText = item.meta || stripHtml(item.html).substring(0, 80) || "Reusable template";
1484
+
1485
+ card.onclick = function () {
1486
+ selectedId = item.id;
1487
+ render();
1488
+ };
1489
+
1490
+ card.ondblclick = function () {
1491
+ selectedId = item.id;
1492
+ applySelected();
1493
+ };
1494
+ })(items[i]);
1495
+ }
1496
+
1497
+ if (selectedId) {
1498
+ var visible = false;
1499
+ for (i = 0; i < items.length; i++) {
1500
+ if (items[i].id === selectedId) {
1501
+ visible = true;
1502
+ break;
1503
+ }
1504
+ }
1505
+ if (!visible) {
1506
+ selectedId = "";
1507
+ }
1508
+ }
1509
+
1510
+ updateFooter(items);
1511
+ }
1512
+
1513
+ search.oninput = render;
1514
+ cancelButton.onclick = closeDialog;
1515
+ applyButton.onclick = applySelected;
1516
+
1517
+ render();
1518
+ search.focus();
1519
+ };
1520
+ }
1521
+
1522
+
1523
+ RTE_DefaultConfig.plugin_zz_richtextbox_dialog_style = RTE_Plugin_RichTextBoxDialogStyle;
1524
+
1525
+ function RTE_Plugin_RichTextBoxDialogStyle() {
1526
+ var obj = this;
1527
+
1528
+ obj.PluginName = "RichTextBoxDialogStyle";
1529
+
1530
+ obj.InitConfig = function (config) {
1531
+ if (!config.imageItems) {
1532
+ config.imageItems = [];
1533
+ }
1534
+ if (!config.galleryImages) {
1535
+ config.galleryImages = [];
1536
+ }
1537
+ if (!config.htmlTemplates) {
1538
+ config.htmlTemplates = [];
1539
+ }
1540
+ if (!config.documentItems) {
1541
+ config.documentItems = [];
1542
+ }
1543
+ };
1544
+
1545
+ obj.InitEditor = function () {
1546
+ };
1547
+
1548
+ function append(parent, tagName, cssText, className) {
1549
+ var tag = parent.ownerDocument.createElement(tagName);
1550
+ if (cssText) {
1551
+ tag.style.cssText = cssText;
1552
+ }
1553
+ if (className) {
1554
+ tag.className = className;
1555
+ }
1556
+ parent.appendChild(tag);
1557
+ return tag;
1558
+ }
1559
+
1560
+ function getUrlValue(input) {
1561
+ return input && input.value ? input.value.replace(/^\s+|\s+$/g, "") : "";
1562
+ }
1563
+
1564
+ function getUrlHost(value) {
1565
+ try {
1566
+ return new URL(value, window.location.href).hostname || "";
1567
+ } catch (ex) {
1568
+ return "";
1569
+ }
1570
+ }
1571
+
1572
+ function getUrlFileName(value) {
1573
+ var clean = String(value || "").split("#")[0].split("?")[0];
1574
+ var slash = clean.lastIndexOf("/");
1575
+ var fileName = slash >= 0 ? clean.substring(slash + 1) : clean;
1576
+ try {
1577
+ fileName = decodeURIComponent(fileName);
1578
+ } catch (ex) {
1579
+ }
1580
+ return fileName || "";
1581
+ }
1582
+
1583
+ function getExtension(value) {
1584
+ var fileName = getUrlFileName(value);
1585
+ var dot = fileName.lastIndexOf(".");
1586
+ if (dot < 0) {
1587
+ return "LINK";
1588
+ }
1589
+ return fileName.substring(dot + 1).toUpperCase().substring(0, 4);
1590
+ }
1591
+
1592
+ function ensureUploadIntro(panel, className, message) {
1593
+ if (!panel || panel.querySelector("." + className)) {
1594
+ return;
1595
+ }
1596
+ var intro = append(panel, "div", "", className);
1597
+ intro.innerText = message;
1598
+ }
1599
+
1600
+ function bindInput(input, handler, flagName) {
1601
+ if (input[flagName]) {
1602
+ return false;
1603
+ }
1604
+
1605
+ if (input.addEventListener) {
1606
+ input.addEventListener("input", handler);
1607
+ } else {
1608
+ input.onkeyup = handler;
1609
+ input.onchange = handler;
1610
+ input.onpaste = handler;
1611
+ }
1612
+
1613
+ input[flagName] = true;
1614
+ return true;
1615
+ }
1616
+
1617
+ function ensureImagePreview(panel, urlLine) {
1618
+ if (!panel || !urlLine) {
1619
+ return;
1620
+ }
1621
+
1622
+ var input = urlLine.querySelector("input[type='text']");
1623
+ if (!input) {
1624
+ return;
1625
+ }
1626
+
1627
+ if (!input.placeholder) {
1628
+ input.placeholder = "https://example.com/image.jpg";
1629
+ }
1630
+
1631
+ var preview = panel.querySelector(".rte-insertimage-preview");
1632
+ if (!preview) {
1633
+ preview = append(panel, "div", "", "rte-insertimage-preview is-empty");
1634
+ var image = append(preview, "img", "", "rte-insertimage-preview-image");
1635
+ image.alt = "Image preview";
1636
+ append(preview, "div", "", "rte-insertimage-preview-caption");
1637
+ }
1638
+
1639
+ if (input.__rteRichTextBoxImagePreviewBound) {
1640
+ return;
1641
+ }
1642
+
1643
+ var previewImage = preview.querySelector(".rte-insertimage-preview-image");
1644
+ var previewCaption = preview.querySelector(".rte-insertimage-preview-caption");
1645
+
1646
+ function updatePreview() {
1647
+ var value = getUrlValue(input);
1648
+ if (!value) {
1649
+ preview.classList.add("is-empty");
1650
+ preview.classList.remove("is-error");
1651
+ previewImage.removeAttribute("src");
1652
+ previewCaption.innerText = "Enter an image URL to preview it here.";
1653
+ return;
1654
+ }
1655
+
1656
+ preview.classList.remove("is-empty");
1657
+ preview.classList.remove("is-error");
1658
+ previewCaption.innerText = "Loading preview...";
1659
+ previewImage.src = value;
1660
+ }
1661
+
1662
+ previewImage.onload = function () {
1663
+ preview.classList.remove("is-empty");
1664
+ preview.classList.remove("is-error");
1665
+ previewCaption.innerText = "Ready to insert this image.";
1666
+ };
1667
+
1668
+ previewImage.onerror = function () {
1669
+ preview.classList.remove("is-empty");
1670
+ preview.classList.add("is-error");
1671
+ previewCaption.innerText = "Preview unavailable for this URL.";
1672
+ };
1673
+
1674
+ bindInput(input, updatePreview, "__rteRichTextBoxImagePreviewBound");
1675
+ updatePreview();
1676
+ }
1677
+
1678
+ function ensureDocumentPreview(panel, urlLine) {
1679
+ if (!panel || !urlLine) {
1680
+ return;
1681
+ }
1682
+
1683
+ var input = urlLine.querySelector("input[type='text']");
1684
+ if (!input) {
1685
+ return;
1686
+ }
1687
+
1688
+ if (!input.placeholder) {
1689
+ input.placeholder = "https://example.com/files/proposal.pdf";
1690
+ }
1691
+
1692
+ var preview = panel.querySelector(".rte-insertdocument-preview");
1693
+ if (!preview) {
1694
+ preview = append(panel, "div", "", "rte-insertdocument-preview is-empty");
1695
+ var icon = append(preview, "div", "", "rte-insertdocument-preview-icon");
1696
+ append(icon, "div", "", "rte-insertdocument-preview-ext");
1697
+ var body = append(preview, "div", "", "rte-insertdocument-preview-body");
1698
+ append(body, "div", "", "rte-insertdocument-preview-title");
1699
+ append(body, "div", "", "rte-insertdocument-preview-meta");
1700
+ }
1701
+
1702
+ if (input.__rteRichTextBoxDocumentPreviewBound) {
1703
+ return;
1704
+ }
1705
+
1706
+ var ext = preview.querySelector(".rte-insertdocument-preview-ext");
1707
+ var title = preview.querySelector(".rte-insertdocument-preview-title");
1708
+ var meta = preview.querySelector(".rte-insertdocument-preview-meta");
1709
+
1710
+ function updatePreview() {
1711
+ var value = getUrlValue(input);
1712
+ if (!value) {
1713
+ preview.classList.add("is-empty");
1714
+ ext.innerText = "DOC";
1715
+ title.innerText = "No document selected";
1716
+ meta.innerText = "Enter a document URL to preview the inserted link.";
1717
+ return;
1718
+ }
1719
+
1720
+ preview.classList.remove("is-empty");
1721
+ ext.innerText = getExtension(value);
1722
+ title.innerText = getUrlFileName(value) || value;
1723
+
1724
+ var host = getUrlHost(value);
1725
+ meta.innerText = host
1726
+ ? ("Source: " + host + " | The editor inserts a clickable link.")
1727
+ : "The editor inserts a clickable link at the current cursor position.";
1728
+ }
1729
+
1730
+ bindInput(input, updatePreview, "__rteRichTextBoxDocumentPreviewBound");
1731
+ updatePreview();
1732
+ }
1733
+
1734
+ function enhanceInsertImagePanels(root) {
1735
+ var panels = [];
1736
+ var i;
1737
+
1738
+ if (root.classList && root.classList.contains("rte-panel-insertimage")) {
1739
+ panels.push(root);
1740
+ }
1741
+
1742
+ if (root.querySelectorAll) {
1743
+ var nested = root.querySelectorAll(".rte-panel-insertimage");
1744
+ for (i = 0; i < nested.length; i++) {
1745
+ panels.push(nested[i]);
1746
+ }
1747
+ }
1748
+
1749
+ for (i = 0; i < panels.length; i++) {
1750
+ var panel = panels[i];
1751
+ panel.classList.add("rte-richtextbox-dialog");
1752
+
1753
+ var uploadTab = panel.querySelector(".fileuploader-dragdrop");
1754
+ if (uploadTab) {
1755
+ ensureUploadIntro(uploadTab, "rte-insertimage-intro", "Drop an image here or click anywhere in this panel to browse.");
1756
+ }
1757
+
1758
+ var urlTab = panel.querySelector(".rte_insertimage_byurl");
1759
+ if (urlTab) {
1760
+ ensureUploadIntro(urlTab, "rte-insertimage-intro", "Paste a hosted image URL and verify the preview before inserting.");
1761
+ ensureImagePreview(urlTab, urlTab.querySelector(".rte-dialog-line-url"));
1762
+ }
1763
+
1764
+ var actionButton = panel.querySelector(".rte-dialog-line-action .rte-dialog-button");
1765
+ if (actionButton && actionButton.innerText === "Insert") {
1766
+ actionButton.innerText = "Insert image";
1767
+ }
1768
+ }
1769
+ }
1770
+
1771
+ function enhanceInsertDocumentPanels(root) {
1772
+ var panels = [];
1773
+ var i;
1774
+
1775
+ if (root.classList && root.classList.contains("rte-panel-insertdocument")) {
1776
+ panels.push(root);
1777
+ }
1778
+
1779
+ if (root.querySelectorAll) {
1780
+ var nested = root.querySelectorAll(".rte-panel-insertdocument");
1781
+ for (i = 0; i < nested.length; i++) {
1782
+ panels.push(nested[i]);
1783
+ }
1784
+ }
1785
+
1786
+ for (i = 0; i < panels.length; i++) {
1787
+ var panel = panels[i];
1788
+ panel.classList.add("rte-richtextbox-dialog");
1789
+
1790
+ var uploadTab = panel.querySelector(".fileuploader-dragdrop");
1791
+ if (uploadTab) {
1792
+ ensureUploadIntro(uploadTab, "rte-insertdocument-intro", "Upload a local file or drag it into the dialog to create a document link.");
1793
+ }
1794
+
1795
+ var urlTab = panel.querySelector(".rte_insertdocument_byurl");
1796
+ if (urlTab) {
1797
+ ensureUploadIntro(urlTab, "rte-insertdocument-intro", "Paste a hosted file URL and review the link details before inserting.");
1798
+ ensureDocumentPreview(urlTab, urlTab.querySelector(".rte-dialog-line-url"));
1799
+ }
1800
+
1801
+ var actionLine = panel.querySelector(".rte-dialog-line-action");
1802
+ if (actionLine) {
1803
+ actionLine.classList.add("rte-insertdocument-actions");
1804
+ }
1805
+
1806
+ var actionButton = panel.querySelector(".rte-dialog-line-action .rte-dialog-button");
1807
+ if (actionButton && actionButton.innerText === "Insert") {
1808
+ actionButton.innerText = "Insert document";
1809
+ }
1810
+ if (actionButton && actionButton.innerText === "Update") {
1811
+ actionButton.innerText = "Update document";
1812
+ }
1813
+ }
1814
+ }
1815
+
1816
+ function patchTree(root) {
1817
+ if (!root || root.nodeType !== 1) {
1818
+ return;
1819
+ }
1820
+
1821
+ enhanceInsertImagePanels(root);
1822
+ enhanceInsertDocumentPanels(root);
1823
+ }
1824
+
1825
+ function start() {
1826
+ patchTree(document.documentElement);
1827
+
1828
+ if (!window.MutationObserver) {
1829
+ return;
1830
+ }
1831
+
1832
+ var observer = new MutationObserver(function (mutations) {
1833
+ var i;
1834
+ var j;
1835
+ for (i = 0; i < mutations.length; i++) {
1836
+ for (j = 0; j < mutations[i].addedNodes.length; j++) {
1837
+ patchTree(mutations[i].addedNodes[j]);
1838
+ }
1839
+ }
1840
+ });
1841
+
1842
+ observer.observe(document.documentElement, {
1843
+ childList: true,
1844
+ subtree: true
1845
+ });
1846
+ }
1847
+
1848
+ if (document.readyState === "loading") {
1849
+ if (document.addEventListener) {
1850
+ document.addEventListener("DOMContentLoaded", start);
1851
+ } else {
1852
+ window.attachEvent("onload", start);
1853
+ }
1854
+ } else {
1855
+ start();
1856
+ }
1857
+ }
1060
1858
 
1061
1859
 
1062
1860