motorcyclejs / dom

The standard DOM driver for motorcycle.js
MIT License
20 stars 2 forks source link

Events bug: tough to say what really #105

Closed TylorS closed 7 years ago

TylorS commented 7 years ago

minimal example

import { run } from '@motorcycle/core';
import { makeDOMDriver as makeDomDriver, button, div } from '@motorcycle/dom';
import { just, combineArray } from 'most';
import isolate from '@cycle/isolate';

function main(sources) {
  // PROBLEM:
  // -------
  // Setting `useCapture: true` causes
  // Uncaught SyntaxError: Failed to execute 'matches' on 'Element': '' is not a valid selector.
  //
  // Setting `useCapture: false` causes event to fire twice. 
  const events = { click: { useCapture: false } };

  const aButton = isolate(
    augmentComponentWithEvents(Button, events)
  )(sources);

  const aButtonToggle$ = aButton.click$.scan(previous => !previous, false);

  const childViews$ = aButton.dom.map(view => [view]);

  const aHeaderSources = { childViews$ };

  const aHeader = augmentComponent(Header, { aButtonToggle$ })(aHeaderSources);

  return {
    dom: aHeader.dom,
    toggle$: aHeader.aButtonToggle$,
  };
}

function Header(sources) {
  const { childViews$ } = sources;
  return {
    dom: childViews$.map(childViews => {
      return div(`#header`, childViews)
    }),
  }
}

function Button() {
  return {
    dom: just(
      div(`#container`, [
        button([`click me`])
      ])
    ),
  };
}

function augmentComponentWithEvents(
  Component: Function,
  events: { [name: string]: { useCapture?: boolean } }
) {
  return function AugmentationComponent(sources: any) {
    const sinks = Component(sources);

    Object.keys(events)
      .forEach(function (key) {
        sinks[`${key}$`] = sources.dom.events(key, events[key]);
    });

    return sinks;
  };
}

function augmentComponent(Component, augmentationSinks) {
  return function AugmentationComponent(sources) {
    const sinks = Component(sources);

    return Object.assign(sinks, augmentationSinks);
  }
}

run(main, {
  dom: makeDomDriver('#app'),
  toggle$: function (subject) { subject.observe(v => bin.log(v)) },
})
TylorS commented 7 years ago

New working example for safe storage: http://www.webpackbin.com/EygJ86FZG