Vanilla JS rich text editor, extremely small

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
7
down vote

favorite
3












A few days ago, I created this rich text editor, and posted it to reddit and got over 300 upvotes in less than 1 day. I am a beginner, so I don't believe that this project is very complex, but with your help I can improve it, and maybe someone will use this.



I put a lot of work into this and I just want it to get better. If you can help in any way I would appreciate it.



Live demo: https://panagram.herokuapp.com/



GitHub: https://github.com/Stoick001/Panagram.js



Editor:



import controlsPremade from './config';

const execute = (el, command, val) =>
if (el && !command.includes('List'))
el.classList.toggle('active');

document.execCommand(command, false, val ? val: null);


export const init = (settings) =>
const controls = controlsPremade[settings.controls];
const ctrElement = settings.ctrElement;
const outElement = settings.outElement;

outElement.contentEditable = true;
outElement.classList.add('output-el');

['click', 'touch'].forEach((evn) =>
ctrElement.addEventListener(evn, (e) =>
outElement.focus();
);
);

outElement.addEventListener('keydown', event => );

controls.forEach(control =>
const button = document.createElement('button');
button.innerHTML = control.icon;
button.title = control.title;
button.setAttribute('type', 'button');
button.classList.add('ctrl-btn');

if (control.short)
document.addEventListener('keydown', (event) =>
if (event.ctrlKey && event.key.toLowerCase() === control.short)
button.classList.toggle('active');

)


['click', 'touch'].forEach((evn) =>
if (control.state)
button.addEventListener(evn, () => execute(button, control.comName));
['keyup', 'mouseup'].forEach(cnt =>
outElement.addEventListener(cnt, (e) =>
if (document.queryCommandState(control.comName) && !control.comName.includes('List'))
button.classList.add('active');
else if (button.classList.contains('active'))
button.classList.remove('active');

);
);
else if (control.formatBlock)
button.addEventListener(evn, () => execute(null, control.formatBlock, control.comName));
else
button.addEventListener(evn, () =>
const val = (control.extra)();
if (val)
execute(null, control.comName, val);

);

);

ctrElement.append(button);
);



Config file:



export default 
defaultControls: [

icon: '<b>B</b>', //fixed matching in tag surrounding icon text.
title: 'Bold',
comName: 'bold',
state: true,
short: 'b',
,
icon: '<i>I</i>',
title: 'Italic',
comName: 'italic',
state: true,
short: 'i',
,
icon: '<u>U</u>',
title: 'Underline',
comName: 'underline',
state: true,
short: 'u',
,
icon: '<b>H<sub>1</sub></b>',
title: 'Heading 1',
comName: '<h1>',
formatBlock: 'formatBlock'
,
icon: '<b>H<sub>2</sub></b>',
title: 'Heading 2',
comName: '<h2>',
formatBlock: 'formatBlock'
,
icon: 'P',
title: 'Paragraph',
comName: '<p>',
formatBlock: 'formatBlock'
,
icon: '“ ”',
title: 'Quote',
comName: '<blockquote>',
formatBlock: 'formatBlock'
,
icon: '#',
title: 'Ordered List',
comName: 'insertOrderedList',
state: true,
,
icon: '•',
title: 'Unordered List',
comName: 'insertUnorderedList',
state: true,
,
icon: '🔗',
title: 'Link',
comName: 'createLink',
extra: () => window.prompt('Enter the link URL'),
,
icon: '📷',
title: 'Image',
comName: 'insertImage',
extra: () => window.prompt('Enter the link URL'),
,
]



EDIT: All code is now up to date.







share|improve this question

















  • 1




    I was tempted to rollback version 4... but it doesn't look like anything changed that could have invalidated the existing answer. Please do not update the code in your question once you have received answers- doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers.
    – Sam Onela
    Apr 7 at 23:44










  • OK, sorry. Didn't know that. Thanks :)
    – Stoik
    Apr 8 at 7:27
















up vote
7
down vote

favorite
3












A few days ago, I created this rich text editor, and posted it to reddit and got over 300 upvotes in less than 1 day. I am a beginner, so I don't believe that this project is very complex, but with your help I can improve it, and maybe someone will use this.



