diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..e2cccc2a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# --- proj files --- +.DS_Store +Thumbs.db +/.idea/ +/*.sublime-project +/*.sublime-workspace \ No newline at end of file diff --git a/ce_interface.js b/ce_interface.js index 19a71e182..b089129da 100644 --- a/ce_interface.js +++ b/ce_interface.js @@ -3,23 +3,24 @@ * @author Savchenko Peter (vk.com/specc) */ -var ce = function(textareaId) { +var ce = function(settings) { - this.resultTextarea = document.getElementById(textareaId); + this.resultTextarea = document.getElementById("codex_editor"); if (typeof this.resultTextarea == undefined || this.resultTextarea == null ){ - - console.warn('Textarea not found with ID %o', textareaId); + console.warn('Textarea not found with ID %o', this.textareaId); return this; + } + /* Prepare settings */ + if ("undefined" == typeof settings) settings = this.defaultSettings; + else { + // todo just merge settings with defaults } - this.toolbarOpened = false; - this.tools = ['header', 'picture', 'list', 'quote', 'code', 'twitter', 'instagram', 'smile']; + settings.tools = settings.tools || this.allTools; + this.settings = settings; - /** Some configurations */ - this.BUTTONS_TOGGLED_CLASSNANE = 'buttons_toggled'; - this.key = { TAB: 9, ENTER: 13, BACKSPACE: 8, DELETE: 46, DOWN: 40, SPACE: 32, ESC: 27, CTRL: 17, META: 91, SHIFT: 16, ALT: 18 }; /** Making a wrapper and interface */ this.makeInterface(); @@ -27,43 +28,50 @@ var ce = function(textareaId) { /** Bind all events */ this.bindEvents(); -} +}; + +// All posible tools +ce.prototype.allTools = ['header', 'picture', 'list', 'quote', 'code', 'twitter', 'instagram', 'smile']; + +// Default settings configuration +ce.prototype.defaultSettings = { + +}; + +// Add this class when open tool bar for css animation +ce.prototype.BUTTONS_TOGGLED_CLASSNANE = 'buttons_toggled'; + +// Default tool bar is closed +ce.prototype.toolbarOpened = false; + +// Key event constants +ce.prototype.key = { TAB: 9, ENTER: 13, BACKSPACE: 8, DELETE: 46, DOWN: 40, SPACE: 32, ESC: 27, CTRL: 17, META: 91, SHIFT: 16, ALT: 18 }; /** -* Editor interface drawing -* @use this.tools to get necessary items -* @todo get tools from user inital-settings + * Editor interface drawing + * calls one time in editor constructor */ ce.prototype.makeInterface = function () { var wrapper = this.make.editorWrapper(), - firstNode = this.make.node(null, 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Porro quia nihil repellendus aut cupiditate reprehenderit sapiente magnam nobis doloremque eaque! Sint nobis assumenda nisi ducimus minima illo tenetur, cumque facilis.' ), - toolbar = this.make.toolbar(), - button; + firstNode = this.make.textNode('Lorem ipsum dolor sit amet, consectetur adipisicing elit. Porro quia nihil repellendus aut cupiditate reprehenderit sapiente magnam nobis doloremque eaque! Sint nobis assumenda nisi ducimus minima illo tenetur, cumque facilis.' ), + toolbar = this.make.toolbar(); - for (var i = 0; i < this.tools.length; i++) { - button = this.make.toolbarButton(this.tools[i]); - toolbar.appendChild(button); - }; + this.wrapper = wrapper; + this.toolbar = toolbar; - /** - * Add toolbar to node - * @todo make toolbar rendering once - */ - firstNode.appendChild(toolbar); + this.toolbarButtons = this.make.toolbarButtons(this.allTools, this.settings.tools); - /** Add first node */ + /** Add first node and tool bar*/ wrapper.appendChild(firstNode); + wrapper.appendChild(toolbar); /** Insert Editor after initial textarea. Hide textarea */ this.resultTextarea.parentNode.insertBefore(wrapper, this.resultTextarea.nextSibling); this.resultTextarea.hidden = true; - /** Set auto focus */ - var contentEditable = firstNode.getElementsByClassName('ce_node_content'); - contentEditable.length && contentEditable[0].focus(); - -} + this.focusNode(firstNode); +}; /** * All events binds in one place @@ -77,7 +85,18 @@ ce.prototype.bindEvents = function () { _this.globalKeydownCallback(event); }, false ); -} +}; + +/** + * Sets focus to node conteneditable child + * todo depending on node type +*/ +ce.prototype.focusNode = function (node) { + + var contentEditable = node.getElementsByClassName('ce_node_content'); + contentEditable.length && contentEditable[0].focus(); + +}; /** * All window keydowns handles here @@ -89,40 +108,69 @@ ce.prototype.globalKeydownCallback = function (event) { case this.key.ENTER : this.enterKeyPressed(event); break; // Enter } -} +}; /** -* @todo: check if currently focused in contenteditable element +* */ ce.prototype.tabKeyPressed = function(event) { - var toolbar = document.getElementsByClassName('add_buttons'); + // check if currently focused in contenteditable element + if ("BODY" == event.target.tagName) return; - if ( !toolbar[0].className.includes(this.BUTTONS_TOGGLED_CLASSNANE) ){ - toolbar[0].className += ' ' + this.BUTTONS_TOGGLED_CLASSNANE; - this.toolbarOpened = true; - } else { - toolbar[0].className = toolbar[0].className.replace(this.BUTTONS_TOGGLED_CLASSNANE, ''); - this.toolbarOpened = false - } + var toolbar = event.target.parentNode.nextSibling, + _this = this; + + toolbar.appendChild(this.toolbarButtons); + + // repair buttons animation - just add css class async + setTimeout(function () { + + if ( !toolbar.className.includes(_this.BUTTONS_TOGGLED_CLASSNANE) ){ + toolbar.className += ' ' + _this.BUTTONS_TOGGLED_CLASSNANE; + _this.toolbarOpened = true; + } else { + toolbar.className = toolbar.className.replace(_this.BUTTONS_TOGGLED_CLASSNANE, ''); + _this.toolbarOpened = false + } + + }); event.preventDefault(); -} +}; /** * Handle Enter key. Adds new Node; */ ce.prototype.enterKeyPressed = function(event) { - console.log('ENTER'); + if (event.shiftKey){ + document.execCommand('insertHTML', false, '

