├── .gitignore
├── .travis.yml
├── .zuul.yml
├── README.md
├── dist
└── base-element.js
├── examples
├── angular.js
├── custom-element.js
├── ember.js
├── es6.js
├── list.js
├── nesting.js
├── react.js
├── server-side.js
├── standalone.js
├── virtual-dom.js
└── webcomponent.js
├── index.js
├── package.json
└── test
├── fixtures
├── button.js
└── nested.js
├── index.js
└── server.js
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - '0.12'
4 | before_install:
5 | - npm install npm -g
6 | before_script:
7 | - npm install
8 | script: npm run ci
9 | addons:
10 | sauce_connect: true
11 | env:
12 | global:
13 | - secure: hluRrXiBDo5jS+H6vp6LqFpuBOoM4E+G7knBYv8VoZ3C48sJsBpDFtKzfLBRBjwCS8+yrHlQT1I6l+1ESGwBZaSD7snn3rX+m7tv1FEoB/hlGLXCpGQAdRXVM9RmSbMf4MvaG4VQIIZzGIsu8zkv3AiD9lg5tb9/IQ+OgeKOZ04=
14 | - secure: Oyo6tyhBv5xaKYmHdVboMO4TL1Wvb5jZ3kyA7vXndyA8aZBqFqSh9PRuu9JDXNK+MPvvYyZLjSB3xiXQAAmY01W4f4dRiKmdBapr+hVAWUtAHcxJIFYpLnUcxPgin8ZvkIEBSRSEVyTfJZEp3Lcrf0DLfiGXK5uRqTdI3DNwYUM=
15 |
--------------------------------------------------------------------------------
/.zuul.yml:
--------------------------------------------------------------------------------
1 | ui: tape
2 | browsers:
3 | - name: chrome
4 | version: latest
5 | - name: firefox
6 | version: latest
7 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # base-element
2 | An element authoring library for creating standalone and performant elements.
3 |
4 | [](https://travis-ci.org/shama/base-element)
5 | [](https://badge.fury.io/js/base-element)
6 | [](http://github.com/hughsk/stability-badges)
7 |
8 | [](https://saucelabs.com/u/shama)
9 |
10 | View [this example List element](https://github.com/shama/base-element/blob/master/examples/list.js) in use with:
11 | * [Angular](https://github.com/shama/base-element/blob/master/examples/angular.js)
12 | * [React](https://github.com/shama/base-element/blob/master/examples/react.js)
13 | * [Ember](https://github.com/shama/base-element/blob/master/examples/ember.js)
14 | * [Web Component](https://github.com/shama/base-element/blob/master/examples/webcomponent.js)
15 | * [virtual-dom](https://github.com/shama/base-element/blob/master/examples/virtual-dom.js)
16 | * [or just standalone](https://github.com/shama/base-element/blob/master/examples/standalone.js)
17 |
18 | Or other examples:
19 | * [with ES6](https://github.com/shama/base-element/blob/master/examples/es6.js)
20 | * [nested architecture](https://github.com/shama/base-element/blob/master/examples/nesting.js)
21 | * [server side rendering](https://github.com/shama/base-element/blob/master/examples/server-side.js)
22 |
23 | ## example usage
24 | You can construct your element API however you choose. A way that I prefer is
25 | by inheriting prototypes:
26 |
27 | ```js
28 | var BaseElement = require('base-element')
29 |
30 | function Bear () {
31 | BaseElement.call(this)
32 | }
33 | Bear.prototype = Object.create(BaseElement.prototype)
34 | // Or inherits(Bear, BaseElement)
35 | // Or class Bear extends BaseElement
36 | ```
37 |
38 | Then build your elements:
39 |
40 | ```js
41 | Bear.prototype.render = function (typeOfBear) {
42 | // Create a virtual DOM tree
43 | var vtree = this.html('div.bear', ['Im a ' + typeOfBear + '!'])
44 | // Call afterRender with your vtree when returning your vtree
45 | return this.afterRender(vtree)
46 | }
47 | ```
48 |
49 | ### Prefer just functions?
50 | If you prefer just functions, an alternative interface is available:
51 |
52 | ```js
53 | var createElement = require('base-element')
54 |
55 | // Create an element on a parent
56 | var el = createElement(document.body)
57 | el.render(function () {
58 | // Render a button upon clicked will alert
59 | return el.html('button', {
60 | onclick: function (e) {
61 | window.alert(e.target.innerText + ' button was clicked')
62 | }
63 | }, 'click me')
64 | })
65 | ```
66 |
67 | ### data down, events up
68 | DOMs work best (in the opinion of myself and many) when data goes down
69 | and event (or actions) go up.
70 |
71 | A simple example is a button element that changes when clicked. **How** it
72 | changes is up to the element but **what** it changes to is up to the user.
73 |
74 | This is our Button element:
75 |
76 | ```js
77 | var BaseElement = require('base-element')
78 |
79 | function Button () {
80 | BaseElement.call(this)
81 | }
82 | Button.prototype = Object.create(BaseElement.prototype)
83 | // Or inherits(Button, BaseElement)
84 | // Or class Button extends BaseElement
85 |
86 | Button.prototype.render = function (label) {
87 | var self = this
88 | // The "label" data is coming down
89 | var vtree = this.html('button', {
90 | onclick: function (event) {
91 | // We send the "clicked" event up
92 | self.send('clicked', event.target)
93 | }
94 | }, label)
95 | return this.afterRender(vtree)
96 | }
97 | ```
98 |
99 | and this is the user's implementation, creates a button and on every click it
100 | changes to a random number:
101 |
102 | ```js
103 | var button = require('your-button')()
104 | button.addEventListener('clicked', function (node) {
105 | button.render('button label ' + Math.random())
106 | })
107 | ```
108 |
109 | ### nested architecture
110 | Elements created using `base-element` are intended on being shared and extended
111 | by others. Each element should not require an additional library/framework to
112 | run it or be injected into it in order to be ran. Elements should be standalone.
113 |
114 | For example if you create an `input-box` element and published on npm:
115 |
116 | ```js
117 | var BaseElement = require('base-element')
118 | function InputBox (el) {
119 | BaseElement.call(this, el)
120 | }
121 | InputBox.prototype = Object.create(BaseElement.prototype)
122 | module.exports = InputBox
123 |
124 | InputBox.prototype.render = function (value) {
125 | // Builds an Enter your email inside this
157 | this.html('label', data.label || 'Enter your email'),
158 | // Call the InputBox's render
159 | InputBox.prototype.render(data.value)
160 | ])
161 | // Return the virtual DOM tree
162 | return this.afterRender(vtree)
163 | }
164 | ```
165 |
166 | Both `input-box` and `email-input` can be ran on their own. When `input-box`
167 | updates over time, `email-input` can stay on a previous version until an upgrade
168 | can be made.
169 |
170 | ## install
171 |
172 | ### npm with browserify, webpack, etc
173 |
174 | * `npm install base-element`
175 | * `var BaseElement = require('base-element')`
176 |
177 | ### standalone
178 |
179 | * copy/download/etc [dist/base-element.js](https://github.com/shama/base-element/blob/master/dist/base-element.js)
180 | * ``
181 | * ``
182 |
183 | ## api
184 |
185 | ### `var element = new BaseElement([attachTo])`
186 | `attachTo` is a DOM element you want to append to such as `document.body`
187 |
188 | By default, the element will not attach itself to a parent node. This is useful
189 | for handling the rendering on your own.
190 |
191 | ### `element.send(name[, params...])`
192 | Sends an event up with a given `name` and `params`.
193 |
194 | ### `element.addEventListener(name, function)`
195 | Register an event listener for a given name:
196 |
197 | ```js
198 | element.addEventListener('clicked', function (params) {})
199 | ```
200 |
201 | ### `element.afterRender([params...])`
202 | This method needs to be called when returning a constructed virtual tree. It
203 | will detect if we are at the top of the render tree and perform the DOM diff
204 | and patching.
205 |
206 | ```js
207 | Button.prototype.render = function (data) {
208 | var vtree = this.html('button')
209 | return this.afterRender(vtree)
210 | }
211 | ```
212 |
213 | ### `element.html(tag[, options], value)`
214 | A convenience wrapper for creating virtual-hyperscript nodes, i.e.:
215 |
216 | ```js
217 | var h = require('virtual-dom/h')
218 | var vtree = h('div', 'Testing')
219 |
220 | // is the same as
221 | var vtree = this.html('div', 'Testing')
222 | ```
223 |
224 | ### `element.toString([data...])`
225 | For rendering your element as a string of HTML. `data` is any initial data
226 | passed to your `render` function.
227 |
228 | ### `element.element`
229 | The root DOM node the virtual tree resides on.
230 |
231 | ### `element.vtree`
232 | The current virtual DOM tree of the base element.
233 |
234 | ### default events
235 | `load` and `unload` events will be sent by default if your top level element
236 | registers `this` as it's properties:
237 |
238 | ```js
239 | var BaseElement = require('base-element')
240 | function Button(el) {
241 | BaseElement.call(this, el)
242 | this.addEventListener('load', function (node) {
243 | console.log(node + ' has loaded!')
244 | })
245 | this.addEventListener('unload', function (node) {
246 | console.log(node + ' has unloaded!')
247 | })
248 | }
249 | Button.prototype.render = function (data) {
250 | // The top level element is provided with `this`, events will be fired
251 | return this.afterRender(this.html('button', this, 'click me'))
252 | }
253 | ```
254 |
255 | ## similar projects
256 |
257 | * [vel](https://github.com/yoshuawuyts/vel)
258 | create and render virtual-dom elements with ease
259 |
260 | # license
261 | (c) 2015 Kyle Robinson Young. MIT License
262 |
--------------------------------------------------------------------------------
/dist/base-element.js:
--------------------------------------------------------------------------------
1 | (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.BaseElement = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o';
163 | }
164 |
165 | function tagContent(node) {
166 | var innerHTML = node.properties.innerHTML;
167 | if (innerHTML != null) return innerHTML;
168 | else {
169 | var ret = '';
170 | if (node.children && node.children.length) {
171 | for (var i = 0, l = node.children.length; i';
183 | }
184 | },{"./create-attribute":3,"./void-elements":14,"escape-html":5,"param-case":11,"virtual-dom/virtual-hyperscript/hooks/attribute-hook":31,"virtual-dom/virtual-hyperscript/hooks/soft-set-hook":33,"virtual-dom/vnode/is-thunk":37,"virtual-dom/vnode/is-vnode":39,"virtual-dom/vnode/is-vtext":40,"virtual-dom/vnode/is-widget":41,"xtend":12}],5:[function(require,module,exports){
185 | /**
186 | * Escape special characters in the given string of html.
187 | *
188 | * @param {String} html
189 | * @return {String}
190 | * @api private
191 | */
192 |
193 | module.exports = function(html) {
194 | return String(html)
195 | .replace(/&/g, '&')
196 | .replace(/"/g, '"')
197 | .replace(/'/g, ''')
198 | .replace(//g, '>');
200 | }
201 |
202 | },{}],6:[function(require,module,exports){
203 | /**
204 | * Special language-specific overrides.
205 | *
206 | * Source: ftp://ftp.unicode.org/Public/UCD/latest/ucd/SpecialCasing.txt
207 | *
208 | * @type {Object}
209 | */
210 | var LANGUAGES = {
211 | tr: {
212 | regexp: /\u0130|\u0049|\u0049\u0307/g,
213 | map: {
214 | '\u0130': '\u0069',
215 | '\u0049': '\u0131',
216 | '\u0049\u0307': '\u0069'
217 | }
218 | },
219 | az: {
220 | regexp: /[\u0130]/g,
221 | map: {
222 | '\u0130': '\u0069',
223 | '\u0049': '\u0131',
224 | '\u0049\u0307': '\u0069'
225 | }
226 | },
227 | lt: {
228 | regexp: /[\u0049\u004A\u012E\u00CC\u00CD\u0128]/g,
229 | map: {
230 | '\u0049': '\u0069\u0307',
231 | '\u004A': '\u006A\u0307',
232 | '\u012E': '\u012F\u0307',
233 | '\u00CC': '\u0069\u0307\u0300',
234 | '\u00CD': '\u0069\u0307\u0301',
235 | '\u0128': '\u0069\u0307\u0303'
236 | }
237 | }
238 | }
239 |
240 | /**
241 | * Lowercase a string.
242 | *
243 | * @param {String} str
244 | * @return {String}
245 | */
246 | module.exports = function (str, locale) {
247 | var lang = LANGUAGES[locale]
248 |
249 | str = str == null ? '' : String(str)
250 |
251 | if (lang) {
252 | str = str.replace(lang.regexp, function (m) { return lang.map[m] })
253 | }
254 |
255 | return str.toLowerCase()
256 | }
257 |
258 | },{}],7:[function(require,module,exports){
259 | var lowerCase = require('lower-case')
260 |
261 | var NON_WORD_REGEXP = require('./vendor/non-word-regexp')
262 | var CAMEL_CASE_REGEXP = require('./vendor/camel-case-regexp')
263 | var TRAILING_DIGIT_REGEXP = require('./vendor/trailing-digit-regexp')
264 |
265 | /**
266 | * Sentence case a string.
267 | *
268 | * @param {String} str
269 | * @param {String} locale
270 | * @param {String} replacement
271 | * @return {String}
272 | */
273 | module.exports = function (str, locale, replacement) {
274 | if (str == null) {
275 | return ''
276 | }
277 |
278 | replacement = replacement || ' '
279 |
280 | function replace (match, index, string) {
281 | if (index === 0 || index === (string.length - match.length)) {
282 | return ''
283 | }
284 |
285 | return replacement
286 | }
287 |
288 | str = String(str)
289 | // Support camel case ("camelCase" -> "camel Case").
290 | .replace(CAMEL_CASE_REGEXP, '$1 $2')
291 | // Support digit groups ("test2012" -> "test 2012").
292 | .replace(TRAILING_DIGIT_REGEXP, '$1 $2')
293 | // Remove all non-word characters and replace with a single space.
294 | .replace(NON_WORD_REGEXP, replace)
295 |
296 | // Lower case the entire string.
297 | return lowerCase(str, locale)
298 | }
299 |
300 | },{"./vendor/camel-case-regexp":8,"./vendor/non-word-regexp":9,"./vendor/trailing-digit-regexp":10,"lower-case":6}],8:[function(require,module,exports){
301 | module.exports = /([\u0061-\u007A\u00B5\u00DF-\u00F6\u00F8-\u00FF\u0101\u0103\u0105\u0107\u0109\u010B\u010D\u010F\u0111\u0113\u0115\u0117\u0119\u011B\u011D\u011F\u0121\u0123\u0125\u0127\u0129\u012B\u012D\u012F\u0131\u0133\u0135\u0137\u0138\u013A\u013C\u013E\u0140\u0142\u0144\u0146\u0148\u0149\u014B\u014D\u014F\u0151\u0153\u0155\u0157\u0159\u015B\u015D\u015F\u0161\u0163\u0165\u0167\u0169\u016B\u016D\u016F\u0171\u0173\u0175\u0177\u017A\u017C\u017E-\u0180\u0183\u0185\u0188\u018C\u018D\u0192\u0195\u0199-\u019B\u019E\u01A1\u01A3\u01A5\u01A8\u01AA\u01AB\u01AD\u01B0\u01B4\u01B6\u01B9\u01BA\u01BD-\u01BF\u01C6\u01C9\u01CC\u01CE\u01D0\u01D2\u01D4\u01D6\u01D8\u01DA\u01DC\u01DD\u01DF\u01E1\u01E3\u01E5\u01E7\u01E9\u01EB\u01ED\u01EF\u01F0\u01F3\u01F5\u01F9\u01FB\u01FD\u01FF\u0201\u0203\u0205\u0207\u0209\u020B\u020D\u020F\u0211\u0213\u0215\u0217\u0219\u021B\u021D\u021F\u0221\u0223\u0225\u0227\u0229\u022B\u022D\u022F\u0231\u0233-\u0239\u023C\u023F\u0240\u0242\u0247\u0249\u024B\u024D\u024F-\u0293\u0295-\u02AF\u0371\u0373\u0377\u037B-\u037D\u0390\u03AC-\u03CE\u03D0\u03D1\u03D5-\u03D7\u03D9\u03DB\u03DD\u03DF\u03E1\u03E3\u03E5\u03E7\u03E9\u03EB\u03ED\u03EF-\u03F3\u03F5\u03F8\u03FB\u03FC\u0430-\u045F\u0461\u0463\u0465\u0467\u0469\u046B\u046D\u046F\u0471\u0473\u0475\u0477\u0479\u047B\u047D\u047F\u0481\u048B\u048D\u048F\u0491\u0493\u0495\u0497\u0499\u049B\u049D\u049F\u04A1\u04A3\u04A5\u04A7\u04A9\u04AB\u04AD\u04AF\u04B1\u04B3\u04B5\u04B7\u04B9\u04BB\u04BD\u04BF\u04C2\u04C4\u04C6\u04C8\u04CA\u04CC\u04CE\u04CF\u04D1\u04D3\u04D5\u04D7\u04D9\u04DB\u04DD\u04DF\u04E1\u04E3\u04E5\u04E7\u04E9\u04EB\u04ED\u04EF\u04F1\u04F3\u04F5\u04F7\u04F9\u04FB\u04FD\u04FF\u0501\u0503\u0505\u0507\u0509\u050B\u050D\u050F\u0511\u0513\u0515\u0517\u0519\u051B\u051D\u051F\u0521\u0523\u0525\u0527\u0561-\u0587\u1D00-\u1D2B\u1D6B-\u1D77\u1D79-\u1D9A\u1E01\u1E03\u1E05\u1E07\u1E09\u1E0B\u1E0D\u1E0F\u1E11\u1E13\u1E15\u1E17\u1E19\u1E1B\u1E1D\u1E1F\u1E21\u1E23\u1E25\u1E27\u1E29\u1E2B\u1E2D\u1E2F\u1E31\u1E33\u1E35\u1E37\u1E39\u1E3B\u1E3D\u1E3F\u1E41\u1E43\u1E45\u1E47\u1E49\u1E4B\u1E4D\u1E4F\u1E51\u1E53\u1E55\u1E57\u1E59\u1E5B\u1E5D\u1E5F\u1E61\u1E63\u1E65\u1E67\u1E69\u1E6B\u1E6D\u1E6F\u1E71\u1E73\u1E75\u1E77\u1E79\u1E7B\u1E7D\u1E7F\u1E81\u1E83\u1E85\u1E87\u1E89\u1E8B\u1E8D\u1E8F\u1E91\u1E93\u1E95-\u1E9D\u1E9F\u1EA1\u1EA3\u1EA5\u1EA7\u1EA9\u1EAB\u1EAD\u1EAF\u1EB1\u1EB3\u1EB5\u1EB7\u1EB9\u1EBB\u1EBD\u1EBF\u1EC1\u1EC3\u1EC5\u1EC7\u1EC9\u1ECB\u1ECD\u1ECF\u1ED1\u1ED3\u1ED5\u1ED7\u1ED9\u1EDB\u1EDD\u1EDF\u1EE1\u1EE3\u1EE5\u1EE7\u1EE9\u1EEB\u1EED\u1EEF\u1EF1\u1EF3\u1EF5\u1EF7\u1EF9\u1EFB\u1EFD\u1EFF-\u1F07\u1F10-\u1F15\u1F20-\u1F27\u1F30-\u1F37\u1F40-\u1F45\u1F50-\u1F57\u1F60-\u1F67\u1F70-\u1F7D\u1F80-\u1F87\u1F90-\u1F97\u1FA0-\u1FA7\u1FB0-\u1FB4\u1FB6\u1FB7\u1FBE\u1FC2-\u1FC4\u1FC6\u1FC7\u1FD0-\u1FD3\u1FD6\u1FD7\u1FE0-\u1FE7\u1FF2-\u1FF4\u1FF6\u1FF7\u210A\u210E\u210F\u2113\u212F\u2134\u2139\u213C\u213D\u2146-\u2149\u214E\u2184\u2C30-\u2C5E\u2C61\u2C65\u2C66\u2C68\u2C6A\u2C6C\u2C71\u2C73\u2C74\u2C76-\u2C7B\u2C81\u2C83\u2C85\u2C87\u2C89\u2C8B\u2C8D\u2C8F\u2C91\u2C93\u2C95\u2C97\u2C99\u2C9B\u2C9D\u2C9F\u2CA1\u2CA3\u2CA5\u2CA7\u2CA9\u2CAB\u2CAD\u2CAF\u2CB1\u2CB3\u2CB5\u2CB7\u2CB9\u2CBB\u2CBD\u2CBF\u2CC1\u2CC3\u2CC5\u2CC7\u2CC9\u2CCB\u2CCD\u2CCF\u2CD1\u2CD3\u2CD5\u2CD7\u2CD9\u2CDB\u2CDD\u2CDF\u2CE1\u2CE3\u2CE4\u2CEC\u2CEE\u2CF3\u2D00-\u2D25\u2D27\u2D2D\uA641\uA643\uA645\uA647\uA649\uA64B\uA64D\uA64F\uA651\uA653\uA655\uA657\uA659\uA65B\uA65D\uA65F\uA661\uA663\uA665\uA667\uA669\uA66B\uA66D\uA681\uA683\uA685\uA687\uA689\uA68B\uA68D\uA68F\uA691\uA693\uA695\uA697\uA723\uA725\uA727\uA729\uA72B\uA72D\uA72F-\uA731\uA733\uA735\uA737\uA739\uA73B\uA73D\uA73F\uA741\uA743\uA745\uA747\uA749\uA74B\uA74D\uA74F\uA751\uA753\uA755\uA757\uA759\uA75B\uA75D\uA75F\uA761\uA763\uA765\uA767\uA769\uA76B\uA76D\uA76F\uA771-\uA778\uA77A\uA77C\uA77F\uA781\uA783\uA785\uA787\uA78C\uA78E\uA791\uA793\uA7A1\uA7A3\uA7A5\uA7A7\uA7A9\uA7FA\uFB00-\uFB06\uFB13-\uFB17\uFF41-\uFF5A])([\u0041-\u005A\u00C0-\u00D6\u00D8-\u00DE\u0100\u0102\u0104\u0106\u0108\u010A\u010C\u010E\u0110\u0112\u0114\u0116\u0118\u011A\u011C\u011E\u0120\u0122\u0124\u0126\u0128\u012A\u012C\u012E\u0130\u0132\u0134\u0136\u0139\u013B\u013D\u013F\u0141\u0143\u0145\u0147\u014A\u014C\u014E\u0150\u0152\u0154\u0156\u0158\u015A\u015C\u015E\u0160\u0162\u0164\u0166\u0168\u016A\u016C\u016E\u0170\u0172\u0174\u0176\u0178\u0179\u017B\u017D\u0181\u0182\u0184\u0186\u0187\u0189-\u018B\u018E-\u0191\u0193\u0194\u0196-\u0198\u019C\u019D\u019F\u01A0\u01A2\u01A4\u01A6\u01A7\u01A9\u01AC\u01AE\u01AF\u01B1-\u01B3\u01B5\u01B7\u01B8\u01BC\u01C4\u01C7\u01CA\u01CD\u01CF\u01D1\u01D3\u01D5\u01D7\u01D9\u01DB\u01DE\u01E0\u01E2\u01E4\u01E6\u01E8\u01EA\u01EC\u01EE\u01F1\u01F4\u01F6-\u01F8\u01FA\u01FC\u01FE\u0200\u0202\u0204\u0206\u0208\u020A\u020C\u020E\u0210\u0212\u0214\u0216\u0218\u021A\u021C\u021E\u0220\u0222\u0224\u0226\u0228\u022A\u022C\u022E\u0230\u0232\u023A\u023B\u023D\u023E\u0241\u0243-\u0246\u0248\u024A\u024C\u024E\u0370\u0372\u0376\u0386\u0388-\u038A\u038C\u038E\u038F\u0391-\u03A1\u03A3-\u03AB\u03CF\u03D2-\u03D4\u03D8\u03DA\u03DC\u03DE\u03E0\u03E2\u03E4\u03E6\u03E8\u03EA\u03EC\u03EE\u03F4\u03F7\u03F9\u03FA\u03FD-\u042F\u0460\u0462\u0464\u0466\u0468\u046A\u046C\u046E\u0470\u0472\u0474\u0476\u0478\u047A\u047C\u047E\u0480\u048A\u048C\u048E\u0490\u0492\u0494\u0496\u0498\u049A\u049C\u049E\u04A0\u04A2\u04A4\u04A6\u04A8\u04AA\u04AC\u04AE\u04B0\u04B2\u04B4\u04B6\u04B8\u04BA\u04BC\u04BE\u04C0\u04C1\u04C3\u04C5\u04C7\u04C9\u04CB\u04CD\u04D0\u04D2\u04D4\u04D6\u04D8\u04DA\u04DC\u04DE\u04E0\u04E2\u04E4\u04E6\u04E8\u04EA\u04EC\u04EE\u04F0\u04F2\u04F4\u04F6\u04F8\u04FA\u04FC\u04FE\u0500\u0502\u0504\u0506\u0508\u050A\u050C\u050E\u0510\u0512\u0514\u0516\u0518\u051A\u051C\u051E\u0520\u0522\u0524\u0526\u0531-\u0556\u10A0-\u10C5\u10C7\u10CD\u1E00\u1E02\u1E04\u1E06\u1E08\u1E0A\u1E0C\u1E0E\u1E10\u1E12\u1E14\u1E16\u1E18\u1E1A\u1E1C\u1E1E\u1E20\u1E22\u1E24\u1E26\u1E28\u1E2A\u1E2C\u1E2E\u1E30\u1E32\u1E34\u1E36\u1E38\u1E3A\u1E3C\u1E3E\u1E40\u1E42\u1E44\u1E46\u1E48\u1E4A\u1E4C\u1E4E\u1E50\u1E52\u1E54\u1E56\u1E58\u1E5A\u1E5C\u1E5E\u1E60\u1E62\u1E64\u1E66\u1E68\u1E6A\u1E6C\u1E6E\u1E70\u1E72\u1E74\u1E76\u1E78\u1E7A\u1E7C\u1E7E\u1E80\u1E82\u1E84\u1E86\u1E88\u1E8A\u1E8C\u1E8E\u1E90\u1E92\u1E94\u1E9E\u1EA0\u1EA2\u1EA4\u1EA6\u1EA8\u1EAA\u1EAC\u1EAE\u1EB0\u1EB2\u1EB4\u1EB6\u1EB8\u1EBA\u1EBC\u1EBE\u1EC0\u1EC2\u1EC4\u1EC6\u1EC8\u1ECA\u1ECC\u1ECE\u1ED0\u1ED2\u1ED4\u1ED6\u1ED8\u1EDA\u1EDC\u1EDE\u1EE0\u1EE2\u1EE4\u1EE6\u1EE8\u1EEA\u1EEC\u1EEE\u1EF0\u1EF2\u1EF4\u1EF6\u1EF8\u1EFA\u1EFC\u1EFE\u1F08-\u1F0F\u1F18-\u1F1D\u1F28-\u1F2F\u1F38-\u1F3F\u1F48-\u1F4D\u1F59\u1F5B\u1F5D\u1F5F\u1F68-\u1F6F\u1FB8-\u1FBB\u1FC8-\u1FCB\u1FD8-\u1FDB\u1FE8-\u1FEC\u1FF8-\u1FFB\u2102\u2107\u210B-\u210D\u2110-\u2112\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u2130-\u2133\u213E\u213F\u2145\u2183\u2C00-\u2C2E\u2C60\u2C62-\u2C64\u2C67\u2C69\u2C6B\u2C6D-\u2C70\u2C72\u2C75\u2C7E-\u2C80\u2C82\u2C84\u2C86\u2C88\u2C8A\u2C8C\u2C8E\u2C90\u2C92\u2C94\u2C96\u2C98\u2C9A\u2C9C\u2C9E\u2CA0\u2CA2\u2CA4\u2CA6\u2CA8\u2CAA\u2CAC\u2CAE\u2CB0\u2CB2\u2CB4\u2CB6\u2CB8\u2CBA\u2CBC\u2CBE\u2CC0\u2CC2\u2CC4\u2CC6\u2CC8\u2CCA\u2CCC\u2CCE\u2CD0\u2CD2\u2CD4\u2CD6\u2CD8\u2CDA\u2CDC\u2CDE\u2CE0\u2CE2\u2CEB\u2CED\u2CF2\uA640\uA642\uA644\uA646\uA648\uA64A\uA64C\uA64E\uA650\uA652\uA654\uA656\uA658\uA65A\uA65C\uA65E\uA660\uA662\uA664\uA666\uA668\uA66A\uA66C\uA680\uA682\uA684\uA686\uA688\uA68A\uA68C\uA68E\uA690\uA692\uA694\uA696\uA722\uA724\uA726\uA728\uA72A\uA72C\uA72E\uA732\uA734\uA736\uA738\uA73A\uA73C\uA73E\uA740\uA742\uA744\uA746\uA748\uA74A\uA74C\uA74E\uA750\uA752\uA754\uA756\uA758\uA75A\uA75C\uA75E\uA760\uA762\uA764\uA766\uA768\uA76A\uA76C\uA76E\uA779\uA77B\uA77D\uA77E\uA780\uA782\uA784\uA786\uA78B\uA78D\uA790\uA792\uA7A0\uA7A2\uA7A4\uA7A6\uA7A8\uA7AA\uFF21-\uFF3A\u0030-\u0039\u00B2\u00B3\u00B9\u00BC-\u00BE\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u09F4-\u09F9\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0B72-\u0B77\u0BE6-\u0BF2\u0C66-\u0C6F\u0C78-\u0C7E\u0CE6-\u0CEF\u0D66-\u0D75\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F33\u1040-\u1049\u1090-\u1099\u1369-\u137C\u16EE-\u16F0\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1946-\u194F\u19D0-\u19DA\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\u2070\u2074-\u2079\u2080-\u2089\u2150-\u2182\u2185-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2CFD\u3007\u3021-\u3029\u3038-\u303A\u3192-\u3195\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\uA620-\uA629\uA6E6-\uA6EF\uA830-\uA835\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19])/g
302 |
303 | },{}],9:[function(require,module,exports){
304 | module.exports = /[^\u0041-\u005A\u0061-\u007A\u00AA\u00B5\u00BA\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02C1\u02C6-\u02D1\u02E0-\u02E4\u02EC\u02EE\u0370-\u0374\u0376\u0377\u037A-\u037D\u0386\u0388-\u038A\u038C\u038E-\u03A1\u03A3-\u03F5\u03F7-\u0481\u048A-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05D0-\u05EA\u05F0-\u05F2\u0620-\u064A\u066E\u066F\u0671-\u06D3\u06D5\u06E5\u06E6\u06EE\u06EF\u06FA-\u06FC\u06FF\u0710\u0712-\u072F\u074D-\u07A5\u07B1\u07CA-\u07EA\u07F4\u07F5\u07FA\u0800-\u0815\u081A\u0824\u0828\u0840-\u0858\u08A0\u08A2-\u08AC\u0904-\u0939\u093D\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097F\u0985-\u098C\u098F\u0990\u0993-\u09A8\u09AA-\u09B0\u09B2\u09B6-\u09B9\u09BD\u09CE\u09DC\u09DD\u09DF-\u09E1\u09F0\u09F1\u0A05-\u0A0A\u0A0F\u0A10\u0A13-\u0A28\u0A2A-\u0A30\u0A32\u0A33\u0A35\u0A36\u0A38\u0A39\u0A59-\u0A5C\u0A5E\u0A72-\u0A74\u0A85-\u0A8D\u0A8F-\u0A91\u0A93-\u0AA8\u0AAA-\u0AB0\u0AB2\u0AB3\u0AB5-\u0AB9\u0ABD\u0AD0\u0AE0\u0AE1\u0B05-\u0B0C\u0B0F\u0B10\u0B13-\u0B28\u0B2A-\u0B30\u0B32\u0B33\u0B35-\u0B39\u0B3D\u0B5C\u0B5D\u0B5F-\u0B61\u0B71\u0B83\u0B85-\u0B8A\u0B8E-\u0B90\u0B92-\u0B95\u0B99\u0B9A\u0B9C\u0B9E\u0B9F\u0BA3\u0BA4\u0BA8-\u0BAA\u0BAE-\u0BB9\u0BD0\u0C05-\u0C0C\u0C0E-\u0C10\u0C12-\u0C28\u0C2A-\u0C33\u0C35-\u0C39\u0C3D\u0C58\u0C59\u0C60\u0C61\u0C85-\u0C8C\u0C8E-\u0C90\u0C92-\u0CA8\u0CAA-\u0CB3\u0CB5-\u0CB9\u0CBD\u0CDE\u0CE0\u0CE1\u0CF1\u0CF2\u0D05-\u0D0C\u0D0E-\u0D10\u0D12-\u0D3A\u0D3D\u0D4E\u0D60\u0D61\u0D7A-\u0D7F\u0D85-\u0D96\u0D9A-\u0DB1\u0DB3-\u0DBB\u0DBD\u0DC0-\u0DC6\u0E01-\u0E30\u0E32\u0E33\u0E40-\u0E46\u0E81\u0E82\u0E84\u0E87\u0E88\u0E8A\u0E8D\u0E94-\u0E97\u0E99-\u0E9F\u0EA1-\u0EA3\u0EA5\u0EA7\u0EAA\u0EAB\u0EAD-\u0EB0\u0EB2\u0EB3\u0EBD\u0EC0-\u0EC4\u0EC6\u0EDC-\u0EDF\u0F00\u0F40-\u0F47\u0F49-\u0F6C\u0F88-\u0F8C\u1000-\u102A\u103F\u1050-\u1055\u105A-\u105D\u1061\u1065\u1066\u106E-\u1070\u1075-\u1081\u108E\u10A0-\u10C5\u10C7\u10CD\u10D0-\u10FA\u10FC-\u1248\u124A-\u124D\u1250-\u1256\u1258\u125A-\u125D\u1260-\u1288\u128A-\u128D\u1290-\u12B0\u12B2-\u12B5\u12B8-\u12BE\u12C0\u12C2-\u12C5\u12C8-\u12D6\u12D8-\u1310\u1312-\u1315\u1318-\u135A\u1380-\u138F\u13A0-\u13F4\u1401-\u166C\u166F-\u167F\u1681-\u169A\u16A0-\u16EA\u1700-\u170C\u170E-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176C\u176E-\u1770\u1780-\u17B3\u17D7\u17DC\u1820-\u1877\u1880-\u18A8\u18AA\u18B0-\u18F5\u1900-\u191C\u1950-\u196D\u1970-\u1974\u1980-\u19AB\u19C1-\u19C7\u1A00-\u1A16\u1A20-\u1A54\u1AA7\u1B05-\u1B33\u1B45-\u1B4B\u1B83-\u1BA0\u1BAE\u1BAF\u1BBA-\u1BE5\u1C00-\u1C23\u1C4D-\u1C4F\u1C5A-\u1C7D\u1CE9-\u1CEC\u1CEE-\u1CF1\u1CF5\u1CF6\u1D00-\u1DBF\u1E00-\u1F15\u1F18-\u1F1D\u1F20-\u1F45\u1F48-\u1F4D\u1F50-\u1F57\u1F59\u1F5B\u1F5D\u1F5F-\u1F7D\u1F80-\u1FB4\u1FB6-\u1FBC\u1FBE\u1FC2-\u1FC4\u1FC6-\u1FCC\u1FD0-\u1FD3\u1FD6-\u1FDB\u1FE0-\u1FEC\u1FF2-\u1FF4\u1FF6-\u1FFC\u2071\u207F\u2090-\u209C\u2102\u2107\u210A-\u2113\u2115\u2119-\u211D\u2124\u2126\u2128\u212A-\u212D\u212F-\u2139\u213C-\u213F\u2145-\u2149\u214E\u2183\u2184\u2C00-\u2C2E\u2C30-\u2C5E\u2C60-\u2CE4\u2CEB-\u2CEE\u2CF2\u2CF3\u2D00-\u2D25\u2D27\u2D2D\u2D30-\u2D67\u2D6F\u2D80-\u2D96\u2DA0-\u2DA6\u2DA8-\u2DAE\u2DB0-\u2DB6\u2DB8-\u2DBE\u2DC0-\u2DC6\u2DC8-\u2DCE\u2DD0-\u2DD6\u2DD8-\u2DDE\u2E2F\u3005\u3006\u3031-\u3035\u303B\u303C\u3041-\u3096\u309D-\u309F\u30A1-\u30FA\u30FC-\u30FF\u3105-\u312D\u3131-\u318E\u31A0-\u31BA\u31F0-\u31FF\u3400-\u4DB5\u4E00-\u9FCC\uA000-\uA48C\uA4D0-\uA4FD\uA500-\uA60C\uA610-\uA61F\uA62A\uA62B\uA640-\uA66E\uA67F-\uA697\uA6A0-\uA6E5\uA717-\uA71F\uA722-\uA788\uA78B-\uA78E\uA790-\uA793\uA7A0-\uA7AA\uA7F8-\uA801\uA803-\uA805\uA807-\uA80A\uA80C-\uA822\uA840-\uA873\uA882-\uA8B3\uA8F2-\uA8F7\uA8FB\uA90A-\uA925\uA930-\uA946\uA960-\uA97C\uA984-\uA9B2\uA9CF\uAA00-\uAA28\uAA40-\uAA42\uAA44-\uAA4B\uAA60-\uAA76\uAA7A\uAA80-\uAAAF\uAAB1\uAAB5\uAAB6\uAAB9-\uAABD\uAAC0\uAAC2\uAADB-\uAADD\uAAE0-\uAAEA\uAAF2-\uAAF4\uAB01-\uAB06\uAB09-\uAB0E\uAB11-\uAB16\uAB20-\uAB26\uAB28-\uAB2E\uABC0-\uABE2\uAC00-\uD7A3\uD7B0-\uD7C6\uD7CB-\uD7FB\uF900-\uFA6D\uFA70-\uFAD9\uFB00-\uFB06\uFB13-\uFB17\uFB1D\uFB1F-\uFB28\uFB2A-\uFB36\uFB38-\uFB3C\uFB3E\uFB40\uFB41\uFB43\uFB44\uFB46-\uFBB1\uFBD3-\uFD3D\uFD50-\uFD8F\uFD92-\uFDC7\uFDF0-\uFDFB\uFE70-\uFE74\uFE76-\uFEFC\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFBE\uFFC2-\uFFC7\uFFCA-\uFFCF\uFFD2-\uFFD7\uFFDA-\uFFDC\u0030-\u0039\u00B2\u00B3\u00B9\u00BC-\u00BE\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u09F4-\u09F9\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0B72-\u0B77\u0BE6-\u0BF2\u0C66-\u0C6F\u0C78-\u0C7E\u0CE6-\u0CEF\u0D66-\u0D75\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F33\u1040-\u1049\u1090-\u1099\u1369-\u137C\u16EE-\u16F0\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1946-\u194F\u19D0-\u19DA\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\u2070\u2074-\u2079\u2080-\u2089\u2150-\u2182\u2185-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2CFD\u3007\u3021-\u3029\u3038-\u303A\u3192-\u3195\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\uA620-\uA629\uA6E6-\uA6EF\uA830-\uA835\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19]+/g
305 |
306 | },{}],10:[function(require,module,exports){
307 | module.exports = /([\u0030-\u0039\u00B2\u00B3\u00B9\u00BC-\u00BE\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u09F4-\u09F9\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0B72-\u0B77\u0BE6-\u0BF2\u0C66-\u0C6F\u0C78-\u0C7E\u0CE6-\u0CEF\u0D66-\u0D75\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F33\u1040-\u1049\u1090-\u1099\u1369-\u137C\u16EE-\u16F0\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1946-\u194F\u19D0-\u19DA\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\u2070\u2074-\u2079\u2080-\u2089\u2150-\u2182\u2185-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2CFD\u3007\u3021-\u3029\u3038-\u303A\u3192-\u3195\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\uA620-\uA629\uA6E6-\uA6EF\uA830-\uA835\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19])([^\u0030-\u0039\u00B2\u00B3\u00B9\u00BC-\u00BE\u0660-\u0669\u06F0-\u06F9\u07C0-\u07C9\u0966-\u096F\u09E6-\u09EF\u09F4-\u09F9\u0A66-\u0A6F\u0AE6-\u0AEF\u0B66-\u0B6F\u0B72-\u0B77\u0BE6-\u0BF2\u0C66-\u0C6F\u0C78-\u0C7E\u0CE6-\u0CEF\u0D66-\u0D75\u0E50-\u0E59\u0ED0-\u0ED9\u0F20-\u0F33\u1040-\u1049\u1090-\u1099\u1369-\u137C\u16EE-\u16F0\u17E0-\u17E9\u17F0-\u17F9\u1810-\u1819\u1946-\u194F\u19D0-\u19DA\u1A80-\u1A89\u1A90-\u1A99\u1B50-\u1B59\u1BB0-\u1BB9\u1C40-\u1C49\u1C50-\u1C59\u2070\u2074-\u2079\u2080-\u2089\u2150-\u2182\u2185-\u2189\u2460-\u249B\u24EA-\u24FF\u2776-\u2793\u2CFD\u3007\u3021-\u3029\u3038-\u303A\u3192-\u3195\u3220-\u3229\u3248-\u324F\u3251-\u325F\u3280-\u3289\u32B1-\u32BF\uA620-\uA629\uA6E6-\uA6EF\uA830-\uA835\uA8D0-\uA8D9\uA900-\uA909\uA9D0-\uA9D9\uAA50-\uAA59\uABF0-\uABF9\uFF10-\uFF19])/g
308 |
309 | },{}],11:[function(require,module,exports){
310 | var sentenceCase = require('sentence-case');
311 |
312 | /**
313 | * Param case a string.
314 | *
315 | * @param {String} string
316 | * @param {String} [locale]
317 | * @return {String}
318 | */
319 | module.exports = function (string, locale) {
320 | return sentenceCase(string, locale, '-');
321 | };
322 |
323 | },{"sentence-case":7}],12:[function(require,module,exports){
324 | module.exports = extend
325 |
326 | function extend() {
327 | var target = {}
328 |
329 | for (var i = 0; i < arguments.length; i++) {
330 | var source = arguments[i]
331 |
332 | for (var key in source) {
333 | if (source.hasOwnProperty(key)) {
334 | target[key] = source[key]
335 | }
336 | }
337 | }
338 |
339 | return target
340 | }
341 |
342 | },{}],13:[function(require,module,exports){
343 | /**
344 | * Attribute types.
345 | */
346 |
347 | var types = {
348 | BOOLEAN: 1,
349 | OVERLOADED_BOOLEAN: 2
350 | };
351 |
352 | /**
353 | * Properties.
354 | *
355 | * Taken from https://github.com/facebook/react/blob/847357e42e5267b04dd6e297219eaa125ab2f9f4/src/browser/ui/dom/HTMLDOMPropertyConfig.js
356 | *
357 | */
358 |
359 | var properties = {
360 | /**
361 | * Standard Properties
362 | */
363 | accept: true,
364 | acceptCharset: true,
365 | accessKey: true,
366 | action: true,
367 | allowFullScreen: types.BOOLEAN,
368 | allowTransparency: true,
369 | alt: true,
370 | async: types.BOOLEAN,
371 | autocomplete: true,
372 | autofocus: types.BOOLEAN,
373 | autoplay: types.BOOLEAN,
374 | cellPadding: true,
375 | cellSpacing: true,
376 | charset: true,
377 | checked: types.BOOLEAN,
378 | classID: true,
379 | className: true,
380 | cols: true,
381 | colSpan: true,
382 | content: true,
383 | contentEditable: true,
384 | contextMenu: true,
385 | controls: types.BOOLEAN,
386 | coords: true,
387 | crossOrigin: true,
388 | data: true, // For `` acts as `src`.
389 | dateTime: true,
390 | defer: types.BOOLEAN,
391 | dir: true,
392 | disabled: types.BOOLEAN,
393 | download: types.OVERLOADED_BOOLEAN,
394 | draggable: true,
395 | enctype: true,
396 | form: true,
397 | formAction: true,
398 | formEncType: true,
399 | formMethod: true,
400 | formNoValidate: types.BOOLEAN,
401 | formTarget: true,
402 | frameBorder: true,
403 | headers: true,
404 | height: true,
405 | hidden: types.BOOLEAN,
406 | href: true,
407 | hreflang: true,
408 | htmlFor: true,
409 | httpEquiv: true,
410 | icon: true,
411 | id: true,
412 | label: true,
413 | lang: true,
414 | list: true,
415 | loop: types.BOOLEAN,
416 | manifest: true,
417 | marginHeight: true,
418 | marginWidth: true,
419 | max: true,
420 | maxLength: true,
421 | media: true,
422 | mediaGroup: true,
423 | method: true,
424 | min: true,
425 | multiple: types.BOOLEAN,
426 | muted: types.BOOLEAN,
427 | name: true,
428 | noValidate: types.BOOLEAN,
429 | open: true,
430 | pattern: true,
431 | placeholder: true,
432 | poster: true,
433 | preload: true,
434 | radiogroup: true,
435 | readOnly: types.BOOLEAN,
436 | rel: true,
437 | required: types.BOOLEAN,
438 | role: true,
439 | rows: true,
440 | rowSpan: true,
441 | sandbox: true,
442 | scope: true,
443 | scrolling: true,
444 | seamless: types.BOOLEAN,
445 | selected: types.BOOLEAN,
446 | shape: true,
447 | size: true,
448 | sizes: true,
449 | span: true,
450 | spellcheck: true,
451 | src: true,
452 | srcdoc: true,
453 | srcset: true,
454 | start: true,
455 | step: true,
456 | style: true,
457 | tabIndex: true,
458 | target: true,
459 | title: true,
460 | type: true,
461 | useMap: true,
462 | value: true,
463 | width: true,
464 | wmode: true,
465 |
466 | /**
467 | * Non-standard Properties
468 | */
469 | // autoCapitalize and autoCorrect are supported in Mobile Safari for
470 | // keyboard hints.
471 | autocapitalize: true,
472 | autocorrect: true,
473 | // itemProp, itemScope, itemType are for Microdata support. See
474 | // http://schema.org/docs/gs.html
475 | itemProp: true,
476 | itemScope: types.BOOLEAN,
477 | itemType: true,
478 | // property is supported for OpenGraph in meta tags.
479 | property: true
480 | };
481 |
482 | /**
483 | * Properties to attributes mapping.
484 | *
485 | * The ones not here are simply converted to lower case.
486 | */
487 |
488 | var attributeNames = {
489 | acceptCharset: 'accept-charset',
490 | className: 'class',
491 | htmlFor: 'for',
492 | httpEquiv: 'http-equiv'
493 | };
494 |
495 | /**
496 | * Exports.
497 | */
498 |
499 | module.exports = {
500 | attributeTypes: types,
501 | properties: properties,
502 | attributeNames: attributeNames
503 | };
504 | },{}],14:[function(require,module,exports){
505 |
506 | /**
507 | * Void elements.
508 | *
509 | * https://github.com/facebook/react/blob/v0.12.0/src/browser/ui/ReactDOMComponent.js#L99
510 | */
511 |
512 | module.exports = {
513 | 'area': true,
514 | 'base': true,
515 | 'br': true,
516 | 'col': true,
517 | 'embed': true,
518 | 'hr': true,
519 | 'img': true,
520 | 'input': true,
521 | 'keygen': true,
522 | 'link': true,
523 | 'meta': true,
524 | 'param': true,
525 | 'source': true,
526 | 'track': true,
527 | 'wbr': true
528 | };
529 | },{}],15:[function(require,module,exports){
530 | var createElement = require("./vdom/create-element.js")
531 |
532 | module.exports = createElement
533 |
534 | },{"./vdom/create-element.js":26}],16:[function(require,module,exports){
535 | var diff = require("./vtree/diff.js")
536 |
537 | module.exports = diff
538 |
539 | },{"./vtree/diff.js":47}],17:[function(require,module,exports){
540 | var h = require("./virtual-hyperscript/index.js")
541 |
542 | module.exports = h
543 |
544 | },{"./virtual-hyperscript/index.js":34}],18:[function(require,module,exports){
545 | /*!
546 | * Cross-Browser Split 1.1.1
547 | * Copyright 2007-2012 Steven Levithan
548 | * Available under the MIT License
549 | * ECMAScript compliant, uniform cross-browser split method
550 | */
551 |
552 | /**
553 | * Splits a string into an array of strings using a regex or string separator. Matches of the
554 | * separator are not included in the result array. However, if `separator` is a regex that contains
555 | * capturing groups, backreferences are spliced into the result each time `separator` is matched.
556 | * Fixes browser bugs compared to the native `String.prototype.split` and can be used reliably
557 | * cross-browser.
558 | * @param {String} str String to split.
559 | * @param {RegExp|String} separator Regex or string to use for separating the string.
560 | * @param {Number} [limit] Maximum number of items to include in the result array.
561 | * @returns {Array} Array of substrings.
562 | * @example
563 | *
564 | * // Basic use
565 | * split('a b c d', ' ');
566 | * // -> ['a', 'b', 'c', 'd']
567 | *
568 | * // With limit
569 | * split('a b c d', ' ', 2);
570 | * // -> ['a', 'b']
571 | *
572 | * // Backreferences in result array
573 | * split('..word1 word2..', /([a-z]+)(\d+)/i);
574 | * // -> ['..', 'word', '1', ' ', 'word', '2', '..']
575 | */
576 | module.exports = (function split(undef) {
577 |
578 | var nativeSplit = String.prototype.split,
579 | compliantExecNpcg = /()??/.exec("")[1] === undef,
580 | // NPCG: nonparticipating capturing group
581 | self;
582 |
583 | self = function(str, separator, limit) {
584 | // If `separator` is not a regex, use `nativeSplit`
585 | if (Object.prototype.toString.call(separator) !== "[object RegExp]") {
586 | return nativeSplit.call(str, separator, limit);
587 | }
588 | var output = [],
589 | flags = (separator.ignoreCase ? "i" : "") + (separator.multiline ? "m" : "") + (separator.extended ? "x" : "") + // Proposed for ES6
590 | (separator.sticky ? "y" : ""),
591 | // Firefox 3+
592 | lastLastIndex = 0,
593 | // Make `global` and avoid `lastIndex` issues by working with a copy
594 | separator = new RegExp(separator.source, flags + "g"),
595 | separator2, match, lastIndex, lastLength;
596 | str += ""; // Type-convert
597 | if (!compliantExecNpcg) {
598 | // Doesn't need flags gy, but they don't hurt
599 | separator2 = new RegExp("^" + separator.source + "$(?!\\s)", flags);
600 | }
601 | /* Values for `limit`, per the spec:
602 | * If undefined: 4294967295 // Math.pow(2, 32) - 1
603 | * If 0, Infinity, or NaN: 0
604 | * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
605 | * If negative number: 4294967296 - Math.floor(Math.abs(limit))
606 | * If other: Type-convert, then use the above rules
607 | */
608 | limit = limit === undef ? -1 >>> 0 : // Math.pow(2, 32) - 1
609 | limit >>> 0; // ToUint32(limit)
610 | while (match = separator.exec(str)) {
611 | // `separator.lastIndex` is not reliable cross-browser
612 | lastIndex = match.index + match[0].length;
613 | if (lastIndex > lastLastIndex) {
614 | output.push(str.slice(lastLastIndex, match.index));
615 | // Fix browsers whose `exec` methods don't consistently return `undefined` for
616 | // nonparticipating capturing groups
617 | if (!compliantExecNpcg && match.length > 1) {
618 | match[0].replace(separator2, function() {
619 | for (var i = 1; i < arguments.length - 2; i++) {
620 | if (arguments[i] === undef) {
621 | match[i] = undef;
622 | }
623 | }
624 | });
625 | }
626 | if (match.length > 1 && match.index < str.length) {
627 | Array.prototype.push.apply(output, match.slice(1));
628 | }
629 | lastLength = match[0].length;
630 | lastLastIndex = lastIndex;
631 | if (output.length >= limit) {
632 | break;
633 | }
634 | }
635 | if (separator.lastIndex === match.index) {
636 | separator.lastIndex++; // Avoid an infinite loop
637 | }
638 | }
639 | if (lastLastIndex === str.length) {
640 | if (lastLength || !separator.test("")) {
641 | output.push("");
642 | }
643 | } else {
644 | output.push(str.slice(lastLastIndex));
645 | }
646 | return output.length > limit ? output.slice(0, limit) : output;
647 | };
648 |
649 | return self;
650 | })();
651 |
652 | },{}],19:[function(require,module,exports){
653 | 'use strict';
654 |
655 | var OneVersionConstraint = require('individual/one-version');
656 |
657 | var MY_VERSION = '7';
658 | OneVersionConstraint('ev-store', MY_VERSION);
659 |
660 | var hashKey = '__EV_STORE_KEY@' + MY_VERSION;
661 |
662 | module.exports = EvStore;
663 |
664 | function EvStore(elem) {
665 | var hash = elem[hashKey];
666 |
667 | if (!hash) {
668 | hash = elem[hashKey] = {};
669 | }
670 |
671 | return hash;
672 | }
673 |
674 | },{"individual/one-version":21}],20:[function(require,module,exports){
675 | (function (global){
676 | 'use strict';
677 |
678 | /*global window, global*/
679 |
680 | var root = typeof window !== 'undefined' ?
681 | window : typeof global !== 'undefined' ?
682 | global : {};
683 |
684 | module.exports = Individual;
685 |
686 | function Individual(key, value) {
687 | if (key in root) {
688 | return root[key];
689 | }
690 |
691 | root[key] = value;
692 |
693 | return value;
694 | }
695 |
696 | }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
697 | },{}],21:[function(require,module,exports){
698 | 'use strict';
699 |
700 | var Individual = require('./index.js');
701 |
702 | module.exports = OneVersion;
703 |
704 | function OneVersion(moduleName, version, defaultValue) {
705 | var key = '__INDIVIDUAL_ONE_VERSION_' + moduleName;
706 | var enforceKey = key + '_ENFORCE_SINGLETON';
707 |
708 | var versionValue = Individual(enforceKey, version);
709 |
710 | if (versionValue !== version) {
711 | throw new Error('Can only have one copy of ' +
712 | moduleName + '.\n' +
713 | 'You already have version ' + versionValue +
714 | ' installed.\n' +
715 | 'This means you cannot install version ' + version);
716 | }
717 |
718 | return Individual(key, defaultValue);
719 | }
720 |
721 | },{"./index.js":20}],22:[function(require,module,exports){
722 | "use strict";
723 |
724 | module.exports = function isObject(x) {
725 | return typeof x === "object" && x !== null;
726 | };
727 |
728 | },{}],23:[function(require,module,exports){
729 | var nativeIsArray = Array.isArray
730 | var toString = Object.prototype.toString
731 |
732 | module.exports = nativeIsArray || isArray
733 |
734 | function isArray(obj) {
735 | return toString.call(obj) === "[object Array]"
736 | }
737 |
738 | },{}],24:[function(require,module,exports){
739 | var patch = require("./vdom/patch.js")
740 |
741 | module.exports = patch
742 |
743 | },{"./vdom/patch.js":29}],25:[function(require,module,exports){
744 | var isObject = require("is-object")
745 | var isHook = require("../vnode/is-vhook.js")
746 |
747 | module.exports = applyProperties
748 |
749 | function applyProperties(node, props, previous) {
750 | for (var propName in props) {
751 | var propValue = props[propName]
752 |
753 | if (propValue === undefined) {
754 | removeProperty(node, propName, propValue, previous);
755 | } else if (isHook(propValue)) {
756 | removeProperty(node, propName, propValue, previous)
757 | if (propValue.hook) {
758 | propValue.hook(node,
759 | propName,
760 | previous ? previous[propName] : undefined)
761 | }
762 | } else {
763 | if (isObject(propValue)) {
764 | patchObject(node, props, previous, propName, propValue);
765 | } else {
766 | node[propName] = propValue
767 | }
768 | }
769 | }
770 | }
771 |
772 | function removeProperty(node, propName, propValue, previous) {
773 | if (previous) {
774 | var previousValue = previous[propName]
775 |
776 | if (!isHook(previousValue)) {
777 | if (propName === "attributes") {
778 | for (var attrName in previousValue) {
779 | node.removeAttribute(attrName)
780 | }
781 | } else if (propName === "style") {
782 | for (var i in previousValue) {
783 | node.style[i] = ""
784 | }
785 | } else if (typeof previousValue === "string") {
786 | node[propName] = ""
787 | } else {
788 | node[propName] = null
789 | }
790 | } else if (previousValue.unhook) {
791 | previousValue.unhook(node, propName, propValue)
792 | }
793 | }
794 | }
795 |
796 | function patchObject(node, props, previous, propName, propValue) {
797 | var previousValue = previous ? previous[propName] : undefined
798 |
799 | // Set attributes
800 | if (propName === "attributes") {
801 | for (var attrName in propValue) {
802 | var attrValue = propValue[attrName]
803 |
804 | if (attrValue === undefined) {
805 | node.removeAttribute(attrName)
806 | } else {
807 | node.setAttribute(attrName, attrValue)
808 | }
809 | }
810 |
811 | return
812 | }
813 |
814 | if(previousValue && isObject(previousValue) &&
815 | getPrototype(previousValue) !== getPrototype(propValue)) {
816 | node[propName] = propValue
817 | return
818 | }
819 |
820 | if (!isObject(node[propName])) {
821 | node[propName] = {}
822 | }
823 |
824 | var replacer = propName === "style" ? "" : undefined
825 |
826 | for (var k in propValue) {
827 | var value = propValue[k]
828 | node[propName][k] = (value === undefined) ? replacer : value
829 | }
830 | }
831 |
832 | function getPrototype(value) {
833 | if (Object.getPrototypeOf) {
834 | return Object.getPrototypeOf(value)
835 | } else if (value.__proto__) {
836 | return value.__proto__
837 | } else if (value.constructor) {
838 | return value.constructor.prototype
839 | }
840 | }
841 |
842 | },{"../vnode/is-vhook.js":38,"is-object":22}],26:[function(require,module,exports){
843 | var document = require("global/document")
844 |
845 | var applyProperties = require("./apply-properties")
846 |
847 | var isVNode = require("../vnode/is-vnode.js")
848 | var isVText = require("../vnode/is-vtext.js")
849 | var isWidget = require("../vnode/is-widget.js")
850 | var handleThunk = require("../vnode/handle-thunk.js")
851 |
852 | module.exports = createElement
853 |
854 | function createElement(vnode, opts) {
855 | var doc = opts ? opts.document || document : document
856 | var warn = opts ? opts.warn : null
857 |
858 | vnode = handleThunk(vnode).a
859 |
860 | if (isWidget(vnode)) {
861 | return vnode.init()
862 | } else if (isVText(vnode)) {
863 | return doc.createTextNode(vnode.text)
864 | } else if (!isVNode(vnode)) {
865 | if (warn) {
866 | warn("Item is not a valid virtual dom node", vnode)
867 | }
868 | return null
869 | }
870 |
871 | var node = (vnode.namespace === null) ?
872 | doc.createElement(vnode.tagName) :
873 | doc.createElementNS(vnode.namespace, vnode.tagName)
874 |
875 | var props = vnode.properties
876 | applyProperties(node, props)
877 |
878 | var children = vnode.children
879 |
880 | for (var i = 0; i < children.length; i++) {
881 | var childNode = createElement(children[i], opts)
882 | if (childNode) {
883 | node.appendChild(childNode)
884 | }
885 | }
886 |
887 | return node
888 | }
889 |
890 | },{"../vnode/handle-thunk.js":36,"../vnode/is-vnode.js":39,"../vnode/is-vtext.js":40,"../vnode/is-widget.js":41,"./apply-properties":25,"global/document":2}],27:[function(require,module,exports){
891 | // Maps a virtual DOM tree onto a real DOM tree in an efficient manner.
892 | // We don't want to read all of the DOM nodes in the tree so we use
893 | // the in-order tree indexing to eliminate recursion down certain branches.
894 | // We only recurse into a DOM node if we know that it contains a child of
895 | // interest.
896 |
897 | var noChild = {}
898 |
899 | module.exports = domIndex
900 |
901 | function domIndex(rootNode, tree, indices, nodes) {
902 | if (!indices || indices.length === 0) {
903 | return {}
904 | } else {
905 | indices.sort(ascending)
906 | return recurse(rootNode, tree, indices, nodes, 0)
907 | }
908 | }
909 |
910 | function recurse(rootNode, tree, indices, nodes, rootIndex) {
911 | nodes = nodes || {}
912 |
913 |
914 | if (rootNode) {
915 | if (indexInRange(indices, rootIndex, rootIndex)) {
916 | nodes[rootIndex] = rootNode
917 | }
918 |
919 | var vChildren = tree.children
920 |
921 | if (vChildren) {
922 |
923 | var childNodes = rootNode.childNodes
924 |
925 | for (var i = 0; i < tree.children.length; i++) {
926 | rootIndex += 1
927 |
928 | var vChild = vChildren[i] || noChild
929 | var nextIndex = rootIndex + (vChild.count || 0)
930 |
931 | // skip recursion down the tree if there are no nodes down here
932 | if (indexInRange(indices, rootIndex, nextIndex)) {
933 | recurse(childNodes[i], vChild, indices, nodes, rootIndex)
934 | }
935 |
936 | rootIndex = nextIndex
937 | }
938 | }
939 | }
940 |
941 | return nodes
942 | }
943 |
944 | // Binary search for an index in the interval [left, right]
945 | function indexInRange(indices, left, right) {
946 | if (indices.length === 0) {
947 | return false
948 | }
949 |
950 | var minIndex = 0
951 | var maxIndex = indices.length - 1
952 | var currentIndex
953 | var currentItem
954 |
955 | while (minIndex <= maxIndex) {
956 | currentIndex = ((maxIndex + minIndex) / 2) >> 0
957 | currentItem = indices[currentIndex]
958 |
959 | if (minIndex === maxIndex) {
960 | return currentItem >= left && currentItem <= right
961 | } else if (currentItem < left) {
962 | minIndex = currentIndex + 1
963 | } else if (currentItem > right) {
964 | maxIndex = currentIndex - 1
965 | } else {
966 | return true
967 | }
968 | }
969 |
970 | return false;
971 | }
972 |
973 | function ascending(a, b) {
974 | return a > b ? 1 : -1
975 | }
976 |
977 | },{}],28:[function(require,module,exports){
978 | var applyProperties = require("./apply-properties")
979 |
980 | var isWidget = require("../vnode/is-widget.js")
981 | var VPatch = require("../vnode/vpatch.js")
982 |
983 | var render = require("./create-element")
984 | var updateWidget = require("./update-widget")
985 |
986 | module.exports = applyPatch
987 |
988 | function applyPatch(vpatch, domNode, renderOptions) {
989 | var type = vpatch.type
990 | var vNode = vpatch.vNode
991 | var patch = vpatch.patch
992 |
993 | switch (type) {
994 | case VPatch.REMOVE:
995 | return removeNode(domNode, vNode)
996 | case VPatch.INSERT:
997 | return insertNode(domNode, patch, renderOptions)
998 | case VPatch.VTEXT:
999 | return stringPatch(domNode, vNode, patch, renderOptions)
1000 | case VPatch.WIDGET:
1001 | return widgetPatch(domNode, vNode, patch, renderOptions)
1002 | case VPatch.VNODE:
1003 | return vNodePatch(domNode, vNode, patch, renderOptions)
1004 | case VPatch.ORDER:
1005 | reorderChildren(domNode, patch)
1006 | return domNode
1007 | case VPatch.PROPS:
1008 | applyProperties(domNode, patch, vNode.properties)
1009 | return domNode
1010 | case VPatch.THUNK:
1011 | return replaceRoot(domNode,
1012 | renderOptions.patch(domNode, patch, renderOptions))
1013 | default:
1014 | return domNode
1015 | }
1016 | }
1017 |
1018 | function removeNode(domNode, vNode) {
1019 | var parentNode = domNode.parentNode
1020 |
1021 | if (parentNode) {
1022 | parentNode.removeChild(domNode)
1023 | }
1024 |
1025 | destroyWidget(domNode, vNode);
1026 |
1027 | return null
1028 | }
1029 |
1030 | function insertNode(parentNode, vNode, renderOptions) {
1031 | var newNode = render(vNode, renderOptions)
1032 |
1033 | if (parentNode) {
1034 | parentNode.appendChild(newNode)
1035 | }
1036 |
1037 | return parentNode
1038 | }
1039 |
1040 | function stringPatch(domNode, leftVNode, vText, renderOptions) {
1041 | var newNode
1042 |
1043 | if (domNode.nodeType === 3) {
1044 | domNode.replaceData(0, domNode.length, vText.text)
1045 | newNode = domNode
1046 | } else {
1047 | var parentNode = domNode.parentNode
1048 | newNode = render(vText, renderOptions)
1049 |
1050 | if (parentNode && newNode !== domNode) {
1051 | parentNode.replaceChild(newNode, domNode)
1052 | }
1053 | }
1054 |
1055 | return newNode
1056 | }
1057 |
1058 | function widgetPatch(domNode, leftVNode, widget, renderOptions) {
1059 | var updating = updateWidget(leftVNode, widget)
1060 | var newNode
1061 |
1062 | if (updating) {
1063 | newNode = widget.update(leftVNode, domNode) || domNode
1064 | } else {
1065 | newNode = render(widget, renderOptions)
1066 | }
1067 |
1068 | var parentNode = domNode.parentNode
1069 |
1070 | if (parentNode && newNode !== domNode) {
1071 | parentNode.replaceChild(newNode, domNode)
1072 | }
1073 |
1074 | if (!updating) {
1075 | destroyWidget(domNode, leftVNode)
1076 | }
1077 |
1078 | return newNode
1079 | }
1080 |
1081 | function vNodePatch(domNode, leftVNode, vNode, renderOptions) {
1082 | var parentNode = domNode.parentNode
1083 | var newNode = render(vNode, renderOptions)
1084 |
1085 | if (parentNode && newNode !== domNode) {
1086 | parentNode.replaceChild(newNode, domNode)
1087 | }
1088 |
1089 | return newNode
1090 | }
1091 |
1092 | function destroyWidget(domNode, w) {
1093 | if (typeof w.destroy === "function" && isWidget(w)) {
1094 | w.destroy(domNode)
1095 | }
1096 | }
1097 |
1098 | function reorderChildren(domNode, moves) {
1099 | var childNodes = domNode.childNodes
1100 | var keyMap = {}
1101 | var node
1102 | var remove
1103 | var insert
1104 |
1105 | for (var i = 0; i < moves.removes.length; i++) {
1106 | remove = moves.removes[i]
1107 | node = childNodes[remove.from]
1108 | if (remove.key) {
1109 | keyMap[remove.key] = node
1110 | }
1111 | domNode.removeChild(node)
1112 | }
1113 |
1114 | var length = childNodes.length
1115 | for (var j = 0; j < moves.inserts.length; j++) {
1116 | insert = moves.inserts[j]
1117 | node = keyMap[insert.key]
1118 | // this is the weirdest bug i've ever seen in webkit
1119 | domNode.insertBefore(node, insert.to >= length++ ? null : childNodes[insert.to])
1120 | }
1121 | }
1122 |
1123 | function replaceRoot(oldRoot, newRoot) {
1124 | if (oldRoot && newRoot && oldRoot !== newRoot && oldRoot.parentNode) {
1125 | oldRoot.parentNode.replaceChild(newRoot, oldRoot)
1126 | }
1127 |
1128 | return newRoot;
1129 | }
1130 |
1131 | },{"../vnode/is-widget.js":41,"../vnode/vpatch.js":44,"./apply-properties":25,"./create-element":26,"./update-widget":30}],29:[function(require,module,exports){
1132 | var document = require("global/document")
1133 | var isArray = require("x-is-array")
1134 |
1135 | var domIndex = require("./dom-index")
1136 | var patchOp = require("./patch-op")
1137 | module.exports = patch
1138 |
1139 | function patch(rootNode, patches) {
1140 | return patchRecursive(rootNode, patches)
1141 | }
1142 |
1143 | function patchRecursive(rootNode, patches, renderOptions) {
1144 | var indices = patchIndices(patches)
1145 |
1146 | if (indices.length === 0) {
1147 | return rootNode
1148 | }
1149 |
1150 | var index = domIndex(rootNode, patches.a, indices)
1151 | var ownerDocument = rootNode.ownerDocument
1152 |
1153 | if (!renderOptions) {
1154 | renderOptions = { patch: patchRecursive }
1155 | if (ownerDocument !== document) {
1156 | renderOptions.document = ownerDocument
1157 | }
1158 | }
1159 |
1160 | for (var i = 0; i < indices.length; i++) {
1161 | var nodeIndex = indices[i]
1162 | rootNode = applyPatch(rootNode,
1163 | index[nodeIndex],
1164 | patches[nodeIndex],
1165 | renderOptions)
1166 | }
1167 |
1168 | return rootNode
1169 | }
1170 |
1171 | function applyPatch(rootNode, domNode, patchList, renderOptions) {
1172 | if (!domNode) {
1173 | return rootNode
1174 | }
1175 |
1176 | var newNode
1177 |
1178 | if (isArray(patchList)) {
1179 | for (var i = 0; i < patchList.length; i++) {
1180 | newNode = patchOp(patchList[i], domNode, renderOptions)
1181 |
1182 | if (domNode === rootNode) {
1183 | rootNode = newNode
1184 | }
1185 | }
1186 | } else {
1187 | newNode = patchOp(patchList, domNode, renderOptions)
1188 |
1189 | if (domNode === rootNode) {
1190 | rootNode = newNode
1191 | }
1192 | }
1193 |
1194 | return rootNode
1195 | }
1196 |
1197 | function patchIndices(patches) {
1198 | var indices = []
1199 |
1200 | for (var key in patches) {
1201 | if (key !== "a") {
1202 | indices.push(Number(key))
1203 | }
1204 | }
1205 |
1206 | return indices
1207 | }
1208 |
1209 | },{"./dom-index":27,"./patch-op":28,"global/document":2,"x-is-array":23}],30:[function(require,module,exports){
1210 | var isWidget = require("../vnode/is-widget.js")
1211 |
1212 | module.exports = updateWidget
1213 |
1214 | function updateWidget(a, b) {
1215 | if (isWidget(a) && isWidget(b)) {
1216 | if ("name" in a && "name" in b) {
1217 | return a.id === b.id
1218 | } else {
1219 | return a.init === b.init
1220 | }
1221 | }
1222 |
1223 | return false
1224 | }
1225 |
1226 | },{"../vnode/is-widget.js":41}],31:[function(require,module,exports){
1227 | 'use strict';
1228 |
1229 | module.exports = AttributeHook;
1230 |
1231 | function AttributeHook(namespace, value) {
1232 | if (!(this instanceof AttributeHook)) {
1233 | return new AttributeHook(namespace, value);
1234 | }
1235 |
1236 | this.namespace = namespace;
1237 | this.value = value;
1238 | }
1239 |
1240 | AttributeHook.prototype.hook = function (node, prop, prev) {
1241 | if (prev && prev.type === 'AttributeHook' &&
1242 | prev.value === this.value &&
1243 | prev.namespace === this.namespace) {
1244 | return;
1245 | }
1246 |
1247 | node.setAttributeNS(this.namespace, prop, this.value);
1248 | };
1249 |
1250 | AttributeHook.prototype.unhook = function (node, prop, next) {
1251 | if (next && next.type === 'AttributeHook' &&
1252 | next.namespace === this.namespace) {
1253 | return;
1254 | }
1255 |
1256 | var colonPosition = prop.indexOf(':');
1257 | var localName = colonPosition > -1 ? prop.substr(colonPosition + 1) : prop;
1258 | node.removeAttributeNS(this.namespace, localName);
1259 | };
1260 |
1261 | AttributeHook.prototype.type = 'AttributeHook';
1262 |
1263 | },{}],32:[function(require,module,exports){
1264 | 'use strict';
1265 |
1266 | var EvStore = require('ev-store');
1267 |
1268 | module.exports = EvHook;
1269 |
1270 | function EvHook(value) {
1271 | if (!(this instanceof EvHook)) {
1272 | return new EvHook(value);
1273 | }
1274 |
1275 | this.value = value;
1276 | }
1277 |
1278 | EvHook.prototype.hook = function (node, propertyName) {
1279 | var es = EvStore(node);
1280 | var propName = propertyName.substr(3);
1281 |
1282 | es[propName] = this.value;
1283 | };
1284 |
1285 | EvHook.prototype.unhook = function(node, propertyName) {
1286 | var es = EvStore(node);
1287 | var propName = propertyName.substr(3);
1288 |
1289 | es[propName] = undefined;
1290 | };
1291 |
1292 | },{"ev-store":19}],33:[function(require,module,exports){
1293 | 'use strict';
1294 |
1295 | module.exports = SoftSetHook;
1296 |
1297 | function SoftSetHook(value) {
1298 | if (!(this instanceof SoftSetHook)) {
1299 | return new SoftSetHook(value);
1300 | }
1301 |
1302 | this.value = value;
1303 | }
1304 |
1305 | SoftSetHook.prototype.hook = function (node, propertyName) {
1306 | if (node[propertyName] !== this.value) {
1307 | node[propertyName] = this.value;
1308 | }
1309 | };
1310 |
1311 | },{}],34:[function(require,module,exports){
1312 | 'use strict';
1313 |
1314 | var isArray = require('x-is-array');
1315 |
1316 | var VNode = require('../vnode/vnode.js');
1317 | var VText = require('../vnode/vtext.js');
1318 | var isVNode = require('../vnode/is-vnode');
1319 | var isVText = require('../vnode/is-vtext');
1320 | var isWidget = require('../vnode/is-widget');
1321 | var isHook = require('../vnode/is-vhook');
1322 | var isVThunk = require('../vnode/is-thunk');
1323 |
1324 | var parseTag = require('./parse-tag.js');
1325 | var softSetHook = require('./hooks/soft-set-hook.js');
1326 | var evHook = require('./hooks/ev-hook.js');
1327 |
1328 | module.exports = h;
1329 |
1330 | function h(tagName, properties, children) {
1331 | var childNodes = [];
1332 | var tag, props, key, namespace;
1333 |
1334 | if (!children && isChildren(properties)) {
1335 | children = properties;
1336 | props = {};
1337 | }
1338 |
1339 | props = props || properties || {};
1340 | tag = parseTag(tagName, props);
1341 |
1342 | // support keys
1343 | if (props.hasOwnProperty('key')) {
1344 | key = props.key;
1345 | props.key = undefined;
1346 | }
1347 |
1348 | // support namespace
1349 | if (props.hasOwnProperty('namespace')) {
1350 | namespace = props.namespace;
1351 | props.namespace = undefined;
1352 | }
1353 |
1354 | // fix cursor bug
1355 | if (tag === 'INPUT' &&
1356 | !namespace &&
1357 | props.hasOwnProperty('value') &&
1358 | props.value !== undefined &&
1359 | !isHook(props.value)
1360 | ) {
1361 | props.value = softSetHook(props.value);
1362 | }
1363 |
1364 | transformProperties(props);
1365 |
1366 | if (children !== undefined && children !== null) {
1367 | addChild(children, childNodes, tag, props);
1368 | }
1369 |
1370 |
1371 | return new VNode(tag, props, childNodes, key, namespace);
1372 | }
1373 |
1374 | function addChild(c, childNodes, tag, props) {
1375 | if (typeof c === 'string') {
1376 | childNodes.push(new VText(c));
1377 | } else if (isChild(c)) {
1378 | childNodes.push(c);
1379 | } else if (isArray(c)) {
1380 | for (var i = 0; i < c.length; i++) {
1381 | addChild(c[i], childNodes, tag, props);
1382 | }
1383 | } else if (c === null || c === undefined) {
1384 | return;
1385 | } else {
1386 | throw UnexpectedVirtualElement({
1387 | foreignObject: c,
1388 | parentVnode: {
1389 | tagName: tag,
1390 | properties: props
1391 | }
1392 | });
1393 | }
1394 | }
1395 |
1396 | function transformProperties(props) {
1397 | for (var propName in props) {
1398 | if (props.hasOwnProperty(propName)) {
1399 | var value = props[propName];
1400 |
1401 | if (isHook(value)) {
1402 | continue;
1403 | }
1404 |
1405 | if (propName.substr(0, 3) === 'ev-') {
1406 | // add ev-foo support
1407 | props[propName] = evHook(value);
1408 | }
1409 | }
1410 | }
1411 | }
1412 |
1413 | function isChild(x) {
1414 | return isVNode(x) || isVText(x) || isWidget(x) || isVThunk(x);
1415 | }
1416 |
1417 | function isChildren(x) {
1418 | return typeof x === 'string' || isArray(x) || isChild(x);
1419 | }
1420 |
1421 | function UnexpectedVirtualElement(data) {
1422 | var err = new Error();
1423 |
1424 | err.type = 'virtual-hyperscript.unexpected.virtual-element';
1425 | err.message = 'Unexpected virtual child passed to h().\n' +
1426 | 'Expected a VNode / Vthunk / VWidget / string but:\n' +
1427 | 'got:\n' +
1428 | errorString(data.foreignObject) +
1429 | '.\n' +
1430 | 'The parent vnode is:\n' +
1431 | errorString(data.parentVnode)
1432 | '\n' +
1433 | 'Suggested fix: change your `h(..., [ ... ])` callsite.';
1434 | err.foreignObject = data.foreignObject;
1435 | err.parentVnode = data.parentVnode;
1436 |
1437 | return err;
1438 | }
1439 |
1440 | function errorString(obj) {
1441 | try {
1442 | return JSON.stringify(obj, null, ' ');
1443 | } catch (e) {
1444 | return String(obj);
1445 | }
1446 | }
1447 |
1448 | },{"../vnode/is-thunk":37,"../vnode/is-vhook":38,"../vnode/is-vnode":39,"../vnode/is-vtext":40,"../vnode/is-widget":41,"../vnode/vnode.js":43,"../vnode/vtext.js":45,"./hooks/ev-hook.js":32,"./hooks/soft-set-hook.js":33,"./parse-tag.js":35,"x-is-array":23}],35:[function(require,module,exports){
1449 | 'use strict';
1450 |
1451 | var split = require('browser-split');
1452 |
1453 | var classIdSplit = /([\.#]?[a-zA-Z0-9_:-]+)/;
1454 | var notClassId = /^\.|#/;
1455 |
1456 | module.exports = parseTag;
1457 |
1458 | function parseTag(tag, props) {
1459 | if (!tag) {
1460 | return 'DIV';
1461 | }
1462 |
1463 | var noId = !(props.hasOwnProperty('id'));
1464 |
1465 | var tagParts = split(tag, classIdSplit);
1466 | var tagName = null;
1467 |
1468 | if (notClassId.test(tagParts[1])) {
1469 | tagName = 'DIV';
1470 | }
1471 |
1472 | var classes, part, type, i;
1473 |
1474 | for (i = 0; i < tagParts.length; i++) {
1475 | part = tagParts[i];
1476 |
1477 | if (!part) {
1478 | continue;
1479 | }
1480 |
1481 | type = part.charAt(0);
1482 |
1483 | if (!tagName) {
1484 | tagName = part;
1485 | } else if (type === '.') {
1486 | classes = classes || [];
1487 | classes.push(part.substring(1, part.length));
1488 | } else if (type === '#' && noId) {
1489 | props.id = part.substring(1, part.length);
1490 | }
1491 | }
1492 |
1493 | if (classes) {
1494 | if (props.className) {
1495 | classes.push(props.className);
1496 | }
1497 |
1498 | props.className = classes.join(' ');
1499 | }
1500 |
1501 | return props.namespace ? tagName : tagName.toUpperCase();
1502 | }
1503 |
1504 | },{"browser-split":18}],36:[function(require,module,exports){
1505 | var isVNode = require("./is-vnode")
1506 | var isVText = require("./is-vtext")
1507 | var isWidget = require("./is-widget")
1508 | var isThunk = require("./is-thunk")
1509 |
1510 | module.exports = handleThunk
1511 |
1512 | function handleThunk(a, b) {
1513 | var renderedA = a
1514 | var renderedB = b
1515 |
1516 | if (isThunk(b)) {
1517 | renderedB = renderThunk(b, a)
1518 | }
1519 |
1520 | if (isThunk(a)) {
1521 | renderedA = renderThunk(a, null)
1522 | }
1523 |
1524 | return {
1525 | a: renderedA,
1526 | b: renderedB
1527 | }
1528 | }
1529 |
1530 | function renderThunk(thunk, previous) {
1531 | var renderedThunk = thunk.vnode
1532 |
1533 | if (!renderedThunk) {
1534 | renderedThunk = thunk.vnode = thunk.render(previous)
1535 | }
1536 |
1537 | if (!(isVNode(renderedThunk) ||
1538 | isVText(renderedThunk) ||
1539 | isWidget(renderedThunk))) {
1540 | throw new Error("thunk did not return a valid node");
1541 | }
1542 |
1543 | return renderedThunk
1544 | }
1545 |
1546 | },{"./is-thunk":37,"./is-vnode":39,"./is-vtext":40,"./is-widget":41}],37:[function(require,module,exports){
1547 | module.exports = isThunk
1548 |
1549 | function isThunk(t) {
1550 | return t && t.type === "Thunk"
1551 | }
1552 |
1553 | },{}],38:[function(require,module,exports){
1554 | module.exports = isHook
1555 |
1556 | function isHook(hook) {
1557 | return hook &&
1558 | (typeof hook.hook === "function" && !hook.hasOwnProperty("hook") ||
1559 | typeof hook.unhook === "function" && !hook.hasOwnProperty("unhook"))
1560 | }
1561 |
1562 | },{}],39:[function(require,module,exports){
1563 | var version = require("./version")
1564 |
1565 | module.exports = isVirtualNode
1566 |
1567 | function isVirtualNode(x) {
1568 | return x && x.type === "VirtualNode" && x.version === version
1569 | }
1570 |
1571 | },{"./version":42}],40:[function(require,module,exports){
1572 | var version = require("./version")
1573 |
1574 | module.exports = isVirtualText
1575 |
1576 | function isVirtualText(x) {
1577 | return x && x.type === "VirtualText" && x.version === version
1578 | }
1579 |
1580 | },{"./version":42}],41:[function(require,module,exports){
1581 | module.exports = isWidget
1582 |
1583 | function isWidget(w) {
1584 | return w && w.type === "Widget"
1585 | }
1586 |
1587 | },{}],42:[function(require,module,exports){
1588 | module.exports = "2"
1589 |
1590 | },{}],43:[function(require,module,exports){
1591 | var version = require("./version")
1592 | var isVNode = require("./is-vnode")
1593 | var isWidget = require("./is-widget")
1594 | var isThunk = require("./is-thunk")
1595 | var isVHook = require("./is-vhook")
1596 |
1597 | module.exports = VirtualNode
1598 |
1599 | var noProperties = {}
1600 | var noChildren = []
1601 |
1602 | function VirtualNode(tagName, properties, children, key, namespace) {
1603 | this.tagName = tagName
1604 | this.properties = properties || noProperties
1605 | this.children = children || noChildren
1606 | this.key = key != null ? String(key) : undefined
1607 | this.namespace = (typeof namespace === "string") ? namespace : null
1608 |
1609 | var count = (children && children.length) || 0
1610 | var descendants = 0
1611 | var hasWidgets = false
1612 | var hasThunks = false
1613 | var descendantHooks = false
1614 | var hooks
1615 |
1616 | for (var propName in properties) {
1617 | if (properties.hasOwnProperty(propName)) {
1618 | var property = properties[propName]
1619 | if (isVHook(property) && property.unhook) {
1620 | if (!hooks) {
1621 | hooks = {}
1622 | }
1623 |
1624 | hooks[propName] = property
1625 | }
1626 | }
1627 | }
1628 |
1629 | for (var i = 0; i < count; i++) {
1630 | var child = children[i]
1631 | if (isVNode(child)) {
1632 | descendants += child.count || 0
1633 |
1634 | if (!hasWidgets && child.hasWidgets) {
1635 | hasWidgets = true
1636 | }
1637 |
1638 | if (!hasThunks && child.hasThunks) {
1639 | hasThunks = true
1640 | }
1641 |
1642 | if (!descendantHooks && (child.hooks || child.descendantHooks)) {
1643 | descendantHooks = true
1644 | }
1645 | } else if (!hasWidgets && isWidget(child)) {
1646 | if (typeof child.destroy === "function") {
1647 | hasWidgets = true
1648 | }
1649 | } else if (!hasThunks && isThunk(child)) {
1650 | hasThunks = true;
1651 | }
1652 | }
1653 |
1654 | this.count = count + descendants
1655 | this.hasWidgets = hasWidgets
1656 | this.hasThunks = hasThunks
1657 | this.hooks = hooks
1658 | this.descendantHooks = descendantHooks
1659 | }
1660 |
1661 | VirtualNode.prototype.version = version
1662 | VirtualNode.prototype.type = "VirtualNode"
1663 |
1664 | },{"./is-thunk":37,"./is-vhook":38,"./is-vnode":39,"./is-widget":41,"./version":42}],44:[function(require,module,exports){
1665 | var version = require("./version")
1666 |
1667 | VirtualPatch.NONE = 0
1668 | VirtualPatch.VTEXT = 1
1669 | VirtualPatch.VNODE = 2
1670 | VirtualPatch.WIDGET = 3
1671 | VirtualPatch.PROPS = 4
1672 | VirtualPatch.ORDER = 5
1673 | VirtualPatch.INSERT = 6
1674 | VirtualPatch.REMOVE = 7
1675 | VirtualPatch.THUNK = 8
1676 |
1677 | module.exports = VirtualPatch
1678 |
1679 | function VirtualPatch(type, vNode, patch) {
1680 | this.type = Number(type)
1681 | this.vNode = vNode
1682 | this.patch = patch
1683 | }
1684 |
1685 | VirtualPatch.prototype.version = version
1686 | VirtualPatch.prototype.type = "VirtualPatch"
1687 |
1688 | },{"./version":42}],45:[function(require,module,exports){
1689 | var version = require("./version")
1690 |
1691 | module.exports = VirtualText
1692 |
1693 | function VirtualText(text) {
1694 | this.text = String(text)
1695 | }
1696 |
1697 | VirtualText.prototype.version = version
1698 | VirtualText.prototype.type = "VirtualText"
1699 |
1700 | },{"./version":42}],46:[function(require,module,exports){
1701 | var isObject = require("is-object")
1702 | var isHook = require("../vnode/is-vhook")
1703 |
1704 | module.exports = diffProps
1705 |
1706 | function diffProps(a, b) {
1707 | var diff
1708 |
1709 | for (var aKey in a) {
1710 | if (!(aKey in b)) {
1711 | diff = diff || {}
1712 | diff[aKey] = undefined
1713 | }
1714 |
1715 | var aValue = a[aKey]
1716 | var bValue = b[aKey]
1717 |
1718 | if (aValue === bValue) {
1719 | continue
1720 | } else if (isObject(aValue) && isObject(bValue)) {
1721 | if (getPrototype(bValue) !== getPrototype(aValue)) {
1722 | diff = diff || {}
1723 | diff[aKey] = bValue
1724 | } else if (isHook(bValue)) {
1725 | diff = diff || {}
1726 | diff[aKey] = bValue
1727 | } else {
1728 | var objectDiff = diffProps(aValue, bValue)
1729 | if (objectDiff) {
1730 | diff = diff || {}
1731 | diff[aKey] = objectDiff
1732 | }
1733 | }
1734 | } else {
1735 | diff = diff || {}
1736 | diff[aKey] = bValue
1737 | }
1738 | }
1739 |
1740 | for (var bKey in b) {
1741 | if (!(bKey in a)) {
1742 | diff = diff || {}
1743 | diff[bKey] = b[bKey]
1744 | }
1745 | }
1746 |
1747 | return diff
1748 | }
1749 |
1750 | function getPrototype(value) {
1751 | if (Object.getPrototypeOf) {
1752 | return Object.getPrototypeOf(value)
1753 | } else if (value.__proto__) {
1754 | return value.__proto__
1755 | } else if (value.constructor) {
1756 | return value.constructor.prototype
1757 | }
1758 | }
1759 |
1760 | },{"../vnode/is-vhook":38,"is-object":22}],47:[function(require,module,exports){
1761 | var isArray = require("x-is-array")
1762 |
1763 | var VPatch = require("../vnode/vpatch")
1764 | var isVNode = require("../vnode/is-vnode")
1765 | var isVText = require("../vnode/is-vtext")
1766 | var isWidget = require("../vnode/is-widget")
1767 | var isThunk = require("../vnode/is-thunk")
1768 | var handleThunk = require("../vnode/handle-thunk")
1769 |
1770 | var diffProps = require("./diff-props")
1771 |
1772 | module.exports = diff
1773 |
1774 | function diff(a, b) {
1775 | var patch = { a: a }
1776 | walk(a, b, patch, 0)
1777 | return patch
1778 | }
1779 |
1780 | function walk(a, b, patch, index) {
1781 | if (a === b) {
1782 | return
1783 | }
1784 |
1785 | var apply = patch[index]
1786 | var applyClear = false
1787 |
1788 | if (isThunk(a) || isThunk(b)) {
1789 | thunks(a, b, patch, index)
1790 | } else if (b == null) {
1791 |
1792 | // If a is a widget we will add a remove patch for it
1793 | // Otherwise any child widgets/hooks must be destroyed.
1794 | // This prevents adding two remove patches for a widget.
1795 | if (!isWidget(a)) {
1796 | clearState(a, patch, index)
1797 | apply = patch[index]
1798 | }
1799 |
1800 | apply = appendPatch(apply, new VPatch(VPatch.REMOVE, a, b))
1801 | } else if (isVNode(b)) {
1802 | if (isVNode(a)) {
1803 | if (a.tagName === b.tagName &&
1804 | a.namespace === b.namespace &&
1805 | a.key === b.key) {
1806 | var propsPatch = diffProps(a.properties, b.properties)
1807 | if (propsPatch) {
1808 | apply = appendPatch(apply,
1809 | new VPatch(VPatch.PROPS, a, propsPatch))
1810 | }
1811 | apply = diffChildren(a, b, patch, apply, index)
1812 | } else {
1813 | apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b))
1814 | applyClear = true
1815 | }
1816 | } else {
1817 | apply = appendPatch(apply, new VPatch(VPatch.VNODE, a, b))
1818 | applyClear = true
1819 | }
1820 | } else if (isVText(b)) {
1821 | if (!isVText(a)) {
1822 | apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b))
1823 | applyClear = true
1824 | } else if (a.text !== b.text) {
1825 | apply = appendPatch(apply, new VPatch(VPatch.VTEXT, a, b))
1826 | }
1827 | } else if (isWidget(b)) {
1828 | if (!isWidget(a)) {
1829 | applyClear = true
1830 | }
1831 |
1832 | apply = appendPatch(apply, new VPatch(VPatch.WIDGET, a, b))
1833 | }
1834 |
1835 | if (apply) {
1836 | patch[index] = apply
1837 | }
1838 |
1839 | if (applyClear) {
1840 | clearState(a, patch, index)
1841 | }
1842 | }
1843 |
1844 | function diffChildren(a, b, patch, apply, index) {
1845 | var aChildren = a.children
1846 | var orderedSet = reorder(aChildren, b.children)
1847 | var bChildren = orderedSet.children
1848 |
1849 | var aLen = aChildren.length
1850 | var bLen = bChildren.length
1851 | var len = aLen > bLen ? aLen : bLen
1852 |
1853 | for (var i = 0; i < len; i++) {
1854 | var leftNode = aChildren[i]
1855 | var rightNode = bChildren[i]
1856 | index += 1
1857 |
1858 | if (!leftNode) {
1859 | if (rightNode) {
1860 | // Excess nodes in b need to be added
1861 | apply = appendPatch(apply,
1862 | new VPatch(VPatch.INSERT, null, rightNode))
1863 | }
1864 | } else {
1865 | walk(leftNode, rightNode, patch, index)
1866 | }
1867 |
1868 | if (isVNode(leftNode) && leftNode.count) {
1869 | index += leftNode.count
1870 | }
1871 | }
1872 |
1873 | if (orderedSet.moves) {
1874 | // Reorder nodes last
1875 | apply = appendPatch(apply, new VPatch(
1876 | VPatch.ORDER,
1877 | a,
1878 | orderedSet.moves
1879 | ))
1880 | }
1881 |
1882 | return apply
1883 | }
1884 |
1885 | function clearState(vNode, patch, index) {
1886 | // TODO: Make this a single walk, not two
1887 | unhook(vNode, patch, index)
1888 | destroyWidgets(vNode, patch, index)
1889 | }
1890 |
1891 | // Patch records for all destroyed widgets must be added because we need
1892 | // a DOM node reference for the destroy function
1893 | function destroyWidgets(vNode, patch, index) {
1894 | if (isWidget(vNode)) {
1895 | if (typeof vNode.destroy === "function") {
1896 | patch[index] = appendPatch(
1897 | patch[index],
1898 | new VPatch(VPatch.REMOVE, vNode, null)
1899 | )
1900 | }
1901 | } else if (isVNode(vNode) && (vNode.hasWidgets || vNode.hasThunks)) {
1902 | var children = vNode.children
1903 | var len = children.length
1904 | for (var i = 0; i < len; i++) {
1905 | var child = children[i]
1906 | index += 1
1907 |
1908 | destroyWidgets(child, patch, index)
1909 |
1910 | if (isVNode(child) && child.count) {
1911 | index += child.count
1912 | }
1913 | }
1914 | } else if (isThunk(vNode)) {
1915 | thunks(vNode, null, patch, index)
1916 | }
1917 | }
1918 |
1919 | // Create a sub-patch for thunks
1920 | function thunks(a, b, patch, index) {
1921 | var nodes = handleThunk(a, b)
1922 | var thunkPatch = diff(nodes.a, nodes.b)
1923 | if (hasPatches(thunkPatch)) {
1924 | patch[index] = new VPatch(VPatch.THUNK, null, thunkPatch)
1925 | }
1926 | }
1927 |
1928 | function hasPatches(patch) {
1929 | for (var index in patch) {
1930 | if (index !== "a") {
1931 | return true
1932 | }
1933 | }
1934 |
1935 | return false
1936 | }
1937 |
1938 | // Execute hooks when two nodes are identical
1939 | function unhook(vNode, patch, index) {
1940 | if (isVNode(vNode)) {
1941 | if (vNode.hooks) {
1942 | patch[index] = appendPatch(
1943 | patch[index],
1944 | new VPatch(
1945 | VPatch.PROPS,
1946 | vNode,
1947 | undefinedKeys(vNode.hooks)
1948 | )
1949 | )
1950 | }
1951 |
1952 | if (vNode.descendantHooks || vNode.hasThunks) {
1953 | var children = vNode.children
1954 | var len = children.length
1955 | for (var i = 0; i < len; i++) {
1956 | var child = children[i]
1957 | index += 1
1958 |
1959 | unhook(child, patch, index)
1960 |
1961 | if (isVNode(child) && child.count) {
1962 | index += child.count
1963 | }
1964 | }
1965 | }
1966 | } else if (isThunk(vNode)) {
1967 | thunks(vNode, null, patch, index)
1968 | }
1969 | }
1970 |
1971 | function undefinedKeys(obj) {
1972 | var result = {}
1973 |
1974 | for (var key in obj) {
1975 | result[key] = undefined
1976 | }
1977 |
1978 | return result
1979 | }
1980 |
1981 | // List diff, naive left to right reordering
1982 | function reorder(aChildren, bChildren) {
1983 | // O(M) time, O(M) memory
1984 | var bChildIndex = keyIndex(bChildren)
1985 | var bKeys = bChildIndex.keys
1986 | var bFree = bChildIndex.free
1987 |
1988 | if (bFree.length === bChildren.length) {
1989 | return {
1990 | children: bChildren,
1991 | moves: null
1992 | }
1993 | }
1994 |
1995 | // O(N) time, O(N) memory
1996 | var aChildIndex = keyIndex(aChildren)
1997 | var aKeys = aChildIndex.keys
1998 | var aFree = aChildIndex.free
1999 |
2000 | if (aFree.length === aChildren.length) {
2001 | return {
2002 | children: bChildren,
2003 | moves: null
2004 | }
2005 | }
2006 |
2007 | // O(MAX(N, M)) memory
2008 | var newChildren = []
2009 |
2010 | var freeIndex = 0
2011 | var freeCount = bFree.length
2012 | var deletedItems = 0
2013 |
2014 | // Iterate through a and match a node in b
2015 | // O(N) time,
2016 | for (var i = 0 ; i < aChildren.length; i++) {
2017 | var aItem = aChildren[i]
2018 | var itemIndex
2019 |
2020 | if (aItem.key) {
2021 | if (bKeys.hasOwnProperty(aItem.key)) {
2022 | // Match up the old keys
2023 | itemIndex = bKeys[aItem.key]
2024 | newChildren.push(bChildren[itemIndex])
2025 |
2026 | } else {
2027 | // Remove old keyed items
2028 | itemIndex = i - deletedItems++
2029 | newChildren.push(null)
2030 | }
2031 | } else {
2032 | // Match the item in a with the next free item in b
2033 | if (freeIndex < freeCount) {
2034 | itemIndex = bFree[freeIndex++]
2035 | newChildren.push(bChildren[itemIndex])
2036 | } else {
2037 | // There are no free items in b to match with
2038 | // the free items in a, so the extra free nodes
2039 | // are deleted.
2040 | itemIndex = i - deletedItems++
2041 | newChildren.push(null)
2042 | }
2043 | }
2044 | }
2045 |
2046 | var lastFreeIndex = freeIndex >= bFree.length ?
2047 | bChildren.length :
2048 | bFree[freeIndex]
2049 |
2050 | // Iterate through b and append any new keys
2051 | // O(M) time
2052 | for (var j = 0; j < bChildren.length; j++) {
2053 | var newItem = bChildren[j]
2054 |
2055 | if (newItem.key) {
2056 | if (!aKeys.hasOwnProperty(newItem.key)) {
2057 | // Add any new keyed items
2058 | // We are adding new items to the end and then sorting them
2059 | // in place. In future we should insert new items in place.
2060 | newChildren.push(newItem)
2061 | }
2062 | } else if (j >= lastFreeIndex) {
2063 | // Add any leftover non-keyed items
2064 | newChildren.push(newItem)
2065 | }
2066 | }
2067 |
2068 | var simulate = newChildren.slice()
2069 | var simulateIndex = 0
2070 | var removes = []
2071 | var inserts = []
2072 | var simulateItem
2073 |
2074 | for (var k = 0; k < bChildren.length;) {
2075 | var wantedItem = bChildren[k]
2076 | simulateItem = simulate[simulateIndex]
2077 |
2078 | // remove items
2079 | while (simulateItem === null && simulate.length) {
2080 | removes.push(remove(simulate, simulateIndex, null))
2081 | simulateItem = simulate[simulateIndex]
2082 | }
2083 |
2084 | if (!simulateItem || simulateItem.key !== wantedItem.key) {
2085 | // if we need a key in this position...
2086 | if (wantedItem.key) {
2087 | if (simulateItem && simulateItem.key) {
2088 | // if an insert doesn't put this key in place, it needs to move
2089 | if (bKeys[simulateItem.key] !== k + 1) {
2090 | removes.push(remove(simulate, simulateIndex, simulateItem.key))
2091 | simulateItem = simulate[simulateIndex]
2092 | // if the remove didn't put the wanted item in place, we need to insert it
2093 | if (!simulateItem || simulateItem.key !== wantedItem.key) {
2094 | inserts.push({key: wantedItem.key, to: k})
2095 | }
2096 | // items are matching, so skip ahead
2097 | else {
2098 | simulateIndex++
2099 | }
2100 | }
2101 | else {
2102 | inserts.push({key: wantedItem.key, to: k})
2103 | }
2104 | }
2105 | else {
2106 | inserts.push({key: wantedItem.key, to: k})
2107 | }
2108 | k++
2109 | }
2110 | // a key in simulate has no matching wanted key, remove it
2111 | else if (simulateItem && simulateItem.key) {
2112 | removes.push(remove(simulate, simulateIndex, simulateItem.key))
2113 | }
2114 | }
2115 | else {
2116 | simulateIndex++
2117 | k++
2118 | }
2119 | }
2120 |
2121 | // remove all the remaining nodes from simulate
2122 | while(simulateIndex < simulate.length) {
2123 | simulateItem = simulate[simulateIndex]
2124 | removes.push(remove(simulate, simulateIndex, simulateItem && simulateItem.key))
2125 | }
2126 |
2127 | // If the only moves we have are deletes then we can just
2128 | // let the delete patch remove these items.
2129 | if (removes.length === deletedItems && !inserts.length) {
2130 | return {
2131 | children: newChildren,
2132 | moves: null
2133 | }
2134 | }
2135 |
2136 | return {
2137 | children: newChildren,
2138 | moves: {
2139 | removes: removes,
2140 | inserts: inserts
2141 | }
2142 | }
2143 | }
2144 |
2145 | function remove(arr, index, key) {
2146 | arr.splice(index, 1)
2147 |
2148 | return {
2149 | from: index,
2150 | key: key
2151 | }
2152 | }
2153 |
2154 | function keyIndex(children) {
2155 | var keys = {}
2156 | var free = []
2157 | var length = children.length
2158 |
2159 | for (var i = 0; i < length; i++) {
2160 | var child = children[i]
2161 |
2162 | if (child.key) {
2163 | keys[child.key] = i
2164 | } else {
2165 | free.push(i)
2166 | }
2167 | }
2168 |
2169 | return {
2170 | keys: keys, // A hash of key name to index
2171 | free: free, // An array of unkeyed item indices
2172 | }
2173 | }
2174 |
2175 | function appendPatch(apply, patch) {
2176 | if (apply) {
2177 | if (isArray(apply)) {
2178 | apply.push(patch)
2179 | } else {
2180 | apply = [apply, patch]
2181 | }
2182 |
2183 | return apply
2184 | } else {
2185 | return patch
2186 | }
2187 | }
2188 |
2189 | },{"../vnode/handle-thunk":36,"../vnode/is-thunk":37,"../vnode/is-vnode":39,"../vnode/is-vtext":40,"../vnode/is-widget":41,"../vnode/vpatch":44,"./diff-props":46,"x-is-array":23}],48:[function(require,module,exports){
2190 | module.exports = BaseElement
2191 |
2192 | var h = require('virtual-dom/h')
2193 | var diff = require('virtual-dom/diff')
2194 | var patch = require('virtual-dom/patch')
2195 | var createElement = require('virtual-dom/create-element')
2196 | var toHTML = require('vdom-to-html')
2197 |
2198 | function BaseElement (el) {
2199 | if (!(this instanceof BaseElement)) return new BaseElement(el)
2200 | this.vtree = null
2201 | this.element = null
2202 | this.__appendTo__ = el
2203 | this.__events__ = Object.create(null)
2204 | this.__BaseElementSig__ = 'be-' + Date.now()
2205 | this.__onload__ = new Onload(this.send.bind(this))
2206 | }
2207 |
2208 | BaseElement.prototype.html = function () {
2209 | return h.apply(this, arguments)
2210 | }
2211 |
2212 | BaseElement.prototype.afterRender = function (vtree) {
2213 | if (this.hasOwnProperty('__BaseElementSig__')) {
2214 | return BaseElement.prototype.render.call(this, vtree)
2215 | }
2216 | return vtree
2217 | }
2218 |
2219 | BaseElement.prototype.render = function (vtree) {
2220 | if (typeof vtree === 'function') {
2221 | vtree = vtree.call(this)
2222 | }
2223 | // Top level vnode must have className for CSS
2224 | // TODO: Check if were using CSS though
2225 | if (vtree && vtree.properties && !vtree.properties.className) {
2226 | vtree.properties.className = this.__BaseElementSig__
2227 | }
2228 | if (!this.vtree) {
2229 | this.vtree = vtree
2230 | this.element = createElement(this.vtree)
2231 | if (this.__appendTo__) {
2232 | this.__appendTo__.appendChild(this.element)
2233 | }
2234 | } else {
2235 | var patches = diff(this.vtree, vtree)
2236 | this.element = patch(this.element, patches)
2237 | this.vtree = vtree
2238 | }
2239 | return this.vtree
2240 | }
2241 |
2242 | BaseElement.prototype.toString = function () {
2243 | this.render.apply(this, arguments)
2244 | return toHTML(this.vtree)
2245 | }
2246 |
2247 | BaseElement.prototype.send = function (name) {
2248 | var found = this.__events__[name]
2249 | if (!found) return this
2250 | var args = Array.prototype.slice.call(arguments, 1)
2251 | for (var i = 0; i < found.length; i++) {
2252 | var fn = found[i]
2253 | if (typeof fn === 'function') fn.apply(this, args)
2254 | }
2255 | return this
2256 | }
2257 |
2258 | BaseElement.prototype.addEventListener = function (name, cb) {
2259 | if (!Array.isArray(this.__events__[name])) this.__events__[name] = []
2260 | this.__events__[name].push(cb)
2261 | }
2262 |
2263 | function Onload (cb) {
2264 | this.cb = cb
2265 | }
2266 | Onload.prototype.hook = function (node) {
2267 | var self = this
2268 | setTimeout(function () {
2269 | self.cb('load', node)
2270 | }, 10)
2271 | }
2272 | Onload.prototype.unhook = function (node) {
2273 | var self = this
2274 | setTimeout(function () {
2275 | self.cb('unload', node)
2276 | }, 10)
2277 | }
2278 |
2279 | },{"vdom-to-html":4,"virtual-dom/create-element":15,"virtual-dom/diff":16,"virtual-dom/h":17,"virtual-dom/patch":24}]},{},[48])(48)
2280 | });
--------------------------------------------------------------------------------
/examples/angular.js:
--------------------------------------------------------------------------------
1 | /*eslint-disable */
2 |
3 | // This example uses ./list.js (an element created with base-element)
4 | // in use with an AngularJS directive: https://docs.angularjs.org/guide/directive
5 |
6 | var List = require('./list.js')
7 |
8 | angular.module('myApp')
9 | .directive('list', function () {
10 | return {
11 | restrict: 'EA',
12 | scope: {
13 | data: '='
14 | },
15 | link: function ($scope, $element) {
16 | var list = new List($element[0])
17 | $scope.$watch('data', function (data) {
18 | list.render(data)
19 | })
20 |
21 | // When item clicked
22 | list.addEventListener('clicked', function (item) {
23 | window.alert('You clicked ' + item.innerHTML)
24 | })
25 |
26 | // When item added
27 | list.addEventListener('added', function () {
28 | data.push(String(Math.random() * 9999))
29 | list.render(data)
30 | })
31 | }
32 | }
33 | })
34 |
--------------------------------------------------------------------------------
/examples/custom-element.js:
--------------------------------------------------------------------------------
1 | // This example uses ./list.js (an element created with base-element)
2 | // in use with the library "custom-element": https://www.npmjs.com/package/custom-element
3 |
4 | require('webcomponents.js')
5 |
6 | var List = require('./list.js')
7 | var createCustom = require('custom-element')
8 |
9 | // Mock data for the element
10 | var data = ['one', 'two', 'three']
11 |
12 | var CustomHTMLElement = createCustom().on('created', function () {
13 | var self = this
14 | // When the element is created, consume List's API
15 | // Attaching to the element so it can be called via the element itself, totally optional though
16 | self.list = new List(self)
17 | self.list.render(data)
18 | self.list.addEventListener('clicked', function (item) {
19 | window.alert('You clicked ' + item.innerHTML)
20 | })
21 | self.list.addEventListener('added', function () {
22 | data.push(String(Math.random() * 9999))
23 | self.list.render(data)
24 | })
25 | }).on('attribute', function (key) {
26 | // When an attribute is set, add the attribute value to our data
27 | var test = this.getAttribute(key)
28 | data.push(test)
29 | this.list.render(data)
30 | })
31 |
32 | // Register our custom element
33 | var CustomElement = document.registerElement('custom-element', CustomHTMLElement)
34 |
35 | // Create and append it to document.body
36 | var el = new CustomElement()
37 | document.body.appendChild(el)
38 |
39 | // 2s later, modify the attribute of the element
40 | setTimeout(function () {
41 | el.setAttribute('data-test', 'I was added because of an attribute')
42 | }, 2000)
43 |
--------------------------------------------------------------------------------
/examples/ember.js:
--------------------------------------------------------------------------------
1 | /*eslint-disable */
2 |
3 | // This example uses ./list.js (an element created with base-element)
4 | // in use with an Ember.js Component: http://emberjs.com/api/classes/Ember.Component.html
5 |
6 | var List = require('./list.js')
7 |
8 | var MyListComponent = Ember.Component.extend({
9 | data: ['one', 'two', 'three'],
10 | didInsertElement: function () {
11 | this._super()
12 |
13 | var data = this.get('data')
14 |
15 | var list = new List(this.element)
16 | list.render(data)
17 |
18 | // When item clicked
19 | list.addEventListener('clicked', function (item) {
20 | window.alert('You clicked ' + item.innerHTML)
21 | })
22 |
23 | // When item added
24 | list.addEventListener('added', function () {
25 | data.push(String(Math.random() * 9999))
26 | list.render(data)
27 | })
28 |
29 | }
30 | })
31 |
--------------------------------------------------------------------------------
/examples/es6.js:
--------------------------------------------------------------------------------
1 | // This example shows an example "complex" slideshow element in use with ES6
2 | // syntax care of babel: https://babeljs.io/
3 |
4 | import BaseElement from '../index.js'
5 |
6 | class Slides extends BaseElement {
7 | constructor (el) {
8 | super(el)
9 | // Create a property for the actively shown slide
10 | this.activeIndex = 0
11 | // When a slide is selected, set that as the activeIndex then render
12 | this.addEventListener('select', idx => {
13 | this.activeIndex = idx
14 | this.render(this.data)
15 | })
16 | // Inline styles for this element
17 | this.style = {
18 | display: 'table',
19 | margin: '0',
20 | padding: '0'
21 | }
22 | }
23 | render (slides) {
24 | // Save a local copy of data for re-rendering
25 | this.data = slides
26 | slides = slides.map((slide, idx) => {
27 | let tag = 'li'
28 | // If this is the active slide, set the content and .active class
29 | if (idx === this.activeIndex) {
30 | tag = 'li.active'
31 | this.content = slide.content
32 | }
33 | // Render each
34 | return this.html(tag, {
35 | style: {
36 | listStyle: 'none',
37 | float: 'left',
38 | margin: '0 .5em'
39 | }
40 | }, [
41 | this.html('button', {
42 | onclick: e => {
43 | // onclick send a select event up with index
44 | this.send('select', idx)
45 | }
46 | }, slide.name)
47 | ])
48 | })
49 | // Build our tree with
buttons
content
50 | let vtree = this.html('div', [
51 | this.html('ul.sections', this, slides),
52 | this.html('.content', {
53 | style: {
54 | padding: '1em'
55 | }
56 | }, this.content)
57 | ])
58 | // Return the tree wrapped in afterRender
59 | return this.afterRender(vtree)
60 | }
61 | }
62 |
63 | // The end user API from here on down
64 | let slides = new Slides(document.body)
65 | slides.render([
66 | { name: 'intro', content: 'Intro...' },
67 | { name: 'examples', content: 'Examples...' },
68 | { name: 'outro', content: 'Outro...' }
69 | ])
70 |
--------------------------------------------------------------------------------
/examples/list.js:
--------------------------------------------------------------------------------
1 | // An example element that can gets used by all the other examples
2 |
3 | module.exports = List
4 |
5 | var BaseElement = require('../index.js')
6 | var attachCSS = require('attach-css')
7 |
8 | function List (el) {
9 | BaseElement.call(this, el)
10 | this.className = 'list'
11 | }
12 | List.prototype = Object.create(BaseElement.prototype)
13 |
14 | List.prototype.render = function (items) {
15 | var self = this
16 |
17 | // Create li upon click just lets us know it was clicked
18 | items = items.map(function (item) {
19 | return self.html('li', {
20 | onclick: function (e) {
21 | self.send('clicked', e.target)
22 | }
23 | }, item)
24 | })
25 |
26 | // Add button that adds new li's to list
27 | items.unshift(this.html('li', this.html('button', {
28 | onclick: function (e) {
29 | self.send('added')
30 | }
31 | }, ['add item'])))
32 |
33 | return this.afterRender(this.html('ul', this, items))
34 | }
35 |
36 | // Localized CSS can be returned using attachCSS()
37 | List.prototype.css = function () {
38 | // Can be a string, brfs a style.css, or css preprocessor
39 | return attachCSS(`
40 | * {
41 | font-family: Helvetica, sans-serif;
42 | }
43 | ul {
44 | margin: 0;
45 | padding: 0;
46 | }
47 | ul li {
48 | list-style: none;
49 | border-bottom: 1px solid #ddd;
50 | padding: .3em 0;
51 | }
52 | ul li:hover {
53 | background-color: #eee;
54 | transition: .5s;
55 | padding-left: .5em;
56 | cursor: pointer;
57 | }
58 | li:first-child {
59 | padding: .3em;
60 | border-bottom: 1px solid #333;
61 | text-align: right;
62 | }
63 | button {
64 | border: none;
65 | padding: .3em .5em;
66 | background-color: #00bcd4;
67 | color: white;
68 | font-size: 1.2em;
69 | cursor: pointer;
70 | }
71 | button:hover {
72 | padding: .3em 1em;
73 | transition: .5s;
74 | }
75 | `, this.vtree)
76 | }
77 |
--------------------------------------------------------------------------------
/examples/nesting.js:
--------------------------------------------------------------------------------
1 | var BaseElement = require('../index.js')
2 |
3 | // First Bear extends BaseElement
4 | function Bear (el) {
5 | BaseElement.call(this, el)
6 | }
7 | Bear.prototype = Object.create(BaseElement.prototype)
8 | Bear.prototype.render = function (items) {
9 | var self = this
10 | var vtree = items.map(function (item) {
11 | return self.html('li.bear', item)
12 | })
13 | return this.afterRender(vtree)
14 | }
15 |
16 | // Second Grizzly extends Bear
17 | function Grizzly (el) {
18 | Bear.call(this, el)
19 | }
20 | Grizzly.prototype = Object.create(Bear.prototype)
21 | Grizzly.prototype.render = function (data) {
22 | var bears = Bear.prototype.render(data.bears)
23 | var vtree = this.html('ul.grizzly', [
24 | this.html('li', 'Top'),
25 | bears,
26 | this.html('li', 'Bottom')
27 | ])
28 | return this.afterRender(vtree)
29 | }
30 |
31 | // Third App extends Grizzly
32 | function App (el) {
33 | Grizzly.call(this, el)
34 | }
35 | App.prototype = Object.create(Grizzly.prototype)
36 | App.prototype.render = function (data) {
37 | var middle = Grizzly.prototype.render(data)
38 | var vtree = this.html('div.app', [data.heading, middle])
39 | return this.afterRender(vtree)
40 | }
41 |
42 | // The end user only cares about App
43 | var app = new App(document.body)
44 | app.render({
45 | heading: 'Bears',
46 | bears: ['Grizzly', 'Polar', 'Brown']
47 | })
48 |
--------------------------------------------------------------------------------
/examples/react.js:
--------------------------------------------------------------------------------
1 | // This example uses ./list.js (an element created with base-element)
2 | // in use with a React component: https://facebook.github.io/react/
3 |
4 | var List = require('./list.js')
5 | var React = require('react')
6 |
7 | // Create a React component that wraps the List
8 | var XList = React.createClass({
9 | propTypes: {
10 | items: React.PropTypes.arrayOf(React.propTypes.string)
11 | },
12 | componentDidMount: function () {
13 | var list = new List(React.findDOMNode(this))
14 | var data = this.props.items
15 | list.render(data)
16 |
17 | // When item clicked
18 | list.addEventListener('clicked', function (item) {
19 | window.alert('You clicked ' + item.innerHTML)
20 | })
21 |
22 | // When item added
23 | list.addEventListener('added', function () {
24 | data.push(String(Math.random() * 9999))
25 | list.render(data)
26 | })
27 | },
28 | render: function () {
29 | return React.createElement('div')
30 | }
31 | })
32 |
33 | React.render(
34 | React.createElement(XList, { items: ['one', 'two', 'three'] }),
35 | document.body
36 | )
37 |
--------------------------------------------------------------------------------
/examples/server-side.js:
--------------------------------------------------------------------------------
1 | var List = require('./list.js')
2 | var http = require('http')
3 | var browserify = require('browserify')
4 | var path = require('path')
5 |
6 | // Create our server
7 | http.createServer(function (req, res) {
8 | // Some crude routing
9 | if (req.url === '/' || req.url === '/index.html') {
10 | index(res)
11 | } else if (req.url === '/bundle.js') {
12 | script(res)
13 | } else {
14 | res.end('')
15 | }
16 | }).listen(1337)
17 | console.log('Server running at http://localhost:1337/')
18 |
19 | // Our index.html
20 | function index (res) {
21 | res.writeHead(200, {'Content-Type': 'text/html'})
22 |
23 | // Initial data for the list
24 | var data = ['This is', 'the initial', 'content']
25 |
26 | // Create/render the list
27 | var list = new List()
28 |
29 | // Convert the list element to static HTML and send out
30 | var html = list.toString(data)
31 |
32 | // Serve up our template
33 | var template = `
34 | ${html}
35 |
36 | `
37 | res.end(template)
38 | }
39 |
40 | // Our script that will take over after the initial static render
41 | function script (res) {
42 | var b = browserify()
43 | b.add(path.join(__dirname, 'standalone.js'))
44 | b.bundle(function (err, buf) {
45 | if (err) throw err
46 | res.writeHead(200, {'Content-Type': 'application/javascript'})
47 | res.end(buf)
48 | })
49 | }
50 |
--------------------------------------------------------------------------------
/examples/standalone.js:
--------------------------------------------------------------------------------
1 | // This example uses ./list.js (an element created with base-element)
2 | // by itself :)
3 |
4 | var List = require('./list.js')
5 |
6 | // Data for the list
7 | var data = ['one', 'two', 'three']
8 |
9 | // Clear out any staticly rendered html (if this script is being served by server-side.js)
10 | document.body.innerHTML = ''
11 |
12 | // Create a list
13 | var list = new List(document.body)
14 | list.className = 'my-list'
15 | list.render(data)
16 |
17 | // When item clicked
18 | list.addEventListener('clicked', function (item) {
19 | window.alert('You clicked ' + item.innerHTML)
20 | })
21 |
22 | // When item added
23 | list.addEventListener('added', function () {
24 | data.push(String(Math.random() * 9999))
25 | list.render(data)
26 | })
27 |
28 | // WIP: CSS should be written out to a separate file or nonce'd
29 | // this part is just for testing and will be removed
30 | var style = document.createElement('style')
31 | style.innerHTML = list.css()
32 | document.head.appendChild(style)
33 |
--------------------------------------------------------------------------------
/examples/virtual-dom.js:
--------------------------------------------------------------------------------
1 | // This example uses ./list.js (an element created with base-element)
2 | // in use with virtual-dom: https://github.com/Matt-Esch/virtual-dom
3 |
4 | var List = require('./list.js')
5 |
6 | var h = require('virtual-dom/h')
7 | var diff = require('virtual-dom/diff')
8 | var patch = require('virtual-dom/patch')
9 | var createElement = require('virtual-dom/create-element')
10 |
11 | // Data for the list
12 | var data = ['one', 'two', 'three']
13 |
14 | // Create a list that does not automatically appendTo
15 | // as we'll be handling that with virtual-dom
16 | var list = new List()
17 |
18 | // When item clicked
19 | list.addEventListener('clicked', function (item) {
20 | window.alert('You clicked ' + item.innerHTML)
21 | })
22 |
23 | // When item added
24 | list.addEventListener('added', function () {
25 | data.push(String(Math.random() * 9999))
26 | list.render(data)
27 | })
28 |
29 | // Main render function
30 | function render () {
31 | return h('.my-list', [
32 | 'With ' + data.length + ' rows:',
33 | list.render(data)
34 | ])
35 | }
36 |
37 | // Initial DOM tree render
38 | var tree = render()
39 | var rootNode = createElement(tree)
40 | document.body.appendChild(rootNode)
41 |
42 | // Main render loop
43 | setInterval(function () {
44 | var newTree = render()
45 | var patches = diff(tree, newTree)
46 | rootNode = patch(rootNode, patches)
47 | tree = newTree
48 | }, 100)
49 |
--------------------------------------------------------------------------------
/examples/webcomponent.js:
--------------------------------------------------------------------------------
1 | /*global HTMLElement:false*/
2 |
3 | // This example uses ./list.js (an element created with base-element)
4 | // in use with web components: http://webcomponents.org/
5 |
6 | var List = require('./list.js')
7 |
8 | var data = ['one', 'two', 'three']
9 |
10 | // Create a proto for our custom element
11 | var proto = Object.create(HTMLElement.prototype)
12 | proto.createdCallback = function () {
13 | // Create a new list and append to this custom element
14 | var list = new List(this)
15 | list.render(data)
16 |
17 | // When item clicked
18 | list.addEventListener('clicked', function (item) {
19 | window.alert('You clicked ' + item.innerHTML)
20 | })
21 |
22 | // When item added
23 | list.addEventListener('added', function () {
24 | data.push(String(Math.random() * 9999))
25 | list.render(data)
26 | })
27 | }
28 |
29 | // Create our tag using the above proto
30 | var XList = document.registerElement('x-list', {
31 | prototype: proto
32 | })
33 | document.body.appendChild(new XList())
34 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | module.exports = BaseElement
2 |
3 | var h = require('virtual-dom/h')
4 | var diff = require('virtual-dom/diff')
5 | var patch = require('virtual-dom/patch')
6 | var createElement = require('virtual-dom/create-element')
7 | var toHTML = require('vdom-to-html')
8 | var EventTarget = require('dom-event-target')
9 | var inherits = require('inherits')
10 | var nextTick = require('next-tick')
11 |
12 | function BaseElement (el) {
13 | if (!(this instanceof BaseElement)) return new BaseElement(el)
14 | EventTarget.call(this)
15 | this.vtree = null
16 | this.element = null
17 | this.__appendTo__ = el
18 | this.__BaseElementSig__ = 'be-' + Date.now()
19 | this.__onload__ = new Onload(this.send.bind(this))
20 | }
21 | inherits(BaseElement, EventTarget)
22 |
23 | BaseElement.prototype.html = function BaseElement_html () {
24 | return h.apply(this, arguments)
25 | }
26 |
27 | BaseElement.prototype.afterRender = function BaseElement_afterRender (vtree) {
28 | if (this.hasOwnProperty('__BaseElementSig__')) {
29 | return BaseElement.prototype.render.call(this, vtree)
30 | }
31 | return vtree
32 | }
33 |
34 | BaseElement.prototype.render = function BaseElement_render (vtree) {
35 | if (typeof vtree === 'function') {
36 | vtree = vtree.call(this)
37 | }
38 | // Top level vnode must have className for CSS
39 | // TODO: Check if were using CSS though
40 | if (vtree && vtree.properties && !vtree.properties.className) {
41 | vtree.properties.className = this.__BaseElementSig__
42 | }
43 | if (!this.vtree) {
44 | this.vtree = vtree
45 | this.element = createElement(this.vtree)
46 | if (this.__appendTo__) {
47 | this.__appendTo__.appendChild(this.element)
48 | }
49 | } else {
50 | var patches = diff(this.vtree, vtree)
51 | this.element = patch(this.element, patches)
52 | this.vtree = vtree
53 | }
54 | return this.vtree
55 | }
56 |
57 | BaseElement.prototype.toString = function BaseElement_toString () {
58 | this.render.apply(this, arguments)
59 | return toHTML(this.vtree)
60 | }
61 |
62 | function Onload (cb) {
63 | this.cb = cb
64 | }
65 | Onload.prototype.hook = function BaseElement_hook (node) {
66 | var self = this
67 | nextTick(function BaseElement_hook_nextTick () {
68 | self.cb('load', node)
69 | })
70 | }
71 | Onload.prototype.unhook = function BaseElement_unhook (node) {
72 | var self = this
73 | nextTick(function BaseElement_unhook_nextTick () {
74 | self.cb('unload', node)
75 | })
76 | }
77 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "base-element",
3 | "version": "3.0.1",
4 | "description": "An element authoring library for creating standalone and performant elements.",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "standard && node test/server.js && zuul --local 9966 -- test/index.js",
8 | "ci": "standard && node test/server.js && zuul -- test/index.js",
9 | "start": "budo examples/standalone.js",
10 | "build": "browserify index.js --standalone BaseElement -o dist/base-element.js",
11 | "prepublish": "npm run build"
12 | },
13 | "author": "Kyle Robinson Young (http://dontkry.com)",
14 | "license": "MIT",
15 | "repository": {
16 | "type": "git",
17 | "url": "https://github.com/shama/base-element.git"
18 | },
19 | "files": [
20 | "index.js",
21 | "dist/"
22 | ],
23 | "standard": {
24 | "ignore": [
25 | "**/dist/**"
26 | ]
27 | },
28 | "keywords": [
29 | "virtual",
30 | "dom",
31 | "element",
32 | "diff",
33 | "browser"
34 | ],
35 | "devDependencies": {
36 | "attach-css": "^1.1.0",
37 | "babelify": "^6.0.2",
38 | "browser-test-helpers": "^1.0.0",
39 | "browserify": "^10.0.0",
40 | "budo": "^4.0.0",
41 | "standard": "^4.0.0",
42 | "tap-spec": "^4.0.0",
43 | "tape": "^4.0.0",
44 | "zuul": "^3.0.0"
45 | },
46 | "dependencies": {
47 | "dom-event-target": "~1.0.0",
48 | "inherits": "~2.0.1",
49 | "isarray": "0.0.1",
50 | "next-tick": "~0.2.2",
51 | "vdom-to-html": "^2.1.1",
52 | "virtual-dom": "^2.0.1"
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/test/fixtures/button.js:
--------------------------------------------------------------------------------
1 | module.exports = Button
2 |
3 | var BaseElement = require('../../index.js')
4 |
5 | function Button (el) {
6 | BaseElement.call(this, el)
7 | var self = this
8 | this.onclick = function (e) {
9 | self.send('clicked', e.target)
10 | }
11 | }
12 | Button.prototype = Object.create(BaseElement.prototype)
13 |
14 | Button.prototype.render = function (label) {
15 | var vtree = this.html('button', this, label)
16 | return this.afterRender(vtree)
17 | }
18 |
--------------------------------------------------------------------------------
/test/fixtures/nested.js:
--------------------------------------------------------------------------------
1 | module.exports = Top
2 |
3 | var BaseElement = require('../../index.js')
4 |
5 | function Bottom (el) {
6 | BaseElement.call(this, el)
7 | }
8 | Bottom.prototype = Object.create(BaseElement.prototype)
9 |
10 | Bottom.prototype.render = function (data) {
11 | var vtree = this.html('li.bottom', data)
12 | return this.afterRender(vtree)
13 | }
14 |
15 | function Middle (el) {
16 | Bottom.call(this, el)
17 | }
18 | Middle.prototype = Object.create(Bottom.prototype)
19 |
20 | Middle.prototype.render = function (data) {
21 | var bottom = Bottom.prototype.render(data)
22 | var vtree = this.html('ul.middle', bottom)
23 | return this.afterRender(vtree)
24 | }
25 |
26 | function Top (el) {
27 | Middle.call(this, el)
28 | }
29 | Top.prototype = Object.create(Middle.prototype)
30 |
31 | Top.prototype.render = function (data) {
32 | var middle = Middle.prototype.render(data)
33 | var vtree = this.html('div.top', middle)
34 | return this.afterRender(vtree)
35 | }
36 |
--------------------------------------------------------------------------------
/test/index.js:
--------------------------------------------------------------------------------
1 | var help = require('browser-test-helpers')()
2 | var test = require('tape')
3 |
4 | var createElement = require('../index.js')
5 | var Button = require('./fixtures/button.js')
6 | var Nested = require('./fixtures/nested.js')
7 |
8 | test('simple down and up', function (t) {
9 | setUp(function (fixture) {
10 | var expected = 'Testing ' + Math.random()
11 | var button = new Button(fixture)
12 | button.addEventListener('clicked', function (el) {
13 | t.equal(el.innerHTML, expected, 'data was sent down and event came up')
14 | tearDown(fixture, t.end)
15 | })
16 | button.render(expected)
17 | help.click(button.element)
18 | })
19 | })
20 |
21 | test('renders nested elements', function (t) {
22 | t.plan(1)
23 | setUp(function (fixture) {
24 | var nested = new Nested(fixture)
25 | nested.render('test')
26 | t.equal(fixture.innerHTML, '