migrate to new git

This commit is contained in:
2025-08-29 01:27:25 +08:00
parent 946eb9961e
commit af2c152ef6
8623 changed files with 1000453 additions and 1 deletions

Binary file not shown.

View File

@@ -0,0 +1,69 @@
/*
Button Editor Plugin
*/
(function () {
var html = '<div class="is-modal buttoneditor">' +
'<div style="width:505px;height:620px;background:#fff;position: relative;display: flex;flex-direction: column;align-items: center;padding: 0px;background:#f8f8f8;">' +
'<div class="is-modal-bar is-draggable" style="position: absolute;top: 0;left: 0;width: 100%;z-index:1;line-height:32px;height:32px;background:#f9f9f9;">' + _cb.out('Button Editor') +
'<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;color:#777;text-align:center;cursor:pointer;">&#10005;</div>' +
'</div>' +
'<iframe data-width="1440" style="width:100%;height:100%;max-width:1440px;border:none;border-top:32px solid transparent;margin:0;box-sizing:border-box;background:#fff;" src="about:blank"></iframe>' +
'</div>' +
'</div>';
_cb.addHtml(html);
var html_button = '<button title="' + _cb.out('Edit Button') + '" data-title="' + _cb.out('Edit Button') + '" class="button-edit" style="display:none;"><svg class="is-icon-flex" style="width:13px;height:13px;"><use xlink:href="#ion-android-create"></use></svg></button>';
var linkTool = document.querySelector('#divLinkTool');
linkTool.insertAdjacentHTML('afterBegin', html_button); //add button to existing #divLinkTool
var buttonEdit = linkTool.querySelector('.button-edit');
//Extend onContentClick
var oldget = _cb.opts.onContentClick;
_cb.opts.onContentClick = function (e) {
let elm = e.target;
var ret = oldget.apply(this, arguments);
var elmDisplay = getStyle(elm, 'display');
if((elm.tagName.toLowerCase() === 'a' && elmDisplay === 'inline-block')) {
buttonEdit.style.display = 'block';
} else {
buttonEdit.style.display = 'none';
}
return ret;
};
buttonEdit.addEventListener('click', function(){
var modal = document.querySelector('.is-modal.buttoneditor');
_cb.showModal(modal);
_cb.saveForUndo(true); // checkLater = true
var btnClose = modal.querySelector('.is-modal-close');
btnClose.addEventListener('click', function(e){
_cb.hideModal(modal);
});
var scriptPath = _cb.getScriptPath();
modal.querySelector('iframe').src = scriptPath + 'plugins/buttoneditor/buttoneditor.html';
});
var getStyle = function(element, property) {
return window.getComputedStyle ? window.getComputedStyle(element, null).getPropertyValue(property) : element.style[property.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); })];
}
})();

View File

@@ -0,0 +1,7 @@
Preview Plugin
To install the plugin, modify config file (contentbuilder\config.js) as follow:
_cb.settings.plugins = ['buttoneditor'];
When you click a button, there will be an 'Edit' icon displayed.

View File

@@ -0,0 +1,15 @@
/*
Hello World Plugin
*/
(function () {
var button_html = '<button id="my_helloworld_button" title="Hello World" style="text-transform:none">hello</button>';
_cb.addButton('helloworld', button_html, '#my_helloworld_button', function () {
alert('Hello World');
});
})();

View File

@@ -0,0 +1,23 @@
Hello World Plugin
To install the plugin, modify config file (contentbuilder\config.js) as follow:
_cb.settings.plugins = ['helloworld'];
This plugin will add a 'Hello World' button on the 'More' popup on toolbar (click the 'More' button).
You can also add the "helloworld" button on the buttons or buttonsMore parameters:
var obj = $.contentbuilder({
...
buttons: [..., "helloworld", ...]
});
or
var obj = $.contentbuilder({
...
buttonsMore: [..., "helloworld", ...]
});
For more info about buttons or buttonsMore parameters, please check the ContentBuilder.js readme.txt.

View File

