<commit_before>//====================================
leaflet_helper.constructors = {};
leaflet_helper.static_root = "/static";

// MIT-licensed code by <NAME>
// https://github.com/bbecquet/Leaflet.PolylineDecorator
L.RotatedMarker = null;
L.rotatedMarker = null;
//Set up base icon
var MapMarker = null;

leaflet_helper.init = function(){

    leaflet_helper.static_root = (typeof aoi_feature_edit!="undefined")?aoi_feature_edit.static_root:"/static";

    L.RotatedMarker = L.Marker.extend({
      options: { angle: 0 },
      _setPos: function(pos) {
        L.Marker.prototype._setPos.call(this, pos);
        if (L.DomUtil.TRANSFORM) {
          // use the CSS transform rule if available
          this._icon.style[L.DomUtil.TRANSFORM] += ' rotate(' + this.options.angle + 'deg)';
        } else if (L.Browser.ie) {
          // fallback for IE6, IE7, IE8
          var rad = this.options.angle * L.LatLng.DEG_TO_RAD,
          costheta = Math.cos(rad),
          sintheta = Math.sin(rad);
          this._icon.style.filter += ' progid:DXImageTransform.Microsoft.Matrix(sizingMethod=\'auto expand\', M11=' +
            costheta + ', M12=' + (-sintheta) + ', M21=' + sintheta + ', M22=' + costheta + ')';
        }
      }
    });
    L.rotatedMarker = function(pos, options) {
        return new L.RotatedMarker(pos, options);
    };
    //Set up base icon
    MapMarker = L.Icon.extend({
        options: {
            id: 0,
            shadowUrl: null,
            iconAnchor: new L.Point(7, 24),
            iconSize: new L.Point(15, 24),
            repeatMode: true,
            text: 'Social Media Pointer',
            iconUrl: leaflet_helper.static_root +"/leaflet/images/orange-marker-icon.png"
        }
    });

};

leaflet_helper.constructors.identifyParser = function(result, outputLayer){
    //Use GeoJSON as the standard to try if no matches are found
    var parser = L.GeoJSON;
    var parserName = "Leaflet GeoJSON";
    result = result || {};

    if (result.results && result.results.length &&
        result.results[0].layerName && result.results && result.results[0].attributes &&
        result.results[0].attributes.Latitude && result.results[0].attributes.ImageMissionId && result.results[0].attributes.ImageURL &&
        result.results[0].attributes.ThumbnailURL && result.results[0].attributes.Heading && result.results[0].geometryType) {

        //Parser is CAP imagery Format
        parser = leaflet_helper.parsers.addFEMAImageEventsData;
        parserName = "FEMA ImageEvents";

    } else if (result.results && result.results.length &&
               result.results[0].layerName && result.results && result.results[0].attributes &&
               result.results[0].attributes.dod_txt && result.results[0].attributes.event_id &&
               result.results[0].attributes.comments && result.results[0].attributes.OBJECTID &&
               result.results[0].geometryType) {

        parser = leaflet_helper.parsers.addNOAADamageAssessmentToolkit;
        parserName = "NOAA Damage Toolkit";

    } else if (result.geometryType && result.geometryType == "esriGeometryPoint" &&
               result.features && result.features.length &&
               result.features[0] && result.features[0].attributes) {

        //Parser is CAP imagery Format
        parser = leaflet_helper.parsers.addDynamicCapimageData;
        parserName = "CAP GeoJSON";

    } else if (result.stat == "ok" && result.photos && result.photos.page &&
               result.photos.photo && result.photos.perpage) {

        parser = leaflet_helper.parsers.flickrImages;
        parserName = "Flickr Photo Search";
    } else if (result.meta && result.meta.code && result.meta.code==200 &&
               result.data && _.isArray(result.data)) {

        parser = leaflet_helper.parsers.instagramImages;
        parserName = "Instagram Search";
    } else if (result && result.summary=="YouTube") {

        parser = leaflet_helper.parsers.youTube;
        parserName = "YouTube Videos";
    } else if (result && result.type && result.type=="FeatureCollection" && result.features && result.features[0] &&
        result.features[0].properties && result.features[0].properties.status && result.features[0].properties.created_at &&
        result.features[0].properties.analyst && result.features[0].properties.updated_at && result.features[0].properties.template ) {

        parser = leaflet_helper.parsers.geoq_exported_json;
        parserName = "GeoQ GeoJSON";

    } else if (result && result.type && result.type=="FeatureCollection" && result.features && result.features[0] &&
        result.features[0].properties && result.features[0].properties.status && result.features[0].properties.created_at &&
        result.features[0].properties.analyst && result.features[0].properties.updated_at && result.features[0].style) {

        parser = leaflet_helper.parsers.leaflet_geojson;
        parserName = "Leaflet GeoJSON";
    } else if (result && result.type && result.type=="FeatureCollection" && result.features && result.features[0] &&
        result.features[0].properties && result.features[0].properties.fulcrum_id && result.features[0].properties.created_at &&
        result.features[0].properties.system_created_at && result.features[0].properties.updated_at ) {

        parser = leaflet_helper.parsers.fulcrum_exported_json;
        parserName = "Fulcrum GeoJSON";



    } else if (result && result.type && result.type=="FeatureCollection" && result.features) {

        parser = leaflet_helper.parsers.basicJson;
        parserName = "Basic JSON";
    } else if (result && result.geonames && result.geonames.length && false) { //TODO: Why not turned on?

        parser = leaflet_helper.parsers.geoNameWikiData;
        parserName = "GeoName Lookup";

    } else if (result && outputLayer && outputLayer.config && outputLayer.config.type && outputLayer.config.type=="Web Data Link") {

        parser = leaflet_helper.parsers.webDataLink;
        parserName = "Web Data Lookup";
    } else if (result && result[0] && result[0].key && result[0].skey && result[0].clon!==undefined
        && result[0].clat!==undefined && result[0].location!==undefined && result[0].ca!==undefined
        && result[0].cd!==undefined && result[0].image_url!==undefined) {

        parser = leaflet_helper.parsers.mapillaryImages;
        parserName = "Mapillary Images";
    }
    //ADD new parser detectors here

    return {parser: parser, parserName:parserName};
};


