contenteditable and rich text editing
The good (?)
The bad.
The ugly.
Why talk about this?
There were some interesting problems
You may have to dig into this code in the future?
How to use the rich text editor
Use the rich_text_editor helper:
<%= text_area 'post', 'text' %>
<%= rich_text_editor 'post' %>
(use sparingly, rich text is usually overkill)
Accessing the Javascript API:
$('#' + textarea_id).data('wysihtml5');
The bare minimum
Check it out:
Introducing wysihtml5
Surely someone has made this all easier?
Yes, they have.
Wysihtml5 basics
- Complete rich text editor with features and stuff
- Deals with browser stuff that hurts your brain
- Really cool markup sanitizing features (in theory)
Cool, we found an all-in-one solution!
...right?
WRONG.
Roadblock #1
From the list of things we need:
"Admins should be able to insert arbitrary HTML"
What wysihtml5 thinks:
"Screw it, let's just remove EVERYTHING."
( people on Github complain, maintainer is very hardheaded about it )
Solution #1
Modify wysihtml5 and make it optional
if(clean) {
// this is the original method for parsing elements
// if we want to use it, set "clean" to true (only done for cleaning up pasted stuff)
returnValue = this.config.parser(htmlOrElement, this.config.parserRules, this.composer.sandbox.getDocument(), this.config.cleanUp);
} else {
// just return it, don't bother cleaning anything up
returnValue = htmlOrElement;
}
Cool, now I can add marquee tags.
Roadblock #2
Rich text copy/paste
Users often copy and paste text from all kinds of sources.
Contenteditable areas will accept rich text.
Not a big issue, right?
Example of what Word throws in your clipboard:
The Paste event
You can intercept pasting! Neat.
Chrome and Firefox allow access to the clipboard:
elem.onpaste = function(event) {
var html = event.clipboardData.getData('html');
var text = event.clipboardData.getData('text');
};
Caveats
- Does not work in any version of IE
- Chrome will remove newlines when requesting text version
That won't work. What now?
- Intercept onpaste event
- Grab contents of editor
- Wrap current selection in temporary tag (hack)
- Clear editor
- setTimeout
- (by the time this fires contents of editor are only pasted text)
- Store pasted text
- Restore contents of editor and cursor position
- Sanitize pasted text
- Set innerHTML of temporary element to pasted text
- Remove temporary element...
WHEW.
What took so long?
Feature Creep
It's really tempting to keep adding stuff.
Drawing the line is really tough.
(there's no one-size-fits all solution to this problem)
Infinite possibilities
The editor provides users with a million ways to interact.
More interactions = more potential bugs.
More bugs = delayed release :(
Once again, where do you draw the line?
What bugs are critical?
Prioritization is hard.
Use the source, Luke
Don't be afraid to dig into library source code!
Poking around the surface may seem easier,
but it may cost you time in the long-run.
Avoid adding minified versions of libraries
(the asset pipeline exists for a reason)
Shout out
Thank you to the whole QA team for helping me!
The testing sessions were invaluable.
Related links
wysihtml5
http://xing.github.io/wysihtml5/
Bootstrap-wysihtml5
http://jhollingworth.github.io/bootstrap-wysihtml5/
contenteditable
https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_Editable
contenteditable
By Eric Wood
contenteditable
- 685