@@ -0,0 +1,257 @@
/*
Preview Plugin
*/
(function () {
var _screenwidth = window.innerWidth;
if (_screenwidth <= 640) return;
var html =
'<div class="is-modal previewcontent" style="z-index:10004">' +
'<div style="width:100%;height:100%;background:#fff;position: relative;display: flex;flex-direction: column;align-items: center;padding: 0px;background:#f8f8f8;">' +
'<div class="is-modal-bar" style="position: absolute;top: 0;left: 0;width: 100%;z-index:1;line-height:1.5;height:32px;padding:0;">' +
'<div style="width:100%;height:100%;display:flex;justify-content:center;">' +
'<div class="size-control" data-width="1440" style="width:1440px;">' +
'<div class="size-control" data-width="1024" style="width:1024px;">' +
'<div class="size-control" data-width="768" style="width:768px;">' +
'<div class="size-control" data-width="425" style="width:425px;">' +
'<div class="size-control" data-width="375" style="width:375px;">' +
'<div class="size-control" data-width="320" style="width:320px;">' +
'<div class="size-control-info" style="line-height:32px;">1440px</div>' +
"</div>" +
"</div>" +
"</div>" +
"</div>" +
"</div>" +
"</div>" +
"</div>" +
'<div class="is-modal-close" style="z-index:1;width:30px;height:30px;position:absolute;top:0px;right:0px;box-sizing:border-box;padding:0;line-height:30px;font-size: 12px;color:#777;text-align:center;cursor:pointer;"><svg class="is-icon-flex" style="fill:rgba(0, 0, 0, 0.47);width:30px;height:30px;"><use xlink:href="#ion-ios-close-empty"></use></svg></div>' +
"</div>" +
'<iframe data-width="1440" style="width:100%;height:100%;max-width:1440px;border:none;border-top:32px solid transparent;margin:0;box-sizing:border-box;background:#fff;" src="about:blank"></iframe>' +
"</div>" +
"</div>" +
'<svg width="0" height="0" style="position:absolute;display:none;">' +
"<defs>" +
'<symbol viewBox="0 0 512 512" id="ion-ios-close-empty"><path d="M340.2 160l-84.4 84.3-84-83.9-11.8 11.8 84 83.8-84 83.9 11.8 11.7 84-83.8 84.4 84.2 11.8-11.7-84.4-84.3 84.4-84.2z"></path></symbol>' +
'<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>' +
"</defs>" +
"</svg>";
_cb.addHtml(html);
var css =
"<style>" +
".size-control {cursor:pointer;background:#ddd;border-left:#fff 2px solid;border-right:#fff 2px solid;height:100%;display:flex;justify-content:center;}" +
".size-control-info {text-align:center;color:#000;}" +
"</style>";
_cb.addCss(css);
var button_html =
'<button class="previewcontent-button" title="Preview" style="font-size:15px;vertical-align:bottom;">' +
'<svg class="is-icon-flex" style="fill:rgba(0,0,0,0.7);width:19px;height:19px;"><use xlink:href="#ion-eye"></use></svg>' +
"</button>";
var modal = document.querySelector(".is-modal.previewcontent");
_cb.addButton('preview', button_html, '.previewcontent-button', function (e) {
_cb.showModal(modal);
//check if builder is inside iframe
if(window.frameElement) {
var c = getFramedWindow(window.frameElement);
var doc = c.document;
} else {
var doc = parent.document;
}
var basehref = "";
var base = doc.querySelectorAll("base[href]");
if (base.length > 0) {
basehref = '<base href="' + base[0].href + '" />';
}
var csslinks = "";
var styles = doc.querySelectorAll("link[href]");
for (var i = 0; i < styles.length; i++) {
if (
styles[i].href.indexOf(".css") != -1 &&
styles[i].href.indexOf("contentbox.css") == -1 &&
styles[i].href.indexOf("contentbuilder.css") == -1
) {
csslinks +=
'<link href="' +
styles[i].href +
'" rel="stylesheet" type="text/css" />';
}
}
var jsincludes = "";
var scripts = doc.querySelectorAll("script[src]");
for (var i = 0; i < scripts.length; i++) {
if (
scripts[i].src.indexOf(".js") != -1 &&
scripts[i].src.indexOf("index.js") == -1 &&
scripts[i].src.indexOf("contentbox.js") == -1 &&
scripts[i].src.indexOf("contentbox.min.js") == -1 &&
scripts[i].src.indexOf("contentbuilder.js") == -1 &&
scripts[i].src.indexOf("contentbuilder.min.js") == -1 &&
scripts[i].src.indexOf("plugin.js") == -1 &&
scripts[i].src.indexOf("config.js") == -1 &&
scripts[i].src.indexOf("en.js") == -1 &&
scripts[i].src.indexOf("minimalist-blocks") == -1
) {
jsincludes +=
'<script src="' +
scripts[i].src +
'" type="text/javascript"></script>';
}
}
// No script
jsincludes = '';
/* Get Page */
if (!document.querySelector(".is-wrapper")) {
var maxwidth = "800px";
var maxw = window.getComputedStyle(document.querySelector(".is-builder")).getPropertyValue('max-width');
if (!isNaN(parseInt(maxw))) maxwidth = maxw;
var content = _cb.html();
var doc = modal.querySelector('iframe').contentWindow.document;
doc.open();
doc.write(
"<html>" +
"<head>" +
basehref +
'<meta charset="utf-8">' +
"<title></title>" +
csslinks +
"<style>" +
".slider-image { display:block !important; }" +
".container {margin:35px auto 0; max-width: " +
maxwidth +
"; width:100%; padding:0 35px; box-sizing: border-box;}" +
"</style>" +
'<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>' +
"</head>" +
"<body>" +
'<div class="container">' +
content +
"</div>" +
jsincludes +
"</body>" +
"</html>"
);
doc.close();
} else {
// ContentBox
var content = jQuery(".is-wrapper")
.data("contentbox")
.html();
var doc = modal.querySelector('iframe').contentWindow.document;
doc.open();
doc.write(
"<html>" +
"<head>" +
basehref +
'<meta charset="utf-8">' +
"<title></title>" +
csslinks +
"<style>" +
".slider-image { display:block !important; }" +
"</style>" +
'<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>' +
"</head>" +
"<body>" +
'<div class="is-wrapper">' +
content +
"</div>" +
jsincludes +
"</body>" +
"</html>"
);
doc.close();
}
//Or you can specify your custom preview page:
//modal.find('iframe').attr('src','preview.html');
e.preventDefault();
});
var btnClose = modal.querySelector('.is-modal-close');
btnClose.addEventListener('click', function(e){
_cb.hideModal(modal);
});
var sizeControls = modal.querySelectorAll(".size-control");
Array.prototype.forEach.call(sizeControls, function(sizeControl){
sizeControl.addEventListener('mouseover', function(e) {
var elms = modal.querySelectorAll(".size-control");
Array.prototype.forEach.call(elms, function(elm){
elm.style.background = "#ddd";
});
sizeControl.style.background = "#aaa";
elms = sizeControl.querySelectorAll(".size-control");
Array.prototype.forEach.call(elms, function(elm){
elm.style.background = "#aaa";
});
modal.querySelector(".size-control-info").style.color = '#fff';
var w = sizeControl.getAttribute('data-width');
modal.querySelector(".size-control-info").innerHTML = w + 'px';
e.preventDefault();
e.stopImmediatePropagation();
});
sizeControl.addEventListener('mouseout', function(e) {
var elms = modal.querySelectorAll(".size-control");
Array.prototype.forEach.call(elms, function(elm){
elm.style.background = "#ddd";
});
modal.querySelector(".size-control-info").style.color = '#000';
var currW = modal.querySelector("iframe").getAttribute('data-width');
modal.querySelector(".size-control-info").innerText = currW + 'px';
});
sizeControl.addEventListener('click', function(e) {
var w = sizeControl.getAttribute('data-width');
modal.querySelector("iframe").style.maxWidth = w + 'px';
modal.querySelector("iframe").setAttribute('data-width', w);
e.preventDefault();
e.stopImmediatePropagation();
});
});
})();
function getFramedWindow(f) {
if(f.parentNode == null)
f = document.body.appendChild(f);
var w = (f.contentWindow || f.contentDocument);
if(w && w.nodeType && w.nodeType==9)
w = (w.defaultView || w.parentWindow);
return w;
}

