ko4j/src/main/java/org/netbeans/html/ko4j/Knockout.java
author Jaroslav Tulach <jtulach@netbeans.org>
Tue, 26 Aug 2014 18:13:30 +0200
changeset 838 bdc3d696dd4a
parent 816 41979bf458e7
child 861 52b0e31920c1
permissions -rw-r--r--
During the API review process (bug 246133) the reviewers decided that in order to include html4j to NetBeans Platform, we need to stop using org.apidesign namespace and switch to NetBeans one. Repackaging all SPI packages into org.netbeans.html.smthng.spi.
jaroslav@37
     1
/**
jaroslav@358
     2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
jaroslav@37
     3
 *
jaroslav@551
     4
 * Copyright 2013-2014 Oracle and/or its affiliates. All rights reserved.
jaroslav@37
     5
 *
jaroslav@358
     6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
jaroslav@358
     7
 * Other names may be trademarks of their respective owners.
jaroslav@37
     8
 *
jaroslav@358
     9
 * The contents of this file are subject to the terms of either the GNU
jaroslav@358
    10
 * General Public License Version 2 only ("GPL") or the Common
jaroslav@358
    11
 * Development and Distribution License("CDDL") (collectively, the
jaroslav@358
    12
 * "License"). You may not use this file except in compliance with the
jaroslav@358
    13
 * License. You can obtain a copy of the License at
jaroslav@358
    14
 * http://www.netbeans.org/cddl-gplv2.html
jaroslav@358
    15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
jaroslav@358
    16
 * specific language governing permissions and limitations under the
jaroslav@358
    17
 * License.  When distributing the software, include this License Header
jaroslav@358
    18
 * Notice in each file and include the License file at
jaroslav@358
    19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
jaroslav@358
    20
 * particular file as subject to the "Classpath" exception as provided
jaroslav@358
    21
 * by Oracle in the GPL Version 2 section of the License file that
jaroslav@358
    22
 * accompanied this code. If applicable, add the following below the
jaroslav@358
    23
 * License Header, with the fields enclosed by brackets [] replaced by
jaroslav@358
    24
 * your own identifying information:
jaroslav@358
    25
 * "Portions Copyrighted [year] [name of copyright owner]"
jaroslav@358
    26
 *
jaroslav@358
    27
 * Contributor(s):
jaroslav@358
    28
 *
jaroslav@358
    29
 * The Original Software is NetBeans. The Initial Developer of the Original
jaroslav@551
    30
 * Software is Oracle. Portions Copyright 2013-2014 Oracle. All Rights Reserved.
jaroslav@358
    31
 *
jaroslav@358
    32
 * If you wish your version of this file to be governed by only the CDDL
jaroslav@358
    33
 * or only the GPL Version 2, indicate your decision by adding
jaroslav@358
    34
 * "[Contributor] elects to include this software in this distribution
jaroslav@358
    35
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
jaroslav@358
    36
 * single choice of license, a recipient has the option to distribute
jaroslav@358
    37
 * your version of this file under either the CDDL, the GPL Version 2 or
jaroslav@358
    38
 * to extend the choice of license to its licensees as provided above.
jaroslav@358
    39
 * However, if you add GPL Version 2 code and therefore, elected the GPL
jaroslav@358
    40
 * Version 2 license, then the option applies only if the new code is
jaroslav@358
    41
 * made subject to such option by the copyright holder.
jaroslav@37
    42
 */
jaroslav@442
    43
package org.netbeans.html.ko4j;
jaroslav@37
    44
jaroslav@131
    45
import net.java.html.js.JavaScriptBody;
jaroslav@163
    46
import net.java.html.js.JavaScriptResource;
jaroslav@37
    47
import net.java.html.json.Model;
jtulach@838
    48
import org.netbeans.html.json.spi.FunctionBinding;
jtulach@838
    49
import org.netbeans.html.json.spi.PropertyBinding;
jaroslav@37
    50
jaroslav@54
    51
