(function() {

  var cache = {};
  var ajax = function(url) {
    if (!cache[url])
      cache[url] = new Promise(function(resolve, reject) {
        var x = new XMLHttpRequest();
        x.onreadystatechange = function() {
          if (x.readyState == 4)
            resolve(x.status == 200 ? x.responseText : null);
        };
        x.open("get", url, true);
        x.send();
      });
    return cache[url];
  };

  L.TileLayer.GeoJSON = L.LayerGroup.extend({
    options : {
      minZoom : 16,
      maxZoom : 16,
      zoom : 16
    },
    initialize : function(tmpl, options, geojson2layers) {
      L.Util.setOptions(this, options);
      this._tmpl = tmpl;
      this._geojson2layers = geojson2layers;
      L.LayerGroup.prototype.initialize.call(this);
    },
    onAdd : function(map) {
      L.LayerGroup.prototype.onAdd.call(this, map);
      this.update();
    },
    onRemove : function(map) {
      L.LayerGroup.prototype.onRemove.call(this, map);
    },
    getEvents : function() {
      return {
        "moveend" : this.update,
        "zoomend" : this.update
      };
    },

    update : function(event) {

      var map = this._map;
      var opt = this.options;
      var geojson2layers = this._geojson2layers;

      if (map.getZoom() > opt.maxZoom || map.getZoom() < opt.minZoom) {
        this.clearLayers();
        return;
      }

      var zoom = opt.zoom;
      var box = map.getBounds();
      var sw = map.project(box.getSouthWest(), zoom - 8).floor();
      var ne = map.project(box.getNorthEast(), zoom - 8).ceil();
      var coords = [];
      for (var y = ne.y - 1; y <= sw.y; y++) {
        for (var x = sw.x; x < ne.x; x++) {
          var coord = L.point(x, y);
          coord.z = zoom;
          coords.push(coord);
        }
      }

      var layers = {};
      for ( var key in this._layers) {
        var layer = this._layers[key];
        layers[layer.coords] = layer;
      }

      coords.forEach(function(c) {
        var key = c.toString();
        if (layers[key]) {
          delete layers[key];
          return;
        }

        var layer = L.layerGroup();
        this.addLayer(layer);
        layer.coords = key;

        var that = this;
        ajax(L.Util.template(that._tmpl, L.extend(c, opt))).then(function(txt) {
          var json = JSON.parse(txt);
          if (!json)
            return;
          geojson2layers(json).forEach(function(a) {
            layer.addLayer(a);
          });
        });

      }, this);

      for ( var key in layers) {
        this.removeLayer(layers[key]);
      }
    }
  });

  L.tileLayer.geoJson = function(tmpl, options, geojson2layers) {
    return new L.TileLayer.GeoJSON(tmpl, options, geojson2layers);
  };

})();
@@ -18,131 +18,592 @@
 var 
-cache = %7B%7D;%0A  var ajax = function(url) %7B
+ajax = %7B%0A    queue: %5B%5D,%0A    load: function(url) %7B%0A      var obj = null;%0A      this.queue.forEach(function(a) %7B%0A        obj = (a.url == url ? a : obj);%0A      %7D);
 %0A    
+  
 if (!
-cache%5Burl%5D)%0A      cache%5Burl%5D = new Promise(function(resolve, reject) %7B%0A  
+obj) %7B%0A        obj = %7B%0A          url: url%0A        %7D;%0A        obj.promise = new Promise(function(resolve, reject) %7B%0A          obj.resolve = resolve;%0A          obj.reject = reject;%0A        %7D);%0A        this.queue.push(obj);%0A        if (this.queue.length == 1)%0A          this.next();%0A      %7D%0A      return obj.promise;%0A    %7D,%0A    next: function() %7B%0A      var obj = this.queue.shift();%0A      if (!obj)%0A        return;%0A
     
@@ -630,26 +630,24 @@
 pRequest();%0A
-  
       x.onre
@@ -680,26 +680,24 @@
 ) %7B%0A        
- 
- 
 if (x.readyS
@@ -706,16 +706,18 @@
 te == 4)
+ %7B
 %0A       
@@ -719,18 +719,20 @@
         
-  
+obj.
 resolve(
@@ -777,29 +777,58 @@
 l);%0A        
+  ajax.next();%0A        %7D%0A      
 %7D;%0A
-  
       x.open
@@ -835,16 +835,20 @@
 (%22get%22, 
+obj.
 url, tru
@@ -851,18 +851,16 @@
  true);%0A
-  
       x.
@@ -875,36 +875,9 @@
     
-  %7D);%0A    return cache%5Burl%5D;
+%7D
 %0A  %7D
@@ -936,17 +936,16 @@
  options
- 
 : %7B%0A    
@@ -949,25 +949,24 @@
      minZoom
- 
 : 16,%0A      
@@ -972,17 +972,16 @@
  maxZoom
- 
 : 16,%0A  
@@ -988,17 +988,16 @@
     zoom
- 
 : 16%0A   
@@ -1014,17 +1014,16 @@
 itialize
- 
 : functi
@@ -1236,17 +1236,16 @@
    onAdd
- 
 : functi
@@ -1346,17 +1346,16 @@
 onRemove
- 
 : functi
@@ -1439,17 +1439,16 @@
 etEvents
- 
 : functi
@@ -1482,25 +1482,24 @@
    %22moveend%22
- 
 : this.updat
@@ -1518,17 +1518,16 @@
 zoomend%22
- 
 : this.u
@@ -1559,17 +1559,16 @@
   update
- 
 : functi
@@ -2255,33 +2255,32 @@
  %7B%7D;%0A      for (
- 
 var key in this.
@@ -2661,16 +2661,21 @@
     ajax
+.load
 (L.Util.
@@ -2953,17 +2953,16 @@
    for (
- 
 var key 
@@ -3178,8 +3178,9 @@
 ;%0A%0A%7D)();
+%0A

implement ajax loader