Introduction to folium.plugins

Just a small description of plugins, what they are, how they work, and how to implement one.

Template structure

To undestand how plugins work, you have to know how Folium template is made. Basically, it is made of four parts :

  • The header : where one defines imports of CSS stylesheets and Javascript external scripts. For example, the link to Leaflet library and stylesheets are there.
  • The css : where one defines specific styles.
  • The html body : where one defines the document object model. For example, the map(s)' divs are defined there.
  • The javascript : where the Leaflet script is written. For example, the map objects, layers, markers... are defined here.

Now, a plugin is an object that inherits from folium.plugins.Plugin, whose goal is to write things into these four parts.

Quick and dirty example

This is an example of plugin, that imports a Javascript library, defines a css class, creates a new div, defines a Javascript object and add it to the map.

from folium.plugins.plugin import Plugin

class MyPlugin(Plugin):
    def __init__(self, data):
        """Creates a MyPlugin plugin to append into a map with
        Map.add_plugin.
        """
        super(MyPlugin, self).__init__()      # We call Plugin.__init__.
        # This will (in particular) define self.object_id as a random hexadecimal string (unique).

        self.plugin_name = 'MyPlugin'         # This will help to name variables in html and js.

    def render_header(self, nb):
        """Generates the header part of the plugin."""
        return """
        <link rel="stylesheet" href="https://myplugin_stylesheet.css">
        <script src="https://myplugin_script.js">
        """ if nb==0 else ""

    def render_css(self, nb):
        """Generates the css part of the plugin."""
        return """
        #myplugin {
            color: #ff00ff,
            width: 314px
            };
        """

    def render_html(self, nb):
        """Generates the html part of the plugin."""
        return """
        <div id="myplugin{id}"></div>
        """.format(id = self.object_name)

    def render_js(self, nb):
        """Generates the Javascript part of the plugin."""
        return """
        var MyPlugin_{id} = myplugin_script.someObject();
        map.addLayer(MyPlugin_{id});
        """.format(id = self.object_name)

Note that you may be willing to put on a map several instances of the same plugin. But you don't want the header to be written several times. This is why each method has a nb argument, that will be incremented at each instance's render. Hence the line

 if nb==0 else ""

More sophisticated example

TODO : write something interesting here.