OpenLayers OpenLayers

Changeset 6116

Show
Ignore:
Timestamp:
02/08/08 11:56:48 (1 year ago)
Author:
ahocevar
Message:

Add optional context property to OpenLayers.Rule, so rules can now be evaluated against diffent contexts than feature.attributes. This changeset also renames Rule.Logical.children to Rule.Logical.rules, to make it more consistent with OL.Style. r=crschmidt (closes #1331)

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/openlayers/lib/OpenLayers/Format/SLD.js

    r5978 r6116  
    344344            for (var i=0; i<filters.length; i++) { 
    345345                if (filters[i].nodeType == 1) { 
    346                     rule.children.push(this.parseFilter(filters[i])); 
     346                    rule.rules.push(this.parseFilter(filters[i])); 
    347347                } 
    348348            } 
     
    358358            for (var i=0; i<filters.length; i++) { 
    359359                if (filters[i].nodeType == 1) { 
    360                     rule.children.push(this.parseFilter(filters[i])); 
     360                    rule.rules.push(this.parseFilter(filters[i])); 
    361361                } 
    362362            } 
     
    369369            var rule = new OpenLayers.Rule.Logical( 
    370370                    {type: OpenLayers.Rule.Logical.NOT}); 
    371             rule.children.push(this.parseFilter(filter[0])); 
     371            rule.rules.push(this.parseFilter(filter[0])); 
    372372            return rule; 
    373373        } 
  • trunk/openlayers/lib/OpenLayers/Rule.js

    r5978 r6116  
    2020     */ 
    2121    name: 'default', 
     22     
     23    /** 
     24     * Property: context 
     25     * {Object} An optional object with properties that the rule and its 
     26     * symbolizers' property values should be evaluatad against. If no 
     27     * context is specified, feature.attributes will be used 
     28     */ 
     29    context: null, 
    2230 
    2331    /** 
     
    94102     */ 
    95103    evaluate: function(feature) { 
    96         // Default rule always applies. Subclasses will want to override this. 
    97         return true; 
     104        var context = this.getContext(feature); 
     105        var applies = true; 
     106 
     107        if (this.minScaleDenominator || this.maxScaleDenominator) { 
     108            var scale = feature.layer.map.getScale(); 
     109        } 
     110         
     111        // check if within minScale/maxScale bounds 
     112        if (this.minScaleDenominator) { 
     113            applies = scale >= OpenLayers.Style.createLiteral( 
     114                    this.minScaleDenominator, context); 
     115        } 
     116        if (applies && this.maxScaleDenominator) { 
     117            applies = scale < OpenLayers.Style.createLiteral( 
     118                    this.maxScaleDenominator, context); 
     119        } 
     120 
     121        return applies; 
    98122    }, 
    99123     
     124    /** 
     125     * Method: getContext 
     126     * Gets the context for evaluating this rule 
     127     *  
     128     * Paramters: 
     129     * feature - {<OpenLayers.Feature>} feature to take the context from if 
     130     *           none is specified. 
     131     */ 
     132    getContext: function(feature) { 
     133        var context = this.context; 
     134        if (!context) { 
     135            context = feature.attributes || feature.data; 
     136        } 
     137        return context; 
     138    }, 
     139         
    100140    CLASS_NAME: "OpenLayers.Rule" 
    101141}); 
  • trunk/openlayers/lib/OpenLayers/Rule/Comparison.js

    r5614 r6116  
    3434     * APIProperty: property 
    3535     * {String} 
    36      * name of the feature attribute to compare 
     36     * name of the context property to compare 
    3737     */ 
    3838    property: null, 
     
    8585    /** 
    8686     * APIMethod: evaluate 
    87      * evaluates this rule for a specific feature 
    88      *  
    89      * Parameters: 
    90      * feature - {<OpenLayers.Feature>} feature to apply the rule to. 
     87     * evaluates this rule for a specific context 
     88     *  
     89     * Parameters: 
     90     * context - {Object} context to apply the rule to. 
    9191     *  
    9292     * Returns: 
     
    9494     */ 
    9595    evaluate: function(feature) { 
    96         var attributes = feature.attributes || feature.data; 
     96        if (!OpenLayers.Rule.prototype.evaluate.apply(this, arguments)) { 
     97            return false; 
     98        } 
     99        var context = this.getContext(feature); 
    97100        switch(this.type) { 
    98101            case OpenLayers.Rule.Comparison.EQUAL_TO: 
     
    101104            case OpenLayers.Rule.Comparison.LESS_THAN_OR_EQUAL_TO: 
    102105            case OpenLayers.Rule.Comparison.GREATER_THAN_OR_EQUAL_TO: 
    103                 return this.binaryCompare(feature, this.property, this.value); 
     106                return this.binaryCompare(context, this.property, this.value); 
    104107             
    105108            case OpenLayers.Rule.Comparison.BETWEEN: 
    106109                var result = 
    107                         attributes[this.property] > this.lowerBoundary; 
     110                        context[this.property] > this.lowerBoundary; 
    108111                result = result && 
    109                         attributes[this.property] < this.upperBoundary; 
     112                        context[this.property] < this.upperBoundary; 
    110113                return result; 
    111114            case OpenLayers.Rule.Comparison.LIKE: 
    112115                var regexp = new RegExp(this.value, 
    113116                                "gi"); 
    114                 return regexp.test(attributes[this.property]);  
     117                return regexp.test(context[this.property]);  
    115118        } 
    116119    }, 
     
    166169     *  
    167170     * Parameters: 
    168      * feature  - {<OpenLayers.Feature>
     171     * context  - {Object
    169172     * property - {String} or {Number} 
    170173     * value    - {String} or {Number}, same as property 
     
    173176     * {boolean} 
    174177     */ 
    175     binaryCompare: function(feature, property, value) { 
    176         var attributes = feature.attributes || feature.data; 
     178    binaryCompare: function(context, property, value) { 
    177179        switch (this.type) { 
    178180            case OpenLayers.Rule.Comparison.EQUAL_TO: 
    179                 return attributes[property] == value; 
     181                return context[property] == value; 
    180182            case OpenLayers.Rule.Comparison.NOT_EQUAL_TO: 
    181                 return attributes[property] != value; 
     183                return context[property] != value; 
    182184            case OpenLayers.Rule.Comparison.LESS_THAN: 
    183                 return attributes[property] < value; 
     185                return context[property] < value; 
    184186            case OpenLayers.Rule.Comparison.GREATER_THAN: 
    185                 return attributes[property] > value; 
     187                return context[property] > value; 
    186188            case OpenLayers.Rule.Comparison.LESS_THAN_OR_EQUAL_TO: 
    187                 return attributes[property] <= value; 
     189                return context[property] <= value; 
    188190            case OpenLayers.Rule.Comparison.GREATER_THAN_OR_EQUAL_TO: 
    189                 return attributes[property] >= value; 
     191                return context[property] >= value; 
    190192        }       
    191193    }, 
  • trunk/openlayers/lib/OpenLayers/Rule/FeatureId.js

    r5614 r6116  
    5454     */ 
    5555    evaluate: function(feature) { 
     56        if (!OpenLayers.Rule.prototype.evaluate.apply(this, arguments)) { 
     57            return false; 
     58        } 
    5659        for (var i=0; i<this.fids.length; i++) { 
    5760            var fid = feature.fid || feature.id; 
  • trunk/openlayers/lib/OpenLayers/Rule/Logical.js

    r5614 r6116  
    2121     * {Array(<OpenLayers.Rule>)} child rules for this rule 
    2222     */ 
    23     children: null,  
     23    rules: null,  
    2424      
    2525    /** 
     
    4444     */ 
    4545    initialize: function(options) { 
    46         this.children = []; 
     46        this.rules = []; 
    4747        OpenLayers.Rule.prototype.initialize.apply(this, [options]); 
    4848    }, 
     
    5353     */ 
    5454    destroy: function() { 
    55         for (var i=0; i<this.children.length; i++) { 
    56             this.children[i].destroy(); 
     55        for (var i=0; i<this.rules.length; i++) { 
     56            this.rules[i].destroy(); 
    5757        } 
    58         this.children = null; 
     58        this.rules = null; 
    5959        OpenLayers.Rule.prototype.destroy.apply(this, arguments); 
    6060    }, 
     
    7171     */ 
    7272    evaluate: function(feature) { 
     73        if (!OpenLayers.Rule.prototype.evaluate.apply(this, arguments)) { 
     74            return false; 
     75        } 
    7376        switch(this.type) { 
    7477            case OpenLayers.Rule.Logical.AND: 
    75                 for (var i=0; i<this.children.length; i++) { 
    76                     if (this.children[i].evaluate(feature) == false) { 
     78                for (var i=0; i<this.rules.length; i++) { 
     79                    if (this.rules[i].evaluate(feature) == false) { 
    7780                        return false; 
    7881                    } 
     
    8184                 
    8285            case OpenLayers.Rule.Logical.OR: 
    83                 for (var i=0; i<this.children.length; i++) { 
    84                     if (this.children[i].evaluate(feature) == true) { 
     86                for (var i=0; i<this.rules.length; i++) { 
     87                    if (this.rules[i].evaluate(feature) == true) { 
    8588                        return true; 
    8689                    } 
     
    8992             
    9093            case OpenLayers.Rule.Logical.NOT: 
    91                 return (!this.children[0].evaluate(feature)); 
     94                return (!this.rules[0].evaluate(feature)); 
    9295        } 
    9396    }, 
  • trunk/openlayers/lib/OpenLayers/Style.js

    r5978 r6116  
    113113        var rules = this.rules; 
    114114 
    115         var rule
     115        var rule, context
    116116        var elseRules = []; 
    117117        var appliedRules = false; 
    118118        for(var i=0; i<rules.length; i++) { 
    119119            rule = rules[i]; 
     120            context = rule.context; 
     121            if (!context) { 
     122                context = feature.attributes || feature.data; 
     123            } 
    120124            // does the rule apply? 
    121125            var applies = rule.evaluate(feature); 
    122126             
    123             if (rule.minScaleDenominator || rule.maxScaleDenominator) { 
    124                 var scale = feature.layer.map.getScale(); 
    125             } 
    126              
    127             // check if within minScale/maxScale bounds 
    128             if (rule.minScaleDenominator) { 
    129                 applies = scale >= OpenLayers.Style.createLiteral( 
    130                         rule.minScaleDenominator, feature); 
    131             } 
    132             if (applies && rule.maxScaleDenominator) { 
    133                 applies = scale < OpenLayers.Style.createLiteral( 
    134                         rule.maxScaleDenominator, feature); 
    135             } 
    136  
    137127            if(applies) { 
    138128                if(rule instanceof OpenLayers.Rule && rule.elseFilter) { 
     
    140130                } else { 
    141131                    appliedRules = true; 
    142                     this.applySymbolizer(rule, style, feature); 
     132                    this.applySymbolizer(rule, style, feature, context); 
    143133                } 
    144134            } 
     
    149139            appliedRules = true; 
    150140            for(var i=0; i<elseRules.length; i++) { 
    151                 this.applySymbolizer(elseRules[i], style, feature); 
    152             } 
    153         } 
    154  
    155         // calculate literals for all styles in the propertyStyles cache 
    156         this.createLiterals(style, feature); 
     141                this.applySymbolizer(elseRules[i], style, feature, context); 
     142            } 
     143        } 
    157144 
    158145        // don't display if there were rules but none applied 
     
    173160     * style - {Object} 
    174161     * feature - {<OpenLayer.Feature.Vector>} 
     162     * context - {Object} 
    175163     * 
    176164     * Returns: 
    177165     * {Object} A style with new symbolizer applied. 
    178166     */ 
    179     applySymbolizer: function(rule, style, feature) { 
     167    applySymbolizer: function(rule, style, feature, context) { 
    180168        var symbolizerPrefix = feature.geometry ? 
    181169                this.getSymbolizerPrefix(feature.geometry) : 
    182170                OpenLayers.Style.SYMBOLIZER_PREFIXES[0]; 
    183171 
     172        var symbolizer = rule.symbolizer[symbolizerPrefix]; 
     173 
    184174        // merge the style with the current style 
    185         var symbolizer = rule.symbolizer[symbolizerPrefix]; 
    186         return OpenLayers.Util.extend(style, symbolizer); 
     175        return this.createLiterals( 
     176                OpenLayers.Util.extend(style, symbolizer), context); 
    187177    }, 
    188178     
     
    195185     * style   - {Object} style to create literals for. Will be modified 
    196186     *           inline. 
    197      * feature - {<OpenLayers.Feature.Vector>} feature to take properties from 
     187     * context - {Object} context to take property values from. Defaults to 
     188     *           feature.attributes (or feature.data, if attributes are not 
     189     *           available) 
    198190     *  
    199191     * Returns; 
    200192     * {Object} the modified style 
    201193     */ 
    202     createLiterals: function(style, feature) { 
     194    createLiterals: function(style, context) { 
    203195        for (var i in this.propertyStyles) { 
    204             style[i] = OpenLayers.Style.createLiteral(style[i], feature); 
     196            style[i] = OpenLayers.Style.createLiteral(style[i], context); 
    205197        } 
    206198        return style; 
     
    303295 *         will be replaced by the value of the "bar" attribute of the passed 
    304296 *         feature. 
    305  * feature {<OpenLayers.Feature>} feature to take attribute values from 
     297 * context {Object} context to take attribute values from 
    306298 *  
    307299 * Returns: 
     
    310302 * attribute named "bar" with the value "valueOfBar". 
    311303 */ 
    312 OpenLayers.Style.createLiteral = function(value, feature) { 
     304OpenLayers.Style.createLiteral = function(value, context) { 
    313305    if (typeof value == "string" && value.indexOf("${") != -1) { 
    314         var attributes = feature.attributes || feature.data; 
    315         value = OpenLayers.String.format(value, attributes) 
     306        value = OpenLayers.String.format(value, context) 
    316307        value = isNaN(value) ? value : parseFloat(value); 
    317308    } 
  • trunk/openlayers/tests/Rule/test_Logical.html

    r5429 r6116  
    2020        var rule = new OpenLayers.Rule.Logical(); 
    2121        rule.destroy(); 
    22         t.eq(rule.children, null, "children array nulled properly"); 
     22        t.eq(rule.rules, null, "rules array nulled properly"); 
    2323    } 
    2424     
     
    2828        var rule = new OpenLayers.Rule.Logical({ 
    2929                type: OpenLayers.Rule.Logical.NOT}); 
    30         rule.children.push(new OpenLayers.Rule()); 
     30        rule.rules.push(new OpenLayers.Rule()); 
    3131         
    3232        var feature = new OpenLayers.Feature.Vector(); 
  • trunk/openlayers/tests/test_Style.html

    r5978 r6116  
    112112        } 
    113113        style.createStyle(new OpenLayers.Feature.Vector()); 
    114  
    115  
     114    } 
     115     
     116    function test_Style_context(t) { 
     117        t.plan(1); 
     118        var context = { 
     119            foo: "bar", 
     120            size: 10}; 
     121        var rule = new OpenLayers.Rule.Comparison({ 
     122            type: OpenLayers.Rule.Comparison.LESS_THAN, 
     123            context: context, 
     124            property: "size", 
     125            value: 11, 
     126            symbolizer: {"Point": {externalGraphic: "${foo}.png"}}}); 
     127        var style = new OpenLayers.Style(); 
     128        style.addRules([rule]); 
     129        var styleHash = style.createStyle(new OpenLayers.Feature.Vector()); 
     130        t.eq(styleHash.externalGraphic, "bar.png", "correctly evaluated rule against a custom context"); 
    116131    } 
    117132