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)
*/
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 ){
console.warn('Textarea not found with ID %o', textareaId);
console.warn('Textarea not found with ID %o', this.textareaId);
return this;
}
this.toolbarOpened = false;
this.tools = ['header', 'picture', 'list', 'quote', 'code', 'twitter', 'instagram', 'smile'];
// prepare settings
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 */
this.toolbarOpened = false;
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 };
@ -27,34 +46,43 @@ var ce = function(textareaId) {
/** Bind all events */
this.bindEvents();
}
};
/**
* Editor interface drawing
* @use this.tools to get necessary items
* @todo get tools from user inital-settings
*/
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.' ),
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(),
button;
button,
tool;
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;
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 */
wrapper.appendChild(firstNode);
/** Add toolbar to node */
wrapper.appendChild(toolbar);
/** Insert Editor after initial textarea. Hide textarea */
this.resultTextarea.parentNode.insertBefore(wrapper, this.resultTextarea.nextSibling);
this.resultTextarea.hidden = true;
@ -63,7 +91,7 @@ ce.prototype.makeInterface = function () {
var contentEditable = firstNode.getElementsByClassName('ce_node_content');
contentEditable.length && contentEditable[0].focus();
}
};
/**
* All events binds in one place
@ -77,7 +105,7 @@ ce.prototype.bindEvents = function () {
_this.globalKeydownCallback(event);
}, false );
}
};
/**
* All window keydowns handles here
@ -89,40 +117,70 @@ 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
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();
}
};
/**
* Handle Enter key. Adds new Node;
*/
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
*/
ce.prototype.make = function (window) {
ce.prototype.make = function () {
/** Empty toolbar with toggler */
function toolbar () {
@ -133,7 +191,7 @@ ce.prototype.make = function (window) {
/** Toggler button*/
bar.innerHTML = '<span class="toggler">' +
'<i class="ce_icon-plus-circled-1"></i>'+
'<i class="plus_btn ce_icon-plus-circled-1"></i>'+
'</span>';
return bar;
@ -153,7 +211,7 @@ ce.prototype.make = function (window) {
* Paragraph node
* @todo set unique id with prefix
*/
function node (id, content){
function textNode (content){
var node = document.createElement('div');
@ -175,13 +233,13 @@ ce.prototype.make = function (window) {
var ceMake = function () {
this.toolbar = toolbar;
this.toolbarButton = toolbarButton;
this.node = node;
this.textNode = textNode;
this.editorWrapper = editorWrapper;
}
};
return new ceMake();
}(this)
}();

View file

@ -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;
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;
display: inline-block;
text-decoration: inherit;
width: 1em;
margin-right: .2em;
text-align: center;
font-variant: normal;
text-transform: none;
line-height: 1em;
line-height: 1em;
/* Animation center compensation - margins should be symmetric */
margin-left: .2em;
/* Animation center compensation - margins should be symmetric */
margin-left: .2em;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
.ce_icon-instagram:before { content: '\e800'; } /* '' */
@ -87,41 +87,55 @@
}
.codex_editor .add_buttons{
position: relative;
/* position: relative; */
/* left: -42px; */
/* top: -30px; */
color: #3b4352;
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{
position: absolute;
left: -42px;
/* position: relative; */
/* left: -42px; */
display: inline-block;
font-size: 23px;
color: #387ff5;
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="">
<textarea name="" id="html_result" cols="30" rows="10"></textarea>
<textarea name="" id="codex_editor" cols="30" rows="10"></textarea>
</form>
@ -48,14 +48,18 @@
</body>
</html>
<script src="ce_interface.js?v=<?= filemtime("public/js/ce_interface.js") ?>"></script>
<script src="ce_interface.js"></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 */
ready(function() {
window.cEditor = new ce('html_result');
window.cEditor = new ce({
tools : ['header', 'picture']
});
})
</script>