I am using WYSIWYG Image Upload (http://drupal.org/project/wysiwyg_imageupload) + WYSIWYG (Newest Dev) + TinyMCE (newest stable), and it seems as though through its use we may have discovered a bug in the WYSIWYG plugin API with TinyMCE.

Basically, in Internet Explorer 7 or 8, whenever an image is inserted via the WYSIWYG Image Upload, the image is inserted in Row 1, Character 1 - regardless of where the mouse cursor is in the TinyMCE document. When using a browser like Chrome or Firefox, this doesn't happen - the image inserts wherever the cursor is. When switching to a different editor such as CKEditor, it works as expected in Internet Explorer.

Anyone experience something similar / have a fix?

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

TwoD’s picture

Wysiwyg module currently doesn't control where things are inserted at all. It simply hands off any insertion "requests" to the editor libraries themselves.
In the case of TinyMCE, it would correspond to this method call on the TinyMCE instance:

tinyMCE.execInstanceCommand(FIELDNAME, 'mceInsertContent', false, CONTENT);

I do not have the time to look into this at the moment, but I'll try to reproduce the issue and see if there's anything we can do to make it easier for TinyMCE/IE to figure out where the cursor is/was. (IE has a tendency to lose track of selections.)

newmediaist’s picture

Thanks for the response - so just to clarify, this sounds like a TinyMCE issue then, and I should jump over to their forums for more info?

EugenMayer’s picture

Hey TwoD, that one is related. http://drupal.org/node/856622

TwoD’s picture

Title: Internet Explorer 7/8 w/TinyMCE + WYSIWYG Bug » Internet Explorer 7/8 w/TinyMCE, insert position bug
Component: Code » Editor - TinyMCE

Thanks, marked #856622: IE8 Bug: Images always inserted at 1st character of 1st line regardless of where curser is a duplicate of this one.

So far I've only had time to make a quick test in IE6 and it appears to be working fine as long as the editing area had focus just prior to the insertion. I have a few ideas on possible workarounds but my vacation is coming up soon and I'm planning to spend it away from home so I don't know whehn I have time to actually do this.

If anyone wants to take a shot in the mean time, try calling the editor's .focus() method inside our implementation layer's .insert() method, just prior to the call I mentioned above.

EugenMayer’s picture

Well i will give it a try, also running low on time thought. Have nice holidays, see you later :)

newmediaist’s picture

I'm here to help with testing - unfortunately my JS skills are sub-par though :(

I did some digging around TinyMCE's forum none the less though, this is the closet thing I found http://tinymce.moxiecode.com/punbb/viewtopic.php?id=18198

"When getting a bookmark for Internet Explorer .selection.getBookmark() apparently needs 1 as a parameter."
ieBookmark = tinyMCE.get ('myTextArea').selection.getBookmark (1);

Maybe this is an occurrence of an a parameter needed by IE which is not required by Chrome/Firefox?

adjperez’s picture

Hello,

I am having the same issue. Any progress?

Regards

TwoD’s picture

Status: Active » Postponed (maintainer needs more info)

@newmediaist, You might be on to something, but knowing when to set that bookmark could be tricky.

@adjperez, not much progress yet in terms of code, but I have a few ideas and leads.

I have confirmed that the editor will always (in IE at least) insert things at the very beginning of the contents if it does not have focus when the insert happens. This has to do with IE only handling a single selection per page.
When handling mouse events (click, mousedown or mouseup) for toolbar buttons TinyMCE stops the event from bubbling and prevents the default browser action. The default action would be to give the clicked element focus, and thus stealing it away from the editor. When the editor no longer has focus (no obvious selection) inserts are by default put at the beginning. It can't guess where you wanted to insert something, and there's probably no "selection bookmark" to restore since the editor was most likely not made aware it needs to store one just because another element on the page got focused (which happens a lot for all kinds of reasons that don't concern the editor). Restoring the selection would also mean the editor "steals" focus, which might not be desired by whichever script does the insert (maybe things are inserted based on over which elements element X is being dragged?).

The code Wysiwyg uses for insertions is the snippet I posted earlier. You can test it, and how TinyMCE's own plugins behave when inserting content, with a few simple steps.

  1. Go to the TinyMCE demo site: http://tinymce.moxiecode.com/tryit/full.php
  2. Click to place the caret somewhere in the editor.
  3. Click the calendar or clock icon in the toolbar to insert a date/time to see if insertions work at all.
  4. If date or time does not appear at the caret position, this is likely a browser-specific bug in TinyMCE.
  5. If it works, let's try inserting something else the same way Wysiwyg does it:
  6. Copy this code snippet exactly: javascript:void(setTimeout(function() {tinyMCE.execInstanceCommand('content', 'mceInsertContent', false, '<p>Wohoo, workin\' fine!</p>')}, 3000));
  7. Paste the snippet to the address bar (replacing everything else) when viewing the demo page.
  8. Press [ENTER] and quickly click somewhere inside the editor.
  9. Wait a couple of seconds to see if the string "Whohoo, workin' fine!" appears where the cursor is, or anywhere else
  10. .

  11. If not, note if the browser throws any errors (lower left corner of IE's status bar) and where the text appears, if at all, and report it here.
  12. Note: The snippet only works on that page as the first parameter to execInstancecommand() is the textarea's id (currently 'content').

    Now let's see what TinyMCE does when focus has been lost on purpose.
    Repeat the steps above, but after placing the caret inside the editor, click somewhere outside it - where doesn't matter as long as it's no part of the editor - then click the date/time icons or run the snippet in the address bar.
    The results I got where the same ones described in the original post here, the inserted content is placed at the beginning of the editing area no matter where the caret was before you clicked outside the editor.

    So, the key here seems to be that to get things inserted where you want them, the editor must not lose focus, or have the selection stored and restored, between the caret being positioned and content being inserted.

    I'm not yet sure always moving focus or the selection back to the editor is such a good idea, but it might be the only solution for situations where inserts are triggered from modal dialogs or similar. It might even be what users are expecting to happen, so let's say we explore that option a bit further.

    My first suggestion about calling the editor's .focus() method did not work, it just placed a visible caret at the beginning of the content. But newmediaist's suggestion of myBookmark = editor.getBookmark(1) (and later calling editor.moveToBookmark(myBookmark)) did work in my tests.

    Now we'll need to know when to save a bookmark, so we don't restore a selection that is too old.
    Maybe onchange_callback can help us here? It says it's triggered when the editor is blurred (the opposite of being focused). Setting a selection bookmark does not look like a very heavy operation if we can trigger it only when the editor is being blurred (or at least not every time something changes).

    I'll dig deeper into this later. Any comments so far?

adjperez’s picture

Thanks @TwoD for your comments and help!

I repeated your steps:

1. Go to the TinyMCE demo site: http://tinymce.moxiecode.com/tryit/full.php
2. Click to place the caret somewhere in the editor.
3. Click the calendar or clock icon in the toolbar to insert a date/time to see if insertions work at all.
4.If date or time does not appear at the caret position, this is likely a browser-specific bug in TinyMCE.
->Works fine! Date was inserted where the cursor was

5. If it works, let's try inserting something else the same way Wysiwyg does it:
# Copy this code snippet exactly: javascript:void(setTimeout(function() {tinyMCE.execInstanceCommand('content', 'mceInsertContent', false, '

Wohoo, workin\' fine!

')}, 3000));
# Paste the snippet to the address bar (replacing everything else) when viewing the demo page.
# Press [ENTER] and quickly click somewhere inside the editor.
# Wait a couple of seconds to see if the string "Whohoo, workin' fine!" appears where the cursor is, or anywhere else
->Works fine too!
.
# If not, note if the browser throws any errors (lower left corner of IE's status bar) and where the text appears, if at all, and report it here.
->No problem at all.

Any idea? Since nobody has reported this error in TinyMCE, I guess that this should be an integration issue in Drupal, right?

Let me know if you need a screen capture but basically no error was reported in IE's status bar

adjperez’s picture

By the way I observed that although in IE8 all images are inserted at the beggining of the text area, once the image is inserted, it can be moved and shifted to other positions.

More info: the issue occurs just using wysiwyg image upload. Img_ass works fine and pictures are inserted where the cursor is

I do not know if this can help you in your investigation

TwoD’s picture

@adjperez, yes, content can be moved around after insert. Only the initial insert point is affected by this behavior.

Image Assist works fine part because it uses a new window, which lets the editor keep focus/selection in the main window, and part because it uses some of TinyMCE's own dialog handling code*. Img assist uses a part of Wysiwyg module's API that was meant to let you open a dialog using the editor's "native" dialog-handling code (so it gets parts of that editor's themeing), without knowing exactly which editor it's talking to.
In theory, it would make issues like this one much easier to manage because the editor itself would know when a dialog was opened, closed etc, since it was the one actually performing the operations. The downside was that it became complex to implement this for more than one editor in a way that wouldn't require cross-editor plugins to talk directly to the editor's API despite our efforts. That and the fact that far from all editors even have a dialog API is making us think about dropping that feature completely starting with the next major version. One alternative is to let plugins manage their dialogs on their own, which is what WYSIWYG Image Upload and others already do. Another alternative is to create our own dialog API, or officialy work with another module that does.

*AFAIK, Image Assist is moving away from this way of handling dialogs but I haven't checked its current state. IA only worked with TinyMCE earlier, since that was the only editor implementation which fully supported the dialog API, but this move should let it work with at least CKEditor and FCKeditor as well.

adjperez’s picture

Thanks, @TwoD. In summary is there any workaround in short term?

TwoD’s picture

For regular users; Make sure the last thing you do before clicking a button (in the toolbar or elsewhere on the page) that inserts something is to position the caret. Don't click anywhere else before clicking the button or the focus/selection might get lost. There are of course clicks that can't be avoided, such as when selecting an image to insert etc, but it might be possible to reposition the caret where you want it before pressing the final "OK/Insert"-button in the dialog.

For developers; If the action triggering something to be inserted is a simple button-click or keypress, try to cancel the default browser action when handling the mouse/key events so the focus/selection stays inside the editor instead of being moved to the button.
If you feel this isn't enough, say because you're using a modal dialog, please get in touch with us if you can help writing an abstraction API for selection bookmarking. Basically, what's needed is a "getBookmark" method on the editor instance to fetch the current selection, if any, and a "setBookmark" method which can be called when the selection needs to be restored. (This is just an off the top of my head solution. If you've got a better one, I'd be glad to hear it.)

adjperez’s picture

@TwoD, your trick for regular user do not work. Before clicking the button to insert an image (wysiwyg image upload) I leave the cursor in the text inside text area. However the image is always inserted at the beginning of the text area. No matters what I do, the image is always inserted at the first row, first position. So I guess that your assumption is not right

Sorry for insisting you but I am a bit frustrated. I tried to use wysiwyg image upload with CKEditor in IE8 and no icon can be selected (but I guess that this is other story...)

TwoD’s picture

@adjperez, that's why I said that it might be possible, depending on how events are handled by the plugin and/or if it's a dialog. Wysiwyg Image Upload uses a modal dialog so it's not possible to click in the textarea to move the selection back there manually before inserting the image.

You'll have to move the image after inserting it in IE8, either by dragging it or moving the tag itself in source mode or with the editor disabled. I can't tell why it didn't work at all for you with CKEditor in IE8, I just tried that before typing this.

sun’s picture

Status: Postponed (maintainer needs more info) » Closed (cannot reproduce)

Sorry, without further information this issue can only be closed as not reproducible.

Feel free to re-open this issue if you want to provide further information. Thanks.

adjperez’s picture

Finally I could solve it! I enabled CSS optimization (Site configuration -> Performance) and the problem was solved.

I guess that there was some mismatch between my theme CSS and wysiwyg image upload/editor

I hope this can help anybody in same situation...

Steven Jones’s picture

Version: 6.x-2.x-dev » 7.x-2.x-dev
Status: Closed (cannot reproduce) » Active

Right, I can exactly reproduce this issue, and have a partial fix.

I've got TinyMCE 3.5.8, and the media module, with it's media library button in the toolbar. In chrome, you can get the cursor in the positiion where you want to enter the media, click the button and then insert it, and it goes in the correct place. However, in IE8, the media is always inserted into the beginning of the editor.

You can also reproduce this with some of the other plugins, like the 'normal' insert image popup. Click the button, then go back to the parent page, and change the position of the cursor, maybe to another field on the page, and then complete the image insert popup, and the image will be inserted into the start of the wysiwyg.

I think that what is needed here is as suggested in #13 above:

say because you're using a modal dialog, please get in touch with us if you can help writing an abstraction API for selection bookmarking. Basically, what's needed is a "getBookmark" method on the editor instance to fetch the current selection, if any, and a "setBookmark" method which can be called when the selection needs to be restored. (This is just an off the top of my head solution. If you've got a better one, I'd be glad to hear it.)

I've got a hacky patch that gets it working, and I'll try to clean it up into something useable now.

Steven Jones’s picture

Status: Active » Needs work
FileSize
938 bytes
561 bytes

So here's a couple of nasty patches that the job done for TinyMCE, but certainly break everything else, I'm not sure how wysiwyg's abstraction layer works, so just throwing this up here really.

TwoD’s picture

Title: Internet Explorer 7/8 w/TinyMCE, insert position bug » Add support for selection bookmarks
Component: Editor - TinyMCE » Code
Category: bug » feature

@Steven Jones, thanks for the patch!

I'll make this non-TinyMCE specific since this would be useful for all editors.

I think we may have to abstract out - if possible - the information returned by getSelectionBookmark() so code could call setSelectionBookmark(bm) without worrying about whether the same editor is still active. Ideally we should automatically get a bookmark when the editor loses focus and restore bookmarks before inserting anything so plugins won't have to do that manually.

This is where having a proper abstraction for interacting with editor instances would be useful as well, so Drupal.wysiwyg.instances[this.instanceId].insert(markup) wouldn't point directly to the editor instance but a wrapper around it so we could call these methods without modifying each implementation, but that's for a different issue...