Vanilla JS rich text editor, extremely small
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
7
down vote
favorite
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.
javascript beginner html text-editor
add a comment |Â
up vote
7
down vote
favorite
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.
javascript beginner html text-editor
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
add a comment |Â
up vote
7
down vote
favorite
up vote
7
down vote
favorite
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.
javascript beginner html text-editor
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.
javascript beginner html text-editor
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
add a comment |Â
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
add a comment |Â
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.
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
add a comment |Â
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.
add a comment |Â
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.
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
add a comment |Â
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.
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
add a comment |Â
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.
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.
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
add a comment |Â
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
add a comment |Â
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.
add a comment |Â
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.
add a comment |Â
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.
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.
answered Apr 7 at 23:59
Sam Onela
5,78461544
5,78461544
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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