The OpenLayers fallen and Leaflet arise… sure???
I wrote this post some months ago, before I publish the OpenLayers Cookbook, but I never published it thinking it could start a flame war instead a constructive thread.
Today, after a twitter conversation (thanks @Starefossen @brymcbride @erilem @mourner and @LeafletJS) I think it is time to publish it.
OpenLayers
OpenLayers is a great project. I think it is the most complete GIS project for creating web mapping applications. Its completeness makes it also a bit complex, but a complexity that is necessary.
OpenLayers allows to use raster and vector layers. Respect vector layers we can load data from different data sources (files, WFS servers, …) and with different formats (GML, GeoJSON, KML, …). OpenLayers allows to render geometries using different technologies (SVG or Canvas) in a way transparent to the user. Its design tries to follow as close as possible the standard concepts of features, geometries, attributes and tries to implement most of them (WMS, WFS, SLD, …).
In summary, OpenLayers tries to offer all the things a complete GIS project could need. Its desing has made having all this in mind and results in a big and complex architecture but, take into account, which is necessary to give response to all the requirements.
Leaflet
On the other hand we found a project like Leaflet, designed from the beginning with a philosophy close to ”make it without complexity” or ”offer only that things required to create a simple maps“.
Leaflet offers raster layers (from a tiled source), vector layers, markers and popups and, every day, a growing set of plugins adding more features to it: read GeoJSON files, clustering strategy, etc.
Leaflet is much more lightweight and, to create a simple map, it is more simple to use.
The secret behind the fame of Leaflet
IMO Leaflet has two main aspects that has made it the perfect option to be used in thousands of web pages: its look and feel and its coding style.
The Leaflet L&F is better than OpenLayers: buttons and layer switcher (among others) looks like an actual and fresh project instead like an almost 10 years old project like OpenLayers.
The Leaflet coding style is actual. The use of short namespaces and the chaining functions style (something like jQuery) makes it feel like a modern project and, probably, easier to use than OpenLayers.
What about Leaflet plugins?
Many of you can think “what about the plugins?” It is known one of the key aspects of Leaflet is the fact it offers a base code on which develop other plugins to make the platform better and greater. Yes, that is nice but is not always true.
For me, the growing set of Leaflet plugins remember the myriad of jQuery plugins. Most of them are great, awesome, but not all of them follow the same rules. Every developer can create plugins without a common design or architecture integration.
For example, the Leaflet.markercluster plugin (from Dave Leaver @daveleaver) is an awesome plugin that allows to make the same as the cluster strategy on OpenLayers, that is, group “points” which are too close and can overlap each other.
I must to say I start coding the AnimatedCluster strategy for OpenLayers after seen the Dave’s work, which I consider superior to mine.
The Leaflet.markercluster version is based in the concept of markers while the AnimatedCluster follow the more standard concept of feature.
To style markers in the Leaflet.markercluster you need to implement a iconCreateFunction and pass to the constructor which must be responsible to set the CSS style for each marker depending on the number of points it clusters (see the _defaultIconCreateFunction as a sample).
In the AnimatedCluster we have all the power of the features, geometries and styles OpenLayers offers us. We can create a vector layer, assign the AnimatedCluster strategy to it with some rules to style and automatically our layer will act as a cluster layer (please read the post Animated marker cluster Strategy for OpenLayers for more detailed explanation).
The fact OpenLayers is designed with many requirements in mind allow to work with a set of well designed pieces, like vector layers, features, geometries, styles, protocols and formats. But in contrast it adds some rigidness to implement new features that must conform the “global” rules.
On the other hand, Leafet lacks from a “global” design and, because of this, two similar plugins can follow to different implementation without the option of “reuse concepts” (think in another plugins that styles markers). But this lack of “global design” is what makes Leaflet be more flexible than OpenLayers.
Conclusions
IMO, both OpenLayers and Leaflet are great tools for different (but also similar) purposes. I consider Leaflet ideal for web pages with relatively simple maps (to create great visualizations with markers, popups, etc) but for a more GIS oriented solution I have no doubt of using OpenLayers.
Having that in mind it is easy to see there are a bigger number of sites requiring something like Leaflet instead of OpenLayers. The 90% of users requires a “simple map solution” instead a GIS solution. Having that in mind it is easy to see we are comparing a “simple map solution” with a GIS solution and I ask you: why?
As developer we have the pleasure to have two great tools on our bag. It is our responsibility to use the appropriate one on each situation.
Related Posts:
SimplyWrite, a free web distraction writing tool
I like to write and I like programming so the obvious consequence were to write some tool to write. More or less this is the history of SimplyWrite.
SimplyWrite is a free web distraction writing tool that recognizes the lightweight markup language Markdown, an easy-to-read, easy-to-write plain format which allow to enrich the text.

