views:

46

answers:

2

Hi. I am writing a pretty simple CMS on GAE, and I want my users to be able to upload images. I have written the part that does the actual uploading and showing the images, and here's what I'd like to do:

Show the usual form for new posts (with a widget that contains a rich text area and a format bar for it) and the list of images the user has ever uploaded (done). Then i want an image to appear in the text area when the user clicks that image.

I generate the list of images on the server, and i can't find a way to call any methods on the Rich Text Area from non-GWT javascript. And I don't really want to generate the list of images by means of AJAX, because it seems quite cumbersome and, hopefully, with the advent of HTML5 it is going to be much simpler.

Well, the question is, how can i access a RichTextArea in a widget from a normal javascript on a page, or is there another way of inserting an image into it (i.e. another is there a way to generate a list of images so that they would be in a kind of widget, but without the use of AJAX).

Thank you.

+1  A: 

To answer your general question of getting access to your GWT code from hand written Javascript, you can use the general built in method or Ray Cromwell's gwt-exporter project. This way, you can expose the specific methods of the RichTextArea instance you're trying to access from external Javascript.

As for your other question, generating a list of Images should only require getting the urls for the images and creating a bunch of Image objects with the given URLs. Then display this list in a PopupPanel or some other widget.

Arthur Kalmenson
+1  A: 

Here is how i finally solved the problem (thanks to Arthur's reply above):

public class NewSection implements EntryPoint {
    private static RichTextAreaWithFormatBar rta;
    private Button                    pseudoSubmit;

    @Override
    public void onModuleLoad() {
        invokeExternal("hello");

        rta = new RichTextAreaWithFormatBar();
        pseudoSubmit = new Button(">>>");
        <...>
    }


<some other code here>
    public static void addImage(String a) {
        rta.textarea().setHTML(
                rta.textarea().getHTML() + "<br /><img src=\"/cms/i/"+ a +"\" alt=\"\"><br />");
    }

    native void invokeExternal(String int1) /*-{
        $wnd.externalJsFunction(function(int1) {
            @ur.g05.smc.client.NewSection::addImage(Ljava/lang/String;)(int1);
        });
    }-*/;
}

And here is the "hand-written" javascript in my templates:

(first the FreeMaker code for creating the image list in that same template):

<#list images as i>
            <td><img src="/cms/i/${i.keyString()}.t" alt='' onclick='addImage("${i.keyString()}.p");'/><br /><p>${i.fullWidth()}·${i.fullHeight()}</p><p>${i.previewWidth()}·${i.previewHeight()}</p><p>${i.thumbWidth()}·${i.thumbHeight()}</p></td>
        </#list>

And the script itself:

    <script language="javascript">
        var callBackFunction; 
        function externalJsFunction(func) {
            callBackFunction = func;
        }

        function addImage(imgid) {
            callBackFunction(imgid);
        }


    </script>

What in fact happens is: First we create a list of images, adding an "onClick" listener to each of them with the url of each corresponding image as the argument. Image urls are formed from their Keys in the datastore, plus ".t" for thumbnails, ".p" for previews and nothing for full-size images.

Each image than calls the "addImage" function. But the addImage function has to know about the textarea, which it doesn't. To that end we create the "callBackFunction" variable, and the "externalJsFunction", that sets the value of that "callBackFunction" variable. And it sets it to whatever it gets as the argument.

Now, we can call that externalJsFunction from our Widget code and pass the function that adds an image to the textarea. However, i couldn't make it work while the richtextarea was not static.

That's basically it. And thanks for replies and votes :)

Ibolit