Sign Up for Free

RunKit +

Try any Node.js package right in your browser

This is a playground to test code. It runs a full Node.js environment and already has all of npm’s 1,000,000+ packages pre-installed, including smap-responsive with all npm packages installed. Try it out:

smap-responsive lists no main file and has no index.js, so it can't be directly required. If this is a mistake, please let us know. It may however contain internal files that you can require manually:

// require("smap-responsive/[??]")

This service is provided by RunKit and is not affiliated with npm, Inc or the package authors.

smap-responsive v1.2.10

A framework for creating responsive web maps


Build Status



sMap-responsive is a software framework for web maps built with Leaflet and Bootstrap. The purpose of the framework is to facilitate creation of maps which support a range of different browsers and devices (specified in the wiki).

Quick install with npm: npm install --save smap-responsive

###Who to blame? The framework is developed by Johan Lahti at City of Malmö together with a team of valuable contributors.

###Why another framework? First of all. This framework is based around Leaflet controls (plugins). The controls are reusable in any other Leaflet-based framework. You can pick Leaflet controls from the Leaflet plugin site or vice versa – pick controls from here and use in your own Leaflet based framework (with few or no modifications needed).

Second. This framework is built to be dynamic and serve multiple objectives in various contexts. Smap-responsive is used in many different types of external applications as well as for stand-alone maps. Although every map is unique, most functionality can be re-used for every map.

Third. In order to minimise the need of programmers' hands-on – we put a lot of effort into making this framework as easy to use as possible for the administrator. New maps – from the most advanced to the simplest of simple – can be created by just copying and modifying one configuration file. This gives the administrator a lot of power and flexibility – without doing any programming.


####0. Overview

Basic chapters:

  • Getting started (1-2)
  • Creating a map (3)
  • URL parameters (4)

Advanced chapters:

  • Include external plugins (5)
  • Develop new plugins (6)
  • Developer API (7)

####1. Preconditions First, make sure you have the following applications installed.

The easy way: Install npm and execute this command: npm install --save smap-responsive inside a directory of your choice (locate the folder node_modules/smap-responsive)

####2. Clone and install dependencies If you are using a Mac or Linux computer, you may need to use sudo before some of the commands. Clone the project using Git or Subversion (you can also use a GUI version of the mentioned):

git clone


svn co smap-responsive

Install dependencies

cd smap-responsive
npm install
bower install

Build the application. Run this from the root directory of your smap clone.

gulp full

If the build went fine, point your browser to http://localhost/smap-responsive/dev.html – or wherever your clone is located. If you want to use a minimised version of the application, just point your browser to http://localhost/smap-responsive/dist/index.html instead. The dist folder contains the whole application but everything is minimised and compressed. While debugging, it is better to use dev.html.

The default language is Swedish (language code "sv"). If you want to change this to English, then edit the file core/js/mainConfig.js and change the variable to defaultLanguage: "en".

Now you are finally ready to create some maps!

3. Create a customised map

  1. Copy and modify the example configuration file.
  2. Rename it to myconfig.js.

The configuration file informs the application of:

  • Starting zoom and centering of the map
  • Background layers to use (e.g. OpenStreetMap)
  • Overlays to use
  • Plugins to be included and their settings

Inside the example configuration file (the one you just copied) is described how each and every parameter affects the application.

Next. We need to specify which configuration file to use. This is accomplished with the URL parameter config:

// Using our newly created configuration file myconfig.js

// Or, using compressed code:

Note that the path to the config file is relative to the html file.

Next step is to change the application's behaviour using URL parameters.

4. URL parameters (REST API)

The application can be called with various URL parameters. For instance, http://localhost/smap?config=another_config.js&zoom=12 will load the config file another_config.js and set the zoom to 12 (higher means more zoomed in).

#####Core parameters:

Parameter keyParameter value(s)DecidesExample value
config{String}Config to usemy_config.js or somefolder/my_config.js or
zoom{Integer} range: 0-18Starting zoom levelzoom=12 (higher=more zoomed in)
center{Integer},{Integer}Starting center13.1,55.6
bl{String}Starting baselayerbl=citymap - the baselayer with given layerId will be active from start
ol{String}, …Starting overlay(s)ol=some_points,some_data (layerId for two layers)
xy{Integer},{Integer},{Optional String},{Optional String}Adds a marker13.1,55.6 or 13.1,55.6,Text%20in%20popup or xy=117541,6163401,Projected coords,EPSG:3008
lang{String}Sets languagelang=en (for English)