I put a lot of work into this and I just want it to get better. If you can help in any way I would appreciate it.



Live demo: https://panagram.herokuapp.com/



GitHub: https://github.com/Stoick001/Panagram.js



Editor:



import controlsPremade from './config';

const execute = (el, command, val) =>
if (el && !command.includes('List'))
el.classList.toggle('active');

document.execCommand(command, false, val ? val: null);


export const init = (settings) =>
const controls = controlsPremade[settings.controls];
const ctrElement = settings.ctrElement;
const outElement = settings.outElement;

outElement.contentEditable = true;
outElement.classList.add('output-el');

['click', 'touch'].forEach((evn) =>
ctrElement.addEventListener(evn, (e) =>
outElement.focus();
);
);

outElement.addEventListener('keydown', event => );

controls.forEach(control =>
const button = document.createElement('button');
button.innerHTML = control.icon;
button.title = control.title;
button.setAttribute('type', 'button');
button.classList.add('ctrl-btn');

if (control.short)
document.addEventListener('keydown', (event) =>
if (event.ctrlKey && event.key.toLowerCase() === control.short)
button.classList.toggle('active');

)


['click', 'touch'].forEach((evn) =>
if (control.state)
button.addEventListener(evn, () => execute(button, control.comName));
['keyup', 'mouseup'].forEach(cnt =>
outElement.addEventListener(cnt, (e) =>
if (document.queryCommandState(control.comName) && !control.comName.includes('List'))
button.classList.add('active');
else if (button.classList.contains('active'))
button.classList.remove('active');

);
);
else if (control.formatBlock)
button.addEventListener(evn, () => execute(null, control.formatBlock, control.comName));
else
button.addEventListener(evn, () =>
const val = (control.extra)();
if (val)
execute(null, control.comName, val);

);

);

ctrElement.append(button);
);



Config file:



export default 
defaultControls: [

icon: '<b>B</b>', //fixed matching in tag surrounding icon text.
title: 'Bold',
comName: 'bold',
state: true,
short: 'b',
,
icon: '<i>I</i>',
title: 'Italic',
comName: 'italic',
state: true,
short: 'i',
,
icon: '<u>U</u>',
title: 'Underline',
comName: 'underline',
state: true,
short: 'u',
,
icon: '<b>H<sub>1</sub></b>',
title: 'Heading 1',
comName: '<h1>',
formatBlock: 'formatBlock'
,
icon: '<b>H<sub>2</sub></b>',
title: 'Heading 2',
comName: '<h2>',
formatBlock: 'formatBlock'
,
icon: 'P',
title: 'Paragraph',
comName: '<p>',
formatBlock: 'formatBlock'
,
icon: '“ ”',
title: 'Quote',
comName: '<blockquote>',
formatBlock: 'formatBlock'
,
icon: '#',
title: 'Ordered List',
comName: 'insertOrderedList',
state: true,
,
icon: '•',
title: 'Unordered List',
comName: 'insertUnorderedList',
state: true,
,
icon: '🔗',
title: 'Link',
comName: 'createLink',
extra: () => window.prompt('Enter the link URL'),
,
icon: '📷',
title: 'Image',
comName: 'insertImage',
extra: () => window.prompt('Enter the link URL'),
,
]



EDIT: All code is now up to date.







share|improve this question

















  • 1




    I was tempted to rollback version 4... but it doesn't look like anything changed that could have invalidated the existing answer. Please do not update the code in your question once you have received answers- doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers.
    – Sam Onela
    Apr 7 at 23:44










  • OK, sorry. Didn't know that. Thanks :)
    – Stoik
    Apr 8 at 7:27












up vote
7
down vote

favorite
3









up vote
7
down vote

favorite
3






3





A few days ago, I created this rich text editor, and posted it to reddit and got over 300 upvotes in less than 1 day. I am a beginner, so I don't believe that this project is very complex, but with your help I can improve it, and maybe someone will use this.



I put a lot of work into this and I just want it to get better. If you can help in any way I would appreciate it.



