Changeset 766

Show
Ignore:
Timestamp:
17/11/08 15:50:15 (2 months ago)
Author:
mpo
Message:

Fix for #121. Allowing uri-templates to hold sub-property expressions on the context.
Plus some extra tests for this feature.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/modules/kauri-forms/kauri-forms-framework/src/main/kauri/js/uritemplate.js

    r599 r766  
    3737 * - listjoin operator was renamed to list (0.3)  
    3838 * - making %HH codes uppercase (per recommendation of URI rfc) - converting number-values automatically 
     39 * - allowing sub-references on context-objects through $.getProperty() 
    3940 *  
    4041 * Added feature 
     
    5455    var kp = $.org.kauriproject; 
    5556 
     57     
     58    var EXPR_REGEXP = /[.[]/; // tests if this is an expression to evaluate 
     59    var SUBPROP_REGEXP = /^(\w+)([.[].*)$/;  // matches [1] for the propname and [2] for the remainder 
     60    var INDEXPROP_REGEXP = /^\[("([^"]+)"|'([^']+)'|(\d*))\](.*)$/; // produces [2] or [3] for propnames or [4] for index number + \5 for remainder 
     61     
     62    /** 
     63     * Gets a property as noted in a js expression (including array and property references) from a context object. 
     64     * <p>Supported sub-property notations include: 
     65     * <ul> <li>x.y</li> 
     66     *      <li>x["y"] or x['y']</li> 
     67     *      <li>x[1]></li> 
     68     *  
     69     * @param {context}  
     70     *      object to read property from 
     71     * @param {expr} 
     72     *      expression to be evaluated versus the context  
     73     */ 
     74    $.getProperty = function (context, expr) { 
     75        if ($.isEmpty(expr) || context == undefined) return context; 
     76         
     77        // fast turn around for the simplest case. 
     78        if (Object.hasOwnProperty.call(context,expr)) return context[expr]; 
     79        // no need to further evaluate if there is no expression inside: 
     80        if (!EXPR_REGEXP.test(expr)) 
     81            return undefined; 
     82         
     83         
     84        /* unsafe eval implementation  
     85         * disadvantages:  
     86         *   1/ inherited context through with()  
     87         *   2/ eval could execute unwanted things 
     88         *   3/ method call-arguments should not be expressed              
     89        var result = undefined; 
     90        with (context) { 
     91            try { 
     92                result = eval(expr); 
     93            } catch (e) { 
     94            } 
     95        } 
     96        return result; 
     97        */ 
     98         
     99        var subexpr, remainder; 
     100 
     101        // switch between two options: starts with '[' or not 
     102        if (expr.charAt(0) == '[') {  // expression starts with ["abc"] ['xyz'] or [123] 
     103            var match = INDEXPROP_REGEXP.exec(expr); 
     104            if (match) { 
     105                subexpr = match[2] || match[3] || match[4]; 
     106                remainder = match[5]; 
     107            } 
     108            else { 
     109                throw "incorrect index-property syntax in expression= " + expr; 
     110            } 
     111        } else { // expression starts with normal character 
     112            var match = SUBPROP_REGEXP.exec(expr); 
     113            if (match) { 
     114                subexpr = match[1]; 
     115                remainder = match[2]; 
     116            } 
     117            else { 
     118                throw "incorrect sub-property syntax in expression= " + expr; 
     119            }             
     120        } 
     121        var subcontext = $.getProperty(context, subexpr); 
     122        if (remainder.charAt(0) == '.') 
     123            remainder = remainder.substring(1); 
     124        return $.getProperty(subcontext, remainder); 
     125    } 
     126     
     127     
    56128    function Template() { 
    57129 
     
    190262        var name = variable[0]; 
    191263        var def = variable[1]; 
    192         var value = context[name]
     264        var value = $.getProperty(context, name)
    193265        if (value instanceof Function) { 
    194266            value = value(); 
  • trunk/modules/kauri-forms/kauri-forms-framework/src/test/js/test-uritemplate.js

    r570 r766  
    11module('Template URI Testing'); 
     2 
     3 
     4test("getProperty tests", function() { 
     5 
     6    expect(15); 
     7     
     8    var context = { 
     9        "obj" : { 
     10            "str": "ok", 
     11            "int": "1", 
     12            "arr": [2, "way", {"str":"do", "int": 3}] 
     13        }, 
     14        "arr" : [4, "wake", {"str":"!", "int": 5}, ["sleep", 6]], 
     15        "str" : "hello", 
     16        "int" : 7, 
     17        "quad.func": function(){return 4;} 
     18    }; 
     19 
     20    checkProperty(context, "int", 7 ); 
     21    checkProperty(context, "str", "hello"); 
     22    checkProperty(context, "arr[0]", 4); 
     23    checkProperty(context, "arr[1]", "wake"); 
     24    checkProperty(context, "arr[2].str", "!"); 
     25    checkProperty(context, 'arr[2]["int"]', 5); 
     26    checkProperty(context, "arr[3][0]", "sleep"); 
     27    checkProperty(context, "arr[3][1]", 6); 
     28    checkProperty(context, "obj.int", 1); 
     29    checkProperty(context, "obj.str", "ok"); 
     30    checkProperty(context, "obj.arr[0]", 2); 
     31    checkProperty(context, "obj.arr[1]", "way"); 
     32    checkProperty(context, "obj.arr[2].str", "do"); 
     33    checkProperty(context, "obj.arr[2]['int']", 3);     
     34    checkProperty(context, "quad.func", context['quad.func']);    
     35    //checkProperty(context, "alert('me')", 4);        
     36}); 
     37 
     38function checkProperty(context, expr, expected) { 
     39    equals($.getProperty(context, expr), expected, "getProperty for [" + expr + "]");  
     40} 
     41 
    242 
    343/* 
     
    1353 
    1454    var testdata = { 
    15          
    16     } 
    17     /* 
    18      * Table 1 
    19      *  
    20      * (Note that the name 'wilma' has not been defined, and the value of 'f' is the empty string.) 
    21      *  
    22      * The following URI Templates will be expanded as shown: 
    23      */ 
    24     var testset = { 
    25         "uri without tokens" :"uri without tokens" 
     55        "x"  : "one", 
     56        "y"  : { 
     57            "y": 2 
     58        }, 
     59        "z.z": function() { return "three" ;} 
     60    } 
     61 
     62    var testset = { 
     63        "uri without tokens" :"uri without tokens", 
     64        "-{x}-{y.y}-{z.z}-": "-one-2-three-"            
    2665    } 
    2766