first import

This commit is contained in:
Bachir Soussi Chiadmi
2015-04-08 11:40:19 +02:00
commit 1bc61b12ad
8435 changed files with 1582817 additions and 0 deletions

View File

@@ -0,0 +1,66 @@
<?php
class openlayers_plus_behavior_blockswitcher extends openlayers_behavior {
/**
* Override of options_init().
*/
function options_init() {
$options = array(
'enabled' => FALSE,
'position' => 'se',
);
return $options;
}
/**
* Override of options_form().
*/
function options_form($defaults) {
return array(
'enabled' => array(
'#type' => 'checkbox',
'#title' => t('Show blockswitcher in map'),
'#default_value' => isset($defaults['enabled']) ? $defaults['enabled'] : array(),
),
'open' => array(
'#type' => 'checkbox',
'#title' => t('Show blockswitcher open when the map loads'),
'#default_value' => isset($defaults['open']) ? $defaults['open'] : array(),
),
'overlay_style' => array(
'#type' => 'select',
'#title' => t('Show overlay layers as checkboxes or radio buttons'),
'#options' => array(
'checkbox' => t('Checkboxes'),
'radio' => t('Radio Buttons'),
),
'#default_value' => isset($defaults['overlay_style']) ? $defaults['overlay_style'] : array(),
),
'position' => array(
'#type' => 'select',
'#title' => t('Position'),
'#options' => array(
'ne' => t('Top right'),
'se' => t('Bottom right'),
'sw' => t('Bottom left'),
'nw' => t('Top left'),
),
'#default_value' => isset($defaults['position']) ? $defaults['position'] : array(),
),
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers_plus')
. '/behaviors/openlayers_plus_behavior_blockswitcher.js');
if ($this->options['enabled']) {
$block = module_invoke('openlayers_plus', 'block_view', 'blockswitcher');
$this->options['block'] = drupal_render($block);
}
return $this->options;
}
}

View File

@@ -0,0 +1,232 @@
/**
* Implementation of Drupal behavior.
*/
(function($) {
/**
* Blockswitcher is **NOT** an OpenLayers control.
*/
Drupal.behaviors.OpenLayersPlusBlockswitcher = {};
/**
* Initializes the */
Drupal.behaviors.OpenLayersPlusBlockswitcher = {
'attach' : function(context, settings) {
/*
* First the support functions
*/
/**
* Checks if the layer state has changed since the last redraw() call.
*
* Returns:
* {Boolean} The layer state changed since the last redraw() call.
*/
Drupal.behaviors.OpenLayersPlusBlockswitcher.needsRedraw = function() {
if ( !this.layerStates.length || (this.map.layers.length != this.layerStates.length) ) {
return true;
}
for (var i=0, len=this.layerStates.length; i<len; i++) {
var layerState = this.layerStates[i];
var layer = this.map.layers[i];
if ( (layerState.name != layer.name) || (layerState.inRange != layer.inRange) || (layerState.id != layer.id) || (layerState.visibility != layer.visibility) ) {
return true;
}
}
return false;
};
/**
* Redraws the blockswitcher to reflect the current state of layers.
*/
Drupal.behaviors.OpenLayersPlusBlockswitcher.redraw = function() {
if (this.needsRedraw()) {
// Clear out previous layers
$('.layers.base .layers-content div', this.blockswitcher).remove();
$('.layers.data .layers-content div', this.blockswitcher).remove();
$('.layers.base', this.blockswitcher).hide();
$('.layers.data', this.blockswitcher).hide();
// Save state -- for checking layer if the map state changed.
// We save this before redrawing, because in the process of redrawing
// we will trigger more visibility changes, and we want to not redraw
// and enter an infinite loop.
var len = this.map.layers.length;
this.layerStates = new Array(len);
for (var i = 0; i < len; i++) {
var layerState = this.map.layers[i];
this.layerStates[i] = {'name': layerState.name, 'visibility': layerState.visibility, 'inRange': layerState.inRange, 'id': layerState.id};
}
var layers = this.map.layers.slice();
for (i = 0, len = layers.length; i < len; i++) {
var layer = layers[i];
var baseLayer = layer.isBaseLayer;
if (layer.displayInLayerSwitcher) {
// Only check a baselayer if it is *the* baselayer, check data layers if they are visible
var checked = baseLayer ? (layer === this.map.baseLayer) : layer.getVisibility();
// Create input element
var inputType = (baseLayer) ? "radio" : this.overlay_style;
var inputElem = $('.factory .'+ inputType, this.blockswitcher).clone();
// Append to container
var container = baseLayer ? $('.layers.base', this.blockswitcher) : $('.layers.data', this.blockswitcher);
$('.layers-content', container).append(inputElem);
// Set label text
$('label', inputElem).append((layer.title !== undefined) ? layer.title : layer.name);
// Add states and click handler
if (baseLayer) {
$(inputElem)
.click(function() { Drupal.behaviors.OpenLayersPlusBlockswitcher.layerClick(this); })
.data('layer', layer)
if (checked) {
$(inputElem).addClass('activated');
}
}
else {
if (this.overlay_style == 'checkbox') {
$('input', inputElem)
.click(function() { Drupal.behaviors.OpenLayersPlusBlockswitcher.layerClick(this); })
.data('layer', layer)
.attr('disabled', !baseLayer && !layer.inRange)
.attr('checked', checked);
}
else if(this.overlay_style == 'radio') {
$(inputElem)
.click(function() { Drupal.behaviors.OpenLayersPlusBlockswitcher.layerClick(this); })
.data('layer', layer)
.attr('disabled', !layer.inRange);
if (checked) {
$(inputElem).addClass('activated');
}
}
// Set key styles
if (layer.styleMap) {
css = Drupal.behaviors.OpenLayersPlusBlockswitcher.styleMapToCSS(layer.styleMap);
$('span.key', inputElem).css(css);
}
}
}
}
/*
* Only show layers when there are more than 1 for baselayers, or 1 for data layers
*/
if ($('.layers.base .layers-content div', this.blockswitcher).lenght > 1) {
$('.layers.base', this.blockswitcher).show();
}
if ($('.layers.data .layers-content div', this.blockswitcher).length > 0) {
$('.layers.data', this.blockswitcher).show();
}
}
};
/**
* Click handler that activates or deactivates a layer.
*/
Drupal.behaviors.OpenLayersPlusBlockswitcher.layerClick = function(element) {
var layer = $(element).data('layer');
if (layer.isBaseLayer) {
$('.layers.base .layers-content .activated').removeClass('activated');
$(element).addClass('activated');
layer.map.setBaseLayer(layer);
}
else if (this.overlay_style == 'radio') {
$('.layers.data .layers-content .activated').removeClass('activated');
$.each(this.map.getLayersBy('isBaseLayer', false),
function() {
if(this.CLASS_NAME !== 'OpenLayers.Layer.Vector.RootContainer' &&
this.displayInLayerSwitcher) {
this.setVisibility(false);
}
}
);
layer.setVisibility(true);
$(element).addClass('activated');
}
else {
layer.setVisibility($(element).is(':checked'));
}
};
/**
* Parameters:
* styleMap {OpenLayers.StyleMap}
*
* Returns:
* {Object} An object with css properties and values that can be applied to an element
*
*/
Drupal.behaviors.OpenLayersPlusBlockswitcher.styleMapToCSS = function(styleMap) {
css = {};
default_style = styleMap.styles['default'].defaultStyle;
if (default_style.fillColor === 'transparent' && typeof default_style.externalGraphic != 'undefined') {
css['background-image'] = 'url('+default_style.externalGraphic+')';
css['background-repeat'] = 'no-repeat';
css['background-color'] = 'transparent';
css.width = default_style.pointRadius * 2;
css.height = default_style.pointRadius * 2;
}
else {
css['background-color'] = default_style.fillColor;
}
if (default_style.strokeWidth > 0) {
css['border-color'] = default_style.strokeColor;
}
return css;
}
this.layerStates = [];
var data = $(context).data('openlayers');
if (data && data.map.behaviors.openlayers_plus_behavior_blockswitcher) {
this.map = data.openlayers;
this.overlay_style = (data.map.behaviors.openlayers_plus_behavior_blockswitcher.overlay_style) ?
data.map.behaviors.openlayers_plus_behavior_blockswitcher.overlay_style : 'checkbox';
// If behavior has requested display inside of map, respect it.
if (data.map.behaviors.openlayers_plus_behavior_blockswitcher.enabled == true) {
var block = $(data.map.behaviors.openlayers_plus_behavior_blockswitcher.block);
block.addClass(data.map.behaviors.openlayers_plus_behavior_blockswitcher.position);
$('.block-title', block).click(function() {
$(this).parents('div.block').toggleClass('expanded');
$(this).siblings('div.block-content').toggle();
});
$(context).find('.olMapViewport').append(block);
if (data.map.behaviors.openlayers_plus_behavior_blockswitcher.open == true) {
$('.block-title', block).click();
}
}
this.blockswitcher = $('div.openlayers_plus-blockswitcher');
// Don't propagate click events to the map
// this doesn't catch events that are below the layer list
$('div.openlayers_plus-blockswitcher').mousedown(function(evt) {
OpenLayers.Event.stop(evt);
});
data.openlayers.events.on({
"addlayer": this.redraw,
"changelayer": this.redraw,
"removelayer": this.redraw,
"changebaselayer": this.redraw,
scope: this
});
this.redraw();
}
}
}
})(jQuery);

