├── History.md ├── .gitignore ├── Makefile ├── cast.css ├── dist ├── cast.css └── cast.js ├── component.json ├── block.js ├── example └── example.html ├── Readme.md ├── test └── cast.js └── index.js /History.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | components 2 | build 3 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | build: components index.js 3 | @component build --dev 4 | 5 | -------------------------------------------------------------------------------- /cast.css: -------------------------------------------------------------------------------- 1 | .Cast { 2 | position: relative; 3 | } 4 | 5 | .Cast-item { 6 | position: absolute; 7 | display: block; 8 | opacity: 1; 9 | transition: opacity 0.5s, transform 0.5s; 10 | } 11 | 12 | .Cast-item.hidden { 13 | opacity: 0; 14 | } -------------------------------------------------------------------------------- /dist/cast.css: -------------------------------------------------------------------------------- 1 | .Cast { 2 | position: relative; 3 | } 4 | 5 | .Cast-item { 6 | position: absolute; 7 | display: block; 8 | opacity: 1; 9 | transition: opacity 0.5s, transform 0.5s; 10 | } 11 | 12 | .Cast-item.hidden { 13 | opacity: 0; 14 | } -------------------------------------------------------------------------------- /component.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cast", 3 | "repo": "bmcmahen/cast", 4 | "description": "Create animated grid layouts given an array of attributes.", 5 | "version": "1.1.1", 6 | "keywords": ["layout", "grid", "isotope"], 7 | "dependencies": { 8 | "component/emitter": "*", 9 | "component/clone": "*", 10 | "component/type": "*", 11 | "bmcmahen/ordered-dictionary": "*", 12 | "component/translate": "*", 13 | "wilsonpage/fastdom": "*", 14 | "component/each": "0.2.3", 15 | "component/classes": "1.2.1", 16 | "anthonyshort/after-transition": "0.0.4", 17 | "yields/empty": "*" 18 | }, 19 | "development": { 20 | "component/assert": "*", 21 | "component/jquery": "*" 22 | }, 23 | "styles": ["cast.css"], 24 | "license": "MIT", 25 | "main": "index.js", 26 | "scripts": [ 27 | "index.js", 28 | "block.js" 29 | ] 30 | } -------------------------------------------------------------------------------- /block.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies 3 | */ 4 | 5 | var each = require('each'); 6 | var classes = require('classes'); 7 | var fastdom = require('fastdom'); 8 | var afterTransition = require('after-transition'); 9 | var clone = require('clone'); 10 | var translate = require('translate'); 11 | 12 | /** 13 | * expose Block 14 | */ 15 | 16 | module.exports = Block; 17 | 18 | /** 19 | * Block 20 | * @param {Object} attr 21 | * @param {Cast} cast 22 | */ 23 | 24 | function Block(attr, cast){ 25 | this.cast = cast; 26 | this.attr = attr; 27 | this.pos = {}; 28 | this.el = document.createElement('div'); 29 | this.classes = classes(this.el); 30 | this.el.className = 'Cast-item hidden'; 31 | this.rendered = false; 32 | this.hidden = true; 33 | this.cast.emit('view-created', this); 34 | } 35 | 36 | /** 37 | * Set attributes 38 | * @param {Object} attr 39 | */ 40 | 41 | Block.prototype.set = function(attr){ 42 | this.attr = attr; 43 | }; 44 | 45 | /** 46 | * Hide the block 47 | * @return {Block} 48 | */ 49 | 50 | Block.prototype.hide = function(fn){ 51 | if (this.hidden) return; 52 | fastdom.write(function(){ 53 | if (fn) afterTransition.once(this.el, fn); 54 | this.classes.add('hidden'); 55 | this.el.setAttribute('aria-hidden', true); 56 | }.bind(this)); 57 | this.hidden = true; 58 | return this; 59 | }; 60 | 61 | /** 62 | * Show the block 63 | * @return {Block} 64 | */ 65 | 66 | Block.prototype.show = function(){ 67 | if (!this.hidden) return; 68 | fastdom.write(function(){ 69 | this.classes.remove('hidden'); 70 | this.el.setAttribute('aria-hidden', false); 71 | }.bind(this)); 72 | this.hidden = false; 73 | return this; 74 | }; 75 | 76 | /** 77 | * Remove block element from dom 78 | * @return {Block} 79 | */ 80 | 81 | Block.prototype.remove = function(){ 82 | this.cast.emit('view-destroyed', this); 83 | this.el.parentNode.removeChild(this.el); 84 | return this; 85 | }; 86 | 87 | /** 88 | * Update position 89 | * @return {Block} 90 | */ 91 | 92 | Block.prototype.position = function(pos){ 93 | if (pos) this.pos = pos; 94 | var style = this.el.style; 95 | fastdom.write(function(){ 96 | style.width = this.pos.width + 'px'; 97 | style.height = this.pos.height + 'px'; 98 | translate(this.el, this.pos.left, this.pos.top); 99 | }.bind(this)); 100 | return this; 101 | }; 102 | 103 | /** 104 | * Get our attr 105 | * @return {Object} 106 | */ 107 | 108 | Block.prototype.toJSON = function(){ 109 | return clone(this.attr); 110 | }; -------------------------------------------------------------------------------- /example/example.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | grid-it example 4 | 5 | 38 | 39 | 40 | 41 | 42 |
43 | 44 | 47 | 48 | 49 | 50 | 51 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # Cast.js 2 | 3 | Cast helps you build beautiful, animated grid layouts. Supply an array of attributes, select a layout mode, supply a template, and get a grid-view. It's vanilla Javascript and it's inspired by [Isotope](https://github.com/desandro/isotope). It works in IE9+, and IE8 with `bind` and `indexOf` polyfills. 4 | 5 | Check out the [demonstration](http://cast.meteor.com) built with Meteor. 6 | 7 | If you're using React, use [react-cast](http://github.com/bmcmahen/react-cast) instead. 8 | 9 | ## Installation 10 | 11 | The easiest way to use Cast is to use the `cast.js` located in the `dist` folder, and require this script in your html page. Cast will then be available under the global variable `cast`'. 12 | 13 | Alternatively, Cast can be used as a [component](https://github.com/component/component). 14 | 15 | $ component install bmcmahen/cast 16 | 17 | ## Example 18 | 19 | ```javascript 20 | var Cast = require('cast'); 21 | 22 | var docs = [{name: 'ben'}, {name: 'kit'}, {name: 'rick'}, {name: 'james'}]; 23 | var container = document.getElementById('#wrapper'); 24 | 25 | function render(attr, el, block){ 26 | el.innerHTML = '

' + attr.name + '