View File

@@ -0,0 +1,23 @@
Preview Plugin
To install the plugin, modify config file (contentbuilder\config.js) as follow:
_cb.settings.plugins = ['preview'];
This plugin will add a 'Preview' button on the 'More' popup on the toolbar (click the 'More' button).
You can also add the "preview" button on the toolbar as follow:
var obj = $.contentbuilder({
...
buttons: [..., "preview", ...]
});
or
var obj = $.contentbuilder({
...
buttonsMore: [..., "preview", ...]
});
(For more info about buttons or buttonsMore parameters, please check the ContentBuilder.js readme.txt)

View File

@@ -0,0 +1,128 @@
/*
Search & Replace Plugin
*/
(function () {
var js1 = 'https://cdnjs.cloudflare.com/ajax/libs/rangy/1.3.0/rangy-core.min.js';
var js2 = 'https://cdnjs.cloudflare.com/ajax/libs/rangy/1.3.0/rangy-textrange.min.js'
// _cb.getScript(js1);
// _cb.getScript(js2);
_cb.getScripts([js1,js2]); //Get js1 first, then after loaded, get js2
var html = '<div class="is-modal searchreplace" style="z-index:10004;position:fixed;width:500px;height:280px;top:50%;left:50%;margin-top:-155px;margin-left:-250px;background:#fff;border: 1px solid rgb(199, 199, 199);box-shadow: 0px 5px 5px 5px rgba(0, 0, 0, 0.02);">' +
'<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') +
'<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;color:#777;text-align:center;cursor:pointer;">&#10005;</div>' +
'</div>' +
'<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>' +
'</div>' +
'<svg width="0" height="0" style="position:absolute;display:none;">' +
'<defs>' +
'<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>' +
'</defs>' +
'</svg>';
_cb.addHtml(html);
var button = '<button class="searchreplace-button" title="Search & Replace" style="font-size:15px;vertical-align:bottom;">' +
'<svg class="is-icon-flex" style="width:17px;height:17px;"><use xlink:href="#ion-ios-search-strong"></use></svg>' +
'</button>';
_cb.addButton('searchreplace', button, '.searchreplace-button', function () {
var modal = document.querySelector(".is-modal.searchreplace");
modal.className = modal.className + ' active';
var btnClose = modal.querySelector('.is-modal-close');
btnClose.addEventListener('click', function(e){
_cb.hideModal(modal);
});
var scriptPath = _cb.getScriptPath();
modal.querySelector('iframe').src = scriptPath + 'plugins/searchreplace/searchreplace.html';
// var wraper = _cb.getScope();
// $wraper.focusEnd();
});
})();
// https://stackoverflow.com/questions/32192664/how-to-select-a-given-string-repeatedly-within-the-text-of-a-contenteditable-ele
function findOne(target, caseSensitive, within, startNode, startPos) {
if (rangy.supported) {
var range = rangy.createRange();
var searchScopeRange = rangy.createRange();
searchScopeRange.selectNodeContents(within);
if (startNode != null && startPos != null) {
searchScopeRange.setStart(startNode, startPos);
}
var options = {
caseSensitive: caseSensitive,
wholeWordsOnly: true,
withinRange: searchScopeRange
};
if (target !== "") {
range.findText(target, options);
selectRange(range.startContainer, range.endContainer, range.startOffset, range.endOffset);
var text = getSelected(parent);
if (text != '') {
return true;
} else {
return false;
}
}
}
function selectRange(startNode, endNode, startPos, endPos) {
var range = document.createRange()
range.setStart(startNode, startPos);
range.setEnd(endNode, endPos);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}
function getSelected(window) {
if (window.getSelection) { return window.getSelection(); }
else if (document.getSelection) { return document.getSelection(); }
else {
var selection = document.selection && document.selection.createRange();
if (selection.text) { return selection.text; }
return false;
}
return false;
}
}
// https://stackoverflow.com/questions/1181700/set-cursor-position-on-contenteditable-div/3323835
// $.fn.focusEnd = function () {
// $(this).focus();
// var tmp = $('<span />').appendTo($(this)),
// node = tmp.get(0),
// range = null,
// sel = null;
// if (document.selection) {
// range = document.body.createTextRange();
// range.moveToElementText(node);
// range.select();
// } else if (window.getSelection) {
// range = document.createRange();
// range.selectNode(node);
// sel = window.getSelection();
// sel.removeAllRanges();
// sel.addRange(range);
// }
// tmp.remove();
// return this;
// }