View File

@@ -0,0 +1,75 @@
<?php
class openlayers_plus_behavior_blocktoggle extends openlayers_behavior {
/**
* Override of options_init().
*/
function options_init() {
$options = array(
'enabled' => FALSE,
'position' => 'se',
);
return $options;
}
/**
* Override of options_form().
*/
function options_form($defaults) {
return array(
'enabled' => array(
'#type' => 'checkbox',
'#title' => t('Show blocktoggle in map'),
'#default_value' => isset($defaults['enabled']) ? $defaults['enabled'] : array(),
),
'a_label' => array(
'#type' => 'textfield',
'#title' => t('Layer A Label'),
'#description' => t('This can either be the name of the layer, or a shorter name you choose.'),
'#default_value' => isset($defaults['a_label']) ? $defaults['a_label'] : array(),
),
'a' => array(
'#type' => 'select',
'#options' => $this->map['layers'],
'#title' => t('Layer A'),
'#default_value' => isset($defaults['a']) ? $defaults['a'] : array(),
),
'b_label' => array(
'#type' => 'textfield',
'#title' => t('Layer B Label'),
'#description' => t('This can either be the name of the layer, or a shorter name you choose.'),
'#default_value' => isset($defaults['b_label']) ? $defaults['b_label'] : array(),
),
'b' => array(
'#type' => 'select',
'#options' => $this->map['layers'],
'#title' => t('Layer B'),
'#default_value' => isset($defaults['b']) ? $defaults['b'] : array(),
),
'position' => array(
'#type' => 'select',
'#title' => t('Position'),
'#options' => array(
'ne' => t('Top right'),
'se' => t('Bottom right'),
'sw' => t('Bottom left'),
'nw' => t('Top left'),
),
'#default_value' => isset($defaults['position']) ? $defaults['position'] : array(),
),
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers_plus')
. '/behaviors/openlayers_plus_behavior_blocktoggle.js');
if ($this->options['enabled']) {
$block = module_invoke('openlayers_plus', 'block_view', 'blocktoggle');
$this->options['block'] = drupal_render($block);
}
return $this->options;
}
}

View File

@@ -0,0 +1,121 @@
/**
* Implementation of Drupal behavior.
*/
//Drupal.behaviors.openlayers_plus_behavior_blocktoggle = function(context) {
// Drupal.OpenLayersPlusBlocktoggle.attach(context);
//};
(function($) {
/**
* Implementation of Drupal behavior.
*/
//Drupal.behaviors.openlayers_plus_behavior_blocktoggle = function(context) {
Drupal.openlayers.addBehavior('openlayers_plus_behavior_blocktoggle', function (data, options) {
Drupal.OpenLayersPlusBlocktoggle.attach(data, options);
});
/**
* Blocktoggle is **NOT** an OpenLayers control.
*/
Drupal.OpenLayersPlusBlocktoggle = {};
Drupal.OpenLayersPlusBlocktoggle.layerStates = [];
/**
* Initializes the blocktoggle and attaches to DOM elements.
*/
Drupal.OpenLayersPlusBlocktoggle.attach = function(data, options) {
/**
* Initializes the blocktoggle and attaches to DOM elements.
*/
//Drupal.OpenLayersPlusBlocktoggle.attach = function(context) {
// var data = $(context).data('openlayers');
if (data && data.map.behaviors.openlayers_plus_behavior_blocktoggle) {
this.map = data.openlayers;
this.layer_a = this.map.getLayersBy('drupalID',
options.a)[0];
this.layer_b = this.map.getLayersBy('drupalID',
options.b)[0];
// If behavior has requested display inside of map, respect it.
if (options.enabled == true) {
var block = $(options.block);
block.addClass(options.position);
$(data.openlayers.viewPortDiv).append(block);
}
this.blocktoggle = $('div.block-openlayers_plus-blocktoggle');
this.blocktoggle.data('layer_a', this.layer_a);
this.blocktoggle.data('layer_b', this.layer_b);
// Don't propagate click events to the map
// this doesn't catch events that are below the layer list
$('div.block-openlayers_plus-blocktoggle *').mousedown(function(evt) {
OpenLayers.Event.stop(evt);
});
$('.openlayers-blocktoggle-a').text(
data.map.behaviors.openlayers_plus_behavior_blocktoggle.a_label
);
$('.openlayers-blocktoggle-b').text(
data.map.behaviors.openlayers_plus_behavior_blocktoggle.b_label
);
$('div.block-openlayers_plus-blocktoggle').toggle(
function() {
$(this).data('layer_a').setVisibility(false);
$(this).data('layer_b').setVisibility(true);
$(this).find('.openlayers-blocktoggle-a').removeClass('activated');
$(this).find('.openlayers-blocktoggle-b').addClass('activated');
},
function() {
$(this).data('layer_b').setVisibility(false);
$(this).data('layer_a').setVisibility(true);
$(this).find('.openlayers-blocktoggle-b').removeClass('activated');
$(this).find('.openlayers-blocktoggle-a').addClass('activated');
}
);
data.openlayers.events.on({
"addlayer": this.redraw,
"changelayer": this.redraw,
"removelayer": this.redraw,
scope: this
});
}
};
/**
* Checks if the layer state has changed since the last redraw() call.
*
* Returns:
* {Boolean} The layer state changed since the last redraw() call.
*/
Drupal.OpenLayersPlusBlocktoggle.needsRedraw = function() {
return (
(this.a_vis ==
$(this).find('.openlayers-blocktoggle-a').hasClass('activated')) ? 1 : 0
^
(this.b_vis ==
$(this).find('.openlayers-blocktoggle-b').hasClass('activated')) ? 1 : 0);
};
/**
* Redraws the blocktoggle to reflect the current state of layers.
*/
Drupal.OpenLayersPlusBlocktoggle.redraw = function() {
if (this.needsRedraw()) {
this.a_vis = this.layer_a.visibility;
this.b_vis = this.layer_b.visibility;
// Clear out previous layers
// Save state -- for checking layer if the map state changed.
// We save this before redrawing, because in the process of redrawing
// we will trigger more visibility changes, and we want to not redraw
// and enter an infinite loop.
$('div.openlayers-blocktoggle').click();
}
};
})(jQuery);

