var $ = { crudify: function (store, query, crud) { if (null == crud) { crud = query; query = store; store = null; } if (store) { query = store.query(query); } query.observe(function (row, deleteIndex, insertIndex) { var del = (0 <= deleteIndex), ins = (0 <= insertIndex); !del && ins && crud.c && crud.c(row); del && ins && crud.u && crud.u(row); del && !ins && crud.d && crud.d(row); }, !!crud.u); }, get : function ( item, keys ) { var i, j; for ( i = 0, j = keys.length; i < j; i++ ) { item = item[ keys[ i ] ]; if ( undefined === item ) { break; } } return item; }, set : function ( item, keys, value ) { var i, j, key; for ( i = 0, j = keys.length - 1; i <= j; i++ ) { key = keys[ i ]; item = item[ key ] = ( i === j ) ? value : ( item[ key ] || [] ); } return value; }, delay : function ( timeout, id, callback ) { this.delays = this.delays || []; var delay = this.delays[ id ]; if ( delay ) { clearTimeout ( delay ); } delay = setTimeout ( callback, timeout ); this.delays[ id ] = delay; }, range : function ( min, max ) { var result = []; while ( min <= max ) { result.push ( min++ ); } return result; } }; var array = { every: function (array, test) { for (var i = 0; i < array.length; i++) { if (!test(array[i], i, array)) return false; } return true; }, filter: function (array, test) { var result = []; for (var i = 0; i < array.length; i++) { test(array[i], i, array) && result.push(array[i]); } return result; }, map: function (array, mapper) { var result = []; for (var i = 0; i < array.length; i++) { result.push(mapper(array[i], i, array)); } return result; }, forEach: function (array, mapper) { for (var i = 0; i < array.length; i++) { mapper(array[i], i, array); } } }; var lang = { mixin: function (to, from) { for (var key in from) { if (from.hasOwnProperty(key)) { to[key] = from[key]; } } return to; } }; var string = { substitute: function (pattern, map) { for (var key in map) { if (map.hasOwnProperty(key)) { pattern = pattern.replace("${" + key + "}", map[key]); } } return pattern; } };