Live demo: https://panagram.herokuapp.com/



GitHub: https://github.com/Stoick001/Panagram.js



Editor:



import controlsPremade from './config';

const execute = (el, command, val) =>
if (el && !command.includes('List'))
el.classList.toggle('active');

document.execCommand(command, false, val ? val: null);


export const init = (settings) =>
const controls = controlsPremade[settings.controls];
const ctrElement = settings.ctrElement;
const outElement = settings.outElement;

outElement.contentEditable = true;
outElement.classList.add('output-el');

['click', 'touch'].forEach((evn) =>
ctrElement.addEventListener(evn, (e) =>
outElement.focus();
);
);

outElement.addEventListener('keydown', event => );

controls.forEach(control =>
const button = document.createElement('button');
button.innerHTML = control.icon;
button.title = control.title;
button.setAttribute('type', 'button');
button.classList.add('ctrl-btn');

if (control.short)
document.addEventListener('keydown', (event) =>
if (event.ctrlKey && event.key.toLowerCase() === control.short)
button.classList.toggle('active');

)


['click', 'touch'].forEach((evn) =>
if (control.state)
button.addEventListener(evn, () => execute(button, control.comName));
['keyup', 'mouseup'].forEach(cnt =>
outElement.addEventListener(cnt, (e) =>
if (document.queryCommandState(control.comName) && !control.comName.includes('List'))
button.classList.add('active');
else if (button.classList.contains('active'))
button.classList.remove('active');

);
);
else if (control.formatBlock)
button.addEventListener(evn, () => execute(null, control.formatBlock, control.comName));
else
button.addEventListener(evn, () =>
const val = (control.extra)();
if (val)
execute(null, control.comName, val);

);

);

ctrElement.append(button);
);



Config file:



export default 
defaultControls: [

icon: '<b>B</b>', //fixed matching in tag surrounding icon text.
title: 'Bold',
comName: 'bold',
state: true,
short: 'b',
,
icon: '<i>I</i>',
title: 'Italic',
comName: 'italic',
state: true,
short: 'i',
,
icon: '<u>U</u>',
title: 'Underline',
comName: 'underline',
state: true,
short: 'u',
,
icon: '<b>H<sub>1</sub></b>',
title: 'Heading 1',
comName: '<h1>',
formatBlock: 'formatBlock'
,
icon: '<b>H<sub>2</sub></b>',
title: 'Heading 2',
comName: '<h2>',
formatBlock: 'formatBlock'
,
icon: 'P',
title: 'Paragraph',
comName: '<p>',
formatBlock: 'formatBlock'
,
icon: '“ ”',
title: 'Quote',
comName: '<blockquote>',
formatBlock: 'formatBlock'
,
icon: '#',
title: 'Ordered List',
comName: 'insertOrderedList',
state: true,
,
icon: '•',
title: 'Unordered List',
comName: 'insertUnorderedList',
state: true,
,
icon: '🔗',
title: 'Link',
comName: 'createLink',
extra: () => window.prompt('Enter the link URL'),
,
icon: '📷',
title: 'Image',
comName: 'insertImage',
extra: () => window.prompt('Enter the link URL'),
,
]



EDIT: All code is now up to date.







share|improve this question













A few days ago, I created this rich text editor, and posted it to reddit and got over 300 upvotes in less than 1 day. I am a beginner, so I don't believe that this project is very complex, but with your help I can improve it, and maybe someone will use this.



I put a lot of work into this and I just want it to get better. If you can help in any way I would appreciate it.



Live demo: https://panagram.herokuapp.com/



GitHub: https://github.com/Stoick001/Panagram.js



Editor:



import controlsPremade from './config';

const execute = (el, command, val) =>
if (el && !command.includes('List'))
el.classList.toggle('active');

document.execCommand(command, false, val ? val: null);


export const init = (settings) =>
const controls = controlsPremade[settings.controls];
const ctrElement = settings.ctrElement;
const outElement = settings.outElement;

outElement.contentEditable = true;
outElement.classList.add('output-el');

['click', 'touch'].forEach((evn) =>
ctrElement.addEventListener(evn, (e) =>
outElement.focus();
);
);