View File

@@ -0,0 +1,24 @@
<?php
class openlayers_plus_behavior_legend extends openlayers_behavior {
function options_init() {
return array();
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers_plus') . '/behaviors/openlayers_plus_behavior_legend.js');
$options = array();
foreach ($map['layers'] as $layer => $layer_data) {
if (isset($layer_data['options']['legend']) && is_array($layer_data['options']['legend'])) {
$options[$layer] = theme('openlayers_plus_legend', array('legend' => $layer_data['options']['legend'], 'layer' => $layer_data, 'layer_id' => $layer));
}
elseif (isset($layer_data['options']['legend'])) {
$options[$layer] = theme('openlayers_plus_legend_raw', array('raw' => $layer_data['options']['legend'], 'layer' => $layer_data, 'layer_id' => $layer));
}
}
return $options;
}
}

View File

@@ -0,0 +1,45 @@
/**
* Implementation of Drupal behavior.
*/
Drupal.behaviors.openlayers_plus_behavior_legend = function(context) {
Drupal.OpenLayersPlusLegend.attach(context);
};
Drupal.OpenLayersPlusLegend = {};
Drupal.OpenLayersPlusLegend.attach = function(context) {
var data = $(context).data('openlayers');
if (data && data.map.behaviors.openlayers_plus_behavior_legend) {
var layer, i;
for (i in data.openlayers.layers) {
layer = data.openlayers.layers[i];
if (data.map.behaviors.openlayers_plus_behavior_legend[layer.drupalID]) {
if (!$('div.openlayers-legends', context).size()) {
$(context).append("<div class='openlayers-legends'></div>");
}
layer.events.register('visibilitychanged', layer, Drupal.OpenLayersPlusLegend.setLegend);
// Trigger the setLegend() method at attach time. We don't know whether
// our behavior is being called after the map has already been drawn.
Drupal.OpenLayersPlusLegend.setLegend(layer);
}
}
}
};
Drupal.OpenLayersPlusLegend.setLegend = function(layer) {
// The layer param may vary based on the context from which we are called.
layer = layer.object ? layer.object : layer;
var name = layer.drupalID;
var map = $(layer.map.div);
var data = map.data('openlayers');
var legend = data.map.behaviors.openlayers_plus_behavior_legend[name];
var legends = $('div.openlayers-legends', map);
if (layer.visibility && $('#openlayers-legend-'+ name, legends).size() === 0) {
legends.append(legend);
}
else if (!layer.visibility) {
$('#openlayers-legend-'+name, legends).remove();
}
};

View File

@@ -0,0 +1,12 @@
<?php
class openlayers_plus_behavior_permalink extends openlayers_behavior {
function options_init() {
return array();
}
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers_plus') . '/behaviors/openlayers_plus_behavior_permalink.js');
return $this->options;
}
}

View File

