migrate to new git
This commit is contained in:
BIN
web/App_Script/ContentBuilder/contentbuilder/plugins/.DS_Store
vendored
Normal file
BIN
web/App_Script/ContentBuilder/contentbuilder/plugins/.DS_Store
vendored
Normal file
Binary file not shown.
BIN
web/App_Script/ContentBuilder/contentbuilder/plugins/buttoneditor/.DS_Store
vendored
Normal file
BIN
web/App_Script/ContentBuilder/contentbuilder/plugins/buttoneditor/.DS_Store
vendored
Normal file
Binary file not shown.
File diff suppressed because it is too large
Load Diff
@@ -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;">✕</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(); })];
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
@@ -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.
|
||||
@@ -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');
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
@@ -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.
|
||||
BIN
web/App_Script/ContentBuilder/contentbuilder/plugins/preview/.DS_Store
vendored
Normal file
BIN
web/App_Script/ContentBuilder/contentbuilder/plugins/preview/.DS_Store
vendored
Normal file
Binary file not shown.
@@ -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;
|
||||
}
|
||||
@@ -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)
|
||||
@@ -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;">✕</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;
|
||||
// }
|
||||
@@ -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.
|
||||
@@ -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>
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
@@ -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.
|
||||
@@ -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;">' +
|
||||
'Ω' +
|
||||
'</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';
|
||||
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
@@ -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
@@ -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">✕</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> <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);
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
})();
|
||||
@@ -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.
|
||||
Reference in New Issue
Block a user