outElement.addEventListener('keydown', event => );

controls.forEach(control =>
const button = document.createElement('button');
button.innerHTML = control.icon;
button.title = control.title;
button.setAttribute('type', 'button');
button.classList.add('ctrl-btn');

if (control.short)
document.addEventListener('keydown', (event) =>
if (event.ctrlKey && event.key.toLowerCase() === control.short)
button.classList.toggle('active');

)


['click', 'touch'].forEach((evn) =>
if (control.state)
button.addEventListener(evn, () => execute(button, control.comName));
['keyup', 'mouseup'].forEach(cnt =>
outElement.addEventListener(cnt, (e) =>
if (document.queryCommandState(control.comName) && !control.comName.includes('List'))
button.classList.add('active');
else if (button.classList.contains('active'))
button.classList.remove('active');

);
);
else if (control.formatBlock)
button.addEventListener(evn, () => execute(null, control.formatBlock, control.comName));
else
button.addEventListener(evn, () =>
const val = (control.extra)();
if (val)
execute(null, control.comName, val);

);

);

ctrElement.append(button);
);



Config file:



export default 
defaultControls: [

icon: '<b>B</b>', //fixed matching in tag surrounding icon text.
title: 'Bold',
comName: 'bold',
state: true,
short: 'b',
,
icon: '<i>I</i>',
title: 'Italic',
comName: 'italic',
state: true,
short: 'i',
,
icon: '<u>U</u>',
title: 'Underline',
comName: 'underline',
state: true,
short: 'u',
,
icon: '<b>H<sub>1</sub></b>',
title: 'Heading 1',
comName: '<h1>',
formatBlock: 'formatBlock'
,
icon: '<b>H<sub>2</sub></b>',
title: 'Heading 2',
comName: '<h2>',
formatBlock: 'formatBlock'
,
icon: 'P',
title: 'Paragraph',
comName: '<p>',
formatBlock: 'formatBlock'
,
icon: '“ ”',
title: 'Quote',
comName: '<blockquote>',
formatBlock: 'formatBlock'
,
icon: '#',
title: 'Ordered List',
comName: 'insertOrderedList',
state: true,
,
icon: '•',
title: 'Unordered List',
comName: 'insertUnorderedList',
state: true,
,
icon: '🔗',
title: 'Link',
comName: 'createLink',
extra: () => window.prompt('Enter the link URL'),
,
icon: '📷',
title: 'Image',
comName: 'insertImage',
extra: () => window.prompt('Enter the link URL'),
,
]



EDIT: All code is now up to date.









share|improve this question












share|improve this question




share|improve this question








edited Apr 7 at 23:46









Sam Onela

5,78461544




5,78461544









asked Apr 6 at 10:45









Stoik

365




365







  • 1




    I was tempted to rollback version 4... but it doesn't look like anything changed that could have invalidated the existing answer. Please do not update the code in your question once you have received answers- doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers.
    – Sam Onela
    Apr 7 at 23:44










  • OK, sorry. Didn't know that. Thanks :)
    – Stoik
    Apr 8 at 7:27












  • 1




    I was tempted to rollback version 4... but it doesn't look like anything changed that could have invalidated the existing answer. Please do not update the code in your question once you have received answers- doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers.
    – Sam Onela
    Apr 7 at 23:44










  • OK, sorry. Didn't know that. Thanks :)
    – Stoik
    Apr 8 at 7:27







1




1




I was tempted to rollback version 4... but it doesn't look like anything changed that could have invalidated the existing answer. Please do not update the code in your question once you have received answers- doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers.
– Sam Onela
Apr 7 at 23:44




I was tempted to rollback version 4... but it doesn't look like anything changed that could have invalidated the existing answer. Please do not update the code in your question once you have received answers- doing so goes against the Question + Answer style of Code Review. This is not a forum where you should keep the most updated version in your question. Please see what you may and may not do after receiving answers.
– Sam Onela
Apr 7 at 23:44












OK, sorry. Didn't know that. Thanks :)
– Stoik
Apr 8 at 7:27




