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,2 @@
.idea
.idea/*

View File

@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View File

@@ -0,0 +1,123 @@
Current for 7.x-2.0-beta1
updated on 2012-08-24
# Description
OpenLayers is a suite of module to help integrate the
OpenLayers Javascript library within Drupal.
# Requirements
OpenLayers Requires
* CTools: http://drupal.org/project/ctools
* Libraries: https://drupal.org/project/libraries - Use the 2.x version, and make sure to create your sites/all/libraries subdirectory.
* GeoPhP https://drupal.org/project/geophp
Sub-modules require
* OpenLayers Views requires Views: http://drupal.org/project/views
OpenLayers can use Features to package maps into modules
* Features: http://drupal.org/project/features
# Sub-Modules
You'll most likely want to enable OpenLayers UI and OpenLayers Views modules for typical uses of OpenLayers.
* OpenLayers UI - Creates a user interface to make map
arrays which can be used in various places
* Views - Allows data to be displayed on a map
via Views
* Filters - Creates a filter to replace
[openlayers map_name] with a map.
# Basic Concepts
## Maps
An OpenLayers map in Drupal is a combination of decisions about which
layers to show, what styles to apply, the minimum and maximum zoom levels,
and how the user can interact with the map. A map object is where
the options for these settings are combined and stored. Maps can be
rendered through OpenLayers views of the type "OpenLayers Map," through
filters provided by the OpenLayers Filters module, or directly in your
modules using the api function openlayers_render_map()
## Layers
OpenLayers allows for the display of a variety of raster and vector data on
maps. These are divided into two categories: basemaps and overlays.
Basemaps, like those from OpenStreetMap or Google Maps, provide a background
for your data. Overlays can be data from OpenLayers data views, KML layers,
or other types of data from external sources.
For more information on layer types, see docs/LAYER_TYPES.txt
## Styles
The OpenLayers module currently allows users to define custom styles for
vector overlays. The primary use-case here will be data from OpenLayers
data views but this could also include KML files. Styles define things like
stroke width, background and outline colors, and point size and allow the
use of icons if desired. They must be associated with layers on a per-
map basis.
## Behaviors
Behaviors can be enabled on maps to control how users interact with
the map. Examples of behaviors include navigation, which, when enabled,
allows users to zoom and pan, and Layer Switcher, which provides a UI that
allows users to toggle on and off the layers available on the map.
## OpenLayers Views
OpenLayers views come in two varieties. The first is a display type called
OpenLayers Data. This is what allows users to control which pieces of
content show up on the map and in what manner. Each OpenLayers data view
provides a layer that can be added to maps when configuring a map. The
second is a style called OpenLayers Map that can be applied to pages,
blocks, attachments, and so on and give users an easy way of rendering
maps.
# Installation
1. Normal Drupal module installation
2. Set OpenLayers Source at: admin/structure/openlayers
It is suggested to download the library and use it locally for performance.
3. A tutorial
# Documentation
More documentation is available in the docs/ directory of this module:
* CUSTOMIZATION.txt: a cookbook for common customizations users might want
to make for performance and tweaking
* API.txt: a technical description of the main map-generating API
* LAYER_TYPES.txt: a technical description of how layer types work and
guide for implementation of new layer types
* KML.txt: an explanation of how KML support works in OpenLayers
* JAVASCRIPT.txt: a technical explanation of how the Javascript included
in the OpenLayers module (not the code in the actual OpenLayers library)
operates
A [tutorial is available on Drupal.org] (https://drupal.org/node/1481374)
# Authors/Credits
* [zzolo](http://drupal.org/user/147331)
* [phayes](http://drupal.org/user/47098)
* [tmcw](http://drupal.org/user/12664)
* [brynbellomy](http://drupal.org/user/537416)
* [bdragon](http://drupal.org/user/53081)
* [OpenLayers monster by Saman Bemel Benrud](http://www.flickr.com/photos/samanpwbb/)
* [strk](http://drupal.org/user/781486)
* [pol](https://drupal.org/user/47194)

View File

@@ -0,0 +1,74 @@
/**
* @file
* OpenLayers Main CSS
*
* This file holds the base CSS for the openlayers module
*
* @ingroup openlayers
*/
.openlayers-cck-feature-selected { border: 2px solid blue; }
.openlayers-map {
z-index:0;
position:relative;
}
/**
* prevent rtl translations from mirroring
* vector layers
*/
.openlayers-map .olLayerDiv {
direction: ltr
}
/**
* Controls
*/
.openlayers-controls {
z-index: 1000;
}
body .olControlLayerSwitcher .layersDiv {
background-color: #222222;
}
body .olControlLayerSwitcher.legacy .layersDiv {
background-color: darkblue;
}
body .olControlAttribution {
right: 5px;
bottom: 5px;
}
/**
* This is a 'sensible default' for a weird decision
* by OpenLayers to make 404 tiles pink.
*/
body .olImageLoadError {
background: transparent;
}
/*
* Do not display the close button on tooltips.
* See #1875844
*/
.openlayers-container #tooltip #tooltip_close {
display: none;
}
/*
* Make OpenLayers img tag behave correctly with responsive stuff.
* See #1816826
*/
.openlayers-container img {
max-width: none;
}
/*
* Fix #1904424 and #1646646.
*/
label.olButton {
display: inline;
}

View File