/** This is an implementation package - just
jaroslav@54
    52
 * include its JAR on classpath and use official {@link Context} API
jaroslav@54
    53
 * to access the functionality.
jaroslav@54
    54
 * <p>
jaroslav@54
    55
 * Provides binding between {@link Model models} and knockout.js running
jaroslav@54
    56
 * inside a JavaFX WebView. 
jaroslav@37
    57
 *
jtulach@790
    58
 * @author Jaroslav Tulach
jaroslav@37
    59
 */
jtulach@816
    60
@JavaScriptResource("knockout-3.2.0.debug.js")
jaroslav@276
    61
final class Knockout {
jaroslav@570
    62
    @JavaScriptBody(args = { "model", "prop", "oldValue", "newValue" }, 
jaroslav@570
    63
        wait4js = false,
jaroslav@570
    64
        body =
jaroslav@276
    65
          "if (model) {\n"
jaroslav@276
    66
        + "  var koProp = model[prop];\n"
jaroslav@276
    67
        + "  if (koProp && koProp['valueHasMutated']) {\n"
jaroslav@567
    68
        + "    if ((oldValue !== null || newValue !== null)) {\n"
jaroslav@567
    69
        + "      koProp['valueHasMutated'](newValue);\n"
jaroslav@567
    70
        + "    } else if (koProp['valueHasMutated']) {\n"
jaroslav@567
    71
        + "      koProp['valueHasMutated']();\n"
jaroslav@567
    72
        + "    }\n"
jaroslav@276
    73
        + "  }\n"
jaroslav@276
    74
        + "}\n"
jaroslav@276
    75
    )
jaroslav@567
    76
    public native static void valueHasMutated(
jaroslav@567
    77
        Object model, String prop, Object oldValue, Object newValue
jaroslav@567
    78
    );
jaroslav@37
    79
jaroslav@570
    80
    @JavaScriptBody(args = { "bindings" }, wait4js = false, body = 
jtulach@816
    81
        "ko.cleanNode(window.document.body);\n" +
jaroslav@570
    82
        "ko.applyBindings(bindings);\n"
jaroslav@570
    83
    )
jaroslav@276
    84
    native static void applyBindings(Object bindings);
jaroslav@276
    85
    
jaroslav@574
    86
    @JavaScriptBody(args = { "cnt" }, body = 
jaroslav@574
    87
        "var arr = new Array(cnt);\n" +
jaroslav@574
    88
        "for (var i = 0; i < cnt; i++) arr[i] = new Object();\n" +
jaroslav@574
    89
        "return arr;\n"
jaroslav@574
    90
    )
jaroslav@574
    91
    native static Object[] allocJS(int cnt);
jaroslav@574
    92
    
jaroslav@276
    93
    @JavaScriptBody(
jaroslav@276
    94
        javacall = true,
jaroslav@570
    95
        wait4js = false,
jaroslav@574
    96
        args = {"ret", "model", "propNames", "propReadOnly", "propValues", "propArr", "funcNames", "funcArr"},
jaroslav@570
    97
        body = 
jaroslav@574
    98
          "ret['ko-fx.model'] = model;\n"
jaroslav@279
    99
        + "function koComputed(name, readOnly, value, prop) {\n"
jtulach@816
   100
        + "  var trigger = ko.observable().extend({notify:'always'});"
jaroslav@279
   101
        + "  function realGetter() {\n"
jaroslav@437
   102
        + "    try {\n"
jtulach@838
   103
        + "      var v = prop.@org.netbeans.html.json.spi.PropertyBinding::getValue()();\n"
jaroslav@437
   104
        + "      return v;\n"
jaroslav@437
   105
        + "    } catch (e) {\n"
jaroslav@437
   106
        + "      alert(\"Cannot call getValue on \" + model + \" prop: \" + name + \" error: \" + e);\n"
jaroslav@437
   107
        + "    }\n"
jaroslav@279
   108
        + "  }\n"
jaroslav@279
   109
        + "  var activeGetter = function() { return value; };\n"
jaroslav@437
   110
        + "  var bnd = {\n"
jtulach@672
   111
        + "    'read': function() {\n"
jtulach@816
   112
        + "      trigger();\n"
jaroslav@437
   113
        + "      var r = activeGetter();\n"
jaroslav@437
   114
        + "      activeGetter = realGetter;\n"
jtulach@758
   115
        + "      if (r) try { var br = r.valueOf(); } catch (err) {}\n"
jtulach@764
   116
        + "      return br === undefined ? r: br;\n"
jaroslav@437
   117
        + "    },\n"
jtulach@672
   118
        + "    'owner': ret\n"
jaroslav@276
   119
        + "  };\n"
jaroslav@276
   120
        + "  if (!readOnly) {\n"
jtulach@672
   121
        + "    bnd['write'] = function(val) {\n"
jtulach@809
   122
        + "      var model = val['ko-fx.model'];\n"
jtulach@838
   123
        + "      prop.@org.netbeans.html.json.spi.PropertyBinding::setValue(Ljava/lang/Object;)(model ? model : val);\n"
jaroslav@437
   124
        + "    };\n"
jaroslav@437
   125
        + "  };\n"
jtulach@672
   126
        + "  var cmpt = ko['computed'](bnd);\n"
jtulach@672
   127
        + "  cmpt['valueHasMutated'] = function(val) {\n"
jaroslav@567
   128
        + "    if (arguments.length === 1) activeGetter = function() { return val; };\n"
jtulach@816
   129
        + "    trigger.valueHasMutated();\n"
jaroslav@567
   130
        + "  };\n"
jaroslav@567
   131
        + "  ret[name] = cmpt;\n"
jaroslav@276
   132
        + "}\n"
jaroslav@276
   133
        + "for (var i = 0; i < propNames.length; i++) {\n"
jaroslav@279
   134
        + "  koComputed(propNames[i], propReadOnly[i], propValues[i], propArr[i]);\n"
jaroslav@276
   135
        + "}\n"
jaroslav@276
   136
        + "function koExpose(name, func) {\n"
jaroslav@276
   137
        + "  ret[name] = function(data, ev) {\n"
jtulach@838
   138
        + "    func.@org.netbeans.html.json.spi.FunctionBinding::call(Ljava/lang/Object;Ljava/lang/Object;)(data, ev);\n"
jaroslav@276
   139
        + "  };\n"
jaroslav@276
   140
        + "}\n"
jaroslav@276
   141
        + "for (var i = 0; i < funcNames.length; i++) {\n"
jaroslav@276
   142
        + "  koExpose(funcNames[i], funcArr[i]);\n"
jaroslav@276
   143
        + "}\n"
jaroslav@276
   144
        )
jaroslav@574
   145
    static native void wrapModel(
jaroslav@574
   146
        Object ret, Object model,
jaroslav@279
   147
        String[] propNames, boolean[] propReadOnly, Object propValues, PropertyBinding[] propArr,
jaroslav@275
   148
        String[] funcNames, FunctionBinding[] funcArr
jaroslav@276
   149
    );
jaroslav@430
   150
    
jaroslav@430
   151
    @JavaScriptBody(args = { "o" }, body = "return o['ko-fx.model'] ? o['ko-fx.model'] : o;")
jaroslav@570
   152
    private static native Object toModelImpl(Object wrapper);
jaroslav@570
   153
    static Object toModel(Object wrapper) {
jaroslav@570
   154
        return toModelImpl(wrapper);
jaroslav@570
   155
    }
jaroslav@590
   156
    
jaroslav@590
   157
    @JavaScriptBody(args = {}, body = "if (window.WebSocket) return true; else return false;")
jaroslav@590
   158
    static final boolean areWebSocketsSupported() {
jaroslav@590
   159
        return false;
jaroslav@590
   160
    }
jaroslav@37
   161
}