OK, sorry. Didn't know that. Thanks :)
– Stoik
Apr 8 at 7:27










2 Answers
2






active

oldest

votes

















up vote
2
down vote













Vet style commands.



I would like to say "Great stuff!" as the code quality is good, but unfortunately it has some problems that make using document.execCommand function not as straight forward as it could be.



The problem is that it does not check if the formatting requested makes intuitive sense. This can badly messes up the document and make it near impossible to correct.



Examples



  • It is possible to have nested styles when the selection crosses over the start or end of an existing style. Then depending on the document layout trying to fix the problem with the UI just makes it worse.


  • When pasting from another html document, the pasted elements can have styles that negate the UI controllable styles, effectively blocking the ability to edit style via the buttons, in part or all of the document.


Vet



To fix these problems you need to look at the document content and remove unwanted formatting/styles. You need to check the selection before calling a command and not allow counter intuitive actions. You need to remove empty (thus invisible) tags as they will interfere with formatting and making editing counter intuitive.






share|improve this answer





















  • Hi, this code is out of the date, I have made a lot of changes so you can check them out on new links, I'll update the code soon. Edit: I have updated the code.
    – Stoik
    Apr 7 at 15:54


















up vote
1
down vote













I would suggest that whenever you create a lambda/anonymous function/closure to simply call one other function, use Function.bind() to create partially applied functions instead. That way, there will be one less function call in the stack.



So for instance:




['click', 'touch'].forEach((evn) => 
ctrElement.addEventListener(evn, (e) =>
outElement.focus();
);
);



Can be re-written as:



['click', 'touch'].forEach((evn) => 
ctrElement.addEventListener(evn, outElement.focus.bind(outElement));
);


And similarly,




setTimeout(() => 
execute(null, 'formatBlock', '<div>');
, 0);



Can be re-written as:



setTimeout(execute.bind(null, null, 'formatBlock', '<div>'), 0);


Bear in mind that for functions passed as the listener argument to EventTarget.addEventListener(), the first argument after any arguments bound via Function.bind() will be the Event reference.