@@ -0,0 +1,275 @@
/**
* Implementation of Drupal behavior.
*/
Drupal.behaviors.openlayers_plus_behavior_permalink = function(context) {
Drupal.OpenLayersPermalink.attach(context);
};
Drupal.OpenLayersPermalink = {};
Drupal.OpenLayersPermalink.attach = function(context) {
var data = $(context).data('openlayers');
if (data && data.map.behaviors.openlayers_plus_behavior_permalink) {
// Doctor link hrefs.
$('#canvas a:not(.processed-permalink)').each(function() {
$(this).addClass('processed-permalink');
$(this).click(function() {
var href = $(this).attr('href');
if (href.indexOf('#') === -1) {
href = Drupal.OpenLayersPermalink.addQuery(href);
$(this).attr('href', href);
}
});
});
// Doctor form submission.
$('form:not(.processed-permalink)').each(function() {
$(this).addClass('processed-permalink');
$(this).submit(function() {
var action = $(this).attr('action');
action = Drupal.OpenLayersPermalink.addQuery(action, '?');
$(this).attr('action', action);
});
});
// Add control
var control = new OpenLayers.Control.PermalinkPlus();
data.openlayers.addControl(control);
control.activate();
}
};
Drupal.OpenLayersPermalink.addQuery = function(href, delimiter) {
delimiter = delimiter ? delimiter : '#';
var processed = false;
$('div.openlayers-map').each(function() {
if (!processed) {
var data = $(this).data('openlayers');
if (data.openlayers) {
// If there is a permalink control present, attempt to persist layer settings when clicking through.
for (var i in data.openlayers.controls) {
if (data.openlayers.controls[i].CLASS_NAME == 'OpenLayers.Control.PermalinkPlus') {
var params = OpenLayers.Util.getParameterString(data.openlayers.controls[i].createParams());
params = params.split('&');
var url = href.split(delimiter);
for (var key in params) {
if (params[key].split('=')[0] == 'layers' || params[key].split('=')[0] == 'baseLayers' ) {
if (url[1]) {
url[1] += '&' + params[key];
}
else {
url[1] = params[key];
}
}
}
href = url.join(delimiter);
}
}
}
}
});
return href;
};
OpenLayers.Control.ArgParserPlus = OpenLayers.Class(OpenLayers.Control.ArgParser, {
/**
* Alternative to OpenLayers.Utils.getParameters() that uses the URL hash.
*/
getParameters: function() {
// Parse out parameters portion of url string
var paramsString = window.location.hash.substring(1);
var parameters = {};
var pairs = paramsString.split(/[&;]/);
for(var i=0, len=pairs.length; i<len; ++i) {
var keyValue = pairs[i].split('=');
if (keyValue[0]) {
var key = decodeURIComponent(keyValue[0]);
var value = keyValue[1] || ''; //empty string if no value
//decode individual values
value = value.split(",");
for(var j=0, jlen=value.length; j<jlen; j++) {
value[j] = decodeURIComponent(value[j]);
}
//if there's only one value, do not return as array
if (value.length == 1) {
value = value[0];
}
parameters[key] = value;
}
}
return parameters;
},
/**
* Override of SetMap.
*/
setMap: function(map) {
OpenLayers.Control.prototype.setMap.apply(this, arguments);
// Make sure we dont already have an arg parser attached
for(var i=0, len=this.map.controls.length; i<len; i++) {
var control = this.map.controls[i];
if ( (control != this) &&
(control.CLASS_NAME == "OpenLayers.Control.ArgParser") ) {
// If a second argparser is added to the map, then we
// override the displayProjection to be the one added to the
// map.
if (control.displayProjection != this.displayProjection) {
this.displayProjection = control.displayProjection;
}
break;
}
}
if (i == this.map.controls.length) {
var args = this.getParameters();
// Be careful to set layer first, to not trigger unnecessary layer loads
if (args.layers) {
this.layers = typeof(args.layers) === 'string' ? this.layers = [args.layers] : args.layers;
}
if (args.baseLayers) {
this.baseLayers = typeof(args.baseLayers) === 'string' ? this.baseLayers = [args.baseLayers] : args.baseLayers;
}
if (this.layers || this.baseLayers) {
// when we add a new layer, set its visibility
this.map.events.register('addlayer', this,
this.configureLayers);
this.configureLayers();
}
if (args.lat && args.lon) {
this.center = new OpenLayers.LonLat(parseFloat(args.lon),
parseFloat(args.lat));
if (args.zoom) {
this.zoom = parseInt(args.zoom, 10);
}
// when we add a new baselayer to see when we can set the center
this.map.events.register('changebaselayer', this,
this.setCenter);
this.setCenter();
}
}
},
/**
* Override of configureLayers().
*/
configureLayers: function() {
this.map.events.unregister('addlayer', this, this.configureLayers);
var hasLayers = false;
var argLayers = {};
var i, j, name, layer;
if (this.layers) {
// Iterate over layers and filter arg layers down to ones that exist.
for (i in this.layers) {
name = this.layers[i];
for (j in this.map.layers) {
layer = this.map.layers[j];
if (!layer.isBaseLayer && layer.name === name) {
argLayers[name] = 1;
hasLayers = true;
}
}
}
// If any query layers exist, disable default layer settings and enable layers.
if (hasLayers) {
for (j in this.map.layers) {
layer = this.map.layers[j];
if (!layer.isBaseLayer) {
layer.setVisibility(layer.name in argLayers);
}
}
}
}
// Iterate over baseLayers. We can safely set the baselayer and bail without
// additional logic since there is only one base layer.
if (this.baseLayers) {
for (i in this.baseLayers) {
name = this.baseLayers[i];
for (j in this.map.layers) {
layer = this.map.layers[j];
if (layer.name === name) {
this.map.setBaseLayer(layer);
break;
}
}
}
}
},
CLASS_NAME: "OpenLayers.Control.ArgParserPlus"
});
OpenLayers.Control.PermalinkPlus = OpenLayers.Class(OpenLayers.Control.Permalink, {
argParserClass: OpenLayers.Control.ArgParserPlus,
/**
* Override of updateLink().
*/
updateLink: function() {
var href = this.base;
if (href.indexOf('#') != -1) {
href = href.substring( 0, href.indexOf('#') );
}
href += '#' + OpenLayers.Util.getParameterString(this.createParams());
this.element.href = href;
},
/**
* Override of createParams(). Generates smarter layer/baselayer query string.
*/
createParams: function(center, zoom, layers) {
center = center || this.map.getCenter();
var params = {};
// If there's still no center, map is not initialized yet.
// Break out of this function, and simply return the params from the
// base link.
if (center) {
//zoom
params.zoom = zoom || this.map.getZoom();
//lon,lat
var lat = center.lat;
var lon = center.lon;
if (this.displayProjection) {
var mapPosition = OpenLayers.Projection.transform(
{ x: lon, y: lat },
this.map.getProjectionObject(),
this.displayProjection );
lon = mapPosition.x;
lat = mapPosition.y;
}
params.lat = Math.round(lat*100000)/100000;
params.lon = Math.round(lon*100000)/100000;
// Handle layers & baselayers separately.
params.layers = [];
params.baseLayers = [];
layers = layers || this.map.layers;
for (var i in layers) {
var layer = layers[i];
if (layer.isBaseLayer) {
if (layer == this.map.baseLayer) {
params.baseLayers.push(layer.name);
}
}
else if (layer.getVisibility() && layer.displayInLayerSwitcher) {
params.layers.push(layer.name);
}
}
}
return params;
},
CLASS_NAME: "OpenLayers.Control.PermalinkPlus"
});

View File

@@ -0,0 +1,45 @@
<?php
class openlayers_plus_behavior_popup extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'layers' => array(),
);
}
/**
* Form defintion for per map customizations.
*/
function options_form($defaults = array()) {
// Only prompt for vector layers
$vector_layers = array();
foreach ($this->map['layers'] as $id => $name) {
$layer = openlayers_layer_load($id);
if (isset($layer->data['vector']) && $layer->data['vector'] == TRUE) {
$vector_layers[$id] = $name;
}
}
return array(
'layers' => array(
'#title' => t('Layers'),
'#type' => 'checkboxes',
'#options' => $vector_layers,
'#description' => t('Select layer to apply popups to.'),
'#default_value' => isset($defaults['layers']) ?
$defaults['layers'] : array(),
),
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers_plus') . '/behaviors/openlayers_plus_behavior_popup.js');
return $this->options;
}
}

View File

