function keydown() {
     if (d3.event.altKey) {
         freeDraw.setMode(L.FreeDraw.MODES.EDIT);
     }
     if (d3.event.metaKey | d3.event.shiftKey) {
         freeDraw.setMode(L.FreeDraw.MODES.VIEW);
     }
     if (d3.event.shiftKey & (d3.event.keyCode == 37 | d3.event.keyCode == 39)) {
         d3.event.preventDefault();
         if (d3.event.keyCode == 37) {
             colorIndex = mod(colorIndex - 1, COLOR_MODES.length);
         }
         if (d3.event.keyCode == 39) {
             colorIndex = mod(colorIndex + 1, COLOR_MODES.length);
         }
         updateStyles();
     }
 }
    img.onload = function() {

        // get image dimensions
        var imw = img.width;
        var imh = img.height;

        // use image dimensions to set css
        var w = maxWidth,
            h = maxWidth * (imh / imw);

        self.$el.find('#image-map-' + self.mid).width(w).height(h);

        //create the map
        if(self.map) {
            self.map.remove();    
        }
        self.map = L.map('image-map-' + self.mid, {
            minZoom: 1,
            maxZoom: 8,
            center: [w/2, h/2],
            zoom: 1,
            attributionControl: false,
            zoomControl: false,
            crs: L.CRS.Simple,
        });
        
        var map = self.map;
             
        // calculate the edges of the image, in coordinate space
        var southWest = map.unproject([0, h], 1);
        var northEast = map.unproject([w, 0], 1);
        var bounds = new L.LatLngBounds(southWest, northEast);
         
        // add the image overlay to cover the map
        var overlay = L.imageOverlay(img.src, bounds);
        map.addLayer(overlay)
         
        // tell leaflet that the map is exactly as big as the image
        map.setMaxBounds(bounds);

        // add free drawing
        var freeDraw = new L.FreeDraw({
          mode: L.FreeDraw.MODES.CREATE | L.FreeDraw.MODES.DELETE | L.FreeDraw.MODES.DELETE,
        });

        // set free drawing options
        freeDraw.options.attemptMerge = false;
        freeDraw.options.setHullAlgorithm('brian3kb/graham_scan_js');
        freeDraw.options.setSmoothFactor(0);
        
        // add the free drawing layer
        map.addLayer(freeDraw);

        // initialize with any polygons from the data
        if (!_.isEmpty(data)) {

            var polygons = data.polygons;

            polygons = polygons.map(function (g) {
                var converted = [];
                g.map(function (p) {
                    var newp = new L.point(p[0] / (imw / w), p[1] / (imh / h), false);
                    var newpoint = map.unproject(newp, 1);
                    converted.push(newpoint);
                });
                return converted;
            });

            freeDraw.options.simplifyPolygon = false;
            polygons.forEach(function (g) {
                freeDraw.createPolygon(g, true);
            });
            freeDraw.options.simplifyPolygon = true;

            COLOR_MODES = ['white', 'bright', 'data-white'];
            var colorIndex = 2;

            getUserData()

        } else {

            COLOR_MODES = ['white', 'bright'];
            var colorIndex = 0;

        }

        d3.select(self.$el[0]).on('keydown', keydown).on('keyup', keyup);

        updateStyles();

        function updateStyles() {

            var c;
            if(COLOR_MODES[colorIndex].indexOf('white') > -1) {
                c = d3.hsl('rgb(255,255,255)');
            } else if (COLOR_MODES[colorIndex].indexOf('bright') > -1) {
                c = d3.hsl('rgb(240,30,110)');
            }

            var isData = (data.color && COLOR_MODES[colorIndex].indexOf('data') > -1);

            d3.select(self.$el[0])
               .selectAll('.image-map g path.leaflet-freedraw-polygon')
               .style('stroke', function(d, i) {
                if(isData && i < data.color.length) {
                    return data.color[i];
                }
                return c;
               })
               .style('fill', function(d, i) {
                var fill;
                if(isData && i < data.color.length) {
                    fill = d3.hsl(data.color[i]);
                } else {
                    fill = c;
                }
                return fill.brighter(1.2).toString();
               }); 

        }


        var mod = function(x, n) {
            return ((x%n)+n)%n;
        };
        function keydown() {
            if (d3.event.altKey) {
                freeDraw.setMode(L.FreeDraw.MODES.EDIT);
            }
            if (d3.event.metaKey | d3.event.shiftKey) {
                freeDraw.setMode(L.FreeDraw.MODES.VIEW);
            }
            if (d3.event.shiftKey & (d3.event.keyCode == 37 | d3.event.keyCode == 39)) {
                d3.event.preventDefault();
                if (d3.event.keyCode == 37) {
                    colorIndex = mod(colorIndex - 1, COLOR_MODES.length);
                }
                if (d3.event.keyCode == 39) {
                    colorIndex = mod(colorIndex + 1, COLOR_MODES.length);
                }
                updateStyles();
            }
        }

        function keyup() {
            freeDraw.setMode(L.FreeDraw.MODES.CREATE | L.FreeDraw.MODES.DELETE)
        }

        self.emit('image:loaded');

        function getUserData() {
            // extract coordinates from regions
            var n = freeDraw.memory.states.length;
            var coords = freeDraw.memory.states[n-1].map( function(d) {
                var points = [];
                d.forEach(function (p) {
                    var newpoint = map.project(p, 1);
                    newpoint.x *= (imw / w);
                    newpoint.y *= (imh / h);
                    points.push([newpoint.x, newpoint.y]);
                });
                return points;
            });

            utils.sendCommMessage(self, 'selection', coords);
            utils.updateSettings(self, {
                coords: coords
            }, function(err) {
                if(err) {
                    console.log('err saving user data');
                    console.log(err);
                }
            });
        }

        self.$el.unbind().click(function() {
            getUserData()
        });

        utils.getSettings(self, function(err, settings) {
            if(!err) {
                coords = settings.coords;
            }
        });
        
        freeDraw.on('markers', updateStyles);
        freeDraw.on('destroy', function(d) {

            var i = d.index;
            
            if(data.color && _.isArray(data.color)) {
                data.color.splice(i, 1);    

                if(data.color.length === 0) {
                    colorIndex = 0;
                    COLOR_MODES = ['white', 'bright'];
                }
            }

            getUserData()
            updateStyles()
        })
        
        self.map = map
        self.bounds = bounds
        self.overlay = overlay
        
    }
 function keyup() {
     freeDraw.setMode(L.FreeDraw.MODES.CREATE | L.FreeDraw.MODES.DELETE)
 }
 polygons.forEach(function (g) {
     freeDraw.createPolygon(g, true);
 });