uchcode
1/17/2019 - 1:57 PM

Web components + superfine

Web components + superfine

<title>Currency Coverter</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="module">

import { h, patch } from 'https://unpkg.com/superfine?module'
//import { h, patch } from './superfine.js'

const Numberbox = self => ({
  type: 'number',
  value: self.dataCount,
  oninput: e => self.dataCount = e.target.value
})

const Increment = self => ({
  onclick: e => self.dataCount += 1
})

const Decrement = self => ({
  onclick: e => self.dataCount -= 1
})

const CounterTemplate = self => h('span', {},
  h('style', {}, `
    input, button {
      font-size: 2rem;
      touch-action: manipulation;
    }
  `),
  h('input' , Numberbox(self)),
  h('button', Decrement(self), '-'),
  h('button', Increment(self), '+'),
)

export class Counter extends HTMLElement {
  constructor() {
    super()
    this.attachShadow({mode:'open'})
    this.render = (node => () => {
      node = patch(node, CounterTemplate(this), this.shadowRoot)
    })()
    this.render()
  }
  
  get dataCount() {
    return +this.dataset.count || 0
    //return JSON.parse(this.dataset.xxx)
  }
  
  set dataCount(newVal) {
    this.dataset.count = +newVal || 0
    //this.dataset.xxx = JSON.stringify(newVal)
  }
  
  attributeChangedCallback(attrName, oldVal, newVal) {
    if(oldVal != newVal) this.render()
  }
  
  static get observedAttributes() {
    return ['data-count']
  }
}

customElements.define('x-counter', Counter)

//==========================================================

const Rate = self =>
  ({
    id: 'rate',
    'data-count': self.dataset.rate
  })

const Dollars = self =>
  ({
    id: 'dollars',
    'data-count': self.dataset.dollars
  })

const ExchangerTemplate = self => h('div', {},
  h('style', {}, `
    h1 {
      font-size: 4rem;
    }
    span {
      font-size: 2rem;
    }
  `),
  h('h1', {}, '¥' + self.dataset.yen),
  h('span', {}, 'rate'), h('x-counter', Rate(self)),
  h('br', {}),
  h('span', {}, 'doll'), h('x-counter', Dollars(self)),
)

const observe = (targets, filter, clallback) => {
  const observer = new MutationObserver(clallback)
  const config = { attributes:true, attributeFilter:[filter] }
  for(let t of targets) observer.observe(t, config)
}

export class Exchanger extends HTMLElement {
  constructor() {
    super()
    
    this.dataset.rate = this.dataset.rate || 109
    this.dataset.dollars = this.dataset.dollars || 1
    this.dataset.yen = +this.dataset.rate * +this.dataset.dollars
    
    this.attachShadow({mode:'open'})
    this.render = (node => () => {
      node = patch(node, ExchangerTemplate(this), this.shadowRoot)
    })()
    this.render()
    
    const $ = s => this.shadowRoot.querySelector(s)
    
    const rate = $('#rate'), dollars = $('#dollars')
    
    observe([rate, dollars], 'data-count', () => {
      this.dataset.yen = rate.dataCount * dollars.dataCount
      this.dataset.rate = rate.dataCount
      this.dataset.dollars = dollars.dataCount
    })
  }
  
  attributeChangedCallback(attrName, oldVal, newVal) {
    if(oldVal != newVal) this.render()
  }
  
  static get observedAttributes() {
    return ['data-rate', 'data-dollars']
  }
}

customElements.define('x-exchanger', Exchanger)

</script>

<body>
  <x-exchanger data-rate="110"></x-exchanger>
</body>