@@ -0,0 +1,36 @@
Current for 6.x-2.0-alpha2
This file contains the main API functions for OpenLayers and its sub-modules.
Please refer to the project page for more up to date information and
documentation:
* http://drupal.org/project/openlayers
# Advanced Help
Browsable documentation is available through the [Advanced Help
module.](http://drupal.org/project/advanced_help)
# Map Build Process
The parts to build a map - layers, behaviors, maps, and styles - are loaded
with menu loaders, like `openlayers_layer_export_load`. They should not be
loaded manually because menu loaders do the necessary instantiation and
cache-clearing.
In 2.x, layers, behaviors, and styles contain more logic for 'rendering
themselves' than before, but cannot completely exist on their own. The functions
that iterate over included layers, behaviors, and styles are in
`openlayers.render.inc`.
`openlayers_build_map` and `openlayers_render_map` are the two essential parts
of the actual map building and rendering, and are included in
`openlayers.module`.
The map building process does not directly deal with map data: in the case that
Drupal is rendering data (as in openlayers_views), this functionality is
encapsulated in the `render()` method of the layer type. See
`modules/openlayers_views` for an example of how this works.

View File

@@ -0,0 +1,124 @@
Current for 6.x-2.0-alpha6
# Creating a new OpenLayers Behavior from Scratch
First, you'll need to create a module. Of course, skip through this step if
there's already a module that exists to which this behavior will be added. But
if not, create a file called `modulename.info` with the contents
core = "6.x"
dependencies[] = "openlayers"
name = "modulename"
package = "OpenLayers"
project = "modulename"
In this case, you're creating a module just for this feature. So you'll need to
implement a hook to notify OpenLayers that your module can do something for it.
There's a hook called `hook_openlayers_behaviors` for this, and since your
module is called modulename, its implementation should be
`modulename_openlayers_behaviors`. A basic implementation would be
function modulename_openlayers_behaviors() {
return array(
'openlayers_behavior_mybehavior' => array(
'title' => t('My Behavior'),
'description' => t('Does something'),
'type' => 'layer',
'path' => drupal_get_path('module', 'modulename')
.'/includes/behaviors',
'file' => 'openlayers_behavior_mybehavior.inc',
'behavior' => array(
'class' => 'openlayers_behavior_mybehavior',
'parent' => 'openlayers_behavior',
),
),
);
}
Note the essentials here: this tells the OpenLayers module that there is a file
in `modules/modulename/includes/behaviors/` which implements a class called
`openlayers_behavior_mybehavior`. It isn't strictly necessary to create an
includes folder and a behaviors folder under it, but it's good practice so that
your module doesn't become cluttered.
So on to the PHP that this hook refers to: usually there's only a small amount
of PHP written for each behavior. On the first level, the file simply must
include a class that extends the class openlayers_behavior:
class openlayers_behavior_mybehavior extends openlayers_behavior {}
There'll be a little bit for this one, but it's not very functional - only
adding JavaScript code and declaring forms.
Here's what you'll write for this behavior:
class openlayers_behavior_mybehavior extends openlayers_behavior {}
function options_init() {
return array(
);
}
function options_form($defaults) {
return array(
'filteredlayer' => array(
'#type' => 'select',
'#options' => $this->map['layers'],
'#description' => t('Select layer to filter'),
'#default_value' => isset($defaults['filteredlayer']) ?
$defaults['filteredlayer'] : NULL
),
);
}
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'mybehavior')
.'/includes/behaviors/js/openlayers_behavior_mybehavior.js');
return $this->options;
}
}
As you can see, there's an options_form method which is called when the list of
behaviors is generated for each map, and given a `$defaults` array if there
have already been values saved. It isn't required to implement this method,
although many behaviors will need it. And at this level - in the options_form,
you have access to the map object with $this - so you can get layers, styles,
and other parts of the map to play around with The `render(&$map)` function
is indeed required, since it is called for every behavior.
There's quite a bit of Javascript to write for this behavior:
/**
* Maptimeline Behavior
*/
Drupal.behaviors.openlayers_behavior_mybehavior = function(context) {
var data = $(context).data('openlayers');
var slider_div = {};
if (data && data.map.behaviors['openlayers_behavior_mybehavior']) {
behavior = data.map.behaviors['openlayers_behavior_mybehavior'];
layer = data.openlayers.getLayersBy(
'drupalID',
behavior.filteredlayer)[0];
// Do things with this feature, etc.
});
}
}
Note the essentials of this file: all of the functionality needed is contained
in a single function, `Drupal.behaviors.openlayers_behavior_mybehavior`. The
facts that the containing function is called `openlayers_behavior_mybehavior`
and that it receives a single argument, `context`, are essential, but besides
those restrictions, behaviors can contain any Javascript code whatsoever.
Behaviors are called after all layers and styles are added to the map and the
map is rendered.
This code demonstrates a few core concepts of behavior-writing:
* The OpenLayers [Map object](http://dev.openlayers.org/releases/OpenLayers-2.8/doc/apidocs/files/OpenLayers/Map-js.html)
is accessible via `$(context).data('openlayers').openlayers`
* The [jQuery Data function](http://api.jquery.com/jQuery.data/) is used in the
OpenLayers module to simplify variable scope and avoid the possibility of
memory leaks.

View File

@@ -0,0 +1,2 @@
This is maintained on Drupal.org at the following URL:
http://drupal.org/node/177400/release

View File

@@ -0,0 +1,46 @@
Current for 6.x-2.0-alpha3
Obviously there are many points at which advanced users will want to push the
limits of what the OpenLayers module can do. In many cases, these changes can be
make without any 'hacks' to the module, and before hacking, it is highly
recommended to think about ways that changes could be incorporated into the
module proper via patches.
# Performance
The largest performance hit of OpenLayers at the moment seems to be in the very
large size of the OpenLayers.js library. The real route to fixing this problem
is by narrowing down the set of components included in the Javascript file. In
order to do this:
## Manually
svn checkout http://svn.openlayers.org/trunk/openlayers/ cd openlayers/build
edit full.cfg or lite.cfg to include the components your map uses.
python build.py [yourcustomized.cfg]
This will produce a compacted, slimmed OpenLayers.js file.
After doing this, make sure to set the ImgPath and ThemePath in the OpenLayers
administration - these are per-map settings. The OpenLayers library guesses
the location of its style.css and images, so if you make a compacted
OpenLayers.js in an otherwise empty folder, it will fail in this task and have
blank images and a nonfunctional ZoomBox control (the red 'zooming box') will
not appear.
## Map Performance
Using multiple domain names for layers will [dodge the browser connection
limit](http://trac.openlayers.org/wiki/OpenLayersOptimization) and allow more
tiles to load in parallel. However, this has a bad interaction with the default
buffer setting, making tiles outside the viewport load first in many cases, so
buffer should be set to 0 if multiple urls are enabled.
# Custom Behaviors
If behaviors similar to those included are necessary, just clone the behaviors
and create a tiny new module that includes the copy. The same goes for layers,
etc.

View File

@@ -0,0 +1,61 @@
Using the OpenLayers Javascript from the OpenLayers module can present some
problems with rendering vector layers in IE.
The root cause of the issue:
Internet Explorer has a thing called VML: Vector Markup Language, which it uses
to draw graphics. VML is what you use in IE: canvas4ie is way slow, google maps
uses VML to draw routes, and OpenLayers uses it to draw vectors.
VML elements are styled by creating CSS-like styles in a namespace. OpenLayers
creates an ol: namespace and then creates styles like ol:line ol:circle, etc.
To do this, it has to access document.namespaces. Document.namespaces is not
always around: notably, you can't depend on it being around before
document.ready.
But, sometimes document.namespaces *is* around before document.ready and that's
the thing that messed up my worldview. So, the theory was, there are modes.
Something in HTML can prevent document.namespaces being filled in before
document.ready.
Here's how it goes.
### $( or $(document).ready()
* If there is a broken image on the page, then namespaces is not filled in.
* If the page has no broken images, then document.namespaces is accessible
### document.load()
* document.namespaces is always filled in.
### 31 stylesheets
IE cannot handle more than 31 stylesheets on a page at a time. This is clearly
the devil's work, but it persists beyond IE8. If there are 31 stylesheets and
you run an OpenLayers map, it cannot add another stylesheet to initialize its
VML namespace. Therefore, the map breaks. You must aggregate your CSS.
### The Fix
We can't move openlayers to document.load() because it is dependent on the
Drupal behaviors stack, that runs on document.ready(). We need to just define
document.namespaces before OpenLayers asks its VML renderer whether the current
browser is capable of rendering VML (a task it tries to complete by calling
!!(document.namespaces))
### Other Fixes
Adding a tag
<code><meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" /></code>
will allow IE8 to render vectors if it doesn't render them correctly on a normal
pageload. Note that this must be the first element inside the header tag.
### Image Opacity
The opacity of image pointers are created with IE filters, which do not function
correctly when combined with semi-transparent PNG images. Thus it is necessary
to set opacity of such elements to 1.0 in order for alpha-transparent PNG images
to appear correctly.

View File

@@ -0,0 +1,34 @@
Current for 6.x-2.0-alpha3
The OpenLayers module aims to add minimal abstraction in Javascript to what is
already provided by the [OpenLayers](http://openlayers.org/) Javascript library.
However, it does create certain structures that may not be immediately obvious.
# Data Storage
The module stores all settings initially under Drupal.settings.openlayers. It
does this in a slightly modified way if your server supports native JSON writing
- this basically means that, instead of using Drupal to encode the settings
array, it uses a PHP extension (written in C). This greatly increases
performance for displaying many points on maps.
# Keeping Track of Maps
The OpenLayers map object, which contains pointers to all layers, etc., is
stored with the [jQuery data() method](http://api.jquery.com/jQuery.data/),
which provides the phenomenal convenience of storing arbitrary data within the
DOM itself. This means that the map object is attached to the openlayers-map-0,
or so on, div element in your page. So, to access it, one could use a line like
$('#openlayers-map-0').data('openlayers')
In FireBug, Safari, or Chrome.
Note that the 2.x branch strives to not duplicate map information: it exists in
the Drupal settings array and then is transformed into a map object, but after
that point, the canonical location for data about maps is in the map object.
This is for purposes of both flexibility, since the map object lets developers
access objects by better getter methods, and for the purpose of keeping
OpenLayers behaviors and layer initialization code less tied to Drupal than
before.

View File

@@ -0,0 +1,29 @@
Current for 2.x
# KML
Many users find it necessary to include KML files on their websites, and often
KML files are located on remote servers; especially dynamic KML. However, the
core of the [XMLHttpRequest](http://en.wikipedia.org/wiki/XMLHttpRequest)
object, the Javascript convenience that allows AJAX to happen, prevents requests
across domains.
This means that a site
http://www.hello.com/
cannot load KML from
http://world.com/
Without a special workaround.
# Proxy Host
For this, there is a special setting in every map called "Proxy Host." It is
in the 'General information' tab, at the bottom of the page. You can use any of
a number of [PHP
proxies](http://www.google.com/search?sourceid=chrome&ie=UTF-8&q=php+proxy) for
this purpose, or you can use the [proxy
module](http://drupal.org/project/proxy), which integrates with Drupal.

View File

@@ -0,0 +1,78 @@
Current for 6.x-2.x
# Layer Types
Layer types are one of the fundamental building blocks of the OpenLayers module.
They are factories for layers themselves - a layer type is like a wrapper around
an OpenLayers (javascript) object which lets you configure settings through the
UI and also encapsulate other tasks that layers need to do, like loading
information.
## Structure
Typically a layer type is a class that extends `openlayers_layer_type`, although
it can extend another layer type class if necessary. All that's really needed is
that it implements the right methods. Which are...
* `render`: The `render(&$map)` function is called on each layer type when a map
is rendered. Since the map array is passed by reference, this function can
modify it in any way it wishes. However, typically render functions just
include layer javascript and then return their options array.
* `settings_form`: The settings form of a layer type is different from the
options form in two very important ways. The first, practical reason for their
separation is that layer type settings are settings that you'll want to set
for an entire website, like a Google Maps API key or javascript location. So,
these settings are not attached to individual layers. The other, technical
difference, is that, while layer *options* end up in the data array, which is
serialized and exported, etc., layer *settings* are saved as Drupal variables,
so that they can optionally intercepted by modules like Spaces, which allow
users to customize domain-specific settings (like API keys) by space.
* `options_form`: The options form of the layer is what the user sees when they
land on the layer add form. The results of this form submission are
automatically saved as the contents of the layer's 'data' property, which is
then sent to javascript and, depending on layer type, pushed into the
Javascript layer constructor. This means that exported layers can have more
properties than the OpenLayers Drupal Module knows about, and they will be
seamlessly pushed into Javascript and serve their function in Javascript-land.
* `options_init`: The options_init function defines the default options of any
given layer. This is used for options that will not be set in the options
form, but would be awkward to code as hidden fields. If your layer type class
has the correct __construct implementation (like those in the OpenLayers
Module), then these settings will be added whenever you initialize a layer
## Vector
* Map objects can contain an attribute called 'vector', defined in options_init():
function options_init() {
return array(
'vector' => TRUE,
);
}
* This is an important attribute - it designates layers that are derived from
the OpenLayers Vector layer class [1]. Unlike tile or image-based layers -
like OpenStreetMap or Google Maps, these will typically be from data files
like KML, GML, or OpenLayers Data layers. And also unlike image-based maps,
they don't need to be in the projection of the rest of the map, since they are
easily reprojected by the OpenLayers Javascript library. So, it is possible to
have a WMS layer in the EPSG:4326 projection with KML data on it, and also put
that KML data on a Google Maps map in the EPSG:900913 projection, and the data
will be displayed on both. Thus setting the vector attribute allows certain
layers to be added to maps of any projection.
[^1]: http://dev.openlayers.org/releases/OpenLayers-2.9.1/doc/apidocs/files/OpenLayers/Layer/Vector-js.html
## Javascript
OpenLayers Layer Types typically have a bit of Javascript accompanying them
which follows a certain form. It will provide a method in the
`Drupal.openlayers.layer` namespace, like `Drupal.openlayers.layer.cloudmade`,
takes arguments `(name, map, options)`, and will return a fully initialized map
object. These are basically factories for OpenLayers Layer Type objects, and are
usually under 50 lines long. Note that if you plan on making a distinctly
different layer type, it's best not to do it within this javascript file, but to
create a new OpenLayers Layer Type (in javascript) - see the MapBox module for
an example of a new OpenLayers Layer Type (`OpenLayers.Layer.MapBox`), which is
entirely independent of the Drupal module.

View File

@@ -0,0 +1,11 @@
Current for 6.x-2.x
# Filtering map views
The best way to handle filtering the points on maps is to use normal OpenLayers
exposed filters, whose input is passed through to the underlying Data
view. If there are no other views on the same page, like tabular listings,
that can 'own' and display the exposed filters, it is recommended to make the
filters blocks via the views interface and make sure that they appear on
the specified page with the block system or context module.

View File

@@ -0,0 +1,65 @@
Raw layers are an addition to OpenLayers post-alpha7 which allow users to
manually add points to a layer type. In comparison to the layer_type
method of pulling in custom data, this allows you to 'push' data into the
layer data array itself. In any case where reusability is a priority,
layer_types should be utilized (as documented in LAYER_TYPES.txt). However,
this is a quick method for success that may be more accessible to more
developers.
A brief, example-only implementation of an arbitrary layer is below.
/**
* Implementation of hook_ctools_plugin_api().
* Required to provide layers
*/
function geolocator_ctools_plugin_api($module, $api) {
if ($module == "openlayers") {
switch ($api) {
case 'openlayers_layers':
return array('version' => 1);
}
}
}
/**
* One can have the 'features' => element point to a function
* or be built on the fly within the _layers method. However,
* close attention must be paid to ctools caching in order to
* insure that dynamic data stays dynamic
*/
function geolocator_openlayers_layers() {
$layers = array();
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'afghanistan';
$layer->title = 'One Point on Afghanistan';
$layer->description = '';
$layer->data = array(
'layer_type' => 'openlayers_layer_type_raw',
'projection' => array('900913'),
'features' => array(
array(
"wkt"=> "POINT(65 33)",
"projection"=> "4326",
"attributes"=>
array(
"name"=> "Afghanistan",
"description"=> "248"
)
)
)
);
$layers[$layer->name] = $layer;
return $layers;
}
/**
* map_preprocess_alter allows one to add a new layer to a map
* before layers are rendered and data is pulled from them.
*/
function geolocator_openlayers_map_preprocess_alter(&$map) {
$map['layers']['afghanistan'] = 'afghanistan';
$map['layer_activated']['afghanistan'] = 'afghanistan';
$map['layer_switcher']['afghanistan'] = 'afghanistan';
}

View File

@@ -0,0 +1,13 @@
Documentation for upgrading is managed on Drupal.org.
For Upgrading from 6.x-2.x -> 7.x-2.x:
==========================================
* http://drupal.org/node/1136810
For Upgrading from 6.x-1.x -> 6.x-2.x:
==========================================
* http://drupal.org/node/714366

View File

@@ -0,0 +1,283 @@
<?php
/**
* @file
* Hooks provided by the OpenLayers suite of modules. This file allows
* hooks to be documented automatically with Doxygen, like on api.drupal.org.
*
* @ingroup openlayers
*/
/**
* OpenLayers Map Preprocess Alter
*
* Map array alter. Fired before processing the array, and
* before checking for errors. The whole array is passed
* along and will allow you to alter it in any way. This
* is a good place to alter the map, if the other hooks
* do not provide the functionality you need.
*
* @param $map
* Map array
*/
function hook_openlayers_map_preprocess_alter(&$map = array()) {
// Do something to the $map
}
/**
* OpenLayers Map Alter
*
* Post-processing Map array alter. Fired after processing the array, and
* before checking for errors. The whole array is passed
* along and will allow you to alter it in any way. Adding behaviors,
* pre-defined layers here will not work. This is good for minor tweaks
* after the map has been processed.
*
* @param $map
* Map array
*/
function hook_openlayers_map_alter(&$map = array()) {
// Do something to the $map
}
/**
* OpenLayers Layer Types
*
* Provides information on layer types. This is a CTools plugin. Please
* see LAYER_TYPES.txt in the module for more information.
*
* @return
* Return a nested associative array with the top level
* being a unique string identifier key which corresponds to the
* layers' types. The next level being an array of key/value
* pairs:
* - "description":
* - "layer_type":
*/
function hook_openlayers_layer_types() {
// Take from openlayers.layer_types.inc
return array(
'openlayers_layer_type_google' => array(
'title' => t('Google'),
'description' => t('Google Maps API Map'),
'layer_type' => array(
'path' => drupal_get_path('module', 'openlayers') .'/includes/layer_types',
'file' => 'google.inc',
'class' => 'openlayers_layer_type_google',
'parent' => 'openlayers_layer_type',
),
),
);
}
/**
* CTools Registration Hook
*
* IMPORTANT:
*
* In order to support styles, maps, and layers in an external module,
* one must notify the CTools module that that module provides implementations
* of the hooks for styles, maps, and/or layers.
*
* This function is just an example implementation of
* hook_ctools_plugin_api() and should be alter according to
* your module's name.
*
* @param $module
* Name of a module that supports CTools exportables.
* @param $api
* Name of the kind of exportable supported.
* @return
* If $module is 'openlayers', and $api is a type of exportable that
* your module provides, and you are using Openlayers 2.x, then
* return array with the following values:
* - version => 1
*/
function openlayers_example_ctools_plugin_api($module, $api) {
if ($module == "openlayers") {
switch ($api) {
case 'openlayers_maps':
return array('version' => 1);
case 'openlayers_layers':
return array('version' => 1);
case 'openlayers_styles':
return array('version' => 1);
}
}
}
/**
* OpenLayers Layers
*
* This hook tells OpenLayers about the available layers
* that can be used by name in maps.
*
* Ensure that you are telling CTools about this as well.
* @see openlayers_example_ctools_plugin_api().
*
* Please note, that to support translation for exportable
* code for potx extraction, you should include separate code
* of translatable string.
*
* @return
* Return an associative array with index being a unique string
* identifier, and simple objects with the following properties:
* - "api_version":
* - "name":
* - "title":
* - "data":
*/
function hook_openlayers_layers() {
// Taken from openlayers.layers.inc
$layers = array();
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'google_satellite';
$layer->title = 'Google Maps Satellite';
$layer->description = 'Google Maps Satellite Imagery.';
$layer->data = array(
'isBaseLayer' => TRUE,
'type' => 'satellite',
'projection' => array('900913'),
'layer_type' => 'openlayers_layer_type_google',
);
$layers[$layer->name] = $layer;
return $layers;
// Extra code to support potx extractors
$potx = array(
t('Google Maps Satellite'),
t('Google Maps Satellite Imagery.'),
);
}
/**
* OpenLayers Behaviors
*
* This hook tells OpenLayers about the available behaviors
* that can be used in maps.
*
* Ensure that you are telling CTools about this as well.
* @see openlayers_example_ctools_plugin_api().
*
* @return
* Return a nested associative array with the top level
* being a unique string identifier, and the nested array
* containing the following key/pairs:
* - "title":
* - "description":
* - "file":
* - "type":
* - "behavior":
*/
function hook_openlayers_behaviors() {
// Taken from openlayers.behaviors.inc
return array(
'openlayers_behavior_attribution' => array(
'title' => t('Attribution'),
'description' => t('Allows layers to provide attribution to the map if it exists.'),
'type' => 'layer',
'path' => drupal_get_path('module', 'openlayers') .'/includes/behaviors',
'file' => 'openlayers_behavior_attribution.inc',
'behavior' => array(
'class' => 'openlayers_behavior_attribution',
'parent' => 'openlayers_behavior',
),
),
);
}
/**
* OpenLayers Styles
*
* This hook tells OpenLayers about the available styles
* that can be used in maps.
*
* Ensure that you are telling CTools about this as well.
* @see openlayers_example_ctools_plugin_api().
*
* @return
* Return an associative array with index being a unique string
* identifier, and simple objects with the following properties:
* - "api_version":
* - "name":
* - "title":
* - "data":
*/
function hook_openlayers_styles() {
// Taken from openlayers.styles.inc
$styles = array();
$style = new stdClass();
$style->api_version = 1;
$style->name = 'default';
$style->title = t('Default style');
$style->description = t('Basic default style.');
$style->data = array(
'pointRadius' => '5',
'fillColor' => '#FFCC66',
'strokeColor' => '#FF9933',
'strokeWidth' => '4',
'fillOpacity' => '0.5'
);
$styles[$style->name] = $style;
return $styles;
}
/**
* OpenLayers maps
*
* Define map objects.
*
* @return
* Return an associative array with index being a unique string
* identifier, and simple objects with the following properties:
* - "api_version":
* - "name":
* - "title":
* - "data":
*/
function hook_openlayers_maps() {
// Taken from openlayers.maps.inc
$default = new stdClass();
$default->api_version = 1;
$default->name = 'default';
$default->title = t('Default Map');
$default->description = t('This is the default map that comes with the OpenLayers module.');
$default->data = array(
'projection' => '900913',
'width' => 'auto',
'default_layer' => 'osm_mapnik',
'height' => '400px',
'center' => array(
'initial' => array(
'centerpoint' => '0,0',
'zoom' => '2'
)
),
'options' => array(
'displayProjection' => '4326',
'maxExtent' => openlayers_get_extent('4326'),
),
'behaviors' => array(
'openlayers_behavior_panzoombar' => array(),
'openlayers_behavior_layerswitcher' => array(),
'openlayers_behavior_attribution' => array(),
'openlayers_behavior_keyboarddefaults' => array(),
'openlayers_behavior_navigation' => array(),
),
'layers' => array(
'osm_mapnik' => 'osm_mapnik',
)
);
return array('default' => $default);
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* OpenLayers Box
*/
class openlayers_simple extends boxes_box {
/**
* Implementation of boxes_content::options_defaults().
*/
public function options_defaults() {
return array(
'map' => ''
);
}
/**
* Implementation of boxes_content::options_form().
*/
public function options_form(&$form_state) {
$form = array();
// Map objects
$form['map'] = array(
'#type' => 'select',
'#title' => t('Map'),
'#description' => t('This is map that will be used to render the view.'),
'#options' => openlayers_map_options(),
'#default_value' => $this->options['map'] ?
$this->options['map'] : variable_get('openlayers_default_map', 'default'),
);
return $form;
}
/**
* Implementation of boxes_content::options_form().
*/
public function render() {
$title = isset($this->title) ? check_plain($this->title) : NULL;
$map = openlayers_map_load($this->options['map']);
return array(
'delta' => $this->delta, // Crucial.
'title' => $title,
'subject' => $title,
'content' => openlayers_render_map($map, $map->name)
);
}
}

View File

@@ -0,0 +1,67 @@
<?php
/**
* @file
* OpenLayers Map Content Type. Displays a Map.
*/
/**
* Plugins are described by creating a $plugin array which will be used
* by the system that includes this file.
*/
$plugin = array(
// And this is just the administrative title.
// All our callbacks are named according to the standard pattern and can be deduced.
'title' => t('Openlayers Map'),
'content type' => 'openlayers_openlayers_map_content_type_content_types',
'render callback' => 'openlayers_map_content_type_render',
);
/**
* Return all content types available.
*/
function openlayers_openlayers_map_content_type_content_types($plugin) {
$types = array();
$maps = openlayers_maps();
foreach ($maps as $map) {
$types[$map->name] = array (
'map' => $map->name,
'title' => $map->title,
'description' => $map->description,
'category' => t('OpenLayers Maps'),
);
}
return $types;
}
/**
* Run-time rendering of the body of the block.
*
* @param $subtype
* @param $conf
* Configuration as done at admin time.
* @param $args
* @param $context
* Context - in this case we don't have any.
*
* @return
* An object with at least title and content members.
*/
function openlayers_map_content_type_render($subtype, $conf, $args, $context) {
$map = openlayers_map_load($subtype);
$block = new stdClass();
$block->title = $map->title;
$block->content = openlayers_render_map($map);
return $block;
}
/**
* Empty form so we can have the default override title.
*/
function openlayers_openlayers_map_content_type_edit_form($form, &$form_state) {
// Does nothing!
return $form;
}

View File

@@ -0,0 +1,474 @@
<?php
/**
* @file
*
* OpenLayers default packaged layers
*/
function _openlayers_openlayers_layers() {
global $is_https;
$mapquest_host = $is_https ? '-s.mqcdn.com' : '.mqcdn.com';
$layers = array();
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'google_satellite';
$layer->title = 'Google Maps Satellite';
$layer->description = 'Google Maps Satellite Imagery.';
$layer->data = array(
'isBaseLayer' => TRUE,
'type' => 'satellite',
'projection' => array('900913'),
'layer_type' => 'openlayers_layer_type_google',
);
$layers[$layer->name] = $layer;
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'google_hybrid';
$layer->title = 'Google Maps Hybrid';
$layer->description = 'Google Maps with roads and terrain.';
$layer->data = array(
'isBaseLayer' => TRUE,
'type' => 'hybrid',
'projection' => array('900913'),
'layer_type' => 'openlayers_layer_type_google',
);
$layers[$layer->name] = $layer;
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'google_normal';
$layer->title = 'Google Maps Normal';
$layer->description = 'Standard Google Maps Roads';
$layer->data = array(
'isBaseLayer' => TRUE,
'type' => 'normal',
'projection' => array('900913'),
'layer_type' => 'openlayers_layer_type_google',
);
$layers[$layer->name] = $layer;
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'google_physical';
$layer->title = 'Google Maps Physical';
$layer->description = 'Google Maps Hillshades';
$layer->data = array(
'isBaseLayer' => TRUE,
'type' => 'physical',
'projection' => array('900913'),
'layer_type' => 'openlayers_layer_type_google',
);
$layers[$layer->name] = $layer;
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'mapquest_osm';
$layer->title = 'MapQuest OSM';
$layer->description = 'MapQuests rendering of OpenStreetMap.';
$layer->data = array(
'isBaseLayer' => TRUE,
'attribution' => t('&copy;<a href="@ccbysa">CCBYSA</a> '.
'<a href="@openstreetmap">&copy; OpenStreetMap contributors</a>',
array(
'@openstreetmap' => 'http://www.openstreetmap.org/copyright',
'@ccbysa' => 'http://creativecommons.org/licenses/by-sa/2.0/',
)
) . '. '. t('Tiles Courtesy of <a href="http://www.mapquest.com/">MapQuest</a>.'),
'projection' => array('900913'),
'layer_type' => 'openlayers_layer_type_xyz',
'url' => array(
'//otile1' . $mapquest_host . '/tiles/1.0.0/osm/${z}/${x}/${y}.png',
'//otile2' . $mapquest_host . '/tiles/1.0.0/osm/${z}/${x}/${y}.png',
'//otile3' . $mapquest_host . '/tiles/1.0.0/osm/${z}/${x}/${y}.png',
'//otile4' . $mapquest_host . '/tiles/1.0.0/osm/${z}/${x}/${y}.png',
),
'wrapDateLine' => FALSE,
'resolutions' => openlayers_get_resolutions('900913', 0, 19)
);
$layers[$layer->name] = $layer;
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'mapquest_openaerial';
$layer->title = 'MapQuest Open Aerial';
$layer->description = 'MapQuests aerial photo map.';
$layer->data = array(
'isBaseLayer' => TRUE,
'attribution' => t('Portions Courtesy NASA/JPL-Caltech and U.S. Depart. of Agriculture, Farm Service Agency.')
. ' '. t('Tiles Courtesy of <a href="http://www.mapquest.com/">MapQuest</a>.'),
'projection' => array('900913'),
'layer_type' => 'openlayers_layer_type_xyz',
'url' => array(
'//oatile1' . $mapquest_host . '/naip/${z}/${x}/${y}.png',
'//oatile2' . $mapquest_host . '/naip/${z}/${x}/${y}.png',
'//oatile3' . $mapquest_host . '/naip/${z}/${x}/${y}.png',
'//oatile4' . $mapquest_host . '/naip/${z}/${x}/${y}.png',
),
'wrapDateLine' => TRUE,
);
$layers[$layer->name] = $layer;
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'yahoo_satellite';
$layer->title = 'Yahoo Maps Satellite';
$layer->description = 'Yahoo satellite imagery tiles.';
$layer->data = array(
'isBaseLayer' => TRUE,
'type' => 'satellite',
'projection' => array('900913'),
'layer_type' => 'openlayers_layer_type_yahoo',
);
$layers[$layer->name] = $layer;
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'yahoo_street';
$layer->title = 'Yahoo Maps Street';
$layer->description = 'Yahoo streets tiles.';
$layer->data = array(
'isBaseLayer' => TRUE,
'type' => 'street',
'projection' => array('900913'),
'layer_type' => 'openlayers_layer_type_yahoo',
);
$layers[$layer->name] = $layer;
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'yahoo_hybrid';
$layer->title = 'Yahoo Maps Hybrid';
$layer->description = 'Yahoo hybrid of streets and satellite tiles.';
$layer->data = array(
'isBaseLayer' => TRUE,
'type' => 'hybrid',
'projection' => array('900913'),
'layer_type' => 'openlayers_layer_type_yahoo',
);
$layers[$layer->name] = $layer;
// Bing Road
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'bing_road';
$layer->title = 'Bing Road';
$layer->description = 'Bing Road tiles.';
$layer->data = array(
'isBaseLayer' => TRUE,
'type' => 'Road',
'projection' => array('900913'),
'layer_type' => 'openlayers_layer_type_bing',
);
$layers[$layer->name] = $layer;
// Bing Aerial
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'bing_aerial';
$layer->title = 'Bing Aerial';
$layer->description = 'Bing Aerial tiles.';
$layer->data = array(
'isBaseLayer' => TRUE,
'type' => 'Aerial',
'projection' => array('900913'),
'layer_type' => 'openlayers_layer_type_bing',
);
$layers[$layer->name] = $layer;
// Bing Hybrid
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'bing_hybrid';
$layer->title = 'Bing Hybrid';
$layer->description = 'Bing Hybrid tiles.';
$layer->data = array(
'isBaseLayer' => TRUE,
'type' => 'AerialWithLabels',
'projection' => array('900913'),
'layer_type' => 'openlayers_layer_type_bing',
);
$layers[$layer->name] = $layer;
// OpenStreetMap Mapnik
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'osm_mapnik';
$layer->title = 'OSM Mapnik';
$layer->description = 'The main OpenStreetMap map';
$layer->data = array(
'isBaseLayer' => TRUE,
'attribution' => t('&copy;<a href="@ccbysa">CCBYSA</a> '.
'<a href="@openstreetmap">&copy; OpenStreetMap contributors</a>',
array(
'@openstreetmap' => 'http://www.openstreetmap.org/copyright',
'@ccbysa' => 'http://creativecommons.org/licenses/by-sa/2.0/',
)
),
'projection' => array('900913'),
'layer_type' => 'openlayers_layer_type_xyz',
'url' => '//tile.openstreetmap.org/${z}/${x}/${y}.png',
'wrapDateLine' => TRUE,
);
$layers[$layer->name] = $layer;
// OpenStreetMap Cycling Map
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'osm_cycle';
$layer->title = 'OSM Cycling Map';
$layer->description = 'OpenStreetMap with highlighted bike lanes';
$layer->data = array(
'isBaseLayer' => TRUE,
'attribution' => t('&copy;<a href="@ccbysa">CCBYSA</a> '.
'<a href="@openstreetmap">&copy; OpenStreetMap contributors</a>',
array(
'@openstreetmap' => 'http://www.openstreetmap.org/copyright',
'@ccbysa' => 'http://creativecommons.org/licenses/by-sa/2.0/',
)
),
'projection' => array('900913'),
'layer_type' => 'openlayers_layer_type_xyz',
'url' => '//a.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png',
'wrapDateLine' => TRUE,
);
$layers[$layer->name] = $layer;
// OpenStreetMap 426 hybrid overlay
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'osm_4326_hybrid';
$layer->title = 'OSM Overlay';
$layer->description = 'Semi-transparent hybrid overlay. Projected into
WSG84 for use on non spherical-mercator maps.';
$layer->data = array(
'isBaseLayer' => FALSE,
'attribution' => t('&copy;<a href="@ccbysa">CCBYSA</a> '.
'<a href="@openstreetmap">&copy; OpenStreetMap contributors</a>',
array(
'@openstreetmap' => 'http://www.openstreetmap.org/copyright',
'@ccbysa' => 'http://creativecommons.org/licenses/by-sa/2.0/',
)
),
'projection' => array('4326'),
'layer_type' => 'openlayers_layer_type_wms',
'url' => 'http://oam.hypercube.telascience.org/tiles',
'params' => array(
'isBaseLayer' => FALSE,
'layers' => 'osm-4326-hybrid',
),
'options' => array(
'buffer' => 1,
),
);
$layers[$layer->name] = $layer;
/* Example with KML layer */
$layer = new stdClass();
$layer->disabled = FALSE; /* Edit this to true to make a default openlayers_layers disabled initially */
$layer->api_version = 1;
$layer->name = 'openlayers_kml_example';
$layer->title = 'KML Example Layer';
$layer->description = 'A simple example of KML Layer Type.';
$layer->data = array(
'method' => 'raw',
'raw' => '<?xml version="1.0" encoding="UTF-8"?><kml xmlns="http://www.opengis.net/kml/2.2"><Placemark><name>Simple placemark</name><description>Attached to the ground. Intelligently places itself at the height of the underlying terrain.</description><Point><coordinates>-122.0822035425683,37.42228990140251,0</coordinates></Point></Placemark></kml>',
'formatOptions' => array(
'extractStyles' => TRUE,
'extractTracks' => FALSE,
'extractAttributes' => TRUE,
),
'projection' => array(
0 => '4326',
),
'isBaseLayer' => 0,
'layer_type' => 'openlayers_layer_type_kml',
'layer_handler' => 'kml',
'vector' => TRUE,
);
$layers[$layer->name] = $layer;
// MetaCarts base map
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'wms_default';
$layer->title = 'Default OpenLayers WMS';
$layer->description = 'MetaCarta basemap of province and water boundaries';
$layer->data = array(
'projection' => array('4326'),
'isBaseLayer' => TRUE,
'layer_type' => 'openlayers_layer_type_wms',
'base_url' => '//labs.metacarta.com/wms-c/Basic.py',
'params' => array(
'isBaseLayer' => TRUE,
),
'options' => array(
'layers' => array('basic'),
'maxExtent' => openlayers_get_extent('4326'),
),
);
$layers[$layer->name] = $layer;
// GeoJSON example with direct data
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = 'openlayers_geojson_picture_this';
$layer->title = t('Example GeoJSON, "Picture This"');
$layer->description = t('Example that puts GeoJSON directly in layer without Views.');
$layer->data = array(
'resolutions' => openlayers_get_resolutions('900913'),
'serverResolutions' => openlayers_get_resolutions('4326'),
'layer_type' => 'openlayers_layer_type_geojson',
'layer_handler' => 'geojson',
'projection' => array('4326'),
'isBaseLayer' => FALSE,
'vector' => TRUE,
'geojson_data' => '
{
"type": "Feature",
"properties": {
"name": "' . t('Picture This') . '",
"description": "' . t('Outside of the North Carolina Museum of Art.') . '"
},
"geometry": {
"type": "Point",
"coordinates": [
-78.702798,
35.809411
]
},
"crs": {
"type": "name",
"properties": {
"name": "urn:ogc:def:crs:OGC:1.3:CRS84"
}
}
}
',
);
$layers[$layer->name] = $layer;
$info = _mapbox_layers_info();
$resolutions = array_combine(range(0, 21), openlayers_get_resolutions('900913'));
foreach ($info as $key => $item) {
$openlayers_layers = new stdClass;
$openlayers_layers->disabled = FALSE; /* Edit this to true to make a default openlayers_layers disabled initially */
$openlayers_layers->api_version = 1;
$openlayers_layers->name = $key;
$openlayers_layers->title = $item['name'];
$openlayers_layers->description = $item['description'];
$openlayers_layers->data = array(
'url' => array(
0 => 'http://a.tiles.mapbox.com/',
1 => 'http://b.tiles.mapbox.com/',
2 => 'http://c.tiles.mapbox.com/',
3 => 'http://d.tiles.mapbox.com/',
),
'layername' => $item['layername'],
'layer_type' => 'openlayers_layer_type_mapbox',
'osm' => FALSE,
'isBaseLayer' => TRUE,
'type' => 'png',
'resolutions' => array_intersect_key($resolutions, array_flip(range($item['minzoom'], $item['maxzoom']))),
'projection' => array('900913'),
);
$layers[$key] = $openlayers_layers;
}
return $layers;
}
/**
* This function is for the po editor to be able to find these strings,
* since in the codebase they are not in t()'s, because they are later
* run through t() in the layer loader function
*/
function _openlayers_openlayers_layers_i18n() {
$translatable_strings = array(
// titles
t('Google Maps Satellite'),
t('Google Maps Hybrid'),
t('Google Maps Normal'),
t('Google Maps Physical'),
t('Bing Road'),
t('Bing Aerial'),
t('Bing Hybrid'),
t('Yahoo Maps Street'),
t('Yahoo Maps Hybrid'),
t('Yahoo Maps Satellite'),
t('OSM Mapnik'),
t('OSM Cycling Map'),
t('OSM Overlay'),
t('Default OpenLayers WMS'),
// descriptions
t('Alternative, community-rendered OpenStreetMap'),
t('Google Maps Hillshades'),
t('Google Maps Satellite Imagery.'),
t('Google Maps with roads and terrain.'),
t('MetaCarta basemap of province and water boundaries'),
t('OpenStreetMap with highlighted bike lanes'),
t('Semi-transparent hybrid overlay. Projected into
WSG84 for use on non spherical-mercator maps.'),
t('Standard Google Maps Roads'),
t('The main OpenStreetMap map'),
t('Bing Road tiles.'),
t('Bing Aerial tiles.'),
t('Bing Hybrid tiles.'),
t('Yahoo hybrid of streets and satellite tiles.'),
t('Yahoo satellite imagery tiles.'),
t('Yahoo streets tiles.'),
t('MapQuests rendering of OpenStreetMap.'),
t('MapQuests aerial photo map.'),
);
}
function _mapbox_layers_info() {
$info = array();
$info['mapbox_streets'] = array(
'name'=> t('MapBox Streets'),
'description' => t('MapBox Streets'),
'layername' => 'mapbox-streets',
'minzoom' => 0,
'maxzoom' => 16
);
$info['mapbox_world_bright'] = array(
'name' => t('MapBox World Bright'),
'description' => t('MapBox World Bright'),
'layername' => 'world-bright',
'minzoom' => 0,
'maxzoom' => 11,
);
$info['mapbox_world_dark'] = array(
'name' => t('MapBox World Dark'),
'description' => t('MapBox World Dark'),
'layername' => 'world-dark',
'minzoom' => 0,
'maxzoom' => 11,
);
$info['mapbox_world_light'] = array(
'name' => t('MapBox World Light'),
'description' => t('MapBox World Light'),
'layername' => 'world-light',
'minzoom' => 0,
'maxzoom' => 11,
);
$info['mapbox_world_print'] = array(
'name' => t('MapBox World Print'),
'description' => t('MapBox World Print'),
'layername' => 'world-print',
'minzoom' => 0,
'maxzoom' => 9,
);
$info['mapbox_world_black'] = array(
'name' => t('MapBox World Black'),
'description' => t('MapBox World Black'),
'layername' => 'world-black',
'minzoom' => 0,
'maxzoom' => 11,
);
return $info;
}

View File

@@ -0,0 +1,426 @@
<?php
/**
* @file
* This file contains map implementations
*
* @ingroup openlayers
*/
/**
* Map definitions
*
* Internal callback for openlayers map implementation.
*
* @return
* Array of maps
*/
function _openlayers_openlayers_maps() {
$items = array();
// Default map with MapQuest
$default = new stdClass();
$default->api_version = 1;
$default->name = 'default';
$default->title = t('Default Map');
$default->description = t('This is the default map that will be the basis for all maps, unless you have changed the !settings. This is also a good example of a basic map.', array('!settings' => l(t('OpenLayers main settings'), 'admin/structure/openlayers')));
$default->data = array(
'projection' => '900913',
'width' => 'auto',
'height' => '400px',
'default_layer' => 'mapquest_osm',
'center' => array(
'initial' => array(
'centerpoint' => '0,0',
'zoom' => '0'
)
),
'image_path' => drupal_get_path('module', 'openlayers') . '/themes/default_dark/img/',
'css_path' => drupal_get_path('module', 'openlayers') . '/themes/default_dark/style.css',
'displayProjection' => '4326',
'maxExtent' => openlayers_get_extent('4326'),
'behaviors' => array(
'openlayers_behavior_panzoombar' => array(),
'openlayers_behavior_layerswitcher' => array(),
'openlayers_behavior_attribution' => array(),
'openlayers_behavior_keyboarddefaults' => array(),
'openlayers_behavior_navigation' => array(),
),
'layers' => array(
'mapquest_osm' => 'mapquest_osm',
'mapquest_openaerial' => 'mapquest_openaerial',
),
'styles' => array(
'default' => 'default',
'select' => 'default_select',
'temporary' => 'default',
),
);
$items['default'] = $default;
// An example Google map
$openlayers_maps = new stdClass;
$openlayers_maps->disabled = FALSE;
$openlayers_maps->api_version = 1;
$openlayers_maps->name = 'example_google';
$openlayers_maps->title = t('Example Google Map');
$openlayers_maps->description = t('An example map using Google Maps API layers.');
$openlayers_maps->data = array(
'width' => 'auto',
'height' => '400px',
'image_path' => drupal_get_path('module', 'openlayers') . '/themes/default_dark/img/',
'css_path' => drupal_get_path('module', 'openlayers') . '/themes/default_dark/style.css',
'center' => array(
'initial' => array(
'centerpoint' => '0, 0',
'zoom' => '2',
),
'restrict' => array(
'restrictextent' => 0,
'restrictedExtent' => '',
),
),
'behaviors' => array(
'openlayers_behavior_attribution' => array(
'seperator' => '',
),
'openlayers_behavior_keyboarddefaults' => array(),
'openlayers_behavior_layerswitcher' => array(
'ascending' => 1,
'roundedCorner' => 1,
'roundedCornerColor' => '#222222',
),
'openlayers_behavior_navigation' => array(
'zoomWheelEnabled' => 1,
'zoomBoxEnabled' => 1,
'documentDrag' => 0,
),
'openlayers_behavior_permalink' => array(
'anchor' => 1,
),
'openlayers_behavior_zoompanel' => array(),
),
'default_layer' => 'google_physical',
'layers' => array(
'google_satellite' => 'google_satellite',
'google_hybrid' => 'google_hybrid',
'google_normal' => 'google_normal',
'google_physical' => 'google_physical',
),
'projection' => '900913',
'displayProjection' => '4326',
'styles' => array(
'default' => 'default',
'select' => 'default_select',
'temporary' => 'default',
),
);
$items['default_google'] = $openlayers_maps;
// Example map with MapQuest and GeoJSON
$openlayers_maps = new stdClass();
$openlayers_maps->disabled = FALSE; /* Edit this to true to make a default openlayers_maps disabled initially */
$openlayers_maps->api_version = 1;
$openlayers_maps->name = 'example_geojson';
$openlayers_maps->title = 'Example GeoJSON Map';
$openlayers_maps->description = 'A simple map with a custom GeoJSON layer with direct data. Also an example of zooming into a layer.';
$openlayers_maps->data = array(
'width' => 'auto',
'height' => '400px',
'image_path' => drupal_get_path('module', 'openlayers') . '/themes/default_dark/img/',
'css_path' => drupal_get_path('module', 'openlayers') . '/themes/default_dark/style.css',
'proxy_host' => '',
'hide_empty_map' => 0,
'center' => array(
'initial' => array(
'centerpoint' => '0,0',
'zoom' => '2',
),
'restrict' => array(
'restrictextent' => 0,
'restrictedExtent' => '',
),
),
'behaviors' => array(
'openlayers_behavior_keyboarddefaults' => array(),
'openlayers_behavior_layerswitcher' => array(
'ascending' => 1,
'sortBaseLayer' => '0',
'roundedCorner' => 1,
'roundedCornerColor' => '#222222',
'maximizeDefault' => 0,
),
'openlayers_behavior_navigation' => array(
'zoomWheelEnabled' => 1,
'zoomBoxEnabled' => 1,
'documentDrag' => 0,
),
'openlayers_behavior_panzoombar' => array(
'zoomWorldIcon' => 0,
'panIcons' => 1,
),
'openlayers_behavior_popup' => array(
'layers' => array(
'openlayers_geojson_picture_this' => 'openlayers_geojson_picture_this',
),
'panMapIfOutOfView' => 0,
'keepInMap' => 1,
),
'openlayers_behavior_zoomtolayer' => array(
'zoomtolayer' => array(
'openlayers_geojson_picture_this' => 'openlayers_geojson_picture_this',
),
'point_zoom_level' => '5',
'zoomtolayer_scale' => '1',
),
),
'default_layer' => 'mapquest_openaerial',
'layers' => array(
'mapquest_osm' => 'mapquest_osm',
'mapquest_openaerial' => 'mapquest_openaerial',
'openlayers_geojson_picture_this' => 'openlayers_geojson_picture_this',
),
'layer_activated' => array(
'openlayers_geojson_picture_this' => 'openlayers_geojson_picture_this',
),
'projection' => '900913',
'displayProjection' => '4326',
'styles' => array(
'default' => 'default',
'select' => 'default_select',
'temporary' => 'default',
),
);
$items['example_geojson'] = $openlayers_maps;
// Example map with MapQuest and GeoJSON
$openlayers_maps = new stdClass();
$openlayers_maps->disabled = FALSE; /* Edit this to true to make a default openlayers_maps disabled initially */
$openlayers_maps->api_version = 1;
$openlayers_maps->name = 'example_kml';
$openlayers_maps->title = 'Example KML Map';
$openlayers_maps->description = 'A simple map with a KML layer.';
$openlayers_maps->data = array(
'width' => 'auto',
'height' => '400px',
'image_path' => drupal_get_path('module', 'openlayers') . '/themes/default_dark/img/',
'css_path' => drupal_get_path('module', 'openlayers') . '/themes/default_dark/style.css',
'proxy_host' => '',
'hide_empty_map' => 0,
'center' => array(
'initial' => array(
'centerpoint' => '-122.0822035425683, 37.42228990140251',
'zoom' => '6',
),
'restrict' => array(
'restrictextent' => 0,
'restrictedExtent' => '',
),
),
'behaviors' => array(
'openlayers_behavior_mouseposition' => array(),
'openlayers_behavior_keyboarddefaults' => array(),
'openlayers_behavior_layerswitcher' => array(
'ascending' => 1,
'sortBaseLayer' => '0',
'roundedCorner' => 1,
'roundedCornerColor' => '#222222',
'maximizeDefault' => 0,
),
'openlayers_behavior_navigation' => array(
'zoomWheelEnabled' => 1,
'zoomBoxEnabled' => 1,
'documentDrag' => 0,
),
'openlayers_behavior_panzoombar' => array(
'zoomWorldIcon' => 0,
'panIcons' => 1,
),
'openlayers_behavior_popup' => array(
'layers' => array(
'openlayers_kml_example' => 'openlayers_kml_example',
),
'panMapIfOutOfView' => 0,
'keepInMap' => 1,
),
/*
'openlayers_behavior_zoomtolayer' => array(
'zoomtolayer' => array(
'openlayers_kml_example' => 'openlayers_kml_example',
),
'point_zoom_level' => '5',
'zoomtolayer_scale' => '1',
),
*/
),
'default_layer' => 'mapquest_osm',
'layers' => array(
'mapquest_osm' => 'mapquest_osm',
'openlayers_kml_example' => 'openlayers_kml_example',
),
'layer_activated' => array(
'openlayers_kml_example' => 'openlayers_kml_example',
),
'projection' => '900913',
'displayProjection' => '4326',
'styles' => array(
'default' => 'default',
'select' => 'default_select',
'temporary' => 'default',
),
);
$items['example_kml'] = $openlayers_maps;
// Example Virtual Earth map
$openlayers_maps = new stdClass;
$openlayers_maps->disabled = FALSE;
$openlayers_maps->api_version = 1;
$openlayers_maps->name = 'example_bing';
$openlayers_maps->title = t('Example Microsoft Bing Map');
$openlayers_maps->description = t('This map uses the Microsoft Bing map API.');
$openlayers_maps->data = array(
'width' => 'auto',
'height' => '400px',
'image_path' => drupal_get_path('module', 'openlayers') . '/themes/default_dark/img/',
'css_path' => drupal_get_path('module', 'openlayers') . '/themes/default_dark/style.css',
'proxy_host' => '',
'hide_empty_map' => 0,
'center' => array(
'initial' => array(
'centerpoint' => '-63.281250000007, -20.46819494553',
'zoom' => '2',
),
'restrict' => array(
'restrictextent' => 0,
'restrictedExtent' => '',
),
),
'behaviors' => array(
'openlayers_behavior_attribution' => array(
'seperator' => '',
),
'openlayers_behavior_fullscreen' => array(
'activated' => 0,
),
'openlayers_behavior_keyboarddefaults' => array(),
'openlayers_behavior_layerswitcher' => array(
'ascending' => 1,
'roundedCorner' => 1,
'roundedCornerColor' => '#222222',
),
'openlayers_behavior_navigation' => array(
'zoomWheelEnabled' => 1,
'zoomBoxEnabled' => 1,
'documentDrag' => 0,
),
'openlayers_behavior_panzoom' => array(),
),
'default_layer' => 'bing_road',
'layers' => array(
'bing_road' => 'bing_road',
'bing_hybrid' => 'bing_hybrid',
'bing_aerial' => 'bing_aerial',
),
'projection' => '900913',
'displayProjection' => '4326',
'styles' => array(
'default' => 'default',
'select' => 'default_select',
'temporary' => 'default',
),
);
$items['example_bing'] = $openlayers_maps;
// Example OpenStreetMap
$openlayers_maps = new stdClass;
$openlayers_maps->disabled = FALSE;
$openlayers_maps->api_version = 1;
$openlayers_maps->name = 'example_osm';
$openlayers_maps->title = 'Example OpenStreetMap Map';
$openlayers_maps->description = 'Map to show off the OpenStreetMap layers.';
$openlayers_maps->data = array(
'width' => 'auto',
'height' => '400px',
'image_path' => drupal_get_path('module', 'openlayers') . '/themes/default_dark/img/',
'css_path' => drupal_get_path('module', 'openlayers') . '/themes/default_dark/style.css',
'proxy_host' => '',
'hide_empty_map' => 0,
'center' => array(
'initial' => array(
'centerpoint' => '-0.093009923589588, 51.500381463117',
'zoom' => '12',
),
'restrict' => array(
'restrictextent' => 0,
'restrictedExtent' => '',
),
),
'behaviors' => array(
'openlayers_behavior_attribution' => array(
'seperator' => '',
),
'openlayers_behavior_keyboarddefaults' => array(),
'openlayers_behavior_layerswitcher' => array(
'ascending' => 1,
'roundedCorner' => 1,
'roundedCornerColor' => '#222222',
),
'openlayers_behavior_navigation' => array(
'zoomWheelEnabled' => 1,
'zoomBoxEnabled' => 1,
'documentDrag' => 0,
),
'openlayers_behavior_zoompanel' => array(),
'openlayers_behavior_scaleline' => array(),
),
'default_layer' => 'osm_mapnik',
'layers' => array(
'osm_mapnik' => 'osm_mapnik',
'osm_cycle' => 'osm_cycle',
),
'projection' => '900913',
'displayProjection' => '4326',
'styles' => array(
'default' => 'default',
'select' => 'default_select',
'temporary' => 'default',
),
);
$items["example_osm"] = $openlayers_maps;
// Backwards compatibilty for features presets. Since features
// no longers cares about the preset hooks, we need to manually include
// the preset file that stores the old hooks.
$found_features = FALSE;
if (module_exists('features')) {
$features = features_get_features();
foreach ($features as $feature) {
// Only utilize enabled features and look for presets
if ($feature->status > 0 && !empty($feature->info['features']['openlayers_map_presets'])) {
$found_features = TRUE;
// Include the file we need.
$presets = $feature->info['features']['openlayers_map_presets'];
$module = $feature->name;
$inc = module_load_include('inc', $module, $module . '.openlayers_presets');
}
}
}
// If features found, we have to explicilty reset the implement
// cache. This could be a significant performance hit on a site
// that has a high number of modules installed.
if ($found_features) {
module_implements('openlayers_presets', FALSE, TRUE);
}
// Backwards compatibilty for normal presets
$data = module_invoke_all('openlayers_presets');
if (count($data) > 0) {
$items = $items + $data;
}
return $items;
}

View File

@@ -0,0 +1,228 @@
<?php
/**
* @file
* Processing functions for layers and behaviors
* @ingroup openlayers
*/
/**
* Initialize the layer array into an indexed array of layer objects
*
* @param $layers
* Array of layers to process
* @param $map
* Map array
* @return $layer_data
* Array of initialized layer objects
*/
function _openlayers_layers_process($layers = array(), &$map = array()) {
$layer_data = array();
// Load Layers and assign weights
foreach ($layers as $key => $layer){
if ($layer_object = openlayers_layer_load($layer)) {
$layers[$key] = $layer_object;
if (!empty($map['layer_weight'][$key])) {
$layers[$key]->weight = $map['layer_weight'][$key];
}
else $layers[$key]->weight = 0;
}
else unset($layers[$key]);
}
// Sort layers
usort($layers, '_openlayers_layers_process_sort');
// Process into array-based layer data for the map
foreach ($layers as $type => $layer_object) {
if (is_object($layer_object)) {
$layer_object->render($map);
$layer_object->data['title'] = $layer_object->title;
$layer_object->data['weight'] = $layer_object->weight;
$layer_data[$layer_object->name] = $layer_object->data;
}
}
return $layer_data;
}
/**
* Callback function for sorting
*
* @param $a
* Layer $a
* @param $b
* Layer $b
* @return $a_greater_b
* Return the weight different - allowing usort to sort
*/
function _openlayers_layers_process_sort($a, $b) {
return intval($a->weight - $b->weight);
}
/**
* Execute render() method for all enabled behaviors.
*
* @param $behaviors
* Array of behaviors to process
* @param $map
* Map array
* @return $rendered
* Indexed array of rendered behaviors
*/
function _openlayers_behaviors_render($behaviors = array(), &$map = array()) {
$rendered = array();
foreach (openlayers_behaviors() as $key => $plugin) {
if (isset($behaviors[$key]) && $class = ctools_plugin_get_class($plugin, 'behavior')) {
$behavior = new $class($behaviors[$key], $map);
$rendered[$key] = $behavior->render($map);
}
}
return $rendered;
}
/**
* Process Styles
*
* Get full data for any styles. The idea is that we load
* all the needed styles into the ['styles'] key of the
* map object, and keep a reference in ['layer_styles']
* and ['layer_styles_select'] for layer specific styling.
*
* TODO: Overall, this is not a great approach to managing
* styles.
*
* @param $styles
* Array of map styles ( <style_role> : <style_name> | <style_array> )
* @param $layer_styles
* Array of layer styles ( <layer_name> : <style_name> )
* @param $layer_styles_select
* Array of layer styles ( <layer_name> : <style_name> )
* @param $map
* Map array
* @return $processed
* Array of processed styles ( <style_name> => <style_array> )
*/
function _openlayers_styles_process($styles = array(),
$layer_styles = array(), $layer_styles_select = array(), &$map = array()) {
// Get styles info array
$styles_info = openlayers_styles();
// Go through styles
$processed = array();
foreach ($styles as $k => $style) {
// Check if array, if array, just pass on
if (is_array($style)) {
$processed[$k] = $style;
}
elseif (!empty($styles_info[$style]) && $info = $styles_info[$style]->data) {
$processed[$k] = $info;
}
}
// Add layer styles
foreach ($layer_styles as $style) {
if (!isset($processed[$style]) &&
!empty($styles_info[$style]) &&
$info = $styles_info[$style]->data) {
$processed[$style] = $info;
}
}
// Add layer styles select
foreach ($layer_styles_select as $style) {
if (!isset($processed[$style]) &&
!empty($styles_info[$style]) &&
$info = $styles_info[$style]->data) {
$processed[$style] = $info;
}
}
// Add layer styles
foreach ($layer_styles as $style) {
if (!isset($processed[$style]) &&
!empty($styles_info[$style]) &&
$info = $styles_info[$style]->data) {
$processed[$style] = $info;
}
}
// Update URLs to support different types of paths
foreach ($processed as $k => $style) {
$processed[$k] = openlayers_render_style($style);
}
// Run through theme function
$processed = theme('openlayers_styles', array(
'styles' => $processed,
'map' => $map)
);
// Return processed
return $processed;
}
/**
* Render style array.
*
* At the moment, this only makes the external grpahics
* relative.
*/
function openlayers_render_style($style = array()) {
// Relative path conversion
if (!empty($style['externalGraphic'])) {
// Check full URL or absolute path
if (!valid_url($style['externalGraphic'], TRUE)
&& strpos($style['externalGraphic'], '/') !== 0) {
// Make full URL from Drupal path
$style['externalGraphic'] = openlayers_style_path($style['externalGraphic']);
}
}
return $style;
}
/**
* Create Map ID
*
* Create a unique ID for any maps that are not assigned an ID
*
* @note
* Technically someone can assign a map ID identical
* to the one that is created
* @return
* New map id
*/
function _openlayers_create_map_id() {
return 'openlayers-map-' . substr(md5(uniqid(mt_rand())), 0, 8);
}
/**
* URL Style
*
* Takes in a path and makes full URL for style. Overall, this
* can be handled by url(), but we have to avoid some encoding
* for variable replacement. Note that this is not perfect as
* it will decode values that maybe not specifically part of the
* attribute replacement.
*
* A value that is just a replacement value, ${value} should
* not be run through the file_create_url() function.
*
* @param $path
* Path to process.
* @return
* Processed path.
*/
function openlayers_style_path($path) {
if (strpos($path, '${') !== 0) {
$path = file_create_url($path);
$path = str_replace('%24%7B', '${', $path);
$path = str_replace('%7D', '}', $path);
}
return $path;
}

View File

@@ -0,0 +1,123 @@
<?php
/**
* @file
* This file contains styles implementations
*
* @ingroup openlayers
*/
/**
* Style Implementation
*
* Internal callback for openlayers style implementation.
*
* @return
* Array of styles for an OpenLayers map
*/
function _openlayers_openlayers_styles() {
$styles = array();
// Default style
$style = new stdClass();
$style->api_version = 1;
$style->name = 'default';
$style->title = t('Default style');
$style->description = t('Basic default style.');
$style->data = array(
'pointRadius' => '6',
'fillColor' => '#888888',
'strokeColor' => '#222222',
'strokeWidth' => '4',
'fillOpacity' => '0.5',
'strokeOpacity' => '0.7',
);
$styles[$style->name] = $style;
// Hides features
$style = new stdClass();
$style->api_version = 1;
$style->name = 'invisible';
$style->title = t('Invisible style');
$style->description = t('Invisible default style.');
$style->data = array(
'pointRadius' => '0',
'strokeWidth' => '0',
'fillOpacity' => '0'
);
$styles[$style->name] = $style;
// Default select style
$style = new stdClass();
$style->api_version = 1;
$style->name = 'default_select';
$style->title = t('Default select style');
$style->description = t('Default style for selected geometries');
$style->data = array(
'pointRadius' => '6',
'fillColor' => '#222222',
'strokeColor' => '#888888',
'strokeWidth' => '4',
'fillOpacity' => '0.7',
'strokeOpacity' => '0.8',
);
$styles[$style->name] = $style;
// Marker styles
$markers = array(
'red' => t('Red'),
'green' => t('Green'),
'gold' => t('Gold'),
'blue' => t('Blue'),
);
foreach ($markers as $marker => $color) {
$style = new stdClass();
$style->api_version = 1;
$style->name = 'default_marker_' . $marker;
$style->title = t('Marker !color', array('!color' => $color));
$style->description = t('!color marker provided by the OpenLayers module.',
array('!color' => $color));
$style->data = array(
'externalGraphic' => drupal_get_path('module', 'openlayers') .
'/themes/default_dark/img/marker-' . $marker . '.png',
'graphicWidth' => 21,
'graphicHeight' => 25,
'graphicXOffset' => -10,
'graphicYOffset' => -25,
);
$styles[$style->name] = $style;
}
// Custom black markers
$style = new stdClass();
$style->api_version = 1;
$style->name = 'default_marker_black';
$style->title = t('Marker Black');
$style->description = t('Black marker provided by the OpenLayers module.');
$style->data = array(
'externalGraphic' => drupal_get_path('module', 'openlayers') .
'/themes/default_dark/markers/marker-black.png',
'graphicWidth' => 25,
'graphicHeight' => 41,
'graphicXOffset' => -12,
'graphicYOffset' => -41,
);
$styles[$style->name] = $style;
$style = new stdClass();
$style->api_version = 1;
$style->name = 'default_marker_black_small';
$style->title = t('Marker Black Small');
$style->description = t('Small black marker provided by the OpenLayers module.');
$style->data = array(
'externalGraphic' => drupal_get_path('module', 'openlayers') .
'/themes/default_dark/markers/marker-black-small.png',
'graphicWidth' => 16,
'graphicHeight' => 26,
'graphicXOffset' => -8,
'graphicYOffset' => -26,
);
$styles[$style->name] = $style;
return $styles;
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* @file
* This file holds the theme and preprocess functions for openlayers module
*
* @ingroup openlayers
*/
/**
* Preprocess function for openlayers_map
*/
function openlayers_preprocess_openlayers_map(&$variables, $hook) {
$map = $variables['map'];
$map['map_name'] = isset($map['map_name']) ? $map['map_name'] : '';
$css_map_name = drupal_clean_css_identifier($map['map_name']);
$links = array();
if (!empty($map['map_name'])) {
$links = array(
'#type' => 'contextual_links',
'#contextual_links' => array(
'openlayers' => array(
'admin/structure/openlayers/maps/list', array($map['map_name']),
),
)
);
}
$variables['links'] = render($links);
$variables['container']['classes'] = implode(" ", array(
'contextual-links-region',
'openlayers-container',
'openlayers-container-map-' . $css_map_name
));
$variables['container']['width'] = $map['width'];
$variables['container']['height'] = $map['height'];
$variables['container']['id'] = 'openlayers-container-' . $map['id'];
$variables['classes_array'][] = 'openlayers-map-' . $css_map_name;
}
/**
* Theme function to be able to override styles
*/
function theme_openlayers_styles($args) {
return $args['styles'];
}

View File

@@ -0,0 +1,393 @@
/*jslint white: false */
/*jslint forin: true */
/*global OpenLayers Drupal $ document jQuery window */
/**
* @file
* This file holds the main javascript API for OpenLayers. It is
* responsable for loading and displaying the map.
*
* @ingroup openlayers
*/
/**
* This is a workaround for a bug involving IE and VML support.
* See the Drupal Book page describing this problem:
* http://drupal.org/node/613002
*/
document.namespaces;
(function($) {
Drupal.settings.openlayers = {};
Drupal.settings.openlayers.maps = {};
/**
* Minimal OpenLayers map bootstrap.
* All additional operations occur in additional Drupal behaviors.
*/
Drupal.behaviors.openlayers = {
'attach': function(context, settings) {
if (typeof(Drupal.settings.openlayers) === 'object' &&
Drupal.settings.openlayers.maps &&
!$(context).data('openlayers')) {
$('.openlayers-map:not(.openlayers-processed)').each(function() {
// By setting the stop_render variable to TRUE, this will
// halt the render process. If set, one could remove this setting
// then call Drupal.attachBehaviors again to get it started
var map_id = $(this).attr('id');
if (Drupal.settings.openlayers.maps[map_id] && Drupal.settings.openlayers.maps[map_id].stop_render != true) {
var map = Drupal.settings.openlayers.maps[map_id];
$(this).addClass('openlayers-processed');
// Use try..catch for error handling.
try {
// Set OpenLayers language based on document language,
// rather than browser language
OpenLayers.Lang.setCode($('html').attr('lang'));
$(this)
// @TODO: move this into markup in theme function, doing this dynamically is a waste.
.css('width', map.width)
.css('height', map.height);
var options = {};
// This is necessary because the input JSON cannot contain objects
options.projection = new OpenLayers.Projection('EPSG:' + map.projection);
options.displayProjection = new OpenLayers.Projection('EPSG:' + map.displayProjection);
// TODO: work around this scary code
if (map.projection === '900913') {
options.maxExtent = new OpenLayers.Bounds(
-20037508.34, -20037508.34, 20037508.34, 20037508.34);
options.units = "m";
}
if (map.projection === '4326') {
options.maxExtent = new OpenLayers.Bounds(-180, -90, 180, 90);
}
options.maxResolution = 'auto'; // 1.40625;
options.controls = [];
// Change image, CSS, and proxy paths if specified
if (map.image_path) {
OpenLayers.ImgPath = Drupal.openlayers.relatePath(map.image_path,
Drupal.settings.basePath);
}
if (map.css_path) {
options.theme = Drupal.openlayers.relatePath(map.css_path,
Drupal.settings.basePath);
}
if (map.proxy_host) {
OpenLayers.ProxyHost = Drupal.openlayers.relatePath(map.proxy_host,
Drupal.settings.basePath);
}
// Initialize openlayers map
var openlayers = new OpenLayers.Map(map.id, options);
// Run the layer addition first
Drupal.openlayers.addLayers(map, openlayers);
// Attach data to map DOM object
$(this).data('openlayers', {'map': map, 'openlayers': openlayers});
// Finally, attach behaviors
Drupal.attachBehaviors(this);
if ($.browser.msie) {
Drupal.openlayers.redrawVectors();
}
}
catch (e) {
var errorMessage = e.name + ': ' + e.message;
if (typeof console != 'undefined') {
console.log(errorMessage);
}
else {
$(this).text('Error during map rendering: ' + errorMessage);
}
}
}
});
}
}
};
/**
* Collection of helper methods.
*/
Drupal.openlayers = {
// Determine path based on format.
'relatePath': function(path, basePath) {
// Check for a full URL or an absolute path.
if (path.indexOf('://') >= 0 || path.indexOf('/') == 0) {
return path;
}
else {
return basePath + path;
}
},
/*
* Redraw Vectors.
* This is necessary because various version of IE cannot draw vectors on
* $(document).ready()
*/
'redrawVectors': function() {
$(window).load(
function() {
var map;
for (map in Drupal.settings.openlayers.maps) {
$.each($('#' + map).data('openlayers')
.openlayers.getLayersByClass('OpenLayers.Layer.Vector'),
function(i, layer) {
layer.redraw();
}
);
}
}
);
},
/**
* Add layers to the map
*
* @param map Drupal settings object for the map.
* @param openlayers OpenLayers Map Object.
*/
'addLayers': function(map, openlayers) {
var sorted = [];
for (var name in map.layers) {
sorted.push({'name': name, 'weight': map.layers[name].weight, 'isBaseLayer': map.layers[name].isBaseLayer });
}
sorted.sort(function(a, b) {
var x = parseInt(a.weight, 10), y = parseInt(b.weight, 10);
return ((a.isBaseLayer && x < y) ? -1 : ((b.isBaseLayer || x > y) ? 1 : 0));
});
for (var i = 0; i < sorted.length; ++i) {
var layer,
name = sorted[i].name,
options = map.layers[name];
// Add reference to our layer ID
options.drupalID = name;
// Ensure that the layer handler is available
if (options.layer_handler !== undefined &&
Drupal.openlayers.layer[options.layer_handler] !== undefined) {
var layer = Drupal.openlayers.layer[options.layer_handler](map.layers[name].title, map, options);
layer.visibility = !!(!map.layer_activated || map.layer_activated[name]);
if (layer.isBaseLayer === false) {
layer.displayInLayerSwitcher = (!map.layer_switcher || map.layer_switcher[name]);
}
if (map.center.wrapdateline === '1') {
// TODO: move into layer specific settings
layer.wrapDateLine = true;
}
openlayers.addLayer(layer);
}
}
openlayers.setBaseLayer(openlayers.getLayersBy('drupalID', map.default_layer)[0]);
// Set the restricted extent if wanted.
// Prevents the map from being panned outside of a specfic bounding box.
if (typeof map.center.restrict !== 'undefined' && map.center.restrict.restrictextent) {
openlayers.restrictedExtent = OpenLayers.Bounds.fromString(
map.center.restrict.restrictedExtent);
}
// Zoom & center
if (map.center.initial) {
var center = OpenLayers.LonLat.fromString(map.center.initial.centerpoint).transform(
new OpenLayers.Projection('EPSG:4326'),
new OpenLayers.Projection('EPSG:' + map.projection));
var zoom = parseInt(map.center.initial.zoom, 10);
openlayers.setCenter(center, zoom, false, false);
}
},
/**
* Abstraction of OpenLayer's feature adding syntax to work with Drupal output.
* Ideally this should be rolled into the PHP code, because we don't want to manually
* parse WKT
*/
'addFeatures': function(map, layer, features) {
var newFeatures = [];
// Go through features
for (var key in features) {
var feature = features[key];
var newFeatureObject = this.objectFromFeature(feature);
// If we have successfully extracted geometry add additional
// properties and queue it for addition to the layer
if (newFeatureObject) {
var newFeatureSet = [];
// Check to see if it is a new feature, or an array of new features.
if (typeof(newFeatureObject[0]) === 'undefined') {
newFeatureSet[0] = newFeatureObject;
}
else {
newFeatureSet = newFeatureObject;
}
// Go through new features
for (var i in newFeatureSet) {
var newFeature = newFeatureSet[i];
// Transform the geometry if the 'projection' property is different from the map projection
if (feature.projection) {
if (feature.projection !== map.projection) {
var featureProjection = new OpenLayers.Projection('EPSG:' + feature.projection);
var mapProjection = new OpenLayers.Projection('EPSG:' + map.projection);
newFeature.geometry.transform(featureProjection, mapProjection);
}
}
// Add attribute data
if (feature.attributes) {
// Attributes belong to features, not single component geometries
// of them. But we're creating a geometry for each component for
// better performance and clustering support. Let's call these
// "pseudofeatures".
//
// In order to identify the real feature each geometry belongs to
// we then add a 'fid' parameter to the "pseudofeature".
// NOTE: 'drupalFID' is only unique within a single layer.
newFeature.attributes = feature.attributes;
newFeature.data = feature.attributes;
newFeature.drupalFID = key;
}
// Add style information
if (feature.style) {
newFeature.style = jQuery.extend({},
OpenLayers.Feature.Vector.style['default'],
feature.style);
}
// Push new features
newFeatures.push(newFeature);
}
}
}
// Add new features if there are any
if (newFeatures.length !== 0) {
layer.addFeatures(newFeatures);
}
},
'getStyleMap': function(map, layername) {
if (map.styles) {
var stylesAdded = {};
// Grab and map base styles.
for (var style in map.styles) {
stylesAdded[style] = new OpenLayers.Style(map.styles[style]);
}
// Implement layer-specific styles. First default, then select.
if (map.layer_styles !== undefined && map.layer_styles[layername]) {
var style = map.layer_styles[layername];
stylesAdded['default'] = new OpenLayers.Style(map.styles[style]);
}
if (map.layer_styles_select !== undefined && map.layer_styles_select[layername]) {
var style = map.layer_styles_select[layername];
stylesAdded['select'] = new OpenLayers.Style(map.styles[style]);
}
return new OpenLayers.StyleMap(stylesAdded);
}
else {
return new OpenLayers.StyleMap({
'default': new OpenLayers.Style({
pointRadius: 5,
fillColor: '#ffcc66',
strokeColor: '#ff9933',
strokeWidth: 4,
fillOpacity: 0.5
}),
'select': new OpenLayers.Style({
fillColor: '#66ccff',
strokeColor: '#3399ff'
})
});
}
},
'objectFromFeature': function(feature) {
var wktFormat = new OpenLayers.Format.WKT();
// Extract geometry either from wkt property or lon/lat properties
if (feature.wkt) {
return wktFormat.read(feature.wkt);
}
else if (feature.lon) {
return wktFormat.read('POINT(' + feature.lon + ' ' + feature.lat + ')');
}
},
/**
* Add Behavior.
*
* This is a wrapper around adding behaviors for OpenLayers.
* a module does not have to use this, but it helps cut
* down on code.
*
* @param id
* The identifier of the behavior that is attached to
* the map.
* @param attach
* The callback function for the attach part of the
* Drupal behavior.
* @param detach
* The callback function for the detach part of the
* Drupal behavior.
*/
'addBehavior': function(id, attach, detach) {
// Add as a Drupal behavior. Add a prefix, just to be safe.
Drupal.behaviors['openlayers_auto_' + id] = {
attach: function (context, settings) {
var data = $(context).data('openlayers');
// Ensure that there is a map and that the appropriate
// behavior exists. Need "data &&" to avoid js crash
// when data is empty
var localBehavior = data && data.map.behaviors[id];
// Ensure scope in the attach callback
var that = this;
if (localBehavior) {
$(context).once('openlayers-' + id, function () {
attach.apply(that, [data, data.map.behaviors[id], context, settings]);
});
}
},
// Maybe we need a little more handling here.
detach: detach
};
},
/**
* Add Control.
*
* This is a wrapper around adding controls to maps. It
* is not needed but saves some code.
*/
'addControl': function(openlayers, controlName, options) {
var control = new OpenLayers.Control[controlName](options);
openlayers.addControl(control);
control.activate();
return control;
}
};
Drupal.openlayers.layer = {};
})(jQuery);

View File

@@ -0,0 +1,109 @@
<?php
/**
* @file
* This file holds the functions for the main openlayers Admin settings.
*
* @ingroup openlayers
*/
/**
* Menu callback; displays the openlayers module settings page.
*
* @see system_settings_form()
*/
function openlayers_ui_admin_settings() {
$client_check = variable_get('openlayers_ui_version_check', 'no-check');
$source_description =
t('<p>By default the your site will point to a hosted version of the
OpenLayers library at %ol_api_url.</p>
<p>For better performance and reliability, you should <a href="!ol_url">download the
OpenLayers library</a>, and add it to your Drupal installation. For instance,
you could use a Drupal relative path like: %suggested_path. You can also use a double backslash
before the domain name (eg. //www.example.com/OpenLayers.js) which
then respects the use of both HTTPS and HTTP protocols.</p>
<ul>
<li>The default suggested, compatible version: <strong>%suggested_api</strong></li>
<li>The default suggested, compatible hosted URL: <strong>%ol_api_url</strong></li>
<li>Your version found from client-side, Javascript check: <strong>%client</strong></li>
</ul>',
array(
'%ol_api_url' => OPENLAYERS_DEFAULT_LIBRARY,
'%suggested_api' => OPENLAYERS_SUGGESTED_LIBRARY,
'!ol_url' => 'http://openlayers.org/',
'%suggested_path' => 'sites/all/libraries/OpenLayers/OpenLayers.js',
'%client' => ($client_check == 'no-check') ? t('(not checked)') : $client_check,
)
);
// Define Form
$form['openlayers_source'] = array(
'#type' => 'textfield',
'#title' => t('OpenLayers Source'),
'#description' => $source_description,
'#default_value' => variable_get('openlayers_source', OPENLAYERS_DEFAULT_LIBRARY),
);
$form['openlayers_default_map'] = array(
'#type' => 'select',
'#title' => t('OpenLayers Default Map'),
'#description' => t('This is the default map that will be used
in cases where one is not defined. It will also be used as
the default when creating new maps.'),
'#options' => openlayers_map_options(),
'#default_value' => variable_get('openlayers_default_map', 'default'),
);
$form['openlayers_ui_preview_map'] = array(
'#type' => 'checkbox',
'#title' => t('Preview Map'),
'#description' => t('Turning this on will show you a map preview when editing it through the !link.',
array('!link' => l(t('Map Interface'), 'admin/structure/openlayers/maps'))),
'#default_value' => variable_get('openlayers_ui_preview_map', FALSE),
);
// A hidden value to reset client check
$form['openlayers_ui_version_check'] = array(
'#type' => 'hidden',
'#value' => '',
);
// Make a system setting form and return
return system_settings_form($form);
}
/**
* Callback endpoint for sending in OL version from client JS.
*/
function openlayers_ui_version_check($version = 0) {
$version = check_plain($version);
// Set variable with version for hook_requirements
// and so we dont do this on every page load.
variable_set('openlayers_ui_version_check', $version);
// Do a basic check
if (strpos($version, (string) OPENLAYERS_SUGGESTED_LIBRARY) !== FALSE) {
$status = 'valid';
$message = t('Valid library found with a Javascript client check; version: %version', array('%version' => $version));
}
else {
$status = 'invalid';
$message = t('Could not find a valid library with a Javascript client-side check; Value found: %version. Please visit the !settings for more details.',
array(
'%version' => $version,
'!settings' => l(t('OpenLayers settings page'), 'admin/structure/openlayers'),
)
);
}
// Kind of a hack, but since we are using messages for this, let's clear the
// messages queue out.
$messages = drupal_get_messages();
// We just want to send some markup back.
drupal_json_output(array(
'status' => $status,
'response' => $message,
));
}

View File

@@ -0,0 +1,49 @@
<?php
/**
* @file
* This file holds the functions handling layers in the
* Openlayers UI.
*
* @ingroup openlayers
*/
/**
* Layer-wide-settings form
*/
function openlayers_ui_layers_settings($form, &$form_state, $layer = NULL) {
$form = array();
$layer_types = openlayers_layer_types();
foreach ($layer_types as $name => $type_def) {
$type = openlayers_layer_type_load($name);
if (method_exists($type, 'settings_form')) {
$form[$name] = array(
'#type' => 'fieldset',
'#tree' => TRUE,
'#title' => $type_def['title']);
$form[$name]['settings'] = $type->settings_form();
}
}
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Save'),
);
return $form;
}
/**
* Submit handler for openlayers_ui_layers_settings
*/
function openlayers_ui_layers_settings_submit(&$form, &$form_state) {
$layer_types = openlayers_layer_types();
foreach ($form_state['values'] as $key => $value) {
if (in_array($key, array_keys($layer_types))) {
foreach ($value['settings'] as $k => $v) {
variable_set($k, $v);
}
}
}
}

View File

@@ -0,0 +1,265 @@
<?php
/**
* @file
* This file holds the functions handling maps in the
* Openlayers UI.
*
* @ingroup openlayers
*/
/**
* Form submit for map add form, for the projection add ahah
*/
function openlayers_ui_maps_add_projection_submit($form, &$form_state) {
unset($form_state['submit_handlers']);
form_execute_handlers('submit', $form, $form_state);
$form_state['rebuild'] = TRUE;
}
/**
* OpenLayers AHAH
*
* Function to handle the AHAH request of the openlayers form
*/
function openlayers_ui_map_ahah() {
$form_state = array('storage' => NULL, 'submitted' => FALSE);
$form_build_id = $_POST['form_build_id'];
$form = form_get_cache($form_build_id, $form_state);
// Get variables
$args = $form['#parameters'];
$form_id = array_shift($args);
$form_state['post'] = $form['#post'] = $_POST;
$form['#programmed'] = $form['#redirect'] = FALSE;
// Reprocess form with new form state
drupal_process_form($form_id, $form, $form_state);
// Rebuild form and remove any submit handlers
$form = drupal_rebuild_form($form_id, $form_state, $args, $form_build_id);
// Unset wrapper and create output
$output = theme('status_messages') . drupal_render($form['layerstyles']);
// Final rendering callback.
drupal_json(array('status' => TRUE, 'data' => $output));
}
/**
* Process form submission into a map array.
*
* @param $values
* Array of values to process.
* @return
* Map data array.
*/
function openlayers_ui_maps_form_process($values = array()) {
// Valid keys that we will cherry-pick from the form values.
$keys = array(
'width',
'height',
'image_path',
'css_path',
'proxy_host',
'hide_empty_map',
'center',
'behaviors',
'layers',
'layer_weight',
'layer_styles',
'layer_styles_select',
'layer_activated',
'layer_switcher',
'projections',
'styles'
);
// TODO: eliminate this process, too much disconnect between
// forms and data
$processed = array();
foreach ($keys as $key) {
switch ($key) {
case 'behaviors':
$processed['behaviors'] = array();
foreach ($values['behaviors'] as $behavior => $settings) {
if ($settings['enabled']) {
$processed['behaviors'][$behavior] =
isset($settings['options_set']['options']) ?
$settings['options_set']['options'] : array();
}
}
break;
case 'projections':
$processed['projection'] = $values['projections']['easy_projection'];
$processed['displayProjection'] = $values['projections']['displayProjection'];
break;
case 'layers':
// Put the default layer in the right place.
// TODO: finish port here
$processed['default_layer'] = $values['layers']['default_layer'];
$baselayers = array_filter($values['layers']['baselayers']);
$overlays = (isset($values['layers']['overlays'])) ?
array_filter($values['layers']['overlays']) : array();
// Sort overlay layers by weight, in case browser didn't
// send them already sorted
if (isset($values['layer_weight'])) {
$overlays = array();
asort($values['layer_weight']);
foreach (array_keys($values['layer_weight']) as $layer_key) {
if ($values['layers']['overlays'][$layer_key]) {
$overlays[$layer_key] = $layer_key;
}
}
// TODO: Above code is terrrrrrrrible. rewrite when I have the time
}
// Merge our different layer sections together
$processed['layers'] = array_merge($baselayers, $overlays);
break;
default:
// $processed[$key] = is_array($values[$key]) ?
// array_filter($values[$key]) : $values[$key];
$processed[$key] = isset($values[$key]) ? $values[$key] : array();
break;
}
}
// Ensure these values are arrays
$ensure_array = array('behaviors', 'layers', 'layer_weight', 'layer_styles', 'layer_styles_select', 'styles');
foreach ($ensure_array as $key) {
if (empty($processed[$key])) {
$processed[$key] = array();
}
}
return $processed;
}
/**
* Get behavior options.
*/
function openlayers_ui_get_behavior_options($type, $defaults) {
$form = array();
$behaviors = openlayers_behaviors();
uasort($behaviors, '_openlayers_ui_sort_behaviors');
foreach ($behaviors as $key => $plugin) {
// Get behavior class
$class = ctools_plugin_load_class(
'openlayers',
'behaviors',
$key,
'behavior');
if (!empty($class)) {
$options = isset($defaults['behaviors'][$key]) ?
$defaults['behaviors'][$key] : array();
$behavior = new $class($options, $defaults);
if (!isset($plugin['ui_visibility']) || $plugin['ui_visibility']) {
// Create basic form structure for behavior
$form[$key] = array(
'enabled' => array(
'#type' => 'checkbox',
'#title' => $plugin['title'],
'#description' => $plugin['description'],
'#default_value' => isset($defaults['behaviors'][$key]),
'#id' => $key . '-enabled',
),
'dependencies' => openlayers_dependency_widget(
$behavior->js_dependency()),
'options' => array(),
);
// Create options items
$options = $behavior->options_form($options);
if (!empty($options)) {
// HACK. In order to use ctools form
// dependencies, we have to use a hidden
// field as it supports processing and IDs.
$form[$key]['options_set'][$key . '-prefix'] = array(
'#type' => 'hidden',
'#id' => $key . '-options',
'#prefix' => '<div><fieldset id="' . $key . '-options' .
'" class="collapsible">',
'#process' => array('ctools_dependent_process'),
'#dependency' => array($key . '-enabled' => array(1)),
'#weight' => -1000,
);
$form[$key]['options_set']['options'] = $options;
$form[$key]['options_set'][$key . '-suffix'] = array(
'#value' => '</fieldset></div>',
'#weight' => 1000,
);
}
}
}
else {
}
}
return $form;
}
/**
* Callback sorting behaviors alphabetically
*/
function _openlayers_ui_sort_behaviors($a, $b) {
return strnatcmp($a['title'], $b['title']);
}
/**
* Create Centering Map
*
* Create map for interactive default centering
*
* @param $defaults
* Array of defults to use for the map of centering and zooming
* @return
* Themed map array
*/
function openlayers_ui_maps_form_center_map($defaults = array()) {
// Pass variables etc. to javascript
$pass_values = array(
'openlayersForm' => array(
'projectionLayers' => openlayers_ui_get_projection_options(),
),
);
drupal_add_js($pass_values, 'setting');
// centerpoint & zoom of this map are overridden
// by the mapformvalues behavior on page load.
//
// Note that navigation screws up the boxselect
// behavior for getting extent.
$centermap_def = array(
'id' => 'openlayers-center-helpmap',
'projection' => '900913',
'displayProjection' => '900913',
'default_layer' => 'mapquest_osm',
'width' => '600px',
'height' => '400px',
'center' => array(
'initial' => array(
'centerpoint' => "0, 0",
'zoom' => 2,
),
),
'image_path' => drupal_get_path('module', 'openlayers') . '/themes/default_dark/img/',
'layers' => array(
'mapquest_osm',
),
'behaviors' => array(
//'openlayers_behavior_navigation' => array(),
'openlayers_behavior_panzoombar' => array(),
//'openlayers_behavior_dragpan' => array(),
'openlayers_behavior_mapformvalues' => array(),
'openlayers_behavior_boxselect' => array(),
'openlayers_behavior_attribution' => array(),
),
);
return openlayers_render_map_data($centermap_def);
}

View File

@@ -0,0 +1,108 @@
<?php
/**
* @file
* This file holds the theme functions for openlayers ui module
*
* @ingroup openlayers
*/
/**
* Theme function for form description of layers
*/
function theme_openlayers_ui_form_layer_description($args) {
if (!empty($args['layer_link'])) {
$args['layer_title'] = l($args['layer_title'], $args['layer_link'], array('query' => drupal_get_destination()));
}
return $args['layer_title'] . ($args['layer_description'] ?
' <span class="openlayers-form-layer-description">' .
$args['layer_description'] . '</span>' :
'');
}
/**
* Theme function for form description of projection
*/
function theme_openlayers_ui_form_projection_description($args) {
$output = $args['projection_title'];
if (count($args['available_layers'])) {
$names = implode(', ', $args['available_layers']);
$output .= " - <span class='openlayers-form-projection-description'>$names</span>";
}
return $output;
}
function theme_openlayers_ui_maps_form_layers($args) {
$form = $args['elements'];
$output = '';
// Base layers
$rows = array();
foreach (element_children($form['layers']['baselabels']) as $key) {
unset($form['layers']['default_layer'][$key]['#title']);
unset($form['layers']['baselayers'][$key]['#title']);
$rows[] = array(
drupal_render($form['layers']['baselabels'][$key]),
drupal_render($form['layers']['baselayers'][$key]),
drupal_render($form['layers']['default_layer'][$key]));
}
$output .= theme('table', array(
'header' => array(t('Base layers'), t('Enabled'), t('Default')),
'rows' => $rows)
);
// Overlay layers
$rows = array();
foreach (element_children($form['layers']['overlaylabels']) as $key) {
unset($form['layers']['overlays'][$key]['#title']);
unset($form['layer_activated'][$key]['#title']);
unset($form['layer_switcher'][$key]['#title']);
$rows[] = array(
'data' => array(
drupal_render($form['layers']['overlaylabels'][$key]),
drupal_render($form['layer_weight'][$key]),
drupal_render($form['layers']['overlays'][$key]),
drupal_render($form['layer_activated'][$key]),
drupal_render($form['layer_switcher'][$key]),
drupal_render($form['layer_styles'][$key]),
drupal_render($form['layer_styles_select'][$key]),
),
'class' => array('draggable')
);
}
$output .= theme('table',
array(
'header' => array(
t('Overlay layers'), t('Weight'), t('Enabled'),
t('Activated'), t('In Switcher'), t('Style'), t('Select Style')
),
'rows' => $rows,
array('id' => 'overlay-layer-table')
)
);
drupal_add_tabledrag('overlay-layer-table', 'order', 'sibling',
'layer-weight');
return $output . drupal_render_children($form);
}
/**
* Drupal theme implementation for Behaviors in the map form
*/
function theme_openlayers_ui_maps_form_behaviors($args) {
$form = $args['elements'];
$rows = array();
foreach (element_children($form) as $key) {
$rows[] = array(drupal_render($form[$key]['enabled']) .
drupal_render($form[$key]['options_set']) .
drupal_render($form[$key]['dependencies']));
}
return theme('table',
array(
'header' => array(t('Behaviors')),
'rows' => $rows));
}

View File

@@ -0,0 +1,53 @@
/**
* @file
* Javascript for OL UI Admin
*
* @ingroup openlayers
*/
// Namespace jQuery
(function ($) {
/**
* Drupal behaviors for OpenLayers UI form.
*/
Drupal.behaviors.openlayers_ui_admin = {
'attach': function(context, settings) {
$('.openlayers-ui-version-check-message').once('openlayers-ui-version-check-message', function() {
// Determine version
var version = '0';
var $thisContainer = $(this);
if (typeof OpenLayers != 'undefined' && OpenLayers.hasOwnProperty('VERSION_NUMBER')) {
version = OpenLayers.VERSION_NUMBER;
}
// Mark as loading, then do AJAX request
$thisContainer.addClass('throbbing');
var url = settings.basePath + '?q=admin/structure/openlayers/callbacks/version_check/' + version;
$.ajax({
url: url,
success: function(data) {
$thisContainer.removeClass('throbbing');
$thisContainer.html(data.response);
if (data.status == 'valid') {
$thisContainer.parent()
.removeClass('warning')
.addClass('status');
}
else {
$thisContainer.parent()
.removeClass('status')
.addClass('warning');
}
},
error: function(data) {
$thisContainer.removeClass('throbbing');
$thisContainer.html(Drupal.t('Error making request to server.'));
}
});
});
}
};
})(jQuery);

View File

@@ -0,0 +1,155 @@
/**
* @file
* This file holds the javascript functions for the map UI
*
* @ingroup openlayers
*/
/**
* Test whether function exists,
* even if it is the child of another object
* @param head the function name as a string,
* optionally with dots for invoking children
* @return bool true or false for existence
*/
function function_exists(head) {
return _function_exists(head.split('.'), window);
}
function _function_exists(head, f) {
if (head.length == 0) {
return true;
}
h = head.shift();
if (typeof f[h] !== 'undefined') {
return _function_exists(head, f[h]);
}
else {
return false;
}
}
(function ($) {
/**
* Drupal behaviors for OpenLayers UI form.
*/
Drupal.behaviors.openlayers_ui = {
'attach': function(context, settings) {
// mark openlayers dependencies as valid or invalid
$('.openlayers-dependency-flag').each(function() {
if (!function_exists($(this).find('.openlayers-dependency-value').text())) {
$(this).find('.openlayers-dependency-broken').show();
}
});
// Since CTools dependency is not working
$('#edit-behaviors:not(.openlayers-behaviors-checks-processed)').each(function () {
$('#edit-behaviors').addClass('openlayers-behaviors-checks-processed');
$('#edit-behaviors table tbody tr td > div.form-type-checkbox').each(function () {
var $thisBehavior = $(this);
var $thisCheck = $('input[type=checkbox]', $thisBehavior);
if ($thisCheck.attr('checked')) {
$thisBehavior.siblings().show();
}
else {
$thisBehavior.siblings().hide();
}
$thisCheck.click(function() {
if ($thisCheck.attr('checked')) {
$thisBehavior.siblings().show();
}
else {
$thisBehavior.siblings().hide();
}
});
});
});
// Run once on load.
Drupal.openlayers_ui.updateMapCenter();
}
};
/**
* Register form center value updating events.
*/
Drupal.behaviors.openlayers_ui_center = {
'attach': function(context, settings) {
var data = $(context).data('openlayers');
if (data) {
data.openlayers.events.register('moveend', data.map, function() {
Drupal.openlayers_ui.updateCenterFormValues()
});
data.openlayers.events.register('zoomend', data.map, function() {
Drupal.openlayers_ui.updateCenterFormValues()
});
}
}
};
/**
* Helper functions.
*/
Drupal.openlayers_ui = {
/**
* Update the center of the helpmap using the values from the form
*
* Take the center lat, lon and zoom values from the form and update
* the helper map.
*/
'updateMapCenter': function() {
var data = $('#openlayers-center-helpmap').data('openlayers');
if (data) {
var projection = $('#edit-projections-projection').val();
var zoom = $('#edit-center-zoom').val();
var lonlat = $('#edit-center-initial-centerpoint').val();
if (typeof lonlat == Array) {
// Create new center
var center = new OpenLayers.LonLat(
parseFloat(lonlat[0]),
parseFloat(lonlat[1]));
// Transform for projection
center.transform(
new OpenLayers.Projection('EPSG:' + projection),
new OpenLayers.Projection('EPSG:4326'));
// Set center of map.
data.openlayers.setCenter(center, zoom);
}
}
},
/**
* Event callback for updating center form field values when map
* is dragged or zoomed.
*/
'updateCenterFormValues': function() {
var data = $('#openlayers-center-helpmap').data('openlayers');
if (data) {
var helpmap = data.openlayers;
var projection = $('#edit-projections-projection').val();
var zoom = helpmap.getZoom();
var center = helpmap.getCenter();
// Transform center
center.transform(
new OpenLayers.Projection('EPSG:4326'),
new OpenLayers.Projection('EPSG:' + projection));
// Get new lat and lon
var lat = center.lat;
var lon = center.lon;
// Set new values
$('#edit-center-zoom').val(zoom);
$('#edit-center-lat').val(lat);
$('#edit-center-lon').val(lon);
}
}
}
})(jQuery);

View File

@@ -0,0 +1,58 @@
/**
* @file
* Javascript for OL Styles UI.
*
* @ingroup openlayers
*/
// Namespace jQuery
(function ($) {
/**
* Drupal behaviors for OpenLayers UI form.
*/
Drupal.behaviors.openlayers_ui_styles = {
'attach': function(context, settings) {
var maps = {};
// Go through each preview
$('.openlayers-ui-style-preview:not(.openlayers-ui-style-preview-processed)').each(function() {
$thisPreview = $(this);
$thisPreview.addClass('openlayers-ui-style-preview-processed');
var id = $thisPreview.attr('id');
var style = Drupal.settings.openlayers_ui.style_preview[id].data;
// We want to create a very simple map with a style on
// top. There's no need to use the Drupal API for this as we
// want to keep it lean.
maps[id] = new OpenLayers.Map(id, { controls: [] });
var mapquest = new OpenLayers.Layer.OSM(Drupal.t('MapQuest-OSM Tiles'),
[(location.protocol === 'https:' ? '//otile1-s' : '//otile1') + '.mqcdn.com/tiles/1.0.0/osm/${z}/${x}/${y}.png']);
maps[id].addLayer(mapquest);
var point = new OpenLayers.LonLat(Math.random() * 175, Math.random() * 80).transform(
new OpenLayers.Projection("EPSG:4326"), maps[id].getProjectionObject()
);
maps[id].setCenter(point, (Math.floor(Math.random() * 4) + 1));
// Now add a point with the preview style.
var feature = new OpenLayers.Feature.Vector(
new OpenLayers.Geometry.Point(point.lon, point.lat));
var vector = new OpenLayers.Layer.Vector(Drupal.t('Preview'), {
styleMap: new OpenLayers.StyleMap(style)
});
vector.addFeatures([ feature ]);
maps[id].addLayer(vector);
// And finally, lets add a little crosshair so that
// the user can see how the style is centered. If it is
// enabled;
if (Drupal.settings.openlayers_ui.style_preview[id + '_crosshairs']) {
$thisPreview.find('.olMapViewport')
.append('<div class="openlayers-ui-style-preview-top"></div>')
.append('<div class="openlayers-ui-style-preview-left"></div>');
}
});
}
};
})(jQuery);

View File

@@ -0,0 +1,120 @@
/**
* @file
* OpenLayers Admin CSS
*
* This file holds CSS for the openlayers ui module
*
* @ingroup openlayers
*/
/**
* Map Form
*/
.openlayers-form-projection-description,
.openlayers-form-layer-description {
font-size: smaller;
font-style: italic;
}
#openlayers-form-proj-msg {
display: none;
}
span.openlayers-dependency-value {
display: none;
}
span.openlayers-dependency-broken {
font-size: smaller;
display: none;
color: red;
}
/**
* Overriding for vertical tabs
*/
div.vertical-tabs fieldset {
border: 1px solid #CCCCCC;
margin: 1em 0;
padding: 2.5em 0 0;
position: relative;
}
div.vertical-tabs .vertical-tabs-panes legend {
display: block;
}
div.vertical-tabs .vertical-tabs-panes > fieldset {
border: 0 none;
margin: 0;
padding: 0;
}
div.vertical-tabs .vertical-tabs-panes > fieldset > legend {
display: none;
}
/**
* Behaviors table
*/
div.vertical-tabs table tbody tr fieldset {
font-size: .85em;
margin-left: 20px;
margin-right: 20px;
padding: 10px;
background-color: #EEEEEE;
position: inherit;
}
div.vertical-tabs table tbody tr.odd .form-item,
div.vertical-tabs table tbody tr.even .form-item {
white-space: normal;
}
/**
* Style previews
*/
.openlayers-ui-style-preview {
width: 60px;
height: 60px;
background-color: #DDDDDD;
border: 1px solid #222222;
}
#openlayers-ui-styles-form .openlayers-ui-style-preview {
width: 200px;
height: 200px;
}
#openlayers-ui-styles-form #edit-preview-style-container {
float: right;
width: 210px;
margin: 0 0 10px 10px;
}
.openlayers-ui-style-preview .openlayers-ui-style-preview-top,
.openlayers-ui-style-preview .openlayers-ui-style-preview-left {
position: absolute;
z-index: 999999;
}
.openlayers-ui-style-preview .openlayers-ui-style-preview-top {
top: 0;
right: 0;
left: 0;
width: 100%;
height: 50%;
border-bottom: 1px solid rgb(33, 33, 33);
border-bottom: 1px solid rgba(33, 33, 33, .2);
}
.openlayers-ui-style-preview .openlayers-ui-style-preview-left {
top: 0;
right: 0;
left: 0;
width: 50%;
height: 100%;
border-right: 1px solid rgb(33, 33, 33);
border-right: 1px solid rgba(33, 33, 33, .2);
}

View File

@@ -0,0 +1,15 @@
name = "OpenLayers UI"
description = "Provides a user interface to manage OpenLayers maps."
core = "7.x"
package = "OpenLayers"
dependencies[] = "openlayers"
configure = admin/structure/openlayers
files[] = openlayers_ui.module
; Information added by drupal.org packaging script on 2013-02-05
version = "7.x-2.0-beta3+76-dev"
core = "7.x"
project = "openlayers"
datestamp = "1360071107"

View File

@@ -0,0 +1,34 @@
<?php
/**
* @file
* This file holds the functions for the installing
* and enabling of the openlayers_ui module.
*
* @ingroup openlayers
*/
/**
* Implementation of hook_uninstall().
*/
function openlayers_ui_uninstall() {
// Get module variables
global $conf;
foreach (array_keys($conf) as $key) {
// Find variables that have the module prefix
if (strpos($key, 'openlayers_ui_') === 0) {
variable_del($key);
}
}
}
/**
* This is needed to rebuild menu items and set parent correctly on
* Openlayers tabs when using CTools Export UI and have a good breadcrumb.
* Thanks @Dave Reid for the help !
*/
function openlayers_ui_update_7201() {
db_delete('menu_links')
->condition('link_path', 'admin/structure/openlayers%', 'LIKE')
->execute();
}

View File

@@ -0,0 +1,345 @@
<?php
/**
* @file
* Main Drupal module file for the OpenLayers UI module
*
* @ingroup openlayers
*/
/**
* Implements hook_init().
*/
function openlayers_ui_init() {
// For backwards compability for the change from maps to presets
// in the 7.x-2.x version, we want to make it really obvious that
// administrators and developers should be updating their maps
//
// There are also other requirement checks like the compatible
// suggestlibrary version.
if (strpos($_GET['q'], 'admin/structure/openlayers') === 0) {
include_once DRUPAL_ROOT . '/includes/install.inc';
drupal_load_updates();
module_load_include('install', 'openlayers', 'openlayers');
$reqs = openlayers_requirements('runtime');
foreach ($reqs as $r) {
if ($r['severity'] != REQUIREMENT_OK) {
$severity = $r['severity'] == REQUIREMENT_WARNING ? 'warning' : 'error';
drupal_set_message(t('<strong>!title</strong> !message', array(
'!title' => $r['value'],
'!message' => isset($r['description']) ? $r['description'] : '',
)), $severity);
}
}
// We also want to do some nice AJAX magic to get the library
// version to the system.
$check = variable_get('openlayers_ui_version_check', '');
if (empty($check)) {
// Load AJAX libraries
drupal_add_library('system', 'drupal.ajax');
drupal_add_library('system', 'jquery.form');
// Ensure that the library is included
openlayers_include();
// Add custom client JS
drupal_add_js(drupal_get_path('module', 'openlayers_ui') . '/js/openlayers_ui.admin.js');
// We shouldn't, but we are just gonna put a message up there
// to get replaced.
drupal_set_message('<div class="openlayers-ui-version-check-message">' .
t('Checking client library via Javascript...') . '</div>', 'none');
}
}
}
/**
* Implements hook_help
*/
function openlayers_ui_help($path, $arg) {
switch ($path) {
case 'admin/help#openlayers_ui':
return '<p>'. t('Provides a user interface to manage OpenLayers maps.') .'</p>';
case 'admin/structure/openlayers':
return '<p>'. t('Configure where Drupal finds
the OpenLayers javascript library. Using a local or <a href="@olb">compacted
version</a> of OpenLayers can reduce filesize, but remember to set the Image Path and
CSS Path options in every map, because OpenLayers is not able to find these resources
automatically. See the included documentation in /doc for
more details.',
array('@olb' => 'http://trac.openlayers.org/wiki/Profiles')) .'</p>';
case 'admin/structure/openlayers/styles':
return '<p>'. t('OpenLayer styles are stored versions of
<a href="@ols">javascript StyleMap objects</a>, but are much easier to
configure through an interface. Styles will typically define the icon,
fill color, border, and radius of points or polygons, so they are used
on overlays more often than base layers, which are not affected by vector
styles.', array("@ols" => 'http://trac.openlayers.org/wiki/Styles')) .'</p>';
case 'admin/structure/openlayers/styles/add':
return '<p>'. t('The name, title, and description you give a style is for Drupal\'s
interal storage. The rest of the properties are documented on openlayers.org')
. '</p>';
case 'admin/structure/openlayers/maps':
return '<p>'. t('Maps are combinations of the layers, styles, and behaviors
which constitute maps. They also contain basic configuration like the
width and centerpoint of the map - everything except for a mechanism
to put a map on a page. For that, use the Views OpenLayers Map style.') .'</p>';
case 'admin/structure/openlayers/layers':
return '<p>'. t('Layers are stored versions of javascript OpenLayers layer
objects. They point at a data source, like OpenStreetMap, Google Maps,
or Drupal itself, and sometimes define the zoom levels for which they apply.') .'</p>';
case 'admin/structure/openlayers/layers/settings':
return '<p>'. t('Commercial layer providers like Google will require API keys
to ensure that users are\'t abusing the service and to enforce limits. Not all
of these keys are required, of course, only those that are used on a site.') .'</p>';
}
}
/**
* Implements hook_permission().
*/
function openlayers_ui_permission() {
return array(
'administer openlayers' => array(
'title' => t('Administer OpenLayers'),
'description' => t('Configure OpenLayers settings, styles, maps, and layers.'),
),
);
}
/**
* Implements hook_menu
*/
function openlayers_ui_menu() {
$items = array();
// Core OpenLayers settings pages.
$items['admin/structure/openlayers'] = array(
'title' => 'OpenLayers',
'description' => 'Manage maps, layers, styles, and map behaviors.',
'page callback' => 'drupal_get_form',
'page arguments' => array('openlayers_ui_admin_settings'),
'access arguments' => array('administer openlayers'),
'file' => 'includes/openlayers_ui.admin.inc',
'type' => MENU_NORMAL_ITEM
);
$items['admin/structure/openlayers/settings'] = array(
'title' => 'Settings',
'type' => MENU_DEFAULT_LOCAL_TASK,
'weight' => -20,
);
// Layer-type-wide settings form
$items['admin/structure/openlayers/layers/settings'] = array(
'title' => 'API Keys',
'page callback' => 'drupal_get_form',
'page arguments' => array('openlayers_ui_layers_settings'),
'access arguments' => array('administer openlayers'),
'file' => 'includes/openlayers_ui.layers.inc',
'type' => MENU_LOCAL_TASK,
'weight' => -10,
);
$items['admin/structure/openlayers/callbacks/version_check/%'] = array(
'title' => 'OpenLayers Version Check',
'page callback' => 'openlayers_ui_version_check',
'page arguments' => array(5),
'access arguments' => array('administer openlayers'),
'file' => 'includes/openlayers_ui.admin.inc',
'type' => MENU_CALLBACK,
);
return $items;
}
/**
* Implements hook_theme().
*/
function openlayers_ui_theme($existing, $type, $theme, $path) {
return array(
'openlayers_ui_form_layer_description' => array(
'variables' => array(
'layer_title' => '',
'layer_description' => '',
),
'file' => 'includes/openlayers_ui.theme.inc',
),
'openlayers_ui_form_projection_description' => array(
'variables' => array(
'projection_title' => '',
'available_layers' => array(),
'layers' => array(),
),
'file' => 'includes/openlayers_ui.theme.inc',
),
'openlayers_ui_maps_form' => array(
'render element' => 'elements',
'file' => 'includes/openlayers_ui.theme.inc',
),
'openlayers_ui_maps_form_layers' => array(
'render element' => 'elements',
'file' => 'includes/openlayers_ui.theme.inc',
),
'openlayers_ui_maps_form_behaviors' => array(
'render element' => 'elements',
'file' => 'includes/openlayers_ui.theme.inc',
),
'openlayers_ui_styles_preview' => array(
'arguments' => array(
'style' => NULL,
),
'template' => 'openlayers-ui-styles-preview',
'path' => drupal_get_path('module', 'openlayers_ui') . '/themes',
),
);
}
/**
* Get projection options.
*
* @return
* Array of projection options suitable for use in a FormAPI element.
*/
function openlayers_ui_get_projection_options() {
$options = array();
foreach (openlayers_layers_load() as $key => $layer) {
if ($layer->data['projection']) {
foreach ($layer->data['projection'] as $projection) {
$options[$projection] = $projection;
}
}
}
return $options;
}
/**
* Get layer options.
*/
function openlayers_ui_get_layer_options($type = 'baselayer',
$projection = NULL) {
$options = array();
$layers = array();
// Get layers in an array
foreach (openlayers_layers_load() as $l) {
$layers[$l->name] = openlayers_get_layer_object($l);
}
// Go through layers to theme output.
foreach ($layers as $key => $layer) {
if (!is_object($layer)) continue;
// not filtering by projection
// this layer has an appropriate projection
// this layer can be reprojected because it is vector
$variables = array();
if (
!isset($projection) ||
in_array($projection, $layer->data['projection']) ||
!empty($layer->data['vector'])
) {
if ($layer->data['isBaseLayer'] == TRUE && $type == 'baselayer') {
$variables = array(
'layer_title' => $layer->title,
'layer_description' => $layer->description,
'layer_link' => $layer->export_type & EXPORT_IN_DATABASE ?
"admin/structure/openlayers/layers/list/{$layer->name}/edit" : NULL
);
}
if ($layer->data['isBaseLayer'] == FALSE && $type == 'overlay') {
$variables = array(
'layer_title' => $layer->title,
'layer_description' => $layer->description,
'layer_link' => $layer->export_type & EXPORT_IN_DATABASE ?
"admin/structure/openlayers/layers/list/{$layer->name}/edit" : NULL
);
if ($layer->data['layer_type'] == 'openlayers_views_vector') {
$variables = array(
'layer_title' => $layer->title,
'layer_description' => $layer->description,
'layer_link' => "admin/structure/views/view/{$layer->data['views']['view']}/edit/{$layer->data['views']['display']}"
);
}
}
}
if (!empty($variables)) {
$options[$key] = theme('openlayers_ui_form_layer_description', $variables);
}
}
return $options;
}
/**
* Get style options.
*
* @return
* Array of style options suitable for use in a FormAPI element.
*/
function openlayers_ui_get_style_options() {
$options = array();
foreach (openlayers_styles() as $key => $style) {
$options[$key] = $style->title;
}
return $options;
}
/**
* dependencies widget helper
* @param $dependencies
* Array of Javascript dependencies as strings of function names
* @return $form
* Form element of dependencies if any
*/
function openlayers_dependency_widget($dependencies) {
if (is_array($dependencies) > 0) {
$dependency_form = array();
foreach ($dependencies as $dependency) {
$dependency_form[] = array(
'#markup' => "<div class='openlayers-dependency-flag'>"
. "<span class='openlayers-dependency-value'>$dependency</span>"
. "<span class='openlayers-dependency-broken'>"
. t('Dependency not found:') . ' ' . $dependency . "</span>"
. "</div>"
);
}
return $dependency_form;
}
}
/**
* Create Style Preview
*
* Create a style preview given style object.
*/
function openlayers_ui_style_preview($style, $crosshairs = FALSE) {
drupal_add_js(drupal_get_path('module', 'openlayers_ui') . '/js/openlayers_ui.styles.js');
drupal_add_css(drupal_get_path('module', 'openlayers_ui') . '/openlayers_ui.css');
module_load_include('inc', 'openlayers', 'includes/openlayers.render');
openlayers_include();
// Render style data
$style->data = openlayers_render_style($style->data);
// Let's make a tiny map for a preview
drupal_add_js(array('openlayers_ui' =>
array(
'style_preview' => array(
$style->name => $style,
$style->name . '_crosshairs' => $crosshairs,
),
),
), 'setting');
return theme('openlayers_ui_styles_preview', array('style' => $style));
}
/**
* Implements hook_ctools_plugin_directory().
*/
function openlayers_ui_ctools_plugin_directory($module, $plugin) {
if ($module == 'ctools' && $plugin == 'export_ui') {
return 'plugins/' . $plugin;
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* CTools Export UI required function for plugin definition
* See function ctools_plugin_load_includes() in the module ctools.
*/
function openlayers_ui_openlayers_layers_ctools_export_ui() {
return array(
'schema' => 'openlayers_layers',
'access' => 'administer openlayers',
'menu' => array(
'menu prefix' => 'admin/structure/openlayers',
'menu item' => 'layers',
'menu title' => 'Layers',
'menu description' => 'Administer OpenLayers Layers presets.',
),
'handler' => array(
'class' => 'openlayers_layers_ui',
),
'export' => array(
'admin_title' => 'name',
'admin_description' => 'description',
),
'title singular' => t('layer'),
'title plural' => t('layers'),
'title singular proper' => t('OpenLayers Layer preset'),
'title plural proper' => t('OpenLayers Layers presets'),
'strings' => array(
'confirmation' => array(
'add' => array(
'success' => t('Layer saved.'),
),
'delete' => array(
'success' => t('Layer was deleted.'),
)
)
),
);
}

View File

@@ -0,0 +1,272 @@
<?php
/**
* @file
*/
class openlayers_layers_ui extends ctools_export_ui {
function edit_form(&$form, &$form_state) {
parent::edit_form($form, $form_state);
$layer_types = openlayers_layer_types();
$options = array('' => t('Select the layer type'));
$layer = NULL;
if ($form_state['op'] == 'edit' && $form_state['form type'] == 'edit') {
$layer = openlayers_layer_load($form_state['item']->name);
}
if ($form_state['op'] == 'add' && $form_state['form type'] == 'clone') {
$layer = openlayers_layer_load($form_state['function args'][2]->name);
$layer->title = t('Clone of ') . $layer->title;
}
$form['info']['title'] = array(
'#id' => 'layertitle',
'#type' => 'textfield',
'#weight' => -1,
'#title' => t('Layer Title'),
'#default_value' => isset($layer->title) ? $layer->title : '',
'#description' => t('The friendly name of your layer, which will appear in the administration interface as well on the map interface if it is exposed.'),
);
$form['info']['name']['#machine_name']['source'] = array('info', 'title');
$layers_options = array();
// Go trough all layer types and get each options form.
foreach ($layer_types as $layer_type) {
if (is_object($layer) && get_class($layer) == $layer_type['layer_type']['class']) {
// Layer is of current layer type.
$layer_type_object = $layer;
} else {
// Otherwise load layer object for current layer type.
$layer_type_object = openlayers_layer_type_load($layer_type['name']);
}
$layer_options_form = array();
if (method_exists($layer_type_object, 'options_form')) {
// This is because the class openlayers_layer_type
// is not abstract.
// Maybe there's a better way to do ?
$parent = get_parent_class($layer_type_object);
$parent_object = new $parent;
$layer_options_form = $layer_type_object->options_form() + $parent_object->options_form($layer);
}
if ($layer_type_object == FALSE || empty($layer_options_form)) {
continue;
}
$layers_option = array(
'#type' => 'fieldset',
'#tree' => TRUE,
'#title' => t('Layer specific options for @layer_title', array('@layer_title' => $layer_type['title'])),
);
$layers_option += $layer_options_form;
$layers_option['#states'] = array(
'visible' => array(
':input[name="layer_type"]' => array('value' => $layer_type['name']),
),
);
$layers_option['layer_type'] = array(
'#type' => 'hidden',
'#value' => $layer_type['name'],
);
$layers_options[$layer_type['name']] = $layers_option;
$options[$layer_type['name']] = $layer_type['title'];
}
$form['layer_type'] = array(
'#type' => 'select',
'#title' => t('Layer Type'),
'#default_value' => isset($layer->data['layer_type']) ? $layer->data['layer_type']: '',
'#description' => t('Select the type of layer.'),
'#options' => $options,
);
$form += $layers_options;
}
function edit_form_validate(&$form, &$form_state) {
$layer = openlayers_layer_type_load($form_state['values']['layer_type']);
$form_state['values']['data'] = $form_state['values'][$form_state['values']['layer_type']];
if (empty($form_state['values']['layer_type'])) {
form_set_error('layer_type', 'Layer type cannot be empty.');
}
$parent = get_parent_class($layer);
$parent_object = new $parent;
$form_state['values']['data'] += $layer->options_init();
$form_state['values']['data'] += $parent_object->options_init();
$layer_types = openlayers_layer_types();
foreach($layer_types as $layer_type) {
unset($form_state['values'][$layer_type['name']]);
}
unset($form_state['values']['layer_type']);
if (method_exists($layer, 'options_form_validate')) {
$layer->options_form_validate($form, $form_state['values']);
}
parent::edit_form_validate($form, $form_state);
}
/**
* Prepare the tag values before they are added to the database.
*/
function edit_form_submit(&$form, &$form_state) {
$layer = openlayers_layer_type_load($form_state['values']['data']['layer_type']);
if (method_exists($layer, 'options_form_submit')) {
$layer->options_form_submit($form, $form_state);
}
parent::edit_form_submit($form, $form_state);
}
/**
* Deletes exportable items from the database.
*/
function delete_form_submit(&$form_state) {
$item = $form_state['item'];
$layer = openlayers_layer_type_load($item->data['layer_type']);
if (method_exists($layer, 'delete')) {
$layer->delete($item);
}
parent::delete_form_submit($form_state);
}
/**
* hook_menu() entry point.
*
* Child implementations that need to add or modify menu items should
* probably call parent::hook_menu($items) and then modify as needed.
*/
function hook_menu(&$items) {
parent::hook_menu($items);
$items['admin/structure/openlayers/layers']['type'] = MENU_LOCAL_TASK;
}
/**
* Build a row based on the item.
*
* By default all of the rows are placed into a table by the render
* method, so this is building up a row suitable for theme('table').
* This doesn't have to be true if you override both.
*/
function list_build_row($item, &$form_state, $operations) {
// Set up sorting
$name = $item->{$this->plugin['export']['key']};
$schema = ctools_export_get_schema($this->plugin['schema']);
$layers_types = openlayers_layer_types();
if (!isset($layers_types[$item->data['layer_type']])) {
return;
}
// Note: $item->{$schema['export']['export type string']} should have already been set up by export.inc so
// we can use it safely.
switch ($form_state['values']['order']) {
case 'disabled':
$this->sorts[$name] = empty($item->disabled) . $name;
break;
case 'title':
$this->sorts[$name] = $item->{$this->plugin['export']['admin_title']};
break;
case 'name':
$this->sorts[$name] = $name;
break;
case 'storage':
$this->sorts[$name] = $item->{$schema['export']['export type string']} . $name;
break;
}
$this->rows[$name]['data'] = array();
$this->rows[$name]['class'] = !empty($item->disabled) ? array('ctools-export-ui-disabled') : array('ctools-export-ui-enabled');
// If we have an admin title, make it the first row.
if (!empty($this->plugin['export']['admin_title'])) {
$this->rows[$name]['data'][] = array('data' => check_plain($item->{$this->plugin['export']['admin_title']}), 'class' => array('ctools-export-ui-title'));
}
$this->rows[$name]['data'][] = array('data' => $item->title, 'class' => array('ctools-export-ui-title'));
$this->rows[$name]['data'][] = array('data' => $layers_types[$item->data['layer_type']]['title'], 'class' => array('ctools-export-ui-layer-type'));
$this->rows[$name]['data'][] = array('data' => $item->description, 'class' => array('ctools-export-ui-description'));
$this->rows[$name]['data'][] = array('data' => check_plain($item->{$schema['export']['export type string']}), 'class' => array('ctools-export-ui-storage'));
// This should be in the module openlayers_views, but I'm still looking
// for a solution to do it properly.
// Temporarily removed.
/*
if ($item->data['layer_type'] == 'openlayers_views_vector') {
$operations['edit']['href'] = 'admin/structure/views/view/' . $item->data['views']['view'] . '/edit/' . $item->data['views']['display'];
$operations['disable']['href'] = 'admin/structure/views/view/' . $item->data['views']['view'] . '/disable/' . $item->data['views']['display'];
$operations['clone']['href'] = 'admin/structure/views/view/' . $item->data['views']['view'] . '/clone/' . $item->data['views']['display'];
$operations['export']['href'] = 'admin/structure/views/view/' . $item->data['views']['view'] . '/export/' . $item->data['views']['display'];
}
*/
$ops = theme('links__ctools_dropbutton', array('links' => $operations, 'attributes' => array('class' => array('links', 'inline'))));
$this->rows[$name]['data'][] = array('data' => $ops, 'class' => array('ctools-export-ui-operations'));
// Add an automatic mouseover of the description if one exists.
if (!empty($this->plugin['export']['admin_description'])) {
$this->rows[$name]['title'] = $item->{$this->plugin['export']['admin_description']};
}
}
/**
* Provide the table header.
*
* If you've added columns via list_build_row() but are still using a
* table, override this method to set up the table header.
*/
function list_table_header() {
$header = array();
if (!empty($this->plugin['export']['admin_title'])) {
$header[] = array('data' => t('Name'), 'class' => array('ctools-export-ui-name'));
}
$header[] = array('data' => t('Title'), 'class' => array('ctools-export-ui-title'));
$header[] = array('data' => t('Type'), 'class' => array('ctools-export-ui-layer-type'));
$header[] = array('data' => t('Description'), 'class' => array('ctools-export-ui-description'));
$header[] = array('data' => t('Storage'), 'class' => array('ctools-export-ui-storage'));
$header[] = array('data' => t('Operations'), 'class' => array('ctools-export-ui-operations'));
return $header;
}
/**
* Provide a list of sort options.
*
* Override this if you wish to provide more or change how these work.
* The actual handling of the sorting will happen in build_row().
*/
function list_sort_options() {
if (!empty($this->plugin['export']['admin_title'])) {
$options = array(
'disabled' => t('Enabled, title'),
$this->plugin['export']['admin_title'] => t('Title'),
);
}
else {
$options = array(
'disabled' => t('Enabled, title'),
);
}
$options += array(
'storage' => t('Storage'),
);
return $options;
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* CTools Export UI required function for plugin definition
* See function ctools_plugin_load_includes() in the module ctools.
*/
function openlayers_ui_openlayers_maps_ctools_export_ui() {
return array(
'schema' => 'openlayers_maps',
'access' => 'administer openlayers',
'menu' => array(
'menu prefix' => 'admin/structure/openlayers',
'menu item' => 'maps',
'menu title' => 'Maps',
'menu description' => 'Administer OpenLayers Maps presets.',
),
'handler' => array(
'class' => 'openlayers_maps_ui'
),
'export' => array(
'admin_title' => 'name',
'admin_description' => 'description',
),
'title singular' => t('map'),
'title plural' => t('maps'),
'title singular proper' => t('Openlayers Map preset'),
'title plural proper' => t('Openlayers Maps presets'),
'strings' => array(
'confirmation' => array(
'add' => array(
'success' => t('Map saved.'),
),
'delete' => array(
'success' => t('Map was deleted.'),
)
)
),
);
}

View File

@@ -0,0 +1,726 @@
<?php
/**
* @file
*/
class openlayers_maps_ui extends ctools_export_ui {
function edit_form(&$form, &$form_state) {
parent::edit_form($form, $form_state);
$map = $form_state['item'];
if (empty($map->name)) {
$map = NULL;
}
module_load_include('inc', 'openlayers_ui', 'includes/openlayers_ui.maps');
openlayers_include();
ctools_include('dependent');
drupal_add_js(drupal_get_path('module', 'openlayers_ui') .
'/js/openlayers_ui.maps.js');
drupal_add_css(drupal_get_path('module', 'openlayers_ui') .
'/openlayers_ui.css');
// If cloning or editing, attempt to get map.
$defaults = array();
if (empty($map)) {
$default_map = openlayers_map_load(variable_get('openlayers_default_map', 'default'));
if ($default_map) {
$defaults = $default_map->data;
}
}
else {
$defaults = $map->data;
}
// Map preview. It's a little in the way, so we allow the user
// to turn it on or off. Show on preview, otherwise look at setting.
// Might want to look at disableing the mousewheel zoom since
// the map could be very in the way.
if ( (isset($form_state['clicked_button']['#id'])
&& ($form_state['clicked_button']['#id'] == 'edit-buttons-preview'))
|| (variable_get('openlayers_ui_preview_map', TRUE))) {
$map_preview = isset($form_state['values']) ? openlayers_ui_maps_form_process($form_state['values']) : $map;
$form['preview'] = array(
'#tree' => FALSE,
'#type' => 'fieldset',
'#title' => t('Preview'),
'#description' => t('The following is a preview of your map. Click <em>Preview</em>
to refresh the map with the new values. ' .
(!variable_get('openlayers_ui_preview_map', FALSE) ?
t('Turn map previews on by default on the !link.',
array('!link' => l(t('Settings page'), 'admin/structure/openlayers/settings'))) : ''
)
),
);
$form['preview']['map'] = array(
'#markup' => openlayers_render_map($map_preview),
);
} else {
$form['preview'] = array();
$form['preview']['map'] = array(
'#markup' => '<p>' . t('Turn map previews on by default on the !link.',
array('!link' => l(t('Settings page'), 'admin/structure/openlayers/settings'))) . '</p>',
);
}
// Utilize vertical tabs for a better interface.
$form['ui'] = array(
'#type' => 'vertical_tabs',
'#default_tab' => 'info'
);
// General map information.
$form['info']['#type'] = 'fieldset';
$form['info']['#group'] = 'ui';
$form['info']['#title'] = 'Infos';
$form['info']['title'] = array(
'#id' => 'maptitle',
'#type' => 'textfield',
'#title' => t('Map Title'),
'#description' => t('This is the descriptive title of the map and will show up most often in the interface.'),
'#maxlength' => 255,
'#default_value' => !empty($map->title) ? $map->title : '',
'#required' => TRUE,
'#weight' => -1
);
$form['info']['name']['#machine_name']['source'] = array('info', 'title');
$form['info']['width'] = array(
'#type' => 'textfield',
'#title' => t('Width'),
'#description' => t('The map\'s width. "auto" will make the map fill
the space it is given; otherwise, enter a value in pixels, like 400px.'),
'#default_value' => !empty($defaults['width']) ? $defaults['width'] : '',
'#maxlength' => 128,
'#required' => TRUE,
);
$form['info']['height'] = array(
'#type' => 'textfield',
'#title' => t('Height'),
'#description' => t('The map\'s height. Enter a value in pixels,
like 400px.'),
'#default_value' => !empty($defaults['height']) ? $defaults['height'] : '',
'#maxlength' => 128,
'#required' => TRUE,
);
// Only show this if Openlayers Views is enabled
if (module_exists('openlayers_views')) {
$form['info']['hide_empty_map'] = array(
'#type' => 'checkbox',
'#title' => t('Hide empty map for Views'),
'#description' => t("Show views empty text or hide the map if there are
no map overlays with features. Otherwise an empty map is displayed."),
'#default_value' => isset($defaults['hide_empty_map']) ?
$defaults['hide_empty_map'] : FALSE,
);
}
$default_image_path = drupal_get_path('module', 'openlayers') . '/themes/default_dark/img/';
$form['info']['image_path'] = array(
'#type' => 'textfield',
'#title' => t('Image Path'),
'#description' => t('<p>The path to a directory of UI graphics. Use any of the
following:</p>
<ul>
<li><strong>Leave blank</strong> for default graphics as provided
by the OpenLayers library. </li>
<li><strong>Relative Drupal path</strong> a path without leading slash and
the base path will be prepended, ex. "sites/all/themes/path/to/images/"</li>
<li><strong>Absolute path</strong> a path with leading slash and path will
start from sites root directory, ex. "/path/to/images/"</li>
<li><strong>Full URL</strong> such as "http://example.com/image/"</li>
</ul>
<p>Always include trailing slash. The default path provided with this module
is: %default</p>
<p><strong>This is actually a setting for the OpenLayers
object and will affect all maps on the same page.</strong></p>',
array('%default' => $default_image_path)
),
'#default_value' => !empty($defaults['image_path']) ?
$defaults['image_path'] : '',
);
$default_css_path = drupal_get_path('module', 'openlayers') . '/themes/default_dark/style.css';
$form['info']['css_path'] = array(
'#type' => 'textfield',
'#title' => t('CSS Path'),
'#description' => t('<p>The path to a CSS file for overriding CSS. You
don\'t really need to override this as CSS is almost always overridable.
Use any of the following:</p>
<ul>
<li><strong>Leave blank</strong> for default hosted OpenLayers which
is !link</li>
<li><strong>Relative Drupal path</strong> a path without leading slash and
the base path will be prepended, ex. "sites/all/themes/path/to/style.css"</li>
<li><strong>Absolute path</strong> a path with leading slash and path will
start from sites root directory, ex. "/path/to/style.css"</li>
<li><strong>Full URL</strong> such as "http://example.com/style.css"</li>
</ul>
<p>The default path provided with this module
is: %default</p>
<p><strong>This is actually a setting for the OpenLayers
object and will affect all maps on the same page.</strong></p>',
array(
'!link' => l('http://openlayers.org/api/theme/default/style.css',
'http://openlayers.org/api/theme/default/style.css'),
'%default' => $default_css_path,
)
),
'#default_value' => !empty($defaults['css_path']) ?
$defaults['css_path'] : '',
);
$form['info']['proxy_host'] = array(
'#type' => 'textfield',
'#title' => t('Proxy Host'),
'#description' => t('<p>A proxy (typically on the same domain as this site)
which enables requests to cross-domain AJAX resources (including remote
KML). Use any of the following:</p>
<ul>
<li><strong>Leave blank</strong> no proxy path.</li>
<li><strong>Relative Drupal path</strong> a path without leading slash and
the base path will be prepended, ex. "proxy?request="</li>
<li><strong>Absolute path</strong> a path with leading slash and path will
start from sites root directory, ex. "/cgi_proxy?request="</li>
<li><strong>Full URL</strong> such as "http://example.com/proxy?request="</li>
</ul>
<p><strong>This is actually a setting for the OpenLayers
object and will affect all maps on the same page.</strong></p>'
),
'#default_value' => !empty($defaults['proxy_host']) ?
$defaults['proxy_host'] : '',
);
// Center
$form['center'] = array(
'#title' => t('Center & Bounds'),
'#description' => t('Where the map will center itself initially.
<strong>Shift-drag</strong> a box on the map to set the Restricted Extent.'),
'#tree' => TRUE,
'#type' => 'fieldset',
'#group' => 'ui'
);
$form['center']['helpmap'] = array(
'#markup' => '<div class="form-item openlayers-center-helpmap"
style="display:block">' .
openlayers_ui_maps_form_center_map($defaults) . '</div>'
);
$form['center']['initial'] = array(
'#type' => 'fieldset',
'#title' => t('Initial Map View')
);
$form['center']['initial']['centerpoint'] = array(
'#type' => 'textfield',
'#title' => t('Centerpoint'),
'#description' => t('Coordinates that are the intial focus of the map. This
is formated like <em>longitude,latitude</em>.'),
'#default_value' => $defaults['center']['initial']['centerpoint'],
'#attributes' => array('class' => array('openlayers-form-centerpoint')),
'#size' => 25,
);
$form['center']['initial']['zoom'] = array(
'#type' => 'textfield',
'#title' => t('Zoom Level'),
'#description' => t('Initial Zoom Level when the map intially displays.
Higher is more zoomed in.'),
'#default_value' => $defaults['center']['initial']['zoom'],
'#attributes' => array('class' => array('openlayers-form-zoom')),
'#size' => 25,
);
$form['center']['restrict'] = array(
'#type' => 'fieldset',
'#title' => t('Restrict Extent')
);
$form['center']['restrict']['restrictextent'] = array(
'#type' => 'checkbox',
'#title' => t('Restrict Extent'),
'#description' => t('Setting the restricted extent of a map prevents users
from panning the map outside a specified area. This can be set
interactively by <strong>holding the shift key and dragging a box</strong> over the map
above. Setting the extent does not restrict how far users can zoom out,
so setting restricted zoom levels (via individual layer settings) is
recommended.'),
'#id' => 'restrictextent',
'#default_value' => isset($defaults['center']['restrict']['restrictextent']) ?
$defaults['center']['restrict']['restrictextent'] : '',
);
$form['center']['restrict']['restrictedExtent'] = array(
'#type' => 'textfield',
'#title' => t('Restricted Extent'),
'#description' => t('Prevents users from panning outside of a specific bounding box'),
'#default_value' => isset($defaults['center']['restrict']['restrictedExtent']) ?
$defaults['center']['restrict']['restrictedExtent'] : '',
'#attributes' => array('class' => array('openlayers-form-restrictedExtent')),
'#size' => 25,
'#process' => array('ctools_dependent_process'),
'#dependency' => array('restrictextent' => array(1))
);
// Layers & styles
$form['layerstyles'] = array(
'#title' => t('Layers & Styles'),
'#description' => t('Layer settings. The Layer options will change based on the projection chosen.'),
'#theme' => 'openlayers_ui_maps_form_layers',
'#tree' => FALSE,
'#type' => 'fieldset',
'#group' => 'ui'
);
// Projection options
$projections = array();
foreach (openlayers_ui_get_projection_options() as $projection) {
$projection_layers = array_merge(
openlayers_ui_get_layer_options('baselayer', $projection),
openlayers_ui_get_layer_options('overlay', $projection));
$projections[$projection] = theme(
'openlayers_ui_form_projection_description',
array(
'projection_title' => $projection,
'available_layers' => array_keys($projection_layers)
)
);
}
// Construct data for theme_openlayers_ui_maps_form_layers
$form['layerstyles']['layers']['#tree'] = TRUE;
$form['layerstyles']['layers']['baselabels'] = array();
$base_options = openlayers_ui_get_layer_options('baselayer', $defaults['projection']);
foreach ($base_options as $id => $description) {
$form['layerstyles']['layers']['baselabels'][$id] =
array('#markup' => $description);
}
$form['layerstyles']['layers']['baselayers'] = array(
'#type' => 'checkboxes',
'#options' => $base_options,
'#default_value' => !empty($defaults['layers']) ?
array_intersect_key($defaults['layers'], $base_options) :
array()
);
$form['layerstyles']['layers']['default_layer'] = array(
'#type' => 'radios',
'#options' => $base_options,
'#default_value' => !empty($defaults['default_layer']) &&
isset($base_options[$defaults['default_layer']]) ?
$defaults['default_layer'] :
NULL,
);
// Overlay layers
$overlay_options = openlayers_ui_get_layer_options('overlay', $defaults['projection']);
$form['layerstyles']['layers']['overlaylabels'] = array();
if (!empty($overlay_options)) {
// Have enabled layers maintain their order
$available = array_keys($overlay_options);
$enabled = array_intersect(array_keys($defaults['layers']), $available);
$disabled = array_diff($available, $enabled);
$overlay_options_keys = array_merge($disabled, $enabled);
// Create overlay options.
$form['layerstyles']['layer_styles']['#tree'] = TRUE;
$form['layerstyles']['layer_styles_select']['#tree'] = TRUE;
$form['layerstyles']['layer_weight']['#tree'] = TRUE;
foreach ($overlay_options_keys as $id) {
$description = $overlay_options[$id];
$form['layerstyles']['layers']['overlaylabels'][$id] = array('#markup' => $description);
// Layer styles tha define the default style of layer.
$form['layerstyles']['layer_styles'][$id] = array(
'#type' => 'select',
'#options' => array('<' . t('use default style') . '>') + openlayers_ui_get_style_options(),
'#default_value' => !empty($defaults['layer_styles'][$id]) ?
$defaults['layer_styles'][$id] : '',
);
// Layer select style.
$form['layerstyles']['layer_styles_select'][$id] = array(
'#type' => 'select',
'#options' => array('<' . t('use default style') . '>') + openlayers_ui_get_style_options(),
'#default_value' => !empty($defaults['layer_styles_select'][$id]) ?
$defaults['layer_styles_select'][$id] : '',
);
// Weight of layer. This will affect how the layer shows up in the
// switcher and is rendered.
$form['layerstyles']['layer_weight'][$id] = array(
'#type' => 'weight',
'#default_value' => !empty($defaults['layer_weight'][$id]) ? $defaults['layer_weight'][$id] : 0,
'#attributes' => array(
'class' => array('layer-weight')
)
);
}
// Checkbox options for overlay layers.
$form['layerstyles']['layers']['overlays'] = array(
'#type' => 'checkboxes',
'#options' => $overlay_options,
'#default_value' => !empty($defaults['layers']) ?
array_intersect_key($defaults['layers'], $overlay_options) : array(),
);
$form['layerstyles']['layer_activated'] = array(
'#type' => 'checkboxes',
'#options' => $overlay_options,
'#default_value' => !empty($defaults['layer_activated']) ?
array_intersect_key($defaults['layer_activated'], $overlay_options) : array(),
);
$form['layerstyles']['layer_switcher'] = array(
'#type' => 'checkboxes',
'#options' => $overlay_options,
'#default_value' => !empty($defaults['layer_switcher']) ?
array_intersect_key($defaults['layer_switcher'], $overlay_options) : array(),
);
}
// Data overlay help.
$form['layerstyles']['help_data_overlays'] = array(
'#type' => 'item',
'#description' => t('<strong>Add Data Overlays</strong>: You can add regular
overlays, like <a href="!geojson">GeoJSON</a> or <a href="!kml">KML</a>,
or you can utilize <a href="!views_url">Views</a> to create data overlays.
To create a Views-based overlay, you must choose the <strong>OpenLayers
Data Overlay Display Type</strong>, and then explicitly set the the
<strong>same for the Format</strong>. The options in the <em>Format
Settings</em> will only use fields you have added. To learn more, take
a look at the <a href="!online_url">online documentation on Drupal.org</a>.',
array(
'!views_url' => url('admin/structure/views'),
'!geojson' => url('admin/structure/openlayers/layers/add/openlayers_layer_type_geojson'),
'!kml' => url('admin/structure/openlayers/layers/add/openlayers_layer_type_kml'),
'!online_url' => url('http://drupal.org/node/595872'),
)
),
);
// Styles
$form['layerstyles']['styles'] = array(
'#type' => 'fieldset',
'#title' => t('Default Styles'),
'#description' => t('Define default style designations for layers when there
are no overrides.'),
'#tree' => TRUE,
);
$form['layerstyles']['styles']['default'] = array(
'#type' => 'select',
'#title' => t('Default style'),
'#description' => t('Default style for features in a vector.'),
'#options' => openlayers_ui_get_style_options(),
'#default_value' => !empty($defaults['styles']['default']) ?
$defaults['styles']['default'] : NULL,
);
$form['layerstyles']['styles']['select'] = array(
'#type' => 'select',
'#title' => t('Select style'),
'#description' => t('Style for features in a vector that are selected.'),
'#options' => openlayers_ui_get_style_options(),
'#default_value' => !empty($defaults['styles']['select']) ?
$defaults['styles']['select'] : NULL,
);
$form['layerstyles']['styles']['temporary'] = array(
'#type' => 'select',
'#title' => t('Temporary Style'),
'#description' => t('Default style for any temporary features in a vector.
This will also be used for rollovers for things like Tooltips.'),
'#options' => openlayers_ui_get_style_options(),
'#default_value' => !empty($defaults['styles']['temporary']) ?
$defaults['styles']['temporary'] : NULL,
);
// TODO: This projection stuff sucks. See
// http://drupal.org/node/1331410
//
// Grab default from submitted form values on AHAH rebuild.
// Start AHAH Wrapper
/*
$form['layerstyles']['ahah-start'] = array('#value' => '<div id="openlayers-layers-select">');
if (isset($form_state['values']['projections'])) {
if ($form_state['values']['projections']['easy_projection'] == 'other') {
$defaults['projection'] = $form_state['values']['projections']['projection'];
}
else {
$defaults['projection'] = $form_state['values']['projections']['easy_projection'];
}
}
*/
// Just kind of hide the projection stuff for now.
$form['layerstyles']['projections'] = array(
'#type' => 'fieldset',
'#title' => t('Projections'),
'#description' => t('<p><strong>WARNING: Projections are not well supported in
this module. If you need to handle non spherical mercator projections
you may be better using the API directly.</strong></p>
<p>Select the EPSG code of the !link_proj for your map. The list next
to each projection is the layers that support this projection.</p>',
array('!link_proj' => l(t('geographical projection'),
'http://en.wikipedia.org/wiki/Map_projection'))
),
'#tree' => TRUE,
);
$form['layerstyles']['projections']['easy_projection'] = array(
'#type' => 'radios',
'#title' => t('Map Projection'),
'#description' => t('The !link_proj of this map: all layers will either be requested or reprojected to this format.', array(
'!link_proj' => l(
t('geographical projection'),
'http://en.wikipedia.org/wiki/Map_projection'),
)),
'#default_value' => isset($defaults['projection']) ? $defaults['projection'] : '900913',
'#options' => $projections,
'#attributes' => array('class' => array('openlayers-form-easy-projection')),
);
$form['layerstyles']['projections']['displayProjection'] = array(
'#type' => 'textfield',
'#title' => t('Display Projection'),
'#description' => t('All interaction with the map - drawing, panning,
centering, and more - occurs in the display projection. The vast majority
of maps use 4326 (latitude/longitude) for this value.'),
'#default_value' => !empty($defaults['displayProjection']) ?
$defaults['displayProjection'] : '4326',
'#maxlength' => 6
);
// Behaviors
$form['behaviors'] = array(
'#title' => t('Behaviors'),
'#description' => t('Configure interactive map behaviors. Behaviors are general interactions for the map, they can be anything from popups or keyboard handling. Enable the ones you want and their respective options. Note that some behaviors do not work with each other or one may encompass another.'),
'#theme' => 'openlayers_ui_maps_form_behaviors',
'#tree' => TRUE,
'#type' => 'fieldset',
'#group' => 'ui'
);
$form['behaviors'] = $form['behaviors'] + openlayers_ui_get_behavior_options('map', $defaults);
// Displays
$form['displays'] = array(
'#title' => t('Displays'),
'#description' => t('Learn how to display your maps.'),
'#tree' => TRUE,
'#type' => 'fieldset',
'#group' => 'ui'
);
if (module_exists('openlayers_views')) {
$form['displays']['views'] = array(
'#type' => 'item',
'#title' => t('Views'),
'#description' => t('Utilize the <a href="!views_url">Views</a> module to
display your map as page or in a block. By creating a new Views Display of
type <strong>Page</strong> or <strong>Block</strong> you can then choose
the <strong>OpenLayers Map Format</strong>. For more details, check out
the <a href="!online_url">online documentation on Drupal.org</a>.',
array(
'!views_url' => url('admin/structure/views'),
'!online_url' => url('http://drupal.org/node/595872')
)
),
'#suffix' => theme('image', array('path' =>
'https://img.skitch.com/20111106-c6ukwxgpgykxx8m41yrn8qew4n.png')),
);
$form['displays']['api'] = array(
'#type' => 'item',
'#title' => t('API'),
'#description' => t('You can always utilize the API to directly display
your maps. The key function to use is <code>openlayers_render_map()</code>.
Most of the code is well documented. To learn how to extend the module,
take a look at the <a href="!online_url">online documentation on
Drupal.org</a> as well as the files in the <code>docs/</code> folder.',
array('!online_url' => url('http://drupal.org/node/595872'))
),
);
}
$form['buttons']['submit']['#weight'] = 0;
$form['buttons']['delete']['#weight'] = 20;
$form['buttons']['saveandedit'] = array(
'#type' => 'submit',
'#value' => t('Save and edit'),
'#weight' => 10
);
// Add preview button.
$form['buttons']['preview'] = array(
'#type' => 'button',
'#value' => t('Preview'),
'#weight' => 30
);
}
/**
* Prepare the tag values before they are added to the database.
*/
function edit_form_submit(&$form, &$form_state) {
module_load_include('inc', 'openlayers_ui', 'includes/openlayers_ui.maps');
$form_state['values']['data'] = openlayers_ui_maps_form_process($form_state['values']);
parent::edit_form_submit($form, $form_state);
}
/**
* Implements ctools_export_ui::edit_execute_form().
*
* This is hacky, but since CTools Export UI uses drupal_goto() we have to
* effectively change the plugin to modify the redirect path dynamically.
*/
function edit_execute_form(&$form_state) {
$output = parent::edit_execute_form($form_state);
if (!empty($form_state['executed'])) {
$clicked = $form_state['clicked_button']['#value'];
if (t('Save and edit') == $clicked) {
// We always want to redirect back to this page when adding an item,
// but we want to preserve the destination so we can be redirected back
// to where we came from after clicking "Save".
$options = array();
if (!empty($_GET['destination'])) {
$options['query']['destination'] = $_GET['destination'];
unset($_GET['destination']);
}
// Sets redirect path and options.
$op = $form_state['op'];
$name = $form_state['values']['name'];
$path = ('add' != $op) ? current_path() : 'admin/structure/openlayers/maps/list/' . $name . '/edit';
$this->plugin['redirect'][$op] = array($path, $options);
}
}
return $output;
}
/**
* Build a row based on the item.
*
* By default all of the rows are placed into a table by the render
* method, so this is building up a row suitable for theme('table').
* This doesn't have to be true if you override both.
*/
function list_build_row($item, &$form_state, $operations) {
// Set up sorting
$name = $item->{$this->plugin['export']['key']};
$schema = ctools_export_get_schema($this->plugin['schema']);
// Note: $item->{$schema['export']['export type string']} should have already been set up by export.inc so
// we can use it safely.
switch ($form_state['values']['order']) {
case 'disabled':
$this->sorts[$name] = empty($item->disabled) . $name;
break;
case 'title':
$this->sorts[$name] = $item->{$this->plugin['export']['admin_title']};
break;
case 'name':
$this->sorts[$name] = $name;
break;
case 'storage':
$this->sorts[$name] = $item->{$schema['export']['export type string']} . $name;
break;
}
$this->rows[$name]['data'] = array();
$this->rows[$name]['class'] = !empty($item->disabled) ? array('ctools-export-ui-disabled') : array('ctools-export-ui-enabled');
// If we have an admin title, make it the first row.
if (!empty($this->plugin['export']['admin_title'])) {
$this->rows[$name]['data'][] = array('data' => check_plain($item->{$this->plugin['export']['admin_title']}), 'class' => array('ctools-export-ui-title'));
}
$layers = openlayers_layers_load();
$layers_names = array();
foreach ($item->data['layers'] as $layer) {
if (isset($layers[$layer])) {
$layers_names[] = empty($layers[$layer]->title) ? $layer : filter_xss_admin($layers[$layer]->title);
}
}
sort($layers_names);
$layers_names = implode(',', $layers_names);
$this->rows[$name]['data'][] = array('data' => $item->title, 'class' => array('ctools-export-ui-title'));
$this->rows[$name]['data'][] = array('data' => $layers_names, 'class' => array('ctools-export-ui-layers'));
$this->rows[$name]['data'][] = array('data' => $item->description, 'class' => array('ctools-export-ui-description'));
$this->rows[$name]['data'][] = array('data' => check_plain($item->{$schema['export']['export type string']}), 'class' => array('ctools-export-ui-storage'));
$ops = theme('links__ctools_dropbutton', array('links' => $operations, 'attributes' => array('class' => array('links', 'inline'))));
$this->rows[$name]['data'][] = array('data' => $ops, 'class' => array('ctools-export-ui-operations'));
// Add an automatic mouseover of the description if one exists.
if (!empty($this->plugin['export']['admin_description'])) {
$this->rows[$name]['title'] = $item->{$this->plugin['export']['admin_description']};
}
}
/**
* Provide the table header.
*
* If you've added columns via list_build_row() but are still using a
* table, override this method to set up the table header.
*/
function list_table_header() {
$header = array();
if (!empty($this->plugin['export']['admin_title'])) {
$header[] = array('data' => t('Name'), 'class' => array('ctools-export-ui-name'));
}
$header[] = array('data' => t('Title'), 'class' => array('ctools-export-ui-title'));
$header[] = array('data' => t('Layers'), 'class' => array('ctools-export-ui-layers'));
$header[] = array('data' => t('Description'), 'class' => array('ctools-export-ui-description'));
$header[] = array('data' => t('Storage'), 'class' => array('ctools-export-ui-storage'));
$header[] = array('data' => t('Operations'), 'class' => array('ctools-export-ui-operations'));
return $header;
}
/**
* hook_menu() entry point.
*
* Child implementations that need to add or modify menu items should
* probably call parent::hook_menu($items) and then modify as needed.
*/
function hook_menu(&$items) {
parent::hook_menu($items);
$items['admin/structure/openlayers/maps']['type'] = MENU_LOCAL_TASK;
$items['admin/structure/openlayers/maps/list/%ctools_export_ui/clone']['context'] = MENU_CONTEXT_INLINE;
$items['admin/structure/openlayers/maps/list/%ctools_export_ui/edit']['context'] = MENU_CONTEXT_INLINE;
$items['admin/structure/openlayers/maps/list/%ctools_export_ui/export']['context'] = MENU_CONTEXT_INLINE;
$items['admin/structure/openlayers/maps/list/%ctools_export_ui/revert']['context'] = MENU_CONTEXT_INLINE;
$items['admin/structure/openlayers/maps/list/%ctools_export_ui/clone']['type'] = MENU_LOCAL_TASK;
$items['admin/structure/openlayers/maps/list/%ctools_export_ui/edit']['type'] = MENU_LOCAL_TASK;
$items['admin/structure/openlayers/maps/list/%ctools_export_ui/export']['type'] = MENU_LOCAL_TASK;
$items['admin/structure/openlayers/maps/list/%ctools_export_ui/revert']['type'] = MENU_LOCAL_TASK;
}
/**
* Provide a list of sort options.
*
* Override this if you wish to provide more or change how these work.
* The actual handling of the sorting will happen in build_row().
*/
function list_sort_options() {
if (!empty($this->plugin['export']['admin_title'])) {
$options = array(
'disabled' => t('Enabled, title'),
$this->plugin['export']['admin_title'] => t('Title'),
);
}
else {
$options = array(
'disabled' => t('Enabled, title'),
);
}
$options += array(
'storage' => t('Storage'),
);
return $options;
}
}

View File

@@ -0,0 +1,42 @@
<?php
/**
* CTools Export UI required function for plugin definition
* See function ctools_plugin_load_includes() in the module ctools.
*/
function openlayers_ui_openlayers_styles_ctools_export_ui() {
return array(
'schema' => 'openlayers_styles',
'access' => 'administer openlayers',
'menu' => array(
'menu prefix' => 'admin/structure/openlayers',
'menu item' => 'styles',
'menu title' => 'Styles',
'menu description' => 'Administer OpenLayers Styles presets.',
),
'handler' => array(
'class' => 'openlayers_styles_ui',
),
'export' => array(
'admin_title' => 'name',
'admin_description' => 'description',
),
'title singular' => t('style'),
'title plural' => t('styles'),
'title singular proper' => t('OpenLayers Style preset'),
'title plural proper' => t('OpenLayers Styles presets'),
'strings' => array(
'confirmation' => array(
'add' => array(
'success' => t('Style saved.'),
),
'delete' => array(
'success' => t('Style was deleted.'),
)
)
),
);
}

View File

@@ -0,0 +1,445 @@
<?php
/**
* @file
*/
class openlayers_styles_ui extends ctools_export_ui {
function edit_form(&$form, &$form_state) {
parent::edit_form($form, $form_state);
$style = $form_state['item'];
if (empty($style->name)) {
$style = NULL;
}
module_load_include('inc', 'openlayers_ui', 'includes/openlayers_ui.styles');
$properties = array(
'externalGraphic' => array(
'default' => '',
'desc' => t('The URL of an icon for points in a layer. The following options are available:
<ul><li>Full path, such as http://example.com/icon.png</li>
<li>Relative Drupal path, such as sites/all/modules/example/icon.png</li>
<li>Absolute path, such as /icon.png (though this is not suggested for maintainability reasons)</li></ul>'),
'maxlength' => 2083
),
'imageStyle' => array(
'type' => 'select',
'title' => 'Image style',
'options' => array(''=> 'None (original image)') + image_style_options(FALSE),
'default' => '',
'desc' => t('The Drupal Image Style to apply to the marker.'),
),
'pointRadius' => array(
'default' => 6,
'desc' => t('The radius of a vector point or the size of
an icon. Note that, when using icons, this value should be half the
width of the icon image.'),
'type' => 'integer',
'element_validate' => array('element_validate_integer_positive'),
),
'fillColor' => array(
'default' => '#EE9900',
'desc' => t('This is the color used for
filling in Polygons. It is also used in the center of marks for
points: the interior color of circles or other shapes. It is
not used if an externalGraphic is applied to a point. This should be
a hexadecimal value like #FFFFFF.'),
),
'strokeColor' => array(
'default' => '#EE9900',
'desc' => t('This is color of the line on features. On
polygons and point marks, it is used as an outline to the feature.
On lines, this is the representation of the feature. This should be
a hexadecimal value like #FFFFFF.'),
),
'strokeWidth' => array(
'default' => 1,
'desc' => t('This is width of the line on features. On
polygons and point marks, it is used as an outline to
the feature. On lines, this is the representation of the
feature. This is a value in pixels.'),
'type' => 'integer',
'element_validate' => array('element_validate_integer_positive'),
),
'fillOpacity' => array(
'default' => 1,
'desc' => t('This is the opacity used for filling in Polygons.
It is also used in the center of marks for points: the interior
color of circles or other shapes. It is not used if an
externalGraphic is applied to a point. This should be a value
between 0 and 1.'),
'type' => 'float',
'element_validate' => array('_element_validate_between_zero_and_one', 'element_validate_number'),
),
'strokeOpacity' => array(
'default' => 1,
'desc' => t('This is opacity of the line on features.
On polygons and point marks, it is used as an outline to the
feature. On lines, this is the representation of the feature.
This should be a value between 0 and 1.'),
'type' => 'float',
'element_validate' => array('_element_validate_between_zero_and_one', 'element_validate_number'),
),
'strokeLinecap' => array(
'default' => 'round',
'desc' => t('Options are butt, round, square. This property
is similar to the SVG stroke-linecap property. It determines
what the end of lines should look like. See the SVG link for
image examples.'),
'options' => array(
'butt' => t('Butt'),
'round' => t('Round'),
'square' => t('Square'),
),
),
'strokeDashstyle' => array(
'default' => 'solid',
'desc' => t('Options are dot, dash, dashdot, longdash, longdashdot, solid.'),
'options' => array(
'dot' => t('Dot'),
'dash' => t('Dash'),
'dashdot' => t('Dash-dot'),
'longdash' => t('Long-dash'),
'longdashdot' => t('Long-dash-dot'),
'solid' => t('Solid'),
),
),
'cursor' => array(
'default' => '',
'desc' => t('Cursor used when mouse is over the feature. Default
is an empty string, which inherits from parent elements. See
<a href="!url">CSS cursor styles</a>.', array(
'!url' => 'http://www.w3schools.com/css/pr_class_cursor.asp',
)),
),
'graphicWidth' => array(
'default' => '',
'desc' => t('This properties define the width of an externalGraphic.
This is an alternative to the pointRadius symbolizer property
to be used when your graphic has different sizes in the X and
Y direction. This should be in pixels.'),
'type' => 'integer',
'element_validate' => array('element_validate_integer_positive'),
),
'graphicHeight' => array(
'default' => '',
'desc' => t('This properties define the height of an externalGraphic.
This is an alternative to the pointRadius symbolizer property
to be used when your graphic has different sizes in the X and
Y direction. This should be in pixels.'),
'type' => 'integer',
'element_validate' => array('element_validate_integer_positive'),
),
'graphicOpacity' => array(
'default' => '1',
'desc' => t('Opacity of an external graphic. This should be a
value between 0 and 1. Graphics that are already semitransparent,
like alpha PNGs, should have this set to 1, or rendering problems in
Internet Explorer will ensue.'),
'type' => 'float',
'element_validate' => array('_element_validate_between_zero_and_one', 'element_validate_number'),
),
'graphicXOffset' => array(
'default' => '',
'desc' => t('Where the X value of the "center" of an
externalGraphic should be. This should be in pixels.'),
'type' => 'integer',
'element_validate' => array('element_validate_integer'),
),
'graphicYOffset' => array(
'default' => '',
'desc' => t('Where the Y value of the "center" of an
externalGraphic should be. This should be in pixels.'),
'type' => 'integer',
'element_validate' => array('element_validate_integer'),
),
'graphicName' => array(
'default' => '',
'desc' => t('Name of a type of symbol to be used
for a point mark.'),
),
'rotation' => array(
'default' => '',
'desc' => t('The rotation angle in degrees clockwise for
a point symbolizer.'),
),
'display' => array(
'default' => '',
'desc' => t('Can be set to "none" to hide features
from rendering.'),
'options' => array(
'' => t('On'),
'none' => t('None (off)'),
),
),
'label' => array(
'default' => '',
'desc' => t('A label to show for features. '
. 'Typically used with ${attribute} syntax.')
),
'labelAlign' => array(
'default' => 'cm',
'desc' => t('Label alignment.'),
'options' => array(
'cm' => t('Center, middle'),
'ct' => t('Center, top'),
'cb' => t('Center, bottom'),
'lm' => t('Left, middle'),
'lt' => t('Left, top'),
'lb' => t('Left, bottom'),
'rm' => t('Right, middle'),
'rt' => t('Right, top'),
'rb' => t('Right, bottom'),
),
),
'labelXOffset' => array(
'default' => '',
'desc' => t('Label X offset. Positive numbers move label right.'),
'type' => 'integer',
'element_validate' => array('element_validate_integer'),
),
'labelYOffset' => array(
'default' => '',
'desc' => t('Label Y offset. Positive numbers move label up.'),
'type' => 'integer',
'element_validate' => array('element_validate_integer'),
),
'fontColor' => array(
'default' => '',
'desc' => t('Label font color.'),
),
'fontSize' => array(
'default' => '',
'desc' => t('Label font size.'),
),
'fontFamily' => array(
'default' => '',
'desc' => t('Label font family.'),
),
'fontWeight' => array(
'default' => '',
'desc' => t('Label font weight.'),
),
);
// Provide a preview of the style
if (isset($form_state['clicked_button']['#id']) && ($form_state['clicked_button']['#id'] == 'edit-preview')) {
$preview_style = new stdClass();
$preview_style->name = $form_state['values']['name'];
$preview_style->title = $form_state['input']['title'];
$preview_style->description = $form_state['input']['description'];
$preview_style->data = $form_state['input']['data'];
$form['info']['preview_style_container'] = array(
'#type' => 'item',
'#title' => t('Preview'),
'#markup' => openlayers_ui_style_preview($preview_style, TRUE),
'#description' => t('If you are using attribute replacement, the style may not show properly. The crosshairs point out where the feature is centered.'),
);
}
$form['info']['title'] = array(
'#id' => 'styletitle',
'#type' => 'textfield',
'#weight' => -1,
'#title' => t('Style title'),
'#default_value' => isset($style->title) ? $style->title : '',
'#description' => t('The friendly name of your style, which will appear in the administration interface as well on the map interface.'),
);
$form['info']['name']['#machine_name']['source'] = array('info', 'title');
// OpenLayers style properties
$form['data'] = array(
'#type' => 'fieldset',
'#tree' => TRUE,
'#title' => t('Style Properties'),
'#description' => t('The specific properties for the style.'),
);
foreach ($properties as $key => $prop) {
$form['data'][$key] = array(
'#type' => !isset($prop['options']) ? 'textfield' : 'select',
'#title' => !isset($prop['title']) ? check_plain($key) : check_plain($prop['title']),
'#description' => filter_xss($prop['desc']),
'#default_value' => isset($style->data[$key]) ?
$style->data[$key] : $prop['default'],
'#element_validate' => isset($prop['element_validate']) ?
$prop['element_validate'] : array(),
'#element_validate' => isset($prop['element_validate']) ?
$prop['element_validate'] : array() );
// Add options if needed
if (isset($prop['options']) && is_array($prop['options'])) {
$form['data'][$key]['#options'] = $prop['options'];
}
// Add maxlength if needed
if (isset($prop['maxlength']) && is_numeric($prop['maxlength'])) {
$form['data'][$key]['#maxlength'] = $prop['maxlength'];
}
}
// Add preview button.
$form['buttons']['preview'] = array(
'#type' => 'button',
'#value' => t('Preview'),
);
}
/**
* Prepare the tag values before they are added to the database.
*/
function edit_form_submit(&$form, &$form_state) {
$style_data = $form_state['values']['data'];
// Cast and unset values so JS can handle them better,
// Unless values are in the form ${attribute}
foreach ($form_state['values']['data'] as $key => $value) {
if ($form_state['values']['data'][$key] === '') {
unset($form_state['values']['data'][$key]);
}
elseif (isset($style_data[$key]['type']) &&
strpos($form_state['values']['data'][$key], '${') !== 0) {
if ($style_data[$key]['type'] == 'integer') {
$form_state['values']['data'][$key] =
(int) $form_state['values']['data'][$key];
}
elseif ($style_data[$key]['type'] == 'float') {
$form_state['values']['data'][$key] =
(float) $form_state['values']['data'][$key];
}
}
}
parent::edit_form_submit($form, $form_state);
}
/**
* Build a row based on the item.
*
* By default all of the rows are placed into a table by the render
* method, so this is building up a row suitable for theme('table').
* This doesn't have to be true if you override both.
*/
function list_build_row($item, &$form_state, $operations) {
// Set up sorting
$name = $item->{$this->plugin['export']['key']};
$schema = ctools_export_get_schema($this->plugin['schema']);
// Note: $item->{$schema['export']['export type string']} should have already been set up by export.inc so
// we can use it safely.
switch ($form_state['values']['order']) {
case 'disabled':
$this->sorts[$name] = empty($item->disabled) . $name;
break;
case 'title':
$this->sorts[$name] = $item->{$this->plugin['export']['admin_title']};
break;
case 'name':
$this->sorts[$name] = $name;
break;
case 'storage':
$this->sorts[$name] = $item->{$schema['export']['export type string']} . $name;
break;
}
$this->rows[$name]['data'] = array();
$this->rows[$name]['class'] = !empty($item->disabled) ? array('ctools-export-ui-disabled') : array('ctools-export-ui-enabled');
$this->rows[$name]['data'][] = array('data' => openlayers_ui_style_preview($item), 'class' => array('ctools-export-ui-preview'));
// If we have an admin title, make it the first row.
if (!empty($this->plugin['export']['admin_title'])) {
$this->rows[$name]['data'][] = array('data' => check_plain($item->{$this->plugin['export']['admin_title']}), 'class' => array('ctools-export-ui-admin-title'));
}
$this->rows[$name]['data'][] = array('data' => $item->title, 'class' => array('ctools-export-ui-title'));
$this->rows[$name]['data'][] = array('data' => $item->description, 'class' => array('ctools-export-ui-description'));
$this->rows[$name]['data'][] = array('data' => check_plain($item->{$schema['export']['export type string']}), 'class' => array('ctools-export-ui-storage'));
$ops = theme('links__ctools_dropbutton', array('links' => $operations, 'attributes' => array('class' => array('links', 'inline'))));
$this->rows[$name]['data'][] = array('data' => $ops, 'class' => array('ctools-export-ui-operations'));
// Add an automatic mouseover of the description if one exists.
if (!empty($this->plugin['export']['admin_description'])) {
$this->rows[$name]['title'] = $item->{$this->plugin['export']['admin_description']};
}
}
/**
* Provide the table header.
*
* If you've added columns via list_build_row() but are still using a
* table, override this method to set up the table header.
*/
function list_table_header() {
$header = array();
$header[] = array('data' => t('Preview'), 'class' => array('ctools-export-ui-preview'));
if (!empty($this->plugin['export']['admin_title'])) {
$header[] = array('data' => t('Name'), 'class' => array('ctools-export-ui-name'));
}
$header[] = array('data' => t('Title'), 'class' => array('ctools-export-ui-title'));
$header[] = array('data' => t('Description'), 'class' => array('ctools-export-ui-description'));
$header[] = array('data' => t('Storage'), 'class' => array('ctools-export-ui-storage'));
$header[] = array('data' => t('Operations'), 'class' => array('ctools-export-ui-operations'));
return $header;
}
/**
* hook_menu() entry point.
*
* Child implementations that need to add or modify menu items should
* probably call parent::hook_menu($items) and then modify as needed.
*/
function hook_menu(&$items) {
parent::hook_menu($items);
$items['admin/structure/openlayers/styles']['type'] = MENU_LOCAL_TASK;
}
/**
* Provide a list of sort options.
*
* Override this if you wish to provide more or change how these work.
* The actual handling of the sorting will happen in build_row().
*/
function list_sort_options() {
if (!empty($this->plugin['export']['admin_title'])) {
$options = array(
'disabled' => t('Enabled, title'),
$this->plugin['export']['admin_title'] => t('Title'),
);
}
else {
$options = array(
'disabled' => t('Enabled, title'),
);
}
$options += array(
'storage' => t('Storage'),
);
return $options;
}
}
/**
* Custom validations functions.
* See #element_validate in Form API.
*/
function _element_validate_between_zero_and_one($element, &$form_state, $form) {
if ($element['#value'] < 0 || $element['#value'] > 1) {
form_error($element, t('The @property property must be between 0 and 1.', array('@property' => $element['#title'])));
}
}
function _element_validate_number_positive($element, &$form_state, $form) {
if ($element['#value'] <= 0) {
form_error($element, t('The @property property must be a positive number.', array('@property' => $element['#title'])));
}
}

View File

@@ -0,0 +1 @@
<div id="<?php print $style->name; ?>" class="openlayers-ui-style-preview"></div>

View File

@@ -0,0 +1,32 @@
<?php
/**
* @file
* This file holds the theme functions for openlayers_views module
*
* @ingroup openlayers
*/
/**
* Theme function for openlayers_views_group_display_item
*
* Output of OpenLayers View diplay plugin for grouped items.
*/
function theme_openlayers_views_group_display_item($args) {
// Build output
return ((!empty($args['name'])) ?
'<h2 class="point-title openlayers-views-group-feature-name">'
. $args['name']
. '</h2>' : '') .
(!empty($args['description']) ?
'<div class="point-content openlayers-views-group-feature-description">'
. $args['description']
. '</div>' : '');
}
/**
* Theme function for openlayers_views_render_feature
*/
function theme_openlayers_views_render_feature($args) {
return $args['feature'];
}

View File

@@ -0,0 +1,23 @@
name = OpenLayers Views
description = Provides OpenLayers Views plugins.
core = 7.x
package = OpenLayers
dependencies[] = openlayers
dependencies[] = views
dependencies[] = geophp
; Core files
files[] = openlayers_views.module
files[] = views/openlayers_views.views.inc
files[] = views/openlayers_views_style_map.inc
files[] = views/openlayers_views_style_data.inc
files[] = views/openlayers_views_plugin_display_openlayers.inc
files[] = views/openlayers_views_plugin_row_point.inc
files[] = views/openlayers_views_plugin_row_bounding_box.inc
files[] = views/openlayers_views_plugin_row_geometry.inc
; Information added by drupal.org packaging script on 2013-02-05
version = "7.x-2.0-beta3+76-dev"
core = "7.x"
project = "openlayers"
datestamp = "1360071107"

View File

@@ -0,0 +1,23 @@
<?php
/**
* @file
* This file holds the functions for the installing
* and enabling of the openlayers_views module.
*
* @ingroup openlayers
*/
/**
* Implementation of hook_uninstall().
*/
function openlayers_views_uninstall() {
// Get module variables
global $conf;
foreach (array_keys($conf) as $key) {
// Find variables that have the module prefix
if (strpos($key, 'openlayers_views_') === 0) {
variable_del($key);
}
}
}

View File

@@ -0,0 +1,234 @@
<?php
/**
* @file
* This file holds the main Drupal hook functions
* and private functions for the openlayers_views module.
*
* @ingroup openlayers
*/
/**
* Implements hook_help().
*/
function openlayers_views_help($path, $arg) {
switch ($path) {
case 'admin/help#openlayers_views':
return '<p>'
. t('The OpenLayers Views module provides a set of plugins '
. 'for Views.')
. '</p>';
}
}
/**
* Implements hook_theme().
*/
function openlayers_views_theme($existing, $type, $theme, $path) {
return array(
'openlayers_views_group_display_item' => array(
'arguments' => array(
'name' => '',
'description' => '',
),
'file' => 'includes/openlayers_views.theme.inc',
),
'openlayers_views_render_feature' => array(
'arguments' => array(
'feature' => '',
'record' => '',
),
'file' => 'includes/openlayers_views.theme.inc',
),
'openlayers_image_formatter' => array(
'variables' => array(
'item' => NULL,
'node' => NULL,
'field' => array(),
'display_settings' => array(),
),
'file' => 'views/openlayers_views.views.theme.inc',
),
'openlayers_views_map' => array(
'arguments' => array(
'map' => array(),
'title' => '',
),
'file' => 'views/openlayers_views.views.theme.inc',
),
);
}
/**
* Implements hook_views_api().
*/
function openlayers_views_views_api() {
return array(
'api' => 3,
'path' => drupal_get_path('module', 'openlayers_views') .'/views',
);
}
/**
* Implements hook_ctools_plugin_directory().
*/
function openlayers_views_ctools_plugin_directory($module, $plugin) {
if ($module == 'openlayers' && !empty($plugin)) {
return 'plugins/' . $plugin;
}
}
/**
* Implements hook_ctools_plugin_api().
*/
function openlayers_views_ctools_plugin_api($module, $api) {
if ($module == "openlayers") {
switch ($api) {
case 'openlayers_layers':
return array('version' => 1);
}
}
}
/**
* Implements hook_openlayers_layers().
*/
function openlayers_views_openlayers_layers() {
$layers = array();
// Attempt to load information from cache.
// For now use a arg based check for skipping cache.
if (arg(0) != 'admin') {
$cache = cache_get('openlayers_views');
if (isset($cache->data)) {
return $cache->data;
}
}
$views = views_get_all_views();
// Provide each OpenLayers Data display as a layer
foreach ($views as $view) {
foreach ($view->display as $display => $data) {
$view->set_display($display);
// Check for OpenLayers Data Overlays
if ($view->display_handler->get_option('style_plugin') == 'openlayers_data' && $display != 'default') {
//Build Layer
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = $view->name . '_' . $display;
$layer->title = empty($data->display_options['title']) ? $view->name : $data->display_options['title'];
$layer->title .= ' - ' . $data->display_title;
$layer->description = $view->description;
$layer->data = array(
'layer_type' => 'openlayers_views_vector',
'layer_handler' => 'openlayers_views_vector',
'projection' => array('4326'),
'isBaseLayer' => FALSE,
'vector' => TRUE,
'type' => 'Vector',
'url' => array(),
'options' => array(),
'events' => array(),
'views' => array('view' => $view->name, 'display' => $display),
);
$layers[$layer->name] = $layer;
}
// Make GeoJSON layers from the views_geojson module
if ($view->display_handler->get_option('style_plugin') == 'views_geojson' &&
$view->display_handler->display->display_plugin == 'page' &&
$view->display_handler->get_option('path') != ''
) {
$layer = new stdClass();
$layer->api_version = 1;
$layer->name = $view->name . '_' . $display;
$layer->title = empty($data->display_options['title']) ? $view->name : $data->display_options['title'];
$layer->title .= ' - ' . $data->display_title;
$layer->description = $view->description;
// Determine if we should use a BBOX strategy.
$useBBOX = FALSE;
if (isset($view->display['default']->display_options['arguments']) &&
isset($view->display['default']->display_options['arguments']['bbox_argument']) &&
$view->display['default']->display_options['arguments']['bbox_argument']['arg_id'] == 'bbox') {
$useBBOX = TRUE;
}
$layer->data = array(
'layer_type' => 'openlayers_layer_type_geojson',
'url' => url($view->display_handler->get_option('path'), array('absolute' => TRUE)),
'geojson_data' => '',
'views' => array('view' => $view->name, 'display' => $display),
'useBBOX' => $useBBOX,
);
$layers[$layer->name] = $layer;
}
}
$view->destroy();
}
cache_set('openlayers_views', $layers);
return $layers;
}
/**
* Implements hook_field_formatter_info().
*/
function openlayers_views_field_formatter_info() {
return array(
'openlayers' => array(
'label' => t('OpenLayers Style'),
'field types' => array('image'),
'settings' => array('image_style' => ''),
),
);
}
/**
* Implements hook_field_formatter_view().
*/
function openlayers_views_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) {
$element = array();
foreach ($items as $delta => $item) {
$element[$delta] = array(
'#theme' => 'openlayers_image_formatter',
'#item' => $item,
'#display_settings' => $display['settings'],
'#node' => $entity,
'#field' => $field,
);
}
return $element;
}
/**
* Implements hook_field_formatter_settings_form().
*/
function openlayers_views_field_formatter_settings_form($field, $instance, $view_mode, $form, &$form_state) {
$display = $instance['display'][$view_mode];
$settings = $display['settings'];
$style = new stdClass();
$style->name = drupal_html_id('style');
$style->data = $settings;
$form_state['item'] = $style;
ctools_include('export-ui');
$plugin = ctools_get_export_ui('openlayers_styles');
$handler = ctools_export_ui_get_handler($plugin);
call_user_func_array(array($handler, 'edit_form'), array(&$form, &$form_state));
$form = $form['data'];
unset($form['#type']);
unset($form['#tree']);
unset($form['#title']);
unset($form['#description']);
unset($form['externalGraphic']);
return $form;
}

View File

@@ -0,0 +1,133 @@
<?php
/**
* @file
* OpenLayers Views Vector Layer Type
*/
/**
* Ctools plugin definition
*/
function openlayers_views_openlayers_views_vector_openlayers_layer_types() {
return array(
'title' => t('OpenLayers Views'),
'description' => t('OpenLayers Views Vector'),
'layer_type' => array(
'file' => 'openlayers_views_vector.inc',
'class' => 'openlayers_layer_type_openlayers_views_vector',
'parent' => 'openlayers_layer_type',
),
);
}
class openlayers_layer_type_openlayers_views_vector
extends openlayers_layer_type {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'layer_handler' => 'openlayers_views_vector',
'projection' => array('4326'),
'isBaseLayer' => FALSE,
'vector' => TRUE,
'type' => 'Vector',
'url' => array(),
'options' => array(),
'events' => array(),
'views' => array()
);
}
/**
* Options form which generates layers
*/
function options_form($defaults = array()) {
$form = array();
$views = views_get_all_views();
$options = array('' => '<none>');
foreach($views as $view) {
foreach ($view->display as $display => $data) {
if ($data->display_plugin == 'openlayers') {
$options[$view->name . '::' . $display] = $view->human_name . ': '.$display;
}
}
}
$default = NULL;
if (isset($this->data['views']['view']) && isset($this->data['views']['display'])) {
$default = $this->data['views']['view'] . '::' . $this->data['views']['display'];
}
$form['views']['composite'] = array(
'#type' => 'select',
'#options' => $options,
'#title' => 'View name',
'#default_value' => isset($default) ?
$default : '',
);
return $form;
}
function options_form_validate($form, &$form_state) {
if (!empty($form_state['data']['views']['composite'])) {
list($view, $display) = explode('::', $form_state['data']['views']['composite']);
$form_state['data']['views']['view'] = $view;
$form_state['data']['views']['display'] = $display;
unset($form_state['data']['views']['composite']);
} else {
$field = $form_state['data']['layer_type'].'][views][composite';
form_set_error($field, t('A View must be set.'));
}
}
/**
* Get features for this view
*
* @param $view_name
* the view name
* @param $display_name
* the view display name
* @return
* array of features
*/
function get_features() {
if ($view = views_get_view($this->data['views']['view'])) {
$args = array();
// Retrieve args/filters from current view
// to pass on to our vector layer.
$current_view = views_get_current_view();
if (!empty($current_view)) {
$args = $current_view->args;
if (isset($current_view->exposed_input)) {
$view->set_exposed_input($current_view->exposed_input);
}
}
if (isset($this->data['views']['arguments'])) {
$args = $this->data['views']['arguments'];
}
$features = $view->execute_display($this->data['views']['display'], $args);
// Get dynamic title from view
$this->title = $view->get_title();
$view->destroy();
}
$this->data['features'] = isset($features) ? $features : array();
return $this->data['features'];
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers_views') .
'/plugins/layer_types/openlayers_views_vector.js');
$this->get_features();
}
}

View File

@@ -0,0 +1,23 @@
/**
* OpenLayers Views Vector Layer Handler
*/
Drupal.openlayers.layer.openlayers_views_vector = function(title, map, options) {
// Note, so that we do not pass all the features along to the Layer
// options, we use the options.options to give to Layer
options.options.drupalID = options.drupalID;
// Create projection
options.projection = new OpenLayers.Projection('EPSG:'+options.projection);
// Get style map
options.options.styleMap = Drupal.openlayers.getStyleMap(map, options.drupalID);
// Create layer object
var layer = new OpenLayers.Layer.Vector(title, options.options);
// Add features if there are any
if (options.features) {
Drupal.openlayers.addFeatures(map, layer, options.features);
}
return layer;
};

View File

@@ -0,0 +1,60 @@
<?php
/**
* @file
* This file holds main views functions for the openlayers_views module.
*
* @ingroup openlayers
*/
/**
* Implementation of hook_views_plugins().
*/
function openlayers_views_views_plugins() {
return array(
'module' => 'openlayers_views',
'display' => array(
'openlayers' => array(
'title' => t('OpenLayers Data Overlay'),
'help' => t('Data layer for OpenLayers maps.'),
'handler' => 'openlayers_views_plugin_display_openlayers',
'path' => drupal_get_path('module', 'openlayers_views') . '/views',
'uses hook menu' => FALSE,
'use ajax' => FALSE,
'use pager' => TRUE,
'accept attachments' => FALSE,
'admin' => t('OpenLayers Data Overlay'),
),
),
'style' => array(
'openlayers_map' => array(
'title' => t('OpenLayers Map'),
'help' => t('Displays a View as an OpenLayers map.'),
'handler' => 'openlayers_views_style_map',
'theme' => 'openlayers_views_map',
'theme path' => drupal_get_path('module', 'openlayers_views') . '/views',
'path' => drupal_get_path('module', 'openlayers_views') . '/views',
'uses fields' => FALSE,
'uses row plugin' => FALSE,
'uses options' => TRUE,
'uses grouping' => FALSE,
'type' => 'normal',
'even empty' => FALSE,
),
'openlayers_data' => array(
'title' => t('OpenLayers Data Overlay'),
'help' => t('Provides Data to Power an OpenLayers map.'),
'handler' => 'openlayers_views_style_data',
'theme' => 'openlayers_views_data',
'theme path' => drupal_get_path('module', 'openlayers_views') . '/views',
'path' => drupal_get_path('module', 'openlayers_views') . '/views',
'uses fields' => TRUE,
'uses row plugin' => TRUE,
'uses options' => TRUE,
'uses grouping' => TRUE,
'type' => 'openlayers',
'even empty' => TRUE,
),
),
);
}

View File

@@ -0,0 +1,45 @@
<?php
/**
* @file
* This file holds views theme function for style plugin.
*
* @ingroup openlayers
*/
/**
* Implementation of theme function
*/
function theme_openlayers_views_map($args) {
return (isset($args['title']) ? '<h3>' . $args['title'] . '</h3>' : '') .
'<div class="openlayers-views-map">'
. $args['map']
. '</div>';
}
/**
* Implementation of theme function
*/
function theme_openlayers_image_formatter($variables) {
$item = $variables['item'];
$image = array(
'path' => $item['uri'],
'alt' => $item['alt'],
);
if (isset($item['width']) && isset($item['height'])) {
$image['width'] = $item['width'];
$image['height'] = $item['height'];
}
$output = $image['path'];
if ($variables['display_settings']['imageStyle']) {
$image_style = image_style_load($variables['display_settings']['imageStyle']);
$output = image_style_path($image_style['name'], $image['path']);
$preview_file_url = image_style_url($image_style['name'], $image['path']);
image_style_create_derivative($image_style, $image['path'], $preview_file_url);
}
return $output;
}

View File

@@ -0,0 +1,47 @@
<?php
/**
* @file
* Display plugin for OpenLayers Data
*
* @ingroup openlayers
*/
class openlayers_views_plugin_display_openlayers extends views_plugin_display {
function uses_breadcrumb() { return FALSE; }
function get_style_type() { return 'openlayers'; }
/**
* OpenLayers data features are used directly in the map object.
*/
function execute() {
return $this->view->render();
}
function preview() {
return '<pre>' . check_plain($this->view->render()) . '</pre>';
}
function render() {
return $this->view->style_plugin->render($this->view->result);
}
function option_definition() {
$options = parent::option_definition();
$options['title']['translatable'] = 0;
$options['displays'] = array('default' => array());
$options['style_plugin']['default'] = 'openlayers_data';
$options['row_plugin']['default'] = 'fields';
$options['defaults']['default']['row_plugin'] = FALSE;
return $options;
}
function options_summary(&$categories, &$options) {
parent::options_summary($categories, $options);
unset($options['header']);
unset($options['footer']);
unset($options['empty']);
unset($options['exposed_block']);
unset($options['analyze-theme']);
}
}

View File

@@ -0,0 +1,561 @@
<?php
/**
* @file
* This file holds style plugin for OpenLayers Views
*
* @ingroup openlayers
*/
/**
* @class
* Extension of the Views Plugin Style for OpenLayers
*
* This class extended the default views plugin class to provide
* a style plugin for the Open Layers module.
*/
class openlayers_views_style_data extends views_plugin_style {
/**
* Render the map features.
*
* Overrides views_plugin_style->render
*/
function render() {
$grouped_results = $this->render_grouping($this->view->result, $this->options['grouping']);
$data = $this->map_features($grouped_results);
// If we are not in preview, just return the data
if (empty($this->view->live_preview)) {
return $data;
}
else {
// If we are in preview mode, dump out some useful information about this data layer
$output = "You can use the following parameters in your styles as dynamic values";
$output .= "\n------------\n";
if (!empty($data)) {
$keys = array_keys($data);
foreach ($data[$keys[0]]['attributes'] as $key => $value) {
$output .= '${'.$key."}\n";
}
}
$output .= "\n------------\n";
$output .= t('The following is a dump of the data that is rendered from this display. It is used for debugging purposes only.') . '
' . var_export($data, TRUE);
return $output;
}
}
/**
* Set default options
*
* Overrides views_plugin_style->option_definition
*/
function option_definition() {
$options = parent::option_definition();
$options['data_source'] = array('default' => 'openlayers_wkt');
return $options;
}
/**
* Options form
*
* Overrides views_plugin_style->options_form
*/
function options_form(&$form, &$form_state) {
parent::options_form($form, $form_state);
// Get list of fields in this view & flag available geodata fields
$handlers = $this->display->handler->get_handlers('field');
// Check for any fields, as the view needs them
if (empty($handlers)) {
$form['error_markup'] = array(
'#value' => t('You need to enable at least one field before you can '
. 'configure your field settings'),
'#prefix' => '<div class="error form-item description">',
'#suffix' => '</div>',
);
return;
}
$fields = array();
foreach ($handlers as $field_id => $handler) {
$fields[$field_id] = $handler->ui_name();
}
$form['data_source'] = array(
'#type' => 'fieldset',
'#tree' => TRUE,
'#title' => t('Data Source'),
'#collapsible' => TRUE,
'#collapsed' => FALSE,
);
$form['data_source']['value'] = array(
'#type' => 'select',
'#title' => t('Map Data Sources'),
'#description' => t('Choose which sources of data that the map will '
. 'provide features for.'),
'#options' => array(
'other_latlon' => t('Lat/Lon Pair'),
'other_boundingbox' => t('Bounding Box'),
'wkt' => t('WKT')
),
'#default_value' => $this->options['data_source']['value'],
);
if (count($fields > 0)) {
$form['data_source']['other_lat'] = array(
'#type' => 'select',
'#title' => t('Latitude Field'),
'#description' => t('Choose a field for Latitude. This should be a '
. 'field that is a decimal or float value.'),
'#options' => $fields,
'#default_value' => $this->options['data_source']['other_lat'],
'#states' => $this->datasource_dependent('other_latlon')
);
$form['data_source']['other_lon'] = array(
'#type' => 'select',
'#title' => t('Longitude Field'),
'#description' => t('Choose a field for Longitude. This should be a '
. 'field that is a decimal or float value.'),
'#options' => $fields,
'#default_value' => $this->options['data_source']['other_lon'],
'#states' => $this->datasource_dependent('other_latlon')
);
$form['data_source']['wkt'] = array(
'#type' => 'select',
'#title' => t('WKT Field'),
'#description' => t('Choose the OpenLayers WKT field.'),
'#options' => $fields,
'#default_value' => $this->options['data_source']['wkt'],
'#states' => $this->datasource_dependent('wkt')
);
$form['data_source']['other_top'] = array(
'#type' => 'select',
'#title' => t('Top Field'),
'#description' => t('Choose a field for Top. This should be a '
. 'field that is a decimal or float value.'),
'#options' => $fields,
'#default_value' => $this->options['data_source']['other_top'],
'#states' => $this->datasource_dependent('other_boundingbox')
);
$form['data_source']['other_right'] = array(
'#type' => 'select',
'#title' => t('Right Field'),
'#description' => t('Choose a field for Right. This should be a field '
. 'that is a decimal or float value.'),
'#options' => $fields,
'#default_value' => $this->options['data_source']['other_right'],
'#states' => $this->datasource_dependent('other_boundingbox')
);
$form['data_source']['other_bottom'] = array(
'#type' => 'select',
'#title' => t('Bottom Field'),
'#description' => t('Choose a field for Bottom. This should be a '
. 'field that is a decimal or float value.'),
'#options' => $fields,
'#default_value' => $this->options['data_source']['other_bottom'],
'#states' => $this->datasource_dependent('other_boundingbox')
);
$form['data_source']['other_left'] = array(
'#type' => 'select',
'#title' => t('Left Field'),
'#description' => t('Choose a field for Left. This should be a field ' .
'that is a decimal or float value.'),
'#options' => $fields,
'#default_value' => $this->options['data_source']['other_left'],
'#states' => $this->datasource_dependent('other_boundingbox')
);
}
$form['data_source']['name_field'] = array(
'#type' => 'select',
'#title' => t('Title Field'),
'#description' => t('Choose the field which will appear as a title on ' .
'tooltips.'),
'#options' => array_merge(array('' => ''), $fields),
'#default_value' => $this->options['data_source']['name_field'],
);
// For node content type, we can render the node as with a specific
// view mode.
if ($this->view->base_table == 'node') {
$desc_options = array_merge(array(
'' => '',
'#row' => '<' . t('entire row') . '>',
'#node' => '<' . t('entire node') . '>'
), $fields);
}
else {
$desc_options = array_merge(array(
'' => '',
'#row' => '<' . t('entire row') . '>',
), $fields);
}
// Description field
$form['data_source']['description_field'] = array(
'#type' => 'select',
'#title' => t('Description Content'),
'#description' => t('Choose the field or rendering method which will
appear as a description on tooltips or popups.'),
'#required' => FALSE,
'#options' => $desc_options,
'#default_value' => $this->options['data_source']['description_field'],
);
// Create view mode options
if ($this->view->base_table == 'node') {
// Available_view_modes is the array to contain the avaible
// view modes, for now this is not content type aware, but should be
$available_view_modes = array();
$entity_info = entity_get_info();
// Get the machine names of the view modes
$view_modes_machine_names[] = array_keys($entity_info['node']['view modes']);
// Get the labels (human readable) of the view modes
foreach ($entity_info['node']['view modes'] as $key => $view_mode) {
$view_modes_labels[] = $view_mode['label'];
}
// Combine the machine view mode name with the label, this could sure be done much better?
$entities_to_display = array_combine($view_modes_machine_names[0], $view_modes_labels);
//output the form
$form['data_source']['view_mode'] = array(
'#type' => 'select',
'#title' => t('View mode'),
'#description' => t('View modes are ways of displaying nodes.'),
'#options' => $entities_to_display,
'#default_value' => !empty($this->options['data_source']['view_mode']) ?
$this->options['data_source']['view_mode'] : 'full',
'#states' => array(
'visible' => array(
':input[name="style_options[data_source][description_field]"]' => array('value' => '#node'),
),
),
);
}
$form['data_source']['style_field'] = array(
'#type' => 'select',
'#title' => t('Style Field'),
'#description' => t('Choose the field which will appear as a style on '
. 'the layer.'),
'#required' => FALSE,
'#options' => array('' => '',) + $fields,
'#default_value' => $this->options['data_source']['style_field'],
);
// A simple way to display attributes and styling
$form['attributes'] = array(
'#type' => 'fieldset',
'#title' => t('Attributes and Styling'),
'#description' => t('Attributes are field data attached to each '
. 'feature. This can be used with styling to create Variable styling.'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
$variable_fields = array();
if (!empty($this->options['data_source']['name_field'])) {
$variable_fields['name'] = '${name}';
}
if (!empty($this->options['data_source']['description_field'])) {
$variable_fields['description'] = '${description}';
}
foreach ($this->view->display_handler->get_handlers('field') as
$field => $handler) {
if (($field != $this->options['data_source']['name_field']) &&
($field != $this->options['data_source']['description_field'])) {
$variable_fields[$field] = '${' . $field . '}';
$variable_fields[$field . '_rendered'] = '${' . $field . '_rendered}';
}
}
$form['attributes']['styling'] = array(
'#markup' => '
<p>' . t('Any fields that you add to this view will be attached to '
. 'their respective feature (point, line, polygon) as attributes. '
. 'These attributes can then be used to add variable styling to your '
. 'themes. This is accomplished by using the %syntax syntax in the '
. 'values for a style. You can see a list of available variables in '
. 'the view preview; these can be placed right in the style interface. '
. 'The %rendered one means that it has been processed '
. 'by Views and may have a different value.',
array(
'%syntax' => '${field_name}',
'%rendered' => '_rendered'))
. '</p>'
. theme('item_list', array('items' => $variable_fields))
. '<p>'
. t('Please note that this does not apply to Grouped Displays.')
. '</p>',
);
}
/**
* @param $records ...
*
* openlayers_views_style_data specific
*/
function map_features($sets = array()) {
$features = $excluded_fields = array();
$handlers = $this->display->handler->get_handlers('field');
foreach ($sets as $title => $records) {
foreach ($records as $id => $record) {
$this->view->row_index = $id;
$attributes = array();
foreach ($handlers as $hid => $handler) {
if (!empty($handler->options['exclude']) && !in_array($hid, $this->options['data_source'])) {
$excluded_fields[] = $hid;
// Ensure that $handler->last_render is correctly populated with the
// value corresponding to the record being processed, otherwise
// fields whose output is rewritten based on excluded fields might
// get the wrong values.
$handler->last_render = $this->rendered_fields[$id][$hid];
}
else {
$attributes[$hid . '_rendered'] = $handler->allow_advanced_render() ? $handler->advanced_render($record) : $handler->render($record);
if (isset($record->{'field_' . $hid}) && empty($record->{'field_' . $hid})) {
// This is an empty field value so we cannot use
// $handler->original_value as that will be set to the value held
// by the last record that had this value set.
$attributes[$hid] = NULL;
}
else {
$attributes[$hid] = isset($handler->original_value) ? $handler->original_value : NULL;
}
}
}
if (isset($this->options['data_source']['description_field'])) {
// Handle rendering the whole record.
if ($this->options['data_source']['description_field'] === '#row') {
$attributes['#row_rendered'] = $this->row_plugin->render($record);
}
// Handle rendering of a node view.
if ($this->options['data_source']['description_field'] === '#node' &&
is_object($record) && isset($record->nid)) {
$view_mode = $this->options['data_source']['view_mode'] ? $this->options['data_source']['view_mode'] : 'full';
// This has to be done to avoid warning on some version of PHP.
$node_view = node_view(node_load($record->nid), $view_mode);
$attributes['#node_rendered'] = drupal_render($node_view);
}
}
// Create features array.
$feature = array(
'projection' => '4326',
'attributes' => $attributes,
'style' => $this->get_style($attributes, $handlers, $this->options['data_source'], $record),
'wkt' => $this->get_wkt($attributes, $handlers, $this->options['data_source']),
);
$features = $this->reduce_features($this->options['grouping'], $features, $feature, $title);
}
}
// For grouping, handle a bit differently.
if ($this->options['grouping']) {
$features = $this->coalesce_groups($features, $handlers, $this->options['data_source']);
}
else {
$features = $this->add_title_desc($features, $handlers, $this->options['data_source']);
}
return $features;
}
/**
* Basically a macro because
* #state is rather verbose
*
* openlayers_views_style_data specific
*/
function datasource_dependent($type) {
return array('visible' => array('#edit-style-options-data-source-value' => array('value' => $type)));
}
/**
* Find and compute styling attributes.
*/
function get_style($feature, $handlers, $datasource, $record) {
$style = array();
if (isset($datasource['style_field']) && !empty($datasource['style_field'])) {
$style_field = $handlers[$datasource['style_field']];
$style = $style_field->options['settings'];
if ($style_field->original_value) {
$image_info = image_get_info($style_field->original_value);
$style['graphicWidth'] = $image_info['width'];
$style['graphicHeight'] = $image_info['height'];
unset($style['imageStyle']);
$style['externalGraphic'] = file_create_url($style_field->original_value);
}
foreach ($style as $prop => $value) {
if (empty($value)) {
unset($style[$prop]);
}
}
}
return $style;
}
/**
* Find the data source of an element and pull it into a wkt field
*
* openlayers_views_style_data specific
*/
function get_wkt($feature, $handlers, $datasource) {
$feature['projection'] = '4326';
switch ($datasource['value']) {
case 'wkt':
return strip_tags($feature[$datasource['wkt']]);
break;
case 'other_latlon':
return 'POINT(' . strip_tags($feature[$datasource['other_lon']]) . ' ' . strip_tags($feature[$datasource['other_lat']]) . ')';
break;
}
}
/**
* Coalesce features into single grouped feature when grouping is enabled.
*
* openlayers_views_style_data specific
*/
function coalesce_groups($features, $handlers, $ds) {
// Combine wkt into geometry collections if they are an array
foreach ($features as &$feature) {
if (is_array($feature['wkt'])) {
if (count($feature['wkt']) > 1) {
$feature['wkt'] = $this->get_group_wkt($feature['wkt']);
}
else {
$feature['wkt'] = $feature['wkt'][0];
}
}
}
// Process title and description for groups
foreach ($features as $k => &$feature) {
$feature['attributes']['name'] = $k;
$feature['attributes'] = array_merge($feature['attributes'], $feature['features'][0]['attributes']);
$formatted_features = array();
foreach ($feature['features'] as $subfeature) {
// Create name and description attributes. Note that there are a
// couple exceptions to using fields.
$exceptions = array('#row', '#node');
// Run the output through a theme.
$formatted_features[] = theme('openlayers_views_group_display_item',
array(
'name' => isset($handlers[$ds['name_field']]) ?
$subfeature['attributes'][$ds['name_field'] . '_rendered'] : false,
'description' => (in_array($ds['description_field'], $exceptions) ||
isset($handlers[$ds['description_field']])) ?
$subfeature['attributes'][$ds['description_field'] . '_rendered'] : false
)
);
// Remove rendered rows to keep data size down for JS.
if (in_array($ds['description_field'], $exceptions)) {
unset($subfeature['attributes'][$ds['description_field'] . '_rendered']);
}
}
// Then run all gathered features through item_ist theme.
$feature['attributes']['description'] = theme('item_list',
array('items' => $formatted_features)
);
}
return $features;
}
/**
* Combine all group wkt into a single geometry collection
*
* openlayers_views_style_data specific
*/
function get_group_wkt($wkt_array) {
geophp_load();
$geophp = geoPHP::load($wkt_array, 'wkt');
return $geophp->out('wkt');
}
/**
* Retrieve name and description for individual features when grouping is not enabled.
*
* openlayers_views_style_data specific
*/
function add_title_desc($features, $handlers, $ds) {
foreach ($features as $k => &$f) {
// Create name/title attribute
if (isset($handlers[$ds['name_field']])) {
$f['attributes']['name'] = $f['attributes'][$ds['name_field'] . '_rendered'];
}
// Create description attribute. Note that there are a couple
// exceptions to using fields
$exceptions = array('#row', '#node');
if (isset($ds['description_field'])) {
if (in_array($ds['description_field'], $exceptions) || isset($handlers[$ds['description_field']])) {
$f['attributes']['description'] = $f['attributes'][$ds['description_field'] . '_rendered'];
// Remove rendered row to keep data size down for JS.
if (in_array($ds['description_field'], $exceptions)) {
unset($f['attributes'][$ds['description_field'] . '_rendered']);
}
}
}
}
return $features;
}
/**
* Split string according to first match of passed regEx index of $regExes
*/
function preg_explode($regEx, $str) {
$matches = array();
preg_match($this->regExes[$regEx], $str, $matches);
return empty($matches)?array(trim($str)):explode($matches[0], trim($str));
}
/**
* Basically an algebraic reduction; given whether to group,
* a feature, a list of features, etc., return a full $features
* array with the element added, either straight non-grouped,
* or within a new or existing group
*
* openlayers_views_style_data specific
*/
function reduce_features($is_grouped, $features, $feature, $group) {
if ($is_grouped) {
if (isset($features[$group])) {
$features[$group]['attributes']['count']++;
$features[$group]['wkt'][] = $feature['wkt'];
$features[$group]['features'][] = $feature;
return $features;
}
else {
$features[$group] = array(
'attributes' => array('count' => 1),
'wkt' => array($feature['wkt']),
'projection' => $feature['projection'],
'features' => array($feature)
);
return $features;
}
}
else {
array_push($features, $feature);
return $features;
}
}
}

View File

@@ -0,0 +1,73 @@
<?php
/**
* @file
* This file holds style plugin for OpenLayers Views
*
* @ingroup openlayers
*/
/**
* @class
* Extension of the Views Plugin Syle for OpenLayers
*
* This class extended the default views plugin class to provide
* a style plugin for the Open Layers module.
*/
class openlayers_views_style_map extends views_plugin_style {
/**
* Set default options
*/
function option_definition() {
$options = parent::option_definition();
$options['map'] = array(
'default' => variable_get('openlayers_default_map', 'default'));
return $options;
}
/**
* Options form
*/
function options_form(&$form, &$form_state) {
parent::options_form($form, $form_state);
// Map
$form['map'] = array(
'#type' => 'select',
'#title' => t('Map'),
'#description' => t('This is map that will be used to render the view.'),
'#options' => openlayers_map_options(),
'#default_value' => $this->options['map'] ?
$this->options['map'] :
variable_get('openlayers_default_map', 'default'),
);
}
/**
* Query - override to make sure this doesn't get run
*/
function query() {
if (isset($this->view->query->fields)) {
$this->view->query->fields = array();
}
$this->view->executed = TRUE;
$this->view->result = TRUE;
$map = openlayers_map_load($this->options['map']);
$render = openlayers_render_map($map, $map->name);
$this->view->result = $render || !$map->data['hide_empty_map'] ? TRUE : FALSE;
}
/**
* Renders views (map)
*/
function render() {
// Get selected map
$map = openlayers_map_load($this->options['map']);
return theme($this->theme_functions(), array(
'view' => $this->view,
'options' => $this->options,
'map' => openlayers_render_map($map, $map->name)
));
}
}

View File

@@ -0,0 +1,15 @@
name = "OpenLayers"
description = "OpenLayers base API module"
core = 7.x
package = "OpenLayers"
php = 5.2
dependencies[] = ctools
; Core files
files[] = openlayers.module
; Information added by drupal.org packaging script on 2013-02-05
version = "7.x-2.0-beta3+76-dev"
core = "7.x"
project = "openlayers"
datestamp = "1360071107"

View File

@@ -0,0 +1,325 @@
<?php
/**
* @file
* This file holds the functions for the installing
* and enabling of the openlayers module.
*
* @ingroup openlayers
*/
/**
* Implements hook_install().
*/
function openlayers_install() {
}
/**
* Implements hook_uninstall().
*/
function openlayers_uninstall() {
// Get module variables
global $conf;
foreach (array_keys($conf) as $key) {
// Find variables that have the module prefix
if (strpos($key, 'openlayers_') === 0) {
variable_del($key);
}
}
}
/**
* Implements hook_schema().
*/
function openlayers_schema() {
$schema = array();
// Maps table (ctools extras)
$schema['openlayers_maps'] = array(
'description' => 'Storage for User defined OpenLayers maps.',
'export' => array(
'key' => 'name',
'key name' => 'Name',
'primary key' => 'name',
'identifier' => 'openlayers_maps',
'default hook' => 'openlayers_maps',
'api' => array(
'owner' => 'openlayers',
'api' => 'openlayers_maps',
'minimum_version' => 1,
'current_version' => 1,
),
),
'fields' => array(
'name' => array(
'description' => 'The primary identifier for the map.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
),
'title' => array(
'description' => 'The title of the map.',
'type' => 'varchar',
'length' => 255,
'not null' => TRUE,
),
'description' => array(
'description' => 'The description of the map.',
'type' => 'text',
'not null' => TRUE,
),
'data' => array(
'description' => 'The serialized map.',
'type' => 'text',
'not null' => TRUE,
'serialize' => TRUE,
),
),
'primary key' => array('name'),
);
// Layer table (ctools extras)
$schema['openlayers_layers'] = array(
'description' => 'Storage for user defined OpenLayers layers.',
'export' => array(
'key' => 'name',
'key name' => 'Name',
'primary key' => 'name',
'identifier' => 'openlayers_layers',
'default hook' => 'openlayers_layers',
'api' => array(
'owner' => 'openlayers',
'api' => 'openlayers_layers',
'minimum_version' => 1,
'current_version' => 1,
),
),
'fields' => array(
'name' => array(
'type' => 'varchar',
'length' => '255',
'not null' => TRUE,
'default' => '',
'description' => 'Layer name.',
),
'title' => array(
'type' => 'varchar',
'length' => '255',
'not null' => TRUE,
'default' => '',
'description' => 'Layer title.',
),
'description' => array(
'type' => 'text',
'not null' => TRUE,
'description' => 'Layer description.',
),
'data' => array(
'type' => 'text',
'not null' => FALSE,
'description' => 'Layer data serialized.',
'serialize' => TRUE,
),
),
'primary key' => array('name'),
);
// Styles table (ctools extras)
$schema['openlayers_styles'] = array(
'description' => 'Storage for user defined OpenLayers styles.',
'export' => array(
'key' => 'name',
'key name' => 'Name',
'primary key' => 'name',
'identifier' => 'openlayers_styles',
'default hook' => 'openlayers_styles',
'api' => array(
'owner' => 'openlayers',
'api' => 'openlayers_styles',
'minimum_version' => 1,
'current_version' => 1,
),
),
'fields' => array(
'name' => array(
'type' => 'varchar',
'length' => '255',
'not null' => TRUE,
'default' => '',
'description' => 'Style name.',
),
'title' => array(
'type' => 'varchar',
'length' => '255',
'not null' => TRUE,
'default' => '',
'description' => 'Style title.',
),
'description' => array(
'type' => 'text',
'not null' => TRUE,
'description' => 'Style description.',
),
'data' => array(
'type' => 'text',
'not null' => FALSE,
'description' => 'Style data serialized.',
'serialize' => TRUE,
),
),
'primary key' => array('name'),
);
return $schema;
}
/**
* Implements hook_requirements().
*/
function openlayers_requirements($phase) {
$req = array();
$t = get_t();
// We should not require a specfic version of the OpenLayers library, but
// we should tell the administrator that specific versions are more
// compatible than others.
if ($phase == 'runtime') {
$ol_library_version = 0;
$current_library = variable_get('openlayers_source', OPENLAYERS_DEFAULT_LIBRARY);
// As of 2.11, the hosted version supports the newest hosted
// stable with an actual version number. This used to be just under
// the 'api' path.
if (strpos($current_library, (string) OPENLAYERS_SUGGESTED_LIBRARY) !== FALSE) {
$ol_library_version = OPENLAYERS_SUGGESTED_LIBRARY;
}
// Check if it is the default hosted.
if ($current_library == 'http://openlayers.org/api/OpenLayers.js') {
$ol_library_version = OPENLAYERS_HOSTED_API_LIBRARY;
}
// Finally, let's see if the client has sent us a value
// from the UI module AJAX magic.
$client = variable_get('openlayers_ui_version_check', '');
if (strpos($client, (string) OPENLAYERS_SUGGESTED_LIBRARY) !== FALSE) {
$ol_library_version = OPENLAYERS_SUGGESTED_LIBRARY;
}
// Check if suggest version.
if ($ol_library_version == OPENLAYERS_SUGGESTED_LIBRARY) {
$req['openlayers_old_presets'] = array(
'title' => $t('OpenLayers library version'),
'value' => $t('Using suggested compatible version %suggested.',
array(
'%suggested' => OPENLAYERS_SUGGESTED_LIBRARY,
)),
'severity' => REQUIREMENT_OK,
);
}
else {
$req['openlayers_old_presets'] = array(
'title' => $t('OpenLayers library version'),
'value' => $t('Not suggested compatible version.'),
'description' => $t('Though you are very welcome to use whatever version of the OpenLayers library you want, it is suggested that you use version %suggested. You are currently not using that version or we are unable to determine which version you are using. Update your library settings at !settings.',
array(
'%suggested' => OPENLAYERS_SUGGESTED_LIBRARY,
'!settings' => l(t('OpenLayers settings'), 'admin/structure/openlayers'),
)),
'severity' => REQUIREMENT_WARNING,
);
}
}
// There are some backwards compability for the shift from
// preset to maps. We want to communicate to administrators
// that this will not be there forever.
if ($phase == 'runtime') {
// Check preset hook
$presets = module_invoke_all('openlayers_presets');
$found_presets = (count($presets) > 0) ? TRUE : FALSE;
// Check features
$feature_names = array();
$found_features = FALSE;
if (module_exists('features')) {
$features = features_get_features();
foreach ($features as $feature) {
// Only utilize enabled features and look for presets
if ($feature->status > 0 && !empty($feature->info['features']['openlayers_map_presets'])) {
$feature_names[] = $feature->name;
$found_features = TRUE;
}
}
}
// Create requirement entries
if ($found_presets) {
$req['openlayers_old_presets'] = array(
'title' => $t('OpenLayers Presets'),
'value' => $t('Found old presets.'),
'description' => $t('With the 7.x-2.x version of the OpenLayers module, map presets were renamed to just maps. This has some implications on APIs and hooks. One or more of of the modules installed on this site is utilizing the deprecated %hook. Please <a href="@url">read the upgrade page</a>, then contact the module owner or fix the custom module yourself.',
array(
'%hook' => 'hook_openlayers_presets()',
'@url' => url('http://drupal.org/node/1136810'),
)),
'severity' => REQUIREMENT_ERROR,
);
}
if ($found_features) {
$req['openlayers_old_features'] = array(
'title' => $t('OpenLayers Presets'),
'value' => $t('Found Features with presets.'),
'description' => $t('With the 7.x-2.x version of the OpenLayers module, map presets were renamed to just maps. This has some implications on APIs and hooks. There are Features on this site that contain the old map presets. Please <a href="@url">read the upgrade page</a>, and rebuild the following Features: %features',
array(
'@url' => url('http://drupal.org/node/1136810'),
'%features' => implode(',', $feature_names),
)),
'severity' => REQUIREMENT_ERROR,
);
}
}
return $req;
}
/**
* Implements hook_update_N().
*
* Rename of presets to maps.
*/
function openlayers_update_7201() {
// Change table name
db_rename_table('openlayers_map_presets', 'openlayers_maps');
// Set default map variable
variable_set('openlayers_default_map', variable_get('openlayers_default_preset', 'default'));
variable_del('openlayers_default_preset');
}
/**
* Drop name indexes duplicates of primary key.
*/
function openlayers_update_7202() {
db_drop_index('openlayers_layers', 'name');
db_drop_index('openlayers_styles', 'name');
}
/**
* Renamme the 'baselayer' in 'isBaseLayer' in layers.
*/
function openlayers_update_7204() {
foreach (openlayers_layers_load() as $key => $layer) {
if ($layer->export_type != 1) continue;
if (isset($layer->data['baselayer'])) {
$layer->data['isBaseLayer'] = $layer->data['baselayer'];
unset($layer->data['baselayer']);
ctools_export_crud_save('openlayers_layers', $layer);
}
}
}
/**
* Change the case of machine_name for layers, maps and styles.
* Warning, it can break things.
*/
function openlayers_update_7205() {
db_query('UPDATE {openlayers_layers} SET name = LOWER(name);');
db_query('UPDATE {openlayers_styles} SET name = LOWER(name);');
db_query('UPDATE {openlayers_maps} SET name = LOWER(name);');
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,61 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_argparser_openlayers_behaviors() {
return array(
'title' => t('Argument Parser'),
'description' => t('Parses Permalink-formatted arguments without adding a
Permalink link to the map. Permalink is usually similar to:
?zoom=1&lat=11&lon=11&layers=B0F'),
'type' => 'layer',
'behavior' => array(
'file' => 'openlayers_behavior_argparser.inc',
'class' => 'openlayers_behavior_argparser',
'parent' => 'openlayers_behavior',
),
);
}
/**
* Attribution Behavior
*/
class openlayers_behavior_argparser extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'anchor' => FALSE,
);
}
function js_dependency() {
return array('OpenLayers.Control.ArgParser');
}
function options_form($defaults = array()) {
return array(
'anchor' => array(
'#type' => 'checkbox',
'#title' => t('Anchor'),
'#description' => t('Permalink is in the form of an anchor (#) instead of a query (?).'),
'#default_value' => (isset($defaults['anchor'])) ? $defaults['anchor'] : FALSE,
),
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_argparser.js');
return $this->options;
}
}

View File

@@ -0,0 +1,12 @@
/**
* @file
* JS Implementation of OpenLayers behavior.
*/
/**
* ArgParser Behavior. Implements the ArgParser OpenLayers
* Control.
*/
Drupal.openlayers.addBehavior('openlayers_behavior_argparser', function (data, options) {
Drupal.openlayers.addControl(data.openlayers, 'ArgParser', options);
});

View File

@@ -0,0 +1,58 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_attribution_openlayers_behaviors() {
return array(
'title' => t('Layer Attribution'),
'description' => t('Allows layers to provide attribution to the map if it exists. Most third-party layer will have some sort of attribution, but this may come with the actual tiles as well.'),
'type' => 'layer',
'behavior' => array(
'file' => 'openlayers_behavior_attribution.inc',
'class' => 'openlayers_behavior_attribution',
'parent' => 'openlayers_behavior',
),
);
}
/**
* Attribution Behavior
*/
class openlayers_behavior_attribution extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'seperator' => '',
);
}
function js_dependency() {
return array('OpenLayers.Control.Attribution');
}
function options_form($defaults = array()) {
return array(
'seperator' => array(
'#type' => 'textfield',
'#title' => t('Seperator'),
'#description' => t('For multiple layers that need attribution, provide a separation string.'),
'#default_value' => (isset($defaults['seperator'])) ? $defaults['seperator'] : FALSE,
),
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_attribution.js');
return $this->options;
}
}

View File

@@ -0,0 +1,12 @@
/**
* @file
* JS Implementation of OpenLayers behavior.
*/
/**
* Attribution Behavior. Implements the Attribution OpenLayers
* Control.
*/
Drupal.openlayers.addBehavior('openlayers_behavior_attribution', function (data, options) {
Drupal.openlayers.addControl(data.openlayers, 'Attribution', options);
});

View File

@@ -0,0 +1,57 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_boxselect_openlayers_behaviors() {
return array(
'title' => t('Bounding Box Select'),
'description' => t('Allows the selection and display of a bounding box. Currently hard-coded for the map making interface.'),
'type' => 'map',
'ui_visibility' => FALSE,
'behavior' => array(
'file' => 'openlayers_behavior_boxselect.inc',
'class' => 'openlayers_behavior_boxselect',
'parent' => 'openlayers_behavior',
),
);
}
/**
* BoxSelect Behavior
*/
class openlayers_behavior_boxselect extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'input_fields' => '',
);
}
function js_dependency() {
return array(
'OpenLayers.Control.DrawFeature',
'OpenLayers.Layer.Vector',
'OpenLayers.Handler.RegularPolygon'
);
}
function options_form($defaults = array()) {
return array(
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_boxselect.js');
return $this->options;
}
}

View File

@@ -0,0 +1,61 @@
/**
* @file
* JS Implementation of OpenLayers behavior.
*/
// Not the best, but gets around scoping;
var selections_layer;
(function ($) {
/**
* Box Select Behavior. Allows user to select a bounding box.
*
* TODO: This is currently hard coded for the center UI form.
*/
Drupal.openlayers.addBehavior('openlayers_behavior_boxselect', function (data, options) {
// Callback to set extent into a specific form item.
function setRestrictedExtent(box) {
var bounding_box = box.geometry.getBounds().toBBOX();
$('#edit-center-restrict-restrictedextent').val(bounding_box);
// Check box
if (!($('#restrictextent').attr('checked'))) {
$('#restrictextent')
.attr('checked', 'checked')
.trigger('change');
}
// Remove any other features.
for (var i = 0; i < selections_layer.features.length; i++) {
if (selections_layer.features[i] != box) {
selections_layer.features[i].destroy();
}
}
}
// Create layer to draw with and handle events.
var selections_layer = new OpenLayers.Layer.Vector('Temporary Box Layer');
var control = new OpenLayers.Control.DrawFeature(selections_layer,
OpenLayers.Handler.RegularPolygon, {
featureAdded: setRestrictedExtent
}
);
control.handler.setOptions({
'keyMask': OpenLayers.Handler.MOD_SHIFT,
'sides': 4,
'irregular': true
});
control.events.on({'featureAdded': this.setRestrictedExtent});
data.openlayers.addLayer(selections_layer);
data.openlayers.addControl(control);
// If there already is a value, then update the map appropriately.
if ($('#edit-center-restrict-restrictedextent').val()) {
bounds = $('#edit-center-restrict-restrictedextent').val();
geometry = new OpenLayers.Bounds.fromString(bounds).toGeometry();
feature = new OpenLayers.Feature.Vector(geometry);
selections_layer.addFeatures([feature]);
}
control.activate();
});
}(jQuery));

View File

@@ -0,0 +1,96 @@
<?php
/**
* @file
* Implementation of OpenLayers Cluster behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_cluster_openlayers_behaviors() {
return array(
'title' => t('Cluster Features'),
'description' => t('Provides vector layer features clustering by proximity. This will not always respect the styles that assigned to the layer.'),
'type' => 'layer',
'behavior' => array(
'file' => 'openlayers_behavior_cluster.inc',
'class' => 'openlayers_behavior_cluster',
'parent' => 'openlayers_behavior',
),
);
}
/**
* Cluster behavior
*/
class openlayers_behavior_cluster extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'clusterlayer' => array(),
'distance' => '20',
'threshold' => NULL,
);
}
/**
* OpenLayers library dependency.
*/
function js_dependency() {
return array('OpenLayers.Strategy.Cluster');
}
/**
* Provide form for configurations per map.
*/
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(
'clusterlayer' => array(
'#title' => t('Layers'),
'#type' => 'checkboxes',
'#options' => $vector_layers,
'#description' => t('Select layers to cluster.'),
'#default_value' => isset($defaults['clusterlayer']) ?
$defaults['clusterlayer'] : array(),
),
'distance' => array(
'#type' => 'textfield',
'#default_value' => (isset($defaults['distance'])) ?
$defaults['distance'] : 20,
'#size' => 5,
'#title' => t('Distance'),
'#description' => t('Pixel distance between features that should ' .
'be considered a single cluster'),
),
'threshold' => array(
'#type' => 'textfield',
'#default_value' => (isset($defaults['threshold'])) ?
$defaults['threshold'] : NULL,
'#size' => 5,
'#title' => t('Threshold'),
'#description' => t('Optional threshold below which original ' .
'features will be added to the layer instead of clusters'),
)
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_cluster.js');
return $this->options;
}
}

View File

@@ -0,0 +1,69 @@
/**
* @file
* OpenLayers Behavior implementation for clustering.
*/
/**
* OpenLayers Cluster Behavior.
*/
Drupal.openlayers.addBehavior('openlayers_behavior_cluster', function (data, options) {
var map = data.openlayers;
var distance = parseInt(options.distance, 10);
var threshold = parseInt(options.threshold, 10);
var layers = [];
for (var i in options.clusterlayer) {
var selectedLayer = map.getLayersBy('drupalID', options.clusterlayer[i]);
if (typeof selectedLayer[0] != 'undefined') {
layers.push(selectedLayer[0]);
}
}
// Go through chosen layers
for (var i in layers) {
var layer = layers[i];
// Ensure vector layer
if (layer.CLASS_NAME == 'OpenLayers.Layer.Vector') {
var cluster = new OpenLayers.Strategy.Cluster(options);
layer.addOptions({ 'strategies': [cluster] });
cluster.setLayer(layer);
cluster.features = layer.features.slice();
cluster.activate();
cluster.cluster();
}
}
});
/**
* Override of callback used by 'popup' behaviour to support clusters
*/
Drupal.theme.openlayersPopup = function (feature) {
if (feature.cluster) {
var output = '';
var visited = []; // to keep track of already-visited items
var classes = [];
for (var i = 0; i < feature.cluster.length; i++) {
var pf = feature.cluster[i]; // pseudo-feature
if (typeof pf.drupalFID != 'undefined') {
var mapwide_id = feature.layer.drupalID + pf.drupalFID;
if (mapwide_id in visited) continue;
visited[mapwide_id] = true;
}
classes = ['openlayers-popup', 'openlayers-popup-feature'];
if (i == 0) {
classes.push('first');
}
if (i == (feature.cluster.length - 1)) {
classes.push('last');
}
output += '<div class="'+classes.join(' ')+'">' +
Drupal.theme.prototype.openlayersPopup(pf) + '</div>';
}
return output;
}
else {
return Drupal.theme.prototype.openlayersPopup(feature);
}
};

View File

@@ -0,0 +1,73 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_dragpan_openlayers_behaviors() {
return array(
'title' => t('Mouse Drag Pan'),
'description' => t('Provides the ability to pan in the map interface with the mouse. The Navigation Control includes this control. You should only use this behavior if you want fine control over what interactions you want on your map.'),
'type' => 'map',
'behavior' => array(
'file' => 'openlayers_behavior_dragpan.inc',
'class' => 'openlayers_behavior_dragpan',
'parent' => 'openlayers_behavior',
),
);
}
/**
* DragPan Behavior
*/
class openlayers_behavior_dragpan extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'enableKinetic' => FALSE,
'kineticInterval' => 10,
);
}
function js_dependency() {
return array('OpenLayers.Control.DragPan');
}
function options_form($defaults = array()) {
$form = array();
// This options seem to be buggy. Shoudl look into more.
/*
$form = array(
'enableKinetic' => array(
'#title' => t('Enable Kinetic Dragging'),
'#type' => 'checkbox',
'#description' => t('Enables dragging and panning to have acceleration.'),
'#default_value' => isset($defaults['enableKinetic']) ? $defaults['enableKinetic'] : FALSE,
),
'kineticInterval' => array(
'#title' => t('Kinetic Interval'),
'#type' => 'textfield',
'#description' => t('An integer of millseconds of time between steps in "Kinetic Scrolling".'),
'#default_value' => isset($defaults['kineticInterval']) ? $defaults['kineticInterval'] : 10,
),
);
*/
return $form;
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_dragpan.js');
return $this->options;
}
}

View File

@@ -0,0 +1,12 @@
/**
* @file
* JS Implementation of OpenLayers behavior.
*/
/**
* DragPan Behavior. Implements the DragPan OpenLayers
* Control.
*/
Drupal.openlayers.addBehavior('openlayers_behavior_dragpan', function (data, options) {
Drupal.openlayers.addControl(data.openlayers, 'DragPan', options);
});

View File

@@ -0,0 +1,12 @@
/**
* @file
* CSS for OpenLayers Draw Features Behavior
*/
.olControlEditingToolbar .olControlModifyFeatureItemActive {
background-position: -1px -24px;
}
.olControlEditingToolbar .olControlModifyFeatureItemInactive {
background-position: -1px -1px;
}

View File

@@ -0,0 +1,79 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_drawfeatures_openlayers_behaviors() {
return array(
'title' => t('Draw Features'),
'description' => t('Provides functionality for adding features to a map.'),
'type' => 'layer',
'behavior' => array(
'file' => 'openlayers_behavior_drawfeatures.inc',
'class' => 'openlayers_behavior_drawfeatures',
'parent' => 'openlayers_behavior',
),
);
}
/**
* Draw Features behavior
*/
class openlayers_behavior_drawfeatures extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'element_id' => '',
'feature_types' => array(),
'feature_limit' => 0,
);
}
function options_form($defaults = array()) {
$features = array(
'point' => t('Point'),
'path' => t('Path'),
'polygon' => t('Polygon'),
);
return array(
'feature_types' => array(
'#title' => t('Available Features'),
'#type' => 'checkboxes',
'#options' => $features,
'#description' => t('Select what features are available to draw.'),
'#default_value' => isset($defaults['feature_types']) ? $defaults['feature_types'] : array(),
),
'feature_limit' => array(
'#title' => t('Number of features'),
'#type' => 'textfield',
'#description' => t('The number of features that are allowed to be
drawn. Leave blank or at 0 for unlimited.'),
'#default_value' => isset($defaults['feature_limit']) ? $defaults['feature_limit'] : 0,
),
'element_id' => array(
'#type' => 'textfield',
'#default_value' => (isset($defaults['element_id'])) ?
$defaults['element_id'] : '',
'#title' => t('Element ID'),
'#description' => t('The DOM element ID that will be passed the value of the features. This will probably be a textfield or textarea.'),
)
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_css(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_drawfeatures.css');
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_drawfeatures.js');
return $this->options;
}
}

View File

@@ -0,0 +1,153 @@
/**
* @file
* DrawFeatures Behavior
*/
(function($) {
/**
* Behavior for Draw Features.
*
* TODO: Update this to use the addBehaviors helper function.
*/
Drupal.behaviors.openlayers_behavior_drawfeatures = {
'attach': function(context, settings) {
// Update function to write to element.
function openlayers_behavior_drawfeatures_update(features) {
WktWriter = new OpenLayers.Format.WKT();
while (features.type == 'featureadded' && (this.feature_limit > 0) &&
(this.feature_limit < features.object.features.length)) {
features.feature.layer.removeFeatures(features.object.features.shift());
}
var features_copy = features.object.clone();
for (var i in features_copy.features) {
features_copy.features[i].geometry.transform(
features.object.map.projection,
new OpenLayers.Projection('EPSG:4326')
);
}
if (this.element != undefined) {
this.element.val(WktWriter.write(features_copy.features));
}
}
// Start behavior process
var data = $(context).data('openlayers');
var behavior = data && data.map.behaviors['openlayers_behavior_drawfeatures'];
if (!$(context).hasClass('openlayers-drawfeatures-processed') && behavior) {
// Create element
var feature_types = data.map.behaviors['openlayers_behavior_drawfeatures'].feature_types;
if (data.map.behaviors['openlayers_behavior_drawfeatures'].element_id != "") {
this.element = $('#' + data.map.behaviors['openlayers_behavior_drawfeatures'].element_id);
}
// Handle vector layer for drawing on
this.feature_limit = data.map.behaviors['openlayers_behavior_drawfeatures'].feature_limit;
var dataLayer = new OpenLayers.Layer.Vector(Drupal.t('Feature Layer'), {
projection: new OpenLayers.Projection('EPSG:4326'),
drupalID: 'openlayers_drawfeatures_layer'
});
dataLayer.styleMap = Drupal.openlayers.getStyleMap(data.map, 'openlayers_drawfeatures_layer');
data.openlayers.addLayer(dataLayer);
if (this.feature_limit == "") {
this.feature_limit = 0;
}
// If there is data in there now, use to populate the layer.
if ((this.element != undefined) && (this.element.text() != '')) {
var wktFormat = new OpenLayers.Format.WKT();
var features = wktFormat.read(this.element.text());
if (features.constructor == Array) {
for (var i in features) {
features[i].geometry = features[i].geometry.transform(
new OpenLayers.Projection('EPSG:4326'),
data.openlayers.projection
);
}
}
else {
features.geometry = features.geometry.transform(
new OpenLayers.Projection('EPSG:4326'),
data.openlayers.projection
);
features = [features];
}
dataLayer.addFeatures(features);
}
// Registering events late, because adding data
// would result in a reprojection loop
dataLayer.events.register('featureadded', this,
openlayers_behavior_drawfeatures_update);
dataLayer.events.register('featureremoved', this,
openlayers_behavior_drawfeatures_update);
dataLayer.events.register('featuremodified', this,
openlayers_behavior_drawfeatures_update);
// Use the Editing Toolbar for creating features.
var control = new OpenLayers.Control.EditingToolbar(dataLayer);
data.openlayers.addControl(control);
control.activate();
// Build an array of the requested feature classes
var feature_classmap = {
'point': 'OpenLayers.Handler.Point',
'path': 'OpenLayers.Handler.Path',
'polygon': 'OpenLayers.Handler.Polygon'
};
var feature_classes = [];
for (var i in feature_types) {
if (feature_types[i] !== 0) {
feature_classes.push(feature_classmap[feature_types[i]]);
}
}
// Reconstruct editing toolbar controls so to only contain
// the tools for the requested feature types / classes
// plus the navigation tool
control.controls = $.map(control.controls,
function(control) {
return (control.CLASS_NAME == 'OpenLayers.Control.Navigation' ||
$.inArray(control.handler.CLASS_NAME, feature_classes) != -1)
? control : null;
}
);
control.activateControl(control.getControlsByClass('OpenLayers.Control.Navigation')[0]);
control.redraw();
if (this.element != undefined) {
this.element.parents('form').bind('submit',
{
control: control,
dataLayer: dataLayer
}, function(evt) {
$.map(evt.data.control.controls, function(c) { c.deactivate(); });
dataLayer.events.triggerEvent('featuremodified');
}
);
}
// Add modify feature tool
control.addControls(new OpenLayers.Control.ModifyFeature(
dataLayer, {
displayClass: 'olControlModifyFeature',
deleteCodes: [46, 68, 100],
handleKeypress: function(evt) {
if (this.feature && $.inArray(evt.keyCode, this.deleteCodes) > -1) {
// We must unselect the feature before we delete it
var feature_to_delete = this.feature;
this.selectControl.unselectAll();
this.layer.removeFeatures([feature_to_delete]);
}
}
}
)
);
$(context).addClass('openlayers-drawfeatures-processed');
}
}
};
})(jQuery);

View File

@@ -0,0 +1,25 @@
.openlayers_map_fullscreen {
position: fixed;
z-index: 9999;
background-color: #fff;
top: 0;
left: 0;
height: 100% !important;
width: 100% !important;
}
.openlayers_behavior_fullscreen_button_panel {
position: absolute;
top: 5px;
right: 5px;
}
.openlayers_behavior_fullscreen_buttonItemInactive {
background:url(openlayers_behavior_fullscreen.png);
width:20px;
height:20px;
}
.openlayers_map_fullscreen .openlayers_behavior_fullscreen_buttonItemInactive {
background-position:20px 0;
}

View File

@@ -0,0 +1,67 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_fullscreen_openlayers_behaviors() {
return array(
'title' => t('Fullscreen'),
'description' => t('Provides a button that expands maps to the size of the page.'),
'type' => 'map',
'behavior' => array(
'file' => 'openlayers_behavior_fullscreen.inc',
'class' => 'openlayers_behavior_fullscreen',
'parent' => 'openlayers_behavior',
),
);
}
/**
* Fullscreen Behavior
*/
class openlayers_behavior_fullscreen extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'activated' => FALSE
);
}
/**
* Provide form for configurations per map.
*/
function options_form($defaults = array()) {
return array(
'activated' => array(
'#title' => t('Initially activated'),
'#type' => 'checkbox',
'#description' => t('Select to be in fullscreen by default.'),
'#default_value' => isset($defaults['activated']) ? $defaults['activated'] : FALSE
)
);
}
function js_dependency() {
return array(
'OpenLayers.Control.Button'
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_css(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_fullscreen.css');
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_fullscreen.js');
return $this->options;
}
}

View File

@@ -0,0 +1,46 @@
/**
* @file
* JS Implementation of OpenLayers behavior.
*/
/**
* Attribution Behavior
*/
Drupal.openlayers.addBehavior('openlayers_behavior_fullscreen', function (data, options) {
// Create new panel control and add.
var fullscreenPanel = new OpenLayers.Control.Panel({
displayClass: 'openlayers_behavior_fullscreen_button_panel'
});
data.openlayers.addControl(fullscreenPanel);
// Create toggleing control and cutton.
var toggler = OpenLayers.Function.bind(
Drupal.openlayers.fullscreenToggle, data);
var button = new OpenLayers.Control.Button({
displayClass: 'openlayers_behavior_fullscreen_button',
title: Drupal.t('Fullscreen'),
trigger: toggler
});
fullscreenPanel.addControls([button]);
// Make fullscreen by default if activited.
if (options.activated == true) {
toggler();
}
});
(function ($) {
/**
* Toggling function for FullScreen control.
*/
Drupal.openlayers.fullscreenToggle = function () {
var map = this.openlayers;
var $map = $(this.openlayers.div);
var extent = map.getExtent();
$map.parent().toggleClass('openlayers_map_fullscreen');
$map.toggleClass('openlayers_map_fullscreen');
$map.data('openlayers').openlayers.updateSize();
$map.data('openlayers').openlayers.zoomToExtent(extent, true);
};
}(jQuery));

Binary file not shown.

After

Width:  |  Height:  |  Size: 663 B

View File

@@ -0,0 +1,91 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_geolocate_openlayers_behaviors() {
return array(
'title' => t('Geolocate Client'),
'description' => t('Provides the geolcoation control that simply zooms to users location on map load. Based on HTML5 geolocation, so this will not be supported in all browsers.'),
'type' => 'map',
'behavior' => array(
'file' => 'openlayers_behavior_geolocate.inc',
'class' => 'openlayers_behavior_geolocate',
'parent' => 'openlayers_behavior',
),
);
}
/**
* Zoom Panel Behavior
* http://dev.openlayers.org/docs/files/OpenLayers/Control/Geolocate-js.html
*/
class openlayers_behavior_geolocate extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'bind' => TRUE,
'watch' => FALSE,
'geolocationOptions' => array(
'enableHighAccuracy' => FALSE,
'maximumAge' => 0,
'timeout' => 7000,
),
'zoom_level' => 12,
);
}
function options_form($defaults = array()) {
$intials = $this->options_init();
return array(
'bind' => array(
'#title' => t('Center when located'),
'#type' => 'select',
'#options' => array(
TRUE => t('Yes'),
FALSE => t('No'),
),
'#description' => t('When enabled, if the geolocation control finds a location, it will set the center of the map at this point.'),
'#default_value' => isset($defaults['bind']) ? $defaults['bind'] : $intials['bind'],
),
'zoom_level' => array(
'#title' => t('Zoom level'),
'#type' => 'textfield',
'#description' => t('An integer zoom level for when a location is found. 0 is the most zoomed out and higher numbers mean more zoomed in (the number of zoom levels depends on your map).'),
'#default_value' => isset($defaults['zoom_level']) ? $defaults['zoom_level'] : $intials['zoom_level'],
),
'watch' => array(
'#title' => t('Watch'),
'#type' => 'select',
'#options' => array(
TRUE => t('Yes'),
FALSE => t('No'),
),
'#description' => t('When enabled, the map will continue to try to update the location of the device.'),
'#default_value' => isset($defaults['watch']) ? $defaults['watch'] : $intials['watch'],
),
);
}
function js_dependency() {
return array(
'OpenLayers.Control.Geolocate'
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_geolocate.js');
return $this->options;
}
}

View File

@@ -0,0 +1,29 @@
/**
* @file
* JS Implementation of OpenLayers behavior.
*/
/**
* Geolocate Control. Implements the Geolocate OpenLayers
* Control.
*/
Drupal.openlayers.addBehavior('openlayers_behavior_geolocate', function (data, options) {
// Create Geolocate control
var geolocate = new OpenLayers.Control.Geolocate(options);
data.openlayers.addControl(geolocate);
// Adding the watch options.
// {Boolean} If true, position will be update regularly.
geolocate.watch = (options.watch == 1) ? true : false;
// Add some event handling
geolocate.events.register('locationupdated', this, function(e) {
data.openlayers.setCenter(new OpenLayers.Geometry.Point(e.point.x, e.point.y), options.zoom_level);
});
geolocate.events.register('locationfailed', this, function(e) {
OpenLayers.Console.log(Drupal.t('Location detection failed'));
});
// Activate!
geolocate.activate();
});

View File

@@ -0,0 +1,100 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_graticule_openlayers_behaviors() {
return array(
'title' => t('Graticule'),
'description' => t('Adds a graticule control to the map to display a grid of latitude and longitude.'),
'type' => 'layer',
'behavior' => array(
'file' => 'openlayers_behavior_graticule.inc',
'class' => 'openlayers_behavior_graticule',
'parent' => 'openlayers_behavior',
),
);
}
/**
* Attribution Behavior
*/
class openlayers_behavior_graticule extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'labelled' => TRUE,
'numPoints' => 50,
'targetSize' => 200,
'displayInLayerSwitcher' => TRUE,
'lineSymbolizer' => array(
'strokeColor' => '#333',
'strokeWidth' => 1,
'strokeOpacity' => 0.5
)
);
}
function options_form($defaults = array()) {
return array(
'displayInLayerSwitcher' => array(
'#type' => 'checkbox',
'#title' => t('Display in layer switcher ?'),
'#description' => t('Allows the Graticule control to be switched on and off by LayerSwitcher control. Default is true.'),
'#default_value' => (isset($defaults['displayInLayerSwitcher'])) ? $defaults['displayInLayerSwitcher'] : TRUE,
),
'labelled' => array(
'#type' => 'checkbox',
'#title' => t('Labelled'),
'#description' => t('Should the graticule lines be labelled ? Default is true.'),
'#default_value' => (isset($defaults['labelled'])) ? $defaults['labelled'] : TRUE,
),
'numPoints' => array(
'#type' => 'textfield',
'#title' => t('Number of points'),
'#description' => t('The number of points to use in each graticule line. Higher numbers result in a smoother curve for projected maps '),
'#default_value' => (isset($defaults['numPoints'])) ? $defaults['numPoints'] : 50,
),
'targetSize' => array(
'#type' => 'textfield',
'#title' => t('Target size'),
'#description' => t('The maximum size of the grid in pixels on the map.'),
'#default_value' => (isset($defaults['targetSize'])) ? $defaults['targetSize'] : 200,
),
'lineSymbolizer' => array(
'strokeColor' => array(
'#type' => 'textfield',
'#title' => t('Stroke color'),
'#description' => t('The color code to use for the lines. Example: #333'),
'#default_value' => (isset($defaults['lineSymbolizer']['strokeColor'])) ? $defaults['lineSymbolizer']['strokeColor'] : '#333',
),
'strokeWidth' => array(
'#type' => 'textfield',
'#title' => t('Stroke width'),
'#description' => t('The width of the lines. Example: 1'),
'#default_value' => (isset($defaults['lineSymbolizer']['strokeWidth'])) ? $defaults['lineSymbolizer']['strokeWidth'] : 1,
),
'strokeOpacity' => array(
'#type' => 'textfield',
'#title' => t('Stroke opacity'),
'#description' => t('The opacity of the line, from 0 to 1. Example: 0.5'),
'#default_value' => (isset($defaults['lineSymbolizer']['strokeOpacity'])) ? $defaults['lineSymbolizer']['strokeOpacity'] : 0.5,
),
)
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_graticule.js');
return $this->options;
}
}

View File

@@ -0,0 +1,11 @@
/**
* @file
* JS Implementation of OpenLayers behavior.
*/
/**
* Graticule Behavior. Implements the Graticule Control.
*/
Drupal.openlayers.addBehavior('openlayers_behavior_graticule', function (data, options) {
Drupal.openlayers.addControl(data.openlayers, 'Graticule', options);
});

View File

@@ -0,0 +1,44 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_keyboarddefaults_openlayers_behaviors() {
return array(
'title' => t('Keyboard Controls'),
'description' => t('Provides keyboard shortcuts to pan and zoom the map, such as the up, down, left, and right arrows. This is included with the Navigation control. This should not be enabled unless you want to have finer control on how the user interacts with the map.'),
'type' => 'layer',
'behavior' => array(
'file' => 'openlayers_behavior_keyboarddefaults.inc',
'class' => 'openlayers_behavior_keyboarddefaults',
'parent' => 'openlayers_behavior',
),
);
}
/**
* Keyboard Defaults Behavior
*/
class openlayers_behavior_keyboarddefaults extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'keyboarddefaults' => '',
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_keyboarddefaults.js');
return $this->options;
}
}

View File

@@ -0,0 +1,13 @@
/**
* @file
* JS Implementation of OpenLayers behavior.
*/
/**
* Keyboard Defaults Behavior. Implements the KeyboardDefaults OpenLayers
* Control.
*/
Drupal.openlayers.addBehavior('openlayers_behavior_keyboarddefaults', function (data, options) {
Drupal.openlayers.addControl(data.openlayers, 'KeyboardDefaults');
});

View File

@@ -0,0 +1,104 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_layerswitcher_openlayers_behaviors() {
return array(
'title' => t('Layer Switcher'),
'description' => t('Provides the ability to switch layers in the map interface. This provides an expandable box on the map to enable and disable layers.'),
'type' => 'map',
'behavior' => array(
'file' => 'openlayers_behavior_layerswitcher.inc',
'class' => 'openlayers_behavior_layerswitcher',
'parent' => 'openlayers_behavior',
),
);
}
/**
* Layer Switcher Behavior
*/
class openlayers_behavior_layerswitcher extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'layerswitcher' => '',
'ascending' => TRUE,
'sortBaseLayer' => '0',
'roundedCorner' => TRUE,
'roundedCornerColor' => '#222222',
'maximizeDefault' => FALSE,
);
}
function js_dependency() {
return array('OpenLayers.Control.LayerSwitcher');
}
function options_form($defaults = array()) {
return array(
'ascending' => array(
'#type' => 'checkbox',
'#title' => t('Show layers in ascending order'),
'#description' => t('Higher layers shown toward the bottom'),
'#default_value' => isset($defaults['ascending']) ? $defaults['ascending'] : TRUE,
),
'sortBaseLayer' => array(
'#type' => 'select',
'#title' => t('Sort Base Layers by Title'),
'#description' => t('Display the layers in the layer switcher by title'),
'#default_value' => isset($defaults['sortBaseLayer']) ? $defaults['sortBaseLayer'] : 0,
'#options' => array('0' => t('- None -'), 'ASC' => t('ASC'), 'DESC' => 'DESC'),
),
'roundedCorner' => array(
'#type' => 'checkbox',
'#title' => t('Rounded corners'),
'#description' => t('If true the Rico library is used for rounding the corners of the layer switcher box.'),
'#default_value' => isset($defaults['roundedCorner']) ? $defaults['roundedCorner'] : TRUE,
),
'roundedCornerColor' => array(
'#type' => 'textfield',
'#title' => t('Rounded corners color'),
'#description' => t('For rounded corners, this is the CSS color to use for the corners.'),
'#default_value' => isset($defaults['roundedCornerColor']) ? $defaults['roundedCornerColor'] : '#222222',
),
'maximizeDefault' => array(
'#type' => 'checkbox',
'#title' => t('Maximize by Default'),
'#description' => t('Turn on to have the Layer Switcher open by default.'),
'#default_value' => isset($defaults['maximizeDefault']) ? $defaults['maximizeDefault'] : FALSE,
),
);
}
/**
* Render.
*/
function render(&$map) {
// Legacy code for maps not using the default images now
// provided with the code, or for maps that dont have images
// set. We have to set the rounded corner color and add a
// class for CSS to style
if (empty($map['image_path'])) {
$this->options['roundedCornerColor'] = 'darkblue';
$this->options['displayClass'] = 'olControlLayerSwitcher legacy';
}
if ($this->options['sortBaseLayer'] == 'ASC' || $this->options['sortBaseLayer'] == 'DESC') {
uasort($map['layers'], 'drupal_sort_title');
if ($this->options['sortBaseLayer'] == 'ASC') {
$map['layers'] = array_reverse ($map['layers'], TRUE);
}
}
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_layerswitcher.js');
return $this->options;
}
}

View File

@@ -0,0 +1,17 @@
/**
* @file
* JS Implementation of OpenLayers behavior.
*/
/**
* Layer Switcher Behavior
*/
Drupal.openlayers.addBehavior('openlayers_behavior_layerswitcher', function (data, options) {
options.ascending = !! options.ascending;
Drupal.openlayers.addControl(data.openlayers, 'LayerSwitcher', options);
// Maximize if needed.
if (!! options.maximizeDefault == true) {
data.openlayers.getControlsByClass('OpenLayers.Control.LayerSwitcher')[0].maximizeControl();
}
});

View File

@@ -0,0 +1,67 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_layerzoom_openlayers_behaviors() {
return array(
'title' => t('Zoom restrictions for non-base layers.'),
'description' => t('Enables restriction of layer display based on zoom level.'),
'type' => 'layer',
'behavior' => array(
'file' => 'openlayers_behavior_layerzoom.inc',
'class' => 'openlayers_behavior_layerzoom',
'parent' => 'openlayers_behavior',
),
);
}
/**
* Attribution Behavior
*/
class openlayers_behavior_layerzoom extends openlayers_behavior {
function options_form($defaults = array()) {
$options = array();
foreach ($this->map['layers'] as $layer) {
if ($layer != $this->map['default_layer']) {
$options[$layer] = array(
'enable' => array(
'#type' => 'checkbox',
'#title' => t('Enable dynamic zoom levels for @layer', array('@layer' => $layer)),
'#default_value' => isset($this->options[$layer]['enable']) ? $this->options[$layer]['enable'] : 0,
),
'resolutions' => array(
'#type' => 'select',
'#multiple' => TRUE,
'#options' => array_combine(
array_map('strval', openlayers_get_resolutions('900913')),
range(0, 21)
),
'#title' => t('Zoom Level Range for @layer', array('@layer' => $layer)),
'#default_value' => isset($this->options[$layer]['resolutions']) ?
$this->options[$layer]['resolutions'] :
array_map('strval', openlayers_get_resolutions('900913')),
'#description' => t('The zoom levels at which this layer will display.'),
),
);
}
}
return $options;
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_layerzoom.js');
return $this->options;
}
}

View File

@@ -0,0 +1,25 @@
/**
* @file
* JS Implementation of OpenLayers behavior.
*/
/**
* OpenLayers Zoom to Layer Behavior
*/
Drupal.openlayers.addBehavior('openlayers_behavior_layerzoom', function (data, options) {
var map = data.openlayers;
for (var layerName in options) {
if (options[layerName].enable) {
var layers = map.getLayersBy('drupalID', layerName);
// Go through selected layers to get full extent.
for (var i in layers) {
layer = layers[i];
// Restrict zoom levels.
var keys = Object.keys(options[layerName].resolutions);
layer.alwaysInRange = false;
layer.minResolution = options[layerName].resolutions[keys[keys.length-1]];
layer.maxResolution = options[layerName].resolutions[keys[0]];
}
}
}
});

View File

@@ -0,0 +1,46 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_mapformvalues_openlayers_behaviors() {
return array(
'title' => t('Map Form Values'),
'description' => t('Provides a way of updating form elements with zoom level and centering from a map.'),
'type' => 'map',
'ui_visibility' => FALSE,
'behavior' => array(
'file' => 'openlayers_behavior_mapformvalues.inc',
'class' => 'openlayers_behavior_mapformvalues',
'parent' => 'openlayers_behavior',
),
);
}
/**
* Map Form Values Behavior
*/
class openlayers_behavior_mapformvalues extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'center_form' => '#edit-center-initial-centerpoint',
'zoom_form' => '#edit-center-initial-zoom'
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_mapformvalues.js');
return $this->options;
}
}

View File

@@ -0,0 +1,44 @@
/**
* @file
* JS Implementation of OpenLayers behavior.
*/
(function ($) {
/**
* Map Form Values Behavior
*/
Drupal.openlayers.addBehavior('openlayers_behavior_mapformvalues', function (data, options) {
function updateForm(evt) {
if (evt.object.centerpoint_form) {
center = evt.object.getCenter().transform(
evt.object.projection,
new OpenLayers.Projection('EPSG:4326')).toShortString();
evt.object.centerpoint_form.val(center);
}
if (evt.object.zoom_form) {
zoom = evt.object.getZoom();
evt.object.zoom_form.val(zoom);
}
}
centerpoint_form = $(options.center_form);
zoom_form = $(options.zoom_form);
if (centerpoint_form.length) {
data.openlayers.centerpoint_form = centerpoint_form;
center_point = centerpoint_form.val();
data.openlayers.setCenter(
OpenLayers.LonLat.fromString(center_point).transform(
new OpenLayers.Projection('EPSG:4326'),
data.openlayers.projection)
);
}
if (zoom_form.length) {
data.openlayers.zoom_form = zoom_form;
zoom = zoom_form.val();
data.openlayers.zoomTo(parseInt(zoom));
}
data.openlayers.events.on({'moveend': updateForm});
});
}(jQuery));

View File

@@ -0,0 +1,87 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_mouseposition_openlayers_behaviors() {
return array(
'title' => t('Mouse Position'),
'description' => t('Provides a visual indication of the mouse position to the user.'),
'type' => 'map',
'behavior' => array(
'file' => 'openlayers_behavior_mouseposition.inc',
'class' => 'openlayers_behavior_mouseposition',
'parent' => 'openlayers_behavior',
),
);
}
/**
* Mouse Position Behavior
*/
class openlayers_behavior_mouseposition extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'prefix' => '',
'separator' => ', ',
'suffix' => '',
'numDigits' => 4,
'emptyString' => '',
);
}
function js_dependency() {
return array('OpenLayers.Control.MousePosition');
}
function options_form($defaults = array()) {
return array(
'prefix' => array(
'#title' => t('Prefix'),
'#type' => 'textfield',
'#description' => t('A textual prefix to the mouse position.'),
'#default_value' => isset($defaults['prefix']) ? $defaults['prefix'] : '',
),
'separator' => array(
'#title' => t('Separator'),
'#type' => 'textfield',
'#description' => t('A textual separator between the first and second value.'),
'#default_value' => isset($defaults['separator']) ? $defaults['separator'] : ', ',
),
'suffix' => array(
'#title' => t('Suffix'),
'#type' => 'textfield',
'#description' => t('A textual suffix to the mouse position.'),
'#default_value' => isset($defaults['suffix']) ? $defaults['suffix'] : '',
),
'numDigits' => array(
'#title' => t('Number of Decimal Digits'),
'#type' => 'textfield',
'#description' => t('Number of decimal digits to show.'),
'#default_value' => isset($defaults['numDigits']) ? $defaults['numDigits'] : '',
),
'emptyString' => array(
'#title' => t('Empty Value'),
'#type' => 'textfield',
'#description' => t('What will be seen if there is no value for the mouse position.'),
'#default_value' => isset($defaults['emptyString']) ? $defaults['emptyString'] : '',
),
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_mouseposition.js');
return $this->options;
}
}

View File

@@ -0,0 +1,11 @@
/**
* @file
* JS Implementation of OpenLayers behavior.
*/
/**
* Mouse Position Behavior
*/
Drupal.openlayers.addBehavior('openlayers_behavior_mouseposition', function (data, options) {
Drupal.openlayers.addControl(data.openlayers, 'MousePosition', options);
});

View File

@@ -0,0 +1,75 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_navigation_openlayers_behaviors() {
return array(
'title' => t('Navigation'),
'description' => t('Provides the ability to navigate the map interface. This is just for user interactions and does not show any visual controls. This behavior automatically includes the Pan Zoom, Zoom Box, and Pinch Zoom controls.'),
'type' => 'map',
'behavior' => array(
'file' => 'openlayers_behavior_navigation.inc',
'class' => 'openlayers_behavior_navigation',
'parent' => 'openlayers_behavior',
),
);
}
/**
* Navigation Behavior
*/
class openlayers_behavior_navigation extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'navigation' => '',
'zoomWheelEnabled' => TRUE,
'zoomBoxEnabled' => TRUE,
'documentDrag' => FALSE,
);
}
function js_dependency() {
return array('OpenLayers.Control.Navigation');
}
function options_form($defaults = array()) {
return array(
'zoomWheelEnabled' => array(
'#type' => 'checkbox',
'#title' => t('Enable Zoom Wheel'),
'#description' => t('Enable zooming via the mouse scroll wheel. This can
interfere with page scrolling.'),
'#default_value' => isset($defaults['zoomWheelEnabled']) ? $defaults['zoomWheelEnabled'] : TRUE
),
'zoomBoxEnabled' => array(
'#type' => 'checkbox',
'#title' => t('Enable Zoom Box'),
'#description' => t('Enable zooming with selecting a box by <em>SHIFT + clicking</em>.'),
'#default_value' => isset($defaults['zoomBoxEnabled']) ? $defaults['zoomBoxEnabled'] : TRUE
),
'documentDrag' => array(
'#type' => 'checkbox',
'#title' => t('Document Drag'),
'#description' => t('Allow panning of the map by dragging outside map viewport.'),
'#default_value' => isset($defaults['documentDrag']) ? $defaults['documentDrag'] : FALSE
),
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_navigation.js');
return $this->options;
}
}

View File

@@ -0,0 +1,12 @@
/**
* @file
* JS Implementation of OpenLayers behavior.
*/
/**
* Navigation Behavior
*/
Drupal.openlayers.addBehavior('openlayers_behavior_navigation', function (data, options) {
options.documentDrag = !!options.documentDrag;
Drupal.openlayers.addControl(data.openlayers, 'Navigation', options);
});

View File

@@ -0,0 +1,49 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_panzoom_openlayers_behaviors() {
return array(
'title' => t('Pan and Zoom Control'),
'description' => t('Provides controls with the ability to pan and zoom in the map interface. Do not use with the Pan Zoom Bar Control or the Zoom Panel Control.'),
'type' => 'map',
'behavior' => array(
'file' => 'openlayers_behavior_panzoom.inc',
'class' => 'openlayers_behavior_panzoom',
'parent' => 'openlayers_behavior',
),
);
}
/**
* Pan Zoom Bar Behavior
*/
class openlayers_behavior_panzoom extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'panzoom' => '',
);
}
function options_form($defaults = array()) {
return array(
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_panzoom.js');
return $this->options;
}
}

View File

@@ -0,0 +1,11 @@
/**
* @file
* JS Implementation of OpenLayers behavior.
*/
/**
* Pan Zoom Bar Behavior
*/
Drupal.openlayers.addBehavior('openlayers_behavior_panzoom', function (data, options) {
Drupal.openlayers.addControl(data.openlayers, 'PanZoom');
});

View File

@@ -0,0 +1,66 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_panzoombar_openlayers_behaviors() {
return array(
'title' => t('Pan and Zoom Bar Controls'),
'description' => t('Gives user ability to pan and zoom, with a full zoom bar in the map interface. Do not use with Pan Zoom Contols or Zoom Panel Controls.'),
'type' => 'map',
'behavior' => array(
'file' => 'openlayers_behavior_panzoombar.inc',
'class' => 'openlayers_behavior_panzoombar',
'parent' => 'openlayers_behavior',
),
);
}
/**
* Pan Zoom Bar Behavior
*/
class openlayers_behavior_panzoombar extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'zoomWorldIcon' => FALSE,
'panIcons' => TRUE,
);
}
function js_dependency() {
return array('OpenLayers.Control.PanZoomBar');
}
function options_form($defaults = array()) {
return array(
'zoomWorldIcon' => array(
'#type' => 'checkbox',
'#title' => t('World Icon'),
'#description' => t('This puts the world icon in the pan controls. This button will zoom to the max extent when it is pressed.'),
'#default_value' => isset($defaults['zoomWorldIcon']) ? $defaults['zoomWorldIcon'] : FALSE
),
'panIcons' => array(
'#type' => 'checkbox',
'#title' => t('Pan Icons'),
'#description' => t('Enable the pan controls. Without it, then the user will only see a zoom bar.'),
'#default_value' => isset($defaults['panIcons']) ? $defaults['panIcons'] : TRUE
),
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_panzoombar.js');
return $this->options;
}
}

View File

@@ -0,0 +1,11 @@
/**
* @file
* JS Implementation of OpenLayers behavior.
*/
/**
* Pan Zoom Bar Behavior
*/
Drupal.openlayers.addBehavior('openlayers_behavior_panzoombar', function (data, options) {
Drupal.openlayers.addControl(data.openlayers, 'PanZoomBar', options);
});

View File

@@ -0,0 +1,59 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_permalink_openlayers_behaviors() {
return array(
'title' => t('Permalink'),
'description' => t('Provides a link that will create an URL that will link to a specific map position. Permalink is usually similar to: ?zoom=1&lat=11&lon=11&layers=B0F'),
'type' => 'map',
'behavior' => array(
'file' => 'openlayers_behavior_permalink.inc',
'class' => 'openlayers_behavior_permalink',
'parent' => 'openlayers_behavior',
),
);
}
/**
* PermaLink Behavior
*/
class openlayers_behavior_permalink extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'anchor' => FALSE,
);
}
function js_dependency() {
return array('OpenLayers.Control.Permalink');
}
function options_form($defaults = array()) {
return array(
'anchor' => array(
'#type' => 'checkbox',
'#title' => t('Anchor'),
'#description' => t('Permalink is in the form of an anchor (#) instead of a query (?). Also, this means that the URL location will be constantly updated, and no link will appear.'),
'#default_value' => (isset($defaults['anchor'])) ? $defaults['anchor'] : FALSE,
),
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_permalink.js');
return $this->options;
}
}

View File

@@ -0,0 +1,11 @@
/**
* @file
* JS Implementation of OpenLayers behavior.
*/
/**
* Permalink Behavior
*/
Drupal.openlayers.addBehavior('openlayers_behavior_permalink', function (data, options) {
Drupal.openlayers.addControl(data.openlayers, 'Permalink', options);
});

View File

@@ -0,0 +1,85 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_popup_openlayers_behaviors() {
return array(
'title' => t('Pop Up for Features'),
'description' => t('Adds clickable info boxes to points or shapes on maps. This does not work with the Tooltip behavior due to limitation of event handling in the OpenLayers library.'),
'type' => 'layer',
'behavior' => array(
'file' => 'openlayers_behavior_popup.inc',
'class' => 'openlayers_behavior_popup',
'parent' => 'openlayers_behavior',
),
);
}
/**
* Attribution Behavior
*/
class openlayers_behavior_popup extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'layers' => array(),
'panMapIfOutOfView' => FALSE,
'keepInMap' => TRUE,
);
}
/**
* 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(),
),
'panMapIfOutOfView' => array(
'#type' => 'checkbox',
'#title' => t('Pan map if popup out of view'),
'#description' => t('When drawn, pan map such that the entire popup is visible in the current viewport (if necessary).'),
'#default_value' => isset($defaults['panMapIfOutOfView']) ? $defaults['panMapIfOutOfView'] : FALSE
),
'keepInMap' => array(
'#type' => 'checkbox',
'#title' => t('Keep in map'),
'#description' => t('If panMapIfOutOfView is false, and this property is true, contrain the popup such that it always fits in the available map space.'),
'#default_value' => isset($defaults['keepInMap']) ? $defaults['keepInMap'] : TRUE
),
);
}
/**
* Render.
*/
function render(&$map) {
// Put weight on JS so that we know navigation is included already as this
// will affect touch devices.
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_popup.js', array('weight' => 10));
return $this->options;
}
}

View File

@@ -0,0 +1,95 @@
/**
* @file
* JS Implementation of OpenLayers behavior.
*/
/**
* Javascript Drupal Theming function for inside of Popups
*
* To override
*
* @param feature
* OpenLayers feature object.
* @return
* Formatted HTML.
*/
Drupal.theme.prototype.openlayersPopup = function(feature) {
var output = '';
if (feature.attributes.name) {
output += '<div class="openlayers-popup openlayers-tooltip-name">' + feature.attributes.name + '</div>';
}
if (feature.attributes.description) {
output += '<div class="openlayers-popup openlayers-tooltip-description">' + feature.attributes.description + '</div>';
}
return output;
};
// Make sure the namespace exists
Drupal.openlayers.popup = Drupal.openlayers.popup || {};
/**
* OpenLayers Popup Behavior
*/
Drupal.openlayers.addBehavior('openlayers_behavior_popup', function (data, options) {
var map = data.openlayers;
var layers = [];
var selectedFeature;
// 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]);
}
}
}
// if only 1 layer exists, do not add as an array. Kind of a
// hack, see https://drupal.org/node/1393460
if (layers.length == 1) {
layers = layers[0];
}
var popupSelect = new OpenLayers.Control.SelectFeature(layers,
{
onSelect: function(feature) {
// Create FramedCloud popup.
popup = new OpenLayers.Popup.FramedCloud(
'popup',
feature.geometry.getBounds().getCenterLonLat(),
null,
Drupal.theme('openlayersPopup', feature),
null,
true,
function(evt) {
Drupal.openlayers.popup.popupSelect.unselect(selectedFeature);
}
);
// Assign popup to feature and map.
popup.panMapIfOutOfView = options.panMapIfOutOfView;
popup.keepInMap = options.keepInMap;
selectedFeature = feature;
feature.popup = popup;
Drupal.attachBehaviors();
map.addPopup(popup);
},
onUnselect: function(feature) {
map.removePopup(feature.popup);
feature.popup.destroy();
feature.popup = null;
}
}
);
map.addControl(popupSelect);
popupSelect.activate();
Drupal.openlayers.popup.popupSelect = popupSelect;
});

View File

@@ -0,0 +1,52 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_scaleline_openlayers_behaviors() {
return array(
'title' => t('Scale Line'),
'description' => t('Provides a line of scale in the map interface.'),
'type' => 'map',
'behavior' => array(
'file' => 'openlayers_behavior_scaleline.inc',
'class' => 'openlayers_behavior_scaleline',
'parent' => 'openlayers_behavior',
),
);
}
/**
* Scaleline Behavior
*/
class openlayers_behavior_scaleline extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'scaleline' => '',
);
}
function js_dependency() {
return array('OpenLayers.Control.ScaleLine');
}
function options_form($defaults = array()) {
return array();
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_scaleline.js');
return $this->options;
}
}

View File

@@ -0,0 +1,11 @@
/**
* @file
* JS Implementation of OpenLayers behavior.
*/
/**
* Scale Line Behavior
*/
Drupal.openlayers.addBehavior('openlayers_behavior_scaleline', function (data, options) {
Drupal.openlayers.addControl(data.openlayers, 'ScaleLine');
});

View File

@@ -0,0 +1,70 @@
<?php
/**
* @file
* Implementation of OpenLayers behavior for tooltips.
*/
/**
* Ctools plugin definition.
*/
function openlayers_openlayers_behavior_tooltip_openlayers_behaviors() {
return array(
'title' => t('Tooltip for Features'),
'description' => t('Adds info boxes on hover to points or shapes on maps. This does not work with the Popup behavior due to limitation of event handling in the OpenLayers library.'),
'type' => 'layer',
'behavior' => array(
'file' => 'openlayers_behavior_tooltip.inc',
'class' => 'openlayers_behavior_tooltip',
'parent' => 'openlayers_behavior',
),
);
}
/**
* Attribution Behavior
*/
class openlayers_behavior_tooltip extends openlayers_behavior {
/**
* Provide initial values for options.
*/
function options_init() {
return array(
'attribution' => '',
'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 tooltips to.'),
'#default_value' => isset($defaults['layers']) ?
$defaults['layers'] : array(),
),
);
}
/**
* Render.
*/
function render(&$map) {
drupal_add_js(drupal_get_path('module', 'openlayers') .
'/plugins/behaviors/openlayers_behavior_tooltip.js');
return $this->options;
}
}

Some files were not shown because too many files have changed in this diff Show More