@@ -0,0 +1,182 @@
(function ($) {
Drupal.behaviors.openlayers_plus_behavior_popup = {
attach: function(context, settings) {
var data = $(context).data('openlayers');
if (data && data.map.behaviors.openlayers_plus_behavior_popup) {
var map = data.openlayers;
var options = data.map.behaviors.openlayers_plus_behavior_popup;
var layers = [];
// For backwards compatiability, if layers is not
// defined, then include all vector layers
if (typeof options.layers == 'undefined' || options.layers.length == 0) {
layers = map.getLayersByClass('OpenLayers.Layer.Vector');
}
else {
for (var i in options.layers) {
var selectedLayer = map.getLayersBy('drupalID', options.layers[i]);
if (typeof selectedLayer[0] != 'undefined') {
layers.push(selectedLayer[0]);
}
}
}
/*
* Due to a bug in OpenLayers,
* if you pass 1 layer to the SelectFeature control as an array
* the onClick event is not cancelled after the first layer.
* Some people might need that.
*/
if (layers.length == 1) {
layers = layers[0];
}
// Add control
var control = new OpenLayers.Control.SelectFeature(
layers,
{
activeByDefault: true,
highlightOnly: false,
multiple: false,
hover: false,
callbacks: {
'over': Drupal.openlayers_plus_behavior_popup.over,
'out': Drupal.openlayers_plus_behavior_popup.out,
'click': Drupal.openlayers_plus_behavior_popup.openPopup
}
}
);
data.openlayers.addControl(control);
control.activate();
}
else if ($(context).is('.openlayers-popupbox')) {
// Popup close
$('a.popup-close', context).click(function() {
$(this).parents('.openlayers-popupbox').fadeOut('fast', function() { $(this).remove(); });
return false;
});
// Set initial pager state
Drupal.openlayers_plus_behavior_popup.pager(context, 'set');
// Next link
$('ul.popup-links a.next', context).click(function() {
var context = $(this).parents('.openlayers-popupbox');
Drupal.openlayers_plus_behavior_popup.pager(context, 'next');
});
// Prev link
$('ul.popup-links a.prev', context).click(function() {
var context = $(this).parents('.openlayers-popupbox');
Drupal.openlayers_plus_behavior_popup.pager(context, 'prev');
});
}
}
};
Drupal.openlayers_plus_behavior_popup = {
// Pager actions
'pager': function(context, op) {
var active = $('li.openlayers-popupbox-active', context);
var index = $('div.item-list > ul > li', context).index(active);
var total = $('div.item-list > ul > li', context).size();
switch (op) {
case 'set':
if (active.size() === 0) {
index = 0;
$('div.item-list > ul > li', context).hide();
$('div.item-list > ul > li:first', context).addClass('openlayers-popupbox-active').show();
$('ul.popup-links a.prev', context).addClass('disabled');
if (total <= 1) {
$('ul.popup-links', context).hide();
}
}
else {
if (index === 0) {
$('ul.popup-links a.prev', context).addClass('disabled');
$('ul.popup-links a.next', context).removeClass('disabled');
}
else if (index == (total - 1)) {
$('ul.popup-links a.next', context).addClass('disabled');
$('ul.popup-links a.prev', context).removeClass('disabled');
}
else {
$('ul.popup-links a.next', context).removeClass('disabled');
$('ul.popup-links a.prev', context).removeClass('disabled');
}
}
var count = parseInt(index + 1, 10) + ' / ' + parseInt(total, 10);
$('span.count', context).text(count);
break;
case 'next':
if (index < (total - 1)) {
active.removeClass('openlayers-popupbox-active').hide()
.next('li').addClass('openlayers-popupbox-active').show();
Drupal.openlayers_plus_behavior_popup.pager(context, 'set');
}
break;
case 'prev':
if (index > 0) {
active.removeClass('openlayers-popupbox-active').hide()
.prev('li').addClass('openlayers-popupbox-active').show();
Drupal.openlayers_plus_behavior_popup.pager(context, 'set');
}
break;
}
},
// Click state
'openPopup': function(feature) {
var context = $(feature.layer.map.div);
// Initialize popup
if (!$('.openlayers-popupbox', context).size()) {
context.append("<div class='openlayers-popupbox popup'></div>");
}
else {
$('.openlayers-popupbox:not(.popup)').addClass('popup');
}
// Hide the layer switcher if it's open.
for (var key in context.data('openlayers').openlayers.controls) {
if (context.data('openlayers').openlayers.controls[key].CLASS_NAME == "OpenLayers.Control.LayerSwitcherPlus") {
context.data('openlayers').openlayers.controls[key].minimizeControl();
}
}
var text;
text = "<a href='#close' class='popup-close'>X</a>";
text += "<h2 class='popup-title'>" + feature.attributes.name + "</h2>";
if (feature.attributes.description != undefined) {
text += "<div class='popup-content'>" + feature.attributes.description + "</div>";
}
text += "<div class='popup-pager'><ul class='links popup-links'><li><a class='prev' href='#prev'>Prev</a></li><li><a class='next' href='#next'>Next</a></li></ul><span class='count'></span></div>";
$('.openlayers-popupbox', context).html(text).show();
Drupal.attachBehaviors($('.openlayers-popupbox', context));
},
// Callback for hover state
// Only show tooltips on hover if the story popup is not open.
'over': function(feature) {
var context = $(feature.layer.map.div);
if (!$('.openlayers-popupbox.popup', context).size()) {
if (feature.attributes.name) {
var text = "<div class='openlayers-popupbox'>";
text += "<h2 class='popup-title'>" + feature.attributes.name + "</h2>";
text += "<div class='popup-count'>" + parseInt(feature.attributes.count, 10) + "</div>";
text += "</div>";
context.append(text);
}
}
},
// Call back for out state.
'out': function(feature) {
var context = $(feature.layer.map.div);
$('.openlayers-popupbox:not(.popup)', context).fadeOut('fast', function() { $(this).remove(); });
}
};
})(jQuery);

View File

