javascriptobjecteventscyclejs

Cannot get document keydown events with Object.assign


I am using

sources.DOM.select('document').events('keydown')
  .map(ev => Object.assign({}, ev, {type: 'keydown'}))

but the resulting stream gives objects with just the "isTrusted" property (and not "key", "code", etc.). Instead, with 'mousemove' I get events as expected (with "isTrusted" but also "movementX", "movementY", etc.). What is wrong?


Solution

  • You're right, not a Cycle.js problem but rather a limitation of Object.assign.

    Simply put—Object.assign does not copy inherited properties.

    This answer on a similar problem provided a working alternative:

    function main (sources) {
      const vdom$ = sources.DOM.select('document').events('keydown')
        .map(ev => cloneEvent(ev))
        .map(mykey => div('Key pressed: ' + mykey.key + ', code:' + mykey.code))
        .startWith(div('Press a key.'))
    
      return {
        DOM: vdom$
      }
    }
    
    function cloneEvent(e) {
      if (e===undefined || e===null) return undefined;
      function ClonedEvent() {};  
      let clone=new ClonedEvent();
      for (let p in e) {
        let d=Object.getOwnPropertyDescriptor(e, p);
        if (d && (d.get || d.set)) Object.defineProperty(clone, p, d); else clone[p] = e[p];
      }
      Object.setPrototypeOf(clone, e);
      return clone;
    }
    

    See updated codepen.io example.

    These SO questions and answers also helped clarify the situation:

    Poor Use Case of Object.assign() - Simple Example

    Javascript hasOwnProperty always false on Event objects?