Skip to content
This repository has been archived by the owner on Apr 2, 2021. It is now read-only.

New lines inserted after header containers are broken in Chrome/Safari #360

Merged
merged 31 commits into from
Jul 30, 2013

Conversation

winhamwr
Copy link
Member

Steps to reproduce:

  1. Visit the demo page in Chrome 19 or Safari 5.1.7 - http://files.wymeditor.org/wymeditor/examples/01-basic.html
  2. Change the 'Hello World' paragraph container to any header container
  3. Place the cursor at the end of the 'Hello World' text and hit enter

Expected result: a new paragraph container is created below the header container. This occurs in Firefox.

Actual result: a plain div is created below the header container. This div container cannot be changed to any other type of container. The only way to fix this is to switch to HTML view and change the div to another standard container (ex. p or h1).

@winhamwr
Copy link
Member

Hi Dana,

Well shoot. I expect this is related to the fix for #352. This is when Selenium-style tests sure would be nice since it's pretty rough to try and simulate keystroke behavior in javascript.

It looks like we're going to need to go to a configuration option to allow folks to use div tags as their default block level elements.

Thanks so much for the bug report. We'll have to tackle this one for a beta 4.

-Wes

winhamwr added a commit that referenced this pull request Jul 11, 2012

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
winhamwr added a commit that referenced this pull request Jul 12, 2012
winhamwr added a commit that referenced this pull request Jul 12, 2012
Used the common.js package specification and the jquery plugins
manifest spec to create starting points for those files. They're
useful with grunt.js
@Bratzilla
Copy link

Is there a good workaround for this until a formal fix is provided? This is the ONLY "show-stopper" that's keeping me from deploying the editor, considering who my target audience is. ::cringes at mental image of emails from scared writers::

@winhamwr
Copy link
Member

Using the 1.0.0b1 release will fix this bug. It was a regression in the 1.0.0b2 release. You'll lose the bug fixes listed in the b2 changelog, but my guess is those aren't particularly useful fixes for your use cases. You probably don't have a lot of table/image insertion.

@Bratzilla
Copy link

In my case you're correct. There will be image insertion, but really only via hyperlink.

I'll keep pushing forward and testing.

Thanks for the quick response!

SIDE NOTE: This is also the EASIEST editor to theme that I've come across. Whatever you do, PLEASE keep it this simple. :)

@winhamwr
Copy link
Member

SIDE NOTE: This is also the EASIEST editor to theme that I've come across. Whatever you do, PLEASE keep it this simple.

That's great to hear. The documentation around creating new themes could definitely be improved, and there are definitely ways we could improve performance, but I also love that just copying a folder and going from there keeps the barrier to creating new skins very low.

@Bratzilla
Copy link

Um... could you please tell me how to download Version 1.0.0b1? I'm such a noob I can't find it. Thanks!

@winhamwr
Copy link
Member

All of the packaged versions of WYMeditor are available from the Downloads Page. You can also build packaged versions of WYMeditor yourself using git by following these instructions.

@winhamwr
Copy link
Member

If anyone needs a fix for this issue and can't jump back to WYM 1.0.0b1, you should try @vjt's fix in #369.

@Bratzilla
Copy link

This may sound crazy... but even though I am using 1.0.0b1, this patch magically fixed the issue I was having with posting after a heading paragraph block that I posted about elsewhere. So long as Paste from Word is used properly, problems appear to be gone.