@@ -0,0 +1,267 @@
<?php
class openlayers_plus_behavior_scalepoints extends openlayers_behavior {
/**
* Override of options_init().
*/
function options_init() {
$options['min'] = array(
'pointRadius' => 5,
'value' => 0,
);
$options['max'] = array(
'pointRadius' => 20,
'value' => '',
);
$options['distinct'] = 5;
$options['min_label'] = -1;
$options['method'] = 'area';
// @TODO: This sucks. Get a submission/validation handling into the behaviors base class and fix this.
$options['fields'] = array('count, weight');
return $options;
}
/**
* Override of options_form().
*/
function options_form($defaults) {
$options = array (
'min' => array(
'#tree' => TRUE,
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#type' => 'fieldset',
'#title' => t('Minimum values'),
),
'max' => array(
'#tree' => TRUE,
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#type' => 'fieldset',
'#title' => t('Maximum values'),
)
);
foreach (array('min', 'max') as $key) {
$options[$key]['value'] = array(
'#title' => t('Value'),
'#description' => t('Enter a fixed value for this field or leave empty to autoscale points.'),
'#type' => 'textfield',
'#size' => 4,
'#default_value' => isset($defaults[$key]['value']) ? $defaults[$key]['value'] : array(),
);
$options[$key]['pointRadius'] = array(
'#title' => t('Radius'),
'#type' => 'textfield',
'#size' => 4,
'#default_value' => isset($defaults[$key]['pointRadius']) ? $defaults[$key]['pointRadius'] : array(),
);
$options[$key]['fillOpacity'] = array(
'#title' => t('Fill opacity'),
'#type' => 'textfield',
'#size' => 4,
'#maxlength' => 4,
'#default_value' => isset($defaults[$key]['fillOpacity']) ? $defaults[$key]['fillOpacity'] : array(),
);
$options[$key]['strokeWidth'] = array(
'#title' => t('Stroke width'),
'#type' => 'textfield',
'#size' => 4,
'#maxlength' => 4,
'#default_value' => isset($defaults[$key]['strokeWidth']) ? $defaults[$key]['strokeWidth'] : array(),
);
// @TODO: Handle color gradation using API functions in color module
/*
$form[$key]['fillColor'] = array(
'#title' => t('Fill color'),
'#type' => 'textfield',
'#size' => 7,
'#maxlength' => 7,
'#default_value' => $this->options[$key]['fillColor'],
);
$form[$key]['strokeColor'] = array(
'#title' => t('Stroke color'),
'#type' => 'textfield',
'#size' => 7,
'#maxlength' => 7,
'#default_value' => $this->options[$key]['strokeColor'],
);
*/
};
$options['method'] = array(
'#title' => t('Scaling method'),
'#type' => 'select',
'#options' => array(
'area' => t('Circle area'),
'radius' => t('Circle radius'),
),
'#default_value' => isset($defaults['method']) ? $defaults['method'] : array(),
);
$options['distinct'] = array(
'#title' => t('Number of distinct sizes'),
'#type' => 'textfield',
'#default_value' => isset($defaults['distinct']) ? $defaults['distinct'] : array(),
);
$options['fields'] = array(
'#title' => t('Fields'),
'#description' => t('Enter a comma separated list of attribute fields that can be used for scaling points. The first found attribute will be used.'),
'#type' => 'textfield',
'#default_value' => isset($defaults['fields']) ? $defaults['fields'] : array(),
);
$options['min_label'] = array(
'#tree' => TRUE,
'#collapsible' => TRUE,
'#collapsed' => TRUE,
'#type' => 'textfield',
'#title' => t('Minimum weight point to label'),
'#default_value' => isset($defaults['min_label']) ? $defaults['min_label'] : array(),
'#description' => t('Don\'t show labels below a certain point weight'),
);
return $options;
}
/**
* Generate weight segments from the number of distinct values.
*/
function get_weights() {
if (!is_numeric($this->options['distinct']) || $this->options['distinct'] < 1) {
$this->options['distinct'] = 5;
}
$size = number_format(1 / $this->options['distinct'], 2);
$weights = array();
for ($i = 1; $i < $this->options['distinct']; $i++) {
$key = (string) ($i * $size);
$weights[$key] = $i;
}
$weights[1] = $this->options['distinct'];
return $weights;
}
/**
* Generate a weight => pointRadius mapping.
*/
function get_styles() {
$weights = array_values($this->get_weights());
$styles = array();
foreach (array_keys($this->options['min']) as $key) {
if ($key !== 'value' && (!empty($this->options['min'][$key]) || !empty($this->options['max'][$key]))) {
$pointdiff = ($this->options['max'][$key] - $this->options['min'][$key]) / $this->options['distinct'];
$pointdiff = number_format($pointdiff, 2);
foreach ($weights as $weight) {
$styles[$weight][$key] = $this->options['min'][$key] + ($weight - 1) * $pointdiff;
if ($weight <= $this->options['min_label']) {
$styles[$weight]['label'] = '';
}
}
$styles[$this->options['distinct']][$key] = $this->options['max'][$key];
}
}
return $styles;
}
/**
* Retrieve the first found usable field from a set of features.
*/
protected function get_field($features) {
$fields = explode(',', $this->options['fields']);
foreach ($fields as $k => $v) {
$fields[$k] = trim($v);
}
foreach ($features as $feature) {
foreach ($fields as $field) {
if (isset($feature['attributes'][$field])) {
return $field;
}
}
}
return FALSE;
}
protected function get_layers($layers) {
$vector_layers = array();
foreach ($layers as $key => $layer) {
// get type == Vector for backwards-compatibility.
// TODO: After OpenLayers alpha8 it should be removed
if (((isset($layer['vector']) && $layer['vector'] == 1)) && !empty($layer['features'])) {
$vector_layers[$key] = $layer;
}
}
return $vector_layers;
}
protected function process_weight($ratio, $method) {
switch ($method) {
case 'radius':
return $ratio;
case 'area':
default:
return sqrt($ratio);
}
}
/**
* Render.
*/
function render(&$map) {
// Get the layers we are going to use.
$layers = $this->get_layers($map['layers']);
$get_min = $this->options['min']['value'] === '' || !isset($this->options['min']['value']);
$get_max = $this->options['max']['value'] === '' || !isset($this->options['max']['value']);
$weights = $this->get_weights();
foreach ($layers as $k => $layer) {
// Get the field we are going to use.
if ($field = $this->get_field($layer['features'])) {
// Get min/max per layer.
$min = isset($this->options['min']['value']) && is_numeric($this->options['min']['value']) ? $this->options['min']['value'] : 1000000;
$max = isset($this->options['max']['value']) && is_numeric($this->options['max']['value']) ? $this->options['max']['value'] : 0;
$count_min = 1000000;
$count_max = 0;
if ($get_min || $get_max) {
foreach ($layer['features'] as $j => $feature) {
if ($field && isset($feature['attributes'][$field]) && $count = $feature['attributes'][$field]) {
// Replace the count attribute with the selected one.
if ($field !== 'count') {
$map['layers'][$k]['features'][$j]['attributes']['count'] = $count;
}
$max = ($count > $max) && $get_max ? $count : $max;
$min = ($count < $min) && $get_min ? $count : $min;
$count_max = ($count > $count_max) ? $count : $count_max;
$count_min = ($count < $count_min) ? $count : $count_min;
}
}
}
// Sensible defaults code right here: If count_max & count_min are both under 1,
// assume data source is doing a ratio calc for us. Set max to 1.
if ($count_max < 1 && $count_min < 1) {
$max = 1;
}
foreach ($layer['features'] as $j => $feature) {
if ($field && isset($feature['attributes'][$field]) && $count = $feature['attributes'][$field]) {
// For layers with only a single value always use the smallest weight.
if ($count_max === $count_min) {
$map['layers'][$k]['features'][$j]['attributes']['weight'] = 1;
}
// Otherwise iterate through to find the right weight.
else {
$calculated = $this->process_weight(($count - $min) / ($max - $min), $this->options['method']);
foreach ($weights as $percentile => $weight) {
if ($calculated <= $percentile) {
$map['layers'][$k]['features'][$j]['attributes']['weight'] = $weight;
break;
}
}
}
}
}
}
}
drupal_add_js(drupal_get_path('module', 'openlayers_plus') . '/behaviors/openlayers_plus_behavior_scalepoints.js');
$options = array();
$options['styles'] = $this->get_styles();
return $options;
}
}

