2
\$\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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.