View File

@@ -0,0 +1,23 @@
Search & Replace Plugin
To install the plugin, modify config file (contentbuilder\config.js) as follow:
_cb.settings.plugins = ['searchreplace'];
This plugin will add a 'Search & Replace' button on the 'More' popup on toolbar (click the 'More' button).
You can also add the "searchreplace" button on the buttons or buttonsMore parameters:
var obj = $.contentbuilder({
...
buttons: [..., "searchreplace", ...]
});
or
var obj = $.contentbuilder({
...
buttonsMore: [..., "searchreplace", ...]
});
For more info about buttons or buttonsMore parameters, please check the ContentBuilder.js readme.txt.

View File

@@ -0,0 +1,253 @@
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
body {margin:20px 20px 0;overflow-x:hidden;overflow-y:auto;font-family:sans-serif}
.container {}
.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;}
.clearfix:before, .clearfix:after {content: " ";display: table;}
.clearfix:after {clear: both;}
.clearfix {*zoom: 1;}
.inptext {width:90%;font-size:17px;letter-spacing:1px;border:none;padding:10px;border:rgba(127, 127, 127, 0.32) 1px solid;}
button {
width: 55px;
height: 50px;
line-height: 1;
display: inline-block;
box-sizing: border-box;
margin: 0;
padding: 0;
cursor: pointer;
background-color: #fff;
color: #4a4a4a;
border: 1px solid transparent;
font-family: sans-serif;
letter-spacing: 1px;
font-size: 12px;
font-weight: normal;
text-transform: uppercase;
text-align: center;
position: relative;
border-radius: 0;
transition: all ease 0.3s
}
.inptext:focus {outline:none}
button:focus {outline:none;}
button.classic-primary {
display: inline-block;
width: auto;
height: 50px;
padding-left: 10px;
padding-right: 10px;
min-width: 135px;
background: #f7f7f7;
}
button.classic-secondary {
display: inline-block;
width: auto;
height: 50px;
padding-left: 10px;
padding-right: 10px;
background: transparent;
}
</style>
</head>
<body>
<div style="display:flex;justify-content:space-between;">
<input id="txtSearch" tabindex="1" class="inptext" type="text" style="width:100%;" value="" />
<button class="input-search classic-primary" style="border:rgba(127, 127, 127, 0.32) 1px solid;border-left:none;width:130px;">Search Next</button>
</div>
<div style="margin:10px 0">
<label for="txtReplaceWith">Replace with:</label>
</div>
<div style="display:flex;justify-content:space-between;">
<input id="txtReplaceWith" tabindex="2" class="inptext" type="text" style="width:100%;" value="" />
<button class="input-replace classic-primary" style="border:rgba(127, 127, 127, 0.32) 1px solid;border-left:none;width:130px;">Replace</button>
</div>
<div style="display:flex;justify-content:space-between;margin:17px 0;">
<div>
<label id="lblMatchCase" for="chkMatchCase">
<input type="checkbox" name="chkMatchCase" id="chkMatchCase"> Match case
</label>
<div id="divStatus" style="margin-top:12px;"></div>
</div>
<button class="input-replaceall classic-primary" style="border:rgba(127, 127, 127, 0.32) 1px solid;width:130px;">Replace All</button>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
var nReplaceCount = 0;
jQuery(document).ready(function () {
jQuery('#txtSearch').focus();
jQuery('.input-replaceall').click(function () {
jQuery('#divStatus').html('');
var target = jQuery('#txtSearch').val();
var replaceWith = jQuery('#txtReplaceWith').val();
if (jQuery("#chkMatchCase").prop("checked")) {
var bMatchCase = true;
} else {
var bMatchCase = false;
}
var within = parent._cb.getScope();
var sel = parent.getSelection();
var r1 = parent.document.createRange();
r1.selectNodeContents(within);
// https://stackoverflow.com/questions/32192664/how-to-select-a-given-string-repeatedly-within-the-text-of-a-contenteditable-ele
if (sel.toString().search(target) > -1) {
var ok = parent.findOne(target, bMatchCase, within, sel.focusNode, sel.focusOffset);
if (ok) {
var rng = parent.getSelection().getRangeAt(0);
rng.deleteContents();
rng.insertNode(document.createTextNode(replaceWith));
nReplaceCount++;
}
jQuery('.input-replaceall').trigger('click');
} else if (sel.toString().length > 0) {
var ok = parent.findOne(target, bMatchCase, within, sel.focusNode, sel.focusOffset);
if (ok) {
var rng = parent.getSelection().getRangeAt(0);
rng.deleteContents();
rng.insertNode(document.createTextNode(replaceWith));
nReplaceCount++;
}
jQuery('.input-replaceall').trigger('click');
} else if (sel.rangeCount) {
var ok = parent.findOne(target, bMatchCase, within, r1.commonAncestorContainer, r1.startOffset);
if (ok) {
var rng = parent.getSelection().getRangeAt(0);
rng.deleteContents();
rng.insertNode(document.createTextNode(replaceWith));
nReplaceCount++;
jQuery('.input-replaceall').trigger('click');
} else {
jQuery('#divStatus').html(nReplaceCount + ' occurrence(s) replaced.');
nReplaceCount = 0;
}
}
});
jQuery('.input-search').click(function () {
var target = jQuery('#txtSearch').val();
var replaceWith = jQuery('#txtReplaceWith').val();
if (jQuery("#chkMatchCase").prop("checked")) {
var bMatchCase = true;
} else {
var bMatchCase = false;
}
var within = parent._cb.getScope();
var sel = parent.getSelection();
var r1 = parent.document.createRange();
r1.selectNodeContents(within);
if (sel.toString().search(target) > -1) {
var ok = parent.findOne(target, bMatchCase, within, sel.focusNode, sel.focusOffset);
if (ok) {
jQuery('#divStatus').html('');
} else {
}
} else if (sel.toString().length > 0) {
var ok = parent.findOne(target, bMatchCase, within, sel.focusNode, sel.focusOffset);
if (ok) {
jQuery('#divStatus').html('');
} else {
jQuery('#divStatus').html('Passed the end of the content.');
var ok = parent.findOne(target, bMatchCase, within, r1.commonAncestorContainer, r1.startOffset);
if (ok) {
jQuery('#divStatus').html('');
} else {
jQuery('#divStatus').html('The specified text was not found.');
}
}
} else if (sel.rangeCount) {
var ok = parent.findOne(target, bMatchCase, within, sel.anchorNode, sel.anchorOffset);
if (ok) {
jQuery('#divStatus').html('');
} else {
var ok = parent.findOne(target, bMatchCase, within, r1.commonAncestorContainer, r1.startOffset);
if (ok) {
jQuery('#divStatus').html('');
} else {
jQuery('#divStatus').html('The specified text was not found.');
}
}
}
});
jQuery('.input-replace').click(function () {
var target = jQuery('#txtSearch').val();
var replaceWith = jQuery('#txtReplaceWith').val();
if (jQuery("#chkMatchCase").prop("checked")) {
var bMatchCase = true;
} else {
var bMatchCase = false;
}
var within = parent._cb.getScope();
var sel = parent.getSelection();
var r1 = parent.document.createRange();
r1.selectNodeContents(within);
var text = getSelected(parent);
if (text) {
if ((((text + '').toLowerCase() == target.toLowerCase()) && bMatchCase==false) ||
((text == target) && bMatchCase == true)) {
var rng = parent.getSelection().getRangeAt(0);
rng.deleteContents();
rng.insertNode(document.createTextNode(replaceWith));
}
}
if (sel.rangeCount) {
var ok = parent.findOne(target, bMatchCase, within, sel.anchorNode, sel.anchorOffset);
if (ok) {
jQuery('#divStatus').html('');
} else {
var ok = parent.findOne(target, bMatchCase, within, r1.commonAncestorContainer, r1.startOffset);
if (ok) {
jQuery('#divStatus').html('');
} else {
jQuery('#divStatus').html('The specified text was not found.');
}
}
}
});
});
function getSelected(window) {
if (window.getSelection) { return window.getSelection(); }
else if (document.getSelection) { return document.getSelection(); }
else {
var selection = document.selection && document.selection.createRange();
if (selection.text) { return selection.text; }
return false;
}
return false;
}
</script>
</body>
</html>

