| 1 | {{py: |
|---|
| 2 | import simplejson |
|---|
| 3 | |
|---|
| 4 | def jsondumps(value): return simplejson.dumps(value) |
|---|
| 5 | |
|---|
| 6 | dict = None |
|---|
| 7 | if json is not None: |
|---|
| 8 | dict = simplejson.loads(json) |
|---|
| 9 | if not dict.has_key('data'): |
|---|
| 10 | dict['data'] = {} |
|---|
| 11 | if not dict['data'].has_key('datasources'): |
|---|
| 12 | dict['data']['datasources'] = {} |
|---|
| 13 | |
|---|
| 14 | if not dict.has_key('header'): |
|---|
| 15 | dict['header'] = {'height':100, 'content':'Dummy content'} |
|---|
| 16 | |
|---|
| 17 | controller_base_url = '' |
|---|
| 18 | |
|---|
| 19 | def isEnabled(what): |
|---|
| 20 | for datasource in dict['data']['datasources'].keys(): |
|---|
| 21 | if dict['data']['datasources'][datasource].has_key(what): return True |
|---|
| 22 | return False |
|---|
| 23 | }} |
|---|
| 24 | {{if dict is not None}} |
|---|
| 25 | /** |
|---|
| 26 | * This is a generated mapfish application from MapFish Studio. |
|---|
| 27 | * Changes made to this file will not be taken into account |
|---|
| 28 | * in your studio project. |
|---|
| 29 | */ |
|---|
| 30 | |
|---|
| 31 | app = {}; |
|---|
| 32 | |
|---|
| 33 | app.create = function() { |
|---|
| 34 | this.map = app.createMap(); |
|---|
| 35 | {{if isEnabled('tooltip')}} |
|---|
| 36 | app.tooltip = this.createTooltip(this.map) |
|---|
| 37 | {{endif}} |
|---|
| 38 | this.toolbar = app.createToolbar(this.map); |
|---|
| 39 | this.createLayout(this.map, this.toolbar); |
|---|
| 40 | this.toolbar.initializeDefaults(); |
|---|
| 41 | }; |
|---|
| 42 | |
|---|
| 43 | app.createMap = function() { |
|---|
| 44 | OpenLayers.DOTS_PER_INCH = {{dict['map']['dpi']}}; |
|---|
| 45 | var map = new OpenLayers.Map('map', { |
|---|
| 46 | projection: {{jsondumps(dict['map']['projection'])}}, |
|---|
| 47 | scales: {{jsondumps(dict['map']['scales'])}}, |
|---|
| 48 | units: {{jsondumps(dict['map']['units'])}}, |
|---|
| 49 | maxExtent: new OpenLayers.Bounds.fromArray({{jsondumps(dict['map']['maxExtent'])}}) |
|---|
| 50 | }); |
|---|
| 51 | // TODO: IE hack for png layers: OpenLayers.Util.alphaHack()?'image/gif':'image/png' |
|---|
| 52 | {{for layer in dict['layers']}} |
|---|
| 53 | map.addLayer(new OpenLayers.Layer.{{layer['type']}}( |
|---|
| 54 | {{jsondumps(layer['name'])}}, |
|---|
| 55 | {{jsondumps(layer['url'])}}, |
|---|
| 56 | {{jsondumps(layer['params'])}}, { |
|---|
| 57 | isBaseLayer: {{jsondumps(layer['options']['isBaseLayer'])}}, |
|---|
| 58 | singleTile: true, |
|---|
| 59 | ratio: 1.0, |
|---|
| 60 | buffer: 0, |
|---|
| 61 | {{if layer['options']['maxExtent'] is not None}} |
|---|
| 62 | //TODO: must be converted from WGS84 to the actual coordinate system |
|---|
| 63 | //maxExtent: new OpenLayers.Bounds.fromArray({{jsondumps(layer['options']['maxExtent'])}}) |
|---|
| 64 | {{endif}} |
|---|
| 65 | } |
|---|
| 66 | //TODO: manage maxExtent options issue (has to be a new OL.Bounds())</%doc> |
|---|
| 67 | )); |
|---|
| 68 | {{endfor}} |
|---|
| 69 | map.zoomToMaxExtent(); |
|---|
| 70 | return map; |
|---|
| 71 | }; |
|---|
| 72 | |
|---|
| 73 | app.createTooltip = function(map) { |
|---|
| 74 | {{for source in dict['data']['datasources']}} |
|---|
| 75 | {{py:sourceDict=dict['data']['datasources'][source]}} |
|---|
| 76 | {{if sourceDict.has_key('tooltip')}} |
|---|
| 77 | app.createTooltip.displayPopup_{{source}} = function(response) { |
|---|
| 78 | var features = response.features; |
|---|
| 79 | |
|---|
| 80 | if (features && features.length > 0) { |
|---|
| 81 | // build HTML table |
|---|
| 82 | var html = '<table border="1"><tr>'; |
|---|
| 83 | {{for col in sourceDict['columns']}} |
|---|
| 84 | {{py:colDict=sourceDict['columns'][col]}} |
|---|
| 85 | {{if colDict.has_key('tooltip')}} |
|---|
| 86 | html += "<th>{{colDict.get('alias', col)}}</th>"; |
|---|
| 87 | {{endif}} |
|---|
| 88 | {{endfor}} |
|---|
| 89 | html += "</tr>"; |
|---|
| 90 | for (var i = 0; i < features.length; i++) { |
|---|
| 91 | var attributes= features[i].attributes; |
|---|
| 92 | html += "<tr>"; |
|---|
| 93 | {{for col in sourceDict['columns']}} |
|---|
| 94 | {{py:colDict=sourceDict['columns'][col]}} |
|---|
| 95 | {{if colDict.has_key('tooltip')}} |
|---|
| 96 | html += "<td>" + attributes[{{jsondumps(col)}}] + "</td>"; |
|---|
| 97 | {{endif}} |
|---|
| 98 | {{endfor}} |
|---|
| 99 | html += "</tr>"; |
|---|
| 100 | } |
|---|
| 101 | html += "</table>"; |
|---|
| 102 | |
|---|
| 103 | var popup = this.popup = new OpenLayers.Popup.FramedCloud( |
|---|
| 104 | "mapfish_popup", // popup id |
|---|
| 105 | tooltip.popupLonLat, // OpenLayers.LonLat object |
|---|
| 106 | null, // popup is autosized |
|---|
| 107 | html, // html string |
|---|
| 108 | null, // no anchor |
|---|
| 109 | true // close button |
|---|
| 110 | ); |
|---|
| 111 | map.addPopup(popup, true); |
|---|
| 112 | } else { |
|---|
| 113 | if (this.popup) map.removePopup(this.popup); |
|---|
| 114 | } |
|---|
| 115 | }; |
|---|
| 116 | {{endif}} |
|---|
| 117 | {{endfor}} |
|---|
| 118 | |
|---|
| 119 | function createProtocol(controller) { |
|---|
| 120 | return mapfish.Protocol.decorateProtocol({ |
|---|
| 121 | protocol: new mapfish.Protocol.MapFish({ |
|---|
| 122 | url: '{{controller_base_url}}' + controller, |
|---|
| 123 | params: { |
|---|
| 124 | maxfeatures: 10, |
|---|
| 125 | no_geom: true |
|---|
| 126 | } |
|---|
| 127 | }), |
|---|
| 128 | TriggerEventDecorator: { |
|---|
| 129 | eventListeners: { |
|---|
| 130 | crudfinished: app.createTooltip['displayPopup_'+controller] |
|---|
| 131 | } |
|---|
| 132 | } |
|---|
| 133 | }); |
|---|
| 134 | } |
|---|
| 135 | |
|---|
| 136 | var protocol = createProtocol('dummy'); |
|---|
| 137 | var tooltip = new mapfish.Searcher.Map({ |
|---|
| 138 | mode: mapfish.Searcher.Map.HOVER, |
|---|
| 139 | protocol: protocol, |
|---|
| 140 | displayDefaultPopup: false |
|---|
| 141 | }); |
|---|
| 142 | tooltip.updateUrl = function(controller) { |
|---|
| 143 | if (this.protocol && this.protocol.destroy) this.protocol.destroy(); |
|---|
| 144 | this.protocol = createProtocol(controller); |
|---|
| 145 | }; |
|---|
| 146 | map.addControl(tooltip); |
|---|
| 147 | return tooltip; |
|---|
| 148 | }; |
|---|
| 149 | |
|---|
| 150 | app.createToolbar = function(map, buttons) { |
|---|
| 151 | var toolbar = new mapfish.widgets.toolbar.Toolbar({ |
|---|
| 152 | map: map, |
|---|
| 153 | configurable: false |
|---|
| 154 | }); |
|---|
| 155 | // This is a quick fix for http://trac.mapfish.org/trac/mapfish/ticket/126 |
|---|
| 156 | toolbar.autoHeight = false; |
|---|
| 157 | toolbar.height = 25; |
|---|
| 158 | // Spacer append helper |
|---|
| 159 | toolbar.addCuteSeparator = function() { |
|---|
| 160 | toolbar.addSpacer(); |
|---|
| 161 | toolbar.addSeparator(); |
|---|
| 162 | toolbar.addSpacer(); |
|---|
| 163 | }; |
|---|
| 164 | toolbar.initializeDefaults = function(map) { |
|---|
| 165 | toolbar.addControl( |
|---|
| 166 | new OpenLayers.Control.ZoomToMaxExtent({ |
|---|
| 167 | map: map, |
|---|
| 168 | title: 'Zoom to maximum map extent' |
|---|
| 169 | }), { |
|---|
| 170 | iconCls: 'zoomfull', |
|---|
| 171 | toggleGroup: 'map' |
|---|
| 172 | } |
|---|
| 173 | ); |
|---|
| 174 | toolbar.addCuteSeparator(); |
|---|
| 175 | toolbar.addControl( |
|---|
| 176 | new OpenLayers.Control.ZoomBox({ |
|---|
| 177 | title: 'Zoom in: click in the map or use the left mouse button and drag to create a rectangle' |
|---|
| 178 | }), { |
|---|
| 179 | iconCls: 'zoomin', |
|---|
| 180 | toggleGroup: 'map' |
|---|
| 181 | } |
|---|
| 182 | ); |
|---|
| 183 | toolbar.addControl( |
|---|
| 184 | new OpenLayers.Control.ZoomBox({ |
|---|
| 185 | out: true, |
|---|
| 186 | title: 'Zoom out: click in the map or use the left mouse button and drag to create a rectangle' |
|---|
| 187 | }), { |
|---|
| 188 | iconCls: 'zoomout', |
|---|
| 189 | toggleGroup: 'map' |
|---|
| 190 | } |
|---|
| 191 | ); |
|---|
| 192 | toolbar.addControl( |
|---|
| 193 | new OpenLayers.Control.DragPan({ |
|---|
| 194 | isDefault: true, |
|---|
| 195 | title: 'Pan map: keep the left mouse button pressed and drag the map' |
|---|
| 196 | }), { |
|---|
| 197 | iconCls: 'pan', |
|---|
| 198 | toggleGroup: 'map' |
|---|
| 199 | } |
|---|
| 200 | ); |
|---|
| 201 | }; |
|---|
| 202 | return toolbar; |
|---|
| 203 | } |
|---|
| 204 | |
|---|
| 205 | app.createLayout = function(map, toolbar) { |
|---|
| 206 | function createHeaderPanel(dict) { |
|---|
| 207 | return { |
|---|
| 208 | region: 'north', |
|---|
| 209 | height: {{jsondumps(dict['header']['height'])}}, |
|---|
| 210 | html: {{jsondumps(dict['header']['content'])}} |
|---|
| 211 | }; |
|---|
| 212 | } |
|---|
| 213 | |
|---|
| 214 | function createLayerTreePanel(map) { |
|---|
| 215 | return { |
|---|
| 216 | title: 'Layer Tree', |
|---|
| 217 | border: false, |
|---|
| 218 | xtype: 'layertree', |
|---|
| 219 | ascending: false, |
|---|
| 220 | map: map |
|---|
| 221 | }; |
|---|
| 222 | } |
|---|
| 223 | |
|---|
| 224 | {{if isEnabled('tooltip')}} |
|---|
| 225 | function createTooltipPanel(map) { |
|---|
| 226 | var store = new Ext.data.SimpleStore({ |
|---|
| 227 | fields: ['value', 'text'], |
|---|
| 228 | // data: [{{for source in dict['data']['datasources']}}{{if dict['data']['datasources'][source].has_key('tooltip')}}{{py:isFirst=True}}{{for column in dict['data']['datasources'][source]['columns']}}{{if dict['data']['datasources'][source]['columns'][column].has_key('tooltip')}}{{if not isFirst}},{{endif}} |
|---|
| 229 | // [{{jsondumps(column)}}, {{jsondumps(dict['data']['datasources'][source]['columns'][column].get('alias', column))}}]{{py:isFirst=False}}{{endif}}{{endfor}}{{endif}}{{endfor}} |
|---|
| 230 | // ] |
|---|
| 231 | data: [{{py:isFirst=True}} |
|---|
| 232 | {{for source in dict['data']['datasources']}} |
|---|
| 233 | {{py:sourceDict=dict['data']['datasources'][source]}} |
|---|
| 234 | {{if sourceDict.has_key('tooltip')}} |
|---|
| 235 | {{if not isFirst}},{{endif}} |
|---|
| 236 | [{{jsondumps(source)}}, {{jsondumps(sourceDict['name'])}}] |
|---|
| 237 | {{py:isFirst=False}} |
|---|
| 238 | {{endif}} |
|---|
| 239 | {{endfor}} |
|---|
| 240 | ] |
|---|
| 241 | }); |
|---|
| 242 | var value = store.getAt(0).data.value; |
|---|
| 243 | app.tooltip.updateUrl(value); |
|---|
| 244 | return { |
|---|
| 245 | title: 'Tooltip', |
|---|
| 246 | layout: 'form', |
|---|
| 247 | border: false, |
|---|
| 248 | items: [{ |
|---|
| 249 | xtype: 'combo', |
|---|
| 250 | store: store, |
|---|
| 251 | anchor: '100%', |
|---|
| 252 | hideLabel: true, |
|---|
| 253 | mode: 'local', |
|---|
| 254 | displayField: 'text', |
|---|
| 255 | valueField: 'value', |
|---|
| 256 | name: 'combovalue', |
|---|
| 257 | hiddenName: 'combovalue', |
|---|
| 258 | lazyRender: true, |
|---|
| 259 | lazyInit: true, |
|---|
| 260 | //width: 150, |
|---|
| 261 | //listWidth: 150, |
|---|
| 262 | editable: false, |
|---|
| 263 | listeners: { |
|---|
| 264 | 'select': function(combo) { app.tooltip.updateUrl(combo.value) } |
|---|
| 265 | }, |
|---|
| 266 | triggerAction: 'all', |
|---|
| 267 | value: value |
|---|
| 268 | }], |
|---|
| 269 | listeners: { |
|---|
| 270 | expand: function() { |
|---|
| 271 | app.tooltip.activate(); |
|---|
| 272 | }, |
|---|
| 273 | collapse: function() { |
|---|
| 274 | app.tooltip.deactivate(); |
|---|
| 275 | } |
|---|
| 276 | } |
|---|
| 277 | }; |
|---|
| 278 | } |
|---|
| 279 | {{endif}} |
|---|
| 280 | |
|---|
| 281 | {{if isEnabled('search')}} |
|---|
| 282 | function createSearchPanel(map) { |
|---|
| 283 | return { |
|---|
| 284 | title: 'Search', |
|---|
| 285 | labelAlign: 'top', |
|---|
| 286 | xtype: 'wsrecenter', |
|---|
| 287 | border: false, |
|---|
| 288 | cls: 'wsrecenter', |
|---|
| 289 | defaultZoom: 4, |
|---|
| 290 | defaults: {anchor: '100%'}, |
|---|
| 291 | map: map, |
|---|
| 292 | wsRecenterServices: [ |
|---|
| 293 | {{py:isFirst=True}} |
|---|
| 294 | {{for source in dict['data']['datasources']}} |
|---|
| 295 | {{py:sourceDict=dict['data']['datasources'][source]}} |
|---|
| 296 | {{if sourceDict.has_key('search')}} |
|---|
| 297 | {{for column in sourceDict['columns']}} |
|---|
| 298 | {{py:columnDict=sourceDict['columns'][column]}} |
|---|
| 299 | {{if columnDict.has_key('search')}} |
|---|
| 300 | {{if not isFirst}},{{endif}} |
|---|
| 301 | { |
|---|
| 302 | id: '{{source}}_{{column}}', |
|---|
| 303 | label: '{{sourceDict['name']}} / {{columnDict.get('alias', column)}}', |
|---|
| 304 | url: '{{controller_base_url}}/{{source}}', |
|---|
| 305 | urlSuffixGeo: '', |
|---|
| 306 | paramIdGeo: {{jsondumps(column)}}, |
|---|
| 307 | displayField: {{jsondumps(column)}}, |
|---|
| 308 | listFields: [{name: 'id', mapping: 'id'}, {name: '{{column}}', mapping: 'properties.{{column}}'}], |
|---|
| 309 | tpl: new Ext.XTemplate( |
|---|
| 310 | '<tpl for=".">', |
|---|
| 311 | '<div class="x-combo-list-item">', |
|---|
| 312 | '<h3><span>{{'{'+column+'}'}}</span></h3>', |
|---|
| 313 | '</div>', |
|---|
| 314 | '</tpl>' |
|---|
| 315 | ).compile(), |
|---|
| 316 | isDefault: {{if isFirst}}true{{else}}false{{endif}} |
|---|
| 317 | } |
|---|
| 318 | {{py:isFirst=False}} |
|---|
| 319 | {{endif}} |
|---|
| 320 | {{endfor}} |
|---|
| 321 | {{endif}} |
|---|
| 322 | {{endfor}} |
|---|
| 323 | ] |
|---|
| 324 | }; |
|---|
| 325 | } |
|---|
| 326 | {{endif}} |
|---|
| 327 | |
|---|
| 328 | var tools = []; |
|---|
| 329 | tools.push(createLayerTreePanel(map)); |
|---|
| 330 | {{if isEnabled('tooltip')}}tools.push(createTooltipPanel(map));{{endif}} |
|---|
| 331 | {{if isEnabled('search')}}tools.push(createSearchPanel(map));{{endif}} |
|---|
| 332 | |
|---|
| 333 | |
|---|
| 334 | var viewport = new Ext.Viewport({ |
|---|
| 335 | layout:'border', |
|---|
| 336 | items:[ |
|---|
| 337 | {{if dict.has_key('header') and dict['header']['content']}} |
|---|
| 338 | createHeaderPanel(), |
|---|
| 339 | {{endif}} |
|---|
| 340 | { |
|---|
| 341 | region: 'west', |
|---|
| 342 | id: 'west-panel', |
|---|
| 343 | title: 'Tools', |
|---|
| 344 | split: true, |
|---|
| 345 | width: 300, |
|---|
| 346 | minSize: 175, |
|---|
| 347 | maxSize: 400, |
|---|
| 348 | collapsible: true, |
|---|
| 349 | margins: '0 0 0 5', |
|---|
| 350 | layout: 'accordion', |
|---|
| 351 | layoutConfig:{ |
|---|
| 352 | animate: true |
|---|
| 353 | }, |
|---|
| 354 | items: tools |
|---|
| 355 | },{ |
|---|
| 356 | region: 'center', |
|---|
| 357 | title: 'Map', |
|---|
| 358 | layout: 'fit', |
|---|
| 359 | xtype: 'mapcomponent', |
|---|
| 360 | map: map, |
|---|
| 361 | tbar: toolbar |
|---|
| 362 | } |
|---|
| 363 | ] |
|---|
| 364 | }); |
|---|
| 365 | } |
|---|
| 366 | |
|---|
| 367 | Ext.BLANK_IMAGE_URL = "{{mfbase}}/ext/resources/images/default/s.gif"; |
|---|
| 368 | Ext.onReady(function() { app.create(); }); |
|---|
| 369 | {{else}} |
|---|
| 370 | {{skip_template()}} |
|---|
| 371 | {{endif}} |
|---|