GithubHelp home page GithubHelp logo

w8r / leaflet.bookmarks Goto Github PK

View Code? Open in Web Editor NEW
60.0 10.0 17.0 3.13 MB

Leaflet plugin for user-generated bookmarks

Home Page: http://w8r.github.io/Leaflet.Bookmarks/

JavaScript 86.88% Less 13.12%
leaflet leaflet-plugin bookmarks localstorage

leaflet.bookmarks's Introduction

Leaflet.Bookmarks

npm version Bower version CircleCI

Highly customizable Leaflet plugin for user-generated bookmarks, stored locally or on the server.

See demo and documentation

Description

This is a highly customizable plugin for leaflet to allow users to drop bookmarks on your map and to store them locally or on server. It uses localstorage by default, but allows you to implement your own storage solution. You can also redefine the addition of bookmarks, their looks and fields.

Right-click on the map, to add a new bookmark

Usage

Includes

<script src="/path/to/leaflet.js"></script>
<script src="/path/to/Leaflet.Bookmarks.min.js"></script>
<link type="text/css" rel="stylesheet" href="/path/to/leaflet.bookmarks.css">

Put control on the map

var map = new L.Map(...);
var control = new L.Control.Bookmarks().addTo(map);

Adding a bookmark

How you trigger a bookmark addition is your own choice. For the demo I used the beautiful Leaflet.contextmenu plugin by @aratcliffe, but you are free to take any approach you want - it's based on the event bookmark:new dispatched by the map instance:

map.fire('bookmark:new', {
    latlng: new L.LatLng(..., ...)
});

If you want you can omit the naming step and add a bookmark straight to the list using a bookmark:add event.

map.fire('bookmark:add', {
  data: {
    id: 'XXXX' // make sure it's unique,
    name: 'Bookmark name',
    latlng: [lat, lng] // important, we're dealing with JSON here,
    your_key: 'your value'
  }
});

Events

Triggered on map:

  • bookmark:removed - Bookmark has been removed from storage and interface
  • bookmark:show - bookmark selected from list or just created

GeoJSON support

There are GeoJSON import/export methods provided for convinence and use within the storage methods of your choice

  • .bookmarkToFeature(bookmark) Use it on a single bookmark if you want to convert it into geoJSON Feature before send
  • .toGeoJSON() Exports the whole list into GeoJSON, uses .bookmarkToFeature
  • .fromGeoJSON(geojson) Uses properties as the bookmark contents, geometry as the location. GeoJSON Point expected, you can change it for a different type of geometry, if you want, then you'll have to take care of the centroid routines.

Customizing

localStorage or variable storage

The control uses localStorage by default. Your bookmarks will be stored in prefixed key-value pairs. You can customize the prefix if you want to

var control = new L.Control.Bookmarks({
    name: 'your-storage-prefix', // defaults to 'leaflet-bookmarks'
    localStorage: false // if you want to use local variable for storage
});

P.S. You can access the storage directly through the control:

control._storage.getItem(key, callback);
control._storage.setItem(key, value, callback);
control._storage.removeItem(key, callback);
control._storage.getAllItems(callback);

Custom storage(e.g AJAX)

I intentionally didn't add an engine for anything else than localStorage and local variable storage, so you could use your own xhr functions. To do that, you have to pass the interface to your storage to the control like this:

var control = new L.Control.Bookmarks({
    storage: {
        getItem: function(id, callback){
            $.ajax({
                url: '/bookmarks/' + id,
                type: 'GET',
                dataType: 'json',
                success: callback
            });
        },
        setItem: function(id, value, callback){
            $.ajax({
                url: '/bookmarks/' + id,
                type: 'PUT',
                data: value,
                dataType: 'json',
                success: callback
            });
        },
        removeItem: function(id, callback){
            $.ajax({
                url: '/bookmarks/' + id,
                type: 'DELETE',
                dataType: 'json',
                success: callback
            });
        },
        getAllItems: function(callback){
            $.ajax({
                url: '/bookmarks/',
                type: 'GET',
                dataType: 'json',
                success: callback
            });
        }
    }
}).addTo(map);

