Providing an ability to apply model to element with certain id ApplyId
authorJaroslav Tulach <jtulach@netbeans.org>
Tue, 16 Dec 2014 21:03:16 +0100
branchApplyId
changeset 908ee7a0b3b2d4c
parent 905 6242ffbcfd16
Providing an ability to apply model to element with certain id
json/src/main/java/org/netbeans/html/json/impl/Bindings.java
json/src/main/java/org/netbeans/html/json/impl/JSONList.java
json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java
json/src/main/java/org/netbeans/html/json/spi/Proto.java
json/src/main/java/org/netbeans/html/json/spi/Technology.java
json/src/test/java/net/java/html/json/MapModelTest.java
ko4j/src/main/java/org/netbeans/html/ko4j/KOTech.java
ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
src/main/javadoc/overview.html
     1.1 --- a/json/src/main/java/org/netbeans/html/json/impl/Bindings.java	Sun Dec 14 14:36:30 2014 +0100
     1.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/Bindings.java	Tue Dec 16 21:03:16 2014 +0100
     1.3 @@ -42,6 +42,8 @@
     1.4   */
     1.5  package org.netbeans.html.json.impl;
     1.6  
     1.7 +import java.util.logging.Level;
     1.8 +import java.util.logging.Logger;
     1.9  import net.java.html.BrwsrCtx;
    1.10  import org.netbeans.html.json.spi.FunctionBinding;
    1.11  import org.netbeans.html.json.spi.PropertyBinding;
    1.12 @@ -53,6 +55,8 @@
    1.13   * @author Jaroslav Tulach
    1.14   */
    1.15  public final class Bindings<Data> {
    1.16 +    private static final Logger LOG = Logger.getLogger(Bindings.class.getName()); 
    1.17 +    
    1.18      private Data data;
    1.19      private final Technology<Data> bp;
    1.20  
    1.21 @@ -105,7 +109,18 @@
    1.22          }
    1.23      }
    1.24      
    1.25 -    public void applyBindings() {
    1.26 +    public void applyBindings(String id) {
    1.27 +        if (bp instanceof Technology.ApplyId) {
    1.28 +            Technology.ApplyId<Data> ai = (Technology.ApplyId<Data>) bp;
    1.29 +            ai.applyBindings(id, data);
    1.30 +            return;
    1.31 +        }
    1.32 +        if (id != null) {
    1.33 +            LOG.log(Level.WARNING, 
    1.34 +                "Technology {0} does not implement ApplyId extension. Can't apply to {1}. Applying globally.", 
    1.35 +                new Object[]{bp, id}
    1.36 +            );
    1.37 +        }
    1.38          bp.applyBindings(data);
    1.39      }
    1.40  
     2.1 --- a/json/src/main/java/org/netbeans/html/json/impl/JSONList.java	Sun Dec 14 14:36:30 2014 +0100
     2.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/JSONList.java	Tue Dec 16 21:03:16 2014 +0100
     2.3 @@ -179,7 +179,7 @@
     2.4              public void run() {
     2.5                  Bindings m = PropertyBindingAccessor.getBindings(proto, false);
     2.6                  if (m != null) {
     2.7 -                    m.valueHasMutated(name, null, null);
     2.8 +                    m.valueHasMutated(name, null, JSONList.this);
     2.9                      for (String dependant : deps) {
    2.10                          m.valueHasMutated(dependant, null, null);
    2.11                      }
     3.1 --- a/json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java	Sun Dec 14 14:36:30 2014 +0100
     3.2 +++ b/json/src/main/java/org/netbeans/html/json/impl/ModelProcessor.java	Tue Dec 16 21:03:16 2014 +0100
     3.3 @@ -504,12 +504,26 @@
     3.4                      + "In case of using Knockout technology, this means to \n"
     3.5                      + "bind JSON like data in this model instance with Knockout tags in \n"
     3.6                      + "the surrounding HTML page.\n"
     3.7 +                    + "@return returns <code>this</code>\n"
     3.8                      + "*/\n"
     3.9                  );
    3.10                  w.write("  public " + className + " applyBindings() {\n");
    3.11                  w.write("    proto.applyBindings();\n");
    3.12                  w.write("    return this;\n");
    3.13                  w.write("  }\n");
    3.14 +                w.write("  /** Activates this model instance in the current {@link \n"
    3.15 +                    + "net.java.html.json.Models#bind(java.lang.Object, net.java.html.BrwsrCtx) browser context}. \n"
    3.16 +                    + "In case of using Knockout technology, this means to \n"
    3.17 +                    + "bind JSON like data in this model instance with Knockout tags in \n"
    3.18 +                    + "the surrounding HTML page.\n"
    3.19 +                    + "@param id identifies the element to apply the model to\n"
    3.20 +                    + "@return returns <code>this</code>\n"
    3.21 +                    + "*/\n"
    3.22 +                );
    3.23 +                w.write("  public " + className + " applyBindings(String id) {\n");
    3.24 +                w.write("    proto.applyBindings(id);\n");
    3.25 +                w.write("    return this;\n");
    3.26 +                w.write("  }\n");
    3.27                  w.write("  public boolean equals(Object o) {\n");
    3.28                  w.write("    if (o == this) return true;\n");
    3.29                  w.write("    if (!(o instanceof " + className + ")) return false;\n");
     4.1 --- a/json/src/main/java/org/netbeans/html/json/spi/Proto.java	Sun Dec 14 14:36:30 2014 +0100
     4.2 +++ b/json/src/main/java/org/netbeans/html/json/spi/Proto.java	Tue Dec 16 21:03:16 2014 +0100
     4.3 @@ -193,7 +193,21 @@
     4.4       * of the current model to the <em>body</em> element of the page.
     4.5       */
     4.6      public void applyBindings() {
     4.7 -        initBindings().applyBindings();
     4.8 +        initBindings().applyBindings(null);
     4.9 +    }
    4.10 +    
    4.11 +    /** Initializes the associated model to the specified element's subtree.
    4.12 +     * The technology is taken from the current {@link #getContext() context} and
    4.13 +     * in case of <em>knockout.js</em> applies given bindings 
    4.14 +     * of the current model to the element of the page with 'id' attribute
    4.15 +     * set to the specified <code>id</code> value.
    4.16 +     * 
    4.17 +     * @param id the id of element to apply the binding to
    4.18 +     * @since 1.1
    4.19 +     * @see Technology.ApplyId
    4.20 +     */
    4.21 +    public void applyBindings(String id) {
    4.22 +        initBindings().applyBindings(id);
    4.23      }
    4.24      
    4.25      /** Invokes the provided runnable in the {@link #getContext() context}
     5.1 --- a/json/src/main/java/org/netbeans/html/json/spi/Technology.java	Sun Dec 14 14:36:30 2014 +0100
     5.2 +++ b/json/src/main/java/org/netbeans/html/json/spi/Technology.java	Tue Dec 16 21:03:16 2014 +0100
     5.3 @@ -173,4 +173,22 @@
     5.4           */
     5.5          public void valueHasMutated(D data, String propertyName, Object oldValue, Object newValue);
     5.6      }
     5.7 +    
     5.8 +    /** Apply technology bindings at selected subtree of the HTML page.
     5.9 +     * Can be accessed via {@link Proto#applyBindings(java.lang.String)} or
    5.10 +     * via method <code>applyBindings(String)</code> generated when one
    5.11 +     * is using the {@link Model} annotation.
    5.12 +     * 
    5.13 +     * @param <D> the internal data for the technology
    5.14 +     * @since 1.1
    5.15 +     */
    5.16 +    public static interface ApplyId<D> extends Technology<D> {
    5.17 +        /** Applies given data to current context (usually an element on an 
    5.18 +         * HTML page).
    5.19 +         * 
    5.20 +         * @param id the id of an element to apply the data to
    5.21 +         * @param data the data to apply
    5.22 +         */
    5.23 +        public void applyBindings(String id, D data);
    5.24 +    }
    5.25  }
     6.1 --- a/json/src/test/java/net/java/html/json/MapModelTest.java	Sun Dec 14 14:36:30 2014 +0100
     6.2 +++ b/json/src/test/java/net/java/html/json/MapModelTest.java	Tue Dec 16 21:03:16 2014 +0100
     6.3 @@ -76,6 +76,7 @@
     6.4      
     6.5      @Test public void isThereABinding() throws Exception {
     6.6          Person p = Models.bind(new Person(), c).applyBindings();
     6.7 +        assertNull(t.appliedId, "Applied globally");
     6.8          p.setFirstName("Jarda");
     6.9          
    6.10          Map m = (Map)Models.toRaw(p);
    6.11 @@ -94,6 +95,10 @@
    6.12          assertEquals(o.changes, 2, "Snd change");
    6.13      }
    6.14      
    6.15 +    @Test public void applyLocally() throws Exception {
    6.16 +        Person p = Models.bind(new Person(), c).applyBindings("local");
    6.17 +        assertEquals(t.appliedId, "local", "Applied locally");
    6.18 +    }
    6.19      
    6.20      @Test public void dontNotifySameProperty() throws Exception {
    6.21          Person p = Models.bind(new Person(), c);
    6.22 @@ -293,7 +298,9 @@
    6.23      }
    6.24      
    6.25      static final class MapTechnology 
    6.26 -    implements Technology<Map<String,One>>, Transfer {
    6.27 +    implements Technology.ApplyId<Map<String,One>>, Transfer {
    6.28 +        private Map<String, One> appliedData;
    6.29 +        private String appliedId;
    6.30  
    6.31          @Override
    6.32          public Map<String, One> wrapModel(Object model) {
    6.33 @@ -329,6 +336,7 @@
    6.34  
    6.35          @Override
    6.36          public void applyBindings(Map<String, One> data) {
    6.37 +            throw new UnsupportedOperationException("Never called!");
    6.38          }
    6.39  
    6.40          @Override
    6.41 @@ -370,5 +378,11 @@
    6.42          public void runSafe(Runnable r) {
    6.43              throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
    6.44          }
    6.45 +
    6.46 +        @Override
    6.47 +        public void applyBindings(String id, Map<String, One> data) {
    6.48 +            this.appliedId = id;
    6.49 +            this.appliedData = data;
    6.50 +        }
    6.51      }
    6.52  }
     7.1 --- a/ko4j/src/main/java/org/netbeans/html/ko4j/KOTech.java	Sun Dec 14 14:36:30 2014 +0100
     7.2 +++ b/ko4j/src/main/java/org/netbeans/html/ko4j/KOTech.java	Tue Dec 16 21:03:16 2014 +0100
     7.3 @@ -57,7 +57,7 @@
     7.4   */
     7.5  @Contexts.Id("ko4j")
     7.6  final class KOTech
     7.7 -implements Technology.BatchInit<Object>, Technology.ValueMutated<Object> {
     7.8 +implements Technology.BatchInit<Object>, Technology.ValueMutated<Object>, Technology.ApplyId<Object> {
     7.9      private Object[] jsObjects;
    7.10      private int jsIndex;
    7.11  
    7.12 @@ -131,7 +131,11 @@
    7.13  
    7.14      @Override
    7.15      public void applyBindings(Object data) {
    7.16 -        Object ko = Knockout.applyBindings(data);
    7.17 +        applyBindings(null, data);
    7.18 +    }
    7.19 +    @Override
    7.20 +    public void applyBindings(String id, Object data) {
    7.21 +        Object ko = Knockout.applyBindings(id, data);
    7.22          if (ko instanceof Knockout) {
    7.23              ((Knockout)ko).hold();
    7.24          }
     8.1 --- a/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java	Sun Dec 14 14:36:30 2014 +0100
     8.2 +++ b/ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java	Tue Dec 16 21:03:16 2014 +0100
     8.3 @@ -131,12 +131,14 @@
     8.4          Object model, String prop, Object oldValue, Object newValue
     8.5      );
     8.6  
     8.7 -    @JavaScriptBody(args = { "bindings" }, body = 
     8.8 -        "ko['cleanNode'](window['document']['body']);\n" +
     8.9 -        "ko['applyBindings'](bindings);\n" +
    8.10 +    @JavaScriptBody(args = { "id", "bindings" }, body = 
    8.11 +        "var d = window['document'];\n" +
    8.12 +        "var e = id ? d['getElementById'](id) : d['body'];\n" +
    8.13 +        "ko['cleanNode'](e);\n" +
    8.14 +        "ko['applyBindings'](bindings, e);\n" +
    8.15          "return bindings['ko4j'];\n"
    8.16      )
    8.17 -    native static Object applyBindings(Object bindings);
    8.18 +    native static Object applyBindings(String id, Object bindings);
    8.19      
    8.20      @JavaScriptBody(args = { "cnt" }, body = 
    8.21          "var arr = new Array(cnt);\n" +
     9.1 --- a/src/main/javadoc/overview.html	Sun Dec 14 14:36:30 2014 +0100
     9.2 +++ b/src/main/javadoc/overview.html	Tue Dec 16 21:03:16 2014 +0100
     9.3 @@ -93,7 +93,13 @@
     9.4              module registers its 
     9.5              {@link org.netbeans.html.json.spi.Transfer Java based JSON} and 
     9.6              {@link org.netbeans.html.json.spi.WSTransfer WebSocket} implementations
     9.7 -            under the name <b>tyrus</b>.
     9.8 +            under the name <b>tyrus</b>. Also the particular DOM subtree
     9.9 +            that a <a href="knockoutjs.com">knockout.js</a> model gets
    9.10 +            applied can now be selected by using 
    9.11 +            {@link org.netbeans.html.json.spi.Proto#applyBindings(java.lang.String)
    9.12 +            applyBindings(id)} with an id of an HTML element.
    9.13 +        </p>
    9.14 +        <p>
    9.15              Memory model when using Knockout bindings has been improved
    9.16              (required additions of two new methods:
    9.17              {@link org.netbeans.html.json.spi.PropertyBinding#weak()} and