├── .gitignore ├── LICENSE.md ├── README.md ├── keymaps └── geojson-preview.cson ├── lib ├── geojson-preview-view.coffee └── geojson-preview.coffee ├── menus └── geojson-preview.cson ├── package.json ├── spec ├── geojson-preview-spec.coffee └── geojson-preview-view-spec.coffee ├── stylesheets ├── geojson-preview.less └── leaflet.css └── test.geojson /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | npm-debug.log 3 | node_modules 4 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GeoJSON Preview 2 | 3 | Lets you preview .geojson files in your editor on a leaflet map. 4 | 5 | Show the geojson on a map to the right of the current editor using `ctrl-shift-g` 6 | 7 | ![geojson-preview](https://f.cloud.github.com/assets/26278/2306038/b8feb124-a277-11e3-9635-e882eaf8c5ce.gif) 8 | -------------------------------------------------------------------------------- /keymaps/geojson-preview.cson: -------------------------------------------------------------------------------- 1 | # Keybindings require three things to be fully defined: A selector that is 2 | # matched against the focused element, the keystroke and the command to 3 | # execute. 4 | # 5 | # Below is a basic keybinding which registers on all platforms by applying to 6 | # the root workspace element. 7 | 8 | # For more detailed documentation see 9 | # https://atom.io/docs/latest/advanced/keymaps 10 | '.atom-workspace': 11 | 'ctrl-G': 'geojson-preview:show' 12 | -------------------------------------------------------------------------------- /lib/geojson-preview-view.coffee: -------------------------------------------------------------------------------- 1 | path = require 'path' 2 | {$, $$$, EditorView, ScrollView} = require 'atom' 3 | _ = require 'underscore-plus' 4 | {File} = require 'pathwatcher' 5 | geojsonhint = require 'geojsonhint' 6 | require 'mapbox.js' 7 | 8 | module.exports = 9 | class GeoJSONPreviewView extends ScrollView 10 | atom.deserializers.add(this) 11 | 12 | @deserialize: ({filePath}) -> 13 | new GeoJSONPreviewView(filePath) 14 | 15 | @content: -> 16 | @div class: 'geojson-preview native-key-bindings', tabindex: -1 17 | 18 | constructor: (filePath) -> 19 | super 20 | @file = new File(filePath) 21 | @handleEvents() 22 | 23 | serialize: -> 24 | deserializer: 'GeoJSONPreviewView' 25 | filePath: @getPath() 26 | 27 | destroy: -> 28 | @unsubscribe() 29 | 30 | handleEvents: -> 31 | @subscribe atom.syntax, 'grammar-added grammar-updated', _.debounce((=> @renderGeoJSON()), 250) 32 | @subscribe this, 'core:move-up', => @scrollUp() 33 | @subscribe this, 'core:move-down', => @scrollDown() 34 | @subscribe @file, 'contents-changed', => 35 | @renderGeoJSON() 36 | pane = atom.workspace.paneForUri(@getUri()) 37 | if pane? and pane isnt atom.workspace.getActivePane() 38 | pane.activateItem(this) 39 | 40 | renderGeoJSON: -> 41 | @showLoading() 42 | @file.read().then (contents) => 43 | errors = geojsonhint.hint(contents) 44 | if errors.length > 0 45 | @showError(errors) 46 | else 47 | @html $$$ -> 48 | @div class: 'geojson-preview-map', '' 49 | window.L.Icon.Default.imagePath = 'http:' + window.L.Icon.Default.imagePath 50 | @map = L.mapbox.map($(@html).find('.geojson-preview-map')[0], 'mickt.hdof2a3d').setView([0, 0],4); 51 | layer = L.mapbox.featureLayer(JSON.parse(contents)).addTo(@map); 52 | @map.fitBounds(layer.getBounds()) 53 | 54 | getTitle: -> 55 | "#{path.basename(@getPath())} Preview" 56 | 57 | getUri: -> 58 | "geojson-preview://#{@getPath()}" 59 | 60 | getPath: -> 61 | @file.getPath() 62 | 63 | showError: (result) -> 64 | failureMessage = result?.message 65 | 66 | @html $$$ -> 67 | @h2 'Previewing GeoJSON Failed' 68 | @h3 failureMessage if failureMessage? 69 | 70 | showLoading: -> 71 | @html $$$ -> 72 | @div class: 'geojson-spinner', 'Loading Map...' 73 | 74 | createMap: (geojson) => 75 | html = $("
") 76 | html 77 | -------------------------------------------------------------------------------- /lib/geojson-preview.coffee: -------------------------------------------------------------------------------- 1 | url = require 'url' 2 | fs = require 'fs-plus' 3 | 4 | GeoJSONPreviewView = require './geojson-preview-view' 5 | 6 | module.exports = 7 | 8 | activate: -> 9 | atom.workspaceView.command 'geojson-preview:show', => 10 | @show() 11 | 12 | atom.workspace.registerOpener (uriToOpen) -> 13 | {protocol, pathname} = url.parse(uriToOpen) 14 | pathname = decodeURI(pathname) if pathname 15 | return unless protocol is 'geojson-preview:' and fs.isFileSync(pathname) 16 | new GeoJSONPreviewView(pathname) 17 | 18 | show: -> 19 | editor = atom.workspace.getActiveEditor() 20 | return unless editor? 21 | 22 | #unless editor.getGrammar().scopeName is "source.gfm" 23 | # console.warn("Cannot render geojson for '#{editor.getUri() ? 'untitled'}'") 24 | # return 25 | 26 | unless fs.isFileSync(editor.getPath()) 27 | console.warn("Cannot render geojson for '#{editor.getPath() ? 'untitled'}'") 28 | return 29 | 30 | previousActivePane = atom.workspace.getActivePane() 31 | uri = "geojson-preview://#{editor.getPath()}" 32 | atom.workspace.open(uri, split: 'right', searchAllPanes: true).done (geoJSONPreviewView) -> 33 | if geoJSONPreviewView instanceof GeoJSONPreviewView 34 | geoJSONPreviewView.renderGeoJSON() 35 | previousActivePane.activate() 36 | -------------------------------------------------------------------------------- /menus/geojson-preview.cson: -------------------------------------------------------------------------------- 1 | # See https://atom.io/docs/latest/creating-a-package#menus for more details 2 | 'context-menu': 3 | '.overlayer': 4 | 'GeoJSON': 'geojson-preview:show' 5 | 6 | 'menu': [ 7 | { 8 | 'label': 'Packages' 9 | 'submenu': [ 10 | 'label': 'GeoJSON' 11 | 'submenu': [ 12 | { 'label': 'Preview Buffer', 'command': 'geojson-preview:show' } 13 | ] 14 | ] 15 | } 16 | ] 17 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "geojson-preview", 3 | "main": "./lib/geojson-preview", 4 | "version": "0.4.0", 5 | "description": "Preview geojson file in your text editor!", 6 | "keywords": [ 7 | "geojson", 8 | "preview", 9 | "json", 10 | "map" 11 | ], 12 | "repository": "https://github.com/mick/geojson-preview", 13 | "license": "MIT", 14 | "engines": { 15 | "atom": ">0.50.0" 16 | }, 17 | "dependencies": { 18 | "mapbox.js": "1.6.x", 19 | "geojsonhint": "0.2.x", 20 | "fs-plus": "2.x", 21 | "pathwatcher": "^2.0.10", 22 | "underscore-plus": "1.x" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /spec/geojson-preview-spec.coffee: -------------------------------------------------------------------------------- 1 | GeoJSONPreview = require '../lib/geojson-preview' 2 | 3 | # Use the command `window:run-package-specs` (cmd-alt-ctrl-p) to run specs. 4 | # 5 | # To run a specific `it` or `describe` block add an `f` to the front (e.g. `fit` 6 | # or `fdescribe`). Remove the `f` to unfocus the block. 7 | 8 | describe "GeoJSONPreview", -> 9 | activationPromise = null 10 | 11 | beforeEach -> 12 | atom.workspaceView = new WorkspaceView 13 | activationPromise = atom.packages.activatePackage('geojsonPreview') 14 | 15 | describe "when the geojson-preview:toggle event is triggered", -> 16 | it "attaches and then detaches the view", -> 17 | expect(atom.workspaceView.find('.geojson-preview')).not.toExist() 18 | 19 | # This is an activation event, triggering it will cause the package to be 20 | # activated. 21 | atom.workspaceView.trigger 'geojson-preview:toggle' 22 | 23 | waitsForPromise -> 24 | activationPromise 25 | 26 | runs -> 27 | expect(atom.workspaceView.find('.geojson-preview')).toExist() 28 | atom.workspaceView.trigger 'geojson-preview:toggle' 29 | expect(atom.workspaceView.find('.geojson-preview')).not.toExist() 30 | -------------------------------------------------------------------------------- /spec/geojson-preview-view-spec.coffee: -------------------------------------------------------------------------------- 1 | GeoJSONPreviewView = require '../lib/geojson-preview-view' 2 | {WorkspaceView} = require 'atom' 3 | 4 | describe "GeoJSONPreviewView", -> 5 | it "has one valid test", -> 6 | expect("life").toBe "easy" 7 | -------------------------------------------------------------------------------- /stylesheets/geojson-preview.less: -------------------------------------------------------------------------------- 1 | // The ui-variables file is provided by base themes provided by Atom. 2 | // 3 | // See https://github.com/atom/atom-dark-ui/blob/master/stylesheets/ui-variables.less 4 | // for a full listing of what's available. 5 | @import "ui-variables"; 6 | 7 | .geojson-preview { 8 | background:#000; 9 | } 10 | .geojson-preview-map { 11 | width:100%; 12 | height:100%; 13 | } 14 | -------------------------------------------------------------------------------- /stylesheets/leaflet.css: -------------------------------------------------------------------------------- 1 | /* required styles */ 2 | 3 | .leaflet-map-pane, 4 | .leaflet-tile, 5 | .leaflet-marker-icon, 6 | .leaflet-marker-shadow, 7 | .leaflet-tile-pane, 8 | .leaflet-tile-container, 9 | .leaflet-overlay-pane, 10 | .leaflet-shadow-pane, 11 | .leaflet-marker-pane, 12 | .leaflet-popup-pane, 13 | .leaflet-overlay-pane svg, 14 | .leaflet-zoom-box, 15 | .leaflet-image-layer, 16 | .leaflet-layer { 17 | position: absolute; 18 | left: 0; 19 | top: 0; 20 | } 21 | .leaflet-container { 22 | overflow: hidden; 23 | -ms-touch-action: none; 24 | } 25 | .leaflet-tile, 26 | .leaflet-marker-icon, 27 | .leaflet-marker-shadow { 28 | -webkit-user-select: none; 29 | -moz-user-select: none; 30 | user-select: none; 31 | -webkit-user-drag: none; 32 | } 33 | .leaflet-marker-icon, 34 | .leaflet-marker-shadow { 35 | display: block; 36 | } 37 | /* map is broken in FF if you have max-width: 100% on tiles */ 38 | .leaflet-container img { 39 | max-width: none !important; 40 | } 41 | /* stupid Android 2 doesn't understand "max-width: none" properly */ 42 | .leaflet-container img.leaflet-image-layer { 43 | max-width: 15000px !important; 44 | } 45 | .leaflet-tile { 46 | filter: inherit; 47 | visibility: hidden; 48 | } 49 | .leaflet-tile-loaded { 50 | visibility: inherit; 51 | } 52 | .leaflet-zoom-box { 53 | width: 0; 54 | height: 0; 55 | } 56 | /* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */ 57 | .leaflet-overlay-pane svg { 58 | -moz-user-select: none; 59 | } 60 | 61 | .leaflet-tile-pane { z-index: 2; } 62 | .leaflet-objects-pane { z-index: 3; } 63 | .leaflet-overlay-pane { z-index: 4; } 64 | .leaflet-shadow-pane { z-index: 5; } 65 | .leaflet-marker-pane { z-index: 6; } 66 | .leaflet-popup-pane { z-index: 7; } 67 | 68 | .leaflet-vml-shape { 69 | width: 1px; 70 | height: 1px; 71 | } 72 | .lvml { 73 | behavior: url(#default#VML); 74 | display: inline-block; 75 | position: absolute; 76 | } 77 | 78 | 79 | /* control positioning */ 80 | 81 | .leaflet-control { 82 | position: relative; 83 | z-index: 7; 84 | pointer-events: auto; 85 | } 86 | .leaflet-top, 87 | .leaflet-bottom { 88 | position: absolute; 89 | z-index: 1000; 90 | pointer-events: none; 91 | } 92 | .leaflet-top { 93 | top: 0; 94 | } 95 | .leaflet-right { 96 | right: 0; 97 | } 98 | .leaflet-bottom { 99 | bottom: 0; 100 | } 101 | .leaflet-left { 102 | left: 0; 103 | } 104 | .leaflet-control { 105 | float: left; 106 | clear: both; 107 | } 108 | .leaflet-right .leaflet-control { 109 | float: right; 110 | } 111 | .leaflet-top .leaflet-control { 112 | margin-top: 10px; 113 | } 114 | .leaflet-bottom .leaflet-control { 115 | margin-bottom: 10px; 116 | } 117 | .leaflet-left .leaflet-control { 118 | margin-left: 10px; 119 | } 120 | .leaflet-right .leaflet-control { 121 | margin-right: 10px; 122 | } 123 | 124 | 125 | /* zoom and fade animations */ 126 | 127 | .leaflet-fade-anim .leaflet-tile, 128 | .leaflet-fade-anim .leaflet-popup { 129 | opacity: 0; 130 | -webkit-transition: opacity 0.2s linear; 131 | -moz-transition: opacity 0.2s linear; 132 | -o-transition: opacity 0.2s linear; 133 | transition: opacity 0.2s linear; 134 | } 135 | .leaflet-fade-anim .leaflet-tile-loaded, 136 | .leaflet-fade-anim .leaflet-map-pane .leaflet-popup { 137 | opacity: 1; 138 | } 139 | 140 | .leaflet-zoom-anim .leaflet-zoom-animated { 141 | -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1); 142 | -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1); 143 | -o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1); 144 | transition: transform 0.25s cubic-bezier(0,0,0.25,1); 145 | } 146 | .leaflet-zoom-anim .leaflet-tile, 147 | .leaflet-pan-anim .leaflet-tile, 148 | .leaflet-touching .leaflet-zoom-animated { 149 | -webkit-transition: none; 150 | -moz-transition: none; 151 | -o-transition: none; 152 | transition: none; 153 | } 154 | 155 | .leaflet-zoom-anim .leaflet-zoom-hide { 156 | visibility: hidden; 157 | } 158 | 159 | 160 | /* cursors */ 161 | 162 | .leaflet-clickable { 163 | cursor: pointer; 164 | } 165 | .leaflet-container { 166 | cursor: -webkit-grab; 167 | cursor: -moz-grab; 168 | } 169 | .leaflet-popup-pane, 170 | .leaflet-control { 171 | cursor: auto; 172 | } 173 | .leaflet-dragging .leaflet-container, 174 | .leaflet-dragging .leaflet-clickable { 175 | cursor: move; 176 | cursor: -webkit-grabbing; 177 | cursor: -moz-grabbing; 178 | } 179 | 180 | 181 | /* visual tweaks */ 182 | 183 | .leaflet-container { 184 | background: #ddd; 185 | outline: 0; 186 | } 187 | .leaflet-container a { 188 | color: #0078A8; 189 | } 190 | .leaflet-container a.leaflet-active { 191 | outline: 2px solid orange; 192 | } 193 | .leaflet-zoom-box { 194 | border: 2px dotted #38f; 195 | background: rgba(255,255,255,0.5); 196 | } 197 | 198 | 199 | /* general typography */ 200 | .leaflet-container { 201 | font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif; 202 | } 203 | 204 | 205 | /* general toolbar styles */ 206 | 207 | .leaflet-bar { 208 | box-shadow: 0 1px 5px rgba(0,0,0,0.65); 209 | border-radius: 4px; 210 | } 211 | .leaflet-bar a, 212 | .leaflet-bar a:hover { 213 | background-color: #fff; 214 | border-bottom: 1px solid #ccc; 215 | width: 26px; 216 | height: 26px; 217 | line-height: 26px; 218 | display: block; 219 | text-align: center; 220 | text-decoration: none; 221 | color: black; 222 | } 223 | .leaflet-bar a, 224 | .leaflet-control-layers-toggle { 225 | background-position: 50% 50%; 226 | background-repeat: no-repeat; 227 | display: block; 228 | } 229 | .leaflet-bar a:hover { 230 | background-color: #f4f4f4; 231 | } 232 | .leaflet-bar a:first-child { 233 | border-top-left-radius: 4px; 234 | border-top-right-radius: 4px; 235 | } 236 | .leaflet-bar a:last-child { 237 | border-bottom-left-radius: 4px; 238 | border-bottom-right-radius: 4px; 239 | border-bottom: none; 240 | } 241 | .leaflet-bar a.leaflet-disabled { 242 | cursor: default; 243 | background-color: #f4f4f4; 244 | color: #bbb; 245 | } 246 | 247 | .leaflet-touch .leaflet-bar a { 248 | width: 30px; 249 | height: 30px; 250 | line-height: 30px; 251 | } 252 | 253 | 254 | /* zoom control */ 255 | 256 | .leaflet-control-zoom-in, 257 | .leaflet-control-zoom-out { 258 | font: bold 18px 'Lucida Console', Monaco, monospace; 259 | text-indent: 1px; 260 | } 261 | .leaflet-control-zoom-out { 262 | font-size: 20px; 263 | } 264 | 265 | .leaflet-touch .leaflet-control-zoom-in { 266 | font-size: 22px; 267 | } 268 | .leaflet-touch .leaflet-control-zoom-out { 269 | font-size: 24px; 270 | } 271 | 272 | 273 | /* layers control */ 274 | 275 | .leaflet-control-layers { 276 | box-shadow: 0 1px 5px rgba(0,0,0,0.4); 277 | background: #fff; 278 | border-radius: 5px; 279 | } 280 | .leaflet-control-layers-toggle { 281 | background-image: url(images/layers.png); 282 | width: 36px; 283 | height: 36px; 284 | } 285 | .leaflet-retina .leaflet-control-layers-toggle { 286 | background-image: url(images/layers-2x.png); 287 | background-size: 26px 26px; 288 | } 289 | .leaflet-touch .leaflet-control-layers-toggle { 290 | width: 44px; 291 | height: 44px; 292 | } 293 | .leaflet-control-layers .leaflet-control-layers-list, 294 | .leaflet-control-layers-expanded .leaflet-control-layers-toggle { 295 | display: none; 296 | } 297 | .leaflet-control-layers-expanded .leaflet-control-layers-list { 298 | display: block; 299 | position: relative; 300 | } 301 | .leaflet-control-layers-expanded { 302 | padding: 6px 10px 6px 6px; 303 | color: #333; 304 | background: #fff; 305 | } 306 | .leaflet-control-layers-selector { 307 | margin-top: 2px; 308 | position: relative; 309 | top: 1px; 310 | } 311 | .leaflet-control-layers label { 312 | display: block; 313 | } 314 | .leaflet-control-layers-separator { 315 | height: 0; 316 | border-top: 1px solid #ddd; 317 | margin: 5px -10px 5px -6px; 318 | } 319 | 320 | 321 | /* attribution and scale controls */ 322 | 323 | .leaflet-container .leaflet-control-attribution { 324 | background: #fff; 325 | background: rgba(255, 255, 255, 0.7); 326 | margin: 0; 327 | } 328 | .leaflet-control-attribution, 329 | .leaflet-control-scale-line { 330 | padding: 0 5px; 331 | color: #333; 332 | } 333 | .leaflet-control-attribution a { 334 | text-decoration: none; 335 | } 336 | .leaflet-control-attribution a:hover { 337 | text-decoration: underline; 338 | } 339 | .leaflet-container .leaflet-control-attribution, 340 | .leaflet-container .leaflet-control-scale { 341 | font-size: 11px; 342 | } 343 | .leaflet-left .leaflet-control-scale { 344 | margin-left: 5px; 345 | } 346 | .leaflet-bottom .leaflet-control-scale { 347 | margin-bottom: 5px; 348 | } 349 | .leaflet-control-scale-line { 350 | border: 2px solid #777; 351 | border-top: none; 352 | line-height: 1.1; 353 | padding: 2px 5px 1px; 354 | font-size: 11px; 355 | white-space: nowrap; 356 | overflow: hidden; 357 | -moz-box-sizing: content-box; 358 | box-sizing: content-box; 359 | 360 | background: #fff; 361 | background: rgba(255, 255, 255, 0.5); 362 | } 363 | .leaflet-control-scale-line:not(:first-child) { 364 | border-top: 2px solid #777; 365 | border-bottom: none; 366 | margin-top: -2px; 367 | } 368 | .leaflet-control-scale-line:not(:first-child):not(:last-child) { 369 | border-bottom: 2px solid #777; 370 | } 371 | 372 | .leaflet-touch .leaflet-control-attribution, 373 | .leaflet-touch .leaflet-control-layers, 374 | .leaflet-touch .leaflet-bar { 375 | box-shadow: none; 376 | } 377 | .leaflet-touch .leaflet-control-layers, 378 | .leaflet-touch .leaflet-bar { 379 | border: 2px solid rgba(0,0,0,0.2); 380 | background-clip: padding-box; 381 | } 382 | 383 | 384 | /* popup */ 385 | 386 | .leaflet-popup { 387 | position: absolute; 388 | text-align: center; 389 | } 390 | .leaflet-popup-content-wrapper { 391 | padding: 1px; 392 | text-align: left; 393 | border-radius: 12px; 394 | } 395 | .leaflet-popup-content { 396 | margin: 13px 19px; 397 | line-height: 1.4; 398 | } 399 | .leaflet-popup-content p { 400 | margin: 18px 0; 401 | } 402 | .leaflet-popup-tip-container { 403 | margin: 0 auto; 404 | width: 40px; 405 | height: 20px; 406 | position: relative; 407 | overflow: hidden; 408 | } 409 | .leaflet-popup-tip { 410 | width: 17px; 411 | height: 17px; 412 | padding: 1px; 413 | 414 | margin: -10px auto 0; 415 | 416 | -webkit-transform: rotate(45deg); 417 | -moz-transform: rotate(45deg); 418 | -ms-transform: rotate(45deg); 419 | -o-transform: rotate(45deg); 420 | transform: rotate(45deg); 421 | } 422 | .leaflet-popup-content-wrapper, 423 | .leaflet-popup-tip { 424 | background: white; 425 | 426 | box-shadow: 0 3px 14px rgba(0,0,0,0.4); 427 | } 428 | .leaflet-container a.leaflet-popup-close-button { 429 | position: absolute; 430 | top: 0; 431 | right: 0; 432 | padding: 4px 4px 0 0; 433 | text-align: center; 434 | width: 18px; 435 | height: 14px; 436 | font: 16px/14px Tahoma, Verdana, sans-serif; 437 | color: #c3c3c3; 438 | text-decoration: none; 439 | font-weight: bold; 440 | background: transparent; 441 | } 442 | .leaflet-container a.leaflet-popup-close-button:hover { 443 | color: #999; 444 | } 445 | .leaflet-popup-scrolled { 446 | overflow: auto; 447 | border-bottom: 1px solid #ddd; 448 | border-top: 1px solid #ddd; 449 | } 450 | 451 | .leaflet-oldie .leaflet-popup-content-wrapper { 452 | zoom: 1; 453 | } 454 | .leaflet-oldie .leaflet-popup-tip { 455 | width: 24px; 456 | margin: 0 auto; 457 | 458 | -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)"; 459 | filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678); 460 | } 461 | .leaflet-oldie .leaflet-popup-tip-container { 462 | margin-top: -1px; 463 | } 464 | 465 | .leaflet-oldie .leaflet-control-zoom, 466 | .leaflet-oldie .leaflet-control-layers, 467 | .leaflet-oldie .leaflet-popup-content-wrapper, 468 | .leaflet-oldie .leaflet-popup-tip { 469 | border: 1px solid #999; 470 | } 471 | 472 | 473 | /* div icon */ 474 | 475 | .leaflet-div-icon { 476 | background: #fff; 477 | border: 1px solid #666; 478 | } 479 | --------------------------------------------------------------------------------