Custom templates

Pass those into the options if you want to customize the popup or list templates. Proceed with caution

{
       // list item MUST contain `data-id` attribute,
       // or provide your own `options.getBookmarkFromListItem(listItem)` method
       bookmarkTemplate: '<li class="{{ itemClass }}" data-id="{{ data.id }}">' +
            '<span class="{{ removeClass }}">&times;</span>' +
            '<span class="{{ nameClass }}">{{ data.name }}</span>' +
            '<span class="{{ coordsClass }}">{{ data.coords }}</span>' +
            '</li>',

        // format list item name
        formatName: function(name){ ... },

        // format coords
        // again, you have access to the control here, so you can
        // output projected coords for example
        formatCoords: function(laltlng){
            var projected = this._map.project(L.latLng(latlng[0], latlng[1]));
            return 'X: ' + projected.x + 'm, Y: ' + projected.y + 'm';
        },

        // no bookmarks yet
        emptyTemplate: '<li class="{{ itemClass }} {{ emptyClass }}">' +
            '{{ data.emptyMessage }}</li>',

        // no bookmarks text
        emptyMessage: "Hell no, I forgot where I've been!",

        // you can change them, but then provide your own styling
        bookmarkTemplateOptions: {
            itemClass: 'bookmark-item',
            nameClass: 'bookmark-name',
            coordsClass: 'bookmark-coords',
            removeClass: 'bookmark-remove',
            emptyClass: 'bookmarks-empty'
        },

        // change that if you have custom fields in your bookmarks
        popupTemplate: '<div><h3>{{ name }}</h3><p>{{ latlng }}</p>',

        // here you extract them for the template.
        // note - you have access to controls methods and fields here
        getPopupContent: function(bookmark) {
            return L.Util.template(this.options.popupTemplate, {
                latlng: this.formatCoords(bookmark.latlng),
                name: bookmark.name
            });
        },

        // here you can filter bookmarks that you get from
        // the storage or a user, make sure it returns an Array
        filterBookmarks: function(bookmarks){ ... },
}

You can customize the bookmark add form too, pass that to the control options:

formPopup: {
        className: 'leaflet-bookmarks-form-popup',
        templateOptions: {
            formClass: 'leaflet-bookmarks-form',
            inputClass: 'leaflet-bookmarks-form-input',
            coordsClass: 'leaflet-bookmarks-form-coords',
            submitClass: 'leaflet-bookmarks-form-submit',
            inputPlaceholder: 'Bookmark name',
            submitText: '+'
        },
        getBookmarkData: function(){
            var input = this._contentNode.querySelector('.' +
            this.options.templateOptions.inputClass);
            ...
            return {
                id: 'YOUR_UNIQUE_ID',
                name: 'Bookmark name',
                your_custom_field: ... // get it from the form inputs
                latlng: this._source.getLatLng() // get it from the marker
            };
        },
        onRemove: function(bookmark, callback){
          /* use that to add confirmation menus
             when removing a bookmark */
           },
        generateNames: true, // generate unique name if it's not provided by the user
        generateNamesPrefix: 'Bookmark ',
        template: '<form class="{{ formClass }}">' +
            '<input type="text" name="bookmark-name" ' +
            'placeholder="{{ inputPlaceholder }}" class="{{ inputClass }}">' +
            '<input type="submit" value="{{ submitText }}" ' +
            'class="{{ submitClass }}">' +
            '<div class="{{ coordsClass }}">{{ coords }}</div>' +
            '</form>',
    }

Editing

You can enable bookmarks editing/removal by putting a flag in the bookmark object

{
  name: '',
  id: 'XXX',
  latlng: [lat, lng],
  editable: true,
  removable: true
}

This will enable a menu on popup to remove or edit the bookmark. Presence of menu items will is defined by those params also

screenshot 2015-05-27 21 32 51

Removal

You can pass a custom confirm function to the control, so you could handle confirmation menus

  onRemove: function(bookmark, callback){
    if(confirm('Are you really sure?')){
      if(bookmark.name === 'Bamby') {
        alert('Keep your hands away!');
        callback(false); // won't be removed
      } else {
        callback(true);  // will be removed
      }
    } else {
      callback(false);
    }
  }