Features
- Auto show/hide of menus to allow a clean working area.
- Show working and total timer. Total timer counts the time since you open SimplyWrite. Working timer counts the time you have set active the SimplyWrite page.
- Count lines, words and characters.
- Export your writes to a new page, ready to be saved.
- Allow to configure font family and size.
- SimplyWrite stores all your writes on the client side. It makes use of the HTML5 local storage feature so no server is required.
Be careful with this feature. You can lost your data if you manually clean the broswer cached data and also browser cleans the local storage area automatically when the space used grown over some value (like 500mb).
The source code of SimplyWrite is available at GitHub under MIT license. Feel free to contribute.
The Design
I would like to specially mention the fact the SimplyWrite design was made by my friend Guillem Sevilla (@gllmsvll) a great minimalism designer !!!
Technology
SimplyWrite has been a nice challenge for me. It gives me the opportunity to work with the next tools:
- grunt, the awesome JavaScript task runner. It allows, among others, to minimize and concatenate files.
- grunt-bbb, the grunt Backbone Boilerplate Build extension. Simplifies the work with Backbone framework.
- backbone, a lightweight MVC framework.
- backbone.layoutmanager, an extension of backbone to improve the work with views.
- CodeMirror, an awesome code editor component for the browser.
- Bootstrap, a front-end framework used for the UIX.
Related Posts:
The Book: GeoServer Beginner’s Guide
GeoServer is one of the most importants open source geospatial servers nowadays. Implemented in Java, based on the powerful GeoTools libraries, GeoServer offers a great degree of interporability publishing data from major spatial data sources using Open Geospatial Consortium (OGC) standards.
Hopefully, for those who work or start working with GeoServer, recently Packt Publishing has released a new book titled GeoServer Beginner’s Guide.
Written by Stefano Iacovella, with contributions from Brian Youngblood, the book guide us on the main topics to work with GeoServer, through the next list of chapters:
Chapter 1: GIS Fundamentals
Chapter 2: Getting Started with GeoServer
Chapter 3: Exploring the Administrative Interface
Chapter 4: Accessing Layers
Chapter 5: Adding Your Data
Chapter 6: Styling Your Layers
Chapter 7: Creating Simple Maps
Chapter 8: Performance and Caching
Chapter 9: Automating Tasks: GeoServer REST Interface
Chapter 10: Securing GeoServer Before Production
Chapter 11: Tuning GeoServer in a Production Environment
Chapter 12: Going Further: Getting Help and Troubleshooting
Despite of its title, the book is great from newbies to those with intermediate knowledges on GeoServer, and also put some efforts on advance topics, like performance and configuration for production environment chapters.
Personally, I like the way Stefano writes: simply, plain and, most important, making clear complex questions. In addition, the book is plenty of samples and figures which help us to understand better what is talking on.
Conceptually, we can divide the book in three sections: introduction (chapter 1, 2 and 3), basic or common usage (chapters 4, 5, 6 and 7) and advanced topics (chapter 8, 9, 10 and 11).
The book introduces us in the GIS world (chapter 1) starting with an introduction of many related topics: projections, coordinate systems, modeling information, etc. After this, it shows how to install GeoServer (chapter 2) in two different operating systems: Ubuntu Linux and Windows and finally, passed to show the main aspects of the administrative interface of GeoServer (chapter 3).
From here, the book covers the main aspect on how to access, add and serve data (chapter 4 and 5), how to style to serve them in a better way (chapter 6) and basic samples on how to create maps against GeoServer using Google Maps, OpenLayers and Leaflet libraries.
The third block, concentrates improving the performance of the server using the GeoWebCache system (chapter 8), administer GeoServer via its REST interface (chapter 9), securing its access and administration (chapter 10) and tune it up ready for a production environment (chapter 11).
The book is mainly oriented to WMS but dedicates the chapter 12 to talk specifically on WFS and WCS, also supported by GeoServer.
Without a doubt, GeoServer Beginner’s Guide is a book must be on your working table.
Related Posts:
Things I learned creating a jQuery Plugin (Part II)
This post is the continuation of the series Things I learned creating a jQuery Plugin.
In the first part we have seen how the structure of a jQuery plugin must be, the plugin entry point (so called wrapper function) and how we can control the behavior of a method as a getter or setter.
Define default options
Your plugin more probably will accept different set of options to allow some configuration. For these reason it is important to define a set of default options which will be applied in cases where no options are specified by the user. Place it within the jQuery wrapper function is a good practice:
//
// Default options
//
$.fn[pluginName].defaults = {
opt_A: ""
};
Encapsulate your plugin code
A good practice is to encapsulate the logic of our plugin within a function, this way our plugin’s entry point function can easily initialize or call the right method.
For example, in a really simple wrapper function, that simply initializes a plugin’s instance on each selected element, we could write something like:
$.fn[pluginName] = function(options) {
return this.each(function() {
new Plugin(this, options);
});
}
The plugin constructor
The main part of your plugin is the constructor function. Usually this function is responsible to initialize the plugin, store a reference to the selected element or merge the passed options with the default ones:
function Plugin(element, options) {
// Store references to the selected element
this.el = element;
this.$el = $(element);
// Merge passes options with defaults
this.options = $.extend({}, $.fn[pluginName].defaults, options);
// ...other code here...
// Initialize the plugin instance
this.init();
}
Prototype your plugin
Once the Plugin function is defined we can modify its prototype adding all the desired methods we want for our plugin.
There are a couple of methods are a good practice to implement:
- A
initmethod, which initializes each plugins instance: creating new DOM elements, registering listeners, etc - A
destroymethod, responsible to free any resource used by the plugin: extra elements, unregister listeners, etc.
Other methods can be created within your plugin’s prototype but remember the convention: Use method names starting with underscore for those methods we want to be private.
If you remember the first part of this series, what really happens is when you call a plugin’s method, the wrapper function of our plugin checks if the method’s name starts with underscore and if so then avoids the call.
//
// Plugin prototype
//
Plugin.prototype = {
//
// Initialize the plugin instance
//
init: function() {
...
},
//
// Free resources
//
destroy: function() {
...
},
//
// Public method
//
publicMethod: function() {
...
},
//
// Private method (it starts with an underscore)
//
_privateMethod: function() {
...
}
}
A note on the destroy method
As we have commented, the destroy method must free any resource used by the plugin instance, like extra created elements, unregister listeners, etc
If you remember the first article, you will notice that the plugin’s instance is stored within the selected DOM element where the plugin is applied:
$.fn[pluginName] = function(options) {
var args = arguments;
if (options === undefined || typeof options === 'object') {
// Creates a new plugin instance, for each selected element, and
// stores a reference withint the element's data
return this.each(function() {
if (!$.data(this, 'plugin_' + pluginName)) {
$.data(this, 'plugin_' + pluginName, new Plugin(this, options));
}
});
}
...
};
That occurs in the line:
$.data(this, 'plugin_' + pluginName, new Plugin(this, options));
So, the last action in your destroy method must be always remove the plugin’s instance reference from the element’s data. This can easily done using the reference to the DOM element stored in the plugin instance:
//
// Free resources
//
destroy: function() {
// Remove elements, unregister listerners, etc
// Remove data
this.$el.removeData();
}
Allow the use of callbacks in our plugin
It is common jQuery plugins allows to register callback functions to be called when an event or action is generated by the plugins. For example, in the tagger plugin the user can be notified when a new tag is added, removed, clicked, etc.
Next lines shows the initialization of the tagger plugin setting the parameter fieldSeparator to a value different from the default options value and registering a callback function for the onTagAdded event:
$('#inputID').tagger({
fieldSeparator: '|'
onTagsAdded: function(tags) {
console.log('Added new tag: '+tags+'\n');
}
});
To achieve this we need to make to main steps:
- Define a default and empty callback function in the plugins default options.
- At some place of our plugin’s code make a call to the callback function.
Continuing with the sample of the tagger plugin, its default options looks like:
//
// Default options
//
$.fn[pluginName].defaults = {
fieldSeparator: ",",
readOnly: false,
// Callback invoked when user calls the 'tags' method
onTagsAdded: function() {
},
// Callback invoked when user calls the 'remove' method
onTagsRemoved: function() {
},
// Callback invoked when user calls the 'clear' method.
// Note: Internally the 'clear' method uses the 'remove'.
onClear: function() {
},
// Callback invoked when the user click a tag label
onClick: function() {
}
};
Later, in the method responsible to add new tags to the tag list, a call is made to the onTagsAdded function:
// Adds one or more tags
// ...
//
tags: function(tags) {
...
// Call the callback
this.options.onTagsAdded.call(this, tags);
...
}
},
Note how we have forced to set the
thisobject and passed the value of the new added tag to the callback function.
Summary
Ok, this is the end. A short series of two articles to introduce the main concepts to creating jQuery plugins isn’t a bad thing when you are looking for help starting with jQuery and custom plugin development.
Let’s try to summarize the main points we have seen in this couple of posts:
- Understand the importance of entry point to your plugin. This is handled in a new function on the
$.fnobject and is responsible to (or can) control: plugin initialization, call to setter or getter methods, simulate private methods, etc. - Encapsulate your plugin’s functionalities in a prototyped function
- Store, if needed, a reference to the DOM element where your plugin is applied to.
- Remember to implement a
destroymethod responsible to free all the resources used by your plugin - Create a default options object that serves as a base to extend it with the options specified by the user
- Keep calm and remember try and error is a (necessary) way to learn
References
The web is plenty of great information:
http://docs.jquery.com/Plugins/Authoring
http://www.websanova.com/tutorials/jquery/the-ultimate-guide-to-writing-jquery-plugins
https://github.com/zenorocha/jquery-plugin-patterns
http://coding.smashingmagazine.com/2011/10/11/essential-jquery-plugin-patterns/
http://addyosmani.com/resources/essentialjsdesignpatterns/book/#jquerypluginpatterns



