diff --git a/README.md b/README.md index 38c066c..0b5bad5 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Live demo: [https://jaredreich.com/pell](https://jaredreich.com/pell) | library | size (min+gzip) | size (min) | jquery | bootstrap | link | |---------------|-----------------|------------|--------|-----------|------| -| pell | 1.11kB | 2.85kB | | | https://github.com/jaredreich/pell | +| pell | 1.29kB | 3.48kB | | | https://github.com/jaredreich/pell | | squire | 16kB | 49kB | | | https://github.com/neilj/Squire | | medium-editor | 27kB | 105kB | | | https://github.com/yabwe/medium-editor | | quill | 43kB | 205kB | | | https://github.com/quilljs/quill | @@ -29,7 +29,7 @@ Live demo: [https://jaredreich.com/pell](https://jaredreich.com/pell) * Pure JavaScript, no dependencies, written in ES6 * Easily customizable with the sass file (pell.scss) or overwrite the CSS -Current actions: +Included actions: - Bold - Italic - Underline @@ -45,7 +45,7 @@ Current actions: - Link - Image -Other possible future actions: +Other available actions (listed at https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand): - Justify Center - Justify Full - Justify Left @@ -60,6 +60,8 @@ Other possible future actions: - Undo - Redo +Or create any custom action! + ## Browser Support * IE 9+ @@ -116,7 +118,7 @@ window.pell ```js // Initialize pell on an HTMLElement -pell.init({ +init({ // , required element: document.getElementById('some-id'), @@ -193,7 +195,7 @@ pell.exec(command, value) ``` ```js -const editor = pell.init({ +const editor = init({ element: document.getElementById('pell'), onChange: html => { document.getElementById('text-output').innerHTML = html @@ -206,7 +208,7 @@ const editor = pell.init({ 'underline', { name: 'italic', - result: () => window.pell.exec('italic') + result: () => exec('italic') }, { name: 'custom', @@ -218,14 +220,14 @@ const editor = pell.init({ name: 'image', result: () => { const url = window.prompt('Enter the image URL') - if (url) window.pell.exec('insertImage', ensureHTTP(url)) + if (url) exec('insertImage', ensureHTTP(url)) } }, { name: 'link', result: () => { const url = window.prompt('Enter the link URL') - if (url) window.pell.exec('createLink', ensureHTTP(url)) + if (url) exec('createLink', ensureHTTP(url)) } } ], diff --git a/demo.gif b/demo.gif index 23eae76..cbeea1a 100644 Binary files a/demo.gif and b/demo.gif differ diff --git a/dist/pell.css b/dist/pell.css index 4052319..a0e6a1c 100644 --- a/dist/pell.css +++ b/dist/pell.css @@ -1,23 +1,17 @@ .pell { - border-radius: 5px; - box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1), 0 0 0 1px rgba(10, 10, 10, 0.1); - box-sizing: border-box; - width: 100%; } + border: 1px solid rgba(10, 10, 10, 0.1); + box-sizing: border-box; } .pell-content { box-sizing: border-box; height: 300px; outline: 0; overflow-y: auto; - padding: 10px; - width: 100%; } + padding: 10px; } .pell-actionbar { background-color: #FFF; - border-bottom: 1px solid rgba(10, 10, 10, 0.1); - border-top-left-radius: 5px; - border-top-right-radius: 5px; - width: 100%; } + border-bottom: 1px solid rgba(10, 10, 10, 0.1); } .pell-button { background-color: transparent; @@ -25,4 +19,8 @@ cursor: pointer; height: 30px; outline: 0; - width: 30px; } + width: 30px; + vertical-align: bottom; } + +.pell-button-selected { + background-color: #F0F0F0; } diff --git a/dist/pell.js b/dist/pell.js index 2768106..323afab 100644 --- a/dist/pell.js +++ b/dist/pell.js @@ -10,6 +10,9 @@ var actions = { bold: { icon: 'B', title: 'Bold', + state: function state() { + return queryCommandState('bold'); + }, result: function result() { return exec('bold'); } @@ -17,6 +20,9 @@ var actions = { italic: { icon: 'I', title: 'Italic', + state: function state() { + return queryCommandState('italic'); + }, result: function result() { return exec('italic'); } @@ -24,6 +30,9 @@ var actions = { underline: { icon: 'U', title: 'Underline', + state: function state() { + return queryCommandState('underline'); + }, result: function result() { return exec('underline'); } @@ -31,6 +40,9 @@ var actions = { strikethrough: { icon: 'S', title: 'Strike-through', + state: function state() { + return queryCommandState('strikeThrough'); + }, result: function result() { return exec('strikeThrough'); } @@ -112,19 +124,24 @@ var actions = { var classes = { actionbar: 'pell-actionbar', button: 'pell-button', - content: 'pell-content' + content: 'pell-content', + selected: 'pell-button-selected' }; -var exec = function exec(command) { - var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; - - document.execCommand(command, false, value); +var queryCommandState = function queryCommandState(command) { + return document.queryCommandState(command); }; var preventTab = function preventTab(event) { if (event.which === 9) event.preventDefault(); }; +var exec = function exec(command) { + var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; + + document.execCommand(command, false, value); +}; + var init = function init(settings) { settings.actions = settings.actions ? settings.actions.map(function (action) { if (typeof action === 'string') return actions[action];else if (actions[action.name]) return _extends({}, actions[action.name], action); @@ -153,10 +170,24 @@ var init = function init(settings) { button.className = settings.classes.button; button.innerHTML = action.icon; button.title = action.title; - button.onclick = action.result; + button.setAttribute('type', 'button'); + button.onclick = function () { + return action.result() || settings.element.content.focus(); + }; + + if (action.state) { + var handler = function handler() { + return button.classList[action.state() ? 'add' : 'remove'](settings.classes.selected); + }; + settings.element.content.addEventListener('keyup', handler); + settings.element.content.addEventListener('mouseup', handler); + button.addEventListener('click', handler); + } + actionbar.appendChild(button); }); + if (settings.defaultParagraphSeparator) exec('defaultParagraphSeparator', settings.defaultParagraphSeparator); if (settings.styleWithCSS) exec('styleWithCSS'); return settings.element; diff --git a/dist/pell.min.css b/dist/pell.min.css index 313ca93..98daf9b 100644 --- a/dist/pell.min.css +++ b/dist/pell.min.css @@ -1 +1 @@ -.pell{border-radius:5px;box-shadow:0 2px 3px hsla(0,0%,4%,.1),0 0 0 1px hsla(0,0%,4%,.1)}.pell,.pell-content{box-sizing:border-box;width:100%}.pell-content{height:300px;outline:0;overflow-y:auto;padding:10px}.pell-actionbar{background-color:#fff;border-bottom:1px solid hsla(0,0%,4%,.1);border-top-left-radius:5px;border-top-right-radius:5px;width:100%}.pell-button{background-color:transparent;border:none;cursor:pointer;height:30px;outline:0;width:30px} \ No newline at end of file +.pell{border:1px solid hsla(0,0%,4%,.1)}.pell,.pell-content{box-sizing:border-box}.pell-content{height:300px;outline:0;overflow-y:auto;padding:10px}.pell-actionbar{background-color:#fff;border-bottom:1px solid hsla(0,0%,4%,.1)}.pell-button{background-color:transparent;border:none;cursor:pointer;height:30px;outline:0;width:30px;vertical-align:bottom}.pell-button-selected{background-color:#f0f0f0} \ No newline at end of file diff --git a/dist/pell.min.js b/dist/pell.min.js index 124f7ed..a21afee 100644 --- a/dist/pell.min.js +++ b/dist/pell.min.js @@ -1 +1 @@ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.pell={})}(this,function(t){"use strict";var e=Object.assign||function(t){for(var e=1;eB",title:"Bold",result:function(){return o("bold")}},italic:{icon:"I",title:"Italic",result:function(){return o("italic")}},underline:{icon:"U",title:"Underline",result:function(){return o("underline")}},strikethrough:{icon:"S",title:"Strike-through",result:function(){return o("strikeThrough")}},heading1:{icon:"H1",title:"Heading 1",result:function(){return o("formatBlock","

")}},heading2:{icon:"H2",title:"Heading 2",result:function(){return o("formatBlock","

")}},paragraph:{icon:"¶",title:"Paragraph",result:function(){return o("formatBlock","

")}},quote:{icon:"“ ”",title:"Quote",result:function(){return o("formatBlock","

")}},olist:{icon:"#",title:"Ordered List",result:function(){return o("insertOrderedList")}},ulist:{icon:"•",title:"Unordered List",result:function(){return o("insertUnorderedList")}},code:{icon:"</>",title:"Code",result:function(){return o("formatBlock","
")}},line:{icon:"―",title:"Horizontal Line",result:function(){return o("insertHorizontalRule")}},link:{icon:"🔗",title:"Link",result:function(){var t=window.prompt("Enter the link URL");t&&o("createLink",t)}},image:{icon:"📷",title:"Image",result:function(){var t=window.prompt("Enter the image URL");t&&o("insertImage",t)}}},i={actionbar:"pell-actionbar",button:"pell-button",content:"pell-content"},o=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;document.execCommand(t,!1,e)},r=function(t){9===t.which&&t.preventDefault()},l=function(t){t.actions=t.actions?t.actions.map(function(t){return"string"==typeof t?n[t]:n[t.name]?e({},n[t.name],t):t}):Object.keys(n).map(function(t){return n[t]}),t.classes=e({},i,t.classes);var l=document.createElement("div");return l.className=t.classes.actionbar,t.element.appendChild(l),t.element.content=document.createElement("div"),t.element.content.contentEditable=!0,t.element.content.className=t.classes.content,t.element.content.oninput=function(e){return t.onChange(e.target.innerHTML)},t.element.content.onkeydown=r,t.element.appendChild(t.element.content),t.actions.forEach(function(e){var n=document.createElement("button");n.className=t.classes.button,n.innerHTML=e.icon,n.title=e.title,n.onclick=e.result,l.appendChild(n)}),t.styleWithCSS&&o("styleWithCSS"),t.element},c={exec:o,init:l};t.exec=o,t.init=l,t.default=c,Object.defineProperty(t,"__esModule",{value:!0})});
+!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e(t.pell={})}(this,function(t){"use strict";var e=Object.assign||function(t){for(var e=1;eB",title:"Bold",state:function(){return i("bold")},result:function(){return l("bold")}},italic:{icon:"I",title:"Italic",state:function(){return i("italic")},result:function(){return l("italic")}},underline:{icon:"U",title:"Underline",state:function(){return i("underline")},result:function(){return l("underline")}},strikethrough:{icon:"S",title:"Strike-through",state:function(){return i("strikeThrough")},result:function(){return l("strikeThrough")}},heading1:{icon:"H1",title:"Heading 1",result:function(){return l("formatBlock","

")}},heading2:{icon:"H2",title:"Heading 2",result:function(){return l("formatBlock","

")}},paragraph:{icon:"¶",title:"Paragraph",result:function(){return l("formatBlock","

")}},quote:{icon:"“ ”",title:"Quote",result:function(){return l("formatBlock","

")}},olist:{icon:"#",title:"Ordered List",result:function(){return l("insertOrderedList")}},ulist:{icon:"•",title:"Unordered List",result:function(){return l("insertUnorderedList")}},code:{icon:"</>",title:"Code",result:function(){return l("formatBlock","
")}},line:{icon:"―",title:"Horizontal Line",result:function(){return l("insertHorizontalRule")}},link:{icon:"🔗",title:"Link",result:function(){var t=window.prompt("Enter the link URL");t&&l("createLink",t)}},image:{icon:"📷",title:"Image",result:function(){var t=window.prompt("Enter the image URL");t&&l("insertImage",t)}}},r={actionbar:"pell-actionbar",button:"pell-button",content:"pell-content",selected:"pell-button-selected"},i=function(t){return document.queryCommandState(t)},o=function(t){9===t.which&&t.preventDefault()},l=function(t){var e=arguments.length>1&&void 0!==arguments[1]?arguments[1]:null;document.execCommand(t,!1,e)},u=function(t){t.actions=t.actions?t.actions.map(function(t){return"string"==typeof t?n[t]:n[t.name]?e({},n[t.name],t):t}):Object.keys(n).map(function(t){return n[t]}),t.classes=e({},r,t.classes);var i=document.createElement("div");return i.className=t.classes.actionbar,t.element.appendChild(i),t.element.content=document.createElement("div"),t.element.content.contentEditable=!0,t.element.content.className=t.classes.content,t.element.content.oninput=function(e){return t.onChange(e.target.innerHTML)},t.element.content.onkeydown=o,t.element.appendChild(t.element.content),t.actions.forEach(function(e){var n=document.createElement("button");if(n.className=t.classes.button,n.innerHTML=e.icon,n.title=e.title,n.setAttribute("type","button"),n.onclick=function(){return e.result()||t.element.content.focus()},e.state){var r=function(){return n.classList[e.state()?"add":"remove"](t.classes.selected)};t.element.content.addEventListener("keyup",r),t.element.content.addEventListener("mouseup",r),n.addEventListener("click",r)}i.appendChild(n)}),t.defaultParagraphSeparator&&l("defaultParagraphSeparator",t.defaultParagraphSeparator),t.styleWithCSS&&l("styleWithCSS"),t.element},c={exec:l,init:u};t.exec=l,t.init=u,t.default=c,Object.defineProperty(t,"__esModule",{value:!0})});
diff --git a/package.json b/package.json
index ef97e6e..6ff86f5 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
   "name": "pell",
   "description": "pell - the simplest and smallest WYSIWYG text editor for web, with no dependencies",
   "author": "Jared Reich",
-  "version": "0.7.0",
+  "version": "1.0.0",
   "main": "./dist/pell.min.js",
   "scripts": {
     "dev": "gulp",