L.Util._template

Small template function used by this project. It's a simple implementation of @lodash templates, using mustache interpolation syntax. You get it as a souvenir.

L.Util._template('Whereof one cannot {{ data.action }}, thereof one must keep {{ data.instead }}', { data: { action: 'speak', instead: 'silent' }});
// -> "Whereof one cannot speak, thereof one must keep silent"

Authors and Contributors

Alexander Milevski

License

MIT

Changelog

  • 0.4.0
    • Leaflet 1.6 support
  • 0.3.0
    • Fixed some bugs
    • Migrated to rollup build system and ESM modules
  • 0.2.0
    • Editing/removal funtionality
    • "Add new" button
    • Tests added
  • 0.1.5
    • GeoJSON support
  • 0.1.3
    • Different layout when in topleft position
    • Scroll to bookmark on addition
  • 0.1.2
    • Remove marker when bookmark is removed
  • 0.1.0
    • npm & bower packages published
  • 0.0.2
    • Zoom level ztored and used by default
    • Remove button flickering fixed
    • Add bookmark UX: now you can show the newly created bookmark right away
  • 0.0.1
    • Initial release

leaflet.bookmarks's People

Contributors

dependabot[bot] avatar slongberry avatar w8r avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

leaflet.bookmarks's Issues

Can't interact with bookmarks

This is a very useful plugin. Thanks for creating it. I would like to be able to interact with bookmarks after adding them and closing their popups. It doesn't seem possible to drag them or re-open the popup on click. I can see reference to things like dragging and 'rise on hover' etc in your code but nothing happens when I hover and I can't drag the marker.

These missing behaviours are also visible in your own demo as well as reproduced in my own map (I am using 0.5.1 and leaflet 1.9.4). Using your own demo, I see the same missing behaviours in Chrome, Firefox, DuckDuckGo and Edge.

Is this a bug or do I need to enable it all somehow (and if so how)?

Many thanks

Not working on mobile

The best leaflet plugin but unfortunately not working on Android where it can not open the keyboard.

Plugin is broken with leaflet 1.9.3

It seems the plugin is broken with the latest leaflet version 1.9.3 or one of the version before.
The exmaple runs with leaflet version 1.6.0.

Remote storage

Sorry I'm really new to web developing. Could you explain more about remote storage with AJAX?

  1. In the example you said url: '/bookmarks/' + id I'm not quite sure what does that mean. (Isn't it supposed to point to the server handler first? eg. server.php)
  2. In the 'data: value' part, should I use the variable 'value' straight away when using this plugin?
    Thank you!

Make bookmarks stay on map after placed

I noticed that after I place the bookmark they hide. How I can make them stay on map?
Or better, if it uses a layer, can you tell me which layer, so I can toggle it on/off?
Thanks, awesome plugin

Option for more information

Really nice work on this add-on for Leaflet. Small feature request. It would be great to see an additional option for a note that would populate the infowindow beyond just the title.

variable issue

Leaflet.Bookmarks.js line 1245 =>'id: Inputid.value || unique()' is this supposed to be 'id: idInput.value || unique()'?

Bookmark data for custom template

Really like the plugin, it has saved me a ton of time. I have come across one issue though.

We have the ability to customize the way the list of bookmarks appears through the bookmarkTemplate option. However, if I add a custom field to the bookmark, I don't see how to access that data to display it.

I modified the _getBookmarkDataForTemplate function in the code to look more like the _getPopupContent function:

  _getBookmarkDataForTemplate: function(bookmark) {
    if (this.options.getBookmarkDataForTemplate) {
      return this.options.getBookmarkDataForTemplate.call(this, bookmark);
    } else { 
    return {
      coords: this.formatCoords(bookmark.latlng),
      name: this.formatName(bookmark.name),
      zoom: bookmark.zoom,
      id: bookmark.id
      };
    }
  },

This allowed me to write me own custom getBookmarkDataForTemplate function and pass it to the bookmarks control as an option on creation. If there is another way that I should have accessed the data, please let me know.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.