adapter.native.coffee

Jump To …
adapter.ender.coffee adapter.jquery.coffee adapter.native.coffee adapter.prototype.coffee opentip.coffee

# adapter.native.coffee |
--- | ---
¶ |
¶ # Native Opentip Adapter Use this adapter if you don't use a framework like jQuery and you don't really care about oldschool browser compatibility. |
    class Adapter

      name: "native"
¶ Invoke callback as soon as dom is ready Source: https://github.com/dperini/ContentLoaded/blob/master/src/contentloaded.js |
      domReady: (callback) ->
        done = no
        top = true
        win = window
        doc = document

        return callback() if doc.readyState in [ "complete", "loaded" ]

        root = doc.documentElement
        add = (if doc.addEventListener then "addEventListener" else "attachEvent")
        rem = (if doc.addEventListener then "removeEventListener" else "detachEvent")
        pre = (if doc.addEventListener then "" else "on")

        init = (e) ->
          return  if e.type is "readystatechange" and doc.readyState isnt "complete"
          (if e.type is "load" then win else doc)[rem] pre + e.type, init, false
          unless done
            done = yes
            callback()

        poll = ->
          try
            root.doScroll "left"
          catch e
            setTimeout poll, 50
            return
          init "poll"

        unless doc.readyState is "complete"
          if doc.createEventObject and root.doScroll
            try
              top = not win.frameElement
            poll()  if top
          doc[add] pre + "DOMContentLoaded", init, false
          doc[add] pre + "readystatechange", init, false
          win[add] pre + "load", init, false
¶ # DOM |
¶ Create the HTML passed as string |
      create: (htmlString) ->
        div = document.createElement "div"
        div.innerHTML = htmlString
        @wrap div.childNodes
¶ ## Element handling |
¶ Wrap the element in the framework |
      wrap: (element) ->
        if element instanceof NodeList
          element = (el for el in element)
        else if element not instanceof Array
          element = [ element ]
        element
¶ Returns the unwrapped element |
      unwrap: (element) -> @wrap(element)[0]
¶ Returns the tag name of the element |
      tagName: (element) -> @unwrap(element).tagName
¶ Returns or sets the given attribute of element |
      attr: (element, attr, value) ->
        if arguments.length == 3
          @unwrap(element).setAttribute attr, value
        else
          @unwrap(element).getAttribute? attr

      lastDataId = 0
      dataValues = { }
¶ Returns or sets the given data of element |
      data: (element, name, value) ->
        dataId = @attr element, "data-id"
        unless dataId
          dataId = ++lastDataId
          @attr element, "data-id", dataId
          dataValues[dataId] = { }

        if arguments.length == 3
¶ Setter |
          dataValues[dataId][name] = value
        else
          value = dataValues[dataId][name]
          return value if value?

          value = @attr element, "data-#{Opentip::dasherize name}"
          if value
            dataValues[dataId][name] = value
          return value
¶ Finds elements by selector |
      find: (element, selector) -> @unwrap(element).querySelector selector
¶ Finds all elements by selector |
      findAll: (element, selector) -> @unwrap(element).querySelectorAll selector
¶ Updates the content of the element |
      update: (element, content, escape) ->
        element = @unwrap element
        if escape
          element.innerHTML = "" # Clearing the content
          element.appendChild document.createTextNode content
        else
          element.innerHTML = content
¶ Appends given child to element |
      append: (element, child) ->
        unwrappedChild = @unwrap child
        unwrappedElement = @unwrap element
        unwrappedElement.appendChild unwrappedChild
¶ Add a class |
      addClass: (element, className) -> @unwrap(element).classList.add className
¶ Remove a class |
      removeClass: (element, className) -> @unwrap(element).classList.remove className
¶ Set given css properties |
      css: (element, properties) ->
        element = @unwrap @wrap element
        for own key, value of properties
          element.style[key] = value
¶ Returns an object with given dimensions |
      dimensions: (element) ->
        element = @unwrap @wrap element
        dimensions =
          width: element.offsetWidth
          height: element.offsetHeight

        unless dimensions.width and dimensions.height
¶ The element is probably invisible. So make it visible |
          revert =
            position: element.style.position || ''
            visibility: element.style.visibility || ''
            display: element.style.display || ''

          @css element,
            position: "absolute"
            visibility: "hidden"
            display: "block"

          dimensions =
            width: element.offsetWidth
            height: element.offsetHeight

          @css element, revert

        dimensions
¶ Returns the scroll offsets of current document |
      scrollOffset: ->
        [
          window.pageXOffset or document.documentElement.scrollLeft or document.body.scrollLeft
          window.pageYOffset or document.documentElement.scrollTop or document.body.scrollTop
        ]
¶ Returns the dimensions of the viewport (currently visible browser area) |
      viewportDimensions: ->
        {
          width: document.documentElement.clientWidth
          height: document.documentElement.clientHeight
        }
¶ Returns an object with x and y |
      mousePosition: (e) ->
        pos = x: 0, y: 0

        e ?= window.event

        return unless e?

        if e.pageX or e.pageY
          pos.x = e.pageX
          pos.y = e.pageY
        else if e.clientX or e.clientY
          pos.x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft
          pos.y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop

        pos
¶ Returns the offset of the element |
      offset: (element) ->
        element = @unwrap element

        offset = {
          top: element.offsetTop
          left: element.offsetLeft
        }

        while element = element.offsetParent
          offset.top += element.offsetTop
          offset.left += element.offsetLeft

          if element != document.body
            offset.top -= element.scrollTop
            offset.left -= element.scrollLeft

        offset
¶ Observe given eventName |
      observe: (element, eventName, observer) -> @unwrap(element).addEventListener eventName, observer
¶ Stop observing event |
      stopObserving: (element, eventName, observer) -> @unwrap(element).removeEventListener eventName, observer
¶ Perform an AJAX request and call the appropriate callbacks. |
      ajax: (options) ->
        throw new Error "No url provided" unless options.url?

        if window.XMLHttpRequest
¶ Mozilla, Safari, ... |
          request = new XMLHttpRequest
        else if window.ActiveXObject
¶ IE |
          try
            request = new ActiveXObject "Msxml2.XMLHTTP"
          catch e
            try
              request = new ActiveXObject "Microsoft.XMLHTTP"
            catch e

        throw new Error "Can't create XMLHttpRequest" unless request

        request.onreadystatechange = ->
          if request.readyState == 4
            try
              if request.status == 200
                options.onSuccess? request.responseText
              else
                options.onError? "Server responded with status #{request.status}"
            catch e
              options.onError? e.message

            options.onComplete?()

        request.open options.method?.toUpperCase() ? "GET", options.url
        request.send()
¶ # Utility functions |
¶ Creates a shallow copy of the object |
      clone: (object) ->
        newObject = { }
        for own key, val of object
          newObject[key] = val
        newObject
¶ Copies all properties from sources to target |
      extend: (target, sources...) ->
        for source in sources
          for own key, val of source
            target[key] = val
        target
¶ Add the adapter to the list |
    Opentip.addAdapter new Adapter