Skip to content

Instantly share code, notes, and snippets.

@webketje
Created May 20, 2015 23:15
Show Gist options
  • Save webketje/8c949d57beffe097a770 to your computer and use it in GitHub Desktop.
Save webketje/8c949d57beffe097a770 to your computer and use it in GitHub Desktop.
CKEditor Toolbar code generator
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>CKEditor Toolbar builder</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<style>
body { font-family: sans-serif; font-size: 14px; padding: 0; margin: 0;}
#statusbar { position: absolute; right: 0; background: white; padding: 5px; width: 200px; border: 1px solid #c0c0c0; border-top-width: 0; border-right-width: 0; border-bottom-left-radius: 3px; height: 1em; top: 0;}
#predefined-schemes { padding: 5px 0; }
div.button.selected { background: #ffe; }
#toolbar { background: #eeeeee; overflow: auto; margin-top: 15px; }
#toolbar div.button-group, #toolbar div.button { border: 1px solid #c0c0c0; float: left; margin: 5px; padding: 2px; border-radius: 3px; font-family: sans-serif;font-size: 13px; }
#toolbar div.button {margin: 2px; padding: 2px 4px;}
#toolbar div.icon { background-image: url(http://i.imgur.com/MnAHdlU.png); width: 16px; height: 16px;}
#output { border: 1px solid #c0c0c0; padding: 2px; border-radius: 3px;}
</style>
</head>
<body>
<div id="predefined-schemes" data-bind="foreach: schemes">
<input type="radio" name="predef-schemes" data-bind="checked: $root.selScheme, checkedValue: $index(), disable: name === 'custom'">
<label data-bind="text: name" for="predef-schemes"></label>
</div>
<div data-bind="text: activeButton() ? activeButton() : ''" id="statusbar"></div>
<div id="toolbar" data-bind="foreach: buttonGroups">
<div data-bind="foreach: items" class="button-group">
<div class="button" data-bind="click: function() { selected(!selected()); }, css: { selected: selected }">
<!-- ko if: $data.hasOwnProperty('pos') -->
<div data-bind="style: { backgroundPosition: '0 -' + (pos*16) + 'px', float: name === 'Source' ? 'left' : 'none' }" class="icon"></div>
<!-- ko if: name === 'Source' -->
<span data-bind="text: name" style="margin-left: 3px; vertical-align: middle;"></span>
<!-- /ko -->
<!-- /ko -->
<!-- ko ifnot: $data.hasOwnProperty('pos') -->
<div data-bind="text: name" style="font-size: 14px;"></div>
<!-- /ko -->
</div>
</div>
</div>
<div style="margin-top: 10px;">
<label for="output" style="margin-right: 10px;">Paste code:</label>
<input type="text" name="output" id="output" data-bind="value: output, event: {click: $element.select()} "/>
</div>
<script>
var app = {
activeButton: ko.observable(false),
buttonGroups: [
{ name: 'Document', items : [ {name: 'Source', pos: 0}, {name: 'Save', pos: 2}, {name: 'NewPage', pos: 3}, {name: 'DocProps', pos: 4}, {name: 'Preview', pos: 4}, {name: 'Print', pos: 11}, {name: 'Templates', pos: 5}]},
{ name: 'Clipboard', items : [ {name: 'Cut', pos: 6}, {name: 'Copy', pos: 7}, {name: 'Paste', pos: 8}, {name: 'PasteText', pos: 9}, {name: 'PasteFromWord', pos: 10},{name: 'Undo', pos: 13}, {name: 'Redo', pos: 14}]},
{ name: 'Editing', items : [ {name: 'Find', pos: 15}, {name: 'Replace', pos: 16}, {name: 'SelectAll', pos: 17}, {name: 'SpellChecker', pos: 12}, {name: 'Scayt', pos: 12 }]},
{ name: 'Forms', br: true, items : [{name: 'Form', pos: 51},{name: 'Checkbox', pos:48}, {name: 'Radio', pos: 49}, {name: 'TextField', pos: 50}, {name: 'Textarea', pos: 51}, {name: 'Select', pos: 52}, {name: 'Button', pos: 53},{name: 'ImageButton', pos: 54},{name: 'HiddenField', pos: 55}]},
{ name: 'Basicstyles', br: true, items : [ {name: 'Bold', pos: 19}, {name: 'Italic', pos: 20},{name: 'Underline', pos: 21}, {name: 'Strike', pos: 22}, {name: 'Subscript', pos:23},{name: 'Superscript', pos: 24},{name: 'RemoveFormat', pos: 18}]},
{ name: 'Paragraph', items : [ {name: 'NumberedList', pos: 25},{name: 'BulletedList', pos: 26},{name: 'Outdent', pos: 27},{name: 'Indent', pos: 28},{name: 'Blockquote', pos: 72}, {name: 'CreateDiv', pos: 73},{name: 'JustifyLeft', pos: 29},{name: 'JustifyCenter', pos: 30}, {name: 'JustifyRight', pos: 31}, {name: 'JustifyBlock', pos: 32},{name: 'BidiLtr', pos: 66}, {name: 'BidiRtl', pos: 67}]},
{ name: 'Links', items : [ {name: 'Link', pos:33}, {name: 'Unlink', pos:34}, {name: 'Anchor', pos:35}]},
{ name: 'Insert', items : [ {name: 'Image', pos:36}, {name: 'Flash', pos:37}, {name: 'Table', pos:38}, {name: 'HorizontalRule', pos:39}, {name: 'Smiley', pos:40}, {name: 'SpecialChar', pos:41}, {name: 'PageBreak', pos:42}, {name: 'Iframe', pos:43}]},
{ name: 'Styles', items : [ {name: 'Styles'}, {name: 'Format'}, {name: 'Font'}, {name: 'FontSize'}]},
{ name: 'Colors', items : [ {name: 'TextColor', pos: 45}, {name: 'BGColor', pos: 46}]},
{ name: 'Tools', items : [ {name: 'Maximize', pos: 65}, {name: 'ShowBlocks', pos: 47}, {name: 'About', pos: 46}]}
]
};
var order = 0;
ko.utils.arrayForEach(app.buttonGroups, function(btg) {
ko.utils.arrayForEach(btg.items, function(bt) {
bt.selected = ko.observable(false);
bt.order = order++;
});
});
app.triggerUpdates = ko.observable(true);
app.selectedButtons = ko.computed(function() {
var result = [];
ko.utils.arrayForEach(app.buttonGroups, function(btg) {
ko.utils.arrayForEach(btg.items, function(bt) {
var x = bt;
if ( bt.selected() === true) {
x.group = btg.name;
result.push(x);
}
});
});
result.sort(function (l, r) { return l.order > r.order ? 1 : -1 })
return result;
}).extend({rateLimit: 200 });
app.selectedButtons.subscribe(function(value) {
function match(a, b) {
if (a.length === b.length) {
for (var i = 0; i < a.length; i++) {
if (a[i] !== b[i]) {
console.log(a[i] + ' - ' + b[i]);
return false;
}
}
return true;
}
return false;
}
var value = ko.utils.arrayMap(value, function(item) { return item.name }), flag = false;
ko.utils.arrayForEach(app.schemes, function(scheme, i) {
if (scheme.items && match(value, scheme.items)) {
flag = true;
if (app.selScheme() !== i) app.selScheme(i);
}
});
if (flag === false) {
app.selScheme(app.schemes.length-1);
}
});
app.output = ko.computed(function() {
var collection = app.selectedButtons(), output = '[', groups = 0;
var seps = function(i) {
var arr = [2, 3, 5, 7];
for (var x = arr.length; x--;) {
if (i === arr[x]) return true;
}
return false;
};
for (var i = 0; i < collection.length; i++) {
var item = collection[i];
if (i === 0)
output += '[';
if (collection[i-1] && collection[i-1].group !== item.group)
groups++;
output += '"' + item.name + '"';
if (collection[i+1] && collection[i+1].group === item.group) {
output += ',';
}
else if (i === collection.length-1)
output += ']';
else {
//if (seps(groups))
// continue; //output += '], "/", [';
//else
output += '], [';
}
}
return output + ']';
});
app.iterateButtons = function(action) {
ko.utils.arrayForEach(app.buttonGroups, function(btg) {
ko.utils.arrayForEach(btg.items, function(bt) {
action(btg, bt);
});
});
};
app.schemes = [
{name: 'none', items: [], output: '[]'},
{name: 'basic', items: ['Source','Bold', 'Italic', 'Underline', 'RemoveFormat', 'NumberedList', 'BulletedList', 'JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock', 'Link', 'Unlink', 'Image'], output: ko.toJSON(['Source','Bold', 'Italic', 'Underline', 'RemoveFormat', 'NumberedList', 'BulletedList', 'JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock', 'Link', 'Unlink', 'Image'])},
{name: 'advanced', items: ['Source','Bold', 'Italic', 'Underline', 'RemoveFormat', 'NumberedList', 'BulletedList', 'JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock', 'Link', 'Unlink', 'Image', 'Table', 'Styles','Format','Font','FontSize','TextColor', 'BGColor'],
output: ko.toJSON([['Bold', 'Italic', 'Underline', 'NumberedList', 'BulletedList', 'JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock', 'Table', 'TextColor', 'BGColor', 'Link', 'Unlink', 'Image', 'RemoveFormat', 'Source'],'/',['Styles','Format','Font','FontSize']])},
{name: 'full', items: [], output: ''},
{name: 'custom'}
];
app.iterateButtons(function(group, button) { app.schemes[3].items.push(button.name); });
app.schemes[3].output = ko.toJSON(app.schemes[3].items);
app.selScheme = ko.observable(0);
app.selScheme.subscribe(function(value) {
var s = app.schemes[ko.unwrap(value)].items;
if (app.selScheme() !== 4) {
app.iterateButtons(function(group, bt) {
if (s.indexOf(bt.name) > -1)
bt.selected(true);
else
bt.selected(false);
});
}
});
app.getScheme = function(scheme) {
if (scheme === 'full') {
var result = [];
ko.utils.arrayForEach(app.buttonGroups, function(btg) {
var btGroup = [];
ko.utils.arrayForEach(btg.items, function(bt) {
btGroup.push(bt.name);
});
result.push(btGroup);
});
return result;
} else {
return app.schemes[scheme];
}
};
ko.applyBindings(app);
$('.button').mouseenter(function() {
var data = ko.dataFor(this).name,
ctx = ko.contextFor(this).$parent.name;
app.activeButton(ctx + ': ' + data);
});
$('.button').mouseleave(function() {
app.activeButton(false);
});
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment