IE8 screen/widget disappears with CKEditor

I have a
simple test app
that displays a button and a CKEditor widget. For some reason on IE8 only (maybe other IE versions too?), when I first load the app, if I click the “Hit server” button (dummy button not tied into anything, just a way to force an ‘immediate’ client.updateComponent()) or click the “Save” button in CKEditor, the CKEditor widget disappears.

But if you load the application, hit the browser refresh, then it works in IE8 fine, like it needs a double load for whatever reason to be sticky. But it appears to be correct on the first load (nothing is missing), and clicking the button even submits the CKEditor buffer back to the server side, it just disappears.

This does not happen on FF 3.5, Chrome 4, Safari 4 or Opera 10.

What might I be doing wrong with respect to IE8? I am using a recent Vaadin 6.3 nightly.

The entire test app is:

public class VaadinCKEditorApplication extends Application {
	@Override
	public void init() {
		Window mainWindow = new Window("Vaadin CkEditor Application", new CssLayout());
		setMainWindow(mainWindow);
		
		mainWindow.addComponent(new Button("Hit server"));
		
		CKEditorTextField ckEditorTextField = new CKEditorTextField();
		
		// The following defines the toolbar to be a custom toolbar, and defines the custom toolbar.
		ckEditorTextField.setInPageConfig(
			"{ " +
				"extraPlugins: 'vaadinsave'," + // add this if using the editor's VaadinSave button
				"toolbar : 'Custom'," +
				"toolbar_Custom : [" +
					"['Styles','Format','Bold','Italic','TextColor','BGColor','-','Font','FontSize','-','JustifyLeft','JustifyCenter','JustifyRight','JustifyBlock','-','Image','Link']
," +
					"'/'," +
					"['Cut','Copy','Paste','PasteText','PasteFromWord','-','Undo','Redo','-','NumberedList','BulletedList','-','Outdent','Indent','-','Table','HorizontalRule','-','Maximize','-','Source','ShowBlocks','-','VaadinSave']
" +
								 "]" +
			" }" 
				     					);
		ckEditorTextField.useCompactTags();

		mainWindow.addComponent(ckEditorTextField);
		
		ckEditorTextField.setValue("<p>Thanks TinyMCEEditor for getting us started on the CKEditor integration.</p><h1>Like TinyMCEEditor said, &quot;Vaadin rocks!&quot;</h1><h1>And CKEditor is no slouch either.</h1>");
		
		ckEditorTextField.addListener(new Property.ValueChangeListener() {
			public void valueChange(ValueChangeEvent event) {
				getMainWindow().showNotification("Content now: " + event.getProperty().toString().replaceAll("<", "&lt;"));
			}
		});
		
	}
}

And the server side widget extends TextField, but it’s paint method is pretty simple:

	public void paintContent(PaintTarget target) throws PaintException {
		super.paintContent(target);
		if (inPageConfig != null) {
			target.addAttribute("inPageConfig", inPageConfig);
		}
		if ( writerRules != null ) {
			int i = 0;
			Set<String> tagNameSet = writerRules.keySet();
			for( String tagName : tagNameSet ) {
				target.addAttribute("writerRules.tagName"+i, tagName);
				target.addAttribute("writerRules.jsRule"+i, writerRules.get(tagName));
				++i;
			}
		}
	}

The client side of the widget code is also pretty straightforward:

	public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
		this.client = client;
		paintableId = uidl.getId();

		// This call should be made first.
		// It handles sizes, captions, tooltips, etc. automatically.
		// If client.updateComponent returns true there have been no changes
		// and we do not need to update anything.
		if ( client.updateComponent(this, uidl, true) ) {
			return;
		}

		immediate = uidl.getBooleanAttribute("immediate");

		// Save reference to server connection object to be able to send
		// user interaction later

		// Save the client side identifier (paintable id) for the widget
		getElement().setId(paintableId);
		
		dataBeforeEdit = uidl.getStringVariable("text");

		if ( ckEditor == null ) {
			getElement().setInnerHTML(dataBeforeEdit);
			String inPageConfig = uidl.hasAttribute("inPageConfig") ? uidl.getStringAttribute("inPageConfig") : null;
			
			// See if we have any writer rules
			int i = 0;
			while( true ) {
				if ( ! uidl.hasAttribute("writerRules.tagName"+i)  ) {
					break;
				}
				// Save the rules until our instance is ready
				String tagName = uidl.getStringAttribute("writerRules.tagName"+i);
				String jsRule  = uidl.getStringAttribute("writerRules.jsRule"+i);
				if ( writerRules == null ) {
					writerRules = new HashMap<String,String>();
				}
				writerRules.put(tagName, jsRule);
				++i;
			}
			
			ckEditor = (CKEditor)CKEditorService.loadEditor(paintableId, this, inPageConfig);
		} else {
			CKEditorService.get(paintableId).setData(dataBeforeEdit);
		}
	}

	// Listener callback
	@Override
	public void onSave() {
		if ( client != null && paintableId != null && ckEditor != null ) {
			// Called if the user clicks the Save button. 
			String data = ckEditor.getData();
			if ( ! data.equals(dataBeforeEdit) ) {
				client.updateVariable(paintableId, "text", data, true);
				dataBeforeEdit = data;
			}
		}
	}

In other debugging, I have found that if I don’t use the default CssLayout of the main window of the test app, but instead use a VerticalLayout, the text editor no longer disappears in IE8, but instead shifts down.

What’s interesting is that the shift down occurs in all other browsers, too.

In Firebug, I can see that a vertical layout DIV height gets bigger by 270px just by pressing the button, so I’m not sure why the layout is changing at all, and of course this is the same amount that the editor is shifting down in the display.

I do know that the editor class extends TextField, and maybe that’s part of the problem. Since I’m not calculating any heights, how can I figure out what is going on that changes the div’s height calculation?

Here’s the HTML from firebug.

Original layout when it first loads the button, editor and button in a Vertical layout:

<div style="overflow: hidden; width: 1401px; height: 332px;" class="v-verticallayout">
  <div style="margin: 0px; overflow: hidden; width: 1401px; height: 332px;">
    <div style="overflow: hidden; height: 26px; width: 1401px; padding-left: 0px; padding-top: 0px;">
      <div style="float: left; margin-left: 0px;">
        <div tabindex="0" class="v-button" role="button">
          <span class="v-button-wrap"><span class="v-button-caption">Hit server</span></span>
        </div>
      </div>
    </div>
    <div style="overflow: hidden; height: 280px; width: 1401px; padding-left: 0pt; padding-top: 0px;">

Here’s what it looks like after clicking the button that should not have changed anything:

<div style="overflow: hidden; width: 1401px; height: 602px;" class="v-verticallayout">
  <div style="margin: 0px; overflow: hidden; width: 1401px; height: 602px;"> 
    <div style="overflow: hidden; height: 26px; width: 1401px; padding-left: 0px; padding-top: 0px;">
      <div style="float: left; margin-left: 0px;">
        <div tabindex="0" class="v-button" role="button">
          <span class="v-button-wrap"><span class="v-button-caption">Hit server</span></span>
        </div>
      </div>
    </div>
    <div style="overflow: hidden; height: 550px; width: 1401px; padding-left: 0pt; padding-top: 0px;"> 

The rest of the HTML appears to be the same, just the bigger heights…

Any ideas what is wrong or how I can better figure out where the height calculation takes place? Thanks!

Perhaps I found the root cause (ran a text compare instead of trust my eyes), and I found that my ckeditor text field div initially comes up display:none:

But after the button press, it becomes:

My client side widget (extends com.google.gwt.user.client.ui.Widget) does create a DIV element, with setStyleName(“v-ckeditortextfield”) to make that.

Then in the updateFromUIDL() method, I do set the div id: getElement().setId(uidl.getId()) when the widget is first created (CKEditor is then loaded in the div by id).

I don’t seem to have code to set display:none, or to remove it. What would cause the widget’s display attribute to change?

Thanks.

The div issue has been resolved with a hack that just turns “display: none;” back on each time the updateFromUIDL takes place that causes the editor’s data to be set to a new value.

getElement().getStyle().setDisplay(com.google.gwt.dom.client.Style.Display.NONE);

Resetting the buffer from the server-side is probably not too common as they are generally loaded with nothing or some initial content, and then the idea is to get the updated value, but it surely could be used for a “Reset” type button that abandons all changes and sets it back to what it was before. Of course, CKEditor has an Undo feature too.

The hope that this would somehow fix the IE8 editors disappearing entirely on any button press after it’s first loaded won’t be the case. That IE bug remains. But again, if you load the page, then hit refresh, it doesn’t happen in IE8 either. There’s something about the initial load only that IE8 doesn’t like, but have no idea where the problem comes from. Using IE8’s developer tools, aside from PID# changes, the HTML appears very similar in the initial load and the refresh load, except the initial load does show:

<STYLE>.cke_skin_kama {
	VISIBILITY: hidden
}
</STYLE>

while the refreshed load shows:

<STYLE>.cke_skin_kama{visibility:hidden;}</STYLE>

I’ve not found out where these come from as they do not appear to be in any CKEditor files, but the former appears a bit odd with the capitalized VISIBILITY and no semi-colon after “hidden”. Kama is the default skin for CKEditor, so it may somehow be related, though I have no idea where/how it gets there.

Also, when I do an initial load in FF 3.5, Firebug shows the latter format, too.

If anybody has any ideas, I’d sure be grateful since I just can’t figure this one out. Even how to find out how/when/who changes/inserts such code into the page would be helpful. Thanks!

On IE8, when I click the button and the CKEditors disappear, I captured the HTML from IE8’s developer tools, and it showed that my widget’s DIVs were there, but the editor’s TABLE that is placed after was no longer there.

Since I am clicking on a Vaadin button, I believe there be some timing or the like issue related to Vaadin that is causing this to happen, or perhaps when something happens initially, I need to do something to tell my editors to rebuild the DOM, too.

It is just so odd, though, that if I load, then reload, it won’t happen, so it’s only something to do with the very first button click on a newly created DOM with Vaadin. My widget creates a DIV element and then attaches the editor to that DOM element. But somehow that is getting lost in this one instance on this one browser…

Someone at Vaadin seen anything like this before with any pointers? I mean, it just had to be IE, the one browser I’m sure to run into a lot. :wink:

Managed to resolve this by swapping out CssLayout for VerticalLayout.

So I guess there’s some subtle bug in the CssLayout that causes this.