├── .gitmodules ├── CHANGELOG ├── LICENSE ├── README.md ├── build ├── Makefile ├── build.bat ├── build.html └── deps.js ├── debug └── lvector-include.js ├── demos ├── arc2earth │ └── index.html ├── arcgis-server │ └── index.html ├── cartodb │ └── index.html ├── geoiq │ └── index.html ├── gis-cloud │ └── index.html ├── gitspatial │ └── index.html ├── index.html └── postgis-restful-web-service-framework │ └── index.html ├── dist └── lvector.js ├── docs-demo ├── css │ ├── bootstrap.css │ ├── bootstrap.min.css │ ├── demo.css │ ├── docs.css │ └── prettify.css ├── img │ ├── dynamic.png │ ├── github-fork.png │ ├── markers │ │ ├── bus.png │ │ ├── computer.png │ │ ├── golf.png │ │ ├── hydrant-blue.png │ │ ├── hydrant-red.png │ │ ├── library.png │ │ ├── manhole.png │ │ ├── nature-preserve.png │ │ ├── park.png │ │ ├── plow.png │ │ ├── recreation-center.png │ │ ├── school.png │ │ ├── ski-lift.png │ │ ├── truck.png │ │ ├── utility-blue.png │ │ ├── utility-orange.png │ │ └── utility-red.png │ ├── popup.png │ └── providers.png └── js │ ├── bootstrap-dropdown.js │ ├── docs-demos.js │ ├── jquery-1.8.1.min.js │ └── prettify.js ├── documentation └── index.html ├── download └── index.html ├── index.html ├── lib └── closure-compiler │ ├── COPYING │ ├── README │ └── compiler.jar ├── src ├── layer │ ├── A2E.js │ ├── AGS.js │ ├── CartoDB.js │ ├── EsriJSONLayer.js │ ├── GISCloud.js │ ├── GeoIQ.js │ ├── GeoJSONLayer.js │ ├── GitSpatial.js │ ├── Layer.js │ └── PRWSF.js └── lvector.js └── tips-tricks └── index.html /.gitmodules: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /CHANGELOG: -------------------------------------------------------------------------------- 1 | 1.0.0 2 | - Initial Release 3 | 4 | 1.1.0 5 | - Adding PostGIS RESTful Web Service Framework layer (lvector.PRWSF) 6 | 7 | 1.1.1 8 | - Fixing bug where multiple layers on same map failed when turning them on/off. All instances of lvector.PRWSF were referencing the same _idleListener and _zoomChangeListener objects. Oops. 9 | - Fixing bug where layer.setMap(null) to a layer that was already turned off threw errors. 10 | - Fixing sloppy semis; 11 | 12 | 1.2.0 13 | - New GIS Cloud layer (gvector.GISCloud) 14 | - DRYing up the code. Moved _processFeatures from individual layers into Layer.js 15 | - Creating two super-layers from which all other layers extend from: GeoJSONLayer and EsriJSONLayer 16 | - Fixed issue where any property change would trigger a symbology change in dynamic, styled layers. We now check to see if the symbology property has changed. 17 | 18 | 1.3.0 19 | - Support Leaflet 0.4.x 20 | - Fix bug where GeoIQ was returning JSON wrapped in single quotes, then they didn't, then this layer type broke. 21 | - Reduce filesize by 6k because I was dumb and duplicating some code. Still some room for improvement here. 22 | - Added code examples for GISCloud -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Jason Sanford 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are 5 | permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this list of 8 | conditions and the following disclaimer. 9 | 10 | 2. Redistributions in binary form must reproduce the above copyright notice, this list 11 | of conditions and the following disclaimer in the documentation and/or other materials 12 | provided with the distribution. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 15 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 16 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 17 | COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 19 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 21 | TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### About 2 | 3 | This library will add Leaflet vector (Point, Polyline, Polygon) layers from multiple geo web services including ArcGIS Server, GeoIQ, Arc2Earth, CartoDB, GIS Cloud, etc. 4 | 5 | Prefer Google Maps? Check out [Google Vector Layers](https://github.com/JasonSanford/google-vector-layers). 6 | 7 | ### Docs + Demos 8 | 9 | For details see the [documentation and demos](http://jasonsanford.github.io/leaflet-vector-layers/). 10 | -------------------------------------------------------------------------------- /build/Makefile: -------------------------------------------------------------------------------- 1 | ../dist/lvector.js: Makefile 2 | java -jar ../lib/closure-compiler/compiler.jar \ 3 | --js ../src/lvector.js \ 4 | --js ../src/core/Util.js \ 5 | --js ../src/core/Class.js \ 6 | --js ../src/layer/Layer.js \ 7 | --js ../src/layer/GeoJSONLayer.js \ 8 | --js ../src/layer/EsriJSONLayer.js \ 9 | --js ../src/layer/AGS.js \ 10 | --js ../src/layer/A2E.js \ 11 | --js ../src/layer/GeoIQ.js \ 12 | --js ../src/layer/CartoDB.js \ 13 | --js ../src/layer/PRWSF.js \ 14 | --js ../src/layer/GISCloud.js \ 15 | --js ../src/layer/GitSpatial.js \ 16 | --js_output_file ../dist/lvector.js 17 | -------------------------------------------------------------------------------- /build/build.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | java -jar ../lib/closure-compiler/compiler.jar ^ 3 | --js ../src/gvector.js ^ 4 | --js ../src/core/Util.js ^ 5 | --js ../src/core/Class.js ^ 6 | --js ../src/layer/Layer.js ^ 7 | --js ../src/layer/GeoJSONLayer.js ^ 8 | --js ../src/layer/EsriJSONLayer.js ^ 9 | --js ../src/layer/AGS.js ^ 10 | --js ../src/layer/A2E.js ^ 11 | --js ../src/layer/GeoIQ.js ^ 12 | --js ../src/layer/CartoDB.js ^ 13 | --js ../src/layer/PRWSF.js ^ 14 | --js ../src/layer/GISCloud.js ^ 15 | --js ../src/layer/GitSpatial.js ^ 16 | --js_output_file ../dist/lvector.js -------------------------------------------------------------------------------- /build/build.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Leaflet Vector Layers Build Helper 5 | 6 | 7 | 8 | 59 | 60 | 61 |
62 |

Leaflet Vector Layers Build Helper

63 | 64 |

65 | Select All | 66 | Deselect All 67 |

68 | 69 | 70 | 71 |

72 | Run this command in the build directory:
73 | 74 |

