<commit_before>{% load maps leaflet_tags geojson_tags static %}

{% leaflet_map module fitextent=False %}
<style type="text/css">
    {% if not display_wkt %}#{{ attrs.id }} { display: none; }{% endif %}
</style>

<link rel="stylesheet" href="{% static "Leaflet.draw/leaflet.draw.css" %}"></link>
<script type="text/javascript" src="{% static "Leaflet.draw/leaflet.draw.js" %}"></script>

<script type="text/javascript" src="{% static "js/dijkstra.js" %}"></script>
<script type="text/javascript" src="{% static "core/multipath.js" %}"></script>
<script type="text/javascript" src="{% static "mapentity/mapentity.js" %}"></script>


{% if display_wkt %}<p> WKT debugging window:</p>{% endif %}
{% include "floppyforms/textarea.html" %}

<script type="text/javascript">
if (! {{ module }}); var {{ module }} = {};


{{ module }}.enableDrawing = function(map, drawncallback, startovercallback) {
    var drawControl = new L.Control.Draw({
        position: 'topright',
        polygon: {{ is_polygone|yesno:"true,false" }},
        rectangle: false,
        circle: false,
        marker: {{ is_point|yesno:"true,false" }},
        polyline: {{ is_linestring|yesno:"true,false" }} && {
            shapeOptions: {
                color: '#35FF00',
                opacity: 0.8,
                weight: 3
            }
        }
    });
    map.addControl(drawControl);
    map.drawControl = drawControl;

    // Delete current on first clic (start drawing)
    map.on('click', function (e) {
        // Delete current on clic if drawing
        for (var handlertype in map.drawControl.handlers) {
            if (map.drawControl.handlers[handlertype].enabled()) {
                startovercallback();
                return;
            }
        }
    });

    // Listen to all events of creation, Leaflet.Draw naming inconsistency
    var draw_types = {
        'polyline': 'poly',
        'point': 'marker',
        'polygon': 'polygon',
    };
    for (var geomtype in draw_types) {
        var draw_type = draw_types[geomtype];
        map.on('draw:' + draw_type + '-created', L.Util.bind(function (e) {
            console.log('Drawn ' + this.type);
            var drawn = e[this.type];  // Leaflet.Draw naming inconsistency
            drawncallback(drawn);
        }, {type: draw_type}));
    }
};


{{ module }}.enablePathSnapping = function(map, modelname, objectsLayer) {
    var snapObserver = null;
    MapEntity.SnapObserver.MIN_SNAP_ZOOM = {{ min_snap_zoom }};
    // Snapping is always on paths layer. But only if model is not path,
    // since snapping will then be on objects layer. 
    // Allows to save loading twice the same layer.
    if (modelname != 'path') {
        var pathsLayer = new Caminae.ObjectsLayer(null, {
            style: {weight: 2, clickable: true},
        });
        map.addLayer(pathsLayer);
        snapObserver = new MapEntity.SnapObserver(map, pathsLayer);
        // Start ajax loading at last
        pathsLayer.load("{% url core:path_layer %}");
    }
    else {
        snapObserver = new MapEntity.SnapObserver(map, objectsLayer);
    }
    return snapObserver;
};


{{ module }}.addObjectsLayer = function(map, modelname) {
    // On creation, this should be null
    var object_pk = $('form input[name="pk"]').val() || null;

    var exclude_current_object = null;
    if (object_pk) {
        exclude_current_object = function (geojson) {
            if (geojson.properties && geojson.properties.pk)
                return geojson.properties.pk != object_pk;
        }
    }

    // Start loading all objects, readonly
    // Build URL like an animal, please don't tell my mother.
    var objectsLayer = new Caminae.ObjectsLayer(null, {
            style: {weight: 2, clickable: true},
            filter: exclude_current_object
        }),
        url = '{% url core:path_layer %}'.replace(new RegExp('path', 'g'), modelname); // OMG, another way for JS url rewriting
    map.addLayer(objectsLayer);
    objectsLayer.load(url);
    return objectsLayer;
};

