<|start_filename|>lib/registerElement.coffee<|end_filename|>
# numtel:webcomponent
# MIT License, <EMAIL>
# lib/registerElement.coffee

# Register a Blaze Template as a WebComponent
# @param {string} name - Node name for new element (must include hyphen)
# @param {object} options
# @option {string} css - Rules to apply in Shadow DOM context
# @option {[string]} cssLinks - list of hrefs
Blaze.Template.prototype.registerElement = (name, options) ->
  blazeTemplate = @
  options = _.defaults options || {},
    css: undefined
    cssLinks: []

  # Build styles from options
  styles = ''
  if options.css or options.cssLinks
    styles += '<style>'
    for link in options.cssLinks
      styles += '@import url("' + link + '");'
    if options.css
      styles += options.css
    styles += '</style>'
  # Blaze Template must be wrapped as jQuery fails to find children
  # directly from the shadowRoot.
  shadowContent = styles + '<div></div>'

  newPrototype = Object.create HTMLElement.prototype
  newPrototype.createdCallback = ->
    shadow = this.createShadowRoot()
    shadow.innerHTML = shadowContent
    @childRoot = shadow.querySelector 'div'
    @blazeData = {}
    @blazeView = Blaze.renderWithData blazeTemplate, @blazeData, @childRoot
    @blazeView.autorun =>
      _.each @blazeView.dataVar.get(), (name, attr) =>
        @childRoot.parentNode.host.setAttribute attr, name
  newPrototype.attributeChangedCallback = (name, oldValue, newValue) ->
    @blazeData = @blazeView.dataVar.get()
    @blazeData[name] = newValue
    @blazeView.dataVar.set @blazeData

  element = document.registerElement name,
    prototype: newPrototype

  # Create global reference
  nameCamelCase = name.replace /-([a-z])/g, (g) -> g[1].toUpperCase()
  window[nameCamelCase] = element


<|start_filename|>test/mockup/component.coffee<|end_filename|>
Session.setDefault 'counter', 0

Template.testElementInner.helpers
  counter: -> Session.get 'counter'

Template.testElementInner.events
  'click button': -> Session.set 'counter', Session.get('counter') + 1

Template.testElement.registerElement 'test-element',
  css: 'h1 { color: red; } p { color: blue; }'
  cssLinks: ['notfound.css']



<|start_filename|>test/mockup/component.css<|end_filename|>
p { color: green; }

test-element { display: none; }


<|start_filename|>test/componentRendered.coffee<|end_filename|>
# numtel:webcomponent
# MIT License, <EMAIL>
# test/componentRendered.coffee

Tinytest.add 'window reference created', (test) ->
  test.equal typeof window.testElement, 'function'

Tinytest.add 'return value correct', (test) ->
  retval = Template.testElement.registerElement 'return-test'
  test.equal typeof retval, 'function'

Tinytest.add 'h1 is red and contains "someval"', (test) ->
  rendered = document.querySelector 'test-element'
  h1 = rendered.shadowRoot.querySelector 'h1'
  style = rendered.shadowRoot.querySelector 'style'
  # Check attribute forwarding
  test.equal h1.innerHTML, 'someval'
  # Check css option
  test.include ['rgb(255, 0, 0)', 'red'], getStyleProperty(h1, 'color')
  # Check cssLinks option
  test.matches style.innerText, \
    /^(@import url\("notfound.css"\);)/

Tinytest.addAsync 'counter span text is 1 greater after click', (test, done) ->
  # Check that events and reactivity work
  rendered = document.querySelector 'test-element'
  span = rendered.shadowRoot.querySelector 'span'
  button = rendered.shadowRoot.querySelector 'button'
  origValue = parseInt span.innerHTML, 10
  $(button).trigger 'click'
  Meteor.setTimeout (->
    newValue = parseInt span.innerHTML, 10
    test.equal origValue, newValue - 1
    done()
  ), 10


<|start_filename|>package.js<|end_filename|>
Package.describe({
  name: 'numtel:webcomponent',
  summary: 'Create WebComponents from Templates',
  version: '0.0.6',
  git: 'https://github.com/numtel/meteor-webcomponent.git'
});

Package.onUse(function(api) {
  api.versionsFrom('METEOR@0.9.3.1');
  api.use([
    'underscore',
    'coffeescript',
    'templating'
  ]);
  api.addFiles([
    'dist/bindPolyfill.js',
    'dist/webcomponents.js',
    'lib/registerElement.coffee'
  ], 'client');
});

Package.onTest(function(api) {
  api.use([
    'tinytest',
    'test-helpers',
    'coffeescript',
    'session',
    'templating',
    'numtel:webcomponent'
  ]);
  api.addFiles([
    'test/mockup/component.html',
    'test/mockup/component.css',
    'test/mockup/component.coffee',
    'test/componentRendered.coffee'
  ], 'client');
});
