My AbstractJavaScriptComponent doesn't render in a Window

My AbstractJavaScriptComponent (CKEditor) seems to be working and rendering when I add it to the layout associated with my UI. But when I use it in a popup WIndow, it’s not rendering at all. The space seems to be allocated in the window for my widget, but when I look, the DIV is empty, like I didn’t add anything to it. Here’s how it shows the rendering (VCK_10 is the ID I set on the DIV based on my JS code getting a this.getConnectorId() value of 10):


<div class="v-slot" style="height: 100%; margin-top: -40px;"><div class="v-widget v-has-width v-has-height" id="VCK_10" style="height: 450px; width: 100%; overflow: hidden; visibility: visible;"></div></div>

And when I close the window, I get this error:

WARNING: cleanConnectorMap unregistered connector org.yozons.vaadin.ckeditor.CKEditor(10) (parent: com.vaadin.ui.VerticalLayout(9)). This should have been done when the connector was detached.

In case, it matters, this is my UI code that opens the window on a button click that was added to my main UI’s layout:


		layout.addComponent(new Button("Open Non-Modal Subwindow with 100% Height", new ClickListener() {                      

			@Override
	        public void buttonClick(ClickEvent event) {
	                Window sub = new Window("Subwindow non-modal 100% height");
	                VerticalLayout subLayout = new VerticalLayout();
	                sub.setContent(subLayout);
	                sub.setWidth("80%");
	                sub.setHeight("500px");

	                subLayout.setSizeFull();
	                
	                CKEditorConfig config = new CKEditorConfig();
	                config.useCompactTags();
	                config.disableElementsPath();
	                config.disableSpellChecker();
	                config.enableVaadinSavePlugin();
                    // set BaseFloatZIndex 1000 higher than CKEditor's default of 10000; probably a result of an editor opening
                    // in a window that's on top of the main two editors of this demo app
                    config.setBaseFloatZIndex(11000); 
                    config.setStartupFocus(true);
	                
	                final CKEditor ckEditor = new CKEditor(config);
	                //ckEditor.setHeight("100%");
	                ckEditor.setHeight("450px");
	                ckEditor.addValueChangeListener(new ValueChangeListener() {

						public void valueChange(String newValue) {
							Notification.show("CKEditor v" + ckEditor.getVersion() + "/" + getVersion() + " - POPUP NON-MODAL 100% HEIGHT contents: " + ckEditor.getValue());
	        			}
	        		});
	                subLayout.addComponent(ckEditor);
	                subLayout.setExpandRatio(ckEditor,1.0f);
	                
	                final TextField textField = new TextField("TextField");
	                textField.addValueChangeListener(new Property.ValueChangeListener() {

						public void valueChange(ValueChangeEvent event) {
							Notification.show("TextField - POPUP NON-MODAL 100% HEIGHT contents: " + event.getProperty().getValue().toString());
	        			}
	        		});
	                subLayout.addComponent(textField);
	                
	                sub.center();
	                
	                event.getButton().getUI().addWindow(sub);
	        }
        }));

I have narrowed down the issue here. The problem is that a popup Window is not attached to the DOM by the time I add my CKEditor widget to the window’s VerticalLayout (content).

I checked, and when my JavaScriptComponent (CKEditor) is being instantiated, I have an element id, but the main overlay DIV is not yet in the DOM, so document.getElementById() doesn’t work because it’s not accessible yet.

So when I add my editors to the layout of the UI, it seems the UI has build the DOM in time, but when it’s in a popup Window, it’s not present.

In the javascript debugger, I can see that my element is not available, but shortly thereafter, the popup window’s DIV is added to the DOM like:

So, what is the correct way to handle this? Seems like the Windows and its layout needs to be part of the DOM before I can then render JavaScript widgets that access the assigned element given to my component.

It seems I have the same issue instantiating my JavaScriptComponent in a TabSheet as well. It appears to be the same issue that the DOM elements are not in place and attached before my component is being created and so it fails to find the element by its ID.

Is there a way to defer the creation of my components until the various elements are added to the DOM?

I have upgraded to 7.1.0, and I have basic JavaScriptComponent as well as a corresponding CustomField working for CKEditor. But…

This popup window and tabsheet issue still persists even though it otherwise is working okay for the components added to to the UI’s layout. The editor is appearing in the window, but it’s not getting events passed around as expected. When I close the Window, this error appears, which no doubt is tied to the fact that my component somehow is not getting tied in:

Jun 27, 2013 6:03:20 PM com.vaadin.ui.ConnectorTracker cleanConnectorMap
WARNING: cleanConnectorMap unregistered connector org.yozons.vaadin.ckeditor.CKEditor(22) (parent: org.yozons.vaadin.ckeditor.CKEditorField(21)). This should have been done when the connector was detached.

Here’s the JavaScript console output when I click a Vaadin button that triggers opening the window and putting the editor in:


Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Making UIDL Request with params: c4346147-7d7d-4e81-8ad7-5bd6f62b018d[["13","com.vaadin.shared.ui.button.ButtonServerRpc","click",[{"type":"1", "shiftKey":false, "ctrlKey":false, "altKey":false, "relativeY":"13", "clientX":"137", "relativeX":"119", "metaKey":false, "clientY":"787", "button":"LEFT"}]
]] 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Server visit took 17ms 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: JSON parsing took 0ms 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Handling message from server 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Handling resources from server 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Handling type inheritance map from server 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Handling type mappings from server 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Handling resource dependencies 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Handling meta information 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Creating connectors (if needed) 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Updating connector states 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Handling locales 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Updating connector hierarchy 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Sending hierarchy change events 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Running @DelegateToWidget 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Sending state change events 0.js:205
MyComponent creating CKEDITOR append to div id: VCKE_22; config: { extraPlugins : 'vaadinsave', removePlugins : 'elementspath,scayt', baseFloatZIndex : 11000, startupFocus : true } ckeditorForVaadin7.js:32
MyComponent created CKEDITOR: [object Object]
 ckeditorForVaadin7.js:34
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: JavaScript connector initialized using org_yozons_vaadin_ckeditor_CKEditor 0.js:205
DEBUG: CKEditor onStateChange: editor id: cke_236; cid: 22; viewWithoutEditor: false; readOnly: false >>><<< ckeditor-connector.js:18
DEBUG: CKEditor component is not yet ready -- ignoring onStateChange ckeditor-connector.js:41
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Passing UIDL to Vaadin 6 style connectors 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Performing server to client RPC calls 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: * Unregistered 0 connectors 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: handleUIDLMessage: 30 ms 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Starting layout phase 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Measured 5 non connector elements 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Pass 1 measured 4 elements, fired 4 listeners and did 1 layouts. 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Did overflow fix for 1 elements 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Pass 2 measured 8 elements, fired 1 listeners and did 0 layouts. 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Did overflow fix for 1 elements 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Pass 3 measured 1 elements, fired 0 listeners and did 0 layouts. 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: No more changes in pass 4 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Total layout phase time: 33ms 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  Processing time was 67ms for 2261 characters of JSON 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Referenced paintables: 19 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Making UIDL Request with params: c4346147-7d7d-4e81-8ad7-5bd6f62b018d[["19","v","v",["positionx",["i","149"]
]],["19","v","v",["positiony",["i","159"]
]],["22","com.vaadin.ui.JavaScript$JavaScriptCallbackRpc","call",["onInstanceReady",["4.1.2"]
]]] 0.js:205
DEBUG: editor.dataProcessor.writer.setRules tag: li; rule: {indent : true,  breakBeforeOpen : true, breakAfterOpen : false, breakBeforeClose : false, breakAfterClose : true} ckeditorForVaadin7.js:76
DEBUG: editor.dataProcessor.writer.setRules tag: p; rule: {indent : false, breakBeforeOpen : true, breakAfterOpen : false, breakBeforeClose : false, breakAfterClose : true} ckeditorForVaadin7.js:76
DEBUG: editor.dataProcessor.writer.setRules tag: h5; rule: {indent : false, breakBeforeOpen : true, breakAfterOpen : false, breakBeforeClose : false, breakAfterClose : true} ckeditorForVaadin7.js:76
DEBUG: editor.dataProcessor.writer.setRules tag: h4; rule: {indent : false, breakBeforeOpen : true, breakAfterOpen : false, breakBeforeClose : false, breakAfterClose : true} ckeditorForVaadin7.js:76
DEBUG: editor.dataProcessor.writer.setRules tag: h6; rule: {indent : false, breakBeforeOpen : true, breakAfterOpen : false, breakBeforeClose : false, breakAfterClose : true} ckeditorForVaadin7.js:76
DEBUG: editor.dataProcessor.writer.setRules tag: h1; rule: {indent : false, breakBeforeOpen : true, breakAfterOpen : false, breakBeforeClose : false, breakAfterClose : true} ckeditorForVaadin7.js:76
DEBUG: editor.dataProcessor.writer.setRules tag: h3; rule: {indent : false, breakBeforeOpen : true, breakAfterOpen : false, breakBeforeClose : false, breakAfterClose : true} ckeditorForVaadin7.js:76
DEBUG: editor.dataProcessor.writer.setRules tag: h2; rule: {indent : false, breakBeforeOpen : true, breakAfterOpen : false, breakBeforeClose : false, breakAfterClose : true} ckeditorForVaadin7.js:76
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Server visit took 41ms 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: JSON parsing took 0ms 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Handling message from server 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Handling resources from server 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Handling type inheritance map from server 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Handling type mappings from server 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Handling resource dependencies 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Handling meta information 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Creating connectors (if needed) 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Updating connector states 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Handling locales 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Updating connector hierarchy 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Running @DelegateToWidget 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Sending state change events 0.js:205
DEBUG: CKEditor onStateChange: editor id: cke_236; cid: 22; viewWithoutEditor: false; readOnly: false >>><<< ckeditor-connector.js:18
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Passing UIDL to Vaadin 6 style connectors 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Performing server to client RPC calls 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: * Unregistered 0 connectors 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: handleUIDLMessage: 8 ms 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Starting layout phase 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Measured 5 non connector elements 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Pass 1 measured 4 elements, fired 0 listeners and did 1 layouts. 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Pass 2 measured 1 elements, fired 0 listeners and did 0 layouts. 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: No more changes in pass 3 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Total layout phase time: 8ms 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO:  Processing time was 20ms for 1717 characters of JSON 0.js:205
Thu Jun 27 18:01:12 GMT-700 2013 com.vaadin.client.VConsole
INFO: Referenced paintables: 19 0.js:205

I didn’t see much, but here’s what gets output when that window is then closed:


Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO: Making UIDL Request with params: c4346147-7d7d-4e81-8ad7-5bd6f62b018d[["19","v","v",["close",["b",true]
]]] 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO: Server visit took 15ms 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO: JSON parsing took 0ms 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO: Handling message from server 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Handling resources from server 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Handling type inheritance map from server 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO: Handling type mappings from server 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO: Handling resource dependencies 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Handling meta information 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Creating connectors (if needed) 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Updating connector states 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Handling locales 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Updating connector hierarchy 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Sending hierarchy change events 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Running @DelegateToWidget 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Sending state change events 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Passing UIDL to Vaadin 6 style connectors 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO:  * Performing server to client RPC calls 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO: * Unregistered 5 connectors 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO: handleUIDLMessage: 13 ms 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO: Starting layout phase 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO: Measured 2 non connector elements 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO: No more changes in pass 1 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO: Total layout phase time: 17ms 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO:  Processing time was 34ms for 262 characters of JSON 0.js:205
Thu Jun 27 18:03:20 GMT-700 2013 com.vaadin.client.VConsole
INFO: Referenced paintables: 14 

David, I was wondering if you ever found a solution for the DOM issue when using a JS component in a TabSheet? I’m seeing the same issue with some of my JS components where they JS library does a getElementByID but the component’s DOM tree hasn’t been attached to the document yet.

It seems like the onStateChange method gets called on the panels in a TabSheet before the panel is attached to the document. This makes it really hard to use some third party JS libraries because they want to access the DOM when created.

-mike

I came up with this solution which may or may not work for you. I created a CustomField object (I needed a field, CustomComponent should work as well) that combined a normal component, in my case a ListSelect, and another component extending AbstractJavaScriptComponent. I then overrode setId/getId methods to call the corresponding ListSelect methods and then overrode the attach method to fire this bit of JavaScript:

JavaScript.getCurrent().execute("$('#" + this.getId() +
             "').children(':first').dropdownchecklist({showCheckboxes:true});");

I haven’t finished it completely, but it does work and does draw the UI properly in a window and I would imagine in a tab sheet as well. I plan on using this pattern for a handful of jQuery components I really need/like. I’ve still got to add in all the options to pass to the jQuery component.

John