javascript pasar Cómo codificar el objeto del evento?




manejadores de eventos (4)

No estoy seguro de si ayuda, pero acabo de tropezar con esto en la documentación de Angular JS:

* Fuente: https://code.angularjs.org/1.5.5/docs/guide/expression#-event-

/*
 * return a copy of an object with only non-object keys
 * we need this to avoid circular references
 */
function simpleKeys (original) {
  return Object.keys(original).reduce(function (obj, key) {
    obj[key] = typeof original[key] === 'object' ? '{ ... }' : original[key];
    return obj;
  }, {});
}

Ahora podrías hacer algo como:

JSON.stringify(simpleKeys(eventObject));

JSON.stringify(eventObject);

da:

TypeError: Converting circular structure to JSON

dojox.json.ref.toJson(eventObject);

da:

TypeError: Accessing selectionEnd on an input element that cannot have a selection.

¿Hay alguna biblioteca / código listo para usar para lograrlo?


Use la función "replacer" para evitar errores:

JSON.stringify(evt, function(k, v) {
    if (v instanceof Node) {
        return 'Node';
    }
    if (v instanceof Window) {
        return 'Window';
    }
    return v;
}, ' ');

Tuve un problema similar y escribí un serializador simple de eventos con un método auxiliar para limpiar el atributo de ruta del evento. El enfoque para esta solución para transformar datos del evento en un objeto serializable:

  • Copia sobre atributos primitivos
  • Copie outerHTML para atributos de elemento en el objeto de evento
  • Calcular la ruta del selector para el atributo path (esto evita copiar el outerHTML de la página HTML completa)

// Calculate a string representation of a node's DOM path.
var pathToSelector = function(node) {
  if (!node || !node.outerHTML) {
    return null;
  }

  var path;
  while (node.parentElement) {
    var name = node.localName;
    if (!name) break;
    name = name.toLowerCase();
    var parent = node.parentElement;

    var domSiblings = [];

    if (parent.children && parent.children.length > 0) {
      for (var i = 0; i < parent.children.length; i++) {
        var sibling = parent.children[i];
        if (sibling.localName && sibling.localName.toLowerCase) {
          if (sibling.localName.toLowerCase() === name) {
            domSiblings.push(sibling);
          }
        }
      }
    }

    if (domSiblings.length > 1) {
      name += ':eq(' + domSiblings.indexOf(node) + ')';
    }
    path = name + (path ? '>' + path : '');
    node = parent;
  }

  return path;
};

// Generate a JSON version of the event.
var serializeEvent = function(e) {
  if (e) {
    var o = {
      eventName: e.toString(),
      altKey: e.altKey,
      bubbles: e.bubbles,
      button: e.button,
      buttons: e.buttons,
      cancelBubble: e.cancelBubble,
      cancelable: e.cancelable,
      clientX: e.clientX,
      clientY: e.clientY,
      composed: e.composed,
      ctrlKey: e.ctrlKey,
      currentTarget: e.currentTarget ? e.currentTarget.outerHTML : null,
      defaultPrevented: e.defaultPrevented,
      detail: e.detail,
      eventPhase: e.eventPhase,
      fromElement: e.fromElement ? e.fromElement.outerHTML : null,
      isTrusted: e.isTrusted,
      layerX: e.layerX,
      layerY: e.layerY,
      metaKey: e.metaKey,
      movementX: e.movementX,
      movementY: e.movementY,
      offsetX: e.offsetX,
      offsetY: e.offsetY,
      pageX: e.pageX,
      pageY: e.pageY,
      path: pathToSelector(e.path && e.path.length ? e.path[0] : null),
      relatedTarget: e.relatedTarget ? e.relatedTarget.outerHTML : null,
      returnValue: e.returnValue,
      screenX: e.screenX,
      screenY: e.screenY,
      shiftKey: e.shiftKey,
      sourceCapabilities: e.sourceCapabilities ? e.sourceCapabilities.toString() : null,
      target: e.target ? e.target.outerHTML : null,
      timeStamp: e.timeStamp,
      toElement: e.toElement ? e.toElement.outerHTML : null,
      type: e.type,
      view: e.view ? e.view.toString() : null,
      which: e.which,
      x: e.x,
      y: e.y
    };

    console.log(JSON.stringify(o, null, 2));
  }
};

// Create a mock event for this example
var evt = new MouseEvent("click", {
  bubbles: true,
  cancelable: true,
  view: window
});
var cb = document.getElementById("clicker");

// Add a click listener
cb.addEventListener("click", serializeEvent);

// Fire the event
cb.dispatchEvent(evt);
<div>
  <button id="clicker" /> JSONify my click!
</div>


No podrá serializar un objeto de evento con JSON.stringify, porque un objeto de evento contiene referencias a nodos DOM, y el DOM tiene referencias circulares por todas partes (por ejemplo, relaciones hijo / padre). JSON no puede manejar esto de forma predeterminada, por lo que tiene un poco de suerte allí.

Sugeriría ver ¿Cómo serializar el nodo DOM a JSON incluso si hay referencias circulares? que tiene algunas sugerencias sobre cómo serializar un nodo DOM. Además, las siguientes preguntas parecen tener información útil:

Las bibliotecas JSON capaces de manejar referencias circulares parecen ser

Alternativamente, puede eliminar todas las referencias a los nodos DOM si no los necesita, y luego serializar el objeto. No deberías hacer esto después de todo. Ver el comentario de @PointedEars :)





stringify