QUESTION What is the best way to get the average user to actually use the Word Paste feature? Most folks just want to copy and paste right in the window, and we know how tragic that would be. I just want something that says, "HEY, YOU... YEAH YOU! DO NOT PASTE YOUR WORD CRUFT HERE!!! USE THE BRIGHT SHINY WORD PASTE!" (of course, without yelling, but damn if cross-browser crap isn't frustrating enough, now you gotta add this turd to the punch bowl!!!!). I know getting all browsers to behave is a toss-up at best sometimes, but is there a reliable, cross-browser method to prevent direct pasting into the editor window? If so, I will gladly use this as a temporary fix until a more permanent solution comes along.

PS: I did extensive testing with the old catchpaste and hotkey plugins, but unfortunately they did not seem to play well with Firefox. :(

@winhamwr
Copy link
Member

this patch magically fixed the issue I was having with posting after a heading paragraph block

Awesome! That's very encouraging.

What is the best way to get the average user to actually use the Word Paste feature?

I wish I had a good solution for this (because I would be using it myself). The only solution I'm aware of that works outside IE is the way that tiny mce does it by using a magic, invisible div to catch the contents of the paste and then processing them. Implementing that isn't super difficult, but it does require some real javascript to make happen.

If nobody beats me to it (I hope they do), I'll definitely build that at some point. If you know any good javascript developers who are looking for consulting work, let me know. I've got some budget to pay someone to work on this and related issues.

-Wes

@Bratzilla
Copy link

I wish I knew some good developers! I'd be using them myself actually.

This paste issue is critical to my project, as the pagination plugin uses paragraphs to determine when to page-break. The only OTHER alternative is to beef-up the editor's native capabilities so that if someone pastes directly in the window (and "if" in this case means "oh hell yes they're gonna do it"), at the very least everything is wrapped in p-tags and cruft is sifted out.

That's the ONLY thing stopping me from deploying the editor in my component - I have worked with writers before, and I KNOW of what they are capable. :(

@Bratzilla
Copy link

Okay, slight change in strategy:

I'm still wrapping my brain around how to patch in to the onpaste event. Firefox is a bit touchy about iframes and pasting it seems, which is why I had to disable the catchpaste plugin.

If I could just write a simple event like the following pseudo-code, I can just add in my own paste clean routine:

$(editor).onpaste(function()
     // add word crap cleaning code here
 )

@winhamwr
Copy link
Member

I may be remembering this completely wrong (and I'd love correction if that's true), but IE is the only browser that lets you access the contents of a paste directly with a handler. For Chrome and FF, they don't because it's a security concern. Because of that, it's not as easy as just writing an onpaste handler (except for IE).

@winhamwr
Copy link
Member

Also, this stackoverflow thread has a good, detailed discussion of the techniques required to catch the pasted content: http://stackoverflow.com/questions/2176861/javascript-get-clipboard-data-on-paste-event-cross-browser

Edit: Specifically, check out the second answer and then Tim Down's response. Dude is a cross-browser selection genius. He has a jsfiddle with his solution here: http://jsfiddle.net/weswinham/2QufM/

I left a comment on the spot where you'll want to do the work to clean up the HTML before inserting the document fragment.

@Bratzilla
Copy link

This is EXACTLY what I've been trying to find! I apologize for not being clearer in my earlier statements. I'm well aware of the safety limitations of paste access implemented by the various browsers (and for damn good reason). What I should have said was that, after pasting (which means it is now content within the editor), I wanted to then clean up the mess. I keep forgetting that especially with client-side scripting you HAVE to be very clear about what you're saying. :)

I see your notes - now that I see HOW to capture the pasted information, I'll start implementing my Word crap cleaning code. I already developed it for jwysiwyg so it'll be interesting to see how that works here - and yes, I also use timeout as part of the solution. :)

How do you recommend this be implemented? Should it be incorporated into the core? Would this function better as a plugin? Admittedly, I'm still learning editor syntax, but hey, I'll give it a shot. I think this REALLY would be helpful to so many, since most people aren't going to be good boys and girls and use the bright shiny paste button.

Thank you again for all the help!

@winhamwr
Copy link
Member

This is EXACTLY what I've been trying to find!

Awesome! Glad I could help. This is the strategy I've been trying to explain via text and the references to tinymce/fsckeditor, but this code is definitely a much less complex/ambiguous method of communication.

How do you recommend this be implemented? Should it be incorporated into the core?

I think it should definitely be in core and I'd love a pull request on it. It would be especially great if the method that did the actual HTML cleanup was separate from the code that did the capture, which would make it easy for folks to write plugins that changed that behavior (since my guess is that it would vary a little bit here and there). I am super-duper interested in this functionality, so if you were able to at least get started with some code and some tests in a pull request, I'll definitely be able to justify spending hours collaborating on it.

since most people aren't going to be good boys and girls and use the bright shiny paste button.

Definitely. It's basically perverse from a user experience perspective for us to ask them to. Removing that button will make me very happy :)

@Bratzilla
Copy link

Hey, I'm no client-side scripting guru, but since I need it I'll try. :)

@winhamwr
Copy link
Member

no client-side scripting guru

I think there are like 5 of those in the world. Kind of like unicorns :)

@winhamwr
Copy link
Member

@Bratzilla I just got a comment notification email with a note from you about editing the jsfiddle, but it doesn't seem to be here. Github error, or did you delete it?

@Bratzilla
Copy link

My bad... I submitted the comment too soon.

I'm still learning my way around Rangy, and I'm trying to figure out how to parse the pastedHTML. Ideally, all I want to grab is the content of the editable container (the big "glop" of text so to speak) and run that through my sanitizer.

@winhamwr
Copy link
Member

No problem. One thing that you'll probably find useful from WYMeditor is the wym.restoreSelectionAfterManipulation helper function. Example usage here.

If you write your paste catching + cleanup code as a callable, you'll be able to use that to reliably grab the user's current selection and then restore it after you do your paste stuff.

As far as detecting whether your inserted HTML should be wrapped in P tags itself, check out the current paste function. It does the same kind of logic you'll need to do for determining if it's a multi-line past, which calls _handleMultilineBlockContainerPaste. Basically, you'll look at your DocumentFragment, and if there's more than one block-level element, you'll split the current container in two and insert them all after the first split container. If it's only one block-level element, it probably means you want to strip the surrounding P tags from your DocumentFragment and just insert the stuff in the middle inline without splitting the current container.

