Permalink
Browse files

Add featureContext and listContext to use whit templates.

  • Loading branch information...
1 parent 706f6d2 commit 816b1ece43f2f2f3d4e9d96f43b1d0f175f382c1 @jorix committed Dec 22, 2012
Showing with 118 additions and 116 deletions.
  1. +118 −45 lib/FeaturePopups.js
  2. +0 −71 lib/patches_OL-popup-autosize.js
View
@@ -672,6 +672,14 @@ OpenLayers.Control.FeaturePopups = OpenLayers.Class(OpenLayers.Control, {
*
* Valid options:
* templates - {Object} Templates
+ * listContext - {Object} Contains the keys with the values that were used
+ * instead of values of context used by templates `list` and
+ * `hoverList`. If 'undefined' key exists their value will be
+ * used instead of text 'undefined'.
+ * featureContext - {Object} Contains the keys with the values that were
+ * used instead of values of feature properties (used by
+ * templates: single, item, hover, hoverItem) If 'undefined' key exists
+ * their value will be used instead of text 'undefined'.
* eventListeners - {Object} This object will be registered with
* <OpenLayers.Events.on>, default scope is the control.
*
@@ -1625,6 +1633,18 @@ OpenLayers.Control.FeaturePopups.Layer = OpenLayers.Class({
*/
templates: null,
+ /**
+ * APIProperty: featureContext
+ * {Object} See <FeaturePopups.AddLayer>
+ */
+ featureContext: null,
+
+ /**
+ * APIProperty: listContext
+ * {Object} See <FeaturePopups.AddLayer>
+ */
+ listContext: null,
+
/**
* Property: safeSelection
* {Boolean} Internal use to optimize performance, true if
@@ -1750,15 +1770,17 @@ OpenLayers.Control.FeaturePopups.Layer = OpenLayers.Class({
this.control = control;
this.layer = layer;
+ // Prepare for special options
+ options = options || {};
+
// Templates
- var oTemplates = options && options.templates || {};
+ var oTemplates = options.templates || {};
var templates = {};
for (var templateName in oTemplates) {
templates[templateName] =
this.prepareTemplate(oTemplates[templateName]);
}
this.templates = templates;
- this.eventListeners = options.eventListeners,
// Events
this.events = new OpenLayers.Events(this, null, this.EVENT_TYPES);
@@ -1788,6 +1810,76 @@ OpenLayers.Control.FeaturePopups.Layer = OpenLayers.Class({
OpenLayers.Control.FeaturePopups.CLOSE_ON_REMOVE) {
this.layerListeners['featuresremoved'] = this.onFeaturesremoved;
}
+
+ // Renderer of templates
+ // ---------------
+ // private vars
+ var _context, _extendedContext;
+ var _replacer = function(str, match) {
+ var replacement;
+ // Loop through all subs. Example: ${a.b.c}
+ var subs = match.split(/\.+/);
+ if (_extendedContext && subs.length === 1) {
+ replacement = _extendedContext[subs[0]];
+ if (replacement && typeof replacement == 'function') {
+ replacement = replacement.call(this, _context);
+ }
+ }
+ if (replacement === undefined) {
+ for (var i = 0; i < subs.length; i++) {
+ if (i == 0) {
+ replacement = _context;
+ }
+ if (replacement === undefined) {
+ break;
+ }
+ replacement = replacement[subs[i]];
+ }
+ }
+ // If replacement is undefined, return the string 'undefined'.
+ if (replacement === undefined) {
+ replacement = _extendedContext['undefined'];
+ replacement =
+ (replacement !== undefined ? replacement : 'undefined');
+ }
+ return replacement;
+ };
+
+ /**
+ * Function: renderTemplate
+ * Given a string with tokens in the form ${token}, return a string
+ * with tokens replaced with properties from the given context
+ * object. Represent a literal "${" by doubling it, e.g. "${${".
+ *
+ * Parameters:
+ * template - {String || Function}
+ * If template is a string then template
+ * has the form "literal ${token}" where the token will be replaced
+ * by the value of context["token"]. When is a function it will
+ * receive the context as a argument.
+ * context - {Object} Object with properties corresponding to the tokens
+ * in the template.
+ * extendedContext - {Object} Object with properties corresponding to
+ * the overlaid tokens, if a token is a function its scope is
+ * context.
+ *
+ * Returns:
+ * {String} A string with tokens replaced from the context object.
+ */
+ var renderTemplate = function(template, context, extendedContext) {
+ if (typeof template == 'string') {
+ _context = context;
+ _extendedContext = extendedContext;
+ return template.replace(
+ OpenLayers.String.tokenRegEx, _replacer);
+ } else if (typeof template == 'function') {
+ return template(context);
+ } else {
+ return '';
+ }
+ };
+ // published as public function
+ this.renderTemplate = renderTemplate;
},
/**
@@ -1916,7 +2008,8 @@ OpenLayers.Control.FeaturePopups.Layer = OpenLayers.Class({
popupObjHover.clear();
var templates = this.templates,
- template = templates.hover;
+ template = templates.hover,
+ oContextFeature = this.featureContext;
if (template) {
var lonLat = control.getLocationFromSelPixel(control.controls.hover,
feature);
@@ -1929,7 +2022,8 @@ OpenLayers.Control.FeaturePopups.Layer = OpenLayers.Class({
feature: feature
},
lonLat,
- this.renderTemplate(template, feature.cluster[0]));
+ this.renderTemplate(
+ template, feature.cluster[0]), oContextFeature);
} else {
var html = '',
popupObjHoverList = control.popupObjs.hoverList;
@@ -1941,7 +2035,7 @@ OpenLayers.Control.FeaturePopups.Layer = OpenLayers.Class({
for (var i = 0, len = cFeatures.length;
i < len; i++) {
htmlAux.push(this.renderTemplate(itemTemplate,
- cFeatures[i]));
+ cFeatures[i], oContextFeature));
}
html = htmlAux.join('\n');
}
@@ -1955,18 +2049,19 @@ OpenLayers.Control.FeaturePopups.Layer = OpenLayers.Class({
layer: feature.layer,
count: cFeatures.length,
html: html
- })
+ }, this.listContext)
);
}
}
} else {
popupObjHover.showPopup({
- layerObj: this,
- layer: this.layer,
- feature: feature
- },
- lonLat,
- this.renderTemplate(template, feature));
+ layerObj: this,
+ layer: this.layer,
+ feature: feature
+ },
+ lonLat,
+ this.renderTemplate(template, feature, oContextFeature)
+ );
}
}
},
@@ -2222,7 +2317,8 @@ OpenLayers.Control.FeaturePopups.Layer = OpenLayers.Class({
var i, len, feature,
selectionHash = [],
staticSelectionHash = '',
- layerSelection = this.layer.selectedFeatures;
+ layerSelection = this.layer.selectedFeatures,
+ oContextFeature = this.featureContext;
if (this.safeSelection) {
var savedSF = this.selection;
for (i = 0, len = layerSelection.length; i < len; ++i) {
@@ -2262,7 +2358,8 @@ OpenLayers.Control.FeaturePopups.Layer = OpenLayers.Class({
feature = features[i];
bounds.extend(feature.geometry.getBounds());
layerTemplate && htmlAux.push(
- this.renderTemplate(itemTemplate, feature));
+ this.renderTemplate(itemTemplate, feature, oContextFeature)
+ );
if (feature.fid) {
selectionHash.push(feature.fid);
} else {
@@ -2288,7 +2385,8 @@ OpenLayers.Control.FeaturePopups.Layer = OpenLayers.Class({
layer: layer,
count: features.length,
html: htmlAux.join('\n')
- }
+ },
+ this.listContext
);
}
}
@@ -2320,7 +2418,8 @@ OpenLayers.Control.FeaturePopups.Layer = OpenLayers.Class({
hasTemplate = false,
sTemplate = this.templates.single;
if (sTemplate) {
- html = this.renderTemplate(sTemplate, feature);
+ html = this.renderTemplate(
+ sTemplate, feature, this.featureContext);
hasTemplate = true;
}
return {hasTemplate: hasTemplate, html: html};
@@ -2531,7 +2630,9 @@ OpenLayers.Control.FeaturePopups.Layer = OpenLayers.Class({
feature: feature
},
feature.geometry.getBounds().getCenterLonLat(),
- this.renderTemplate(template, feature)
+ this.renderTemplate(
+ template, feature, this.featureContext
+ )
);
}
clearPopup = false;
@@ -2584,33 +2685,5 @@ OpenLayers.Control.FeaturePopups.Layer = OpenLayers.Class({
return sFeatures;
},
- /**
- * Function: renderTemplate
- * Given a string with tokens in the form ${token}, return a string
- * with tokens replaced with properties from the given context
- * object. Represent a literal "${" by doubling it, e.g. "${${".
- *
- * Parameters:
- * template - {String || Function}
- * If template is a string then template
- * has the form "literal ${token}" where the token will be replaced
- * by the value of context["token"]. When is a function it will receive
- * the context as a argument.
- * context - {Object} Object with properties corresponding to the tokens
- * in the template.
- *
- * Returns:
- * {String} A string with tokens replaced from the context object.
- */
- renderTemplate: function(template, context) {
- if (typeof template == 'string') {
- return OpenLayers.String.format(template, context);
- } else if (typeof template == 'function') {
- return template(context);
- } else {
- return '';
- }
- },
-
CLASS_NAME: 'OpenLayers.Control.FeaturePopups.Layer'
});
@@ -22,8 +22,6 @@ Patches included:
scroll bar to calculate min/max size.
https://github.com/openlayers/openlayers/pull/613 FramedCloud Popup:
adjust the insertion point.
- https://github.com/openlayers/openlayers/pull/631 Avoid breaking the
- "OpenLayers.String.format" execution
fixed in 2.12:
https://github.com/openlayers/openlayers/pull/505
other patches included but are pending publication as "Pull Rquest" on OL:
@@ -34,7 +32,6 @@ Patches included:
is zero.
Patched functions:
- OpenLayers.String.format
OpenLayers.Util.getRenderedDimensions
OpenLayers.Util.getScrollbarWidth
OpenLayers.Util.getW3cBoxModel <-- new!
@@ -44,74 +41,6 @@ Patched functions:
OpenLayers.Popup.FramedCloud.prototype.positionBlocks (object)
*/
-// ** OpenLayers.BaseTypes **
- /**
- * APIFunction: format
- * Given a string with tokens in the form ${token}, return a string
- * with tokens replaced with properties from the given context
- * object. Represent a literal "${" by doubling it, e.g. "${${".
- *
- * Parameters:
- * template - {String} A string with tokens to be replaced. A template
- * has the form "literal ${token}" where the token will be replaced
- * by the value of context["token"].
- * context - {Object} An optional object with properties corresponding
- * to the tokens in the format string. If no context is sent, the
- * window object will be used.
- * args - {Array} Optional arguments to pass to any functions found in
- * the context. If a context property is a function, the token
- * will be replaced by the return from the function called with
- * these arguments.
- *
- * Returns:
- * {String} A string with tokens replaced from the context object.
- */
-OpenLayers.String.format = function(template, context, args) {
- if(!context) {
- context = window;
- }
-
- // Example matching:
- // str = ${foo.bar}
- // match = foo.bar
- var replacer = function(str, match) {
- var replacement;
-
- // Loop through all subs. Example: ${a.b.c}
- // 0 -> replacement = context[a];
- // 1 -> replacement = context[a][b];
- // 2 -> replacement = context[a][b][c];
- var subs = match.split(/\.+/);
- for (var i=0; i< subs.length; i++) {
- if (i == 0) {
- replacement = context;
- }
- if (replacement === undefined) {
- break;
- }
- replacement = replacement[subs[i]];
- }
-
- if(typeof replacement == "function") {
- replacement = args ?
- replacement.apply(null, args) :
- replacement();
- }
-
- // If replacement is undefined, return the string 'undefined'.
- // This is a workaround for a bugs in browsers not properly
- // dealing with non-participating groups in regular expressions:
- // http://blog.stevenlevithan.com/archives/npcg-javascript
- if (typeof replacement == 'undefined') {
- return 'undefined';
- } else {
- return replacement;
- }
- };
-
- return template.replace(OpenLayers.String.tokenRegEx, replacer);
- };
-
// ** OpenLayers.Util **
/**
* Method: getRenderedDimensions

0 comments on commit 816b1ec

Please sign in to comment.