text: /*
   * FM.Util contains various utility functions used throughout fenix-map-js code.
   *
   */
  
  FM.Util = {
  
      initializeLangProperties: function(lang) {
          var I18NLang = '';
  
          //TODO swith to requirejs i18n
          //TODO lowercase lang code
  
          switch (lang) {
              case 'FR' : I18NLang = 'fr'; break;
              case 'ES' : I18NLang = 'es'; break;
              default: I18NLang = 'en'; break;
          }
          var path = FMCONFIG.BASEURL_LANG;
  
          $.i18n.properties({
              name: 'I18N',
              path: path,
              mode: 'both',
              language: I18NLang
          });
      },
  
      extend: function (dest) { // (Object[, Object, ...]) ->
          var sources = Array.prototype.slice.call(arguments, 1),
              i, j, len, src;
  
          for (j = 0, len = sources.length; j < len; j++) {
              src = sources[j] || {};
              for (i in src) {
                  if (src.hasOwnProperty(i)) {
                      dest[i] = src[i];
                  }
              }
          }
          return dest;
      },
  
      bind: function (fn, obj) { // (Function, Object) -> Function
          var args = arguments.length > 2 ? Array.prototype.slice.call(arguments, 2) : null;
          return function () {
              return fn.apply(obj, args || arguments);
          };
      },
  
      stamp: (function () {
          var lastId = 0, key = '_leaflet_id';
          return function (/*Object*/ obj) {
              obj[key] = obj[key] || ++lastId;
              return obj[key];
          };
      }()),
  
      limitExecByInterval: function (fn, time, context) {
          var lock, execOnUnlock;
  
          return function wrapperFn() {
              var args = arguments;
  
              if (lock) {
                  execOnUnlock = true;
                  return;
              }
  
              lock = true;
  
              setTimeout(function () {
                  lock = false;
  
                  if (execOnUnlock) {
                      wrapperFn.apply(context, args);
                      execOnUnlock = false;
                  }
              }, time);
  
              fn.apply(context, args);
          };
      },
  
      falseFn: function () {
          return false;
      },
  
      formatNum: function (num, digits) {
          var pow = Math.pow(10, digits || 5);
          return Math.round(num * pow) / pow;
      },
  
      splitWords: function (str) {
          return str.replace(/^\s+|\s+$/g, '').split(/\s+/);
      },
  
      setOptions: function (obj, options) {
          obj.options = L.extend({}, obj.options, options);
          return obj.options;
      },
  
      getParamString: function (obj, existingUrl) {
          var params = [];
          for (var i in obj) {
              if (obj.hasOwnProperty(i)) {
                  params.push(i + '=' + obj[i]);
              }
          }
          return ((!existingUrl || existingUrl.indexOf('?') === -1) ? '?' : '&') + params.join('&');
      },
  
      template: function (str, data) {
          return str.replace(/\{ *([\w_]+) *\}/g, function (str, key) {
              var value = data[key];
              if (!data.hasOwnProperty(key)) {
                  throw new Error('No value provided for variable ' + str);
              }
              return value;
          });
      },
  
      isArray: function (obj) {
          return (Object.prototype.toString.call(obj) === '[object Array]');
      },
  
      emptyImageUrl: 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='
  };
  
  (function () {
  
      // inspired by http://paulirish.com/2011/requestanimationframe-for-smart-animating/
  
      function getPrefixed(name) {
          var i, fn,
              prefixes = ['webkit', 'moz', 'o', 'ms'];
  
          for (i = 0; i < prefixes.length && !fn; i++) {
              fn = window[prefixes[i] + name];
          }
  
          return fn;
      }
  
      var lastTime = 0;
  
      function timeoutDefer(fn) {
          var time = +new Date(),
              timeToCall = Math.max(0, 16 - (time - lastTime));
  
          lastTime = time + timeToCall;
          return window.setTimeout(fn, timeToCall);
      }
  
      var requestFn = window.requestAnimationFrame ||
          getPrefixed('RequestAnimationFrame') || timeoutDefer;
  
      var cancelFn = window.cancelAnimationFrame ||
          getPrefixed('CancelAnimationFrame') ||
          getPrefixed('CancelRequestAnimationFrame') ||
          function (id) { window.clearTimeout(id); };
  
  
      FM.Util.requestAnimFrame = function (fn, context, immediate, element) {
          fn = L.bind(fn, context);
  
          if (immediate && requestFn === timeoutDefer) {
              fn();
          } else {
              return requestFn.call(window, fn, element);
          }
      };
  
      FM.Util.cancelAnimFrame = function (id) {
          if (id) {
              cancelFn.call(window, id);
          }
      };
  
      FM.Util.replaceAll = function(text, stringToFind, stringToReplace) {
          return text.replace(new RegExp(stringToFind, 'g'), stringToReplace);
      },
  
      FM.Util.parseLayerRequest = function(layer) {
          var layerValues = eval(layer);
          var layerRequest = '';
          $.each(layerValues, function(key, value) {
              layerRequest += '&' + key + '=' + value;
          });
          return layerRequest;
      },
  
      FM.Util.randomID = function() {
          var randLetter = Math.random().toString(36).substring(7);
          return (randLetter + Date.now()).toLocaleLowerCase();
      },
  
      FM.Util.fire = function(item , type, data){
          var evt = document.createEvent("CustomEvent");
          evt.initCustomEvent(type, true, true, data);
          item.dispatchEvent(evt);
      }
  
      FM.Util.on = function(item , type, data, callback){
          item.addEventListener(type, callback, false);
      }
  
  }());
  
  // shortcuts for most used utility functions
  FM.extend = FM.Util.extend;
  FM.bind = FM.Util.bind;
  FM.stamp = FM.Util.stamp;
  FM.setOptions = FM.Util.setOptions;
  FM.loadModuleLibs = FM.Util.loadModuleLibs;
  FM.initializeLangProperties = FM.Util.initializeLangProperties;