Moving the WMS previewer. You can enable it loading the wms_preview plugin in the ini file
|
@ -0,0 +1,7 @@
|
|||
try:
|
||||
import pkg_resources
|
||||
pkg_resources.declare_namespace(__name__)
|
||||
except ImportError:
|
||||
import pkgutil
|
||||
__path__ = pkgutil.extend_path(__path__, __name__)
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
import urllib2
|
||||
|
||||
from pylons.i18n import _
|
||||
|
||||
import ckan.lib.helpers as h, json
|
||||
from ckan.lib.base import BaseController, c, g, request, \
|
||||
response, session, render, config, abort, redirect
|
||||
|
||||
from ckan.model import Package
|
||||
|
||||
class ViewController(BaseController):
|
||||
|
||||
def __before__(self, action, **env):
|
||||
super(ViewController, self).__before__(action, **env)
|
||||
# All calls to this controller must be with a sysadmin key
|
||||
if not self.authorizer.is_sysadmin(c.user):
|
||||
response_msg = _('Not authorized to see this page')
|
||||
status = 401
|
||||
abort(status, response_msg)
|
||||
|
||||
def wms_preview(self,id):
|
||||
#check if package exists
|
||||
c.pkg = Package.get(id)
|
||||
if c.pkg is None:
|
||||
abort(404, 'Package not found')
|
||||
|
||||
for res in c.pkg.resources:
|
||||
if res.format == "WMS":
|
||||
c.wms = res
|
||||
break
|
||||
if not c.wms:
|
||||
abort(400, 'This package does not have a WMS')
|
||||
|
||||
return render('ckanext/spatial/wms_preview.html')
|
||||
|
||||
def proxy(self):
|
||||
if not 'url' in request.params:
|
||||
abort(400)
|
||||
try:
|
||||
server_response = urllib2.urlopen(request.params['url'])
|
||||
headers = server_response.info()
|
||||
if headers.get('Content-Type'):
|
||||
response.content_type = headers.get('Content-Type')
|
||||
return server_response.read()
|
||||
except urllib2.HTTPError as e:
|
||||
response.status_int = e.getcode()
|
||||
return
|
|
@ -0,0 +1,5 @@
|
|||
MAP_VIEW="""
|
||||
<div class="mapview">
|
||||
<a href="/package/%(name)s/map">View available WMS layers »</a>
|
||||
</div>
|
||||
"""
|
|
@ -0,0 +1,72 @@
|
|||
import os
|
||||
from logging import getLogger
|
||||
|
||||
from genshi.input import HTML
|
||||
from genshi.filters import Transformer
|
||||
|
||||
import ckan.lib.helpers as h
|
||||
|
||||
from ckan.plugins import implements, SingletonPlugin
|
||||
from ckan.plugins import IRoutes, IConfigurer
|
||||
from ckan.plugins import IConfigurable, IGenshiStreamFilter
|
||||
|
||||
import html
|
||||
|
||||
log = getLogger(__name__)
|
||||
|
||||
class WMSPreview(SingletonPlugin):
|
||||
|
||||
implements(IGenshiStreamFilter)
|
||||
implements(IRoutes, inherit=True)
|
||||
implements(IConfigurer, inherit=True)
|
||||
|
||||
def filter(self, stream):
|
||||
from pylons import request, tmpl_context as c
|
||||
routes = request.environ.get('pylons.routes_dict')
|
||||
|
||||
if routes.get('controller') == 'package' and \
|
||||
routes.get('action') == 'read' and c.pkg.id:
|
||||
|
||||
is_inspire = (c.pkg.extras.get('INSPIRE') == 'True')
|
||||
# TODO: What about WFS, WCS...
|
||||
is_wms = (c.pkg.extras.get('resource-type') == 'service')
|
||||
if is_inspire and is_wms:
|
||||
data = {'name': c.pkg.name}
|
||||
stream = stream | Transformer('body//div[@class="resources subsection"]')\
|
||||
.append(HTML(html.MAP_VIEW % data))
|
||||
|
||||
|
||||
return stream
|
||||
|
||||
def before_map(self, map):
|
||||
|
||||
map.connect('map_view', '/package/:id/map',
|
||||
controller='ckanext.spatial.controllers.view:ViewController',
|
||||
action='wms_preview')
|
||||
|
||||
map.connect('proxy', '/proxy',
|
||||
controller='ckanext.spatial.controllers.view:ViewController',
|
||||
action='proxy')
|
||||
|
||||
map.connect('api_spatial_query', '/api/2/search/package/geo',
|
||||
controller='ckanext.spatial.controllers.api:ApiController',
|
||||
action='spatial_query')
|
||||
|
||||
return map
|
||||
|
||||
def update_config(self, config):
|
||||
here = os.path.dirname(__file__)
|
||||
rootdir = os.path.dirname(os.path.dirname(here))
|
||||
|
||||
template_dir = os.path.join(rootdir, 'templates')
|
||||
public_dir = os.path.join(rootdir, 'public')
|
||||
|
||||
if config.get('extra_template_paths'):
|
||||
config['extra_template_paths'] += ','+template_dir
|
||||
else:
|
||||
config['extra_template_paths'] = template_dir
|
||||
if config.get('extra_public_paths'):
|
||||
config['extra_public_paths'] += ','+public_dir
|
||||
else:
|
||||
config['extra_public_paths'] = public_dir
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
This is a custom build of the OpenLayers Javascript mapping library,
|
||||
slimmed down to only the features we need.
|
||||
|
||||
The file ckan.cfg contains the build profile used to build OpenLayers.
|
||||
In order to add more functionality, new classes must be added in the
|
||||
build profile, and then run the build command from the OpenLayers
|
||||
distribution:
|
||||
|
||||
1. svn co http://svn.openlayers.org/trunk/openlayers
|
||||
|
||||
2. Modify ckan.cfg
|
||||
|
||||
3. Go to build/ and execute::
|
||||
|
||||
python build.py {path-to-ckan.cfg} {output-file}
|
||||
|
||||
The theme used for the OpenLayers controls is the "dark" theme made available
|
||||
by Development Seed under the BSD License:
|
||||
|
||||
https://github.com/developmentseed/openlayers_themes/blob/master/LICENSE.txt
|
|
@ -0,0 +1,40 @@
|
|||
[first]
|
||||
OpenLayers/SingleFile.js
|
||||
OpenLayers.js
|
||||
OpenLayers/BaseTypes.js
|
||||
OpenLayers/BaseTypes/Class.js
|
||||
OpenLayers/Util.js
|
||||
Rico/Corner.js
|
||||
|
||||
[last]
|
||||
|
||||
[include]
|
||||
OpenLayers/Console.js
|
||||
OpenLayers/Ajax.js
|
||||
OpenLayers/Events.js
|
||||
OpenLayers/Map.js
|
||||
OpenLayers/Layer.js
|
||||
OpenLayers/Layer/Grid.js
|
||||
OpenLayers/Layer/HTTPRequest.js
|
||||
OpenLayers/Layer/WMS.js
|
||||
OpenLayers/Layer/WMS/Untiled.js
|
||||
OpenLayers/Tile.js
|
||||
OpenLayers/Tile/Image.js
|
||||
OpenLayers/Control/Navigation.js
|
||||
OpenLayers/Control/PanZoom.js
|
||||
OpenLayers/Control/PanZoomBar.js
|
||||
OpenLayers/Control/Scale.js
|
||||
OpenLayers/Control/MousePosition.js
|
||||
OpenLayers/Control/LayerSwitcher.js
|
||||
OpenLayers/Format/XML.js
|
||||
OpenLayers/Format/WMSCapabilities/v1_1_1.js
|
||||
OpenLayers/Format/WMSCapabilities/v1_1_1_WMSC.js
|
||||
OpenLayers/Format/WMSCapabilities/v1_3_0.js
|
||||
|
||||
[exclude]
|
||||
Firebug/firebug.js
|
||||
Firebug/firebugx.js
|
||||
OpenLayers/Lang/de.js
|
||||
OpenLayers/Lang/en-CA.js
|
||||
OpenLayers/Lang/fr.js
|
||||
OpenLayers/Lang/cs-CZ.js
|
After Width: | Height: | Size: 43 B |
After Width: | Height: | Size: 298 B |
After Width: | Height: | Size: 303 B |
After Width: | Height: | Size: 367 B |
After Width: | Height: | Size: 298 B |
After Width: | Height: | Size: 327 B |
After Width: | Height: | Size: 236 B |
After Width: | Height: | Size: 310 B |
After Width: | Height: | Size: 299 B |
After Width: | Height: | Size: 229 B |
After Width: | Height: | Size: 276 B |
After Width: | Height: | Size: 545 B |
After Width: | Height: | Size: 232 B |
|
@ -0,0 +1,17 @@
|
|||
.olLayerGoogleCopyright {
|
||||
right: 3px;
|
||||
bottom: 2px;
|
||||
left: auto;
|
||||
}
|
||||
.olLayerGoogleV3.olLayerGoogleCopyright {
|
||||
bottom: 0px;
|
||||
right: 0px !important;
|
||||
}
|
||||
.olLayerGooglePoweredBy {
|
||||
left: 2px;
|
||||
bottom: 2px;
|
||||
}
|
||||
.olLayerGoogleV3.olLayerGooglePoweredBy {
|
||||
bottom: 0px !important;
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
.olControlZoomPanel div {
|
||||
background-image: url(img/zoom-panel-NOALPHA.png);
|
||||
}
|
||||
.olControlPanPanel div {
|
||||
background-image: url(img/pan-panel-NOALPHA.png);
|
||||
}
|
||||
|
|
@ -0,0 +1,423 @@
|
|||
div.olMap {
|
||||
z-index: 0;
|
||||
padding: 0px!important;
|
||||
margin: 0px!important;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
div.olMapViewport {
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
div.olLayerDiv {
|
||||
-moz-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
}
|
||||
|
||||
.olLayerGoogleCopyright {
|
||||
left: 2px;
|
||||
bottom: 2px;
|
||||
}
|
||||
.olLayerGoogleV3.olLayerGoogleCopyright {
|
||||
right: auto !important;
|
||||
}
|
||||
.olLayerGooglePoweredBy {
|
||||
left: 2px;
|
||||
bottom: 15px;
|
||||
}
|
||||
.olLayerGoogleV3.olLayerGooglePoweredBy {
|
||||
bottom: 15px !important;
|
||||
}
|
||||
.olControlAttribution {
|
||||
font-size: smaller;
|
||||
right: 3px;
|
||||
bottom: 4.5em;
|
||||
position: absolute;
|
||||
display: block;
|
||||
}
|
||||
.olControlScale {
|
||||
right: 3px;
|
||||
bottom: 3em;
|
||||
display: block;
|
||||
position: absolute;
|
||||
font-size: smaller;
|
||||
}
|
||||
.olControlScaleLine {
|
||||
display: block;
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
bottom: 15px;
|
||||
font-size: xx-small;
|
||||
}
|
||||
.olControlScaleLineBottom {
|
||||
border: solid 2px black;
|
||||
border-bottom: none;
|
||||
margin-top:-2px;
|
||||
text-align: center;
|
||||
}
|
||||
.olControlScaleLineTop {
|
||||
border: solid 2px black;
|
||||
border-top: none;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.olControlPermalink {
|
||||
right: 3px;
|
||||
bottom: 1.5em;
|
||||
display: block;
|
||||
position: absolute;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
div.olControlMousePosition {
|
||||
bottom: 0em;
|
||||
right: 3px;
|
||||
display: block;
|
||||
position: absolute;
|
||||
font-family: Arial;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.olControlOverviewMapContainer {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
}
|
||||
|
||||
.olControlOverviewMapElement {
|
||||
padding: 10px 18px 10px 10px;
|
||||
background-color: #00008B;
|
||||
-moz-border-radius: 1em 0 0 0;
|
||||
}
|
||||
|
||||
.olControlOverviewMapMinimizeButton {
|
||||
right: 0px;
|
||||
bottom: 80px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.olControlOverviewMapMaximizeButton {
|
||||
right: 0px;
|
||||
bottom: 80px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.olControlOverviewMapExtentRectangle {
|
||||
overflow: hidden;
|
||||
background-image: url("img/blank.gif");
|
||||
cursor: move;
|
||||
border: 2px dotted red;
|
||||
}
|
||||
.olControlOverviewMapRectReplacement {
|
||||
overflow: hidden;
|
||||
cursor: move;
|
||||
background-image: url("img/overview_replacement.gif");
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.olLayerGeoRSSDescription {
|
||||
float:left;
|
||||
width:100%;
|
||||
overflow:auto;
|
||||
font-size:1.0em;
|
||||
}
|
||||
.olLayerGeoRSSClose {
|
||||
float:right;
|
||||
color:gray;
|
||||
font-size:1.2em;
|
||||
margin-right:6px;
|
||||
font-family:sans-serif;
|
||||
}
|
||||
.olLayerGeoRSSTitle {
|
||||
float:left;font-size:1.2em;
|
||||
}
|
||||
|
||||
.olPopupContent {
|
||||
padding:5px;
|
||||
overflow: auto;
|
||||
}
|
||||
.olControlNavToolbar {
|
||||
width:0px;
|
||||
height:0px;
|
||||
}
|
||||
.olControlNavToolbar div {
|
||||
display:block;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
top: 300px;
|
||||
left: 6px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.olControlNavigationHistory {
|
||||
background-image: url("img/navigation_history.png");
|
||||
background-repeat: no-repeat;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
|
||||
}
|
||||
.olControlNavigationHistoryPreviousItemActive {
|
||||
background-position: 0px 0px;
|
||||
}
|
||||
.olControlNavigationHistoryPreviousItemInactive {
|
||||
background-position: 0px -24px;
|
||||
}
|
||||
.olControlNavigationHistoryNextItemActive {
|
||||
background-position: -24px 0px;
|
||||
}
|
||||
.olControlNavigationHistoryNextItemInactive {
|
||||
background-position: -24px -24px;
|
||||
}
|
||||
|
||||
.olControlNavToolbar .olControlNavigationItemActive {
|
||||
background-image: url("img/panning-hand-on.png");
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.olControlNavToolbar .olControlNavigationItemInactive {
|
||||
background-image: url("img/panning-hand-off.png");
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.olControlNavToolbar .olControlZoomBoxItemActive {
|
||||
background-image: url("img/drag-rectangle-on.png");
|
||||
background-color: orange;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.olControlNavToolbar .olControlZoomBoxItemInactive {
|
||||
background-image: url("img/drag-rectangle-off.png");
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
.olControlEditingToolbar {
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
height: 30px;
|
||||
width: 200px;
|
||||
}
|
||||
.olControlEditingToolbar div {
|
||||
background-image: url("img/editing_tool_bar.png");
|
||||
background-repeat: no-repeat;
|
||||
float:right;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin: 5px;
|
||||
}
|
||||
.olControlEditingToolbar .olControlNavigationItemActive {
|
||||
background-position: -103px -23px;
|
||||
}
|
||||
.olControlEditingToolbar .olControlNavigationItemInactive {
|
||||
background-position: -103px -0px;
|
||||
}
|
||||
.olControlEditingToolbar .olControlDrawFeaturePointItemActive {
|
||||
background-position: -77px -23px;
|
||||
}
|
||||
.olControlEditingToolbar .olControlDrawFeaturePointItemInactive {
|
||||
background-position: -77px -0px;
|
||||
}
|
||||
.olControlEditingToolbar .olControlDrawFeaturePathItemInactive {
|
||||
background-position: -51px 0px;
|
||||
}
|
||||
.olControlEditingToolbar .olControlDrawFeaturePathItemActive {
|
||||
background-position: -51px -23px;
|
||||
}
|
||||
.olControlEditingToolbar .olControlDrawFeaturePolygonItemInactive {
|
||||
background-position: -26px 0px;
|
||||
}
|
||||
.olControlEditingToolbar .olControlDrawFeaturePolygonItemActive {
|
||||
background-position: -26px -23px ;
|
||||
}
|
||||
div.olControlSaveFeaturesItemActive {
|
||||
background-image: url(img/save_features_on.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0px 1px;
|
||||
}
|
||||
div.olControlSaveFeaturesItemInactive {
|
||||
background-image: url(img/save_features_off.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0px 1px;
|
||||
}
|
||||
|
||||
.olHandlerBoxZoomBox {
|
||||
border: 2px solid red;
|
||||
position: absolute;
|
||||
background-color: white;
|
||||
opacity: 0.50;
|
||||
font-size: 1px;
|
||||
filter: alpha(opacity=50);
|
||||
}
|
||||
.olHandlerBoxSelectFeature {
|
||||
border: 2px solid blue;
|
||||
position: absolute;
|
||||
background-color: white;
|
||||
opacity: 0.50;
|
||||
font-size: 1px;
|
||||
filter: alpha(opacity=50);
|
||||
}
|
||||
|
||||
.olControlPanPanel {
|
||||
top: 10px;
|
||||
left: 5px;
|
||||
}
|
||||
|
||||
.olControlPanPanel div {
|
||||
background-image: url(img/pan-panel.png);
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.olControlPanPanel .olControlPanNorthItemInactive {
|
||||
top: 0px;
|
||||
left: 9px;
|
||||
background-position: 0px 0px;
|
||||
}
|
||||
.olControlPanPanel .olControlPanSouthItemInactive {
|
||||
top: 36px;
|
||||
left: 9px;
|
||||
background-position: 18px 0px;
|
||||
}
|
||||
.olControlPanPanel .olControlPanWestItemInactive {
|
||||
position: absolute;
|
||||
top: 18px;
|
||||
left: 0px;
|
||||
background-position: 0px 18px;
|
||||
}
|
||||
.olControlPanPanel .olControlPanEastItemInactive {
|
||||
top: 18px;
|
||||
left: 18px;
|
||||
background-position: 18px 18px;
|
||||
}
|
||||
|
||||
.olControlZoomPanel {
|
||||
top: 71px;
|
||||
left: 14px;
|
||||
}
|
||||
|
||||
.olControlZoomPanel div {
|
||||
background-image: url(img/zoom-panel.png);
|
||||
position: absolute;
|
||||
height: 18px;
|
||||
width: 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.olControlZoomPanel .olControlZoomInItemInactive {
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
background-position: 0px 0px;
|
||||
}
|
||||
|
||||
.olControlZoomPanel .olControlZoomToMaxExtentItemInactive {
|
||||
top: 18px;
|
||||
left: 0px;
|
||||
background-position: 0px -18px;
|
||||
}
|
||||
|
||||
.olControlZoomPanel .olControlZoomOutItemInactive {
|
||||
top: 36px;
|
||||
left: 0px;
|
||||
background-position: 0px 18px;
|
||||
}
|
||||
|
||||
/*
|
||||
* When a potential text is bigger than the image it move the image
|
||||
* with some headers (closes #3154)
|
||||
*/
|
||||
.olControlPanZoomBar div {
|
||||
font-size: 1px;
|
||||
}
|
||||
|
||||
.olPopupCloseBox {
|
||||
background: url("img/close.gif") no-repeat;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.olFramedCloudPopupContent {
|
||||
padding: 5px;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.olControlNoSelect {
|
||||
-moz-user-select: none;
|
||||
-khtml-user-select: none;
|
||||
}
|
||||
|
||||
.olImageLoadError {
|
||||
background-color: pink;
|
||||
opacity: 0.5;
|
||||
filter: alpha(opacity=50); /* IE */
|
||||
}
|
||||
|
||||
/**
|
||||
* Cursor styles
|
||||
*/
|
||||
|
||||
.olCursorWait {
|
||||
cursor: wait;
|
||||
}
|
||||
.olDragDown {
|
||||
cursor: move;
|
||||
}
|
||||
.olDrawBox {
|
||||
cursor: crosshair;
|
||||
}
|
||||
.olControlDragFeatureOver {
|
||||
cursor: move;
|
||||
}
|
||||
.olControlDragFeatureActive.olControlDragFeatureOver.olDragDown {
|
||||
cursor: -moz-grabbing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Layer switcher
|
||||
*/
|
||||
.olControlLayerSwitcher {
|
||||
position: absolute;
|
||||
top: 25px;
|
||||
right: 0px;
|
||||
width: 20em;
|
||||
font-family: sans-serif;
|
||||
font-weight: bold;
|
||||
margin-top: 3px;
|
||||
margin-left: 3px;
|
||||
margin-bottom: 3px;
|
||||
font-size: smaller;
|
||||
color: white;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.olControlLayerSwitcher .layersDiv {
|
||||
padding-top: 5px;
|
||||
padding-left: 10px;
|
||||
padding-bottom: 5px;
|
||||
padding-right: 75px;
|
||||
background-color: darkblue;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.olControlLayerSwitcher .layersDiv .baseLbl,
|
||||
.olControlLayerSwitcher .layersDiv .dataLbl {
|
||||
margin-top: 3px;
|
||||
margin-left: 3px;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.olControlLayerSwitcher .layersDiv .baseLayersDiv,
|
||||
.olControlLayerSwitcher .layersDiv .dataLayersDiv {
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.olControlLayerSwitcher .maximizeDiv,
|
||||
.olControlLayerSwitcher .minimizeDiv {
|
||||
top: 5px;
|
||||
right: 0px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.olBingAttribution {
|
||||
color: #DDD;
|
||||
}
|
||||
.olBingAttribution.road {
|
||||
color: #333;
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
var CKAN = CKAN || {};
|
||||
|
||||
CKAN.WMSPreview = function($){
|
||||
|
||||
// Private
|
||||
var defaultVersion = "1.3.0";
|
||||
|
||||
var preferredFormat = "image/png";
|
||||
|
||||
var proxy = "/proxy?url=";
|
||||
|
||||
var getURL = function(server,version){
|
||||
if (server.indexOf("?") === -1)
|
||||
server += "?"
|
||||
|
||||
var url = server +
|
||||
"SERVICE=WMS" +
|
||||
"&REQUEST=GetCapabilities" +
|
||||
"&VERSION=" + defaultVersion
|
||||
return (proxy) ? proxy + escape(url) : url;
|
||||
}
|
||||
|
||||
var getFormat = function(formats){
|
||||
for(var i = 0; i < formats.length; i++){
|
||||
if (formats[i] == preferredFormat){
|
||||
return formats[i];
|
||||
}
|
||||
}
|
||||
return formats[0];
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Public
|
||||
return {
|
||||
map: null,
|
||||
setup: function(server){
|
||||
|
||||
var url = getURL(server);
|
||||
|
||||
var self = this;
|
||||
$.get(url,function(data){
|
||||
// Most WMS Servers will return the version they prefer,
|
||||
// regardless of which one you requested, so better check
|
||||
// for the actual version returned.
|
||||
var version = $(data).find("WMS_Capabilities").attr("version"); // 1.3.0
|
||||
if (!version)
|
||||
version = $(data).find("WMS_MS_Capabilities").attr("version"); // 1.1.1
|
||||
|
||||
var format = new OpenLayers.Format.WMSCapabilities({"version":version});
|
||||
|
||||
var capabilities = format.read(data);
|
||||
if (capabilities.capability){
|
||||
var layers = capabilities.capability.layers;
|
||||
|
||||
var olLayers = [];
|
||||
var maxExtent = false;
|
||||
var maxScale = false;
|
||||
var minScale = false;
|
||||
for (var count = 0; count < layers.length; count++){
|
||||
layer = layers[count];
|
||||
|
||||
// Extend the maps's maxExtent to include this layer extent
|
||||
layerMaxExtent = new OpenLayers.Bounds(layer.llbbox[0],layer.llbbox[1],layer.llbbox[2],layer.llbbox[3]);
|
||||
if (!maxExtent){
|
||||
maxExtent = layerMaxExtent;
|
||||
} else {
|
||||
maxExtent.extend(layerMaxExtent);
|
||||
}
|
||||
if (layer.maxScale && (layer.maxScale > maxScale || maxScale === false)) maxScale = layer.maxScale;
|
||||
if (layer.minScale && (layer.minScale < minScale || minScale === false)) minScale = layer.minScale;
|
||||
olLayers.push(new OpenLayers.Layer.WMS(
|
||||
layer.title,
|
||||
server,
|
||||
{"layers": layer.name,
|
||||
"format": getFormat(layer.formats),
|
||||
"transparent":true
|
||||
},
|
||||
{"buffer":0,
|
||||
"maxExtent": layerMaxExtent,
|
||||
"maxScale": (layer.maxScale) ? layer.maxScale : null,
|
||||
"minScale": (layer.minScale) ? layer.minScale : null,
|
||||
"isBaseLayer": false,
|
||||
"visibility": (count == 0)
|
||||
}) //Tiled?
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
var dummyLayer = new OpenLayers.Layer("Dummy",{
|
||||
"maxExtent": maxExtent,
|
||||
"displayInLayerSwitcher":false,
|
||||
"isBaseLayer":true,
|
||||
"visibility":false,
|
||||
"minScale": (minScale) ? minScale : null,
|
||||
"maxScale": (maxScale) ? maxScale : null
|
||||
});
|
||||
olLayers.push(dummyLayer);
|
||||
|
||||
// Setup some sizes
|
||||
var w = $("#container").width() * 0.50;
|
||||
if (w > 1024) w = 1024;
|
||||
$("#content").width($("#container").width());
|
||||
$("#map").width(w);
|
||||
$("#map").height(500);
|
||||
|
||||
// Create a new map
|
||||
self.map = new OpenLayers.Map("map" ,
|
||||
{
|
||||
"projection": new OpenLayers.Projection("EPSG:4326"),
|
||||
"maxResolution":"auto",
|
||||
"controls":[
|
||||
new OpenLayers.Control.PanZoomBar(),
|
||||
new OpenLayers.Control.Navigation(),
|
||||
new OpenLayers.Control.CustomMousePosition({
|
||||
"displayClass":"olControlMousePosition",
|
||||
"numDigits":4
|
||||
}),
|
||||
new OpenLayers.Control.LayerSwitcher({
|
||||
"div": document.getElementById("layers"),
|
||||
"roundedCorner":false
|
||||
})
|
||||
],
|
||||
"theme":"/ckanext/spatial/js/openlayers/theme/default/style.css"
|
||||
});
|
||||
|
||||
self.map.maxExtent = maxExtent;
|
||||
self.map.addLayers(olLayers);
|
||||
|
||||
self.map.zoomTo(1);
|
||||
} else {
|
||||
$("#main").prepend(
|
||||
$("<div></div>").attr("class","flash-banner-box").append(
|
||||
$("<div></div>").attr("class","flash-banner error").html(
|
||||
"Error parsing the WMS capabilities document"
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}(jQuery)
|
||||
|
||||
|
||||
OpenLayers.ImgPath = "/ckanext/spatial/js/openlayers/img/";
|
||||
OpenLayers.Lang.en.overlays = "Available Layers:";
|
||||
|
||||
OpenLayers.Control.CustomMousePosition = OpenLayers.Class(OpenLayers.Control.MousePosition,{
|
||||
formatOutput: function(lonLat) {
|
||||
var newHtml = OpenLayers.Control.MousePosition.prototype.formatOutput.apply(this, [lonLat]);
|
||||
newHtml = "1:" + parseInt(this.map.getScale()) + " | WGS84 " + newHtml;
|
||||
return newHtml;
|
||||
},
|
||||
|
||||
CLASS_NAME: "OpenLayers.Control.CustomMousePosition"
|
||||
})
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
#map{
|
||||
float: left;
|
||||
display: inline;
|
||||
}
|
||||
#layers{
|
||||
float: left;
|
||||
display: inline;
|
||||
margin-left: 20px;
|
||||
}
|
||||
|
||||
/* OpenLayers */
|
||||
.dataLbl{
|
||||
font-weight: bold;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.dataLayersDiv input{
|
||||
margin: 0 10px 10px 0;
|
||||
}
|
||||
|
||||
.dataLayersDiv span{
|
||||
margin: 0;
|
||||
}
|
2
setup.py
|
@ -26,6 +26,6 @@ setup(
|
|||
"""
|
||||
[ckan.plugins]
|
||||
# Add plugins here, eg
|
||||
# myplugin=ckanext.spatial:PluginClass
|
||||
wms_preview=ckanext.spatial.plugin:WMSPreview
|
||||
""",
|
||||
)
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
<html xmlns:py="http://genshi.edgewall.org/"
|
||||
xmlns:i18n="http://genshi.edgewall.org/i18n"
|
||||
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||
py:strip="">
|
||||
|
||||
<py:def function="page_title">${c.pkg.title or c.pkg.name} - WMS preview</py:def>
|
||||
|
||||
<py:def function="optional_head">
|
||||
<link type="text/css" rel="stylesheet" media="all" href="/ckanext/spatial/wms_preview.css" />
|
||||
<script type="text/javascript" src="/ckanext/spatial/js/openlayers/OpenLayers_ckan.js"></script>
|
||||
<script type="text/javascript" src="/ckanext/spatial/js/wms_preview.js"></script>
|
||||
</py:def>
|
||||
|
||||
<div py:match="content">
|
||||
<div class="map-view-content">
|
||||
<h2 class="head">
|
||||
${c.pkg.title}
|
||||
</h2>
|
||||
|
||||
<!-- Source URL -->
|
||||
<div class="url" py:if="c.pkg.url">
|
||||
<p>
|
||||
Source: <a href="${c.wms.url}" target="_blank">${c.wms.url}</a>
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
<a
|
||||
href="${url(controller='package', action='read', id=c.pkg.name)}"
|
||||
title="Package Details">
|
||||
Package details</a>
|
||||
</p>
|
||||
<div class="package subsection">
|
||||
<h3>WMS preview</h3>
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
$(document).ready(function(){
|
||||
CKAN.WMSPreview.setup("${c.wms.url}");
|
||||
})
|
||||
//]]>
|
||||
</script>
|
||||
<div id="map"></div>
|
||||
<div id="layers"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<xi:include href="../../layout.html" />
|
||||
</html>
|