@innovastudio/contentbuilder 1.1.12 → 1.1.13

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,460 +1,460 @@
1
- /*
2
- Search & Replace Plugin
3
- */
4
-
5
- (function () {
6
- if(typeof _cb === 'undefined') return;
7
-
8
- var js1 = 'https://cdnjs.cloudflare.com/ajax/libs/rangy/1.3.0/rangy-core.min.js';
9
- var js2 = 'https://cdnjs.cloudflare.com/ajax/libs/rangy/1.3.0/rangy-textrange.min.js'
10
-
11
- // _cb.getScript(js1);
12
- // _cb.getScript(js2);
13
- _cb.getScripts([js1,js2]); //Get js1 first, then after loaded, get js2
14
-
15
- var html = '<div class="is-modal is-modal-content searchreplace">' +
16
- '<div class="is-modal-bar is-draggable" style="position: absolute;top: 0;left: 0;width: 100%;z-index:1;line-height:32px;height:32px;">' + _cb.out('Search & Replace') +
17
- '<div class="is-modal-close" style="z-index:1;width:32px;height:32px;position:absolute;top:0px;right:0px;box-sizing:border-box;padding:0;line-height:32px;font-size: 12px;text-align:center;cursor:pointer;">&#10005;</div>' +
18
- '</div>' +
19
- '<iframe style="position: absolute;top: 0;left: 0;width:100%;height:100%;border:none;border-top:32px solid transparent;margin:0;box-sizing:border-box;" src="about:blank"></iframe>' +
20
- '</div>' +
21
- '<svg width="0" height="0" style="position:absolute;display:none;">' +
22
- '<defs>' +
23
- '<symbol viewBox="0 0 512 512" id="ion-ios-search-strong"><path d="M344.5 298c15-23.6 23.8-51.6 23.8-81.7 0-84.1-68.1-152.3-152.1-152.3C132.1 64 64 132.2 64 216.3c0 84.1 68.1 152.3 152.1 152.3 30.5 0 58.9-9 82.7-24.4l6.9-4.8L414.3 448l33.7-34.3-108.5-108.6 5-7.1zm-43.1-166.8c22.7 22.7 35.2 52.9 35.2 85s-12.5 62.3-35.2 85c-22.7 22.7-52.9 35.2-85 35.2s-62.3-12.5-85-35.2c-22.7-22.7-35.2-52.9-35.2-85s12.5-62.3 35.2-85c22.7-22.7 52.9-35.2 85-35.2s62.3 12.5 85 35.2z"></path></symbol>' +
24
- '</defs>' +
25
- '</svg>';
26
-
27
- _cb.addHtml(html);
28
-
29
- var css = '<style>#_cbhtml .is-modal.searchreplace {' +
30
- 'z-index:10004;position:fixed;width:500px;height:265px;top:50%;left:50%;margin-top:-155px;margin-left:-250px;' +
31
- '}' +
32
- '</style>';
33
-
34
- _cb.addCss(css);
35
-
36
- var button = '<button class="searchreplace-button" title="Search & Replace" style="font-size:15px;vertical-align:bottom;">' +
37
- '<svg class="is-icon-flex" style="width:17px;height:17px;"><use xlink:href="#ion-ios-search-strong"></use></svg>' +
38
- '</button>';
39
-
40
- _cb.addButton('searchreplace', button, '.searchreplace-button', function () {
41
-
42
-
43
- var modal = document.querySelector(".is-modal.searchreplace");
44
- modal.className = modal.className + ' active';
45
-
46
- var btnClose = modal.querySelector('.is-modal-close');
47
- btnClose.addEventListener('click', function(e){
48
- _cb.hideModal(modal);
49
- });
50
-
51
- // var scriptPath = _cb.getScriptPath();
52
- // modal.querySelector('iframe').src = scriptPath + 'plugins/searchreplace/searchreplace.html';
53
-
54
- // var wraper = _cb.getScope();
55
- // $wraper.focusEnd();
56
-
57
- iframe = modal.querySelector('iframe');
58
- doc = iframe.contentWindow.document;
59
- doc.open();
60
- doc.write(getHTML());
61
- doc.close();
62
-
63
- });
64
- /*
65
- _cb.addButton2('searchreplace', button, '.searchreplace-button', function () {
66
-
67
- var modal = document.querySelector(".is-modal.searchreplace");
68
- modal.className = modal.className + ' active';
69
-
70
- var btnClose = modal.querySelector('.is-modal-close');
71
- btnClose.addEventListener('click', function(e){
72
- _cb.hideModal(modal);
73
- });
74
-
75
- // var scriptPath = _cb.getScriptPath();
76
- // modal.querySelector('iframe').src = scriptPath + 'plugins/searchreplace/searchreplace.html';
77
-
78
- // var wraper = _cb.getScope();
79
- // $wraper.focusEnd();
80
-
81
- iframe = modal.querySelector('iframe');
82
- doc = iframe.contentWindow.document;
83
- doc.open();
84
- doc.write(getHTML());
85
- doc.close();
86
-
87
- });
88
- */
89
-
90
- function getHTML() {
91
-
92
- const html = `
93
- <!DOCTYPE HTML>
94
- <html>
95
- <head>
96
- <meta charset="utf-8">
97
- <title></title>
98
- <style>
99
- body {margin:20px 20px 0;overflow-x:hidden;overflow-y:auto;font-family:sans-serif;
100
- font-size: 12px;
101
- letter-spacing: 1px;
102
- font-weight: 300;}
103
- .container {}
104
- .container > div {text-align:center;font-size:24px;cursor:pointer;margin: 0;display:inline-block;float:left;width:25%;height:80px;line-height:80px;border:#eee 1px solid;box-sizing:border-box;}
105
- .clearfix:before, .clearfix:after {content: " ";display: table;}
106
- .clearfix:after {clear: both;}
107
- .clearfix {*zoom: 1;}
108
-
109
- .inptext {
110
- width: 90%;
111
- height: 45px;
112
- box-sizing: border-box;
113
- margin: 0;
114
- font-family: sans-serif;
115
- font-size: 15px;
116
- letter-spacing: 1px;
117
- padding: 0;
118
- padding-left: 8px;
119
- display: inline-block;
120
- border: none;
121
- border-radius: 0;
122
- color: ${_cb.styleInputColor};
123
- background-color: ${_cb.styleInputBackground};
124
- border-bottom: ${_cb.styleInputBorderBottom};
125
- }
126
- #chkMatchCase {opacity:0.9}
127
- button {
128
- width: 55px;
129
- height: 45px;
130
- background-color: ${_cb.styleButtonClassicBackground};
131
- color: ${_cb.styleButtonClassicColor};
132
- border: transparent 1px solid;
133
- border-bottom: ${_cb.styleInputBorderBottom};
134
- font-family: sans-serif;
135
- font-size: 12px;
136
- letter-spacing: 1px;
137
- font-weight: 300;
138
- opacity: 1;
139
- line-height: 1;
140
- display: inline-block;
141
- box-sizing: border-box;
142
- margin: 0;
143
- padding: 0;
144
- cursor: pointer;
145
- text-transform: none;
146
- text-align: center;
147
- position: relative;
148
- border-radius: 0;
149
- user-select: none;
150
- -moz-user-select: none;
151
- -khtml-user-select: none;
152
- -webkit-user-select: none;
153
- -o-user-select: none;
154
- white-space: nowrap;
155
- display: flex;
156
- align-items: center;
157
- justify-content: center;
158
- }
159
- .inptext:focus {outline:none}
160
- button:focus {outline:none;}
161
- .input-replaceall {
162
- border: none;
163
- }
164
- button:hover {
165
- background-color: ${_cb.styleButtonClassicBackgroundHover};
166
- }
167
-
168
- label {
169
- color: ${_cb.styleLabelColor};
170
- }
171
- </style>
172
- </head>
173
- <body>
174
- <form autocomplete="off">
175
- <div style="display:flex;justify-content:space-between;">
176
- <input id="txtSearch" tabindex="1" class="inptext" type="text" style="width:100%;" autocomplete="off" />
177
- <button class="input-search" style="width:130px;">Search Next</button>
178
- </div>
179
- <div style="margin:10px 0">
180
- <label for="txtReplaceWith">Replace with:</label>
181
- </div>
182
- <div style="display:flex;justify-content:space-between;">
183
- <input id="txtReplaceWith" tabindex="2" class="inptext" type="text" style="width:100%;" autocomplete="off" />
184
- <button class="input-replace" style="width:130px;">Replace</button>
185
- </div>
186
- <div style="display:flex;justify-content:space-between;margin:17px 0;">
187
- <div>
188
- <label id="lblMatchCase" for="chkMatchCase">
189
- <input type="checkbox" name="chkMatchCase" id="chkMatchCase"> Match case
190
- </label>
191
- <div id="divStatus" style="margin-top:12px;"></div>
192
- </div>
193
- <button class="input-replaceall" style="width:130px;">Replace All</button>
194
- </div>
195
- </form>
196
-
197
-
198
- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
199
- <script>
200
- var nReplaceCount = 0;
201
-
202
- jQuery(document).ready(function () {
203
-
204
- jQuery('#txtSearch').focus();
205
-
206
- jQuery('.input-replaceall').click(function (e) {
207
-
208
- e.preventDefault();
209
-
210
- jQuery('#divStatus').html('');
211
-
212
- var target = jQuery('#txtSearch').val();
213
- var replaceWith = jQuery('#txtReplaceWith').val();
214
- if (jQuery("#chkMatchCase").prop("checked")) {
215
- var bMatchCase = true;
216
- } else {
217
- var bMatchCase = false;
218
- }
219
-
220
- var within = parent._cb.getScope();
221
-
222
- var sel = parent.getSelection();
223
-
224
- var r1 = parent.document.createRange();
225
- r1.selectNodeContents(within);
226
-
227
- // https://stackoverflow.com/questions/32192664/how-to-select-a-given-string-repeatedly-within-the-text-of-a-contenteditable-ele
228
- if (sel.toString().search(target) > -1) {
229
- var ok = parent.findOne(target, bMatchCase, within, sel.focusNode, sel.focusOffset);
230
- if (ok) {
231
- var rng = parent.getSelection().getRangeAt(0);
232
- rng.deleteContents();
233
- rng.insertNode(document.createTextNode(replaceWith));
234
- nReplaceCount++;
235
- }
236
- jQuery('.input-replaceall').trigger('click');
237
- } else if (sel.toString().length > 0) {
238
- var ok = parent.findOne(target, bMatchCase, within, sel.focusNode, sel.focusOffset);
239
- if (ok) {
240
- var rng = parent.getSelection().getRangeAt(0);
241
- rng.deleteContents();
242
- rng.insertNode(document.createTextNode(replaceWith));
243
- nReplaceCount++;
244
- }
245
- jQuery('.input-replaceall').trigger('click');
246
- } else if (sel.rangeCount) {
247
- var ok = parent.findOne(target, bMatchCase, within, r1.commonAncestorContainer, r1.startOffset);
248
- if (ok) {
249
- var rng = parent.getSelection().getRangeAt(0);
250
- rng.deleteContents();
251
- rng.insertNode(document.createTextNode(replaceWith));
252
- nReplaceCount++;
253
- jQuery('.input-replaceall').trigger('click');
254
- } else {
255
- jQuery('#divStatus').html(nReplaceCount + ' occurrence(s) replaced.');
256
- nReplaceCount = 0;
257
- }
258
- }
259
- });
260
-
261
- jQuery('.input-search').click(function (e) {
262
-
263
- e.preventDefault();
264
-
265
- var target = jQuery('#txtSearch').val();
266
- var replaceWith = jQuery('#txtReplaceWith').val();
267
- if (jQuery("#chkMatchCase").prop("checked")) {
268
- var bMatchCase = true;
269
- } else {
270
- var bMatchCase = false;
271
- }
272
-
273
- var within = parent._cb.getScope();
274
-
275
- var sel = parent.getSelection();
276
-
277
- var r1 = parent.document.createRange();
278
- r1.selectNodeContents(within);
279
-
280
- if (sel.toString().search(target) > -1) {
281
- var ok = parent.findOne(target, bMatchCase, within, sel.focusNode, sel.focusOffset);
282
- if (ok) {
283
- jQuery('#divStatus').html('');
284
- } else {
285
-
286
- }
287
- } else if (sel.toString().length > 0) {
288
- var ok = parent.findOne(target, bMatchCase, within, sel.focusNode, sel.focusOffset);
289
- if (ok) {
290
- jQuery('#divStatus').html('');
291
- } else {
292
- jQuery('#divStatus').html('Passed the end of the content.');
293
- var ok = parent.findOne(target, bMatchCase, within, r1.commonAncestorContainer, r1.startOffset);
294
- if (ok) {
295
- jQuery('#divStatus').html('');
296
- } else {
297
- jQuery('#divStatus').html('The specified text was not found.');
298
- }
299
- }
300
- } else if (sel.rangeCount) {
301
- var ok = parent.findOne(target, bMatchCase, within, sel.anchorNode, sel.anchorOffset);
302
- if (ok) {
303
- jQuery('#divStatus').html('');
304
- } else {
305
- var ok = parent.findOne(target, bMatchCase, within, r1.commonAncestorContainer, r1.startOffset);
306
- if (ok) {
307
- jQuery('#divStatus').html('');
308
- } else {
309
- jQuery('#divStatus').html('The specified text was not found.');
310
- }
311
- }
312
- }
313
-
314
- });
315
-
316
- jQuery('.input-replace').click(function (e) {
317
-
318
- e.preventDefault();
319
-
320
- var target = jQuery('#txtSearch').val();
321
- var replaceWith = jQuery('#txtReplaceWith').val();
322
- if (jQuery("#chkMatchCase").prop("checked")) {
323
- var bMatchCase = true;
324
- } else {
325
- var bMatchCase = false;
326
- }
327
-
328
- var within = parent._cb.getScope();
329
-
330
- var sel = parent.getSelection();
331
-
332
- var r1 = parent.document.createRange();
333
- r1.selectNodeContents(within);
334
-
335
- var text = getSelected(parent);
336
- if (text) {
337
- if ((((text + '').toLowerCase() == target.toLowerCase()) && bMatchCase==false) ||
338
- ((text == target) && bMatchCase == true)) {
339
- var rng = parent.getSelection().getRangeAt(0);
340
- rng.deleteContents();
341
- rng.insertNode(document.createTextNode(replaceWith));
342
- }
343
- }
344
-
345
- if (sel.rangeCount) {
346
- var ok = parent.findOne(target, bMatchCase, within, sel.anchorNode, sel.anchorOffset);
347
- if (ok) {
348
- jQuery('#divStatus').html('');
349
- } else {
350
- var ok = parent.findOne(target, bMatchCase, within, r1.commonAncestorContainer, r1.startOffset);
351
- if (ok) {
352
- jQuery('#divStatus').html('');
353
- } else {
354
- jQuery('#divStatus').html('The specified text was not found.');
355
- }
356
- }
357
- }
358
- });
359
-
360
- });
361
-
362
- function getSelected(window) {
363
- if (window.getSelection) { return window.getSelection(); }
364
- else if (document.getSelection) { return document.getSelection(); }
365
- else {
366
- var selection = document.selection && document.selection.createRange();
367
- if (selection.text) { return selection.text; }
368
- return false;
369
- }
370
- return false;
371
- }
372
-
373
- </script>
374
- </body>
375
- </html>
376
-
377
- `;
378
-
379
- return html;
380
- }
381
-
382
- })();
383
-
384
- // https://stackoverflow.com/questions/32192664/how-to-select-a-given-string-repeatedly-within-the-text-of-a-contenteditable-ele
385
- function findOne(target, caseSensitive, within, startNode, startPos) {
386
- if (rangy.supported) {
387
- var range = rangy.createRange();
388
- var searchScopeRange = rangy.createRange();
389
-
390
- searchScopeRange.selectNodeContents(within);
391
-
392
- if (startNode != null && startPos != null) {
393
- searchScopeRange.setStart(startNode, startPos);
394
- }
395
-
396
- var options = {
397
- caseSensitive: caseSensitive,
398
- wholeWordsOnly: true,
399
- withinRange: searchScopeRange
400
- };
401
-
402
- if (target !== "") {
403
- range.findText(target, options);
404
-
405
- selectRange(range.startContainer, range.endContainer, range.startOffset, range.endOffset);
406
-
407
- var text = getSelected(parent);
408
- if (text != '') {
409
- return true;
410
- } else {
411
- return false;
412
- }
413
- }
414
- }
415
-
416
- function selectRange(startNode, endNode, startPos, endPos) {
417
- var range = document.createRange()
418
- range.setStart(startNode, startPos);
419
- range.setEnd(endNode, endPos);
420
-
421
- var sel = window.getSelection();
422
- sel.removeAllRanges();
423
- sel.addRange(range);
424
- }
425
-
426
- function getSelected(window) {
427
- if (window.getSelection) { return window.getSelection(); }
428
- else if (document.getSelection) { return document.getSelection(); }
429
- else {
430
- var selection = document.selection && document.selection.createRange();
431
- if (selection.text) { return selection.text; }
432
- return false;
433
- }
434
- return false;
435
- }
436
-
437
- }
438
-
439
- // https://stackoverflow.com/questions/1181700/set-cursor-position-on-contenteditable-div/3323835
440
- // $.fn.focusEnd = function () {
441
- // $(this).focus();
442
- // var tmp = $('<span />').appendTo($(this)),
443
- // node = tmp.get(0),
444
- // range = null,
445
- // sel = null;
446
-
447
- // if (document.selection) {
448
- // range = document.body.createTextRange();
449
- // range.moveToElementText(node);
450
- // range.select();
451
- // } else if (window.getSelection) {
452
- // range = document.createRange();
453
- // range.selectNode(node);
454
- // sel = window.getSelection();
455
- // sel.removeAllRanges();
456
- // sel.addRange(range);
457
- // }
458
- // tmp.remove();
459
- // return this;
1
+ /*
2
+ Search & Replace Plugin
3
+ */
4
+
5
+ (function () {
6
+ if(typeof _cb === 'undefined') return;
7
+
8
+ var js1 = 'https://cdnjs.cloudflare.com/ajax/libs/rangy/1.3.0/rangy-core.min.js';
9
+ var js2 = 'https://cdnjs.cloudflare.com/ajax/libs/rangy/1.3.0/rangy-textrange.min.js'
10
+
11
+ // _cb.getScript(js1);
12
+ // _cb.getScript(js2);
13
+ _cb.getScripts([js1,js2]); //Get js1 first, then after loaded, get js2
14
+
15
+ var html = '<div class="is-modal is-modal-content searchreplace">' +
16
+ '<div class="is-modal-bar is-draggable" style="position: absolute;top: 0;left: 0;width: 100%;z-index:1;line-height:32px;height:32px;">' + _cb.out('Search & Replace') +
17
+ '<div class="is-modal-close" style="z-index:1;width:32px;height:32px;position:absolute;top:0px;right:0px;box-sizing:border-box;padding:0;line-height:32px;font-size: 12px;text-align:center;cursor:pointer;">&#10005;</div>' +
18
+ '</div>' +
19
+ '<iframe style="position: absolute;top: 0;left: 0;width:100%;height:100%;border:none;border-top:32px solid transparent;margin:0;box-sizing:border-box;" src="about:blank"></iframe>' +
20
+ '</div>' +
21
+ '<svg width="0" height="0" style="position:absolute;display:none;">' +
22
+ '<defs>' +
23
+ '<symbol viewBox="0 0 512 512" id="ion-ios-search-strong"><path d="M344.5 298c15-23.6 23.8-51.6 23.8-81.7 0-84.1-68.1-152.3-152.1-152.3C132.1 64 64 132.2 64 216.3c0 84.1 68.1 152.3 152.1 152.3 30.5 0 58.9-9 82.7-24.4l6.9-4.8L414.3 448l33.7-34.3-108.5-108.6 5-7.1zm-43.1-166.8c22.7 22.7 35.2 52.9 35.2 85s-12.5 62.3-35.2 85c-22.7 22.7-52.9 35.2-85 35.2s-62.3-12.5-85-35.2c-22.7-22.7-35.2-52.9-35.2-85s12.5-62.3 35.2-85c22.7-22.7 52.9-35.2 85-35.2s62.3 12.5 85 35.2z"></path></symbol>' +
24
+ '</defs>' +
25
+ '</svg>';
26
+
27
+ _cb.addHtml(html);
28
+
29
+ var css = '<style>#_cbhtml .is-modal.searchreplace {' +
30
+ 'z-index:10004;position:fixed;width:500px;height:265px;top:50%;left:50%;margin-top:-155px;margin-left:-250px;' +
31
+ '}' +
32
+ '</style>';
33
+
34
+ _cb.addCss(css);
35
+
36
+ var button = '<button class="searchreplace-button" title="Search & Replace" style="font-size:15px;vertical-align:bottom;">' +
37
+ '<svg class="is-icon-flex" style="width:17px;height:17px;"><use xlink:href="#ion-ios-search-strong"></use></svg>' +
38
+ '</button>';
39
+
40
+ _cb.addButton('searchreplace', button, '.searchreplace-button', function () {
41
+
42
+
43
+ var modal = document.querySelector(".is-modal.searchreplace");
44
+ modal.className = modal.className + ' active';
45
+
46
+ var btnClose = modal.querySelector('.is-modal-close');
47
+ btnClose.addEventListener('click', function(e){
48
+ _cb.hideModal(modal);
49
+ });
50
+
51
+ // var scriptPath = _cb.getScriptPath();
52
+ // modal.querySelector('iframe').src = scriptPath + 'plugins/searchreplace/searchreplace.html';
53
+
54
+ // var wraper = _cb.getScope();
55
+ // $wraper.focusEnd();
56
+
57
+ iframe = modal.querySelector('iframe');
58
+ doc = iframe.contentWindow.document;
59
+ doc.open();
60
+ doc.write(getHTML());
61
+ doc.close();
62
+
63
+ });
64
+ /*
65
+ _cb.addButton2('searchreplace', button, '.searchreplace-button', function () {
66
+
67
+ var modal = document.querySelector(".is-modal.searchreplace");
68
+ modal.className = modal.className + ' active';
69
+
70
+ var btnClose = modal.querySelector('.is-modal-close');
71
+ btnClose.addEventListener('click', function(e){
72
+ _cb.hideModal(modal);
73
+ });
74
+
75
+ // var scriptPath = _cb.getScriptPath();
76
+ // modal.querySelector('iframe').src = scriptPath + 'plugins/searchreplace/searchreplace.html';
77
+
78
+ // var wraper = _cb.getScope();
79
+ // $wraper.focusEnd();
80
+
81
+ iframe = modal.querySelector('iframe');
82
+ doc = iframe.contentWindow.document;
83
+ doc.open();
84
+ doc.write(getHTML());
85
+ doc.close();
86
+
87
+ });
88
+ */
89
+
90
+ function getHTML() {
91
+
92
+ const html = `
93
+ <!DOCTYPE HTML>
94
+ <html>
95
+ <head>
96
+ <meta charset="utf-8">
97
+ <title></title>
98
+ <style>
99
+ body {margin:20px 20px 0;overflow-x:hidden;overflow-y:auto;font-family:sans-serif;
100
+ font-size: 12px;
101
+ letter-spacing: 1px;
102
+ font-weight: 300;}
103
+ .container {}
104
+ .container > div {text-align:center;font-size:24px;cursor:pointer;margin: 0;display:inline-block;float:left;width:25%;height:80px;line-height:80px;border:#eee 1px solid;box-sizing:border-box;}
105
+ .clearfix:before, .clearfix:after {content: " ";display: table;}
106
+ .clearfix:after {clear: both;}
107
+ .clearfix {*zoom: 1;}
108
+
109
+ .inptext {
110
+ width: 90%;
111
+ height: 45px;
112
+ box-sizing: border-box;
113
+ margin: 0;
114
+ font-family: sans-serif;
115
+ font-size: 15px;
116
+ letter-spacing: 1px;
117
+ padding: 0;
118
+ padding-left: 8px;
119
+ display: inline-block;
120
+ border: none;
121
+ border-radius: 0;
122
+ color: ${_cb.styleInputColor};
123
+ background-color: ${_cb.styleInputBackground};
124
+ border-bottom: ${_cb.styleInputBorderBottom};
125
+ }
126
+ #chkMatchCase {opacity:0.9}
127
+ button {
128
+ width: 55px;
129
+ height: 45px;
130
+ background-color: ${_cb.styleButtonClassicBackground};
131
+ color: ${_cb.styleButtonClassicColor};
132
+ border: transparent 1px solid;
133
+ border-bottom: ${_cb.styleInputBorderBottom};
134
+ font-family: sans-serif;
135
+ font-size: 12px;
136
+ letter-spacing: 1px;
137
+ font-weight: 300;
138
+ opacity: 1;
139
+ line-height: 1;
140
+ display: inline-block;
141
+ box-sizing: border-box;
142
+ margin: 0;
143
+ padding: 0;
144
+ cursor: pointer;
145
+ text-transform: none;
146
+ text-align: center;
147
+ position: relative;
148
+ border-radius: 0;
149
+ user-select: none;
150
+ -moz-user-select: none;
151
+ -khtml-user-select: none;
152
+ -webkit-user-select: none;
153
+ -o-user-select: none;
154
+ white-space: nowrap;
155
+ display: flex;
156
+ align-items: center;
157
+ justify-content: center;
158
+ }
159
+ .inptext:focus {outline:none}
160
+ button:focus {outline:none;}
161
+ .input-replaceall {
162
+ border: none;
163
+ }
164
+ button:hover {
165
+ background-color: ${_cb.styleButtonClassicBackgroundHover};
166
+ }
167
+
168
+ label {
169
+ color: ${_cb.styleLabelColor};
170
+ }
171
+ </style>
172
+ </head>
173
+ <body>
174
+ <form autocomplete="off">
175
+ <div style="display:flex;justify-content:space-between;">
176
+ <input id="txtSearch" tabindex="1" class="inptext" type="text" style="width:100%;" autocomplete="off" />
177
+ <button class="input-search" style="width:130px;">Search Next</button>
178
+ </div>
179
+ <div style="margin:10px 0">
180
+ <label for="txtReplaceWith">Replace with:</label>
181
+ </div>
182
+ <div style="display:flex;justify-content:space-between;">
183
+ <input id="txtReplaceWith" tabindex="2" class="inptext" type="text" style="width:100%;" autocomplete="off" />
184
+ <button class="input-replace" style="width:130px;">Replace</button>
185
+ </div>
186
+ <div style="display:flex;justify-content:space-between;margin:17px 0;">
187
+ <div>
188
+ <label id="lblMatchCase" for="chkMatchCase">
189
+ <input type="checkbox" name="chkMatchCase" id="chkMatchCase"> Match case
190
+ </label>
191
+ <div id="divStatus" style="margin-top:12px;"></div>
192
+ </div>
193
+ <button class="input-replaceall" style="width:130px;">Replace All</button>
194
+ </div>
195
+ </form>
196
+
197
+
198
+ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
199
+ <script>
200
+ var nReplaceCount = 0;
201
+
202
+ jQuery(document).ready(function () {
203
+
204
+ jQuery('#txtSearch').focus();
205
+
206
+ jQuery('.input-replaceall').click(function (e) {
207
+
208
+ e.preventDefault();
209
+
210
+ jQuery('#divStatus').html('');
211
+
212
+ var target = jQuery('#txtSearch').val();
213
+ var replaceWith = jQuery('#txtReplaceWith').val();
214
+ if (jQuery("#chkMatchCase").prop("checked")) {
215
+ var bMatchCase = true;
216
+ } else {
217
+ var bMatchCase = false;
218
+ }
219
+
220
+ var within = parent._cb.getScope();
221
+
222
+ var sel = parent.getSelection();
223
+
224
+ var r1 = parent.document.createRange();
225
+ r1.selectNodeContents(within);
226
+
227
+ // https://stackoverflow.com/questions/32192664/how-to-select-a-given-string-repeatedly-within-the-text-of-a-contenteditable-ele
228
+ if (sel.toString().search(target) > -1) {
229
+ var ok = parent.findOne(target, bMatchCase, within, sel.focusNode, sel.focusOffset);
230
+ if (ok) {
231
+ var rng = parent.getSelection().getRangeAt(0);
232
+ rng.deleteContents();
233
+ rng.insertNode(document.createTextNode(replaceWith));
234
+ nReplaceCount++;
235
+ }
236
+ jQuery('.input-replaceall').trigger('click');
237
+ } else if (sel.toString().length > 0) {
238
+ var ok = parent.findOne(target, bMatchCase, within, sel.focusNode, sel.focusOffset);
239
+ if (ok) {
240
+ var rng = parent.getSelection().getRangeAt(0);
241
+ rng.deleteContents();
242
+ rng.insertNode(document.createTextNode(replaceWith));
243
+ nReplaceCount++;
244
+ }
245
+ jQuery('.input-replaceall').trigger('click');
246
+ } else if (sel.rangeCount) {
247
+ var ok = parent.findOne(target, bMatchCase, within, r1.commonAncestorContainer, r1.startOffset);
248
+ if (ok) {
249
+ var rng = parent.getSelection().getRangeAt(0);
250
+ rng.deleteContents();
251
+ rng.insertNode(document.createTextNode(replaceWith));
252
+ nReplaceCount++;
253
+ jQuery('.input-replaceall').trigger('click');
254
+ } else {
255
+ jQuery('#divStatus').html(nReplaceCount + ' occurrence(s) replaced.');
256
+ nReplaceCount = 0;
257
+ }
258
+ }
259
+ });
260
+
261
+ jQuery('.input-search').click(function (e) {
262
+
263
+ e.preventDefault();
264
+
265
+ var target = jQuery('#txtSearch').val();
266
+ var replaceWith = jQuery('#txtReplaceWith').val();
267
+ if (jQuery("#chkMatchCase").prop("checked")) {
268
+ var bMatchCase = true;
269
+ } else {
270
+ var bMatchCase = false;
271
+ }
272
+
273
+ var within = parent._cb.getScope();
274
+
275
+ var sel = parent.getSelection();
276
+
277
+ var r1 = parent.document.createRange();
278
+ r1.selectNodeContents(within);
279
+
280
+ if (sel.toString().search(target) > -1) {
281
+ var ok = parent.findOne(target, bMatchCase, within, sel.focusNode, sel.focusOffset);
282
+ if (ok) {
283
+ jQuery('#divStatus').html('');
284
+ } else {
285
+
286
+ }
287
+ } else if (sel.toString().length > 0) {
288
+ var ok = parent.findOne(target, bMatchCase, within, sel.focusNode, sel.focusOffset);
289
+ if (ok) {
290
+ jQuery('#divStatus').html('');
291
+ } else {
292
+ jQuery('#divStatus').html('Passed the end of the content.');
293
+ var ok = parent.findOne(target, bMatchCase, within, r1.commonAncestorContainer, r1.startOffset);
294
+ if (ok) {
295
+ jQuery('#divStatus').html('');
296
+ } else {
297
+ jQuery('#divStatus').html('The specified text was not found.');
298
+ }
299
+ }
300
+ } else if (sel.rangeCount) {
301
+ var ok = parent.findOne(target, bMatchCase, within, sel.anchorNode, sel.anchorOffset);
302
+ if (ok) {
303
+ jQuery('#divStatus').html('');
304
+ } else {
305
+ var ok = parent.findOne(target, bMatchCase, within, r1.commonAncestorContainer, r1.startOffset);
306
+ if (ok) {
307
+ jQuery('#divStatus').html('');
308
+ } else {
309
+ jQuery('#divStatus').html('The specified text was not found.');
310
+ }
311
+ }
312
+ }
313
+
314
+ });
315
+
316
+ jQuery('.input-replace').click(function (e) {
317
+
318
+ e.preventDefault();
319
+
320
+ var target = jQuery('#txtSearch').val();
321
+ var replaceWith = jQuery('#txtReplaceWith').val();
322
+ if (jQuery("#chkMatchCase").prop("checked")) {
323
+ var bMatchCase = true;
324
+ } else {
325
+ var bMatchCase = false;
326
+ }
327
+
328
+ var within = parent._cb.getScope();
329
+
330
+ var sel = parent.getSelection();
331
+
332
+ var r1 = parent.document.createRange();
333
+ r1.selectNodeContents(within);
334
+
335
+ var text = getSelected(parent);
336
+ if (text) {
337
+ if ((((text + '').toLowerCase() == target.toLowerCase()) && bMatchCase==false) ||
338
+ ((text == target) && bMatchCase == true)) {
339
+ var rng = parent.getSelection().getRangeAt(0);
340
+ rng.deleteContents();
341
+ rng.insertNode(document.createTextNode(replaceWith));
342
+ }
343
+ }
344
+
345
+ if (sel.rangeCount) {
346
+ var ok = parent.findOne(target, bMatchCase, within, sel.anchorNode, sel.anchorOffset);
347
+ if (ok) {
348
+ jQuery('#divStatus').html('');
349
+ } else {
350
+ var ok = parent.findOne(target, bMatchCase, within, r1.commonAncestorContainer, r1.startOffset);
351
+ if (ok) {
352
+ jQuery('#divStatus').html('');
353
+ } else {
354
+ jQuery('#divStatus').html('The specified text was not found.');
355
+ }
356
+ }
357
+ }
358
+ });
359
+
360
+ });
361
+
362
+ function getSelected(window) {
363
+ if (window.getSelection) { return window.getSelection(); }
364
+ else if (document.getSelection) { return document.getSelection(); }
365
+ else {
366
+ var selection = document.selection && document.selection.createRange();
367
+ if (selection.text) { return selection.text; }
368
+ return false;
369
+ }
370
+ return false;
371
+ }
372
+
373
+ </script>
374
+ </body>
375
+ </html>
376
+
377
+ `;
378
+
379
+ return html;
380
+ }
381
+
382
+ })();
383
+
384
+ // https://stackoverflow.com/questions/32192664/how-to-select-a-given-string-repeatedly-within-the-text-of-a-contenteditable-ele
385
+ function findOne(target, caseSensitive, within, startNode, startPos) {
386
+ if (rangy.supported) {
387
+ var range = rangy.createRange();
388
+ var searchScopeRange = rangy.createRange();
389
+
390
+ searchScopeRange.selectNodeContents(within);
391
+
392
+ if (startNode != null && startPos != null) {
393
+ searchScopeRange.setStart(startNode, startPos);
394
+ }
395
+
396
+ var options = {
397
+ caseSensitive: caseSensitive,
398
+ wholeWordsOnly: true,
399
+ withinRange: searchScopeRange
400
+ };
401
+
402
+ if (target !== "") {
403
+ range.findText(target, options);
404
+
405
+ selectRange(range.startContainer, range.endContainer, range.startOffset, range.endOffset);
406
+
407
+ var text = getSelected(parent);
408
+ if (text != '') {
409
+ return true;
410
+ } else {
411
+ return false;
412
+ }
413
+ }
414
+ }
415
+
416
+ function selectRange(startNode, endNode, startPos, endPos) {
417
+ var range = document.createRange()
418
+ range.setStart(startNode, startPos);
419
+ range.setEnd(endNode, endPos);
420
+
421
+ var sel = window.getSelection();
422
+ sel.removeAllRanges();
423
+ sel.addRange(range);
424
+ }
425
+
426
+ function getSelected(window) {
427
+ if (window.getSelection) { return window.getSelection(); }
428
+ else if (document.getSelection) { return document.getSelection(); }
429
+ else {
430
+ var selection = document.selection && document.selection.createRange();
431
+ if (selection.text) { return selection.text; }
432
+ return false;
433
+ }
434
+ return false;
435
+ }
436
+
437
+ }
438
+
439
+ // https://stackoverflow.com/questions/1181700/set-cursor-position-on-contenteditable-div/3323835
440
+ // $.fn.focusEnd = function () {
441
+ // $(this).focus();
442
+ // var tmp = $('<span />').appendTo($(this)),
443
+ // node = tmp.get(0),
444
+ // range = null,
445
+ // sel = null;
446
+
447
+ // if (document.selection) {
448
+ // range = document.body.createTextRange();
449
+ // range.moveToElementText(node);
450
+ // range.select();
451
+ // } else if (window.getSelection) {
452
+ // range = document.createRange();
453
+ // range.selectNode(node);
454
+ // sel = window.getSelection();
455
+ // sel.removeAllRanges();
456
+ // sel.addRange(range);
457
+ // }
458
+ // tmp.remove();
459
+ // return this;
460
460
  // }