75 |
76 | 77 | 207 | 208 | -------------------------------------------------------------------------------- /build/deps.js: -------------------------------------------------------------------------------- 1 | var deps = { 2 | Core: { 3 | src: ['lvector.js'], 4 | desc: 'The core of the library' 5 | }, 6 | 7 | Layer: { 8 | src: ['layer/Layer.js'], 9 | desc: 'The base class for all layers', 10 | heading: 'Layers Core' 11 | }, 12 | 13 | GeoJSONLayer: { 14 | src: ['layer/GeoJSONLayer.js'], 15 | desc: 'The GeoJSON geometry parsing layer type', 16 | heading: 'Layers that extend this can parse GeoJSON geometry', 17 | deps: ['Layer'] 18 | }, 19 | 20 | EsriJSONLayer: { 21 | src: ['layer/EsriJSONLayer.js'], 22 | desc: 'The EsriJSON geometry parsing layer type', 23 | heading: 'Layers that extend this can parse EsriJSON geometry', 24 | deps: ['Layer'] 25 | }, 26 | 27 | AGS: { 28 | src: ['layer/AGS.js'], 29 | desc: 'The ArcGIS Server layer.', 30 | heading: 'ArcGIS Server', 31 | deps: ['EsriJSONLayer'] 32 | }, 33 | 34 | A2E: { 35 | src: ['layer/A2E.js'], 36 | desc: 'The Arc2Earth layer.', 37 | heading: 'Arc2Earth', 38 | deps: ['AGS'] 39 | }, 40 | 41 | GeoIQ: { 42 | src: ['layer/GeoIQ.js'], 43 | desc: 'The GeoIQ layer.', 44 | heading: 'GeoIQ', 45 | deps: ['GeoJSONLayer'] 46 | }, 47 | 48 | CartoDB: { 49 | src: ['layer/CartoDB.js'], 50 | desc: 'The CartoDB layer.', 51 | heading: 'CartoDB', 52 | deps: ['GeoJSONLayer'] 53 | }, 54 | 55 | PRWSF: { 56 | src: ['layer/PRWSF.js'], 57 | desc: 'The PostGIS RESTful Web Service Framework layer.', 58 | heading: 'PRWSF', 59 | deps: ['GeoJSONLayer'] 60 | }, 61 | 62 | GISCloud: { 63 | src: ['layer/GISCloud.js'], 64 | desc: 'The GIS Cloud Layer', 65 | heading: 'GIS Cloud', 66 | deps: ['GeoJSONLayer'] 67 | }, 68 | 69 | GitSpatial: { 70 | src: ['layer/GitSpatial.js'], 71 | desc: 'The GitSpatial Layer', 72 | heading: 'GitSpatial', 73 | deps: ['GeoJSONLayer'] 74 | } 75 | }; -------------------------------------------------------------------------------- /debug/lvector-include.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve Using portions of Leaflet code (http://github.com/Leaflet/Leaflet) 3 | */ 4 | (function() { 5 | 6 | var scripts = [ 7 | 'lvector.js', 8 | 9 | 'layer/Layer.js', 10 | 'layer/GeoJSONLayer.js', 11 | 'layer/EsriJSONLayer.js', 12 | 13 | 'layer/AGS.js', 14 | 'layer/A2E.js', 15 | 'layer/GeoIQ.js', 16 | 'layer/CartoDB.js', 17 | 'layer/PRWSF.js', 18 | 'layer/GISCloud.js', 19 | 'layer/GitSpatial.js' 20 | ]; 21 | 22 | function getSrcUrl() { 23 | var scripts = document.getElementsByTagName('script'); 24 | for (var i = 0; i < scripts.length; i++) { 25 | var src = scripts[i].src; 26 | if (src) { 27 | var res = src.match(/^(.*)lvector-include\.js$/); 28 | if (res) { 29 | return res[1] + '../src/'; 30 | } 31 | } 32 | } 33 | } 34 | 35 | var path = getSrcUrl(); 36 | for (var i = 0; i < scripts.length; i++) { 37 | document.writeln(""); 38 | } 39 | })(); 40 | -------------------------------------------------------------------------------- /demos/arc2earth/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Leaflet Vector Layers - Arc2Earth Demo 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Fork me on GitHub 25 |
26 |
27 |
28 | Leaflet Vector Layers 29 | 47 |
48 |
49 |
50 | 51 |
52 |
53 |

Arc2Earth

54 | 55 |

Since Arc2Earth implements Esri's Geo REST specification it's very easy to create layers from an Arc2Earth instance.

56 | 57 |

Light Rail Lines/Stations

58 |

This layer shows two layers from Arc2Earth Sync. Read below the demo for more information about Arc2Earth Sync.

59 |

For both of these layers we're using the esriOptions option. When set to true the ArcGIS Server instance is queried to set other options like scaleRange and symbology. This can be particularly helpful if you've spent a lot of time styling your layers in ArcMap and don't want to replicate with Google's vector configurations.

60 |
61 |
62 |
a2e_light_rail_lines = new lvector.A2E({
 63 |     url: "http://sync.arc2earth.com/6442491/ArcGIS/rest/services/tfs/2447511/FeatureServer/0",
 64 |     esriOptions: true,
 65 |     showAll: true,
 66 |     where: "ROUTE != '101'",
 67 |     popupTemplate: '<div class="iw-content"><h3>{ROUTE}</h3></div>',
 68 |     singlePopup: true
 69 | });
 70 | 
 71 | a2e_light_rail_stations = new lvector.A2E({
 72 |     url: "http://sync.arc2earth.com/6442491/ArcGIS/rest/services/tfs/2447610/FeatureServer/0",
 73 |     esriOptions: true,
 74 |     uniqueField: "global_fid",
 75 |     popupTemplate: '<div class="iw-content"><h3>{NAME}</h3><table class="condensed-table"><tr><th>Address</th><td>{ADDRESS}</td></tr><tr><th># Parking Spaces</th><td>{AUTOS}</td></tr><tr><th># Bike Racks</th><td>{RACKS}</td></tr><tr><th># Bike Lockers</th><td>{LOCKERS}</td></tr><tr><th># Shelters</th><td>{SHELTERS}</td></tr></table></div>',
 76 |     singlePopup: true
 77 | });
78 |
79 |
80 |
81 | 85 |
86 |
87 | 88 |
89 | 90 |

Live Feature Updates

91 |

This example shows an Arc2Earth Sync layer that is updated in near-real time. To accomplish this we set the dynamic and autoUpdate parameters to true.

92 |

To see this in action you should:

93 |
    94 |
  1. Turn the layer below on
  2. 95 |
  3. Open up a new browser window and view this ArcGIS.com map
  4. 96 |
  5. Be sure you can see both the ArcGIS.com map and the map below
  6. 97 |
  7. Make an edit the the ArcGIS.com map
  8. 98 |
  9. Watch the feature update live (<1 sec) in the map below
  10. 99 |
100 |

Changing the feature's type (Sewer Issue, Tree Issue, etc) should change symbology and geometry changes (moving the point) should change the same feature's location below.

101 |
102 |
103 |
a2e_vgi = new lvector.A2E({
104 |     url: "http://sync.arc2earth.com/6442491/ArcGIS/rest/services/tfs/2447544/FeatureServer/0",
105 |     esriOptions: true,
106 |     uniqueField: "global_fid",
107 |     popupTemplate: '<div class="iw-content"><h3>{Name}</h3></div>',
108 |     singlePopup: true,
109 |     dynamic: true,
110 |     autoUpdate: true
111 | });
112 |
113 |
114 |
115 |
116 | 117 |
118 |
119 |
120 | 121 |
122 | 123 |

Arc2Earth Sync

124 | 125 |

The demo above shows two Arc2Earth Sync layers using Google Fusion Tables as the backend datastore. The online layers and the Fusion Tables are automatically synchronized with a local ArcGIS cache so all renderer, symbology, layer definitions and edits are updated online when you make changes from ArcMap (and vice versa). Arc2Earth Sync is an easy way for ArcGIS users to maintain online feature services directly from their desktop.

126 | 127 |

Here's how the live layers look in ArcMap:

128 | 129 |

130 | 131 |

Also, since Sync implements the Open Geospatial REST spec (ArcGIS Server), you can also view and edit your tables from ArcGIS.com apps and apis. Here's the same map in ArcGIS.com.

132 | 133 |

If you want to help beta test Arc2Earth Sync, fill out this form.

134 | 135 | 138 |
139 |
140 | 141 | 142 | 143 | 144 | 145 | 146 | 205 | 206 | -------------------------------------------------------------------------------- /demos/cartodb/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Leaflet Vector Layers - CartoDB Demo 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Fork me on GitHub 25 |
26 |
27 |
28 | Leaflet Vector Layers 29 | 47 |
48 |
49 |
50 | 51 |
52 |
53 |

CartoDB

54 |

Sewer Network

55 |

This demo shows a point an a line table from CartoDB, sewer lines and man holes. The man holes are displayed using a simple symbology while the sewer lines use the range symbology. Pipes up to 8" in diameter are shown with a thinner green line, while larger pipes are shown with a thicker orange line.

56 |

We're also using the singlePopup option here so that only one Popup is shown for each layer. This keeps the map from getting cluttered when selecting lots of features.

57 |
58 |
59 |
cartodb_sewer_line = new lvector.CartoDB({
 60 |     user: "geojason",
 61 |     table: "sewer_line",
 62 |     scaleRange: [15, 20],
 63 |     symbology: {
 64 |         type: "range",
 65 |         property: "pipe_dia",
 66 |         ranges: [
 67 |             {
 68 |                 range: [0, 8],
 69 |                 vectorOptions: {
 70 |                     weight: 4,
 71 |                     color: "#46461f",
 72 |                     opacity: 0.8
 73 |                 }
 74 |             },{
 75 |                 range: [8.00001, 100],
 76 |                 vectorOptions: {
 77 |                     weight: 8,
 78 |                     color: "#ff7800",
 79 |                     opacity: 0.8
 80 |                 }
 81 |             }
 82 |         ]
 83 |     },
 84 |     popupTemplate: '<div class="iw-content"><h3>Sewer Line</h3><table class="condensed-table"><tr><th>Diameter</th><td>{pipe_dia} in.</td></tr><tr><th>Material</th><td>{pipe_mat}</td></tr><tr><th>Flows To</th><td>{wwtp} WWTP</td></tr></table></div>',
 85 |     singlePopup: true
 86 | });
 87 | 
 88 | var customMarker = L.Icon.extend({
 89 |     options: {
 90 |         iconUrl: "../../docs-demo/img/markers/manhole.png",
 91 |         shadowUrl: null,
 92 |         iconSize: new L.Point(16, 16),
 93 |         iconAnchor: new L.Point(8, 8),
 94 |         popupAnchor: new L.Point(1, -8)
 95 |     }
 96 | });
 97 | 
 98 | cartodb_man_hole = new lvector.CartoDB({
 99 |     user: "geojason",
100 |     table: "man_hole",
101 |     scaleRange: [16, 20],
102 |     symbology: {
103 |         type: "single",
104 |         vectorOptions: {
105 |             circleMarker: true,
106 |             radius: 20
107 |         }
108 |     },
109 |     popupTemplate: '<div class="iw-content"><h3>Man Hole</h3><table class="condensed-table"><tr><th>Diameter</th><td>{mh_dia} ft.</td></tr><tr><th>Depth</th><td>{mh_depth} ft.</td></tr><tr><th>Address</th><td>{street_add}</td></tr><tr><th>Flows To</th><td>{wwtp} WWTP</td></tr></table></div>',
110 |     singlePopup: true
111 | });
112 |
113 |
114 |
115 | 119 |
120 |
121 |
122 | 123 |

Flood Zones

124 |

One huge benefit when using CartoDB is that we get direct SQL access to the PostGIS database. In this example we're using the ST_Simplify function to trim down the number of vertices on returned geometry so that features appear a little quicker. This isn't necessary on all data sets but is helpful when dealing with complex geometries.

125 |

Keep in mind when performing geometric functions with SQL, your output geometry must be in a field named the_geom to return proper GeoJSON.

126 |
127 |
128 |
cartodb_flood_zones = new lvector.CartoDB({
129 |     user: "geojason",
130 |     table: "flood_zones",
131 |     fields: "cartodb_id,label,st_simplify(the_geom,0.000008) the_geom",
132 |     scaleRange: [14, 20],
133 |     symbology: {
134 |         type: "unique",
135 |         property: "label",
136 |         values: [
137 |             {
138 |                 value: "AE",
139 |                 vectorOptions: {
140 |                     fillColor: "#2f952f",
141 |                     fillOpacity: 0.6,
142 |                     weight: 1,
143 |                     color: "#fff",
144 |                     opacity: 0
145 |                 }
146 |             },
147 |             {
148 |                 value: "AE-FW",
149 |                 vectorOptions: {
150 |                     fillColor: "#004a00",
151 |                     fillOpacity: 0.6,
152 |                     weight: 1,
153 |                     color: "#fff",
154 |                     opacity: 0
155 |                 }
156 |             },
157 |             {
158 |                 value: "0.2% Annual Chance",
159 |                 vectorOptions: {
160 |                     fillColor: "#aaff7a",
161 |                     fillOpacity: 0.6,
162 |                     weight: 1,
163 |                     color: "#fff",
164 |                     opacity: 0
165 |                 }
166 |             }
167 |         ],
168 |     },
169 |     popupTemplate: '<div class="iw-content"><h3>Flood Zone</h3><table class="condensed-table"><tr><th>Type</th><td>{label}</td></tr></table></div>',
170 |     singlePopup: true
171 | });
172 |
173 |
174 |
175 |
176 | 177 |
178 |
179 |
180 | 181 | 184 |
185 |
186 | 187 | 188 | 189 | 190 | 191 | 192 | 316 | 317 | -------------------------------------------------------------------------------- /demos/geoiq/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Leaflet Vector Layers - GeoIQ Demo 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Fork me on GitHub 25 |
26 |
27 |
28 | Leaflet Vector Layers 29 | 47 |
48 |
49 |
50 | 51 |
52 |
53 |

GeoIQ

54 |

Ski Areas

55 |

This simple demo shows ski areas throughout the US. We've defined a scaleRange so we don't show too many markers at lower zoom levels.

56 |

A very simple popupTemplate has also been provided as well as a single symbology type that shows a custom marker.

57 |
58 |
59 |
var customMarker = L.Icon.extend({
 60 |     options: {
 61 |         iconUrl: "../../docs-demo/img/markers/ski-lift.png",
 62 |         shadowUrl: null,
 63 |         iconSize: new L.Point(32, 37),
 64 |         iconAnchor: new L.Point(16, 37),
 65 |         popupAnchor: new L.Point(0, -35)
 66 |     }
 67 | });
 68 | 
 69 | geoiq_ski_areas = new lvector.GeoIQ({
 70 | 	dataset: 164880,
 71 | 	uniqueField: "NAME",
 72 | 	scaleRange: [6, 20],
 73 | 	popupTemplate: '<div class="iw-content"><h3>{NAME}</h3></div>',
 74 | 	singlePopup: true,
 75 | 	symbology: {
 76 | 	    type: "single",
 77 | 	    vectorOptions: {
 78 | 		    icon: new customMarker()
 79 | 	    }
 80 | 	}
 81 | });
82 |
83 |
84 |
85 |
86 | 87 |
88 |
89 |
90 | 91 |
92 | 93 |

US FOSS4G Registrants

94 |

This demo shows how to use a range symbology type to symbolize more FOSS4G registrants with a darker shade of blue.

95 |

We're also using the showAll parameter to fetch all features at once, since we're initially zoomed out to a level where we can see almost the entire dataset. There's no sense in re-fetching this (quite large) dataset more than once.

96 |

Keep in mind that it could take a few seconds to load this dataset due to its large size.

97 |
98 |
99 |
geoiq_foss4g_reg = new lvector.GeoIQ({
100 |     dataset: 147336,
101 |     uniqueField: "state",
102 |     showAll: true,
103 |     popupTemplate: '<div class="iw-content"><h3>{state}</h3><table class="condensed-table"><tr><th>Registrants</th><td>{count}</td></tr><tr><th>Percent of Total</th><td>{percent}</td></tr></table></div>',
104 |     singlePopup: true,
105 |     symbology: {
106 |         type: "range",
107 |         property: "count",
108 |         ranges: [
109 |             {
110 |                 range: [1, 1],
111 |                 vectorOptions: {
112 |                     fillColor: "#F1EEF6",
113 |                     fillOpacity: 0.85,
114 |                     color: "#333",
115 |                     weight: 1,
116 |                     opacity: 1
117 |                 }
118 |             },
119 |             {
120 |                 range: [2, 10],
121 |                 vectorOptions: {
122 |                     fillColor: "#BDC9E1",
123 |                     fillOpacity: 0.85,
124 |                     color: "#333",
125 |                     weight: 1,
126 |                     opacity: 1
127 |                 }
128 |             },
129 |             {
130 |                 range: [11, 20],
131 |                 vectorOptions: {
132 |                     fillColor: "#74A9CF",
133 |                     fillOpacity: 0.85,
134 |                     color: "#333",
135 |                     weight: 1,
136 |                     opacity: 1
137 |                 }
138 |             },
139 |             {
140 |                 range: [21, 126],
141 |                 vectorOptions: {
142 |                     fillColor: "#0570B0",
143 |                     fillOpacity: 0.85,
144 |                     color: "#333",
145 |                     weight: 1,
146 |                     opacity: 1
147 |                 }
148 |             }
149 |         ]
150 |     }
151 | });
152 |
153 |
154 |
155 |
156 | 157 |
158 |
159 |
160 | 161 |
162 | 163 |

Mecklenburg County Parks

164 |

This example has features styled using the unique symbology type where values of a particular attribute ("prktype" in this example) have a specific style.

165 |

We're also using a function based popupTemplate to format our data so it's a little easier to read - In this case convert attributes to Proper Case instead of UPPER CASE.

166 |
167 |
168 |
geoiq_parks = new lvector.GeoIQ({
169 |     dataset: 181235,
170 |     uniqueField: "prkid",
171 |     popupTemplate: function(properties) {
172 |         var properCase = function(s) {
173 |             if (s){
174 |                 return s.replace(/_/gi, " ").replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
175 |             } else {
176 |                 return "";
177 |             }
178 |         };
179 |         var html = '<div class="iw-content"><h3>' + properCase(properties.name) + '</h3><table class="condensed-table">';
180 |         html += '<tr><th>Address</th><td>' + properCase(properties.prkaddr) + '</td></tr>';
181 |         html += '<tr><th>Size</th><td>' + properties.prksize + ' acres</td></tr>';
182 |         return html += '</table></div>';
183 |     },
184 |     symbology: {
185 |         type: "unique",
186 |         property: "prktype",
187 |         values: [
188 |             {
189 |                 value: "REGIONAL PARK",
190 |                 vectorOptions: {
191 |                     icon: new customMarker({
192 |                         iconUrl: "../../docs-demo/img/markers/park.png"
193 |                     })
194 |                 }
195 |             },
196 |             {
197 |                 value: "NEIGHBORHOOD PARK",
198 |                 vectorOptions: {
199 |                     icon: new customMarker({
200 |                         iconUrl: "../../docs-demo/img/markers/park.png"
201 |                     })
202 |                 }
203 |             },
204 |             {
205 |                 value: "COMMUNITY PARK",
206 |                 vectorOptions: {
207 |                     icon: new customMarker({
208 |                         iconUrl: "../../docs-demo/img/markers/park.png"
209 |                     })
210 |                 }
211 |             },
212 |             {
213 |                 value: "NATURE PRESERVE",
214 |                 vectorOptions: {
215 |                     icon: new customMarker({
216 |                         iconUrl: "../../docs-demo/img/markers/nature-preserve.png"
217 |                     })
218 |                 }
219 |             },
220 |             {
221 |                 value: "RECREATION CENTER",
222 |                 vectorOptions: {
223 |                     icon: new customMarker({
224 |                         iconUrl: "../../docs-demo/img/markers/recreation-center.png"
225 |                     })
226 |                 }
227 |             },
228 |             {
229 |                 value: "GOLF COURSE",
230 |                 vectorOptions: {
231 |                     icon: new customMarker({
232 |                         iconUrl: "../../docs-demo/img/markers/golf.png"
233 |                     })
234 |                 }
235 |             }
236 |         ]
237 |     }
238 | });
239 |
240 |
241 |
242 |
243 | 244 |
245 |
246 |
247 | 248 | 251 |
252 |
253 | 254 | 255 | 256 | 257 | 258 | 259 | 451 | 452 | -------------------------------------------------------------------------------- /demos/gitspatial/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Leaflet Vector Layers - GitSpatial Demo 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Fork me on GitHub 25 |
26 |
27 |
28 | Leaflet Vector Layers 29 | 47 |
48 |
49 |
50 | 51 |
52 |
53 |

GitSpatial

54 | 55 |

Mecklenburg County Parks

56 |

This example has features styled using the unique symbology type where values of a particular attribute ("prktype" in this example) have a specific style.

57 |

We're also using a function based popupTemplate to format our data so it's a little easier to read - In this case convert attributes to Proper Case instead of UPPER CASE.

58 |
59 |
60 |
gitspatial_parks = new lvector.GitSpatial({
 61 |     user: 'JasonSanford',
 62 |     repo: 'mecklenburg-gis-opendata',
 63 |     featureSet: 'parks',
 64 |     popupTemplate: function(properties) {
 65 |         var properCase = function(s) {
 66 |             if (s){
 67 |                 return s.replace(/_/gi, " ").replace(/\w\S*/g, function(txt){return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();});
 68 |             } else {
 69 |                 return "";
 70 |             }
 71 |         };
 72 |         var html = '<div class="iw-content"><h3>' + properCase(properties.name) + '</h3><table class="condensed-table">';
 73 |         html += '<tr><th>Address</th><td>' + properCase(properties.address) + '</td></tr>';
 74 |         return html += '</table></div>';
 75 |     },
 76 |     symbology: {
 77 |         type: "unique",
 78 |         property: "type",
 79 |         values: [
 80 |             {
 81 |                 value: "REGIONAL PARK",
 82 |                 vectorOptions: {
 83 |                     icon: new customMarker({
 84 |                         iconUrl: "../../docs-demo/img/markers/park.png"
 85 |                     })
 86 |                 }
 87 |             },
 88 |             {
 89 |                 value: "NEIGHBORHOOD PARK",
 90 |                 vectorOptions: {
 91 |                     icon: new customMarker({
 92 |                         iconUrl: "../../docs-demo/img/markers/park.png"
 93 |                     })
 94 |                 }
 95 |             },
 96 |             {
 97 |                 value: "COMMUNITY PARK",
 98 |                 vectorOptions: {
 99 |                     icon: new customMarker({
100 |                         iconUrl: "../../docs-demo/img/markers/park.png"
101 |                     })
102 |                 }
103 |             },
104 |             {
105 |                 value: "NATURE PRESERVE",
106 |                 vectorOptions: {
107 |                     icon: new customMarker({
108 |                         iconUrl: "../../docs-demo/img/markers/nature-preserve.png"
109 |                     })
110 |                 }
111 |             },
112 |             {
113 |                 value: "RECREATION CENTER",
114 |                 vectorOptions: {
115 |                     icon: new customMarker({
116 |                         iconUrl: "../../docs-demo/img/markers/recreation-center.png"
117 |                     })
118 |                 }
119 |             },
120 |             {
121 |                 value: "GOLF COURSE",
122 |                 vectorOptions: {
123 |                     icon: new customMarker({
124 |                         iconUrl: "../../docs-demo/img/markers/golf.png"
125 |                     })
126 |                 }
127 |             }
128 |         ]
129 |     }
130 | });
131 |
132 |
133 |
134 |
135 | 136 |
137 |
138 |
139 | 140 |
141 | 142 |

Cambridge Neighborhoods

143 |

This example has a simple, single symbology and uses the showAll parameter to fetch all features at once since there are only a handful.

144 |

We're also using a simple string based popupTemplate and have singlePopup set to true so that the map isn't too cluttered.

145 |
146 |
147 |
gitspatial_neighborhoods = new lvector.GitSpatial({
148 |     user: 'JasonSanford',
149 |     repo: 'cambridgegis_data',
150 |     featureSet: 'neighborhoods',
151 |     showAll: true,
152 |     symbology: {
153 |         type: 'single',
154 |         vectorOptions: {
155 |             fillColor: '#ff7800',
156 |             color: '#46461f',
157 |             weight: 3,
158 |             opacity: 1
159 |         }
160 |     },
161 |     popupTemplate: '<h3>{NAME}</h3>',
162 |     singlePopup: true
163 | });
164 |
165 |
166 |
167 |
168 | 169 |
170 |
171 |
172 | 173 |
174 | 175 |

Cambridge Utility Poles

176 |

This example uses a range symbology type to display utility poles with three different ranges of height using different colored markers.

177 |
178 |
179 |
gitspatial_utility_poles = new lvector.GitSpatial({
180 |     user: 'JasonSanford',
181 |     repo: 'cambridgegis_data',
182 |     featureSet: 'utility_poles',
183 |     scaleRange: [16, 18],
184 |     popupTemplate: '<h4>Height: {ELEV}\'</h4>',
185 |     singlePopup: true,
186 |     symbology: {
187 |         type: 'range',
188 |         property: 'ELEV',
189 |         ranges: [
190 |             {
191 |                 range: [0, 12],
192 |                 vectorOptions: {
193 |                     icon: new customMarker({
194 |                         iconUrl: '../../docs-demo/img/markers/utility-blue.png'
195 |                     })
196 |                 }
197 |             },
198 |             {
199 |                 range: [12.000001, 20],
200 |                 vectorOptions: {
201 |                     icon: new customMarker({
202 |                         iconUrl: '../../docs-demo/img/markers/utility-orange.png'
203 |                     })
204 |                 }
205 |             },
206 |             {
207 |                 range: [20.000001, 100],
208 |                 vectorOptions: {
209 |                     icon: new customMarker({
210 |                         iconUrl: '../../docs-demo/img/markers/utility-red.png'
211 |                     })
212 |                 }
213 |             }
214 |         ]
215 |     }
216 | });
217 |
218 |
219 |
220 |
221 | 222 |
223 |
224 |
225 | 226 | 229 |
230 |
231 | 232 | 233 | 234 | 235 | 236 | 237 | 418 | 419 | 420 | -------------------------------------------------------------------------------- /demos/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Leaflet Vector Layers - Jason Sanford 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Fork me on GitHub 24 |
25 |
26 |
27 | Leaflet Vector Layers 28 | 46 |
47 |
48 |
49 | 50 |
51 |
52 |

Demos

53 |
54 |
55 |

Arc2Earth

56 |
57 |
58 |

ArcGIS Server

59 |
60 |
61 |

CartoDB

62 |
63 |
64 |

GeoIQ

65 |
66 |
67 | 70 |
71 |
72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /demos/postgis-restful-web-service-framework/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Leaflet Vector Layers - PostGIS RESTful Web Service Framework Demo 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | Fork me on GitHub 25 |
26 |
27 |
28 | Leaflet Vector Layers 29 | 46 |
47 |
48 |
49 | 50 |
51 |
52 |

PostGIS RESTful Web Service Framework

53 | 54 |

Mountain Backdrop Preservation Areas

55 |

This simple demo shows mountain backdrop preservation areas. We're using the showAll parameter since there are only a handful of features and there's no sense re-fetching features with each map pan or zoom.

56 |

Also, note the use of the clickable: false option in the vector symbology definitions. This ensures that the cursor doesn't change to something that would make the user think they could click these polygons since they're just here for display and don't contain any attribute to populate an Popup.

57 |
58 |
59 |
prwsf_preservation = new lvector.PRWSF({
 60 |     url: "http://gis.drcog.org/REST",
 61 |     geotable: "mountain_backdrop_preservation_area",
 62 |     fields: "gid",
 63 |     uniqueField: "gid",
 64 |     srid: 2232,
 65 |     showAll: true,
 66 |     symbology: {
 67 |         type: "single",
 68 |         vectorOptions: {
 69 |             fillColor: "#2f4a00",
 70 |             fillOpacity: 0.4,
 71 |             weight: 1.8,
 72 |             color: "#2f4a00",
 73 |             opacity: 1,
 74 |             clickable: false
 75 |         }
 76 |     }
 77 | });
78 |
79 |
80 |
81 |
82 | 83 |
84 |
85 |
86 | 87 |
88 | 89 |

Fire Hydrants

90 |

This demo uses the unique symbology type so we can view the difference between public and private fire hydrants. There's also a simple popupTemplate to help describe the features and a title tooltip when hovering over the marker.

91 |

We're also using the scaleRange parameter so that when someone zooms out beyond zoom level 15, no more feature requests are made. This helps keep the map from being too cluttered.

92 |
93 |
94 |
var customMarker = L.Icon.extend({
 95 |     options: {
 96 |         iconUrl: "../../docs-demo/img/markers/hydrant-blue.png",
 97 |         shadowUrl: null,
 98 |         iconSize: new L.Point(32, 37),
 99 |         iconAnchor: new L.Point(16, 37),
100 |         popupAnchor: new L.Point(0, -35)
101 |     }
102 | });
103 | 
104 | prwsf_hydrants = new lvector.PRWSF({
105 |     url: "http://maps.co.mecklenburg.nc.us/rest",
106 |     geotable: "fire_hydrants",
107 |     fields: "gid,tagnumber,barrelsize,owner",
108 |     uniqueField: "gid",
109 |     srid: 2264,
110 |     scaleRange: [15, 20],
111 |     popupTemplate: '<div class="iw-content"><h3>Tag #{tagnumber}</h3><table class="condensed-table bordered-table zebra-striped"><tbody><tr><th>Owner</th><td>{owner}</td></tr><tr><th>Barrel Size</th><td>{barrelsize}</td></tr></tbody></table></div>',
112 |     singlePopup: true,
113 |     symbology: {
114 |         type: "unique",
115 |         property: "owner",
116 |         values: [
117 |             {
118 |                 value: "Public",
119 |                 vectorOptions: {
120 |                     icon: new customMarker(),
121 |                     title: "{tagnumber} ({owner})"
122 |                 }
123 |             },
124 |             {
125 |                 value: "Private",
126 |                 vectorOptions: {
127 |                     icon: new customMarker({
128 |                         iconUrl: "../../docs-demo/img/markers/hydrant-red.png"
129 |                     }),
130 |                     title: "{tagnumber} ({owner})"
131 |                 }
132 |             }
133 |         ]
134 |     }
135 | });
136 |
137 |
138 |
139 |
140 | 141 |
142 |
143 |
144 | 145 |
146 | 147 |

Libraries (and directions to them)

148 |

This demo has a simple, single symbology for all libraries and makes use of a popupTempmlate to inject the libraries address into the Popup, making driving directions to each location just a mouse click away.

149 |
150 |
151 |
var customMarker = L.Icon.extend({
152 |     options: {
153 |         iconUrl: "../../docs-demo/img/markers/library.png",
154 |         shadowUrl: null,
155 |         iconSize: new L.Point(32, 37),
156 |         iconAnchor: new L.Point(16, 37),
157 |         popupAnchor: new L.Point(0, -35)
158 |     }
159 | });
160 | 
161 | prwsf_libraries = new lvector.PRWSF({
162 |     url: "http://maps.co.mecklenburg.nc.us/rest",
163 |     geotable: "libraries",
164 |     fields: "gid,name,address,city",
165 |     uniqueField: "gid",
166 |     srid: 2264,
167 |     scaleRange: [7, 20],
168 |     showAll: true,
169 |     popupTemplate: '<div class="iw-content"><h3>{name}</h3><a href="http://maps.google.com/maps?saddr=&daddr={address}, {city}" target="_blank"><h4>{address} (click for directions)</h4></a></div>',
170 |     singlePopup: true,
171 |     symbology: {
172 |         type: "single",
173 |         vectorOptions: {
174 |             icon: new customMarker()
175 |         }
176 |     }
177 | });
178 |
179 |
180 |
181 |
182 | 183 |
184 |
185 |
186 | 187 |
188 | 189 |

Bus Stops

190 |

This demo shows RTD (Denver, CO) Bus Stop locations and updates with each map pan and zoom.

191 |

The popupTemplate in this demo is slightly more complex as we're using a function (which gets passed feature properties) that helps us create links to each route's schedule with a bit of JavaScript hackery.

192 |
193 |
194 |
var busMarker = L.Icon.extend({
195 |     options: {
196 |         iconUrl: "../../docs-demo/img/markers/bus.png",
197 |         shadowUrl: null,
198 |         iconSize: new L.Point(17, 19),
199 |         iconAnchor: new L.Point(0, 19),
200 |         popupAnchor: new L.Point(9, -19)
201 |     }
202 | });
203 | 
204 | prwsf_bus = new lvector.PRWSF({
205 |     url: "http://gis.drcog.org/REST",
206 |     geotable: "rtd_busstops",
207 |     fields: "gid,bsid,routes,stopname,dir,location",
208 |     uniqueField: "gid",
209 |     srid: 2232,
210 |     scaleRange: [14, 20],
211 |     popupTemplate: function(properties) {
212 |         var html = '<div class="iw-content"><h3>' + properties.stopname + '</h4><h4>' + properties.dir + '-bound</h4><table class="condensed-table bordered-table zebra-striped"><tbody><tr><th>Bus Stop ID</th><td>' + properties.bsid + '</td></tr><tr><th>Routes</th><td>';
213 |         var routes = properties.routes.split(",");
214 |         var routesHtml = '';
215 |         for (var i = 0, len = routes.length; i < len; i++) {
216 |             routesHtml += (routesHtml.length ? ", " : "") + '<a href="http://www3.rtd-denver.com/schedules/getSchedule.action?&routeId=' + routes[i].trim() + '" target="_blank">' + routes[i].trim() + '</a>';
217 |         }
218 |         html += routesHtml + '</td></tr></tbody></table></div>';
219 |         return html;
220 |     },
221 |     popupWindow: true,
222 |     symbology: {
223 |         type: "single",
224 |         vectorOptions: {
225 |             icon: new busMarker({
226 |                 iconUrl: "../../docs-demo/img/markers/bus.png"
227 |             })
228 |         }
229 |     }
230 | });
231 |
232 |
233 |
234 |
235 | 236 |
237 |
238 |
239 | 240 | 243 |
244 |
245 | 246 | 247 | 248 | 249 | 250 | 251 | 426 | 427 | -------------------------------------------------------------------------------- /docs-demo/css/demo.css: -------------------------------------------------------------------------------- 1 | body { 2 | padding-top: 60px; 3 | } 4 | h2 small { 5 | color: #5a5a5a; 6 | } 7 | .container-fluid > .sidebar { 8 | position: fixed !important; 9 | margin-top: 60px; 10 | } 11 | .sample-image { 12 | border: 1px solid #DDD; 13 | -webkit-border-radius: 4px; 14 | -moz-border-radius: 4px; 15 | border-radius: 4px; 16 | -webkit-box-shadow: 0 3px 3px rgba(0, 0, 0, 0.075); 17 | -moz-box-shadow: 0 3px 3px rgba(0, 0, 0, 0.075); 18 | box-shadow: 0 3px 3px rgba(0, 0, 0, 0.075); 19 | float: left; 20 | margin: 0 10px 4px 0; 21 | padding: 5px; 22 | } 23 | .demo { 24 | height: 450px; 25 | position: relative; 26 | } 27 | .demo .height-controlled { 28 | height: 100%; 29 | } 30 | .demo pre { 31 | height: 100%; 32 | overflow: auto; 33 | white-space: pre; 34 | word-wrap: normal; 35 | } 36 | .map { 37 | height: 100%; 38 | border: 1px solid #a5a5a5; 39 | -moz-box-shadow: 5px 5px 5px #d2d2d2; 40 | -webkit-box-shadow: 5px 5px 5px #d2d2d2; 41 | box-shadow: 5px 5px 5px #d2d2d2; 42 | } 43 | .layer-buttons { 44 | position: absolute; 45 | bottom: 0; 46 | right: 0; 47 | margin-right: 8px; 48 | margin-bottom: 15px; 49 | z-index: 100; 50 | float: right; 51 | } 52 | .layer-button-row a{ 53 | margin-bottom: 5px; 54 | } 55 | .iw-content { 56 | 57 | } 58 | .iw-content h3 { 59 | font-size: 18px; 60 | text-align: center; 61 | margin: 4px 0 4px 0; 62 | line-height: inherit; 63 | } 64 | .iw-content h4 { 65 | font-size: 14px; 66 | text-align: center; 67 | margin: 0 0 4px 0; 68 | line-height: inherit; 69 | } 70 | ul.docs li, ol.docs li{ 71 | color: #404040 !important; 72 | } -------------------------------------------------------------------------------- /docs-demo/css/docs.css: -------------------------------------------------------------------------------- 1 | h2.docs { 2 | background-color: #E1E1E1; 3 | -webkit-border-radius: 8px; 4 | -moz-border-radius: 8px; 5 | border-radius: 8px; 6 | padding: 0 10px; 7 | margin-bottom: 12px; 8 | } 9 | .docs code { 10 | font-family: "Courier New", monospace; 11 | background-color: inherit !important; 12 | color: rgba(0, 0, 0, 0.75); 13 | padding: 0 !important; 14 | } 15 | pre.docs { 16 | overflow: auto; 17 | white-space: pre; 18 | word-wrap: normal; 19 | } 20 | table.docs { 21 | border: 1px solid #ddd; 22 | } 23 | .docs td { 24 | min-width: 120px; 25 | } 26 | .content-centered { 27 | text-align: center; 28 | } -------------------------------------------------------------------------------- /docs-demo/css/prettify.css: -------------------------------------------------------------------------------- 1 | .pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} -------------------------------------------------------------------------------- /docs-demo/img/dynamic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/dynamic.png -------------------------------------------------------------------------------- /docs-demo/img/github-fork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/github-fork.png -------------------------------------------------------------------------------- /docs-demo/img/markers/bus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/markers/bus.png -------------------------------------------------------------------------------- /docs-demo/img/markers/computer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/markers/computer.png -------------------------------------------------------------------------------- /docs-demo/img/markers/golf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/markers/golf.png -------------------------------------------------------------------------------- /docs-demo/img/markers/hydrant-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/markers/hydrant-blue.png -------------------------------------------------------------------------------- /docs-demo/img/markers/hydrant-red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/markers/hydrant-red.png -------------------------------------------------------------------------------- /docs-demo/img/markers/library.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/markers/library.png -------------------------------------------------------------------------------- /docs-demo/img/markers/manhole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/markers/manhole.png -------------------------------------------------------------------------------- /docs-demo/img/markers/nature-preserve.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/markers/nature-preserve.png -------------------------------------------------------------------------------- /docs-demo/img/markers/park.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/markers/park.png -------------------------------------------------------------------------------- /docs-demo/img/markers/plow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/markers/plow.png -------------------------------------------------------------------------------- /docs-demo/img/markers/recreation-center.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/markers/recreation-center.png -------------------------------------------------------------------------------- /docs-demo/img/markers/school.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/markers/school.png -------------------------------------------------------------------------------- /docs-demo/img/markers/ski-lift.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/markers/ski-lift.png -------------------------------------------------------------------------------- /docs-demo/img/markers/truck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/markers/truck.png -------------------------------------------------------------------------------- /docs-demo/img/markers/utility-blue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/markers/utility-blue.png -------------------------------------------------------------------------------- /docs-demo/img/markers/utility-orange.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/markers/utility-orange.png -------------------------------------------------------------------------------- /docs-demo/img/markers/utility-red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/markers/utility-red.png -------------------------------------------------------------------------------- /docs-demo/img/popup.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/popup.png -------------------------------------------------------------------------------- /docs-demo/img/providers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/docs-demo/img/providers.png -------------------------------------------------------------------------------- /docs-demo/js/bootstrap-dropdown.js: -------------------------------------------------------------------------------- 1 | /* ============================================================ 2 | * bootstrap-dropdown.js v1.4.0 3 | * http://twitter.github.com/bootstrap/javascript.html#dropdown 4 | * ============================================================ 5 | * Copyright 2011 Twitter, Inc. 6 | * 7 | * Licensed under the Apache License, Version 2.0 (the "License"); 8 | * you may not use this file except in compliance with the License. 9 | * You may obtain a copy of the License at 10 | * 11 | * http://www.apache.org/licenses/LICENSE-2.0 12 | * 13 | * Unless required by applicable law or agreed to in writing, software 14 | * distributed under the License is distributed on an "AS IS" BASIS, 15 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | * See the License for the specific language governing permissions and 17 | * limitations under the License. 18 | * ============================================================ */ 19 | 20 | 21 | !function( $ ){ 22 | 23 | "use strict" 24 | 25 | /* DROPDOWN PLUGIN DEFINITION 26 | * ========================== */ 27 | 28 | $.fn.dropdown = function ( selector ) { 29 | return this.each(function () { 30 | $(this).delegate(selector || d, 'click', function (e) { 31 | var li = $(this).parent('li') 32 | , isActive = li.hasClass('open') 33 | 34 | clearMenus() 35 | !isActive && li.toggleClass('open') 36 | return false 37 | }) 38 | }) 39 | } 40 | 41 | /* APPLY TO STANDARD DROPDOWN ELEMENTS 42 | * =================================== */ 43 | 44 | var d = 'a.menu, .dropdown-toggle' 45 | 46 | function clearMenus() { 47 | $(d).parent('li').removeClass('open') 48 | } 49 | 50 | $(function () { 51 | $('html').bind("click", clearMenus) 52 | $('body').dropdown( '[data-dropdown] a.menu, [data-dropdown] .dropdown-toggle' ) 53 | }) 54 | 55 | }( window.jQuery || window.ender ); 56 | -------------------------------------------------------------------------------- /docs-demo/js/docs-demos.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function() { 2 | prettyPrint(); 3 | 4 | /*$.getJSON("https://api.github.com/repos/JasonSanford/google-vector-layers/issues?state=open&callback=?", function(issues) { 5 | if (issues && issues.data && issues.data.length) { 6 | var issuesHTML = '
Current Issues
'; 12 | $("div.sidebar > div.well").append(issuesHTML); 13 | } 14 | });*/ 15 | }); -------------------------------------------------------------------------------- /docs-demo/js/prettify.js: -------------------------------------------------------------------------------- 1 | var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; 2 | (function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= 3 | [],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), 9 | l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, 10 | q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, 11 | q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, 12 | "");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), 13 | a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} 14 | for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], 18 | "catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], 19 | H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], 20 | J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ 21 | I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), 22 | ["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", 23 | /^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), 24 | ["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", 25 | hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= 26 | !k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p 2 | 3 | 4 | 5 | Leaflet Vector Layers - Jason Sanford 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Fork me on GitHub 24 |
25 |
26 |
27 | Leaflet Vector Layers 28 | 46 |
47 |
48 |
49 | 50 |
51 |
52 |

Downloads

53 |

It's suggested that you download the latest version, but pervious versions are also provided. Check the Changelog to see release notes. 54 |

Current Version

55 |
56 |

The current version of Leaflet Vector Layers supports Leaflet version 0.5.x.

57 |

lvector-1.6.0.zip

58 |
59 |
60 |

Previous Versions

61 | 62 |
63 |
64 |

Leaflet Vector Layers version 1.5.1 supports Leaflet version 0.5.x.

65 |

lvector-1.5.1.zip

66 |
67 |
68 |

Leaflet Vector Layers version 1.5.0 supports Leaflet version 0.5.x.

69 |

lvector-1.5.0.zip

70 |
71 |
72 |

Leaflet Vector Layers version 1.4.0 supports Leaflet version 0.5.x.

73 |

lvector-1.4.0.zip

74 |
75 |
76 |

Leaflet Vector Layers version 1.3.0 supports Leaflet version 0.4.x.

77 |

lvector-1.3.0.zip

78 |
79 |
80 |

Leaflet Vector Layers version 1.2.0 supports Leaflet version 0.3.x.

81 |

lvector-1.2.0.zip

82 |
83 |
84 |

Leaflet Vector Layers version 1.1.1 supports Leaflet version 0.3.x.

85 |

lvector-1.1.1.zip

86 |
87 |
88 |

Leaflet Vector Layers version 1.1.0 supports Leaflet version 0.3.x.

89 |

lvector-1.1.0.zip

90 |
91 |
92 |

Leaflet Vector Layers version 1.0.0 supports Leaflet version 0.3.x.

93 |

lvector-1.0.0.zip

94 |
95 |
96 |
97 |

© Jason Sanford - geojason.info 2013

98 |
99 |
100 |
101 | 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Leaflet Vector Layers - Jason Sanford 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Fork me on GitHub 24 |
25 |
26 |
27 | Leaflet Vector Layers 28 | 46 |
47 |
48 |
49 | 50 |
51 |
52 |

Leaflet Vector Layers

53 |
54 |
55 |

What?

56 |

Leaflet Vector Layers allows you to easily add one or more vector layers from a number of different geo web services to a Leaflet map.

57 |

Currently there's support for ArcGIS Server, Arc2Earth, GeoIQ, CartoDB and GIS Cloud with more planned.

58 |

Check the demos to see the library in action.

59 |
60 |
61 |

How?

62 |

Leaflet Vector Layers works by listening to map events (pan and zoom) and then fetching features within the map bounds after each event. This method works great for data sets with lots of features that you want to interact with, but not load all at once.

63 |

Sound Chatty? Only have a handful of features? You can also load all of the data once, without listening to map pan and zoom events.

64 |
65 |
66 |

Help

67 |

This is an open source project so enhancements and patches are encouraged.

68 |

So grab the code, report bugs and let me know what you think.

69 |

There's also a Leaflet Vector Layers group if you're interested in joining.

70 |

Leaflet Vector Layers on GitHub »

71 |
72 |
73 |
74 |

Features

75 |
76 |
77 |

Multi-provider Support

78 |

Leaflet Vector Layers makes it easy to dynamically pull vector features from a number of different geo web service providers including ArcGIS Server, Arc2Earth, CartoDB and Geocommons.

79 |

If you're interested in, or know of any other providers for this library please let me know.

80 |
81 |
82 |

Easy Popup Templating

83 |

The simplest way to describe features in a Leaflet map is by using the API's Popup.

84 |

Templates can be in the form of a simple string with field names mustache-wrapped ({driver_name}), or a function that returns HTML content for the Popup. The feature's properties are passed to this function so you can do things like analyze data or show charts and graphs.

85 |

For details on Popup templating check the documentation.

86 |
87 |
88 |
89 |
90 |

Dynamic Data Support

91 |

Leaflet Vector Layers makes it easy to visualize live data in a Leaflet map. Just mark the layer as dynamic and auto-updating when you create it and set the interval for how often you'd like to check for updated features.

92 | 93 |

For details on displaying dynamic data check the documentation.

94 |
95 |
96 |

Simple, Powerful Symbology

97 |

Creating effective map styling and symbology is key to getting your message accross to your users.

98 |

With Leaflet Vector Layers you can style your layers with a single symbology, a unique symbol for specific attribute values or set symbols to display if a feature's attributes are within a specific range.

99 |

For details on symbology options check the documentation.

100 |
101 |
102 |
103 |
104 |

Scale Dependent Rendering

105 |

You likely wouldn't want to show lots of features with complex geometies at lower zoom levels. Using the scaleRange option allows you to set the minimum and maximum zoom levels at which a layer is visible.

106 |
107 |
108 |
109 |

© Jason Sanford - geojason.info 2013

110 |
111 |
112 |
113 | 114 | 115 | 116 | 117 | 118 | -------------------------------------------------------------------------------- /lib/closure-compiler/COPYING: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /lib/closure-compiler/README: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009 The Closure Compiler Authors. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | // 18 | // Contents 19 | // 20 | 21 | The Closure Compiler performs checking, instrumentation, and 22 | optimizations on JavaScript code. The purpose of this README is to 23 | explain how to build and run the Closure Compiler. 24 | 25 | The Closure Compiler requires Java 6 or higher. 26 | http://www.java.com/ 27 | 28 | 29 | // 30 | // Building The Closure Compiler 31 | // 32 | 33 | There are three ways to get a Closure Compiler executable. 34 | 35 | 1) Use one we built for you. 36 | 37 | Pre-built Closure binaries can be found at 38 | http://code.google.com/p/closure-compiler/downloads/list 39 | 40 | 41 | 2) Check out the source and build it with Apache Ant. 42 | 43 | First, check out the full source tree of the Closure Compiler. There 44 | are instructions on how to do this at the project site. 45 | http://code.google.com/p/closure-compiler/source/checkout 46 | 47 | Apache Ant is a cross-platform build tool. 48 | http://ant.apache.org/ 49 | 50 | At the root of the source tree, there is an Ant file named 51 | build.xml. To use it, navigate to the same directory and type the 52 | command 53 | 54 | ant jar 55 | 56 | This will produce a jar file called "build/compiler.jar". 57 | 58 | 59 | 3) Check out the source and build it with Eclipse. 60 | 61 | Eclipse is a cross-platform IDE. 62 | http://www.eclipse.org/ 63 | 64 | Under Eclipse's File menu, click "New > Project ..." and create a 65 | "Java Project." You will see an options screen. Give the project a 66 | name, select "Create project from existing source," and choose the 67 | root of the checked-out source tree as the existing directory. Verify 68 | that you are using JRE version 6 or higher. 69 | 70 | Eclipse can use the build.xml file to discover rules. When you 71 | navigate to the build.xml file, you will see all the build rules in 72 | the "Outline" pane. Run the "jar" rule to build the compiler in 73 | build/compiler.jar. 74 | 75 | 76 | // 77 | // Running The Closure Compiler 78 | // 79 | 80 | Once you have the jar binary, running the Closure Compiler is straightforward. 81 | 82 | On the command line, type 83 | 84 | java -jar compiler.jar 85 | 86 | This starts the compiler in interactive mode. Type 87 | 88 | var x = 17 + 25; 89 | 90 | then hit "Enter", then hit "Ctrl-Z" (on Windows) or "Ctrl-D" (on Mac or Linux) 91 | and "Enter" again. The Compiler will respond: 92 | 93 | var x=42; 94 | 95 | The Closure Compiler has many options for reading input from a file, 96 | writing output to a file, checking your code, and running 97 | optimizations. To learn more, type 98 | 99 | java -jar compiler.jar --help 100 | 101 | You can read more detailed documentation about the many flags at 102 | http://code.google.com/closure/compiler/docs/gettingstarted_app.html 103 | 104 | 105 | // 106 | // Compiling Multiple Scripts 107 | // 108 | 109 | If you have multiple scripts, you should compile them all together with 110 | one compile command. 111 | 112 | java -jar compiler.jar --js=in1.js --js=in2.js ... --js_output_file=out.js 113 | 114 | The Closure Compiler will concatenate the files in the order they're 115 | passed at the command line. 116 | 117 | If you need to compile many, many scripts together, you may start to 118 | run into problems with managing dependencies between scripts. You 119 | should check out the Closure Library. It contains functions for 120 | enforcing dependencies between scripts, and a tool called calcdeps.py 121 | that knows how to give scripts to the Closure Compiler in the right 122 | order. 123 | 124 | http://code.google.com/p/closure-library/ 125 | 126 | // 127 | // Licensing 128 | // 129 | 130 | Unless otherwise stated, all source files are licensed under 131 | the Apache License, Version 2.0. 132 | 133 | 134 | ----- 135 | Code under: 136 | src/com/google/javascript/rhino 137 | test/com/google/javascript/rhino 138 | 139 | URL: http://www.mozilla.org/rhino 140 | Version: 1.5R3, with heavy modifications 141 | License: Netscape Public License and MPL / GPL dual license 142 | 143 | Description: A partial copy of Mozilla Rhino. Mozilla Rhino is an 144 | implementation of JavaScript for the JVM. The JavaScript parser and 145 | the parse tree data structures were extracted and modified 146 | significantly for use by Google's JavaScript compiler. 147 | 148 | Local Modifications: The packages have been renamespaced. All code not 149 | relavant to parsing has been removed. A JSDoc parser and static typing 150 | system have been added. 151 | 152 | 153 | ----- 154 | Code in: 155 | lib/libtrunk_rhino_parser_jarjared.jar 156 | 157 | Rhino 158 | URL: http://www.mozilla.org/rhino 159 | Version: Trunk 160 | License: Netscape Public License and MPL / GPL dual license 161 | 162 | Description: Mozilla Rhino is an implementation of JavaScript for the JVM. 163 | 164 | Local Modifications: None. We've used JarJar to renamespace the code 165 | post-compilation. See: 166 | http://code.google.com/p/jarjar/ 167 | 168 | 169 | ----- 170 | Code in: 171 | lib/args4j.jar 172 | 173 | Args4j 174 | URL: https://args4j.dev.java.net/ 175 | Version: 2.0.12 176 | License: MIT 177 | 178 | Description: 179 | args4j is a small Java class library that makes it easy to parse command line 180 | options/arguments in your CUI application. 181 | 182 | Local Modifications: None. 183 | 184 | 185 | ----- 186 | Code in: 187 | lib/guava.jar 188 | 189 | Guava Libraries 190 | URL: http://code.google.com/p/guava-libraries/ 191 | Version: r08 192 | License: Apache License 2.0 193 | 194 | Description: Google's core Java libraries. 195 | 196 | Local Modifications: None. 197 | 198 | 199 | ----- 200 | Code in: 201 | lib/jsr305.jar 202 | 203 | Annotations for software defect detection 204 | URL: http://code.google.com/p/jsr-305/ 205 | Version: svn revision 47 206 | License: BSD License 207 | 208 | Description: Annotations for software defect detection. 209 | 210 | Local Modifications: None. 211 | 212 | 213 | ---- 214 | Code in: 215 | lib/junit.jar 216 | 217 | JUnit 218 | URL: http://sourceforge.net/projects/junit/ 219 | Version: 4.8.2 220 | License: Common Public License 1.0 221 | 222 | Description: A framework for writing and running automated tests in Java. 223 | 224 | Local Modifications: None. 225 | 226 | 227 | --- 228 | Code in: 229 | lib/protobuf-java.jar 230 | 231 | Protocol Buffers 232 | URL: http://code.google.com/p/protobuf/ 233 | Version: 2.3.0 234 | License: New BSD License 235 | 236 | Description: Supporting libraries for protocol buffers, 237 | an encoding of structured data. 238 | 239 | Local Modifications: None 240 | 241 | 242 | --- 243 | Code in: 244 | lib/ant.jar 245 | lib/ant-launcher.jar 246 | 247 | URL: http://ant.apache.org/bindownload.cgi 248 | Version: 1.8.1 249 | License: Apache License 2.0 250 | Description: 251 | Ant is a Java based build tool. In theory it is kind of like "make" 252 | without make's wrinkles and with the full portability of pure java code. 253 | 254 | Local Modifications: None 255 | 256 | 257 | --- 258 | Code in: 259 | lib/json.jar 260 | URL: http://json.org/java/index.html 261 | Version: JSON version 20090211 262 | License: MIT license 263 | Description: 264 | JSON is a set of java files for use in transmitting data in JSON format. 265 | 266 | Local Modifications: None 267 | 268 | --- 269 | Code in: 270 | tools/maven-ant-tasks-2.1.1.jar 271 | URL: http://maven.apache.org 272 | Version 2.1.1 273 | License: Apache License 2.0 274 | Description: 275 | Maven Ant tasks are used to manage dependencies and to install/deploy to 276 | maven repositories. 277 | 278 | Local Modifications: None 279 | -------------------------------------------------------------------------------- /lib/closure-compiler/compiler.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JasonSanford/leaflet-vector-layers/428939b539c91741488ac5c1772758cc74562731/lib/closure-compiler/compiler.jar -------------------------------------------------------------------------------- /src/layer/A2E.js: -------------------------------------------------------------------------------- 1 | lvector.A2E = lvector.AGS.extend({ 2 | initialize: function(options) { 3 | 4 | // Check for required parameters 5 | for (var i = 0, len = this._requiredParams.length; i < len; i++) { 6 | if (!options[this._requiredParams[i]]) { 7 | throw new Error("No \"" + this._requiredParams[i] + "\" parameter found."); 8 | } 9 | } 10 | 11 | // _globalPointer is a string that points to a global function variable 12 | // Features returned from a JSONP request are passed to this function 13 | this._globalPointer = "A2E_" + Math.floor(Math.random() * 100000); 14 | window[this._globalPointer] = this; 15 | 16 | // If the url wasn't passed with a trailing /, add it. 17 | if (options.url.substr(options.url.length - 1, 1) !== "/") { 18 | options.url += "/"; 19 | } 20 | 21 | this._originalOptions = L.Util.extend({}, options); 22 | 23 | if (options.esriOptions) { 24 | if (typeof options.esriOptions == "object") { 25 | L.Util.extend(options, this._convertEsriOptions(options.esriOptions)); 26 | } else { 27 | // Send to function that request JSON from server 28 | // Use a callback to process returned JSON and send back to initialize layer with proper options 29 | this._getEsriOptions(); 30 | return; // Get out of here until we have proper JSON 31 | } 32 | } 33 | 34 | // Extend Layer to create A2E 35 | lvector.Layer.prototype.initialize.call(this, options); 36 | 37 | if (this.options.where) { 38 | this.options.where = encodeURIComponent(this.options.where); 39 | } 40 | 41 | // Create an array to hold the features 42 | this._vectors = []; 43 | 44 | if (this.options.map) { 45 | if (this.options.scaleRange && this.options.scaleRange instanceof Array && this.options.scaleRange.length === 2) { 46 | var z = this.options.map.getZoom(); 47 | var sr = this.options.scaleRange; 48 | this.options.visibleAtScale = (z >= sr[0] && z <= sr[1]); 49 | } 50 | this._show(); 51 | } 52 | 53 | // 54 | // Check for an autoUpdate option and pubnub info to pull live updates 55 | // 56 | if (this.options.autoUpdate && this.options.esriOptions.editFeedInfo) { 57 | //Load the pubnub JavaScript API 58 | this._makeJsonpRequest("http://cdn.pubnub.com/pubnub-3.1.min.js"); 59 | 60 | // Keep checking to see when the library successfully loaded 61 | var me = this; 62 | this._pubNubScriptLoaderInterval = setInterval(function() { 63 | if (window.PUBNUB) { 64 | me._pubNubScriptLoaded(); 65 | } 66 | }, 200); 67 | } 68 | }, 69 | 70 | _pubNubScriptLoaded: function() { 71 | // Stop checking for the pubnub script 72 | clearInterval(this._pubNubScriptLoaderInterval); 73 | 74 | // Initialize pubnub script 75 | this.pubNub = PUBNUB.init({ 76 | subscribe_key: this.options.esriOptions.editFeedInfo.pubnubSubscribeKey, 77 | ssl: false, 78 | origin: "pubsub.pubnub.com" 79 | }); 80 | 81 | var me = this; 82 | 83 | // Subscribe to changes 84 | this.pubNub.subscribe({ 85 | channel: this.options.esriOptions.editFeedInfo.pubnubChannel, 86 | callback: function(message) { 87 | me._getFeatures(); 88 | }, 89 | error: function() { 90 | 91 | } 92 | }); 93 | } 94 | 95 | }); 96 | -------------------------------------------------------------------------------- /src/layer/AGS.js: -------------------------------------------------------------------------------- 1 | lvector.AGS = lvector.EsriJSONLayer.extend({ 2 | initialize: function(options) { 3 | 4 | // Check for required parameters 5 | for (var i = 0, len = this._requiredParams.length; i < len; i++) { 6 | if (!options[this._requiredParams[i]]) { 7 | throw new Error("No \"" + this._requiredParams[i] + "\" parameter found."); 8 | } 9 | } 10 | 11 | // _globalPointer is a string that points to a global function variable 12 | // Features returned from a JSONP request are passed to this function 13 | this._globalPointer = "AGS_" + Math.floor(Math.random() * 100000); 14 | window[this._globalPointer] = this; 15 | 16 | // If the url wasn't passed with a trailing /, add it. 17 | if (options.url.substr(options.url.length - 1, 1) !== "/") { 18 | options.url += "/"; 19 | } 20 | 21 | this._originalOptions = L.Util.extend({}, options); 22 | 23 | if (options.esriOptions) { 24 | if (typeof options.esriOptions == "object") { 25 | L.Util.extend(options, this._convertEsriOptions(options.esriOptions)); 26 | } else { 27 | // Send to function that request JSON from server 28 | // Use a callback to process returned JSON and send back to initialize layer with proper options 29 | this._getEsriOptions(); 30 | return; // Get out of here until we have proper JSON 31 | } 32 | } 33 | 34 | // Extend Layer to create AGS 35 | lvector.Layer.prototype.initialize.call(this, options); 36 | 37 | if (this.options.where) { 38 | this.options.where = encodeURIComponent(this.options.where); 39 | } 40 | 41 | // Create an array to hold the features 42 | this._vectors = []; 43 | 44 | if (this.options.map) { 45 | if (this.options.scaleRange && this.options.scaleRange instanceof Array && this.options.scaleRange.length === 2) { 46 | var z = this.options.map.getZoom(); 47 | var sr = this.options.scaleRange; 48 | this.options.visibleAtScale = (z >= sr[0] && z <= sr[1]); 49 | } 50 | this._show(); 51 | } 52 | }, 53 | 54 | options: { 55 | where: "1=1", 56 | url: null, 57 | useEsriOptions: false 58 | }, 59 | 60 | _requiredParams: ["url"], 61 | 62 | _convertEsriOptions: function(esriOptions) { 63 | var lvectorOptions = {}; 64 | 65 | // Check to see if minScale and maxScale are present, if so conver to Google Vector Layers format 66 | if (!(esriOptions.minScale == undefined || esriOptions.maxScale == undefined)) { 67 | var minScale = this._scaleToLevel(esriOptions.minScale); 68 | var maxScale = this._scaleToLevel(esriOptions.maxScale); 69 | if (maxScale == 0) { 70 | maxScale = 20; 71 | } 72 | lvectorOptions.scaleRange = [minScale, maxScale]; 73 | } 74 | 75 | // Check to see if drawingInfo and rendere are present, if so convert to Google Vector Layers format 76 | if (esriOptions.drawingInfo && esriOptions.drawingInfo.renderer) { 77 | lvectorOptions.symbology = this._renderOptionsToSymbology(esriOptions.drawingInfo.renderer); 78 | } 79 | 80 | // TODO: options.popupTemplate 81 | 82 | return lvectorOptions; 83 | }, 84 | 85 | _getEsriOptions: function() { 86 | this._makeJsonpRequest(this._originalOptions.url + "?f=json&callback=" + this._globalPointer + "._processEsriOptions"); 87 | }, 88 | 89 | _processEsriOptions: function(data) { 90 | var options = this._originalOptions; 91 | options.esriOptions = data; 92 | this.initialize(options); 93 | }, 94 | 95 | _scaleToLevel: function(scale) { 96 | var agsScales = [591657527.591555, 295828763.795777, 147914381.897889, 73957190.948944, 36978595.474472, 18489297.737236, 9244648.868618, 4622324.434309, 2311162.217155, 1155581.108577, 577790.554289, 288895.277144, 144447.638572, 72223.819286, 36111.909643, 18055.954822, 9027.977411, 4513.988705, 2256.994353, 1128.497176, 564.248588, 282.124294]; 97 | if (scale == 0) { 98 | return 0; 99 | } 100 | var level = 0; 101 | for (var i = 0; i < agsScales.length - 1; i++) { 102 | var currentScale = agsScales[i]; 103 | var nextScale = agsScales[i+1]; 104 | if ((scale <= currentScale) && (scale > nextScale)) { 105 | level = i; 106 | break; 107 | } 108 | } 109 | return level; 110 | }, 111 | 112 | _renderOptionsToSymbology: function(renderOptions) { 113 | symbology = {}; 114 | switch (renderOptions.type) { 115 | case "simple": 116 | symbology.type = "single"; 117 | symbology.vectorOptions = this._parseSymbology(renderOptions.symbol); 118 | break; 119 | 120 | case "uniqueValue": 121 | symbology.type = "unique"; 122 | symbology.property = renderOptions.field1; //only support single field uniqueValues rends, rarely see multis anyway 123 | var values = []; 124 | for (var i = 0; i < renderOptions.uniqueValueInfos.length; i++) { 125 | var uvi = renderOptions.uniqueValueInfos[i]; 126 | var value = {}; 127 | value.value = uvi.value; 128 | value.vectorOptions = this._parseSymbology(uvi.symbol); 129 | value.label = uvi.label; //not in lvector spec yet but useful 130 | values.push(value); 131 | } 132 | symbology.values = values; 133 | break; 134 | 135 | case "classBreaks": 136 | symbology.type = "range"; 137 | symbology.property = rend.field; 138 | var ranges = []; 139 | var cbrk = renderOptions.minValue; 140 | for (var i = 0; i < renderOptions.classBreakInfos.length; i++) 141 | { 142 | var cbi = renderOptions.classBreakInfos[i]; 143 | var brk = {}; 144 | brk.range = [cbrk, cbi.classMaxValue]; 145 | cbrk = cbi.classMaxValue; //advance 146 | brk.vectorOptions = this._parseSymbology(cbi.symbol); 147 | brk.label = cbi.label; //not in lvector spec yet but useful 148 | ranges.push(brk); 149 | } 150 | symbology.ranges = ranges; 151 | break; 152 | } 153 | return symbology; 154 | }, 155 | 156 | _parseSymbology: function(symbol) { 157 | var vectorOptions = {}; 158 | switch (symbol.type) { 159 | case "esriSMS": 160 | case "esriPMS": 161 | var customMarker = L.icon({ 162 | iconUrl: "data:" + symbol.contentType + ";base64," + symbol.imageData, 163 | shadowUrl: null, 164 | iconSize: new L.Point(symbol.width, symbol.height), 165 | iconAnchor: new L.Point((symbol.width / 2) + symbol.xoffset, (symbol.height / 2) + symbol.yoffset), 166 | popupAnchor: new L.Point(0, -(symbol.height / 2)) 167 | }); 168 | vectorOptions.icon = customMarker; 169 | break; 170 | 171 | case "esriSLS": 172 | //we can only do solid lines in GM (true in latest build?) 173 | vectorOptions.weight = symbol.width; 174 | vectorOptions.color = this._parseColor(symbol.color); 175 | vectorOptions.opacity = this._parseAlpha(symbol.color[3]); 176 | break; 177 | 178 | case "esriSFS": 179 | //solid or hollow only 180 | if (symbol.outline) { 181 | vectorOptions.weight = symbol.outline.width; 182 | vectorOptions.color = this._parseColor(symbol.outline.color); 183 | vectorOptions.opacity = this._parseAlpha(symbol.outline.color[3]); 184 | } else { 185 | vectorOptions.weight = 0; 186 | vectorOptions.color = "#000000"; 187 | vectorOptions.opacity = 0.0; 188 | } 189 | if (symbol.style != "esriSFSNull") { 190 | vectorOptions.fillColor = this._parseColor(symbol.color); 191 | vectorOptions.fillOpacity = this._parseAlpha(symbol.color[3]); 192 | } else { 193 | vectorOptions.fillColor = "#000000"; 194 | vectorOptions.fillOpacity = 0.0; 195 | } 196 | break; 197 | } 198 | return vectorOptions; 199 | }, 200 | 201 | _parseColor: function(color) { 202 | red = this._normalize(color[0]); 203 | green = this._normalize(color[1]); 204 | blue = this._normalize(color[2]); 205 | return '#' + this._pad(red.toString(16)) + this._pad(green.toString(16)) + this._pad(blue.toString(16)); 206 | }, 207 | 208 | _normalize: function(color) { 209 | return (color < 1.0 && color > 0.0) ? Math.floor(color * 255) : color; 210 | }, 211 | 212 | _pad: function(s) { 213 | return s.length > 1 ? s.toUpperCase() : "0" + s.toUpperCase(); 214 | }, 215 | 216 | _parseAlpha: function(a) { 217 | // 0-255 -> 0-1.0 218 | return (a / 255); 219 | }, 220 | 221 | _getFeatures: function() { 222 | // Build URL 223 | var url = this.options.url + "query" + // Query this layer 224 | "?returnGeometry=true" + // Of course we want geometry 225 | "&outSR=4326" + // receive geometry in WGS 84 Lat/Lng. 226 | "&f=json" + // Wish it were GeoJSON, but we'll take it 227 | "&outFields=" + this.options.fields + // Please return the following fields 228 | "&where=" + this.options.where + // By default return all feature (1=1) but could pass SQL statement (value<90) 229 | "&callback=" + this._globalPointer + "._processFeatures"; // Need this for JSONP 230 | if (!this.options.showAll) { 231 | url += "&inSR=4326" + // request geometry in WGS 84 Lat/Lng. 232 | "&spatialRel=esriSpatialRelIntersects" + // Find stuff that intersects this envelope 233 | "&geometryType=esriGeometryEnvelope" + // Our "geometry" url param will be an envelope 234 | "&geometry=" + this.options.map.getBounds().toBBoxString(); // Build envelope geometry 235 | } 236 | 237 | // JSONP request 238 | this._makeJsonpRequest(url); 239 | } 240 | 241 | }); 242 | -------------------------------------------------------------------------------- /src/layer/CartoDB.js: -------------------------------------------------------------------------------- 1 | lvector.CartoDB = lvector.GeoJSONLayer.extend({ 2 | initialize: function(options) { 3 | 4 | // Check for required parameters 5 | for (var i = 0, len = this._requiredParams.length; i < len; i++) { 6 | if (!options[this._requiredParams[i]]) { 7 | throw new Error("No \"" + this._requiredParams[i] + "\" parameter found."); 8 | } 9 | } 10 | 11 | // Extend Layer to create CartoDB 12 | lvector.Layer.prototype.initialize.call(this, options); 13 | 14 | // _globalPointer is a string that points to a global function variable 15 | // Features returned from a JSONP request are passed to this function 16 | this._globalPointer = "CartoDB_" + Math.floor(Math.random() * 100000); 17 | window[this._globalPointer] = this; 18 | 19 | // Create an array to hold the features 20 | this._vectors = []; 21 | 22 | if (this.options.map) { 23 | if (this.options.scaleRange && this.options.scaleRange instanceof Array && this.options.scaleRange.length === 2) { 24 | var z = this.options.map.getZoom(); 25 | var sr = this.options.scaleRange; 26 | this.options.visibleAtScale = (z >= sr[0] && z <= sr[1]); 27 | } 28 | this._show(); 29 | } 30 | }, 31 | 32 | options: { 33 | version: 1, 34 | user: null, 35 | table: null, 36 | fields: "*", 37 | where: null, 38 | limit: null, 39 | key: null, 40 | uniqueField: "cartodb_id" 41 | }, 42 | 43 | _requiredParams: ["user", "table"], 44 | 45 | _getFeatures: function() { 46 | // Build Query 47 | var where = this.options.where || ""; 48 | if (!this.options.showAll) { 49 | var bounds = this.options.map.getBounds(); 50 | var sw = bounds.getSouthWest(); 51 | var ne = bounds.getNorthEast(); 52 | var tableCount = this.options.table.split(",").length; 53 | for (var i = 0; i < tableCount; i++) { 54 | where += (where.length ? " AND " : "") + (tableCount > 1 ? this.options.table.split(",")[i].split(".")[0] + ".the_geom" : "the_geom") + " && st_setsrid(st_makebox2d(st_point(" + sw.lng + "," + sw.lat + "),st_point(" + ne.lng + "," + ne.lat + ")),4326)"; 55 | } 56 | } 57 | if (this.options.limit) { 58 | where += (where.length ? " " : "") + "limit " + this.options.limit; 59 | } 60 | where = (where.length ? " " + where : ""); 61 | var query = "SELECT " + this.options.fields + " FROM " + this.options.table + (where.length ? " WHERE " + where : ""); 62 | 63 | // Build URL 64 | var url = "http://" + this.options.user + ".cartodb.com/api/v" + this.options.version + "/sql" + // The API entry point 65 | "?q=" + encodeURIComponent(query) + // The SQL statement 66 | "&format=geojson" + // GeoJSON please 67 | "&callback=" + this._globalPointer + "._processFeatures"; // Need this for JSONP 68 | if (this.options.apiKey) { 69 | url += "&api_key=" + this.options.apiKey; 70 | } 71 | // JSONP request 72 | this._makeJsonpRequest(url); 73 | } 74 | 75 | }); 76 | -------------------------------------------------------------------------------- /src/layer/EsriJSONLayer.js: -------------------------------------------------------------------------------- 1 | // 2 | // Extend Layer to support EsriJSON geometry parsing 3 | // 4 | lvector.EsriJSONLayer = lvector.Layer.extend({ 5 | // 6 | // Turn EsriJSON into Leaflet vectors 7 | // 8 | _esriJsonGeometryToLeaflet: function(geometry, opts) { 9 | // 10 | // Create a variable for a single vector and for multi part vectors. 11 | // 12 | var vector, vectors; 13 | 14 | if (geometry.x && geometry.y) { 15 | // 16 | // A Point 17 | // 18 | vector = new L.Marker(new L.LatLng(geometry.y, geometry.x), opts); 19 | } else if (geometry.points) { 20 | // 21 | // A MultiPoint 22 | // 23 | vectors = []; 24 | for (var i = 0, len = geometry.points.length; i < len; i++) { 25 | vectors.push(new L.Marker(new L.LatLng(geometry.points[i].y, geometry.points[i].x), opts)); 26 | } 27 | } else if (geometry.paths) { 28 | if (geometry.paths.length > 1) { 29 | // 30 | // A MultiLineString 31 | // 32 | vectors = []; 33 | for (var i = 0, len = geometry.paths.length; i < len; i++) { 34 | var latlngs = []; 35 | for (var i2 = 0, len2 = geometry.paths[i].length; i2 < len2; i2++) { 36 | latlngs.push(new L.LatLng(geometry.paths[i][i2][1], geometry.paths[i][i2][0])); 37 | } 38 | vectors.push(new L.Polyline(latlngs, opts)); 39 | } 40 | } else { 41 | // 42 | // A LineString 43 | // 44 | var latlngs = []; 45 | for (var i = 0, len = geometry.paths[0].length; i < len; i++) { 46 | latlngs.push(new L.LatLng(geometry.paths[0][i][1], geometry.paths[0][i][0])); 47 | } 48 | vector = new L.Polyline(latlngs, opts); 49 | } 50 | } else if (geometry.rings) { 51 | if (geometry.rings.length > 1) { 52 | // 53 | // A MultiPolygon 54 | // 55 | vectors = []; 56 | for (var i = 0, len = geometry.rings.length; i < len; i++) { 57 | var latlngss = []; 58 | var latlngs = []; 59 | for (var i2 = 0, len2 = geometry.rings[i].length; i2 < len2; i2++) { 60 | latlngs.push(new L.LatLng(geometry.rings[i][i2][1], geometry.rings[i][i2][0])); 61 | } 62 | latlngss.push(latlngs); 63 | vectors.push(new L.Polygon(latlngss, opts)); 64 | } 65 | } else { 66 | // 67 | // A Polygon 68 | // 69 | var latlngss = []; 70 | var latlngs = []; 71 | for (var i = 0, len = geometry.rings[0].length; i < len; i++) { 72 | latlngs.push(new L.LatLng(geometry.rings[0][i][1], geometry.rings[0][i][0])); 73 | } 74 | latlngss.push(latlngs); 75 | vector = new L.Polygon(latlngss, opts); 76 | } 77 | } 78 | return vector || vectors; 79 | } 80 | }); 81 | -------------------------------------------------------------------------------- /src/layer/GISCloud.js: -------------------------------------------------------------------------------- 1 | lvector.GISCloud = lvector.GeoJSONLayer.extend({ 2 | initialize: function(options) { 3 | 4 | // Check for required parameters 5 | for (var i = 0, len = this._requiredParams.length; i < len; i++) { 6 | if (!options[this._requiredParams[i]]) { 7 | throw new Error("No \"" + this._requiredParams[i] + "\" parameter found."); 8 | } 9 | } 10 | 11 | // Extend Layer to create GISCloud 12 | lvector.Layer.prototype.initialize.call(this, options); 13 | 14 | // _globalPointer is a string that points to a global function variable 15 | // Features returned from a JSONP request are passed to this function 16 | this._globalPointer = "GISCloud_" + Math.floor(Math.random() * 100000); 17 | window[this._globalPointer] = this; 18 | 19 | // Create an array to hold the features 20 | this._vectors = []; 21 | 22 | 23 | if (this.options.map) { 24 | if (this.options.scaleRange && this.options.scaleRange instanceof Array && this.options.scaleRange.length === 2) { 25 | var z = this.options.map.getZoom(); 26 | var sr = this.options.scaleRange; 27 | this.options.visibleAtScale = (z >= sr[0] && z <= sr[1]); 28 | } 29 | this._show(); 30 | } 31 | }, 32 | 33 | options: { 34 | mapID: null, 35 | layerID: null, 36 | uniqueField: "id" 37 | }, 38 | 39 | _requiredParams: ["mapID", "layerID"], 40 | 41 | _getFeatures: function() { 42 | 43 | // Build URL 44 | var url = "http://api.giscloud.com/1/maps/" + this.options.mapID + // GISCloud Map ID 45 | "/layers/" + this.options.layerID + 46 | "/features.json?" + // JSON please 47 | "geometry=geojson" + // Return GeoJSON formatted data 48 | "&epsg=4326" + // Using Lat Lng for bounding box units 49 | "&callback=" + this._globalPointer + "._processFeatures"; // Need this for JSONP 50 | if (!this.options.showAll) { 51 | url += "&bounds=" + this.options.map.getBounds().toBBoxString(); // Build bbox geometry 52 | } 53 | if (this.options.where) { 54 | url += "&where=" + encodeURIComponent(this.options.where); 55 | } 56 | 57 | // JSONP request 58 | this._makeJsonpRequest(url); 59 | 60 | } 61 | }); 62 | -------------------------------------------------------------------------------- /src/layer/GeoIQ.js: -------------------------------------------------------------------------------- 1 | lvector.GeoIQ = lvector.GeoJSONLayer.extend({ 2 | initialize: function(options) { 3 | 4 | // Check for required parameters 5 | for (var i = 0, len = this._requiredParams.length; i < len; i++) { 6 | if (!options[this._requiredParams[i]]) { 7 | throw new Error("No \"" + this._requiredParams[i] + "\" parameter found."); 8 | } 9 | } 10 | 11 | // Extend Layer to create GeoIQ 12 | lvector.Layer.prototype.initialize.call(this, options); 13 | 14 | // _globalPointer is a string that points to a global function variable 15 | // Features returned from a JSONP request are passed to this function 16 | this._globalPointer = "GeoIQ_" + Math.floor(Math.random() * 100000); 17 | window[this._globalPointer] = this; 18 | 19 | // Create an array to hold the features 20 | this._vectors = []; 21 | 22 | 23 | if (this.options.map) { 24 | if (this.options.scaleRange && this.options.scaleRange instanceof Array && this.options.scaleRange.length === 2) { 25 | var z = this.options.map.getZoom(); 26 | var sr = this.options.scaleRange; 27 | this.options.visibleAtScale = (z >= sr[0] && z <= sr[1]); 28 | } 29 | this._show(); 30 | } 31 | }, 32 | 33 | options: { 34 | dataset: null 35 | }, 36 | 37 | _requiredParams: ["dataset"], 38 | 39 | _getFeatures: function() { 40 | // Build URL 41 | var url = "http://geocommons.com/datasets/" + this.options.dataset + // Geocommons dataset ID 42 | "/features.json?" + // JSON please 43 | "geojson=1" + // Return GeoJSON formatted data 44 | "&callback=" + this._globalPointer + "._processFeatures" + // Need this for JSONP 45 | "&limit=999"; // Don't limit our results 46 | if (!this.options.showAll) { 47 | url += "&bbox=" + this.options.map.getBounds().toBBoxString() + // Build bbox geometry 48 | "&intersect=full"; // Return features that intersect this bbox, not just fully contained 49 | } 50 | 51 | // JSONP request 52 | this._makeJsonpRequest(url); 53 | 54 | } 55 | 56 | }); 57 | -------------------------------------------------------------------------------- /src/layer/GeoJSONLayer.js: -------------------------------------------------------------------------------- 1 | // 2 | // Extend Layer to support GeoJSON geometry parsing 3 | // 4 | lvector.GeoJSONLayer = lvector.Layer.extend({ 5 | // 6 | // Convert GeoJSON to Leaflet vectors 7 | // 8 | _geoJsonGeometryToLeaflet: function(geometry, opts) { 9 | // 10 | // Create a variable for a single vector and for multi part vectors. 11 | // 12 | var vector, vectors; 13 | 14 | switch (geometry.type) { 15 | case "Point": 16 | if (opts.circleMarker) { 17 | vector = new L.CircleMarker(new L.LatLng(geometry.coordinates[1], geometry.coordinates[0]), opts); 18 | } 19 | else { 20 | vector = new L.Marker(new L.LatLng(geometry.coordinates[1], geometry.coordinates[0]), opts); 21 | } 22 | break; 23 | 24 | case "MultiPoint": 25 | vectors = []; 26 | for (var i = 0, len = geometry.coordinates.length; i < len; i++) { 27 | vectors.push(new L.Marker(new L.LatLng(geometry.coordinates[i][1], geometry.coordinates[i][0]), opts)); 28 | } 29 | break; 30 | 31 | case "LineString": 32 | var latlngs = []; 33 | for (var i = 0, len = geometry.coordinates.length; i < len; i++) { 34 | latlngs.push(new L.LatLng(geometry.coordinates[i][1], geometry.coordinates[i][0])); 35 | } 36 | vector = new L.Polyline(latlngs, opts); 37 | break; 38 | 39 | case "MultiLineString": 40 | vectors = []; 41 | for (var i = 0, len = geometry.coordinates.length; i < len; i++){ 42 | var latlngs = []; 43 | for (var i2 = 0, len2 = geometry.coordinates[i].length; i2 < len2; i2++){ 44 | latlngs.push(new L.LatLng(geometry.coordinates[i][i2][1], geometry.coordinates[i][i2][0])); 45 | } 46 | vectors.push(new L.Polyline(latlngs, opts)); 47 | } 48 | break; 49 | 50 | case "Polygon": 51 | var latlngss = []; 52 | for (var i = 0, len = geometry.coordinates.length; i < len; i++) { 53 | var latlngs = []; 54 | for (var i2 = 0, len2 = geometry.coordinates[i].length; i2 < len2; i2++) { 55 | latlngs.push(new L.LatLng(geometry.coordinates[i][i2][1], geometry.coordinates[i][i2][0])); 56 | } 57 | latlngss.push(latlngs); 58 | } 59 | vector = new L.Polygon(latlngss, opts); 60 | break; 61 | 62 | case "MultiPolygon": 63 | vectors = []; 64 | for (var i = 0, len = geometry.coordinates.length; i < len; i++) { 65 | latlngss = []; 66 | for (var i2 = 0, len2 = geometry.coordinates[i].length; i2 < len2; i2++) { 67 | var latlngs = []; 68 | for (var i3 = 0, len3 = geometry.coordinates[i][i2].length; i3 < len3; i3++) { 69 | latlngs.push(new L.LatLng(geometry.coordinates[i][i2][i3][1], geometry.coordinates[i][i2][i3][0])); 70 | } 71 | latlngss.push(latlngs); 72 | } 73 | vectors.push(new L.Polygon(latlngss, opts)); 74 | } 75 | break; 76 | 77 | case "GeometryCollection": 78 | vectors = []; 79 | for (var i = 0, len = geometry.geometries.length; i < len; i++) { 80 | vectors.push(this._geoJsonGeometryToLeaflet(geometry.geometries[i], opts)); 81 | } 82 | break; 83 | } 84 | return vector || vectors; 85 | } 86 | }); 87 | -------------------------------------------------------------------------------- /src/layer/GitSpatial.js: -------------------------------------------------------------------------------- 1 | lvector.GitSpatial = lvector.GeoJSONLayer.extend({ 2 | initialize: function(options) { 3 | 4 | // Check for required parameters 5 | for (var i = 0, len = this._requiredParams.length; i < len; i++) { 6 | if (!options[this._requiredParams[i]]) { 7 | throw new Error("No \"" + this._requiredParams[i] + "\" parameter found."); 8 | } 9 | } 10 | 11 | // Extend Layer to create GitSpatial 12 | lvector.Layer.prototype.initialize.call(this, options); 13 | 14 | // _globalPointer is a string that points to a global function variable 15 | // Features returned from a JSONP request are passed to this function 16 | this._globalPointer = "GitSpatial_" + Math.floor(Math.random() * 100000); 17 | window[this._globalPointer] = this; 18 | 19 | // Create an array to hold the features 20 | this._vectors = []; 21 | 22 | 23 | if (this.options.map) { 24 | if (this.options.scaleRange && this.options.scaleRange instanceof Array && this.options.scaleRange.length === 2) { 25 | var z = this.options.map.getZoom(); 26 | var sr = this.options.scaleRange; 27 | this.options.visibleAtScale = (z >= sr[0] && z <= sr[1]); 28 | } 29 | this._show(); 30 | } 31 | }, 32 | 33 | options: { 34 | 35 | }, 36 | 37 | _requiredParams: ["user", "repo", "featureSet"], 38 | 39 | _getFeatures: function() { 40 | // Build URL 41 | var url = "http://gitspatial.com/api/v1/" + this.options.user + // The GitHub user name 42 | "/" + this.options.repo + // The GitHub repo name 43 | "/" + this.options.featureSet + // The GitSpatial feature set name 44 | "?callback=" + this._globalPointer + "._processFeatures"; // Need this for JSONP 45 | if (!this.options.showAll) { 46 | url += "&bbox=" + this.options.map.getBounds().toBBoxString(); // Build bbox geometry 47 | } 48 | 49 | // JSONP request 50 | this._makeJsonpRequest(url); 51 | 52 | } 53 | 54 | }); 55 | -------------------------------------------------------------------------------- /src/layer/PRWSF.js: -------------------------------------------------------------------------------- 1 | lvector.PRWSF = lvector.GeoJSONLayer.extend({ 2 | initialize: function(options) { 3 | 4 | // Check for required parameters 5 | for (var i = 0, len = this._requiredParams.length; i < len; i++) { 6 | if (!options[this._requiredParams[i]]) { 7 | throw new Error("No \"" + this._requiredParams[i] + "\" parameter found."); 8 | } 9 | } 10 | 11 | // If the url wasn't passed with a trailing /, add it. 12 | if (options.url.substr(options.url.length - 1, 1) !== "/") { 13 | options.url += "/"; 14 | } 15 | 16 | // Extend Layer to create PRWSF 17 | lvector.Layer.prototype.initialize.call(this, options); 18 | 19 | // _globalPointer is a string that points to a global function variable 20 | // Features returned from a JSONP request are passed to this function 21 | this._globalPointer = "PRWSF_" + Math.floor(Math.random() * 100000); 22 | window[this._globalPointer] = this; 23 | 24 | // Create an array to hold the features 25 | this._vectors = []; 26 | 27 | 28 | if (this.options.map) { 29 | if (this.options.scaleRange && this.options.scaleRange instanceof Array && this.options.scaleRange.length === 2) { 30 | var z = this.options.map.getZoom(); 31 | var sr = this.options.scaleRange; 32 | this.options.visibleAtScale = (z >= sr[0] && z <= sr[1]); 33 | } 34 | this._show(); 35 | } 36 | }, 37 | 38 | options: { 39 | geotable: null, 40 | srid: null, 41 | geomFieldName: "the_geom", 42 | geomPrecision: "", 43 | fields: "", 44 | where: null, 45 | limit: null, 46 | uniqueField: null 47 | }, 48 | 49 | _requiredParams: ["url", "geotable"], 50 | 51 | _getFeatures: function() { 52 | 53 | // Build Query 54 | var where = this.options.where || ""; 55 | if (!this.options.showAll) { 56 | var bounds = this.options.map.getBounds(); 57 | var sw = bounds.getSouthWest(); 58 | var ne = bounds.getNorthEast(); 59 | where += where.length ? " AND " : ""; 60 | if (this.options.srid) { 61 | where += this.options.geomFieldName + " && transform(st_setsrid(st_makebox2d(st_point(" + sw.lng + "," + sw.lat + "),st_point(" + ne.lng + "," + ne.lat + ")),4326)," + this.options.srid + ")"; 62 | } else { 63 | where += "transform(" + this.options.geomFieldName + ",4326) && st_setsrid(st_makebox2d(st_point(" + sw.lng + "," + sw.lat + "),st_point(" + ne.lng + "," + ne.lat + ")),4326)"; 64 | } 65 | } 66 | 67 | // Limit returned features 68 | if (this.options.limit) { 69 | where += (where.length ? " " : "") + "limit " + this.options.limit; 70 | } 71 | 72 | // Build fields 73 | var fields = (this.options.fields.length ? this.options.fields + "," : "") + "st_asgeojson(transform(" + this.options.geomFieldName + ",4326)" + (this.options.geomPrecision ? "," + this.options.geomPrecision : "") + ") as geojson"; 74 | 75 | // Build URL 76 | var url = this.options.url + "v1/ws_geo_attributequery.php" + // The attribute query service 77 | "?parameters=" + encodeURIComponent(where) + // The SQL where statement 78 | "&geotable=" + this.options.geotable + // The table name 79 | "&fields=" + encodeURIComponent(fields) + // 80 | "&format=json" + // JSON please 81 | "&callback=" + this._globalPointer + "._processFeatures"; // Need this for JSONP 82 | 83 | // JSONP request 84 | this._makeJsonpRequest(url); 85 | } 86 | 87 | }); 88 | -------------------------------------------------------------------------------- /src/lvector.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve Copyright (c) 2013 - 2015, Jason Sanford 3 | * Leaflet Vector Layers is a library for showing geometry objects 4 | * from multiple geoweb services in a Leaflet map 5 | */ 6 | 7 | /*global lvector */ 8 | 9 | (function (root) { 10 | root.lvector = { 11 | VERSION: '1.6.0', 12 | 13 | noConflict: function () { 14 | root.lvector = this._originallvector; 15 | return this; 16 | }, 17 | 18 | _originallvector: root.lvector 19 | }; 20 | }(this)); 21 | -------------------------------------------------------------------------------- /tips-tricks/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Leaflet Vector Layers - Jason Sanford 6 | 7 | 8 | 9 | 10 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Fork me on GitHub 24 |
25 |
26 |
27 | Leaflet Vector Layers 28 | 46 |
47 |
48 |
49 | 50 |
51 |
52 |

Tips & Tricks

53 |

CartoDB

54 | 55 |

Simplify

56 |

Use PostGIS' simplify function to simplify complex geometries in your database. This is especially helpful at lower zoom levels where high numbers of vertices aren't necessary.

57 | 58 |

the_geom

59 |

When performing spatial functions like the simplify example above, be sure that the geometry returned is always in a field named the_geom. This is the field name that is necessary to create GeoJSON (what Leaflet Vector Layers uses for geometry).

60 |
61 |

© Jason Sanford - geojason.info 2013

62 |
63 |
64 |
65 | 66 | 67 | 68 | 69 | 70 | --------------------------------------------------------------------------------