View File

@@ -0,0 +1,67 @@
/*
Show Grid Plugin
*/
(function () {
var icon_html = '<svg width="0" height="0" style="position:absolute;display:none;">' +
'<defs>' +
'<symbol viewBox="0 0 512 512" id="ion-ios-grid-view-outline"><path d="M448 192v-16H336V64h-16v112H192V64h-16v112H64v16h112v128H64v16h112v112h16V336h128v112h16V336h112v-16H336V192h112zM320 320H192V192h128v128z"></path></symbol>' +
'</defs>' +
'</svg>';
_cb.addHtml(icon_html);
var css = '<style>' +
'.container.showgrid > div > div {outline: 1px solid rgba(132, 132, 132, 0.27); outline-offset: 1px;}' +
'</style>';
_cb.addCss(css);
var button_html = '<button id="btnShowGrid" title="Grid Outline">' +
'<svg class="is-icon-flex" style="fill:rgba(0, 0, 0, 0.7);width:14px;height:14px;"><use xlink:href="#ion-ios-grid-view-outline"></use></svg>' +
'</button>';
_cb.addButton('showgrid', button_html, '#btnShowGrid', function () {
showGrid();
});
function showGrid() {
// Get all editable areas
const areas = document.querySelectorAll('.container');
Array.prototype.forEach.call(areas, function(area){
if(hasClass(area,'showgrid')){
removeClass(area, 'showgrid');
} else {
addClass(area, 'showgrid');
}
});
}
function addClass(element, classname) {
if(!element) return;
if(hasClass(element,classname)) return;
if(element.classList.length===0) element.className = classname;
else element.className = element.className + ' ' + classname;
element.className = element.className.replace(/ +/g, ' ');
}
function removeClass(element, classname) {
if(!element) return;
if(element.classList.length>0) {
element.className = element.className.replace(new RegExp('\\b'+ classname+'\\b', 'g'), '');
element.className = element.className.replace(/ +/g, ' ');
}
}
function hasClass(element, classname) {
if(!element) return false;
return element.classList ? element.classList.contains(classname) : new RegExp('\\b'+ classname+'\\b').test(element.className);
}
})();