leaflet_helper.constructors.urlTemplater =function(url, map, layer_json){
    if (!url || !url.indexOf || url.indexOf("{") < 0) return url;

    //Turn search strings into underscore templates to make parseable text (safer than an eval statement)
    _.templateSettings.interpolate = /\{\{(.+?)\}\}/g;
    var _url_template = _.template(url);

    //Get map info that will be added into the url if needed
    var mapExtent = map.getBounds();
    var center = map.getCenter();
    var size = map.getSize();
    var mapState={
        zoom:map.getZoom(),
        lat:center.lat,
        lon:center.lng,
        lng:center.lng,
        n:mapExtent._northEast.lat,
        s:mapExtent._southWest.lat,
        e:mapExtent._northEast.lng,
        w:mapExtent._southWest.lng,
        width:parseInt(size.x),
        height:parseInt(size.y),
        radius:2
    };
    mapState.bbox = mapState.w+","+mapState.n+","+mapState.e+","+mapState.s;

    //Feed the generated variables into the template, and return the result
    layer_json = $.extend(layer_json,mapState);
    layer_json.tags = aoi_feature_edit.tags  || "disaster";

    var new_url;
    try {
        new_url = _url_template(layer_json);
    } catch (ex) {
        log.error ("Error in parsing a URL template: " + ex.message);
    }

    return new_url || url;
};