share|improve this answer





















    Your Answer




    StackExchange.ifUsing("editor", function ()
    return StackExchange.using("mathjaxEditing", function ()
    StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
    StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
    );
    );
    , "mathjax-editing");

    StackExchange.ifUsing("editor", function ()
    StackExchange.using("externalEditor", function ()
    StackExchange.using("snippets", function ()
    StackExchange.snippets.init();
    );
    );
    , "code-snippets");

    StackExchange.ready(function()
    var channelOptions =
    tags: "".split(" "),
    id: "196"
    ;
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function()
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled)
    StackExchange.using("snippets", function()
    createEditor();
    );

    else
    createEditor();

    );

    function createEditor()
    StackExchange.prepareEditor(
    heartbeatType: 'answer',
    convertImagesToLinks: false,
    noModals: false,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: null,
    bindNavPrevention: true,
    postfix: "",
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    );



    );








     

    draft saved


    draft discarded


















    StackExchange.ready(
    function ()
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191399%2fvanilla-js-rich-text-editor-extremely-small%23new-answer', 'question_page');

    );

    Post as a guest






























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    up vote
    2
    down vote













    Vet style commands.



    I would like to say "Great stuff!" as the code quality is good, but unfortunately it has some problems that make using document.execCommand function not as straight forward as it could be.



    The problem is that it does not check if the formatting requested makes intuitive sense. This can badly messes up the document and make it near impossible to correct.



    Examples



    • It is possible to have nested styles when the selection crosses over the start or end of an existing style. Then depending on the document layout trying to fix the problem with the UI just makes it worse.


    • When pasting from another html document, the pasted elements can have styles that negate the UI controllable styles, effectively blocking the ability to edit style via the buttons, in part or all of the document.


    Vet



    To fix these problems you need to look at the document content and remove unwanted formatting/styles. You need to check the selection before calling a command and not allow counter intuitive actions. You need to remove empty (thus invisible) tags as they will interfere with formatting and making editing counter intuitive.






    share|improve this answer





















    • Hi, this code is out of the date, I have made a lot of changes so you can check them out on new links, I'll update the code soon. Edit: I have updated the code.
      – Stoik
      Apr 7 at 15:54















    up vote
    2
    down vote













    Vet style commands.



    I would like to say "Great stuff!" as the code quality is good, but unfortunately it has some problems that make using document.execCommand function not as straight forward as it could be.



    The problem is that it does not check if the formatting requested makes intuitive sense. This can badly messes up the document and make it near impossible to correct.



    Examples



    • It is possible to have nested styles when the selection crosses over the start or end of an existing style. Then depending on the document layout trying to fix the problem with the UI just makes it worse.


    • When pasting from another html document, the pasted elements can have styles that negate the UI controllable styles, effectively blocking the ability to edit style via the buttons, in part or all of the document.


    Vet



    To fix these problems you need to look at the document content and remove unwanted formatting/styles. You need to check the selection before calling a command and not allow counter intuitive actions. You need to remove empty (thus invisible) tags as they will interfere with formatting and making editing counter intuitive.






    share|improve this answer





















    • Hi, this code is out of the date, I have made a lot of changes so you can check them out on new links, I'll update the code soon. Edit: I have updated the code.
      – Stoik
      Apr 7 at 15:54













    up vote
    2
    down vote










    up vote
    2
    down vote









    Vet style commands.



    I would like to say "Great stuff!" as the code quality is good, but unfortunately it has some problems that make using document.execCommand function not as straight forward as it could be.



    The problem is that it does not check if the formatting requested makes intuitive sense. This can badly messes up the document and make it near impossible to correct.



    Examples



    • It is possible to have nested styles when the selection crosses over the start or end of an existing style. Then depending on the document layout trying to fix the problem with the UI just makes it worse.


    • When pasting from another html document, the pasted elements can have styles that negate the UI controllable styles, effectively blocking the ability to edit style via the buttons, in part or all of the document.


    Vet



    To fix these problems you need to look at the document content and remove unwanted formatting/styles. You need to check the selection before calling a command and not allow counter intuitive actions. You need to remove empty (thus invisible) tags as they will interfere with formatting and making editing counter intuitive.






    share|improve this answer













    Vet style commands.



    I would like to say "Great stuff!" as the code quality is good, but unfortunately it has some problems that make using document.execCommand function not as straight forward as it could be.



    The problem is that it does not check if the formatting requested makes intuitive sense. This can badly messes up the document and make it near impossible to correct.



    Examples



    • It is possible to have nested styles when the selection crosses over the start or end of an existing style. Then depending on the document layout trying to fix the problem with the UI just makes it worse.


    • When pasting from another html document, the pasted elements can have styles that negate the UI controllable styles, effectively blocking the ability to edit style via the buttons, in part or all of the document.


    Vet



    To fix these problems you need to look at the document content and remove unwanted formatting/styles. You need to check the selection before calling a command and not allow counter intuitive actions. You need to remove empty (thus invisible) tags as they will interfere with formatting and making editing counter intuitive.







    share|improve this answer













    share|improve this answer



    share|improve this answer











    answered Apr 7 at 12:29









    Blindman67

    5,3611320




    5,3611320











    • Hi, this code is out of the date, I have made a lot of changes so you can check them out on new links, I'll update the code soon. Edit: I have updated the code.
      – Stoik
      Apr 7 at 15:54

















    • Hi, this code is out of the date, I have made a lot of changes so you can check them out on new links, I'll update the code soon. Edit: I have updated the code.
      – Stoik
      Apr 7 at 15:54
















    Hi, this code is out of the date, I have made a lot of changes so you can check them out on new links, I'll update the code soon. Edit: I have updated the code.
    – Stoik
    Apr 7 at 15:54





    Hi, this code is out of the date, I have made a lot of changes so you can check them out on new links, I'll update the code soon. Edit: I have updated the code.
    – Stoik
    Apr 7 at 15:54













    up vote
    1
    down vote













    I would suggest that whenever you create a lambda/anonymous function/closure to simply call one other function, use Function.bind() to create partially applied functions instead. That way, there will be one less function call in the stack.



    So for instance:




    ['click', 'touch'].forEach((evn) => 
    ctrElement.addEventListener(evn, (e) =>
    outElement.focus();
    );
    );



    Can be re-written as:



    ['click', 'touch'].forEach((evn) => 
    ctrElement.addEventListener(evn, outElement.focus.bind(outElement));
    );


    And similarly,




    setTimeout(() => 
    execute(null, 'formatBlock', '<div>');
    , 0);



    Can be re-written as:



    setTimeout(execute.bind(null, null, 'formatBlock', '<div>'), 0);


    Bear in mind that for functions passed as the listener argument to EventTarget.addEventListener(), the first argument after any arguments bound via Function.bind() will be the Event reference.






    share|improve this answer

























      up vote
      1
      down vote













      I would suggest that whenever you create a lambda/anonymous function/closure to simply call one other function, use Function.bind() to create partially applied functions instead. That way, there will be one less function call in the stack.



      So for instance:




      ['click', 'touch'].forEach((evn) => 
      ctrElement.addEventListener(evn, (e) =>
      outElement.focus();
      );
      );



      Can be re-written as:



      ['click', 'touch'].forEach((evn) => 
      ctrElement.addEventListener(evn, outElement.focus.bind(outElement));
      );


      And similarly,




      setTimeout(() => 
      execute(null, 'formatBlock', '<div>');
      , 0);



      Can be re-written as:



      setTimeout(execute.bind(null, null, 'formatBlock', '<div>'), 0);


      Bear in mind that for functions passed as the listener argument to EventTarget.addEventListener(), the first argument after any arguments bound via Function.bind() will be the Event reference.






      share|improve this answer























        up vote
        1
        down vote










        up vote
        1
        down vote









        I would suggest that whenever you create a lambda/anonymous function/closure to simply call one other function, use Function.bind() to create partially applied functions instead. That way, there will be one less function call in the stack.



        So for instance:




        ['click', 'touch'].forEach((evn) => 
        ctrElement.addEventListener(evn, (e) =>
        outElement.focus();
        );
        );



        Can be re-written as:



        ['click', 'touch'].forEach((evn) => 
        ctrElement.addEventListener(evn, outElement.focus.bind(outElement));
        );


        And similarly,




        setTimeout(() => 
        execute(null, 'formatBlock', '<div>');
        , 0);



        Can be re-written as:



        setTimeout(execute.bind(null, null, 'formatBlock', '<div>'), 0);


        Bear in mind that for functions passed as the listener argument to EventTarget.addEventListener(), the first argument after any arguments bound via Function.bind() will be the Event reference.






        share|improve this answer













        I would suggest that whenever you create a lambda/anonymous function/closure to simply call one other function, use Function.bind() to create partially applied functions instead. That way, there will be one less function call in the stack.



        So for instance:




        ['click', 'touch'].forEach((evn) => 
        ctrElement.addEventListener(evn, (e) =>
        outElement.focus();
        );
        );



        Can be re-written as:



        ['click', 'touch'].forEach((evn) => 
        ctrElement.addEventListener(evn, outElement.focus.bind(outElement));
        );


        And similarly,




        setTimeout(() => 
        execute(null, 'formatBlock', '<div>');
        , 0);



        Can be re-written as:



        setTimeout(execute.bind(null, null, 'formatBlock', '<div>'), 0);


        Bear in mind that for functions passed as the listener argument to EventTarget.addEventListener(), the first argument after any arguments bound via Function.bind() will be the Event reference.







        share|improve this answer













        share|improve this answer



        share|improve this answer











        answered Apr 7 at 23:59









        Sam Onela

        5,78461544




        5,78461544






















             

            draft saved


            draft discarded


























             


            draft saved


            draft discarded














            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f191399%2fvanilla-js-rich-text-editor-extremely-small%23new-answer', 'question_page');

            );

            Post as a guest













































































            Popular posts from this blog

            Chat program with C++ and SFML

            Function to Return a JSON Like Objects Using VBA Collections and Arrays

            Will my employers contract hold up in court?