Test to verify Knockout can handle String properties model
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 22 Jan 2013 21:57:27 +0100
branchmodel
changeset 5303ce069ec3312
parent 529 8140ba8c005b
child 531 35ed49f3c322
Test to verify Knockout can handle String properties
javaquery/api/pom.xml
javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/Knockout.java
javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java
javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java
javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnEvent.java
javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/KnockoutTest.java
javaquery/api/src/test/resources/org/apidesign/bck2brwsr/htmlpage/Knockout.xhtml
     1.1 --- a/javaquery/api/pom.xml	Tue Jan 22 19:27:00 2013 +0100
     1.2 +++ b/javaquery/api/pom.xml	Tue Jan 22 21:57:27 2013 +0100
     1.3 @@ -64,5 +64,11 @@
     1.4        <type>jar</type>
     1.5        <scope>test</scope>
     1.6      </dependency>
     1.7 +    <dependency>
     1.8 +      <groupId>${project.groupId}</groupId>
     1.9 +      <artifactId>vmtest</artifactId>
    1.10 +      <version>${project.version}</version>
    1.11 +      <scope>test</scope>
    1.12 +    </dependency>
    1.13    </dependencies>
    1.14  </project>
     2.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/Knockout.java	Tue Jan 22 19:27:00 2013 +0100
     2.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/Knockout.java	Tue Jan 22 21:57:27 2013 +0100
     2.3 @@ -17,8 +17,10 @@
     2.4   */
     2.5  package org.apidesign.bck2brwsr.htmlpage;
     2.6  
     2.7 +import java.lang.reflect.Method;
     2.8  import org.apidesign.bck2brwsr.core.ExtraJavaScript;
     2.9  import org.apidesign.bck2brwsr.core.JavaScriptBody;
    2.10 +import org.apidesign.bck2brwsr.htmlpage.api.Element;
    2.11  
    2.12  /** Provides binding between models and 
    2.13   *
    2.14 @@ -40,11 +42,17 @@
    2.15          if (bindings == null) {
    2.16              bindings = new Knockout();
    2.17          }
    2.18 -        for (int i = 0; i < propsGettersAndSetters.length; i += 3) {
    2.19 -            bind(bindings, model, propsGettersAndSetters[i],
    2.20 -                propsGettersAndSetters[i + 1],
    2.21 -                propsGettersAndSetters[i + 2]
    2.22 -            );
    2.23 +        for (int i = 0; i < propsGettersAndSetters.length; i += 4) {
    2.24 +            try {
    2.25 +                Method getter = modelClass.getMethod(propsGettersAndSetters[i + 3]);
    2.26 +                bind(bindings, model, propsGettersAndSetters[i],
    2.27 +                    propsGettersAndSetters[i + 1],
    2.28 +                    propsGettersAndSetters[i + 2],
    2.29 +                    getter.getReturnType().isPrimitive()
    2.30 +                );
    2.31 +            } catch (NoSuchMethodException ex) {
    2.32 +                Element.alert("Error: " + ex.getMessage());
    2.33 +            }
    2.34          }
    2.35          applyBindings(bindings);
    2.36          return bindings;
    2.37 @@ -56,7 +64,12 @@
    2.38      public void valueHasMutated(String prop) {
    2.39      }
    2.40      
    2.41 -    @JavaScriptBody(args = { "bindings", "model", "prop", "getter", "setter" }, body =
    2.42 +
    2.43 +    @JavaScriptBody(args = { "id", "ev" }, body = "ko.utils.triggerEvent(window.document.getElementById(id), ev.substring(2));")
    2.44 +    public static void triggerEvent(String id, String ev) {
    2.45 +    }
    2.46 +    
    2.47 +    @JavaScriptBody(args = { "bindings", "model", "prop", "getter", "setter", "primitive" }, body =
    2.48            "var bnd = {\n"
    2.49          + "  read: function() {\n"
    2.50          + "    var v = model[getter]();\n"
    2.51 @@ -66,13 +79,13 @@
    2.52          + "};\n"
    2.53          + "if (setter != null) {\n"
    2.54          + "  bnd.write = function(val) {\n"
    2.55 -        + "    model[setter](new Number(val));\n"
    2.56 +        + "    model[setter](primitive ? new Number(val) : val);\n"
    2.57          + "  };\n"
    2.58          + "}\n"
    2.59          + "bindings[prop] = ko.computed(bnd);"
    2.60      )
    2.61      private static void bind(
    2.62 -        Object bindings, Object model, String prop, String getter, String setter
    2.63 +        Object bindings, Object model, String prop, String getter, String setter, boolean primitive
    2.64      ) {
    2.65      }
    2.66      
     3.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java	Tue Jan 22 19:27:00 2013 +0100
     3.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/PageProcessor.java	Tue Jan 22 21:57:27 2013 +0100
     3.3 @@ -127,6 +127,10 @@
     3.4                              sep = ",\n";
     3.5                          }
     3.6                          w.write("\n  });\n  return this;\n}\n");
     3.7 +                        
     3.8 +                        w.write("public void triggerEvent(Element e, OnEvent ev) {\n");
     3.9 +                        w.write("  org.apidesign.bck2brwsr.htmlpage.Knockout.triggerEvent(e.getId(), ev.getElementPropertyName());\n");
    3.10 +                        w.write("}\n");
    3.11                      }
    3.12                      w.append("}\n");
    3.13                  } finally {
    3.14 @@ -329,6 +333,7 @@
    3.15              props.add(p.name());
    3.16              props.add(gs[2]);
    3.17              props.add(gs[3]);
    3.18 +            props.add(gs[0]);
    3.19          }
    3.20      }
    3.21  
    3.22 @@ -383,6 +388,7 @@
    3.23              props.add(e.getSimpleName().toString());
    3.24              props.add(gs[2]);
    3.25              props.add(null);
    3.26 +            props.add(gs[0]);
    3.27          }
    3.28          
    3.29          return true;
     4.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java	Tue Jan 22 19:27:00 2013 +0100
     4.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/Element.java	Tue Jan 22 21:57:27 2013 +0100
     4.3 @@ -30,6 +30,13 @@
     4.4          this.id = id;
     4.5      }
     4.6      
     4.7 +    /** Id of the element in the document.
     4.8 +     * @return the id for this element
     4.9 +     */
    4.10 +    public String getId() {
    4.11 +        return id;
    4.12 +    }
    4.13 +    
    4.14      abstract void dontSubclass();
    4.15      
    4.16      @JavaScriptBody(
     5.1 --- a/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnEvent.java	Tue Jan 22 19:27:00 2013 +0100
     5.2 +++ b/javaquery/api/src/main/java/org/apidesign/bck2brwsr/htmlpage/api/OnEvent.java	Tue Jan 22 21:57:27 2013 +0100
     5.3 @@ -26,6 +26,7 @@
     5.4      BLUR("onblur"),
     5.5      CAN_PLAY("oncanplay"),
     5.6      CAN_PLAY_THROUGH("oncanplaythrough"),
     5.7 +    CHANGE("onchange"),
     5.8      CLICK("onclick"),
     5.9      CONTEXT_MENU("oncontextmenu"),
    5.10      DBL_CLICK("ondblclick"),
    5.11 @@ -82,6 +83,13 @@
    5.12          this.id = id;
    5.13      }
    5.14      
    5.15 +    /** The name of property this event is referenced by from an {@link Element}.
    5.16 +     * For {@link OnEvent#CHANGE}, it is <code>onchange</code>.
    5.17 +     */
    5.18 +    public String getElementPropertyName() {
    5.19 +        return id;
    5.20 +    }
    5.21 +    
    5.22      /** What should happen when this even happen on one
    5.23       * of associated elements. Continue by calling {@link OnController#perform(java.lang.Runnable)}
    5.24       * method.
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/javaquery/api/src/test/java/org/apidesign/bck2brwsr/htmlpage/KnockoutTest.java	Tue Jan 22 21:57:27 2013 +0100
     6.3 @@ -0,0 +1,62 @@
     6.4 +/**
     6.5 + * Back 2 Browser Bytecode Translator
     6.6 + * Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     6.7 + *
     6.8 + * This program is free software: you can redistribute it and/or modify
     6.9 + * it under the terms of the GNU General Public License as published by
    6.10 + * the Free Software Foundation, version 2 of the License.
    6.11 + *
    6.12 + * This program is distributed in the hope that it will be useful,
    6.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    6.15 + * GNU General Public License for more details.
    6.16 + *
    6.17 + * You should have received a copy of the GNU General Public License
    6.18 + * along with this program. Look for COPYING file in the top folder.
    6.19 + * If not, see http://opensource.org/licenses/GPL-2.0.
    6.20 + */
    6.21 +package org.apidesign.bck2brwsr.htmlpage;
    6.22 +
    6.23 +import org.apidesign.bck2brwsr.htmlpage.api.ComputedProperty;
    6.24 +import org.apidesign.bck2brwsr.htmlpage.api.OnEvent;
    6.25 +import org.apidesign.bck2brwsr.htmlpage.api.Page;
    6.26 +import org.apidesign.bck2brwsr.htmlpage.api.Property;
    6.27 +import org.apidesign.bck2brwsr.vmtest.BrwsrTest;
    6.28 +import org.apidesign.bck2brwsr.vmtest.HtmlFragment;
    6.29 +import org.apidesign.bck2brwsr.vmtest.VMTest;
    6.30 +import org.testng.annotations.Factory;
    6.31 +
    6.32 +/**
    6.33 + *
    6.34 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    6.35 + */
    6.36 +@Page(xhtml="Knockout.xhtml", className="KnockoutModel", properties={
    6.37 +    @Property(name="name", type=String.class)
    6.38 +}) 
    6.39 +public class KnockoutTest {
    6.40 +    
    6.41 +    @HtmlFragment(
    6.42 +        "<h1 data-bind=\"text: helloMessage\">Loading Bck2Brwsr's Hello World...</h1>\n" +
    6.43 +        "Your name: <input id='input' data-bind=\"value: name\"></input>\n" +
    6.44 +        "<button id=\"hello\">Say Hello!</button>\n"
    6.45 +    )
    6.46 +    @BrwsrTest public void modifyValueAssertChangeInModel() {
    6.47 +        KnockoutModel m = new KnockoutModel();
    6.48 +        m.setName("Kukuc");
    6.49 +        m.applyBindings();
    6.50 +        assert "Kukuc".equals(m.INPUT.getValue()) : "Value is really kukuc: " + m.INPUT.getValue();
    6.51 +        m.INPUT.setValue("Jardo");
    6.52 +        m.triggerEvent(m.INPUT, OnEvent.CHANGE);
    6.53 +        assert "Jardo".equals(m.getName()) : "Name property updated: " + m.getName();
    6.54 +    }
    6.55 +    
    6.56 +    @ComputedProperty
    6.57 +    static String helloMessage(String name) {
    6.58 +        return "Hello " + name + "!";
    6.59 +    }
    6.60 +    
    6.61 +    @Factory
    6.62 +    public static Object[] create() {
    6.63 +        return VMTest.create(KnockoutTest.class);
    6.64 +    }
    6.65 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/javaquery/api/src/test/resources/org/apidesign/bck2brwsr/htmlpage/Knockout.xhtml	Tue Jan 22 21:57:27 2013 +0100
     7.3 @@ -0,0 +1,25 @@
     7.4 +<?xml version="1.0" encoding="UTF-8"?>
     7.5 +<!--
     7.6 +
     7.7 +    Back 2 Browser Bytecode Translator
     7.8 +    Copyright (C) 2012 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     7.9 +
    7.10 +    This program is free software: you can redistribute it and/or modify
    7.11 +    it under the terms of the GNU General Public License as published by
    7.12 +    the Free Software Foundation, version 2 of the License.
    7.13 +
    7.14 +    This program is distributed in the hope that it will be useful,
    7.15 +    but WITHOUT ANY WARRANTY; without even the implied warranty of
    7.16 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    7.17 +    GNU General Public License for more details.
    7.18 +
    7.19 +    You should have received a copy of the GNU General Public License
    7.20 +    along with this program. Look for COPYING file in the top folder.
    7.21 +    If not, see http://opensource.org/licenses/GPL-2.0.
    7.22 +
    7.23 +-->
    7.24 +<p>
    7.25 +    <h1 data-bind="text: helloMessage">Loading Bck2Brwsr's Hello World...</h1>
    7.26 +    Your name: <input id="input" data-bind="value: name, valueUpdate: 'afterkeydown'"></input>
    7.27 +    <button id="hello">Say Hello!</button>
    7.28 +</p>