View File

@@ -0,0 +1,23 @@
Show Grid Plugin
To install the plugin, modify config file (contentbuilder\config.js) as follow:
_cb.settings.plugins = ['showgrid'];
This plugin will add a 'show grid outline' button on the 'More' popup on toolbar (click the 'More' button).
You can also add the "showgrid" button on the buttons or buttonsMore parameters:
var obj = $.contentbuilder({
...
buttons: [..., "showgrid", ...]
});
or
var obj = $.contentbuilder({
...
buttonsMore: [..., "showgrid", ...]
});
For more info about buttons or buttonsMore parameters, please check the ContentBuilder.js readme.txt.

View File

@@ -0,0 +1,36 @@
/*
Insert HTML Symbols Plugin
*/
(function () {
var html = '<div class="is-modal is-side' + (_cb.settings.sidePanel == 'right' ? '' : ' fromleft') + ' viewsymbols" style="width:280px;z-index:10004;">' +
'<button title="' + _cb.out('Close') + '" class="is-side-close" style="z-index:1;width:25px;height:25px;position:absolute;top:10px;right:13px;box-sizing:border-box;padding:0;line-height:25px;font-size: 12px;text-align:center;cursor:pointer;background:transparent"><svg class="is-icon-flex" style="width:25px;height:25px;"><use xlink:href="#ion-ios-close-empty"></use></svg></button>' +
'' +
'<iframe src="about:blank" style="width:100%;height:100%;position:absolute;top:0;left:0;border: none;"></iframe>' +
'' +
'</div>';
_cb.addHtml(html);
var button = '<button class="insertsymbol-button" title="Symbol" style="font-size:14px;vertical-align:bottom;">' +
'&#8486;' +
'</button>';
_cb.addButton('symbols', button, '.insertsymbol-button', function () {
var modal = document.querySelector('.is-side.viewsymbols');
_cb.showSidePanel(modal);
var btnClose = modal.querySelector('.is-side-close');
btnClose.addEventListener('click', function(e){
_cb.hideSidePanel(modal);
});
var scriptPath = _cb.getScriptPath();
modal.querySelector('iframe').src = scriptPath + 'plugins/symbols/symbols.html';
});
})();

