       yes
 
     # - Much simpler toggler. As long as tip isn't truly visible, sleep is unneeded.
-    sleepByTrigger: ($t) ->
+    sleepByTrigger: ($trigger) ->
       return no if @_state isnt 'awake'
       @_state = 'sleeping'
       clearTimeout @_wakeCountdown
       @_sleepCountdown = setTimeout =>
         @onHide()
-        @$tip.fadeOut @o.ms.duration.out, =>
+        @$tip.fadeOut @ms.duration.out, =>
           @_state = 'asleep'
           @afterHide()
-
-      , @o.ms.delay.out
+      , @ms.delay.out
       # - Success.
       yes
 
     # Hooks
-    onShow: (triggerChanged, evt) -> return
+    onShow: (triggerChanged, event) -> return
     onHide: $.noop
-    afterShow: (triggerChanged, evt) -> return
+    afterShow: (triggerChanged, event) -> return
     afterHide: $.noop
     htmlOnRender: $.noop
-    offsetOnTriggerMouseMove: (evt, offset, $t) -> no
+    offsetOnTriggerMouseMove: (event, offset, $trigger) -> no
 
   # SnapTip API
   # -----------
   class SnapTip extends Tip
 
-    constructor: ($ts, o, $ctx) ->
-      super $ts, o, $ctx
-      if @o.snap.toTrigger is off
-        @o.snap.toTrigger = @o.snap.toXAxis is on or @o.snap.toYAxis is on
-      if @o.snap.toXAxis is on then @o.cursorHeight = 0
-      if @o.snap.toYAxis is on then @o.cursorHeight = 2
+    constructor: ($triggers, options, $context) ->
+      super $triggers, options, $context
+      if @snap.toTrigger is off
+        @snap.toTrigger = @snap.toXAxis is on or @snap.toYAxis is on
+      if @snap.toXAxis is on then @cursorHeight = 0
+      if @snap.toYAxis is on then @cursorHeight = 2
       @_offsetStart = null
       # - Add snapping config as classes.
-      _.each @o.snap, (active, prop) => if active then @$tip.addClass @o.cls.snap[prop]
+      @$tip.addClass @classNames.snap[key] for key, active of @snap when active
 
     # ###Protected
 
     # - The main positioner. Uses the trigger offset as the base.
     #   TODO - Still needs to support all the directions.
-    _moveToTrigger: ($t, baseOffset) ->
-      # @debugLog baseOffset
-      offset = $t.offset()
-      if @o.snap.toXAxis is on
-        if @isDirection 'south' then offset.top += $t.outerHeight()
-        if @o.snap.toYAxis is off
+    _moveToTrigger: ($trigger, baseOffset) ->
+      #@debugLog baseOffset
+      offset = $trigger.offset()
+      if @snap.toXAxis is on
+        if @isDirection 'south' then offset.top += $trigger.outerHeight()
+        if @snap.toYAxis is off
           offset.left = baseOffset.left - (@$tip.outerWidth() - 12)/ 2 # Note arbitrary buffer offset.
-      if @o.snap.toYAxis is on
-        if @isDirection 'east' then offset.left += $t.outerWidth()
-        if @o.snap.toXAxis is off
+      if @snap.toYAxis is on
+        if @isDirection 'east' then offset.left += $trigger.outerWidth()
+        if @snap.toXAxis is off
           offset.top = baseOffset.top - @$tip.outerHeight() / 2
       offset
 
     # - Bind to get initial position for snapping. This is only for snapping
     #   without snapping to the trigger, which is only what's currently supported.
     #   See `afterShow` hook.
-    _bindTrigger: ($t) ->
-      super $t
-      $t.on @evt('truemouseleave'), (evt) => @_offsetStart = null
+    _bindTrigger: ($trigger) ->
+      super $trigger
+      $trigger.on @evt('truemouseleave'), (event) => @_offsetStart = null
 
     # ###Public
 
     # Hooked
 
     # - Make the tip invisible while it's being positioned, then reveal it.
-    onShow: (triggerChanged, evt) ->
+    onShow: (triggerChanged, event) ->
       if triggerChanged is yes
         @$tip.css 'visibility', 'hidden'
 
-    afterShow: (triggerChanged, evt) ->
+    afterShow: (triggerChanged, event) ->
       if triggerChanged is yes
         @$tip.css 'visibility', 'visible'
         @_offsetStart =
-          top: evt.pageY
-          left: evt.pageX
+          top: event.pageY
+          left: event.pageX
 
     # - Main positioning handler.
-    offsetOnTriggerMouseMove: (evt, offset, $t) ->
+    offsetOnTriggerMouseMove: (event, offset, $trigger) ->
       newOffset = _.clone offset
-      if @o.snap.toTrigger is on
-        newOffset = @_moveToTrigger $t, newOffset
+      if @snap.toTrigger is on
+        newOffset = @_moveToTrigger $trigger, newOffset
       else
-        if @o.snap.toXAxis is on
+        if @snap.toXAxis is on
           newOffset.top = @_offsetStart.top
           @debugLog 'xSnap'
