I am trying to write a jQuery Plugin from a piece of JS code I had written.  What this plugin does is it converts a select box into a map of Australia where I can select individual states. It's working perfectly well. However, I'd like to know how I can write it with OOP principles like SOLID etc. can someone review my code and suggest changes. ;(function ( $, window, document, undefined ) {// undefined is used here as the undefined global variable in ECMAScript 3 is// mutable (ie. it can be changed by someone else). undefined isn't really being// passed in so we can ensure the value of it is truly undefined. In ES5, undefined// can no longer be modified.// window and document are passed through as local variable rather than global// as this (slightly) quickens the resolution process and can be more efficiently// minified (especially when both are regularly referenced in your plugin).// Create the defaults oncevar pluginName = genAusMap,    defaults = {};// The actual plugin constructorfunction Plugin ( element, options ) {    this.element = element;    var imagesLoaded = 0;    var canvas, ctx,ausMap,states;    var elemLeft,elemTop;    this.setCanvas = function(c,w,h){        canvas = c;        canvas.setAttribute('width',w);        canvas.setAttribute('height',h);        // Add event listener for `click` events.        $(canvas).on('click', function(event) {            var x = event.pageX - elemLeft, y = event.pageY - elemTop;            canvas.width = canvas.width; // clear the canvas            ctx.drawImage(ausMap, 0, 0);            if (y > 59 && y < 164 && x > 146 && x < 205) {                drawImageOnLoad('nt');            }            if (y > 59 && y < 192 && x > 205 && x < 301) {                drawImageOnLoad('qld');            }            if (y > 164 && y < 249 && x > 147 && x < 214) {                drawImageOnLoad('sa');            }            if (y > 260 && y < 295 && x > 229 && x < 261) {                drawImageOnLoad('tas');            }            if (y > 223 && y < 260 && x > 213 && x < 265) {                drawImageOnLoad('vic');            }            if ((y > 191 && y < 222 && x > 220 && x < 297) || (y > 221 & y < 233 & x > 230  & x < 277) || (y > 233 & y < 245 & x > 254  & x < 269) ) {                // ctx.rect(220,191,77,31); ctx.rect(230,221,47,12); ctx.rect(254,233,15,12); ctx.stroke();       // draw a rectangle box with the various co-ordinates to know where to start from and where to end for nsw /                drawImageOnLoad('nsw');            }            if ((y > 207 && y < 232 && x > 240 && x < 270) || (y > 233 & y < 245 & x > 254  & x < 269)) {                // ctx.rect(240,207,30,25); ctx.rect(254,233,15,12); ctx.stroke();                drawImageOnLoad('act');            }            if (y > 75 && y < 235 && x > 40 && x < 146) {                drawImageOnLoad('wa');            }        });    };    this.setCanvasOffsets = function(l,t){        elemLeft = l;        elemTop = t;    };    this.getCanvas = function(){        return canvas;    };    this.setCtx = function(c){        ctx = c;    };    this.getCtx = function(){        return ctx;    };    this.setAusMap = function(map){        ausMap = map;    }    this.setStates = function(listOfStates){        states = listOfStates;    }    // jQuery has an extend method which merges the contents of two or    // more objects, storing the result in the first object. The first object    // is generally empty as we don't want to alter the default options for    // future instances of the plugin    var checkAllImagesLoaded = function () {        imagesLoaded += 1;        if(imagesLoaded == 9) {            drawImageOnLoad();        }    };    var drawImageOnLoad = function(drawState){        drawState = typeof drawState !== 'undefined' ? drawState : ''; // Assigning Default value        if(imagesLoaded == 9) {            canvas.width = canvas.width;            ctx.drawImage(ausMap, 0, 0);            ctx.globalAlpha = 0.5;            $.each(states, function(state){                state = this;                console.log(drawState);                if(drawState == state.getAttribute('data-name')) {                    ctx.drawImage(state, parseInt(state.getAttribute('data-positionX')), parseInt(state.getAttribute('data-positionY')));                    //selectDeselectOption(state.getAttribute('data-name'));                }            });        }    };    this.imageObj = function(src, x, y,name){        this.src = src;        this.x = x;        this.y = y;        this.name = name;    };    this.loadImage = function(image, onload) {        var img = new Image();        img.onload = checkAllImagesLoaded;        img.src = image.src;        img.setAttribute('data-positionX',image.x);        img.setAttribute('data-positionY', image.y);        img.setAttribute('data-name', image.name);        return img;    };    var selectDeselectOption = function(state){        $(this.element).val(state);    };    if(this.element.tagName == 'SELECT') {        this.settings = $.extend( {}, defaults, options );        this._defaults = defaults;        this._name = pluginName;        this.states = [];        this.init();    } else {        alert('Cannot instantiate plugin '+pluginName+' on a '+this.element.tagName+'. Try using a SELECT element instead');    }}// Avoid Plugin.prototype conflicts$.extend(Plugin.prototype, {    init: function () {        $el = $(this.element);        this.setCanvas(document.createElement('canvas'),319,313);        this.setCtx(this.getCanvas().getContext(2d));        this.setAusMap(this.loadImage(new this.imageObj(this.settings.mapOfAustralia ,0,0)));        this.states.push(this.loadImage(new this.imageObj('http://localhost/test/act.png',0,0,'act')));        this.states.push(this.loadImage(new this.imageObj('http://localhost/test/nsw.png',0,0,'nsw')));        this.states.push(this.loadImage(new this.imageObj('http://localhost/test/nt.png',0,0,'nt')));        this.states.push(this.loadImage(new this.imageObj('http://localhost/test/sa.png',0,0,'sa')));        this.states.push(this.loadImage(new this.imageObj('http://localhost/test/qld.png',0,0,'qld')));        this.states.push(this.loadImage(new this.imageObj('http://localhost/test/tas.png',0,0,'tas')));        this.states.push(this.loadImage(new this.imageObj('http://localhost/test/vic.png',0,0,'vic')));        this.states.push(this.loadImage(new this.imageObj('http://localhost/test/wa.png',0,0,'wa')));        this.setStates(this.states);        $el.after(this.getCanvas());        console.log(this.getCanvas());        this.setCanvasOffsets(this.getCanvas().offsetLeft,this.getCanvas().offsetTop)    }});// A really lightweight plugin wrapper around the constructor,// preventing against multiple instantiations$.fn[ pluginName ] = function ( options ) {    this.each(function() {        if ( !$.data( this, plugin_ + pluginName ) ) {            $.data( this, plugin_ + pluginName, new Plugin( this, options ) );        }    });    // chain jQuery functions    return this;};})( jQuery, window, document );
Writing my own jQuery plugin
javascript;jquery;image;canvas
This plugin looks like an attempt to reinvent image maps using a canvas.  Most of this code could be eliminated in favour of techniques that were available in 1997.