leaflet_helper.constructors.geojson_layer_count = 0;
leaflet_helper.constructors.geojson = function(layerConfig, map, useLayerInstead) {

    if (!layerConfig) layerConfig = {};
    var url = layerConfig.url || "";

    if (layerConfig.type == 'ESRI Identifiable MapServer'){
        if (_.str.endsWith(url,'?')) url = url.substr(0,url.length-1);
        if (_.str.endsWith(url,'/')) url = url.substr(0,url.length-1);
        if (_.str.endsWith(url,'/export')) url = url.substr(0,url.length-7) + '/identity';
        url += '?geometryType=esriGeometryEnvelope&geometry={{bbox}}&mapExtent={{bbox}}';
        url += '&imageDisplay={{width}},{{height}},96&tolerance={{width}}&f=json&layers=visible:'+(layerConfig.layer||"all");
    }

    if (useLayerInstead && (useLayerInstead.geojson_layer_count !== undefined)) {
        layerConfig.geojson_layer_count = useLayerInstead.geojson_layer_count;
    } else {
        leaflet_helper.constructors.geojson_layer_count++;
        layerConfig.geojson_layer_count = leaflet_helper.constructors.geojson_layer_count;
    }

    function iconCallback(feature, latlng){
        var iconUrl = "";
        var iconX = 15;
        var iconY = 24;
        var iconAnchor = null;

        //TODO: Move these to a special iconParser?
        if (feature && feature.properties && feature.properties.icon_type=="ImageEvents" &&  feature.properties.layer_type) {

            var imageRoot = leaflet_helper.static_root +"/images/ImageEvents/";
            iconX = 14;
            iconY = 14;
            iconAnchor = new L.Point(7, 7);

            if (feature.properties.layer_type == "Aerial Oblique") {
                if (feature.properties.heading) {
                    //TODO: Rotate properly
                    iconUrl = imageRoot+"c5739cf19fe5e7635c04ae6eb2e7572f.png";
                } else {
                    iconUrl = imageRoot+"32d612809f495aa6e5491efbe6ebc8fd.png";
                }
            } else if (feature.properties.layer_type == "Aerial Oblique Target") {
                iconUrl = imageRoot+"f92b227dfe6c1fbdc122eeeef2904381.png";
            } else if (feature.properties.layer_type == "Aerial Oblique Line") {
                //Should only be lines and set in polygonStyleCallBack, keeping this as a backup
                iconUrl = imageRoot+"f92b227dfe6c1fbdc122eeeef2904381.png";

            } else if (feature.properties.layer_type == "Aerial Nadir") {
                iconUrl = imageRoot+"a2790e3ba9dcb053c40320e539a7ad59.png";


            } else if (feature.properties.layer_type == "Ground Images") {
                if (feature.properties.heading) {
                    //TODO: Validate that these are Rotated properly
                    iconUrl = imageRoot+"3353b7bc2d8b9fa6085b08ba446dfc8a.png";
                } else {
                    iconUrl = imageRoot+"5e65279a5d62555c05d2bc421e7ddc62.png";
                }
            } else if (feature.properties.layer_type == "Ground Targets") {
                iconUrl = imageRoot+"8e4c73a221dda8debdcf2658969c3670.png";
            } else if (feature.properties.layer_type == "Ground Lines") {
                //Should only be lines and set in polygonStyleCallBack, keeping this as a backup
                iconUrl = imageRoot+"8e4c73a221dda8debdcf2658969c3670.png";
            } else {
                var layerNum = layerConfig.geojson_layer_count % aoi_feature_edit.available_icons.length;
                iconUrl = aoi_feature_edit.available_icons[layerNum];
            }

        } else if (layerConfig && layerConfig.layerParams && (layerConfig.layerParams.icon || layerConfig.layerParams.iconUrl)) {
            iconUrl = layerConfig.layerParams.icon || layerConfig.layerParams.iconUrl;
            if (layerConfig.layerParams.iconX && layerConfig.layerParams.iconY) {
                iconX = layerConfig.layerParams.iconX;
                iconY = layerConfig.layerParams.iconY;
            }
        } else {
            var layerNum = layerConfig.geojson_layer_count % aoi_feature_edit.available_icons.length;
            iconUrl = aoi_feature_edit.available_icons[layerNum];
        }

        //Build the icon injects
        var iconData = {
            iconUrl: iconUrl,
            iconSize: new L.Point(iconX, iconY),
            text: layerConfig.name
        };
        if (iconAnchor) iconData.iconAnchor = iconAnchor;
        var icon = new MapMarker(iconData);

        //Construct the final Icon
        return L.rotatedMarker(latlng, {icon: icon});
    }

    var outputLayer = useLayerInstead || new L.geoJson(undefined,{
        onEachFeature: function(feature, layer) {leaflet_helper.parsers.standard_onEachFeature(feature, layer, layerConfig); },
        style: leaflet_helper.constructors.keepStyleBuilderCallback,
        pointToLayer: iconCallback
    });
    if (outputLayer.geojson_layer_count == undefined) {
        outputLayer.geojson_layer_count = layerConfig.geojson_layer_count;
    }

    if (outputLayer && !outputLayer.options) {
        outputLayer.options = {};
    }

    var opacity = 1;
    if (outputLayer.config) {
        opacity = outputLayer.config.shown ? outputLayer.config.opacity : 0;
    }

    outputLayer.options = $.extend(outputLayer.options, layerConfig.layerParams);

    outputLayer.options.opacity = opacity;
    outputLayer.options.style = outputLayer.options.style || {};
    outputLayer.options.style.opacity = opacity;

    url = leaflet_helper.constructors.urlTemplater(url, map, layerConfig.layerParams);
    var proxiedURL = leaflet_helper.proxify(url);

    $.ajax({
        type: 'GET',
        url: proxiedURL,
        dataType: layerConfig.format || 'json',
        success: function(data){
            leaflet_helper.constructors.geojson_success(data, proxiedURL, map, outputLayer);
            // try to set correct opacity
            leaflet_layer_control.setLayerOpacity(outputLayer, outputLayer.options.toShowOnLoad, true);
        },
        error: leaflet_helper.constructors.geojson_error
    });

    return outputLayer;
};
leaflet_helper.constructors.iconBuilderCallback = function(feature, latlng, layerConfig){
    var iconX = 15;
    var iconY = 24;
    var iconAnchor = null;

    layerConfig = layerConfig || {geojson_layer_count:1, name:'JSON Layer'};

    var layerNum = layerConfig.geojson_layer_count % aoi_feature_edit.available_icons.length;
    var iconUrl = aoi_feature_edit.available_icons[layerNum];

    //Build the icon injects
    var iconData = {
        iconUrl: iconUrl,
        iconSize: new L.Point(iconX, iconY),
        text: layerConfig.name
    };
    if (iconAnchor) iconData.iconAnchor = iconAnchor;
    var icon = new MapMarker(iconData);
<commit_msg>Make sure we check for good variables<commit_after>//====================================
leaflet_helper.constructors = {};
leaflet_helper.static_root = "/static";

// MIT-licensed code by <NAME>
// https://github.com/bbecquet/Leaflet.PolylineDecorator
L.RotatedMarker = null;
L.rotatedMarker = null;
//Set up base icon
var MapMarker = null;

leaflet_helper.init = function(){

    leaflet_helper.static_root = (typeof aoi_feature_edit!="undefined")?aoi_feature_edit.static_root:"/static";

    L.RotatedMarker = L.Marker.extend({
      options: { angle: 0 },
      _setPos: function(pos) {
        L.Marker.prototype._setPos.call(this, pos);
        if (L.DomUtil.TRANSFORM) {
          // use the CSS transform rule if available
          this._icon.style[L.DomUtil.TRANSFORM] += ' rotate(' + this.options.angle + 'deg)';
        } else if (L.Browser.ie) {
          // fallback for IE6, IE7, IE8
          var rad = this.options.angle * L.LatLng.DEG_TO_RAD,
          costheta = Math.cos(rad),
          sintheta = Math.sin(rad);
          this._icon.style.filter += ' progid:DXImageTransform.Microsoft.Matrix(sizingMethod=\'auto expand\', M11=' +
            costheta + ', M12=' + (-sintheta) + ', M21=' + sintheta + ', M22=' + costheta + ')';
        }
      }
    });
    L.rotatedMarker = function(pos, options) {
        return new L.RotatedMarker(pos, options);
    };
    //Set up base icon
    MapMarker = L.Icon.extend({
        options: {
            id: 0,
            shadowUrl: null,
            iconAnchor: new L.Point(7, 24),
            iconSize: new L.Point(15, 24),
            repeatMode: true,
            text: 'Social Media Pointer',
            iconUrl: leaflet_helper.static_root +"/leaflet/images/orange-marker-icon.png"
        }
    });

};

leaflet_helper.constructors.identifyParser = function(result, outputLayer){
    //Use GeoJSON as the standard to try if no matches are found
    var parser = L.GeoJSON;
    var parserName = "Leaflet GeoJSON";
    result = result || {};

    if (result.results && result.results.length &&
        result.results[0].layerName && result.results && result.results[0].attributes &&
        result.results[0].attributes.Latitude && result.results[0].attributes.ImageMissionId && result.results[0].attributes.ImageURL &&
        result.results[0].attributes.ThumbnailURL && result.results[0].attributes.Heading && result.results[0].geometryType) {

        //Parser is CAP imagery Format
        parser = leaflet_helper.parsers.addFEMAImageEventsData;
        parserName = "FEMA ImageEvents";

    } else if (result.results && result.results.length &&
               result.results[0].layerName && result.results && result.results[0].attributes &&
               result.results[0].attributes.dod_txt && result.results[0].attributes.event_id &&
               result.results[0].attributes.comments && result.results[0].attributes.OBJECTID &&
               result.results[0].geometryType) {

        parser = leaflet_helper.parsers.addNOAADamageAssessmentToolkit;
        parserName = "NOAA Damage Toolkit";

    } else if (result.geometryType && result.geometryType == "esriGeometryPoint" &&
               result.features && result.features.length &&
               result.features[0] && result.features[0].attributes) {

        //Parser is CAP imagery Format
        parser = leaflet_helper.parsers.addDynamicCapimageData;
        parserName = "CAP GeoJSON";

    } else if (result.stat == "ok" && result.photos && result.photos.page &&
               result.photos.photo && result.photos.perpage) {

        parser = leaflet_helper.parsers.flickrImages;
        parserName = "Flickr Photo Search";
    } else if (result.meta && result.meta.code && result.meta.code==200 &&
               result.data && _.isArray(result.data)) {

        parser = leaflet_helper.parsers.instagramImages;
        parserName = "Instagram Search";
    } else if (result && result.summary=="YouTube") {

        parser = leaflet_helper.parsers.youTube;
        parserName = "YouTube Videos";
    } else if (result && result.type && result.type=="FeatureCollection" && result.features && result.features[0] &&
        result.features[0].properties && result.features[0].properties.status && result.features[0].properties.created_at &&
        result.features[0].properties.analyst && result.features[0].properties.updated_at && result.features[0].properties.template ) {

        parser = leaflet_helper.parsers.geoq_exported_json;
        parserName = "GeoQ GeoJSON";

    } else if (result && result.type && result.type=="FeatureCollection" && result.features && result.features[0] &&
        result.features[0].properties && result.features[0].properties.status && result.features[0].properties.created_at &&
        result.features[0].properties.analyst && result.features[0].properties.updated_at && result.features[0].style) {

        parser = leaflet_helper.parsers.leaflet_geojson;
        parserName = "Leaflet GeoJSON";
    } else if (result && result.type && result.type=="FeatureCollection" && result.features && result.features[0] &&
        result.features[0].properties && result.features[0].properties.fulcrum_id && result.features[0].properties.created_at &&
        result.features[0].properties.system_created_at && result.features[0].properties.updated_at ) {

        parser = leaflet_helper.parsers.fulcrum_exported_json;
        parserName = "Fulcrum GeoJSON";



    } else if (result && result.type && result.type=="FeatureCollection" && result.features) {

        parser = leaflet_helper.parsers.basicJson;
        parserName = "Basic JSON";
    } else if (result && result.geonames && result.geonames.length && false) { //TODO: Why not turned on?

        parser = leaflet_helper.parsers.geoNameWikiData;
        parserName = "GeoName Lookup";

    } else if (result && outputLayer && outputLayer.config && outputLayer.config.type && outputLayer.config.type=="Web Data Link") {

        parser = leaflet_helper.parsers.webDataLink;
        parserName = "Web Data Lookup";
    } else if (result && result[0] && result[0].key && result[0].skey && result[0].clon!==undefined
        && result[0].clat!==undefined && result[0].location!==undefined && result[0].ca!==undefined
        && result[0].cd!==undefined && result[0].image_url!==undefined) {

        parser = leaflet_helper.parsers.mapillaryImages;
        parserName = "Mapillary Images";
    }
    //ADD new parser detectors here

    return {parser: parser, parserName:parserName};
};


leaflet_helper.constructors.urlTemplater =function(url, map, layer_json){
    if (!url || !url.indexOf || url.indexOf("{") < 0) return url;

    //Turn search strings into underscore templates to make parseable text (safer than an eval statement)
    _.templateSettings.interpolate = /\{\{(.+?)\}\}/g;
    var _url_template = _.template(url);

    //Get map info that will be added into the url if needed
    var mapExtent = map.getBounds();
    var center = map.getCenter();
    var size = map.getSize();
    var mapState={
        zoom:map.getZoom(),
        lat:center.lat,
        lon:center.lng,
        lng:center.lng,
        n:mapExtent._northEast.lat,
        s:mapExtent._southWest.lat,
        e:mapExtent._northEast.lng,
        w:mapExtent._southWest.lng,
        width:parseInt(size.x),
        height:parseInt(size.y),
        radius:2
    };
    mapState.bbox = mapState.w+","+mapState.n+","+mapState.e+","+mapState.s;

    //Feed the generated variables into the template, and return the result
    layer_json = $.extend(layer_json,mapState);
    layer_json.tags = aoi_feature_edit.tags  || "disaster";

    var new_url;
    try {
        new_url = _url_template(layer_json);
    } catch (ex) {
        log.error ("Error in parsing a URL template: " + ex.message);
    }

    return new_url || url;
};

leaflet_helper.constructors.geojson_layer_count = 0;
leaflet_helper.constructors.geojson = function(layerConfig, map, useLayerInstead) {

    if (!layerConfig) layerConfig = {};
    var url = layerConfig.url || "";

    if (layerConfig.type == 'ESRI Identifiable MapServer'){
        if (_.str.endsWith(url,'?')) url = url.substr(0,url.length-1);
        if (_.str.endsWith(url,'/')) url = url.substr(0,url.length-1);
        if (_.str.endsWith(url,'/export')) url = url.substr(0,url.length-7) + '/identity';
        url += '?geometryType=esriGeometryEnvelope&geometry={{bbox}}&mapExtent={{bbox}}';
        url += '&imageDisplay={{width}},{{height}},96&tolerance={{width}}&f=json&layers=visible:'+(layerConfig.layer||"all");
    }

    if (useLayerInstead && (useLayerInstead.geojson_layer_count !== undefined)) {
        layerConfig.geojson_layer_count = useLayerInstead.geojson_layer_count;
    } else {
        leaflet_helper.constructors.geojson_layer_count++;
        layerConfig.geojson_layer_count = leaflet_helper.constructors.geojson_layer_count;
    }

    function iconCallback(feature, latlng){
        var iconUrl = "";
        var iconX = 15;
        var iconY = 24;
        var iconAnchor = null;

        //TODO: Move these to a special iconParser?
        if (feature && feature.properties && feature.properties.icon_type=="ImageEvents" &&  feature.properties.layer_type) {

            var imageRoot = leaflet_helper.static_root +"/images/ImageEvents/";
            iconX = 14;
            iconY = 14;
            iconAnchor = new L.Point(7, 7);

            if (feature.properties.layer_type == "Aerial Oblique") {
                if (feature.properties.heading) {
                    //TODO: Rotate properly
                    iconUrl = imageRoot+"c5739cf19fe5e7635c04ae6eb2e7572f.png";
                } else {
                    iconUrl = imageRoot+"32d612809f495aa6e5491efbe6ebc8fd.png";
                }
            } else if (feature.properties.layer_type == "Aerial Oblique Target") {
                iconUrl = imageRoot+"f92b227dfe6c1fbdc122eeeef2904381.png";
            } else if (feature.properties.layer_type == "Aerial Oblique Line") {
                //Should only be lines and set in polygonStyleCallBack, keeping this as a backup
                iconUrl = imageRoot+"f92b227dfe6c1fbdc122eeeef2904381.png";

            } else if (feature.properties.layer_type == "Aerial Nadir") {
                iconUrl = imageRoot+"a2790e3ba9dcb053c40320e539a7ad59.png";


            } else if (feature.properties.layer_type == "Ground Images") {
                if (feature.properties.heading) {
                    //TODO: Validate that these are Rotated properly
                    iconUrl = imageRoot+"3353b7bc2d8b9fa6085b08ba446dfc8a.png";
                } else {
                    iconUrl = imageRoot+"5e65279a5d62555c05d2bc421e7ddc62.png";
                }
            } else if (feature.properties.layer_type == "Ground Targets") {
                iconUrl = imageRoot+"8e4c73a221dda8debdcf2658969c3670.png";
            } else if (feature.properties.layer_type == "Ground Lines") {
                //Should only be lines and set in polygonStyleCallBack, keeping this as a backup
                iconUrl = imageRoot+"8e4c73a221dda8debdcf2658969c3670.png";
            } else {
                var layerNum = layerConfig.geojson_layer_count % aoi_feature_edit.available_icons.length;
                iconUrl = aoi_feature_edit.available_icons[layerNum];
            }

        } else if (layerConfig && layerConfig.layerParams && (layerConfig.layerParams.icon || layerConfig.layerParams.iconUrl)) {
            iconUrl = layerConfig.layerParams.icon || layerConfig.layerParams.iconUrl;
            if (layerConfig.layerParams.iconX && layerConfig.layerParams.iconY) {
                iconX = layerConfig.layerParams.iconX;
                iconY = layerConfig.layerParams.iconY;
            }
        } else {
            var layerNum = layerConfig.geojson_layer_count % aoi_feature_edit.available_icons.length;
            iconUrl = aoi_feature_edit.available_icons[layerNum];
        }

        //Build the icon injects
        var iconData = {
            iconUrl: iconUrl,
            iconSize: new L.Point(iconX, iconY),
            text: layerConfig.name
        };
        if (iconAnchor) iconData.iconAnchor = iconAnchor;
        var icon = new MapMarker(iconData);

        //Construct the final Icon
        return L.rotatedMarker(latlng, {icon: icon});
    }

    var outputLayer = useLayerInstead || new L.geoJson(undefined,{
        onEachFeature: function(feature, layer) {leaflet_helper.parsers.standard_onEachFeature(feature, layer, layerConfig); },
        style: leaflet_helper.constructors.keepStyleBuilderCallback,
        pointToLayer: iconCallback
    });
    if (outputLayer.geojson_layer_count == undefined) {
        outputLayer.geojson_layer_count = layerConfig.geojson_layer_count;
    }

    if (outputLayer && !outputLayer.options) {
        outputLayer.options = {};
    }

    var opacity = 1;
    if (outputLayer.config) {
        opacity = outputLayer.config.shown ? outputLayer.config.opacity : 0;
    }

    outputLayer.options = $.extend(outputLayer.options, layerConfig.layerParams);

    outputLayer.options.opacity = opacity;
    outputLayer.options.style = outputLayer.options.style || {};
    outputLayer.options.style.opacity = opacity;

    url = leaflet_helper.constructors.urlTemplater(url, map, layerConfig.layerParams);
    var proxiedURL = leaflet_helper.proxify(url);

    $.ajax({
        type: 'GET',
        url: proxiedURL,
        dataType: layerConfig.format || 'json',
        success: function(data){
            leaflet_helper.constructors.geojson_success(data, proxiedURL, map, outputLayer);
            // try to set correct opacity
            if (outputLayer && outputLayer.options && outputLayer.options.toShowOnLoad) {
                leaflet_layer_control.setLayerOpacity(outputLayer, outputLayer.options.toShowOnLoad, true);
            }
        },
        error: leaflet_helper.constructors.geojson_error
    });

    return outputLayer;
};
leaflet_helper.constructors.iconBuilderCallback = function(feature, latlng, layerConfig){
    var iconX = 15;
    var iconY = 24;
    var iconAnchor = null;

    layerConfig = layerConfig || {geojson_layer_count:1, name:'JSON Layer'};

    var layerNum = layerConfig.geojson_layer_count % aoi_feature_edit.available_icons.length;
    var iconUrl = aoi_feature_edit.available_icons[layerNum];

    //Build the icon injects
    var iconData = {
        iconUrl: iconUrl,
        iconSize: new L.Point(iconX, iconY),
        text: layerConfig.name
    };
    if (iconAnchor) iconData.iconAnchor = iconAnchor;
    var icon = new MapMarker(iconData);

{'fraction_non_alphanumeric': 0.12588396841743907, 'fraction_numerical': 0.018194301407483692, 'mean_word_length': 2.7852130977130978, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 5, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4257969', 'n_tokens_mistral': 9054, 'n_tokens_neox': 8570, 'n_words': 1628}