-        if @o.snap.toYAxis is on
+        if @snap.toYAxis is on
           newOffset.left = @_offsetStart.left
           @debugLog 'ySnap'
       newOffset

      return no if @$tip.html().length
      html = @htmlOnRender()
      if not (html? and html.length) then html = @_defaultHtml()
      @$tip = $(html).addClass @o.cls.follow
      @$tip.prependTo @$ctx

    # - The tip content will change as it's being refreshed / initialized.
    _inflateByTrigger: ($t) ->
      do (c=@o.cls) =>
        dir = if $t.data(@attr 'direction') then $t.data(@attr 'direction').split(' ') else @o.defaultDirection
        @debugLog 'update direction class', dir
        @$tip.find(".#{c.content}").text($t.data @attr 'content').end()
             .removeClass([c.north, c.south, c.east, c.west].join ' ')
             .addClass($.trim _.reduce dir, ((cls, dir) => "#{cls} #{c[dir]}"), '')


    # - The main toggle handler. Hooked into by `offsetOnTriggerMouseMove`.
    _onTriggerMouseMove: (evt) ->
      return no if not evt.pageX?
      $t = if ($t = $(evt.currentTarget)) and $t.hasClass(@o.cls.trigger) then $t else $t.closest(@o.cls.trigger)
      return no if not $t.length
      @wakeByTrigger $t, evt, =>
        offset =
          top: evt.pageY
          left: evt.pageX
        offset = @offsetOnTriggerMouseMove(evt, offset, $t) or offset
        if @isDirection 'north', $t then offset.top -= @$tip.outerHeight() + @o.cursorHeight
        if @isDirection 'west',  $t then offset.left -= @$tip.outerWidth()
        if @isDirection 'south', $t then offset.top += @o.cursorHeight
        offset.top += @o.cursorHeight
        @$tip.css offset
        @debugLog '_onTriggerMouseMove', @_state, offset

    # - Auto-direction support. Given the context boundary, choose the best
    #   direction. The data is stored with the trigger and gets accessed elsewhere.
    _updateDirectionByTrigger: ($t) ->
      return no if @o.autoDirection is off
      # - Check if adapting is needed. Adapt and store as needed.
      checkDir = (dir) =>
        if not @_bounds? then @_setBounds()
        ok = yes
        switch dir
          when 'south' then ok = (edge = tPosition.top + tHeight + size.height) and @_bounds.bottom > edge
          when 'east'  then ok = (edge = tPosition.left + size.width)  and @_bounds.right > edge
          when 'north' then ok = (edge = tPosition.top - size.height) and @_bounds.top < edge
          when 'west'  then ok = (edge = tPosition.left - size.width) and @_bounds.left < edge
        @debugLog 'checkDir', "'#{$t.html()}'", dir, edge, size
        if not ok
          switch dir
            when 'south' then newDir[0] = 'north'
            when 'east'  then newDir[1] = 'west'
            when 'north' then newDir[0] = 'south'
            when 'west'  then newDir[1] = 'east'
          $t.data @attr('direction'), newDir.join ' '
      # - Prepare for checking subroutine.
      tPosition = $t.position()
      tWidth    = $t.outerWidth()
      tHeight   = $t.outerHeight()
      size      = @sizeForTrigger $t
      newDir = _.clone @o.defaultDirection
      # - Check each direction.
      checkDir dir for dir in @o.defaultDirection

    _setBounds: ->
      $ctx = if @$ctx.is('body') then $(window) else @$ctx
      @_bounds =
        top:    parseInt @$ctx.css('padding-top'), 10
        left:   parseInt @$ctx.css('padding-left'), 10
        bottom: $ctx.innerHeight()
        right:  @$ctx.innerWidth()

    # ###Public

    # Accessors
    options: -> @o
    tip: -> @$tip
    # - Does a stealth render to find tip size. The data is stored with the
    #   trigger and gets accessed elsewhere.
    sizeForTrigger: ($t, force=no) ->
      # - Try cached.
      size =
        width:  $t.data @attr 'width'
        height: $t.data @attr 'height'
      return size if size.width and size.height
      # - Otherwise new.
      @$tip.find(".#{@o.cls.content}").text($t.data @attr 'content').end()
        .css
          display: 'block',
          visibility: 'hidden'
      $t.data @attr('width'),  (size.width = @$tip.outerWidth())
      $t.data @attr('height'), (size.height = @$tip.outerHeight())
      @$tip.css
        display: 'none',
        visibility: 'visible'
      size

    # - Direction is actually an array.
    isDirection: (dir, $t) -> (@$tip.hasClass @o.cls[dir]) or
      ((not $t? or not $t.data @attr 'direction') and _.include @o.defaultDirection, dir)

    # Methods


      defaultDirection: ['south', 'east']
      safeToggle: on
      autoDirection: on
      classNames: do ->
        classNames = {}
        keys = ['inner', 'content', 'stem', 'north', 'east', 'south', 'west', 'follow', 'trigger']
        (classNames[key] = "#{pre}#{key}") for key in keys
        classNames.tip = 'js-tip'
        classNames

  # Snap-Tip
  # --------