View File

@@ -0,0 +1,36 @@
/**
* Implementation of Drupal behavior.
*/
Drupal.behaviors.openlayers_plus_behavior_scalepoints = function(context) {
var data = $(context).data('openlayers');
if (data && data.map.behaviors.openlayers_plus_behavior_scalepoints) {
var styles = data.map.behaviors.openlayers_plus_behavior_scalepoints.styles;
// Collect vector layers
var vector_layers = [];
for (var key in data.openlayers.layers) {
var layer = data.openlayers.layers[key];
if (layer.isVector === true) {
var styleMap = layer.styleMap;
styleMap.addUniqueValueRules("default", "weight", styles);
layer.redraw();
vector_layers.push(layer);
}
}
/**
* This attempts to fix a problem in IE7 in which points
* are not displayed until the map is moved.
*
* Since namespaces is filled neither on window.load nor
* document.ready, and testing it is unsafe, this renders
* map layers after 500 milliseconds.
*/
if($.browser.msie) {
setTimeout(function() {
$.each(data.openlayers.getLayersByClass('OpenLayers.Layer.Vector'),
function() {
this.redraw();
});
}, 500);
}
}
};

View File

@@ -0,0 +1,48 @@
<?php
class openlayers_plus_behavior_themeregion extends openlayers_behavior {
/**
* Override of options_init().
*/
function options_init() {
$options = array(
);
return $options;
}
/**
* Override of options_form().
*/
function options_form($defaults) {
return array(
'regions' => array(
'#type' => 'checkboxes',
'#title' => t('Select Regions'),
'#options' => system_region_list(variable_get('theme_default'), REGIONS_ALL),
'#default_value' => isset($defaults['regions']) ? $defaults['regions'] : array(),
'#description' => t('Select the region(s) you want to move in the map. You will have to edit the CSS to make this work nicely with more than 1 region.')
),
'prefix' => array(
'#type' => 'textfield',
'#title' => t('CSS Prefix'),
'#default_value' => isset($defaults['prefix']) ? $defaults['prefix'] : '#',
'#description' => t('Prefix for the CSS identifier of the Regions div in your theme.')
),
'suffix' => array(
'#type' => 'textfield',
'#title' => t('CSS Suffix'),
'#default_value' => isset($defaults['suffix']) ? $defaults['suffix'] : '',
'#description' => t('Suffix for the CSS identifier of the Regions div in your theme.')
),
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers_plus')
. '/behaviors/openlayers_plus_behavior_themeregion.js');
return $this->options;
}
}

View File

@@ -0,0 +1,58 @@
/**
* Implementation of Drupal behavior.
*/
//Drupal.behaviors.openlayers_plus_behavior_themeregion = function(context) {
// Drupal.OpenLayersPlusthemeregion.attach(context);
//};
(function($) {
/**
* Implementation of Drupal behavior.
*/
//Drupal.behaviors.openlayers_plus_behavior_themeregion = function(context) {
Drupal.openlayers.addBehavior('openlayers_plus_behavior_themeregion', function (data, options) {
Drupal.OpenLayersPlusthemeregion.attach(data, options);
});
/**
* themeregion is **NOT** an OpenLayers control.
*/
Drupal.OpenLayersPlusthemeregion = {};
Drupal.OpenLayersPlusthemeregion.layerStates = [];
/**
* Initializes the themeregion and attaches to DOM elements.
*/
Drupal.OpenLayersPlusthemeregion.attach = function(data, options) {
/**
* Initializes the themeregion and attaches to DOM elements.
*/
if (data && data.map.behaviors.openlayers_plus_behavior_themeregion) {
for (regionkey in options.regions) {
if (regionkey != 0) {
if (options.regions[regionkey]) {
region = options.regions[regionkey].replace('_', '-').toLowerCase();
var cssid = options.prefix + region + options.suffix;
if ($(cssid).length > 0) {
$(data.openlayers.viewPortDiv).append($(cssid));
$(cssid).addClass('olControlNoSelect');
$(cssid).addClass('openlayers_plus-themeregion');
$(cssid).css('position', 'absolute'); // we need to do this because some themes override this with the id of the region
}
}
}
}
// Don't propagate click events to the map
// this doesn't catch events that are below the layer list
$('div.block-openlayers_plus-themeregion *').mousedown(function(evt) {
OpenLayers.Event.stop(evt);
});
}
};
})(jQuery);

View File

