Search code examples
gwtiframerichtextboxjsni

How to adjust height of richtextbox dynamically based on inner content?


public class AutoResizeBox extends RichTextArea
{
    public AutoResizeBox()
    {
       set(getElement());
    }

   public static native void set(Element f) /*-{
       console.log(f.tagName) ;
         // console.log(f.document.body.scrollHeight + 'px');
   }-*/;
}

RichTextBox is based on iframe,I tried to use JSNI.For above code,"console.log(f.tagName)" will print out "IFRAME",but "console.log(f.document.body.scrollHeight + 'px');" will preduce a compilation error:" com.google.gwt.core.client.JavaScriptException: (TypeError): f.document is undefined", can anybody tell me reasons?


Solution

  • Blow is a worked version

    import com.google.gwt.dom.client.BodyElement;
    import com.google.gwt.event.dom.client.BlurEvent;
    import com.google.gwt.event.dom.client.BlurHandler;
    import com.google.gwt.event.dom.client.ClickEvent;
    import com.google.gwt.event.dom.client.ClickHandler;
    import com.google.gwt.user.client.DOM;
    import com.google.gwt.user.client.Event;
    import com.google.gwt.user.client.ui.RichTextArea;
    import com.google.inject.Inject;
    
    public class AutoResizeTextArea extends RichTextArea implements ClickHandler,
         BlurHandler
    {
    private static final int margin = 6;
    private BodyElement body;
    private String defaultText;
    private int minHeight = 25;
    private String title;
    
    @Inject
    public AutoResizeTextArea()
    {
        addBlurHandler(this);
        addClickHandler(this);
        setHeight(minHeight + "px");
        setStyleName("textArea");
        sinkEvents(Event.ONKEYUP | Event.ONKEYPRESS);
    }
    
    private void adjustHeight()
    {
        // NP remove blow will cause auto-grow doesn't work
        if (body != null)
        {
            int offsetHeight = body.getOffsetHeight();
            if (offsetHeight != body.getClientHeight())
            {
                int height = (offsetHeight < minHeight ? minHeight : offsetHeight);
                boolean breaking = height > minHeight;
                if (breaking)
                {
                    height = height + margin * 2;
                }
                setHeight(height + "px");
            }
        }
    }
    
    public void clean()
    {
        setText(defaultText);
        setHeight(minHeight + "px");
        setBodyStyle(true);
    }
    
    @Override
    public String getHTML()
    {
        // AP RichTextArea.getHTML will return "<br>",even no html exists
        // within it,report this issue to gwt team;
        String html = super.getHTML();
        return html.equals("<br>") || html.equals(defaultText) ? "" : html;
    }
    
    @Override
    public String getText()
    {
        String text = super.getText();
        return text.equals(defaultText) ? "" : text;
    }
    
    @Override
    public void onBlur(BlurEvent event)
    {
        if (defaultText != null && "".equals(getText()))
        {
            setDefaultText(defaultText);
            setBodyStyle(true);
        }
    }
    
    @Override
    public void onBrowserEvent(Event event)
    {
        super.onBrowserEvent(event);
        int eventType = DOM.eventGetType(event);
        if (eventType == Event.ONKEYUP || eventType == Event.ONKEYPRESS)
        {
            adjustHeight();
        }
    }
    
    @Override
    public void onClick(ClickEvent event)
    {
    
        super.setText(null);
        setBodyStyle(false);
    }
    
    private native void registerOnCut(BodyElement element) /*-{
        var that = this;
        console.log("registerOnCut");
        element.oncut = $entry(function(event) {
            [email protected]::adjustHeight()();
            return false;
        });
        element.onpaste = $entry(function(event) {
            [email protected]::adjustHeight()();
            return false;
        });
    }-*/;
    
    private void setBodyStyle(boolean useDefaultTextStyle)
    {
        if (body != null)
        {
            body.setAttribute(  "style",
                                (useDefaultTextStyle ? "color: gray;font-style: italic;" : "")
                                        + "word-wrap:break-word;overflow:hidden;margin: "
                                        + margin
                                        + "px;padding: 0;font-size: 13px;font-family: arial,\"Microsoft YaHei\", Verdana, Tahoma, Arial, STHeiTi,sans-serif, Simsun;");
        }
    }
    
    public void setDefaultText(String defaultText)
    {
        super.setText(this.defaultText = defaultText);
    }
    
    
    @Override
    public void setHTML(String html)
    {
        super.setHTML(html);
        if (html == null || "".equals(html))
        {
            setDefaultText(defaultText);
        }
        adjustHeight();
    }
    
    
    public void setMinHeight(int minHeight)
    {
        setHeight((this.minHeight = minHeight) + "px");
    }
    
    @Override
    public void setText(String text)
    {
        super.setText(text);
        if (text == null || "".equals(text))
        {
            setDefaultText(defaultText);
        }
    }
    
    @Override
    public void setTitle(String title)
    {
        this.title = title;
    }
    }