add new paragrath by pressing enter key

add new line by pressing shift + enter key
add editor settings
make add buttons by one instance and move it through DOM
some css changes
This commit is contained in:
Mark Dermanov 2015-12-09 03:34:32 +03:00
parent 3b57d72c4d
commit cda692edec
3 changed files with 168 additions and 92 deletions

View file

@ -3,21 +3,40 @@
* @author Savchenko Peter (vk.com/specc) * @author Savchenko Peter (vk.com/specc)
*/ */
var ce = function(textareaId) { var ce = function(settings) {
this.resultTextarea = document.getElementById(textareaId); this.textareaId = "codex_editor";
this.resultTextarea = document.getElementById(this.textareaId);
if (typeof this.resultTextarea == undefined || this.resultTextarea == null ){ 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; return this;
} }
this.toolbarOpened = false; // prepare settings
this.tools = ['header', 'picture', 'list', 'quote', 'code', 'twitter', 'instagram', 'smile']; this.allTools = ['header', 'picture', 'list', 'quote', 'code', 'twitter', 'instagram', 'smile'];
var defaultSettings = {
};
if ("undefined" == typeof settings || "object" != typeof settings)
settings = defaultSettings;
else {
// todo just merge settings with defaults
}
if ("undefined" == typeof settings.tools || !Array.isArray(settings.tools))
settings.tools = this.allTools;
this.settings = settings;
/** Some configurations */ /** Some configurations */
this.toolbarOpened = false;
this.BUTTONS_TOGGLED_CLASSNANE = 'buttons_toggled'; 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 }; this.key = { TAB: 9, ENTER: 13, BACKSPACE: 8, DELETE: 46, DOWN: 40, SPACE: 32, ESC: 27, CTRL: 17, META: 91, SHIFT: 16, ALT: 18 };
@ -27,34 +46,43 @@ var ce = function(textareaId) {
/** Bind all events */ /** Bind all events */
this.bindEvents(); this.bindEvents();
} };
/** /**
* Editor interface drawing * Editor interface drawing
* @use this.tools to get necessary items
* @todo get tools from user inital-settings
*/ */
ce.prototype.makeInterface = function () { ce.prototype.makeInterface = function () {
var wrapper = this.make.editorWrapper(), 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.' ), 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(), toolbar = this.make.toolbar(),
button; button,
tool;
for (var i = 0; i < this.tools.length; i++) { this.wrapper = wrapper;
button = this.make.toolbarButton(this.tools[i]); this.toolbar = toolbar;
toolbar.appendChild(button);
}; this.toolbarButtons = document.createElement("span");
this.toolbarButtons.classList.add("buttons");
// îáõîäèì áàçîâûé ñïèñîê, ÷òîáû ñîõðàíèòü îðèãèíàëüíóþ ïîñëåäîâàòåëüíîñòü êíîïîê
for (var i = 0; i < this.allTools.length; i++) {
tool = this.allTools[i];
if (this.settings.tools.indexOf(tool) < 0)
continue;
button = this.make.toolbarButton(tool);
this.toolbarButtons.appendChild(button);
}
/**
* Add toolbar to node
* @todo make toolbar rendering once
*/
firstNode.appendChild(toolbar);
/** Add first node */ /** Add first node */
wrapper.appendChild(firstNode); wrapper.appendChild(firstNode);
/** Add toolbar to node */
wrapper.appendChild(toolbar);
/** Insert Editor after initial textarea. Hide textarea */ /** Insert Editor after initial textarea. Hide textarea */
this.resultTextarea.parentNode.insertBefore(wrapper, this.resultTextarea.nextSibling); this.resultTextarea.parentNode.insertBefore(wrapper, this.resultTextarea.nextSibling);
this.resultTextarea.hidden = true; this.resultTextarea.hidden = true;
@ -63,7 +91,7 @@ ce.prototype.makeInterface = function () {
var contentEditable = firstNode.getElementsByClassName('ce_node_content'); var contentEditable = firstNode.getElementsByClassName('ce_node_content');
contentEditable.length && contentEditable[0].focus(); contentEditable.length && contentEditable[0].focus();
} };
/** /**
* All events binds in one place * All events binds in one place
@ -77,7 +105,7 @@ ce.prototype.bindEvents = function () {
_this.globalKeydownCallback(event); _this.globalKeydownCallback(event);
}, false ); }, false );
} };
/** /**
* All window keydowns handles here * All window keydowns handles here
@ -89,40 +117,70 @@ ce.prototype.globalKeydownCallback = function (event) {
case this.key.ENTER : this.enterKeyPressed(event); break; // Enter case this.key.ENTER : this.enterKeyPressed(event); break; // Enter
} }
} };
/** /**
* @todo: check if currently focused in contenteditable element *
*/ */
ce.prototype.tabKeyPressed = function(event) { 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) ){ var toolbar = event.target.parentNode.nextSibling,
toolbar[0].className += ' ' + this.BUTTONS_TOGGLED_CLASSNANE; _this = this;
this.toolbarOpened = true;
} else { toolbar.appendChild(this.toolbarButtons);
toolbar[0].className = toolbar[0].className.replace(this.BUTTONS_TOGGLED_CLASSNANE, '');
this.toolbarOpened = false // repair buttons animation
} 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
}
}, 10);
event.preventDefault(); event.preventDefault();
} };
/** /**
* Handle Enter key. Adds new Node; * Handle Enter key. Adds new Node;
*/ */
ce.prototype.enterKeyPressed = function(event) { ce.prototype.enterKeyPressed = function(event) {
console.log('ENTER'); if (event.shiftKey){
document.execCommand('insertHTML', false, '<br><br>');
} 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 * Creates HTML elements
*/ */
ce.prototype.make = function (window) { ce.prototype.make = function () {
/** Empty toolbar with toggler */ /** Empty toolbar with toggler */
function toolbar () { function toolbar () {
@ -133,7 +191,7 @@ ce.prototype.make = function (window) {
/** Toggler button*/ /** Toggler button*/
bar.innerHTML = '<span class="toggler">' + bar.innerHTML = '<span class="toggler">' +
'<i class="ce_icon-plus-circled-1"></i>'+ '<i class="plus_btn ce_icon-plus-circled-1"></i>'+
'</span>'; '</span>';
return bar; return bar;
@ -153,7 +211,7 @@ ce.prototype.make = function (window) {
* Paragraph node * Paragraph node
* @todo set unique id with prefix * @todo set unique id with prefix
*/ */
function node (id, content){ function textNode (content){
var node = document.createElement('div'); var node = document.createElement('div');
@ -175,13 +233,13 @@ ce.prototype.make = function (window) {
var ceMake = function () { var ceMake = function () {
this.toolbar = toolbar; this.toolbar = toolbar;
this.toolbarButton = toolbarButton; this.toolbarButton = toolbarButton;
this.node = node; this.textNode = textNode;
this.editorWrapper = editorWrapper; this.editorWrapper = editorWrapper;
} };
return new ceMake(); return new ceMake();
}(this) }();

View file

@ -1,34 +1,34 @@
@font-face { @font-face {
font-family: 'codex_editor'; font-family: 'codex_editor';
src: url('fonts/codex_editor/codex_editor.eot?52438661'); src: url('fonts/codex_editor/codex_editor.eot?52438661');
src: url('fonts/codex_editor/codex_editor.eot?52438661#iefix') format('embedded-opentype'), 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.woff?52438661') format('woff'),
url('fonts/codex_editor/codex_editor.ttf?52438661') format('truetype'), url('fonts/codex_editor/codex_editor.ttf?52438661') format('truetype'),
url('fonts/codex_editor/codex_editor.svg?52438661#codex_editor') format('svg'); url('fonts/codex_editor/codex_editor.svg?52438661#codex_editor') format('svg');
font-weight: normal; font-weight: normal;
font-style: normal; font-style: normal;
} }
[class^="ce_icon-"]:before, [class*="ce_icon-"]:before { [class^="ce_icon-"]:before, [class*="ce_icon-"]:before {
font-family: "codex_editor"; font-family: "codex_editor";
font-style: normal; font-style: normal;
font-weight: normal; font-weight: normal;
speak: none; speak: none;
display: inline-block; display: inline-block;
text-decoration: inherit; text-decoration: inherit;
width: 1em; width: 1em;
margin-right: .2em; margin-right: .2em;
text-align: center; text-align: center;
font-variant: normal; font-variant: normal;
text-transform: none; text-transform: none;
line-height: 1em; line-height: 1em;
/* Animation center compensation - margins should be symmetric */ /* Animation center compensation - margins should be symmetric */
margin-left: .2em; margin-left: .2em;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.ce_icon-instagram:before { content: '\e800'; } /* '' */ .ce_icon-instagram:before { content: '\e800'; } /* '' */
@ -87,41 +87,55 @@
} }
.codex_editor .add_buttons{ .codex_editor .add_buttons{
position: relative; /* position: relative; */
/* left: -42px; */
/* top: -30px; */
color: #3b4352; color: #3b4352;
font-size: 16px; font-size: 16px;
margin-left: -42px;
margin-top: -20px;
margin-bottom: -25px;
}
.add_buttons .buttons {
position: absolute;
}
.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 .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{ .codex_editor .toggler{
position: absolute; /* position: relative; */
left: -42px; /* left: -42px; */
display: inline-block; display: inline-block;
font-size: 23px; font-size: 23px;
color: #387ff5; color: #387ff5;
transition: transform 100ms ease-in; transition: transform 100ms ease-in;
} }
.codex_editor .buttons_toggled .toggler{
transform: rotate(45deg); .codex_editor .toggler .buttons {
} position: relative;
top: -2px;
}
.codex_editor .buttons_toggled .plus_btn{
transform: rotate(45deg);
}

View file

@ -12,7 +12,7 @@
<form action=""> <form action="">
<textarea name="" id="html_result" cols="30" rows="10"></textarea> <textarea name="" id="codex_editor" cols="30" rows="10"></textarea>
</form> </form>
@ -48,14 +48,18 @@
</body> </body>
</html> </html>
<script src="ce_interface.js?v=<?= filemtime("public/js/ce_interface.js") ?>"></script> <script src="ce_interface.js"></script>
<script> <script>
function ready(f){/in/.test(document.readyState) ? setTimeout(ready,9,f) : f();} function ready(f){
/in/.test(document.readyState) ? setTimeout(ready,9,f) : f();
}
/** Document is ready */ /** Document is ready */
ready(function() { ready(function() {
window.cEditor = new ce('html_result'); window.cEditor = new ce({
tools : ['header', 'picture']
});
}) })
</script> </script>