@@ -0,0 +1,31 @@
<?php
class openlayers_plus_behavior_tooltips extends openlayers_behavior {
/**
* Override of options_init().
*/
function options_init() {
return array('positioned' => FALSE);
}
/**
* Override of options_form().
*/
function options_form($defaults) {
return array(
'positioned' => array(
'#type' => 'checkbox',
'#title' => t('Position tooltip over feature'),
'#default_value' => isset($defaults['positioned']) ? $defaults['positioned'] : array(),
),
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers_plus') . '/behaviors/openlayers_plus_behavior_tooltips.js');
return $this->options;
}
}

View File

@@ -0,0 +1,104 @@
(function ($) {
/**
* Implementation of Drupal behavior.
*/
Drupal.behaviors.openlayers_plus_behavior_tooltips = function(context) {
Drupal.OpenLayersTooltips.attach(context);
};
Drupal.OpenLayersTooltips = {};
Drupal.OpenLayersTooltips.attach = function(context) {
var data = $(context).data('openlayers');
if (data && data.map.behaviors.openlayers_plus_behavior_tooltips) {
// Options
var select_method = 'select';
if (data.map.behaviors.openlayers_plus_behavior_tooltips.positioned) {
select_method = 'positionedSelect';
}
// Collect vector layers
var vector_layers = [];
for (var key in data.openlayers.layers) {
var layer = data.openlayers.layers[key];
if (layer.isVector === true) {
vector_layers.push(layer);
}
}
// Add control
var control = new OpenLayers.Control.SelectFeature(vector_layers, {
activeByDefault: true,
highlightOnly: false,
onSelect: Drupal.OpenLayersTooltips.select,
onUnselect: Drupal.OpenLayersTooltips.unselect,
multiple: false,
hover: true,
callbacks: {
'click': Drupal.OpenLayersTooltips.click,
'over': Drupal.OpenLayersTooltips[select_method],
'out': Drupal.OpenLayersTooltips.unselect
}
});
data.openlayers.addControl(control);
control.activate();
}
};
Drupal.OpenLayersTooltips.click = function(feature) {
var html = '';
if (feature.attributes.name) {
html += feature.attributes.name;
}
if (feature.attributes.description) {
html += feature.attributes.description;
}
// @TODO: Make this a behavior option and allow interaction with other
// behaviors like the MN story popup.
var link;
if ($(html).is('a')) {
link = $(html);
}
else if ($(html).children('a').size() > 0) {
link = $(html).children('a')[0];
}
if (link) {
var href = $(link).attr('href');
if (Drupal.OpenLayersPermalink && Drupal.OpenLayersPermalink.addQuery) {
href = Drupal.OpenLayersPermalink.addQuery(href);
}
window.location = href;
return false;
}
return;
};
Drupal.OpenLayersTooltips.getToolTip = function(feature) {
var text = "<div class='openlayers-tooltip'>";
if (feature.attributes.name) {
text += "<div class='openlayers-tooltip-name'>" + feature.attributes.name + "</div>";
}
if (feature.attributes.description) {
text += "<div class='openlayers-tooltip-description'>" + feature.attributes.description + "</div>";
}
text += "</div>";
return $(text);
}
Drupal.OpenLayersTooltips.select = function(feature) {
var tooltip = Drupal.OpenLayersTooltips.getToolTip(feature);
$(feature.layer.map.div).append(tooltip);
};
Drupal.OpenLayersTooltips.positionedSelect = function(feature) {
var tooltip = Drupal.OpenLayersTooltips.getToolTip(feature);
var point = new OpenLayers.LonLat(feature.geometry.x, feature.geometry.y);
var offset = feature.layer.getViewPortPxFromLonLat(point);
$(tooltip).css({zIndex: '1000', position: 'absolute', left: offset.x, top: offset.y});
$(feature.layer.map.div).css({position:'relative'}).append(tooltip);
};
Drupal.OpenLayersTooltips.unselect = function(feature) {
$(feature.layer.map.div).children('div.openlayers-tooltip').fadeOut('fast', function() { $(this).remove(); });
};
})(jQuery);

View File

@@ -0,0 +1,45 @@
<?php
class openlayers_plus_behavior_tooltips_field extends openlayers_behavior {
/**
* Override of options_init().
*/
function options_init() {
return array('positioned' => FALSE);
}
/**
* Override of options_form().
*/
function options_form() {
$form = parent::options_form();
$form['positioned'] = array(
'#type' => 'checkbox',
'#title' => t('Position tooltip over feature displaying specific field'),
'#default_value' => $this->options['positioned'],
);
$form['field_displayed'] = array(
'#type' => 'textfield',
'#title' => t('Field to Display'),
'#description' => t('Field from openlayers view to be displayed. (usually field_your_special_field)'),
'#default_value' => isset($this->options['field_displayed'])
? $this->options['field_displayed'] : NULL
);
return $form;
}
/**
* Render.
*/
function render(&$map) {
$settings = array(
'openlayers_plus_behavior_tooltips_field' => array(
'field' => "field_category",
),
);
drupal_add_js($settings, array('type' => 'setting'));
drupal_add_js(drupal_get_path('module', 'openlayers_plus')
. '/behaviors/openlayers_plus_behavior_tooltips_field.js');
return $this->options;
}
}

View File

@@ -0,0 +1,129 @@
(function($) {
/**
* Implementation of Drupal behavior.
*/
Drupal.behaviors.openlayers_plus_behavior_tooltips_field = {
'attach': function(context, settings) {
Drupal.OpenLayersTooltips.attach(context);
}
};
Drupal.OpenLayersTooltips = {};
Drupal.OpenLayersTooltips.attach = function(context) {
var data = $(context).data('openlayers');
var isVector = function(layer) {
if (layer.__proto__) {
return layer.__proto__.CLASS_NAME === 'OpenLayers.Layer.Vector';
}
else if (layer.CLASS_NAME) {
return layer.CLASS_NAME === 'OpenLayers.Layer.Vector';
}
};
if (data && data.map.behaviors.openlayers_plus_behavior_tooltips_field) {
// Options
var select_method = (data.map.behaviors
.openlayers_plus_behavior_tooltips_field.positioned) ?
'positionedSelect' : 'select';
// Collect vector layers
var vector_layers = [];
for (var key in data.openlayers.layers) {
var layer = data.openlayers.layers[key];
if (isVector(layer)) {
vector_layers.push(layer);
}
}
Drupal.settings.openlayers_plus_behavior_tooltips_field.field = data.map.behaviors.openlayers_plus_behavior_tooltips_field.field_displayed;
// Add control
var control = new OpenLayers.Control.SelectFeature(vector_layers, {
activeByDefault: true,
highlightOnly: false,
onSelect: Drupal.OpenLayersTooltips.select,
onUnselect: Drupal.OpenLayersTooltips.unselect,
multiple: false,
hover: true,
callbacks: {
'click': Drupal.OpenLayersTooltips.click,
'over': Drupal.OpenLayersTooltips[select_method],
'out': Drupal.OpenLayersTooltips.unselect
}
});
data.openlayers.addControl(control);
control.activate();
}
};
Drupal.OpenLayersTooltips.click = function(feature) {
var html = '';
if (feature.attributes.name) {
html += feature.attributes.name;
}
if (feature.attributes.description) {
html += feature.attributes.description;
}
// @TODO: Make this a behavior option and allow interaction with other
// behaviors like the MN story popup.
var link;
if ($(html).is('a')) {
link = $(html);
}
else if ($('a', html).size() > 0) {
link = $('a', html);
}
if (link) {
var href = $(link).attr('href');
if (Drupal.OpenLayersPermalink &&
Drupal.OpenLayersPermalink.addQuery) {
href = Drupal.OpenLayersPermalink.addQuery(href);
}
window.location = href;
return false;
}
return;
};
Drupal.OpenLayersTooltips.getToolTip = function(feature) {
var field = Drupal.settings.openlayers_plus_behavior_tooltips_field.field
var text = "<div class='openlayers-tooltip'>";
if (typeof feature.cluster != 'undefined') {
text += "<div class='openlayers-tooltip-name'>" +
feature.cluster[0].attributes[field] + " (" + feature.attributes.count + ")</div>";
}
else if (typeof feature.attributes[field] != 'undefined') {
text += "<div class='openlayers-tooltip-name'>" +
feature.attributes[field] + "</div>";
}
text += "</div>";
return $(text);
}
Drupal.OpenLayersTooltips.select = function(feature) {
var tooltip = Drupal.OpenLayersTooltips.getToolTip(feature);
$(feature.layer.map.div).append(tooltip);
};
Drupal.OpenLayersTooltips.positionedSelect = function(feature) {
var tooltip = Drupal.OpenLayersTooltips.getToolTip(feature);
var point = new OpenLayers.LonLat(
feature.geometry.x,
feature.geometry.y);
var offset = feature.layer.getViewPortPxFromLonLat(point);
$(tooltip).css({
zIndex: '1000',
position: 'absolute',
left: (offset.x - 60),
top: (offset.y - 50)});
$(feature.layer.map.div).css({position:'relative'})
.append(tooltip);
};
Drupal.OpenLayersTooltips.unselect = function(feature) {
$(feature.layer.map.div).children('div.openlayers-tooltip')
.fadeOut('fast', function() {
$(this).remove();
});
};
})(jQuery);