Rule.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /* Copyright (c) 2006-2013 by OpenLayers Contributors (see authors.txt for
  2. * full list of contributors). Published under the 2-clause BSD license.
  3. * See license.txt in the OpenLayers distribution or repository for the
  4. * full text of the license. */
  5. /**
  6. * @requires OpenLayers/BaseTypes/Class.js
  7. * @requires OpenLayers/Util.js
  8. * @requires OpenLayers/Style.js
  9. */
  10. /**
  11. * Class: OpenLayers.Rule
  12. * This class represents an SLD Rule, as being used for rule-based SLD styling.
  13. */
  14. OpenLayers.Rule = OpenLayers.Class({
  15. /**
  16. * Property: id
  17. * {String} A unique id for this session.
  18. */
  19. id: null,
  20. /**
  21. * APIProperty: name
  22. * {String} name of this rule
  23. */
  24. name: null,
  25. /**
  26. * Property: title
  27. * {String} Title of this rule (set if included in SLD)
  28. */
  29. title: null,
  30. /**
  31. * Property: description
  32. * {String} Description of this rule (set if abstract is included in SLD)
  33. */
  34. description: null,
  35. /**
  36. * Property: context
  37. * {Object} An optional object with properties that the rule should be
  38. * evaluated against. If no context is specified, feature.attributes will
  39. * be used.
  40. */
  41. context: null,
  42. /**
  43. * Property: filter
  44. * {<OpenLayers.Filter>} Optional filter for the rule.
  45. */
  46. filter: null,
  47. /**
  48. * Property: elseFilter
  49. * {Boolean} Determines whether this rule is only to be applied only if
  50. * no other rules match (ElseFilter according to the SLD specification).
  51. * Default is false. For instances of OpenLayers.Rule, if elseFilter is
  52. * false, the rule will always apply. For subclasses, the else property is
  53. * ignored.
  54. */
  55. elseFilter: false,
  56. /**
  57. * Property: symbolizer
  58. * {Object} Symbolizer or hash of symbolizers for this rule. If hash of
  59. * symbolizers, keys are one or more of ["Point", "Line", "Polygon"]. The
  60. * latter if useful if it is required to style e.g. vertices of a line
  61. * with a point symbolizer. Note, however, that this is not implemented
  62. * yet in OpenLayers, but it is the way how symbolizers are defined in
  63. * SLD.
  64. */
  65. symbolizer: null,
  66. /**
  67. * Property: symbolizers
  68. * {Array} Collection of symbolizers associated with this rule. If
  69. * provided at construction, the symbolizers array has precedence
  70. * over the deprecated symbolizer property. Note that multiple
  71. * symbolizers are not currently supported by the vector renderers.
  72. * Rules with multiple symbolizers are currently only useful for
  73. * maintaining elements in an SLD document.
  74. */
  75. symbolizers: null,
  76. /**
  77. * APIProperty: minScaleDenominator
  78. * {Number} or {String} minimum scale at which to draw the feature.
  79. * In the case of a String, this can be a combination of text and
  80. * propertyNames in the form "literal ${propertyName}"
  81. */
  82. minScaleDenominator: null,
  83. /**
  84. * APIProperty: maxScaleDenominator
  85. * {Number} or {String} maximum scale at which to draw the feature.
  86. * In the case of a String, this can be a combination of text and
  87. * propertyNames in the form "literal ${propertyName}"
  88. */
  89. maxScaleDenominator: null,
  90. /**
  91. * Constructor: OpenLayers.Rule
  92. * Creates a Rule.
  93. *
  94. * Parameters:
  95. * options - {Object} An optional object with properties to set on the
  96. * rule
  97. *
  98. * Returns:
  99. * {<OpenLayers.Rule>}
  100. */
  101. initialize: function(options) {
  102. this.symbolizer = {};
  103. OpenLayers.Util.extend(this, options);
  104. if (this.symbolizers) {
  105. delete this.symbolizer;
  106. }
  107. this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
  108. },
  109. /**
  110. * APIMethod: destroy
  111. * nullify references to prevent circular references and memory leaks
  112. */
  113. destroy: function() {
  114. for (var i in this.symbolizer) {
  115. this.symbolizer[i] = null;
  116. }
  117. this.symbolizer = null;
  118. delete this.symbolizers;
  119. },
  120. /**
  121. * APIMethod: evaluate
  122. * evaluates this rule for a specific feature
  123. *
  124. * Parameters:
  125. * feature - {<OpenLayers.Feature>} feature to apply the rule to.
  126. *
  127. * Returns:
  128. * {Boolean} true if the rule applies, false if it does not.
  129. * This rule is the default rule and always returns true.
  130. */
  131. evaluate: function(feature) {
  132. var context = this.getContext(feature);
  133. var applies = true;
  134. if (this.minScaleDenominator || this.maxScaleDenominator) {
  135. var scale = feature.layer.map.getScale();
  136. }
  137. // check if within minScale/maxScale bounds
  138. if (this.minScaleDenominator) {
  139. applies = scale >= OpenLayers.Style.createLiteral(
  140. this.minScaleDenominator, context);
  141. }
  142. if (applies && this.maxScaleDenominator) {
  143. applies = scale < OpenLayers.Style.createLiteral(
  144. this.maxScaleDenominator, context);
  145. }
  146. // check if optional filter applies
  147. if(applies && this.filter) {
  148. // feature id filters get the feature, others get the context
  149. if(this.filter.CLASS_NAME == "OpenLayers.Filter.FeatureId") {
  150. applies = this.filter.evaluate(feature);
  151. } else {
  152. applies = this.filter.evaluate(context);
  153. }
  154. }
  155. return applies;
  156. },
  157. /**
  158. * Method: getContext
  159. * Gets the context for evaluating this rule
  160. *
  161. * Paramters:
  162. * feature - {<OpenLayers.Feature>} feature to take the context from if
  163. * none is specified.
  164. */
  165. getContext: function(feature) {
  166. var context = this.context;
  167. if (!context) {
  168. context = feature.attributes || feature.data;
  169. }
  170. if (typeof this.context == "function") {
  171. context = this.context(feature);
  172. }
  173. return context;
  174. },
  175. /**
  176. * APIMethod: clone
  177. * Clones this rule.
  178. *
  179. * Returns:
  180. * {<OpenLayers.Rule>} Clone of this rule.
  181. */
  182. clone: function() {
  183. var options = OpenLayers.Util.extend({}, this);
  184. if (this.symbolizers) {
  185. // clone symbolizers
  186. var len = this.symbolizers.length;
  187. options.symbolizers = new Array(len);
  188. for (var i=0; i<len; ++i) {
  189. options.symbolizers[i] = this.symbolizers[i].clone();
  190. }
  191. } else {
  192. // clone symbolizer
  193. options.symbolizer = {};
  194. var value, type;
  195. for(var key in this.symbolizer) {
  196. value = this.symbolizer[key];
  197. type = typeof value;
  198. if(type === "object") {
  199. options.symbolizer[key] = OpenLayers.Util.extend({}, value);
  200. } else if(type === "string") {
  201. options.symbolizer[key] = value;
  202. }
  203. }
  204. }
  205. // clone filter
  206. options.filter = this.filter && this.filter.clone();
  207. // clone context
  208. options.context = this.context && OpenLayers.Util.extend({}, this.context);
  209. return new OpenLayers.Rule(options);
  210. },
  211. CLASS_NAME: "OpenLayers.Rule"
  212. });