View File

@@ -0,0 +1,23 @@
Insert Symbols Plugin
To install the plugin, modify config file (contentbuilder\config.js) as follow:
_cb.settings.plugins = ['symbols'];
This plugin will add an 'Insert Symbols' button on the 'More' popup on toolbar (click the 'More' button).
You can also add the "symbols" button on the buttons or buttonsMore parameters:
var obj = $.contentbuilder({
...
buttons: [..., "symbols", ...]
});
or
var obj = $.contentbuilder({
...
buttonsMore: [..., "symbols", ...]
});
For more info about buttons or buttonsMore parameters, please check the ContentBuilder.js readme.txt.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,66 @@
/*
Word Count Plugin
*/
(function () {
var html = '<div class="is-modal wordcount" style="z-index:10005">' +
'<div style="max-width:300px;height:200px;padding:0;">' +
'<div class="is-modal-bar is-draggable" style="height:32px;line-height:32px;">' +
_cb.out('Word Count') +
'<div class="is-modal-close">&#10005;</div>' +
'</div>' +
'<div style="padding:19px 20px 0;">' +
'<div style="line-height:1"><span id="spanWords" style="font-size:60px;font-weight:700;color:#333"></span> &nbsp;<span style="letter-spacing: 1px;color: #333;font-size:15px;">words</span></div>' +
'<div style="padding:8px 0 0 5px;letter-spacing: 1px;color: #333;font-size:15px;">' +
'Characters: <span id="spanChars"></span><br>' +
'Characters (no spaces): <span id="spanCharsNoSpaces"></span>' +
'</div>' +
'<div id="tmp_wordcount" style="width:1px;height:1px;visibility:hidden;""></div>' +
'</div>' +
'</div>' +
'</div>' +
'<svg width="0" height="0" style="display:none;">' +
'<defs>' +
'<symbol viewBox="0 0 512 512" id="ion-information"><path d="M288 448V192h-96v16h32v240h-32v16h128v-16zM255.8 144.5c26.6 0 48.2-21.6 48.2-48.2s-21.6-48.2-48.2-48.2-48.2 21.6-48.2 48.2 21.6 48.2 48.2 48.2z"></path></symbol>' +
'</defs>' +
'</svg>';
_cb.addHtml(html);
var css = '' +
'' +
'';
_cb.addCss(css);
var button = '<button class="wordcount-button" title="Word Count" style="font-size:15px;vertical-align:bottom;">' +
'<svg class="is-icon-flex" style="margin-top:-1px"><use xlink:href="#ion-information"></use></svg>' +
'</button>';
_cb.addButton('wordcount', button, '.wordcount-button', function () {
var modal = document.querySelector(".is-modal.wordcount");
_cb.showModal(modal, true);
modal.querySelector('#tmp_wordcount').innerHTML = _cb.html();
var txt = modal.querySelector('#tmp_wordcount').textContent;
modal.querySelector('#tmp_wordcount').innerHTML = '';
// https://stackoverflow.com/questions/9864644/jquery-character-and-word-count
var chars = txt.length;
var charsnospaces = txt.replace(/\s/g, "").length;
var words = txt.replace(/[^\w ]/g, "").split(/\s+/).length;
modal.querySelector('#spanWords').innerText = words;
modal.querySelector('#spanChars').innerText = chars;
modal.querySelector('#spanCharsNoSpaces').innerText = charsnospaces;
var btnClose = modal.querySelector('.is-modal-close');
btnClose.addEventListener('click', function(e){
_cb.hideModal(modal);
});
});
})();

View File

@@ -0,0 +1,23 @@
Word Count Plugin
To install the plugin, modify config file (contentbuilder\config.js) as follow:
_cb.settings.plugins = ['wordcount'];
This plugin will add a 'Word Count' button on the 'More' popup on toolbar (click the 'More' button).
You can also add the "showgrid" button on the buttons or buttonsMore parameters:
var obj = $.contentbuilder({
...
buttons: [..., "wordcount", ...]
});
or
var obj = $.contentbuilder({
...
buttonsMore: [..., "wordcount", ...]
});
For more info about buttons or buttonsMore parameters, please check the ContentBuilder.js readme.txt.