Have you been able to get rolling with this stuff inside WYMeditor? Since there are so many different cases to handle, this is something that would really benefit (for your sanity) on some unit tests. If you ever want to drop by freenode IRC in the #wymeditor channel, I can probably help you get started with that.

@Bratzilla
Copy link

Sorry about the delay... real life has sidelined me for a bit.

I've done a LOT more digging into this... even found some nice charts and articles explaining about cross-browser paste compatibility. Opera and Safari really throw a monkey wrench in, as some versions may have paste detection and "faking" capabilities on Windows, but not the Mac...

It seems like there are a LOT of variables to making direct paste clean-up work cross-browser, because not every browser can even properly DETECT the paste event.

I found this amazing fiddle: someone else seems to be going through a LOT of pain to make cross-browser paste work predictably:

http://jsfiddle.net/JgU37/44/

I am THIS close to just pushing the whole bloody thing off to the server and let PHP sort it all out. At least that seems to be what some suggest. :P

@Bratzilla
Copy link

ANOTHER TACT....

Just thought of something...

WYMEditor has a "write-back" function to update the textarea with what's currently in the iframe.

Is there a way to simply take THAT text and clean it up? Theoretically, you could completely bypass the complexities of cross-browser paste events.

@NickMcL
Copy link
Contributor

NickMcL commented Jul 26, 2013

One thing I forgot to mention: There's a lot of code repetition between the browser extension classes of the editor for this ticket, but I decided to save trying to consolidate all of the different browser extensions into the editor base for another ticket since this ticket is already quite long.

// This test doesn't pass in older versions of IE because they add an extra
// space onto the end of an `li` element's text content. The functionality
// tested still works in those older IE versions.
if (!jQuery.browser.msie || !SKIP_KNOWN_FAILING_TESTS) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test was failing in IE 7 and 8, and I suspect it might also fail in newer versions of IE. The only reason the test fails in those browsers is because they add a space between text and a table within an li element despite the actual outdenting that is tested functioning as expected. I looked into fixing the test in those browsers for a little bit, but I couldn't find an easy solution, so I don't think it's worth spending any more time on fixing at the moment.

@NickMcL
Copy link
Contributor

NickMcL commented Jul 29, 2013

Issue #369 was fixed by the changes I made in this ticket. I tried my hand at writing a selenium test to demonstrate the behavior in #369 to show that it is now fixed (I've never written selenium tests before, so I just modelled the test after the other selenium tests). It looks like the test does properly replicate the behavior in #369, and the test passes, thus showing that the issue is fixed.

@NickMcL
Copy link
Contributor

NickMcL commented Jul 29, 2013

I can't confirm it, but I think my changes in this ticket also probably fix the third of the three problems described in #367 because the div containers should be converted to p containers now.

selenium: selenium-chrome

unittest:
@@build/phantomjs_test.sh localhost:8000/test/unit
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably remove this, since we can do this via grunt, now. No reason to have two ways of doing the same thing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

evt.keyCode !== WYMeditor.KEY.ENTER &&
// If the inputted key cannont create a block element and is not a command,
// check to make sure the selection is properly wrapped in a container
if (!wym.keyCanCreateBlockElement(evt.which) &&
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I eliminated some of the code duplication in the keyup handlers in the browser extension classes by adding the methods keyCanCreateBlockElement and isForbiddenMainContainer to the editor base to determine if a key code can create a block element and if a tag is a forbidden main container respectively. I think using these methods also makes the keyup handlers a lot more readable.

I also added constants to the core for both of those methods to utilize (POTENTIAL_BLOCK_ELEMENT_CREATION_KEYS and FORBIDDEN_MAIN_CONTAINERS respectively) to make it easy to modify in future if needed which keys are considered able to create block elements and which tag names are forbidden main containers.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is much more readable. Great change!

@@ -7,6 +7,7 @@ module.exports = function(grunt) {
qunit: {
all: {
options: {
timeout: 15000,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Travis build was failing on a time out intermittently every once in a while despite all of the same test runs passing on my local machine, so I figured the time out was happening because Travis was running the tests too slowly sometimes, so I changed the time out from the default of 5 seconds to 15 seconds when the tests are run with Grunt to try to avoid the tests timing out on Travis.

winhamwr added a commit that referenced this pull request Jul 30, 2013
Fixes #360. New lines inserted after header containers are broken in Chrome/Safari
@winhamwr winhamwr merged commit 56ba260 into master Jul 30, 2013
@winhamwr winhamwr deleted the issue_360 branch July 30, 2013 20:54
lehni pushed a commit to wemakeit/wymeditor that referenced this pull request May 15, 2014
…nd-of-breaking.

Issue wymeditor#360 will have a fully-baked fix for this.
@mightyiam mightyiam modified the milestones: 1.0.0, 1.0.x Sep 8, 2014
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants