Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    #16
    It looks like you're not getting your onChange event to fire at all, since it's failing to even display your alerts.
    This would appear to be a CKEditor issue rather than a SmartGWT issue per se.
    Obviously that's really a question to bring to the CKEditor folks but from a quick google search it appears you need to install the onChange add-on to make this work, if you haven't already.

    Note that if you are able to get onChange to fire for your CKEditor outside of the SmartGWT integration, but somehow the process of wrapping it in a SmartGWT widget is breaking things, we could possibly take a look. We'd essentially need to see a little sample we could run on our end demonstrating the failure case (probably with a sample demonstrating the working case as well so we can analyze what is going wrong).

    Other than that - if you ultimately can't get a proper change notification from CKEditor to fire at all, you could also take another approach to determine when to update the form value.

    A couple of possibilities that come to mind: You could use a "blur" notification to store out the value when the user takes focus from the editor, if that is available.

    Or you could modify your UI to (for example) show the CKEditor in a pop up modal window, and have the user click a standard SmartGWT "Done" button to complete their edit, which would both dismiss the editor and fire the "storeValue()" method, updating the form values.

    Comment


      #17
      Hello:
      I install the 'onChange' plugin for ckeditor, and it still can not work for , Ckeditor's method change.
      The console print some exception
      Code:
      Uncaught JavaScript exception [引发了异常但未捕获] in http://127.0.0.1:8888/BuiltInDS.html?gwt.codesvr=127.0.0.1:9997, line 5
      Code:
      	protected native void loadCKEditor() /*-{
      		if (!this.@com.smartgwt.sample.client.CKEditor::initialised) {
      			var editorId = this.@com.smartgwt.sample.client.CKEditor::getID()()
      					+ "_ta";
      			$wnd.CKEDITOR.replace(editorId);
      			this.@com.smartgwt.sample.client.CKEditor::initialised = true;
      			$wnd.CKEDITOR.instances[ editorId ].on( 'change', function( env ) { 
      				this.@com.smartgwt.sample.client.CKEditor::change()();
      			});
      		}
      	}-*/;
      
      	public void change() {
      		// some code.
      	}
      Attached Files

      Comment


        #18
        hello, Isomorphic. I sent an email to support@isomorphic.com
        There I tested ckeditor project source code, please note that check

        Comment


          #19
          Hello
          We received the sample project. However before we spend time analyzing this on our end, can we verify: Are you able to get the CKEditor onchange event handler to work outside of SmartGWT?

          If not, this would suggest that the failure to fire the onchange event is unrelated to SmartGWT - most likely a problem with how you're applying the handler to CKEditor, or perhaps a bug in the plugin, etc.
          Obviously we have no control over this, and it would make sense for you to contact the makers of CKEditor for assistance if this is the case.

          If you are able to get the onchange handler to fire for a CKEditor control outside of your SmartGWT application, and the problem only occurs once you attempt to integrate with SmartGWT, let us know and we can take a look. It would be helpful in this case to see your working (non SGWT) implementation so we can see exactly what is being changed and determine whether we have a framework problem or simply need to rework the application code a little.

          Also note that in our earlier post we made a couple of suggestions of how to proceed if you ultimately can't get the change event to fire in CKEditor (using blur, perhaps, or changing the UI such that you have some user interface component like a "Done" button to store the value and dismiss the editor).

          Regardless, the first step is probably to put together a test case with no SmartGWT to simply get a CKEditor interface working and attempt to apply the change handler to it directly to see if the problem is actually related to SmartGWT at all.

          Regards
          Isomorphic Software

          Comment


            #20
            Ckeditor's onchange event can work if use code "alert('fu') " . But when I invoke my method "change()" dot not work and throw exception like this
            Code:
            11:29:29.519 [ERROR] [builtinds] 11:29:29.517:WARN:Log:Error:     '引发了异常但未捕获'     in http://127.0.0.1:8888/BuiltInDS.html?gwt.codesvr=127.0.0.1:9997     at line 5 
                anonymous(msg=>"引发了异常但未捕获",  url=>"http://127.0.0.1:8888/BuiltInDS.html?gwt..."[63],  line=>5, 7)
            Code:
            	protected native void loadCKEditor() /*-{
            		if (!this.@com.smartgwt.sample.client.CKEditor::initialised) {
            			var editorId = this.@com.smartgwt.sample.client.CKEditor::getID()()
            					+ "_ta";
            			$wnd.CKEDITOR.replace(editorId);
            			this.@com.smartgwt.sample.client.CKEditor::initialised = true;
            			$wnd.CKEDITOR.instances[ editorId ].on( 'change', function( env ) { 
            				// this.@com.smartgwt.sample.client.CKEditor::change()();
            				alert( 'fu' );
            			});
            		}
            	}-*/;
            	
            	public void change() {
            		// some code.
            	}
            Last edited by xu; 25 Jul 2013, 19:36.

            Comment


              #21
              Thanks for the clarification. This is scheduled to be looked at. We'll follow up as soon as we have more information.

              Comment


                #22
                This turned out to be a scope problem.
                In CKEditor.java, you have this:

                Code:
                	protected native void loadCKEditor() /*-{
                		if (!this.@com.smartgwt.sample.client.CKEditor::initialised) {
                			var editorId = this.@com.smartgwt.sample.client.CKEditor::getID()()
                					+ "_ta";
                			$wnd.CKEDITOR.replace(editorId);
                			this.@com.smartgwt.sample.client.CKEditor::initialised = true;
                			$wnd.CKEDITOR.instances[ editorId ].on( 'change', function( env ) { 
                				this.@com.smartgwt.sample.client.CKEditor::change()();
                			});
                		}
                	}-*/;
                The problem is that the function being assigned as a change handler is executed in the scope of the native CKEditor JavaScript instance, not in the scope of your Java CKEditor instance, so the this.@com.smartgwt.sample.client.CKEditor... reference will fail.
                The easiest way to do this is to use closure to make the appropriate object available within the function - something like this:
                Code:
                	protected native void loadCKEditor() /*-{
                		if (!this.@com.smartgwt.sample.client.CKEditor::initialised) {
                			var editorId = this.@com.smartgwt.sample.client.CKEditor::getID()()
                					+ "_ta";
                			$wnd.CKEDITOR.replace(editorId);
                			this.@com.smartgwt.sample.client.CKEditor::initialised = true;
                			var _this = this;
                			$wnd.CKEDITOR.instances[ editorId ].on( 'change', function( env ) { 
                				_this.@com.smartgwt.sample.client.CKEditor::change()();
                			});
                		}
                	}-*/;
                Regards
                Isomorphic Software

                Comment


                  #23
                  Thanks, I use closure to make the appropriate object available within the function.But i write change code like this
                  Code:
                  	public void change() {
                  		// some code.
                  		if ( null != cKEditorItem ) {
                  			System.out.println( "change store value: ");
                  			cKEditorItem.storeValue();
                  		}
                  	}
                  The method invoke successful,but when i invoke form getValue, or form.save , There are still problems in the picture in the Attached Images
                  Attached Files

                  Comment


                    #24
                    We haven't yet run the code but from your snippet it appears you are calling storeValue() without passing in the actual value you want stored. You will need to pass in the value you want stored.

                    If this isn't enough information to get it working, let us know and we'll run your latest example code and let you know what we find.

                    Comment


                      #25
                      1. I use this code, it throws exception, so I invoke storeValue() method without args .

                      Code:
                      protected native void loadCKEditor() /*-{
                      		if (!this.@com.smartgwt.sample.client.CKEditor::initialised) {
                      			var editorId = this.@com.smartgwt.sample.client.CKEditor::getID()() + "_ta";
                      			$wnd.CKEDITOR.replace(editorId);
                      			this.@com.smartgwt.sample.client.CKEditor::initialised = true;
                      			var _this = this;
                      			
                      			$wnd.CKEDITOR.instances[ editorId ].on( 'change', function( env ) {
                      				_this.@com.smartgwt.sample.client.CKEditor::change(env.editor.getData())();
                      			});
                      		}
                      	}-*/;
                      	
                      	
                      	
                      	public void change( final String value ) {
                      		// some code.
                      		if ( null != cKEditorItem ) {
                      			System.out.println( "change store value: ");
                      			cKEditorItem.storeValue( value );
                      		}
                      	}
                      2. My storeValue() invoke the overrided method storeValue( String )
                      Code:
                      	@Override
                      	public void storeValue(Object value) {
                      		setValue(value);
                      	}
                      
                      	public void storeValue() {
                      		setValue( getValue() );
                      		storeValue( getValue() );
                      	}

                      Comment


                        #26
                        There are still some fundamental problems with this code.
                        You should not be overriding getValue(), setValue(Object value), or storeValue(Object value).
                        Your showValue handler should not be calling 'setValue()' - that can lead to infinite loops as showValue is called as a result of the value being set programmatically (For example via a "setValue()" call on the item).
                        Similarly your changed handler which ultimately calls the storeValue implementation with no arguments should not be calling 'setValue()'

                        What you actually want is quite simple. You want a showValue handler which updates the CKEditor native text-box content. This will be called whenever the form item value is changed programmatically and will ensure the user sees the new value.
                        And you want a changed handler implementation on the CKEditor native text box which calls "storeValue(...)" and passes in the user-edited string. This ensures that standard item-level change handlers fire, and that a call to getValue() on the item, or form.getValues() picks up the user-entered values.

                        Having said all that, we've made the required changes to simplify this down and are hitting a mysterious error. We're still investigating but will follow up as soon as we have more information on this

                        Regards
                        Isomorphic Software

                        Comment


                          #27
                          We've spent some time on this and put together a reworked version of your class for you to use as a starting point.
                          The basic changes we've made are:

                          1) Rather than having an overridden constructor create and apply the CKEditor instance directly, we're making use of the "FormItemInitHandler" to do this when the live SmartClient form item is actually created. For various reasons, when loading your item from a .ui.xml file (as in your test case), this pattern is currently required in order to ensure the FormItem is actually intialized as expected in JavaScript when the code to associate with it runs.

                          2) We've got rid of any setValue() / getValue() overrides, and have set up the showValue() notification, and the storeValue() method calls properly to keep the user-visible ckEditor in synch with the logical "value" for the item.

                          Code:
                          import com.smartgwt.client.widgets.form.fields.CanvasItem;
                          import com.smartgwt.client.widgets.form.fields.FormItem;
                          import com.smartgwt.client.widgets.form.fields.events.FormItemInitHandler;
                          import com.smartgwt.client.widgets.form.fields.events.ShowValueEvent;
                          import com.smartgwt.client.widgets.form.fields.events.ShowValueHandler;
                          
                          public class CKEditorItem extends CanvasItem {
                          	private CKEditor editorCanvas;
                          
                          
                          	public CKEditorItem() {
                          		super();
                          		setInitHandler(new FormItemInitHandler() {
                          			
                          			@Override
                          			public void onInit(FormItem item) {
                          				String name = item.getName();
                          				editorCanvas = new CKEditor(name);
                          				
                          				((CKEditorItem)item).setCanvas(editorCanvas);
                          				item.setShouldSaveValue(true);
                          				
                          				
                          				addShowValueHandler( new ShowValueHandler() {
                          					@Override
                          					public void onShowValue(ShowValueEvent event) {
                          						Object value = event.getDataValue();
                          						String stringValue = value == null ? null : value.toString();
                          						((CKEditorItem) event.getItem()).setEditorValue(stringValue);
                          					}
                          				});
                          				
                          				editorCanvas.setCKEditorItem( (CKEditorItem)item );
                          				
                          			}
                          		});
                          	}
                          
                          	@Override
                          	public void setWidth(String width) {
                          		super.setWidth(width);
                          		if (editorCanvas != null) editorCanvas.setWidth(width);
                          	}
                          
                          	@Override
                          	public void setWidth(int width) {
                          		super.setWidth(width);
                          		if (editorCanvas != null) editorCanvas.setWidth(width);
                          	}
                          
                          	@Override
                          	public void setHeight(String height) {
                          		super.setHeight(height);
                          		if (editorCanvas != null) editorCanvas.setHeight(height);
                          	}
                          
                          	@Override
                          	public void setHeight(int height) {
                          		super.setHeight(height);
                          		if (editorCanvas != null) editorCanvas.setHeight(height);
                          	}
                          
                          	// internal helpers to set / get the CKEditor text-box value
                          	
                          	// Update CKEditor text-box.
                          	// Called from "showValue" handler
                          	public void setEditorValue(String value) {
                          		super.setValue(value);
                          		if (editorCanvas.isLoaded())
                          			setEditorValue(editorCanvas.getID() + "_ta", value);
                          		else
                          			editorCanvas.setContents(value);
                          	}
                          
                          	private native void setEditorValue(String id, String value) /*-{
                          		if ($wnd.CKEDITOR.instances[id]) {
                          			$wnd.CKEDITOR.instances[id].setData(value);
                          		}
                          	}-*/;
                          
                          	// Retrieve the current CKEditor text-box value
                          	// Called from "storeValue()" - triggered from the change handler on the
                          	// ckEditor
                          	public Object getEditorValue() {
                          		return getEditorValue(editorCanvas.getID() + "_ta");
                          	}
                          
                          	private native String getEditorValue(String id) /*-{
                          		if ($wnd.CKEDITOR.instances[id]) {
                          			return $wnd.CKEDITOR.instances[id].getData();
                          		}
                          
                          		return null;
                          	}-*/;
                          	
                          	// Zero argument version of "storeValue()" triggered from change handler on the 
                          	// ckEditor. This will call the standard "storeValue(Object value)" method to
                          	// store out the changed value.
                          	public void storeValue() {
                          		storeValue( getEditorValue() );
                          	}
                          	
                          	
                          }
                          We also had to fix the click handler on the button (applied in BuiltInDS.java) to pass in the correct field name - "itemName" - when retrieving the value for the rich text editor.
                          With these changes in place, if you type some characters and hit the "save" button, you should see the edited value being picked up properly.

                          Code:
                                          saveButton.addClickHandler(new ClickHandler() {   
                                              @Override  
                                              public void onClick(ClickEvent event) {   
                          
                                              	Object obj = saveForm.getValue("itemName");
                                              	
                                              	if ( null != obj ) {
                                              		SC.say( obj.toString() );
                                              	} else {
                                              		
                                              		SC.say(" can not get the value ");
                                              	}
                                              	//saveForm.saveData();
                                              }   
                                          });
                          Regards
                          Isomorphic Software

                          Comment


                            #28
                            Did you ever get this working? If so, could you please post your final working code? It would be great to have a working example of CKEditor implemented as a CanvasItem in SmartGWT.

                            Comment

                            Working...
                            X