makinacorpus / django-leaflet

Use Leaflet in your Django projects
GNU Lesser General Public License v3.0
716 stars 282 forks source link

Customized Widget in IE11: 'geom' is not defined #184

Closed Schumi09 closed 7 years ago

Schumi09 commented 7 years ago

Hi there,

I wanted to make use of a customized form widget so I got control about the geometry etc.

While modern browsers like Chrome or FF don't seem to have any issues, I get

'geom' is not defined

in

function id_site_location_geom_map_callback(map, options) {
        geodjango_id_site_location_geom.store_class = L.FieldStore;
        (new geom(geodjango_id_site_location_geom)).addTo(map);        
};

I couldn't find anything related here, is there something known?

What I've done is

geom = L.GeometryField.extend({
                addTo: function (map) {
                    L.GeometryField.prototype.addTo.call(this, map);
                    // Customize map for field
                    drawControl = this._drawControl;
                    drawControl._toolbars.draw.options.polyline = false;
                    drawControl._toolbars.draw.options.marker = false;
                    map.addControl(drawControl);
                },
            });
class Model(models.Model):
    address = models.CharField(max_length=256)
    geom = PolygonField()

class ExtLeafletWidget(LeafletWidget): geometry_field_class = 'geom'

class SiteLocationForm(forms.ModelForm):

    class Meta:
        model = Model
        fields = ('address', 'geom')
        widgets = {'geom': ExtLeafletWidget()}

    def __init__(self, *args, **kwargs):
        super(forms.ModelForm, self).__init__(*args, **kwargs)
        self.fields['address'].widget = forms.HiddenInput()
        self.fields['geom'].help_text = None
        self.fields['geom'].label = ''

As it works in other browsers I dont think I did anything wrong.

I would appreciate any kind of help, Thanks for this amazing project 👍

Gagaro commented 7 years ago

You shouldn't need to make your own javascript GeometryField if you use the PolygonField from django.leaflet in your model.

What is the full stack trace ?

Schumi09 commented 7 years ago

Thanks for your fast reply. Seems like I missed the point of it completly.

What's the best way to disable certain drawing tools? Right now I'm using

map.on('map:loadfield', function (e) {
                drawControl = e.field._drawControl;
                drawControl._toolbars.draw.options.polyline = false;
                drawControl._toolbars.draw.options.marker = false;
                map.addControl(drawControl);
            });

But obviously IE ignores it. It looks a bit hacky anyway. Are there some settings?

Unfortunately I can't provide you a full stack trace. My project ist not set up that far right now :(

Gagaro commented 7 years ago

Actually, you may need to change the field on your form directly. Something like:

from leaflet.forms.fields import PolygonField

class SiteLocationForm(forms.ModelForm):
    geom = PolygonField()

    class Meta:
        model = Model
        fields = ('address', 'geom')

or

class SiteLocationForm(forms.ModelForm):

    class Meta:
        model = Model
        fields = ('address', 'geom')
        widgets = {'geom': LeafletWidget(geom_type="POLYGON")}

If you want full control on the drawing tools, you will need to have your own JS GeometryField. There is a _controlDrawOptions method:

YourGeometryField = L.GeometryField.extend({
    _controlDrawOptions: function () {
        return {
            edit: {
                featureGroup: this.drawnItems
            },
            draw: {
                polyline: this.options.is_linestring,
                polygon: this.options.is_polygon,
                circle: false, // Turns off this drawing tool
                rectangle: this.options.is_polygon,
                marker: this.options.is_point,
            }
        };
    }
});
Schumi09 commented 7 years ago

It works pretty well, even in IE 👍

Unfortunately one thing that does not work in IE is adding another controls, e.g. Layer or Geocoding

Simple example would be

var osm = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
                attribution: '&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
            });
var baseMaps = {"OpenStreetMap": osm,};
osm.addTo(map);
L.control.layers(baseMaps).addTo(map);

Works in other browsers, not in IE11. Any idea? ;)

Gagaro commented 7 years ago

I never really tried that with IE, I can't really help you on that, sorry :disappointed: .

Schumi09 commented 7 years ago

As my project meanwhile relies on jQuery I could use $(window).on('map:init', function (e) { }); instead of window.addEventListener("map:init", function (e) {}); 👍