#249319: targetId and an ability to apply bindings to specific element on the HTML page
1.1 --- a/json-tck/src/main/java/net/java/html/json/tests/GCKnockoutTest.java Thu Dec 18 09:22:47 2014 +0100
1.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/GCKnockoutTest.java Fri Dec 19 10:57:23 2014 +0100
1.3 @@ -71,7 +71,7 @@
1.4 try {
1.5 GC m = Models.bind(new GC(), ctx);
1.6 m.getAll().add(new Fullname("Jarda", "Tulach"));
1.7 - m.applyBindings();
1.8 + Models.applyBindings(m);
1.9
1.10 int cnt = Utils.countChildren(GCKnockoutTest.class, "ul");
1.11 assert cnt == 1 : "One child, but was " + cnt;
2.1 --- a/json-tck/src/main/java/net/java/html/json/tests/JSONTest.java Thu Dec 18 09:22:47 2014 +0100
2.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/JSONTest.java Fri Dec 19 10:57:23 2014 +0100
2.3 @@ -57,7 +57,7 @@
2.4 *
2.5 * @author Jaroslav Tulach
2.6 */
2.7 -@Model(className = "JSONik", properties = {
2.8 +@Model(className = "JSONik", targetId = "", properties = {
2.9 @Property(name = "fetched", type = Person.class),
2.10 @Property(name = "fetchedCount", type = int.class),
2.11 @Property(name = "fetchedResponse", type = String.class),
3.1 --- a/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java Thu Dec 18 09:22:47 2014 +0100
3.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/KnockoutTest.java Fri Dec 19 10:57:23 2014 +0100
3.3 @@ -58,7 +58,7 @@
3.4 *
3.5 * @author Jaroslav Tulach
3.6 */
3.7 -@Model(className="KnockoutModel", properties={
3.8 +@Model(className="KnockoutModel", targetId = "", properties={
3.9 @Property(name="name", type=String.class),
3.10 @Property(name="results", type=String.class, array = true),
3.11 @Property(name="numbers", type=int.class, array = true),
4.1 --- a/json-tck/src/main/java/net/java/html/json/tests/MinesTest.java Thu Dec 18 09:22:47 2014 +0100
4.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/MinesTest.java Fri Dec 19 10:57:23 2014 +0100
4.3 @@ -57,7 +57,7 @@
4.4
4.5 /** Tests model of a mine field and its behavior in the browser.
4.6 */
4.7 -@Model(className = "Mines", properties = {
4.8 +@Model(className = "Mines", targetId = "", properties = {
4.9 @Property(name = "state", type = MinesTest.GameState.class),
4.10 @Property(name = "rows", type = Row.class, array = true),
4.11 })
5.1 --- a/json-tck/src/main/java/net/java/html/json/tests/PairModel.java Thu Dec 18 09:22:47 2014 +0100
5.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/PairModel.java Fri Dec 19 10:57:23 2014 +0100
5.3 @@ -54,7 +54,7 @@
5.4 *
5.5 * @author Jaroslav Tulach
5.6 */
5.7 -@Model(className = "Pair", properties = {
5.8 +@Model(className = "Pair", targetId = "", properties = {
5.9 @Property(name = "firstName", type = String.class),
5.10 @Property(name = "lastName", type = String.class),
5.11 @Property(name = "next", type = Pair.class)
6.1 --- a/json-tck/src/main/java/net/java/html/json/tests/WebSocketTest.java Thu Dec 18 09:22:47 2014 +0100
6.2 +++ b/json-tck/src/main/java/net/java/html/json/tests/WebSocketTest.java Fri Dec 19 10:57:23 2014 +0100
6.3 @@ -53,7 +53,7 @@
6.4 *
6.5 * @author Jaroslav Tulach
6.6 */
6.7 -@Model(className = "WebSocketik", properties = {
6.8 +@Model(className = "WebSocketik", targetId="", properties = {
6.9 @Property(name = "fetched", type = Person.class),
6.10 @Property(name = "fetchedCount", type = int.class),
6.11 @Property(name = "open", type = int.class),
7.1 --- a/json/src/main/java/net/java/html/json/Model.java Thu Dec 18 09:22:47 2014 +0100
7.2 +++ b/json/src/main/java/net/java/html/json/Model.java Fri Dec 19 10:57:23 2014 +0100
7.3 @@ -48,6 +48,7 @@
7.4 import java.lang.annotation.Target;
7.5 import java.net.URL;
7.6 import java.util.List;
7.7 +import org.netbeans.html.json.spi.Technology;
7.8
7.9 /** Defines a model class that represents a single
7.10 * <a target="_blank" href="http://en.wikipedia.org/wiki/JSON">JSON</a>-like object
7.11 @@ -122,7 +123,7 @@
7.12 * <p>
7.13 * In case you are using <a target="_blank" href="http://knockoutjs.com/">Knockout technology</a>
7.14 * for Java then you can associate such model object with surrounding HTML page by
7.15 - * calling: <code>p.applyBindings();</code>. The page can then use regular
7.16 + * calling: <code>p.applyBindings();</code> (in case you specify {@link #tar. The page can then use regular
7.17 * <a target="_blank" href="http://knockoutjs.com/">Knockout</a> bindings to reference your
7.18 * model and create dynamic connection between your model in Java and
7.19 * live DOM structure in the browser:
7.20 @@ -202,4 +203,22 @@
7.21 * @return array of property definitions
7.22 */
7.23 Property[] properties();
7.24 +
7.25 + /** The id of an element to bind this model too. If this
7.26 + * property is specified an <code>applyBindings</code> method
7.27 + * in the model class is going to be generated which later calls
7.28 + * {@link Models#applyBindings(java.lang.Object, java.lang.String)}
7.29 + * with appropriate <code>targetId</code>. If the <code>targetId</code>
7.30 + * is specified as empty string, <code>null</code> value is passed
7.31 + * to {@link Models#applyBindings(java.lang.Object, java.lang.String)} method.
7.32 + * If the <code>targetId</code> is not specified at all, no public
7.33 + * <code>applyBindings</code> method is generated at all (a change compared
7.34 + * to previous versions of this API).
7.35 + *
7.36 + * @return an empty string (means apply globally), or ID of a (usually DOM)
7.37 + * element to apply this model after calling its generated
7.38 + * <code>applyBindings()</code> method to
7.39 + * @since 1.1
7.40 + */
7.41 + String targetId() default "";
7.42 }
8.1 --- a/json/src/main/java/net/java/html/json/Models.java Thu Dec 18 09:22:47 2014 +0100
8.2 +++ b/json/src/main/java/net/java/html/json/Models.java Fri Dec 19 10:57:23 2014 +0100
8.3 @@ -150,11 +150,8 @@
8.4 return JSON.find(model);
8.5 }
8.6
8.7 - /** Apply bindings of a model class. Each model class has an
8.8 - * apply bindings method that "activates" it. In <em>ko4j</em> mode,
8.9 - * it binds the model values to the currently active page. One
8.10 - * can call the generated method directly, or use this static
8.11 - * helper method to perform the activation.
8.12 + /** Apply bindings of a model class to overall page. In <em>ko4j</em> mode,
8.13 + * it binds the model values to the currently active page.
8.14 *
8.15 * @param model instance of a {@link Model class}
8.16 * @throws IllegalArgumentException if the <code>model</code> is not
8.17 @@ -164,6 +161,22 @@
8.18 * @since 0.7
8.19 */
8.20 public static void applyBindings(Object model) {
8.21 - JSON.applyBindings(model);
8.22 + JSON.applyBindings(model, null);
8.23 + }
8.24 +
8.25 +
8.26 + /** Apply bindings of a model class. In <em>ko4j</em> mode,
8.27 + * it binds the model values to an element on currently active page.
8.28 + *
8.29 + * @param model instance of a {@link Model class}
8.30 + * @param targetId the id of the element to apply the binding to
8.31 + * @throws IllegalArgumentException if the <code>model</code> is not
8.32 + * instance of a class generated by {@link Model model annotation}
8.33 + * processor.
8.34 + *
8.35 + * @since 1.1
8.36 + */
8.37 + public static void applyBindings(Object model, String targetId) {
8.38 + JSON.applyBindings(model, targetId);
8.39 }
8.40 }
9.1 --- a/json/src/main/java/org/netbeans/html/json/impl/Bindings.java Thu Dec 18 09:22:47 2014 +0100
9.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/Bindings.java Fri Dec 19 10:57:23 2014 +0100
9.3 @@ -42,6 +42,8 @@
9.4 */
9.5 package org.netbeans.html.json.impl;
9.6
9.7 +import java.util.logging.Level;
9.8 +import java.util.logging.Logger;
9.9 import net.java.html.BrwsrCtx;
9.10 import org.netbeans.html.json.spi.FunctionBinding;
9.11 import org.netbeans.html.json.spi.PropertyBinding;
9.12 @@ -53,6 +55,8 @@
9.13 * @author Jaroslav Tulach
9.14 */
9.15 public final class Bindings<Data> {
9.16 + private static final Logger LOG = Logger.getLogger(Bindings.class.getName());
9.17 +
9.18 private Data data;
9.19 private final Technology<Data> bp;
9.20
9.21 @@ -105,7 +109,18 @@
9.22 }
9.23 }
9.24
9.25 - public void applyBindings() {
9.26 + public void applyBindings(String id) {
9.27 + if (bp instanceof Technology.ApplyId) {
9.28 + Technology.ApplyId<Data> ai = (Technology.ApplyId<Data>) bp;
9.29 + ai.applyBindings(id, data);
9.30 + return;
9.31 + }
9.32 + if (id != null) {
9.33 + LOG.log(Level.WARNING,
9.34 + "Technology {0} does not implement ApplyId extension. Can't apply to {1}. Applying globally.",
9.35 + new Object[]{bp, id}
9.36 + );
9.37 + }
9.38 bp.applyBindings(data);
9.39 }
9.40
10.1 --- a/json/src/main/java/org/netbeans/html/json/impl/JSON.java Thu Dec 18 09:22:47 2014 +0100
10.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/JSON.java Fri Dec 19 10:57:23 2014 +0100
10.3 @@ -296,12 +296,12 @@
10.4 return find(object, null);
10.5 }
10.6
10.7 - public static void applyBindings(Object object) {
10.8 + public static void applyBindings(Object object, String id) {
10.9 final Proto proto = findProto(object);
10.10 if (proto == null) {
10.11 throw new IllegalArgumentException("Not a model: " + object.getClass());
10.12 }
10.13 - proto.applyBindings();
10.14 + proto.applyBindings(id);
10.15 }
10.16
10.17 public static void loadJSON(
11.1 --- a/json/src/main/java/org/netbeans/html/json/impl/JSONList.java Thu Dec 18 09:22:47 2014 +0100
11.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/JSONList.java Fri Dec 19 10:57:23 2014 +0100
11.3 @@ -179,7 +179,7 @@
11.4 public void run() {
11.5 Bindings m = PropertyBindingAccessor.getBindings(proto, false);
11.6 if (m != null) {
11.7 - m.valueHasMutated(name, null, null);
11.8 + m.valueHasMutated(name, null, JSONList.this);
11.9 for (String dependant : deps) {
11.10 m.valueHasMutated(dependant, null, null);
11.11 }
12.1 --- a/json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java Thu Dec 18 09:22:47 2014 +0100
12.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java Fri Dec 19 10:57:23 2014 +0100
12.3 @@ -499,17 +499,31 @@
12.4 w.append(" }\n");
12.5 writeToString(props, w);
12.6 writeClone(className, props, w);
12.7 - w.write(" /** Activates this model instance in the current {@link \n"
12.8 - + "net.java.html.json.Models#bind(java.lang.Object, net.java.html.BrwsrCtx) browser context}. \n"
12.9 - + "In case of using Knockout technology, this means to \n"
12.10 - + "bind JSON like data in this model instance with Knockout tags in \n"
12.11 - + "the surrounding HTML page.\n"
12.12 - + "*/\n"
12.13 - );
12.14 - w.write(" public " + className + " applyBindings() {\n");
12.15 - w.write(" proto.applyBindings();\n");
12.16 - w.write(" return this;\n");
12.17 - w.write(" }\n");
12.18 + String targetId = findTargetId(e);
12.19 + if (targetId != null) {
12.20 + w.write(" /** Activates this model instance in the current {@link \n"
12.21 + + "net.java.html.json.Models#bind(java.lang.Object, net.java.html.BrwsrCtx) browser context}. \n"
12.22 + + "In case of using Knockout technology, this means to \n"
12.23 + + "bind JSON like data in this model instance with Knockout tags in \n"
12.24 + + "the surrounding HTML page.\n"
12.25 + );
12.26 + if (targetId != null) {
12.27 + w.write("This method binds to element '" + targetId + "' on the page\n");
12.28 + }
12.29 + w.write(""
12.30 + + "@return <code>this</code> object\n"
12.31 + + "*/\n"
12.32 + );
12.33 + w.write(" public " + className + " applyBindings() {\n");
12.34 + w.write(" proto.applyBindings();\n");
12.35 + // w.write(" proto.applyBindings(id);\n");
12.36 + w.write(" return this;\n");
12.37 + w.write(" }\n");
12.38 + } else {
12.39 + w.write(" private " + className + " applyBindings() {\n");
12.40 + w.write(" throw new IllegalStateException(\"Please specify targetId=\\\"\\\" in your @Model annotation\");\n");
12.41 + w.write(" }\n");
12.42 + }
12.43 w.write(" public boolean equals(Object o) {\n");
12.44 w.write(" if (o == this) return true;\n");
12.45 w.write(" if (!(o instanceof " + className + ")) return false;\n");
12.46 @@ -1757,6 +1771,21 @@
12.47 }
12.48 }
12.49
12.50 + private static String findTargetId(Element e) {
12.51 + for (AnnotationMirror m : e.getAnnotationMirrors()) {
12.52 + if (m.getAnnotationType().toString().equals(Model.class.getName())) {
12.53 + for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entrySet : m.getElementValues().entrySet()) {
12.54 + ExecutableElement key = entrySet.getKey();
12.55 + AnnotationValue value = entrySet.getValue();
12.56 + if ("targetId()".equals(key.toString())) {
12.57 + return value.toString();
12.58 + }
12.59 + }
12.60 + }
12.61 + }
12.62 + return null;
12.63 + }
12.64 +
12.65 private static class Prprt {
12.66 private final Element e;
12.67 private final AnnotationMirror tm;
13.1 --- a/json/src/main/java/org/netbeans/html/json/spi/Proto.java Thu Dec 18 09:22:47 2014 +0100
13.2 +++ b/json/src/main/java/org/netbeans/html/json/spi/Proto.java Fri Dec 19 10:57:23 2014 +0100
13.3 @@ -193,7 +193,21 @@
13.4 * of the current model to the <em>body</em> element of the page.
13.5 */
13.6 public void applyBindings() {
13.7 - initBindings().applyBindings();
13.8 + initBindings().applyBindings(null);
13.9 + }
13.10 +
13.11 + /** Initializes the associated model to the specified element's subtree.
13.12 + * The technology is taken from the current {@link #getContext() context} and
13.13 + * in case of <em>knockout.js</em> applies given bindings
13.14 + * of the current model to the element of the page with 'id' attribute
13.15 + * set to the specified <code>id</code> value.
13.16 + *
13.17 + * @param id the id of element to apply the binding to
13.18 + * @since 1.1
13.19 + * @see Technology.ApplyId
13.20 + */
13.21 + public void applyBindings(String id) {
13.22 + initBindings().applyBindings(id);
13.23 }
13.24
13.25 /** Invokes the provided runnable in the {@link #getContext() context}
14.1 --- a/json/src/main/java/org/netbeans/html/json/spi/Technology.java Thu Dec 18 09:22:47 2014 +0100
14.2 +++ b/json/src/main/java/org/netbeans/html/json/spi/Technology.java Fri Dec 19 10:57:23 2014 +0100
14.3 @@ -173,4 +173,22 @@
14.4 */
14.5 public void valueHasMutated(D data, String propertyName, Object oldValue, Object newValue);
14.6 }
14.7 +
14.8 + /** Apply technology bindings at selected subtree of the HTML page.
14.9 + * Can be accessed via {@link Proto#applyBindings(java.lang.String)} or
14.10 + * via method <code>applyBindings(String)</code> generated when one
14.11 + * is using the {@link Model} annotation.
14.12 + *
14.13 + * @param <D> the internal data for the technology
14.14 + * @since 1.1
14.15 + */
14.16 + public static interface ApplyId<D> extends Technology<D> {
14.17 + /** Applies given data to current context (usually an element on an
14.18 + * HTML page).
14.19 + *
14.20 + * @param id the id of an element to apply the data to
14.21 + * @param data the data to apply
14.22 + */
14.23 + public void applyBindings(String id, D data);
14.24 + }
14.25 }
15.1 --- a/json/src/test/java/net/java/html/json/MapModelTest.java Thu Dec 18 09:22:47 2014 +0100
15.2 +++ b/json/src/test/java/net/java/html/json/MapModelTest.java Fri Dec 19 10:57:23 2014 +0100
15.3 @@ -74,8 +74,20 @@
15.4 register(Transfer.class, t, 1).build();
15.5 }
15.6
15.7 + @Test public void isThereNoApplyBinding() throws Exception {
15.8 + try {
15.9 + Person.class.getMethod("applyBindings");
15.10 + } catch (NoSuchMethodException ex) {
15.11 + // OK
15.12 + return;
15.13 + }
15.14 + fail("There should be no applyBindings() method");
15.15 + }
15.16 +
15.17 @Test public void isThereABinding() throws Exception {
15.18 - Person p = Models.bind(new Person(), c).applyBindings();
15.19 + Person p = Models.bind(new Person(), c);
15.20 + Models.applyBindings(p);
15.21 + assertNull(t.appliedId, "Applied globally");
15.22 p.setFirstName("Jarda");
15.23
15.24 Map m = (Map)Models.toRaw(p);
15.25 @@ -94,6 +106,11 @@
15.26 assertEquals(o.changes, 2, "Snd change");
15.27 }
15.28
15.29 + @Test public void applyLocally() throws Exception {
15.30 + Person p = Models.bind(new Person(), c);
15.31 + Models.applyBindings(p, "local");
15.32 + assertEquals(t.appliedId, "local", "Applied locally");
15.33 + }
15.34
15.35 @Test public void dontNotifySameProperty() throws Exception {
15.36 Person p = Models.bind(new Person(), c);
15.37 @@ -293,7 +310,9 @@
15.38 }
15.39
15.40 static final class MapTechnology
15.41 - implements Technology<Map<String,One>>, Transfer {
15.42 + implements Technology.ApplyId<Map<String,One>>, Transfer {
15.43 + private Map<String, One> appliedData;
15.44 + private String appliedId;
15.45
15.46 @Override
15.47 public Map<String, One> wrapModel(Object model) {
15.48 @@ -329,6 +348,7 @@
15.49
15.50 @Override
15.51 public void applyBindings(Map<String, One> data) {
15.52 + throw new UnsupportedOperationException("Never called!");
15.53 }
15.54
15.55 @Override
15.56 @@ -370,5 +390,11 @@
15.57 public void runSafe(Runnable r) {
15.58 throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
15.59 }
15.60 +
15.61 + @Override
15.62 + public void applyBindings(String id, Map<String, One> data) {
15.63 + this.appliedId = id;
15.64 + this.appliedData = data;
15.65 + }
15.66 }
15.67 }
16.1 --- a/json/src/test/java/net/java/html/json/ModelTest.java Thu Dec 18 09:22:47 2014 +0100
16.2 +++ b/json/src/test/java/net/java/html/json/ModelTest.java Fri Dec 19 10:57:23 2014 +0100
16.3 @@ -60,7 +60,7 @@
16.4 *
16.5 * @author Jaroslav Tulach
16.6 */
16.7 -@Model(className = "Modelik", properties = {
16.8 +@Model(className = "Modelik", targetId = "", properties = {
16.9 @Property(name = "value", type = int.class),
16.10 @Property(name = "count", type = int.class),
16.11 @Property(name = "unrelated", type = long.class),
17.1 --- a/json/src/test/java/net/java/html/json/PersonImpl.java Thu Dec 18 09:22:47 2014 +0100
17.2 +++ b/json/src/test/java/net/java/html/json/PersonImpl.java Fri Dec 19 10:57:23 2014 +0100
17.3 @@ -92,7 +92,7 @@
17.4 }
17.5 }
17.6
17.7 - @Model(className = "People", properties = {
17.8 + @Model(className = "People", targetId="myPeople", properties = {
17.9 @Property(array = true, name = "info", type = Person.class),
17.10 @Property(array = true, name = "nicknames", type = String.class),
17.11 @Property(array = true, name = "age", type = int.class),
18.1 --- a/json/src/test/java/org/netbeans/html/json/impl/DeepChangeTest.java Thu Dec 18 09:22:47 2014 +0100
18.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/DeepChangeTest.java Fri Dec 19 10:57:23 2014 +0100
18.3 @@ -77,7 +77,7 @@
18.4 register(Transfer.class, t, 1).build();
18.5 }
18.6
18.7 - @Model(className = "MyX", properties = {
18.8 + @Model(className = "MyX", targetId = "anythingX", properties = {
18.9 @Property(name = "one", type = MyY.class),
18.10 @Property(name = "all", type = MyY.class, array = true)
18.11 })
18.12 @@ -253,7 +253,8 @@
18.13 @Test public void firstChangeInArrayNotifiedTransitively() throws Exception {
18.14 MyOverall p = Models.bind(
18.15 new MyOverall(new MyX(new MyY("Ahoj", 0), new MyY("Hi", 333), new MyY("Hello", 999))
18.16 - ), c).applyBindings();
18.17 + ), c);
18.18 + Models.applyBindings(p);
18.19
18.20 Map m = (Map)Models.toRaw(p);
18.21 Object v = m.get("valueAccross");
19.1 --- a/json/src/test/java/org/netbeans/html/json/impl/EmployerTest.java Thu Dec 18 09:22:47 2014 +0100
19.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/EmployerTest.java Fri Dec 19 10:57:23 2014 +0100
19.3 @@ -60,6 +60,6 @@
19.4 @Test public void preLoadsTheClass() {
19.5 Employer em = Models.fromRaw(BrwsrCtx.EMPTY, Employer.class, this);
19.6 Assert.assertNotNull(em, "Class loaded");
19.7 - em.applyBindings();
19.8 + Models.applyBindings(em);
19.9 }
19.10 }
20.1 --- a/json/src/test/java/org/netbeans/html/json/impl/ToDoTest.java Thu Dec 18 09:22:47 2014 +0100
20.2 +++ b/json/src/test/java/org/netbeans/html/json/impl/ToDoTest.java Fri Dec 19 10:57:23 2014 +0100
20.3 @@ -105,7 +105,8 @@
20.4 new Todo("First", false),
20.5 new Todo("2nd", true),
20.6 new Todo("Third", false)
20.7 - ), c).applyBindings();
20.8 + ), c);
20.9 + Models.applyBindings(ui);
20.10
20.11 Map m = (Map) Models.toRaw(ui);
20.12 Object v = m.get("remaining");
21.1 --- a/ko4j/src/main/java/org/netbeans/html/ko4j/KOTech.java Thu Dec 18 09:22:47 2014 +0100
21.2 +++ b/ko4j/src/main/java/org/netbeans/html/ko4j/KOTech.java Fri Dec 19 10:57:23 2014 +0100
21.3 @@ -57,7 +57,7 @@
21.4 */
21.5 @Contexts.Id("ko4j")
21.6 final class KOTech
21.7 -implements Technology.BatchInit<Object>, Technology.ValueMutated<Object> {
21.8 +implements Technology.BatchInit<Object>, Technology.ValueMutated<Object>, Technology.ApplyId<Object> {
21.9 private Object[] jsObjects;
21.10 private int jsIndex;
21.11
21.12 @@ -131,7 +131,11 @@
21.13
21.14 @Override
21.15 public void applyBindings(Object data) {
21.16 - Object ko = Knockout.applyBindings(data);
21.17 + applyBindings(null, data);
21.18 + }
21.19 + @Override
21.20 + public void applyBindings(String id, Object data) {
21.21 + Object ko = Knockout.applyBindings(id, data);
21.22 if (ko instanceof Knockout) {
21.23 ((Knockout)ko).hold();
21.24 }
22.1 --- a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java Thu Dec 18 09:22:47 2014 +0100
22.2 +++ b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java Fri Dec 19 10:57:23 2014 +0100
22.3 @@ -131,12 +131,14 @@
22.4 Object model, String prop, Object oldValue, Object newValue
22.5 );
22.6
22.7 - @JavaScriptBody(args = { "bindings" }, body =
22.8 - "ko['cleanNode'](window['document']['body']);\n" +
22.9 - "ko['applyBindings'](bindings);\n" +
22.10 + @JavaScriptBody(args = { "id", "bindings" }, body =
22.11 + "var d = window['document'];\n" +
22.12 + "var e = id ? d['getElementById'](id) : d['body'];\n" +
22.13 + "ko['cleanNode'](e);\n" +
22.14 + "ko['applyBindings'](bindings, e);\n" +
22.15 "return bindings['ko4j'];\n"
22.16 )
22.17 - native static Object applyBindings(Object bindings);
22.18 + native static Object applyBindings(String id, Object bindings);
22.19
22.20 @JavaScriptBody(args = { "cnt" }, body =
22.21 "var arr = new Array(cnt);\n" +
23.1 --- a/ko4j/src/test/java/org/netbeans/html/ko4j/LessCallbacksCheck.java Thu Dec 18 09:22:47 2014 +0100
23.2 +++ b/ko4j/src/test/java/org/netbeans/html/ko4j/LessCallbacksCheck.java Fri Dec 19 10:57:23 2014 +0100
23.3 @@ -53,7 +53,7 @@
23.4 *
23.5 * @author Jaroslav Tulach
23.6 */
23.7 -@Model(className = "LessCalls", properties = {
23.8 +@Model(className = "LessCalls", targetId = "", properties = {
23.9 @Property(name = "value", type = int.class)
23.10 })
23.11 public class LessCallbacksCheck {
24.1 --- a/src/main/javadoc/overview.html Thu Dec 18 09:22:47 2014 +0100
24.2 +++ b/src/main/javadoc/overview.html Fri Dec 19 10:57:23 2014 +0100
24.3 @@ -94,6 +94,27 @@
24.4 {@link org.netbeans.html.json.spi.Transfer Java based JSON} and
24.5 {@link org.netbeans.html.json.spi.WSTransfer WebSocket} implementations
24.6 under the name <b>tyrus</b>.
24.7 + </p>
24.8 + <p>
24.9 + A particular DOM subtree
24.10 + that a <a target="_blank" href="http://knockoutjs.com">knockout.js</a> model gets
24.11 + applied to can be selected by using
24.12 + {@link net.java.html.json.Models#applyBindings(java.lang.Object,%20java.lang.String)
24.13 + Models.applyBindings(m, id)} with an id of an HTML element.
24.14 + There is new {@link net.java.html.json.Model#targetId()} attribute
24.15 + which controls behavior of the generated <code>applyBindings</code> method.
24.16 + If <em>specified and non-empty</em>, then the generated method
24.17 + will call {@link net.java.html.json.Models#applyBindings(java.lang.Object,java.lang.String)}
24.18 + with <code>this</code> and the provided {@link net.java.html.json.Model#targetId() target id}.
24.19 + If <em>specified, but left empty</em>, then the generated method
24.20 + calls {@link net.java.html.json.Models#applyBindings(java.lang.Object)}.
24.21 + <em>If unspecified</em>, the method will <b>not</b> be generated at all
24.22 + (a change with respect to older versions). However one can
24.23 + still use {@link net.java.html.json.Models#applyBindings(java.lang.Object)}
24.24 + or {@link net.java.html.json.Models#applyBindings(java.lang.Object,java.lang.String)}
24.25 + to perform the association of any model with the page element.
24.26 + </ul>
24.27 + <p>
24.28 Memory model when using Knockout bindings has been improved
24.29 (required additions of two new methods:
24.30 {@link org.netbeans.html.json.spi.PropertyBinding#weak()} and