'); + } else { + var newNode = this.make.textNode(), + toolbar = this.make.toolbar(); + + /** Add node */ + this.wrapper.insertBefore(newNode, event.target.parentNode.nextSibling); + + /** Add toolbar to node */ + this.wrapper.insertBefore(toolbar, newNode); -} + /** Set auto focus */ + var contentEditable = newNode.getElementsByClassName('ce_node_content'); + contentEditable.length && contentEditable[0].focus(); + } + + event.preventDefault(); +}; /** * Creates HTML elements */ -ce.prototype.make = function (window) { +ce.prototype.make = function () { + + var _this = this; /** Empty toolbar with toggler */ function toolbar () { @@ -133,12 +181,13 @@ ce.prototype.make = function (window) { /** Toggler button*/ bar.innerHTML = '' + - ''+ + ''+ ''; return bar; } + // Creates one button with given type function toolbarButton (type) { var button = document.createElement('button'); @@ -147,13 +196,33 @@ ce.prototype.make = function (window) { button.innerHTML = ''; return button; + + } + + // Creates all tool bar buttons from editor settings + // allTools, usedTools - needs becose cant get them from editor object - bad context + function toolbarButtons (allTools, usedTools) { + + var toolbarButtons = document.createElement("span"); + + toolbarButtons.classList.add("buttons"); + + // Walk base buttons list - save buttons origin sorting + allTools.forEach(function(item) { + + if (usedTools.indexOf(item) >= 0) toolbarButtons.appendChild( this.toolbarButton(item) ); + + }, this); + + return toolbarButtons; + } /** * Paragraph node * @todo set unique id with prefix */ - function node (id, content){ + function textNode (content){ var node = document.createElement('div'); @@ -173,15 +242,16 @@ ce.prototype.make = function (window) { } var ceMake = function () { - this.toolbar = toolbar; - this.toolbarButton = toolbarButton; - this.node = node; - this.editorWrapper = editorWrapper; - } + this.toolbar = toolbar; + this.toolbarButtons = toolbarButtons; + this.toolbarButton = toolbarButton; + this.textNode = textNode; + this.editorWrapper = editorWrapper; + }; return new ceMake(); -}(this) +}(); diff --git a/editor.css b/editor.css index 7357e71d0..b03455c9a 100644 --- a/editor.css +++ b/editor.css @@ -1,34 +1,34 @@ @font-face { - font-family: 'codex_editor'; - src: url('fonts/codex_editor/codex_editor.eot?52438661'); - src: url('fonts/codex_editor/codex_editor.eot?52438661#iefix') format('embedded-opentype'), - url('fonts/codex_editor/codex_editor.woff?52438661') format('woff'), - url('fonts/codex_editor/codex_editor.ttf?52438661') format('truetype'), - url('fonts/codex_editor/codex_editor.svg?52438661#codex_editor') format('svg'); - font-weight: normal; - font-style: normal; + font-family: 'codex_editor'; + src: url('fonts/codex_editor/codex_editor.eot?52438661'); + src: url('fonts/codex_editor/codex_editor.eot?52438661#iefix') format('embedded-opentype'), + url('fonts/codex_editor/codex_editor.woff?52438661') format('woff'), + url('fonts/codex_editor/codex_editor.ttf?52438661') format('truetype'), + url('fonts/codex_editor/codex_editor.svg?52438661#codex_editor') format('svg'); + font-weight: normal; + font-style: normal; } [class^="ce_icon-"]:before, [class*="ce_icon-"]:before { - font-family: "codex_editor"; - font-style: normal; - font-weight: normal; - speak: none; - - display: inline-block; - text-decoration: inherit; - width: 1em; - margin-right: .2em; - text-align: center; - font-variant: normal; - text-transform: none; - - line-height: 1em; - - /* Animation center compensation - margins should be symmetric */ - margin-left: .2em; - - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; + font-family: "codex_editor"; + font-style: normal; + font-weight: normal; + speak: none; + + display: inline-block; + text-decoration: inherit; + width: 1em; + margin-right: .2em; + text-align: center; + font-variant: normal; + text-transform: none; + + line-height: 1em; + + /* Animation center compensation - margins should be symmetric */ + margin-left: .2em; + + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; } .ce_icon-instagram:before { content: '\e800'; } /* '' */ @@ -84,172 +84,59 @@ .codex_editor .node{ position: relative; + z-index: 5; } .codex_editor .add_buttons{ - position: relative; color: #3b4352; font-size: 16px; + margin-left: -42px; + margin-top: -50px; + margin-bottom: -25px; + position: relative; } - .codex_editor .add_buttons button:hover, - .codex_editor .add_buttons .focused{ - color: #3770ef; - } - .codex_editor .add_buttons button{ - transition: all 150ms ease-in; - transform: translate3d(-50px, 0 , 0); - opacity: 0; - font-size: 14px; - /*display: none;*/ - } - .codex_editor .buttons_toggled{ - background: #fff; - } - .codex_editor .buttons_toggled button{ - opacity: 1; - transform: translate3d(0,0,0); - } - -.codex_editor .toggler{ +.add_buttons .buttons { position: absolute; - left: -42px; - display: inline-block; - font-size: 23px; - color: #387ff5; - transition: transform 100ms ease-in; -} - .codex_editor .buttons_toggled .toggler{ - transform: rotate(45deg); - } - - - - -/** Typography styles */ -.codex_editor p{ - margin: 30px 0; - font-size: 17px; -} - - - - - -/* -.editor_content {} -.editor_content label {display:block;margin-bottom:10px;} -.editor_content input[type=file]{} -.editor_content textarea{} -*/ -/* -.editor_content button#btn_save{ - padding: 5px 15px; - float: right; + top: 3px; } -.editor_content .cover{ - border: 1px solid gray; - width: 96%; - display: block; - margin: 5px 0 15px 0; - padding: 2%; +.codex_editor .add_buttons button:hover, +.codex_editor .add_buttons .focused{ + color: #3770ef; } -.editor_content .cover img{max-width: 100%;margin: auto;display: block;} - -.editor_content .cover .actions { - text-align: center; +.codex_editor .add_buttons button{ + transition: all 150ms ease-in; + transform: translate3d(-50px, 0 , 0); + opacity: 0; + font-size: 14px; } -.editor_content .cover .actions a{ - margin: 0 10px; - border-bottom: 1px dashed; +.codex_editor .buttons_toggled{ + background: #fff; + z-index: 10; } -.editor_content .cover .actions a:hover{ - text-decoration:none; +.codex_editor .buttons_toggled button{ + opacity: 1; + transform: translate3d(0,0,0); } -.editor_content .actions span{ - - color: #6091c8; - - margin-right: 15px; - border-bottom: 1px dashed; - - cursor: pointer; +.codex_editor .toggler{ + display: inline-block; + font-size: 23px; + color: #387ff5; + transition: transform 100ms ease-in; } - -.editor_content .add_buttons{ - width: 300px; - margin: 21px auto; - padding: 10px 0; - text-align: center; - background: #F2F2F6; +.codex_editor .toggler .buttons { position: relative; + top: -2px; } -.editor_content .add_buttons:before{ - content: ""; - background: no-repeat url(/public/img/editor_buttons.png) -135px 0px; - position: absolute; - padding: 10px; - left: 140px; - top: 17px; -} -.editor_content .add_buttons:hover:before{background-image: none;} -.editor_content .add_buttons:hover button{ - visibility: visible; - z-index: 0; -} -.editor_content .add_buttons button { - float: none; - padding: 5px; - margin: 0px 0px; - width: 35px; - height: 35px; - border: none; - position: relative; - visibility: hidden; - z-index: -1; - background: transparent; -} -.editor_content .add_buttons button:before { - content: ""; - background: no-repeat url(/public/img/editor_buttons.png?) 0; - position: absolute; - width: 20px; - height: 20px; - left: 8px; - top: 8px; -} -.editor_content .add_buttons .paragraph:before{ - background-position: -156px -1px; -} -.editor_content .add_buttons .img:before{ - background-position: -27px 0; - width: 22px; - left: 7px; -} -.editor_content .add_buttons .list:before{ - background-position: -56px 0; - width: 21px; -} -.editor_content .node{ - border: 1px dashed; - padding: 5px; - margin: 20px 0; -} -.editor_content .node .content{} -.editor_content .node .content p{min-height: 25px;} -.editor_content .node .action_buttons{ - border-top: 1px dashed; - text-align: right; - padding: 5px 0 0; -} -.editor_content .node .action_buttons button{ - width: 35px; - height: 35px; +.codex_editor .buttons_toggled .toggler{ + transform: rotate(45deg); } -.editor_wrapper #html_result { - height: 350px; -}*/ \ No newline at end of file +/** Typography styles */ +.codex_editor p{ + margin: 30px 0; + font-size: 17px; +} \ No newline at end of file diff --git a/example.html b/example.html index 6b81a21f0..3e57bf74c 100644 --- a/example.html +++ b/example.html @@ -12,7 +12,7 @@

CodeX Editor

- +
@@ -48,14 +48,18 @@

CodeX Editor

- +