├── README.md ├── behaviors ├── openlayers_plus_behavior_blockswitcher.inc ├── openlayers_plus_behavior_blockswitcher.js ├── openlayers_plus_behavior_blocktoggle.inc ├── openlayers_plus_behavior_blocktoggle.js ├── openlayers_plus_behavior_legend.inc ├── openlayers_plus_behavior_legend.js ├── openlayers_plus_behavior_permalink.inc ├── openlayers_plus_behavior_permalink.js ├── openlayers_plus_behavior_popup.inc ├── openlayers_plus_behavior_popup.js ├── openlayers_plus_behavior_scalepoints.inc ├── openlayers_plus_behavior_scalepoints.js ├── openlayers_plus_behavior_tooltips.inc └── openlayers_plus_behavior_tooltips.js ├── openlayers_plus.info ├── openlayers_plus.module └── theme ├── active.png ├── inactive.png ├── openlayers-plus-blockswitcher.tpl.php ├── openlayers-plus-blocktoggle.tpl.php ├── openlayers-plus-legend-raw.tpl.php ├── openlayers-plus-legend.tpl.php ├── openlayers_plus-rtl.css ├── openlayers_plus.css ├── point-button.png ├── point-choro.png └── theme.inc /README.md: -------------------------------------------------------------------------------- 1 | `openlayers_plus` is a collection of behaviors that work with 2 | [the Drupal OpenLayers module](http://drupal.org/project/openlayers), 3 | version 2 and up. This module requires the OpenLayers module, but not 4 | vice versa. 5 | 6 | This provides the following functionality: 7 | 8 | * BlockSwitcher: a clone of [LayerSwitcher](http://dev.openlayers.org/docs/files/OpenLayers/Control/LayerSwitcher-js.html), with better themability and positioning via the Drupal block system. 9 | * BlockToggle: a version of BlockSwitcher that toggles between two different layers only. Useful for situations in which layers represent the same data in slightly different ways. 10 | * Legend: a block in a corner of a map that provides information on layers. 11 | * Permalink: a version of [Permalink](http://dev.openlayers.org/docs/files/OpenLayers/Control/Permalink-js.html) optimized to persist layers between pages with different layer setups and without explicitly using the control. 12 | * Popup: an interaction with point-based, clustered maps that allows clicking on points that results in scanning between items. 13 | * Tooltip: an interaction with point-based maps that results in following links on hover. 14 | * Scale Points: dynamic styling, changing point radii based on a certain value 15 | 16 | This module does not provide thorough theming or accessory images: it's the 17 | responsibility of the site builder to tune styling. 18 | -------------------------------------------------------------------------------- /behaviors/openlayers_plus_behavior_blockswitcher.inc: -------------------------------------------------------------------------------- 1 | FALSE, 'position' => 'se'); 10 | return $options; 11 | } 12 | 13 | /** 14 | * Override of options_form(). 15 | */ 16 | function options_form() { 17 | $form = parent::options_form(); 18 | $form['map'] = array('#tree' => TRUE); 19 | $form['map']['enabled'] = array( 20 | '#type' => 'checkbox', 21 | '#title' => t('Show blockswitcher in map'), 22 | '#default_value' => $this->options['map']['enabled'], 23 | ); 24 | $form['map']['open'] = array( 25 | '#type' => 'checkbox', 26 | '#title' => t('Show blockswitcher open when the map loads'), 27 | '#default_value' => $this->options['map']['open'], 28 | ); 29 | $form['map']['overlay_style'] = array( 30 | '#type' => 'select', 31 | '#title' => t('Show overlay layers as checkboxes or radio buttons'), 32 | '#options' => array( 33 | 'checkbox' => t('Checkboxes'), 34 | 'radio' => t('Radio Buttons')), 35 | '#default_value' => $this->options['map']['overlay_style'], 36 | ); 37 | $form['map']['position'] = array( 38 | '#type' => 'select', 39 | '#title' => t('Position'), 40 | '#options' => array( 41 | 'ne' => t('Top right'), 42 | 'se' => t('Bottom right'), 43 | 'sw' => t('Bottom left'), 44 | 'nw' => t('Top left')), 45 | '#default_value' => $this->options['map']['position'], 46 | ); 47 | return $form; 48 | } 49 | 50 | /** 51 | * Render. 52 | */ 53 | function render(&$map) { 54 | drupal_add_js(drupal_get_path('module', 'openlayers_plus') 55 | .'/behaviors/openlayers_plus_behavior_blockswitcher.js'); 56 | if ($this->options['map']['enabled']) { 57 | $block = (object) module_invoke('openlayers_plus', 'block', 'view', 'blockswitcher'); 58 | $block->module = 'openlayers_plus'; 59 | $block->delta = 'blockswitcher'; 60 | $this->options['block'] = theme('block', $block); 61 | } 62 | return $this->options; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /behaviors/openlayers_plus_behavior_blockswitcher.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementation of Drupal behavior. 3 | */ 4 | Drupal.behaviors.openlayers_plus_behavior_blockswitcher = function(context) { 5 | Drupal.OpenLayersPlusBlockswitcher.attach(context); 6 | }; 7 | 8 | /** 9 | * Blockswitcher is **NOT** an OpenLayers control. 10 | */ 11 | Drupal.OpenLayersPlusBlockswitcher = {}; 12 | Drupal.OpenLayersPlusBlockswitcher.layerStates = []; 13 | 14 | /** 15 | * Initializes the blockswitcher and attaches to DOM elements. 16 | */ 17 | Drupal.OpenLayersPlusBlockswitcher.attach = function(context) { 18 | var data = $(context).data('openlayers'); 19 | if (data && data.map.behaviors.openlayers_plus_behavior_blockswitcher) { 20 | this.map = data.openlayers; 21 | this.overlay_style = (data.map.behaviors.openlayers_plus_behavior_blockswitcher.map.overlay_style) ? 22 | data.map.behaviors.openlayers_plus_behavior_blockswitcher.map.overlay_style : 'checkbox'; 23 | 24 | 25 | // If behavior has requested display inside of map, respect it. 26 | if (data.map.behaviors.openlayers_plus_behavior_blockswitcher.map.enabled == true) { 27 | var block = $(data.map.behaviors.openlayers_plus_behavior_blockswitcher.block); 28 | block.addClass(data.map.behaviors.openlayers_plus_behavior_blockswitcher.map.position); 29 | $('.block-title', block).click(function() { 30 | $(this).parents('div.block').toggleClass('expanded'); 31 | $(this).siblings('div.block-content').toggle(); 32 | }); 33 | 34 | $(context).append(block); 35 | 36 | if (data.map.behaviors.openlayers_plus_behavior_blockswitcher.map.open == true) { 37 | $('.block-title', block).click(); 38 | } 39 | } 40 | 41 | this.blockswitcher = $('div.openlayers-blockswitcher'); 42 | 43 | // Don't propagate click events to the map 44 | // this doesn't catch events that are below the layer list 45 | $('div.openlayers-blockswitcher').mousedown(function(evt) { 46 | OpenLayers.Event.stop(evt); 47 | }); 48 | 49 | data.openlayers.events.on({ 50 | "addlayer": this.redraw, 51 | "changelayer": this.redraw, 52 | "removelayer": this.redraw, 53 | "changebaselayer": this.redraw, 54 | scope: this 55 | }); 56 | 57 | this.redraw(); 58 | } 59 | }; 60 | 61 | /** 62 | * Checks if the layer state has changed since the last redraw() call. 63 | * 64 | * Returns: 65 | * {Boolean} The layer state changed since the last redraw() call. 66 | */ 67 | Drupal.OpenLayersPlusBlockswitcher.needsRedraw = function() { 68 | if ( !this.layerStates.length || (this.map.layers.length != this.layerStates.length) ) { 69 | return true; 70 | } 71 | for (var i=0, len=this.layerStates.length; i 0) { 211 | css['border-color'] = default_style.strokeColor; 212 | } 213 | return css; 214 | }; 215 | -------------------------------------------------------------------------------- /behaviors/openlayers_plus_behavior_blocktoggle.inc: -------------------------------------------------------------------------------- 1 | FALSE, 'position' => 'se'); 10 | return $options; 11 | } 12 | 13 | /** 14 | * Override of options_form(). 15 | */ 16 | function options_form() { 17 | $form = parent::options_form(); 18 | $form['map'] = array('#tree' => TRUE); 19 | $form['map']['enabled'] = array( 20 | '#type' => 'checkbox', 21 | '#title' => t('Show blocktoggle in map'), 22 | '#default_value' => $this->options['map']['enabled'], 23 | ); 24 | 25 | $form['layer']['a_label'] = array( 26 | '#type' => 'textfield', 27 | '#title' => t('Layer A Label'), 28 | '#description' => t('This can either be the name of the layer, or a shorter name you choose.'), 29 | '#default_value' => isset($this->options['layer']['a_label']) ? $this->options['layer']['a_label'] : NULL 30 | ); 31 | 32 | $form['layer']['a'] = array( 33 | '#type' => 'select', 34 | '#options' => $this->map['layers'], 35 | '#title' => t('Layer A'), 36 | '#default_value' => isset($this->options['layer']['a']) ? $this->options['layer']['a'] : NULL 37 | ); 38 | 39 | $form['layer']['b_label'] = array( 40 | '#type' => 'textfield', 41 | '#title' => t('Layer B Label'), 42 | '#description' => t('This can either be the name of the layer, or a shorter name you choose.'), 43 | '#default_value' => isset($this->options['layer']['b_label']) ? $this->options['layer']['b_label'] : NULL 44 | ); 45 | 46 | $form['layer']['b'] = array( 47 | '#type' => 'select', 48 | '#options' => $this->map['layers'], 49 | '#title' => t('Layer B'), 50 | '#default_value' => isset($this->options['layer']['b']) ? $this->options['layer']['b'] : NULL 51 | ); 52 | 53 | $form['map']['position'] = array( 54 | '#type' => 'select', 55 | '#title' => t('Position'), 56 | '#options' => array( 57 | 'ne' => t('Top right'), 58 | 'se' => t('Bottom right'), 59 | 'sw' => t('Bottom left'), 60 | 'nw' => t('Top left')), 61 | '#default_value' => $this->options['map']['position'], 62 | ); 63 | return $form; 64 | } 65 | 66 | /** 67 | * Render. 68 | */ 69 | function render(&$map) { 70 | drupal_add_js(drupal_get_path('module', 'openlayers_plus') 71 | .'/behaviors/openlayers_plus_behavior_blocktoggle.js'); 72 | if ($this->options['map']['enabled']) { 73 | $block = (object) module_invoke('openlayers_plus', 'block', 'view', 'blocktoggle'); 74 | $block->module = 'openlayers_plus'; 75 | $block->delta = 'blocktoggle'; 76 | $this->options['block'] = theme('block', $block); 77 | } 78 | return $this->options; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /behaviors/openlayers_plus_behavior_blocktoggle.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementation of Drupal behavior. 3 | */ 4 | Drupal.behaviors.openlayers_plus_behavior_blocktoggle = function(context) { 5 | Drupal.OpenLayersPlusBlocktoggle.attach(context); 6 | }; 7 | 8 | /** 9 | * Blocktoggle is **NOT** an OpenLayers control. 10 | */ 11 | Drupal.OpenLayersPlusBlocktoggle = {}; 12 | Drupal.OpenLayersPlusBlocktoggle.layerStates = []; 13 | 14 | /** 15 | * Initializes the blocktoggle and attaches to DOM elements. 16 | */ 17 | Drupal.OpenLayersPlusBlocktoggle.attach = function(context) { 18 | var data = $(context).data('openlayers'); 19 | 20 | if (data && data.map.behaviors.openlayers_plus_behavior_blocktoggle) { 21 | 22 | this.map = data.openlayers; 23 | this.layer_a = this.map.getLayersBy('drupalID', 24 | data.map.behaviors.openlayers_plus_behavior_blocktoggle.layer.a)[0]; 25 | this.layer_b = this.map.getLayersBy('drupalID', 26 | data.map.behaviors.openlayers_plus_behavior_blocktoggle.layer.b)[0]; 27 | 28 | // If behavior has requested display inside of map, respect it. 29 | if (data.map.behaviors.openlayers_plus_behavior_blocktoggle.map.enabled == true) { 30 | var block = $(data.map.behaviors.openlayers_plus_behavior_blocktoggle.block); 31 | 32 | block.addClass(data.map.behaviors.openlayers_plus_behavior_blocktoggle.map.position); 33 | $(context).append(block); 34 | } 35 | 36 | this.blocktoggle = $('div.openlayers-blocktoggle'); 37 | this.blocktoggle.data('layer_a', this.layer_a); 38 | this.blocktoggle.data('layer_b', this.layer_b); 39 | 40 | // Don't propagate click events to the map 41 | // this doesn't catch events that are below the layer list 42 | $('div.openlayers-blocktoggle *').mousedown(function(evt) { 43 | OpenLayers.Event.stop(evt); 44 | }); 45 | 46 | $('.openlayers-blocktoggle-a').text( 47 | data.map.behaviors.openlayers_plus_behavior_blocktoggle.layer.a_label 48 | ); 49 | 50 | $('.openlayers-blocktoggle-b').text( 51 | data.map.behaviors.openlayers_plus_behavior_blocktoggle.layer.b_label 52 | ); 53 | 54 | $('div.openlayers-blocktoggle').toggle( 55 | function() { 56 | $(this).data('layer_a').setVisibility(false); 57 | $(this).data('layer_b').setVisibility(true); 58 | $(this).find('.openlayers-blocktoggle-a').removeClass('activated'); 59 | $(this).find('.openlayers-blocktoggle-b').addClass('activated'); 60 | }, 61 | function() { 62 | $(this).data('layer_b').setVisibility(false); 63 | $(this).data('layer_a').setVisibility(true); 64 | $(this).find('.openlayers-blocktoggle-b').removeClass('activated'); 65 | $(this).find('.openlayers-blocktoggle-a').addClass('activated'); 66 | } 67 | ); 68 | 69 | data.openlayers.events.on({ 70 | "addlayer": this.redraw, 71 | "changelayer": this.redraw, 72 | "removelayer": this.redraw, 73 | scope: this 74 | }); 75 | } 76 | }; 77 | 78 | /** 79 | * Checks if the layer state has changed since the last redraw() call. 80 | * 81 | * Returns: 82 | * {Boolean} The layer state changed since the last redraw() call. 83 | */ 84 | Drupal.OpenLayersPlusBlocktoggle.needsRedraw = function() { 85 | return ( 86 | (this.a_vis == 87 | $(this).find('.openlayers-blocktoggle-a').hasClass('activated')) ? 1 : 0 88 | ^ 89 | (this.b_vis == 90 | $(this).find('.openlayers-blocktoggle-b').hasClass('activated')) ? 1 : 0); 91 | }; 92 | 93 | /** 94 | * Redraws the blocktoggle to reflect the current state of layers. 95 | */ 96 | Drupal.OpenLayersPlusBlocktoggle.redraw = function() { 97 | if (this.needsRedraw()) { 98 | this.a_vis = this.layer_a.visibility; 99 | this.b_vis = this.layer_b.visibility; 100 | // Clear out previous layers 101 | // Save state -- for checking layer if the map state changed. 102 | // We save this before redrawing, because in the process of redrawing 103 | // we will trigger more visibility changes, and we want to not redraw 104 | // and enter an infinite loop. 105 | $('div.openlayers-blocktoggle').click(); 106 | } 107 | }; 108 | -------------------------------------------------------------------------------- /behaviors/openlayers_plus_behavior_legend.inc: -------------------------------------------------------------------------------- 1 | $layer_data) { 13 | if (isset($layer_data['options']['legend']) && is_array($layer_data['options']['legend'])) { 14 | $options[$layer] = theme('openlayers_plus_legend', $layer_data['options']['legend'], $layer_data, $layer); 15 | } 16 | elseif (isset($layer_data['options']['legend'])) { 17 | $options[$layer] = theme('openlayers_plus_legend_raw', $layer_data['options']['legend'], $layer_data, $layer); 18 | } 19 | } 20 | return $options; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /behaviors/openlayers_plus_behavior_legend.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementation of Drupal behavior. 3 | */ 4 | Drupal.behaviors.openlayers_plus_behavior_legend = function(context) { 5 | Drupal.OpenLayersPlusLegend.attach(context); 6 | }; 7 | 8 | Drupal.OpenLayersPlusLegend = {}; 9 | 10 | Drupal.OpenLayersPlusLegend.attach = function(context) { 11 | var data = $(context).data('openlayers'); 12 | if (data && data.map.behaviors.openlayers_plus_behavior_legend) { 13 | var layer, i; 14 | for (i in data.openlayers.layers) { 15 | layer = data.openlayers.layers[i]; 16 | if (data.map.behaviors.openlayers_plus_behavior_legend[layer.drupalID]) { 17 | if (!$('div.openlayers-legends', context).size()) { 18 | $(context).append("
"); 19 | } 20 | layer.events.register('visibilitychanged', layer, Drupal.OpenLayersPlusLegend.setLegend); 21 | 22 | // Trigger the setLegend() method at attach time. We don't know whether 23 | // our behavior is being called after the map has already been drawn. 24 | Drupal.OpenLayersPlusLegend.setLegend(layer); 25 | } 26 | } 27 | } 28 | }; 29 | 30 | Drupal.OpenLayersPlusLegend.setLegend = function(layer) { 31 | // The layer param may vary based on the context from which we are called. 32 | layer = layer.object ? layer.object : layer; 33 | 34 | var name = layer.drupalID; 35 | var map = $(layer.map.div); 36 | var data = map.data('openlayers'); 37 | var legend = data.map.behaviors.openlayers_plus_behavior_legend[name]; 38 | var legends = $('div.openlayers-legends', map); 39 | if (layer.visibility && $('#openlayers-legend-'+ name, legends).size() === 0) { 40 | legends.append(legend); 41 | } 42 | else if (!layer.visibility) { 43 | $('#openlayers-legend-'+name, legends).remove(); 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /behaviors/openlayers_plus_behavior_permalink.inc: -------------------------------------------------------------------------------- 1 | options; 9 | } 10 | } -------------------------------------------------------------------------------- /behaviors/openlayers_plus_behavior_permalink.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementation of Drupal behavior. 3 | */ 4 | Drupal.behaviors.openlayers_plus_behavior_permalink = function(context) { 5 | Drupal.OpenLayersPermalink.attach(context); 6 | }; 7 | 8 | Drupal.OpenLayersPermalink = {}; 9 | 10 | Drupal.OpenLayersPermalink.attach = function(context) { 11 | var data = $(context).data('openlayers'); 12 | if (data && data.map.behaviors.openlayers_plus_behavior_permalink) { 13 | // Doctor link hrefs. 14 | $('#canvas a:not(.processed-permalink)').each(function() { 15 | $(this).addClass('processed-permalink'); 16 | $(this).click(function() { 17 | var href = $(this).attr('href'); 18 | if (href.indexOf('#') === -1) { 19 | href = Drupal.OpenLayersPermalink.addQuery(href); 20 | $(this).attr('href', href); 21 | } 22 | }); 23 | }); 24 | // Doctor form submission. 25 | $('form:not(.processed-permalink)').each(function() { 26 | $(this).addClass('processed-permalink'); 27 | $(this).submit(function() { 28 | var action = $(this).attr('action'); 29 | action = Drupal.OpenLayersPermalink.addQuery(action, '?'); 30 | $(this).attr('action', action); 31 | }); 32 | }); 33 | // Add control 34 | var control = new OpenLayers.Control.PermalinkPlus(); 35 | data.openlayers.addControl(control); 36 | control.activate(); 37 | } 38 | }; 39 | 40 | Drupal.OpenLayersPermalink.addQuery = function(href, delimiter) { 41 | delimiter = delimiter ? delimiter : '#'; 42 | var processed = false; 43 | $('div.openlayers-map').each(function() { 44 | if (!processed) { 45 | var data = $(this).data('openlayers'); 46 | if (data.openlayers) { 47 | // If there is a permalink control present, attempt to persist layer settings when clicking through. 48 | for (var i in data.openlayers.controls) { 49 | if (data.openlayers.controls[i].CLASS_NAME == 'OpenLayers.Control.PermalinkPlus') { 50 | var params = OpenLayers.Util.getParameterString(data.openlayers.controls[i].createParams()); 51 | params = params.split('&'); 52 | var url = href.split(delimiter); 53 | for (var key in params) { 54 | if (params[key].split('=')[0] == 'layers' || params[key].split('=')[0] == 'baseLayers' ) { 55 | if (url[1]) { 56 | url[1] += '&' + params[key]; 57 | } 58 | else { 59 | url[1] = params[key]; 60 | } 61 | } 62 | } 63 | href = url.join(delimiter); 64 | } 65 | } 66 | } 67 | } 68 | }); 69 | return href; 70 | }; 71 | 72 | OpenLayers.Control.ArgParserPlus = OpenLayers.Class(OpenLayers.Control.ArgParser, { 73 | /** 74 | * Alternative to OpenLayers.Utils.getParameters() that uses the URL hash. 75 | */ 76 | getParameters: function() { 77 | // Parse out parameters portion of url string 78 | var paramsString = window.location.hash.substring(1); 79 | 80 | var parameters = {}; 81 | var pairs = paramsString.split(/[&;]/); 82 | for(var i=0, len=pairs.length; ioptions; 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /behaviors/openlayers_plus_behavior_popup.js: -------------------------------------------------------------------------------- 1 | Drupal.behaviors.openlayers_plus_behavior_popup = function(context) { 2 | var data = $(context).data('openlayers'); 3 | if (data && data.map.behaviors.openlayers_plus_behavior_popup) { 4 | // Collect vector layers 5 | var vector_layers = []; 6 | for (var key in data.openlayers.layers) { 7 | var layer = data.openlayers.layers[key]; 8 | if (layer.isVector === true) { 9 | vector_layers.push(layer); 10 | } 11 | } 12 | 13 | // Add control 14 | var control = new OpenLayers.Control.SelectFeature( 15 | vector_layers, 16 | { 17 | activeByDefault: true, 18 | highlightOnly: false, 19 | multiple: false, 20 | hover: false, 21 | callbacks: { 22 | 'over': Drupal.openlayers_plus_behavior_popup.over, 23 | 'out': Drupal.openlayers_plus_behavior_popup.out, 24 | 'click': Drupal.openlayers_plus_behavior_popup.openPopup 25 | } 26 | } 27 | ); 28 | data.openlayers.addControl(control); 29 | control.activate(); 30 | } 31 | else if ($(context).is('.openlayers-popupbox')) { 32 | // Popup close 33 | $('a.popup-close', context).click(function() { 34 | $(this).parents('.openlayers-popupbox').fadeOut('fast', function() { $(this).remove(); }); 35 | return false; 36 | }); 37 | 38 | // Set initial pager state 39 | Drupal.openlayers_plus_behavior_popup.pager(context, 'set'); 40 | 41 | // Next link 42 | $('ul.popup-links a.next', context).click(function() { 43 | var context = $(this).parents('.openlayers-popupbox'); 44 | Drupal.openlayers_plus_behavior_popup.pager(context, 'next'); 45 | }); 46 | 47 | // Prev link 48 | $('ul.popup-links a.prev', context).click(function() { 49 | var context = $(this).parents('.openlayers-popupbox'); 50 | Drupal.openlayers_plus_behavior_popup.pager(context, 'prev'); 51 | }); 52 | } 53 | }; 54 | 55 | Drupal.openlayers_plus_behavior_popup = { 56 | 57 | // Pager actions 58 | 'pager': function(context, op) { 59 | var active = $('li.openlayers-popupbox-active', context); 60 | var index = $('div.item-list > ul > li', context).index(active); 61 | var total = $('div.item-list > ul > li', context).size(); 62 | 63 | switch (op) { 64 | case 'set': 65 | if (active.size() === 0) { 66 | index = 0; 67 | $('div.item-list > ul > li', context).hide(); 68 | $('div.item-list > ul > li:first', context).addClass('openlayers-popupbox-active').show(); 69 | $('ul.popup-links a.prev', context).addClass('disabled'); 70 | if (total <= 1) { 71 | $('ul.popup-links', context).hide(); 72 | } 73 | } 74 | else { 75 | if (index === 0) { 76 | $('ul.popup-links a.prev', context).addClass('disabled'); 77 | $('ul.popup-links a.next', context).removeClass('disabled'); 78 | } 79 | else if (index == (total - 1)) { 80 | $('ul.popup-links a.next', context).addClass('disabled'); 81 | $('ul.popup-links a.prev', context).removeClass('disabled'); 82 | } 83 | else { 84 | $('ul.popup-links a.next', context).removeClass('disabled'); 85 | $('ul.popup-links a.prev', context).removeClass('disabled'); 86 | } 87 | } 88 | var count = parseInt(index + 1, 10) + ' / ' + parseInt(total, 10); 89 | $('span.count', context).text(count); 90 | break; 91 | case 'next': 92 | if (index < (total - 1)) { 93 | active.removeClass('openlayers-popupbox-active').hide() 94 | .next('li').addClass('openlayers-popupbox-active').show(); 95 | Drupal.openlayers_plus_behavior_popup.pager(context, 'set'); 96 | } 97 | break; 98 | case 'prev': 99 | if (index > 0) { 100 | active.removeClass('openlayers-popupbox-active').hide() 101 | .prev('li').addClass('openlayers-popupbox-active').show(); 102 | Drupal.openlayers_plus_behavior_popup.pager(context, 'set'); 103 | } 104 | break; 105 | } 106 | }, 107 | 108 | // Click state 109 | 'openPopup': function(feature) { 110 | var context = $(feature.layer.map.div); 111 | 112 | // Initialize popup 113 | if (!$('.openlayers-popupbox', context).size()) { 114 | context.append(""); 115 | } 116 | else { 117 | $('.openlayers-popupbox:not(.popup)').addClass('popup'); 118 | } 119 | 120 | // Hide the layer switcher if it's open. 121 | for (var key in context.data('openlayers').openlayers.controls) { 122 | if (context.data('openlayers').openlayers.controls[key].CLASS_NAME == "OpenLayers.Control.LayerSwitcherPlus") { 123 | context.data('openlayers').openlayers.controls[key].minimizeControl(); 124 | } 125 | } 126 | 127 | var text; 128 | text = "X"; 129 | text += ""; 130 | text += ""; 131 | text += ""; 132 | $('.openlayers-popupbox', context).html(text).show(); 133 | Drupal.attachBehaviors($('.openlayers-popupbox', context)); 134 | }, 135 | 136 | // Callback for hover state 137 | // Only show tooltips on hover if the story popup is not open. 138 | 'over': function(feature) { 139 | var context = $(feature.layer.map.div); 140 | if (!$('.openlayers-popupbox.popup', context).size()) { 141 | if (feature.attributes.name) { 142 | var text = "
"; 143 | text += ""; 144 | text += ""; 145 | text += "
"; 146 | context.append(text); 147 | } 148 | } 149 | }, 150 | 151 | // Call back for out state. 152 | 'out': function(feature) { 153 | var context = $(feature.layer.map.div); 154 | $('.openlayers-popupbox:not(.popup)', context).fadeOut('fast', function() { $(this).remove(); }); 155 | } 156 | }; 157 | 158 | -------------------------------------------------------------------------------- /behaviors/openlayers_plus_behavior_scalepoints.inc: -------------------------------------------------------------------------------- 1 | 5, 'value' => 0); 10 | $options['max'] = array('pointRadius' => 20, 'value' => ''); 11 | $options['distinct'] = 5; 12 | $options['min_label'] = -1; 13 | $options['method'] = 'area'; 14 | // @TODO: This sucks. Get a submission/validation handling into the behaviors base class and fix this. 15 | $options['fields'] = array('count, weight'); 16 | return $options; 17 | } 18 | 19 | /** 20 | * Override of options_form(). 21 | */ 22 | function options_form() { 23 | $form = parent::options_form(); 24 | $form['min'] = array( 25 | '#tree' => TRUE, 26 | '#collapsible' => TRUE, 27 | '#collapsed' => TRUE, 28 | '#type' => 'fieldset', 29 | '#title' => t('Minimum values'), 30 | ); 31 | $form['max'] = array( 32 | '#tree' => TRUE, 33 | '#collapsible' => TRUE, 34 | '#collapsed' => TRUE, 35 | '#type' => 'fieldset', 36 | '#title' => t('Maximum values'), 37 | ); 38 | foreach (array('min', 'max') as $key) { 39 | $form[$key]['value'] = array( 40 | '#title' => t('Value'), 41 | '#description' => t('Enter a fixed value for this field or leave empty to autoscale points.'), 42 | '#type' => 'textfield', 43 | '#size' => 4, 44 | '#default_value' => $this->options[$key]['value'], 45 | ); 46 | $form[$key]['pointRadius'] = array( 47 | '#title' => t('Radius'), 48 | '#type' => 'textfield', 49 | '#size' => 4, 50 | '#default_value' => $this->options[$key]['pointRadius'], 51 | ); 52 | $form[$key]['fillOpacity'] = array( 53 | '#title' => t('Fill opacity'), 54 | '#type' => 'textfield', 55 | '#size' => 4, 56 | '#maxlength' => 4, 57 | '#default_value' => $this->options[$key]['fillOpacity'], 58 | ); 59 | $form[$key]['strokeWidth'] = array( 60 | '#title' => t('Stroke width'), 61 | '#type' => 'textfield', 62 | '#size' => 4, 63 | '#maxlength' => 4, 64 | '#default_value' => $this->options[$key]['strokeWidth'], 65 | ); 66 | // @TODO: Handle color gradation using API functions in color module 67 | /* 68 | $form[$key]['fillColor'] = array( 69 | '#title' => t('Fill color'), 70 | '#type' => 'textfield', 71 | '#size' => 7, 72 | '#maxlength' => 7, 73 | '#default_value' => $this->options[$key]['fillColor'], 74 | ); 75 | $form[$key]['strokeColor'] = array( 76 | '#title' => t('Stroke color'), 77 | '#type' => 'textfield', 78 | '#size' => 7, 79 | '#maxlength' => 7, 80 | '#default_value' => $this->options[$key]['strokeColor'], 81 | ); 82 | */ 83 | } 84 | $form['method'] = array( 85 | '#title' => t('Scaling method'), 86 | '#type' => 'select', 87 | '#options' => array( 88 | 'area' => t('Circle area'), 89 | 'radius' => t('Circle radius'), 90 | ), 91 | '#default_value' => $this->options['distinct'], 92 | ); 93 | $form['distinct'] = array( 94 | '#title' => t('Number of distinct sizes'), 95 | '#type' => 'textfield', 96 | '#default_value' => $this->options['distinct'], 97 | ); 98 | $form['fields'] = array( 99 | '#title' => t('Fields'), 100 | '#description' => t('Enter a comma separated list of attribute fields that can be used for scaling points. The first found attribute will be used.'), 101 | '#type' => 'textfield', 102 | '#default_value' => $this->options['fields'], 103 | ); 104 | $form['min_label'] = array( 105 | '#tree' => TRUE, 106 | '#collapsible' => TRUE, 107 | '#collapsed' => TRUE, 108 | '#type' => 'textfield', 109 | '#title' => t('Minimum weight point to label'), 110 | '#default_value' => $this->options['min_label'], 111 | '#description' => t('Don\'t show labels below a certain point weight'), 112 | ); 113 | return $form; 114 | } 115 | 116 | /** 117 | * Generate weight segments from the number of distinct values. 118 | */ 119 | function get_weights() { 120 | if (!is_numeric($this->options['distinct']) || $this->options['distinct'] < 1) { 121 | $this->options['distinct'] = 5; 122 | } 123 | $size = number_format(1 / $this->options['distinct'], 2); 124 | $weights = array(); 125 | for ($i = 1; $i < $this->options['distinct']; $i++) { 126 | $key = (string) ($i * $size); 127 | $weights[$key] = $i; 128 | } 129 | $weights[1] = $this->options['distinct']; 130 | return $weights; 131 | } 132 | 133 | /** 134 | * Generate a weight => pointRadius mapping. 135 | */ 136 | function get_styles() { 137 | $weights = array_values($this->get_weights()); 138 | $styles = array(); 139 | foreach (array_keys($this->options['min']) as $key) { 140 | if ($key !== 'value' && (!empty($this->options['min'][$key]) || !empty($this->options['max'][$key]))) { 141 | $pointdiff = ($this->options['max'][$key] - $this->options['min'][$key]) / $this->options['distinct']; 142 | $pointdiff = number_format($pointdiff, 2); 143 | foreach ($weights as $weight) { 144 | $styles[$weight][$key] = $this->options['min'][$key] + ($weight - 1) * $pointdiff; 145 | if ($weight <= $this->options['min_label']) { 146 | $styles[$weight]['label'] = ''; 147 | } 148 | } 149 | $styles[$this->options['distinct']][$key] = $this->options['max'][$key]; 150 | } 151 | } 152 | return $styles; 153 | } 154 | 155 | /** 156 | * Retrieve the first found usable field from a set of features. 157 | */ 158 | protected function get_field($features) { 159 | $fields = explode(',', $this->options['fields']); 160 | foreach ($fields as $k => $v) { 161 | $fields[$k] = trim($v); 162 | } 163 | foreach ($features as $feature) { 164 | foreach ($fields as $field) { 165 | if (isset($feature['attributes'][$field])) { 166 | return $field; 167 | } 168 | } 169 | } 170 | return FALSE; 171 | } 172 | 173 | protected function get_layers($layers) { 174 | $vector_layers = array(); 175 | foreach ($layers as $key => $layer) { 176 | // get type == Vector for backwards-compatibility. 177 | // TODO: After OpenLayers alpha8 it should be removed 178 | if (((isset($layer['vector']) && $layer['vector'] == 1)) && !empty($layer['features'])) { 179 | $vector_layers[$key] = $layer; 180 | } 181 | } 182 | return $vector_layers; 183 | } 184 | 185 | protected function process_weight($ratio, $method) { 186 | switch ($method) { 187 | case 'radius': 188 | return $ratio; 189 | case 'area': 190 | default: 191 | return sqrt($ratio); 192 | } 193 | } 194 | 195 | /** 196 | * Render. 197 | */ 198 | function render(&$map) { 199 | // Get the layers we are going to use. 200 | $layers = $this->get_layers($map['layers']); 201 | 202 | $get_min = $this->options['min']['value'] === '' || !isset($this->options['min']['value']); 203 | $get_max = $this->options['max']['value'] === '' || !isset($this->options['max']['value']); 204 | 205 | $weights = $this->get_weights(); 206 | foreach ($layers as $k => $layer) { 207 | // Get the field we are going to use. 208 | if ($field = $this->get_field($layer['features'])) { 209 | // Get min/max per layer. 210 | $min = isset($this->options['min']['value']) && is_numeric($this->options['min']['value']) ? $this->options['min']['value'] : 1000000; 211 | $max = isset($this->options['max']['value']) && is_numeric($this->options['max']['value']) ? $this->options['max']['value'] : 0; 212 | $count_min = 1000000; 213 | $count_max = 0; 214 | if ($get_min || $get_max) { 215 | foreach ($layer['features'] as $j => $feature) { 216 | if ($field && isset($feature['attributes'][$field]) && $count = $feature['attributes'][$field]) { 217 | // Replace the count attribute with the selected one. 218 | if ($field !== 'count') { 219 | $map['layers'][$k]['features'][$j]['attributes']['count'] = $count; 220 | } 221 | $max = ($count > $max) && $get_max ? $count : $max; 222 | $min = ($count < $min) && $get_min ? $count : $min; 223 | $count_max = ($count > $count_max) ? $count : $count_max; 224 | $count_min = ($count < $count_min) ? $count : $count_min; 225 | } 226 | } 227 | } 228 | 229 | // Sensible defaults code right here: If count_max & count_min are both under 1, 230 | // assume data source is doing a ratio calc for us. Set max to 1. 231 | if ($count_max < 1 && $count_min < 1) { 232 | $max = 1; 233 | } 234 | 235 | foreach ($layer['features'] as $j => $feature) { 236 | if ($field && isset($feature['attributes'][$field]) && $count = $feature['attributes'][$field]) { 237 | // For layers with only a single value always use the smallest weight. 238 | if ($count_max === $count_min) { 239 | $map['layers'][$k]['features'][$j]['attributes']['weight'] = 1; 240 | } 241 | // Otherwise iterate through to find the right weight. 242 | else { 243 | $calculated = $this->process_weight(($count - $min)/($max - $min), $this->options['method']); 244 | foreach ($weights as $percentile => $weight) { 245 | if ($calculated <= $percentile) { 246 | $map['layers'][$k]['features'][$j]['attributes']['weight'] = $weight; 247 | break; 248 | } 249 | } 250 | } 251 | } 252 | } 253 | } 254 | } 255 | 256 | drupal_add_js(drupal_get_path('module', 'openlayers_plus') .'/behaviors/openlayers_plus_behavior_scalepoints.js'); 257 | $options = array(); 258 | $options['styles'] = $this->get_styles(); 259 | return $options; 260 | } 261 | } 262 | -------------------------------------------------------------------------------- /behaviors/openlayers_plus_behavior_scalepoints.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementation of Drupal behavior. 3 | */ 4 | Drupal.behaviors.openlayers_plus_behavior_scalepoints = function(context) { 5 | var data = $(context).data('openlayers'); 6 | if (data && data.map.behaviors.openlayers_plus_behavior_scalepoints) { 7 | var styles = data.map.behaviors.openlayers_plus_behavior_scalepoints.styles; 8 | // Collect vector layers 9 | var vector_layers = []; 10 | for (var key in data.openlayers.layers) { 11 | var layer = data.openlayers.layers[key]; 12 | if (layer.isVector === true) { 13 | var styleMap = layer.styleMap; 14 | styleMap.addUniqueValueRules("default", "weight", styles); 15 | layer.redraw(); 16 | vector_layers.push(layer); 17 | } 18 | } 19 | /** 20 | * This attempts to fix a problem in IE7 in which points 21 | * are not displayed until the map is moved. 22 | * 23 | * Since namespaces is filled neither on window.load nor 24 | * document.ready, and testing it is unsafe, this renders 25 | * map layers after 500 milliseconds. 26 | */ 27 | if($.browser.msie) { 28 | setTimeout(function() { 29 | $.each(data.openlayers.getLayersByClass('OpenLayers.Layer.Vector'), 30 | function() { 31 | this.redraw(); 32 | }); 33 | }, 500); 34 | } 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /behaviors/openlayers_plus_behavior_tooltips.inc: -------------------------------------------------------------------------------- 1 | FALSE); 9 | } 10 | 11 | /** 12 | * Override of options_form(). 13 | */ 14 | function options_form() { 15 | $form = parent::options_form(); 16 | $form['positioned'] = array( 17 | '#type' => 'checkbox', 18 | '#title' => t('Position tooltip over feature'), 19 | '#default_value' => $this->options['positioned'], 20 | ); 21 | return $form; 22 | } 23 | 24 | /** 25 | * Render. 26 | */ 27 | function render(&$map) { 28 | drupal_add_js(drupal_get_path('module', 'openlayers_plus') .'/behaviors/openlayers_plus_behavior_tooltips.js'); 29 | return $this->options; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /behaviors/openlayers_plus_behavior_tooltips.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Implementation of Drupal behavior. 3 | */ 4 | Drupal.behaviors.openlayers_plus_behavior_tooltips = function(context) { 5 | Drupal.OpenLayersTooltips.attach(context); 6 | }; 7 | 8 | Drupal.OpenLayersTooltips = {}; 9 | 10 | Drupal.OpenLayersTooltips.attach = function(context) { 11 | var data = $(context).data('openlayers'); 12 | if (data && data.map.behaviors.openlayers_plus_behavior_tooltips) { 13 | // Options 14 | var select_method = 'select'; 15 | if (data.map.behaviors.openlayers_plus_behavior_tooltips.positioned) { 16 | select_method = 'positionedSelect'; 17 | } 18 | // Collect vector layers 19 | var vector_layers = []; 20 | for (var key in data.openlayers.layers) { 21 | var layer = data.openlayers.layers[key]; 22 | if (layer.isVector === true) { 23 | vector_layers.push(layer); 24 | } 25 | } 26 | // Add control 27 | var control = new OpenLayers.Control.SelectFeature(vector_layers, { 28 | activeByDefault: true, 29 | highlightOnly: false, 30 | onSelect: Drupal.OpenLayersTooltips.select, 31 | onUnselect: Drupal.OpenLayersTooltips.unselect, 32 | multiple: false, 33 | hover: true, 34 | callbacks: { 35 | 'click': Drupal.OpenLayersTooltips.click, 36 | 'over': Drupal.OpenLayersTooltips[select_method], 37 | 'out': Drupal.OpenLayersTooltips.unselect 38 | } 39 | }); 40 | data.openlayers.addControl(control); 41 | control.activate(); 42 | } 43 | }; 44 | 45 | Drupal.OpenLayersTooltips.click = function(feature) { 46 | var html = ''; 47 | if (feature.attributes.name) { 48 | html += feature.attributes.name; 49 | } 50 | if (feature.attributes.description) { 51 | html += feature.attributes.description; 52 | } 53 | // @TODO: Make this a behavior option and allow interaction with other 54 | // behaviors like the MN story popup. 55 | var link; 56 | if ($(html).is('a')) { 57 | link = $(html); 58 | } 59 | else if ($(html).children('a').size() > 0) { 60 | link = $(html).children('a')[0]; 61 | } 62 | if (link) { 63 | var href = $(link).attr('href'); 64 | if (Drupal.OpenLayersPermalink && Drupal.OpenLayersPermalink.addQuery) { 65 | href = Drupal.OpenLayersPermalink.addQuery(href); 66 | } 67 | window.location = href; 68 | return false; 69 | } 70 | return; 71 | }; 72 | 73 | Drupal.OpenLayersTooltips.getToolTip = function(feature) { 74 | var text = "
"; 75 | if (feature.attributes.name) { 76 | text += "
" + feature.attributes.name + "
"; 77 | } 78 | if (feature.attributes.description) { 79 | text += "
" + feature.attributes.description + "
"; 80 | } 81 | text += "
"; 82 | return $(text); 83 | } 84 | 85 | Drupal.OpenLayersTooltips.select = function(feature) { 86 | var tooltip = Drupal.OpenLayersTooltips.getToolTip(feature); 87 | $(feature.layer.map.div).append(tooltip); 88 | }; 89 | 90 | Drupal.OpenLayersTooltips.positionedSelect = function(feature) { 91 | var tooltip = Drupal.OpenLayersTooltips.getToolTip(feature); 92 | var point = new OpenLayers.LonLat(feature.geometry.x, feature.geometry.y); 93 | var offset = feature.layer.getViewPortPxFromLonLat(point); 94 | $(tooltip).css({zIndex: '1000', position: 'absolute', left: offset.x, top: offset.y}); 95 | $(feature.layer.map.div).css({position:'relative'}).append(tooltip); 96 | }; 97 | 98 | Drupal.OpenLayersTooltips.unselect = function(feature) { 99 | $(feature.layer.map.div).children('div.openlayers-tooltip').fadeOut('fast', function() { $(this).remove(); }); 100 | }; 101 | -------------------------------------------------------------------------------- /openlayers_plus.info: -------------------------------------------------------------------------------- 1 | ; $Id$ 2 | core = "6.x" 3 | name = "OpenLayers Plus" 4 | dependencies[] = "openlayers" 5 | description = "Additional tools and behaviors for OpenLayers" 6 | package = "OpenLayers" 7 | -------------------------------------------------------------------------------- /openlayers_plus.module: -------------------------------------------------------------------------------- 1 | array('info' => t('OL+ Blockswitcher'))); 10 | return $blocks; 11 | case 'view': 12 | switch ($delta) { 13 | case 'blockswitcher': 14 | return array( 15 | 'subject' => t('Map layers'), 16 | 'content' => theme('openlayers_plus_blockswitcher') 17 | ); 18 | case 'blocktoggle': 19 | return array( 20 | 'subject' => t('Map layers'), 21 | 'content' => theme('openlayers_plus_blocktoggle') 22 | ); 23 | } 24 | } 25 | } 26 | 27 | /** 28 | * Implementation of hook_theme(). 29 | */ 30 | function openlayers_plus_theme() { 31 | return array( 32 | 'openlayers_plus_blockswitcher' => array( 33 | 'arguments' => array(), 34 | 'path' => drupal_get_path('module', 'openlayers_plus') . '/theme', 35 | 'template' => 'openlayers-plus-blockswitcher', 36 | 'file' => 'theme.inc', 37 | ), 38 | 'openlayers_plus_blocktoggle' => array( 39 | 'arguments' => array('a_label' => '', 'b_label' => ''), 40 | 'path' => drupal_get_path('module', 'openlayers_plus') . '/theme', 41 | 'template' => 'openlayers-plus-blocktoggle', 42 | 'file' => 'theme.inc', 43 | ), 44 | 'openlayers_plus_legend_raw' => array( 45 | 'arguments' => array('raw' => '', 'layer' => array(), 'layer_id' => array()), 46 | 'path' => drupal_get_path('module', 'openlayers_plus') . '/theme', 47 | 'template' => 'openlayers-plus-legend-raw', 48 | 'file' => 'theme.inc', 49 | ), 50 | 'openlayers_plus_legend' => array( 51 | 'arguments' => array('legend' => array(), 'layer' => array(), 'layer_id' => array()), 52 | 'path' => drupal_get_path('module', 'openlayers_plus') . '/theme', 53 | 'template' => 'openlayers-plus-legend', 54 | 'file' => 'theme.inc', 55 | ), 56 | ); 57 | } 58 | 59 | /** 60 | * Implementation of hook_openlayers_behaviors(). 61 | * 62 | * This is a ctools plugins hook. 63 | */ 64 | function openlayers_plus_openlayers_behaviors() { 65 | return array( 66 | 'openlayers_plus_behavior_blockswitcher' => array( 67 | 'title' => t('OL+: Blockswitcher'), 68 | 'description' => t('A clone of LayerSwitcher, with better themability and positioning via the Drupal block system.'), 69 | 'behavior' => array( 70 | 'path' => drupal_get_path('module', 'openlayers_plus') .'/behaviors', 71 | 'file' => 'openlayers_plus_behavior_blockswitcher.inc', 72 | 'class' => 'openlayers_plus_behavior_blockswitcher', 73 | 'parent' => 'openlayers_behavior', 74 | ), 75 | ), 76 | 'openlayers_plus_behavior_blocktoggle' => array( 77 | 'title' => t('OL+: Blocktoggle'), 78 | 'description' => t('A version of BlockSwitcher that toggles between two different layers only. Useful for situations in which layers represent the same data in slightly different ways.'), 79 | 'behavior' => array( 80 | 'path' => drupal_get_path('module', 'openlayers_plus') .'/behaviors', 81 | 'file' => 'openlayers_plus_behavior_blocktoggle.inc', 82 | 'class' => 'openlayers_plus_behavior_blocktoggle', 83 | 'parent' => 'openlayers_behavior', 84 | ), 85 | ), 86 | 'openlayers_plus_behavior_legend' => array( 87 | 'title' => t('OL+: Map legend'), 88 | 'description' => t('A block in a corner of a map that provides information on layers.'), 89 | 'behavior' => array( 90 | 'path' => drupal_get_path('module', 'openlayers_plus') .'/behaviors', 91 | 'file' => 'openlayers_plus_behavior_legend.inc', 92 | 'class' => 'openlayers_plus_behavior_legend', 93 | 'parent' => 'openlayers_behavior', 94 | ), 95 | ), 96 | 'openlayers_plus_behavior_permalink' => array( 97 | 'title' => t('OL+: Permalink'), 98 | 'description' => t('A version of Permalink optimized to persist layers between pages with different layer setups and without explicitly using the control.'), 99 | 'behavior' => array( 100 | 'path' => drupal_get_path('module', 'openlayers_plus') .'/behaviors', 101 | 'file' => 'openlayers_plus_behavior_permalink.inc', 102 | 'class' => 'openlayers_plus_behavior_permalink', 103 | 'parent' => 'openlayers_behavior', 104 | ), 105 | ), 106 | 'openlayers_plus_behavior_scalepoints' => array( 107 | 'title' => t('OL+: Scalepoints'), 108 | 'description' => t('Dynamic styling, changing point radii based on a certain value.'), 109 | 'behavior' => array( 110 | 'path' => drupal_get_path('module', 'openlayers_plus') .'/behaviors', 111 | 'file' => 'openlayers_plus_behavior_scalepoints.inc', 112 | 'class' => 'openlayers_plus_behavior_scalepoints', 113 | 'parent' => 'openlayers_behavior', 114 | ), 115 | ), 116 | 'openlayers_plus_behavior_tooltips' => array( 117 | 'title' => t('OL+: Tooltips'), 118 | 'description' => t('An interaction with point-based maps that results in following links on hover.'), 119 | 'behavior' => array( 120 | 'path' => drupal_get_path('module', 'openlayers_plus') .'/behaviors', 121 | 'file' => 'openlayers_plus_behavior_tooltips.inc', 122 | 'class' => 'openlayers_plus_behavior_tooltips', 123 | 'parent' => 'openlayers_behavior', 124 | ), 125 | ), 126 | 'openlayers_plus_behavior_popup' => array( 127 | 'title' => t('OL+: Popups'), 128 | 'description' => t('An interaction with point-based, clustered maps that allows clicking on points that results in scanning between items.'), 129 | 'behavior' => array( 130 | 'path' => drupal_get_path('module', 'openlayers_plus') .'/behaviors', 131 | 'file' => 'openlayers_plus_behavior_popup.inc', 132 | 'class' => 'openlayers_plus_behavior_popup', 133 | 'parent' => 'openlayers_behavior', 134 | ), 135 | ), 136 | ); 137 | } 138 | -------------------------------------------------------------------------------- /theme/active.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/developmentseed/openlayers_plus/34529f8fcd5a060271d07938702bd7fa6e8afc71/theme/active.png -------------------------------------------------------------------------------- /theme/inactive.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/developmentseed/openlayers_plus/34529f8fcd5a060271d07938702bd7fa6e8afc71/theme/inactive.png -------------------------------------------------------------------------------- /theme/openlayers-plus-blockswitcher.tpl.php: -------------------------------------------------------------------------------- 1 |
2 |
3 |

4 |
5 |
6 |
7 |
8 |

9 |
10 |
11 |
12 | 13 | 21 |
22 | -------------------------------------------------------------------------------- /theme/openlayers-plus-blocktoggle.tpl.php: -------------------------------------------------------------------------------- 1 | 8 |
9 |
10 |
11 |
12 |
13 |
14 | -------------------------------------------------------------------------------- /theme/openlayers-plus-legend-raw.tpl.php: -------------------------------------------------------------------------------- 1 | 9 |
10 | 11 |
12 | -------------------------------------------------------------------------------- /theme/openlayers-plus-legend.tpl.php: -------------------------------------------------------------------------------- 1 | 9 |
10 | 11 |

12 | 13 | $item): ?> 14 |
15 | '> 16 | 17 |
18 | 19 |
20 | -------------------------------------------------------------------------------- /theme/openlayers_plus-rtl.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Blockswitcher ====================================================== 3 | */ 4 | .openlayers-blockswitcher span.key { 5 | float:right; 6 | margin-right:0px; 7 | margin-left:5px; 8 | } 9 | 10 | .openlayers-blockswitcher input.form-radio, 11 | .openlayers-blockswitcher input.form-checkbox { 12 | margin-right:0px; 13 | margin-left:5px; 14 | } 15 | 16 | div.openlayers-map #block-openlayers_plus-blockswitcher.ne { right:auto; left:0px; } 17 | div.openlayers-map #block-openlayers_plus-blockswitcher.nw { left:auto; right:0px; } 18 | div.openlayers-map #block-openlayers_plus-blockswitcher.se { right:auto; left:0px; } 19 | div.openlayers-map #block-openlayers_plus-blockswitcher.sw { left:auto; right:0px; } 20 | 21 | /** 22 | * Blocktoggle ======================================================== 23 | */ 24 | div.openlayers-map #block-openlayers_plus-blocktoggle.ne { right:auto; left:0px; } 25 | div.openlayers-map #block-openlayers_plus-blocktoggle.nw { left:auto; right:0px; } 26 | div.openlayers-map #block-openlayers_plus-blocktoggle.se { right:auto; left:0px; } 27 | div.openlayers-map #block-openlayers_plus-blocktoggle.sw { left:auto; right:0px; } -------------------------------------------------------------------------------- /theme/openlayers_plus.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Legend ============================================================= 3 | */ 4 | .openlayers-legends { 5 | position:absolute; 6 | left:5px; 7 | bottom:5px; 8 | z-index:3000; 9 | } 10 | 11 | .openlayers-legends .legend { 12 | background:#fff; 13 | -moz-border-radius:3px; 14 | -webkit-border-radius:3px; 15 | } 16 | 17 | .openlayers-legends .swatch { 18 | float:left; 19 | display:block; 20 | width:15px; 21 | height:15px; 22 | margin-right:5px; 23 | } 24 | 25 | /** 26 | * Blockswitcher ====================================================== 27 | */ 28 | .openlayers-blockswitcher span.key { 29 | display:block; 30 | float:left; 31 | height:20px; 32 | width:20px; 33 | margin-right:5px; 34 | } 35 | 36 | .openlayers-blockswitcher input.form-radio, 37 | .openlayers-blockswitcher input.form-checkbox { margin-right:5px; } 38 | 39 | div.openlayers-map #block-openlayers_plus-blockswitcher { 40 | position:absolute; 41 | z-index:3000; 42 | background:#fff; 43 | width:auto; 44 | } 45 | 46 | div.openlayers-map #block-openlayers_plus-blockswitcher.ne { top:0px; right:0px; } 47 | div.openlayers-map #block-openlayers_plus-blockswitcher.nw { top:0px; left:0px; } 48 | div.openlayers-map #block-openlayers_plus-blockswitcher.se { bottom:0px; right:0px; } 49 | div.openlayers-map #block-openlayers_plus-blockswitcher.sw { bottom:0px; left:0px; } 50 | 51 | div.openlayers-map #block-openlayers_plus-blockswitcher h2.block-title { cursor:pointer; } 52 | div.openlayers-map #block-openlayers_plus-blockswitcher div.block-content { display:none; } 53 | 54 | div.openlayers-map #block-openlayers_plus-blockswitcher div.radio { 55 | background: #fff url('inactive.png'); 56 | background-repeat: no-repeat; 57 | padding: 3px 0 3px 25px; 58 | } 59 | 60 | div.openlayers-map #block-openlayers_plus-blockswitcher div.activated { 61 | background: #fff url('active.png'); 62 | background-repeat: no-repeat; 63 | padding: 3px 0 3px 25px; 64 | } 65 | 66 | /** 67 | * Blocktoggle ======================================================== 68 | */ 69 | div.openlayers-map #block-openlayers_plus-blocktoggle { 70 | position:absolute; 71 | z-index:3000; 72 | background:transparent; 73 | width:auto; 74 | padding: 0; 75 | -moz-border-radius:3px; 76 | -webkit-border-radius:3px; 77 | } 78 | 79 | div.openlayers-map #block-openlayers_plus-blocktoggle.ne { top:0px; right:0px; } 80 | div.openlayers-map #block-openlayers_plus-blocktoggle.nw { top:0px; left:0px; } 81 | div.openlayers-map #block-openlayers_plus-blocktoggle.se { bottom:0px; right:0px; } 82 | div.openlayers-map #block-openlayers_plus-blocktoggle.sw { bottom:0px; left:0px; } 83 | 84 | div.openlayers-map #block-openlayers_plus-blocktoggle h2.block-title { display:none; } 85 | 86 | div.openlayers-map #block-openlayers_plus-blocktoggle .openlayers-blocktoggle-a, 87 | div.openlayers-map #block-openlayers_plus-blocktoggle .openlayers-blocktoggle-b { 88 | float:left; 89 | color:#666; 90 | background:url('point-button.png') #fff 5px 50% no-repeat; 91 | padding:0px 5px 0px 20px; 92 | line-height:20px; 93 | width:50px; 94 | cursor:pointer; 95 | } 96 | 97 | div.openlayers-map #block-openlayers_plus-blocktoggle .openlayers-blocktoggle-a { 98 | -moz-border-radius: 3px 0 0 3px; 99 | -webkit-border-radius: 3px 0 0 3px; 100 | border-right:1px solid #ccc; 101 | } 102 | 103 | div.openlayers-map #block-openlayers_plus-blocktoggle .openlayers-blocktoggle-b { 104 | -moz-border-radius: 0 3px 3px 0; 105 | -webkit-border-radius: 0 3px 3px 0; 106 | background-image:url('point-choro.png'); 107 | } 108 | 109 | div.openlayers-map #block-openlayers_plus-blocktoggle .activated { 110 | background-color:#eee; 111 | color:#222; 112 | } 113 | -------------------------------------------------------------------------------- /theme/point-button.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/developmentseed/openlayers_plus/34529f8fcd5a060271d07938702bd7fa6e8afc71/theme/point-button.png -------------------------------------------------------------------------------- /theme/point-choro.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/developmentseed/openlayers_plus/34529f8fcd5a060271d07938702bd7fa6e8afc71/theme/point-choro.png -------------------------------------------------------------------------------- /theme/theme.inc: -------------------------------------------------------------------------------- 1 |