<div id="app"></div>
window.xs = window.xstream.default;
window.xs.fromEvent = window.fromEvent.default;

function createElement(obj) {
  const elem = document.createElement(obj.tagName);
  obj.children.forEach(child => {
    if (typeof child === "object") {
      elem.appendChild(createElement(child));
    } else {
      elem.textContent = child;
    }
  });
  return elem;
}

function tagFactory(tagName) {
  return function(children) {
    return {
      tagName,
      children
    };
  };
}

const h1 = tagFactory("h1");
const span = tagFactory("span");

function main(sources) {
  const click$ = sources.DOM.selectEvents("span", "click");
  return {
    DOM: click$
      .startWith(null)
      .map(() => xs.periodic(1000).fold(prev => prev + 1, 0))
      .flatten()
      .map(i => h1([span([`Seconds elapsed: ${i}`])])),
    log: xs.periodic(2000).fold(prev => prev + 1, 0)
  };
}

function domDriver(text$) {
  text$.subscribe({
    next: obj => {
      const app = document.querySelector("#app");
      app.textContent = "";
      const elem = createElement(obj);
      app.appendChild(elem);
    }
  });
  const domSource = {
    selectEvents: function(tagName, eventType) {
      return xs
        .fromEvent(document, eventType)
        .filter(ev => ev.target.tagName === tagName.toUpperCase());
    }
  };
  return domSource;
}

function logDriver(msg$) {
  msg$.subscribe({
    next: str => {
      console.log(str);
    }
  });
}

Cycle.run(main, {
  DOM: domDriver,
  log: logDriver
});
View Compiled
Run Pen

External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

  1. https://static.jonirrings.com/xstream/xstream.min.js
  2. https://static.jonirrings.com/xstream/extra/fromEvent.js
  3. https://unpkg.com/@cycle/run@4.4.0/dist/cycle-run.min.js