{{ module }}.enableMultipath = function(map, objectsLayer, layerStore) {
    objectsLayer.on('load', function() {
        $.getJSON('{% url core:path_json_graph %}', function(graph) {

            var dijkstra = {
                'compute_path': Caminae.compute_path,
                'graph': graph
            };

            var multipath_control = new L.Control.Multipath(map, objectsLayer, dijkstra);
            multipath_control.multipath_handler.on('computed_paths', function(data) {
                var new_edges = data['new_edges'];

                // Gather all LatLngs - $.map autoconcatenate
                var lls = $.map(new_edges, function(edge) {
                    return objectsLayer.getLayer(edge.id).getLatLngs(); 
                });

                // This is just used to get the WKT
                // TODO: later we should pass list of pks instead of resulting geom
                var layer = new L.Polyline(lls);

                layerStore.storeLayerGeomInField(layer);
            });

            map.addControl(multipath_control);

        });
    });
};

{{ module }}.init = function(map, bounds) {
    map.removeControl(map.attributionControl);
    
    /*** <Map bounds and reset> ***/
    
    var initialBounds = bounds,
         objectBounds = {{ field|latlngbounds }},
         currentBounds = objectBounds || initialBounds;
    getBounds = function () {
        return currentBounds;
    };
    map.addControl(new L.Control.ResetView(getBounds));
    map.fitBounds(currentBounds);
    map.addControl(new L.Control.Scale());

    // Show other objects of same type
    var modelname = $('form input[name="model"]').val(),
        objectsLayer = {{ module }}.addObjectsLayer(map, modelname);
    
    // Enable snapping ?
    var path_snapping = {{ path_snapping|yesno:"true,false" }};
    var snapObserver = null;
    if (path_snapping) {
        snapObserver = {{ module }}.enablePathSnapping(map, modelname, objectsLayer);
    }

    var layerStore = MapEntity.makeGeoFieldProxy($('#{{ attrs.id }}'));

    /*** <objectLayer> ***/

    var geojson = {{ field|geojsonfeature|safe }};  // If no field, will be null.
    var objectLayer = new L.GeoJSON(geojson, {
        style: {weight: 5, opacity: 1, clickable: true},
        onEachFeature: function (feature, layer) {
            onNewLayer(layer);
        }
    });
    map.addLayer(objectLayer);

    function _edit_handler(map, layer) {
        var edit_handler = L.Handler.PolyEdit;
        if (path_snapping) {
            edit_handler = L.Handler.SnappedEdit;
            if (layer instanceof L.Marker) {
                edit_handler =  MapEntity.MarkerSnapping;
            }
        }
        return new edit_handler(map, layer);
    };
    
    function onNewLayer(new_layer) {
        if (new_layer instanceof L.Marker) {
            currentBounds = map.getBounds(); // A point has no bounds, take map bounds
            // Set custom icon, using CSS instead of JS
            new_layer.setIcon(new L.Icon({
                iconUrl:'{% static "images/marker-trans.png" %}',
                shadowUrl:'{% static "leaflet/images/marker-shadow.png" %}',
                iconSize: new L.Point(25, 41),<commit_msg>Extracted all django specific settings into a json options - (ref #129)<commit_after>{% load maps leaflet_tags geojson_tags static %}

{% leaflet_map module fitextent=False %}
<style type="text/css">
    {% if not display_wkt %}#{{ attrs.id }} { display: none; }{% endif %}
</style>

<link rel="stylesheet" href="{% static "Leaflet.draw/leaflet.draw.css" %}"></link>
<script type="text/javascript" src="{% static "Leaflet.draw/leaflet.draw.js" %}"></script>

<script type="text/javascript" src="{% static "js/dijkstra.js" %}"></script>
<script type="text/javascript" src="{% static "core/multipath.js" %}"></script>
<script type="text/javascript" src="{% static "mapentity/mapentity.js" %}"></script>


{% if display_wkt %}<p> WKT debugging window:</p>{% endif %}
{% include "floppyforms/textarea.html" %}

<script type="text/javascript">
if (! {{ module }}); var {{ module }} = {};

var {{ module }}_settings = {
    'enableDrawing': {
        'is_polygon': {{ is_polygone|yesno:"true,false" }},
        'is_marker': {{ is_point|yesno:"true,false" }},
        'is_polyline': {{ is_linestring|yesno:"true,false" }}
    },
    'enablePathSnapping': {
        'MIN_SNAP_ZOOM': {{ min_snap_zoom }},
        'pathsLayer_url': "{% url core:path_layer %}"
    },
    'addObjectsLayer': {
        // OMG, another way for JS url rewriting
        'getUrl': function(modelname) {
            return '{% url core:path_layer %}'.replace(new RegExp('path', 'g'), modelname);
        }
    },
    'enableMultipath': {
        'path_json_graph_url': '{% url core:path_json_graph %}'
    },
    'init': {
        'objectBounds': {{ field|latlngbounds }},
        'path_snapping': {{ path_snapping|yesno:"true,false" }},
        'layerStoreElemSelector': '#{{ attrs.id }}',
        'geojson': {{ field|geojsonfeature|safe }},  // If no field, will be null.
        'iconUrl': '{% static "images/marker-trans.png" %}',
        'shadowUrl': '{% static "leaflet/images/marker-shadow.png" %}'
    }
};


{{ module }}.enableDrawing = function(map, drawncallback, startovercallback) {
    var drawControl = new L.Control.Draw({
        position: 'topright',
        polygon: {{ module }}_settings.enableDrawing.is_polygon,
        rectangle: false,
        circle: false,
        marker: {{ module }}_settings.enableDrawing.is_marker,
        polyline: {{ module }}_settings.enableDrawing.is_polyline && {
            shapeOptions: {
                color: '#35FF00',
                opacity: 0.8,
                weight: 3
            }
        }
    });
    map.addControl(drawControl);
    map.drawControl = drawControl;

    // Delete current on first clic (start drawing)
    map.on('click', function (e) {
        // Delete current on clic if drawing
        for (var handlertype in map.drawControl.handlers) {
            if (map.drawControl.handlers[handlertype].enabled()) {
                startovercallback();
                return;
            }
        }
    });

    // Listen to all events of creation, Leaflet.Draw naming inconsistency
    var draw_types = {
        'polyline': 'poly',
        'point': 'marker',
        'polygon': 'polygon',
    };
    for (var geomtype in draw_types) {
        var draw_type = draw_types[geomtype];
        map.on('draw:' + draw_type + '-created', L.Util.bind(function (e) {
            console.log('Drawn ' + this.type);
            var drawn = e[this.type];  // Leaflet.Draw naming inconsistency
            drawncallback(drawn);
        }, {type: draw_type}));
    }
};


{{ module }}.enablePathSnapping = function(map, modelname, objectsLayer) {
    var snapObserver = null;
    MapEntity.SnapObserver.MIN_SNAP_ZOOM = {{ module }}_settings.enablePathSnapping.MIN_SNAP_ZOOM;
    // Snapping is always on paths layer. But only if model is not path,
    // since snapping will then be on objects layer. 
    // Allows to save loading twice the same layer.
    if (modelname != 'path') {
        var pathsLayer = new Caminae.ObjectsLayer(null, {
            style: {weight: 2, clickable: true},
        });
        map.addLayer(pathsLayer);
        snapObserver = new MapEntity.SnapObserver(map, pathsLayer);
        // Start ajax loading at last
        pathsLayer.load({{ module }}_settings.enablePathSnapping.pathsLayer_url);
    }
    else {
        snapObserver = new MapEntity.SnapObserver(map, objectsLayer);
    }
    return snapObserver;
};


{{ module }}.addObjectsLayer = function(map, modelname) {
    // On creation, this should be null
    var object_pk = $('form input[name="pk"]').val() || null;

    var exclude_current_object = null;
    if (object_pk) {
        exclude_current_object = function (geojson) {
            if (geojson.properties && geojson.properties.pk)
                return geojson.properties.pk != object_pk;
        }
    }

    // Start loading all objects, readonly
    // Build URL like an animal, please don't tell my mother.
    var objectsLayer = new Caminae.ObjectsLayer(null, {
            style: {weight: 2, clickable: true},
            filter: exclude_current_object
        }),
        url = {{ module }}_settings.addObjectsLayer.getUrl(modelname);
    map.addLayer(objectsLayer);
    objectsLayer.load(url);
    return objectsLayer;
};

{{ module }}.enableMultipath = function(map, objectsLayer, layerStore) {
    objectsLayer.on('load', function() {
        $.getJSON({{ module }}_settings.enableMultipath.path_json_graph_url, function(graph) {

            var dijkstra = {
                'compute_path': Caminae.compute_path,
                'graph': graph
            };

            var multipath_control = new L.Control.Multipath(map, objectsLayer, dijkstra);
            multipath_control.multipath_handler.on('computed_paths', function(data) {
                var new_edges = data['new_edges'];

                // Gather all LatLngs - $.map autoconcatenate
                var lls = $.map(new_edges, function(edge) {
                    return objectsLayer.getLayer(edge.id).getLatLngs(); 
                });

                // This is just used to get the WKT
                // TODO: later we should pass list of pks instead of resulting geom
                var layer = new L.Polyline(lls);

                layerStore.storeLayerGeomInField(layer);
            });

            map.addControl(multipath_control);

        });
    });
};

{{ module }}.init = function(map, bounds) {
    map.removeControl(map.attributionControl);
    
    /*** <Map bounds and reset> ***/
    
    var initialBounds = bounds,
        objectBounds = {{ module }}_settings.init.objectsBounds,
         currentBounds = objectBounds || initialBounds;
    getBounds = function () {
        return currentBounds;
    };
    map.addControl(new L.Control.ResetView(getBounds));
    map.fitBounds(currentBounds);
    map.addControl(new L.Control.Scale());

    // Show other objects of same type
    var modelname = $('form input[name="model"]').val(),
        objectsLayer = {{ module }}.addObjectsLayer(map, modelname);
    
    // Enable snapping ?
    var path_snapping = {{ module }}_settings.init.path_snapping;
    var snapObserver = null;
    if (path_snapping) {
        snapObserver = {{ module }}.enablePathSnapping(map, modelname, objectsLayer);
    }

    var layerStore = MapEntity.makeGeoFieldProxy($({{ module }}_settings.init.layerStoreElemSelector));

    /*** <objectLayer> ***/

    var geojson = {{ module }}_settings.init.geojson;  // If no field, will be null.
    var objectLayer = new L.GeoJSON(geojson, {
        style: {weight: 5, opacity: 1, clickable: true},
        onEachFeature: function (feature, layer) {
            onNewLayer(layer);
        }
    });
    map.addLayer(objectLayer);

    function _edit_handler(map, layer) {
        var edit_handler = L.Handler.PolyEdit;
        if (path_snapping) {
            edit_handler = L.Handler.SnappedEdit;
            if (layer instanceof L.Marker) {
                edit_handler =  MapEntity.MarkerSnapping;
            }
        }
        return new edit_handler(map, layer);
    };
    
    function onNewLayer(new_layer) {
        if (new_layer instanceof L.Marker) {
            currentBounds = map.getBounds(); // A point has no bounds, take map bounds
            // Set custom icon, using CSS instead of JS
            new_layer.setIcon(new L.Icon({
                iconUrl: {{ module }}_settings.init.iconUrl,
                shadowUrl: {{ module }}_settings.init.shadowUrl,
                iconSize: new L.Point(25, 41),
{'fraction_non_alphanumeric': 0.13639256619144602, 'fraction_numerical': 0.00210030549898167, 'mean_word_length': 2.441305300043802, 'pattern_counts': {'":': 0, '<': 37, '<?xml version=': 0, '>': 37, 'https://': 0, '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': '5827112', 'n_tokens_mistral': 4778, 'n_tokens_neox': 4561, 'n_words': 1088}