'; 27 | } 28 | 29 | // Create our cast 30 | var grid = new Cast(container) 31 | .render(render) 32 | .data(docs, 'name') 33 | .sortBy('name') 34 | .justify(50, 50, 10, 10) 35 | .draw(); 36 | ``` 37 | 38 | ## API 39 | 40 | ### new Cast(container) 41 | 42 | `container` should be the element that you want your cast to appear in. 43 | 44 | ### .render(fn) 45 | 46 | Render will be called whenever a new element is rendered in the cast layout. This should be called __before adding documents to your cast__. For example: 47 | 48 | ```javascript 49 | var layout = new Cast(container) 50 | .render(function(attr, el, block){ 51 | el.innerHTML = template(attr); 52 | }) 53 | .data(docs, 'name'); 54 | ``` 55 | 56 | ### .data(docs, Fn|String) 57 | 58 | Supply Cast with an array of documents. Use the callback function to supply a unique identifer for each field, which will allow Cast to update, remove, and add attributes on subsequent calls. Alternatively, supply the key of the unique identifer ('_id', 'id', etc.). 59 | 60 | cast.data(docs, function(attr){ 61 | return attr._id; 62 | }); 63 | 64 | cast.data(docs, '_id'); 65 | 66 | ### .justify(width, height, paddingWidth, paddingHeight) 67 | 68 | Calculates grid positions to maintain a container left & right padding of zero. Grid item width and height remain constant, while grid-item-padding is dyanimc. If `#draw` has been called, `#justify` will automatically rerender your views. 69 | 70 | ### .center(width, height, paddingWidth, paddingHeight) 71 | 72 | Calculates the grid with dynamic width on the left and right side of the wrapper. Grid item width, height, paddingWidth, and paddingHeight are constant. If `#draw` has been called, `#center` will automatically rerender your views. 73 | 74 | ### .dynamic(width, height, paddingWidth, paddingHeight) 75 | 76 | Calculates the grid with a constant `paddingWidth` and `paddingHeight`, and a dynamic `boxWidth` and `boxHeight`. If `#draw` has been called, `#dynamic` will automatically rerender your views. 77 | 78 | ### .list(height, paddingHeight) 79 | 80 | Calculates the grid as a list, with one object per line. 81 | 82 | ### .toJSON() 83 | 84 | var json = cast.data(docs).justify(40, 40, 10, 10).toJSON(); 85 | 86 | ### .reset(docs, fn|String) 87 | 88 | Resets the Cast object with the supplied array. Use the callback to provide a unique, constant value for the field. 89 | 90 | cast.reset(docs, function(attr){ 91 | return attr._id; 92 | }); 93 | 94 | cast.reset(docs, 'id'); 95 | 96 | ### .add(docs, fn|String) 97 | 98 | Appends docs to the Cast object. 99 | 100 | ### .remove(uid) 101 | 102 | cast.remove('34'); 103 | 104 | ### .sortBy(field, 1) 105 | 106 | Sorts the collection based on a `field`. 107 | 108 | cast.sortBy('name', -1).center(50, 50, 10, 10); 109 | 110 | ### .draw() 111 | 112 | Simple utility function to append the cast layout to the container element. 113 | 114 | ## Events 115 | 116 | ### enter(model) 117 | 118 | cast.on('enter', function(model){ }); 119 | 120 | ### exit(model) 121 | ### view-created(view) 122 | ### view-destroyed(view) 123 | 124 | 125 | 126 | ## Meteor Usage 127 | 128 | See an example app [here](https://github.com/bmcmahen/meteor-cast-example). Include the standalone `cast.js` file in your client-side folder structure, and Meteor should automatically load it into your application. Create a template that will act as your cast wrapper. 129 | 130 | ```html 131 | {{#constant}} 132 |
133 | {{/constant}} 134 | ``` 135 | 136 | In your code, you'll want to create a simple template function that will be used to render each cast item. Here's a simple example: 137 | 138 | ```javascript 139 | function renderTemplate(obj){ 140 | return '

' + obj.title + '

'; 141 | } 142 | ``` 143 | 144 | Inside your templat rendered callback, instantiate a new `cast` and attach the data to the cast, specifying the layout that you want. Putting your `data` attachment function inside of an autorun will automatically update your cast layout any time the collection changes. 145 | 146 | ```javascript 147 | Template.cast.rendered = function(){ 148 | 149 | var el = document.getElementById('#cast'); 150 | 151 | var mycast = cast(el, renderTemplate); 152 | mycast.draw(); 153 | 154 | this.handle = Meteor.autorun(function(){ 155 | var videos = Videos.find().fetch(); 156 | mycast 157 | .data(videos, '_id') 158 | .dynamic(150, 150, 10, 10); 159 | }); 160 | } 161 | ``` 162 | ## License 163 | 164 | MIT 165 | -------------------------------------------------------------------------------- /test/cast.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var cast = require('cast'); 3 | var $ = require('jquery'); 4 | 5 | var testTemplate = function(attr){ 6 | return '

'+attr.name+'

'; 7 | }; 8 | 9 | var container = document.createElement('div'); 10 | container.id = 'cast'; 11 | container.style.width = 500 + 'px'; 12 | document.body.appendChild(container); 13 | 14 | describe('Cast', function(){ 15 | 16 | beforeEach(function(){ 17 | this.cast = cast(container); 18 | }); 19 | 20 | afterEach(function(){ 21 | delete this.cast; 22 | }); 23 | 24 | it('should be constructed with a container', function(){ 25 | assert(this.cast); 26 | assert(this.cast instanceof cast); 27 | assert(this.cast.wrapper); 28 | }); 29 | 30 | it('should set the width', function(){ 31 | assert(this.cast.wrapperWidth === 500); 32 | }); 33 | 34 | describe('#data', function(){ 35 | var docs = [{name: 'ben'}, {name: 'kit'}, {name: 'joe'}]; 36 | 37 | it('should iterate through the docs array and create models', function(){ 38 | this.cast.data(docs, 'name'); 39 | assert(this.cast.collection.length() === 3); 40 | assert(this.cast.collection.at(0).get('name') === 'ben'); 41 | assert(this.cast.collection.get('ben').get('name') === 'ben'); 42 | }); 43 | 44 | it('should support a fn callback to determine unique id', function(){ 45 | this.cast.data(docs, function(attr){ 46 | return attr.name; 47 | }); 48 | assert(this.cast.collection.length() === 3); 49 | }); 50 | 51 | it('should remove missing docs upon subsequent calls', function(){ 52 | this.cast.data(docs, 'name'); 53 | this.cast.data([{ name: 'ben' }], 'name'); 54 | assert(this.cast.collection.length() === 1); 55 | assert(!this.cast.collection.get('kit')); 56 | }); 57 | 58 | it('should fill in new docs upon subsquent calls', function(){ 59 | this.cast.data(docs, 'name'); 60 | var extended = docs; 61 | extended.push({ name: 'superman' }); 62 | this.cast.data(extended, 'name'); 63 | assert(this.cast.collection.get('superman')); 64 | assert(this.cast.toJSON().length === 4); 65 | }); 66 | 67 | }); 68 | 69 | describe('#toJSON', function(){ 70 | var docs = [{name: 'ben', age: 28}, {name: 'kit'}, {name: 'joe'}]; 71 | 72 | it('should return all of our docs', function(){ 73 | this.cast.data(docs, 'name'); 74 | var json = this.cast.toJSON(); 75 | assert(json.length === 3); 76 | assert(json[0].name === 'ben'); 77 | assert(json[0].age == 28); 78 | assert(json[2].name === 'joe'); 79 | }); 80 | 81 | }); 82 | 83 | describe('#reset', function(){ 84 | var docs = [{name: 'ben', age: 28}, {name: 'kit'}, {name: 'joe'}]; 85 | 86 | it('should clear out our previous attributes, and add new ones', function(){ 87 | this.cast.data(docs, 'name'); 88 | this.cast.reset([{name: 'albert'}, {name: 'roger'}], 'name'); 89 | var json = this.cast.toJSON(); 90 | assert(json.length === 2); 91 | assert(!this.cast.collection.get('ben')); 92 | assert(json[0].name === 'albert'); 93 | assert(json[1].name === 'roger'); 94 | }); 95 | }); 96 | 97 | describe('#add', function(){ 98 | 99 | it('should add a value to an empty cast collection', function(){ 100 | this.cast.add({name: 'ben'}, 'name'); 101 | assert(this.cast.toJSON()[0].name === 'ben'); 102 | this.cast.add({name: 'kit'}, 'name'); 103 | assert(this.cast.toJSON().length === 2); 104 | assert(this.cast.toJSON()[1].name === 'kit'); 105 | }); 106 | 107 | }); 108 | 109 | // better tests here... 110 | describe('#justify', function(){ 111 | var docs = [{name: 'ben', age: 28}, {name: 'kit'}, {name: 'joe'}]; 112 | 113 | it('should set a left and top attribute', function(){ 114 | this.cast.data(docs, 'name'); 115 | this.cast.justify(50, 50, 20, 20); 116 | var json = this.cast.toJSON(); 117 | assert(json); 118 | for (var i = 0; i < json.length; i++){ 119 | assert(typeof json[i].left !== 'undefined'); 120 | assert(json[i].top); 121 | } 122 | }); 123 | 124 | it('should set the first to 0, 20; last to 450, 20', function(){ 125 | this.cast.data(docs, 'name'); 126 | this.cast.justify(50, 50, 20, 20); 127 | var json = this.cast.toJSON(); 128 | assert(json[0].left === 0); 129 | assert(json[0].top === 20); 130 | }); 131 | }); 132 | 133 | // better tests here... 134 | describe('#center', function(){ 135 | var docs = [{name: 'ben', age: 28}, {name: 'kit'}, {name: 'joe'}]; 136 | 137 | it('should set a left and top attribute', function(){ 138 | this.cast.data(docs, 'name'); 139 | this.cast.center(50, 50, 20, 20); 140 | var json = this.cast.toJSON(); 141 | assert(json); 142 | for (var i = 0; i < json.length; i++){ 143 | assert(json[i].left); 144 | assert(json[i].top); 145 | } 146 | 147 | }); 148 | }); 149 | 150 | // better tests here... 151 | describe('#dynamic', function(){ 152 | var docs = [{name: 'ben', age: 28}, {name: 'kit'}, {name: 'joe'}]; 153 | 154 | it('should set a left, top, width, and height', function(){ 155 | this.cast.data(docs, 'name'); 156 | this.cast.dynamic(50, 50, 20, 20); 157 | var json = this.cast.toJSON(); 158 | assert(json); 159 | for (var i = 0; i < json.length; i++){ 160 | assert(json[i].left); 161 | assert(json[i].top); 162 | assert(json[i].width); 163 | assert(json[i].top); 164 | } 165 | 166 | }); 167 | 168 | 169 | }); 170 | 171 | describe('#draw', function(){ 172 | var docs = [{name: 'ben', age: 28}, {name: 'kit'}, {name: 'joe'}]; 173 | 174 | beforeEach(function(){ 175 | this.cast = cast(container) 176 | .data(docs, 'name') 177 | .justify(50, 50, 20, 20) 178 | .draw(testTemplate); 179 | }); 180 | 181 | afterEach(function(){ 182 | delete this.cast; 183 | }); 184 | 185 | it('should attach itself to the container', function(){ 186 | assert(container.children[0].children.length === 3); 187 | }); 188 | 189 | it('should render using the supplied template', function(){ 190 | assert($(container.children[0].children[0]).find('p').text() === 'ben'); 191 | assert($(container.children[0].children[1]).find('p').text() === 'kit'); 192 | }); 193 | 194 | it('should remove a view when associated doc is removed', function(done){ 195 | this.cast.data([{name: 'ben'}], 'name'); 196 | 197 | setTimeout(function(){ 198 | assert($('.Cast-item').length === 1); 199 | assert($('.Cast-item').find('p').text() === 'ben'); 200 | done(); 201 | }, 500); 202 | }); 203 | 204 | it('should add a view when new doc is added', function(){ 205 | this.cast.data([{name: 'zoey'}], 'name'); 206 | assert($('.Cast-item').length === 4); 207 | }); 208 | 209 | 210 | }); 211 | 212 | }); 213 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Module dependencies 3 | */ 4 | 5 | var Emitter = require('emitter'); 6 | var Dict = require('ordered-dictionary'); 7 | var fastdom = require('fastdom'); 8 | var type = require('type'); 9 | var Block = require('./block'); 10 | var empty = require('empty'); 11 | 12 | module.exports = Cast; 13 | 14 | /** 15 | * Cast 16 | * @param {Element} wrapper 17 | */ 18 | 19 | function Cast(wrapper){ 20 | if (!(this instanceof Cast)) return new Cast(wrapper); 21 | this.wrapper = wrapper; 22 | this.wrapperWidth = this.wrapper.clientWidth; 23 | this.el = document.createElement('div'); 24 | this.el.className = 'Cast'; 25 | this.collection = new Dict(); 26 | } 27 | 28 | Emitter(Cast.prototype); 29 | 30 | /** 31 | * Supply our Cast with a collection of documents. If a unique identifier is 32 | * supplied, then we can efficiently update, add, and remove models on subsequent 33 | * .data() calls. If we don't have a uid, then reset collection. 34 | * 35 | * @param {Object} attr 36 | * @param {Function|String} fn unique id 37 | * @return {Cast} 38 | */ 39 | 40 | Cast.prototype.data = function(docs, fn) { 41 | if (!fn) throw new Error('Unique id required'); 42 | 43 | var len = this.collection.length(); 44 | var keys = []; 45 | var isFn = (type(fn) === 'function'); 46 | 47 | // Either update our model, or make a new one for each docsibute 48 | // that we have passed. 49 | for ( var i = 0, l = docs.length; i < l; i++ ){ 50 | var key = isFn ? fn(docs[i]) : docs[i][fn]; 51 | var model = this.collection.get(key); 52 | keys.push(key); 53 | if (model) { 54 | model.set(docs[i]); 55 | } else { 56 | var block = new Block(docs[i], this, this.template); 57 | this.renderNew(block); 58 | this.collection.set(key, block); 59 | } 60 | } 61 | 62 | // If running .data() multiple times, remove any attributes 63 | // that were not contained in subsequent calls. This is fugly. Yoiks. 64 | if (len) { 65 | var toRemove = []; 66 | this.collection.forEach(function(key, model, i){ 67 | if (keys.indexOf(key) === -1 ) toRemove.push(key); 68 | }); 69 | for (var x = 0, length = toRemove.length; x < length; x++){ 70 | this.removeOld(toRemove[x]); 71 | this.collection.remove(toRemove[x]); 72 | } 73 | } 74 | return this; 75 | }; 76 | 77 | /** 78 | * return the JSON of our Cast. 79 | * 80 | * @return {Array} 81 | */ 82 | 83 | Cast.prototype.toJSON = function(){ 84 | var json = []; 85 | this.collection.forEach(function(key, value){ 86 | json.push(value.toJSON()); 87 | }); 88 | return json; 89 | }; 90 | 91 | 92 | /** 93 | * Reset Cast with given docs. 94 | * 95 | * @param {Array|Object} attr 96 | * @param {Function|String} fn 97 | * @return {Cast} 98 | */ 99 | 100 | Cast.prototype.reset = function(docs, fn){ 101 | this.collection.clear(); 102 | this.add(docs, fn); 103 | return this; 104 | }; 105 | 106 | /** 107 | * Add item with optional uid. 108 | * 109 | * @param {Object|Array} attr 110 | * @param {Function|String} fn 111 | */ 112 | 113 | Cast.prototype.add = function(docs, fn){ 114 | if (type(docs) !== 'array') docs = [docs]; 115 | if (!fn) throw new Error('Unique id required'); 116 | var isFn = type(fn) === 'function'; 117 | for (var i = 0, l = docs.length; i < l; i++){ 118 | var key = isFn ? fn(docs[i]) : docs[i][fn]; 119 | var val = new Block(docs[i], this); 120 | this.collection.set(key, val); 121 | } 122 | return this; 123 | }; 124 | 125 | /** 126 | * Remove item given a unique id. 127 | * 128 | * @param {String} key 129 | * @return {Cast} 130 | */ 131 | 132 | Cast.prototype.remove = function(uid){ 133 | this.collection.remove(uid); 134 | return this; 135 | }; 136 | 137 | 138 | 139 | /** 140 | * Remove any left/right padding from the container. 141 | * 142 | * @param {Number} w width 143 | * @param {Number} h height 144 | * @param {Number} pw padding-width 145 | * @param {Number} ph padding-height 146 | * @return {Cast} 147 | */ 148 | 149 | Cast.prototype.justify = function(w, h, pw, ph){ 150 | var cw = this.wrapperWidth; 151 | 152 | var bpr = Math.floor((cw - (pw * 2)) / (w + pw)); 153 | 154 | var getLeft = function(c, r) { 155 | if (c === 0) return 0; 156 | if (c === bpr - 1) return cw - w; 157 | var remainingSpace = cw - (w * bpr); 158 | var padding = remainingSpace / (bpr - 1); 159 | return w + (c * padding) + ((c - 1) * w); 160 | }; 161 | 162 | this.collection.forEach(function(key, block, i){ 163 | var r = Math.floor(i / bpr); 164 | var c = i % bpr; 165 | var left = getLeft(c, r); 166 | var top = ((r * h) + (r + 1) * ph); 167 | 168 | block.position({ 169 | 'left': left, 170 | 'top': top, 171 | 'width': w, 172 | 'height': h 173 | }); 174 | }); 175 | 176 | var t = this.collection.length(); 177 | var wrapperHeight = Math.ceil(t / bpr) * (h + ph) + ph; 178 | this.setHeight(wrapperHeight); 179 | return this; 180 | }; 181 | 182 | 183 | /** 184 | * The left and right container padding is the 185 | * dynamic property here. 186 | * 187 | * @param {Number} w width 188 | * @param {Number} h height 189 | * @param {Number} pw padding-width 190 | * @param {Number} ph padding-height 191 | * @return {Cast} 192 | */ 193 | 194 | Cast.prototype.center = function(w, h, pw, ph){ 195 | var cw = this.wrapperWidth; 196 | var bpr = Math.floor(cw/(w + pw)); 197 | var mx = (cw - (bpr * w) - (bpr - 1) * pw) * 0.5; 198 | 199 | this.collection.forEach(function(key, block, i){ 200 | var r = Math.floor(i / bpr); 201 | var c = i % bpr; 202 | var left = mx + (c * (w + pw)); 203 | var top = (r * h) + (r + 1) * ph; 204 | 205 | block.position({ 206 | 'left': left, 207 | 'top': top, 208 | 'width': w, 209 | 'height': h 210 | }); 211 | }); 212 | 213 | var t = this.collection.length(); 214 | var wrapperHeight = Math.ceil(t / bpr) * (h + ph) + ph; 215 | this.setHeight(wrapperHeight); 216 | return this; 217 | }; 218 | 219 | 220 | /** 221 | * Keep a constant padding-width & padding-height with 222 | * a dynamic cast-item width and height. 223 | * 224 | * @param {Number} w width 225 | * @param {Number} h height 226 | * @param {Number} pw padding-width 227 | * @param {Number} ph padding-height 228 | * @return {Cast} 229 | */ 230 | 231 | Cast.prototype.dynamic = function(w, h, pw, ph){ 232 | var cw = this.wrapperWidth; 233 | var bpr = Math.floor(cw / ( w + pw )); 234 | var newWidth = (cw - (bpr * pw)) / bpr; 235 | var newHeight = ( newWidth / w ) * h; 236 | var mx = (cw - (bpr * newWidth) - (bpr - 1) * pw) * 0.5; 237 | 238 | // XXX This logic is the same as center(). Should we make 239 | // this a shared function? 240 | this.collection.forEach(function(id, block, i){ 241 | var r = Math.floor(i / bpr); 242 | var c = i % bpr; 243 | var left = mx + (c * (newWidth + pw)); 244 | var top = (r * newHeight) + (r + 1) * ph; 245 | 246 | block.position({ 247 | 'width': newWidth, 248 | 'left': left, 249 | 'top': top, 250 | 'height': newHeight 251 | }); 252 | }); 253 | 254 | var t = this.collection.length(); 255 | var wrapperHeight = Math.ceil(t / bpr) * (newHeight + ph) + ph; 256 | this.setHeight(wrapperHeight); 257 | return this; 258 | }; 259 | 260 | /** 261 | * List layout 262 | * 263 | * @param {Number} h height 264 | * @param {Number} ph padding-height 265 | * @return {Cast} 266 | */ 267 | 268 | Cast.prototype.list = function(h, ph){ 269 | 270 | this.collection.forEach(function(id, block, i){ 271 | var top = (h + ph) * i; 272 | block.position({ 273 | 'left': 0, 274 | 'top': top, 275 | 'height': h 276 | }); 277 | }); 278 | 279 | this.setHeight(this.collection.length() * (h + ph)); 280 | return this; 281 | }; 282 | 283 | /** 284 | * Sort data by field 285 | * 286 | * @param {String} field 287 | * @param {Number} invert 288 | * @return {Cast} 289 | */ 290 | 291 | Cast.prototype.sortBy = function(field, invert){ 292 | invert = invert || 1; 293 | 294 | this.collection.sort(function(left, right){ 295 | var leftVal = left.attr[field]; 296 | var rightVal = right.attr[field]; 297 | if (leftVal < rightVal) return (-1 * invert); 298 | if (leftVal > rightVal) return (1 * invert); 299 | return 0; 300 | }); 301 | 302 | return this; 303 | }; 304 | 305 | /** 306 | * render new block 307 | * @param {Block} block 308 | */ 309 | 310 | Cast.prototype.renderNew = function(block){ 311 | this.emit('render', block) 312 | fastdom.write(function(){ 313 | this.el.appendChild(block.el); 314 | }.bind(this)); 315 | fastdom.defer(block.show.bind(block)); 316 | }; 317 | 318 | /** 319 | * render function 320 | * @param {Function} fn 321 | * @return {Cast} 322 | */ 323 | 324 | Cast.prototype.render = function(fn){ 325 | this.on('render', function(block){ 326 | if (fn) fn(block.attr, block.el, block); 327 | }.bind(this)); 328 | return this; 329 | }; 330 | 331 | /** 332 | * remove old block 333 | * @param {Block} block 334 | */ 335 | 336 | Cast.prototype.removeOld = function(id){ 337 | var block = this.collection.get(id); 338 | fastdom.write(function(){ 339 | block.hide(function(){ block.remove(); }); 340 | }); 341 | }; 342 | 343 | /** 344 | * Set our cast.js height 345 | * @param {Number} height 346 | */ 347 | 348 | Cast.prototype.setHeight = function(height){ 349 | fastdom.write(function(){ 350 | this.el.style.height = height + 'px'; 351 | }.bind(this)); 352 | }; 353 | 354 | 355 | /** 356 | * Draw function 357 | * @param {Function} template 358 | * @return {Cast} 359 | */ 360 | 361 | Cast.prototype.draw = function(template){ 362 | this.template = template; 363 | fastdom.write(function(){ 364 | empty(this.wrapper); 365 | this.wrapper.appendChild(this.el); 366 | }.bind(this)); 367 | return this; 368 | }; 369 | -------------------------------------------------------------------------------- /dist/cast.js: -------------------------------------------------------------------------------- 1 | ;(function(){ 2 | 3 | /** 4 | * Require the given path. 5 | * 6 | * @param {String} path 7 | * @return {Object} exports 8 | * @api public 9 | */ 10 | 11 | function require(path, parent, orig) { 12 | var resolved = require.resolve(path); 13 | 14 | // lookup failed 15 | if (null == resolved) { 16 | orig = orig || path; 17 | parent = parent || 'root'; 18 | var err = new Error('Failed to require "' + orig + '" from "' + parent + '"'); 19 | err.path = orig; 20 | err.parent = parent; 21 | err.require = true; 22 | throw err; 23 | } 24 | 25 | var module = require.modules[resolved]; 26 | 27 | // perform real require() 28 | // by invoking the module's 29 | // registered function 30 | if (!module._resolving && !module.exports) { 31 | var mod = {}; 32 | mod.exports = {}; 33 | mod.client = mod.component = true; 34 | module._resolving = true; 35 | module.call(this, mod.exports, require.relative(resolved), mod); 36 | delete module._resolving; 37 | module.exports = mod.exports; 38 | } 39 | 40 | return module.exports; 41 | } 42 | 43 | /** 44 | * Registered modules. 45 | */ 46 | 47 | require.modules = {}; 48 | 49 | /** 50 | * Registered aliases. 51 | */ 52 | 53 | require.aliases = {}; 54 | 55 | /** 56 | * Resolve `path`. 57 | * 58 | * Lookup: 59 | * 60 | * - PATH/index.js 61 | * - PATH.js 62 | * - PATH 63 | * 64 | * @param {String} path 65 | * @return {String} path or null 66 | * @api private 67 | */ 68 | 69 | require.resolve = function(path) { 70 | if (path.charAt(0) === '/') path = path.slice(1); 71 | 72 | var paths = [ 73 | path, 74 | path + '.js', 75 | path + '.json', 76 | path + '/index.js', 77 | path + '/index.json' 78 | ]; 79 | 80 | for (var i = 0; i < paths.length; i++) { 81 | var path = paths[i]; 82 | if (require.modules.hasOwnProperty(path)) return path; 83 | if (require.aliases.hasOwnProperty(path)) return require.aliases[path]; 84 | } 85 | }; 86 | 87 | /** 88 | * Normalize `path` relative to the current path. 89 | * 90 | * @param {String} curr 91 | * @param {String} path 92 | * @return {String} 93 | * @api private 94 | */ 95 | 96 | require.normalize = function(curr, path) { 97 | var segs = []; 98 | 99 | if ('.' != path.charAt(0)) return path; 100 | 101 | curr = curr.split('/'); 102 | path = path.split('/'); 103 | 104 | for (var i = 0; i < path.length; ++i) { 105 | if ('..' == path[i]) { 106 | curr.pop(); 107 | } else if ('.' != path[i] && '' != path[i]) { 108 | segs.push(path[i]); 109 | } 110 | } 111 | 112 | return curr.concat(segs).join('/'); 113 | }; 114 | 115 | /** 116 | * Register module at `path` with callback `definition`. 117 | * 118 | * @param {String} path 119 | * @param {Function} definition 120 | * @api private 121 | */ 122 | 123 | require.register = function(path, definition) { 124 | require.modules[path] = definition; 125 | }; 126 | 127 | /** 128 | * Alias a module definition. 129 | * 130 | * @param {String} from 131 | * @param {String} to 132 | * @api private 133 | */ 134 | 135 | require.alias = function(from, to) { 136 | if (!require.modules.hasOwnProperty(from)) { 137 | throw new Error('Failed to alias "' + from + '", it does not exist'); 138 | } 139 | require.aliases[to] = from; 140 | }; 141 | 142 | /** 143 | * Return a require function relative to the `parent` path. 144 | * 145 | * @param {String} parent 146 | * @return {Function} 147 | * @api private 148 | */ 149 | 150 | require.relative = function(parent) { 151 | var p = require.normalize(parent, '..'); 152 | 153 | /** 154 | * lastIndexOf helper. 155 | */ 156 | 157 | function lastIndexOf(arr, obj) { 158 | var i = arr.length; 159 | while (i--) { 160 | if (arr[i] === obj) return i; 161 | } 162 | return -1; 163 | } 164 | 165 | /** 166 | * The relative require() itself. 167 | */ 168 | 169 | function localRequire(path) { 170 | var resolved = localRequire.resolve(path); 171 | return require(resolved, parent, path); 172 | } 173 | 174 | /** 175 | * Resolve relative to the parent. 176 | */ 177 | 178 | localRequire.resolve = function(path) { 179 | var c = path.charAt(0); 180 | if ('/' == c) return path.slice(1); 181 | if ('.' == c) return require.normalize(p, path); 182 | 183 | // resolve deps by returning 184 | // the dep in the nearest "deps" 185 | // directory 186 | var segs = parent.split('/'); 187 | var i = lastIndexOf(segs, 'deps') + 1; 188 | if (!i) i = 0; 189 | path = segs.slice(0, i + 1).join('/') + '/deps/' + path; 190 | return path; 191 | }; 192 | 193 | /** 194 | * Check if module is defined at `path`. 195 | */ 196 | 197 | localRequire.exists = function(path) { 198 | return require.modules.hasOwnProperty(localRequire.resolve(path)); 199 | }; 200 | 201 | return localRequire; 202 | }; 203 | require.register("component-emitter/index.js", function(exports, require, module){ 204 | 205 | /** 206 | * Expose `Emitter`. 207 | */ 208 | 209 | module.exports = Emitter; 210 | 211 | /** 212 | * Initialize a new `Emitter`. 213 | * 214 | * @api public 215 | */ 216 | 217 | function Emitter(obj) { 218 | if (obj) return mixin(obj); 219 | }; 220 | 221 | /** 222 | * Mixin the emitter properties. 223 | * 224 | * @param {Object} obj 225 | * @return {Object} 226 | * @api private 227 | */ 228 | 229 | function mixin(obj) { 230 | for (var key in Emitter.prototype) { 231 | obj[key] = Emitter.prototype[key]; 232 | } 233 | return obj; 234 | } 235 | 236 | /** 237 | * Listen on the given `event` with `fn`. 238 | * 239 | * @param {String} event 240 | * @param {Function} fn 241 | * @return {Emitter} 242 | * @api public 243 | */ 244 | 245 | Emitter.prototype.on = 246 | Emitter.prototype.addEventListener = function(event, fn){ 247 | this._callbacks = this._callbacks || {}; 248 | (this._callbacks[event] = this._callbacks[event] || []) 249 | .push(fn); 250 | return this; 251 | }; 252 | 253 | /** 254 | * Adds an `event` listener that will be invoked a single 255 | * time then automatically removed. 256 | * 257 | * @param {String} event 258 | * @param {Function} fn 259 | * @return {Emitter} 260 | * @api public 261 | */ 262 | 263 | Emitter.prototype.once = function(event, fn){ 264 | var self = this; 265 | this._callbacks = this._callbacks || {}; 266 | 267 | function on() { 268 | self.off(event, on); 269 | fn.apply(this, arguments); 270 | } 271 | 272 | on.fn = fn; 273 | this.on(event, on); 274 | return this; 275 | }; 276 | 277 | /** 278 | * Remove the given callback for `event` or all 279 | * registered callbacks. 280 | * 281 | * @param {String} event 282 | * @param {Function} fn 283 | * @return {Emitter} 284 | * @api public 285 | */ 286 | 287 | Emitter.prototype.off = 288 | Emitter.prototype.removeListener = 289 | Emitter.prototype.removeAllListeners = 290 | Emitter.prototype.removeEventListener = function(event, fn){ 291 | this._callbacks = this._callbacks || {}; 292 | 293 | // all 294 | if (0 == arguments.length) { 295 | this._callbacks = {}; 296 | return this; 297 | } 298 | 299 | // specific event 300 | var callbacks = this._callbacks[event]; 301 | if (!callbacks) return this; 302 | 303 | // remove all handlers 304 | if (1 == arguments.length) { 305 | delete this._callbacks[event]; 306 | return this; 307 | } 308 | 309 | // remove specific handler 310 | var cb; 311 | for (var i = 0; i < callbacks.length; i++) { 312 | cb = callbacks[i]; 313 | if (cb === fn || cb.fn === fn) { 314 | callbacks.splice(i, 1); 315 | break; 316 | } 317 | } 318 | return this; 319 | }; 320 | 321 | /** 322 | * Emit `event` with the given args. 323 | * 324 | * @param {String} event 325 | * @param {Mixed} ... 326 | * @return {Emitter} 327 | */ 328 | 329 | Emitter.prototype.emit = function(event){ 330 | this._callbacks = this._callbacks || {}; 331 | var args = [].slice.call(arguments, 1) 332 | , callbacks = this._callbacks[event]; 333 | 334 | if (callbacks) { 335 | callbacks = callbacks.slice(0); 336 | for (var i = 0, len = callbacks.length; i < len; ++i) { 337 | callbacks[i].apply(this, args); 338 | } 339 | } 340 | 341 | return this; 342 | }; 343 | 344 | /** 345 | * Return array of callbacks for `event`. 346 | * 347 | * @param {String} event 348 | * @return {Array} 349 | * @api public 350 | */ 351 | 352 | Emitter.prototype.listeners = function(event){ 353 | this._callbacks = this._callbacks || {}; 354 | return this._callbacks[event] || []; 355 | }; 356 | 357 | /** 358 | * Check if this emitter has `event` handlers. 359 | * 360 | * @param {String} event 361 | * @return {Boolean} 362 | * @api public 363 | */ 364 | 365 | Emitter.prototype.hasListeners = function(event){ 366 | return !! this.listeners(event).length; 367 | }; 368 | 369 | }); 370 | require.register("component-clone/index.js", function(exports, require, module){ 371 | 372 | /** 373 | * Module dependencies. 374 | */ 375 | 376 | var type; 377 | 378 | try { 379 | type = require('type'); 380 | } catch(e){ 381 | type = require('type-component'); 382 | } 383 | 384 | /** 385 | * Module exports. 386 | */ 387 | 388 | module.exports = clone; 389 | 390 | /** 391 | * Clones objects. 392 | * 393 | * @param {Mixed} any object 394 | * @api public 395 | */ 396 | 397 | function clone(obj){ 398 | switch (type(obj)) { 399 | case 'object': 400 | var copy = {}; 401 | for (var key in obj) { 402 | if (obj.hasOwnProperty(key)) { 403 | copy[key] = clone(obj[key]); 404 | } 405 | } 406 | return copy; 407 | 408 | case 'array': 409 | var copy = new Array(obj.length); 410 | for (var i = 0, l = obj.length; i < l; i++) { 411 | copy[i] = clone(obj[i]); 412 | } 413 | return copy; 414 | 415 | case 'regexp': 416 | // from millermedeiros/amd-utils - MIT 417 | var flags = ''; 418 | flags += obj.multiline ? 'm' : ''; 419 | flags += obj.global ? 'g' : ''; 420 | flags += obj.ignoreCase ? 'i' : ''; 421 | return new RegExp(obj.source, flags); 422 | 423 | case 'date': 424 | return new Date(obj.getTime()); 425 | 426 | default: // string, number, boolean, … 427 | return obj; 428 | } 429 | } 430 | 431 | }); 432 | require.register("component-type/index.js", function(exports, require, module){ 433 | 434 | /** 435 | * toString ref. 436 | */ 437 | 438 | var toString = Object.prototype.toString; 439 | 440 | /** 441 | * Return the type of `val`. 442 | * 443 | * @param {Mixed} val 444 | * @return {String} 445 | * @api public 446 | */ 447 | 448 | module.exports = function(val){ 449 | switch (toString.call(val)) { 450 | case '[object Function]': return 'function'; 451 | case '[object Date]': return 'date'; 452 | case '[object RegExp]': return 'regexp'; 453 | case '[object Arguments]': return 'arguments'; 454 | case '[object Array]': return 'array'; 455 | case '[object String]': return 'string'; 456 | } 457 | 458 | if (val === null) return 'null'; 459 | if (val === undefined) return 'undefined'; 460 | if (val && val.nodeType === 1) return 'element'; 461 | if (val === Object(val)) return 'object'; 462 | 463 | return typeof val; 464 | }; 465 | 466 | }); 467 | require.register("component-indexof/index.js", function(exports, require, module){ 468 | module.exports = function(arr, obj){ 469 | if (arr.indexOf) return arr.indexOf(obj); 470 | for (var i = 0; i < arr.length; ++i) { 471 | if (arr[i] === obj) return i; 472 | } 473 | return -1; 474 | }; 475 | }); 476 | require.register("bmcmahen-ordered-dictionary/index.js", function(exports, require, module){ 477 | // Modules 478 | var indexOf = require('indexof'), 479 | Emitter = require('emitter'); 480 | 481 | var OrderedDictonary = function(attr){ 482 | if (!(this instanceof OrderedDictonary)) 483 | return new OrderedDictonary(attr); 484 | 485 | this.map = {}; 486 | this.array = []; 487 | 488 | if (typeof attr === 'object') 489 | this.set(attr); 490 | }; 491 | 492 | module.exports = OrderedDictonary; 493 | 494 | Emitter(OrderedDictonary.prototype); 495 | 496 | // Allow both 'key', 'value' and {key: value} style arguments. 497 | OrderedDictonary.prototype.set = function(key, val){ 498 | var attr, attrs; 499 | if (typeof key === 'object') attrs = key; 500 | else (attrs = {})[key] = val; 501 | for (attr in attrs) { 502 | if (attr in this.map) this.map[attr] = attrs[attr]; 503 | else { 504 | this.array.push(attr); 505 | this.map[attr] = attrs[attr]; 506 | this.emit('enter', attrs[attr]); 507 | } 508 | } 509 | return this; 510 | }; 511 | 512 | OrderedDictonary.prototype.remove = function(key) { 513 | var index = indexOf(this.array, key); 514 | if (index === -1) throw new Error('Key doesnt exist'); 515 | this.emit('exit', this.map[key]); 516 | this.array.splice(index, 1); 517 | delete this.map[key]; 518 | }; 519 | 520 | OrderedDictonary.prototype.get = function(key){ 521 | return this.map[key]; 522 | }; 523 | 524 | OrderedDictonary.prototype.at = function(index){ 525 | return this.map[this.array[index]]; 526 | }; 527 | 528 | OrderedDictonary.prototype.length = function(){ 529 | return this.array.length; 530 | }; 531 | 532 | // Iterates through our array, providing the key, value, 533 | // and index of the field. 534 | OrderedDictonary.prototype.forEach = function(fn){ 535 | var key, value; 536 | for (var i = 0, len = this.array.length; i < len; i++) { 537 | key = this.array[i]; 538 | value = this.map[key]; 539 | fn(key, value, i); 540 | } 541 | return this; 542 | }; 543 | 544 | OrderedDictonary.prototype.sort = function(fn){ 545 | var _this = this; 546 | this.array.sort(function(left, right){ 547 | return fn(_this.map[left], _this.map[right]); 548 | }); 549 | return this; 550 | }; 551 | 552 | OrderedDictonary.prototype.clear = function(){ 553 | this.map = {}; 554 | this.array = []; 555 | return this; 556 | }; 557 | }); 558 | require.register("component-has-translate3d/index.js", function(exports, require, module){ 559 | 560 | var prop = require('transform-property'); 561 | // IE8<= doesn't have `getComputedStyle` 562 | if (!prop || !window.getComputedStyle) return module.exports = false; 563 | 564 | var map = { 565 | webkitTransform: '-webkit-transform', 566 | OTransform: '-o-transform', 567 | msTransform: '-ms-transform', 568 | MozTransform: '-moz-transform', 569 | transform: 'transform' 570 | }; 571 | 572 | // from: https://gist.github.com/lorenzopolidori/3794226 573 | var el = document.createElement('div'); 574 | el.style[prop] = 'translate3d(1px,1px,1px)'; 575 | document.body.insertBefore(el, null); 576 | var val = getComputedStyle(el).getPropertyValue(map[prop]); 577 | document.body.removeChild(el); 578 | module.exports = null != val && val.length && 'none' != val; 579 | 580 | }); 581 | require.register("component-transform-property/index.js", function(exports, require, module){ 582 | 583 | var styles = [ 584 | 'webkitTransform', 585 | 'MozTransform', 586 | 'msTransform', 587 | 'OTransform', 588 | 'transform' 589 | ]; 590 | 591 | var el = document.createElement('p'); 592 | var style; 593 | 594 | for (var i = 0; i < styles.length; i++) { 595 | style = styles[i]; 596 | if (null != el.style[style]) { 597 | module.exports = style; 598 | break; 599 | } 600 | } 601 | 602 | }); 603 | require.register("component-translate/index.js", function(exports, require, module){ 604 | 605 | /** 606 | * Module dependencies. 607 | */ 608 | 609 | var transform = require('transform-property'); 610 | var has3d = require('has-translate3d'); 611 | 612 | /** 613 | * Expose `translate`. 614 | */ 615 | 616 | module.exports = translate; 617 | 618 | /** 619 | * Translate `el` by `(x, y)`. 620 | * 621 | * @param {Element} el 622 | * @param {Number} x 623 | * @param {Number} y 624 | * @api public 625 | */ 626 | 627 | function translate(el, x, y){ 628 | if (transform) { 629 | if (has3d) { 630 | el.style[transform] = 'translate3d(' + x + 'px,' + y + 'px, 0)'; 631 | } else { 632 | el.style[transform] = 'translate(' + x + 'px,' + y + 'px)'; 633 | } 634 | } else { 635 | el.style.left = x + 'px'; 636 | el.style.top = y + 'px'; 637 | } 638 | }; 639 | 640 | }); 641 | require.register("wilsonpage-fastdom/index.js", function(exports, require, module){ 642 | /** 643 | * FastDom 644 | * 645 | * Eliminates layout thrashing 646 | * by batching DOM read/write 647 | * interactions. 648 | * 649 | * @author Wilson Page 650 | */ 651 | 652 | ;(function(fastdom){ 653 | 654 | 'use strict'; 655 | 656 | // Normalize rAF 657 | var raf = window.requestAnimationFrame 658 | || window.webkitRequestAnimationFrame 659 | || window.mozRequestAnimationFrame 660 | || window.msRequestAnimationFrame 661 | || function(cb) { return window.setTimeout(cb, 1000 / 60); }; 662 | 663 | // Normalize cAF 664 | var caf = window.cancelAnimationFrame 665 | || window.cancelRequestAnimationFrame 666 | || window.mozCancelAnimationFrame 667 | || window.mozCancelRequestAnimationFrame 668 | || window.webkitCancelAnimationFrame 669 | || window.webkitCancelRequestAnimationFrame 670 | || window.msCancelAnimationFrame 671 | || window.msCancelRequestAnimationFrame 672 | || function(id) { window.clearTimeout(id); }; 673 | 674 | /** 675 | * Creates a fresh 676 | * FastDom instance. 677 | * 678 | * @constructor 679 | */ 680 | function FastDom() { 681 | this.frames = []; 682 | this.lastId = 0; 683 | 684 | // Placing the rAF method 685 | // on the instance allows 686 | // us to replace it with 687 | // a stub for testing. 688 | this.raf = raf; 689 | 690 | this.batch = { 691 | hash: {}, 692 | read: [], 693 | write: [], 694 | mode: null 695 | }; 696 | } 697 | 698 | /** 699 | * Adds a job to the 700 | * read batch and schedules 701 | * a new frame if need be. 702 | * 703 | * @param {Function} fn 704 | * @api public 705 | */ 706 | FastDom.prototype.read = function(fn, ctx) { 707 | var job = this.add('read', fn, ctx); 708 | var id = job.id; 709 | 710 | // Add this job to the read queue 711 | this.batch.read.push(job.id); 712 | 713 | // We should *not* schedule a new frame if: 714 | // 1. We're 'reading' 715 | // 2. A frame is already scheduled 716 | var doesntNeedFrame = this.batch.mode === 'reading' 717 | || this.batch.scheduled; 718 | 719 | // If a frame isn't needed, return 720 | if (doesntNeedFrame) return id; 721 | 722 | // Schedule a new 723 | // frame, then return 724 | this.scheduleBatch(); 725 | return id; 726 | }; 727 | 728 | /** 729 | * Adds a job to the 730 | * write batch and schedules 731 | * a new frame if need be. 732 | * 733 | * @param {Function} fn 734 | * @api public 735 | */ 736 | FastDom.prototype.write = function(fn, ctx) { 737 | var job = this.add('write', fn, ctx); 738 | var mode = this.batch.mode; 739 | var id = job.id; 740 | 741 | // Push the job id into the queue 742 | this.batch.write.push(job.id); 743 | 744 | // We should *not* schedule a new frame if: 745 | // 1. We are 'writing' 746 | // 2. We are 'reading' 747 | // 3. A frame is already scheduled. 748 | var doesntNeedFrame = mode === 'writing' 749 | || mode === 'reading' 750 | || this.batch.scheduled; 751 | 752 | // If a frame isn't needed, return 753 | if (doesntNeedFrame) return id; 754 | 755 | // Schedule a new 756 | // frame, then return 757 | this.scheduleBatch(); 758 | return id; 759 | }; 760 | 761 | /** 762 | * Defers the given job 763 | * by the number of frames 764 | * specified. 765 | * 766 | * If no frames are given 767 | * then the job is run in 768 | * the next free frame. 769 | * 770 | * @param {Number} frame 771 | * @param {Function} fn 772 | * @api public 773 | */ 774 | FastDom.prototype.defer = function(frame, fn, ctx) { 775 | 776 | // Accepts two arguments 777 | if (typeof frame === 'function') { 778 | ctx = fn; 779 | fn = frame; 780 | frame = 1; 781 | } 782 | 783 | var self = this; 784 | var index = frame - 1; 785 | 786 | return this.schedule(index, function() { 787 | self.run({ 788 | fn: fn, 789 | ctx: ctx 790 | }); 791 | }); 792 | }; 793 | 794 | /** 795 | * Clears a scheduled 'read', 796 | * 'write' or 'defer' job. 797 | * 798 | * @param {Number} id 799 | * @api public 800 | */ 801 | FastDom.prototype.clear = function(id) { 802 | 803 | // Defer jobs are cleared differently 804 | if (typeof id === 'function') { 805 | return this.clearFrame(id); 806 | } 807 | 808 | var job = this.batch.hash[id]; 809 | if (!job) return; 810 | 811 | var list = this.batch[job.type]; 812 | var index = list.indexOf(id); 813 | 814 | // Clear references 815 | delete this.batch.hash[id]; 816 | if (~index) list.splice(index, 1); 817 | }; 818 | 819 | /** 820 | * Clears a scheduled frame. 821 | * 822 | * @param {Function} frame 823 | * @api private 824 | */ 825 | FastDom.prototype.clearFrame = function(frame) { 826 | var index = this.frames.indexOf(frame); 827 | if (~index) this.frames.splice(index, 1); 828 | }; 829 | 830 | /** 831 | * Schedules a new read/write 832 | * batch if one isn't pending. 833 | * 834 | * @api private 835 | */ 836 | FastDom.prototype.scheduleBatch = function() { 837 | var self = this; 838 | 839 | // Schedule batch for next frame 840 | this.schedule(0, function() { 841 | self.batch.scheduled = false; 842 | self.runBatch(); 843 | }); 844 | 845 | // Set flag to indicate 846 | // a frame has been scheduled 847 | this.batch.scheduled = true; 848 | }; 849 | 850 | /** 851 | * Generates a unique 852 | * id for a job. 853 | * 854 | * @return {Number} 855 | * @api private 856 | */ 857 | FastDom.prototype.uniqueId = function() { 858 | return ++this.lastId; 859 | }; 860 | 861 | /** 862 | * Calls each job in 863 | * the list passed. 864 | * 865 | * If a context has been 866 | * stored on the function 867 | * then it is used, else the 868 | * current `this` is used. 869 | * 870 | * @param {Array} list 871 | * @api private 872 | */ 873 | FastDom.prototype.flush = function(list) { 874 | var id; 875 | 876 | while (id = list.shift()) { 877 | this.run(this.batch.hash[id]); 878 | } 879 | }; 880 | 881 | /** 882 | * Runs any 'read' jobs followed 883 | * by any 'write' jobs. 884 | * 885 | * We run this inside a try catch 886 | * so that if any jobs error, we 887 | * are able to recover and continue 888 | * to flush the batch until it's empty. 889 | * 890 | * @api private 891 | */ 892 | FastDom.prototype.runBatch = function() { 893 | try { 894 | 895 | // Set the mode to 'reading', 896 | // then empty all read jobs 897 | this.batch.mode = 'reading'; 898 | this.flush(this.batch.read); 899 | 900 | // Set the mode to 'writing' 901 | // then empty all write jobs 902 | this.batch.mode = 'writing'; 903 | this.flush(this.batch.write); 904 | 905 | this.batch.mode = null; 906 | 907 | } catch (e) { 908 | this.runBatch(); 909 | throw e; 910 | } 911 | }; 912 | 913 | /** 914 | * Adds a new job to 915 | * the given batch. 916 | * 917 | * @param {Array} list 918 | * @param {Function} fn 919 | * @param {Object} ctx 920 | * @returns {Number} id 921 | * @api private 922 | */ 923 | FastDom.prototype.add = function(type, fn, ctx) { 924 | var id = this.uniqueId(); 925 | return this.batch.hash[id] = { 926 | id: id, 927 | fn: fn, 928 | ctx: ctx, 929 | type: type 930 | }; 931 | }; 932 | 933 | /** 934 | * Runs a given job. 935 | * 936 | * Applications using FastDom 937 | * have the options of setting 938 | * `fastdom.onError`. 939 | * 940 | * This will catch any 941 | * errors that may throw 942 | * inside callbacks, which 943 | * is useful as often DOM 944 | * nodes have been removed 945 | * since a job was scheduled. 946 | * 947 | * Example: 948 | * 949 | * fastdom.onError = function(e) { 950 | * // Runs when jobs error 951 | * }; 952 | * 953 | * @param {Object} job 954 | * @api private 955 | */ 956 | FastDom.prototype.run = function(job){ 957 | var ctx = job.ctx || this; 958 | var fn = job.fn; 959 | 960 | // Clear reference to the job 961 | delete this.batch.hash[job.id]; 962 | 963 | // If no `onError` handler 964 | // has been registered, just 965 | // run the job normally. 966 | if (!this.onError) { 967 | return fn.call(ctx); 968 | } 969 | 970 | // If an `onError` handler 971 | // has been registered, catch 972 | // errors that throw inside 973 | // callbacks, and run the 974 | // handler instead. 975 | try { fn.call(ctx); } catch (e) { 976 | this.onError(e); 977 | } 978 | }; 979 | 980 | /** 981 | * Starts a rAF loop 982 | * to empty the frame queue. 983 | * 984 | * @api private 985 | */ 986 | FastDom.prototype.loop = function() { 987 | var self = this; 988 | var raf = this.raf; 989 | 990 | // Don't start more than one loop 991 | if (this.looping) return; 992 | 993 | raf(function frame() { 994 | var fn = self.frames.shift(); 995 | 996 | // If no more frames, 997 | // stop looping 998 | if (!self.frames.length) { 999 | self.looping = false; 1000 | 1001 | // Otherwise, schedule the 1002 | // next frame 1003 | } else { 1004 | raf(frame); 1005 | } 1006 | 1007 | // Run the frame. Note that 1008 | // this may throw an error 1009 | // in user code, but all 1010 | // fastdom tasks are dealt 1011 | // with already so the code 1012 | // will continue to iterate 1013 | if (fn) fn(); 1014 | }); 1015 | 1016 | this.looping = true; 1017 | }; 1018 | 1019 | /** 1020 | * Adds a function to 1021 | * a specified index 1022 | * of the frame queue. 1023 | * 1024 | * @param {Number} index 1025 | * @param {Function} fn 1026 | * @return {Function} 1027 | */ 1028 | FastDom.prototype.schedule = function(index, fn) { 1029 | 1030 | // Make sure this slot 1031 | // hasn't already been 1032 | // taken. If it has, try 1033 | // re-scheduling for the next slot 1034 | if (this.frames[index]) { 1035 | return this.schedule(index + 1, fn); 1036 | } 1037 | 1038 | // Start the rAF 1039 | // loop to empty 1040 | // the frame queue 1041 | this.loop(); 1042 | 1043 | // Insert this function into 1044 | // the frames queue and return 1045 | return this.frames[index] = fn; 1046 | }; 1047 | 1048 | // We only ever want there to be 1049 | // one instance of FastDom in an app 1050 | fastdom = fastdom || new FastDom(); 1051 | 1052 | /** 1053 | * Expose 'fastdom' 1054 | */ 1055 | 1056 | if (typeof module !== 'undefined' && module.exports) { 1057 | module.exports = fastdom; 1058 | } else if (typeof define === 'function' && define.amd) { 1059 | define(function(){ return fastdom; }); 1060 | } else { 1061 | window['fastdom'] = fastdom; 1062 | } 1063 | 1064 | })(window.fastdom); 1065 | 1066 | }); 1067 | require.register("component-props/index.js", function(exports, require, module){ 1068 | /** 1069 | * Global Names 1070 | */ 1071 | 1072 | var globals = /\b(this|Array|Date|Object|Math|JSON)\b/g; 1073 | 1074 | /** 1075 | * Return immediate identifiers parsed from `str`. 1076 | * 1077 | * @param {String} str 1078 | * @param {String|Function} map function or prefix 1079 | * @return {Array} 1080 | * @api public 1081 | */ 1082 | 1083 | module.exports = function(str, fn){ 1084 | var p = unique(props(str)); 1085 | if (fn && 'string' == typeof fn) fn = prefixed(fn); 1086 | if (fn) return map(str, p, fn); 1087 | return p; 1088 | }; 1089 | 1090 | /** 1091 | * Return immediate identifiers in `str`. 1092 | * 1093 | * @param {String} str 1094 | * @return {Array} 1095 | * @api private 1096 | */ 1097 | 1098 | function props(str) { 1099 | return str 1100 | .replace(/\.\w+|\w+ *\(|"[^"]*"|'[^']*'|\/([^/]+)\//g, '') 1101 | .replace(globals, '') 1102 | .match(/[$a-zA-Z_]\w*/g) 1103 | || []; 1104 | } 1105 | 1106 | /** 1107 | * Return `str` with `props` mapped with `fn`. 1108 | * 1109 | * @param {String} str 1110 | * @param {Array} props 1111 | * @param {Function} fn 1112 | * @return {String} 1113 | * @api private 1114 | */ 1115 | 1116 | function map(str, props, fn) { 1117 | var re = /\.\w+|\w+ *\(|"[^"]*"|'[^']*'|\/([^/]+)\/|[a-zA-Z_]\w*/g; 1118 | return str.replace(re, function(_){ 1119 | if ('(' == _[_.length - 1]) return fn(_); 1120 | if (!~props.indexOf(_)) return _; 1121 | return fn(_); 1122 | }); 1123 | } 1124 | 1125 | /** 1126 | * Return unique array. 1127 | * 1128 | * @param {Array} arr 1129 | * @return {Array} 1130 | * @api private 1131 | */ 1132 | 1133 | function unique(arr) { 1134 | var ret = []; 1135 | 1136 | for (var i = 0; i < arr.length; i++) { 1137 | if (~ret.indexOf(arr[i])) continue; 1138 | ret.push(arr[i]); 1139 | } 1140 | 1141 | return ret; 1142 | } 1143 | 1144 | /** 1145 | * Map with prefix `str`. 1146 | */ 1147 | 1148 | function prefixed(str) { 1149 | return function(_){ 1150 | return str + _; 1151 | }; 1152 | } 1153 | 1154 | }); 1155 | require.register("component-to-function/index.js", function(exports, require, module){ 1156 | /** 1157 | * Module Dependencies 1158 | */ 1159 | 1160 | var expr = require('props'); 1161 | 1162 | /** 1163 | * Expose `toFunction()`. 1164 | */ 1165 | 1166 | module.exports = toFunction; 1167 | 1168 | /** 1169 | * Convert `obj` to a `Function`. 1170 | * 1171 | * @param {Mixed} obj 1172 | * @return {Function} 1173 | * @api private 1174 | */ 1175 | 1176 | function toFunction(obj) { 1177 | switch ({}.toString.call(obj)) { 1178 | case '[object Object]': 1179 | return objectToFunction(obj); 1180 | case '[object Function]': 1181 | return obj; 1182 | case '[object String]': 1183 | return stringToFunction(obj); 1184 | case '[object RegExp]': 1185 | return regexpToFunction(obj); 1186 | default: 1187 | return defaultToFunction(obj); 1188 | } 1189 | } 1190 | 1191 | /** 1192 | * Default to strict equality. 1193 | * 1194 | * @param {Mixed} val 1195 | * @return {Function} 1196 | * @api private 1197 | */ 1198 | 1199 | function defaultToFunction(val) { 1200 | return function(obj){ 1201 | return val === obj; 1202 | } 1203 | } 1204 | 1205 | /** 1206 | * Convert `re` to a function. 1207 | * 1208 | * @param {RegExp} re 1209 | * @return {Function} 1210 | * @api private 1211 | */ 1212 | 1213 | function regexpToFunction(re) { 1214 | return function(obj){ 1215 | return re.test(obj); 1216 | } 1217 | } 1218 | 1219 | /** 1220 | * Convert property `str` to a function. 1221 | * 1222 | * @param {String} str 1223 | * @return {Function} 1224 | * @api private 1225 | */ 1226 | 1227 | function stringToFunction(str) { 1228 | // immediate such as "> 20" 1229 | if (/^ *\W+/.test(str)) return new Function('_', 'return _ ' + str); 1230 | 1231 | // properties such as "name.first" or "age > 18" or "age > 18 && age < 36" 1232 | return new Function('_', 'return ' + get(str)); 1233 | } 1234 | 1235 | /** 1236 | * Convert `object` to a function. 1237 | * 1238 | * @param {Object} object 1239 | * @return {Function} 1240 | * @api private 1241 | */ 1242 | 1243 | function objectToFunction(obj) { 1244 | var match = {} 1245 | for (var key in obj) { 1246 | match[key] = typeof obj[key] === 'string' 1247 | ? defaultToFunction(obj[key]) 1248 | : toFunction(obj[key]) 1249 | } 1250 | return function(val){ 1251 | if (typeof val !== 'object') return false; 1252 | for (var key in match) { 1253 | if (!(key in val)) return false; 1254 | if (!match[key](val[key])) return false; 1255 | } 1256 | return true; 1257 | } 1258 | } 1259 | 1260 | /** 1261 | * Built the getter function. Supports getter style functions 1262 | * 1263 | * @param {String} str 1264 | * @return {String} 1265 | * @api private 1266 | */ 1267 | 1268 | function get(str) { 1269 | var props = expr(str); 1270 | if (!props.length) return '_.' + str; 1271 | 1272 | var val; 1273 | for(var i = 0, prop; prop = props[i]; i++) { 1274 | val = '_.' + prop; 1275 | val = "('function' == typeof " + val + " ? " + val + "() : " + val + ")"; 1276 | str = str.replace(new RegExp(prop, 'g'), val); 1277 | } 1278 | 1279 | return str; 1280 | } 1281 | 1282 | }); 1283 | require.register("component-each/index.js", function(exports, require, module){ 1284 | 1285 | /** 1286 | * Module dependencies. 1287 | */ 1288 | 1289 | var type = require('type'); 1290 | var toFunction = require('to-function'); 1291 | 1292 | /** 1293 | * HOP reference. 1294 | */ 1295 | 1296 | var has = Object.prototype.hasOwnProperty; 1297 | 1298 | /** 1299 | * Iterate the given `obj` and invoke `fn(val, i)` 1300 | * in optional context `ctx`. 1301 | * 1302 | * @param {String|Array|Object} obj 1303 | * @param {Function} fn 1304 | * @param {Object} [ctx] 1305 | * @api public 1306 | */ 1307 | 1308 | module.exports = function(obj, fn, ctx){ 1309 | fn = toFunction(fn); 1310 | ctx = ctx || this; 1311 | switch (type(obj)) { 1312 | case 'array': 1313 | return array(obj, fn, ctx); 1314 | case 'object': 1315 | if ('number' == typeof obj.length) return array(obj, fn, ctx); 1316 | return object(obj, fn, ctx); 1317 | case 'string': 1318 | return string(obj, fn, ctx); 1319 | } 1320 | }; 1321 | 1322 | /** 1323 | * Iterate string chars. 1324 | * 1325 | * @param {String} obj 1326 | * @param {Function} fn 1327 | * @param {Object} ctx 1328 | * @api private 1329 | */ 1330 | 1331 | function string(obj, fn, ctx) { 1332 | for (var i = 0; i < obj.length; ++i) { 1333 | fn.call(ctx, obj.charAt(i), i); 1334 | } 1335 | } 1336 | 1337 | /** 1338 | * Iterate object keys. 1339 | * 1340 | * @param {Object} obj 1341 | * @param {Function} fn 1342 | * @param {Object} ctx 1343 | * @api private 1344 | */ 1345 | 1346 | function object(obj, fn, ctx) { 1347 | for (var key in obj) { 1348 | if (has.call(obj, key)) { 1349 | fn.call(ctx, key, obj[key]); 1350 | } 1351 | } 1352 | } 1353 | 1354 | /** 1355 | * Iterate array-ish. 1356 | * 1357 | * @param {Array|Object} obj 1358 | * @param {Function} fn 1359 | * @param {Object} ctx 1360 | * @api private 1361 | */ 1362 | 1363 | function array(obj, fn, ctx) { 1364 | for (var i = 0; i < obj.length; ++i) { 1365 | fn.call(ctx, obj[i], i); 1366 | } 1367 | } 1368 | 1369 | }); 1370 | require.register("component-classes/index.js", function(exports, require, module){ 1371 | /** 1372 | * Module dependencies. 1373 | */ 1374 | 1375 | var index = require('indexof'); 1376 | 1377 | /** 1378 | * Whitespace regexp. 1379 | */ 1380 | 1381 | var re = /\s+/; 1382 | 1383 | /** 1384 | * toString reference. 1385 | */ 1386 | 1387 | var toString = Object.prototype.toString; 1388 | 1389 | /** 1390 | * Wrap `el` in a `ClassList`. 1391 | * 1392 | * @param {Element} el 1393 | * @return {ClassList} 1394 | * @api public 1395 | */ 1396 | 1397 | module.exports = function(el){ 1398 | return new ClassList(el); 1399 | }; 1400 | 1401 | /** 1402 | * Initialize a new ClassList for `el`. 1403 | * 1404 | * @param {Element} el 1405 | * @api private 1406 | */ 1407 | 1408 | function ClassList(el) { 1409 | if (!el) throw new Error('A DOM element reference is required'); 1410 | this.el = el; 1411 | this.list = el.classList; 1412 | } 1413 | 1414 | /** 1415 | * Add class `name` if not already present. 1416 | * 1417 | * @param {String} name 1418 | * @return {ClassList} 1419 | * @api public 1420 | */ 1421 | 1422 | ClassList.prototype.add = function(name){ 1423 | // classList 1424 | if (this.list) { 1425 | this.list.add(name); 1426 | return this; 1427 | } 1428 | 1429 | // fallback 1430 | var arr = this.array(); 1431 | var i = index(arr, name); 1432 | if (!~i) arr.push(name); 1433 | this.el.className = arr.join(' '); 1434 | return this; 1435 | }; 1436 | 1437 | /** 1438 | * Remove class `name` when present, or 1439 | * pass a regular expression to remove 1440 | * any which match. 1441 | * 1442 | * @param {String|RegExp} name 1443 | * @return {ClassList} 1444 | * @api public 1445 | */ 1446 | 1447 | ClassList.prototype.remove = function(name){ 1448 | if ('[object RegExp]' == toString.call(name)) { 1449 | return this.removeMatching(name); 1450 | } 1451 | 1452 | // classList 1453 | if (this.list) { 1454 | this.list.remove(name); 1455 | return this; 1456 | } 1457 | 1458 | // fallback 1459 | var arr = this.array(); 1460 | var i = index(arr, name); 1461 | if (~i) arr.splice(i, 1); 1462 | this.el.className = arr.join(' '); 1463 | return this; 1464 | }; 1465 | 1466 | /** 1467 | * Remove all classes matching `re`. 1468 | * 1469 | * @param {RegExp} re 1470 | * @return {ClassList} 1471 | * @api private 1472 | */ 1473 | 1474 | ClassList.prototype.removeMatching = function(re){ 1475 | var arr = this.array(); 1476 | for (var i = 0; i < arr.length; i++) { 1477 | if (re.test(arr[i])) { 1478 | this.remove(arr[i]); 1479 | } 1480 | } 1481 | return this; 1482 | }; 1483 | 1484 | /** 1485 | * Toggle class `name`, can force state via `force`. 1486 | * 1487 | * For browsers that support classList, but do not support `force` yet, 1488 | * the mistake will be detected and corrected. 1489 | * 1490 | * @param {String} name 1491 | * @param {Boolean} force 1492 | * @return {ClassList} 1493 | * @api public 1494 | */ 1495 | 1496 | ClassList.prototype.toggle = function(name, force){ 1497 | // classList 1498 | if (this.list) { 1499 | if ("undefined" !== typeof force) { 1500 | if (force !== this.list.toggle(name, force)) { 1501 | this.list.toggle(name); // toggle again to correct 1502 | } 1503 | } else { 1504 | this.list.toggle(name); 1505 | } 1506 | return this; 1507 | } 1508 | 1509 | // fallback 1510 | if ("undefined" !== typeof force) { 1511 | if (!force) { 1512 | this.remove(name); 1513 | } else { 1514 | this.add(name); 1515 | } 1516 | } else { 1517 | if (this.has(name)) { 1518 | this.remove(name); 1519 | } else { 1520 | this.add(name); 1521 | } 1522 | } 1523 | 1524 | return this; 1525 | }; 1526 | 1527 | /** 1528 | * Return an array of classes. 1529 | * 1530 | * @return {Array} 1531 | * @api public 1532 | */ 1533 | 1534 | ClassList.prototype.array = function(){ 1535 | var str = this.el.className.replace(/^\s+|\s+$/g, ''); 1536 | var arr = str.split(re); 1537 | if ('' === arr[0]) arr.shift(); 1538 | return arr; 1539 | }; 1540 | 1541 | /** 1542 | * Check if class `name` is present. 1543 | * 1544 | * @param {String} name 1545 | * @return {ClassList} 1546 | * @api public 1547 | */ 1548 | 1549 | ClassList.prototype.has = 1550 | ClassList.prototype.contains = function(name){ 1551 | return this.list 1552 | ? this.list.contains(name) 1553 | : !! ~index(this.array(), name); 1554 | }; 1555 | 1556 | }); 1557 | require.register("anthonyshort-has-transitions/index.js", function(exports, require, module){ 1558 | /** 1559 | * This will store the property that the current 1560 | * browser uses for transitionDuration 1561 | */ 1562 | var property; 1563 | 1564 | /** 1565 | * The properties we'll check on an element 1566 | * to determine if it actually has transitions 1567 | * We use duration as this is the only property 1568 | * needed to technically have transitions 1569 | * @type {Array} 1570 | */ 1571 | var types = [ 1572 | "transitionDuration", 1573 | "MozTransitionDuration", 1574 | "webkitTransitionDuration" 1575 | ]; 1576 | 1577 | /** 1578 | * Determine the correct property for this browser 1579 | * just once so we done need to check every time 1580 | */ 1581 | while(types.length) { 1582 | var type = types.shift(); 1583 | if(type in document.body.style) { 1584 | property = type; 1585 | } 1586 | } 1587 | 1588 | /** 1589 | * Determine if the browser supports transitions or 1590 | * if an element has transitions at all. 1591 | * @param {Element} el Optional. Returns browser support if not included 1592 | * @return {Boolean} 1593 | */ 1594 | function hasTransitions(el){ 1595 | if(!property) { 1596 | return false; // No browser support for transitions 1597 | } 1598 | if(!el) { 1599 | return property != null; // We just want to know if browsers support it 1600 | } 1601 | var duration = getComputedStyle(el)[property]; 1602 | return duration !== "" && parseFloat(duration) !== 0; // Does this element have transitions? 1603 | } 1604 | 1605 | module.exports = hasTransitions; 1606 | }); 1607 | require.register("component-event/index.js", function(exports, require, module){ 1608 | var bind = window.addEventListener ? 'addEventListener' : 'attachEvent', 1609 | unbind = window.removeEventListener ? 'removeEventListener' : 'detachEvent', 1610 | prefix = bind !== 'addEventListener' ? 'on' : ''; 1611 | 1612 | /** 1613 | * Bind `el` event `type` to `fn`. 1614 | * 1615 | * @param {Element} el 1616 | * @param {String} type 1617 | * @param {Function} fn 1618 | * @param {Boolean} capture 1619 | * @return {Function} 1620 | * @api public 1621 | */ 1622 | 1623 | exports.bind = function(el, type, fn, capture){ 1624 | el[bind](prefix + type, fn, capture || false); 1625 | return fn; 1626 | }; 1627 | 1628 | /** 1629 | * Unbind `el` event `type`'s callback `fn`. 1630 | * 1631 | * @param {Element} el 1632 | * @param {String} type 1633 | * @param {Function} fn 1634 | * @param {Boolean} capture 1635 | * @return {Function} 1636 | * @api public 1637 | */ 1638 | 1639 | exports.unbind = function(el, type, fn, capture){ 1640 | el[unbind](prefix + type, fn, capture || false); 1641 | return fn; 1642 | }; 1643 | }); 1644 | require.register("anthonyshort-css-emitter/index.js", function(exports, require, module){ 1645 | /** 1646 | * Module Dependencies 1647 | */ 1648 | 1649 | var events = require('event'); 1650 | 1651 | // CSS events 1652 | 1653 | var watch = [ 1654 | 'transitionend' 1655 | , 'webkitTransitionEnd' 1656 | , 'oTransitionEnd' 1657 | , 'MSTransitionEnd' 1658 | , 'animationend' 1659 | , 'webkitAnimationEnd' 1660 | , 'oAnimationEnd' 1661 | , 'MSAnimationEnd' 1662 | ]; 1663 | 1664 | /** 1665 | * Expose `CSSnext` 1666 | */ 1667 | 1668 | module.exports = CssEmitter; 1669 | 1670 | /** 1671 | * Initialize a new `CssEmitter` 1672 | * 1673 | */ 1674 | 1675 | function CssEmitter(element){ 1676 | if (!(this instanceof CssEmitter)) return new CssEmitter(element); 1677 | this.el = element; 1678 | } 1679 | 1680 | /** 1681 | * Bind CSS events. 1682 | * 1683 | * @api public 1684 | */ 1685 | 1686 | CssEmitter.prototype.bind = function(fn){ 1687 | for (var i=0; i < watch.length; i++) { 1688 | events.bind(this.el, watch[i], fn); 1689 | } 1690 | return this; 1691 | }; 1692 | 1693 | /** 1694 | * Unbind CSS events 1695 | * 1696 | * @api public 1697 | */ 1698 | 1699 | CssEmitter.prototype.unbind = function(fn){ 1700 | for (var i=0; i < watch.length; i++) { 1701 | events.unbind(this.el, watch[i], fn); 1702 | } 1703 | return this; 1704 | }; 1705 | 1706 | /** 1707 | * Fire callback only once 1708 | * 1709 | * @api public 1710 | */ 1711 | 1712 | CssEmitter.prototype.once = function(fn){ 1713 | var self = this; 1714 | function on(){ 1715 | self.unbind(on); 1716 | fn.apply(self.el, arguments); 1717 | } 1718 | self.bind(on); 1719 | return this; 1720 | }; 1721 | 1722 | 1723 | }); 1724 | require.register("anthonyshort-after-transition/index.js", function(exports, require, module){ 1725 | var hasTransitions = require('has-transitions'); 1726 | var emitter = require('css-emitter'); 1727 | 1728 | function afterTransition(el, callback) { 1729 | if(hasTransitions(el)) { 1730 | return emitter(el).bind(callback); 1731 | } 1732 | return callback.apply(el); 1733 | }; 1734 | 1735 | afterTransition.once = function(el, callback) { 1736 | afterTransition(el, function fn(){ 1737 | callback.apply(el); 1738 | emitter(el).unbind(fn); 1739 | }); 1740 | }; 1741 | 1742 | module.exports = afterTransition; 1743 | }); 1744 | require.register("yields-empty/index.js", function(exports, require, module){ 1745 | 1746 | /** 1747 | * Empty the given `el`. 1748 | * 1749 | * @param {Element} el 1750 | * @return {Element} 1751 | */ 1752 | 1753 | module.exports = function(el, node){ 1754 | while (node = el.firstChild) el.removeChild(node); 1755 | return el; 1756 | }; 1757 | 1758 | }); 1759 | require.register("component-domify/index.js", function(exports, require, module){ 1760 | 1761 | /** 1762 | * Expose `parse`. 1763 | */ 1764 | 1765 | module.exports = parse; 1766 | 1767 | /** 1768 | * Wrap map from jquery. 1769 | */ 1770 | 1771 | var map = { 1772 | legend: [1, '
', '
'], 1773 | tr: [2, '', '
'], 1774 | col: [2, '', '
'], 1775 | _default: [0, '', ''] 1776 | }; 1777 | 1778 | map.td = 1779 | map.th = [3, '', '
']; 1780 | 1781 | map.option = 1782 | map.optgroup = [1, '']; 1783 | 1784 | map.thead = 1785 | map.tbody = 1786 | map.colgroup = 1787 | map.caption = 1788 | map.tfoot = [1, '', '
']; 1789 | 1790 | map.text = 1791 | map.circle = 1792 | map.ellipse = 1793 | map.line = 1794 | map.path = 1795 | map.polygon = 1796 | map.polyline = 1797 | map.rect = [1, '','']; 1798 | 1799 | /** 1800 | * Parse `html` and return the children. 1801 | * 1802 | * @param {String} html 1803 | * @return {Array} 1804 | * @api private 1805 | */ 1806 | 1807 | function parse(html) { 1808 | if ('string' != typeof html) throw new TypeError('String expected'); 1809 | 1810 | // tag name 1811 | var m = /<([\w:]+)/.exec(html); 1812 | if (!m) return document.createTextNode(html); 1813 | 1814 | html = html.replace(/^\s+|\s+$/g, ''); // Remove leading/trailing whitespace 1815 | 1816 | var tag = m[1]; 1817 | 1818 | // body support 1819 | if (tag == 'body') { 1820 | var el = document.createElement('html'); 1821 | el.innerHTML = html; 1822 | return el.removeChild(el.lastChild); 1823 | } 1824 | 1825 | // wrap map 1826 | var wrap = map[tag] || map._default; 1827 | var depth = wrap[0]; 1828 | var prefix = wrap[1]; 1829 | var suffix = wrap[2]; 1830 | var el = document.createElement('div'); 1831 | el.innerHTML = prefix + html + suffix; 1832 | while (depth--) el = el.lastChild; 1833 | 1834 | // one element 1835 | if (el.firstChild == el.lastChild) { 1836 | return el.removeChild(el.firstChild); 1837 | } 1838 | 1839 | // several elements 1840 | var fragment = document.createDocumentFragment(); 1841 | while (el.firstChild) { 1842 | fragment.appendChild(el.removeChild(el.firstChild)); 1843 | } 1844 | 1845 | return fragment; 1846 | } 1847 | 1848 | }); 1849 | require.register("cast/index.js", function(exports, require, module){ 1850 | /** 1851 | * Module dependencies 1852 | */ 1853 | 1854 | var Emitter = require('emitter'); 1855 | var Dict = require('ordered-dictionary'); 1856 | var fastdom = require('fastdom'); 1857 | var type = require('type'); 1858 | var Block = require('./block'); 1859 | var empty = require('empty'); 1860 | 1861 | module.exports = Cast; 1862 | 1863 | /** 1864 | * Cast 1865 | * @param {Element} wrapper 1866 | */ 1867 | 1868 | function Cast(wrapper, template){ 1869 | if (!(this instanceof Cast)) return new Cast(wrapper, template); 1870 | this.wrapper = wrapper; 1871 | this.template = template; 1872 | this.wrapperWidth = this.wrapper.clientWidth; 1873 | this.el = document.createElement('div'); 1874 | this.el.className = 'Cast'; 1875 | this.collection = new Dict(); 1876 | this.collection.on('enter', this.renderNew.bind(this)); 1877 | this.collection.on('exit', this.removeOld.bind(this)); 1878 | } 1879 | 1880 | Emitter(Cast.prototype); 1881 | 1882 | /** 1883 | * Supply our Cast with a collection of documents. If a unique identifier is 1884 | * supplied, then we can efficiently update, add, and remove models on subsequent 1885 | * .data() calls. If we don't have a uid, then reset collection. 1886 | * 1887 | * @param {Object} attr 1888 | * @param {Function|String} fn unique id 1889 | * @return {Cast} 1890 | */ 1891 | 1892 | Cast.prototype.data = function(docs, fn) { 1893 | if (!fn) throw new Error('Unique id required'); 1894 | 1895 | var len = this.collection.length(); 1896 | var keys = []; 1897 | var isFn = (type(fn) === 'function'); 1898 | 1899 | // Either update our model, or make a new one for each docsibute 1900 | // that we have passed. 1901 | for ( var i = 0, l = docs.length; i < l; i++ ){ 1902 | var key = isFn ? fn(docs[i]) : docs[i][fn]; 1903 | var model = this.collection.get(key); 1904 | keys.push(key); 1905 | if (model) model.set(docs[i]); 1906 | else this.collection.set(key, new Block(docs[i], this)); 1907 | } 1908 | 1909 | // If running .data() multiple times, remove any attributes 1910 | // that were not contained in subsequent calls. This is fugly. Yoiks. 1911 | if (len) { 1912 | var toRemove = []; 1913 | this.collection.forEach(function(key, model, i){ 1914 | if (keys.indexOf(key) === -1 ) toRemove.push(key); 1915 | }); 1916 | for (var x = 0, length = toRemove.length; x < length; x++){ 1917 | this.collection.remove(toRemove[x]); 1918 | } 1919 | } 1920 | return this; 1921 | }; 1922 | 1923 | /** 1924 | * return the JSON of our Cast. 1925 | * 1926 | * @return {Array} 1927 | */ 1928 | 1929 | Cast.prototype.toJSON = function(){ 1930 | var json = []; 1931 | this.collection.forEach(function(key, value){ 1932 | json.push(value.toJSON()); 1933 | }); 1934 | return json; 1935 | }; 1936 | 1937 | 1938 | /** 1939 | * Reset Cast with given docs. 1940 | * 1941 | * @param {Array|Object} attr 1942 | * @param {Function|String} fn 1943 | * @return {Cast} 1944 | */ 1945 | 1946 | Cast.prototype.reset = function(docs, fn){ 1947 | this.collection.clear(); 1948 | this.add(docs, fn); 1949 | return this; 1950 | }; 1951 | 1952 | /** 1953 | * Add item with optional uid. 1954 | * 1955 | * @param {Object|Array} attr 1956 | * @param {Function|String} fn 1957 | */ 1958 | 1959 | Cast.prototype.add = function(docs, fn){ 1960 | if (type(docs) !== 'array') docs = [docs]; 1961 | if (!fn) throw new Error('Unique id required'); 1962 | var isFn = type(fn) === 'function'; 1963 | for (var i = 0, l = docs.length; i < l; i++){ 1964 | var key = isFn ? fn(docs[i]) : docs[i][fn]; 1965 | var val = new Block(docs[i], this); 1966 | this.collection.set(key, val); 1967 | } 1968 | return this; 1969 | }; 1970 | 1971 | /** 1972 | * Remove item given a unique id. 1973 | * 1974 | * @param {String} key 1975 | * @return {Cast} 1976 | */ 1977 | 1978 | Cast.prototype.remove = function(uid){ 1979 | this.collection.remove(uid); 1980 | return this; 1981 | }; 1982 | 1983 | 1984 | 1985 | /** 1986 | * Remove any left/right padding from the container. 1987 | * 1988 | * @param {Number} w width 1989 | * @param {Number} h height 1990 | * @param {Number} pw padding-width 1991 | * @param {Number} ph padding-height 1992 | * @return {Cast} 1993 | */ 1994 | 1995 | Cast.prototype.justify = function(w, h, pw, ph){ 1996 | var cw = this.wrapperWidth; 1997 | 1998 | var bpr = Math.floor((cw - (pw * 2)) / (w + pw)); 1999 | 2000 | var getLeft = function(c, r) { 2001 | if (c === 0) return 0; 2002 | if (c === bpr - 1) return cw - w; 2003 | var remainingSpace = cw - (w * bpr); 2004 | var padding = remainingSpace / (bpr - 1); 2005 | return w + (c * padding) + ((c - 1) * w); 2006 | }; 2007 | 2008 | this.collection.forEach(function(key, block, i){ 2009 | var r = Math.floor(i / bpr); 2010 | var c = i % bpr; 2011 | var left = getLeft(c, r); 2012 | var top = ((r * h) + (r + 1) * ph); 2013 | 2014 | block.position({ 2015 | 'left': left, 2016 | 'top': top, 2017 | 'width': w, 2018 | 'height': h 2019 | }); 2020 | }); 2021 | 2022 | var t = this.collection.length(); 2023 | var wrapperHeight = Math.ceil(t / bpr) * (h + ph) + ph; 2024 | this.setHeight(wrapperHeight); 2025 | return this; 2026 | }; 2027 | 2028 | 2029 | /** 2030 | * The left and right container padding is the 2031 | * dynamic property here. 2032 | * 2033 | * @param {Number} w width 2034 | * @param {Number} h height 2035 | * @param {Number} pw padding-width 2036 | * @param {Number} ph padding-height 2037 | * @return {Cast} 2038 | */ 2039 | 2040 | Cast.prototype.center = function(w, h, pw, ph){ 2041 | var cw = this.wrapperWidth; 2042 | var bpr = Math.floor(cw/(w + pw)); 2043 | var mx = (cw - (bpr * w) - (bpr - 1) * pw) * 0.5; 2044 | 2045 | this.collection.forEach(function(key, block, i){ 2046 | var r = Math.floor(i / bpr); 2047 | var c = i % bpr; 2048 | var left = mx + (c * (w + pw)); 2049 | var top = (r * h) + (r + 1) * ph; 2050 | 2051 | block.position({ 2052 | 'left': left, 2053 | 'top': top, 2054 | 'width': w, 2055 | 'height': h 2056 | }); 2057 | }); 2058 | 2059 | var t = this.collection.length(); 2060 | var wrapperHeight = Math.ceil(t / bpr) * (h + ph) + ph; 2061 | this.setHeight(wrapperHeight); 2062 | return this; 2063 | }; 2064 | 2065 | 2066 | /** 2067 | * Keep a constant padding-width & padding-height with 2068 | * a dynamic cast-item width and height. 2069 | * 2070 | * @param {Number} w width 2071 | * @param {Number} h height 2072 | * @param {Number} pw padding-width 2073 | * @param {Number} ph padding-height 2074 | * @return {Cast} 2075 | */ 2076 | 2077 | Cast.prototype.dynamic = function(w, h, pw, ph){ 2078 | var cw = this.wrapperWidth; 2079 | var bpr = Math.floor(cw / ( w + pw )); 2080 | var newWidth = (cw - (bpr * pw)) / bpr; 2081 | var newHeight = ( newWidth / w ) * h; 2082 | var mx = (cw - (bpr * newWidth) - (bpr - 1) * pw) * 0.5; 2083 | 2084 | // XXX This logic is the same as center(). Should we make 2085 | // this a shared function? 2086 | this.collection.forEach(function(id, block, i){ 2087 | var r = Math.floor(i / bpr); 2088 | var c = i % bpr; 2089 | var left = mx + (c * (newWidth + pw)); 2090 | var top = (r * newHeight) + (r + 1) * ph; 2091 | 2092 | block.position({ 2093 | 'width': newWidth, 2094 | 'left': left, 2095 | 'top': top, 2096 | 'height': newHeight 2097 | }); 2098 | }); 2099 | 2100 | var t = this.collection.length(); 2101 | var wrapperHeight = Math.ceil(t / bpr) * (newHeight + ph) + ph; 2102 | this.setHeight(wrapperHeight); 2103 | return this; 2104 | }; 2105 | 2106 | /** 2107 | * List layout 2108 | * 2109 | * @param {Number} h height 2110 | * @param {Number} ph padding-height 2111 | * @return {Cast} 2112 | */ 2113 | 2114 | Cast.prototype.list = function(h, ph){ 2115 | 2116 | this.collection.forEach(function(id, block, i){ 2117 | var top = (h + ph) * i; 2118 | block.position({ 2119 | 'left': 0, 2120 | 'top': top, 2121 | 'height': h 2122 | }); 2123 | }); 2124 | 2125 | this.setHeight(this.collection.length() * (h + ph)); 2126 | return this; 2127 | }; 2128 | 2129 | /** 2130 | * Sort data by field 2131 | * 2132 | * @param {String} field 2133 | * @param {Number} invert 2134 | * @return {Cast} 2135 | */ 2136 | 2137 | Cast.prototype.sortBy = function(field, invert){ 2138 | invert = invert || 1; 2139 | 2140 | this.collection.sort(function(left, right){ 2141 | var leftVal = left.attr[field]; 2142 | var rightVal = right.attr[field]; 2143 | if (leftVal < rightVal) return (-1 * invert); 2144 | if (leftVal > rightVal) return (1 * invert); 2145 | return 0; 2146 | }); 2147 | 2148 | return this; 2149 | }; 2150 | 2151 | /** 2152 | * render new block 2153 | * @param {Block} block 2154 | */ 2155 | 2156 | Cast.prototype.renderNew = function(block){ 2157 | fastdom.write(function(){ 2158 | this.el.appendChild(block.el); 2159 | }.bind(this)); 2160 | }; 2161 | 2162 | /** 2163 | * remove old block 2164 | * @param {Block} block 2165 | */ 2166 | 2167 | Cast.prototype.removeOld = function(block){ 2168 | fastdom.write(function(){ 2169 | block.hide(function(){ 2170 | block.remove(); 2171 | }); 2172 | }.bind(this)); 2173 | }; 2174 | 2175 | /** 2176 | * Set our cast.js height 2177 | * @param {Number} height 2178 | */ 2179 | 2180 | Cast.prototype.setHeight = function(height){ 2181 | fastdom.write(function(){ 2182 | this.el.style.height = height + 'px'; 2183 | }.bind(this)); 2184 | }; 2185 | 2186 | 2187 | Cast.prototype.draw = function(template){ 2188 | this.template = template; 2189 | empty(this.wrapper); 2190 | this.wrapper.appendChild(this.el); 2191 | return this; 2192 | }; 2193 | 2194 | }); 2195 | require.register("cast/block.js", function(exports, require, module){ 2196 | /** 2197 | * Module dependencies 2198 | */ 2199 | 2200 | var each = require('each'); 2201 | var classes = require('classes'); 2202 | var fastdom = require('fastdom'); 2203 | var afterTransition = require('after-transition'); 2204 | var domify = require('domify'); 2205 | var type = require('type'); 2206 | var empty = require('empty'); 2207 | var clone = require('clone'); 2208 | var translate = require('translate'); 2209 | 2210 | /** 2211 | * expose Block 2212 | */ 2213 | 2214 | module.exports = Block; 2215 | 2216 | /** 2217 | * Block 2218 | * @param {Object} attr 2219 | * @param {Cast} cast 2220 | */ 2221 | 2222 | function Block(attr, cast){ 2223 | this.cast = cast; 2224 | this.attr = {}; 2225 | this.pos = {}; 2226 | this.template = cast.template; 2227 | this.el = document.createElement('div'); 2228 | this.classes = classes(this.el); 2229 | this.el.className = 'Cast-item'; 2230 | this.rendered = false; 2231 | this.hidden = false; 2232 | this.set(attr); 2233 | this.cast.emit('view-created', this); 2234 | } 2235 | 2236 | /** 2237 | * Set attributes 2238 | * @param {Object} attr 2239 | */ 2240 | 2241 | Block.prototype.set = function(attr){ 2242 | var changed = false; 2243 | if (!attr) return; 2244 | 2245 | var prev = clone(this.attr); 2246 | 2247 | each(attr, function(key){ 2248 | this.attr[key] = attr[key]; 2249 | if (this.attr[key] !== prev[key]) { 2250 | changed = true; 2251 | } 2252 | }.bind(this)); 2253 | 2254 | if (changed) this.render(); 2255 | }; 2256 | 2257 | /** 2258 | * Hide the block 2259 | * @return {Block} 2260 | */ 2261 | 2262 | Block.prototype.hide = function(fn){ 2263 | if (this.hidden) return; 2264 | fastdom.write(function(){ 2265 | if (fn) afterTransition.once(this.el, fn); 2266 | this.classes.add('hidden'); 2267 | this.el.setAttribute('aria-hidden', true); 2268 | }.bind(this)); 2269 | this.hidden = true; 2270 | return this; 2271 | }; 2272 | 2273 | /** 2274 | * Show the block 2275 | * @return {Block} 2276 | */ 2277 | 2278 | Block.prototype.show = function(){ 2279 | if (!this.hidden) return; 2280 | fastdom.write(function(){ 2281 | this.classes.remove('hidden'); 2282 | this.el.setAttribute('aria-hidden', false); 2283 | }.bind(this)); 2284 | this.hidden = false; 2285 | return this; 2286 | }; 2287 | 2288 | /** 2289 | * Render block with template 2290 | * @return {Block} 2291 | */ 2292 | 2293 | Block.prototype.render = function(){ 2294 | var tmp = this.template(this.attr, this.el); 2295 | var content = (type(tmp) === 'string') ? domify(tmp) : tmp; 2296 | fastdom.write(function(){ 2297 | empty(this.el); 2298 | this.el.appendChild(content); 2299 | this.cast.emit('view-rendered', this); 2300 | this.rendered = true; 2301 | }.bind(this)); 2302 | return this; 2303 | }; 2304 | 2305 | /** 2306 | * Remove block element from dom 2307 | * @return {Block} 2308 | */ 2309 | 2310 | Block.prototype.remove = function(){ 2311 | this.cast.emit('view-destroyed', this); 2312 | this.el.parentNode.removeChild(this.el); 2313 | return this; 2314 | }; 2315 | 2316 | /** 2317 | * Update position 2318 | * @return {Block} 2319 | */ 2320 | 2321 | Block.prototype.position = function(pos){ 2322 | if (pos) this.pos = pos; 2323 | var style = this.el.style; 2324 | fastdom.write(function(){ 2325 | style.width = this.pos.width + 'px'; 2326 | style.height = this.pos.height + 'px'; 2327 | translate(this.el, this.pos.left, this.pos.top); 2328 | }.bind(this)); 2329 | return this; 2330 | }; 2331 | 2332 | /** 2333 | * Get our attr 2334 | * @return {Object} 2335 | */ 2336 | 2337 | Block.prototype.toJSON = function(){ 2338 | return clone(this.attr); 2339 | }; 2340 | }); 2341 | 2342 | 2343 | 2344 | 2345 | 2346 | 2347 | 2348 | 2349 | 2350 | 2351 | 2352 | 2353 | 2354 | 2355 | 2356 | 2357 | 2358 | 2359 | 2360 | 2361 | 2362 | 2363 | 2364 | 2365 | 2366 | 2367 | require.alias("component-emitter/index.js", "cast/deps/emitter/index.js"); 2368 | require.alias("component-emitter/index.js", "emitter/index.js"); 2369 | 2370 | require.alias("component-clone/index.js", "cast/deps/clone/index.js"); 2371 | require.alias("component-clone/index.js", "clone/index.js"); 2372 | require.alias("component-type/index.js", "component-clone/deps/type/index.js"); 2373 | 2374 | require.alias("component-type/index.js", "cast/deps/type/index.js"); 2375 | require.alias("component-type/index.js", "type/index.js"); 2376 | 2377 | require.alias("bmcmahen-ordered-dictionary/index.js", "cast/deps/ordered-dictionary/index.js"); 2378 | require.alias("bmcmahen-ordered-dictionary/index.js", "ordered-dictionary/index.js"); 2379 | require.alias("component-indexof/index.js", "bmcmahen-ordered-dictionary/deps/indexof/index.js"); 2380 | 2381 | require.alias("component-emitter/index.js", "bmcmahen-ordered-dictionary/deps/emitter/index.js"); 2382 | 2383 | require.alias("component-translate/index.js", "cast/deps/translate/index.js"); 2384 | require.alias("component-translate/index.js", "cast/deps/translate/index.js"); 2385 | require.alias("component-translate/index.js", "translate/index.js"); 2386 | require.alias("component-has-translate3d/index.js", "component-translate/deps/has-translate3d/index.js"); 2387 | require.alias("component-transform-property/index.js", "component-has-translate3d/deps/transform-property/index.js"); 2388 | 2389 | require.alias("component-transform-property/index.js", "component-translate/deps/transform-property/index.js"); 2390 | 2391 | require.alias("component-translate/index.js", "component-translate/index.js"); 2392 | require.alias("wilsonpage-fastdom/index.js", "cast/deps/fastdom/index.js"); 2393 | require.alias("wilsonpage-fastdom/index.js", "cast/deps/fastdom/index.js"); 2394 | require.alias("wilsonpage-fastdom/index.js", "fastdom/index.js"); 2395 | require.alias("wilsonpage-fastdom/index.js", "wilsonpage-fastdom/index.js"); 2396 | require.alias("component-each/index.js", "cast/deps/each/index.js"); 2397 | require.alias("component-each/index.js", "each/index.js"); 2398 | require.alias("component-to-function/index.js", "component-each/deps/to-function/index.js"); 2399 | require.alias("component-props/index.js", "component-to-function/deps/props/index.js"); 2400 | 2401 | require.alias("component-type/index.js", "component-each/deps/type/index.js"); 2402 | 2403 | require.alias("component-classes/index.js", "cast/deps/classes/index.js"); 2404 | require.alias("component-classes/index.js", "classes/index.js"); 2405 | require.alias("component-indexof/index.js", "component-classes/deps/indexof/index.js"); 2406 | 2407 | require.alias("anthonyshort-after-transition/index.js", "cast/deps/after-transition/index.js"); 2408 | require.alias("anthonyshort-after-transition/index.js", "cast/deps/after-transition/index.js"); 2409 | require.alias("anthonyshort-after-transition/index.js", "after-transition/index.js"); 2410 | require.alias("anthonyshort-has-transitions/index.js", "anthonyshort-after-transition/deps/has-transitions/index.js"); 2411 | require.alias("anthonyshort-has-transitions/index.js", "anthonyshort-after-transition/deps/has-transitions/index.js"); 2412 | require.alias("anthonyshort-has-transitions/index.js", "anthonyshort-has-transitions/index.js"); 2413 | require.alias("anthonyshort-css-emitter/index.js", "anthonyshort-after-transition/deps/css-emitter/index.js"); 2414 | require.alias("component-emitter/index.js", "anthonyshort-css-emitter/deps/emitter/index.js"); 2415 | 2416 | require.alias("component-event/index.js", "anthonyshort-css-emitter/deps/event/index.js"); 2417 | 2418 | require.alias("anthonyshort-after-transition/index.js", "anthonyshort-after-transition/index.js"); 2419 | require.alias("yields-empty/index.js", "cast/deps/empty/index.js"); 2420 | require.alias("yields-empty/index.js", "cast/deps/empty/index.js"); 2421 | require.alias("yields-empty/index.js", "empty/index.js"); 2422 | require.alias("yields-empty/index.js", "yields-empty/index.js"); 2423 | require.alias("component-domify/index.js", "cast/deps/domify/index.js"); 2424 | require.alias("component-domify/index.js", "domify/index.js"); 2425 | 2426 | require.alias("cast/index.js", "cast/index.js");if (typeof exports == "object") { 2427 | module.exports = require("cast"); 2428 | } else if (typeof define == "function" && define.amd) { 2429 | define([], function(){ return require("cast"); }); 2430 | } else { 2431 | this["cast"] = require("cast"); 2432 | }})(); --------------------------------------------------------------------------------