add meteor frontend app
@@ -0,0 +1,26 @@
|
||||
(function(){/* Services */
|
||||
|
||||
_ = lodash;
|
||||
|
||||
socket = new Primus({url: 'wss://stats.ethdev.com'});
|
||||
|
||||
toastr = window.toastr;
|
||||
toastr.options = {
|
||||
"closeButton": false,
|
||||
"debug": false,
|
||||
"progressBar": false,
|
||||
"newestOnTop": true,
|
||||
"positionClass": "toast-top-right",
|
||||
"preventDuplicates": false,
|
||||
"onclick": null,
|
||||
"showDuration": "300",
|
||||
"hideDuration": "1000",
|
||||
"timeOut": "5000",
|
||||
"extendedTimeOut": "1000",
|
||||
"showEasing": "swing",
|
||||
"hideEasing": "linear",
|
||||
"showMethod": "fadeIn",
|
||||
"hideMethod": "fadeOut"
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,670 @@
|
||||
(function(){// Collections
|
||||
|
||||
Blockchain = new Mongo.Collection('blockchain', {connection: null});
|
||||
Nodes = new Mongo.Collection('nodes', {connection: null});
|
||||
Map = new Mongo.Collection('map', {connection: null});
|
||||
|
||||
|
||||
|
||||
/* Controllers */
|
||||
|
||||
|
||||
var MAX_BINS = 40;
|
||||
|
||||
// Main Stats init
|
||||
// ---------------
|
||||
|
||||
Blockchain.insert({
|
||||
_id: 'meta',
|
||||
frontierHash: '0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa',
|
||||
nodesTotal: 0,
|
||||
nodesActive: 0,
|
||||
bestBlock: 0,
|
||||
lastBlock: 0,
|
||||
lastDifficulty: 0,
|
||||
upTimeTotal: 0,
|
||||
avgBlockTime: 0,
|
||||
blockPropagationAvg: 0,
|
||||
avgHashrate: 0,
|
||||
uncleCount: 0,
|
||||
bestStats: {},
|
||||
|
||||
lastBlocksTime: _.fill(Array(MAX_BINS), 2),
|
||||
difficultyChart: _.fill(Array(MAX_BINS), 2),
|
||||
transactionDensity: _.fill(Array(MAX_BINS), 2),
|
||||
gasSpending: _.fill(Array(MAX_BINS), 2),
|
||||
miners: [],
|
||||
|
||||
map: [],
|
||||
blockPropagationChart: [],
|
||||
uncleCountChart: _.fill(Array(MAX_BINS), 2),
|
||||
coinbases: [],
|
||||
|
||||
latency: 0,
|
||||
|
||||
currentApiVersion: "0.0.16",
|
||||
|
||||
predicate: localStorage.predicate || ['-pinned', '-stats.active', '-stats.block.number', 'stats.block.propagation'],
|
||||
reverse: localStorage.reverse || false,
|
||||
pinned: localStorage.pinned || [],
|
||||
|
||||
prefixPredicate: ['-pinned', '-stats.active'],
|
||||
originalPredicate: ['-stats.block.number', 'stats.block.propagation']
|
||||
});
|
||||
|
||||
|
||||
// $scope.orderTable = function(predicate, reverse)
|
||||
// {
|
||||
// if(!_.isEqual(predicate, $scope.originalPredicate))
|
||||
// {
|
||||
// $scope.reverse = reverse;
|
||||
// $scope.originalPredicate = predicate;
|
||||
// $scope.predicate = _.union($scope.prefixPredicate, predicate);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// $scope.reverse = !$scope.reverse;
|
||||
|
||||
// if($scope.reverse === true){
|
||||
// _.forEach(predicate, function (value, key) {
|
||||
// predicate[key] = (value[0] === '-' ? value.replace('-', '') : '-' + value);
|
||||
// });
|
||||
// }
|
||||
|
||||
// $scope.predicate = _.union($scope.prefixPredicate, predicate);
|
||||
// }
|
||||
|
||||
// localStorage.predicate = $scope.predicate;
|
||||
// localStorage.reverse = $scope.reverse;
|
||||
// }
|
||||
|
||||
// $scope.pinNode = function(id)
|
||||
// {
|
||||
// index = findIndex({id: id});
|
||||
|
||||
// if( !_.isUndefined($scope.nodes[index]) )
|
||||
// {
|
||||
// $scope.nodes[index].pinned = !$scope.nodes[index].pinned;
|
||||
|
||||
// if($scope.nodes[index].pinned)
|
||||
// {
|
||||
// $scope.pinned.push(id);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// $scope.pinned.splice($scope.pinned.indexOf(id), 1);
|
||||
// }
|
||||
// }
|
||||
|
||||
// localStorage.pinned = $scope.pinned;
|
||||
// }
|
||||
|
||||
// var timeout = setInterval(function ()
|
||||
// {
|
||||
// $scope.$apply();
|
||||
// }, 300);
|
||||
|
||||
// $scope.getNumber = function (num) {
|
||||
// return new Array(num);
|
||||
// }
|
||||
|
||||
// Socket listeners
|
||||
// ----------------
|
||||
|
||||
socket.on('open', function open() {
|
||||
socket.emit('ready');
|
||||
console.log('The connection has been opened.');
|
||||
})
|
||||
.on('end', function end() {
|
||||
console.log('Socket connection ended.')
|
||||
})
|
||||
.on('error', function error(err) {
|
||||
console.log(err);
|
||||
})
|
||||
.on('reconnecting', function reconnecting(opts) {
|
||||
console.log('We are scheduling a reconnect operation', opts);
|
||||
})
|
||||
.on('data', function incoming(data) {
|
||||
socketAction(data.action, data.data);
|
||||
});
|
||||
|
||||
socket.on('init', function(data)
|
||||
{
|
||||
_.each(data.nodes, function(node){
|
||||
Nodes.upsert(node.id, socketAction('init', node));
|
||||
|
||||
addToMap(node);
|
||||
});
|
||||
});
|
||||
|
||||
socket.on('client-latency', function(data)
|
||||
{
|
||||
Blockchain.update('meta', {$set: {
|
||||
latency: data.latency
|
||||
}});
|
||||
})
|
||||
|
||||
function socketAction(action, data)
|
||||
{
|
||||
// console.log('Action: ', action);
|
||||
// console.log('Data: ', data);
|
||||
|
||||
switch(action)
|
||||
{
|
||||
case "init":
|
||||
var node = data;
|
||||
|
||||
// Init hashrate
|
||||
if( _.isUndefined(node.stats.hashrate) )
|
||||
node.stats.hashrate = 0;
|
||||
|
||||
// Init latency
|
||||
latencyFilter(node);
|
||||
|
||||
// Init history
|
||||
if( _.isUndefined(data.history) )
|
||||
{
|
||||
data.history = new Array(40);
|
||||
_.fill(data.history, -1);
|
||||
}
|
||||
|
||||
// Init or recover pin
|
||||
node.pinned = (Blockchain.findOne().pinned.indexOf(node.id) >= 0 ? true : false);
|
||||
|
||||
if( Nodes.find().count() > 0 )
|
||||
{
|
||||
toastr['success']("Got nodes list", "Got nodes!");
|
||||
|
||||
updateActiveNodes();
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
case "add":
|
||||
|
||||
if( addNewNode(data) )
|
||||
toastr['success']("New node "+ Nodes.findOne(data.id).info.name +" connected!", "New node!");
|
||||
else
|
||||
toastr['info']("Node "+ Nodes.findOne(data.id).info.name +" reconnected!", "Node is back!");
|
||||
|
||||
break;
|
||||
|
||||
// TODO: Remove when everybody updates api client to 0.0.12
|
||||
case "update":
|
||||
var foundNode = Nodes.findOne(data.id);
|
||||
|
||||
if( foundNode && !_.isUndefined(foundNode.stats) )
|
||||
{
|
||||
if( !_.isUndefined(foundNode.stats.latency) )
|
||||
data.stats.latency = foundNode.stats.latency;
|
||||
|
||||
if( _.isUndefined(data.stats.hashrate) )
|
||||
data.stats.hashrate = 0;
|
||||
|
||||
if( foundNode.stats.block.number < data.stats.block.number )
|
||||
{
|
||||
|
||||
var best = Nodes.findOne({},{sort: {'stats.block.number': -1}});
|
||||
|
||||
if(best) {
|
||||
if (data.block.number > best.stats.block.number) {
|
||||
data.block.arrived = _.now();
|
||||
} else {
|
||||
data.block.arrived = best.stats.block.arrived;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
foundNode.history = data.history;
|
||||
}
|
||||
|
||||
foundNode.stats = data.stats;
|
||||
foundNode.stats.block = data.block; // necessary?
|
||||
|
||||
if( !_.isUndefined(data.stats.latency) && _.get(foundNode, 'stats.latency', 0) !== data.stats.latency )
|
||||
{
|
||||
foundNode.stats.latency = data.stats.latency;
|
||||
|
||||
latencyFilter(foundNode);
|
||||
}
|
||||
|
||||
Nodes.update(data.id, foundNode);
|
||||
|
||||
updateBestBlock();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "block":
|
||||
var foundNode = Nodes.findOne(data.id);
|
||||
if( foundNode && foundNode.stats )
|
||||
{
|
||||
var set = {};
|
||||
|
||||
if( foundNode.stats.block.number < data.block.number )
|
||||
{
|
||||
var best = Nodes.findOne({},{sort: {'stats.block.number': -1}});
|
||||
|
||||
if(best) {
|
||||
if (data.block.number > best.stats.block.number) {
|
||||
data.block.arrived = _.now();
|
||||
} else {
|
||||
data.block.arrived = best.stats.block.arrived;
|
||||
}
|
||||
}
|
||||
|
||||
set.history = data.history;
|
||||
}
|
||||
|
||||
set['stats.block'] = data.block;
|
||||
set['stats.propagationAvg'] = data.propagationAvg;
|
||||
|
||||
Nodes.update('meta', {$set: set});
|
||||
|
||||
updateBestBlock();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "pending":
|
||||
var foundNode = Nodes.findOne(data.id);
|
||||
|
||||
if( !_.isUndefined(data.id) && foundNode )
|
||||
{
|
||||
|
||||
if( !_.isUndefined(foundNode) && !_.isUndefined(foundNode.stats.pending) && !_.isUndefined(data.pending) )
|
||||
Nodes.update(data.id, {$set: {
|
||||
'stats.pending': data.pending
|
||||
}});
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "stats":
|
||||
var foundNode = Nodes.findOne(data.id);
|
||||
|
||||
if( !_.isUndefined(data.id) && foundNode )
|
||||
{
|
||||
|
||||
if( !_.isUndefined(foundNode) && !_.isUndefined(foundNode.stats) )
|
||||
{
|
||||
Nodes.update(foundNode._id, {$set:{
|
||||
'stats.active': data.stats.active,
|
||||
'stats.mining': data.stats.mining,
|
||||
'stats.hashrate': data.stats.hashrate,
|
||||
'stats.peers': data.stats.peers,
|
||||
'stats.gasPrice': data.stats.gasPrice,
|
||||
'stats.uptime': data.stats.uptime
|
||||
}});
|
||||
|
||||
if( !_.isUndefined(data.stats.latency) && _.get(foundNode, 'stats.latency', 0) !== data.stats.latency )
|
||||
{
|
||||
Nodes.update(foundNode._id, {$set:{
|
||||
'stats.latency': data.stats.latency
|
||||
}});
|
||||
|
||||
latencyFilter(foundNode);
|
||||
}
|
||||
|
||||
updateActiveNodes();
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "info":
|
||||
var foundNode = Nodes.findOne(data.id);
|
||||
|
||||
if( foundNode )
|
||||
{
|
||||
var set = {};
|
||||
|
||||
set.info = data.info;
|
||||
|
||||
if( _.isUndefined(foundNode.pinned) )
|
||||
set.pinned = false;
|
||||
|
||||
Nodes.update(data.id, {$set: set});
|
||||
|
||||
// Init latency
|
||||
latencyFilter(foundNode);
|
||||
|
||||
updateActiveNodes();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "blockPropagationChart":
|
||||
Blockchain.update('meta', {$set:{
|
||||
blockPropagationChart: data.histogram,
|
||||
blockPropagationAvg: data.avg
|
||||
}});
|
||||
|
||||
break;
|
||||
|
||||
case "uncleCount":
|
||||
Blockchain.update('meta', {$set:{
|
||||
uncleCount: data[0] + data[1],
|
||||
uncleCountChart: (function(){
|
||||
data.reverse();
|
||||
return data;
|
||||
})()
|
||||
}});
|
||||
|
||||
break;
|
||||
|
||||
case "charts":
|
||||
var meta = Blockchain.findOne('meta');
|
||||
|
||||
if( !_.isEqual(meta.avgBlockTime, data.avgBlocktime) )
|
||||
meta.avgBlockTime = data.avgBlocktime;
|
||||
|
||||
if( !_.isEqual(meta.avgHashrate, data.avgHashrate) )
|
||||
meta.avgHashrate = data.avgHashrate;
|
||||
|
||||
if( !_.isEqual(meta.lastBlocksTime, data.blocktime) && data.blocktime.length >= MAX_BINS )
|
||||
meta.lastBlocksTime = data.blocktime;
|
||||
|
||||
if( !_.isEqual(meta.difficultyChart, data.difficulty) && data.difficulty.length >= MAX_BINS )
|
||||
meta.difficultyChart = data.difficulty;
|
||||
|
||||
if( !_.isEqual(meta.blockPropagationChart, data.propagation.histogram) ) {
|
||||
meta.blockPropagationChart = data.propagation.histogram;
|
||||
meta.blockPropagationAvg = data.propagation.avg;
|
||||
}
|
||||
|
||||
data.uncleCount.reverse();
|
||||
|
||||
if( !_.isEqual(meta.uncleCountChart, data.uncleCount) && data.uncleCount.length >= MAX_BINS ) {
|
||||
meta.uncleCount = data.uncleCount[data.uncleCount.length-2] + data.uncleCount[data.uncleCount.length-1];
|
||||
meta.uncleCountChart = data.uncleCount;
|
||||
}
|
||||
|
||||
if( !_.isEqual(meta.transactionDensity, data.transactions) && data.transactions.length >= MAX_BINS )
|
||||
meta.transactionDensity = data.transactions;
|
||||
|
||||
if( !_.isEqual(meta.gasSpending, data.gasSpending) && data.gasSpending.length >= MAX_BINS )
|
||||
meta.gasSpending = data.gasSpending;
|
||||
|
||||
if( !_.isEqual(meta.miners, data.miners) ) {
|
||||
meta.miners = data.miners;
|
||||
getMinersNames(meta);
|
||||
}
|
||||
|
||||
// update
|
||||
delete meta._id;
|
||||
Blockchain.update('meta', {$set: meta});
|
||||
|
||||
break;
|
||||
|
||||
case "inactive":
|
||||
var foundNode = Nodes.findOne(data.id);
|
||||
|
||||
if( foundNode )
|
||||
{
|
||||
if( !_.isUndefined(data.stats) ) {
|
||||
Nodes.update(data.id, {$set: {
|
||||
stats: data.stats
|
||||
}});
|
||||
}
|
||||
|
||||
toastr['error']("Node "+ foundNode.info.name +" went away!", "Node connection was lost!");
|
||||
|
||||
updateActiveNodes();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "latency":
|
||||
if( !_.isUndefined(data.id) && !_.isUndefined(data.latency) )
|
||||
{
|
||||
var foundNode = Nodes.findOne(data.id);
|
||||
|
||||
if( foundNode )
|
||||
{
|
||||
|
||||
if( !_.isUndefined(foundNode) && !_.isUndefined(foundNode.stats) && !_.isUndefined(foundNode.stats.latency) && foundNode.stats.latency !== data.latency )
|
||||
{
|
||||
Nodes.update(data.id, {$set: {
|
||||
'stats.latency': data.latency
|
||||
}});
|
||||
|
||||
latencyFilter(foundNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "client-ping":
|
||||
socket.emit('client-pong', {
|
||||
serverTime: data.serverTime,
|
||||
clientTime: _.now()
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
// $scope.$apply();
|
||||
}
|
||||
|
||||
|
||||
function getMinersNames(meta)
|
||||
{
|
||||
if( meta.miners.length > 0 )
|
||||
{
|
||||
_.forIn(meta.miners, function (value, key)
|
||||
{
|
||||
if(value.name !== false)
|
||||
return;
|
||||
|
||||
if(value.miner === "0x0000000000000000000000000000000000000000")
|
||||
return;
|
||||
|
||||
if(miner = Nodes.findOne({'info.coinbase': value.miner}))
|
||||
var name = miner.info.name;
|
||||
|
||||
if( !_.isUndefined(name) ) {
|
||||
meta.miners[key].name = name;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return meta;
|
||||
}
|
||||
|
||||
function addNewNode(data)
|
||||
{
|
||||
var foundNode = Nodes.findOne(data.id);
|
||||
|
||||
if( _.isUndefined(data.history) )
|
||||
{
|
||||
data.history = new Array(40);
|
||||
_.fill(data.history, -1);
|
||||
}
|
||||
|
||||
|
||||
data.pinned = ( !_.isUndefined(foundNode.pinned) ? foundNode.pinned : false);
|
||||
|
||||
if( !_.isUndefined(foundNode.history) )
|
||||
{
|
||||
data.history = foundNode.history;
|
||||
}
|
||||
|
||||
// update node
|
||||
Nodes.upsert(data.id, {$set: data});
|
||||
|
||||
addToMap(data);
|
||||
|
||||
updateActiveNodes();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function addToMap(data) {
|
||||
// add to map
|
||||
var bestblock = Blockchain.findOne().bestBlock;
|
||||
|
||||
if(!Map.findOne(data.id) && data.geo != null)
|
||||
Map.insert({
|
||||
_id: data.id,
|
||||
radius: 3,
|
||||
latitude: data.geo.ll[0],
|
||||
longitude: data.geo.ll[1],
|
||||
nodeName: data.info.name,
|
||||
fillClass: mainClass(data.stats, bestblock),
|
||||
fillKey: mainClass(data.stats, bestblock).replace('text-', ''),
|
||||
});
|
||||
}
|
||||
|
||||
function updateActiveNodes()
|
||||
{
|
||||
updateBestBlock();
|
||||
|
||||
var nodesTotal = Nodes.find().count(),
|
||||
nodesActive = 0,
|
||||
upTimeTotal = 0;
|
||||
|
||||
// iterate over all nodes to get the correct data
|
||||
_.each(Nodes.find().fetch(), function(node){
|
||||
|
||||
if(node.stats) {
|
||||
if(node.stats.active)
|
||||
nodesActive++
|
||||
|
||||
upTimeTotal += node.stats.uptime;
|
||||
}
|
||||
});
|
||||
|
||||
Blockchain.update('meta', {$set: {
|
||||
|
||||
nodesTotal: nodesTotal,
|
||||
nodesActive: nodesActive,
|
||||
upTimeTotal: upTimeTotal / nodesTotal
|
||||
}});
|
||||
}
|
||||
|
||||
function updateBestBlock()
|
||||
{
|
||||
if( Nodes.find().count() )
|
||||
{
|
||||
// var chains = {};
|
||||
// var maxScore = 0;
|
||||
|
||||
// _($scope.nodes)
|
||||
// .map(function (item)
|
||||
// {
|
||||
// maxScore += (item.trusted ? 50 : 1);
|
||||
|
||||
// if( _.isUndefined(chains[item.stats.block.number]) )
|
||||
// chains[item.stats.block.number] = [];
|
||||
|
||||
// if( _.isUndefined(chains[item.stats.block.number][item.stats.block.fork]) )
|
||||
// chains[item.stats.block.number][item.stats.block.fork] = {
|
||||
// fork: item.stats.block.fork,
|
||||
// count: 0,
|
||||
// trusted: 0,
|
||||
// score: 0
|
||||
// };
|
||||
|
||||
// if(item.stats.block.trusted)
|
||||
// chains[item.stats.block.number][item.stats.block.fork].trusted++;
|
||||
// else
|
||||
// chains[item.stats.block.number][item.stats.block.fork].count++;
|
||||
|
||||
// chains[item.stats.block.number][item.stats.block.fork].score = chains[item.stats.block.number][item.stats.block.fork].trusted * 50 + chains[item.stats.block.number][item.stats.block.fork].count;
|
||||
// })
|
||||
// .value();
|
||||
|
||||
// $scope.maxScore = maxScore;
|
||||
// $scope.chains = _.reduce(chains, function (result, item, key)
|
||||
// {
|
||||
// result[key] = _.max(item, 'score');
|
||||
// return result;
|
||||
// }, {});
|
||||
|
||||
var bestBlock = Nodes.findOne({'stats.block.number': {$exists: true}},{sort: {'stats.block.number': -1}});
|
||||
if( bestBlock && bestBlock.stats.block.number !== Blockchain.findOne().bestBlock )
|
||||
{
|
||||
console.log('bestblock', bestBlock.stats.block.number);
|
||||
|
||||
Blockchain.update('meta', {$set: {
|
||||
bestBlock: bestBlock.stats.block.number,
|
||||
bestStats: bestBlock.stats,
|
||||
lastBlock: bestBlock.stats.block.arrived,
|
||||
lastDifficulty: bestBlock.stats.block.difficulty
|
||||
}});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// function forkFilter(node)
|
||||
// {
|
||||
// if( _.isUndefined(node.readable) )
|
||||
// node.readable = {};
|
||||
|
||||
// node.readable.forkClass = 'hidden';
|
||||
// node.readable.forkMessage = '';
|
||||
|
||||
// return true;
|
||||
|
||||
// if( $scope.chains[node.stats.block.number].fork === node.stats.block.fork && $scope.chains[node.stats.block.number].score / $scope.maxScore >= 0.5 )
|
||||
// {
|
||||
// node.readable.forkClass = 'hidden';
|
||||
// node.readable.forkMessage = '';
|
||||
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// if( $scope.chains[node.stats.block.number].fork !== node.stats.block.fork )
|
||||
// {
|
||||
// node.readable.forkClass = 'text-danger';
|
||||
// node.readable.forkMessage = 'Wrong chain.<br/>This chain is a fork.';
|
||||
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// if( $scope.chains[node.stats.block.number].score / $scope.maxScore < 0.5)
|
||||
// {
|
||||
// node.readable.forkClass = 'text-warning';
|
||||
// node.readable.forkMessage = 'May not be main chain.<br/>Waiting for more confirmations.';
|
||||
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
function latencyFilter(node)
|
||||
{
|
||||
// var set = {};
|
||||
// if( _.isUndefined(node.readable) )
|
||||
// set['node.readable'] = {};
|
||||
|
||||
// if( _.isUndefined(node.stats) ) {
|
||||
// set['readable.latencyClass'] = 'text-danger';
|
||||
// set['readable.latency'] = 'offline';
|
||||
// }
|
||||
|
||||
// if (node.stats.active === false)
|
||||
// {
|
||||
// set['readable.latencyClass'] = 'text-danger';
|
||||
// set['readable.latency'] = 'offline';
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if (node.stats.latency <= 100)
|
||||
// set['readable.latencyClass'] = 'text-success';
|
||||
|
||||
// if (node.stats.latency > 100 && node.stats.latency <= 1000)
|
||||
// set['readable.latencyClass'] = 'text-warning';
|
||||
|
||||
// if (node.stats.latency > 1000)
|
||||
// set['readable.latencyClass'] = 'text-danger';
|
||||
|
||||
// set['readable.latency'] = node.stats.latency + ' ms';
|
||||
// }
|
||||
|
||||
// // update node
|
||||
// Nodes.upsert(node.id, {$set: set});
|
||||
}
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,24 @@
|
||||
(function(){mainClass = function(node, bestBlock)
|
||||
{
|
||||
|
||||
if(!node)
|
||||
return;
|
||||
|
||||
if( ! node.active)
|
||||
return 'text-gray';
|
||||
|
||||
if(node.peers === 0)
|
||||
return 'text-danger';
|
||||
|
||||
return peerClass(node.peers, node.active);
|
||||
}
|
||||
|
||||
peerClass = function(peers, active)
|
||||
{
|
||||
if( ! active)
|
||||
return 'text-gray';
|
||||
|
||||
return (peers <= 1 ? 'text-danger' : (peers > 1 && peers < 4 ? 'text-warning' : 'text-success'));
|
||||
}
|
||||
|
||||
})();
|
||||
14
web-app/.meteor/local/build/programs/web.browser/app/client/js/lib/bootstrap.min.js
vendored
Normal file
3
web-app/.meteor/local/build/programs/web.browser/app/client/js/lib/d3.tip.min.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
(function(){d3.tip=function(){function t(t){v=d(t),w=v.createSVGPoint(),document.body.appendChild(x)}function e(){return"n"}function n(){return[0,0]}function r(){return" "}function o(){var t=y();return{top:t.n.y-x.offsetHeight,left:t.n.x-x.offsetWidth/2}}function l(){var t=y();return{top:t.s.y,left:t.s.x-x.offsetWidth/2}}function s(){var t=y();return{top:t.e.y-x.offsetHeight/2,left:t.e.x}}function f(){var t=y();return{top:t.w.y-x.offsetHeight/2,left:t.w.x-x.offsetWidth}}function i(){var t=y();return{top:t.nw.y-x.offsetHeight,left:t.nw.x-x.offsetWidth}}function u(){var t=y();return{top:t.ne.y-x.offsetHeight,left:t.ne.x}}function a(){var t=y();return{top:t.sw.y,left:t.sw.x-x.offsetWidth}}function c(){var t=y();return{top:t.se.y,left:t.e.x}}function p(){var t=d3.select(document.createElement("div"));return t.style({position:"absolute",opacity:0,pointerEvents:"none",boxSizing:"border-box"}),t.node()}function d(t){return t=t.node(),"svg"==t.tagName.toLowerCase()?t:t.ownerSVGElement}function y(){var t=T||d3.event.target,e={},n=t.getScreenCTM(),r=t.getBBox(),o=r.width,l=r.height,s=r.x,f=r.y,i=document.documentElement.scrollTop||document.body.scrollTop,u=document.documentElement.scrollLeft||document.body.scrollLeft;return w.x=s+u,w.y=f+i,e.nw=w.matrixTransform(n),w.x+=o,e.ne=w.matrixTransform(n),w.y+=l,e.se=w.matrixTransform(n),w.x-=o,e.sw=w.matrixTransform(n),w.y-=l/2,e.w=w.matrixTransform(n),w.x+=o,e.e=w.matrixTransform(n),w.x-=o/2,w.y-=l/2,e.n=w.matrixTransform(n),w.y+=l,e.s=w.matrixTransform(n),e}var m=e,g=n,h=r,x=p(),v=null,w=null,T=null;t.show=function(){var e=Array.prototype.slice.call(arguments);e[e.length-1]instanceof SVGElement&&(T=e.pop());var n,r=h.apply(this,e),o=g.apply(this,e),l=m.apply(this,e),s=d3.select(x),f=0;for(s.html(r).style({opacity:1,"pointer-events":"all"});f--;)s.classed(E[f],!1);return n=b.get(l).apply(this),s.classed(l,!0).style({top:n.top+o[0]+"px",left:n.left+o[1]+"px"}),t},t.hide=function(){return nodel=d3.select(x),nodel.style({opacity:0,"pointer-events":"none"}),t},t.attr=function(e){if(arguments.length<2&&"string"==typeof e)return d3.select(x).attr(e);var n=Array.prototype.slice.call(arguments);return d3.selection.prototype.attr.apply(d3.select(x),n),t},t.style=function(e){if(arguments.length<2&&"string"==typeof e)return d3.select(x).style(e);var n=Array.prototype.slice.call(arguments);return d3.selection.prototype.style.apply(d3.select(x),n),t},t.direction=function(e){return arguments.length?(m=null==e?e:d3.functor(e),t):m},t.offset=function(e){return arguments.length?(g=null==e?e:d3.functor(e),t):g},t.html=function(e){return arguments.length?(h=null==e?e:d3.functor(e),t):h};var b=d3.map({n:o,s:l,e:s,w:f,nw:i,ne:u,sw:a,se:c}),E=b.keys();return t};
|
||||
|
||||
})();
|
||||
4
web-app/.meteor/local/build/programs/web.browser/app/client/js/lib/datamaps.min.js
vendored
Normal file
7
web-app/.meteor/local/build/programs/web.browser/app/client/js/lib/jquery.sparkline.min.js
vendored
Normal file
3
web-app/.meteor/local/build/programs/web.browser/app/client/js/lib/moment.en.min.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
(function(){!function(e){"function"==typeof define&&define.amd?define(["moment"],e):"object"==typeof exports?module.exports=e(require("../moment")):e(("undefined"!=typeof global?global:this).moment)}(function(e){return e.defineLocale("en-gb",{months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),monthsShort:"Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),weekdaysShort:"Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),weekdaysMin:"Su_Mo_Tu_We_Th_Fr_Sa".split("_"),longDateFormat:{LT:"HH:mm",LTS:"HH:mm:ss",L:"DD/MM/YYYY",LL:"D MMMM YYYY",LLL:"D MMMM YYYY LT",LLLL:"dddd, D MMMM YYYY LT"},calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},relativeTime:{future:"in %s",past:"%s ago",s:"a few sec",m:"1 min",mm:"%d min",h:"1 h",hh:"%d h",d:"a day",dd:"%d days",M:"a month",MM:"%d mon",y:"a year",yy:"%d years"},ordinalParse:/\d{1,2}(st|nd|rd|th)/,ordinal:function(e){var a=e%10,d=1===~~(e%100/10)?"th":1===a?"st":2===a?"nd":3===a?"rd":"th";return e+d},week:{dow:1,doy:4}})});
|
||||
|
||||
})();
|
||||
9
web-app/.meteor/local/build/programs/web.browser/app/client/js/lib/moment.min.js
vendored
Normal file
3
web-app/.meteor/local/build/programs/web.browser/app/client/js/lib/primus.min.js
vendored
Normal file
3
web-app/.meteor/local/build/programs/web.browser/app/client/js/lib/toastr.min.js
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
(function(){!function(e){e(["jquery"],function(e){return function(){function t(e,t,n){return f({type:O.error,iconClass:g().iconClasses.error,message:e,optionsOverride:n,title:t})}function n(t,n){return t||(t=g()),v=e("#"+t.containerId),v.length?v:(n&&(v=c(t)),v)}function i(e,t,n){return f({type:O.info,iconClass:g().iconClasses.info,message:e,optionsOverride:n,title:t})}function o(e){w=e}function s(e,t,n){return f({type:O.success,iconClass:g().iconClasses.success,message:e,optionsOverride:n,title:t})}function a(e,t,n){return f({type:O.warning,iconClass:g().iconClasses.warning,message:e,optionsOverride:n,title:t})}function r(e){var t=g();v||n(t),l(e,t)||u(t)}function d(t){var i=g();return v||n(i),t&&0===e(":focus",t).length?void h(t):void(v.children().length&&v.remove())}function u(t){for(var n=v.children(),i=n.length-1;i>=0;i--)l(e(n[i]),t)}function l(t,n){return t&&0===e(":focus",t).length?(t[n.hideMethod]({duration:n.hideDuration,easing:n.hideEasing,complete:function(){h(t)}}),!0):!1}function c(t){return v=e("<div/>").attr("id",t.containerId).addClass(t.positionClass).attr("aria-live","polite").attr("role","alert"),v.appendTo(e(t.target)),v}function p(){return{tapToDismiss:!0,toastClass:"toast",containerId:"toast-container",debug:!1,showMethod:"fadeIn",showDuration:300,showEasing:"swing",onShown:void 0,hideMethod:"fadeOut",hideDuration:1e3,hideEasing:"swing",onHidden:void 0,extendedTimeOut:1e3,iconClasses:{error:"toast-error",info:"toast-info",success:"toast-success",warning:"toast-warning"},iconClass:"toast-info",positionClass:"toast-top-right",timeOut:5e3,titleClass:"toast-title",messageClass:"toast-message",target:"body",closeHtml:"<button>×</button>",newestOnTop:!0,preventDuplicates:!1,progressBar:!1}}function m(e){w&&w(e)}function f(t){function i(t){return!e(":focus",l).length||t?(clearTimeout(O.intervalId),l[r.hideMethod]({duration:r.hideDuration,easing:r.hideEasing,complete:function(){h(l),r.onHidden&&"hidden"!==b.state&&r.onHidden(),b.state="hidden",b.endTime=new Date,m(b)}})):void 0}function o(){(r.timeOut>0||r.extendedTimeOut>0)&&(u=setTimeout(i,r.extendedTimeOut),O.maxHideTime=parseFloat(r.extendedTimeOut),O.hideEta=(new Date).getTime()+O.maxHideTime)}function s(){clearTimeout(u),O.hideEta=0,l.stop(!0,!0)[r.showMethod]({duration:r.showDuration,easing:r.showEasing})}function a(){var e=(O.hideEta-(new Date).getTime())/O.maxHideTime*100;f.width(e+"%")}var r=g(),d=t.iconClass||r.iconClass;if(r.preventDuplicates){if(t.message===C)return;C=t.message}"undefined"!=typeof t.optionsOverride&&(r=e.extend(r,t.optionsOverride),d=t.optionsOverride.iconClass||d),T++,v=n(r,!0);var u=null,l=e("<div/>"),c=e("<div/>"),p=e("<div/>"),f=e("<div/>"),w=e(r.closeHtml),O={intervalId:null,hideEta:null,maxHideTime:null},b={toastId:T,state:"visible",startTime:new Date,options:r,map:t};return t.iconClass&&l.addClass(r.toastClass).addClass(d),t.title&&(c.append(t.title).addClass(r.titleClass),l.append(c)),t.message&&(p.append(t.message).addClass(r.messageClass),l.append(p)),r.closeButton&&(w.addClass("toast-close-button").attr("role","button"),l.prepend(w)),r.progressBar&&(f.addClass("toast-progress"),l.prepend(f)),l.hide(),r.newestOnTop?v.prepend(l):v.append(l),l[r.showMethod]({duration:r.showDuration,easing:r.showEasing,complete:r.onShown}),r.timeOut>0&&(u=setTimeout(i,r.timeOut),O.maxHideTime=parseFloat(r.timeOut),O.hideEta=(new Date).getTime()+O.maxHideTime,r.progressBar&&(O.intervalId=setInterval(a,10))),l.hover(s,o),!r.onclick&&r.tapToDismiss&&l.click(i),r.closeButton&&w&&w.click(function(e){e.stopPropagation?e.stopPropagation():void 0!==e.cancelBubble&&e.cancelBubble!==!0&&(e.cancelBubble=!0),i(!0)}),r.onclick&&l.click(function(){r.onclick(),i()}),m(b),r.debug&&console&&console.log(b),l}function g(){return e.extend({},p(),b.options)}function h(e){v||(v=n()),e.is(":visible")||(e.remove(),e=null,0===v.children().length&&v.remove())}var v,w,C,T=0,O={error:"error",info:"info",success:"success",warning:"warning"},b={clear:r,remove:d,error:t,getContainer:n,info:i,options:{},subscribe:o,success:s,version:"2.1.0",warning:a};return b}()})}("function"==typeof define&&define.amd?define:function(e,t){"undefined"!=typeof module&&module.exports?module.exports=t(require("jquery")):window.toastr=t(window.jQuery)});
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,38 @@
|
||||
(function(){(function() {
|
||||
$('body').on('mouseenter', '[data-toggle="tooltip"]', function( event ) {
|
||||
$(this).tooltip('show');
|
||||
}).on('mouseleave', '[data-toggle="tooltip"]', function( event ) {
|
||||
$(this).tooltip('hide');
|
||||
});
|
||||
|
||||
$.fn.sparkline.defaults.bar.height = 63;
|
||||
$.fn.sparkline.defaults.bar.barWidth = 6;
|
||||
$.fn.sparkline.defaults.bar.barSpacing = 1;
|
||||
$.fn.sparkline.defaults.bar.tooltipClassname = 'jqstooltip';
|
||||
$.fn.sparkline.defaults.bar.tooltipOffsetX = 0;
|
||||
$.fn.sparkline.defaults.bar.tooltipFormat = $.spformat('<div class="tooltip-arrow"></div><div class="tooltip-inner">{{prefix}}{{value}} {{suffix}}</div>');
|
||||
$.fn.sparkline.defaults.bar.colorMap = $.range_map({
|
||||
'0:6': '#10a0de',
|
||||
'6:13': '#7bcc3a',
|
||||
'13:20': '#FFD162',
|
||||
'20:30': '#ff8a00',
|
||||
'30:': '#F74B4B'
|
||||
});
|
||||
|
||||
moment.relativeTimeThreshold('s', 60);
|
||||
moment.relativeTimeThreshold('m', 60);
|
||||
moment.relativeTimeThreshold('h', 24);
|
||||
moment.relativeTimeThreshold('d', 28);
|
||||
moment.relativeTimeThreshold('M', 12);
|
||||
|
||||
})();
|
||||
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-63657296-1', 'auto');
|
||||
ga('send', 'pageview');
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,649 @@
|
||||
(function(){
|
||||
function blockTimeClass(diff)
|
||||
{
|
||||
if(diff <= 13)
|
||||
return 'text-success';
|
||||
|
||||
if(diff <= 20)
|
||||
return 'text-warning';
|
||||
|
||||
if(diff <= 30)
|
||||
return 'text-orange';
|
||||
|
||||
return 'text-danger'
|
||||
}
|
||||
|
||||
function timeClass(timestamp)
|
||||
{
|
||||
var diff = ((new Date()).getTime() - timestamp)/1000;
|
||||
|
||||
return blockTimeClass(diff);
|
||||
}
|
||||
|
||||
function compareVersions(v1, comparator, v2)
|
||||
{
|
||||
comparator = comparator == '=' ? '==' : comparator;
|
||||
|
||||
var v1parts = v1.split('.'), v2parts = v2.split('.');
|
||||
var maxLen = Math.max(v1parts.length, v2parts.length);
|
||||
var part1, part2;
|
||||
var cmp = 0;
|
||||
|
||||
for(var i = 0; i < maxLen && !cmp; i++)
|
||||
{
|
||||
part1 = parseInt(v1parts[i], 10) || 0;
|
||||
part2 = parseInt(v2parts[i], 10) || 0;
|
||||
if(part1 < part2)
|
||||
cmp = 1;
|
||||
if(part1 > part2)
|
||||
cmp = -1;
|
||||
}
|
||||
|
||||
return eval('0' + comparator + cmp);
|
||||
}
|
||||
|
||||
function mainClass(node, bestBlock)
|
||||
{
|
||||
|
||||
if(!node)
|
||||
return;
|
||||
|
||||
if( ! node.active)
|
||||
return 'text-gray';
|
||||
|
||||
if(node.peers === 0)
|
||||
return 'text-danger';
|
||||
|
||||
return peerClass(node.peers, node.active);
|
||||
}
|
||||
|
||||
function peerClass(peers, active)
|
||||
{
|
||||
if( ! active)
|
||||
return 'text-gray';
|
||||
|
||||
return (peers <= 1 ? 'text-danger' : (peers > 1 && peers < 4 ? 'text-warning' : 'text-success'));
|
||||
}
|
||||
|
||||
|
||||
function blockTimeClass(diff)
|
||||
{
|
||||
if(diff <= 13)
|
||||
return 'text-success';
|
||||
|
||||
if(diff <= 20)
|
||||
return 'text-warning';
|
||||
|
||||
if(diff <= 30)
|
||||
return 'text-orange';
|
||||
|
||||
return 'text-danger'
|
||||
}
|
||||
|
||||
|
||||
// global template helpers
|
||||
|
||||
Template.registerHelper('Blockchain', function(){
|
||||
return Blockchain.findOne('meta');
|
||||
});
|
||||
|
||||
Template.registerHelper('nodes', function(uptime) {
|
||||
return Nodes.find({},{sort: {'stats.block.number': -1, 'stats.active': -1}});
|
||||
});
|
||||
|
||||
Template.registerHelper('number', function(number){
|
||||
return numeral(number).format('0,0');
|
||||
});
|
||||
|
||||
Template.registerHelper('avgTimeClass', function(time){
|
||||
return blockTimeClass(time);
|
||||
});
|
||||
|
||||
Template.registerHelper('blockTimeFilter', function(timestamp){
|
||||
if(timestamp === 0)
|
||||
return '∞';
|
||||
|
||||
// var time = Math.floor((new Date()).getTime() / 1000);
|
||||
var time = (new Date()).getTime();
|
||||
var diff = Math.floor((time - timestamp)/1000);
|
||||
|
||||
if(diff < 60)
|
||||
return Math.round(diff) + ' s ago';
|
||||
|
||||
return moment.duration(Math.round(diff), 's').humanize() + ' ago';
|
||||
});
|
||||
|
||||
|
||||
Template.registerHelper('timeClass', function(timestamp, active){
|
||||
if( _.isBoolean(active) && ! active)
|
||||
return 'text-gray';
|
||||
|
||||
return timeClass(timestamp);
|
||||
});
|
||||
|
||||
Template.registerHelper('avgTimeFilter', function(time){
|
||||
if(time < 60)
|
||||
return parseFloat(time).toFixed(2) + ' s';
|
||||
|
||||
return moment.duration(Math.round(time), 's').humanize();
|
||||
});
|
||||
|
||||
Template.registerHelper('networkHashrateFilter', function(hashes, isMining){
|
||||
if(hashes === null)
|
||||
hashes = 0;
|
||||
|
||||
var result = 0;
|
||||
var unit = 'K';
|
||||
|
||||
if(hashes !== 0 && hashes < 1000) {
|
||||
result = hashes;
|
||||
unit = '';
|
||||
}
|
||||
|
||||
if(hashes >= 1000 && hashes < Math.pow(1000, 2)) {
|
||||
result = hashes / 1000;
|
||||
unit = 'K';
|
||||
}
|
||||
|
||||
if(hashes >= Math.pow(1000, 2) && hashes < Math.pow(1000, 3)) {
|
||||
result = hashes / Math.pow(1000, 2);
|
||||
unit = 'M';
|
||||
}
|
||||
|
||||
if(hashes >= Math.pow(1000, 3) && hashes < Math.pow(1000, 4)) {
|
||||
result = hashes / Math.pow(1000, 3);
|
||||
unit = 'G';
|
||||
}
|
||||
|
||||
if(hashes >= Math.pow(1000, 4) && hashes < Math.pow(1000, 5)) {
|
||||
result = hashes / Math.pow(1000, 4);
|
||||
unit = 'T';
|
||||
}
|
||||
|
||||
if( !isMining )
|
||||
return new Spacebars.SafeString(result.toFixed(1) + ' <span class="small-hash">' + unit + 'H/s</span>');
|
||||
|
||||
return new Spacebars.SafeString('? <span class="small-hash">' + unit + 'KH/s</span>');
|
||||
});
|
||||
|
||||
|
||||
Template.registerHelper('nodesActiveClass', function(active, total) {
|
||||
var ratio = active/total;
|
||||
|
||||
if(ratio >= 0.9)
|
||||
return 'text-success';
|
||||
|
||||
if(ratio >= 0.75)
|
||||
return 'text-info';
|
||||
|
||||
if(ratio >= 0.5)
|
||||
return 'text-warning';
|
||||
|
||||
return 'text-danger';
|
||||
});
|
||||
|
||||
Template.registerHelper('gasPriceFilter', function(price) {
|
||||
if(typeof price === 'undefined')
|
||||
return "0 wei";
|
||||
|
||||
if(price.length < 4)
|
||||
return numeral(price).format('0,0') + " wei";
|
||||
|
||||
if(price.length < 7)
|
||||
return numeral(price/1000).format('0,0') + " kwei";
|
||||
|
||||
if(price.length < 10)
|
||||
return numeral(price/1000000).format('0,0') + " mwei";
|
||||
|
||||
if(price.length < 13)
|
||||
return numeral(price/1000000000).format('0,0') + " gwei";
|
||||
|
||||
if(price.length < 16)
|
||||
return numeral(price/1000000000000).format('0,0') + " szabo";
|
||||
|
||||
if(price.length < 19)
|
||||
return numeral(price.substr(0, price.length - 15)).format('0,0') + " finney";
|
||||
|
||||
return numeral(price.substr(0, price.length - 18)).format('0,0') + " ether";
|
||||
});
|
||||
|
||||
|
||||
Template.registerHelper('upTimeFilter', function(uptime) {
|
||||
return Math.round(uptime) + '%';
|
||||
});
|
||||
|
||||
Template.registerHelper('propagationAvgTimeClass', function(propagationAvg, active) {
|
||||
if( ! active)
|
||||
return 'text-gray';
|
||||
|
||||
if(propagationAvg == 0)
|
||||
return 'text-info';
|
||||
|
||||
if(propagationAvg < 1000)
|
||||
return 'text-success';
|
||||
|
||||
if(propagationAvg < 3000)
|
||||
return 'text-warning';
|
||||
|
||||
if(propagationAvg < 7000)
|
||||
return 'text-orange';
|
||||
|
||||
return 'text-danger'
|
||||
});
|
||||
|
||||
|
||||
Template.registerHelper('minerBlocksClass', function(blocks, prefix) {
|
||||
if(typeof prefix === 'undefined')
|
||||
prefix = 'bg-';
|
||||
if(blocks <= 6)
|
||||
return prefix + 'success';
|
||||
|
||||
if(blocks <= 12)
|
||||
return prefix + 'info';
|
||||
|
||||
if(blocks <= 18)
|
||||
return prefix + 'warning';
|
||||
|
||||
return prefix + 'danger';
|
||||
});
|
||||
|
||||
Template.registerHelper('latencyClass', function(active, latency) {
|
||||
if(active === false)
|
||||
return 'text-danger';
|
||||
|
||||
if(latency <= 100)
|
||||
return 'text-success';
|
||||
|
||||
if(latency <= 1000)
|
||||
return 'text-warning';
|
||||
|
||||
return 'text-danger'
|
||||
});
|
||||
|
||||
Template.registerHelper('upTimeClass', function(uptime, active) {
|
||||
if( active === false )
|
||||
return 'text-gray';
|
||||
|
||||
if(uptime >= 90)
|
||||
return 'text-success';
|
||||
|
||||
if(uptime >= 75)
|
||||
return 'text-warning';
|
||||
|
||||
return 'text-danger';
|
||||
});
|
||||
|
||||
|
||||
Template.registerHelper('nodePinClass', function(pinned) {
|
||||
if(pinned)
|
||||
return 'icon-check-o';
|
||||
|
||||
return 'icon-loader';
|
||||
});
|
||||
|
||||
Template.registerHelper('mainClass', function(node, bestBlock) {
|
||||
return mainClass(node, bestBlock);
|
||||
});
|
||||
|
||||
Template.registerHelper('peerClass', function(peers, active) {
|
||||
return peerClass(peers, active);
|
||||
});
|
||||
|
||||
Template.registerHelper('miningClass', function(mining, active) {
|
||||
if(! active)
|
||||
return 'text-gray';
|
||||
|
||||
return (! mining ? 'text-danger' : 'text-success');
|
||||
});
|
||||
|
||||
Template.registerHelper('miningIconClass', function(mining) {
|
||||
return (! mining ? 'icon-cancel' : 'icon-check');
|
||||
});
|
||||
|
||||
Template.registerHelper('hashrateClass', function(mining, active) {
|
||||
if(! mining || ! active)
|
||||
return 'text-gray';
|
||||
|
||||
return 'text-success';
|
||||
});
|
||||
|
||||
|
||||
Template.registerHelper('nodeClientClass', function(info, current) {
|
||||
if(typeof info === 'undefined' || typeof info.client === 'undefined' || typeof info.client === '')
|
||||
return 'text-danger';
|
||||
|
||||
if(compareVersions(info.client, '<', current))
|
||||
return 'text-danger';
|
||||
|
||||
return 'hidden';
|
||||
})
|
||||
|
||||
Template.registerHelper('consensusClass', function(nodes, bestBlock) {
|
||||
var status = 'success';
|
||||
var now = _.now();
|
||||
|
||||
for(var x = 0; x < nodes.length; x++)
|
||||
{
|
||||
if(nodes[x].stats.block.number === bestBlock.number && nodes[x].stats.block.hash !== bestBlock.hash)
|
||||
return 'danger';
|
||||
|
||||
if((bestBlock.number - nodes[x].stats.block.number) > 1 && (now - bestBlock.received) >= 20*1000)
|
||||
status = 'orange';
|
||||
|
||||
if((bestBlock.number - nodes[x].stats.block.number) === 1 && (now - bestBlock.received) >= 10*1000 && status !== 'orange')
|
||||
status = 'warning';
|
||||
}
|
||||
|
||||
return status;
|
||||
});
|
||||
|
||||
Template.registerHelper('consensusFilter', function(nodes, bestBlock) {
|
||||
var cnt = 0;
|
||||
|
||||
for(var x = 0; x < nodes.length; x++)
|
||||
{
|
||||
if(nodes[x].stats.block.number === bestBlock.number && nodes[x].stats.block.hash === bestBlock.hash)
|
||||
cnt++;
|
||||
}
|
||||
|
||||
return cnt + '/' + nodes.length;
|
||||
});
|
||||
|
||||
Template.registerHelper('geoTooltip', function(node) {
|
||||
var tooltip = [];
|
||||
var string = '';
|
||||
|
||||
if(!node.info)
|
||||
return;
|
||||
|
||||
if(node.info.node !== '' && typeof node.info.node !== 'undefined') {
|
||||
var eth_version = node.info.node.split('/');
|
||||
|
||||
if(eth_version[1][0] !== 'v' && eth_version[1][2] !== '.')
|
||||
{
|
||||
eth_version.splice(1,1);
|
||||
}
|
||||
|
||||
string = "<b>" + node.info.node + "</b>";
|
||||
tooltip.push(string);
|
||||
|
||||
string = "Version: <b>" + (eth_version[1]) + "</b>";
|
||||
tooltip.push(string);
|
||||
}
|
||||
|
||||
if(node.info.net !== '') {
|
||||
string = "Network: <b>" + (typeof node.info.net !== 'undefined' ? node.info.net : '-') + "</b>";
|
||||
|
||||
tooltip.push(string);
|
||||
}
|
||||
|
||||
if(node.info.protocol !== '') {
|
||||
string = "Protocol: <b>" + (typeof node.info.protocol !== 'undefined' ? node.info.protocol : '-') + "</b>";
|
||||
|
||||
tooltip.push(string);
|
||||
}
|
||||
|
||||
if(node.info.port !== '') {
|
||||
string = "Port: <b>" + (typeof node.info.port !== 'undefined' ? node.info.port : '30303') + "</b>";
|
||||
|
||||
tooltip.push(string);
|
||||
}
|
||||
|
||||
if(node.info.api !== '') {
|
||||
string = "Web3: <b>" + node.info.api + "</b>";
|
||||
|
||||
tooltip.push(string);
|
||||
}
|
||||
|
||||
if(node.info.client !== '') {
|
||||
string = "API: <b>" + (typeof node.info.client !== 'undefined' ? node.info.client : '<= 0.0.3') + "</b>";
|
||||
|
||||
tooltip.push(string);
|
||||
}
|
||||
|
||||
if(node.info.os !== '') {
|
||||
string = "OS: <b>" + (typeof node.info.os !== 'undefined' ? node.info.os + ' ' + node.info.os_v : '?') + "</b>";
|
||||
|
||||
tooltip.push(string);
|
||||
}
|
||||
|
||||
if(node.geo !== null)
|
||||
{
|
||||
string = "Location: <b>";
|
||||
|
||||
if(node.geo.city !== '')
|
||||
string += node.geo.city + ", ";
|
||||
string += node.geo.country + "</b>";
|
||||
|
||||
tooltip.push(string);
|
||||
}
|
||||
|
||||
if(node.info.contact !== '') {
|
||||
string = "Contact: <b>" + (typeof node.info.contact !== 'undefined' ? node.info.contact : '-') + "</b>";
|
||||
|
||||
tooltip.push(string);
|
||||
}
|
||||
|
||||
return tooltip.join("<br>");
|
||||
});
|
||||
|
||||
|
||||
Template.registerHelper('bubbleClass', function(node, bestBlock) {
|
||||
return mainClass(node, bestBlock).replace('text-', '');
|
||||
});
|
||||
|
||||
Template.registerHelper('minerNameFilter', function(address, name) {
|
||||
if(typeof name !== 'undefined' && name !== false && name.length > 0)
|
||||
return name;
|
||||
|
||||
return address.replace('0x', '');
|
||||
});
|
||||
|
||||
Template.registerHelper('blockPropagationFilter', function(ms, prefix) {
|
||||
if(!prefix)
|
||||
prefix = '+';
|
||||
|
||||
var result = 0;
|
||||
|
||||
if(ms < 1000) {
|
||||
return (ms === 0 ? "" : prefix) + ms + " ms";
|
||||
}
|
||||
|
||||
if(ms < 1000*60) {
|
||||
result = ms/1000;
|
||||
return prefix + result.toFixed(1) + " s";
|
||||
}
|
||||
|
||||
if(ms < 1000*60*60) {
|
||||
result = ms/1000/60;
|
||||
return prefix + Math.round(result) + " min";
|
||||
}
|
||||
|
||||
if(ms < 1000*60*60*24) {
|
||||
result = ms/1000/60/60;
|
||||
return prefix + Math.round(result) + " h";
|
||||
}
|
||||
|
||||
result = ms/1000/60/60/24;
|
||||
return prefix + Math.round(result) + " days";
|
||||
});
|
||||
|
||||
Template.registerHelper('blockPropagationAvgFilter', function(stats, bestBlock) {
|
||||
if(!stats)
|
||||
return;
|
||||
|
||||
var ms = stats.propagationAvg;
|
||||
|
||||
if(bestBlock - stats.block.number > 40)
|
||||
return "∞";
|
||||
//ms = _.now() - stats.block.received;
|
||||
|
||||
prefix = '';
|
||||
|
||||
var result = 0;
|
||||
|
||||
if(ms < 1000) {
|
||||
return (ms === 0 ? "" : prefix) + ms + " ms";
|
||||
}
|
||||
|
||||
if(ms < 1000*60) {
|
||||
result = ms/1000;
|
||||
return prefix + result.toFixed(1) + " s";
|
||||
}
|
||||
|
||||
if(ms < 1000*60*60) {
|
||||
result = ms/1000/60;
|
||||
return prefix + Math.round(result) + " min";
|
||||
}
|
||||
|
||||
if(ms < 1000*60*60*24) {
|
||||
result = ms/1000/60/60;
|
||||
return prefix + Math.round(result) + " h";
|
||||
}
|
||||
|
||||
result = ms/1000/60/60/24;
|
||||
return prefix + Math.round(result) + " days";
|
||||
});
|
||||
|
||||
|
||||
Template.registerHelper('propagationTimeClass', function(stats, bestBlock) {
|
||||
if( ! stats.active)
|
||||
return 'text-gray';
|
||||
|
||||
if(stats.block.number < bestBlock)
|
||||
return 'text-gray';
|
||||
|
||||
if(stats.block.propagation == 0)
|
||||
return 'text-info';
|
||||
|
||||
if(stats.block.propagation < 1000)
|
||||
return 'text-success';
|
||||
|
||||
if(stats.block.propagation < 3000)
|
||||
return 'text-warning';
|
||||
|
||||
if(stats.block.propagation < 7000)
|
||||
return 'text-orange';
|
||||
|
||||
return 'text-danger'
|
||||
});
|
||||
|
||||
Template.registerHelper('propagationNodeAvgTimeClass', function(stats, bestBlock) {
|
||||
if(!stats)
|
||||
return;
|
||||
|
||||
if( ! stats.active)
|
||||
return 'text-gray';
|
||||
|
||||
if(stats.block.number < bestBlock)
|
||||
return 'text-gray';
|
||||
|
||||
|
||||
if(stats.propagationAvg == 0)
|
||||
return 'text-info';
|
||||
|
||||
if(stats.propagationAvg < 1000)
|
||||
return 'text-success';
|
||||
|
||||
if(stats.propagationAvg < 3000)
|
||||
return 'text-warning';
|
||||
|
||||
if(stats.propagationAvg < 7000)
|
||||
return 'text-orange';
|
||||
|
||||
return 'text-danger'
|
||||
});
|
||||
|
||||
Template.registerHelper('hashrateFilter', function(hashes, isMining) {
|
||||
var result = 0;
|
||||
var unit = 'K';
|
||||
|
||||
if( !isMining )
|
||||
return new Spacebars.SafeString('<i class="icon-cancel"></i>');
|
||||
|
||||
if(hashes !== 0 && hashes < 1000) {
|
||||
result = hashes;
|
||||
unit = '';
|
||||
}
|
||||
|
||||
if(hashes >= 1000 && hashes < Math.pow(1000, 2)) {
|
||||
result = hashes / 1000;
|
||||
unit = 'K';
|
||||
}
|
||||
|
||||
if(hashes >= Math.pow(1000, 2) && hashes < Math.pow(1000, 3)) {
|
||||
result = hashes / Math.pow(1000, 2);
|
||||
unit = 'M';
|
||||
}
|
||||
|
||||
if(hashes >= Math.pow(1000, 3) && hashes < Math.pow(1000, 4)) {
|
||||
result = hashes / Math.pow(1000, 3);
|
||||
unit = 'G';
|
||||
}
|
||||
|
||||
if(hashes >= Math.pow(1000, 4) && hashes < Math.pow(1000, 5)) {
|
||||
result = hashes / Math.pow(1000, 4);
|
||||
unit = 'T';
|
||||
}
|
||||
|
||||
return new Spacebars.SafeString('<span class="small">' + numeral(result).format('0,0') + ' <span class="small-hash">' + unit + 'H/s</span></span>');
|
||||
});
|
||||
|
||||
Template.registerHelper('nodeVersion', function(version) {
|
||||
if(typeof version !== 'undefined')
|
||||
{
|
||||
var tmp = version.split('/');
|
||||
|
||||
tmp[0] = tmp[0].replace('Ethereum(++)', 'Eth');
|
||||
|
||||
if(tmp[0].indexOf('pyethapp') === 0)
|
||||
{
|
||||
tmp[0] = 'pyeth';
|
||||
}
|
||||
|
||||
if(tmp[1][0] !== 'v' && tmp[1][2] !== '.')
|
||||
{
|
||||
tmp.splice(1,1);
|
||||
}
|
||||
|
||||
if(tmp[2] === 'Release'){
|
||||
tmp.splice(2,1);
|
||||
}
|
||||
|
||||
if(tmp[2].indexOf('Linux') === 0)
|
||||
tmp[2] = 'linux';
|
||||
|
||||
if(tmp[2].indexOf('Darwin') === 0)
|
||||
tmp[2] = 'darwin';
|
||||
|
||||
return new Spacebars.SafeString(tmp.join('/'));
|
||||
}
|
||||
|
||||
return '';
|
||||
});
|
||||
|
||||
Template.registerHelper('blockClass', function(current, best) {
|
||||
if(!current)
|
||||
return;
|
||||
|
||||
if( ! current.active)
|
||||
return 'text-gray';
|
||||
|
||||
return (best - current.block.number < 1 ? 'text-success' : (best - current.block.number === 1 ? 'text-warning' : (best - current.block.number > 1 && best - current.block.number < 4 ? 'text-orange' : 'text-danger')));
|
||||
});
|
||||
|
||||
Template.registerHelper('gasFilter', function(gas) {
|
||||
return (typeof gas !== 'undefined' ? parseInt(gas) : '?');
|
||||
});
|
||||
|
||||
Template.registerHelper('hashFilter', function(hash) {
|
||||
if(typeof hash === 'undefined')
|
||||
return "?";
|
||||
|
||||
if(hash.substr(0,2) === '0x')
|
||||
hash = hash.substr(2,64);
|
||||
|
||||
return hash.substr(0, 8) + '...' + hash.substr(56, 8);
|
||||
});
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,14 @@
|
||||
(function(){
|
||||
Template.__checkName("error");
|
||||
Template["error"] = new Template("Template.error", (function() {
|
||||
var view = this;
|
||||
return [ HTML.H1(Blaze.View("lookup:message", function() {
|
||||
return Spacebars.mustache(view.lookup("message"));
|
||||
})), HTML.H2(Blaze.View("lookup:error.status", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("error"), "status"));
|
||||
})), HTML.PRE(Blaze.View("lookup:error.stack", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("error"), "stack"));
|
||||
})) ];
|
||||
}));
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,515 @@
|
||||
(function(){
|
||||
Template.__checkName("index");
|
||||
Template["index"] = new Template("Template.index", (function() {
|
||||
var view = this;
|
||||
return HTML.DIV({
|
||||
"class": "container-fluid",
|
||||
"ng-controller": "StatsCtrl"
|
||||
}, HTML.DIV({
|
||||
"class": "row"
|
||||
}, HTML.DIV({
|
||||
"class": [ "col-xs-2", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "big-info", " ", "bestblock", " ", "text-info" ]
|
||||
}, HTML.Raw('<div class="pull-left icon-full-width"><i class="icon-block"></i></div>'), "\n", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.Raw('<span class="small-title">best block</span>'), "\n", HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:number", function() {
|
||||
return Spacebars.mustache(view.lookup("number"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}))), "\n", HTML.Raw('<div class="clearfix"></div>'))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-2", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "big-info", " ", "uncleCount", " ", "text-info" ]
|
||||
}, HTML.Raw('<div class="pull-left icon-full-width"><i class="icon-uncle"></i></div>'), "\n", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.Raw('<span class="small-title">uncles \n<span class="small">(current / last 50)</span></span>'), "\n", HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:Blockchain.bestStats.block.uncles.length", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "bestStats", "block", "uncles", "length"));
|
||||
}), "/", Blaze.View("lookup:Blockchain.uncleCount", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "uncleCount"));
|
||||
}))), "\n", HTML.Raw('<div class="clearfix"></div>'))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-2", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "big-info", " ", "blocktime", " ", Spacebars.mustache(view.lookup("timeClass"), view.lookup("lastBlock"), true) ];
|
||||
}
|
||||
}, HTML.Raw('<div class="pull-left icon-full-width"><i class="icon-time"></i></div>'), "\n", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.Raw('<span class="small-title">last block</span>'), "\n", HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:blockTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("blockTimeFilter"), Spacebars.dot(view.lookup("Blockchain"), "lastBlock"));
|
||||
})), "\n", ""), "\n", HTML.Raw('<div class="clearfix"></div>'))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-2", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "big-info", " ", "avgblocktime", " ", Spacebars.mustache(view.lookup("avgTimeClass"), view.lookup("avgBlockTime")) ];
|
||||
}
|
||||
}, HTML.Raw('<div class="pull-left icon-full-width"><i class="icon-gas"></i></div>'), "\n", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.Raw('<span class="small-title">avg block time</span>'), "\n", HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:avgTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("avgTimeFilter"), Spacebars.dot(view.lookup("Blockchain"), "avgBlockTime"));
|
||||
}))), "\n", HTML.Raw('<div class="clearfix"></div>'))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-2", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "big-info", " ", "difficulty", " ", "text-orange" ]
|
||||
}, HTML.Raw('<div class="pull-left icon-full-width"><i class="icon-hashrate"></i></div>'), "\n", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.Raw('<span class="small-title">avg network hashrate</span>'), "\n", HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:networkHashrateFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("networkHashrateFilter"), Spacebars.dot(view.lookup("Blockchain"), "avgHashrate"), false);
|
||||
}))), "\n", HTML.Raw('<div class="clearfix"></div>'))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-2", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "big-info", " ", "difficulty", " ", "text-danger" ]
|
||||
}, HTML.Raw('<div class="pull-left icon-full-width"><i class="icon-difficulty"></i></div>'), "\n", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.Raw('<span class="small-title">difficulty</span>'), "\n", HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-hash"
|
||||
}, Blaze.View("lookup:number", function() {
|
||||
return Spacebars.mustache(view.lookup("number"), Spacebars.dot(view.lookup("Blockchain"), "lastDifficulty"));
|
||||
})))), "\n", HTML.Raw('<div class="clearfix"></div>'))), "\n", HTML.Raw('<div class="clearfix"></div>')), "\n", HTML.DIV({
|
||||
"class": "row"
|
||||
}, HTML.DIV({
|
||||
"class": [ "col-xs-8", " ", "stats-boxes" ],
|
||||
style: "padding-top: 0px;"
|
||||
}, HTML.DIV({
|
||||
"class": [ "row", " ", "second-row" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder", " ", "box" ]
|
||||
}, HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "active-nodes", " ", Spacebars.mustache(view.lookup("nodesActiveClass"), Spacebars.dot(view.lookup("Blockchain"), "nodesActive"), Spacebars.dot(view.lookup("Blockchain"), "nodesTotal")) ];
|
||||
}
|
||||
}, HTML.Raw('<i class="icon-node"></i>'), "\n", HTML.Raw('<span class="small-title">active nodes</span>'), "\n", HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:Blockchain.nodesActive", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "nodesActive"));
|
||||
}), "/", Blaze.View("lookup:Blockchain.nodesTotal", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "nodesTotal"));
|
||||
})))), "\n", "", "\n", "", "\n", "", "\n", "", "\n", "", "\n", HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder", " ", "box" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "gasprice", " ", "text-info" ]
|
||||
}, HTML.Raw('<i class="icon-gasprice"></i>'), "\n", HTML.Raw('<span class="small-title">gas price</span>'), "\n", HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:gasPriceFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("gasPriceFilter"), Spacebars.dot(view.lookup("Blockchain"), "bestStats", "gasPrice", "toString"));
|
||||
})))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder", " ", "box" ]
|
||||
}, HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "page-latency", " ", Spacebars.mustache(view.lookup("latencyClass"), true, Spacebars.dot(view.lookup("Blockchain"), "latency")) ];
|
||||
}
|
||||
}, HTML.Raw('<i class="icon-clock"></i>'), "\n", HTML.Raw('<span class="small-title">page latency</span>'), "\n", HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:Blockchain.latency", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "latency"));
|
||||
}), " ms"))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder", " ", "box" ]
|
||||
}, HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "uptime", " ", Spacebars.mustache(view.lookup("upTimeClass"), view.lookup("upTimeTotal"), true) ];
|
||||
}
|
||||
}, HTML.Raw('<i class="icon-bulb"></i>'), "\n", HTML.Raw('<span class="small-title">uptime</span>'), "\n", HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:upTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("upTimeFilter"), Spacebars.dot(view.lookup("Blockchain"), "upTimeTotal"));
|
||||
}))))), "\n", HTML.DIV({
|
||||
"class": "row"
|
||||
}, HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "big-info", " ", "chart", " ", Spacebars.mustache(view.lookup("avgTimeClass"), Spacebars.dot(view.lookup("Blockchain"), "avgBlockTime")) ];
|
||||
}
|
||||
}, "", "\n", HTML.Raw('<span class="small-title">block time</span>'), "\n", "", "\n", HTML.getTag("sparkchart")({
|
||||
"class": [ "big-details", " ", "spark-blocktimes" ],
|
||||
data: function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "lastBlocksTime", "join"));
|
||||
},
|
||||
tooltipsuffix: "s"
|
||||
}))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "big-info", " ", "chart", " ", "text-info" ]
|
||||
}, "", "\n", HTML.Raw('<span class="small-title">difficulty</span>'), "\n", "", "\n", HTML.getTag("sparkchart")({
|
||||
"class": [ "big-details", " ", "spark-difficulty" ],
|
||||
data: function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "difficultyChart", "join"));
|
||||
}
|
||||
}))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder", " ", "xpull-right" ]
|
||||
}, HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "big-info", " ", "chart", " ", "xdouble-chart", " ", Spacebars.mustache(view.lookup("propagationAvgTimeClass"), Spacebars.dot(view.lookup("Blockchain"), "blockPropagationAvg"), true) ];
|
||||
}
|
||||
}, "", "\n", HTML.Raw('<span class="small-title">block propagation</span>'), "\n", "", "\n", HTML.getTag("histogram")({
|
||||
"class": [ "big-details", " ", "d3-blockpropagation" ],
|
||||
data: "blockPropagationChart"
|
||||
}))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder", " ", "pull-right" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "big-info", " ", "chart", " ", "double-chart" ]
|
||||
}, HTML.Raw('<span class="small-title">last blocks miners</span>'), "\n", HTML.DIV({
|
||||
"class": "blocks-holder",
|
||||
"ng-repeat": "miner in miners track by miner.miner",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "right",
|
||||
"data-original-title": function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "miner", "blocks"));
|
||||
}
|
||||
}, HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "block-count", " ", Spacebars.mustache(view.lookup("minerBlocksClass"), Spacebars.dot(view.lookup("Blockchain"), "miner", "blocks"), "text-") ];
|
||||
}
|
||||
}, Blaze.View("lookup:miner.blocks", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("miner"), "blocks"));
|
||||
})), "\n", "", "\n", HTML.DIV({
|
||||
"class": "small-title-miner"
|
||||
}, Blaze.View("lookup:miner.miner", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("miner"), "miner"));
|
||||
})), "\n", HTML.getTag("minerblock")({
|
||||
blocks: function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "miner", "blocks"));
|
||||
}
|
||||
}), "\n", HTML.Raw('<div class="clearfix"></div>')))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "big-info", " ", "chart", " ", "text-info" ]
|
||||
}, "", "\n", HTML.Raw('<span class="small-title">uncle count \n<span class="small">(25 blocks per bar)</span></span>'), "\n", "", "\n", HTML.getTag("sparkchart")({
|
||||
"class": [ "big-details", " ", "spark-uncles" ],
|
||||
data: function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "uncleCountChart", "join"));
|
||||
}
|
||||
}))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "big-info", " ", "chart", " ", "text-info" ]
|
||||
}, "", "\n", HTML.Raw('<span class="small-title">transactions</span>'), "\n", HTML.getTag("sparkchart")({
|
||||
"class": [ "big-details", " ", "spark-transactions" ],
|
||||
data: function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "transactionDensity"));
|
||||
}
|
||||
}))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-3", " ", "stat-holder" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "big-info", " ", "chart", " ", "text-info" ]
|
||||
}, "", "\n", HTML.Raw('<span class="small-title">gas spending</span>'), "\n", HTML.getTag("sparkchart")({
|
||||
"class": [ "big-details", " ", "spark-gasspending" ],
|
||||
data: function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "gasSpending", "join"));
|
||||
}
|
||||
}))))), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-4", " ", "stat-holder", " ", "map-holder" ]
|
||||
}, "", "\n", HTML.getTag("nodemap")({
|
||||
id: "mapHolder",
|
||||
data: "map"
|
||||
})), "\n", HTML.DIV({
|
||||
"class": [ "col-xs-12", " ", "stats-boxes" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "row", " ", "second-row" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "col-xs-12", " ", "stat-holder", " ", "box" ]
|
||||
}, HTML.DIV({
|
||||
"class": [ "active-nodes", " ", "text-orange" ]
|
||||
}, HTML.Raw('<i class="icon-hashrate"></i>'), "\n", HTML.Raw('<span class="small-title">Block #1028201 hash</span>'), "\n", HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:Blockchain.frontierHash", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("Blockchain"), "frontierHash"));
|
||||
})))))), "\n", HTML.Raw('<div class="clearfix"></div>')), "\n", HTML.DIV({
|
||||
"class": "row",
|
||||
style: "padding-top: 10px"
|
||||
}, HTML.TABLE({
|
||||
"class": [ "table", " ", "table-striped" ]
|
||||
}, HTML.THEAD(HTML.TR({
|
||||
"class": "text-info"
|
||||
}, HTML.TH({
|
||||
"class": "th-nodecheck"
|
||||
}, HTML.I({
|
||||
"class": "icon-check-o",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Pin nodes to display first",
|
||||
"ng-click": "orderTable(['-stats.block.number', 'stats.block.propagation'], false)"
|
||||
})), "\n", HTML.TH({
|
||||
"class": "th-nodename"
|
||||
}, HTML.I({
|
||||
"class": "icon-node",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Node name",
|
||||
"ng-click": "orderTable(['info.name'], false)"
|
||||
})), "\n", HTML.TH({
|
||||
"class": "th-nodetype"
|
||||
}, HTML.I({
|
||||
"class": "icon-laptop",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Node type",
|
||||
"ng-click": "orderTable(['info.node'], false)"
|
||||
})), "\n", HTML.TH({
|
||||
"class": "th-latency"
|
||||
}, HTML.I({
|
||||
"class": "icon-clock",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Node latency",
|
||||
"ng-click": "orderTable(['stats.latency'], false)"
|
||||
})), "\n", HTML.TH(HTML.I({
|
||||
"class": "icon-mining",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Is mining",
|
||||
"ng-click": "orderTable(['-stats.hashrate'], false)"
|
||||
})), "\n", HTML.TH(HTML.I({
|
||||
"class": "icon-group",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Peers",
|
||||
"ng-click": "orderTable(['-stats.peers'], false)"
|
||||
})), "\n", HTML.TH(HTML.I({
|
||||
"class": "icon-network",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Pending transactions",
|
||||
"ng-click": "orderTable(['-stats.pending'], false)"
|
||||
})), "\n", HTML.TH(HTML.I({
|
||||
"class": "icon-block",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Last block",
|
||||
"ng-click": "orderTable(['-stats.block.number', 'stats.block.propagation'], false)"
|
||||
})), "\n", HTML.TH({
|
||||
"class": "th-blockhash"
|
||||
}, HTML.CharRef({
|
||||
html: " ",
|
||||
str: " "
|
||||
})), "\n", HTML.TH({
|
||||
"class": "th-blockhash"
|
||||
}, HTML.I({
|
||||
"class": "icon-difficulty",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Total difficulty",
|
||||
"ng-click": "orderTable(['-stats.block.totalDifficulty'], false)"
|
||||
})), "\n", HTML.TH(HTML.I({
|
||||
"class": "icon-check-o",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Block transactions",
|
||||
"ng-click": "orderTable(['-stats.block.transactions.length'], false)"
|
||||
})), "\n", HTML.TH(HTML.I({
|
||||
"class": "icon-uncle",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Uncles",
|
||||
"ng-click": "orderTable(['-stats.block.uncles.length'], false)"
|
||||
})), "\n", HTML.TH({
|
||||
"class": "th-blocktime"
|
||||
}, HTML.I({
|
||||
"class": "icon-time",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Last block time",
|
||||
"ng-click": "orderTable(['-stats.block.received'], false)"
|
||||
})), "\n", HTML.TH({
|
||||
"class": "th-peerPropagationTime"
|
||||
}, HTML.I({
|
||||
"class": "icon-gas",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Propagation time",
|
||||
"ng-click": "orderTable(['-stats.block.number', 'stats.block.propagation'], false)"
|
||||
})), "\n", HTML.TH({
|
||||
"class": "th-peerPropagationChart"
|
||||
}), "\n", HTML.TH({
|
||||
"class": "th-peerPropagationAvg"
|
||||
}, HTML.I({
|
||||
"class": "icon-gas",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Average propagation time",
|
||||
"ng-click": "orderTable(['stats.propagationAvg'], false)"
|
||||
})), "\n", HTML.TH(HTML.I({
|
||||
"class": "icon-bulb",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Up-time",
|
||||
"ng-click": "orderTable(['-stats.uptime'], false)"
|
||||
})))), "\n", HTML.TBODY(Blaze.Each(function() {
|
||||
return Spacebars.call(view.lookup("nodes"));
|
||||
}, function() {
|
||||
return HTML.TR({
|
||||
"ng-repeat": "node in nodes | orderBy:predicate track by node.id",
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("mainClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
},
|
||||
id: function() {
|
||||
return [ "node_", Spacebars.mustache(view.lookup("id")) ];
|
||||
}
|
||||
}, HTML.TD({
|
||||
"class": "td-nodecheck"
|
||||
}, HTML.I({
|
||||
"ng-click": "pinNode(id)",
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("nodePinClass"), view.lookup("pinned"));
|
||||
},
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "right",
|
||||
"data-original-title": function() {
|
||||
return [ "Click to ", Blaze.If(function() {
|
||||
return Spacebars.call(view.lookup("pinned"));
|
||||
}, function() {
|
||||
return "'un'";
|
||||
}, function() {
|
||||
return "''";
|
||||
}), "pin" ];
|
||||
}
|
||||
})), "\n", HTML.TD({
|
||||
"class": "nodeInfo",
|
||||
rel: function() {
|
||||
return Spacebars.mustache(view.lookup("id"));
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": "small",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
"data-html": "true",
|
||||
"data-original-title": function() {
|
||||
return Spacebars.mustache(view.lookup("geoTooltip"), view.lookup("."));
|
||||
}
|
||||
}, Blaze.View("lookup:info.name", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("info"), "name"));
|
||||
})), "\n", HTML.SPAN({
|
||||
"class": "small"
|
||||
}, HTML.CharRef({
|
||||
html: " ",
|
||||
str: " "
|
||||
}), "(", Blaze.View("lookup:info.ip", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("info"), "ip"));
|
||||
}), ")"), "\n", HTML.A({
|
||||
"class": function() {
|
||||
return [ "small", " ", Spacebars.mustache(view.lookup("nodeClientClass"), view.lookup("info"), Spacebars.dot(view.lookup("Blockchain"), "currentApiVersion")) ];
|
||||
},
|
||||
href: "https://github.com/ethereum/wiki/wiki/Network-Status#updating",
|
||||
target: "_blank",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
"data-html": "true",
|
||||
"data-original-title": "Netstats client needs update.<br>Click this icon for instructions."
|
||||
}, HTML.I({
|
||||
"class": "icon-warning-o"
|
||||
}))), "\n", HTML.TD(HTML.DIV({
|
||||
"class": "small"
|
||||
}, Blaze.View("lookup:nodeVersion", function() {
|
||||
return Spacebars.mustache(view.lookup("nodeVersion"), Spacebars.dot(view.lookup("info"), "node"));
|
||||
}))), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("readable"), "latencyClass"));
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": "small"
|
||||
}, Blaze.View("lookup:readable.latency", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("readable"), "latency"));
|
||||
}))), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("hashrateClass"), Spacebars.dot(view.lookup("stats"), "mining"), Spacebars.dot(view.lookup("stats"), "active"));
|
||||
}
|
||||
}, Blaze.View("lookup:hashrateFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("hashrateFilter"), Spacebars.dot(view.lookup("stats"), "hashrate"), Spacebars.dot(view.lookup("stats"), "mining"));
|
||||
})), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("peerClass"), Spacebars.dot(view.lookup("stats"), "peers"), Spacebars.dot(view.lookup("stats"), "active"));
|
||||
},
|
||||
style: "padding-left: 11px;"
|
||||
}, Blaze.View("lookup:stats.peers", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("stats"), "peers"));
|
||||
})), "\n", HTML.TD({
|
||||
style: "padding-left: 15px;"
|
||||
}, Blaze.View("lookup:stats.pending", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("stats"), "pending"));
|
||||
})), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("blockClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": function() {
|
||||
return Blaze.If(function() {
|
||||
return Spacebars.call(Spacebars.dot(view.lookup("readable"), "forkMessage"));
|
||||
}, function() {
|
||||
return [ " ", Blaze.View("lookup:readable.forkClass", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("readable"), "forkClass"));
|
||||
}), " " ];
|
||||
}, function() {
|
||||
return " '' ";
|
||||
});
|
||||
}
|
||||
}, Blaze.View("lookup:number", function() {
|
||||
return Spacebars.mustache(view.lookup("number"), Spacebars.dot(view.lookup("stats"), "block", "number"));
|
||||
})), "\n", null), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("blockClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": "small"
|
||||
}, Blaze.View("lookup:hashFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("hashFilter"), Spacebars.dot(view.lookup("stats"), "block", "hash"));
|
||||
}))), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("blockClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": "small"
|
||||
}, Blaze.View("lookup:number", function() {
|
||||
return Spacebars.mustache(view.lookup("number"), Spacebars.dot(view.lookup("stats"), "block", "totalDifficulty"));
|
||||
}))), "\n", HTML.TD({
|
||||
style: "padding-left: 14px;"
|
||||
}, Blaze.View("lookup:stats.block.transactions.length", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("stats"), "block", "transactions", "length"));
|
||||
})), "\n", HTML.TD({
|
||||
style: "padding-left: 14px;"
|
||||
}, Blaze.View("lookup:stats.block.uncles.length", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("stats"), "block", "uncles", "length"));
|
||||
})), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("timeClass"), Spacebars.dot(view.lookup("stats"), "block", "received"), Spacebars.dot(view.lookup("stats"), "active"));
|
||||
}
|
||||
}, Blaze.View("lookup:blockTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("blockTimeFilter"), Spacebars.dot(view.lookup("stats"), "block", "received"));
|
||||
})), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("propagationTimeClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, HTML.DIV({
|
||||
"class": "propagationBox"
|
||||
}), "\n", HTML.SPAN(Blaze.View("lookup:blockPropagationFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("blockPropagationFilter"), Spacebars.dot(view.lookup("stats"), "block", "propagation"), false);
|
||||
}))), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return [ "peerPropagationChart", " ", Spacebars.mustache(view.lookup("id")) ];
|
||||
}
|
||||
}), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("propagationNodeAvgTimeClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, Blaze.View("lookup:blockPropagationAvgFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("blockPropagationAvgFilter"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
})), "\n", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("upTimeClass"), Spacebars.dot(view.lookup("stats"), "uptime"), Spacebars.dot(view.lookup("stats"), "active"));
|
||||
}
|
||||
}, Blaze.View("lookup:upTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("upTimeFilter"), Spacebars.dot(view.lookup("stats"), "uptime"));
|
||||
})));
|
||||
})))));
|
||||
}));
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,331 @@
|
||||
(function(){
|
||||
/**
|
||||
Update the spark chart
|
||||
|
||||
@method sparkChart
|
||||
@param {String} property the property name with the chart data
|
||||
@param {String} className the class name of the sparkchart element
|
||||
*/
|
||||
var sparkChart = function(template, property, className){
|
||||
var fields = {};
|
||||
fields[property] = 1;
|
||||
var meta = Blockchain.findOne('meta', fields);
|
||||
|
||||
var element = template.$('sparkchart.'+ className);
|
||||
element.html(meta[property].join(','));
|
||||
element.addClass("big-details");
|
||||
element.sparkline('html', {
|
||||
type: 'bar',
|
||||
tooltipSuffix: (element.attr('tooltipsuffix') || '')
|
||||
});
|
||||
};
|
||||
|
||||
Template['indexMeteor'].onRendered(function(){
|
||||
var template = this;
|
||||
|
||||
// map
|
||||
this.autorun(function(){
|
||||
var data = Map.find({}).fetch();
|
||||
var element = template.$('#mapHolder');
|
||||
var scope = {};
|
||||
|
||||
if(data.length === 0)
|
||||
return;
|
||||
|
||||
var bubbleConfig = {
|
||||
borderWidth: 0,
|
||||
highlightOnHover: false,
|
||||
popupOnHover: true,
|
||||
popupTemplate: function(geo, data) {
|
||||
return ['<div class="tooltip-arrow"></div>',
|
||||
'<div class="hoverinfo ' + data.fillClass + '">',
|
||||
'<div class="propagationBox"></div>',
|
||||
'<strong>',
|
||||
data.nodeName,
|
||||
'</strong>',
|
||||
'</div>'].join('');
|
||||
}
|
||||
};
|
||||
|
||||
element.empty();
|
||||
|
||||
var width = 628,
|
||||
height = 244;
|
||||
|
||||
var map = new Datamap({
|
||||
element: element[0],
|
||||
scope: 'world',
|
||||
width: width,
|
||||
height: 300,
|
||||
fills: {
|
||||
success: '#7BCC3A',
|
||||
info: '#10A0DE',
|
||||
warning: '#FFD162',
|
||||
orange: '#FF8A00',
|
||||
danger: '#F74B4B',
|
||||
defaultFill: '#282828'
|
||||
},
|
||||
geographyConfig: {
|
||||
borderWidth: 0,
|
||||
borderColor: '#000',
|
||||
highlightOnHover: false,
|
||||
popupOnHover: false
|
||||
},
|
||||
bubblesConfig: {
|
||||
borderWidth: 0,
|
||||
highlightOnHover: false,
|
||||
popupOnHover: true
|
||||
},
|
||||
done: function(datamap) {
|
||||
var ev;
|
||||
|
||||
var zoomListener = d3.behavior.zoom()
|
||||
.size([width, height])
|
||||
.scaleExtent([1, 3])
|
||||
.on("zoom", redraw)
|
||||
.on("zoomend", animadraw);
|
||||
|
||||
function redraw() {
|
||||
datamap.svg.select(".datamaps-subunits").attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
|
||||
datamap.svg.select(".bubbles").selectAll("circle")
|
||||
.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")")
|
||||
.attr("r", 3/d3.event.scale);
|
||||
|
||||
ev = d3.event;
|
||||
}
|
||||
|
||||
zoomListener(datamap.svg);
|
||||
|
||||
function animadraw() {
|
||||
var x = Math.min(0, Math.max(ev.translate[0], (-1) * width * (ev.scale-1)));
|
||||
var y = Math.min(0, Math.max(ev.translate[1], (-1) * height * (ev.scale-1)));
|
||||
|
||||
datamap.svg.select(".datamaps-subunits")
|
||||
.transition()
|
||||
.delay(150)
|
||||
.duration(750)
|
||||
.attr("transform", "translate(" + x + "," + y + ")scale(" + ev.scale + ")");
|
||||
|
||||
datamap.svg.select(".bubbles").selectAll("circle")
|
||||
.transition()
|
||||
.delay(150)
|
||||
.duration(750)
|
||||
.attr("transform", "translate(" + x + "," + y + ")scale(" + ev.scale + ")")
|
||||
.attr("r", 3/ev.scale);
|
||||
|
||||
zoomListener.translate([x,y]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
map.bubbles(data, bubbleConfig);
|
||||
});
|
||||
|
||||
// block propagation times chart
|
||||
this.autorun(function(){
|
||||
var element = template.$('histogram.d3-blockpropagation');
|
||||
|
||||
var margin = {top: 0, right: 0, bottom: 0, left: 0};
|
||||
var width = 280 - margin.left - margin.right,
|
||||
height = 63 - margin.top - margin.bottom;
|
||||
|
||||
var TICKS = 40;
|
||||
|
||||
var x = d3.scale.linear()
|
||||
.domain([0, 10000])
|
||||
.rangeRound([0, width])
|
||||
.interpolate(d3.interpolateRound);
|
||||
|
||||
var y = d3.scale.linear()
|
||||
.range([height, 0])
|
||||
.interpolate(d3.interpolateRound);
|
||||
|
||||
var color = d3.scale.linear()
|
||||
.domain([1000, 3000, 7000, 10000])
|
||||
.range(["#7bcc3a", "#FFD162", "#ff8a00", "#F74B4B"]);
|
||||
|
||||
var xAxis = d3.svg.axis()
|
||||
.scale(x)
|
||||
.orient("bottom")
|
||||
.ticks(4, ",.1s")
|
||||
.tickFormat(function(t){ return t/1000 + "s"});
|
||||
|
||||
var yAxis = d3.svg.axis()
|
||||
.scale(y)
|
||||
.orient("left")
|
||||
.ticks(3)
|
||||
.tickFormat(d3.format("%"));
|
||||
|
||||
var line = d3.svg.line()
|
||||
.x(function(d) { return x(d.x + d.dx/2) - 1; })
|
||||
.y(function(d) { return y(d.y) - 2; })
|
||||
.interpolate('basis');
|
||||
|
||||
var tip = d3.tip()
|
||||
.attr('class', 'd3-tip')
|
||||
.offset([10, 0])
|
||||
.direction('s')
|
||||
.html(function(d) {
|
||||
return '<div class="tooltip-arrow"></div><div class="tooltip-inner"><b>' + (d.x/1000) + 's - ' + ((d.x + d.dx)/1000) + 's</b><div class="small">Percent: <b>' + Math.round(d.y * 100) + '%</b>' + '<br>Frequency: <b>' + d.frequency + '</b><br>Cumulative: <b>' + Math.round(d.cumpercent*100) + '%</b></div></div>';
|
||||
})
|
||||
|
||||
var data = Blockchain.findOne('meta', {fields: {blockPropagationChart: 1}}).blockPropagationChart;
|
||||
|
||||
if(data.length === 0)
|
||||
return;
|
||||
|
||||
// Adjust y axis
|
||||
y.domain([0, d3.max(data, function(d) { return d.y; })]);
|
||||
|
||||
// Delete previous histogram
|
||||
element.empty();
|
||||
|
||||
/* Start drawing */
|
||||
var svg = d3.select(".d3-blockpropagation").append("svg")
|
||||
.attr("width", width + margin.left + margin.right)
|
||||
.attr("height", height + margin.top + margin.bottom)
|
||||
.append("g")
|
||||
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");
|
||||
|
||||
svg.call(tip);
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "x axis")
|
||||
.attr("transform", "translate(0," + height + ")")
|
||||
.call(xAxis)
|
||||
.selectAll("text")
|
||||
.attr("y", 6);
|
||||
|
||||
svg.append("g")
|
||||
.attr("class", "y axis")
|
||||
.attr("transform", "translate(" + width + ", 0)")
|
||||
.call(yAxis);
|
||||
|
||||
|
||||
var bar = svg.append("g")
|
||||
.attr("class", "bars")
|
||||
.selectAll("g")
|
||||
.data(data)
|
||||
.enter().append("g")
|
||||
.attr("transform", function(d) { return "translate(" + x(d.x) + ",0)"; })
|
||||
.on('mouseover', function(d) { tip.show(d, d3.select(this).select('.bar').node()); })
|
||||
.on('mouseout', tip.hide);
|
||||
|
||||
bar.insert("rect")
|
||||
.attr("class", "handle")
|
||||
.attr("y", 0)
|
||||
.attr("width", x(data[0].dx + data[0].x) - x(data[0].x))
|
||||
.attr("height", function(d) { return height; });
|
||||
|
||||
bar.insert("rect")
|
||||
.attr("class", "bar")
|
||||
.attr("y", function(d) { return y(d.y); })
|
||||
.attr("rx", 1)
|
||||
.attr("ry", 1)
|
||||
.attr("fill", function(d) { return color(d.x); })
|
||||
.attr("width", x(data[0].dx + data[0].x) - x(data[0].x) - 1)
|
||||
.attr("height", function(d) { return height - y(d.y) + 1; });
|
||||
|
||||
bar.insert("rect")
|
||||
.attr("class", "highlight")
|
||||
.attr("y", function(d) { return y(d.y); })
|
||||
.attr("fill", function(d) { return d3.rgb(color(d.x)).brighter(.7).toString(); })
|
||||
.attr("rx", 1)
|
||||
.attr("ry", 1)
|
||||
.attr("width", x(data[0].dx + data[0].x) - x(data[0].x) - 1)
|
||||
.attr("height", function(d) { return height - y(d.y) + 1; });
|
||||
|
||||
svg.append("path")
|
||||
.attr("class", "line")
|
||||
.attr("d", line(data));
|
||||
});
|
||||
|
||||
// blocktimes chart
|
||||
this.autorun(function(){
|
||||
sparkChart(template, 'lastBlocksTime', 'spark-blocktimes');
|
||||
});
|
||||
|
||||
// difficulty chart
|
||||
this.autorun(function(){
|
||||
sparkChart(template, 'difficultyChart', 'spark-difficulty');
|
||||
});
|
||||
|
||||
// uncles chart
|
||||
this.autorun(function(){
|
||||
sparkChart(template, 'uncleCountChart', 'spark-uncles');
|
||||
});
|
||||
|
||||
// transactions chart
|
||||
this.autorun(function(){
|
||||
sparkChart(template, 'transactionDensity', 'spark-transactions');
|
||||
});
|
||||
|
||||
// gasspending chart
|
||||
this.autorun(function(){
|
||||
sparkChart(template, 'gasSpending', 'spark-gasspending');
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Template['indexMeteor'].helpers({
|
||||
'Blockchain': function(){
|
||||
return Blockchain.findOne('meta');
|
||||
},
|
||||
|
||||
'nodes': function(uptime) {
|
||||
return Nodes.find({stats: {$exists: true}},{limit: 10, sort: {'stats.block.number': -1, 'info.name': 1, 'stats.active': -1}});
|
||||
},
|
||||
|
||||
'blockTimeFilter': function() {
|
||||
var timestamp = this.lastBlock;
|
||||
|
||||
if(timestamp === 0)
|
||||
return '∞';
|
||||
|
||||
// var time = Math.floor((new Date()).getTime() / 1000);
|
||||
var time = (new Date()).getTime();
|
||||
var diff = Math.floor((time - timestamp)/1000);
|
||||
|
||||
if(diff < 60)
|
||||
return Math.round(diff) + ' s ago';
|
||||
|
||||
return moment.duration(Math.round(diff), 's').humanize() + ' ago';
|
||||
},
|
||||
|
||||
'avgTimeFilter': function() {
|
||||
var time = this.avgBlockTime;
|
||||
|
||||
if(time < 60)
|
||||
return parseFloat(time).toFixed(2) + ' s';
|
||||
|
||||
return moment.duration(Math.round(time), 's').humanize();
|
||||
},
|
||||
|
||||
'minerBlocks': function(){
|
||||
var array = [];
|
||||
|
||||
for (var i = 1; i <= this.blocks; i++) {
|
||||
array.push('');
|
||||
};
|
||||
|
||||
return array;
|
||||
},
|
||||
|
||||
'minerBlockClass': function (value) {
|
||||
if(value <= 6)
|
||||
return 'success';
|
||||
|
||||
if(value <= 12)
|
||||
return 'info';
|
||||
|
||||
if(value <= 18)
|
||||
return 'warning';
|
||||
|
||||
if(value <= 24)
|
||||
return 'orange';
|
||||
|
||||
return 'danger';
|
||||
}
|
||||
});
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,603 @@
|
||||
(function(){
|
||||
Template.__checkName("indexMeteor");
|
||||
Template["indexMeteor"] = new Template("Template.indexMeteor", (function() {
|
||||
var view = this;
|
||||
return [ Spacebars.With(function() {
|
||||
return Spacebars.call(view.lookup("Blockchain"));
|
||||
}, function() {
|
||||
return [ "\n ", HTML.DIV({
|
||||
"class": "container-fluid"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "row"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "col-xs-2 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "big-info bestblock text-info"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "pull-left icon-full-width"
|
||||
}, HTML.I({
|
||||
"class": "icon-block"
|
||||
})), "\n ", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "best block"), HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:number", function() {
|
||||
return Spacebars.mustache(view.lookup("number"), view.lookup("bestBlock"));
|
||||
}))), "\n ", HTML.DIV({
|
||||
"class": "clearfix"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-2 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "big-info uncleCount text-info"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "pull-left icon-full-width"
|
||||
}, HTML.I({
|
||||
"class": "icon-uncle"
|
||||
})), "\n ", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "uncles", HTML.CharRef({
|
||||
html: " ",
|
||||
str: " "
|
||||
}), HTML.SPAN({
|
||||
"class": "small"
|
||||
}, "(current / last 50)")), HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:bestStats.block.uncles.length", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("bestStats"), "block", "uncles", "length"));
|
||||
}), "/", Blaze.View("lookup:uncleCount", function() {
|
||||
return Spacebars.mustache(view.lookup("uncleCount"));
|
||||
}))), "\n ", HTML.DIV({
|
||||
"class": "clearfix"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-2 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "big-info blocktime ", Spacebars.mustache(view.lookup("timeClass"), view.lookup("lastBlock"), true) ];
|
||||
}
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "pull-left icon-full-width"
|
||||
}, HTML.I({
|
||||
"class": "icon-time"
|
||||
})), "\n ", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "last block"), HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:blockTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("blockTimeFilter"));
|
||||
})), "\n "), "\n ", HTML.DIV({
|
||||
"class": "clearfix"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-2 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "big-info avgblocktime ", Spacebars.mustache(view.lookup("avgTimeClass"), view.lookup("avgBlockTime")) ];
|
||||
}
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "pull-left icon-full-width"
|
||||
}, HTML.I({
|
||||
"class": "icon-gas"
|
||||
})), "\n ", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "avg block time"), HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:avgTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("avgTimeFilter"));
|
||||
}))), "\n ", HTML.DIV({
|
||||
"class": "clearfix"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-2 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "big-info difficulty text-orange"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "pull-left icon-full-width"
|
||||
}, HTML.I({
|
||||
"class": "icon-hashrate"
|
||||
})), "\n ", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "avg network hashrate"), HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, Blaze.View("lookup:networkHashrateFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("networkHashrateFilter"), view.lookup("avgHashrate"), false);
|
||||
}))), "\n ", HTML.DIV({
|
||||
"class": "clearfix"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-2 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "big-info difficulty text-danger"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "pull-left icon-full-width"
|
||||
}, HTML.I({
|
||||
"class": "icon-difficulty"
|
||||
})), "\n ", HTML.DIV({
|
||||
"class": "big-details-holder"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "difficulty"), HTML.SPAN({
|
||||
"class": "big-details"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-hash"
|
||||
}, Blaze.View("lookup:number", function() {
|
||||
return Spacebars.mustache(view.lookup("number"), view.lookup("lastDifficulty"));
|
||||
})))), "\n ", HTML.DIV({
|
||||
"class": "clearfix"
|
||||
}), "\n "), "\n "), "\n\n ", HTML.DIV({
|
||||
"class": "clearfix"
|
||||
}), "\n "), "\n\n ", HTML.DIV({
|
||||
"class": "row"
|
||||
}, "\n ", HTML.DIV({
|
||||
style: "padding-top: 0px;",
|
||||
"class": "col-xs-8 stats-boxes"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "row second-row"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder box"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "active-nodes ", Spacebars.mustache(view.lookup("nodesActiveClass"), view.lookup("nodesActive"), view.lookup("nodesTotal")) ];
|
||||
}
|
||||
}, HTML.I({
|
||||
"class": "icon-node"
|
||||
}), HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "active nodes"), HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:nodesActive", function() {
|
||||
return Spacebars.mustache(view.lookup("nodesActive"));
|
||||
}), "/", Blaze.View("lookup:nodesTotal", function() {
|
||||
return Spacebars.mustache(view.lookup("nodesTotal"));
|
||||
}))), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder box"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "gasprice text-info"
|
||||
}, HTML.I({
|
||||
"class": "icon-gasprice"
|
||||
}), HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "gas price"), HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:gasPriceFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("gasPriceFilter"), Spacebars.dot(view.lookup("bestStats"), "gasPrice", "toString"));
|
||||
}))), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder box"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "page-latency ", Spacebars.mustache(view.lookup("latencyClass"), true, view.lookup("latency")) ];
|
||||
}
|
||||
}, HTML.I({
|
||||
"class": "icon-clock"
|
||||
}), HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "page latency"), HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:latency", function() {
|
||||
return Spacebars.mustache(view.lookup("latency"));
|
||||
}), " ms")), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder box"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "uptime ", Spacebars.mustache(view.lookup("upTimeClass"), view.lookup("upTimeTotal"), true) ];
|
||||
}
|
||||
}, HTML.I({
|
||||
"class": "icon-bulb"
|
||||
}), HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "uptime"), HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:upTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("upTimeFilter"), view.lookup("upTimeTotal"));
|
||||
}))), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "row"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "big-info chart ", Spacebars.mustache(view.lookup("avgTimeClass"), view.lookup("avgBlockTime")) ];
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "block time"), "\n ", HTML.getTag("sparkchart")({
|
||||
tooltipsuffix: "s",
|
||||
"class": "big-details spark-blocktimes"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "big-info chart text-info"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "difficulty"), "\n ", HTML.getTag("sparkchart")({
|
||||
"class": "big-details spark-difficulty"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder xpull-right"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "big-info chart xdouble-chart ", Spacebars.mustache(view.lookup("propagationAvgTimeClass"), view.lookup("blockPropagationAvg"), true) ];
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "block propagation"), "\n ", HTML.getTag("histogram")({
|
||||
"class": "big-details d3-blockpropagation"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder pull-right"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "big-info chart double-chart"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "last blocks miners"), "\n ", HTML.DIV({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "right",
|
||||
"data-original-title": function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("miner"), "blocks"));
|
||||
},
|
||||
"class": "blocks-holder"
|
||||
}, "\n ", Blaze.Each(function() {
|
||||
return Spacebars.call(view.lookup("miners"));
|
||||
}, function() {
|
||||
return [ "\n ", HTML.DIV({
|
||||
"class": function() {
|
||||
return [ "block-count ", Spacebars.mustache(view.lookup("minerBlocksClass"), view.lookup("blocks"), "text-") ];
|
||||
}
|
||||
}, Blaze.View("lookup:blocks", function() {
|
||||
return Spacebars.mustache(view.lookup("blocks"));
|
||||
})), "\n ", HTML.DIV({
|
||||
"class": "small-title-miner"
|
||||
}, Blaze.View("lookup:miner", function() {
|
||||
return Spacebars.mustache(view.lookup("miner"));
|
||||
})), "\n \n ", HTML.Comment(' <div class="block {{minerBlockClass ../blocks}}"></div> '), "\n \n ", HTML.DIV({
|
||||
"class": "clearfix"
|
||||
}), "\n " ];
|
||||
}), "\n "), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "big-info chart text-info"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "uncle count", HTML.CharRef({
|
||||
html: " ",
|
||||
str: " "
|
||||
}), HTML.SPAN({
|
||||
"class": "small"
|
||||
}, "(25 blocks per bar)")), "\n ", HTML.getTag("sparkchart")({
|
||||
"class": "big-details spark-uncles"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "big-info chart text-info"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "transactions"), "\n ", HTML.getTag("sparkchart")({
|
||||
"class": "big-details spark-transactions"
|
||||
}), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-3 stat-holder"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "big-info chart text-info"
|
||||
}, HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "gas spending"), "\n ", HTML.getTag("sparkchart")({
|
||||
"class": "big-details spark-gasspending"
|
||||
}), "\n "), "\n "), "\n "), "\n "), "\n ", HTML.DIV({
|
||||
"class": "col-xs-4 stat-holder map-holder"
|
||||
}, "\n ", HTML.getTag("nodemap")({
|
||||
id: "mapHolder"
|
||||
}), "\n "), "\n\n ", HTML.DIV({
|
||||
"class": "col-xs-12 stats-boxes"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "row second-row"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "col-xs-12 stat-holder box"
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "active-nodes text-orange"
|
||||
}, HTML.I({
|
||||
"class": "icon-hashrate"
|
||||
}), HTML.SPAN({
|
||||
"class": "small-title"
|
||||
}, "Block #1028201 hash"), HTML.SPAN({
|
||||
"class": "small-value"
|
||||
}, Blaze.View("lookup:frontierHash", function() {
|
||||
return Spacebars.mustache(view.lookup("frontierHash"));
|
||||
}))), "\n "), "\n "), "\n "), "\n\n ", HTML.DIV({
|
||||
"class": "clearfix"
|
||||
}), "\n "), "\n "), "\n " ];
|
||||
}), "\n\n ", HTML.DIV({
|
||||
style: "padding-top: 10px",
|
||||
"class": "row"
|
||||
}, "\n ", HTML.TABLE({
|
||||
"class": "table table-striped"
|
||||
}, "\n ", HTML.THEAD("\n ", HTML.TR({
|
||||
"class": "text-info"
|
||||
}, "\n ", HTML.TH({
|
||||
"class": "th-nodecheck"
|
||||
}, HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Pin nodes to display first",
|
||||
"ng-click": "orderTable(['-stats.block.number', 'stats.block.propagation'], false)",
|
||||
"class": "icon-check-o"
|
||||
})), "\n ", HTML.TH({
|
||||
"class": "th-nodename"
|
||||
}, HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Node name",
|
||||
"ng-click": "orderTable(['info.name'], false)",
|
||||
"class": "icon-node"
|
||||
})), "\n ", HTML.TH({
|
||||
"class": "th-nodetype"
|
||||
}, HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Node type",
|
||||
"ng-click": "orderTable(['info.node'], false)",
|
||||
"class": "icon-laptop"
|
||||
})), "\n ", HTML.TH({
|
||||
"class": "th-latency"
|
||||
}, HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Node latency",
|
||||
"ng-click": "orderTable(['stats.latency'], false)",
|
||||
"class": "icon-clock"
|
||||
})), "\n ", HTML.TH(HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Is mining",
|
||||
"ng-click": "orderTable(['-stats.hashrate'], false)",
|
||||
"class": "icon-mining"
|
||||
})), "\n ", HTML.TH(HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Peers",
|
||||
"ng-click": "orderTable(['-stats.peers'], false)",
|
||||
"class": "icon-group"
|
||||
})), "\n ", HTML.TH(HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Pending transactions",
|
||||
"ng-click": "orderTable(['-stats.pending'], false)",
|
||||
"class": "icon-network"
|
||||
})), "\n ", HTML.TH(HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Last block",
|
||||
"ng-click": "orderTable(['-stats.block.number', 'stats.block.propagation'], false)",
|
||||
"class": "icon-block"
|
||||
})), "\n ", HTML.TH({
|
||||
"class": "th-blockhash"
|
||||
}, HTML.CharRef({
|
||||
html: " ",
|
||||
str: " "
|
||||
})), "\n ", HTML.TH({
|
||||
"class": "th-blockhash"
|
||||
}, HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Total difficulty",
|
||||
"ng-click": "orderTable(['-stats.block.totalDifficulty'], false)",
|
||||
"class": "icon-difficulty"
|
||||
})), "\n ", HTML.TH(HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Block transactions",
|
||||
"ng-click": "orderTable(['-stats.block.transactions.length'], false)",
|
||||
"class": "icon-check-o"
|
||||
})), "\n ", HTML.TH(HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Uncles",
|
||||
"ng-click": "orderTable(['-stats.block.uncles.length'], false)",
|
||||
"class": "icon-uncle"
|
||||
})), "\n ", HTML.TH({
|
||||
"class": "th-blocktime"
|
||||
}, HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Last block time",
|
||||
"ng-click": "orderTable(['-stats.block.received'], false)",
|
||||
"class": "icon-time"
|
||||
})), "\n ", HTML.TH({
|
||||
"class": "th-peerPropagationTime"
|
||||
}, HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Propagation time",
|
||||
"ng-click": "orderTable(['-stats.block.number', 'stats.block.propagation'], false)",
|
||||
"class": "icon-gas"
|
||||
})), "\n ", HTML.TH({
|
||||
"class": "th-peerPropagationChart"
|
||||
}), "\n ", HTML.TH({
|
||||
"class": "th-peerPropagationAvg"
|
||||
}, HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Average propagation time",
|
||||
"ng-click": "orderTable(['stats.propagationAvg'], false)",
|
||||
"class": "icon-gas"
|
||||
})), "\n ", HTML.TH(HTML.I({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
title: "Up-time",
|
||||
"ng-click": "orderTable(['-stats.uptime'], false)",
|
||||
"class": "icon-bulb"
|
||||
})), "\n "), "\n "), "\n ", HTML.TBODY("\n ", Blaze.Each(function() {
|
||||
return Spacebars.call(view.lookup("nodes"));
|
||||
}, function() {
|
||||
return [ "\n ", HTML.TR({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("mainClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
},
|
||||
id: function() {
|
||||
return [ "node_", Spacebars.mustache(view.lookup("id")) ];
|
||||
}
|
||||
}, "\n ", HTML.TD({
|
||||
"class": "td-nodecheck"
|
||||
}, HTML.I({
|
||||
"ng-click": "pinNode(id)",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "right",
|
||||
"data-original-title": function() {
|
||||
return [ "Click to ", Blaze.If(function() {
|
||||
return Spacebars.call(view.lookup("pinned"));
|
||||
}, function() {
|
||||
return "'un'";
|
||||
}, function() {
|
||||
return "''";
|
||||
}), "pin" ];
|
||||
},
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("nodePinClass"), view.lookup("pinned"));
|
||||
}
|
||||
})), "\n ", HTML.TD({
|
||||
rel: function() {
|
||||
return Spacebars.mustache(view.lookup("id"));
|
||||
},
|
||||
"class": "nodeInfo"
|
||||
}, HTML.SPAN({
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
"data-html": "true",
|
||||
"data-original-title": function() {
|
||||
return Spacebars.mustache(view.lookup("geoTooltip"), view.lookup("."));
|
||||
},
|
||||
"class": "small"
|
||||
}, Blaze.View("lookup:info.name", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("info"), "name"));
|
||||
})), HTML.SPAN({
|
||||
"class": "small"
|
||||
}, HTML.CharRef({
|
||||
html: " ",
|
||||
str: " "
|
||||
}), "(", Blaze.View("lookup:info.ip", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("info"), "ip"));
|
||||
}), ")"), HTML.A({
|
||||
href: "https://github.com/ethereum/wiki/wiki/Network-Status#updating",
|
||||
target: "_blank",
|
||||
"data-toggle": "tooltip",
|
||||
"data-placement": "top",
|
||||
"data-html": "true",
|
||||
"data-original-title": [ "Netstats client needs update.", HTML.CharRef({
|
||||
html: "<",
|
||||
str: "<"
|
||||
}), "br", HTML.CharRef({
|
||||
html: ">",
|
||||
str: ">"
|
||||
}), "Click this icon for instructions." ],
|
||||
"class": function() {
|
||||
return [ "small ", Spacebars.mustache(view.lookup("nodeClientClass"), view.lookup("info"), Spacebars.dot(view.lookup("Blockchain"), "currentApiVersion")) ];
|
||||
}
|
||||
}, HTML.I({
|
||||
"class": "icon-warning-o"
|
||||
}))), "\n ", HTML.TD("\n ", HTML.DIV({
|
||||
"class": "small"
|
||||
}, Blaze.View("lookup:nodeVersion", function() {
|
||||
return Spacebars.mustache(view.lookup("nodeVersion"), Spacebars.dot(view.lookup("info"), "node"));
|
||||
})), "\n "), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("readable"), "latencyClass"));
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": "small"
|
||||
}, Blaze.View("lookup:readable.latency", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("readable"), "latency"));
|
||||
}))), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("hashrateClass"), Spacebars.dot(view.lookup("stats"), "mining"), Spacebars.dot(view.lookup("stats"), "active"));
|
||||
}
|
||||
}, Blaze.View("lookup:hashrateFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("hashrateFilter"), Spacebars.dot(view.lookup("stats"), "hashrate"), Spacebars.dot(view.lookup("stats"), "mining"));
|
||||
})), "\n ", HTML.TD({
|
||||
style: "padding-left: 11px;",
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("peerClass"), Spacebars.dot(view.lookup("stats"), "peers"), Spacebars.dot(view.lookup("stats"), "active"));
|
||||
}
|
||||
}, Blaze.View("lookup:stats.peers", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("stats"), "peers"));
|
||||
})), "\n ", HTML.TD({
|
||||
style: "padding-left: 15px;"
|
||||
}, Blaze.View("lookup:stats.pending", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("stats"), "pending"));
|
||||
})), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("blockClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": function() {
|
||||
return Blaze.If(function() {
|
||||
return Spacebars.call(Spacebars.dot(view.lookup("readable"), "forkMessage"));
|
||||
}, function() {
|
||||
return [ " ", Blaze.View("lookup:readable.forkClass", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("readable"), "forkClass"));
|
||||
}), " " ];
|
||||
}, function() {
|
||||
return " '' ";
|
||||
});
|
||||
}
|
||||
}, Blaze.View("lookup:number", function() {
|
||||
return Spacebars.mustache(view.lookup("number"), Spacebars.dot(view.lookup("stats"), "block", "number"));
|
||||
})), "\n "), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("blockClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": "small"
|
||||
}, Blaze.View("lookup:hashFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("hashFilter"), Spacebars.dot(view.lookup("stats"), "block", "hash"));
|
||||
}))), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("blockClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, HTML.SPAN({
|
||||
"class": "small"
|
||||
}, Blaze.View("lookup:number", function() {
|
||||
return Spacebars.mustache(view.lookup("number"), Spacebars.dot(view.lookup("stats"), "block", "totalDifficulty"));
|
||||
}))), "\n ", HTML.TD({
|
||||
style: "padding-left: 14px;"
|
||||
}, Blaze.View("lookup:stats.block.transactions.length", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("stats"), "block", "transactions", "length"));
|
||||
})), "\n ", HTML.TD({
|
||||
style: "padding-left: 14px;"
|
||||
}, Blaze.View("lookup:stats.block.uncles.length", function() {
|
||||
return Spacebars.mustache(Spacebars.dot(view.lookup("stats"), "block", "uncles", "length"));
|
||||
})), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("timeClass"), Spacebars.dot(view.lookup("stats"), "block", "received"), Spacebars.dot(view.lookup("stats"), "active"));
|
||||
}
|
||||
}, Blaze.View("lookup:blockTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("blockTimeFilter"), Spacebars.dot(view.lookup("stats"), "block", "received"));
|
||||
})), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("propagationTimeClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, "\n ", HTML.DIV({
|
||||
"class": "propagationBox"
|
||||
}), HTML.SPAN(Blaze.View("lookup:blockPropagationFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("blockPropagationFilter"), Spacebars.dot(view.lookup("stats"), "block", "propagation"), false);
|
||||
})), "\n "), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return [ "peerPropagationChart ", Spacebars.mustache(view.lookup("id")) ];
|
||||
}
|
||||
}, "\n "), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("propagationNodeAvgTimeClass"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
}
|
||||
}, Blaze.View("lookup:blockPropagationAvgFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("blockPropagationAvgFilter"), view.lookup("stats"), Spacebars.dot(view.lookup("Blockchain"), "bestBlock"));
|
||||
})), "\n ", HTML.TD({
|
||||
"class": function() {
|
||||
return Spacebars.mustache(view.lookup("upTimeClass"), Spacebars.dot(view.lookup("stats"), "uptime"), Spacebars.dot(view.lookup("stats"), "active"));
|
||||
}
|
||||
}, Blaze.View("lookup:upTimeFilter", function() {
|
||||
return Spacebars.mustache(view.lookup("upTimeFilter"), Spacebars.dot(view.lookup("stats"), "uptime"));
|
||||
})), "\n "), "\n " ];
|
||||
}), "\n "), "\n "), "\n ") ];
|
||||
}));
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,8 @@
|
||||
(function(){
|
||||
Template.body.addContent((function() {
|
||||
var view = this;
|
||||
return [ "\n ", Spacebars.include(view.lookupTemplate("indexMeteor")), "\n " ];
|
||||
}));
|
||||
Meteor.startup(Template.body.renderToDocument);
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg">
|
||||
<metadata>Copyright (C) 2015 by original authors @ fontello.com</metadata>
|
||||
<defs>
|
||||
<font id="minimal-icons" horiz-adv-x="1000" >
|
||||
<font-face font-family="minimal-icons" font-weight="400" font-stretch="normal" units-per-em="1000" ascent="1000" descent="0" />
|
||||
<missing-glyph horiz-adv-x="1000" />
|
||||
<glyph glyph-name="truck" unicode="" d="m734 179c-86 0-156 71-156 157s70 157 156 157 157-71 157-157-71-157-157-157z m0 282c-69 0-125-56-125-125s56-125 125-125 125 56 125 125-56 125-125 125z m-484-282c-87 0-157 71-157 157s70 157 157 157c86 0 156-71 156-157s-70-157-156-157z m0 282c-69 0-126-56-126-125s57-125 126-125c69 0 125 56 125 125s-56 125-125 125z m256-93h-83v31h65l19 31h56v-31h-38l-19-31z m441 31h-38v31h25l34 36v90h-109v155h-81l-77-178-28 12 84 198h243l0-290-53-54z m-56 188h77v124h-77v-124z m-325-110l-3 0-461 75c-14 1-25 11-27 24l-75 166v4c0 15 13 28 28 28l680 47c0 0 0 0 0 0 9 0 16-4 21-9v9h229v-32l-220 0-145-288c-2-14-13-24-27-24z m-460 106l457-74 140 280-669-46 72-160z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="database" unicode="" d="m500 984c-192 0-386-37-386-108h31c0 27 122 77 355 77 233 0 355-50 355-77v-31c0-25-125-72-355-72-233 0-355 46-355 72h-31c0-76 231-104 386-104 121 0 287 17 355 60v-191c0-33-138-79-355-79s-355 46-355 79v72h-31v-558c0-68 168-93 241-101 46-5 95-7 145-7 192 0 386 37 386 108v752c0 71-194 108-386 108z m355-860c0-27-122-77-355-77-49 0-97 2-142 7-147 15-213 50-213 70v185c63-44 210-66 355-66s292 22 355 66v-185z m0 234c0-34-138-84-355-84s-355 50-355 84v205c63-42 210-63 355-63s292 21 355 63v-205z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="mining" unicode="" d="m83 9c-8 0-16 3-22 9l-43 43c-12 12-12 31 0 43l350 351 22-22-350-351 43-42 524 525 22-22-525-525c-6-6-14-9-21-9z m739 727l-22 22 11 11-43 42-10-11-22 22 11 11c12 12 31 12 43 0l43-43c12-12 12-31 0-43l-11-11z m-140-171l0 0c-8 0-14 3-19 8l-90 90c-11 11-10 29 2 41l97 97c11 11 31 12 41 2l90-90c5-5 7-12 8-19 0-8-4-16-10-22l-97-97c-6-6-14-10-22-10z m-85 118l85-85 96 95-85 85-96-95z m339-520l-11 6-11 7 5 13c24 67-47 202-185 353l23 21c142-156 186-258 195-320 29 89-25 232-145 373l24 20c159-187 205-373 114-464l-9-9z m-394 571c-233 213-335 191-353 185-12-5-18 3-20 6l3 20c91 91 277 45 464-114l-20-24c-141 120-284 174-373 145 62-9 164-53 320-195l-21-23z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="check" unicode="" d="m393 85c-8 0-16 3-22 9l-354 355c-13 12-13 32 0 44l98 99 22-22-98-99 354-354 568 567-199 200-369-369-155 155-10-10-22 22 10 10c6 6 13 9 22 9 0 0 0 0 0 0 8 0 16-3 22-9l133-133 347 347c12 12 32 12 44 0l200-200c5-5 9-13 9-22 0-8-4-16-9-22l-569-568c-6-6-14-9-22-9z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="cancel" unicode="" d="m268 15c-8 0-16 3-22 9l-222 222c-12 12-12 32 0 44l211 210-211 210c-6 6-9 14-9 22s3 17 9 22l112 112 22-22-112-112 233-232-233-232 222-222 232 233 232-233 222 222-233 232 233 232-222 222-232-233-232 233-10-10-22 22 10 10c12 12 32 12 44 0l210-210 210 210c6 6 14 9 22 9 0 0 0 0 0 0 9 0 17-3 22-9l222-222c6-5 9-13 9-22 0-8-3-16-9-22l-210-210 210-210c12-12 12-32 0-44l-222-222c-12-12-32-12-44 0l-210 211-210-211c-6-6-14-9-22-9z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="loader" unicode="" d="m500 16c-267 0-484 217-484 484 0 103 32 202 92 285l25-19c-56-77-86-170-86-266 0-250 203-453 453-453 250 0 453 203 453 453s-203 453-453 453c-79 0-156-20-224-59l-16 27c73 41 156 63 240 63 267 0 484-217 484-484s-217-484-484-484z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="check-o" unicode="" d="m487 419l214 213 22-22-235-235-11 11-1-1-128 129 22 22 117-117z m477 222l-30-9c13-43 19-87 19-132 0-250-203-453-453-453s-453 203-453 453 203 453 453 453c50 0 99-8 146-24l10 30c-50 17-102 25-156 25-267 0-484-217-484-484s217-484 484-484 484 217 484 484c0 48-7 95-20 141z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="cancel-o" unicode="" d="m662 640l-140-140 140-140-22-22-140 140-140-140-22 22 140 140-140 140 22 22 140-140 140 140 22-22z m302 1l-30-9c13-43 19-87 19-132 0-250-203-453-453-453-250 0-453 203-453 453 0 250 203 453 453 453 50 0 99-8 146-24l10 30c-50 17-103 25-156 25-267 0-484-217-484-484 0-267 217-484 484-484 267 0 484 217 484 484 0 48-7 95-20 141z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="warning-o" unicode="" d="m984 500c0-267-217-484-484-484-267 0-484 217-484 484 0 103 32 202 92 285l25-19c-56-77-86-170-86-266 0-250 203-453 453-453s453 203 453 453-203 453-453 453c-79 0-156-20-224-59l-16 27c73 42 156 63 240 63 267 0 484-217 484-484z m-420 200l0 9c0 36-29 65-64 65-35 0-63-29-63-65 0-2 0-7-1-13l32 0c0 6 0 11 0 13 0 19 14 34 32 34 18 0 32-15 32-34l0-10c4-281-32-295-32-295 0 0-25 9-31 175l-31-1c6-181 35-205 62-205 6 0 15 2 24 10 29 30 42 133 40 317z m-64-378c35 0 64-29 64-64 0-35-29-64-64-64-35 0-63 29-63 64 0 35 28 64 63 64z m0-31c-18 0-32-15-32-33 0-18 14-33 32-33 18 0 32 15 32 33s-14 33-32 33z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="network" unicode="" d="m501 224c-63 0-124 23-172 64l19 22c43-36 97-56 153-56 124 0 227 97 235 221l29-2c-9-139-125-249-264-249z m-249 175c-11 29-16 60-16 91 0 147 119 266 265 266 104 0 199-62 242-158l-27-12c-38 85-122 140-215 140-130 0-236-106-236-236 0-28 5-55 14-81l-27-10z m-120-96c-51 0-86 12-97 38-22 52 61 123 135 174l17-24c-98-67-134-118-125-139 17-40 208-25 479 91 120 51 227 110 303 167 80 60 101 100 94 116-10 23-85 32-227-4l-7 29c86 21 235 48 261-13 16-38-19-89-104-152-77-58-187-118-308-170-152-65-318-113-421-113z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="block" unicode="" d="m1000 779l-16-5-484 140-484-140-16 5v-68h31v26l453-131v-483l-453 131v332h-31v-355l484-141v-9l16 5 16-5v9l484 141v548z m-928-21l428 124 428-124-428-124-428 124z m897-504l-453-131v483l453 131v-483z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="bulb" unicode="" d="m378 219c-12 22-4 37 1 45 4 6 4 7 1 14-27 47-59 84-89 120-36 42-69 81-90 131-12 28-18 56-21 87-1 14-2 28-3 41-1 10-1 20-1 29 0 11 1 24 3 38 18 128 120 231 255 257 22 2 43 3 65 3 22 0 44-1 64-3v0l3 0c150-29 258-153 258-295 0-37-7-85-20-140-23-68-59-110-98-154-28-33-58-67-84-114-4-7-4-8 0-14 5-8 13-22 2-45l-28 15c4 7 3 8-1 14-5 9-13 23-1 45 28 50 59 85 89 119 38 44 71 82 91 143 12 50 19 97 19 131 0 127-97 238-232 264l0 0c-40 4-83 4-123 0-120-23-212-116-228-230-2-13-3-24-3-34 0-8 1-17 1-27 1-14 2-27 3-41 2-27 9-52 19-77 19-45 51-83 84-123 32-36 64-75 93-125 12-22 4-36-1-44-3-7-4-8 0-15l-28-15z m68-203c-25 0-49 7-55 44l30 5c4-18 9-20 47-17 19 2 45 2 64 0 38-3 43-1 46 17l31-5c-8-49-48-46-79-43-20 2-41 2-60 0-7 0-16-1-24-1z m-68 111h242v-31h-242v31z m0 62h242v-31h-242v31z m184 154h-32c0 55 4 103 12 143-16 3-30 8-43 16-12-7-25-13-40-15 7-40 11-87 11-142h-31c0 62-5 107-12 141-50 5-97 35-97 90 0 24 18 43 41 43 13 0 44-6 68-63 5-11 10-24 13-39 8 1 16 4 22 7-15 18-24 41-24 65 0 36 21 62 50 62 29 0 51-26 51-61 0-24-10-48-26-66 7-4 15-6 24-7 3 14 8 27 13 39 25 58 56 64 68 64 23 0 40-18 40-42 0-55-46-86-96-92-7-34-12-80-12-143z m-191 245c-7 0-10-6-10-12 0-32 27-51 58-57-2 10-6 18-8 25-14 32-30 44-40 44z m259 1c-9 0-25-12-39-45-3-7-6-15-9-25 31 7 56 27 56 59 0 2 0 11-8 11z m-130 31c-13 0-19-16-19-31 0-18 7-34 19-47 12 13 19 30 19 48 0 15-6 30-19 30z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="node" unicode="" d="m228 516h529v-31h-529v31z m-30-138h589c26 0 46 21 46 46h-31c0-8-7-15-15-15h-589c-8 0-15 7-15 15v409c0 8 7 14 15 14h589c8 0 15-6 15-14v-197h31v197c0 25-20 46-46 46h-589c-26 0-46-21-46-46v-409c0-25 20-46 46-46z m318-30h-31v-74h-61v-153h152v153h-60v74z m29-195h-90v89h90v-89z m-514 60h363v-31h-363v31z m575 0h363v-31h-363v31z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="laptop" unicode="" d="m893 396c-1 16-9 30-22 39 6 8 9 18 9 29v400c0 29-22 52-49 52h-659c-27 0-49-23-49-52v-38h31v38c0 11 8 21 18 21h659c10 0 18-10 18-21v-400c0-11-8-21-18-21h-659c-10 0-18 10-18 21v244h-31v-244c0-10 3-19 7-27-14-8-24-23-25-41l-89-259v-3c0-27 22-50 49-50h870c27 0 49 23 49 50v3l-91 259z m42-281h-870c-9 0-17 8-18 17l89 259v2c0 11 8 19 18 19h18 659 13c10 0 18-8 18-19v-2l91-259c-1-9-9-17-18-17z m-193 269h-489c-20 0-36-15-38-35l-41-134-1-4c0-21 17-38 38-38h574c20 0 37 17 37 38l-43 138c-2 20-18 35-37 35z m31-119h-39l-9 28h32v22l16-50z m-469 28h48l-7-28h-50l9 28z m-42-28h-40l9 28h40l-9-28z m342 59h-49v29h42l7-29z m25 29h43l9-29h-45l-7 29z m5-147h-271l7 28h257l7-28z m-168 59v28h58v-28h-58z m-32 0h-57l7 28h50v-28z m121 0v28h57l7-28h-64z m-31 59h-58v29h58v-29z m-90 0h-42l7 29h35v-29z m-74 0h-45l9 29h43l-7-29z m-23-90l-7-30h-55l10 30h52z m322 0h53l9-30h-55l-7 30z m-8 31l0 0-7 28h48l9-28h-50z m97 81l7-22h-41l-9 29h37c3 0 6-3 6-7z m-501 0c0 4 2 7 6 7h38l-9-29h-42l6 18 1 4z m-42-137l8 25h39l-10-30h-31c-3 0-5 2-6 5z m580-5h-31l-10 30h39l8-25c-1-3-3-5-6-5z m38 415v193c0 25-20 46-45 46h-550c-25 0-46-21-46-46v-296c0-25 21-45 46-45h550c25 0 45 20 45 45v29h-31v-29c0-8-7-14-14-14h-550c-8 0-14 6-14 14v296c0 8 6 14 14 14h550c7 0 14-6 14-14v-193l31 0 0 0z m-405 72l-124-107 20-23 109 93 135-55 152 124-20 24-137-112-135 56z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="time" unicode="" d="m823 968h-646v-30h52c-14-76-42-354 266-452 300-96 257-367 244-425h-479c-6 33-23 137 19 236l-28 12c-43-103-30-206-22-248h-52v-30h646v30h-54c14 75 45 355-265 454-297 94-257 363-244 423h479c12-57 50-305-206-409l12-28c264 108 238 364 225 437h53v30z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="clock" unicode="" d="m501 484h-307v31h291v161h32v-180l-6-12-10 0z m483 16c0 267-217 484-484 484-39 0-78-4-116-14l8-30c35 9 71 13 108 13 250 0 453-203 453-453s-203-453-453-453-453 203-453 453c0 53 9 106 27 155l-29 11c-20-53-29-109-29-166 0-267 217-484 484-484 267 0 484 217 484 484z m-53 401c-2 21-12 40-28 54-17 14-37 21-58 19-21-1-40-11-54-27l24-20c8 10 19 15 32 16 13 1 25-3 36-12 10-8 16-20 17-33 1-12-2-24-10-34l23-20c14 16 20 36 18 57z m-415 31h-31v-61h31v61z m0-806h-31v-61h31v61z m418 388h-61v-31h61v31z m-806 0h-61v-31h61v31z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="group" unicode="" d="m500 429c-58 0-105 48-105 106 0 59 47 107 105 107 58 0 106-48 106-107 0-58-48-106-106-106z m0 181c-40 0-74-33-74-75s34-75 74-75c41 0 74 34 74 75s-33 75-74 75z m243-356h-31c0 63-97 115-211 115-115 0-212-52-212-115h-31c0 82 107 147 243 147 136 0 242-65 242-147z m-544 327c-50 0-91 41-91 90 0 50 41 91 91 91 50 0 91-41 91-91 0-49-41-90-91-90z m0 149c-33 0-60-26-60-59 0-32 27-59 60-59 33 0 60 27 60 59 0 33-27 59-60 59z m181-309h-32c0 57-63 99-150 99-88 0-151-42-151-99h-31c0 75 76 130 182 130 105 0 182-55 182-130z m422 158c-50 0-90 41-90 91 0 50 40 91 90 91s91-41 91-91c0-50-41-91-91-91z m0 151c-32 0-59-27-59-60 0-33 27-59 59-59s60 26 60 59c0 33-27 60-60 60z m182-309h-31c0 58-63 100-150 100-88 0-151-42-151-100h-31c0 76 76 131 182 131 105 0 181-55 181-131z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="gas" unicode="" d="m500 16c-267 0-484 217-484 484 0 103 32 202 93 285l25-19c-57-77-86-169-86-266 0-250 203-453 452-453 250 0 452 203 452 453 0 250-202 453-452 453-79 0-156-20-224-59l-15 27c72 41 155 63 239 63 267 0 484-217 484-484 0-267-217-484-484-484z m280 453l-13 28 66 28c-6 179-153 322-333 322-183 0-333-149-333-332h-31c0 201 163 364 364 364 201 0 364-163 364-364v-10l-84-36z m-280-270v31c25 0 45 20 45 44 0 44-24 259-45 309-21-50-45-265-45-309h-31c0 18 7 102 18 181 21 154 40 167 58 167 19 0 37-13 58-167 11-79 18-163 18-181 0-41-34-75-76-75z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="difficulty" unicode="" d="m498 21c-9 0-17 3-23 9l-450 450c-12 13-12 33 0 45l140 140c-23 6-43 17-60 34-24 24-38 57-38 92s14 67 38 92c25 25 57 38 92 38s68-13 92-38c25-25 39-58 38-93l-31 0c0 27-10 52-29 71-19 19-43 29-70 29-26 0-51-11-70-29-18-19-29-44-29-70 0-26 11-51 29-70 19-19 45-30 71-29l39 0-190-189 450-451 452 450-140 141c-6-23-17-43-34-60-25-24-57-38-92-38s-67 14-92 38c-25 25-38 57-38 92 0 35 13 68 38 92 17 17 37 29 60 34l-153 152-30-29-22 22 29 29c13 13 33 13 46 0l201-201-38 0c-27 1-52-10-71-29-19-19-29-43-29-70s10-51 29-70c19-18 44-29 70-29s51 11 70 29c19 19 29 44 29 71l-1 39 190-190c6-6 9-14 9-22s-3-17-9-23l-450-450c-6-6-15-9-23-9z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="uncle" unicode="" d="m659 0c-125 0-228 102-228 228 0 41 11 81 32 116l-75 75c-28-17-60-25-92-25-101 0-182 81-182 182s81 182 182 182v-31c-84 0-151-68-151-151s68-151 151-151c30 0 60 9 85 27l11 7 111-111-7-11c-22-32-33-70-33-109 0-109 88-197 196-197s196 88 196 197-88 196-196 196c-46 0-90-16-125-45l-11-9-110 110 7 10c17 26 27 55 27 86 0 27-8 53-22 77l-6 10 128 129 11-6c15-9 31-13 48-13 54 0 98 44 98 98s-44 98-98 98c-16 0-32-4-46-11-32-18-52-51-52-87 0-17 5-34 13-48l6-11-117-117-22 22 100 101c-7 17-11 35-11 53 0 48 26 92 69 114 18 10 39 15 60 15 71 0 129-58 129-129 0-71-58-129-129-129-18 0-36 4-53 11l-95-95c13-26 20-54 20-82 0-33-9-64-25-92l72-72c39 28 86 43 134 43 125 0 228-102 228-227s-103-228-228-228z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="hashrate" unicode="" d="m367 39c-163 37-286 115-340 215-31 57-35 117-13 175l7 20 17-13c80-62 99-64 103-63 4 8-2 42-7 70-8 49-19 110-10 170 17 110 96 175 235 195l24 3-7-23c-15-52-8-91 19-109 31-21 85-11 127 23 67 53 85 142 48 239l-15 38 36-19c271-138 195-309 158-391-7-17-16-37-15-43 3-5 32-40 69-37 39 2 78 46 113 126l12 30 16-28c63-115 73-229 30-331-49-114-161-203-307-242l-8 30c137 37 241 119 286 225 36 84 31 178-14 274-37-74-80-113-128-115-54-3-92 45-97 54-9 16 1 37 15 69 35 81 94 213-110 333 24-95-1-182-69-236-54-43-121-54-164-25-21 14-51 47-37 120-111-21-172-75-186-164-8-55 2-114 10-161 7-44 12-73 2-91-4-8-11-13-20-14-17-4-43 5-111 55-10-43-4-87 19-129 48-91 167-165 319-200l-7-30z" horiz-adv-x="1000" />
|
||||
<glyph glyph-name="gasprice" unicode="" d="m430 1c-8 0-16 3-22 9l-398 398c-12 12-12 32 0 44l345 345 22-22-345-345 398-398 494 494c3 17 11 90 18 161 8 75 17 160 25 222l-58 58c-62-8-146-17-221-24-71-8-145-16-162-19l-8-9-23 22 12 12c6 6 7 7 178 25 77 8 165 17 228 25l8 1 79-79-1-8c-8-63-17-151-26-229-17-170-18-171-24-177l-497-497c-6-6-14-9-22-9z m420 771c-21 0-41 8-55 23-15 14-23 34-23 55 0 21 8 40 23 55s34 23 55 23c21 0 40-8 55-23l-22-22c-18 18-49 18-66 0-9-9-14-21-14-33 0-13 5-24 14-33 17-18 48-18 66 0l22-22c-15-15-34-23-55-23z m-430-565l-22 22 177 177c-73-16-121 29-121 30l21 22-10-11 10 11c4-3 80-72 188 36l0 0 23-22-266-265z" horiz-adv-x="1000" />
|
||||
</font>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 574 B |
|
After Width: | Height: | Size: 574 B |
|
After Width: | Height: | Size: 442 KiB |
|
After Width: | Height: | Size: 722 KiB |
|
After Width: | Height: | Size: 881 KiB |
|
After Width: | Height: | Size: 1.1 MiB |
@@ -0,0 +1,4 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"/>
|
||||
<title>Ethereum Network Status</title>
|
||||
<style type="text/css">[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak { display: none !important; }</style>
|
||||
<link rel="stylesheet" href="//fonts.googleapis.com/css?family=Source+Sans+Pro:200,300,400,600,700"/>
|
||||
@@ -0,0 +1,29 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package.autopublish = {};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,2 @@
|
||||
)]}'
|
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;","file":"/packages/autopublish.js"}
|
||||
@@ -0,0 +1,204 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
var Tracker = Package.tracker.Tracker;
|
||||
var Deps = Package.tracker.Deps;
|
||||
var Retry = Package.retry.Retry;
|
||||
var DDP = Package.ddp.DDP;
|
||||
var Mongo = Package.mongo.Mongo;
|
||||
var _ = Package.underscore._;
|
||||
|
||||
/* Package-scope variables */
|
||||
var Autoupdate, ClientVersions;
|
||||
|
||||
(function () {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/autoupdate/autoupdate_client.js //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Subscribe to the `meteor_autoupdate_clientVersions` collection, // 1
|
||||
// which contains the set of acceptable client versions. // 2
|
||||
// // 3
|
||||
// A "hard code push" occurs when the running client version is not in // 4
|
||||
// the set of acceptable client versions (or the server updates the // 5
|
||||
// collection, there is a published client version marked `current` and // 6
|
||||
// the running client version is no longer in the set). // 7
|
||||
// // 8
|
||||
// When the `reload` package is loaded, a hard code push causes // 9
|
||||
// the browser to reload, so that it will load the latest client // 10
|
||||
// version from the server. // 11
|
||||
// // 12
|
||||
// A "soft code push" represents the situation when the running client // 13
|
||||
// version is in the set of acceptable versions, but there is a newer // 14
|
||||
// version available on the server. // 15
|
||||
// // 16
|
||||
// `Autoupdate.newClientAvailable` is a reactive data source which // 17
|
||||
// becomes `true` if there is a new version of the client is available on // 18
|
||||
// the server. // 19
|
||||
// // 20
|
||||
// This package doesn't implement a soft code reload process itself, // 21
|
||||
// but `newClientAvailable` could be used for example to display a // 22
|
||||
// "click to reload" link to the user. // 23
|
||||
// 24
|
||||
// The client version of the client code currently running in the // 25
|
||||
// browser. // 26
|
||||
var autoupdateVersion = __meteor_runtime_config__.autoupdateVersion || "unknown"; // 27
|
||||
var autoupdateVersionRefreshable = // 28
|
||||
__meteor_runtime_config__.autoupdateVersionRefreshable || "unknown"; // 29
|
||||
// 30
|
||||
// The collection of acceptable client versions. // 31
|
||||
ClientVersions = new Mongo.Collection("meteor_autoupdate_clientVersions"); // 32
|
||||
// 33
|
||||
Autoupdate = {}; // 34
|
||||
// 35
|
||||
Autoupdate.newClientAvailable = function () { // 36
|
||||
return !! ClientVersions.findOne({ // 37
|
||||
_id: "version", // 38
|
||||
version: {$ne: autoupdateVersion} }) || // 39
|
||||
!! ClientVersions.findOne({ // 40
|
||||
_id: "version-refreshable", // 41
|
||||
version: {$ne: autoupdateVersionRefreshable} }); // 42
|
||||
}; // 43
|
||||
// 44
|
||||
var knownToSupportCssOnLoad = false; // 45
|
||||
// 46
|
||||
var retry = new Retry({ // 47
|
||||
// Unlike the stream reconnect use of Retry, which we want to be instant // 48
|
||||
// in normal operation, this is a wacky failure. We don't want to retry // 49
|
||||
// right away, we can start slowly. // 50
|
||||
// // 51
|
||||
// A better way than timeconstants here might be to use the knowledge // 52
|
||||
// of when we reconnect to help trigger these retries. Typically, the // 53
|
||||
// server fixing code will result in a restart and reconnect, but // 54
|
||||
// potentially the subscription could have a transient error. // 55
|
||||
minCount: 0, // don't do any immediate retries // 56
|
||||
baseTimeout: 30*1000 // start with 30s // 57
|
||||
}); // 58
|
||||
var failures = 0; // 59
|
||||
// 60
|
||||
Autoupdate._retrySubscription = function () { // 61
|
||||
Meteor.subscribe("meteor_autoupdate_clientVersions", { // 62
|
||||
onError: function (error) { // 63
|
||||
Meteor._debug("autoupdate subscription failed:", error); // 64
|
||||
failures++; // 65
|
||||
retry.retryLater(failures, function () { // 66
|
||||
// Just retry making the subscription, don't reload the whole // 67
|
||||
// page. While reloading would catch more cases (for example, // 68
|
||||
// the server went back a version and is now doing old-style hot // 69
|
||||
// code push), it would also be more prone to reload loops, // 70
|
||||
// which look really bad to the user. Just retrying the // 71
|
||||
// subscription over DDP means it is at least possible to fix by // 72
|
||||
// updating the server. // 73
|
||||
Autoupdate._retrySubscription(); // 74
|
||||
}); // 75
|
||||
}, // 76
|
||||
onReady: function () { // 77
|
||||
if (Package.reload) { // 78
|
||||
var checkNewVersionDocument = function (doc) { // 79
|
||||
var self = this; // 80
|
||||
if (doc._id === 'version-refreshable' && // 81
|
||||
doc.version !== autoupdateVersionRefreshable) { // 82
|
||||
autoupdateVersionRefreshable = doc.version; // 83
|
||||
// Switch out old css links for the new css links. Inspired by: // 84
|
||||
// https://github.com/guard/guard-livereload/blob/master/js/livereload.js#L710 // 85
|
||||
var newCss = (doc.assets && doc.assets.allCss) || []; // 86
|
||||
var oldLinks = []; // 87
|
||||
_.each(document.getElementsByTagName('link'), function (link) { // 88
|
||||
if (link.className === '__meteor-css__') { // 89
|
||||
oldLinks.push(link); // 90
|
||||
} // 91
|
||||
}); // 92
|
||||
// 93
|
||||
var waitUntilCssLoads = function (link, callback) { // 94
|
||||
var executeCallback = _.once(callback); // 95
|
||||
link.onload = function () { // 96
|
||||
knownToSupportCssOnLoad = true; // 97
|
||||
executeCallback(); // 98
|
||||
}; // 99
|
||||
if (! knownToSupportCssOnLoad) { // 100
|
||||
var id = Meteor.setInterval(function () { // 101
|
||||
if (link.sheet) { // 102
|
||||
executeCallback(); // 103
|
||||
Meteor.clearInterval(id); // 104
|
||||
} // 105
|
||||
}, 50); // 106
|
||||
} // 107
|
||||
}; // 108
|
||||
// 109
|
||||
var removeOldLinks = _.after(newCss.length, function () { // 110
|
||||
_.each(oldLinks, function (oldLink) { // 111
|
||||
oldLink.parentNode.removeChild(oldLink); // 112
|
||||
}); // 113
|
||||
}); // 114
|
||||
// 115
|
||||
var attachStylesheetLink = function (newLink) { // 116
|
||||
document.getElementsByTagName("head").item(0).appendChild(newLink); // 117
|
||||
// 118
|
||||
waitUntilCssLoads(newLink, function () { // 119
|
||||
Meteor.setTimeout(removeOldLinks, 200); // 120
|
||||
}); // 121
|
||||
}; // 122
|
||||
// 123
|
||||
if (newCss.length !== 0) { // 124
|
||||
_.each(newCss, function (css) { // 125
|
||||
var newLink = document.createElement("link"); // 126
|
||||
newLink.setAttribute("rel", "stylesheet"); // 127
|
||||
newLink.setAttribute("type", "text/css"); // 128
|
||||
newLink.setAttribute("class", "__meteor-css__"); // 129
|
||||
newLink.setAttribute("href", Meteor._relativeToSiteRootUrl(css.url)); // 130
|
||||
attachStylesheetLink(newLink); // 131
|
||||
}); // 132
|
||||
} else { // 133
|
||||
removeOldLinks(); // 134
|
||||
} // 135
|
||||
// 136
|
||||
} // 137
|
||||
else if (doc._id === 'version' && doc.version !== autoupdateVersion) { // 138
|
||||
handle && handle.stop(); // 139
|
||||
Package.reload.Reload._reload(); // 140
|
||||
} // 141
|
||||
}; // 142
|
||||
// 143
|
||||
var handle = ClientVersions.find().observe({ // 144
|
||||
added: checkNewVersionDocument, // 145
|
||||
changed: checkNewVersionDocument // 146
|
||||
}); // 147
|
||||
} // 148
|
||||
} // 149
|
||||
}); // 150
|
||||
}; // 151
|
||||
Autoupdate._retrySubscription(); // 152
|
||||
// 153
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package.autoupdate = {
|
||||
Autoupdate: Autoupdate
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,190 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
|
||||
/* Package-scope variables */
|
||||
var Base64;
|
||||
|
||||
(function () {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/base64/base64.js //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Base 64 encoding // 1
|
||||
// 2
|
||||
var BASE_64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; // 3
|
||||
// 4
|
||||
var BASE_64_VALS = {}; // 5
|
||||
// 6
|
||||
for (var i = 0; i < BASE_64_CHARS.length; i++) { // 7
|
||||
BASE_64_VALS[BASE_64_CHARS.charAt(i)] = i; // 8
|
||||
}; // 9
|
||||
// 10
|
||||
Base64 = {}; // 11
|
||||
// 12
|
||||
Base64.encode = function (array) { // 13
|
||||
// 14
|
||||
if (typeof array === "string") { // 15
|
||||
var str = array; // 16
|
||||
array = Base64.newBinary(str.length); // 17
|
||||
for (var i = 0; i < str.length; i++) { // 18
|
||||
var ch = str.charCodeAt(i); // 19
|
||||
if (ch > 0xFF) { // 20
|
||||
throw new Error( // 21
|
||||
"Not ascii. Base64.encode can only take ascii strings."); // 22
|
||||
} // 23
|
||||
array[i] = ch; // 24
|
||||
} // 25
|
||||
} // 26
|
||||
// 27
|
||||
var answer = []; // 28
|
||||
var a = null; // 29
|
||||
var b = null; // 30
|
||||
var c = null; // 31
|
||||
var d = null; // 32
|
||||
for (var i = 0; i < array.length; i++) { // 33
|
||||
switch (i % 3) { // 34
|
||||
case 0: // 35
|
||||
a = (array[i] >> 2) & 0x3F; // 36
|
||||
b = (array[i] & 0x03) << 4; // 37
|
||||
break; // 38
|
||||
case 1: // 39
|
||||
b = b | (array[i] >> 4) & 0xF; // 40
|
||||
c = (array[i] & 0xF) << 2; // 41
|
||||
break; // 42
|
||||
case 2: // 43
|
||||
c = c | (array[i] >> 6) & 0x03; // 44
|
||||
d = array[i] & 0x3F; // 45
|
||||
answer.push(getChar(a)); // 46
|
||||
answer.push(getChar(b)); // 47
|
||||
answer.push(getChar(c)); // 48
|
||||
answer.push(getChar(d)); // 49
|
||||
a = null; // 50
|
||||
b = null; // 51
|
||||
c = null; // 52
|
||||
d = null; // 53
|
||||
break; // 54
|
||||
} // 55
|
||||
} // 56
|
||||
if (a != null) { // 57
|
||||
answer.push(getChar(a)); // 58
|
||||
answer.push(getChar(b)); // 59
|
||||
if (c == null) // 60
|
||||
answer.push('='); // 61
|
||||
else // 62
|
||||
answer.push(getChar(c)); // 63
|
||||
if (d == null) // 64
|
||||
answer.push('='); // 65
|
||||
} // 66
|
||||
return answer.join(""); // 67
|
||||
}; // 68
|
||||
// 69
|
||||
var getChar = function (val) { // 70
|
||||
return BASE_64_CHARS.charAt(val); // 71
|
||||
}; // 72
|
||||
// 73
|
||||
var getVal = function (ch) { // 74
|
||||
if (ch === '=') { // 75
|
||||
return -1; // 76
|
||||
} // 77
|
||||
return BASE_64_VALS[ch]; // 78
|
||||
}; // 79
|
||||
// 80
|
||||
// XXX This is a weird place for this to live, but it's used both by // 81
|
||||
// this package and 'ejson', and we can't put it in 'ejson' without // 82
|
||||
// introducing a circular dependency. It should probably be in its own // 83
|
||||
// package or as a helper in a package that both 'base64' and 'ejson' // 84
|
||||
// use. // 85
|
||||
Base64.newBinary = function (len) { // 86
|
||||
if (typeof Uint8Array === 'undefined' || typeof ArrayBuffer === 'undefined') { // 87
|
||||
var ret = []; // 88
|
||||
for (var i = 0; i < len; i++) { // 89
|
||||
ret.push(0); // 90
|
||||
} // 91
|
||||
ret.$Uint8ArrayPolyfill = true; // 92
|
||||
return ret; // 93
|
||||
} // 94
|
||||
return new Uint8Array(new ArrayBuffer(len)); // 95
|
||||
}; // 96
|
||||
// 97
|
||||
Base64.decode = function (str) { // 98
|
||||
var len = Math.floor((str.length*3)/4); // 99
|
||||
if (str.charAt(str.length - 1) == '=') { // 100
|
||||
len--; // 101
|
||||
if (str.charAt(str.length - 2) == '=') // 102
|
||||
len--; // 103
|
||||
} // 104
|
||||
var arr = Base64.newBinary(len); // 105
|
||||
// 106
|
||||
var one = null; // 107
|
||||
var two = null; // 108
|
||||
var three = null; // 109
|
||||
// 110
|
||||
var j = 0; // 111
|
||||
// 112
|
||||
for (var i = 0; i < str.length; i++) { // 113
|
||||
var c = str.charAt(i); // 114
|
||||
var v = getVal(c); // 115
|
||||
switch (i % 4) { // 116
|
||||
case 0: // 117
|
||||
if (v < 0) // 118
|
||||
throw new Error('invalid base64 string'); // 119
|
||||
one = v << 2; // 120
|
||||
break; // 121
|
||||
case 1: // 122
|
||||
if (v < 0) // 123
|
||||
throw new Error('invalid base64 string'); // 124
|
||||
one = one | (v >> 4); // 125
|
||||
arr[j++] = one; // 126
|
||||
two = (v & 0x0F) << 4; // 127
|
||||
break; // 128
|
||||
case 2: // 129
|
||||
if (v >= 0) { // 130
|
||||
two = two | (v >> 2); // 131
|
||||
arr[j++] = two; // 132
|
||||
three = (v & 0x03) << 6; // 133
|
||||
} // 134
|
||||
break; // 135
|
||||
case 3: // 136
|
||||
if (v >= 0) { // 137
|
||||
arr[j++] = three | v; // 138
|
||||
} // 139
|
||||
break; // 140
|
||||
} // 141
|
||||
} // 142
|
||||
return arr; // 143
|
||||
}; // 144
|
||||
// 145
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package.base64 = {
|
||||
Base64: Base64
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,2 @@
|
||||
)]}'
|
||||
{"version":3,"sources":["base64/base64.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,mB;;AAEA,uF;;AAEA,sB;;AAEA,gD;AACA,4C;AACA,E;;AAEA,Y;;AAEA,kC;;AAEA,kC;AACA,oB;AACA,yC;AACA,0C;AACA,iC;AACA,sB;AACA,wB;AACA,mE;AACA,O;AACA,oB;AACA,K;AACA,G;;AAEA,kB;AACA,e;AACA,e;AACA,e;AACA,e;AACA,0C;AACA,oB;AACA,W;AACA,iC;AACA,iC;AACA,Y;AACA,W;AACA,oC;AACA,gC;AACA,Y;AACA,W;AACA,qC;AACA,0B;AACA,8B;AACA,8B;AACA,8B;AACA,8B;AACA,e;AACA,e;AACA,e;AACA,e;AACA,Y;AACA,K;AACA,G;AACA,kB;AACA,4B;AACA,4B;AACA,kB;AACA,uB;AACA,Q;AACA,8B;AACA,kB;AACA,uB;AACA,G;AACA,yB;AACA,E;;AAEA,8B;AACA,mC;AACA,E;;AAEA,4B;AACA,mB;AACA,c;AACA,G;AACA,0B;AACA,E;;AAEA,oE;AACA,mE;AACA,sE;AACA,qE;AACA,O;AACA,mC;AACA,gF;AACA,iB;AACA,mC;AACA,kB;AACA,K;AACA,mC;AACA,e;AACA,G;AACA,8C;AACA,E;;AAEA,gC;AACA,yC;AACA,0C;AACA,U;AACA,0C;AACA,Y;AACA,G;AACA,kC;;AAEA,iB;AACA,iB;AACA,mB;;AAEA,Y;;AAEA,wC;AACA,0B;AACA,sB;AACA,oB;AACA,W;AACA,gB;AACA,iD;AACA,mB;AACA,Y;AACA,W;AACA,gB;AACA,iD;AACA,2B;AACA,qB;AACA,4B;AACA,Y;AACA,W;AACA,mB;AACA,6B;AACA,uB;AACA,gC;AACA,O;AACA,Y;AACA,W;AACA,mB;AACA,6B;AACA,O;AACA,Y;AACA,K;AACA,G;AACA,a;AACA,E","file":"/packages/base64.js","sourcesContent":["// Base 64 encoding\n\nvar BASE_64_CHARS = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\";\n\nvar BASE_64_VALS = {};\n\nfor (var i = 0; i < BASE_64_CHARS.length; i++) {\n BASE_64_VALS[BASE_64_CHARS.charAt(i)] = i;\n};\n\nBase64 = {};\n\nBase64.encode = function (array) {\n\n if (typeof array === \"string\") {\n var str = array;\n array = Base64.newBinary(str.length);\n for (var i = 0; i < str.length; i++) {\n var ch = str.charCodeAt(i);\n if (ch > 0xFF) {\n throw new Error(\n \"Not ascii. Base64.encode can only take ascii strings.\");\n }\n array[i] = ch;\n }\n }\n\n var answer = [];\n var a = null;\n var b = null;\n var c = null;\n var d = null;\n for (var i = 0; i < array.length; i++) {\n switch (i % 3) {\n case 0:\n a = (array[i] >> 2) & 0x3F;\n b = (array[i] & 0x03) << 4;\n break;\n case 1:\n b = b | (array[i] >> 4) & 0xF;\n c = (array[i] & 0xF) << 2;\n break;\n case 2:\n c = c | (array[i] >> 6) & 0x03;\n d = array[i] & 0x3F;\n answer.push(getChar(a));\n answer.push(getChar(b));\n answer.push(getChar(c));\n answer.push(getChar(d));\n a = null;\n b = null;\n c = null;\n d = null;\n break;\n }\n }\n if (a != null) {\n answer.push(getChar(a));\n answer.push(getChar(b));\n if (c == null)\n answer.push('=');\n else\n answer.push(getChar(c));\n if (d == null)\n answer.push('=');\n }\n return answer.join(\"\");\n};\n\nvar getChar = function (val) {\n return BASE_64_CHARS.charAt(val);\n};\n\nvar getVal = function (ch) {\n if (ch === '=') {\n return -1;\n }\n return BASE_64_VALS[ch];\n};\n\n// XXX This is a weird place for this to live, but it's used both by\n// this package and 'ejson', and we can't put it in 'ejson' without\n// introducing a circular dependency. It should probably be in its own\n// package or as a helper in a package that both 'base64' and 'ejson'\n// use.\nBase64.newBinary = function (len) {\n if (typeof Uint8Array === 'undefined' || typeof ArrayBuffer === 'undefined') {\n var ret = [];\n for (var i = 0; i < len; i++) {\n ret.push(0);\n }\n ret.$Uint8ArrayPolyfill = true;\n return ret;\n }\n return new Uint8Array(new ArrayBuffer(len));\n};\n\nBase64.decode = function (str) {\n var len = Math.floor((str.length*3)/4);\n if (str.charAt(str.length - 1) == '=') {\n len--;\n if (str.charAt(str.length - 2) == '=')\n len--;\n }\n var arr = Base64.newBinary(len);\n\n var one = null;\n var two = null;\n var three = null;\n\n var j = 0;\n\n for (var i = 0; i < str.length; i++) {\n var c = str.charAt(i);\n var v = getVal(c);\n switch (i % 4) {\n case 0:\n if (v < 0)\n throw new Error('invalid base64 string');\n one = v << 2;\n break;\n case 1:\n if (v < 0)\n throw new Error('invalid base64 string');\n one = one | (v >> 4);\n arr[j++] = one;\n two = (v & 0x0F) << 4;\n break;\n case 2:\n if (v >= 0) {\n two = two | (v >> 2);\n arr[j++] = two;\n three = (v & 0x03) << 6;\n }\n break;\n case 3:\n if (v >= 0) {\n arr[j++] = three | v;\n }\n break;\n }\n }\n return arr;\n};\n"]}
|
||||
3609
web-app/.meteor/local/build/programs/web.browser/packages/blaze.js
Normal file
@@ -0,0 +1,431 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
var _ = Package.underscore._;
|
||||
var EJSON = Package.ejson.EJSON;
|
||||
|
||||
/* Package-scope variables */
|
||||
var check, Match;
|
||||
|
||||
(function () {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/check/match.js //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// XXX docs // 1
|
||||
// 2
|
||||
// Things we explicitly do NOT support: // 3
|
||||
// - heterogenous arrays // 4
|
||||
// 5
|
||||
var currentArgumentChecker = new Meteor.EnvironmentVariable; // 6
|
||||
// 7
|
||||
/** // 8
|
||||
* @summary Check that a value matches a [pattern](#matchpatterns). // 9
|
||||
* If the value does not match the pattern, throw a `Match.Error`. // 10
|
||||
* // 11
|
||||
* Particularly useful to assert that arguments to a function have the right // 12
|
||||
* types and structure. // 13
|
||||
* @locus Anywhere // 14
|
||||
* @param {Any} value The value to check // 15
|
||||
* @param {MatchPattern} pattern The pattern to match // 16
|
||||
* `value` against // 17
|
||||
*/ // 18
|
||||
check = function (value, pattern) { // 19
|
||||
// Record that check got called, if somebody cared. // 20
|
||||
// // 21
|
||||
// We use getOrNullIfOutsideFiber so that it's OK to call check() // 22
|
||||
// from non-Fiber server contexts; the downside is that if you forget to // 23
|
||||
// bindEnvironment on some random callback in your method/publisher, // 24
|
||||
// it might not find the argumentChecker and you'll get an error about // 25
|
||||
// not checking an argument that it looks like you're checking (instead // 26
|
||||
// of just getting a "Node code must run in a Fiber" error). // 27
|
||||
var argChecker = currentArgumentChecker.getOrNullIfOutsideFiber(); // 28
|
||||
if (argChecker) // 29
|
||||
argChecker.checking(value); // 30
|
||||
try { // 31
|
||||
checkSubtree(value, pattern); // 32
|
||||
} catch (err) { // 33
|
||||
if ((err instanceof Match.Error) && err.path) // 34
|
||||
err.message += " in field " + err.path; // 35
|
||||
throw err; // 36
|
||||
} // 37
|
||||
}; // 38
|
||||
// 39
|
||||
/** // 40
|
||||
* @namespace Match // 41
|
||||
* @summary The namespace for all Match types and methods. // 42
|
||||
*/ // 43
|
||||
Match = { // 44
|
||||
Optional: function (pattern) { // 45
|
||||
return new Optional(pattern); // 46
|
||||
}, // 47
|
||||
OneOf: function (/*arguments*/) { // 48
|
||||
return new OneOf(_.toArray(arguments)); // 49
|
||||
}, // 50
|
||||
Any: ['__any__'], // 51
|
||||
Where: function (condition) { // 52
|
||||
return new Where(condition); // 53
|
||||
}, // 54
|
||||
ObjectIncluding: function (pattern) { // 55
|
||||
return new ObjectIncluding(pattern); // 56
|
||||
}, // 57
|
||||
ObjectWithValues: function (pattern) { // 58
|
||||
return new ObjectWithValues(pattern); // 59
|
||||
}, // 60
|
||||
// Matches only signed 32-bit integers // 61
|
||||
Integer: ['__integer__'], // 62
|
||||
// 63
|
||||
// XXX matchers should know how to describe themselves for errors // 64
|
||||
Error: Meteor.makeErrorType("Match.Error", function (msg) { // 65
|
||||
this.message = "Match error: " + msg; // 66
|
||||
// The path of the value that failed to match. Initially empty, this gets // 67
|
||||
// populated by catching and rethrowing the exception as it goes back up the // 68
|
||||
// stack. // 69
|
||||
// E.g.: "vals[3].entity.created" // 70
|
||||
this.path = ""; // 71
|
||||
// If this gets sent over DDP, don't give full internal details but at least // 72
|
||||
// provide something better than 500 Internal server error. // 73
|
||||
this.sanitizedError = new Meteor.Error(400, "Match failed"); // 74
|
||||
}), // 75
|
||||
// 76
|
||||
// Tests to see if value matches pattern. Unlike check, it merely returns true // 77
|
||||
// or false (unless an error other than Match.Error was thrown). It does not // 78
|
||||
// interact with _failIfArgumentsAreNotAllChecked. // 79
|
||||
// XXX maybe also implement a Match.match which returns more information about // 80
|
||||
// failures but without using exception handling or doing what check() // 81
|
||||
// does with _failIfArgumentsAreNotAllChecked and Meteor.Error conversion // 82
|
||||
// 83
|
||||
/** // 84
|
||||
* @summary Returns true if the value matches the pattern. // 85
|
||||
* @locus Anywhere // 86
|
||||
* @param {Any} value The value to check // 87
|
||||
* @param {MatchPattern} pattern The pattern to match `value` against // 88
|
||||
*/ // 89
|
||||
test: function (value, pattern) { // 90
|
||||
try { // 91
|
||||
checkSubtree(value, pattern); // 92
|
||||
return true; // 93
|
||||
} catch (e) { // 94
|
||||
if (e instanceof Match.Error) // 95
|
||||
return false; // 96
|
||||
// Rethrow other errors. // 97
|
||||
throw e; // 98
|
||||
} // 99
|
||||
}, // 100
|
||||
// 101
|
||||
// Runs `f.apply(context, args)`. If check() is not called on every element of // 102
|
||||
// `args` (either directly or in the first level of an array), throws an error // 103
|
||||
// (using `description` in the message). // 104
|
||||
// // 105
|
||||
_failIfArgumentsAreNotAllChecked: function (f, context, args, description) { // 106
|
||||
var argChecker = new ArgumentChecker(args, description); // 107
|
||||
var result = currentArgumentChecker.withValue(argChecker, function () { // 108
|
||||
return f.apply(context, args); // 109
|
||||
}); // 110
|
||||
// If f didn't itself throw, make sure it checked all of its arguments. // 111
|
||||
argChecker.throwUnlessAllArgumentsHaveBeenChecked(); // 112
|
||||
return result; // 113
|
||||
} // 114
|
||||
}; // 115
|
||||
// 116
|
||||
var Optional = function (pattern) { // 117
|
||||
this.pattern = pattern; // 118
|
||||
}; // 119
|
||||
// 120
|
||||
var OneOf = function (choices) { // 121
|
||||
if (_.isEmpty(choices)) // 122
|
||||
throw new Error("Must provide at least one choice to Match.OneOf"); // 123
|
||||
this.choices = choices; // 124
|
||||
}; // 125
|
||||
// 126
|
||||
var Where = function (condition) { // 127
|
||||
this.condition = condition; // 128
|
||||
}; // 129
|
||||
// 130
|
||||
var ObjectIncluding = function (pattern) { // 131
|
||||
this.pattern = pattern; // 132
|
||||
}; // 133
|
||||
// 134
|
||||
var ObjectWithValues = function (pattern) { // 135
|
||||
this.pattern = pattern; // 136
|
||||
}; // 137
|
||||
// 138
|
||||
var typeofChecks = [ // 139
|
||||
[String, "string"], // 140
|
||||
[Number, "number"], // 141
|
||||
[Boolean, "boolean"], // 142
|
||||
// While we don't allow undefined in EJSON, this is good for optional // 143
|
||||
// arguments with OneOf. // 144
|
||||
[undefined, "undefined"] // 145
|
||||
]; // 146
|
||||
// 147
|
||||
var checkSubtree = function (value, pattern) { // 148
|
||||
// Match anything! // 149
|
||||
if (pattern === Match.Any) // 150
|
||||
return; // 151
|
||||
// 152
|
||||
// Basic atomic types. // 153
|
||||
// Do not match boxed objects (e.g. String, Boolean) // 154
|
||||
for (var i = 0; i < typeofChecks.length; ++i) { // 155
|
||||
if (pattern === typeofChecks[i][0]) { // 156
|
||||
if (typeof value === typeofChecks[i][1]) // 157
|
||||
return; // 158
|
||||
throw new Match.Error("Expected " + typeofChecks[i][1] + ", got " + // 159
|
||||
typeof value); // 160
|
||||
} // 161
|
||||
} // 162
|
||||
if (pattern === null) { // 163
|
||||
if (value === null) // 164
|
||||
return; // 165
|
||||
throw new Match.Error("Expected null, got " + EJSON.stringify(value)); // 166
|
||||
} // 167
|
||||
// 168
|
||||
// Strings and numbers match literally. Goes well with Match.OneOf. // 169
|
||||
if (typeof pattern === "string" || typeof pattern === "number") { // 170
|
||||
if (value === pattern) // 171
|
||||
return; // 172
|
||||
throw new Match.Error("Expected " + pattern + ", got " + // 173
|
||||
EJSON.stringify(value)); // 174
|
||||
} // 175
|
||||
// 176
|
||||
// Match.Integer is special type encoded with array // 177
|
||||
if (pattern === Match.Integer) { // 178
|
||||
// There is no consistent and reliable way to check if variable is a 64-bit // 179
|
||||
// integer. One of the popular solutions is to get reminder of division by 1 // 180
|
||||
// but this method fails on really large floats with big precision. // 181
|
||||
// E.g.: 1.348192308491824e+23 % 1 === 0 in V8 // 182
|
||||
// Bitwise operators work consistantly but always cast variable to 32-bit // 183
|
||||
// signed integer according to JavaScript specs. // 184
|
||||
if (typeof value === "number" && (value | 0) === value) // 185
|
||||
return // 186
|
||||
throw new Match.Error("Expected Integer, got " // 187
|
||||
+ (value instanceof Object ? EJSON.stringify(value) : value)); // 188
|
||||
} // 189
|
||||
// 190
|
||||
// "Object" is shorthand for Match.ObjectIncluding({}); // 191
|
||||
if (pattern === Object) // 192
|
||||
pattern = Match.ObjectIncluding({}); // 193
|
||||
// 194
|
||||
// Array (checked AFTER Any, which is implemented as an Array). // 195
|
||||
if (pattern instanceof Array) { // 196
|
||||
if (pattern.length !== 1) // 197
|
||||
throw Error("Bad pattern: arrays must have one type element" + // 198
|
||||
EJSON.stringify(pattern)); // 199
|
||||
if (!_.isArray(value) && !_.isArguments(value)) { // 200
|
||||
throw new Match.Error("Expected array, got " + EJSON.stringify(value)); // 201
|
||||
} // 202
|
||||
// 203
|
||||
_.each(value, function (valueElement, index) { // 204
|
||||
try { // 205
|
||||
checkSubtree(valueElement, pattern[0]); // 206
|
||||
} catch (err) { // 207
|
||||
if (err instanceof Match.Error) { // 208
|
||||
err.path = _prependPath(index, err.path); // 209
|
||||
} // 210
|
||||
throw err; // 211
|
||||
} // 212
|
||||
}); // 213
|
||||
return; // 214
|
||||
} // 215
|
||||
// 216
|
||||
// Arbitrary validation checks. The condition can return false or throw a // 217
|
||||
// Match.Error (ie, it can internally use check()) to fail. // 218
|
||||
if (pattern instanceof Where) { // 219
|
||||
if (pattern.condition(value)) // 220
|
||||
return; // 221
|
||||
// XXX this error is terrible // 222
|
||||
throw new Match.Error("Failed Match.Where validation"); // 223
|
||||
} // 224
|
||||
// 225
|
||||
// 226
|
||||
if (pattern instanceof Optional) // 227
|
||||
pattern = Match.OneOf(undefined, pattern.pattern); // 228
|
||||
// 229
|
||||
if (pattern instanceof OneOf) { // 230
|
||||
for (var i = 0; i < pattern.choices.length; ++i) { // 231
|
||||
try { // 232
|
||||
checkSubtree(value, pattern.choices[i]); // 233
|
||||
// No error? Yay, return. // 234
|
||||
return; // 235
|
||||
} catch (err) { // 236
|
||||
// Other errors should be thrown. Match errors just mean try another // 237
|
||||
// choice. // 238
|
||||
if (!(err instanceof Match.Error)) // 239
|
||||
throw err; // 240
|
||||
} // 241
|
||||
} // 242
|
||||
// XXX this error is terrible // 243
|
||||
throw new Match.Error("Failed Match.OneOf or Match.Optional validation"); // 244
|
||||
} // 245
|
||||
// 246
|
||||
// A function that isn't something we special-case is assumed to be a // 247
|
||||
// constructor. // 248
|
||||
if (pattern instanceof Function) { // 249
|
||||
if (value instanceof pattern) // 250
|
||||
return; // 251
|
||||
throw new Match.Error("Expected " + (pattern.name || // 252
|
||||
"particular constructor")); // 253
|
||||
} // 254
|
||||
// 255
|
||||
var unknownKeysAllowed = false; // 256
|
||||
var unknownKeyPattern; // 257
|
||||
if (pattern instanceof ObjectIncluding) { // 258
|
||||
unknownKeysAllowed = true; // 259
|
||||
pattern = pattern.pattern; // 260
|
||||
} // 261
|
||||
if (pattern instanceof ObjectWithValues) { // 262
|
||||
unknownKeysAllowed = true; // 263
|
||||
unknownKeyPattern = [pattern.pattern]; // 264
|
||||
pattern = {}; // no required keys // 265
|
||||
} // 266
|
||||
// 267
|
||||
if (typeof pattern !== "object") // 268
|
||||
throw Error("Bad pattern: unknown pattern type"); // 269
|
||||
// 270
|
||||
// An object, with required and optional keys. Note that this does NOT do // 271
|
||||
// structural matches against objects of special types that happen to match // 272
|
||||
// the pattern: this really needs to be a plain old {Object}! // 273
|
||||
if (typeof value !== 'object') // 274
|
||||
throw new Match.Error("Expected object, got " + typeof value); // 275
|
||||
if (value === null) // 276
|
||||
throw new Match.Error("Expected object, got null"); // 277
|
||||
if (value.constructor !== Object) // 278
|
||||
throw new Match.Error("Expected plain object"); // 279
|
||||
// 280
|
||||
var requiredPatterns = {}; // 281
|
||||
var optionalPatterns = {}; // 282
|
||||
_.each(pattern, function (subPattern, key) { // 283
|
||||
if (subPattern instanceof Optional) // 284
|
||||
optionalPatterns[key] = subPattern.pattern; // 285
|
||||
else // 286
|
||||
requiredPatterns[key] = subPattern; // 287
|
||||
}); // 288
|
||||
// 289
|
||||
_.each(value, function (subValue, key) { // 290
|
||||
try { // 291
|
||||
if (_.has(requiredPatterns, key)) { // 292
|
||||
checkSubtree(subValue, requiredPatterns[key]); // 293
|
||||
delete requiredPatterns[key]; // 294
|
||||
} else if (_.has(optionalPatterns, key)) { // 295
|
||||
checkSubtree(subValue, optionalPatterns[key]); // 296
|
||||
} else { // 297
|
||||
if (!unknownKeysAllowed) // 298
|
||||
throw new Match.Error("Unknown key"); // 299
|
||||
if (unknownKeyPattern) { // 300
|
||||
checkSubtree(subValue, unknownKeyPattern[0]); // 301
|
||||
} // 302
|
||||
} // 303
|
||||
} catch (err) { // 304
|
||||
if (err instanceof Match.Error) // 305
|
||||
err.path = _prependPath(key, err.path); // 306
|
||||
throw err; // 307
|
||||
} // 308
|
||||
}); // 309
|
||||
// 310
|
||||
_.each(requiredPatterns, function (subPattern, key) { // 311
|
||||
throw new Match.Error("Missing key '" + key + "'"); // 312
|
||||
}); // 313
|
||||
}; // 314
|
||||
// 315
|
||||
var ArgumentChecker = function (args, description) { // 316
|
||||
var self = this; // 317
|
||||
// Make a SHALLOW copy of the arguments. (We'll be doing identity checks // 318
|
||||
// against its contents.) // 319
|
||||
self.args = _.clone(args); // 320
|
||||
// Since the common case will be to check arguments in order, and we splice // 321
|
||||
// out arguments when we check them, make it so we splice out from the end // 322
|
||||
// rather than the beginning. // 323
|
||||
self.args.reverse(); // 324
|
||||
self.description = description; // 325
|
||||
}; // 326
|
||||
// 327
|
||||
_.extend(ArgumentChecker.prototype, { // 328
|
||||
checking: function (value) { // 329
|
||||
var self = this; // 330
|
||||
if (self._checkingOneValue(value)) // 331
|
||||
return; // 332
|
||||
// Allow check(arguments, [String]) or check(arguments.slice(1), [String]) // 333
|
||||
// or check([foo, bar], [String]) to count... but only if value wasn't // 334
|
||||
// itself an argument. // 335
|
||||
if (_.isArray(value) || _.isArguments(value)) { // 336
|
||||
_.each(value, _.bind(self._checkingOneValue, self)); // 337
|
||||
} // 338
|
||||
}, // 339
|
||||
_checkingOneValue: function (value) { // 340
|
||||
var self = this; // 341
|
||||
for (var i = 0; i < self.args.length; ++i) { // 342
|
||||
// Is this value one of the arguments? (This can have a false positive if // 343
|
||||
// the argument is an interned primitive, but it's still a good enough // 344
|
||||
// check.) // 345
|
||||
// (NaN is not === to itself, so we have to check specially.) // 346
|
||||
if (value === self.args[i] || (_.isNaN(value) && _.isNaN(self.args[i]))) { // 347
|
||||
self.args.splice(i, 1); // 348
|
||||
return true; // 349
|
||||
} // 350
|
||||
} // 351
|
||||
return false; // 352
|
||||
}, // 353
|
||||
throwUnlessAllArgumentsHaveBeenChecked: function () { // 354
|
||||
var self = this; // 355
|
||||
if (!_.isEmpty(self.args)) // 356
|
||||
throw new Error("Did not check() all arguments during " + // 357
|
||||
self.description); // 358
|
||||
} // 359
|
||||
}); // 360
|
||||
// 361
|
||||
var _jsKeywords = ["do", "if", "in", "for", "let", "new", "try", "var", "case", // 362
|
||||
"else", "enum", "eval", "false", "null", "this", "true", "void", "with", // 363
|
||||
"break", "catch", "class", "const", "super", "throw", "while", "yield", // 364
|
||||
"delete", "export", "import", "public", "return", "static", "switch", // 365
|
||||
"typeof", "default", "extends", "finally", "package", "private", "continue", // 366
|
||||
"debugger", "function", "arguments", "interface", "protected", "implements", // 367
|
||||
"instanceof"]; // 368
|
||||
// 369
|
||||
// Assumes the base of path is already escaped properly // 370
|
||||
// returns key + base // 371
|
||||
var _prependPath = function (key, base) { // 372
|
||||
if ((typeof key) === "number" || key.match(/^[0-9]+$/)) // 373
|
||||
key = "[" + key + "]"; // 374
|
||||
else if (!key.match(/^[a-z_$][0-9a-z_$]*$/i) || _.contains(_jsKeywords, key)) // 375
|
||||
key = JSON.stringify([key]); // 376
|
||||
// 377
|
||||
if (base && base[0] !== "[") // 378
|
||||
return key + '.' + base; // 379
|
||||
return key + base; // 380
|
||||
}; // 381
|
||||
// 382
|
||||
// 383
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package.check = {
|
||||
check: check,
|
||||
Match: Match
|
||||
};
|
||||
|
||||
})();
|
||||
9544
web-app/.meteor/local/build/programs/web.browser/packages/d3js_d3.js
vendored
Normal file
5208
web-app/.meteor/local/build/programs/web.browser/packages/ddp.js
Normal file
@@ -0,0 +1,37 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
var Tracker = Package.tracker.Tracker;
|
||||
var Deps = Package.tracker.Deps;
|
||||
|
||||
/* Package-scope variables */
|
||||
var Tracker, Deps;
|
||||
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package.deps = {
|
||||
Tracker: Tracker,
|
||||
Deps: Deps
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,2 @@
|
||||
)]}'
|
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;","file":"/packages/deps.js"}
|
||||
@@ -0,0 +1,695 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
var JSON = Package.json.JSON;
|
||||
var _ = Package.underscore._;
|
||||
var Base64 = Package.base64.Base64;
|
||||
|
||||
/* Package-scope variables */
|
||||
var EJSON, EJSONTest;
|
||||
|
||||
(function () {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/ejson/ejson.js //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/** // 1
|
||||
* @namespace // 2
|
||||
* @summary Namespace for EJSON functions // 3
|
||||
*/ // 4
|
||||
EJSON = {}; // 5
|
||||
EJSONTest = {}; // 6
|
||||
// 7
|
||||
// 8
|
||||
// 9
|
||||
// Custom type interface definition // 10
|
||||
/** // 11
|
||||
* @class CustomType // 12
|
||||
* @instanceName customType // 13
|
||||
* @memberOf EJSON // 14
|
||||
* @summary The interface that a class must satisfy to be able to become an // 15
|
||||
* EJSON custom type via EJSON.addType. // 16
|
||||
*/ // 17
|
||||
// 18
|
||||
/** // 19
|
||||
* @function typeName // 20
|
||||
* @memberOf EJSON.CustomType // 21
|
||||
* @summary Return the tag used to identify this type. This must match the tag used to register this type with [`EJSON.addType`](#ejson_add_type).
|
||||
* @locus Anywhere // 23
|
||||
* @instance // 24
|
||||
*/ // 25
|
||||
// 26
|
||||
/** // 27
|
||||
* @function toJSONValue // 28
|
||||
* @memberOf EJSON.CustomType // 29
|
||||
* @summary Serialize this instance into a JSON-compatible value. // 30
|
||||
* @locus Anywhere // 31
|
||||
* @instance // 32
|
||||
*/ // 33
|
||||
// 34
|
||||
/** // 35
|
||||
* @function clone // 36
|
||||
* @memberOf EJSON.CustomType // 37
|
||||
* @summary Return a value `r` such that `this.equals(r)` is true, and modifications to `r` do not affect `this` and vice versa.
|
||||
* @locus Anywhere // 39
|
||||
* @instance // 40
|
||||
*/ // 41
|
||||
// 42
|
||||
/** // 43
|
||||
* @function equals // 44
|
||||
* @memberOf EJSON.CustomType // 45
|
||||
* @summary Return `true` if `other` has a value equal to `this`; `false` otherwise. // 46
|
||||
* @locus Anywhere // 47
|
||||
* @param {Object} other Another object to compare this to. // 48
|
||||
* @instance // 49
|
||||
*/ // 50
|
||||
// 51
|
||||
// 52
|
||||
var customTypes = {}; // 53
|
||||
// Add a custom type, using a method of your choice to get to and // 54
|
||||
// from a basic JSON-able representation. The factory argument // 55
|
||||
// is a function of JSON-able --> your object // 56
|
||||
// The type you add must have: // 57
|
||||
// - A toJSONValue() method, so that Meteor can serialize it // 58
|
||||
// - a typeName() method, to show how to look it up in our type table. // 59
|
||||
// It is okay if these methods are monkey-patched on. // 60
|
||||
// EJSON.clone will use toJSONValue and the given factory to produce // 61
|
||||
// a clone, but you may specify a method clone() that will be // 62
|
||||
// used instead. // 63
|
||||
// Similarly, EJSON.equals will use toJSONValue to make comparisons, // 64
|
||||
// but you may provide a method equals() instead. // 65
|
||||
/** // 66
|
||||
* @summary Add a custom datatype to EJSON. // 67
|
||||
* @locus Anywhere // 68
|
||||
* @param {String} name A tag for your custom type; must be unique among custom data types defined in your project, and must match the result of your type's `typeName` method.
|
||||
* @param {Function} factory A function that deserializes a JSON-compatible value into an instance of your type. This should match the serialization performed by your type's `toJSONValue` method.
|
||||
*/ // 71
|
||||
EJSON.addType = function (name, factory) { // 72
|
||||
if (_.has(customTypes, name)) // 73
|
||||
throw new Error("Type " + name + " already present"); // 74
|
||||
customTypes[name] = factory; // 75
|
||||
}; // 76
|
||||
// 77
|
||||
var isInfOrNan = function (obj) { // 78
|
||||
return _.isNaN(obj) || obj === Infinity || obj === -Infinity; // 79
|
||||
}; // 80
|
||||
// 81
|
||||
var builtinConverters = [ // 82
|
||||
{ // Date // 83
|
||||
matchJSONValue: function (obj) { // 84
|
||||
return _.has(obj, '$date') && _.size(obj) === 1; // 85
|
||||
}, // 86
|
||||
matchObject: function (obj) { // 87
|
||||
return obj instanceof Date; // 88
|
||||
}, // 89
|
||||
toJSONValue: function (obj) { // 90
|
||||
return {$date: obj.getTime()}; // 91
|
||||
}, // 92
|
||||
fromJSONValue: function (obj) { // 93
|
||||
return new Date(obj.$date); // 94
|
||||
} // 95
|
||||
}, // 96
|
||||
{ // NaN, Inf, -Inf. (These are the only objects with typeof !== 'object' // 97
|
||||
// which we match.) // 98
|
||||
matchJSONValue: function (obj) { // 99
|
||||
return _.has(obj, '$InfNaN') && _.size(obj) === 1; // 100
|
||||
}, // 101
|
||||
matchObject: isInfOrNan, // 102
|
||||
toJSONValue: function (obj) { // 103
|
||||
var sign; // 104
|
||||
if (_.isNaN(obj)) // 105
|
||||
sign = 0; // 106
|
||||
else if (obj === Infinity) // 107
|
||||
sign = 1; // 108
|
||||
else // 109
|
||||
sign = -1; // 110
|
||||
return {$InfNaN: sign}; // 111
|
||||
}, // 112
|
||||
fromJSONValue: function (obj) { // 113
|
||||
return obj.$InfNaN/0; // 114
|
||||
} // 115
|
||||
}, // 116
|
||||
{ // Binary // 117
|
||||
matchJSONValue: function (obj) { // 118
|
||||
return _.has(obj, '$binary') && _.size(obj) === 1; // 119
|
||||
}, // 120
|
||||
matchObject: function (obj) { // 121
|
||||
return typeof Uint8Array !== 'undefined' && obj instanceof Uint8Array // 122
|
||||
|| (obj && _.has(obj, '$Uint8ArrayPolyfill')); // 123
|
||||
}, // 124
|
||||
toJSONValue: function (obj) { // 125
|
||||
return {$binary: Base64.encode(obj)}; // 126
|
||||
}, // 127
|
||||
fromJSONValue: function (obj) { // 128
|
||||
return Base64.decode(obj.$binary); // 129
|
||||
} // 130
|
||||
}, // 131
|
||||
{ // Escaping one level // 132
|
||||
matchJSONValue: function (obj) { // 133
|
||||
return _.has(obj, '$escape') && _.size(obj) === 1; // 134
|
||||
}, // 135
|
||||
matchObject: function (obj) { // 136
|
||||
if (_.isEmpty(obj) || _.size(obj) > 2) { // 137
|
||||
return false; // 138
|
||||
} // 139
|
||||
return _.any(builtinConverters, function (converter) { // 140
|
||||
return converter.matchJSONValue(obj); // 141
|
||||
}); // 142
|
||||
}, // 143
|
||||
toJSONValue: function (obj) { // 144
|
||||
var newObj = {}; // 145
|
||||
_.each(obj, function (value, key) { // 146
|
||||
newObj[key] = EJSON.toJSONValue(value); // 147
|
||||
}); // 148
|
||||
return {$escape: newObj}; // 149
|
||||
}, // 150
|
||||
fromJSONValue: function (obj) { // 151
|
||||
var newObj = {}; // 152
|
||||
_.each(obj.$escape, function (value, key) { // 153
|
||||
newObj[key] = EJSON.fromJSONValue(value); // 154
|
||||
}); // 155
|
||||
return newObj; // 156
|
||||
} // 157
|
||||
}, // 158
|
||||
{ // Custom // 159
|
||||
matchJSONValue: function (obj) { // 160
|
||||
return _.has(obj, '$type') && _.has(obj, '$value') && _.size(obj) === 2; // 161
|
||||
}, // 162
|
||||
matchObject: function (obj) { // 163
|
||||
return EJSON._isCustomType(obj); // 164
|
||||
}, // 165
|
||||
toJSONValue: function (obj) { // 166
|
||||
var jsonValue = Meteor._noYieldsAllowed(function () { // 167
|
||||
return obj.toJSONValue(); // 168
|
||||
}); // 169
|
||||
return {$type: obj.typeName(), $value: jsonValue}; // 170
|
||||
}, // 171
|
||||
fromJSONValue: function (obj) { // 172
|
||||
var typeName = obj.$type; // 173
|
||||
if (!_.has(customTypes, typeName)) // 174
|
||||
throw new Error("Custom EJSON type " + typeName + " is not defined"); // 175
|
||||
var converter = customTypes[typeName]; // 176
|
||||
return Meteor._noYieldsAllowed(function () { // 177
|
||||
return converter(obj.$value); // 178
|
||||
}); // 179
|
||||
} // 180
|
||||
} // 181
|
||||
]; // 182
|
||||
// 183
|
||||
EJSON._isCustomType = function (obj) { // 184
|
||||
return obj && // 185
|
||||
typeof obj.toJSONValue === 'function' && // 186
|
||||
typeof obj.typeName === 'function' && // 187
|
||||
_.has(customTypes, obj.typeName()); // 188
|
||||
}; // 189
|
||||
// 190
|
||||
// 191
|
||||
// for both arrays and objects, in-place modification. // 192
|
||||
var adjustTypesToJSONValue = // 193
|
||||
EJSON._adjustTypesToJSONValue = function (obj) { // 194
|
||||
// Is it an atom that we need to adjust? // 195
|
||||
if (obj === null) // 196
|
||||
return null; // 197
|
||||
var maybeChanged = toJSONValueHelper(obj); // 198
|
||||
if (maybeChanged !== undefined) // 199
|
||||
return maybeChanged; // 200
|
||||
// 201
|
||||
// Other atoms are unchanged. // 202
|
||||
if (typeof obj !== 'object') // 203
|
||||
return obj; // 204
|
||||
// 205
|
||||
// Iterate over array or object structure. // 206
|
||||
_.each(obj, function (value, key) { // 207
|
||||
if (typeof value !== 'object' && value !== undefined && // 208
|
||||
!isInfOrNan(value)) // 209
|
||||
return; // continue // 210
|
||||
// 211
|
||||
var changed = toJSONValueHelper(value); // 212
|
||||
if (changed) { // 213
|
||||
obj[key] = changed; // 214
|
||||
return; // on to the next key // 215
|
||||
} // 216
|
||||
// if we get here, value is an object but not adjustable // 217
|
||||
// at this level. recurse. // 218
|
||||
adjustTypesToJSONValue(value); // 219
|
||||
}); // 220
|
||||
return obj; // 221
|
||||
}; // 222
|
||||
// 223
|
||||
// Either return the JSON-compatible version of the argument, or undefined (if // 224
|
||||
// the item isn't itself replaceable, but maybe some fields in it are) // 225
|
||||
var toJSONValueHelper = function (item) { // 226
|
||||
for (var i = 0; i < builtinConverters.length; i++) { // 227
|
||||
var converter = builtinConverters[i]; // 228
|
||||
if (converter.matchObject(item)) { // 229
|
||||
return converter.toJSONValue(item); // 230
|
||||
} // 231
|
||||
} // 232
|
||||
return undefined; // 233
|
||||
}; // 234
|
||||
// 235
|
||||
/** // 236
|
||||
* @summary Serialize an EJSON-compatible value into its plain JSON representation. // 237
|
||||
* @locus Anywhere // 238
|
||||
* @param {EJSON} val A value to serialize to plain JSON. // 239
|
||||
*/ // 240
|
||||
EJSON.toJSONValue = function (item) { // 241
|
||||
var changed = toJSONValueHelper(item); // 242
|
||||
if (changed !== undefined) // 243
|
||||
return changed; // 244
|
||||
if (typeof item === 'object') { // 245
|
||||
item = EJSON.clone(item); // 246
|
||||
adjustTypesToJSONValue(item); // 247
|
||||
} // 248
|
||||
return item; // 249
|
||||
}; // 250
|
||||
// 251
|
||||
// for both arrays and objects. Tries its best to just // 252
|
||||
// use the object you hand it, but may return something // 253
|
||||
// different if the object you hand it itself needs changing. // 254
|
||||
// // 255
|
||||
var adjustTypesFromJSONValue = // 256
|
||||
EJSON._adjustTypesFromJSONValue = function (obj) { // 257
|
||||
if (obj === null) // 258
|
||||
return null; // 259
|
||||
var maybeChanged = fromJSONValueHelper(obj); // 260
|
||||
if (maybeChanged !== obj) // 261
|
||||
return maybeChanged; // 262
|
||||
// 263
|
||||
// Other atoms are unchanged. // 264
|
||||
if (typeof obj !== 'object') // 265
|
||||
return obj; // 266
|
||||
// 267
|
||||
_.each(obj, function (value, key) { // 268
|
||||
if (typeof value === 'object') { // 269
|
||||
var changed = fromJSONValueHelper(value); // 270
|
||||
if (value !== changed) { // 271
|
||||
obj[key] = changed; // 272
|
||||
return; // 273
|
||||
} // 274
|
||||
// if we get here, value is an object but not adjustable // 275
|
||||
// at this level. recurse. // 276
|
||||
adjustTypesFromJSONValue(value); // 277
|
||||
} // 278
|
||||
}); // 279
|
||||
return obj; // 280
|
||||
}; // 281
|
||||
// 282
|
||||
// Either return the argument changed to have the non-json // 283
|
||||
// rep of itself (the Object version) or the argument itself. // 284
|
||||
// 285
|
||||
// DOES NOT RECURSE. For actually getting the fully-changed value, use // 286
|
||||
// EJSON.fromJSONValue // 287
|
||||
var fromJSONValueHelper = function (value) { // 288
|
||||
if (typeof value === 'object' && value !== null) { // 289
|
||||
if (_.size(value) <= 2 // 290
|
||||
&& _.all(value, function (v, k) { // 291
|
||||
return typeof k === 'string' && k.substr(0, 1) === '$'; // 292
|
||||
})) { // 293
|
||||
for (var i = 0; i < builtinConverters.length; i++) { // 294
|
||||
var converter = builtinConverters[i]; // 295
|
||||
if (converter.matchJSONValue(value)) { // 296
|
||||
return converter.fromJSONValue(value); // 297
|
||||
} // 298
|
||||
} // 299
|
||||
} // 300
|
||||
} // 301
|
||||
return value; // 302
|
||||
}; // 303
|
||||
// 304
|
||||
/** // 305
|
||||
* @summary Deserialize an EJSON value from its plain JSON representation. // 306
|
||||
* @locus Anywhere // 307
|
||||
* @param {JSONCompatible} val A value to deserialize into EJSON. // 308
|
||||
*/ // 309
|
||||
EJSON.fromJSONValue = function (item) { // 310
|
||||
var changed = fromJSONValueHelper(item); // 311
|
||||
if (changed === item && typeof item === 'object') { // 312
|
||||
item = EJSON.clone(item); // 313
|
||||
adjustTypesFromJSONValue(item); // 314
|
||||
return item; // 315
|
||||
} else { // 316
|
||||
return changed; // 317
|
||||
} // 318
|
||||
}; // 319
|
||||
// 320
|
||||
/** // 321
|
||||
* @summary Serialize a value to a string. // 322
|
||||
// 323
|
||||
For EJSON values, the serialization fully represents the value. For non-EJSON values, serializes the same way as `JSON.stringify`.
|
||||
* @locus Anywhere // 325
|
||||
* @param {EJSON} val A value to stringify. // 326
|
||||
* @param {Object} [options] // 327
|
||||
* @param {Boolean | Integer | String} options.indent Indents objects and arrays for easy readability. When `true`, indents by 2 spaces; when an integer, indents by that number of spaces; and when a string, uses the string as the indentation pattern.
|
||||
* @param {Boolean} options.canonical When `true`, stringifies keys in an object in sorted order. // 329
|
||||
*/ // 330
|
||||
EJSON.stringify = function (item, options) { // 331
|
||||
var json = EJSON.toJSONValue(item); // 332
|
||||
if (options && (options.canonical || options.indent)) { // 333
|
||||
return EJSON._canonicalStringify(json, options); // 334
|
||||
} else { // 335
|
||||
return JSON.stringify(json); // 336
|
||||
} // 337
|
||||
}; // 338
|
||||
// 339
|
||||
/** // 340
|
||||
* @summary Parse a string into an EJSON value. Throws an error if the string is not valid EJSON. // 341
|
||||
* @locus Anywhere // 342
|
||||
* @param {String} str A string to parse into an EJSON value. // 343
|
||||
*/ // 344
|
||||
EJSON.parse = function (item) { // 345
|
||||
if (typeof item !== 'string') // 346
|
||||
throw new Error("EJSON.parse argument should be a string"); // 347
|
||||
return EJSON.fromJSONValue(JSON.parse(item)); // 348
|
||||
}; // 349
|
||||
// 350
|
||||
/** // 351
|
||||
* @summary Returns true if `x` is a buffer of binary data, as returned from [`EJSON.newBinary`](#ejson_new_binary). // 352
|
||||
* @param {Object} x The variable to check. // 353
|
||||
* @locus Anywhere // 354
|
||||
*/ // 355
|
||||
EJSON.isBinary = function (obj) { // 356
|
||||
return !!((typeof Uint8Array !== 'undefined' && obj instanceof Uint8Array) || // 357
|
||||
(obj && obj.$Uint8ArrayPolyfill)); // 358
|
||||
}; // 359
|
||||
// 360
|
||||
/** // 361
|
||||
* @summary Return true if `a` and `b` are equal to each other. Return false otherwise. Uses the `equals` method on `a` if present, otherwise performs a deep comparison.
|
||||
* @locus Anywhere // 363
|
||||
* @param {EJSON} a // 364
|
||||
* @param {EJSON} b // 365
|
||||
* @param {Object} [options] // 366
|
||||
* @param {Boolean} options.keyOrderSensitive Compare in key sensitive order, if supported by the JavaScript implementation. For example, `{a: 1, b: 2}` is equal to `{b: 2, a: 1}` only when `keyOrderSensitive` is `false`. The default is `false`.
|
||||
*/ // 368
|
||||
EJSON.equals = function (a, b, options) { // 369
|
||||
var i; // 370
|
||||
var keyOrderSensitive = !!(options && options.keyOrderSensitive); // 371
|
||||
if (a === b) // 372
|
||||
return true; // 373
|
||||
if (_.isNaN(a) && _.isNaN(b)) // 374
|
||||
return true; // This differs from the IEEE spec for NaN equality, b/c we don't want // 375
|
||||
// anything ever with a NaN to be poisoned from becoming equal to anything. // 376
|
||||
if (!a || !b) // if either one is falsy, they'd have to be === to be equal // 377
|
||||
return false; // 378
|
||||
if (!(typeof a === 'object' && typeof b === 'object')) // 379
|
||||
return false; // 380
|
||||
if (a instanceof Date && b instanceof Date) // 381
|
||||
return a.valueOf() === b.valueOf(); // 382
|
||||
if (EJSON.isBinary(a) && EJSON.isBinary(b)) { // 383
|
||||
if (a.length !== b.length) // 384
|
||||
return false; // 385
|
||||
for (i = 0; i < a.length; i++) { // 386
|
||||
if (a[i] !== b[i]) // 387
|
||||
return false; // 388
|
||||
} // 389
|
||||
return true; // 390
|
||||
} // 391
|
||||
if (typeof (a.equals) === 'function') // 392
|
||||
return a.equals(b, options); // 393
|
||||
if (typeof (b.equals) === 'function') // 394
|
||||
return b.equals(a, options); // 395
|
||||
if (a instanceof Array) { // 396
|
||||
if (!(b instanceof Array)) // 397
|
||||
return false; // 398
|
||||
if (a.length !== b.length) // 399
|
||||
return false; // 400
|
||||
for (i = 0; i < a.length; i++) { // 401
|
||||
if (!EJSON.equals(a[i], b[i], options)) // 402
|
||||
return false; // 403
|
||||
} // 404
|
||||
return true; // 405
|
||||
} // 406
|
||||
// fallback for custom types that don't implement their own equals // 407
|
||||
switch (EJSON._isCustomType(a) + EJSON._isCustomType(b)) { // 408
|
||||
case 1: return false; // 409
|
||||
case 2: return EJSON.equals(EJSON.toJSONValue(a), EJSON.toJSONValue(b)); // 410
|
||||
} // 411
|
||||
// fall back to structural equality of objects // 412
|
||||
var ret; // 413
|
||||
if (keyOrderSensitive) { // 414
|
||||
var bKeys = []; // 415
|
||||
_.each(b, function (val, x) { // 416
|
||||
bKeys.push(x); // 417
|
||||
}); // 418
|
||||
i = 0; // 419
|
||||
ret = _.all(a, function (val, x) { // 420
|
||||
if (i >= bKeys.length) { // 421
|
||||
return false; // 422
|
||||
} // 423
|
||||
if (x !== bKeys[i]) { // 424
|
||||
return false; // 425
|
||||
} // 426
|
||||
if (!EJSON.equals(val, b[bKeys[i]], options)) { // 427
|
||||
return false; // 428
|
||||
} // 429
|
||||
i++; // 430
|
||||
return true; // 431
|
||||
}); // 432
|
||||
return ret && i === bKeys.length; // 433
|
||||
} else { // 434
|
||||
i = 0; // 435
|
||||
ret = _.all(a, function (val, key) { // 436
|
||||
if (!_.has(b, key)) { // 437
|
||||
return false; // 438
|
||||
} // 439
|
||||
if (!EJSON.equals(val, b[key], options)) { // 440
|
||||
return false; // 441
|
||||
} // 442
|
||||
i++; // 443
|
||||
return true; // 444
|
||||
}); // 445
|
||||
return ret && _.size(b) === i; // 446
|
||||
} // 447
|
||||
}; // 448
|
||||
// 449
|
||||
/** // 450
|
||||
* @summary Return a deep copy of `val`. // 451
|
||||
* @locus Anywhere // 452
|
||||
* @param {EJSON} val A value to copy. // 453
|
||||
*/ // 454
|
||||
EJSON.clone = function (v) { // 455
|
||||
var ret; // 456
|
||||
if (typeof v !== "object") // 457
|
||||
return v; // 458
|
||||
if (v === null) // 459
|
||||
return null; // null has typeof "object" // 460
|
||||
if (v instanceof Date) // 461
|
||||
return new Date(v.getTime()); // 462
|
||||
// RegExps are not really EJSON elements (eg we don't define a serialization // 463
|
||||
// for them), but they're immutable anyway, so we can support them in clone. // 464
|
||||
if (v instanceof RegExp) // 465
|
||||
return v; // 466
|
||||
if (EJSON.isBinary(v)) { // 467
|
||||
ret = EJSON.newBinary(v.length); // 468
|
||||
for (var i = 0; i < v.length; i++) { // 469
|
||||
ret[i] = v[i]; // 470
|
||||
} // 471
|
||||
return ret; // 472
|
||||
} // 473
|
||||
// XXX: Use something better than underscore's isArray // 474
|
||||
if (_.isArray(v) || _.isArguments(v)) { // 475
|
||||
// For some reason, _.map doesn't work in this context on Opera (weird test // 476
|
||||
// failures). // 477
|
||||
ret = []; // 478
|
||||
for (i = 0; i < v.length; i++) // 479
|
||||
ret[i] = EJSON.clone(v[i]); // 480
|
||||
return ret; // 481
|
||||
} // 482
|
||||
// handle general user-defined typed Objects if they have a clone method // 483
|
||||
if (typeof v.clone === 'function') { // 484
|
||||
return v.clone(); // 485
|
||||
} // 486
|
||||
// handle other custom types // 487
|
||||
if (EJSON._isCustomType(v)) { // 488
|
||||
return EJSON.fromJSONValue(EJSON.clone(EJSON.toJSONValue(v)), true); // 489
|
||||
} // 490
|
||||
// handle other objects // 491
|
||||
ret = {}; // 492
|
||||
_.each(v, function (value, key) { // 493
|
||||
ret[key] = EJSON.clone(value); // 494
|
||||
}); // 495
|
||||
return ret; // 496
|
||||
}; // 497
|
||||
// 498
|
||||
/** // 499
|
||||
* @summary Allocate a new buffer of binary data that EJSON can serialize. // 500
|
||||
* @locus Anywhere // 501
|
||||
* @param {Number} size The number of bytes of binary data to allocate. // 502
|
||||
*/ // 503
|
||||
// EJSON.newBinary is the public documented API for this functionality, // 504
|
||||
// but the implementation is in the 'base64' package to avoid // 505
|
||||
// introducing a circular dependency. (If the implementation were here, // 506
|
||||
// then 'base64' would have to use EJSON.newBinary, and 'ejson' would // 507
|
||||
// also have to use 'base64'.) // 508
|
||||
EJSON.newBinary = Base64.newBinary; // 509
|
||||
// 510
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/ejson/stringify.js //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Based on json2.js from https://github.com/douglascrockford/JSON-js // 1
|
||||
// // 2
|
||||
// json2.js // 3
|
||||
// 2012-10-08 // 4
|
||||
// // 5
|
||||
// Public Domain. // 6
|
||||
// // 7
|
||||
// NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. // 8
|
||||
// 9
|
||||
function quote(string) { // 10
|
||||
return JSON.stringify(string); // 11
|
||||
} // 12
|
||||
// 13
|
||||
var str = function (key, holder, singleIndent, outerIndent, canonical) { // 14
|
||||
// 15
|
||||
// Produce a string from holder[key]. // 16
|
||||
// 17
|
||||
var i; // The loop counter. // 18
|
||||
var k; // The member key. // 19
|
||||
var v; // The member value. // 20
|
||||
var length; // 21
|
||||
var innerIndent = outerIndent; // 22
|
||||
var partial; // 23
|
||||
var value = holder[key]; // 24
|
||||
// 25
|
||||
// What happens next depends on the value's type. // 26
|
||||
// 27
|
||||
switch (typeof value) { // 28
|
||||
case 'string': // 29
|
||||
return quote(value); // 30
|
||||
case 'number': // 31
|
||||
// JSON numbers must be finite. Encode non-finite numbers as null. // 32
|
||||
return isFinite(value) ? String(value) : 'null'; // 33
|
||||
case 'boolean': // 34
|
||||
return String(value); // 35
|
||||
// If the type is 'object', we might be dealing with an object or an array or // 36
|
||||
// null. // 37
|
||||
case 'object': // 38
|
||||
// Due to a specification blunder in ECMAScript, typeof null is 'object', // 39
|
||||
// so watch out for that case. // 40
|
||||
if (!value) { // 41
|
||||
return 'null'; // 42
|
||||
} // 43
|
||||
// Make an array to hold the partial results of stringifying this object value. // 44
|
||||
innerIndent = outerIndent + singleIndent; // 45
|
||||
partial = []; // 46
|
||||
// 47
|
||||
// Is the value an array? // 48
|
||||
if (_.isArray(value) || _.isArguments(value)) { // 49
|
||||
// 50
|
||||
// The value is an array. Stringify every element. Use null as a placeholder // 51
|
||||
// for non-JSON values. // 52
|
||||
// 53
|
||||
length = value.length; // 54
|
||||
for (i = 0; i < length; i += 1) { // 55
|
||||
partial[i] = str(i, value, singleIndent, innerIndent, canonical) || 'null'; // 56
|
||||
} // 57
|
||||
// 58
|
||||
// Join all of the elements together, separated with commas, and wrap them in // 59
|
||||
// brackets. // 60
|
||||
// 61
|
||||
if (partial.length === 0) { // 62
|
||||
v = '[]'; // 63
|
||||
} else if (innerIndent) { // 64
|
||||
v = '[\n' + innerIndent + partial.join(',\n' + innerIndent) + '\n' + outerIndent + ']'; // 65
|
||||
} else { // 66
|
||||
v = '[' + partial.join(',') + ']'; // 67
|
||||
} // 68
|
||||
return v; // 69
|
||||
} // 70
|
||||
// 71
|
||||
// 72
|
||||
// Iterate through all of the keys in the object. // 73
|
||||
var keys = _.keys(value); // 74
|
||||
if (canonical) // 75
|
||||
keys = keys.sort(); // 76
|
||||
_.each(keys, function (k) { // 77
|
||||
v = str(k, value, singleIndent, innerIndent, canonical); // 78
|
||||
if (v) { // 79
|
||||
partial.push(quote(k) + (innerIndent ? ': ' : ':') + v); // 80
|
||||
} // 81
|
||||
}); // 82
|
||||
// 83
|
||||
// 84
|
||||
// Join all of the member texts together, separated with commas, // 85
|
||||
// and wrap them in braces. // 86
|
||||
// 87
|
||||
if (partial.length === 0) { // 88
|
||||
v = '{}'; // 89
|
||||
} else if (innerIndent) { // 90
|
||||
v = '{\n' + innerIndent + partial.join(',\n' + innerIndent) + '\n' + outerIndent + '}'; // 91
|
||||
} else { // 92
|
||||
v = '{' + partial.join(',') + '}'; // 93
|
||||
} // 94
|
||||
return v; // 95
|
||||
} // 96
|
||||
} // 97
|
||||
// 98
|
||||
// If the JSON object does not yet have a stringify method, give it one. // 99
|
||||
// 100
|
||||
EJSON._canonicalStringify = function (value, options) { // 101
|
||||
// Make a fake root object containing our value under the key of ''. // 102
|
||||
// Return the result of stringifying the value. // 103
|
||||
options = _.extend({ // 104
|
||||
indent: "", // 105
|
||||
canonical: false // 106
|
||||
}, options); // 107
|
||||
if (options.indent === true) { // 108
|
||||
options.indent = " "; // 109
|
||||
} else if (typeof options.indent === 'number') { // 110
|
||||
var newIndent = ""; // 111
|
||||
for (var i = 0; i < options.indent; i++) { // 112
|
||||
newIndent += ' '; // 113
|
||||
} // 114
|
||||
options.indent = newIndent; // 115
|
||||
} // 116
|
||||
return str('', {'': value}, options.indent, "", options.canonical); // 117
|
||||
}; // 118
|
||||
// 119
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package.ejson = {
|
||||
EJSON: EJSON,
|
||||
EJSONTest: EJSONTest
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,470 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
|
||||
/* Package-scope variables */
|
||||
var GeoJSON, module;
|
||||
|
||||
(function () {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/geojson-utils/pre.js //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Define an object named exports. This will cause geojson-utils.js to put `gju` // 1
|
||||
// as a field on it, instead of in the global namespace. See also post.js. // 2
|
||||
module = {exports:{}}; // 3
|
||||
// 4
|
||||
// 5
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/geojson-utils/geojson-utils.js //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
(function () { // 1
|
||||
var gju = {}; // 2
|
||||
// 3
|
||||
// Export the geojson object for **CommonJS** // 4
|
||||
if (typeof module !== 'undefined' && module.exports) { // 5
|
||||
module.exports = gju; // 6
|
||||
} // 7
|
||||
// 8
|
||||
// adapted from http://www.kevlindev.com/gui/math/intersection/Intersection.js // 9
|
||||
gju.lineStringsIntersect = function (l1, l2) { // 10
|
||||
var intersects = []; // 11
|
||||
for (var i = 0; i <= l1.coordinates.length - 2; ++i) { // 12
|
||||
for (var j = 0; j <= l2.coordinates.length - 2; ++j) { // 13
|
||||
var a1 = { // 14
|
||||
x: l1.coordinates[i][1], // 15
|
||||
y: l1.coordinates[i][0] // 16
|
||||
}, // 17
|
||||
a2 = { // 18
|
||||
x: l1.coordinates[i + 1][1], // 19
|
||||
y: l1.coordinates[i + 1][0] // 20
|
||||
}, // 21
|
||||
b1 = { // 22
|
||||
x: l2.coordinates[j][1], // 23
|
||||
y: l2.coordinates[j][0] // 24
|
||||
}, // 25
|
||||
b2 = { // 26
|
||||
x: l2.coordinates[j + 1][1], // 27
|
||||
y: l2.coordinates[j + 1][0] // 28
|
||||
}, // 29
|
||||
ua_t = (b2.x - b1.x) * (a1.y - b1.y) - (b2.y - b1.y) * (a1.x - b1.x), // 30
|
||||
ub_t = (a2.x - a1.x) * (a1.y - b1.y) - (a2.y - a1.y) * (a1.x - b1.x), // 31
|
||||
u_b = (b2.y - b1.y) * (a2.x - a1.x) - (b2.x - b1.x) * (a2.y - a1.y); // 32
|
||||
if (u_b != 0) { // 33
|
||||
var ua = ua_t / u_b, // 34
|
||||
ub = ub_t / u_b; // 35
|
||||
if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) { // 36
|
||||
intersects.push({ // 37
|
||||
'type': 'Point', // 38
|
||||
'coordinates': [a1.x + ua * (a2.x - a1.x), a1.y + ua * (a2.y - a1.y)] // 39
|
||||
}); // 40
|
||||
} // 41
|
||||
} // 42
|
||||
} // 43
|
||||
} // 44
|
||||
if (intersects.length == 0) intersects = false; // 45
|
||||
return intersects; // 46
|
||||
} // 47
|
||||
// 48
|
||||
// Bounding Box // 49
|
||||
// 50
|
||||
function boundingBoxAroundPolyCoords (coords) { // 51
|
||||
var xAll = [], yAll = [] // 52
|
||||
// 53
|
||||
for (var i = 0; i < coords[0].length; i++) { // 54
|
||||
xAll.push(coords[0][i][1]) // 55
|
||||
yAll.push(coords[0][i][0]) // 56
|
||||
} // 57
|
||||
// 58
|
||||
xAll = xAll.sort(function (a,b) { return a - b }) // 59
|
||||
yAll = yAll.sort(function (a,b) { return a - b }) // 60
|
||||
// 61
|
||||
return [ [xAll[0], yAll[0]], [xAll[xAll.length - 1], yAll[yAll.length - 1]] ] // 62
|
||||
} // 63
|
||||
// 64
|
||||
gju.pointInBoundingBox = function (point, bounds) { // 65
|
||||
return !(point.coordinates[1] < bounds[0][0] || point.coordinates[1] > bounds[1][0] || point.coordinates[0] < bounds[0][1] || point.coordinates[0] > bounds[1][1])
|
||||
} // 67
|
||||
// 68
|
||||
// Point in Polygon // 69
|
||||
// http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html#Listing the Vertices // 70
|
||||
// 71
|
||||
function pnpoly (x,y,coords) { // 72
|
||||
var vert = [ [0,0] ] // 73
|
||||
// 74
|
||||
for (var i = 0; i < coords.length; i++) { // 75
|
||||
for (var j = 0; j < coords[i].length; j++) { // 76
|
||||
vert.push(coords[i][j]) // 77
|
||||
} // 78
|
||||
vert.push([0,0]) // 79
|
||||
} // 80
|
||||
// 81
|
||||
var inside = false // 82
|
||||
for (var i = 0, j = vert.length - 1; i < vert.length; j = i++) { // 83
|
||||
if (((vert[i][0] > y) != (vert[j][0] > y)) && (x < (vert[j][1] - vert[i][1]) * (y - vert[i][0]) / (vert[j][0] - vert[i][0]) + vert[i][1])) inside = !inside
|
||||
} // 85
|
||||
// 86
|
||||
return inside // 87
|
||||
} // 88
|
||||
// 89
|
||||
gju.pointInPolygon = function (p, poly) { // 90
|
||||
var coords = (poly.type == "Polygon") ? [ poly.coordinates ] : poly.coordinates // 91
|
||||
// 92
|
||||
var insideBox = false // 93
|
||||
for (var i = 0; i < coords.length; i++) { // 94
|
||||
if (gju.pointInBoundingBox(p, boundingBoxAroundPolyCoords(coords[i]))) insideBox = true // 95
|
||||
} // 96
|
||||
if (!insideBox) return false // 97
|
||||
// 98
|
||||
var insidePoly = false // 99
|
||||
for (var i = 0; i < coords.length; i++) { // 100
|
||||
if (pnpoly(p.coordinates[1], p.coordinates[0], coords[i])) insidePoly = true // 101
|
||||
} // 102
|
||||
// 103
|
||||
return insidePoly // 104
|
||||
} // 105
|
||||
// 106
|
||||
gju.numberToRadius = function (number) { // 107
|
||||
return number * Math.PI / 180; // 108
|
||||
} // 109
|
||||
// 110
|
||||
gju.numberToDegree = function (number) { // 111
|
||||
return number * 180 / Math.PI; // 112
|
||||
} // 113
|
||||
// 114
|
||||
// written with help from @tautologe // 115
|
||||
gju.drawCircle = function (radiusInMeters, centerPoint, steps) { // 116
|
||||
var center = [centerPoint.coordinates[1], centerPoint.coordinates[0]], // 117
|
||||
dist = (radiusInMeters / 1000) / 6371, // 118
|
||||
// convert meters to radiant // 119
|
||||
radCenter = [gju.numberToRadius(center[0]), gju.numberToRadius(center[1])], // 120
|
||||
steps = steps || 15, // 121
|
||||
// 15 sided circle // 122
|
||||
poly = [[center[0], center[1]]]; // 123
|
||||
for (var i = 0; i < steps; i++) { // 124
|
||||
var brng = 2 * Math.PI * i / steps; // 125
|
||||
var lat = Math.asin(Math.sin(radCenter[0]) * Math.cos(dist) // 126
|
||||
+ Math.cos(radCenter[0]) * Math.sin(dist) * Math.cos(brng)); // 127
|
||||
var lng = radCenter[1] + Math.atan2(Math.sin(brng) * Math.sin(dist) * Math.cos(radCenter[0]), // 128
|
||||
Math.cos(dist) - Math.sin(radCenter[0]) * Math.sin(lat)); // 129
|
||||
poly[i] = []; // 130
|
||||
poly[i][1] = gju.numberToDegree(lat); // 131
|
||||
poly[i][0] = gju.numberToDegree(lng); // 132
|
||||
} // 133
|
||||
return { // 134
|
||||
"type": "Polygon", // 135
|
||||
"coordinates": [poly] // 136
|
||||
}; // 137
|
||||
} // 138
|
||||
// 139
|
||||
// assumes rectangle starts at lower left point // 140
|
||||
gju.rectangleCentroid = function (rectangle) { // 141
|
||||
var bbox = rectangle.coordinates[0]; // 142
|
||||
var xmin = bbox[0][0], // 143
|
||||
ymin = bbox[0][1], // 144
|
||||
xmax = bbox[2][0], // 145
|
||||
ymax = bbox[2][1]; // 146
|
||||
var xwidth = xmax - xmin; // 147
|
||||
var ywidth = ymax - ymin; // 148
|
||||
return { // 149
|
||||
'type': 'Point', // 150
|
||||
'coordinates': [xmin + xwidth / 2, ymin + ywidth / 2] // 151
|
||||
}; // 152
|
||||
} // 153
|
||||
// 154
|
||||
// from http://www.movable-type.co.uk/scripts/latlong.html // 155
|
||||
gju.pointDistance = function (pt1, pt2) { // 156
|
||||
var lon1 = pt1.coordinates[0], // 157
|
||||
lat1 = pt1.coordinates[1], // 158
|
||||
lon2 = pt2.coordinates[0], // 159
|
||||
lat2 = pt2.coordinates[1], // 160
|
||||
dLat = gju.numberToRadius(lat2 - lat1), // 161
|
||||
dLon = gju.numberToRadius(lon2 - lon1), // 162
|
||||
a = Math.pow(Math.sin(dLat / 2), 2) + Math.cos(gju.numberToRadius(lat1)) // 163
|
||||
* Math.cos(gju.numberToRadius(lat2)) * Math.pow(Math.sin(dLon / 2), 2), // 164
|
||||
c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); // 165
|
||||
// Earth radius is 6371 km // 166
|
||||
return (6371 * c) * 1000; // returns meters // 167
|
||||
}, // 168
|
||||
// 169
|
||||
// checks if geometry lies entirely within a circle // 170
|
||||
// works with Point, LineString, Polygon // 171
|
||||
gju.geometryWithinRadius = function (geometry, center, radius) { // 172
|
||||
if (geometry.type == 'Point') { // 173
|
||||
return gju.pointDistance(geometry, center) <= radius; // 174
|
||||
} else if (geometry.type == 'LineString' || geometry.type == 'Polygon') { // 175
|
||||
var point = {}; // 176
|
||||
var coordinates; // 177
|
||||
if (geometry.type == 'Polygon') { // 178
|
||||
// it's enough to check the exterior ring of the Polygon // 179
|
||||
coordinates = geometry.coordinates[0]; // 180
|
||||
} else { // 181
|
||||
coordinates = geometry.coordinates; // 182
|
||||
} // 183
|
||||
for (var i in coordinates) { // 184
|
||||
point.coordinates = coordinates[i]; // 185
|
||||
if (gju.pointDistance(point, center) > radius) { // 186
|
||||
return false; // 187
|
||||
} // 188
|
||||
} // 189
|
||||
} // 190
|
||||
return true; // 191
|
||||
} // 192
|
||||
// 193
|
||||
// adapted from http://paulbourke.net/geometry/polyarea/javascript.txt // 194
|
||||
gju.area = function (polygon) { // 195
|
||||
var area = 0; // 196
|
||||
// TODO: polygon holes at coordinates[1] // 197
|
||||
var points = polygon.coordinates[0]; // 198
|
||||
var j = points.length - 1; // 199
|
||||
var p1, p2; // 200
|
||||
// 201
|
||||
for (var i = 0; i < points.length; j = i++) { // 202
|
||||
var p1 = { // 203
|
||||
x: points[i][1], // 204
|
||||
y: points[i][0] // 205
|
||||
}; // 206
|
||||
var p2 = { // 207
|
||||
x: points[j][1], // 208
|
||||
y: points[j][0] // 209
|
||||
}; // 210
|
||||
area += p1.x * p2.y; // 211
|
||||
area -= p1.y * p2.x; // 212
|
||||
} // 213
|
||||
// 214
|
||||
area /= 2; // 215
|
||||
return area; // 216
|
||||
}, // 217
|
||||
// 218
|
||||
// adapted from http://paulbourke.net/geometry/polyarea/javascript.txt // 219
|
||||
gju.centroid = function (polygon) { // 220
|
||||
var f, x = 0, // 221
|
||||
y = 0; // 222
|
||||
// TODO: polygon holes at coordinates[1] // 223
|
||||
var points = polygon.coordinates[0]; // 224
|
||||
var j = points.length - 1; // 225
|
||||
var p1, p2; // 226
|
||||
// 227
|
||||
for (var i = 0; i < points.length; j = i++) { // 228
|
||||
var p1 = { // 229
|
||||
x: points[i][1], // 230
|
||||
y: points[i][0] // 231
|
||||
}; // 232
|
||||
var p2 = { // 233
|
||||
x: points[j][1], // 234
|
||||
y: points[j][0] // 235
|
||||
}; // 236
|
||||
f = p1.x * p2.y - p2.x * p1.y; // 237
|
||||
x += (p1.x + p2.x) * f; // 238
|
||||
y += (p1.y + p2.y) * f; // 239
|
||||
} // 240
|
||||
// 241
|
||||
f = gju.area(polygon) * 6; // 242
|
||||
return { // 243
|
||||
'type': 'Point', // 244
|
||||
'coordinates': [y / f, x / f] // 245
|
||||
}; // 246
|
||||
}, // 247
|
||||
// 248
|
||||
gju.simplify = function (source, kink) { /* source[] array of geojson points */ // 249
|
||||
/* kink in metres, kinks above this depth kept */ // 250
|
||||
/* kink depth is the height of the triangle abc where a-b and b-c are two consecutive line segments */ // 251
|
||||
kink = kink || 20; // 252
|
||||
source = source.map(function (o) { // 253
|
||||
return { // 254
|
||||
lng: o.coordinates[0], // 255
|
||||
lat: o.coordinates[1] // 256
|
||||
} // 257
|
||||
}); // 258
|
||||
// 259
|
||||
var n_source, n_stack, n_dest, start, end, i, sig; // 260
|
||||
var dev_sqr, max_dev_sqr, band_sqr; // 261
|
||||
var x12, y12, d12, x13, y13, d13, x23, y23, d23; // 262
|
||||
var F = (Math.PI / 180.0) * 0.5; // 263
|
||||
var index = new Array(); /* aray of indexes of source points to include in the reduced line */ // 264
|
||||
var sig_start = new Array(); /* indices of start & end of working section */ // 265
|
||||
var sig_end = new Array(); // 266
|
||||
// 267
|
||||
/* check for simple cases */ // 268
|
||||
// 269
|
||||
if (source.length < 3) return (source); /* one or two points */ // 270
|
||||
// 271
|
||||
/* more complex case. initialize stack */ // 272
|
||||
// 273
|
||||
n_source = source.length; // 274
|
||||
band_sqr = kink * 360.0 / (2.0 * Math.PI * 6378137.0); /* Now in degrees */ // 275
|
||||
band_sqr *= band_sqr; // 276
|
||||
n_dest = 0; // 277
|
||||
sig_start[0] = 0; // 278
|
||||
sig_end[0] = n_source - 1; // 279
|
||||
n_stack = 1; // 280
|
||||
// 281
|
||||
/* while the stack is not empty ... */ // 282
|
||||
while (n_stack > 0) { // 283
|
||||
// 284
|
||||
/* ... pop the top-most entries off the stacks */ // 285
|
||||
// 286
|
||||
start = sig_start[n_stack - 1]; // 287
|
||||
end = sig_end[n_stack - 1]; // 288
|
||||
n_stack--; // 289
|
||||
// 290
|
||||
if ((end - start) > 1) { /* any intermediate points ? */ // 291
|
||||
// 292
|
||||
/* ... yes, so find most deviant intermediate point to // 293
|
||||
either side of line joining start & end points */ // 294
|
||||
// 295
|
||||
x12 = (source[end].lng() - source[start].lng()); // 296
|
||||
y12 = (source[end].lat() - source[start].lat()); // 297
|
||||
if (Math.abs(x12) > 180.0) x12 = 360.0 - Math.abs(x12); // 298
|
||||
x12 *= Math.cos(F * (source[end].lat() + source[start].lat())); /* use avg lat to reduce lng */ // 299
|
||||
d12 = (x12 * x12) + (y12 * y12); // 300
|
||||
// 301
|
||||
for (i = start + 1, sig = start, max_dev_sqr = -1.0; i < end; i++) { // 302
|
||||
// 303
|
||||
x13 = source[i].lng() - source[start].lng(); // 304
|
||||
y13 = source[i].lat() - source[start].lat(); // 305
|
||||
if (Math.abs(x13) > 180.0) x13 = 360.0 - Math.abs(x13); // 306
|
||||
x13 *= Math.cos(F * (source[i].lat() + source[start].lat())); // 307
|
||||
d13 = (x13 * x13) + (y13 * y13); // 308
|
||||
// 309
|
||||
x23 = source[i].lng() - source[end].lng(); // 310
|
||||
y23 = source[i].lat() - source[end].lat(); // 311
|
||||
if (Math.abs(x23) > 180.0) x23 = 360.0 - Math.abs(x23); // 312
|
||||
x23 *= Math.cos(F * (source[i].lat() + source[end].lat())); // 313
|
||||
d23 = (x23 * x23) + (y23 * y23); // 314
|
||||
// 315
|
||||
if (d13 >= (d12 + d23)) dev_sqr = d23; // 316
|
||||
else if (d23 >= (d12 + d13)) dev_sqr = d13; // 317
|
||||
else dev_sqr = (x13 * y12 - y13 * x12) * (x13 * y12 - y13 * x12) / d12; // solve triangle // 318
|
||||
if (dev_sqr > max_dev_sqr) { // 319
|
||||
sig = i; // 320
|
||||
max_dev_sqr = dev_sqr; // 321
|
||||
} // 322
|
||||
} // 323
|
||||
// 324
|
||||
if (max_dev_sqr < band_sqr) { /* is there a sig. intermediate point ? */ // 325
|
||||
/* ... no, so transfer current start point */ // 326
|
||||
index[n_dest] = start; // 327
|
||||
n_dest++; // 328
|
||||
} else { /* ... yes, so push two sub-sections on stack for further processing */ // 329
|
||||
n_stack++; // 330
|
||||
sig_start[n_stack - 1] = sig; // 331
|
||||
sig_end[n_stack - 1] = end; // 332
|
||||
n_stack++; // 333
|
||||
sig_start[n_stack - 1] = start; // 334
|
||||
sig_end[n_stack - 1] = sig; // 335
|
||||
} // 336
|
||||
} else { /* ... no intermediate points, so transfer current start point */ // 337
|
||||
index[n_dest] = start; // 338
|
||||
n_dest++; // 339
|
||||
} // 340
|
||||
} // 341
|
||||
// 342
|
||||
/* transfer last point */ // 343
|
||||
index[n_dest] = n_source - 1; // 344
|
||||
n_dest++; // 345
|
||||
// 346
|
||||
/* make return array */ // 347
|
||||
var r = new Array(); // 348
|
||||
for (var i = 0; i < n_dest; i++) // 349
|
||||
r.push(source[index[i]]); // 350
|
||||
// 351
|
||||
return r.map(function (o) { // 352
|
||||
return { // 353
|
||||
type: "Point", // 354
|
||||
coordinates: [o.lng, o.lat] // 355
|
||||
} // 356
|
||||
}); // 357
|
||||
} // 358
|
||||
// 359
|
||||
// http://www.movable-type.co.uk/scripts/latlong.html#destPoint // 360
|
||||
gju.destinationPoint = function (pt, brng, dist) { // 361
|
||||
dist = dist/6371; // convert dist to angular distance in radians // 362
|
||||
brng = gju.numberToRadius(brng); // 363
|
||||
// 364
|
||||
var lat1 = gju.numberToRadius(pt.coordinates[0]); // 365
|
||||
var lon1 = gju.numberToRadius(pt.coordinates[1]); // 366
|
||||
// 367
|
||||
var lat2 = Math.asin( Math.sin(lat1)*Math.cos(dist) + // 368
|
||||
Math.cos(lat1)*Math.sin(dist)*Math.cos(brng) ); // 369
|
||||
var lon2 = lon1 + Math.atan2(Math.sin(brng)*Math.sin(dist)*Math.cos(lat1), // 370
|
||||
Math.cos(dist)-Math.sin(lat1)*Math.sin(lat2)); // 371
|
||||
lon2 = (lon2+3*Math.PI) % (2*Math.PI) - Math.PI; // normalise to -180..+180º // 372
|
||||
// 373
|
||||
return { // 374
|
||||
'type': 'Point', // 375
|
||||
'coordinates': [gju.numberToDegree(lat2), gju.numberToDegree(lon2)] // 376
|
||||
}; // 377
|
||||
}; // 378
|
||||
// 379
|
||||
})(); // 380
|
||||
// 381
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/geojson-utils/post.js //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This exports object was created in pre.js. Now copy the `exports` object // 1
|
||||
// from it into the package-scope variable `GeoJSON`, which will get exported. // 2
|
||||
GeoJSON = module.exports; // 3
|
||||
// 4
|
||||
// 5
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package['geojson-utils'] = {
|
||||
GeoJSON: GeoJSON
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,29 @@
|
||||
/* Imports for global scope */
|
||||
|
||||
moment = Package['momentjs:moment'].moment;
|
||||
lodash = Package['stevezhu:lodash'].lodash;
|
||||
_ = Package.underscore._;
|
||||
numeral = Package['numeral:numeral'].numeral;
|
||||
topojson = Package['mrt:topojson'].topojson;
|
||||
Meteor = Package.meteor.Meteor;
|
||||
WebApp = Package.webapp.WebApp;
|
||||
Log = Package.logging.Log;
|
||||
Tracker = Package.deps.Tracker;
|
||||
Deps = Package.deps.Deps;
|
||||
Session = Package.session.Session;
|
||||
DDP = Package.livedata.DDP;
|
||||
Mongo = Package.mongo.Mongo;
|
||||
Blaze = Package.ui.Blaze;
|
||||
UI = Package.ui.UI;
|
||||
Handlebars = Package.ui.Handlebars;
|
||||
Spacebars = Package.spacebars.Spacebars;
|
||||
Template = Package.templating.Template;
|
||||
check = Package.check.check;
|
||||
Match = Package.check.Match;
|
||||
$ = Package.jquery.$;
|
||||
jQuery = Package.jquery.jQuery;
|
||||
Random = Package.random.Random;
|
||||
EJSON = Package.ejson.EJSON;
|
||||
LaunchScreen = Package['launch-screen'].LaunchScreen;
|
||||
HTML = Package.htmljs.HTML;
|
||||
|
||||
@@ -0,0 +1,679 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
var Tracker = Package.tracker.Tracker;
|
||||
var Deps = Package.tracker.Deps;
|
||||
|
||||
/* Package-scope variables */
|
||||
var HTML, IDENTITY, SLICE;
|
||||
|
||||
(function () {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/htmljs/preamble.js //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
HTML = {}; // 1
|
||||
// 2
|
||||
IDENTITY = function (x) { return x; }; // 3
|
||||
SLICE = Array.prototype.slice; // 4
|
||||
// 5
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/htmljs/visitors.js //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
////////////////////////////// VISITORS // 1
|
||||
// 2
|
||||
// _assign is like _.extend or the upcoming Object.assign. // 3
|
||||
// Copy src's own, enumerable properties onto tgt and return // 4
|
||||
// tgt. // 5
|
||||
var _hasOwnProperty = Object.prototype.hasOwnProperty; // 6
|
||||
var _assign = function (tgt, src) { // 7
|
||||
for (var k in src) { // 8
|
||||
if (_hasOwnProperty.call(src, k)) // 9
|
||||
tgt[k] = src[k]; // 10
|
||||
} // 11
|
||||
return tgt; // 12
|
||||
}; // 13
|
||||
// 14
|
||||
HTML.Visitor = function (props) { // 15
|
||||
_assign(this, props); // 16
|
||||
}; // 17
|
||||
// 18
|
||||
HTML.Visitor.def = function (options) { // 19
|
||||
_assign(this.prototype, options); // 20
|
||||
}; // 21
|
||||
// 22
|
||||
HTML.Visitor.extend = function (options) { // 23
|
||||
var curType = this; // 24
|
||||
var subType = function HTMLVisitorSubtype(/*arguments*/) { // 25
|
||||
HTML.Visitor.apply(this, arguments); // 26
|
||||
}; // 27
|
||||
subType.prototype = new curType; // 28
|
||||
subType.extend = curType.extend; // 29
|
||||
subType.def = curType.def; // 30
|
||||
if (options) // 31
|
||||
_assign(subType.prototype, options); // 32
|
||||
return subType; // 33
|
||||
}; // 34
|
||||
// 35
|
||||
HTML.Visitor.def({ // 36
|
||||
visit: function (content/*, ...*/) { // 37
|
||||
if (content == null) // 38
|
||||
// null or undefined. // 39
|
||||
return this.visitNull.apply(this, arguments); // 40
|
||||
// 41
|
||||
if (typeof content === 'object') { // 42
|
||||
if (content.htmljsType) { // 43
|
||||
switch (content.htmljsType) { // 44
|
||||
case HTML.Tag.htmljsType: // 45
|
||||
return this.visitTag.apply(this, arguments); // 46
|
||||
case HTML.CharRef.htmljsType: // 47
|
||||
return this.visitCharRef.apply(this, arguments); // 48
|
||||
case HTML.Comment.htmljsType: // 49
|
||||
return this.visitComment.apply(this, arguments); // 50
|
||||
case HTML.Raw.htmljsType: // 51
|
||||
return this.visitRaw.apply(this, arguments); // 52
|
||||
default: // 53
|
||||
throw new Error("Unknown htmljs type: " + content.htmljsType); // 54
|
||||
} // 55
|
||||
} // 56
|
||||
// 57
|
||||
if (HTML.isArray(content)) // 58
|
||||
return this.visitArray.apply(this, arguments); // 59
|
||||
// 60
|
||||
return this.visitObject.apply(this, arguments); // 61
|
||||
// 62
|
||||
} else if ((typeof content === 'string') || // 63
|
||||
(typeof content === 'boolean') || // 64
|
||||
(typeof content === 'number')) { // 65
|
||||
return this.visitPrimitive.apply(this, arguments); // 66
|
||||
// 67
|
||||
} else if (typeof content === 'function') { // 68
|
||||
return this.visitFunction.apply(this, arguments); // 69
|
||||
} // 70
|
||||
// 71
|
||||
throw new Error("Unexpected object in htmljs: " + content); // 72
|
||||
// 73
|
||||
}, // 74
|
||||
visitNull: function (nullOrUndefined/*, ...*/) {}, // 75
|
||||
visitPrimitive: function (stringBooleanOrNumber/*, ...*/) {}, // 76
|
||||
visitArray: function (array/*, ...*/) {}, // 77
|
||||
visitComment: function (comment/*, ...*/) {}, // 78
|
||||
visitCharRef: function (charRef/*, ...*/) {}, // 79
|
||||
visitRaw: function (raw/*, ...*/) {}, // 80
|
||||
visitTag: function (tag/*, ...*/) {}, // 81
|
||||
visitObject: function (obj/*, ...*/) { // 82
|
||||
throw new Error("Unexpected object in htmljs: " + obj); // 83
|
||||
}, // 84
|
||||
visitFunction: function (obj/*, ...*/) { // 85
|
||||
throw new Error("Unexpected function in htmljs: " + obj); // 86
|
||||
} // 87
|
||||
}); // 88
|
||||
// 89
|
||||
HTML.TransformingVisitor = HTML.Visitor.extend(); // 90
|
||||
HTML.TransformingVisitor.def({ // 91
|
||||
visitNull: IDENTITY, // 92
|
||||
visitPrimitive: IDENTITY, // 93
|
||||
visitArray: function (array/*, ...*/) { // 94
|
||||
var argsCopy = SLICE.call(arguments); // 95
|
||||
var result = array; // 96
|
||||
for (var i = 0; i < array.length; i++) { // 97
|
||||
var oldItem = array[i]; // 98
|
||||
argsCopy[0] = oldItem; // 99
|
||||
var newItem = this.visit.apply(this, argsCopy); // 100
|
||||
if (newItem !== oldItem) { // 101
|
||||
// copy `array` on write // 102
|
||||
if (result === array) // 103
|
||||
result = array.slice(); // 104
|
||||
result[i] = newItem; // 105
|
||||
} // 106
|
||||
} // 107
|
||||
return result; // 108
|
||||
}, // 109
|
||||
visitComment: IDENTITY, // 110
|
||||
visitCharRef: IDENTITY, // 111
|
||||
visitRaw: IDENTITY, // 112
|
||||
visitObject: IDENTITY, // 113
|
||||
visitFunction: IDENTITY, // 114
|
||||
visitTag: function (tag/*, ...*/) { // 115
|
||||
var oldChildren = tag.children; // 116
|
||||
var argsCopy = SLICE.call(arguments); // 117
|
||||
argsCopy[0] = oldChildren; // 118
|
||||
var newChildren = this.visitChildren.apply(this, argsCopy); // 119
|
||||
// 120
|
||||
var oldAttrs = tag.attrs; // 121
|
||||
argsCopy[0] = oldAttrs; // 122
|
||||
var newAttrs = this.visitAttributes.apply(this, argsCopy); // 123
|
||||
// 124
|
||||
if (newAttrs === oldAttrs && newChildren === oldChildren) // 125
|
||||
return tag; // 126
|
||||
// 127
|
||||
var newTag = HTML.getTag(tag.tagName).apply(null, newChildren); // 128
|
||||
newTag.attrs = newAttrs; // 129
|
||||
return newTag; // 130
|
||||
}, // 131
|
||||
visitChildren: function (children/*, ...*/) { // 132
|
||||
return this.visitArray.apply(this, arguments); // 133
|
||||
}, // 134
|
||||
// Transform the `.attrs` property of a tag, which may be a dictionary, // 135
|
||||
// an array, or in some uses, a foreign object (such as // 136
|
||||
// a template tag). // 137
|
||||
visitAttributes: function (attrs/*, ...*/) { // 138
|
||||
if (HTML.isArray(attrs)) { // 139
|
||||
var argsCopy = SLICE.call(arguments); // 140
|
||||
var result = attrs; // 141
|
||||
for (var i = 0; i < attrs.length; i++) { // 142
|
||||
var oldItem = attrs[i]; // 143
|
||||
argsCopy[0] = oldItem; // 144
|
||||
var newItem = this.visitAttributes.apply(this, argsCopy); // 145
|
||||
if (newItem !== oldItem) { // 146
|
||||
// copy on write // 147
|
||||
if (result === attrs) // 148
|
||||
result = attrs.slice(); // 149
|
||||
result[i] = newItem; // 150
|
||||
} // 151
|
||||
} // 152
|
||||
return result; // 153
|
||||
} // 154
|
||||
// 155
|
||||
if (attrs && HTML.isConstructedObject(attrs)) { // 156
|
||||
throw new Error("The basic HTML.TransformingVisitor does not support " + // 157
|
||||
"foreign objects in attributes. Define a custom " + // 158
|
||||
"visitAttributes for this case."); // 159
|
||||
} // 160
|
||||
// 161
|
||||
var oldAttrs = attrs; // 162
|
||||
var newAttrs = oldAttrs; // 163
|
||||
if (oldAttrs) { // 164
|
||||
var attrArgs = [null, null]; // 165
|
||||
attrArgs.push.apply(attrArgs, arguments); // 166
|
||||
for (var k in oldAttrs) { // 167
|
||||
var oldValue = oldAttrs[k]; // 168
|
||||
attrArgs[0] = k; // 169
|
||||
attrArgs[1] = oldValue; // 170
|
||||
var newValue = this.visitAttribute.apply(this, attrArgs); // 171
|
||||
if (newValue !== oldValue) { // 172
|
||||
// copy on write // 173
|
||||
if (newAttrs === oldAttrs) // 174
|
||||
newAttrs = _assign({}, oldAttrs); // 175
|
||||
newAttrs[k] = newValue; // 176
|
||||
} // 177
|
||||
} // 178
|
||||
} // 179
|
||||
// 180
|
||||
return newAttrs; // 181
|
||||
}, // 182
|
||||
// Transform the value of one attribute name/value in an // 183
|
||||
// attributes dictionary. // 184
|
||||
visitAttribute: function (name, value, tag/*, ...*/) { // 185
|
||||
var args = SLICE.call(arguments, 2); // 186
|
||||
args[0] = value; // 187
|
||||
return this.visit.apply(this, args); // 188
|
||||
} // 189
|
||||
}); // 190
|
||||
// 191
|
||||
// 192
|
||||
HTML.ToTextVisitor = HTML.Visitor.extend(); // 193
|
||||
HTML.ToTextVisitor.def({ // 194
|
||||
visitNull: function (nullOrUndefined) { // 195
|
||||
return ''; // 196
|
||||
}, // 197
|
||||
visitPrimitive: function (stringBooleanOrNumber) { // 198
|
||||
var str = String(stringBooleanOrNumber); // 199
|
||||
if (this.textMode === HTML.TEXTMODE.RCDATA) { // 200
|
||||
return str.replace(/&/g, '&').replace(/</g, '<'); // 201
|
||||
} else if (this.textMode === HTML.TEXTMODE.ATTRIBUTE) { // 202
|
||||
// escape `&` and `"` this time, not `&` and `<` // 203
|
||||
return str.replace(/&/g, '&').replace(/"/g, '"'); // 204
|
||||
} else { // 205
|
||||
return str; // 206
|
||||
} // 207
|
||||
}, // 208
|
||||
visitArray: function (array) { // 209
|
||||
var parts = []; // 210
|
||||
for (var i = 0; i < array.length; i++) // 211
|
||||
parts.push(this.visit(array[i])); // 212
|
||||
return parts.join(''); // 213
|
||||
}, // 214
|
||||
visitComment: function (comment) { // 215
|
||||
throw new Error("Can't have a comment here"); // 216
|
||||
}, // 217
|
||||
visitCharRef: function (charRef) { // 218
|
||||
if (this.textMode === HTML.TEXTMODE.RCDATA || // 219
|
||||
this.textMode === HTML.TEXTMODE.ATTRIBUTE) { // 220
|
||||
return charRef.html; // 221
|
||||
} else { // 222
|
||||
return charRef.str; // 223
|
||||
} // 224
|
||||
}, // 225
|
||||
visitRaw: function (raw) { // 226
|
||||
return raw.value; // 227
|
||||
}, // 228
|
||||
visitTag: function (tag) { // 229
|
||||
// Really we should just disallow Tags here. However, at the // 230
|
||||
// moment it's useful to stringify any HTML we find. In // 231
|
||||
// particular, when you include a template within `{{#markdown}}`, // 232
|
||||
// we render the template as text, and since there's currently // 233
|
||||
// no way to make the template be *parsed* as text (e.g. `<template // 234
|
||||
// type="text">`), we hackishly support HTML tags in markdown // 235
|
||||
// in templates by parsing them and stringifying them. // 236
|
||||
return this.visit(this.toHTML(tag)); // 237
|
||||
}, // 238
|
||||
visitObject: function (x) { // 239
|
||||
throw new Error("Unexpected object in htmljs in toText: " + x); // 240
|
||||
}, // 241
|
||||
toHTML: function (node) { // 242
|
||||
return HTML.toHTML(node); // 243
|
||||
} // 244
|
||||
}); // 245
|
||||
// 246
|
||||
// 247
|
||||
// 248
|
||||
HTML.ToHTMLVisitor = HTML.Visitor.extend(); // 249
|
||||
HTML.ToHTMLVisitor.def({ // 250
|
||||
visitNull: function (nullOrUndefined) { // 251
|
||||
return ''; // 252
|
||||
}, // 253
|
||||
visitPrimitive: function (stringBooleanOrNumber) { // 254
|
||||
var str = String(stringBooleanOrNumber); // 255
|
||||
return str.replace(/&/g, '&').replace(/</g, '<'); // 256
|
||||
}, // 257
|
||||
visitArray: function (array) { // 258
|
||||
var parts = []; // 259
|
||||
for (var i = 0; i < array.length; i++) // 260
|
||||
parts.push(this.visit(array[i])); // 261
|
||||
return parts.join(''); // 262
|
||||
}, // 263
|
||||
visitComment: function (comment) { // 264
|
||||
return '<!--' + comment.sanitizedValue + '-->'; // 265
|
||||
}, // 266
|
||||
visitCharRef: function (charRef) { // 267
|
||||
return charRef.html; // 268
|
||||
}, // 269
|
||||
visitRaw: function (raw) { // 270
|
||||
return raw.value; // 271
|
||||
}, // 272
|
||||
visitTag: function (tag) { // 273
|
||||
var attrStrs = []; // 274
|
||||
// 275
|
||||
var tagName = tag.tagName; // 276
|
||||
var children = tag.children; // 277
|
||||
// 278
|
||||
var attrs = tag.attrs; // 279
|
||||
if (attrs) { // 280
|
||||
attrs = HTML.flattenAttributes(attrs); // 281
|
||||
for (var k in attrs) { // 282
|
||||
if (k === 'value' && tagName === 'textarea') { // 283
|
||||
children = [attrs[k], children]; // 284
|
||||
} else { // 285
|
||||
var v = this.toText(attrs[k], HTML.TEXTMODE.ATTRIBUTE); // 286
|
||||
attrStrs.push(' ' + k + '="' + v + '"'); // 287
|
||||
} // 288
|
||||
} // 289
|
||||
} // 290
|
||||
// 291
|
||||
var startTag = '<' + tagName + attrStrs.join('') + '>'; // 292
|
||||
// 293
|
||||
var childStrs = []; // 294
|
||||
var content; // 295
|
||||
if (tagName === 'textarea') { // 296
|
||||
// 297
|
||||
for (var i = 0; i < children.length; i++) // 298
|
||||
childStrs.push(this.toText(children[i], HTML.TEXTMODE.RCDATA)); // 299
|
||||
// 300
|
||||
content = childStrs.join(''); // 301
|
||||
if (content.slice(0, 1) === '\n') // 302
|
||||
// TEXTAREA will absorb a newline, so if we see one, add // 303
|
||||
// another one. // 304
|
||||
content = '\n' + content; // 305
|
||||
// 306
|
||||
} else { // 307
|
||||
for (var i = 0; i < children.length; i++) // 308
|
||||
childStrs.push(this.visit(children[i])); // 309
|
||||
// 310
|
||||
content = childStrs.join(''); // 311
|
||||
} // 312
|
||||
// 313
|
||||
var result = startTag + content; // 314
|
||||
// 315
|
||||
if (children.length || ! HTML.isVoidElement(tagName)) { // 316
|
||||
// "Void" elements like BR are the only ones that don't get a close // 317
|
||||
// tag in HTML5. They shouldn't have contents, either, so we could // 318
|
||||
// throw an error upon seeing contents here. // 319
|
||||
result += '</' + tagName + '>'; // 320
|
||||
} // 321
|
||||
// 322
|
||||
return result; // 323
|
||||
}, // 324
|
||||
visitObject: function (x) { // 325
|
||||
throw new Error("Unexpected object in htmljs in toHTML: " + x); // 326
|
||||
}, // 327
|
||||
toText: function (node, textMode) { // 328
|
||||
return HTML.toText(node, textMode); // 329
|
||||
} // 330
|
||||
}); // 331
|
||||
// 332
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/htmljs/html.js //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// 1
|
||||
// 2
|
||||
HTML.Tag = function () {}; // 3
|
||||
HTML.Tag.prototype.tagName = ''; // this will be set per Tag subclass // 4
|
||||
HTML.Tag.prototype.attrs = null; // 5
|
||||
HTML.Tag.prototype.children = Object.freeze ? Object.freeze([]) : []; // 6
|
||||
HTML.Tag.prototype.htmljsType = HTML.Tag.htmljsType = ['Tag']; // 7
|
||||
// 8
|
||||
// Given "p" create the function `HTML.P`. // 9
|
||||
var makeTagConstructor = function (tagName) { // 10
|
||||
// HTMLTag is the per-tagName constructor of a HTML.Tag subclass // 11
|
||||
var HTMLTag = function (/*arguments*/) { // 12
|
||||
// Work with or without `new`. If not called with `new`, // 13
|
||||
// perform instantiation by recursively calling this constructor. // 14
|
||||
// We can't pass varargs, so pass no args. // 15
|
||||
var instance = (this instanceof HTML.Tag) ? this : new HTMLTag; // 16
|
||||
// 17
|
||||
var i = 0; // 18
|
||||
var attrs = arguments.length && arguments[0]; // 19
|
||||
if (attrs && (typeof attrs === 'object')) { // 20
|
||||
// Treat vanilla JS object as an attributes dictionary. // 21
|
||||
if (! HTML.isConstructedObject(attrs)) { // 22
|
||||
instance.attrs = attrs; // 23
|
||||
i++; // 24
|
||||
} else if (attrs instanceof HTML.Attrs) { // 25
|
||||
var array = attrs.value; // 26
|
||||
if (array.length === 1) { // 27
|
||||
instance.attrs = array[0]; // 28
|
||||
} else if (array.length > 1) { // 29
|
||||
instance.attrs = array; // 30
|
||||
} // 31
|
||||
i++; // 32
|
||||
} // 33
|
||||
} // 34
|
||||
// 35
|
||||
// 36
|
||||
// If no children, don't create an array at all, use the prototype's // 37
|
||||
// (frozen, empty) array. This way we don't create an empty array // 38
|
||||
// every time someone creates a tag without `new` and this constructor // 39
|
||||
// calls itself with no arguments (above). // 40
|
||||
if (i < arguments.length) // 41
|
||||
instance.children = SLICE.call(arguments, i); // 42
|
||||
// 43
|
||||
return instance; // 44
|
||||
}; // 45
|
||||
HTMLTag.prototype = new HTML.Tag; // 46
|
||||
HTMLTag.prototype.constructor = HTMLTag; // 47
|
||||
HTMLTag.prototype.tagName = tagName; // 48
|
||||
// 49
|
||||
return HTMLTag; // 50
|
||||
}; // 51
|
||||
// 52
|
||||
// Not an HTMLjs node, but a wrapper to pass multiple attrs dictionaries // 53
|
||||
// to a tag (for the purpose of implementing dynamic attributes). // 54
|
||||
var Attrs = HTML.Attrs = function (/*attrs dictionaries*/) { // 55
|
||||
// Work with or without `new`. If not called with `new`, // 56
|
||||
// perform instantiation by recursively calling this constructor. // 57
|
||||
// We can't pass varargs, so pass no args. // 58
|
||||
var instance = (this instanceof Attrs) ? this : new Attrs; // 59
|
||||
// 60
|
||||
instance.value = SLICE.call(arguments); // 61
|
||||
// 62
|
||||
return instance; // 63
|
||||
}; // 64
|
||||
// 65
|
||||
////////////////////////////// KNOWN ELEMENTS // 66
|
||||
// 67
|
||||
HTML.getTag = function (tagName) { // 68
|
||||
var symbolName = HTML.getSymbolName(tagName); // 69
|
||||
if (symbolName === tagName) // all-caps tagName // 70
|
||||
throw new Error("Use the lowercase or camelCase form of '" + tagName + "' here"); // 71
|
||||
// 72
|
||||
if (! HTML[symbolName]) // 73
|
||||
HTML[symbolName] = makeTagConstructor(tagName); // 74
|
||||
// 75
|
||||
return HTML[symbolName]; // 76
|
||||
}; // 77
|
||||
// 78
|
||||
HTML.ensureTag = function (tagName) { // 79
|
||||
HTML.getTag(tagName); // don't return it // 80
|
||||
}; // 81
|
||||
// 82
|
||||
HTML.isTagEnsured = function (tagName) { // 83
|
||||
return HTML.isKnownElement(tagName); // 84
|
||||
}; // 85
|
||||
// 86
|
||||
HTML.getSymbolName = function (tagName) { // 87
|
||||
// "foo-bar" -> "FOO_BAR" // 88
|
||||
return tagName.toUpperCase().replace(/-/g, '_'); // 89
|
||||
}; // 90
|
||||
// 91
|
||||
HTML.knownElementNames = 'a abbr acronym address applet area article aside audio b base basefont bdi bdo big blockquote body br button canvas caption center cite code col colgroup command data datagrid datalist dd del details dfn dir div dl dt em embed eventsource fieldset figcaption figure font footer form frame frameset h1 h2 h3 h4 h5 h6 head header hgroup hr html i iframe img input ins isindex kbd keygen label legend li link main map mark menu meta meter nav noframes noscript object ol optgroup option output p param pre progress q rp rt ruby s samp script section select small source span strike strong style sub summary sup table tbody td textarea tfoot th thead time title tr track tt u ul var video wbr'.split(' ');
|
||||
// (we add the SVG ones below) // 93
|
||||
// 94
|
||||
HTML.knownSVGElementNames = 'altGlyph altGlyphDef altGlyphItem animate animateColor animateMotion animateTransform circle clipPath color-profile cursor defs desc ellipse feBlend feColorMatrix feComponentTransfer feComposite feConvolveMatrix feDiffuseLighting feDisplacementMap feDistantLight feFlood feFuncA feFuncB feFuncG feFuncR feGaussianBlur feImage feMerge feMergeNode feMorphology feOffset fePointLight feSpecularLighting feSpotLight feTile feTurbulence filter font font-face font-face-format font-face-name font-face-src font-face-uri foreignObject g glyph glyphRef hkern image line linearGradient marker mask metadata missing-glyph path pattern polygon polyline radialGradient rect script set stop style svg switch symbol text textPath title tref tspan use view vkern'.split(' ');
|
||||
// Append SVG element names to list of known element names // 96
|
||||
HTML.knownElementNames = HTML.knownElementNames.concat(HTML.knownSVGElementNames); // 97
|
||||
// 98
|
||||
HTML.voidElementNames = 'area base br col command embed hr img input keygen link meta param source track wbr'.split(' ');
|
||||
// 100
|
||||
// Speed up search through lists of known elements by creating internal "sets" // 101
|
||||
// of strings. // 102
|
||||
var YES = {yes:true}; // 103
|
||||
var makeSet = function (array) { // 104
|
||||
var set = {}; // 105
|
||||
for (var i = 0; i < array.length; i++) // 106
|
||||
set[array[i]] = YES; // 107
|
||||
return set; // 108
|
||||
}; // 109
|
||||
var voidElementSet = makeSet(HTML.voidElementNames); // 110
|
||||
var knownElementSet = makeSet(HTML.knownElementNames); // 111
|
||||
var knownSVGElementSet = makeSet(HTML.knownSVGElementNames); // 112
|
||||
// 113
|
||||
HTML.isKnownElement = function (tagName) { // 114
|
||||
return knownElementSet[tagName] === YES; // 115
|
||||
}; // 116
|
||||
// 117
|
||||
HTML.isKnownSVGElement = function (tagName) { // 118
|
||||
return knownSVGElementSet[tagName] === YES; // 119
|
||||
}; // 120
|
||||
// 121
|
||||
HTML.isVoidElement = function (tagName) { // 122
|
||||
return voidElementSet[tagName] === YES; // 123
|
||||
}; // 124
|
||||
// 125
|
||||
// 126
|
||||
// Ensure tags for all known elements // 127
|
||||
for (var i = 0; i < HTML.knownElementNames.length; i++) // 128
|
||||
HTML.ensureTag(HTML.knownElementNames[i]); // 129
|
||||
// 130
|
||||
// 131
|
||||
var CharRef = HTML.CharRef = function (attrs) { // 132
|
||||
if (! (this instanceof CharRef)) // 133
|
||||
// called without `new` // 134
|
||||
return new CharRef(attrs); // 135
|
||||
// 136
|
||||
if (! (attrs && attrs.html && attrs.str)) // 137
|
||||
throw new Error( // 138
|
||||
"HTML.CharRef must be constructed with ({html:..., str:...})"); // 139
|
||||
// 140
|
||||
this.html = attrs.html; // 141
|
||||
this.str = attrs.str; // 142
|
||||
}; // 143
|
||||
CharRef.prototype.htmljsType = CharRef.htmljsType = ['CharRef']; // 144
|
||||
// 145
|
||||
var Comment = HTML.Comment = function (value) { // 146
|
||||
if (! (this instanceof Comment)) // 147
|
||||
// called without `new` // 148
|
||||
return new Comment(value); // 149
|
||||
// 150
|
||||
if (typeof value !== 'string') // 151
|
||||
throw new Error('HTML.Comment must be constructed with a string'); // 152
|
||||
// 153
|
||||
this.value = value; // 154
|
||||
// Kill illegal hyphens in comment value (no way to escape them in HTML) // 155
|
||||
this.sanitizedValue = value.replace(/^-|--+|-$/g, ''); // 156
|
||||
}; // 157
|
||||
Comment.prototype.htmljsType = Comment.htmljsType = ['Comment']; // 158
|
||||
// 159
|
||||
var Raw = HTML.Raw = function (value) { // 160
|
||||
if (! (this instanceof Raw)) // 161
|
||||
// called without `new` // 162
|
||||
return new Raw(value); // 163
|
||||
// 164
|
||||
if (typeof value !== 'string') // 165
|
||||
throw new Error('HTML.Raw must be constructed with a string'); // 166
|
||||
// 167
|
||||
this.value = value; // 168
|
||||
}; // 169
|
||||
Raw.prototype.htmljsType = Raw.htmljsType = ['Raw']; // 170
|
||||
// 171
|
||||
// 172
|
||||
HTML.isArray = function (x) { // 173
|
||||
// could change this to use the more convoluted Object.prototype.toString // 174
|
||||
// approach that works when objects are passed between frames, but does // 175
|
||||
// it matter? // 176
|
||||
return (x instanceof Array); // 177
|
||||
}; // 178
|
||||
// 179
|
||||
HTML.isConstructedObject = function (x) { // 180
|
||||
return (x && (typeof x === 'object') && // 181
|
||||
(x.constructor !== Object) && // 182
|
||||
(! Object.prototype.hasOwnProperty.call(x, 'constructor'))); // 183
|
||||
}; // 184
|
||||
// 185
|
||||
HTML.isNully = function (node) { // 186
|
||||
if (node == null) // 187
|
||||
// null or undefined // 188
|
||||
return true; // 189
|
||||
// 190
|
||||
if (HTML.isArray(node)) { // 191
|
||||
// is it an empty array or an array of all nully items? // 192
|
||||
for (var i = 0; i < node.length; i++) // 193
|
||||
if (! HTML.isNully(node[i])) // 194
|
||||
return false; // 195
|
||||
return true; // 196
|
||||
} // 197
|
||||
// 198
|
||||
return false; // 199
|
||||
}; // 200
|
||||
// 201
|
||||
HTML.isValidAttributeName = function (name) { // 202
|
||||
return /^[:_A-Za-z][:_A-Za-z0-9.\-]*/.test(name); // 203
|
||||
}; // 204
|
||||
// 205
|
||||
// If `attrs` is an array of attributes dictionaries, combines them // 206
|
||||
// into one. Removes attributes that are "nully." // 207
|
||||
HTML.flattenAttributes = function (attrs) { // 208
|
||||
if (! attrs) // 209
|
||||
return attrs; // 210
|
||||
// 211
|
||||
var isArray = HTML.isArray(attrs); // 212
|
||||
if (isArray && attrs.length === 0) // 213
|
||||
return null; // 214
|
||||
// 215
|
||||
var result = {}; // 216
|
||||
for (var i = 0, N = (isArray ? attrs.length : 1); i < N; i++) { // 217
|
||||
var oneAttrs = (isArray ? attrs[i] : attrs); // 218
|
||||
if ((typeof oneAttrs !== 'object') || // 219
|
||||
HTML.isConstructedObject(oneAttrs)) // 220
|
||||
throw new Error("Expected plain JS object as attrs, found: " + oneAttrs); // 221
|
||||
for (var name in oneAttrs) { // 222
|
||||
if (! HTML.isValidAttributeName(name)) // 223
|
||||
throw new Error("Illegal HTML attribute name: " + name); // 224
|
||||
var value = oneAttrs[name]; // 225
|
||||
if (! HTML.isNully(value)) // 226
|
||||
result[name] = value; // 227
|
||||
} // 228
|
||||
} // 229
|
||||
// 230
|
||||
return result; // 231
|
||||
}; // 232
|
||||
// 233
|
||||
// 234
|
||||
// 235
|
||||
////////////////////////////// TOHTML // 236
|
||||
// 237
|
||||
HTML.toHTML = function (content) { // 238
|
||||
return (new HTML.ToHTMLVisitor).visit(content); // 239
|
||||
}; // 240
|
||||
// 241
|
||||
// Escaping modes for outputting text when generating HTML. // 242
|
||||
HTML.TEXTMODE = { // 243
|
||||
STRING: 1, // 244
|
||||
RCDATA: 2, // 245
|
||||
ATTRIBUTE: 3 // 246
|
||||
}; // 247
|
||||
// 248
|
||||
// 249
|
||||
HTML.toText = function (content, textMode) { // 250
|
||||
if (! textMode) // 251
|
||||
throw new Error("textMode required for HTML.toText"); // 252
|
||||
if (! (textMode === HTML.TEXTMODE.STRING || // 253
|
||||
textMode === HTML.TEXTMODE.RCDATA || // 254
|
||||
textMode === HTML.TEXTMODE.ATTRIBUTE)) // 255
|
||||
throw new Error("Unknown textMode: " + textMode); // 256
|
||||
// 257
|
||||
var visitor = new HTML.ToTextVisitor({textMode: textMode});; // 258
|
||||
return visitor.visit(content); // 259
|
||||
}; // 260
|
||||
// 261
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package.htmljs = {
|
||||
HTML: HTML
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,126 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
var _ = Package.underscore._;
|
||||
var JSON = Package.json.JSON;
|
||||
var EJSON = Package.ejson.EJSON;
|
||||
|
||||
/* Package-scope variables */
|
||||
var IdMap;
|
||||
|
||||
(function () {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/id-map/id-map.js //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
IdMap = function (idStringify, idParse) { // 1
|
||||
var self = this; // 2
|
||||
self._map = {}; // 3
|
||||
self._idStringify = idStringify || JSON.stringify; // 4
|
||||
self._idParse = idParse || JSON.parse; // 5
|
||||
}; // 6
|
||||
// 7
|
||||
// Some of these methods are designed to match methods on OrderedDict, since // 8
|
||||
// (eg) ObserveMultiplex and _CachingChangeObserver use them interchangeably. // 9
|
||||
// (Conceivably, this should be replaced with "UnorderedDict" with a specific // 10
|
||||
// set of methods that overlap between the two.) // 11
|
||||
// 12
|
||||
_.extend(IdMap.prototype, { // 13
|
||||
get: function (id) { // 14
|
||||
var self = this; // 15
|
||||
var key = self._idStringify(id); // 16
|
||||
return self._map[key]; // 17
|
||||
}, // 18
|
||||
set: function (id, value) { // 19
|
||||
var self = this; // 20
|
||||
var key = self._idStringify(id); // 21
|
||||
self._map[key] = value; // 22
|
||||
}, // 23
|
||||
remove: function (id) { // 24
|
||||
var self = this; // 25
|
||||
var key = self._idStringify(id); // 26
|
||||
delete self._map[key]; // 27
|
||||
}, // 28
|
||||
has: function (id) { // 29
|
||||
var self = this; // 30
|
||||
var key = self._idStringify(id); // 31
|
||||
return _.has(self._map, key); // 32
|
||||
}, // 33
|
||||
empty: function () { // 34
|
||||
var self = this; // 35
|
||||
return _.isEmpty(self._map); // 36
|
||||
}, // 37
|
||||
clear: function () { // 38
|
||||
var self = this; // 39
|
||||
self._map = {}; // 40
|
||||
}, // 41
|
||||
// Iterates over the items in the map. Return `false` to break the loop. // 42
|
||||
forEach: function (iterator) { // 43
|
||||
var self = this; // 44
|
||||
// don't use _.each, because we can't break out of it. // 45
|
||||
var keys = _.keys(self._map); // 46
|
||||
for (var i = 0; i < keys.length; i++) { // 47
|
||||
var breakIfFalse = iterator.call(null, self._map[keys[i]], // 48
|
||||
self._idParse(keys[i])); // 49
|
||||
if (breakIfFalse === false) // 50
|
||||
return; // 51
|
||||
} // 52
|
||||
}, // 53
|
||||
size: function () { // 54
|
||||
var self = this; // 55
|
||||
return _.size(self._map); // 56
|
||||
}, // 57
|
||||
setDefault: function (id, def) { // 58
|
||||
var self = this; // 59
|
||||
var key = self._idStringify(id); // 60
|
||||
if (_.has(self._map, key)) // 61
|
||||
return self._map[key]; // 62
|
||||
self._map[key] = def; // 63
|
||||
return def; // 64
|
||||
}, // 65
|
||||
// Assumes that values are EJSON-cloneable, and that we don't need to clone // 66
|
||||
// IDs (ie, that nobody is going to mutate an ObjectId). // 67
|
||||
clone: function () { // 68
|
||||
var self = this; // 69
|
||||
var clone = new IdMap(self._idStringify, self._idParse); // 70
|
||||
self.forEach(function (value, id) { // 71
|
||||
clone.set(id, EJSON.clone(value)); // 72
|
||||
}); // 73
|
||||
return clone; // 74
|
||||
} // 75
|
||||
}); // 76
|
||||
// 77
|
||||
// 78
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package['id-map'] = {
|
||||
IdMap: IdMap
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,2 @@
|
||||
)]}'
|
||||
{"version":3,"sources":["id-map/id-map.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,yC;AACA,kB;AACA,iB;AACA,oD;AACA,wC;AACA,E;;AAEA,4E;AACA,6E;AACA,6E;AACA,gD;;AAEA,2B;AACA,sB;AACA,oB;AACA,oC;AACA,0B;AACA,I;AACA,6B;AACA,oB;AACA,oC;AACA,2B;AACA,I;AACA,yB;AACA,oB;AACA,oC;AACA,0B;AACA,I;AACA,sB;AACA,oB;AACA,oC;AACA,iC;AACA,I;AACA,sB;AACA,oB;AACA,gC;AACA,I;AACA,sB;AACA,oB;AACA,mB;AACA,I;AACA,0E;AACA,gC;AACA,oB;AACA,0D;AACA,iC;AACA,2C;AACA,gE;AACA,+D;AACA,iC;AACA,e;AACA,K;AACA,I;AACA,qB;AACA,oB;AACA,6B;AACA,I;AACA,kC;AACA,oB;AACA,oC;AACA,8B;AACA,4B;AACA,yB;AACA,e;AACA,I;AACA,6E;AACA,0D;AACA,sB;AACA,oB;AACA,4D;AACA,uC;AACA,wC;AACA,O;AACA,iB;AACA,G;AACA,G","file":"/packages/id-map.js","sourcesContent":["IdMap = function (idStringify, idParse) {\n var self = this;\n self._map = {};\n self._idStringify = idStringify || JSON.stringify;\n self._idParse = idParse || JSON.parse;\n};\n\n// Some of these methods are designed to match methods on OrderedDict, since\n// (eg) ObserveMultiplex and _CachingChangeObserver use them interchangeably.\n// (Conceivably, this should be replaced with \"UnorderedDict\" with a specific\n// set of methods that overlap between the two.)\n\n_.extend(IdMap.prototype, {\n get: function (id) {\n var self = this;\n var key = self._idStringify(id);\n return self._map[key];\n },\n set: function (id, value) {\n var self = this;\n var key = self._idStringify(id);\n self._map[key] = value;\n },\n remove: function (id) {\n var self = this;\n var key = self._idStringify(id);\n delete self._map[key];\n },\n has: function (id) {\n var self = this;\n var key = self._idStringify(id);\n return _.has(self._map, key);\n },\n empty: function () {\n var self = this;\n return _.isEmpty(self._map);\n },\n clear: function () {\n var self = this;\n self._map = {};\n },\n // Iterates over the items in the map. Return `false` to break the loop.\n forEach: function (iterator) {\n var self = this;\n // don't use _.each, because we can't break out of it.\n var keys = _.keys(self._map);\n for (var i = 0; i < keys.length; i++) {\n var breakIfFalse = iterator.call(null, self._map[keys[i]],\n self._idParse(keys[i]));\n if (breakIfFalse === false)\n return;\n }\n },\n size: function () {\n var self = this;\n return _.size(self._map);\n },\n setDefault: function (id, def) {\n var self = this;\n var key = self._idStringify(id);\n if (_.has(self._map, key))\n return self._map[key];\n self._map[key] = def;\n return def;\n },\n // Assumes that values are EJSON-cloneable, and that we don't need to clone\n // IDs (ie, that nobody is going to mutate an ObjectId).\n clone: function () {\n var self = this;\n var clone = new IdMap(self._idStringify, self._idParse);\n self.forEach(function (value, id) {\n clone.set(id, EJSON.clone(value));\n });\n return clone;\n }\n});\n\n"]}
|
||||
@@ -0,0 +1,29 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package.insecure = {};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,2 @@
|
||||
)]}'
|
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;","file":"/packages/insecure.js"}
|
||||
10415
web-app/.meteor/local/build/programs/web.browser/packages/jquery.js
vendored
Normal file
@@ -0,0 +1,553 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
|
||||
/* Package-scope variables */
|
||||
var JSON;
|
||||
|
||||
(function () {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/json/json_native.js //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Do we already have a global JSON object? Export it as our JSON object. // 1
|
||||
if (window.JSON) // 2
|
||||
JSON = window.JSON; // 3
|
||||
// 4
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/json/json2.js //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/* // 1
|
||||
json2.js // 2
|
||||
2012-10-08 // 3
|
||||
// 4
|
||||
Public Domain. // 5
|
||||
// 6
|
||||
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK. // 7
|
||||
// 8
|
||||
See http://www.JSON.org/js.html // 9
|
||||
// 10
|
||||
// 11
|
||||
This code should be minified before deployment. // 12
|
||||
See http://javascript.crockford.com/jsmin.html // 13
|
||||
// 14
|
||||
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO // 15
|
||||
NOT CONTROL. // 16
|
||||
// 17
|
||||
// 18
|
||||
This file creates a global JSON object containing two methods: stringify // 19
|
||||
and parse. // 20
|
||||
// 21
|
||||
JSON.stringify(value, replacer, space) // 22
|
||||
value any JavaScript value, usually an object or array. // 23
|
||||
// 24
|
||||
replacer an optional parameter that determines how object // 25
|
||||
values are stringified for objects. It can be a // 26
|
||||
function or an array of strings. // 27
|
||||
// 28
|
||||
space an optional parameter that specifies the indentation // 29
|
||||
of nested structures. If it is omitted, the text will // 30
|
||||
be packed without extra whitespace. If it is a number, // 31
|
||||
it will specify the number of spaces to indent at each // 32
|
||||
level. If it is a string (such as '\t' or ' '), // 33
|
||||
it contains the characters used to indent at each level. // 34
|
||||
// 35
|
||||
This method produces a JSON text from a JavaScript value. // 36
|
||||
// 37
|
||||
When an object value is found, if the object contains a toJSON // 38
|
||||
method, its toJSON method will be called and the result will be // 39
|
||||
stringified. A toJSON method does not serialize: it returns the // 40
|
||||
value represented by the name/value pair that should be serialized, // 41
|
||||
or undefined if nothing should be serialized. The toJSON method // 42
|
||||
will be passed the key associated with the value, and this will be // 43
|
||||
bound to the value // 44
|
||||
// 45
|
||||
For example, this would serialize Dates as ISO strings. // 46
|
||||
// 47
|
||||
Date.prototype.toJSON = function (key) { // 48
|
||||
function f(n) { // 49
|
||||
// Format integers to have at least two digits. // 50
|
||||
return n < 10 ? '0' + n : n; // 51
|
||||
} // 52
|
||||
// 53
|
||||
return this.getUTCFullYear() + '-' + // 54
|
||||
f(this.getUTCMonth() + 1) + '-' + // 55
|
||||
f(this.getUTCDate()) + 'T' + // 56
|
||||
f(this.getUTCHours()) + ':' + // 57
|
||||
f(this.getUTCMinutes()) + ':' + // 58
|
||||
f(this.getUTCSeconds()) + 'Z'; // 59
|
||||
}; // 60
|
||||
// 61
|
||||
You can provide an optional replacer method. It will be passed the // 62
|
||||
key and value of each member, with this bound to the containing // 63
|
||||
object. The value that is returned from your method will be // 64
|
||||
serialized. If your method returns undefined, then the member will // 65
|
||||
be excluded from the serialization. // 66
|
||||
// 67
|
||||
If the replacer parameter is an array of strings, then it will be // 68
|
||||
used to select the members to be serialized. It filters the results // 69
|
||||
such that only members with keys listed in the replacer array are // 70
|
||||
stringified. // 71
|
||||
// 72
|
||||
Values that do not have JSON representations, such as undefined or // 73
|
||||
functions, will not be serialized. Such values in objects will be // 74
|
||||
dropped; in arrays they will be replaced with null. You can use // 75
|
||||
a replacer function to replace those with JSON values. // 76
|
||||
JSON.stringify(undefined) returns undefined. // 77
|
||||
// 78
|
||||
The optional space parameter produces a stringification of the // 79
|
||||
value that is filled with line breaks and indentation to make it // 80
|
||||
easier to read. // 81
|
||||
// 82
|
||||
If the space parameter is a non-empty string, then that string will // 83
|
||||
be used for indentation. If the space parameter is a number, then // 84
|
||||
the indentation will be that many spaces. // 85
|
||||
// 86
|
||||
Example: // 87
|
||||
// 88
|
||||
text = JSON.stringify(['e', {pluribus: 'unum'}]); // 89
|
||||
// text is '["e",{"pluribus":"unum"}]' // 90
|
||||
// 91
|
||||
// 92
|
||||
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t'); // 93
|
||||
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]' // 94
|
||||
// 95
|
||||
text = JSON.stringify([new Date()], function (key, value) { // 96
|
||||
return this[key] instanceof Date ? // 97
|
||||
'Date(' + this[key] + ')' : value; // 98
|
||||
}); // 99
|
||||
// text is '["Date(---current time---)"]' // 100
|
||||
// 101
|
||||
// 102
|
||||
JSON.parse(text, reviver) // 103
|
||||
This method parses a JSON text to produce an object or array. // 104
|
||||
It can throw a SyntaxError exception. // 105
|
||||
// 106
|
||||
The optional reviver parameter is a function that can filter and // 107
|
||||
transform the results. It receives each of the keys and values, // 108
|
||||
and its return value is used instead of the original value. // 109
|
||||
If it returns what it received, then the structure is not modified. // 110
|
||||
If it returns undefined then the member is deleted. // 111
|
||||
// 112
|
||||
Example: // 113
|
||||
// 114
|
||||
// Parse the text. Values that look like ISO date strings will // 115
|
||||
// be converted to Date objects. // 116
|
||||
// 117
|
||||
myData = JSON.parse(text, function (key, value) { // 118
|
||||
var a; // 119
|
||||
if (typeof value === 'string') { // 120
|
||||
a = // 121
|
||||
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value); // 122
|
||||
if (a) { // 123
|
||||
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4], // 124
|
||||
+a[5], +a[6])); // 125
|
||||
} // 126
|
||||
} // 127
|
||||
return value; // 128
|
||||
}); // 129
|
||||
// 130
|
||||
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) { // 131
|
||||
var d; // 132
|
||||
if (typeof value === 'string' && // 133
|
||||
value.slice(0, 5) === 'Date(' && // 134
|
||||
value.slice(-1) === ')') { // 135
|
||||
d = new Date(value.slice(5, -1)); // 136
|
||||
if (d) { // 137
|
||||
return d; // 138
|
||||
} // 139
|
||||
} // 140
|
||||
return value; // 141
|
||||
}); // 142
|
||||
// 143
|
||||
// 144
|
||||
This is a reference implementation. You are free to copy, modify, or // 145
|
||||
redistribute. // 146
|
||||
*/ // 147
|
||||
// 148
|
||||
/*jslint evil: true, regexp: true */ // 149
|
||||
// 150
|
||||
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply, // 151
|
||||
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours, // 152
|
||||
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join, // 153
|
||||
lastIndex, length, parse, prototype, push, replace, slice, stringify, // 154
|
||||
test, toJSON, toString, valueOf // 155
|
||||
*/ // 156
|
||||
// 157
|
||||
// 158
|
||||
// Create a JSON object only if one does not already exist. We create the // 159
|
||||
// methods in a closure to avoid creating global variables. // 160
|
||||
// 161
|
||||
if (typeof JSON !== 'object') { // 162
|
||||
JSON = {}; // 163
|
||||
} // 164
|
||||
// 165
|
||||
(function () { // 166
|
||||
'use strict'; // 167
|
||||
// 168
|
||||
function f(n) { // 169
|
||||
// Format integers to have at least two digits. // 170
|
||||
return n < 10 ? '0' + n : n; // 171
|
||||
} // 172
|
||||
// 173
|
||||
if (typeof Date.prototype.toJSON !== 'function') { // 174
|
||||
// 175
|
||||
Date.prototype.toJSON = function (key) { // 176
|
||||
// 177
|
||||
return isFinite(this.valueOf()) // 178
|
||||
? this.getUTCFullYear() + '-' + // 179
|
||||
f(this.getUTCMonth() + 1) + '-' + // 180
|
||||
f(this.getUTCDate()) + 'T' + // 181
|
||||
f(this.getUTCHours()) + ':' + // 182
|
||||
f(this.getUTCMinutes()) + ':' + // 183
|
||||
f(this.getUTCSeconds()) + 'Z' // 184
|
||||
: null; // 185
|
||||
}; // 186
|
||||
// 187
|
||||
String.prototype.toJSON = // 188
|
||||
Number.prototype.toJSON = // 189
|
||||
Boolean.prototype.toJSON = function (key) { // 190
|
||||
return this.valueOf(); // 191
|
||||
}; // 192
|
||||
} // 193
|
||||
// 194
|
||||
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
||||
gap, // 197
|
||||
indent, // 198
|
||||
meta = { // table of character substitutions // 199
|
||||
'\b': '\\b', // 200
|
||||
'\t': '\\t', // 201
|
||||
'\n': '\\n', // 202
|
||||
'\f': '\\f', // 203
|
||||
'\r': '\\r', // 204
|
||||
'"' : '\\"', // 205
|
||||
'\\': '\\\\' // 206
|
||||
}, // 207
|
||||
rep; // 208
|
||||
// 209
|
||||
// 210
|
||||
function quote(string) { // 211
|
||||
// 212
|
||||
// If the string contains no control characters, no quote characters, and no // 213
|
||||
// backslash characters, then we can safely slap some quotes around it. // 214
|
||||
// Otherwise we must also replace the offending characters with safe escape // 215
|
||||
// sequences. // 216
|
||||
// 217
|
||||
escapable.lastIndex = 0; // 218
|
||||
return escapable.test(string) ? '"' + string.replace(escapable, function (a) { // 219
|
||||
var c = meta[a]; // 220
|
||||
return typeof c === 'string' // 221
|
||||
? c // 222
|
||||
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4); // 223
|
||||
}) + '"' : '"' + string + '"'; // 224
|
||||
} // 225
|
||||
// 226
|
||||
// 227
|
||||
function str(key, holder) { // 228
|
||||
// 229
|
||||
// Produce a string from holder[key]. // 230
|
||||
// 231
|
||||
var i, // The loop counter. // 232
|
||||
k, // The member key. // 233
|
||||
v, // The member value. // 234
|
||||
length, // 235
|
||||
mind = gap, // 236
|
||||
partial, // 237
|
||||
value = holder[key]; // 238
|
||||
// 239
|
||||
// If the value has a toJSON method, call it to obtain a replacement value. // 240
|
||||
// 241
|
||||
if (value && typeof value === 'object' && // 242
|
||||
typeof value.toJSON === 'function') { // 243
|
||||
value = value.toJSON(key); // 244
|
||||
} // 245
|
||||
// 246
|
||||
// If we were called with a replacer function, then call the replacer to // 247
|
||||
// obtain a replacement value. // 248
|
||||
// 249
|
||||
if (typeof rep === 'function') { // 250
|
||||
value = rep.call(holder, key, value); // 251
|
||||
} // 252
|
||||
// 253
|
||||
// What happens next depends on the value's type. // 254
|
||||
// 255
|
||||
switch (typeof value) { // 256
|
||||
case 'string': // 257
|
||||
return quote(value); // 258
|
||||
// 259
|
||||
case 'number': // 260
|
||||
// 261
|
||||
// JSON numbers must be finite. Encode non-finite numbers as null. // 262
|
||||
// 263
|
||||
return isFinite(value) ? String(value) : 'null'; // 264
|
||||
// 265
|
||||
case 'boolean': // 266
|
||||
case 'null': // 267
|
||||
// 268
|
||||
// If the value is a boolean or null, convert it to a string. Note: // 269
|
||||
// typeof null does not produce 'null'. The case is included here in // 270
|
||||
// the remote chance that this gets fixed someday. // 271
|
||||
// 272
|
||||
return String(value); // 273
|
||||
// 274
|
||||
// If the type is 'object', we might be dealing with an object or an array or // 275
|
||||
// null. // 276
|
||||
// 277
|
||||
case 'object': // 278
|
||||
// 279
|
||||
// Due to a specification blunder in ECMAScript, typeof null is 'object', // 280
|
||||
// so watch out for that case. // 281
|
||||
// 282
|
||||
if (!value) { // 283
|
||||
return 'null'; // 284
|
||||
} // 285
|
||||
// 286
|
||||
// Make an array to hold the partial results of stringifying this object value. // 287
|
||||
// 288
|
||||
gap += indent; // 289
|
||||
partial = []; // 290
|
||||
// 291
|
||||
// Is the value an array? // 292
|
||||
// 293
|
||||
if (Object.prototype.toString.apply(value) === '[object Array]') { // 294
|
||||
// 295
|
||||
// The value is an array. Stringify every element. Use null as a placeholder // 296
|
||||
// for non-JSON values. // 297
|
||||
// 298
|
||||
length = value.length; // 299
|
||||
for (i = 0; i < length; i += 1) { // 300
|
||||
partial[i] = str(i, value) || 'null'; // 301
|
||||
} // 302
|
||||
// 303
|
||||
// Join all of the elements together, separated with commas, and wrap them in // 304
|
||||
// brackets. // 305
|
||||
// 306
|
||||
v = partial.length === 0 // 307
|
||||
? '[]' // 308
|
||||
: gap // 309
|
||||
? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' // 310
|
||||
: '[' + partial.join(',') + ']'; // 311
|
||||
gap = mind; // 312
|
||||
return v; // 313
|
||||
} // 314
|
||||
// 315
|
||||
// If the replacer is an array, use it to select the members to be stringified. // 316
|
||||
// 317
|
||||
if (rep && typeof rep === 'object') { // 318
|
||||
length = rep.length; // 319
|
||||
for (i = 0; i < length; i += 1) { // 320
|
||||
if (typeof rep[i] === 'string') { // 321
|
||||
k = rep[i]; // 322
|
||||
v = str(k, value); // 323
|
||||
if (v) { // 324
|
||||
partial.push(quote(k) + (gap ? ': ' : ':') + v); // 325
|
||||
} // 326
|
||||
} // 327
|
||||
} // 328
|
||||
} else { // 329
|
||||
// 330
|
||||
// Otherwise, iterate through all of the keys in the object. // 331
|
||||
// 332
|
||||
for (k in value) { // 333
|
||||
if (Object.prototype.hasOwnProperty.call(value, k)) { // 334
|
||||
v = str(k, value); // 335
|
||||
if (v) { // 336
|
||||
partial.push(quote(k) + (gap ? ': ' : ':') + v); // 337
|
||||
} // 338
|
||||
} // 339
|
||||
} // 340
|
||||
} // 341
|
||||
// 342
|
||||
// Join all of the member texts together, separated with commas, // 343
|
||||
// and wrap them in braces. // 344
|
||||
// 345
|
||||
v = partial.length === 0 // 346
|
||||
? '{}' // 347
|
||||
: gap // 348
|
||||
? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' // 349
|
||||
: '{' + partial.join(',') + '}'; // 350
|
||||
gap = mind; // 351
|
||||
return v; // 352
|
||||
} // 353
|
||||
} // 354
|
||||
// 355
|
||||
// If the JSON object does not yet have a stringify method, give it one. // 356
|
||||
// 357
|
||||
if (typeof JSON.stringify !== 'function') { // 358
|
||||
JSON.stringify = function (value, replacer, space) { // 359
|
||||
// 360
|
||||
// The stringify method takes a value and an optional replacer, and an optional // 361
|
||||
// space parameter, and returns a JSON text. The replacer can be a function // 362
|
||||
// that can replace values, or an array of strings that will select the keys. // 363
|
||||
// A default replacer method can be provided. Use of the space parameter can // 364
|
||||
// produce text that is more easily readable. // 365
|
||||
// 366
|
||||
var i; // 367
|
||||
gap = ''; // 368
|
||||
indent = ''; // 369
|
||||
// 370
|
||||
// If the space parameter is a number, make an indent string containing that // 371
|
||||
// many spaces. // 372
|
||||
// 373
|
||||
if (typeof space === 'number') { // 374
|
||||
for (i = 0; i < space; i += 1) { // 375
|
||||
indent += ' '; // 376
|
||||
} // 377
|
||||
// 378
|
||||
// If the space parameter is a string, it will be used as the indent string. // 379
|
||||
// 380
|
||||
} else if (typeof space === 'string') { // 381
|
||||
indent = space; // 382
|
||||
} // 383
|
||||
// 384
|
||||
// If there is a replacer, it must be a function or an array. // 385
|
||||
// Otherwise, throw an error. // 386
|
||||
// 387
|
||||
rep = replacer; // 388
|
||||
if (replacer && typeof replacer !== 'function' && // 389
|
||||
(typeof replacer !== 'object' || // 390
|
||||
typeof replacer.length !== 'number')) { // 391
|
||||
throw new Error('JSON.stringify'); // 392
|
||||
} // 393
|
||||
// 394
|
||||
// Make a fake root object containing our value under the key of ''. // 395
|
||||
// Return the result of stringifying the value. // 396
|
||||
// 397
|
||||
return str('', {'': value}); // 398
|
||||
}; // 399
|
||||
} // 400
|
||||
// 401
|
||||
// 402
|
||||
// If the JSON object does not yet have a parse method, give it one. // 403
|
||||
// 404
|
||||
if (typeof JSON.parse !== 'function') { // 405
|
||||
JSON.parse = function (text, reviver) { // 406
|
||||
// 407
|
||||
// The parse method takes a text and an optional reviver function, and returns // 408
|
||||
// a JavaScript value if the text is a valid JSON text. // 409
|
||||
// 410
|
||||
var j; // 411
|
||||
// 412
|
||||
function walk(holder, key) { // 413
|
||||
// 414
|
||||
// The walk method is used to recursively walk the resulting structure so // 415
|
||||
// that modifications can be made. // 416
|
||||
// 417
|
||||
var k, v, value = holder[key]; // 418
|
||||
if (value && typeof value === 'object') { // 419
|
||||
for (k in value) { // 420
|
||||
if (Object.prototype.hasOwnProperty.call(value, k)) { // 421
|
||||
v = walk(value, k); // 422
|
||||
if (v !== undefined) { // 423
|
||||
value[k] = v; // 424
|
||||
} else { // 425
|
||||
delete value[k]; // 426
|
||||
} // 427
|
||||
} // 428
|
||||
} // 429
|
||||
} // 430
|
||||
return reviver.call(holder, key, value); // 431
|
||||
} // 432
|
||||
// 433
|
||||
// 434
|
||||
// Parsing happens in four stages. In the first stage, we replace certain // 435
|
||||
// Unicode characters with escape sequences. JavaScript handles many characters // 436
|
||||
// incorrectly, either silently deleting them, or treating them as line endings. // 437
|
||||
// 438
|
||||
text = String(text); // 439
|
||||
cx.lastIndex = 0; // 440
|
||||
if (cx.test(text)) { // 441
|
||||
text = text.replace(cx, function (a) { // 442
|
||||
return '\\u' + // 443
|
||||
('0000' + a.charCodeAt(0).toString(16)).slice(-4); // 444
|
||||
}); // 445
|
||||
} // 446
|
||||
// 447
|
||||
// In the second stage, we run the text against regular expressions that look // 448
|
||||
// for non-JSON patterns. We are especially concerned with '()' and 'new' // 449
|
||||
// because they can cause invocation, and '=' because it can cause mutation. // 450
|
||||
// But just to be safe, we want to reject all unexpected forms. // 451
|
||||
// 452
|
||||
// We split the second stage into 4 regexp operations in order to work around // 453
|
||||
// crippling inefficiencies in IE's and Safari's regexp engines. First we // 454
|
||||
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we // 455
|
||||
// replace all simple value tokens with ']' characters. Third, we delete all // 456
|
||||
// open brackets that follow a colon or comma or that begin the text. Finally, // 457
|
||||
// we look to see that the remaining characters are only whitespace or ']' or // 458
|
||||
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval. // 459
|
||||
// 460
|
||||
if (/^[\],:{}\s]*$/ // 461
|
||||
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@') // 462
|
||||
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']') // 463
|
||||
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) { // 464
|
||||
// 465
|
||||
// In the third stage we use the eval function to compile the text into a // 466
|
||||
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity // 467
|
||||
// in JavaScript: it can begin a block or an object literal. We wrap the text // 468
|
||||
// in parens to eliminate the ambiguity. // 469
|
||||
// 470
|
||||
j = eval('(' + text + ')'); // 471
|
||||
// 472
|
||||
// In the optional fourth stage, we recursively walk the new structure, passing // 473
|
||||
// each name/value pair to a reviver function for possible transformation. // 474
|
||||
// 475
|
||||
return typeof reviver === 'function' // 476
|
||||
? walk({'': j}, '') // 477
|
||||
: j; // 478
|
||||
} // 479
|
||||
// 480
|
||||
// If the text is not JSON parseable, then a SyntaxError is thrown. // 481
|
||||
// 482
|
||||
throw new SyntaxError('JSON.parse'); // 483
|
||||
}; // 484
|
||||
} // 485
|
||||
}()); // 486
|
||||
// 487
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package.json = {
|
||||
JSON: JSON
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,139 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
|
||||
/* Package-scope variables */
|
||||
var LaunchScreen;
|
||||
|
||||
(function () {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/launch-screen/mobile-launch-screen.js //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// XXX This currently implements loading screens for mobile apps only, // 1
|
||||
// but in the future can be expanded to all apps. // 2
|
||||
// 3
|
||||
var holdCount = 0; // 4
|
||||
var alreadyHidden = false; // 5
|
||||
// 6
|
||||
LaunchScreen = { // 7
|
||||
hold: function () { // 8
|
||||
if (! Meteor.isCordova) { // 9
|
||||
return { // 10
|
||||
release: function () { /* noop */ } // 11
|
||||
}; // 12
|
||||
} // 13
|
||||
// 14
|
||||
if (alreadyHidden) { // 15
|
||||
throw new Error("Can't show launch screen once it's hidden"); // 16
|
||||
} // 17
|
||||
// 18
|
||||
holdCount++; // 19
|
||||
// 20
|
||||
var released = false; // 21
|
||||
var release = function () { // 22
|
||||
if (! Meteor.isCordova) // 23
|
||||
return; // 24
|
||||
// 25
|
||||
if (! released) { // 26
|
||||
holdCount--; // 27
|
||||
if (holdCount === 0 && // 28
|
||||
typeof navigator !== 'undefined' && navigator.splashscreen) { // 29
|
||||
alreadyHidden = true; // 30
|
||||
navigator.splashscreen.hide(); // 31
|
||||
} // 32
|
||||
} // 33
|
||||
}; // 34
|
||||
// 35
|
||||
// Returns a launch screen handle with a release method // 36
|
||||
return { // 37
|
||||
release: release // 38
|
||||
}; // 39
|
||||
} // 40
|
||||
}; // 41
|
||||
// 42
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/launch-screen/default-behavior.js //
|
||||
// //
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Hold launch screen on app load. This reflects the fact that Meteor // 1
|
||||
// mobile apps that use this package always start with a launch screen // 2
|
||||
// visible. (see XXX comment at the top of package.js for more // 3
|
||||
// details) // 4
|
||||
var handle = LaunchScreen.hold(); // 5
|
||||
// 6
|
||||
var Template = Package.templating && Package.templating.Template; // 7
|
||||
// 8
|
||||
Meteor.startup(function () { // 9
|
||||
if (! Template) { // 10
|
||||
handle.release(); // 11
|
||||
} else if (Package['iron:router']) { // 12
|
||||
// XXX Instead of doing this here, this code should be in // 13
|
||||
// iron:router directly. Note that since we're in a // 14
|
||||
// `Meteor.startup` block it's ok that we don't have a // 15
|
||||
// weak dependency on iron:router in package.js. // 16
|
||||
Package['iron:router'].Router.onAfterAction(function () { // 17
|
||||
handle.release(); // 18
|
||||
}); // 19
|
||||
} else { // 20
|
||||
Template.body.onRendered(function () { // 21
|
||||
handle.release(); // 22
|
||||
}); // 23
|
||||
// 24
|
||||
// In case `Template.body` never gets rendered (due to some bug), // 25
|
||||
// hide the launch screen after 6 seconds. This matches the // 26
|
||||
// observed timeout that Cordova apps on Android (but not iOS) // 27
|
||||
// have on hiding the launch screen (even if you don't call // 28
|
||||
// `navigator.splashscreen.hide()`) // 29
|
||||
setTimeout(function () { // 30
|
||||
handle.release(); // 31
|
||||
}, 6000); // 32
|
||||
} // 33
|
||||
}); // 34
|
||||
// 35
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package['launch-screen'] = {
|
||||
LaunchScreen: LaunchScreen
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,2 @@
|
||||
)]}'
|
||||
{"version":3,"sources":["launch-screen/mobile-launch-screen.js","launch-screen/default-behavior.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,sE;AACA,iD;;AAEA,kB;AACA,0B;;AAEA,gB;AACA,qB;AACA,6B;AACA,c;AACA,2C;AACA,Q;AACA,K;;AAEA,wB;AACA,mE;AACA,K;;AAEA,gB;;AAEA,yB;AACA,+B;AACA,6B;AACA,e;;AAEA,uB;AACA,oB;AACA,8B;AACA,yE;AACA,+B;AACA,wC;AACA,S;AACA,O;AACA,M;;AAEA,2D;AACA,Y;AACA,sB;AACA,M;AACA,G;AACA,E;;;;;;;;;;;;;;;;;;;ACxCA,qE;AACA,sE;AACA,8D;AACA,W;AACA,iC;;AAEA,iE;;AAEA,4B;AACA,mB;AACA,qB;AACA,sC;AACA,6D;AACA,uD;AACA,0D;AACA,oD;AACA,6D;AACA,uB;AACA,O;AACA,U;AACA,0C;AACA,uB;AACA,O;;AAEA,qE;AACA,+D;AACA,kE;AACA,+D;AACA,uC;AACA,4B;AACA,uB;AACA,a;AACA,G;AACA,G","file":"/packages/launch-screen.js","sourcesContent":["// XXX This currently implements loading screens for mobile apps only,\n// but in the future can be expanded to all apps.\n\nvar holdCount = 0;\nvar alreadyHidden = false;\n\nLaunchScreen = {\n hold: function () {\n if (! Meteor.isCordova) {\n return {\n release: function () { /* noop */ }\n };\n }\n\n if (alreadyHidden) {\n throw new Error(\"Can't show launch screen once it's hidden\");\n }\n\n holdCount++;\n\n var released = false;\n var release = function () {\n if (! Meteor.isCordova)\n return;\n\n if (! released) {\n holdCount--;\n if (holdCount === 0 &&\n typeof navigator !== 'undefined' && navigator.splashscreen) {\n alreadyHidden = true;\n navigator.splashscreen.hide();\n }\n }\n };\n\n // Returns a launch screen handle with a release method\n return {\n release: release\n };\n }\n};\n","// Hold launch screen on app load. This reflects the fact that Meteor\n// mobile apps that use this package always start with a launch screen\n// visible. (see XXX comment at the top of package.js for more\n// details)\nvar handle = LaunchScreen.hold();\n\nvar Template = Package.templating && Package.templating.Template;\n\nMeteor.startup(function () {\n if (! Template) {\n handle.release();\n } else if (Package['iron:router']) {\n // XXX Instead of doing this here, this code should be in\n // iron:router directly. Note that since we're in a\n // `Meteor.startup` block it's ok that we don't have a\n // weak dependency on iron:router in package.js.\n Package['iron:router'].Router.onAfterAction(function () {\n handle.release();\n });\n } else {\n Template.body.onRendered(function () {\n handle.release();\n });\n\n // In case `Template.body` never gets rendered (due to some bug),\n // hide the launch screen after 6 seconds. This matches the\n // observed timeout that Cordova apps on Android (but not iOS)\n // have on hiding the launch screen (even if you don't call\n // `navigator.splashscreen.hide()`)\n setTimeout(function () {\n handle.release();\n }, 6000);\n }\n});\n"]}
|
||||
@@ -0,0 +1,36 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
var DDP = Package.ddp.DDP;
|
||||
|
||||
/* Package-scope variables */
|
||||
var DDP, LivedataTest;
|
||||
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package.livedata = {
|
||||
DDP: DDP,
|
||||
LivedataTest: LivedataTest
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,2 @@
|
||||
)]}'
|
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;","file":"/packages/livedata.js"}
|
||||
@@ -0,0 +1,324 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
var _ = Package.underscore._;
|
||||
var EJSON = Package.ejson.EJSON;
|
||||
|
||||
/* Package-scope variables */
|
||||
var Log;
|
||||
|
||||
(function () {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/logging/logging.js //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
Log = function () { // 1
|
||||
return Log.info.apply(this, arguments); // 2
|
||||
}; // 3
|
||||
// 4
|
||||
/// FOR TESTING // 5
|
||||
var intercept = 0; // 6
|
||||
var interceptedLines = []; // 7
|
||||
var suppress = 0; // 8
|
||||
// 9
|
||||
// Intercept the next 'count' calls to a Log function. The actual // 10
|
||||
// lines printed to the console can be cleared and read by calling // 11
|
||||
// Log._intercepted(). // 12
|
||||
Log._intercept = function (count) { // 13
|
||||
intercept += count; // 14
|
||||
}; // 15
|
||||
// 16
|
||||
// Suppress the next 'count' calls to a Log function. Use this to stop // 17
|
||||
// tests from spamming the console, especially with red errors that // 18
|
||||
// might look like a failing test. // 19
|
||||
Log._suppress = function (count) { // 20
|
||||
suppress += count; // 21
|
||||
}; // 22
|
||||
// 23
|
||||
// Returns intercepted lines and resets the intercept counter. // 24
|
||||
Log._intercepted = function () { // 25
|
||||
var lines = interceptedLines; // 26
|
||||
interceptedLines = []; // 27
|
||||
intercept = 0; // 28
|
||||
return lines; // 29
|
||||
}; // 30
|
||||
// 31
|
||||
// Either 'json' or 'colored-text'. // 32
|
||||
// // 33
|
||||
// When this is set to 'json', print JSON documents that are parsed by another // 34
|
||||
// process ('satellite' or 'meteor run'). This other process should call // 35
|
||||
// 'Log.format' for nice output. // 36
|
||||
// // 37
|
||||
// When this is set to 'colored-text', call 'Log.format' before printing. // 38
|
||||
// This should be used for logging from within satellite, since there is no // 39
|
||||
// other process that will be reading its standard output. // 40
|
||||
Log.outputFormat = 'json'; // 41
|
||||
// 42
|
||||
var LEVEL_COLORS = { // 43
|
||||
debug: 'green', // 44
|
||||
// leave info as the default color // 45
|
||||
warn: 'magenta', // 46
|
||||
error: 'red' // 47
|
||||
}; // 48
|
||||
// 49
|
||||
var META_COLOR = 'blue'; // 50
|
||||
// 51
|
||||
// XXX package // 52
|
||||
var RESTRICTED_KEYS = ['time', 'timeInexact', 'level', 'file', 'line', // 53
|
||||
'program', 'originApp', 'satellite', 'stderr']; // 54
|
||||
// 55
|
||||
var FORMATTED_KEYS = RESTRICTED_KEYS.concat(['app', 'message']); // 56
|
||||
// 57
|
||||
var logInBrowser = function (obj) { // 58
|
||||
var str = Log.format(obj); // 59
|
||||
// 60
|
||||
// XXX Some levels should be probably be sent to the server // 61
|
||||
var level = obj.level; // 62
|
||||
// 63
|
||||
if ((typeof console !== 'undefined') && console[level]) { // 64
|
||||
console[level](str); // 65
|
||||
} else { // 66
|
||||
// XXX Uses of Meteor._debug should probably be replaced by Log.debug or // 67
|
||||
// Log.info, and we should have another name for "do your best to // 68
|
||||
// call call console.log". // 69
|
||||
Meteor._debug(str); // 70
|
||||
} // 71
|
||||
}; // 72
|
||||
// 73
|
||||
// @returns {Object: { line: Number, file: String }} // 74
|
||||
Log._getCallerDetails = function () { // 75
|
||||
var getStack = function () { // 76
|
||||
// We do NOT use Error.prepareStackTrace here (a V8 extension that gets us a // 77
|
||||
// pre-parsed stack) since it's impossible to compose it with the use of // 78
|
||||
// Error.prepareStackTrace used on the server for source maps. // 79
|
||||
var err = new Error; // 80
|
||||
var stack = err.stack; // 81
|
||||
return stack; // 82
|
||||
}; // 83
|
||||
// 84
|
||||
var stack = getStack(); // 85
|
||||
// 86
|
||||
if (!stack) return {}; // 87
|
||||
// 88
|
||||
var lines = stack.split('\n'); // 89
|
||||
// 90
|
||||
// looking for the first line outside the logging package (or an // 91
|
||||
// eval if we find that first) // 92
|
||||
var line; // 93
|
||||
for (var i = 1; i < lines.length; ++i) { // 94
|
||||
line = lines[i]; // 95
|
||||
if (line.match(/^\s*at eval \(eval/)) { // 96
|
||||
return {file: "eval"}; // 97
|
||||
} // 98
|
||||
// 99
|
||||
if (!line.match(/packages\/(?:local-test:)?logging(?:\/|\.js)/)) // 100
|
||||
break; // 101
|
||||
} // 102
|
||||
// 103
|
||||
var details = {}; // 104
|
||||
// 105
|
||||
// The format for FF is 'functionName@filePath:lineNumber' // 106
|
||||
// The format for V8 is 'functionName (packages/logging/logging.js:81)' or // 107
|
||||
// 'packages/logging/logging.js:81' // 108
|
||||
var match = /(?:[@(]| at )([^(]+?):([0-9:]+)(?:\)|$)/.exec(line); // 109
|
||||
if (!match) // 110
|
||||
return details; // 111
|
||||
// in case the matched block here is line:column // 112
|
||||
details.line = match[2].split(':')[0]; // 113
|
||||
// 114
|
||||
// Possible format: https://foo.bar.com/scripts/file.js?random=foobar // 115
|
||||
// XXX: if you can write the following in better way, please do it // 116
|
||||
// XXX: what about evals? // 117
|
||||
details.file = match[1].split('/').slice(-1)[0].split('?')[0]; // 118
|
||||
// 119
|
||||
return details; // 120
|
||||
}; // 121
|
||||
// 122
|
||||
_.each(['debug', 'info', 'warn', 'error'], function (level) { // 123
|
||||
// @param arg {String|Object} // 124
|
||||
Log[level] = function (arg) { // 125
|
||||
if (suppress) { // 126
|
||||
suppress--; // 127
|
||||
return; // 128
|
||||
} // 129
|
||||
// 130
|
||||
var intercepted = false; // 131
|
||||
if (intercept) { // 132
|
||||
intercept--; // 133
|
||||
intercepted = true; // 134
|
||||
} // 135
|
||||
// 136
|
||||
var obj = (_.isObject(arg) && !_.isRegExp(arg) && !_.isDate(arg) ) ? // 137
|
||||
arg : {message: new String(arg).toString() }; // 138
|
||||
// 139
|
||||
_.each(RESTRICTED_KEYS, function (key) { // 140
|
||||
if (obj[key]) // 141
|
||||
throw new Error("Can't set '" + key + "' in log message"); // 142
|
||||
}); // 143
|
||||
// 144
|
||||
if (_.has(obj, 'message') && !_.isString(obj.message)) // 145
|
||||
throw new Error("The 'message' field in log objects must be a string"); // 146
|
||||
if (!obj.omitCallerDetails) // 147
|
||||
obj = _.extend(Log._getCallerDetails(), obj); // 148
|
||||
obj.time = new Date(); // 149
|
||||
obj.level = level; // 150
|
||||
// 151
|
||||
// XXX allow you to enable 'debug', probably per-package // 152
|
||||
if (level === 'debug') // 153
|
||||
return; // 154
|
||||
// 155
|
||||
if (intercepted) { // 156
|
||||
interceptedLines.push(EJSON.stringify(obj)); // 157
|
||||
} else if (Meteor.isServer) { // 158
|
||||
if (Log.outputFormat === 'colored-text') { // 159
|
||||
console.log(Log.format(obj, {color: true})); // 160
|
||||
} else if (Log.outputFormat === 'json') { // 161
|
||||
console.log(EJSON.stringify(obj)); // 162
|
||||
} else { // 163
|
||||
throw new Error("Unknown logging output format: " + Log.outputFormat); // 164
|
||||
} // 165
|
||||
} else { // 166
|
||||
logInBrowser(obj); // 167
|
||||
} // 168
|
||||
}; // 169
|
||||
}); // 170
|
||||
// 171
|
||||
// tries to parse line as EJSON. returns object if parse is successful, or null if not // 172
|
||||
Log.parse = function (line) { // 173
|
||||
var obj = null; // 174
|
||||
if (line && line.charAt(0) === '{') { // might be json generated from calling 'Log' // 175
|
||||
try { obj = EJSON.parse(line); } catch (e) {} // 176
|
||||
} // 177
|
||||
// 178
|
||||
// XXX should probably check fields other than 'time' // 179
|
||||
if (obj && obj.time && (obj.time instanceof Date)) // 180
|
||||
return obj; // 181
|
||||
else // 182
|
||||
return null; // 183
|
||||
}; // 184
|
||||
// 185
|
||||
// formats a log object into colored human and machine-readable text // 186
|
||||
Log.format = function (obj, options) { // 187
|
||||
obj = EJSON.clone(obj); // don't mutate the argument // 188
|
||||
options = options || {}; // 189
|
||||
// 190
|
||||
var time = obj.time; // 191
|
||||
if (!(time instanceof Date)) // 192
|
||||
throw new Error("'time' must be a Date object"); // 193
|
||||
var timeInexact = obj.timeInexact; // 194
|
||||
// 195
|
||||
// store fields that are in FORMATTED_KEYS since we strip them // 196
|
||||
var level = obj.level || 'info'; // 197
|
||||
var file = obj.file; // 198
|
||||
var lineNumber = obj.line; // 199
|
||||
var appName = obj.app || ''; // 200
|
||||
var originApp = obj.originApp; // 201
|
||||
var message = obj.message || ''; // 202
|
||||
var program = obj.program || ''; // 203
|
||||
var satellite = obj.satellite; // 204
|
||||
var stderr = obj.stderr || ''; // 205
|
||||
// 206
|
||||
_.each(FORMATTED_KEYS, function(key) { // 207
|
||||
delete obj[key]; // 208
|
||||
}); // 209
|
||||
// 210
|
||||
if (!_.isEmpty(obj)) { // 211
|
||||
if (message) message += " "; // 212
|
||||
message += EJSON.stringify(obj); // 213
|
||||
} // 214
|
||||
// 215
|
||||
var pad2 = function(n) { return n < 10 ? '0' + n : n.toString(); }; // 216
|
||||
var pad3 = function(n) { return n < 100 ? '0' + pad2(n) : n.toString(); }; // 217
|
||||
// 218
|
||||
var dateStamp = time.getFullYear().toString() + // 219
|
||||
pad2(time.getMonth() + 1 /*0-based*/) + // 220
|
||||
pad2(time.getDate()); // 221
|
||||
var timeStamp = pad2(time.getHours()) + // 222
|
||||
':' + // 223
|
||||
pad2(time.getMinutes()) + // 224
|
||||
':' + // 225
|
||||
pad2(time.getSeconds()) + // 226
|
||||
'.' + // 227
|
||||
pad3(time.getMilliseconds()); // 228
|
||||
// 229
|
||||
// eg in San Francisco in June this will be '(-7)' // 230
|
||||
var utcOffsetStr = '(' + (-(new Date().getTimezoneOffset() / 60)) + ')'; // 231
|
||||
// 232
|
||||
var appInfo = ''; // 233
|
||||
if (appName) appInfo += appName; // 234
|
||||
if (originApp && originApp !== appName) appInfo += ' via ' + originApp; // 235
|
||||
if (appInfo) appInfo = '[' + appInfo + '] '; // 236
|
||||
// 237
|
||||
var sourceInfoParts = []; // 238
|
||||
if (program) sourceInfoParts.push(program); // 239
|
||||
if (file) sourceInfoParts.push(file); // 240
|
||||
if (lineNumber) sourceInfoParts.push(lineNumber); // 241
|
||||
var sourceInfo = _.isEmpty(sourceInfoParts) ? // 242
|
||||
'' : '(' + sourceInfoParts.join(':') + ') '; // 243
|
||||
// 244
|
||||
if (satellite) // 245
|
||||
sourceInfo += ['[', satellite, ']'].join(''); // 246
|
||||
// 247
|
||||
var stderrIndicator = stderr ? '(STDERR) ' : ''; // 248
|
||||
// 249
|
||||
var metaPrefix = [ // 250
|
||||
level.charAt(0).toUpperCase(), // 251
|
||||
dateStamp, // 252
|
||||
'-', // 253
|
||||
timeStamp, // 254
|
||||
utcOffsetStr, // 255
|
||||
timeInexact ? '? ' : ' ', // 256
|
||||
appInfo, // 257
|
||||
sourceInfo, // 258
|
||||
stderrIndicator].join(''); // 259
|
||||
// 260
|
||||
var prettify = function (line, color) { // 261
|
||||
return (options.color && Meteor.isServer && color) ? // 262
|
||||
Npm.require('cli-color')[color](line) : line; // 263
|
||||
}; // 264
|
||||
// 265
|
||||
return prettify(metaPrefix, options.metaColor || META_COLOR) + // 266
|
||||
prettify(message, LEVEL_COLORS[level]); // 267
|
||||
}; // 268
|
||||
// 269
|
||||
// Turn a line of text into a loggable object. // 270
|
||||
// @param line {String} // 271
|
||||
// @param override {Object} // 272
|
||||
Log.objFromText = function (line, override) { // 273
|
||||
var obj = {message: line, level: "info", time: new Date(), timeInexact: true}; // 274
|
||||
return _.extend(obj, override); // 275
|
||||
}; // 276
|
||||
// 277
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package.logging = {
|
||||
Log: Log
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,31 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
var Reload = Package.reload.Reload;
|
||||
var Autoupdate = Package.autoupdate.Autoupdate;
|
||||
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package['meteor-platform'] = {};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,2 @@
|
||||
)]}'
|
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;","file":"/packages/meteor-platform.js"}
|
||||
1086
web-app/.meteor/local/build/programs/web.browser/packages/meteor.js
Normal file
1232
web-app/.meteor/local/build/programs/web.browser/packages/mongo.js
Normal file
@@ -0,0 +1,29 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package['mquandalle:jade'] = {};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,2 @@
|
||||
)]}'
|
||||
{"version":3,"sources":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;","file":"/packages/mquandalle_jade.js"}
|
||||
@@ -0,0 +1,578 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
|
||||
/* Package-scope variables */
|
||||
var topojson, n;
|
||||
|
||||
(function () {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/mrt:topojson/topojson.js //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
!function() { // 1
|
||||
topojson = { // 2
|
||||
version: "1.6.8", // 3
|
||||
mesh: function(topology) { return object(topology, meshArcs.apply(this, arguments)); }, // 4
|
||||
meshArcs: meshArcs, // 5
|
||||
merge: function(topology) { return object(topology, mergeArcs.apply(this, arguments)); }, // 6
|
||||
mergeArcs: mergeArcs, // 7
|
||||
feature: featureOrCollection, // 8
|
||||
neighbors: neighbors, // 9
|
||||
presimplify: presimplify // 10
|
||||
}; // 11
|
||||
// 12
|
||||
function stitchArcs(topology, arcs) { // 13
|
||||
var stitchedArcs = {}, // 14
|
||||
fragmentByStart = {}, // 15
|
||||
fragmentByEnd = {}, // 16
|
||||
fragments = [], // 17
|
||||
emptyIndex = -1; // 18
|
||||
// 19
|
||||
// Stitch empty arcs first, since they may be subsumed by other arcs. // 20
|
||||
arcs.forEach(function(i, j) { // 21
|
||||
var arc = topology.arcs[i < 0 ? ~i : i], t; // 22
|
||||
if (arc.length < 3 && !arc[1][0] && !arc[1][1]) { // 23
|
||||
t = arcs[++emptyIndex], arcs[emptyIndex] = i, arcs[j] = t; // 24
|
||||
} // 25
|
||||
}); // 26
|
||||
// 27
|
||||
arcs.forEach(function(i) { // 28
|
||||
var e = ends(i), // 29
|
||||
start = e[0], // 30
|
||||
end = e[1], // 31
|
||||
f, g; // 32
|
||||
// 33
|
||||
if (f = fragmentByEnd[start]) { // 34
|
||||
delete fragmentByEnd[f.end]; // 35
|
||||
f.push(i); // 36
|
||||
f.end = end; // 37
|
||||
if (g = fragmentByStart[end]) { // 38
|
||||
delete fragmentByStart[g.start]; // 39
|
||||
var fg = g === f ? f : f.concat(g); // 40
|
||||
fragmentByStart[fg.start = f.start] = fragmentByEnd[fg.end = g.end] = fg; // 41
|
||||
} else { // 42
|
||||
fragmentByStart[f.start] = fragmentByEnd[f.end] = f; // 43
|
||||
} // 44
|
||||
} else if (f = fragmentByStart[end]) { // 45
|
||||
delete fragmentByStart[f.start]; // 46
|
||||
f.unshift(i); // 47
|
||||
f.start = start; // 48
|
||||
if (g = fragmentByEnd[start]) { // 49
|
||||
delete fragmentByEnd[g.end]; // 50
|
||||
var gf = g === f ? f : g.concat(f); // 51
|
||||
fragmentByStart[gf.start = g.start] = fragmentByEnd[gf.end = f.end] = gf; // 52
|
||||
} else { // 53
|
||||
fragmentByStart[f.start] = fragmentByEnd[f.end] = f; // 54
|
||||
} // 55
|
||||
} else { // 56
|
||||
f = [i]; // 57
|
||||
fragmentByStart[f.start = start] = fragmentByEnd[f.end = end] = f; // 58
|
||||
} // 59
|
||||
}); // 60
|
||||
// 61
|
||||
function ends(i) { // 62
|
||||
var arc = topology.arcs[i < 0 ? ~i : i], p0 = arc[0], p1; // 63
|
||||
if (topology.transform) p1 = [0, 0], arc.forEach(function(dp) { p1[0] += dp[0], p1[1] += dp[1]; }); // 64
|
||||
else p1 = arc[arc.length - 1]; // 65
|
||||
return i < 0 ? [p1, p0] : [p0, p1]; // 66
|
||||
} // 67
|
||||
// 68
|
||||
function flush(fragmentByEnd, fragmentByStart) { // 69
|
||||
for (var k in fragmentByEnd) { // 70
|
||||
var f = fragmentByEnd[k]; // 71
|
||||
delete fragmentByStart[f.start]; // 72
|
||||
delete f.start; // 73
|
||||
delete f.end; // 74
|
||||
f.forEach(function(i) { stitchedArcs[i < 0 ? ~i : i] = 1; }); // 75
|
||||
fragments.push(f); // 76
|
||||
} // 77
|
||||
} // 78
|
||||
// 79
|
||||
flush(fragmentByEnd, fragmentByStart); // 80
|
||||
flush(fragmentByStart, fragmentByEnd); // 81
|
||||
arcs.forEach(function(i) { if (!stitchedArcs[i < 0 ? ~i : i]) fragments.push([i]); }); // 82
|
||||
// 83
|
||||
return fragments; // 84
|
||||
} // 85
|
||||
// 86
|
||||
function meshArcs(topology, o, filter) { // 87
|
||||
var arcs = []; // 88
|
||||
// 89
|
||||
if (arguments.length > 1) { // 90
|
||||
var geomsByArc = [], // 91
|
||||
geom; // 92
|
||||
// 93
|
||||
function arc(i) { // 94
|
||||
var j = i < 0 ? ~i : i; // 95
|
||||
(geomsByArc[j] || (geomsByArc[j] = [])).push({i: i, g: geom}); // 96
|
||||
} // 97
|
||||
// 98
|
||||
function line(arcs) { // 99
|
||||
arcs.forEach(arc); // 100
|
||||
} // 101
|
||||
// 102
|
||||
function polygon(arcs) { // 103
|
||||
arcs.forEach(line); // 104
|
||||
} // 105
|
||||
// 106
|
||||
function geometry(o) { // 107
|
||||
if (o.type === "GeometryCollection") o.geometries.forEach(geometry); // 108
|
||||
else if (o.type in geometryType) geom = o, geometryType[o.type](o.arcs); // 109
|
||||
} // 110
|
||||
// 111
|
||||
var geometryType = { // 112
|
||||
LineString: line, // 113
|
||||
MultiLineString: polygon, // 114
|
||||
Polygon: polygon, // 115
|
||||
MultiPolygon: function(arcs) { arcs.forEach(polygon); } // 116
|
||||
}; // 117
|
||||
// 118
|
||||
geometry(o); // 119
|
||||
// 120
|
||||
geomsByArc.forEach(arguments.length < 3 // 121
|
||||
? function(geoms) { arcs.push(geoms[0].i); } // 122
|
||||
: function(geoms) { if (filter(geoms[0].g, geoms[geoms.length - 1].g)) arcs.push(geoms[0].i); }); // 123
|
||||
} else { // 124
|
||||
for (var i = 0, n = topology.arcs.length; i < n; ++i) arcs.push(i); // 125
|
||||
} // 126
|
||||
// 127
|
||||
return {type: "MultiLineString", arcs: stitchArcs(topology, arcs)}; // 128
|
||||
} // 129
|
||||
// 130
|
||||
function mergeArcs(topology, objects) { // 131
|
||||
var polygonsByArc = {}, // 132
|
||||
polygons = [], // 133
|
||||
components = []; // 134
|
||||
// 135
|
||||
objects.forEach(function(o) { // 136
|
||||
if (o.type === "Polygon") register(o.arcs); // 137
|
||||
else if (o.type === "MultiPolygon") o.arcs.forEach(register); // 138
|
||||
}); // 139
|
||||
// 140
|
||||
function register(polygon) { // 141
|
||||
polygon.forEach(function(ring) { // 142
|
||||
ring.forEach(function(arc) { // 143
|
||||
(polygonsByArc[arc = arc < 0 ? ~arc : arc] || (polygonsByArc[arc] = [])).push(polygon); // 144
|
||||
}); // 145
|
||||
}); // 146
|
||||
polygons.push(polygon); // 147
|
||||
} // 148
|
||||
// 149
|
||||
function exterior(ring) { // 150
|
||||
return cartesianRingArea(object(topology, {type: "Polygon", arcs: [ring]}).coordinates[0]) > 0; // TODO allow spherical?
|
||||
} // 152
|
||||
// 153
|
||||
polygons.forEach(function(polygon) { // 154
|
||||
if (!polygon._) { // 155
|
||||
var component = [], // 156
|
||||
neighbors = [polygon]; // 157
|
||||
polygon._ = 1; // 158
|
||||
components.push(component); // 159
|
||||
while (polygon = neighbors.pop()) { // 160
|
||||
component.push(polygon); // 161
|
||||
polygon.forEach(function(ring) { // 162
|
||||
ring.forEach(function(arc) { // 163
|
||||
polygonsByArc[arc < 0 ? ~arc : arc].forEach(function(polygon) { // 164
|
||||
if (!polygon._) { // 165
|
||||
polygon._ = 1; // 166
|
||||
neighbors.push(polygon); // 167
|
||||
} // 168
|
||||
}); // 169
|
||||
}); // 170
|
||||
}); // 171
|
||||
} // 172
|
||||
} // 173
|
||||
}); // 174
|
||||
// 175
|
||||
polygons.forEach(function(polygon) { // 176
|
||||
delete polygon._; // 177
|
||||
}); // 178
|
||||
// 179
|
||||
return { // 180
|
||||
type: "MultiPolygon", // 181
|
||||
arcs: components.map(function(polygons) { // 182
|
||||
var arcs = []; // 183
|
||||
// 184
|
||||
// Extract the exterior (unique) arcs. // 185
|
||||
polygons.forEach(function(polygon) { // 186
|
||||
polygon.forEach(function(ring) { // 187
|
||||
ring.forEach(function(arc) { // 188
|
||||
if (polygonsByArc[arc < 0 ? ~arc : arc].length < 2) { // 189
|
||||
arcs.push(arc); // 190
|
||||
} // 191
|
||||
}); // 192
|
||||
}); // 193
|
||||
}); // 194
|
||||
// 195
|
||||
// Stitch the arcs into one or more rings. // 196
|
||||
arcs = stitchArcs(topology, arcs); // 197
|
||||
// 198
|
||||
// If more than one ring is returned, // 199
|
||||
// at most one of these rings can be the exterior; // 200
|
||||
// this exterior ring has the same winding order // 201
|
||||
// as any exterior ring in the original polygons. // 202
|
||||
if ((n = arcs.length) > 1) { // 203
|
||||
var sgn = exterior(polygons[0][0]); // 204
|
||||
for (var i = 0, t; i < n; ++i) { // 205
|
||||
if (sgn === exterior(arcs[i])) { // 206
|
||||
t = arcs[0], arcs[0] = arcs[i], arcs[i] = t; // 207
|
||||
break; // 208
|
||||
} // 209
|
||||
} // 210
|
||||
} // 211
|
||||
// 212
|
||||
return arcs; // 213
|
||||
}) // 214
|
||||
}; // 215
|
||||
} // 216
|
||||
// 217
|
||||
function featureOrCollection(topology, o) { // 218
|
||||
return o.type === "GeometryCollection" ? { // 219
|
||||
type: "FeatureCollection", // 220
|
||||
features: o.geometries.map(function(o) { return feature(topology, o); }) // 221
|
||||
} : feature(topology, o); // 222
|
||||
} // 223
|
||||
// 224
|
||||
function feature(topology, o) { // 225
|
||||
var f = { // 226
|
||||
type: "Feature", // 227
|
||||
id: o.id, // 228
|
||||
properties: o.properties || {}, // 229
|
||||
geometry: object(topology, o) // 230
|
||||
}; // 231
|
||||
if (o.id == null) delete f.id; // 232
|
||||
return f; // 233
|
||||
} // 234
|
||||
// 235
|
||||
function object(topology, o) { // 236
|
||||
var absolute = transformAbsolute(topology.transform), // 237
|
||||
arcs = topology.arcs; // 238
|
||||
// 239
|
||||
function arc(i, points) { // 240
|
||||
if (points.length) points.pop(); // 241
|
||||
for (var a = arcs[i < 0 ? ~i : i], k = 0, n = a.length, p; k < n; ++k) { // 242
|
||||
points.push(p = a[k].slice()); // 243
|
||||
absolute(p, k); // 244
|
||||
} // 245
|
||||
if (i < 0) reverse(points, n); // 246
|
||||
} // 247
|
||||
// 248
|
||||
function point(p) { // 249
|
||||
p = p.slice(); // 250
|
||||
absolute(p, 0); // 251
|
||||
return p; // 252
|
||||
} // 253
|
||||
// 254
|
||||
function line(arcs) { // 255
|
||||
var points = []; // 256
|
||||
for (var i = 0, n = arcs.length; i < n; ++i) arc(arcs[i], points); // 257
|
||||
if (points.length < 2) points.push(points[0].slice()); // 258
|
||||
return points; // 259
|
||||
} // 260
|
||||
// 261
|
||||
function ring(arcs) { // 262
|
||||
var points = line(arcs); // 263
|
||||
while (points.length < 4) points.push(points[0].slice()); // 264
|
||||
return points; // 265
|
||||
} // 266
|
||||
// 267
|
||||
function polygon(arcs) { // 268
|
||||
return arcs.map(ring); // 269
|
||||
} // 270
|
||||
// 271
|
||||
function geometry(o) { // 272
|
||||
var t = o.type; // 273
|
||||
return t === "GeometryCollection" ? {type: t, geometries: o.geometries.map(geometry)} // 274
|
||||
: t in geometryType ? {type: t, coordinates: geometryType[t](o)} // 275
|
||||
: null; // 276
|
||||
} // 277
|
||||
// 278
|
||||
var geometryType = { // 279
|
||||
Point: function(o) { return point(o.coordinates); }, // 280
|
||||
MultiPoint: function(o) { return o.coordinates.map(point); }, // 281
|
||||
LineString: function(o) { return line(o.arcs); }, // 282
|
||||
MultiLineString: function(o) { return o.arcs.map(line); }, // 283
|
||||
Polygon: function(o) { return polygon(o.arcs); }, // 284
|
||||
MultiPolygon: function(o) { return o.arcs.map(polygon); } // 285
|
||||
}; // 286
|
||||
// 287
|
||||
return geometry(o); // 288
|
||||
} // 289
|
||||
// 290
|
||||
function reverse(array, n) { // 291
|
||||
var t, j = array.length, i = j - n; while (i < --j) t = array[i], array[i++] = array[j], array[j] = t; // 292
|
||||
} // 293
|
||||
// 294
|
||||
function bisect(a, x) { // 295
|
||||
var lo = 0, hi = a.length; // 296
|
||||
while (lo < hi) { // 297
|
||||
var mid = lo + hi >>> 1; // 298
|
||||
if (a[mid] < x) lo = mid + 1; // 299
|
||||
else hi = mid; // 300
|
||||
} // 301
|
||||
return lo; // 302
|
||||
} // 303
|
||||
// 304
|
||||
function neighbors(objects) { // 305
|
||||
var indexesByArc = {}, // arc index -> array of object indexes // 306
|
||||
neighbors = objects.map(function() { return []; }); // 307
|
||||
// 308
|
||||
function line(arcs, i) { // 309
|
||||
arcs.forEach(function(a) { // 310
|
||||
if (a < 0) a = ~a; // 311
|
||||
var o = indexesByArc[a]; // 312
|
||||
if (o) o.push(i); // 313
|
||||
else indexesByArc[a] = [i]; // 314
|
||||
}); // 315
|
||||
} // 316
|
||||
// 317
|
||||
function polygon(arcs, i) { // 318
|
||||
arcs.forEach(function(arc) { line(arc, i); }); // 319
|
||||
} // 320
|
||||
// 321
|
||||
function geometry(o, i) { // 322
|
||||
if (o.type === "GeometryCollection") o.geometries.forEach(function(o) { geometry(o, i); }); // 323
|
||||
else if (o.type in geometryType) geometryType[o.type](o.arcs, i); // 324
|
||||
} // 325
|
||||
// 326
|
||||
var geometryType = { // 327
|
||||
LineString: line, // 328
|
||||
MultiLineString: polygon, // 329
|
||||
Polygon: polygon, // 330
|
||||
MultiPolygon: function(arcs, i) { arcs.forEach(function(arc) { polygon(arc, i); }); } // 331
|
||||
}; // 332
|
||||
// 333
|
||||
objects.forEach(geometry); // 334
|
||||
// 335
|
||||
for (var i in indexesByArc) { // 336
|
||||
for (var indexes = indexesByArc[i], m = indexes.length, j = 0; j < m; ++j) { // 337
|
||||
for (var k = j + 1; k < m; ++k) { // 338
|
||||
var ij = indexes[j], ik = indexes[k], n; // 339
|
||||
if ((n = neighbors[ij])[i = bisect(n, ik)] !== ik) n.splice(i, 0, ik); // 340
|
||||
if ((n = neighbors[ik])[i = bisect(n, ij)] !== ij) n.splice(i, 0, ij); // 341
|
||||
} // 342
|
||||
} // 343
|
||||
} // 344
|
||||
// 345
|
||||
return neighbors; // 346
|
||||
} // 347
|
||||
// 348
|
||||
function presimplify(topology, triangleArea) { // 349
|
||||
var absolute = transformAbsolute(topology.transform), // 350
|
||||
relative = transformRelative(topology.transform), // 351
|
||||
heap = minAreaHeap(), // 352
|
||||
maxArea = 0, // 353
|
||||
triangle; // 354
|
||||
// 355
|
||||
if (!triangleArea) triangleArea = cartesianTriangleArea; // 356
|
||||
// 357
|
||||
topology.arcs.forEach(function(arc) { // 358
|
||||
var triangles = []; // 359
|
||||
// 360
|
||||
arc.forEach(absolute); // 361
|
||||
// 362
|
||||
for (var i = 1, n = arc.length - 1; i < n; ++i) { // 363
|
||||
triangle = arc.slice(i - 1, i + 2); // 364
|
||||
triangle[1][2] = triangleArea(triangle); // 365
|
||||
triangles.push(triangle); // 366
|
||||
heap.push(triangle); // 367
|
||||
} // 368
|
||||
// 369
|
||||
// Always keep the arc endpoints! // 370
|
||||
arc[0][2] = arc[n][2] = Infinity; // 371
|
||||
// 372
|
||||
for (var i = 0, n = triangles.length; i < n; ++i) { // 373
|
||||
triangle = triangles[i]; // 374
|
||||
triangle.previous = triangles[i - 1]; // 375
|
||||
triangle.next = triangles[i + 1]; // 376
|
||||
} // 377
|
||||
}); // 378
|
||||
// 379
|
||||
while (triangle = heap.pop()) { // 380
|
||||
var previous = triangle.previous, // 381
|
||||
next = triangle.next; // 382
|
||||
// 383
|
||||
// If the area of the current point is less than that of the previous point // 384
|
||||
// to be eliminated, use the latter's area instead. This ensures that the // 385
|
||||
// current point cannot be eliminated without eliminating previously- // 386
|
||||
// eliminated points. // 387
|
||||
if (triangle[1][2] < maxArea) triangle[1][2] = maxArea; // 388
|
||||
else maxArea = triangle[1][2]; // 389
|
||||
// 390
|
||||
if (previous) { // 391
|
||||
previous.next = next; // 392
|
||||
previous[2] = triangle[2]; // 393
|
||||
update(previous); // 394
|
||||
} // 395
|
||||
// 396
|
||||
if (next) { // 397
|
||||
next.previous = previous; // 398
|
||||
next[0] = triangle[0]; // 399
|
||||
update(next); // 400
|
||||
} // 401
|
||||
} // 402
|
||||
// 403
|
||||
topology.arcs.forEach(function(arc) { // 404
|
||||
arc.forEach(relative); // 405
|
||||
}); // 406
|
||||
// 407
|
||||
function update(triangle) { // 408
|
||||
heap.remove(triangle); // 409
|
||||
triangle[1][2] = triangleArea(triangle); // 410
|
||||
heap.push(triangle); // 411
|
||||
} // 412
|
||||
// 413
|
||||
return topology; // 414
|
||||
}; // 415
|
||||
// 416
|
||||
function cartesianRingArea(ring) { // 417
|
||||
var i = -1, // 418
|
||||
n = ring.length, // 419
|
||||
a, // 420
|
||||
b = ring[n - 1], // 421
|
||||
area = 0; // 422
|
||||
// 423
|
||||
while (++i < n) { // 424
|
||||
a = b; // 425
|
||||
b = ring[i]; // 426
|
||||
area += a[0] * b[1] - a[1] * b[0]; // 427
|
||||
} // 428
|
||||
// 429
|
||||
return area * .5; // 430
|
||||
} // 431
|
||||
// 432
|
||||
function cartesianTriangleArea(triangle) { // 433
|
||||
var a = triangle[0], b = triangle[1], c = triangle[2]; // 434
|
||||
return Math.abs((a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1])); // 435
|
||||
} // 436
|
||||
// 437
|
||||
function compareArea(a, b) { // 438
|
||||
return a[1][2] - b[1][2]; // 439
|
||||
} // 440
|
||||
// 441
|
||||
function minAreaHeap() { // 442
|
||||
var heap = {}, // 443
|
||||
array = [], // 444
|
||||
size = 0; // 445
|
||||
// 446
|
||||
heap.push = function(object) { // 447
|
||||
up(array[object._ = size] = object, size++); // 448
|
||||
return size; // 449
|
||||
}; // 450
|
||||
// 451
|
||||
heap.pop = function() { // 452
|
||||
if (size <= 0) return; // 453
|
||||
var removed = array[0], object; // 454
|
||||
if (--size > 0) object = array[size], down(array[object._ = 0] = object, 0); // 455
|
||||
return removed; // 456
|
||||
}; // 457
|
||||
// 458
|
||||
heap.remove = function(removed) { // 459
|
||||
var i = removed._, object; // 460
|
||||
if (array[i] !== removed) return; // invalid request // 461
|
||||
if (i !== --size) object = array[size], (compareArea(object, removed) < 0 ? up : down)(array[object._ = i] = object, i);
|
||||
return i; // 463
|
||||
}; // 464
|
||||
// 465
|
||||
function up(object, i) { // 466
|
||||
while (i > 0) { // 467
|
||||
var j = ((i + 1) >> 1) - 1, // 468
|
||||
parent = array[j]; // 469
|
||||
if (compareArea(object, parent) >= 0) break; // 470
|
||||
array[parent._ = i] = parent; // 471
|
||||
array[object._ = i = j] = object; // 472
|
||||
} // 473
|
||||
} // 474
|
||||
// 475
|
||||
function down(object, i) { // 476
|
||||
while (true) { // 477
|
||||
var r = (i + 1) << 1, // 478
|
||||
l = r - 1, // 479
|
||||
j = i, // 480
|
||||
child = array[j]; // 481
|
||||
if (l < size && compareArea(array[l], child) < 0) child = array[j = l]; // 482
|
||||
if (r < size && compareArea(array[r], child) < 0) child = array[j = r]; // 483
|
||||
if (j === i) break; // 484
|
||||
array[child._ = i] = child; // 485
|
||||
array[object._ = i = j] = object; // 486
|
||||
} // 487
|
||||
} // 488
|
||||
// 489
|
||||
return heap; // 490
|
||||
} // 491
|
||||
// 492
|
||||
function transformAbsolute(transform) { // 493
|
||||
if (!transform) return noop; // 494
|
||||
var x0, // 495
|
||||
y0, // 496
|
||||
kx = transform.scale[0], // 497
|
||||
ky = transform.scale[1], // 498
|
||||
dx = transform.translate[0], // 499
|
||||
dy = transform.translate[1]; // 500
|
||||
return function(point, i) { // 501
|
||||
if (!i) x0 = y0 = 0; // 502
|
||||
point[0] = (x0 += point[0]) * kx + dx; // 503
|
||||
point[1] = (y0 += point[1]) * ky + dy; // 504
|
||||
}; // 505
|
||||
} // 506
|
||||
// 507
|
||||
function transformRelative(transform) { // 508
|
||||
if (!transform) return noop; // 509
|
||||
var x0, // 510
|
||||
y0, // 511
|
||||
kx = transform.scale[0], // 512
|
||||
ky = transform.scale[1], // 513
|
||||
dx = transform.translate[0], // 514
|
||||
dy = transform.translate[1]; // 515
|
||||
return function(point, i) { // 516
|
||||
if (!i) x0 = y0 = 0; // 517
|
||||
var x1 = (point[0] - dx) / kx | 0, // 518
|
||||
y1 = (point[1] - dy) / ky | 0; // 519
|
||||
point[0] = x1 - x0; // 520
|
||||
point[1] = y1 - y0; // 521
|
||||
x0 = x1; // 522
|
||||
y0 = y1; // 523
|
||||
}; // 524
|
||||
} // 525
|
||||
// 526
|
||||
function noop() {} // 527
|
||||
// 528
|
||||
if (typeof define === "function" && define.amd) define(topojson); // 529
|
||||
else if (typeof module === "object" && module.exports) module.exports = topojson; // 530
|
||||
else this.topojson = topojson; // 531
|
||||
}(); // 532
|
||||
// 533
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package['mrt:topojson'] = {
|
||||
topojson: topojson
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,994 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
|
||||
/* Package-scope variables */
|
||||
var numeral;
|
||||
|
||||
(function () {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/numeral:numeral/numeral.js //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/*! // 1
|
||||
* numeral.js // 2
|
||||
* version : 1.5.3 // 3
|
||||
* author : Adam Draper // 4
|
||||
* license : MIT // 5
|
||||
* http://adamwdraper.github.com/Numeral-js/ // 6
|
||||
*/ // 7
|
||||
// 8
|
||||
(function() { // 9
|
||||
// 10
|
||||
/************************************ // 11
|
||||
Constants // 12
|
||||
************************************/ // 13
|
||||
// 14
|
||||
var numeral, // 15
|
||||
VERSION = '1.5.3', // 16
|
||||
// internal storage for language config files // 17
|
||||
languages = {}, // 18
|
||||
currentLanguage = 'en', // 19
|
||||
zeroFormat = null, // 20
|
||||
defaultFormat = '0,0', // 21
|
||||
// check for nodeJS // 22
|
||||
hasModule = (typeof module !== 'undefined' && module.exports); // 23
|
||||
// 24
|
||||
// 25
|
||||
/************************************ // 26
|
||||
Constructors // 27
|
||||
************************************/ // 28
|
||||
// 29
|
||||
// 30
|
||||
// Numeral prototype object // 31
|
||||
function Numeral(number) { // 32
|
||||
this._value = number; // 33
|
||||
} // 34
|
||||
// 35
|
||||
/** // 36
|
||||
* Implementation of toFixed() that treats floats more like decimals // 37
|
||||
* // 38
|
||||
* Fixes binary rounding issues (eg. (0.615).toFixed(2) === '0.61') that present // 39
|
||||
* problems for accounting- and finance-related software. // 40
|
||||
*/ // 41
|
||||
function toFixed(value, precision, roundingFunction, optionals) { // 42
|
||||
var power = Math.pow(10, precision), // 43
|
||||
optionalsRegExp, // 44
|
||||
output; // 45
|
||||
// 46
|
||||
//roundingFunction = (roundingFunction !== undefined ? roundingFunction : Math.round); // 47
|
||||
// Multiply up by precision, round accurately, then divide and use native toFixed(): // 48
|
||||
output = (roundingFunction(value * power) / power).toFixed(precision); // 49
|
||||
// 50
|
||||
if (optionals) { // 51
|
||||
optionalsRegExp = new RegExp('0{1,' + optionals + '}$'); // 52
|
||||
output = output.replace(optionalsRegExp, ''); // 53
|
||||
} // 54
|
||||
// 55
|
||||
return output; // 56
|
||||
} // 57
|
||||
// 58
|
||||
/************************************ // 59
|
||||
Formatting // 60
|
||||
************************************/ // 61
|
||||
// 62
|
||||
// determine what type of formatting we need to do // 63
|
||||
function formatNumeral(n, format, roundingFunction) { // 64
|
||||
var output; // 65
|
||||
// 66
|
||||
// figure out what kind of format we are dealing with // 67
|
||||
if (format.indexOf('$') > -1) { // currency!!!!! // 68
|
||||
output = formatCurrency(n, format, roundingFunction); // 69
|
||||
} else if (format.indexOf('%') > -1) { // percentage // 70
|
||||
output = formatPercentage(n, format, roundingFunction); // 71
|
||||
} else if (format.indexOf(':') > -1) { // time // 72
|
||||
output = formatTime(n, format); // 73
|
||||
} else { // plain ol' numbers or bytes // 74
|
||||
output = formatNumber(n._value, format, roundingFunction); // 75
|
||||
} // 76
|
||||
// 77
|
||||
// return string // 78
|
||||
return output; // 79
|
||||
} // 80
|
||||
// 81
|
||||
// revert to number // 82
|
||||
function unformatNumeral(n, string) { // 83
|
||||
var stringOriginal = string, // 84
|
||||
thousandRegExp, // 85
|
||||
millionRegExp, // 86
|
||||
billionRegExp, // 87
|
||||
trillionRegExp, // 88
|
||||
suffixes = ['KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], // 89
|
||||
bytesMultiplier = false, // 90
|
||||
power; // 91
|
||||
// 92
|
||||
if (string.indexOf(':') > -1) { // 93
|
||||
n._value = unformatTime(string); // 94
|
||||
} else { // 95
|
||||
if (string === zeroFormat) { // 96
|
||||
n._value = 0; // 97
|
||||
} else { // 98
|
||||
if (languages[currentLanguage].delimiters.decimal !== '.') { // 99
|
||||
string = string.replace(/\./g, '').replace(languages[currentLanguage].delimiters.decimal, '.'); // 100
|
||||
} // 101
|
||||
// 102
|
||||
// see if abbreviations are there so that we can multiply to the correct number // 103
|
||||
thousandRegExp = new RegExp('[^a-zA-Z]' + languages[currentLanguage].abbreviations.thousand + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$');
|
||||
millionRegExp = new RegExp('[^a-zA-Z]' + languages[currentLanguage].abbreviations.million + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$');
|
||||
billionRegExp = new RegExp('[^a-zA-Z]' + languages[currentLanguage].abbreviations.billion + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$');
|
||||
trillionRegExp = new RegExp('[^a-zA-Z]' + languages[currentLanguage].abbreviations.trillion + '(?:\\)|(\\' + languages[currentLanguage].currency.symbol + ')?(?:\\))?)?$');
|
||||
// 108
|
||||
// see if bytes are there so that we can multiply to the correct number // 109
|
||||
for (power = 0; power <= suffixes.length; power++) { // 110
|
||||
bytesMultiplier = (string.indexOf(suffixes[power]) > -1) ? Math.pow(1024, power + 1) : false; // 111
|
||||
// 112
|
||||
if (bytesMultiplier) { // 113
|
||||
break; // 114
|
||||
} // 115
|
||||
} // 116
|
||||
// 117
|
||||
// do some math to create our number // 118
|
||||
n._value = ((bytesMultiplier) ? bytesMultiplier : 1) * ((stringOriginal.match(thousandRegExp)) ? Math.pow(10, 3) : 1) * ((stringOriginal.match(millionRegExp)) ? Math.pow(10, 6) : 1) * ((stringOriginal.match(billionRegExp)) ? Math.pow(10, 9) : 1) * ((stringOriginal.match(trillionRegExp)) ? Math.pow(10, 12) : 1) * ((string.indexOf('%') > -1) ? 0.01 : 1) * (((string.split('-').length + Math.min(string.split('(').length - 1, string.split(')').length - 1)) % 2) ? 1 : -1) * Number(string.replace(/[^0-9\.]+/g, ''));
|
||||
// 120
|
||||
// round if we are talking about bytes // 121
|
||||
n._value = (bytesMultiplier) ? Math.ceil(n._value) : n._value; // 122
|
||||
} // 123
|
||||
} // 124
|
||||
return n._value; // 125
|
||||
} // 126
|
||||
// 127
|
||||
function formatCurrency(n, format, roundingFunction) { // 128
|
||||
var symbolIndex = format.indexOf('$'), // 129
|
||||
openParenIndex = format.indexOf('('), // 130
|
||||
minusSignIndex = format.indexOf('-'), // 131
|
||||
space = '', // 132
|
||||
spliceIndex, // 133
|
||||
output; // 134
|
||||
// 135
|
||||
// check for space before or after currency // 136
|
||||
if (format.indexOf(' $') > -1) { // 137
|
||||
space = ' '; // 138
|
||||
format = format.replace(' $', ''); // 139
|
||||
} else if (format.indexOf('$ ') > -1) { // 140
|
||||
space = ' '; // 141
|
||||
format = format.replace('$ ', ''); // 142
|
||||
} else { // 143
|
||||
format = format.replace('$', ''); // 144
|
||||
} // 145
|
||||
// 146
|
||||
// format the number // 147
|
||||
output = formatNumber(n._value, format, roundingFunction); // 148
|
||||
// 149
|
||||
// position the symbol // 150
|
||||
if (symbolIndex <= 1) { // 151
|
||||
if (output.indexOf('(') > -1 || output.indexOf('-') > -1) { // 152
|
||||
output = output.split(''); // 153
|
||||
spliceIndex = 1; // 154
|
||||
if (symbolIndex < openParenIndex || symbolIndex < minusSignIndex) { // 155
|
||||
// the symbol appears before the "(" or "-" // 156
|
||||
spliceIndex = 0; // 157
|
||||
} // 158
|
||||
output.splice(spliceIndex, 0, languages[currentLanguage].currency.symbol + space); // 159
|
||||
output = output.join(''); // 160
|
||||
} else { // 161
|
||||
output = languages[currentLanguage].currency.symbol + space + output; // 162
|
||||
} // 163
|
||||
} else { // 164
|
||||
if (output.indexOf(')') > -1) { // 165
|
||||
output = output.split(''); // 166
|
||||
output.splice(-1, 0, space + languages[currentLanguage].currency.symbol); // 167
|
||||
output = output.join(''); // 168
|
||||
} else { // 169
|
||||
output = output + space + languages[currentLanguage].currency.symbol; // 170
|
||||
} // 171
|
||||
} // 172
|
||||
// 173
|
||||
return output; // 174
|
||||
} // 175
|
||||
// 176
|
||||
function formatPercentage(n, format, roundingFunction) { // 177
|
||||
var space = '', // 178
|
||||
output, // 179
|
||||
value = n._value * 100; // 180
|
||||
// 181
|
||||
// check for space before % // 182
|
||||
if (format.indexOf(' %') > -1) { // 183
|
||||
space = ' '; // 184
|
||||
format = format.replace(' %', ''); // 185
|
||||
} else { // 186
|
||||
format = format.replace('%', ''); // 187
|
||||
} // 188
|
||||
// 189
|
||||
output = formatNumber(value, format, roundingFunction); // 190
|
||||
// 191
|
||||
if (output.indexOf(')') > -1) { // 192
|
||||
output = output.split(''); // 193
|
||||
output.splice(-1, 0, space + '%'); // 194
|
||||
output = output.join(''); // 195
|
||||
} else { // 196
|
||||
output = output + space + '%'; // 197
|
||||
} // 198
|
||||
// 199
|
||||
return output; // 200
|
||||
} // 201
|
||||
// 202
|
||||
function formatTime(n) { // 203
|
||||
var hours = Math.floor(n._value / 60 / 60), // 204
|
||||
minutes = Math.floor((n._value - (hours * 60 * 60)) / 60), // 205
|
||||
seconds = Math.round(n._value - (hours * 60 * 60) - (minutes * 60)); // 206
|
||||
return hours + ':' + ((minutes < 10) ? '0' + minutes : minutes) + ':' + ((seconds < 10) ? '0' + seconds : seconds);
|
||||
} // 208
|
||||
// 209
|
||||
function unformatTime(string) { // 210
|
||||
var timeArray = string.split(':'), // 211
|
||||
seconds = 0; // 212
|
||||
// turn hours and minutes into seconds and add them all up // 213
|
||||
if (timeArray.length === 3) { // 214
|
||||
// hours // 215
|
||||
seconds = seconds + (Number(timeArray[0]) * 60 * 60); // 216
|
||||
// minutes // 217
|
||||
seconds = seconds + (Number(timeArray[1]) * 60); // 218
|
||||
// seconds // 219
|
||||
seconds = seconds + Number(timeArray[2]); // 220
|
||||
} else if (timeArray.length === 2) { // 221
|
||||
// minutes // 222
|
||||
seconds = seconds + (Number(timeArray[0]) * 60); // 223
|
||||
// seconds // 224
|
||||
seconds = seconds + Number(timeArray[1]); // 225
|
||||
} // 226
|
||||
return Number(seconds); // 227
|
||||
} // 228
|
||||
// 229
|
||||
function formatNumber(value, format, roundingFunction) { // 230
|
||||
var negP = false, // 231
|
||||
signed = false, // 232
|
||||
optDec = false, // 233
|
||||
abbr = '', // 234
|
||||
abbrK = false, // force abbreviation to thousands // 235
|
||||
abbrM = false, // force abbreviation to millions // 236
|
||||
abbrB = false, // force abbreviation to billions // 237
|
||||
abbrT = false, // force abbreviation to trillions // 238
|
||||
abbrForce = false, // force abbreviation // 239
|
||||
bytes = '', // 240
|
||||
ord = '', // 241
|
||||
abs = Math.abs(value), // 242
|
||||
suffixes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'], // 243
|
||||
min, // 244
|
||||
max, // 245
|
||||
power, // 246
|
||||
w, // 247
|
||||
precision, // 248
|
||||
thousands, // 249
|
||||
d = '', // 250
|
||||
neg = false; // 251
|
||||
// 252
|
||||
// check if number is zero and a custom zero format has been set // 253
|
||||
if (value === 0 && zeroFormat !== null) { // 254
|
||||
return zeroFormat; // 255
|
||||
} else { // 256
|
||||
// see if we should use parentheses for negative number or if we should prefix with a sign // 257
|
||||
// if both are present we default to parentheses // 258
|
||||
if (format.indexOf('(') > -1) { // 259
|
||||
negP = true; // 260
|
||||
format = format.slice(1, -1); // 261
|
||||
} else if (format.indexOf('+') > -1) { // 262
|
||||
signed = true; // 263
|
||||
format = format.replace(/\+/g, ''); // 264
|
||||
} // 265
|
||||
// 266
|
||||
// see if abbreviation is wanted // 267
|
||||
if (format.indexOf('a') > -1) { // 268
|
||||
// check if abbreviation is specified // 269
|
||||
abbrK = format.indexOf('aK') >= 0; // 270
|
||||
abbrM = format.indexOf('aM') >= 0; // 271
|
||||
abbrB = format.indexOf('aB') >= 0; // 272
|
||||
abbrT = format.indexOf('aT') >= 0; // 273
|
||||
abbrForce = abbrK || abbrM || abbrB || abbrT; // 274
|
||||
// 275
|
||||
// check for space before abbreviation // 276
|
||||
if (format.indexOf(' a') > -1) { // 277
|
||||
abbr = ' '; // 278
|
||||
format = format.replace(' a', ''); // 279
|
||||
} else { // 280
|
||||
format = format.replace('a', ''); // 281
|
||||
} // 282
|
||||
// 283
|
||||
if (abs >= Math.pow(10, 12) && !abbrForce || abbrT) { // 284
|
||||
// trillion // 285
|
||||
abbr = abbr + languages[currentLanguage].abbreviations.trillion; // 286
|
||||
value = value / Math.pow(10, 12); // 287
|
||||
} else if (abs < Math.pow(10, 12) && abs >= Math.pow(10, 9) && !abbrForce || abbrB) { // 288
|
||||
// billion // 289
|
||||
abbr = abbr + languages[currentLanguage].abbreviations.billion; // 290
|
||||
value = value / Math.pow(10, 9); // 291
|
||||
} else if (abs < Math.pow(10, 9) && abs >= Math.pow(10, 6) && !abbrForce || abbrM) { // 292
|
||||
// million // 293
|
||||
abbr = abbr + languages[currentLanguage].abbreviations.million; // 294
|
||||
value = value / Math.pow(10, 6); // 295
|
||||
} else if (abs < Math.pow(10, 6) && abs >= Math.pow(10, 3) && !abbrForce || abbrK) { // 296
|
||||
// thousand // 297
|
||||
abbr = abbr + languages[currentLanguage].abbreviations.thousand; // 298
|
||||
value = value / Math.pow(10, 3); // 299
|
||||
} // 300
|
||||
} // 301
|
||||
// 302
|
||||
// see if we are formatting bytes // 303
|
||||
if (format.indexOf('b') > -1) { // 304
|
||||
// check for space before // 305
|
||||
if (format.indexOf(' b') > -1) { // 306
|
||||
bytes = ' '; // 307
|
||||
format = format.replace(' b', ''); // 308
|
||||
} else { // 309
|
||||
format = format.replace('b', ''); // 310
|
||||
} // 311
|
||||
// 312
|
||||
for (power = 0; power <= suffixes.length; power++) { // 313
|
||||
min = Math.pow(1024, power); // 314
|
||||
max = Math.pow(1024, power + 1); // 315
|
||||
// 316
|
||||
if (value >= min && value < max) { // 317
|
||||
bytes = bytes + suffixes[power]; // 318
|
||||
if (min > 0) { // 319
|
||||
value = value / min; // 320
|
||||
} // 321
|
||||
break; // 322
|
||||
} // 323
|
||||
} // 324
|
||||
} // 325
|
||||
// 326
|
||||
// see if ordinal is wanted // 327
|
||||
if (format.indexOf('o') > -1) { // 328
|
||||
// check for space before // 329
|
||||
if (format.indexOf(' o') > -1) { // 330
|
||||
ord = ' '; // 331
|
||||
format = format.replace(' o', ''); // 332
|
||||
} else { // 333
|
||||
format = format.replace('o', ''); // 334
|
||||
} // 335
|
||||
// 336
|
||||
ord = ord + languages[currentLanguage].ordinal(value); // 337
|
||||
} // 338
|
||||
// 339
|
||||
if (format.indexOf('[.]') > -1) { // 340
|
||||
optDec = true; // 341
|
||||
format = format.replace('[.]', '.'); // 342
|
||||
} // 343
|
||||
// 344
|
||||
w = value.toString().split('.')[0]; // 345
|
||||
precision = format.split('.')[1]; // 346
|
||||
thousands = format.indexOf(','); // 347
|
||||
// 348
|
||||
if (precision) { // 349
|
||||
if (precision.indexOf('[') > -1) { // 350
|
||||
precision = precision.replace(']', ''); // 351
|
||||
precision = precision.split('['); // 352
|
||||
d = toFixed(value, (precision[0].length + precision[1].length), roundingFunction, precision[1].length);
|
||||
} else { // 354
|
||||
d = toFixed(value, precision.length, roundingFunction); // 355
|
||||
} // 356
|
||||
// 357
|
||||
w = d.split('.')[0]; // 358
|
||||
// 359
|
||||
if (d.split('.')[1].length) { // 360
|
||||
d = languages[currentLanguage].delimiters.decimal + d.split('.')[1]; // 361
|
||||
} else { // 362
|
||||
d = ''; // 363
|
||||
} // 364
|
||||
// 365
|
||||
if (optDec && Number(d.slice(1)) === 0) { // 366
|
||||
d = ''; // 367
|
||||
} // 368
|
||||
} else { // 369
|
||||
w = toFixed(value, null, roundingFunction); // 370
|
||||
} // 371
|
||||
// 372
|
||||
// format number // 373
|
||||
if (w.indexOf('-') > -1) { // 374
|
||||
w = w.slice(1); // 375
|
||||
neg = true; // 376
|
||||
} // 377
|
||||
// 378
|
||||
if (thousands > -1) { // 379
|
||||
w = w.toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1' + languages[currentLanguage].delimiters.thousands);
|
||||
} // 381
|
||||
// 382
|
||||
if (format.indexOf('.') === 0) { // 383
|
||||
w = ''; // 384
|
||||
} // 385
|
||||
// 386
|
||||
return ((negP && neg) ? '(' : '') + ((!negP && neg) ? '-' : '') + ((!neg && signed) ? '+' : '') + w + d + ((ord) ? ord : '') + ((abbr) ? abbr : '') + ((bytes) ? bytes : '') + ((negP && neg) ? ')' : '');
|
||||
} // 388
|
||||
} // 389
|
||||
// 390
|
||||
/************************************ // 391
|
||||
Top Level Functions // 392
|
||||
************************************/ // 393
|
||||
// 394
|
||||
numeral = function(input) { // 395
|
||||
if (numeral.isNumeral(input)) { // 396
|
||||
input = input.value(); // 397
|
||||
} else if (input === 0 || typeof input === 'undefined') { // 398
|
||||
input = 0; // 399
|
||||
} else if (!Number(input)) { // 400
|
||||
input = numeral.fn.unformat(input); // 401
|
||||
} // 402
|
||||
// 403
|
||||
return new Numeral(Number(input)); // 404
|
||||
}; // 405
|
||||
// 406
|
||||
// version number // 407
|
||||
numeral.version = VERSION; // 408
|
||||
// 409
|
||||
// compare numeral object // 410
|
||||
numeral.isNumeral = function(obj) { // 411
|
||||
return obj instanceof Numeral; // 412
|
||||
}; // 413
|
||||
// 414
|
||||
// This function will load languages and then set the global language. If // 415
|
||||
// no arguments are passed in, it will simply return the current global // 416
|
||||
// language key. // 417
|
||||
numeral.language = function(key, values) { // 418
|
||||
if (!key) { // 419
|
||||
return currentLanguage; // 420
|
||||
} // 421
|
||||
// 422
|
||||
key = key.toLowerCase(); // 423
|
||||
// 424
|
||||
if (key && !values) { // 425
|
||||
if (!languages[key]) { // 426
|
||||
throw new Error('Unknown language : ' + key); // 427
|
||||
} // 428
|
||||
currentLanguage = key; // 429
|
||||
} // 430
|
||||
// 431
|
||||
if (values || !languages[key]) { // 432
|
||||
loadLanguage(key, values); // 433
|
||||
} // 434
|
||||
// 435
|
||||
return numeral; // 436
|
||||
}; // 437
|
||||
// 438
|
||||
// This function provides access to the loaded language data. If // 439
|
||||
// no arguments are passed in, it will simply return the current // 440
|
||||
// global language object. // 441
|
||||
numeral.languageData = function(key) { // 442
|
||||
if (!key) { // 443
|
||||
return languages[currentLanguage]; // 444
|
||||
} // 445
|
||||
// 446
|
||||
if (!languages[key]) { // 447
|
||||
throw new Error('Unknown language : ' + key); // 448
|
||||
} // 449
|
||||
// 450
|
||||
return languages[key]; // 451
|
||||
}; // 452
|
||||
// 453
|
||||
numeral.language('en', { // 454
|
||||
delimiters: { // 455
|
||||
thousands: ',', // 456
|
||||
decimal: '.' // 457
|
||||
}, // 458
|
||||
abbreviations: { // 459
|
||||
thousand: 'k', // 460
|
||||
million: 'm', // 461
|
||||
billion: 'b', // 462
|
||||
trillion: 't' // 463
|
||||
}, // 464
|
||||
ordinal: function(number) { // 465
|
||||
var b = number % 10; // 466
|
||||
return (~~(number % 100 / 10) === 1) ? 'th' : // 467
|
||||
(b === 1) ? 'st' : // 468
|
||||
(b === 2) ? 'nd' : // 469
|
||||
(b === 3) ? 'rd' : 'th'; // 470
|
||||
}, // 471
|
||||
currency: { // 472
|
||||
symbol: '$' // 473
|
||||
} // 474
|
||||
}); // 475
|
||||
// 476
|
||||
numeral.zeroFormat = function(format) { // 477
|
||||
zeroFormat = typeof(format) === 'string' ? format : null; // 478
|
||||
}; // 479
|
||||
// 480
|
||||
numeral.defaultFormat = function(format) { // 481
|
||||
defaultFormat = typeof(format) === 'string' ? format : '0.0'; // 482
|
||||
}; // 483
|
||||
// 484
|
||||
numeral.validate = function(val, culture) { // 485
|
||||
// 486
|
||||
var _decimalSep, // 487
|
||||
_thousandSep, // 488
|
||||
_currSymbol, // 489
|
||||
_valArray, // 490
|
||||
_abbrObj, // 491
|
||||
_thousandRegEx, // 492
|
||||
languageData, // 493
|
||||
temp; // 494
|
||||
// 495
|
||||
//coerce val to string // 496
|
||||
if (typeof val !== 'string') { // 497
|
||||
val += ''; // 498
|
||||
if (console.warn) { // 499
|
||||
console.warn('Numeral.js: Value is not string. It has been co-erced to: ', val); // 500
|
||||
} // 501
|
||||
} // 502
|
||||
// 503
|
||||
//trim whitespaces from either sides // 504
|
||||
val = val.trim(); // 505
|
||||
// 506
|
||||
//if val is just digits return true // 507
|
||||
if ( !! val.match(/^\d+$/)) { // 508
|
||||
return true; // 509
|
||||
} // 510
|
||||
// 511
|
||||
//if val is empty return false // 512
|
||||
if (val === '') { // 513
|
||||
return false; // 514
|
||||
} // 515
|
||||
// 516
|
||||
//get the decimal and thousands separator from numeral.languageData // 517
|
||||
try { // 518
|
||||
//check if the culture is understood by numeral. if not, default it to current language // 519
|
||||
languageData = numeral.languageData(culture); // 520
|
||||
} catch (e) { // 521
|
||||
languageData = numeral.languageData(numeral.language()); // 522
|
||||
} // 523
|
||||
// 524
|
||||
//setup the delimiters and currency symbol based on culture/language // 525
|
||||
_currSymbol = languageData.currency.symbol; // 526
|
||||
_abbrObj = languageData.abbreviations; // 527
|
||||
_decimalSep = languageData.delimiters.decimal; // 528
|
||||
if (languageData.delimiters.thousands === '.') { // 529
|
||||
_thousandSep = '\\.'; // 530
|
||||
} else { // 531
|
||||
_thousandSep = languageData.delimiters.thousands; // 532
|
||||
} // 533
|
||||
// 534
|
||||
// validating currency symbol // 535
|
||||
temp = val.match(/^[^\d]+/); // 536
|
||||
if (temp !== null) { // 537
|
||||
val = val.substr(1); // 538
|
||||
if (temp[0] !== _currSymbol) { // 539
|
||||
return false; // 540
|
||||
} // 541
|
||||
} // 542
|
||||
// 543
|
||||
//validating abbreviation symbol // 544
|
||||
temp = val.match(/[^\d]+$/); // 545
|
||||
if (temp !== null) { // 546
|
||||
val = val.slice(0, -1); // 547
|
||||
if (temp[0] !== _abbrObj.thousand && temp[0] !== _abbrObj.million && temp[0] !== _abbrObj.billion && temp[0] !== _abbrObj.trillion) {
|
||||
return false; // 549
|
||||
} // 550
|
||||
} // 551
|
||||
// 552
|
||||
_thousandRegEx = new RegExp(_thousandSep + '{2}'); // 553
|
||||
// 554
|
||||
if (!val.match(/[^\d.,]/g)) { // 555
|
||||
_valArray = val.split(_decimalSep); // 556
|
||||
if (_valArray.length > 2) { // 557
|
||||
return false; // 558
|
||||
} else { // 559
|
||||
if (_valArray.length < 2) { // 560
|
||||
return ( !! _valArray[0].match(/^\d+.*\d$/) && !_valArray[0].match(_thousandRegEx)); // 561
|
||||
} else { // 562
|
||||
if (_valArray[0].length === 1) { // 563
|
||||
return ( !! _valArray[0].match(/^\d+$/) && !_valArray[0].match(_thousandRegEx) && !! _valArray[1].match(/^\d+$/));
|
||||
} else { // 565
|
||||
return ( !! _valArray[0].match(/^\d+.*\d$/) && !_valArray[0].match(_thousandRegEx) && !! _valArray[1].match(/^\d+$/));
|
||||
} // 567
|
||||
} // 568
|
||||
} // 569
|
||||
} // 570
|
||||
// 571
|
||||
return false; // 572
|
||||
}; // 573
|
||||
// 574
|
||||
/************************************ // 575
|
||||
Helpers // 576
|
||||
************************************/ // 577
|
||||
// 578
|
||||
function loadLanguage(key, values) { // 579
|
||||
languages[key] = values; // 580
|
||||
} // 581
|
||||
// 582
|
||||
/************************************ // 583
|
||||
Floating-point helpers // 584
|
||||
************************************/ // 585
|
||||
// 586
|
||||
// The floating-point helper functions and implementation // 587
|
||||
// borrows heavily from sinful.js: http://guipn.github.io/sinful.js/ // 588
|
||||
// 589
|
||||
/** // 590
|
||||
* Array.prototype.reduce for browsers that don't support it // 591
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce#Compatibility // 592
|
||||
*/ // 593
|
||||
if ('function' !== typeof Array.prototype.reduce) { // 594
|
||||
Array.prototype.reduce = function(callback, opt_initialValue) { // 595
|
||||
'use strict'; // 596
|
||||
// 597
|
||||
if (null === this || 'undefined' === typeof this) { // 598
|
||||
// At the moment all modern browsers, that support strict mode, have // 599
|
||||
// native implementation of Array.prototype.reduce. For instance, IE8 // 600
|
||||
// does not support strict mode, so this check is actually useless. // 601
|
||||
throw new TypeError('Array.prototype.reduce called on null or undefined'); // 602
|
||||
} // 603
|
||||
// 604
|
||||
if ('function' !== typeof callback) { // 605
|
||||
throw new TypeError(callback + ' is not a function'); // 606
|
||||
} // 607
|
||||
// 608
|
||||
var index, // 609
|
||||
value, // 610
|
||||
length = this.length >>> 0, // 611
|
||||
isValueSet = false; // 612
|
||||
// 613
|
||||
if (1 < arguments.length) { // 614
|
||||
value = opt_initialValue; // 615
|
||||
isValueSet = true; // 616
|
||||
} // 617
|
||||
// 618
|
||||
for (index = 0; length > index; ++index) { // 619
|
||||
if (this.hasOwnProperty(index)) { // 620
|
||||
if (isValueSet) { // 621
|
||||
value = callback(value, this[index], index, this); // 622
|
||||
} else { // 623
|
||||
value = this[index]; // 624
|
||||
isValueSet = true; // 625
|
||||
} // 626
|
||||
} // 627
|
||||
} // 628
|
||||
// 629
|
||||
if (!isValueSet) { // 630
|
||||
throw new TypeError('Reduce of empty array with no initial value'); // 631
|
||||
} // 632
|
||||
// 633
|
||||
return value; // 634
|
||||
}; // 635
|
||||
} // 636
|
||||
// 637
|
||||
// 638
|
||||
/** // 639
|
||||
* Computes the multiplier necessary to make x >= 1, // 640
|
||||
* effectively eliminating miscalculations caused by // 641
|
||||
* finite precision. // 642
|
||||
*/ // 643
|
||||
function multiplier(x) { // 644
|
||||
var parts = x.toString().split('.'); // 645
|
||||
if (parts.length < 2) { // 646
|
||||
return 1; // 647
|
||||
} // 648
|
||||
return Math.pow(10, parts[1].length); // 649
|
||||
} // 650
|
||||
// 651
|
||||
/** // 652
|
||||
* Given a variable number of arguments, returns the maximum // 653
|
||||
* multiplier that must be used to normalize an operation involving // 654
|
||||
* all of them. // 655
|
||||
*/ // 656
|
||||
function correctionFactor() { // 657
|
||||
var args = Array.prototype.slice.call(arguments); // 658
|
||||
return args.reduce(function(prev, next) { // 659
|
||||
var mp = multiplier(prev), // 660
|
||||
mn = multiplier(next); // 661
|
||||
return mp > mn ? mp : mn; // 662
|
||||
}, -Infinity); // 663
|
||||
} // 664
|
||||
// 665
|
||||
// 666
|
||||
/************************************ // 667
|
||||
Numeral Prototype // 668
|
||||
************************************/ // 669
|
||||
// 670
|
||||
// 671
|
||||
numeral.fn = Numeral.prototype = { // 672
|
||||
// 673
|
||||
clone: function() { // 674
|
||||
return numeral(this); // 675
|
||||
}, // 676
|
||||
// 677
|
||||
format: function(inputString, roundingFunction) { // 678
|
||||
return formatNumeral(this, // 679
|
||||
inputString ? inputString : defaultFormat, (roundingFunction !== undefined) ? roundingFunction : Math.round
|
||||
); // 681
|
||||
}, // 682
|
||||
// 683
|
||||
unformat: function(inputString) { // 684
|
||||
if (Object.prototype.toString.call(inputString) === '[object Number]') { // 685
|
||||
return inputString; // 686
|
||||
} // 687
|
||||
return unformatNumeral(this, inputString ? inputString : defaultFormat); // 688
|
||||
}, // 689
|
||||
// 690
|
||||
value: function() { // 691
|
||||
return this._value; // 692
|
||||
}, // 693
|
||||
// 694
|
||||
valueOf: function() { // 695
|
||||
return this._value; // 696
|
||||
}, // 697
|
||||
// 698
|
||||
set: function(value) { // 699
|
||||
this._value = Number(value); // 700
|
||||
return this; // 701
|
||||
}, // 702
|
||||
// 703
|
||||
add: function(value) { // 704
|
||||
var corrFactor = correctionFactor.call(null, this._value, value); // 705
|
||||
// 706
|
||||
function cback(accum, curr, currI, O) { // 707
|
||||
return accum + corrFactor * curr; // 708
|
||||
} // 709
|
||||
this._value = [this._value, value].reduce(cback, 0) / corrFactor; // 710
|
||||
return this; // 711
|
||||
}, // 712
|
||||
// 713
|
||||
subtract: function(value) { // 714
|
||||
var corrFactor = correctionFactor.call(null, this._value, value); // 715
|
||||
// 716
|
||||
function cback(accum, curr, currI, O) { // 717
|
||||
return accum - corrFactor * curr; // 718
|
||||
} // 719
|
||||
this._value = [value].reduce(cback, this._value * corrFactor) / corrFactor; // 720
|
||||
return this; // 721
|
||||
}, // 722
|
||||
// 723
|
||||
multiply: function(value) { // 724
|
||||
function cback(accum, curr, currI, O) { // 725
|
||||
var corrFactor = correctionFactor(accum, curr); // 726
|
||||
return (accum * corrFactor) * (curr * corrFactor) / // 727
|
||||
(corrFactor * corrFactor); // 728
|
||||
} // 729
|
||||
this._value = [this._value, value].reduce(cback, 1); // 730
|
||||
return this; // 731
|
||||
}, // 732
|
||||
// 733
|
||||
divide: function(value) { // 734
|
||||
function cback(accum, curr, currI, O) { // 735
|
||||
var corrFactor = correctionFactor(accum, curr); // 736
|
||||
return (accum * corrFactor) / (curr * corrFactor); // 737
|
||||
} // 738
|
||||
this._value = [this._value, value].reduce(cback); // 739
|
||||
return this; // 740
|
||||
}, // 741
|
||||
// 742
|
||||
difference: function(value) { // 743
|
||||
return Math.abs(numeral(this._value).subtract(value).value()); // 744
|
||||
} // 745
|
||||
// 746
|
||||
}; // 747
|
||||
// 748
|
||||
/************************************ // 749
|
||||
Exposing Numeral // 750
|
||||
************************************/ // 751
|
||||
// 752
|
||||
// CommonJS module is defined // 753
|
||||
if (hasModule) { // 754
|
||||
module.exports = numeral; // 755
|
||||
} // 756
|
||||
// 757
|
||||
/*global ender:false */ // 758
|
||||
if (typeof ender === 'undefined') { // 759
|
||||
// here, `this` means `window` in the browser, or `global` on the server // 760
|
||||
// add `numeral` as a global object via a string identifier, // 761
|
||||
// for Closure Compiler 'advanced' mode // 762
|
||||
this['numeral'] = numeral; // 763
|
||||
} // 764
|
||||
// 765
|
||||
/*global define:false */ // 766
|
||||
if (typeof define === 'function' && define.amd) { // 767
|
||||
define([], function() { // 768
|
||||
return numeral; // 769
|
||||
}); // 770
|
||||
} // 771
|
||||
}).call(this); // 772
|
||||
// 773
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/numeral:numeral/min/languages.min.js //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/*! // 1
|
||||
* numeral.js language configuration // 2
|
||||
* language : belgium-dutch (be-nl) // 3
|
||||
* author : Dieter Luypaert : https://github.com/moeriki // 4
|
||||
*/ // 5
|
||||
!function(){var a={delimiters:{thousands:" ",decimal:","},abbreviations:{thousand:"k",million:" mln",billion:" mld",trillion:" bln"},ordinal:function(a){var b=a%100;return 0!==a&&1>=b||8===b||b>=20?"ste":"de"},currency:{symbol:"€ "}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("be-nl",a)}(),/*!
|
||||
* numeral.js language configuration // 7
|
||||
* language : simplified chinese // 8
|
||||
* author : badplum : https://github.com/badplum // 9
|
||||
*/ // 10
|
||||
function(){var a={delimiters:{thousands:",",decimal:"."},abbreviations:{thousand:"千",million:"百万",billion:"十亿",trillion:"兆"},ordinal:function(){return"."},currency:{symbol:"¥"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("chs",a)}(),/*!
|
||||
* numeral.js language configuration // 12
|
||||
* language : czech (cs) // 13
|
||||
* author : Anatoli Papirovski : https://github.com/apapirovski // 14
|
||||
*/ // 15
|
||||
function(){var a={delimiters:{thousands:" ",decimal:","},abbreviations:{thousand:"tis.",million:"mil.",billion:"b",trillion:"t"},ordinal:function(){return"."},currency:{symbol:"Kč"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("cs",a)}(),/*!
|
||||
* numeral.js language configuration // 17
|
||||
* language : danish denmark (dk) // 18
|
||||
* author : Michael Storgaard : https://github.com/mstorgaard // 19
|
||||
*/ // 20
|
||||
function(){var a={delimiters:{thousands:".",decimal:","},abbreviations:{thousand:"k",million:"mio",billion:"mia",trillion:"b"},ordinal:function(){return"."},currency:{symbol:"DKK"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("da-dk",a)}(),/*!
|
||||
* numeral.js language configuration // 22
|
||||
* language : German in Switzerland (de-ch) // 23
|
||||
* author : Michael Piefel : https://github.com/piefel (based on work from Marco Krage : https://github.com/sinky) // 24
|
||||
*/ // 25
|
||||
function(){var a={delimiters:{thousands:" ",decimal:","},abbreviations:{thousand:"k",million:"m",billion:"b",trillion:"t"},ordinal:function(){return"."},currency:{symbol:"CHF"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("de-ch",a)}(),/*!
|
||||
* numeral.js language configuration // 27
|
||||
* language : German (de) – generally useful in Germany, Austria, Luxembourg, Belgium // 28
|
||||
* author : Marco Krage : https://github.com/sinky // 29
|
||||
*/ // 30
|
||||
function(){var a={delimiters:{thousands:" ",decimal:","},abbreviations:{thousand:"k",million:"m",billion:"b",trillion:"t"},ordinal:function(){return"."},currency:{symbol:"€"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("de",a)}(),/*!
|
||||
* numeral.js language configuration // 32
|
||||
* language : english united kingdom (uk) // 33
|
||||
* author : Dan Ristic : https://github.com/dristic // 34
|
||||
*/ // 35
|
||||
function(){var a={delimiters:{thousands:",",decimal:"."},abbreviations:{thousand:"k",million:"m",billion:"b",trillion:"t"},ordinal:function(a){var b=a%10;return 1===~~(a%100/10)?"th":1===b?"st":2===b?"nd":3===b?"rd":"th"},currency:{symbol:"£"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("en-gb",a)}(),/*!
|
||||
* numeral.js language configuration // 37
|
||||
* language : spanish Spain // 38
|
||||
* author : Hernan Garcia : https://github.com/hgarcia // 39
|
||||
*/ // 40
|
||||
function(){var a={delimiters:{thousands:".",decimal:","},abbreviations:{thousand:"k",million:"mm",billion:"b",trillion:"t"},ordinal:function(a){var b=a%10;return 1===b||3===b?"er":2===b?"do":7===b||0===b?"mo":8===b?"vo":9===b?"no":"to"},currency:{symbol:"€"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("es",a)}(),/*!
|
||||
* numeral.js language configuration // 42
|
||||
* language : spanish // 43
|
||||
* author : Hernan Garcia : https://github.com/hgarcia // 44
|
||||
*/ // 45
|
||||
function(){var a={delimiters:{thousands:".",decimal:","},abbreviations:{thousand:"k",million:"mm",billion:"b",trillion:"t"},ordinal:function(a){var b=a%10;return 1===b||3===b?"er":2===b?"do":7===b||0===b?"mo":8===b?"vo":9===b?"no":"to"},currency:{symbol:"$"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("es",a)}(),/*!
|
||||
* numeral.js language configuration // 47
|
||||
* language : Estonian // 48
|
||||
* author : Illimar Tambek : https://github.com/ragulka // 49
|
||||
* // 50
|
||||
* Note: in Estonian, abbreviations are always separated // 51
|
||||
* from numbers with a space // 52
|
||||
*/ // 53
|
||||
function(){var a={delimiters:{thousands:" ",decimal:","},abbreviations:{thousand:" tuh",million:" mln",billion:" mld",trillion:" trl"},ordinal:function(){return"."},currency:{symbol:"€"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("et",a)}(),/*!
|
||||
* numeral.js language configuration // 55
|
||||
* language : Finnish // 56
|
||||
* author : Sami Saada : https://github.com/samitheberber // 57
|
||||
*/ // 58
|
||||
function(){var a={delimiters:{thousands:" ",decimal:","},abbreviations:{thousand:"k",million:"M",billion:"G",trillion:"T"},ordinal:function(){return"."},currency:{symbol:"€"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("fi",a)}(),/*!
|
||||
* numeral.js language configuration // 60
|
||||
* language : french (Canada) (fr-CA) // 61
|
||||
* author : Léo Renaud-Allaire : https://github.com/renaudleo // 62
|
||||
*/ // 63
|
||||
function(){var a={delimiters:{thousands:" ",decimal:","},abbreviations:{thousand:"k",million:"M",billion:"G",trillion:"T"},ordinal:function(a){return 1===a?"er":"e"},currency:{symbol:"$"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("fr-CA",a)}(),/*!
|
||||
* numeral.js language configuration // 65
|
||||
* language : french (fr-ch) // 66
|
||||
* author : Adam Draper : https://github.com/adamwdraper // 67
|
||||
*/ // 68
|
||||
function(){var a={delimiters:{thousands:"'",decimal:"."},abbreviations:{thousand:"k",million:"m",billion:"b",trillion:"t"},ordinal:function(a){return 1===a?"er":"e"},currency:{symbol:"CHF"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("fr-ch",a)}(),/*!
|
||||
* numeral.js language configuration // 70
|
||||
* language : french (fr) // 71
|
||||
* author : Adam Draper : https://github.com/adamwdraper // 72
|
||||
*/ // 73
|
||||
function(){var a={delimiters:{thousands:" ",decimal:","},abbreviations:{thousand:"k",million:"m",billion:"b",trillion:"t"},ordinal:function(a){return 1===a?"er":"e"},currency:{symbol:"€"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("fr",a)}(),/*!
|
||||
* numeral.js language configuration // 75
|
||||
* language : Hungarian (hu) // 76
|
||||
* author : Peter Bakondy : https://github.com/pbakondy // 77
|
||||
*/ // 78
|
||||
function(){var a={delimiters:{thousands:" ",decimal:","},abbreviations:{thousand:"E",million:"M",billion:"Mrd",trillion:"T"},ordinal:function(){return"."},currency:{symbol:" Ft"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("hu",a)}(),/*!
|
||||
* numeral.js language configuration // 80
|
||||
* language : italian Italy (it) // 81
|
||||
* author : Giacomo Trombi : http://cinquepunti.it // 82
|
||||
*/ // 83
|
||||
function(){var a={delimiters:{thousands:".",decimal:","},abbreviations:{thousand:"mila",million:"mil",billion:"b",trillion:"t"},ordinal:function(){return"º"},currency:{symbol:"€"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("it",a)}(),/*!
|
||||
* numeral.js language configuration // 85
|
||||
* language : japanese // 86
|
||||
* author : teppeis : https://github.com/teppeis // 87
|
||||
*/ // 88
|
||||
function(){var a={delimiters:{thousands:",",decimal:"."},abbreviations:{thousand:"千",million:"百万",billion:"十億",trillion:"兆"},ordinal:function(){return"."},currency:{symbol:"¥"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("ja",a)}(),/*!
|
||||
* numeral.js language configuration // 90
|
||||
* language : Latvian (lv) // 91
|
||||
* author : Lauris Bukšis-Haberkorns : https://github.com/Lafriks // 92
|
||||
*/ // 93
|
||||
function(){var a={delimiters:{thousands:" ",decimal:","},abbreviations:{thousand:" tūkst.",million:" milj.",billion:" mljrd.",trillion:" trilj."},ordinal:function(){return"."},currency:{symbol:"€"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("lv",a)}(),/*!
|
||||
* numeral.js language configuration // 95
|
||||
* language : netherlands-dutch (nl-nl) // 96
|
||||
* author : Dave Clayton : https://github.com/davedx // 97
|
||||
*/ // 98
|
||||
function(){var a={delimiters:{thousands:".",decimal:","},abbreviations:{thousand:"k",million:"mln",billion:"mrd",trillion:"bln"},ordinal:function(a){var b=a%100;return 0!==a&&1>=b||8===b||b>=20?"ste":"de"},currency:{symbol:"€ "}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("nl-nl",a)}(),/*!
|
||||
* numeral.js language configuration // 100
|
||||
* language : polish (pl) // 101
|
||||
* author : Dominik Bulaj : https://github.com/dominikbulaj // 102
|
||||
*/ // 103
|
||||
function(){var a={delimiters:{thousands:" ",decimal:","},abbreviations:{thousand:"tys.",million:"mln",billion:"mld",trillion:"bln"},ordinal:function(){return"."},currency:{symbol:"PLN"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("pl",a)}(),/*!
|
||||
* numeral.js language configuration // 105
|
||||
* language : portuguese brazil (pt-br) // 106
|
||||
* author : Ramiro Varandas Jr : https://github.com/ramirovjr // 107
|
||||
*/ // 108
|
||||
function(){var a={delimiters:{thousands:".",decimal:","},abbreviations:{thousand:"mil",million:"milhões",billion:"b",trillion:"t"},ordinal:function(){return"º"},currency:{symbol:"R$"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("pt-br",a)}(),/*!
|
||||
* numeral.js language configuration // 110
|
||||
* language : portuguese (pt-pt) // 111
|
||||
* author : Diogo Resende : https://github.com/dresende // 112
|
||||
*/ // 113
|
||||
function(){var a={delimiters:{thousands:" ",decimal:","},abbreviations:{thousand:"k",million:"m",billion:"b",trillion:"t"},ordinal:function(){return"º"},currency:{symbol:"€"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("pt-pt",a)}(),function(){var a={delimiters:{thousands:" ",decimal:","},abbreviations:{thousand:"тыс.",million:"млн",billion:"b",trillion:"t"},ordinal:function(){return"."},currency:{symbol:"₴"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("ru-UA",a)}(),/*!
|
||||
* numeral.js language configuration // 115
|
||||
* language : russian (ru) // 116
|
||||
* author : Anatoli Papirovski : https://github.com/apapirovski // 117
|
||||
*/ // 118
|
||||
function(){var a={delimiters:{thousands:" ",decimal:","},abbreviations:{thousand:"тыс.",million:"млн",billion:"b",trillion:"t"},ordinal:function(){return"."},currency:{symbol:"руб."}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("ru",a)}(),/*!
|
||||
* numeral.js language configuration // 120
|
||||
* language : slovak (sk) // 121
|
||||
* author : Ahmed Al Hafoudh : http://www.freevision.sk // 122
|
||||
*/ // 123
|
||||
function(){var a={delimiters:{thousands:" ",decimal:","},abbreviations:{thousand:"tis.",million:"mil.",billion:"b",trillion:"t"},ordinal:function(){return"."},currency:{symbol:"€"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("sk",a)}(),/*!
|
||||
* numeral.js language configuration // 125
|
||||
* language : thai (th) // 126
|
||||
* author : Sathit Jittanupat : https://github.com/jojosati // 127
|
||||
*/ // 128
|
||||
function(){var a={delimiters:{thousands:",",decimal:"."},abbreviations:{thousand:"พัน",million:"ล้าน",billion:"พันล้าน",trillion:"ล้านล้าน"},ordinal:function(){return"."},currency:{symbol:"฿"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("th",a)}(),/*!
|
||||
* numeral.js language configuration // 130
|
||||
* language : turkish (tr) // 131
|
||||
* author : Ecmel Ercan : https://github.com/ecmel, Erhan Gundogan : https://github.com/erhangundogan, Burak Yiğit Kaya: https://github.com/BYK
|
||||
*/ // 133
|
||||
function(){var a={1:"'inci",5:"'inci",8:"'inci",70:"'inci",80:"'inci",2:"'nci",7:"'nci",20:"'nci",50:"'nci",3:"'üncü",4:"'üncü",100:"'üncü",6:"'ncı",9:"'uncu",10:"'uncu",30:"'uncu",60:"'ıncı",90:"'ıncı"},b={delimiters:{thousands:".",decimal:","},abbreviations:{thousand:"bin",million:"milyon",billion:"milyar",trillion:"trilyon"},ordinal:function(b){if(0===b)return"'ıncı";var c=b%10,d=b%100-c,e=b>=100?100:null;return a[c]||a[d]||a[e]},currency:{symbol:"₺"}};"undefined"!=typeof module&&module.exports&&(module.exports=b),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("tr",b)}(),function(){var a={delimiters:{thousands:" ",decimal:","},abbreviations:{thousand:"тис.",million:"млн",billion:"млрд",trillion:"блн"},ordinal:function(){return""},currency:{symbol:"₴"}};"undefined"!=typeof module&&module.exports&&(module.exports=a),"undefined"!=typeof window&&this.numeral&&this.numeral.language&&this.numeral.language("uk-UA",a)}();
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/numeral:numeral/meteor/export.js //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
if ( Meteor.isClient ) { // 1
|
||||
numeral = window.numeral; // 2
|
||||
delete window.numeral; // 3
|
||||
} // 4
|
||||
// 5
|
||||
if ( Meteor.isServer ) { // 6
|
||||
numeral = Npm.require('numeral'); // 7
|
||||
} // 8
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package['numeral:numeral'] = {
|
||||
numeral: numeral
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,399 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
var Tracker = Package.tracker.Tracker;
|
||||
var Deps = Package.tracker.Deps;
|
||||
var LocalCollection = Package.minimongo.LocalCollection;
|
||||
var Minimongo = Package.minimongo.Minimongo;
|
||||
var _ = Package.underscore._;
|
||||
var Random = Package.random.Random;
|
||||
|
||||
/* Package-scope variables */
|
||||
var ObserveSequence, seqChangedToEmpty, seqChangedToArray, seqChangedToCursor;
|
||||
|
||||
(function () {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/observe-sequence/observe_sequence.js //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
var warn = function () { // 1
|
||||
if (ObserveSequence._suppressWarnings) { // 2
|
||||
ObserveSequence._suppressWarnings--; // 3
|
||||
} else { // 4
|
||||
if (typeof console !== 'undefined' && console.warn) // 5
|
||||
console.warn.apply(console, arguments); // 6
|
||||
// 7
|
||||
ObserveSequence._loggedWarnings++; // 8
|
||||
} // 9
|
||||
}; // 10
|
||||
// 11
|
||||
var idStringify = LocalCollection._idStringify; // 12
|
||||
var idParse = LocalCollection._idParse; // 13
|
||||
// 14
|
||||
ObserveSequence = { // 15
|
||||
_suppressWarnings: 0, // 16
|
||||
_loggedWarnings: 0, // 17
|
||||
// 18
|
||||
// A mechanism similar to cursor.observe which receives a reactive // 19
|
||||
// function returning a sequence type and firing appropriate callbacks // 20
|
||||
// when the value changes. // 21
|
||||
// // 22
|
||||
// @param sequenceFunc {Function} a reactive function returning a // 23
|
||||
// sequence type. The currently supported sequence types are: // 24
|
||||
// 'null', arrays and cursors. // 25
|
||||
// // 26
|
||||
// @param callbacks {Object} similar to a specific subset of // 27
|
||||
// callbacks passed to `cursor.observe` // 28
|
||||
// (http://docs.meteor.com/#observe), with minor variations to // 29
|
||||
// support the fact that not all sequences contain objects with // 30
|
||||
// _id fields. Specifically: // 31
|
||||
// // 32
|
||||
// * addedAt(id, item, atIndex, beforeId) // 33
|
||||
// * changedAt(id, newItem, oldItem, atIndex) // 34
|
||||
// * removedAt(id, oldItem, atIndex) // 35
|
||||
// * movedTo(id, item, fromIndex, toIndex, beforeId) // 36
|
||||
// // 37
|
||||
// @returns {Object(stop: Function)} call 'stop' on the return value // 38
|
||||
// to stop observing this sequence function. // 39
|
||||
// // 40
|
||||
// We don't make any assumptions about our ability to compare sequence // 41
|
||||
// elements (ie, we don't assume EJSON.equals works; maybe there is extra // 42
|
||||
// state/random methods on the objects) so unlike cursor.observe, we may // 43
|
||||
// sometimes call changedAt() when nothing actually changed. // 44
|
||||
// XXX consider if we *can* make the stronger assumption and avoid // 45
|
||||
// no-op changedAt calls (in some cases?) // 46
|
||||
// // 47
|
||||
// XXX currently only supports the callbacks used by our // 48
|
||||
// implementation of {{#each}}, but this can be expanded. // 49
|
||||
// // 50
|
||||
// XXX #each doesn't use the indices (though we'll eventually need // 51
|
||||
// a way to get them when we support `@index`), but calling // 52
|
||||
// `cursor.observe` causes the index to be calculated on every // 53
|
||||
// callback using a linear scan (unless you turn it off by passing // 54
|
||||
// `_no_indices`). Any way to avoid calculating indices on a pure // 55
|
||||
// cursor observe like we used to? // 56
|
||||
observe: function (sequenceFunc, callbacks) { // 57
|
||||
var lastSeq = null; // 58
|
||||
var activeObserveHandle = null; // 59
|
||||
// 60
|
||||
// 'lastSeqArray' contains the previous value of the sequence // 61
|
||||
// we're observing. It is an array of objects with '_id' and // 62
|
||||
// 'item' fields. 'item' is the element in the array, or the // 63
|
||||
// document in the cursor. // 64
|
||||
// // 65
|
||||
// '_id' is whichever of the following is relevant, unless it has // 66
|
||||
// already appeared -- in which case it's randomly generated. // 67
|
||||
// // 68
|
||||
// * if 'item' is an object: // 69
|
||||
// * an '_id' field, if present // 70
|
||||
// * otherwise, the index in the array // 71
|
||||
// // 72
|
||||
// * if 'item' is a number or string, use that value // 73
|
||||
// // 74
|
||||
// XXX this can be generalized by allowing {{#each}} to accept a // 75
|
||||
// general 'key' argument which could be a function, a dotted // 76
|
||||
// field name, or the special @index value. // 77
|
||||
var lastSeqArray = []; // elements are objects of form {_id, item} // 78
|
||||
var computation = Tracker.autorun(function () { // 79
|
||||
var seq = sequenceFunc(); // 80
|
||||
// 81
|
||||
Tracker.nonreactive(function () { // 82
|
||||
var seqArray; // same structure as `lastSeqArray` above. // 83
|
||||
// 84
|
||||
if (activeObserveHandle) { // 85
|
||||
// If we were previously observing a cursor, replace lastSeqArray with // 86
|
||||
// more up-to-date information. Then stop the old observe. // 87
|
||||
lastSeqArray = _.map(lastSeq.fetch(), function (doc) { // 88
|
||||
return {_id: doc._id, item: doc}; // 89
|
||||
}); // 90
|
||||
activeObserveHandle.stop(); // 91
|
||||
activeObserveHandle = null; // 92
|
||||
} // 93
|
||||
// 94
|
||||
if (!seq) { // 95
|
||||
seqArray = seqChangedToEmpty(lastSeqArray, callbacks); // 96
|
||||
} else if (seq instanceof Array) { // 97
|
||||
seqArray = seqChangedToArray(lastSeqArray, seq, callbacks); // 98
|
||||
} else if (isStoreCursor(seq)) { // 99
|
||||
var result /* [seqArray, activeObserveHandle] */ = // 100
|
||||
seqChangedToCursor(lastSeqArray, seq, callbacks); // 101
|
||||
seqArray = result[0]; // 102
|
||||
activeObserveHandle = result[1]; // 103
|
||||
} else { // 104
|
||||
throw badSequenceError(); // 105
|
||||
} // 106
|
||||
// 107
|
||||
diffArray(lastSeqArray, seqArray, callbacks); // 108
|
||||
lastSeq = seq; // 109
|
||||
lastSeqArray = seqArray; // 110
|
||||
}); // 111
|
||||
}); // 112
|
||||
// 113
|
||||
return { // 114
|
||||
stop: function () { // 115
|
||||
computation.stop(); // 116
|
||||
if (activeObserveHandle) // 117
|
||||
activeObserveHandle.stop(); // 118
|
||||
} // 119
|
||||
}; // 120
|
||||
}, // 121
|
||||
// 122
|
||||
// Fetch the items of `seq` into an array, where `seq` is of one of the // 123
|
||||
// sequence types accepted by `observe`. If `seq` is a cursor, a // 124
|
||||
// dependency is established. // 125
|
||||
fetch: function (seq) { // 126
|
||||
if (!seq) { // 127
|
||||
return []; // 128
|
||||
} else if (seq instanceof Array) { // 129
|
||||
return seq; // 130
|
||||
} else if (isStoreCursor(seq)) { // 131
|
||||
return seq.fetch(); // 132
|
||||
} else { // 133
|
||||
throw badSequenceError(); // 134
|
||||
} // 135
|
||||
} // 136
|
||||
}; // 137
|
||||
// 138
|
||||
var badSequenceError = function () { // 139
|
||||
return new Error("{{#each}} currently only accepts " + // 140
|
||||
"arrays, cursors or falsey values."); // 141
|
||||
}; // 142
|
||||
// 143
|
||||
var isStoreCursor = function (cursor) { // 144
|
||||
return cursor && _.isObject(cursor) && // 145
|
||||
_.isFunction(cursor.observe) && _.isFunction(cursor.fetch); // 146
|
||||
}; // 147
|
||||
// 148
|
||||
// Calculates the differences between `lastSeqArray` and // 149
|
||||
// `seqArray` and calls appropriate functions from `callbacks`. // 150
|
||||
// Reuses Minimongo's diff algorithm implementation. // 151
|
||||
var diffArray = function (lastSeqArray, seqArray, callbacks) { // 152
|
||||
var diffFn = Package.minimongo.LocalCollection._diffQueryOrderedChanges; // 153
|
||||
var oldIdObjects = []; // 154
|
||||
var newIdObjects = []; // 155
|
||||
var posOld = {}; // maps from idStringify'd ids // 156
|
||||
var posNew = {}; // ditto // 157
|
||||
var posCur = {}; // 158
|
||||
var lengthCur = lastSeqArray.length; // 159
|
||||
// 160
|
||||
_.each(seqArray, function (doc, i) { // 161
|
||||
newIdObjects.push({_id: doc._id}); // 162
|
||||
posNew[idStringify(doc._id)] = i; // 163
|
||||
}); // 164
|
||||
_.each(lastSeqArray, function (doc, i) { // 165
|
||||
oldIdObjects.push({_id: doc._id}); // 166
|
||||
posOld[idStringify(doc._id)] = i; // 167
|
||||
posCur[idStringify(doc._id)] = i; // 168
|
||||
}); // 169
|
||||
// 170
|
||||
// Arrays can contain arbitrary objects. We don't diff the // 171
|
||||
// objects. Instead we always fire 'changedAt' callback on every // 172
|
||||
// object. The consumer of `observe-sequence` should deal with // 173
|
||||
// it appropriately. // 174
|
||||
diffFn(oldIdObjects, newIdObjects, { // 175
|
||||
addedBefore: function (id, doc, before) { // 176
|
||||
var position = before ? posCur[idStringify(before)] : lengthCur; // 177
|
||||
// 178
|
||||
if (before) { // 179
|
||||
// If not adding at the end, we need to update indexes. // 180
|
||||
// XXX this can still be improved greatly! // 181
|
||||
_.each(posCur, function (pos, id) { // 182
|
||||
if (pos >= position) // 183
|
||||
posCur[id]++; // 184
|
||||
}); // 185
|
||||
} // 186
|
||||
// 187
|
||||
lengthCur++; // 188
|
||||
posCur[idStringify(id)] = position; // 189
|
||||
// 190
|
||||
callbacks.addedAt( // 191
|
||||
id, // 192
|
||||
seqArray[posNew[idStringify(id)]].item, // 193
|
||||
position, // 194
|
||||
before); // 195
|
||||
}, // 196
|
||||
movedBefore: function (id, before) { // 197
|
||||
if (id === before) // 198
|
||||
return; // 199
|
||||
// 200
|
||||
var oldPosition = posCur[idStringify(id)]; // 201
|
||||
var newPosition = before ? posCur[idStringify(before)] : lengthCur; // 202
|
||||
// 203
|
||||
// Moving the item forward. The new element is losing one position as it // 204
|
||||
// was removed from the old position before being inserted at the new // 205
|
||||
// position. // 206
|
||||
// Ex.: 0 *1* 2 3 4 // 207
|
||||
// 0 2 3 *1* 4 // 208
|
||||
// The original issued callback is "1" before "4". // 209
|
||||
// The position of "1" is 1, the position of "4" is 4. // 210
|
||||
// The generated move is (1) -> (3) // 211
|
||||
if (newPosition > oldPosition) { // 212
|
||||
newPosition--; // 213
|
||||
} // 214
|
||||
// 215
|
||||
// Fix up the positions of elements between the old and the new positions // 216
|
||||
// of the moved element. // 217
|
||||
// // 218
|
||||
// There are two cases: // 219
|
||||
// 1. The element is moved forward. Then all the positions in between // 220
|
||||
// are moved back. // 221
|
||||
// 2. The element is moved back. Then the positions in between *and* the // 222
|
||||
// element that is currently standing on the moved element's future // 223
|
||||
// position are moved forward. // 224
|
||||
_.each(posCur, function (elCurPosition, id) { // 225
|
||||
if (oldPosition < elCurPosition && elCurPosition < newPosition) // 226
|
||||
posCur[id]--; // 227
|
||||
else if (newPosition <= elCurPosition && elCurPosition < oldPosition) // 228
|
||||
posCur[id]++; // 229
|
||||
}); // 230
|
||||
// 231
|
||||
// Finally, update the position of the moved element. // 232
|
||||
posCur[idStringify(id)] = newPosition; // 233
|
||||
// 234
|
||||
callbacks.movedTo( // 235
|
||||
id, // 236
|
||||
seqArray[posNew[idStringify(id)]].item, // 237
|
||||
oldPosition, // 238
|
||||
newPosition, // 239
|
||||
before); // 240
|
||||
}, // 241
|
||||
removed: function (id) { // 242
|
||||
var prevPosition = posCur[idStringify(id)]; // 243
|
||||
// 244
|
||||
_.each(posCur, function (pos, id) { // 245
|
||||
if (pos >= prevPosition) // 246
|
||||
posCur[id]--; // 247
|
||||
}); // 248
|
||||
// 249
|
||||
delete posCur[idStringify(id)]; // 250
|
||||
lengthCur--; // 251
|
||||
// 252
|
||||
callbacks.removedAt( // 253
|
||||
id, // 254
|
||||
lastSeqArray[posOld[idStringify(id)]].item, // 255
|
||||
prevPosition); // 256
|
||||
} // 257
|
||||
}); // 258
|
||||
// 259
|
||||
_.each(posNew, function (pos, idString) { // 260
|
||||
var id = idParse(idString); // 261
|
||||
if (_.has(posOld, idString)) { // 262
|
||||
// specifically for primitive types, compare equality before // 263
|
||||
// firing the 'changedAt' callback. otherwise, always fire it // 264
|
||||
// because doing a deep EJSON comparison is not guaranteed to // 265
|
||||
// work (an array can contain arbitrary objects, and 'transform' // 266
|
||||
// can be used on cursors). also, deep diffing is not // 267
|
||||
// necessarily the most efficient (if only a specific subfield // 268
|
||||
// of the object is later accessed). // 269
|
||||
var newItem = seqArray[pos].item; // 270
|
||||
var oldItem = lastSeqArray[posOld[idString]].item; // 271
|
||||
// 272
|
||||
if (typeof newItem === 'object' || newItem !== oldItem) // 273
|
||||
callbacks.changedAt(id, newItem, oldItem, pos); // 274
|
||||
} // 275
|
||||
}); // 276
|
||||
}; // 277
|
||||
// 278
|
||||
seqChangedToEmpty = function (lastSeqArray, callbacks) { // 279
|
||||
return []; // 280
|
||||
}; // 281
|
||||
// 282
|
||||
seqChangedToArray = function (lastSeqArray, array, callbacks) { // 283
|
||||
var idsUsed = {}; // 284
|
||||
var seqArray = _.map(array, function (item, index) { // 285
|
||||
var id; // 286
|
||||
if (typeof item === 'string') { // 287
|
||||
// ensure not empty, since other layers (eg DomRange) assume this as well // 288
|
||||
id = "-" + item; // 289
|
||||
} else if (typeof item === 'number' || // 290
|
||||
typeof item === 'boolean' || // 291
|
||||
item === undefined) { // 292
|
||||
id = item; // 293
|
||||
} else if (typeof item === 'object') { // 294
|
||||
id = (item && item._id) || index; // 295
|
||||
} else { // 296
|
||||
throw new Error("{{#each}} doesn't support arrays with " + // 297
|
||||
"elements of type " + typeof item); // 298
|
||||
} // 299
|
||||
// 300
|
||||
var idString = idStringify(id); // 301
|
||||
if (idsUsed[idString]) { // 302
|
||||
if (typeof item === 'object' && '_id' in item) // 303
|
||||
warn("duplicate id " + id + " in", array); // 304
|
||||
id = Random.id(); // 305
|
||||
} else { // 306
|
||||
idsUsed[idString] = true; // 307
|
||||
} // 308
|
||||
// 309
|
||||
return { _id: id, item: item }; // 310
|
||||
}); // 311
|
||||
// 312
|
||||
return seqArray; // 313
|
||||
}; // 314
|
||||
// 315
|
||||
seqChangedToCursor = function (lastSeqArray, cursor, callbacks) { // 316
|
||||
var initial = true; // are we observing initial data from cursor? // 317
|
||||
var seqArray = []; // 318
|
||||
// 319
|
||||
var observeHandle = cursor.observe({ // 320
|
||||
addedAt: function (document, atIndex, before) { // 321
|
||||
if (initial) { // 322
|
||||
// keep track of initial data so that we can diff once // 323
|
||||
// we exit `observe`. // 324
|
||||
if (before !== null) // 325
|
||||
throw new Error("Expected initial data from observe in order"); // 326
|
||||
seqArray.push({ _id: document._id, item: document }); // 327
|
||||
} else { // 328
|
||||
callbacks.addedAt(document._id, document, atIndex, before); // 329
|
||||
} // 330
|
||||
}, // 331
|
||||
changedAt: function (newDocument, oldDocument, atIndex) { // 332
|
||||
callbacks.changedAt(newDocument._id, newDocument, oldDocument, // 333
|
||||
atIndex); // 334
|
||||
}, // 335
|
||||
removedAt: function (oldDocument, atIndex) { // 336
|
||||
callbacks.removedAt(oldDocument._id, oldDocument, atIndex); // 337
|
||||
}, // 338
|
||||
movedTo: function (document, fromIndex, toIndex, before) { // 339
|
||||
callbacks.movedTo( // 340
|
||||
document._id, document, fromIndex, toIndex, before); // 341
|
||||
} // 342
|
||||
}); // 343
|
||||
initial = false; // 344
|
||||
// 345
|
||||
return [seqArray, observeHandle]; // 346
|
||||
}; // 347
|
||||
// 348
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package['observe-sequence'] = {
|
||||
ObserveSequence: ObserveSequence
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,256 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
var _ = Package.underscore._;
|
||||
|
||||
/* Package-scope variables */
|
||||
var OrderedDict;
|
||||
|
||||
(function () {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/ordered-dict/ordered_dict.js //
|
||||
// //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// This file defines an ordered dictionary abstraction that is useful for // 1
|
||||
// maintaining a dataset backed by observeChanges. It supports ordering items // 2
|
||||
// by specifying the item they now come before. // 3
|
||||
// 4
|
||||
// The implementation is a dictionary that contains nodes of a doubly-linked // 5
|
||||
// list as its values. // 6
|
||||
// 7
|
||||
// constructs a new element struct // 8
|
||||
// next and prev are whole elements, not keys. // 9
|
||||
var element = function (key, value, next, prev) { // 10
|
||||
return { // 11
|
||||
key: key, // 12
|
||||
value: value, // 13
|
||||
next: next, // 14
|
||||
prev: prev // 15
|
||||
}; // 16
|
||||
}; // 17
|
||||
OrderedDict = function (/* ... */) { // 18
|
||||
var self = this; // 19
|
||||
self._dict = {}; // 20
|
||||
self._first = null; // 21
|
||||
self._last = null; // 22
|
||||
self._size = 0; // 23
|
||||
var args = _.toArray(arguments); // 24
|
||||
self._stringify = function (x) { return x; }; // 25
|
||||
if (typeof args[0] === 'function') // 26
|
||||
self._stringify = args.shift(); // 27
|
||||
_.each(args, function (kv) { // 28
|
||||
self.putBefore(kv[0], kv[1], null); // 29
|
||||
}); // 30
|
||||
}; // 31
|
||||
// 32
|
||||
_.extend(OrderedDict.prototype, { // 33
|
||||
// the "prefix keys with a space" thing comes from here // 34
|
||||
// https://github.com/documentcloud/underscore/issues/376#issuecomment-2815649 // 35
|
||||
_k: function (key) { return " " + this._stringify(key); }, // 36
|
||||
// 37
|
||||
empty: function () { // 38
|
||||
var self = this; // 39
|
||||
return !self._first; // 40
|
||||
}, // 41
|
||||
size: function () { // 42
|
||||
var self = this; // 43
|
||||
return self._size; // 44
|
||||
}, // 45
|
||||
_linkEltIn: function (elt) { // 46
|
||||
var self = this; // 47
|
||||
if (!elt.next) { // 48
|
||||
elt.prev = self._last; // 49
|
||||
if (self._last) // 50
|
||||
self._last.next = elt; // 51
|
||||
self._last = elt; // 52
|
||||
} else { // 53
|
||||
elt.prev = elt.next.prev; // 54
|
||||
elt.next.prev = elt; // 55
|
||||
if (elt.prev) // 56
|
||||
elt.prev.next = elt; // 57
|
||||
} // 58
|
||||
if (self._first === null || self._first === elt.next) // 59
|
||||
self._first = elt; // 60
|
||||
}, // 61
|
||||
_linkEltOut: function (elt) { // 62
|
||||
var self = this; // 63
|
||||
if (elt.next) // 64
|
||||
elt.next.prev = elt.prev; // 65
|
||||
if (elt.prev) // 66
|
||||
elt.prev.next = elt.next; // 67
|
||||
if (elt === self._last) // 68
|
||||
self._last = elt.prev; // 69
|
||||
if (elt === self._first) // 70
|
||||
self._first = elt.next; // 71
|
||||
}, // 72
|
||||
putBefore: function (key, item, before) { // 73
|
||||
var self = this; // 74
|
||||
if (self._dict[self._k(key)]) // 75
|
||||
throw new Error("Item " + key + " already present in OrderedDict"); // 76
|
||||
var elt = before ? // 77
|
||||
element(key, item, self._dict[self._k(before)]) : // 78
|
||||
element(key, item, null); // 79
|
||||
if (elt.next === undefined) // 80
|
||||
throw new Error("could not find item to put this one before"); // 81
|
||||
self._linkEltIn(elt); // 82
|
||||
self._dict[self._k(key)] = elt; // 83
|
||||
self._size++; // 84
|
||||
}, // 85
|
||||
append: function (key, item) { // 86
|
||||
var self = this; // 87
|
||||
self.putBefore(key, item, null); // 88
|
||||
}, // 89
|
||||
remove: function (key) { // 90
|
||||
var self = this; // 91
|
||||
var elt = self._dict[self._k(key)]; // 92
|
||||
if (elt === undefined) // 93
|
||||
throw new Error("Item " + key + " not present in OrderedDict"); // 94
|
||||
self._linkEltOut(elt); // 95
|
||||
self._size--; // 96
|
||||
delete self._dict[self._k(key)]; // 97
|
||||
return elt.value; // 98
|
||||
}, // 99
|
||||
get: function (key) { // 100
|
||||
var self = this; // 101
|
||||
if (self.has(key)) // 102
|
||||
return self._dict[self._k(key)].value; // 103
|
||||
return undefined; // 104
|
||||
}, // 105
|
||||
has: function (key) { // 106
|
||||
var self = this; // 107
|
||||
return _.has(self._dict, self._k(key)); // 108
|
||||
}, // 109
|
||||
// Iterate through the items in this dictionary in order, calling // 110
|
||||
// iter(value, key, index) on each one. // 111
|
||||
// 112
|
||||
// Stops whenever iter returns OrderedDict.BREAK, or after the last element. // 113
|
||||
forEach: function (iter) { // 114
|
||||
var self = this; // 115
|
||||
var i = 0; // 116
|
||||
var elt = self._first; // 117
|
||||
while (elt !== null) { // 118
|
||||
var b = iter(elt.value, elt.key, i); // 119
|
||||
if (b === OrderedDict.BREAK) // 120
|
||||
return; // 121
|
||||
elt = elt.next; // 122
|
||||
i++; // 123
|
||||
} // 124
|
||||
}, // 125
|
||||
first: function () { // 126
|
||||
var self = this; // 127
|
||||
if (self.empty()) // 128
|
||||
return undefined; // 129
|
||||
return self._first.key; // 130
|
||||
}, // 131
|
||||
firstValue: function () { // 132
|
||||
var self = this; // 133
|
||||
if (self.empty()) // 134
|
||||
return undefined; // 135
|
||||
return self._first.value; // 136
|
||||
}, // 137
|
||||
last: function () { // 138
|
||||
var self = this; // 139
|
||||
if (self.empty()) // 140
|
||||
return undefined; // 141
|
||||
return self._last.key; // 142
|
||||
}, // 143
|
||||
lastValue: function () { // 144
|
||||
var self = this; // 145
|
||||
if (self.empty()) // 146
|
||||
return undefined; // 147
|
||||
return self._last.value; // 148
|
||||
}, // 149
|
||||
prev: function (key) { // 150
|
||||
var self = this; // 151
|
||||
if (self.has(key)) { // 152
|
||||
var elt = self._dict[self._k(key)]; // 153
|
||||
if (elt.prev) // 154
|
||||
return elt.prev.key; // 155
|
||||
} // 156
|
||||
return null; // 157
|
||||
}, // 158
|
||||
next: function (key) { // 159
|
||||
var self = this; // 160
|
||||
if (self.has(key)) { // 161
|
||||
var elt = self._dict[self._k(key)]; // 162
|
||||
if (elt.next) // 163
|
||||
return elt.next.key; // 164
|
||||
} // 165
|
||||
return null; // 166
|
||||
}, // 167
|
||||
moveBefore: function (key, before) { // 168
|
||||
var self = this; // 169
|
||||
var elt = self._dict[self._k(key)]; // 170
|
||||
var eltBefore = before ? self._dict[self._k(before)] : null; // 171
|
||||
if (elt === undefined) // 172
|
||||
throw new Error("Item to move is not present"); // 173
|
||||
if (eltBefore === undefined) { // 174
|
||||
throw new Error("Could not find element to move this one before"); // 175
|
||||
} // 176
|
||||
if (eltBefore === elt.next) // no moving necessary // 177
|
||||
return; // 178
|
||||
// remove from its old place // 179
|
||||
self._linkEltOut(elt); // 180
|
||||
// patch into its new place // 181
|
||||
elt.next = eltBefore; // 182
|
||||
self._linkEltIn(elt); // 183
|
||||
}, // 184
|
||||
// Linear, sadly. // 185
|
||||
indexOf: function (key) { // 186
|
||||
var self = this; // 187
|
||||
var ret = null; // 188
|
||||
self.forEach(function (v, k, i) { // 189
|
||||
if (self._k(k) === self._k(key)) { // 190
|
||||
ret = i; // 191
|
||||
return OrderedDict.BREAK; // 192
|
||||
} // 193
|
||||
return undefined; // 194
|
||||
}); // 195
|
||||
return ret; // 196
|
||||
}, // 197
|
||||
_checkRep: function () { // 198
|
||||
var self = this; // 199
|
||||
_.each(self._dict, function (k, v) { // 200
|
||||
if (v.next === v) // 201
|
||||
throw new Error("Next is a loop"); // 202
|
||||
if (v.prev === v) // 203
|
||||
throw new Error("Prev is a loop"); // 204
|
||||
}); // 205
|
||||
} // 206
|
||||
// 207
|
||||
}); // 208
|
||||
OrderedDict.BREAK = {"break": true}; // 209
|
||||
// 210
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package['ordered-dict'] = {
|
||||
OrderedDict: OrderedDict
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,300 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
var _ = Package.underscore._;
|
||||
|
||||
/* Package-scope variables */
|
||||
var Random;
|
||||
|
||||
(function () {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/random/random.js //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// We use cryptographically strong PRNGs (crypto.getRandomBytes() on the server, // 1
|
||||
// window.crypto.getRandomValues() in the browser) when available. If these // 2
|
||||
// PRNGs fail, we fall back to the Alea PRNG, which is not cryptographically // 3
|
||||
// strong, and we seed it with various sources such as the date, Math.random, // 4
|
||||
// and window size on the client. When using crypto.getRandomValues(), our // 5
|
||||
// primitive is hexString(), from which we construct fraction(). When using // 6
|
||||
// window.crypto.getRandomValues() or alea, the primitive is fraction and we use // 7
|
||||
// that to construct hex string. // 8
|
||||
// 9
|
||||
if (Meteor.isServer) // 10
|
||||
var nodeCrypto = Npm.require('crypto'); // 11
|
||||
// 12
|
||||
// see http://baagoe.org/en/wiki/Better_random_numbers_for_javascript // 13
|
||||
// for a full discussion and Alea implementation. // 14
|
||||
var Alea = function () { // 15
|
||||
function Mash() { // 16
|
||||
var n = 0xefc8249d; // 17
|
||||
// 18
|
||||
var mash = function(data) { // 19
|
||||
data = data.toString(); // 20
|
||||
for (var i = 0; i < data.length; i++) { // 21
|
||||
n += data.charCodeAt(i); // 22
|
||||
var h = 0.02519603282416938 * n; // 23
|
||||
n = h >>> 0; // 24
|
||||
h -= n; // 25
|
||||
h *= n; // 26
|
||||
n = h >>> 0; // 27
|
||||
h -= n; // 28
|
||||
n += h * 0x100000000; // 2^32 // 29
|
||||
} // 30
|
||||
return (n >>> 0) * 2.3283064365386963e-10; // 2^-32 // 31
|
||||
}; // 32
|
||||
// 33
|
||||
mash.version = 'Mash 0.9'; // 34
|
||||
return mash; // 35
|
||||
} // 36
|
||||
// 37
|
||||
return (function (args) { // 38
|
||||
var s0 = 0; // 39
|
||||
var s1 = 0; // 40
|
||||
var s2 = 0; // 41
|
||||
var c = 1; // 42
|
||||
// 43
|
||||
if (args.length == 0) { // 44
|
||||
args = [+new Date]; // 45
|
||||
} // 46
|
||||
var mash = Mash(); // 47
|
||||
s0 = mash(' '); // 48
|
||||
s1 = mash(' '); // 49
|
||||
s2 = mash(' '); // 50
|
||||
// 51
|
||||
for (var i = 0; i < args.length; i++) { // 52
|
||||
s0 -= mash(args[i]); // 53
|
||||
if (s0 < 0) { // 54
|
||||
s0 += 1; // 55
|
||||
} // 56
|
||||
s1 -= mash(args[i]); // 57
|
||||
if (s1 < 0) { // 58
|
||||
s1 += 1; // 59
|
||||
} // 60
|
||||
s2 -= mash(args[i]); // 61
|
||||
if (s2 < 0) { // 62
|
||||
s2 += 1; // 63
|
||||
} // 64
|
||||
} // 65
|
||||
mash = null; // 66
|
||||
// 67
|
||||
var random = function() { // 68
|
||||
var t = 2091639 * s0 + c * 2.3283064365386963e-10; // 2^-32 // 69
|
||||
s0 = s1; // 70
|
||||
s1 = s2; // 71
|
||||
return s2 = t - (c = t | 0); // 72
|
||||
}; // 73
|
||||
random.uint32 = function() { // 74
|
||||
return random() * 0x100000000; // 2^32 // 75
|
||||
}; // 76
|
||||
random.fract53 = function() { // 77
|
||||
return random() + // 78
|
||||
(random() * 0x200000 | 0) * 1.1102230246251565e-16; // 2^-53 // 79
|
||||
}; // 80
|
||||
random.version = 'Alea 0.9'; // 81
|
||||
random.args = args; // 82
|
||||
return random; // 83
|
||||
// 84
|
||||
} (Array.prototype.slice.call(arguments))); // 85
|
||||
}; // 86
|
||||
// 87
|
||||
var UNMISTAKABLE_CHARS = "23456789ABCDEFGHJKLMNPQRSTWXYZabcdefghijkmnopqrstuvwxyz"; // 88
|
||||
var BASE64_CHARS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + // 89
|
||||
"0123456789-_"; // 90
|
||||
// 91
|
||||
// If seeds are provided, then the alea PRNG will be used, since cryptographic // 92
|
||||
// PRNGs (Node crypto and window.crypto.getRandomValues) don't allow us to // 93
|
||||
// specify seeds. The caller is responsible for making sure to provide a seed // 94
|
||||
// for alea if a csprng is not available. // 95
|
||||
var RandomGenerator = function (seedArray) { // 96
|
||||
var self = this; // 97
|
||||
if (seedArray !== undefined) // 98
|
||||
self.alea = Alea.apply(null, seedArray); // 99
|
||||
}; // 100
|
||||
// 101
|
||||
RandomGenerator.prototype.fraction = function () { // 102
|
||||
var self = this; // 103
|
||||
if (self.alea) { // 104
|
||||
return self.alea(); // 105
|
||||
} else if (nodeCrypto) { // 106
|
||||
var numerator = parseInt(self.hexString(8), 16); // 107
|
||||
return numerator * 2.3283064365386963e-10; // 2^-32 // 108
|
||||
} else if (typeof window !== "undefined" && window.crypto && // 109
|
||||
window.crypto.getRandomValues) { // 110
|
||||
var array = new Uint32Array(1); // 111
|
||||
window.crypto.getRandomValues(array); // 112
|
||||
return array[0] * 2.3283064365386963e-10; // 2^-32 // 113
|
||||
} else { // 114
|
||||
throw new Error('No random generator available'); // 115
|
||||
} // 116
|
||||
}; // 117
|
||||
// 118
|
||||
RandomGenerator.prototype.hexString = function (digits) { // 119
|
||||
var self = this; // 120
|
||||
if (nodeCrypto && ! self.alea) { // 121
|
||||
var numBytes = Math.ceil(digits / 2); // 122
|
||||
var bytes; // 123
|
||||
// Try to get cryptographically strong randomness. Fall back to // 124
|
||||
// non-cryptographically strong if not available. // 125
|
||||
try { // 126
|
||||
bytes = nodeCrypto.randomBytes(numBytes); // 127
|
||||
} catch (e) { // 128
|
||||
// XXX should re-throw any error except insufficient entropy // 129
|
||||
bytes = nodeCrypto.pseudoRandomBytes(numBytes); // 130
|
||||
} // 131
|
||||
var result = bytes.toString("hex"); // 132
|
||||
// If the number of digits is odd, we'll have generated an extra 4 bits // 133
|
||||
// of randomness, so we need to trim the last digit. // 134
|
||||
return result.substring(0, digits); // 135
|
||||
} else { // 136
|
||||
var hexDigits = []; // 137
|
||||
for (var i = 0; i < digits; ++i) { // 138
|
||||
hexDigits.push(self.choice("0123456789abcdef")); // 139
|
||||
} // 140
|
||||
return hexDigits.join(''); // 141
|
||||
} // 142
|
||||
}; // 143
|
||||
// 144
|
||||
RandomGenerator.prototype._randomString = function (charsCount, // 145
|
||||
alphabet) { // 146
|
||||
var self = this; // 147
|
||||
var digits = []; // 148
|
||||
for (var i = 0; i < charsCount; i++) { // 149
|
||||
digits[i] = self.choice(alphabet); // 150
|
||||
} // 151
|
||||
return digits.join(""); // 152
|
||||
}; // 153
|
||||
// 154
|
||||
RandomGenerator.prototype.id = function (charsCount) { // 155
|
||||
var self = this; // 156
|
||||
// 17 characters is around 96 bits of entropy, which is the amount of // 157
|
||||
// state in the Alea PRNG. // 158
|
||||
if (charsCount === undefined) // 159
|
||||
charsCount = 17; // 160
|
||||
// 161
|
||||
return self._randomString(charsCount, UNMISTAKABLE_CHARS); // 162
|
||||
}; // 163
|
||||
// 164
|
||||
RandomGenerator.prototype.secret = function (charsCount) { // 165
|
||||
var self = this; // 166
|
||||
// Default to 256 bits of entropy, or 43 characters at 6 bits per // 167
|
||||
// character. // 168
|
||||
if (charsCount === undefined) // 169
|
||||
charsCount = 43; // 170
|
||||
return self._randomString(charsCount, BASE64_CHARS); // 171
|
||||
}; // 172
|
||||
// 173
|
||||
RandomGenerator.prototype.choice = function (arrayOrString) { // 174
|
||||
var index = Math.floor(this.fraction() * arrayOrString.length); // 175
|
||||
if (typeof arrayOrString === "string") // 176
|
||||
return arrayOrString.substr(index, 1); // 177
|
||||
else // 178
|
||||
return arrayOrString[index]; // 179
|
||||
}; // 180
|
||||
// 181
|
||||
// instantiate RNG. Heuristically collect entropy from various sources when a // 182
|
||||
// cryptographic PRNG isn't available. // 183
|
||||
// 184
|
||||
// client sources // 185
|
||||
var height = (typeof window !== 'undefined' && window.innerHeight) || // 186
|
||||
(typeof document !== 'undefined' // 187
|
||||
&& document.documentElement // 188
|
||||
&& document.documentElement.clientHeight) || // 189
|
||||
(typeof document !== 'undefined' // 190
|
||||
&& document.body // 191
|
||||
&& document.body.clientHeight) || // 192
|
||||
1; // 193
|
||||
// 194
|
||||
var width = (typeof window !== 'undefined' && window.innerWidth) || // 195
|
||||
(typeof document !== 'undefined' // 196
|
||||
&& document.documentElement // 197
|
||||
&& document.documentElement.clientWidth) || // 198
|
||||
(typeof document !== 'undefined' // 199
|
||||
&& document.body // 200
|
||||
&& document.body.clientWidth) || // 201
|
||||
1; // 202
|
||||
// 203
|
||||
var agent = (typeof navigator !== 'undefined' && navigator.userAgent) || ""; // 204
|
||||
// 205
|
||||
if (nodeCrypto || // 206
|
||||
(typeof window !== "undefined" && // 207
|
||||
window.crypto && window.crypto.getRandomValues)) // 208
|
||||
Random = new RandomGenerator(); // 209
|
||||
else // 210
|
||||
Random = new RandomGenerator([new Date(), height, width, agent, Math.random()]); // 211
|
||||
// 212
|
||||
Random.createWithSeeds = function () { // 213
|
||||
if (arguments.length === 0) { // 214
|
||||
throw new Error('No seeds were provided'); // 215
|
||||
} // 216
|
||||
return new RandomGenerator(arguments); // 217
|
||||
}; // 218
|
||||
// 219
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/random/deprecated.js //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Before this package existed, we used to use this Meteor.uuid() // 1
|
||||
// implementing the RFC 4122 v4 UUID. It is no longer documented // 2
|
||||
// and will go away. // 3
|
||||
// XXX COMPAT WITH 0.5.6 // 4
|
||||
Meteor.uuid = function () { // 5
|
||||
var HEX_DIGITS = "0123456789abcdef"; // 6
|
||||
var s = []; // 7
|
||||
for (var i = 0; i < 36; i++) { // 8
|
||||
s[i] = Random.choice(HEX_DIGITS); // 9
|
||||
} // 10
|
||||
s[14] = "4"; // 11
|
||||
s[19] = HEX_DIGITS.substr((parseInt(s[19],16) & 0x3) | 0x8, 1); // 12
|
||||
s[8] = s[13] = s[18] = s[23] = "-"; // 13
|
||||
// 14
|
||||
var uuid = s.join(""); // 15
|
||||
return uuid; // 16
|
||||
}; // 17
|
||||
// 18
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package.random = {
|
||||
Random: Random
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,266 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
var _ = Package.underscore._;
|
||||
var Tracker = Package.tracker.Tracker;
|
||||
var Deps = Package.tracker.Deps;
|
||||
var EJSON = Package.ejson.EJSON;
|
||||
|
||||
/* Package-scope variables */
|
||||
var ReactiveDict;
|
||||
|
||||
(function () {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/reactive-dict/reactive-dict.js //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// XXX come up with a serialization method which canonicalizes object key // 1
|
||||
// order, which would allow us to use objects as values for equals. // 2
|
||||
var stringify = function (value) { // 3
|
||||
if (value === undefined) // 4
|
||||
return 'undefined'; // 5
|
||||
return EJSON.stringify(value); // 6
|
||||
}; // 7
|
||||
var parse = function (serialized) { // 8
|
||||
if (serialized === undefined || serialized === 'undefined') // 9
|
||||
return undefined; // 10
|
||||
return EJSON.parse(serialized); // 11
|
||||
}; // 12
|
||||
// 13
|
||||
// XXX COMPAT WITH 0.9.1 : accept migrationData instead of dictName // 14
|
||||
ReactiveDict = function (dictName) { // 15
|
||||
// this.keys: key -> value // 16
|
||||
if (dictName) { // 17
|
||||
if (typeof dictName === 'string') { // 18
|
||||
// the normal case, argument is a string name. // 19
|
||||
// _registerDictForMigrate will throw an error on duplicate name. // 20
|
||||
ReactiveDict._registerDictForMigrate(dictName, this); // 21
|
||||
this.keys = ReactiveDict._loadMigratedDict(dictName) || {}; // 22
|
||||
} else if (typeof dictName === 'object') { // 23
|
||||
// back-compat case: dictName is actually migrationData // 24
|
||||
this.keys = dictName; // 25
|
||||
} else { // 26
|
||||
throw new Error("Invalid ReactiveDict argument: " + dictName); // 27
|
||||
} // 28
|
||||
} else { // 29
|
||||
// no name given; no migration will be performed // 30
|
||||
this.keys = {}; // 31
|
||||
} // 32
|
||||
// 33
|
||||
this.keyDeps = {}; // key -> Dependency // 34
|
||||
this.keyValueDeps = {}; // key -> Dependency // 35
|
||||
}; // 36
|
||||
// 37
|
||||
_.extend(ReactiveDict.prototype, { // 38
|
||||
// set() began as a key/value method, but we are now overloading it // 39
|
||||
// to take an object of key/value pairs, similar to backbone // 40
|
||||
// http://backbonejs.org/#Model-set // 41
|
||||
// 42
|
||||
set: function (keyOrObject, value) { // 43
|
||||
var self = this; // 44
|
||||
// 45
|
||||
if ((typeof keyOrObject === 'object') && (value === undefined)) { // 46
|
||||
self._setObject(keyOrObject); // 47
|
||||
return; // 48
|
||||
} // 49
|
||||
// the input isn't an object, so it must be a key // 50
|
||||
// and we resume with the rest of the function // 51
|
||||
var key = keyOrObject; // 52
|
||||
// 53
|
||||
value = stringify(value); // 54
|
||||
// 55
|
||||
var oldSerializedValue = 'undefined'; // 56
|
||||
if (_.has(self.keys, key)) oldSerializedValue = self.keys[key]; // 57
|
||||
if (value === oldSerializedValue) // 58
|
||||
return; // 59
|
||||
self.keys[key] = value; // 60
|
||||
// 61
|
||||
var changed = function (v) { // 62
|
||||
v && v.changed(); // 63
|
||||
}; // 64
|
||||
// 65
|
||||
changed(self.keyDeps[key]); // 66
|
||||
if (self.keyValueDeps[key]) { // 67
|
||||
changed(self.keyValueDeps[key][oldSerializedValue]); // 68
|
||||
changed(self.keyValueDeps[key][value]); // 69
|
||||
} // 70
|
||||
}, // 71
|
||||
// 72
|
||||
setDefault: function (key, value) { // 73
|
||||
var self = this; // 74
|
||||
// for now, explicitly check for undefined, since there is no // 75
|
||||
// ReactiveDict.clear(). Later we might have a ReactiveDict.clear(), in which case // 76
|
||||
// we should check if it has the key. // 77
|
||||
if (self.keys[key] === undefined) { // 78
|
||||
self.set(key, value); // 79
|
||||
} // 80
|
||||
}, // 81
|
||||
// 82
|
||||
get: function (key) { // 83
|
||||
var self = this; // 84
|
||||
self._ensureKey(key); // 85
|
||||
self.keyDeps[key].depend(); // 86
|
||||
return parse(self.keys[key]); // 87
|
||||
}, // 88
|
||||
// 89
|
||||
equals: function (key, value) { // 90
|
||||
var self = this; // 91
|
||||
// 92
|
||||
// Mongo.ObjectID is in the 'mongo' package // 93
|
||||
var ObjectID = null; // 94
|
||||
if (typeof Mongo !== 'undefined') { // 95
|
||||
ObjectID = Mongo.ObjectID; // 96
|
||||
} // 97
|
||||
// 98
|
||||
// We don't allow objects (or arrays that might include objects) for // 99
|
||||
// .equals, because JSON.stringify doesn't canonicalize object key // 100
|
||||
// order. (We can make equals have the right return value by parsing the // 101
|
||||
// current value and using EJSON.equals, but we won't have a canonical // 102
|
||||
// element of keyValueDeps[key] to store the dependency.) You can still use // 103
|
||||
// "EJSON.equals(reactiveDict.get(key), value)". // 104
|
||||
// // 105
|
||||
// XXX we could allow arrays as long as we recursively check that there // 106
|
||||
// are no objects // 107
|
||||
if (typeof value !== 'string' && // 108
|
||||
typeof value !== 'number' && // 109
|
||||
typeof value !== 'boolean' && // 110
|
||||
typeof value !== 'undefined' && // 111
|
||||
!(value instanceof Date) && // 112
|
||||
!(ObjectID && value instanceof ObjectID) && // 113
|
||||
value !== null) // 114
|
||||
throw new Error("ReactiveDict.equals: value must be scalar"); // 115
|
||||
var serializedValue = stringify(value); // 116
|
||||
// 117
|
||||
if (Tracker.active) { // 118
|
||||
self._ensureKey(key); // 119
|
||||
// 120
|
||||
if (! _.has(self.keyValueDeps[key], serializedValue)) // 121
|
||||
self.keyValueDeps[key][serializedValue] = new Tracker.Dependency; // 122
|
||||
// 123
|
||||
var isNew = self.keyValueDeps[key][serializedValue].depend(); // 124
|
||||
if (isNew) { // 125
|
||||
Tracker.onInvalidate(function () { // 126
|
||||
// clean up [key][serializedValue] if it's now empty, so we don't // 127
|
||||
// use O(n) memory for n = values seen ever // 128
|
||||
if (! self.keyValueDeps[key][serializedValue].hasDependents()) // 129
|
||||
delete self.keyValueDeps[key][serializedValue]; // 130
|
||||
}); // 131
|
||||
} // 132
|
||||
} // 133
|
||||
// 134
|
||||
var oldValue = undefined; // 135
|
||||
if (_.has(self.keys, key)) oldValue = parse(self.keys[key]); // 136
|
||||
return EJSON.equals(oldValue, value); // 137
|
||||
}, // 138
|
||||
// 139
|
||||
_setObject: function (object) { // 140
|
||||
var self = this; // 141
|
||||
// 142
|
||||
_.each(object, function (value, key){ // 143
|
||||
self.set(key, value); // 144
|
||||
}); // 145
|
||||
}, // 146
|
||||
// 147
|
||||
_ensureKey: function (key) { // 148
|
||||
var self = this; // 149
|
||||
if (!(key in self.keyDeps)) { // 150
|
||||
self.keyDeps[key] = new Tracker.Dependency; // 151
|
||||
self.keyValueDeps[key] = {}; // 152
|
||||
} // 153
|
||||
}, // 154
|
||||
// 155
|
||||
// Get a JSON value that can be passed to the constructor to // 156
|
||||
// create a new ReactiveDict with the same contents as this one // 157
|
||||
_getMigrationData: function () { // 158
|
||||
// XXX sanitize and make sure it's JSONible? // 159
|
||||
return this.keys; // 160
|
||||
} // 161
|
||||
}); // 162
|
||||
// 163
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/reactive-dict/migration.js //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
ReactiveDict._migratedDictData = {}; // name -> data // 1
|
||||
ReactiveDict._dictsToMigrate = {}; // name -> ReactiveDict // 2
|
||||
// 3
|
||||
ReactiveDict._loadMigratedDict = function (dictName) { // 4
|
||||
if (_.has(ReactiveDict._migratedDictData, dictName)) // 5
|
||||
return ReactiveDict._migratedDictData[dictName]; // 6
|
||||
// 7
|
||||
return null; // 8
|
||||
}; // 9
|
||||
// 10
|
||||
ReactiveDict._registerDictForMigrate = function (dictName, dict) { // 11
|
||||
if (_.has(ReactiveDict._dictsToMigrate, dictName)) // 12
|
||||
throw new Error("Duplicate ReactiveDict name: " + dictName); // 13
|
||||
// 14
|
||||
ReactiveDict._dictsToMigrate[dictName] = dict; // 15
|
||||
}; // 16
|
||||
// 17
|
||||
if (Meteor.isClient && Package.reload) { // 18
|
||||
// Put old migrated data into ReactiveDict._migratedDictData, // 19
|
||||
// where it can be accessed by ReactiveDict._loadMigratedDict. // 20
|
||||
var migrationData = Package.reload.Reload._migrationData('reactive-dict'); // 21
|
||||
if (migrationData && migrationData.dicts) // 22
|
||||
ReactiveDict._migratedDictData = migrationData.dicts; // 23
|
||||
// 24
|
||||
// On migration, assemble the data from all the dicts that have been // 25
|
||||
// registered. // 26
|
||||
Package.reload.Reload._onMigrate('reactive-dict', function () { // 27
|
||||
var dictsToMigrate = ReactiveDict._dictsToMigrate; // 28
|
||||
var dataToMigrate = {}; // 29
|
||||
// 30
|
||||
for (var dictName in dictsToMigrate) // 31
|
||||
dataToMigrate[dictName] = dictsToMigrate[dictName]._getMigrationData(); // 32
|
||||
// 33
|
||||
return [true, {dicts: dataToMigrate}]; // 34
|
||||
}); // 35
|
||||
} // 36
|
||||
// 37
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package['reactive-dict'] = {
|
||||
ReactiveDict: ReactiveDict
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,144 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
var Tracker = Package.tracker.Tracker;
|
||||
var Deps = Package.tracker.Deps;
|
||||
|
||||
/* Package-scope variables */
|
||||
var ReactiveVar;
|
||||
|
||||
(function () {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/reactive-var/reactive-var.js //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/* // 1
|
||||
* ## [new] ReactiveVar(initialValue, [equalsFunc]) // 2
|
||||
* // 3
|
||||
* A ReactiveVar holds a single value that can be get and set, // 4
|
||||
* such that calling `set` will invalidate any Computations that // 5
|
||||
* called `get`, according to the usual contract for reactive // 6
|
||||
* data sources. // 7
|
||||
* // 8
|
||||
* A ReactiveVar is much like a Session variable -- compare `foo.get()` // 9
|
||||
* to `Session.get("foo")` -- but it doesn't have a global name and isn't // 10
|
||||
* automatically migrated across hot code pushes. Also, while Session // 11
|
||||
* variables can only hold JSON or EJSON, ReactiveVars can hold any value. // 12
|
||||
* // 13
|
||||
* An important property of ReactiveVars, which is sometimes the reason // 14
|
||||
* to use one, is that setting the value to the same value as before has // 15
|
||||
* no effect, meaning ReactiveVars can be used to absorb extra // 16
|
||||
* invalidations that wouldn't serve a purpose. However, by default, // 17
|
||||
* ReactiveVars are extremely conservative about what changes they // 18
|
||||
* absorb. Calling `set` with an object argument will *always* trigger // 19
|
||||
* invalidations, because even if the new value is `===` the old value, // 20
|
||||
* the object may have been mutated. You can change the default behavior // 21
|
||||
* by passing a function of two arguments, `oldValue` and `newValue`, // 22
|
||||
* to the constructor as `equalsFunc`. // 23
|
||||
* // 24
|
||||
* This class is extremely basic right now, but the idea is to evolve // 25
|
||||
* it into the ReactiveVar of Geoff's Lickable Forms proposal. // 26
|
||||
*/ // 27
|
||||
// 28
|
||||
/** // 29
|
||||
* @class // 30
|
||||
* @instanceName reactiveVar // 31
|
||||
* @summary Constructor for a ReactiveVar, which represents a single reactive variable. // 32
|
||||
* @locus Client // 33
|
||||
* @param {Any} initialValue The initial value to set. `equalsFunc` is ignored when setting the initial value. // 34
|
||||
* @param {Function} [equalsFunc] Optional. A function of two arguments, called on the old value and the new value whenever the ReactiveVar is set. If it returns true, no set is performed. If omitted, the default `equalsFunc` returns true if its arguments are `===` and are of type number, boolean, string, undefined, or null.
|
||||
*/ // 36
|
||||
ReactiveVar = function (initialValue, equalsFunc) { // 37
|
||||
if (! (this instanceof ReactiveVar)) // 38
|
||||
// called without `new` // 39
|
||||
return new ReactiveVar(initialValue, equalsFunc); // 40
|
||||
// 41
|
||||
this.curValue = initialValue; // 42
|
||||
this.equalsFunc = equalsFunc; // 43
|
||||
this.dep = new Tracker.Dependency; // 44
|
||||
}; // 45
|
||||
// 46
|
||||
ReactiveVar._isEqual = function (oldValue, newValue) { // 47
|
||||
var a = oldValue, b = newValue; // 48
|
||||
// Two values are "equal" here if they are `===` and are // 49
|
||||
// number, boolean, string, undefined, or null. // 50
|
||||
if (a !== b) // 51
|
||||
return false; // 52
|
||||
else // 53
|
||||
return ((!a) || (typeof a === 'number') || (typeof a === 'boolean') || // 54
|
||||
(typeof a === 'string')); // 55
|
||||
}; // 56
|
||||
// 57
|
||||
/** // 58
|
||||
* @summary Returns the current value of the ReactiveVar, establishing a reactive dependency. // 59
|
||||
* @locus Client // 60
|
||||
*/ // 61
|
||||
ReactiveVar.prototype.get = function () { // 62
|
||||
if (Tracker.active) // 63
|
||||
this.dep.depend(); // 64
|
||||
// 65
|
||||
return this.curValue; // 66
|
||||
}; // 67
|
||||
// 68
|
||||
/** // 69
|
||||
* @summary Sets the current value of the ReactiveVar, invalidating the Computations that called `get` if `newValue` is different from the old value.
|
||||
* @locus Client // 71
|
||||
* @param {Any} newValue // 72
|
||||
*/ // 73
|
||||
ReactiveVar.prototype.set = function (newValue) { // 74
|
||||
var oldValue = this.curValue; // 75
|
||||
// 76
|
||||
if ((this.equalsFunc || ReactiveVar._isEqual)(oldValue, newValue)) // 77
|
||||
// value is same as last time // 78
|
||||
return; // 79
|
||||
// 80
|
||||
this.curValue = newValue; // 81
|
||||
this.dep.changed(); // 82
|
||||
}; // 83
|
||||
// 84
|
||||
ReactiveVar.prototype.toString = function () { // 85
|
||||
return 'ReactiveVar{' + this.get() + '}'; // 86
|
||||
}; // 87
|
||||
// 88
|
||||
ReactiveVar.prototype._numListeners = function() { // 89
|
||||
// Tests want to know. // 90
|
||||
// Accesses a private field of Tracker.Dependency. // 91
|
||||
var count = 0; // 92
|
||||
for (var id in this.dep._dependentsById) // 93
|
||||
count++; // 94
|
||||
return count; // 95
|
||||
}; // 96
|
||||
// 97
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package['reactive-var'] = {
|
||||
ReactiveVar: ReactiveVar
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,2 @@
|
||||
)]}'
|
||||
{"version":3,"sources":["reactive-var/reactive-var.js"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,E;AACA,mD;AACA,E;AACA,8D;AACA,gE;AACA,6D;AACA,gB;AACA,E;AACA,uE;AACA,yE;AACA,sE;AACA,0E;AACA,E;AACA,uE;AACA,wE;AACA,8D;AACA,qE;AACA,kE;AACA,uE;AACA,uE;AACA,yE;AACA,qE;AACA,sC;AACA,E;AACA,qE;AACA,8D;AACA,G;;AAEA,G;AACA,U;AACA,4B;AACA,uF;AACA,gB;AACA,+G;AACA,yU;AACA,G;AACA,mD;AACA,sC;AACA,2B;AACA,qD;;AAEA,+B;AACA,+B;AACA,oC;AACA,E;;AAEA,sD;AACA,iC;AACA,0D;AACA,iD;AACA,c;AACA,iB;AACA,M;AACA,0E;AACA,qC;AACA,E;;AAEA,G;AACA,6F;AACA,gB;AACA,G;AACA,yC;AACA,qB;AACA,sB;;AAEA,uB;AACA,E;;AAEA,G;AACA,qJ;AACA,gB;AACA,wB;AACA,G;AACA,iD;AACA,+B;;AAEA,oE;AACA,iC;AACA,W;;AAEA,2B;AACA,qB;AACA,E;;AAEA,8C;AACA,2C;AACA,E;;AAEA,kD;AACA,wB;AACA,oD;AACA,gB;AACA,0C;AACA,Y;AACA,e;AACA,E","file":"/packages/reactive-var.js","sourcesContent":["/*\n * ## [new] ReactiveVar(initialValue, [equalsFunc])\n *\n * A ReactiveVar holds a single value that can be get and set,\n * such that calling `set` will invalidate any Computations that\n * called `get`, according to the usual contract for reactive\n * data sources.\n *\n * A ReactiveVar is much like a Session variable -- compare `foo.get()`\n * to `Session.get(\"foo\")` -- but it doesn't have a global name and isn't\n * automatically migrated across hot code pushes. Also, while Session\n * variables can only hold JSON or EJSON, ReactiveVars can hold any value.\n *\n * An important property of ReactiveVars, which is sometimes the reason\n * to use one, is that setting the value to the same value as before has\n * no effect, meaning ReactiveVars can be used to absorb extra\n * invalidations that wouldn't serve a purpose. However, by default,\n * ReactiveVars are extremely conservative about what changes they\n * absorb. Calling `set` with an object argument will *always* trigger\n * invalidations, because even if the new value is `===` the old value,\n * the object may have been mutated. You can change the default behavior\n * by passing a function of two arguments, `oldValue` and `newValue`,\n * to the constructor as `equalsFunc`.\n *\n * This class is extremely basic right now, but the idea is to evolve\n * it into the ReactiveVar of Geoff's Lickable Forms proposal.\n */\n\n/**\n * @class \n * @instanceName reactiveVar\n * @summary Constructor for a ReactiveVar, which represents a single reactive variable.\n * @locus Client\n * @param {Any} initialValue The initial value to set. `equalsFunc` is ignored when setting the initial value.\n * @param {Function} [equalsFunc] Optional. A function of two arguments, called on the old value and the new value whenever the ReactiveVar is set. If it returns true, no set is performed. If omitted, the default `equalsFunc` returns true if its arguments are `===` and are of type number, boolean, string, undefined, or null.\n */\nReactiveVar = function (initialValue, equalsFunc) {\n if (! (this instanceof ReactiveVar))\n // called without `new`\n return new ReactiveVar(initialValue, equalsFunc);\n\n this.curValue = initialValue;\n this.equalsFunc = equalsFunc;\n this.dep = new Tracker.Dependency;\n};\n\nReactiveVar._isEqual = function (oldValue, newValue) {\n var a = oldValue, b = newValue;\n // Two values are \"equal\" here if they are `===` and are\n // number, boolean, string, undefined, or null.\n if (a !== b)\n return false;\n else\n return ((!a) || (typeof a === 'number') || (typeof a === 'boolean') ||\n (typeof a === 'string'));\n};\n\n/**\n * @summary Returns the current value of the ReactiveVar, establishing a reactive dependency.\n * @locus Client\n */\nReactiveVar.prototype.get = function () {\n if (Tracker.active)\n this.dep.depend();\n\n return this.curValue;\n};\n\n/**\n * @summary Sets the current value of the ReactiveVar, invalidating the Computations that called `get` if `newValue` is different from the old value.\n * @locus Client\n * @param {Any} newValue\n */\nReactiveVar.prototype.set = function (newValue) {\n var oldValue = this.curValue;\n\n if ((this.equalsFunc || ReactiveVar._isEqual)(oldValue, newValue))\n // value is same as last time\n return;\n\n this.curValue = newValue;\n this.dep.changed();\n};\n\nReactiveVar.prototype.toString = function () {\n return 'ReactiveVar{' + this.get() + '}';\n};\n\nReactiveVar.prototype._numListeners = function() {\n // Tests want to know.\n // Accesses a private field of Tracker.Dependency.\n var count = 0;\n for (var id in this.dep._dependentsById)\n count++;\n return count;\n};\n"]}
|
||||
@@ -0,0 +1,302 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
var _ = Package.underscore._;
|
||||
var Log = Package.logging.Log;
|
||||
var JSON = Package.json.JSON;
|
||||
|
||||
/* Package-scope variables */
|
||||
var Reload;
|
||||
|
||||
(function () {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/reload/reload.js //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/** // 1
|
||||
* This code does _NOT_ support hot (session-restoring) reloads on // 2
|
||||
* IE6,7. It only works on browsers with sessionStorage support. // 3
|
||||
* // 4
|
||||
* There are a couple approaches to add IE6,7 support: // 5
|
||||
* // 6
|
||||
* - use IE's "userData" mechanism in combination with window.name. // 7
|
||||
* This mostly works, however the problem is that it can not get to the // 8
|
||||
* data until after DOMReady. This is a problem for us since this API // 9
|
||||
* relies on the data being ready before API users run. We could // 10
|
||||
* refactor using Meteor.startup in all API users, but that might slow // 11
|
||||
* page loads as we couldn't start the stream until after DOMReady. // 12
|
||||
* Here are some resources on this approach: // 13
|
||||
* https://github.com/hugeinc/USTORE.js // 14
|
||||
* http://thudjs.tumblr.com/post/419577524/localstorage-userdata // 15
|
||||
* http://www.javascriptkit.com/javatutors/domstorage2.shtml // 16
|
||||
* // 17
|
||||
* - POST the data to the server, and have the server send it back on // 18
|
||||
* page load. This is nice because it sidesteps all the local storage // 19
|
||||
* compatibility issues, however it is kinda tricky. We can use a unique // 20
|
||||
* token in the URL, then get rid of it with HTML5 pushstate, but that // 21
|
||||
* only works on pushstate browsers. // 22
|
||||
* // 23
|
||||
* This will all need to be reworked entirely when we add server-side // 24
|
||||
* HTML rendering. In that case, the server will need to have access to // 25
|
||||
* the client's session to render properly. // 26
|
||||
*/ // 27
|
||||
// 28
|
||||
// XXX when making this API public, also expose a flag for the app // 29
|
||||
// developer to know whether a hot code push is happening. This is // 30
|
||||
// useful for apps using `window.onbeforeunload`. See // 31
|
||||
// https://github.com/meteor/meteor/pull/657 // 32
|
||||
// 33
|
||||
Reload = {}; // 34
|
||||
// 35
|
||||
var KEY_NAME = 'Meteor_Reload'; // 36
|
||||
// 37
|
||||
var old_data = {}; // 38
|
||||
// read in old data at startup. // 39
|
||||
var old_json; // 40
|
||||
// 41
|
||||
// This logic for sessionStorage detection is based on browserstate/history.js // 42
|
||||
var safeSessionStorage = null; // 43
|
||||
try { // 44
|
||||
// This throws a SecurityError on Chrome if cookies & localStorage are // 45
|
||||
// explicitly disabled // 46
|
||||
// // 47
|
||||
// On Firefox with dom.storage.enabled set to false, sessionStorage is null // 48
|
||||
// // 49
|
||||
// We can't even do (typeof sessionStorage) on Chrome, it throws. So we rely // 50
|
||||
// on the throw if sessionStorage == null; the alternative is browser // 51
|
||||
// detection, but this seems better. // 52
|
||||
safeSessionStorage = window.sessionStorage; // 53
|
||||
// 54
|
||||
// Check we can actually use it // 55
|
||||
if (safeSessionStorage) { // 56
|
||||
safeSessionStorage.setItem('__dummy__', '1'); // 57
|
||||
safeSessionStorage.removeItem('__dummy__'); // 58
|
||||
} else { // 59
|
||||
// Be consistently null, for safety // 60
|
||||
safeSessionStorage = null; // 61
|
||||
} // 62
|
||||
} catch(e) { // 63
|
||||
// Expected on chrome with strict security, or if sessionStorage not supported // 64
|
||||
safeSessionStorage = null; // 65
|
||||
} // 66
|
||||
// 67
|
||||
// Exported for test. // 68
|
||||
Reload._getData = function () { // 69
|
||||
return safeSessionStorage && safeSessionStorage.getItem(KEY_NAME); // 70
|
||||
}; // 71
|
||||
// 72
|
||||
if (safeSessionStorage) { // 73
|
||||
old_json = Reload._getData(); // 74
|
||||
safeSessionStorage.removeItem(KEY_NAME); // 75
|
||||
} else { // 76
|
||||
// Unsupported browser (IE 6,7) or locked down security settings. // 77
|
||||
// No session resumption. // 78
|
||||
// Meteor._debug("XXX UNSUPPORTED BROWSER/SETTINGS"); // 79
|
||||
} // 80
|
||||
// 81
|
||||
if (!old_json) old_json = '{}'; // 82
|
||||
var old_parsed = {}; // 83
|
||||
try { // 84
|
||||
old_parsed = JSON.parse(old_json); // 85
|
||||
if (typeof old_parsed !== "object") { // 86
|
||||
Meteor._debug("Got bad data on reload. Ignoring."); // 87
|
||||
old_parsed = {}; // 88
|
||||
} // 89
|
||||
} catch (err) { // 90
|
||||
Meteor._debug("Got invalid JSON on reload. Ignoring."); // 91
|
||||
} // 92
|
||||
// 93
|
||||
if (old_parsed.reload && typeof old_parsed.data === "object") { // 94
|
||||
// Meteor._debug("Restoring reload data."); // 95
|
||||
old_data = old_parsed.data; // 96
|
||||
} // 97
|
||||
// 98
|
||||
// 99
|
||||
var providers = []; // 100
|
||||
// 101
|
||||
////////// External API ////////// // 102
|
||||
// 103
|
||||
// Packages that support migration should register themselves by calling // 104
|
||||
// this function. When it's time to migrate, callback will be called // 105
|
||||
// with one argument, the "retry function," and an optional 'option' // 106
|
||||
// argument (containing a key 'immediateMigration'). If the package // 107
|
||||
// is ready to migrate, it should return [true, data], where data is // 108
|
||||
// its migration data, an arbitrary JSON value (or [true] if it has // 109
|
||||
// no migration data this time). If the package needs more time // 110
|
||||
// before it is ready to migrate, it should return false. Then, once // 111
|
||||
// it is ready to migrating again, it should call the retry // 112
|
||||
// function. The retry function will return immediately, but will // 113
|
||||
// schedule the migration to be retried, meaning that every package // 114
|
||||
// will be polled once again for its migration data. If they are all // 115
|
||||
// ready this time, then the migration will happen. name must be set if there // 116
|
||||
// is migration data. If 'immediateMigration' is set in the options // 117
|
||||
// argument, then it doesn't matter whether the package is ready to // 118
|
||||
// migrate or not; the reload will happen immediately without waiting // 119
|
||||
// (used for OAuth redirect login). // 120
|
||||
// // 121
|
||||
Reload._onMigrate = function (name, callback) { // 122
|
||||
if (!callback) { // 123
|
||||
// name not provided, so first arg is callback. // 124
|
||||
callback = name; // 125
|
||||
name = undefined; // 126
|
||||
} // 127
|
||||
providers.push({name: name, callback: callback}); // 128
|
||||
}; // 129
|
||||
// 130
|
||||
// Called by packages when they start up. // 131
|
||||
// Returns the object that was saved, or undefined if none saved. // 132
|
||||
// // 133
|
||||
Reload._migrationData = function (name) { // 134
|
||||
return old_data[name]; // 135
|
||||
}; // 136
|
||||
// 137
|
||||
// Options are the same as for `Reload._migrate`. // 138
|
||||
var pollProviders = function (tryReload, options) { // 139
|
||||
tryReload = tryReload || function () {}; // 140
|
||||
options = options || {}; // 141
|
||||
// 142
|
||||
var migrationData = {}; // 143
|
||||
var remaining = _.clone(providers); // 144
|
||||
var allReady = true; // 145
|
||||
while (remaining.length) { // 146
|
||||
var p = remaining.shift(); // 147
|
||||
var status = p.callback(tryReload, options); // 148
|
||||
if (!status[0]) // 149
|
||||
allReady = false; // 150
|
||||
if (status.length > 1 && p.name) // 151
|
||||
migrationData[p.name] = status[1]; // 152
|
||||
}; // 153
|
||||
if (allReady || options.immediateMigration) // 154
|
||||
return migrationData; // 155
|
||||
else // 156
|
||||
return null; // 157
|
||||
}; // 158
|
||||
// 159
|
||||
// Options are: // 160
|
||||
// - immediateMigration: true if the page will be reloaded immediately // 161
|
||||
// regardless of whether packages report that they are ready or not. // 162
|
||||
Reload._migrate = function (tryReload, options) { // 163
|
||||
// Make sure each package is ready to go, and collect their // 164
|
||||
// migration data // 165
|
||||
var migrationData = pollProviders(tryReload, options); // 166
|
||||
if (migrationData === null) // 167
|
||||
return false; // not ready yet.. // 168
|
||||
// 169
|
||||
try { // 170
|
||||
// Persist the migration data // 171
|
||||
var json = JSON.stringify({ // 172
|
||||
data: migrationData, reload: true // 173
|
||||
}); // 174
|
||||
} catch (err) { // 175
|
||||
Meteor._debug("Couldn't serialize data for migration", migrationData); // 176
|
||||
throw err; // 177
|
||||
} // 178
|
||||
// 179
|
||||
if (safeSessionStorage) { // 180
|
||||
try { // 181
|
||||
safeSessionStorage.setItem(KEY_NAME, json); // 182
|
||||
} catch (err) { // 183
|
||||
// We should have already checked this, but just log - don't throw // 184
|
||||
Meteor._debug("Couldn't save data for migration to sessionStorage", err); // 185
|
||||
} // 186
|
||||
} else { // 187
|
||||
Meteor._debug("Browser does not support sessionStorage. Not saving migration state."); // 188
|
||||
} // 189
|
||||
// 190
|
||||
return true; // 191
|
||||
}; // 192
|
||||
// 193
|
||||
// Allows tests to isolate the list of providers. // 194
|
||||
Reload._withFreshProvidersForTest = function (f) { // 195
|
||||
var originalProviders = _.clone(providers); // 196
|
||||
providers = []; // 197
|
||||
try { // 198
|
||||
f(); // 199
|
||||
} finally { // 200
|
||||
providers = originalProviders; // 201
|
||||
} // 202
|
||||
}; // 203
|
||||
// 204
|
||||
// Migrating reload: reload this page (presumably to pick up a new // 205
|
||||
// version of the code or assets), but save the program state and // 206
|
||||
// migrate it over. This function returns immediately. The reload // 207
|
||||
// will happen at some point in the future once all of the packages // 208
|
||||
// are ready to migrate. // 209
|
||||
// // 210
|
||||
var reloading = false; // 211
|
||||
Reload._reload = function (options) { // 212
|
||||
options = options || {}; // 213
|
||||
// 214
|
||||
if (reloading) // 215
|
||||
return; // 216
|
||||
reloading = true; // 217
|
||||
// 218
|
||||
var tryReload = function () { _.defer(function () { // 219
|
||||
if (Reload._migrate(tryReload, options)) { // 220
|
||||
// Tell the browser to shut down this VM and make a new one // 221
|
||||
window.location.reload(); // 222
|
||||
} // 223
|
||||
}); }; // 224
|
||||
// 225
|
||||
tryReload(); // 226
|
||||
}; // 227
|
||||
// 228
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/reload/deprecated.js //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Reload functionality used to live on Meteor._reload. Be nice and try not to // 1
|
||||
// break code that uses it, even though it's internal. // 2
|
||||
// XXX COMPAT WITH 0.6.4 // 3
|
||||
Meteor._reload = { // 4
|
||||
onMigrate: Reload._onMigrate, // 5
|
||||
migrationData: Reload._migrationData, // 6
|
||||
reload: Reload._reload // 7
|
||||
}; // 8
|
||||
// 9
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package.reload = {
|
||||
Reload: Reload
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -0,0 +1,112 @@
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// This is a generated file. You can view the original //
|
||||
// source in your browser if your browser supports source maps. //
|
||||
// //
|
||||
// If you are using Chrome, open the Developer Tools and click the gear //
|
||||
// icon in its lower right corner. In the General Settings panel, turn //
|
||||
// on 'Enable source maps'. //
|
||||
// //
|
||||
// If you are using Firefox 23, go to `about:config` and set the //
|
||||
// `devtools.debugger.source-maps-enabled` preference to true. //
|
||||
// (The preference should be on by default in Firefox 24; versions //
|
||||
// older than 23 do not support source maps.) //
|
||||
// //
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
(function () {
|
||||
|
||||
/* Imports */
|
||||
var Meteor = Package.meteor.Meteor;
|
||||
var _ = Package.underscore._;
|
||||
var Random = Package.random.Random;
|
||||
|
||||
/* Package-scope variables */
|
||||
var Retry;
|
||||
|
||||
(function () {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// //
|
||||
// packages/retry/retry.js //
|
||||
// //
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Retry logic with an exponential backoff. // 1
|
||||
// // 2
|
||||
// options: // 3
|
||||
// baseTimeout: time for initial reconnect attempt (ms). // 4
|
||||
// exponent: exponential factor to increase timeout each attempt. // 5
|
||||
// maxTimeout: maximum time between retries (ms). // 6
|
||||
// minCount: how many times to reconnect "instantly". // 7
|
||||
// minTimeout: time to wait for the first `minCount` retries (ms). // 8
|
||||
// fuzz: factor to randomize retry times by (to avoid retry storms). // 9
|
||||
// 10
|
||||
Retry = function (options) { // 11
|
||||
var self = this; // 12
|
||||
_.extend(self, _.defaults(_.clone(options || {}), { // 13
|
||||
baseTimeout: 1000, // 1 second // 14
|
||||
exponent: 2.2, // 15
|
||||
// The default is high-ish to ensure a server can recover from a // 16
|
||||
// failure caused by load. // 17
|
||||
maxTimeout: 5 * 60000, // 5 minutes // 18
|
||||
minTimeout: 10, // 19
|
||||
minCount: 2, // 20
|
||||
fuzz: 0.5 // +- 25% // 21
|
||||
})); // 22
|
||||
self.retryTimer = null; // 23
|
||||
}; // 24
|
||||
// 25
|
||||
_.extend(Retry.prototype, { // 26
|
||||
// 27
|
||||
// Reset a pending retry, if any. // 28
|
||||
clear: function () { // 29
|
||||
var self = this; // 30
|
||||
if (self.retryTimer) // 31
|
||||
clearTimeout(self.retryTimer); // 32
|
||||
self.retryTimer = null; // 33
|
||||
}, // 34
|
||||
// 35
|
||||
// Calculate how long to wait in milliseconds to retry, based on the // 36
|
||||
// `count` of which retry this is. // 37
|
||||
_timeout: function (count) { // 38
|
||||
var self = this; // 39
|
||||
// 40
|
||||
if (count < self.minCount) // 41
|
||||
return self.minTimeout; // 42
|
||||
// 43
|
||||
var timeout = Math.min( // 44
|
||||
self.maxTimeout, // 45
|
||||
self.baseTimeout * Math.pow(self.exponent, count)); // 46
|
||||
// fuzz the timeout randomly, to avoid reconnect storms when a // 47
|
||||
// server goes down. // 48
|
||||
timeout = timeout * ((Random.fraction() * self.fuzz) + // 49
|
||||
(1 - self.fuzz/2)); // 50
|
||||
return timeout; // 51
|
||||
}, // 52
|
||||
// 53
|
||||
// Call `fn` after a delay, based on the `count` of which retry this is. // 54
|
||||
retryLater: function (count, fn) { // 55
|
||||
var self = this; // 56
|
||||
var timeout = self._timeout(count); // 57
|
||||
if (self.retryTimer) // 58
|
||||
clearTimeout(self.retryTimer); // 59
|
||||
self.retryTimer = Meteor.setTimeout(fn, timeout); // 60
|
||||
return timeout; // 61
|
||||
} // 62
|
||||
// 63
|
||||
}); // 64
|
||||
// 65
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
}).call(this);
|
||||
|
||||
|
||||
/* Exports */
|
||||
if (typeof Package === 'undefined') Package = {};
|
||||
Package.retry = {
|
||||
Retry: Retry
|
||||
};
|
||||
|
||||
})();
|
||||