//= require rails-ujs
//= require turbolinks
//= require_self

const {fire, matches, setData, getData} = Rails;

const Ajax = {
  get: (url, successHandler, errorHandler)=>{
    Rails.ajax({
      url: url,
      type: 'get',
      beforeSend: beforeSend,
      success: successHandler,
      error: errorHandler
    });
  },
  post: (url, data, successHandler, errorHandler)=>{
    Rails.ajax({
      url: url,
      type: 'post',
      data: data,
      beforeSend: beforeSend,
      success: successHandler,
      error: errorHandler
    });
  }
}

var binds = {};

// Rails 5.1.6 hack
function beforeSend(xhr, options) {
  return true;
}

function getMeta(name) {
  let meta = find(document.head, `meta[name=${name}]`);
  return meta.getAttribute('content');
}

function create(html) {
  let template = document.createElement('template');
  template.innerHTML = html.trim();
  return template.content.firstChild;
}

function replace(previous, current) {
  if (typeof current === 'string') {
    current = create(current);
  }
  previous.parentNode.replaceChild(current, previous);
}

function remove(element) {
  element.parentNode.removeChild(element);
}

function append(parent, element) {
  if (typeof element === 'string') {
    element = create(element);
  }
  parent.appendChild(element);
}

function find() {
  let elements = findAll(...arguments);
  return (elements.length > 0 ? elements[0] : null);
}

function findAll() {
  let scope, selector;
  if (arguments.length == 2) {
    [scope, selector] = arguments;
  } else {
    scope = document.body;
    selector = arguments[0];
  }
  let list = scope.querySelectorAll(selector);
  return Array.prototype.slice.call(list);
}

function findParent(element, selector) {
  let parent = element.parentNode;
  if (parent instanceof Element) {
    if (matches(parent, selector)) {
      return parent;
    } else {
      return findParent(parent, selector);
    }
  }
}

function listen() {
  let element, selector, type, handler;
  if (arguments.length == 3) {
    [element, type, handler] = arguments;
  } else {
    [element, selector, type, handler] = arguments;
  }
  element.addEventListener(type, (event)=>{
    let currentTarget = event.target;
    if (selector && !matches(currentTarget, selector)) {
      currentTarget = findParent(currentTarget, selector);
    }
    event = Object.defineProperty(event, 'currentTarget', { value: currentTarget, configurable: true });
    if (currentTarget && handler.call(event.target, event) == false) {
      event.preventDefault();
      event.stopPropagation();
    }
  });
}

function load(scope) {
  for (let [selector, klass] of Object.entries(binds)) {
    let elements = findAll(scope, selector);
    for (let element of elements) {
      new klass(element);
    }
  }
}

listen(document, 'turbolinks:load', ()=>{
  load(document.body);
  let observer = new MutationObserver((mutations)=>{
    for (let mutation of mutations) {
      load(mutation.target);
    }
  });
  observer.observe(
    document.body,
    { attributes: false, childList: true, subtree: true }
  );
});


@@ -1950,24 +1950,25 @@
  let element
+s
 , selector, 
@@ -2025,16 +2025,17 @@
 %5Belement
+s
 , type, 
@@ -2075,24 +2075,25 @@
     %5Belement
+s
 , selector, 
@@ -2124,16 +2124,122 @@
 ts;%0A  %7D%0A
+  if (elements.constructor != Array) %7B%0A    elements = %5Belements%5D;%0A  %7D%0A  for (let element of elements) %7B%0A  
   elemen
@@ -2274,24 +2274,26 @@
 ent)=%3E%7B%0A    
+  
 let currentT
@@ -2314,16 +2314,18 @@
 target;%0A
+  
     if (
@@ -2375,24 +2375,26 @@
 r)) %7B%0A      
+  
 currentTarge
@@ -2426,32 +2426,34 @@
 get, selector);%0A
+  
     %7D%0A    event 
@@ -2442,24 +2442,26 @@
       %7D%0A    
+  
 event = Obje
@@ -2549,24 +2549,26 @@
 rue %7D);%0A    
+  
 if (currentT
@@ -2624,24 +2624,26 @@
 se) %7B%0A      
+  
 event.preven
@@ -2650,24 +2650,26 @@
 tDefault();%0A
+  
       event.
@@ -2691,24 +2691,32 @@
 ();%0A    
-%7D%0A
+  %7D%0A  
   %7D);%0A
+  %7D%0A
 %7D%0A%0Afunct

Improve listen js