\$\begingroup\$

I have this plugin that I have finally finished the big pieces of, there's one or two minor details that are not yet implemented do to lack of a decision yet but everything else is there.

I wrote it and can follow fine but I feel it reads very haphazardly. Could someone with fresh eyes help me make this into a more production level plugin? For clarity, I'm not asking for it be rewritten, just if you see something that could be made better, a nudge in that direction would be super helpful.

;(function($, undefined) { var defaults = { onInit : function () {}, onDestroy: function () {}, onClick : function () {}, onHover : function(id, state) { this.setTransient(id, 'blue'); }, noHover : function(id, state) { this.reset(id); } } var pubAPI = { set : function(id, style) { this.state[id].style = style; this.reset(id); }, reset : function(id) { applyStyle.call(this, id); }, setTransient : function (id, style) { applyStyle.call(this, id, style); }, resetState : function (id) { this.state[id].style = this.state[id].dFault; this.reset(id); }, destroy : function () { this.settings.onDestroy(); unbindEvents(); }, getInstance : function () { return this; } } var Clicklight = function(options) { this.settings = $.extend({}, defaults, options); this.state = {}; } var init = function(elem, inst) { var id = idCheck(elem); if (id) { if (!inst.state[id]) { var color = $(elem).css('color'); inst.state[id] = { group : [], dFault : color, style : color } } inst.state[id].group.push($(elem)); bindEvent($(elem), inst, id); inst.settings.onInit(); return inst; } else { console.log('ERROR: No \'data-cl-uid\' found on', elem, '-this element was not included'); return undefined; // data attr can't hold undefined, forces error later on } } var idCheck = function(elem) { return $(elem).attr('data-cl-uid') ? $(elem).attr('data-cl-uid') : null; } var bindEvent = function($elem, inst, id) { $elem.on('click.clicklight', function () { inst.settings.onClick.call(inst, id, inst.state[id]); }).on('mouseenter.clicklight', function () { inst.settings.onHover.call(inst, id, inst.state[id]); }).on('mouseleave.clicklight', function() { inst.settings.noHover.call(inst, id, inst.state[id]); }); } var unbindEvents = function($elem) { // fill this in } var applyStyle = function (id, style) { var group = this.state[id].group; if (!style) style = this.state[id].style for (var i = 0; i < group.length; i++) group[i].css('color', style); } var getInst = function($elem) { var inst = null; $elem.each(function() { if (!$.data(this, 'cl-instance')) return true else if (!($.data(this, 'cl-instance') instanceof Clicklight)) { console.log('ERROR: Invalid instance found on', this); return true; } else { inst = $.data(this, 'cl-instance'); return false; } }); return inst; } $.extend(Clicklight.prototype, pubAPI); $.fn.clicklight = function (option) { var args = arguments; if (typeof option === 'object' || !option) { var inst = null; return this.each(function() { if (!inst) inst = new Clicklight(option); if (!$.data(this, 'cl-instance')) $.data(this, 'cl-instance', init(this, inst)); else console.log('ERROR: Cannot create a duplicate instance for ',this); }); } else if (typeof option === 'string' && option in pubAPI) { var inst = getInst(this); if (inst) { if (typeof inst[option] === 'function') return inst[option].apply(inst, Array.prototype.slice.call(args, 1)); else console.log('ERROR: No method found with name', option); } else console.log('ERROR: No instance found in selection', this); } else console.log('ERROR: Invalid call of clicklight with argument', option); return this; } })(jQuery, undefined);

For those that want to see it in action, I have it running on this test page.