#####Plugin parameters (for the plugins hosted here):

Parameter keyParameter value(s)DecidesExample valuePlugin
poi{String},{Optional Integer}Triggers geolocate for given addresspoi=Storgatan%201,1 (open popup) poi=Storgatan%201 (no popup)L.Control.Search
lsw{Integer}Open switcher from startlsw=1 opens switcher from start (only small screens)L.Control.LayerSwitcher
md{String}Features to draw- (created internally)L.Control.MeasureDraw

5. Include external plugins

As seen in the example configuration file plugins, any Leaflet control can be included in the map simply by adding its constructor and its options to the plugins array. All options will be transferred to the plugin when it is instanstiated (the pre-assumption is that all controls follow the same syntax pattern, taking only one parameter which is options).

However, first you need to incorporate the plugin into the code. Follow these steps:

  1. Place the files, e.g. MyPlugin.js and MyPlugin.css inside a folder named MyPlugin. This folder should be placed inside the plugins-folder of your smap clone.
  2. Run gulp in order to build the code (from the root directory of your smap clone): gulp full
  3. Open dev.html or index.html and confirm that the plugin has been added into these html-files. Add the plugin to the configuration file in the same manner as in the example configuration file

6. Develop plugins

Developing a plugin for smap-responsive is no different than developing an ordinary Leaflet control, which you can learn better from other sources. However, smap-responsive has some special additions which can be useful when you want to interact with core funcionality. For instance:

  • Responding to a selected feature event
  • Creating or adding URL parameters
  • Fetching an already added layer using its layerId
  • Adding language support

Use the plugin template when developing a new plugin. The only addition to an ordinary Leaflet plugin is the _lang object which allows you to adapt labels and stuff depending on language. If you don't need it, just ignore it.

Note! While developing a plugin you can execute gulp without any parameter: gulp. It will then automatically compile .styl and .sass files into CSS whenever you save something. Check the gulpfile.js and learn more about how to modify it for your needs.

7. Developer API

This section describes:

  • Core events
  • Core methods (used for communicating with the core)
  • Utility methods
Core events:
Event nameTriggered…Example
smap.core.createparams…when URL params are created. Useful if your plugin needs to add something to the URL.smap.event.on("smap.core.createparams", function(e, paramsObject) { paramsObject.new_param = 3; });
smap.core.aftercreateparams…after createparams have been triggered. Useful e.g. if you have a param dependency for your own param(s).smap.event.on("smap.core.createparams", function(e, paramsObject) { paramsObject.new_param = 3; });
smap.core.beforeapplyparams…before URL params are applied in coresmap.event.on("smap.core.beforeapplyparams", function(e, paramsObj) { alert(paramsObj.MY_PARAM); });
smap.core.applyparams…after URL params have been applied in core– " " –
smap.core.pluginsadded…when all plugins have been added. Useful if you need another plugin to be added before you do something.smap.event.on("smap.core.pluginsadded", function() {});
selected…when a feature is selected (through getfeatureinfo or vector select)"selected", function(e) { /* e.layer, e.feature, e.latLng, e.selectedFeatures */});
unselected…when a feature is"unselected", function(e) {});

Note! Check the file where the method exists for a more detailed description of the parameters below.

Core methods – in core/js/cmd.js:
smap.cmd.createParamsaddRoot {Boolean}Create URL params that recreates the mapvar s = smap.cmd.createParams(true);
smap.cmd.createParamsAsObject-Same as previous but params as objectvar obj = smap.cmd.createParamsAsObject();
smap.cmd.getControlcontrolName {String}Get control with given name OR full class namevar search = smap.cmd.getControl("Search");
smap.cmd.getControlscontrolName {String}Same as above but to be used if there are many instancesvar arr = smap.cmd.getControls("RedirectClick");
smap.cmd.notifytext {String}, msgType {String}, options {Object}Alert the user about somethingsmap.cmd.notify("An error", "error");
smap.cmd.addLayerWithConfiglayerConfig {Object}Same method used by core when adding layers from config file
smap.cmd.getLayerlayerId {String}Fetch an already added layervar layer = smap.cmd.getLayer("some_layer_id");
smap.cmd.getLayerConfiglayerId {String}Fetch configuration for a specific layer from config filevar t = smap.cmd.getLayerConfig("some_layer_id");
smap.cmd.getLayerConfigBykey {String}, val {String}, options {Object}Same as previous, but based on different key and valsmap.cmd.getLayerConfigBy("options.displayName", "Districts of Malmö");
smap.cmd.getLang-Get the currently set languagevar lang = smap.cmd.getLang(); // e.g. "en"
smap.cmd.reloadCoreoptions {Object}Reload the map without reloading the browsersmap.cmd.reloadCore({});
smap.cmd.loadingshow {Boolean}, options {Object}Show/hide the loading indicator (set show to false to hide)smap.cmd.loading(true, {text: "Fetching data"});

