Object-oriented widget for reuse I have been using a pattern similar to this basic structure below. Can anyone please let me know if this is a correct way to code an object-oriented widget for reuse?  I am looking to make code than can also be extended easily and modular.

$(function(){
// wrap in jquery .fn wrapper so that may be called on a
function $lider(autoplay, velocity, controls){
  var $lider = [
    // props n methods, accessible through data-slider-* attributes
    { 
      settings : { 
        envokeBecause : $('[data-widget~="slider"]'),
        autoplay : autoplay,
        speed : velocity,
        showControls : controls,
        slideSize : '100%',// 25% will show 4 slides if the parent container is 100% width and so on
      },
      bindings : {
        slideRail : $('[data-function~="slide-rail"]'),
        slide : $('[data-function~="slide"]'),
        nextButton : $('[data-function~="next"]'),
        prevButton : $('[data-function~="prev"]'),
        playButton : $('[data-function~="play"]'),
        pauseButton : $('[data-function~="pause"]'),
        stopButton : $('[data-function~="stop"]')
        // attach this functionality to the DOM
      },
      methods : {
        slideNext :  function(){ slideRail.animate({left: '-=100%'}, velocity)   },
        slidePrev : function(){ slideRail.animate({left: '+=100%'}, velocity)  },
        slideRestart : function(){ slideRail.animate({left: '0%'}, velocity)  },
        slideStart :  function(){ window.$liderTimer = setInterval(slideNext, velocity) },
        slidesCount : function(){ slideRail.children().size()
        }
      }
    }
  ]
  $.each($lider, function(){
    //  iterate through all of the slider objects properties
    window.SliderProps = this;
    // set slider to be accessible to the global scope
  });
  // slider props stored as vars
  var $liderHook = SliderProps.settings.envokeBecause;
  var slideRail = SliderProps.bindings.slideRail;
  var slide = SliderProps.bindings.slide;
  var play = SliderProps.bindings.playButton;
  var next = SliderProps.bindings.nextButton;
  var prev = SliderProps.bindings.prevButton;
  var pause = SliderProps.bindings.pauseButton;
  var stop = SliderProps.bindings.stopButton;
  var slideCount = SliderProps.bindings.slideRail.children().size();
  var slideCounter = 0; 

  function slidePrev(){
    var slidePrev = SliderProps.methods.slidePrev();
  }
  function slideStop(){
    /*slideRail.stop(); */
    window.clearInterval( $liderTimer  )
  }
  function slideRestart(){
    var slidePrev = SliderProps.methods.slideRestart();
    slideRail.stop(); 
  }
  function autoPlay(){
    SliderProps.methods.slideStart(); 
  }
  function slideNext(){
    slideCounter++
    var slideNext = SliderProps.methods.slideNext();
    console.log(slideCounter)  
    console.log(slideCount)
    if (slideCounter != slideCount){
      // offset var-1 for js index compensation
      console.log('keep slidin..')
    }
    else {
      console.log('stop!')
      slideRestart();
      slideCounter = 0;
    }
  }
  // element -&gt; event delegation type -&gt; function()
  slideRail.hover( slideStop )
  next.click( slideNext )
  prev.click( slidePrev )
  stop.click( slideRestart )
  pause.click( slideStop )
  play.click( autoPlay )
} // close function slider()
$lider(true, 750);
});
I'd suggest taking a look at jquery-boilerplate, especially the jqueryUI widget portion.

I started refactoring your code in a true $widget manner. It's not completely functional but should point you in the right direction. 

;(function ( $, window, document, undefined ) {
  $.widget("yourCustomNamespace.slider", {

    /*
     * Options to be used as defaults:
     */

    options: {
      autoplay: true,
      controls: true,
      duration: 750,
      slideSize: '100%',
      selectors: {
        slideRail: '[data-function~="slide-rail"]',
        slide: '[data-function~="slide"]',
        next: '[data-function~="next"]',
        prev: '[data-function~="prev"]',
        play: '[data-function~="play"]',
        pause: '[data-function~="pause"]',
        stop: '[data-function~="stop"]'
      }
    },

    /*
     * Private Methods:
     */

    _create: function() {
      this._setOption("current", 0);
      this._setOption("total", this.element.children().length);
      this._on(this.element, {
        "hover " + this.options.selectors.slideRail: $.proxy(this.stop, this),
        "click " + this.options.selectors.next: $.proxy(this.next, this),
        "click " + this.options.selectors.prev: $.proxy(this.prev, this),
        "click " + this.options.selectors.stop: $.proxy(this.stop, this),
        "click " + this.options.selectors.pause: $.proxy(this.pause, this),
        "click " + this.options.selectors.play: $.proxy(this.play, this)
      });
      if(this.options.autoplay) {
        this.start();
      }
    },
    _destroy: function() {
      this._off(this.element, "click hover");
    },
    _setOption: function(key, value) {
      switch (key) {
        case "current":
          // Update internal object ...
          this.options[key] = value;
          // Update DOM ...
          // this.element.find(this.options.selectors.slideRail.animate({...}, this.options.duration) ...
          break;
        default:
          this.options[key] = value;
          break;
      }
      return this._super("_setOption", key, value);
    },

    /*
     * Public Methods:
     */

    next: function() {
      // TODO: Account for overflow, this.options.total
      this._setOption("current", this.options.current + 1);
    },
    prev: function() {
      // TODO: Account for underflow, this.options.total
      this._setOption("current", this.options.current -1);
    },
    restart: function() {
      this._setOption("current", 0);
    },
    start: function() {
      this.interval = window.setInterval($.proxy(this.next, this), this.options.duration);
    },
    stop: function() {
      window.clearInterval(this.interval);
    },
    getCount: function() {
      return this.options.total;
    }
  });
})( jQuery, window, document );


Reference

There are a couple of things regarding reusability going on in here:


options are your default parameters that can be overwritten on initializing a new widget instance, e.g. $('[data-widget~="slider"]').slider({autoplay: false}); would overwrite the default of autoplay: true
Event binding is handled internally via this._on()
Ideally the widget would manage its own application state logic via this._setOption(). That way you can distinguish between logic and DOM interaction. Whenever a value changes, you update the DOM accordingly. 
You can call public methods from other places via the automatic interface the widget provides, e.g. $('[data-widget~="slider"]').slider("next")