import { matches } from “./dom”

let preventDefault

// Polyfill for CustomEvent in IE9+ // developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill let {

CustomEvent

} = window

if (typeof CustomEvent !== “function”) {

CustomEvent = function(event, params) {
  const evt = document.createEvent("CustomEvent")
  evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail)
  return evt
}

CustomEvent.prototype = window.Event.prototype;

// Fix setting `defaultPrevented` when `preventDefault()` is called
// http://stackoverflow.com/questions/23349191/event-preventdefault-is-not-working-in-ie-11-for-custom-events
({ preventDefault } = CustomEvent.prototype)
CustomEvent.prototype.preventDefault = function() {
  const result = preventDefault.call(this)
  if (this.cancelable && !this.defaultPrevented) {
    Object.defineProperty(this, "defaultPrevented", {get() { return true }})
  }
  return result
}

}

// Triggers a custom event on an element and returns false if the event result is false

// obj

// a native DOM element

// name

// string that corresponds to the event you want to trigger // e.g. ‘click’, ‘submit’

// data

// data you want to pass when you dispatch an event const fire = (obj, name, data) => {

const event = new CustomEvent(
  name, {
  bubbles: true,
  cancelable: true,
  detail: data
}
)
obj.dispatchEvent(event)
return !event.defaultPrevented

}

// Helper function, needed to provide consistent behavior in IE const stopEverything = (e) => {

fire(e.target, "ujs:everythingStopped")
e.preventDefault()
e.stopPropagation()
e.stopImmediatePropagation()

}

// Delegates events // to a specified parent ‘element`, which fires event `handler` // for the specified `selector` when an event of `eventType` is triggered

// element

// parent element that will listen for events e.g. document

// selector

// CSS selector; or an object that has ‘selector` and `exclude` properties (see: Rails.matches)

// eventType

// string representing the event e.g. ‘submit’, ‘click’

// handler

// the event handler to be called const delegate = (element, selector, eventType, handler) => element.addEventListener(eventType, function(e) {

let {
  target
} = e
while (!!(target instanceof Element) && !matches(target, selector)) { target = target.parentNode }
if (target instanceof Element && (handler.call(target, e) === false)) {
  e.preventDefault()
  e.stopPropagation()
}

})

export { fire, stopEverything, delegate }