Utility methods – in core/js/utils.js:
utils.rmPxtext {String}Converts a CSS "size" given as text into an integerutils.rmPx("10px") // -> 10
utils.capitalizetheString {String}Converts string into upper-caseutils.capitalize("Hey there") // -> "HEY THERE"
utils.getBrowser-Get current browser (so far only IE versions)utils.getBrowser().ie8; // {Boolean}
utils.urlAppendbaseUrl {String}, params {String}, separator {String}Merges a URL with paramsutils.urlAppend("http://myurl/folder/, "param=1&hey=2, "?");
utils.isInIframe-Check whether this app runs inside an iframeutils.isInIframe() // {Boolean}
utils.makeUniqueArrarr {String}Removes all duplicates from arrayutils.makeUniqueArr([1,1,2,2,2]); // -> [1,2]
utils.objectToUpperCaseo {Object}Converts all keys in the object into upper-caseutils.objectToUpperCase({test: "hey"}); // -> {"TEST": "hey"}
utils.drawDialogtitle {String}, bodyContent {String or jQuery Object}, footerContent{String or jQuery Object}, options {Object}Returns a Bootstrap modalutils.drawDialog("Title", "


", '').modal("show");
utils.getLayerFromFeaturefeature {unknown}, layer {unknown}Return the parent layer of a featureutils.getLayerFromFeature(f, layer);
utils.roundval {Number}, nbrOfDecimals {Integer}Rounds to number of decimalsutils.round(4.87123, 1); // -> 4.9
utils.makeUnselectabletag {jQuery tag}Make HTML elements in (old) IE unselectableutils.makeUnselectable($("body"));
utils.extractToHtmlhtml {String}, props {Object}Replaces all ${key} with the corresponding value found in propsutils.extractToHtml("


", {"some_key": "Hey"}); // ->


utils.createLabelcenter {L.LatLng}, html {String}, className {String}Returns a map labelutils.createLabel([13,55.6], "I am a label", "label-nbr-1");
utils.getLengtharrLatLng {Array({L.LatLng},{…})}Returns total true (curved) distance for the lineutils.getLength([L.latLng(13, 55), L.latLng(14, 67)])
utils.paramsStringToObjectpString {String}, keysToUpperCase {Boolean}Converts a parameter string into an objectutils.paramsStringToObject("a=2&b=3", true); // -> {"A":2, "B":3}
utils.projectPointeast {Number}, north {Number}, srsSrc {String}, srsDest {String}Convert coords from one projection to anotherutils.projectPoint(13,56,"EPSG:4326","EPSG:3008"); // -> [118803, 6208675]
utils.projectLatLnglatLng, srsSrc, srsDest, reverseAxisSrc, reverseAxisDestSimilar as previous but for L.LatLngutils.projectLatLng(L.latLng([13,56]), "EPSG:4326", "EPSG:3008", false, true);
utils.projectFeaturefeature {GeoJSON Object}, inputCrs {String}, options {Object}Convert entire GeoJSON object into another projection (used by WFS layer class)See L.GeoJSON.WFS class for example usage


sMap as a product consists of source code developed by the contributors of this repository. This code is released under the AGPL-v3 license.

The product uses a number of third-party libraries, such as Leaflet and Bootstrap etc. These are not included in the sMap product. The copyright of these libraries belongs to their respective authors and are protected by their own license.

The sMap package (i.e. the contents of this repository) consists of the sMap product on one hand, and the required third-party libraries on the other.

###Important information regarding data sources

Data sources – whether belonging to the contributors' organisation, or to anyone else – are not included, neither in the product, nor in the package. You need to seek permission from the publisher and/or from the copyright owner to use these data. This also applies if the data is linked from any other code.


If you are using sMap-responsive to make your own map, or if you change it, we would be grateful if you let us know and share your experiences and your code. Please contact the site admin if you want to publish it in the examples section above.

###Questions or suggestions?

We are happy for any type of constructive feed-back.

If you have questions regarding smap-reponsive, please contact Johan Lahti

RunKit is a free, in-browser JavaScript dev environment for prototyping Node.js code, with every npm package installed. Sign up to share your code.
Sign Up for Free