<commit_before>var _ = require('underscore');
var express = require('express');
var request = require('request');
var handlebars = require('handlebars');
var hbs = require('hbs');
var sendgrid = require('sendgrid');
var keys = require(__dirname + '/keys.js');
console.log(keys);
var Firebase = require('firebase');
var FirebaseTokenGenerator = require('firebase-token-generator');
var fb_root = new Firebase('https://feedlisten.firebaseio.com/');
var tokenGenerator = new FirebaseTokenGenerator(keys.FIREBASE);
var APP_ID = '384422024994164';

console.log(tokenGenerator.mSecret);
var adminToken = tokenGenerator.createToken({}, {
	admin: true,
	debug: false,
	expires: 1577836800
});

fb_root.auth(adminToken);

var app = express();

hbs.registerHelper('foreach', function(context, options) {
    var ret = "";
    for(var prop in context)
    {
        ret = ret + options.fn({
			property:prop, value:context[prop]
        });
    }
    return ret;
});

app.configure('development', function() {
	app.use(express.bodyParser());
	app.use(express.errorHandler());
	app.locals.pretty = true;

	app.set("view engine", 'tmpl');
	app.set("view options", { layout: false });

	app.engine('tmpl', require('hbs').__express);

	app.use(express.static(__dirname + '/public'));
	app.use(express.vhost('realtime.feedlisten.com', require('./realtime/index.js')));
});

app.get('/', function(req, res){
	if(req.query.token){
		//show page with selection of groups
		//maybe should be client-side js for loading the groups?
	} else {
		//send them a facebook auth screen - this could be done on the client side, too
	}
	res.send(__dirname + '/public/index.html');
});

app.get('/selection', function(req, res){
	if(req.query.token && req.query.fbid){
		request({json: true, url:'https://graph.facebook.com/me', qs:{'access_token':req.query.token}}, function(error, response, body){
			if(!error && response.statusCode == 200){
				var user_info = body;
				request({json: true, url:'https://graph.facebook.com/me/accounts', qs:{'access_token':req.query.token}}, function(error, response, body){
					if(!error && response.statusCode == 200){
						var data = {
							name: user_info.first_name,
							accessToken: req.query.token,
							pages: body.data
						};
						console.log(data);
						res.render('pages', data, function(err, html){
							if(err){
								console.log(err);
							} else {
								res.send(html);
							}
						});
					}
				});
			}
		});
	} else {
		res.redirect('/');
	}
});

app.get('/:pageid', function(req, res){
	if(req.query.token){
		request({json: true, url:'https://graph.facebook.com/me/accounts', qs:{'access_token':req.query.token}}, function(error, response, body){
			if(!error && response.statusCode == 200){
				var page;
				_.each(body.data, function(element){
					if(element.id == req.params.pageid){
						page = element;
					}
				});
				res.redirect('/' + page.id + '?pageToken=' + page.access_token);
			}
		});
	} else if(req.query.pageToken) {
		request({json: true, url:'https://graph.facebook.com/' + req.params.pageid, qs:{'access_token':req.query.pageToken}}, function(error, response, body){
			if(!error && response.statusCode == 200){
				var page = body;
				request({json: true, url:'https://graph.facebook.com/' + req.params.pageid, qs:{'fields':'feed', 'access_token':req.query.pageToken}}, function(error, response, body){
					if(!error && response.statusCode == 200){
						var item;
						if(body.feed){
							item = body.feed.data[0];
						} else {
							var viewData = {
								page:page,
								name:'Random User'
							};
							res.render('page', viewData, function(err, html){
								if(err){
									console.log(err);
								} else {
									res.send(html);
								}
							});
							return;
						}
						var bodyData = 'apikey=' + keys.ALCHEMY + '&text=' + encodeURIComponent(item.message) + '&outputMode=json';
						request({method: 'post', url:'http://access.alchemyapi.com/calls/text/TextGetTextSentiment', body:bodyData}, function(error, response, body){
							if(!error && response.statusCode == 200){
								body = JSON.parse(body);
								if(body.docSentiment){
									var sentiment = {
										type: body.docSentiment.type,
										value: body.docSentiment.score
									};
									var viewData = {
										post: item,
										sentiment: sentiment,
										page: page,
										name: 'Random User'
									};
									res.render('page', viewData, function(err, html){
										if(err){
											console.log(err);
										} else {
											res.send(html);
										}
									});
								} else {
									console.log(body);
									console.log(bodyData);
									res.send(500, 'Could not get a sentiment');
								}
							} else {
								console.log(body);
								console.log(bodyData);
								res.send(500, 'Could not get a sentiment');
							}
						});
					}
				});
			}
		});
	} else {
		res.redirect('/');
	}
});

app.post('/:pageid', function(req, res){
	if(req.query.pageToken){
		//have to register with facebook and save some data to firebase
		var bodyData = 'object=page&fields=feed&verify_token=flashing7&callback_url=' + encodeURIComponent('http://realtime.feedlisten.com/');
		request({json: true, url: 'https://graph.facebook.com/' + APP_ID + '/subscriptions', method: 'post', body:bodyData}, function(error, response, body){
			if(!error && response.statusCode == 200){
				fb_root.child(req.params.pageid).set({
					token: req.query.pageToken,
					email: req.body.email,
					type: req.body.type
				}, function(fbError){
					if(fbError){
						console.log(fbError);
					} else {
						res.send('The email was registered successfully! There\'s no way to unregister :-P');
					}
				});

			} else {
				console.log(error);
				console.log(bodyData);
				res.send(500, 'We had a problem.');
			}
		});
	} else {
		res.send(500, 'Could not register the email');
	}
});

app.get('/:pageid/:postid', function(req, res){
	res.send('Nope');
});

app.listen(80);<commit_msg>screw it<commit_after>var _ = require('underscore');
var express = require('express');
var request = require('request');
var handlebars = require('handlebars');
var hbs = require('hbs');
var sendgrid = require('sendgrid');
var keys = require(__dirname + '/keys.js');
console.log(keys);
var Firebase = require('firebase');
var FirebaseTokenGenerator = require('firebase-token-generator');
var fb_root = new Firebase('https://feedlisten.firebaseio.com/');
var tokenGenerator = new FirebaseTokenGenerator('nkn6OpQUq6gILOZq2vlrcH21P7aFtVCjgVLwQTYt');
var APP_ID = '384422024994164';

console.log(tokenGenerator.mSecret);
var adminToken = tokenGenerator.createToken({}, {
	admin: true,
	debug: false,
	expires: 1577836800
});

fb_root.auth(adminToken);

var app = express();

hbs.registerHelper('foreach', function(context, options) {
    var ret = "";
    for(var prop in context)
    {
        ret = ret + options.fn({
			property:prop, value:context[prop]
        });
    }
    return ret;
});

app.configure('development', function() {
	app.use(express.bodyParser());
	app.use(express.errorHandler());
	app.locals.pretty = true;

	app.set("view engine", 'tmpl');
	app.set("view options", { layout: false });

	app.engine('tmpl', require('hbs').__express);

	app.use(express.static(__dirname + '/public'));
	app.use(express.vhost('realtime.feedlisten.com', require('./realtime/index.js')));
});

app.get('/', function(req, res){
	if(req.query.token){
		//show page with selection of groups
		//maybe should be client-side js for loading the groups?
	} else {
		//send them a facebook auth screen - this could be done on the client side, too
	}
	res.send(__dirname + '/public/index.html');
});

app.get('/selection', function(req, res){
	if(req.query.token && req.query.fbid){
		request({json: true, url:'https://graph.facebook.com/me', qs:{'access_token':req.query.token}}, function(error, response, body){
			if(!error && response.statusCode == 200){
				var user_info = body;
				request({json: true, url:'https://graph.facebook.com/me/accounts', qs:{'access_token':req.query.token}}, function(error, response, body){
					if(!error && response.statusCode == 200){
						var data = {
							name: user_info.first_name,
							accessToken: req.query.token,
							pages: body.data
						};
						console.log(data);
						res.render('pages', data, function(err, html){
							if(err){
								console.log(err);
							} else {
								res.send(html);
							}
						});
					}
				});
			}
		});
	} else {
		res.redirect('/');
	}
});

app.get('/:pageid', function(req, res){
	if(req.query.token){
		request({json: true, url:'https://graph.facebook.com/me/accounts', qs:{'access_token':req.query.token}}, function(error, response, body){
			if(!error && response.statusCode == 200){
				var page;
				_.each(body.data, function(element){
					if(element.id == req.params.pageid){
						page = element;
					}
				});
				res.redirect('/' + page.id + '?pageToken=' + page.access_token);
			}
		});
	} else if(req.query.pageToken) {
		request({json: true, url:'https://graph.facebook.com/' + req.params.pageid, qs:{'access_token':req.query.pageToken}}, function(error, response, body){
			if(!error && response.statusCode == 200){
				var page = body;
				request({json: true, url:'https://graph.facebook.com/' + req.params.pageid, qs:{'fields':'feed', 'access_token':req.query.pageToken}}, function(error, response, body){
					if(!error && response.statusCode == 200){
						var item;
						if(body.feed){
							item = body.feed.data[0];
						} else {
							var viewData = {
								page:page,
								name:'Random User'
							};
							res.render('page', viewData, function(err, html){
								if(err){
									console.log(err);
								} else {
									res.send(html);
								}
							});
							return;
						}
						var bodyData = 'apikey=' + keys.ALCHEMY + '&text=' + encodeURIComponent(item.message) + '&outputMode=json';
						request({method: 'post', url:'http://access.alchemyapi.com/calls/text/TextGetTextSentiment', body:bodyData}, function(error, response, body){
							if(!error && response.statusCode == 200){
								body = JSON.parse(body);
								if(body.docSentiment){
									var sentiment = {
										type: body.docSentiment.type,
										value: body.docSentiment.score
									};
									var viewData = {
										post: item,
										sentiment: sentiment,
										page: page,
										name: 'Random User'
									};
									res.render('page', viewData, function(err, html){
										if(err){
											console.log(err);
										} else {
											res.send(html);
										}
									});
								} else {
									console.log(body);
									console.log(bodyData);
									res.send(500, 'Could not get a sentiment');
								}
							} else {
								console.log(body);
								console.log(bodyData);
								res.send(500, 'Could not get a sentiment');
							}
						});
					}
				});
			}
		});
	} else {
		res.redirect('/');
	}
});

app.post('/:pageid', function(req, res){
	if(req.query.pageToken){
		//have to register with facebook and save some data to firebase
		var bodyData = 'object=page&fields=feed&verify_token=flashing7&callback_url=' + encodeURIComponent('http://realtime.feedlisten.com/');
		request({json: true, url: 'https://graph.facebook.com/' + APP_ID + '/subscriptions', method: 'post', body:bodyData}, function(error, response, body){
			if(!error && response.statusCode == 200){
				fb_root.child(req.params.pageid).set({
					token: req.query.pageToken,
					email: req.body.email,
					type: req.body.type
				}, function(fbError){
					if(fbError){
						console.log(fbError);
					} else {
						res.send('The email was registered successfully! There\'s no way to unregister :-P');
					}
				});

			} else {
				console.log(error);
				console.log(bodyData);
				res.send(500, 'We had a problem.');
			}
		});
	} else {
		res.send(500, 'Could not register the email');
	}
});

app.get('/:pageid/:postid', function(req, res){
	res.send('Nope');
});

app.listen(80);<|endoftext|>


<commit_before><commit_msg>Get code position of mouse click<commit_after>function getPosition(e, $dom) {
  const rect = $dom.getBoundingClientRect()
  return {
    x: Math.floor((e.clientX - rect.left - 60) / 7.223),
    y: Math.floor((e.clientY - rect.top) / 20)
  }
}

function main() {
  const $dom = document.querySelector('table')
  if (!$dom) {
    return
  }

  const code = $dom.innerText

  $dom.addEventListener('click', function (e) {
    const position = getPosition(e, $dom)
    // console.log(e)
    // console.log(e.offsetX, e.offsetY)
    console.log(position)
  })
}

main()
<|endoftext|>


<commit_before>var chessground = require('chessground');
var round = require('../round');
var partial = chessground.util.partial;
var throttle = require('lodash-node/modern/functions/throttle');

module.exports = {
  standard: function(ctrl, condition, icon, hint, socketMsg) {
    return condition(ctrl.data) ? m('button', {
      class: 'button hint--bottom',
      'data-hint': ctrl.trans(hint),
      onclick: partial(ctrl.socket.send, socketMsg, null)
    }, m('span[data-icon=' + icon + ']')) : null;
  },
  forceResign: function(ctrl) {
    if (!ctrl.data.opponent.ai && !ctrl.data.opponent.onGame && round.resignable(ctrl.data))
      return m('div.force_resign_zone', [
        ctrl.trans('theOtherPlayerHasLeftTheGameYouCanForceResignationOrWaitForHim'),
        m('br'),
        m('a.button', {
          onclick: partial(ctrl.socket.send, 'resign-force'),
        }, ctrl.trans('forceResignation')),
        m('a.button', {
          onclick: partial(ctrl.socket.send, 'draw-force'),
        }, ctrl.trans('forceDraw'))
      ]);
  },
  threefoldClaimDraw: function(ctrl) {
    if (ctrl.data.game.threefold) return m('div#claim_draw_zone', [
      ctrl.trans('threefoldRepetition'),
      m.trust(' '),
      m('a.button', {
        onclick: partial(ctrl.socket.send, 'draw-claim', null)
      }, ctrl.trans('claimADraw'))
    ]);
  },
  cancelDrawOffer: function(ctrl) {
    if (ctrl.data.player.offeringDraw) return m('div.negotiation', [
      ctrl.trans('drawOfferSent') + ' ',
      m('a', {
        onclick: partial(ctrl.socket.send, 'draw-no', null)
      }, ctrl.trans('cancel'))
    ]);
  },
  answerOpponentDrawOffer: function(ctrl) {
    if (ctrl.data.opponent.offeringDraw) return m('div.negotiation', [
      ctrl.trans('yourOpponentOffersADraw'),
      m('br'),
      m('a.button[data-icon=E]', {
        onclick: partial(ctrl.socket.send, 'draw-yes', null)
      }, ctrl.trans('accept')),
      m.trust(' '),
      m('a.button[data-icon=L]', {
        onclick: partial(ctrl.socket.send, 'draw-no', null)
      }, ctrl.trans('decline')),
    ]);
  },
  cancelTakebackProposition: function(ctrl) {
    if (ctrl.data.player.proposingTakeback) return m('div.negotiation', [
      ctrl.trans('takebackPropositionSent') + ' ',
      m('a', {
        onclick: partial(ctrl.socket.send, 'takeback-no', null)
      }, ctrl.trans('cancel'))
    ]);
  },
  answerOpponentTakebackProposition: function(ctrl) {
    if (ctrl.data.opponent.proposingTakeback) return m('div.negotiation', [
      ctrl.trans('yourOpponentProposesATakeback'),
      m('br'),
      m('a.button[data-icon=E]', {
        onclick: partial(ctrl.socket.send, 'takeback-yes', null)
      }, ctrl.trans('accept')),
      m.trust(' '),
      m('a.button[data-icon=L]', {
        onclick: partial(ctrl.socket.send, 'takeback-no', null)
      }, ctrl.trans('decline')),
    ]);
  },
  rematch: function(ctrl) {
    return m('a.rematch.offer.button.hint--bottom', {
      'data-hint': ctrl.trans('playWithTheSameOpponentAgain'),
      onclick: partial(ctrl.socket.send, 'rematch-yes', null)
    }, ctrl.trans('rematch'));
  },
  answerOpponentRematch: function(ctrl) {
    if (ctrl.data.opponent.offeringRematch) return m('div.lichess_play_again_join.rematch_alert', [
      ctrl.trans('yourOpponentWantsToPlayANewGameWithYou'),
      m('a.glowing.button.lichess_play_again.rematch.hint--bottom', {
        'data-hint': ctrl.trans('playWithTheSameOpponentAgain'),
        onclick: partial(ctrl.socket.send, 'rematch-yes', null),
      }, ctrl.trans('joinTheGame')),
      m('a', {
        onclick: partial(ctrl.socket.send, 'rematch-no', null),
      }, ctrl.trans('declineInvitation'))
    ]);
  },
  cancelRematch: function(ctrl) {
    if (ctrl.data.player.offeringRematch) return m('div.lichess_play_again_join.rematch_wait', [
      ctrl.trans('rematchOfferSent'),
      m('br'),
      ctrl.trans('waitingForOpponent'),
      m('br'), m('br'),
      m('a.rematch_cancel', {
        onclick: partial(ctrl.socket.send, 'rematch-no', null),
      }, ctrl.trans('cancelRematchOffer'))
    ]);
  },
  newGame: function(ctrl) {
    if (!ctrl.data.offeringRematch) return m('a.lichess_new_game.button.hint--bottom', {
      'data-hint': ctrl.trans('playWithAnotherOpponent'),
      href: ctrl.router.Lobby.home().url
    }, ctrl.trans('newOpponent'));
  },
  backToTournament: function(ctrl) {
    if (ctrl.data.tournament) return m('a[data-icon=G].button' + (ctrl.data.tournament.running ? '.strong.glowing' : ''), {
      href: ctrl.router.Tournament.show(ctrl.data.tournament.id).url
    }, ctrl.trans('backToTournament'));
  },
  moretime: function(ctrl) {
    if (round.moretimeable(ctrl.data)) return m('a.moretime.hint--bottom-left', {
      'data-hint': ctrl.trans('giveNbSeconds', ctrl.data.clock.moretime),
      onclick: throttle(partial(ctrl.socket.send, 'moretime', null), 600)
    }, m('span[data-icon=O]'));
  },
  flip: function(ctrl) {
    if (ctrl.data.player.spectator) return m('div.underboard',
      m('a.button[data-icon=B]', {
        href: ctrl.router.Round.watcher(ctrl.data.game.id, chessground.util.opposite(ctrl.data.player.color)).url
      }, ctrl.trans('flipBoard')));
  },
  replayAndAnalyse: function(ctrl) {
    if (round.replayable(ctrl.data)) return m('a.button.replay_and_analyse[data-icon=G]', {
      href: ctrl.router.Round.watcher(ctrl.data.game.id, ctrl.data.player.color).url
    }, ctrl.trans('replayAndAnalyse'));
  }
};
<commit_msg>don't show new opponent button for tournament games<commit_after>var chessground = require('chessground');
var round = require('../round');
var partial = chessground.util.partial;
var throttle = require('lodash-node/modern/functions/throttle');

module.exports = {
  standard: function(ctrl, condition, icon, hint, socketMsg) {
    return condition(ctrl.data) ? m('button', {
      class: 'button hint--bottom',
      'data-hint': ctrl.trans(hint),
      onclick: partial(ctrl.socket.send, socketMsg, null)
    }, m('span[data-icon=' + icon + ']')) : null;
  },
  forceResign: function(ctrl) {
    if (!ctrl.data.opponent.ai && !ctrl.data.opponent.onGame && round.resignable(ctrl.data))
      return m('div.force_resign_zone', [
        ctrl.trans('theOtherPlayerHasLeftTheGameYouCanForceResignationOrWaitForHim'),
        m('br'),
        m('a.button', {
          onclick: partial(ctrl.socket.send, 'resign-force'),
        }, ctrl.trans('forceResignation')),
        m('a.button', {
          onclick: partial(ctrl.socket.send, 'draw-force'),
        }, ctrl.trans('forceDraw'))
      ]);
  },
  threefoldClaimDraw: function(ctrl) {
    if (ctrl.data.game.threefold) return m('div#claim_draw_zone', [
      ctrl.trans('threefoldRepetition'),
      m.trust(' '),
      m('a.button', {
        onclick: partial(ctrl.socket.send, 'draw-claim', null)
      }, ctrl.trans('claimADraw'))
    ]);
  },
  cancelDrawOffer: function(ctrl) {
    if (ctrl.data.player.offeringDraw) return m('div.negotiation', [
      ctrl.trans('drawOfferSent') + ' ',
      m('a', {
        onclick: partial(ctrl.socket.send, 'draw-no', null)
      }, ctrl.trans('cancel'))
    ]);
  },
  answerOpponentDrawOffer: function(ctrl) {
    if (ctrl.data.opponent.offeringDraw) return m('div.negotiation', [
      ctrl.trans('yourOpponentOffersADraw'),
      m('br'),
      m('a.button[data-icon=E]', {
        onclick: partial(ctrl.socket.send, 'draw-yes', null)
      }, ctrl.trans('accept')),
      m.trust(' '),
      m('a.button[data-icon=L]', {
        onclick: partial(ctrl.socket.send, 'draw-no', null)
      }, ctrl.trans('decline')),
    ]);
  },
  cancelTakebackProposition: function(ctrl) {
    if (ctrl.data.player.proposingTakeback) return m('div.negotiation', [
      ctrl.trans('takebackPropositionSent') + ' ',
      m('a', {
        onclick: partial(ctrl.socket.send, 'takeback-no', null)
      }, ctrl.trans('cancel'))
    ]);
  },
  answerOpponentTakebackProposition: function(ctrl) {
    if (ctrl.data.opponent.proposingTakeback) return m('div.negotiation', [
      ctrl.trans('yourOpponentProposesATakeback'),
      m('br'),
      m('a.button[data-icon=E]', {
        onclick: partial(ctrl.socket.send, 'takeback-yes', null)
      }, ctrl.trans('accept')),
      m.trust(' '),
      m('a.button[data-icon=L]', {
        onclick: partial(ctrl.socket.send, 'takeback-no', null)
      }, ctrl.trans('decline')),
    ]);
  },
  rematch: function(ctrl) {
    return m('a.rematch.offer.button.hint--bottom', {
      'data-hint': ctrl.trans('playWithTheSameOpponentAgain'),
      onclick: partial(ctrl.socket.send, 'rematch-yes', null)
    }, ctrl.trans('rematch'));
  },
  answerOpponentRematch: function(ctrl) {
    if (ctrl.data.opponent.offeringRematch) return m('div.lichess_play_again_join.rematch_alert', [
      ctrl.trans('yourOpponentWantsToPlayANewGameWithYou'),
      m('a.glowing.button.lichess_play_again.rematch.hint--bottom', {
        'data-hint': ctrl.trans('playWithTheSameOpponentAgain'),
        onclick: partial(ctrl.socket.send, 'rematch-yes', null),
      }, ctrl.trans('joinTheGame')),
      m('a', {
        onclick: partial(ctrl.socket.send, 'rematch-no', null),
      }, ctrl.trans('declineInvitation'))
    ]);
  },
  cancelRematch: function(ctrl) {
    if (ctrl.data.player.offeringRematch) return m('div.lichess_play_again_join.rematch_wait', [
      ctrl.trans('rematchOfferSent'),
      m('br'),
      ctrl.trans('waitingForOpponent'),
      m('br'), m('br'),
      m('a.rematch_cancel', {
        onclick: partial(ctrl.socket.send, 'rematch-no', null),
      }, ctrl.trans('cancelRematchOffer'))
    ]);
  },
  newGame: function(ctrl) {
    if (!ctrl.data.offeringRematch && !ctrl.data.tournament) return m('a.lichess_new_game.button.hint--bottom', {
      'data-hint': ctrl.trans('playWithAnotherOpponent'),
      href: ctrl.router.Lobby.home().url
    }, ctrl.trans('newOpponent'));
  },
  backToTournament: function(ctrl) {
    if (ctrl.data.tournament) return m('a[data-icon=G].button' + (ctrl.data.tournament.running ? '.strong.glowing' : ''), {
      href: ctrl.router.Tournament.show(ctrl.data.tournament.id).url
    }, ctrl.trans('backToTournament'));
  },
  moretime: function(ctrl) {
    if (round.moretimeable(ctrl.data)) return m('a.moretime.hint--bottom-left', {
      'data-hint': ctrl.trans('giveNbSeconds', ctrl.data.clock.moretime),
      onclick: throttle(partial(ctrl.socket.send, 'moretime', null), 600)
    }, m('span[data-icon=O]'));
  },
  flip: function(ctrl) {
    if (ctrl.data.player.spectator) return m('div.underboard',
      m('a.button[data-icon=B]', {
        href: ctrl.router.Round.watcher(ctrl.data.game.id, chessground.util.opposite(ctrl.data.player.color)).url
      }, ctrl.trans('flipBoard')));
  },
  replayAndAnalyse: function(ctrl) {
    if (round.replayable(ctrl.data)) return m('a.button.replay_and_analyse[data-icon=G]', {
      href: ctrl.router.Round.watcher(ctrl.data.game.id, ctrl.data.player.color).url
    }, ctrl.trans('replayAndAnalyse'));
  }
};
<|endoftext|>


<commit_before>/* Estonian initialisation for the jQuery UI date picker plugin. */
/* Written by Mart Sõmermaa (mrts.pydev at gmail com). */
$.datepicker.regional['et'] = {
    closeText: "Sulge",
    prevText: "Eelnev",
    nextText: "Järgnev",
    currentText: "Täna",
    monthNames: ["Jaanuar", "Veebruar", "Märts", "Aprill", "Mai", "Juuni",
        "Juuli", "August", "September", "Oktoober", "November", "Detsember"],
    monthNamesShort: ["Jaan", "Veebr", "Märts", "Apr", "Mai", "Juuni",
        "Juuli", "Aug", "Sept", "Okt", "Nov", "Dets"],
    dayNames: [
        "Pühapäev",
        "Esmaspäev",
        "Teisipäev",
        "Kolmapäev",
        "Neljapäev",
        "Reede",
        "Laupäev"
    ],
    dayNamesShort: ["Pühap", "Esmasp", "Teisip", "Kolmap", "Neljap", "Reede", "Laup"],
    dayNamesMin: ["P", "E", "T", "K", "N", "R", "L"],
    weekHeader: "näd",
    dateFormat: "dd.mm.yy",
    firstDay: 1,
    isRTL: false,
    showMonthAfterYear: false,
    yearSuffix: ""
};

$.datepicker.setDefaults($.datepicker.regional['et']);

var lastQuery = null;
var url = window.location.href + "_async"; // the script where you handle the form input.
var table;
$(document).ready(function () {
        table = $("#results");
        table.tablesorter();

        addFormListener($("#exact"));
        addFormListener($("#general"));

        window.onscroll = function (ev) {
            if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight && lastQuery != null) {
                queryNewRows(lastQuery + "&new=false");
            }
        };

        $("#search_quick_date").datepicker(
            {
                dateFormat: "dd-mm-yy"
            }
        );

        $("#search_date_long").datepicker(
            {
                dateFormat: "dd-mm-yy",
            }
        );

    }
);
/**
 * Override default posting of form and use AJAX instead
 */
function addFormListener(form) {
    form.submit(function (e) {
        table.find("td").remove();
        lastQuery = form.serialize();
        queryNewRows(lastQuery);
        e.preventDefault(); // avoid to execute the actual submit of the form.
    });
}

function queryNewRows(query) {
    $.ajax({
        type: "POST",
        url: url,
        data: query, // serializes the form's elements.
        success: function (data) {
            table.find('tbody').append(data);
            table.trigger("update");
        }
    });
}

<commit_msg>rm unnecessary comma from search.js #79<commit_after>/* Estonian initialisation for the jQuery UI date picker plugin. */
/* Written by Mart Sõmermaa (mrts.pydev at gmail com). */
$.datepicker.regional['et'] = {
    closeText: "Sulge",
    prevText: "Eelnev",
    nextText: "Järgnev",
    currentText: "Täna",
    monthNames: ["Jaanuar", "Veebruar", "Märts", "Aprill", "Mai", "Juuni",
        "Juuli", "August", "September", "Oktoober", "November", "Detsember"],
    monthNamesShort: ["Jaan", "Veebr", "Märts", "Apr", "Mai", "Juuni",
        "Juuli", "Aug", "Sept", "Okt", "Nov", "Dets"],
    dayNames: [
        "Pühapäev",
        "Esmaspäev",
        "Teisipäev",
        "Kolmapäev",
        "Neljapäev",
        "Reede",
        "Laupäev"
    ],
    dayNamesShort: ["Pühap", "Esmasp", "Teisip", "Kolmap", "Neljap", "Reede", "Laup"],
    dayNamesMin: ["P", "E", "T", "K", "N", "R", "L"],
    weekHeader: "näd",
    dateFormat: "dd.mm.yy",
    firstDay: 1,
    isRTL: false,
    showMonthAfterYear: false,
    yearSuffix: ""
};

$.datepicker.setDefaults($.datepicker.regional['et']);

var lastQuery = null;
var url = window.location.href + "_async"; // the script where you handle the form input.
var table;
$(document).ready(function () {
        table = $("#results");
        table.tablesorter();

        addFormListener($("#exact"));
        addFormListener($("#general"));

        window.onscroll = function (ev) {
            if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight && lastQuery != null) {
                queryNewRows(lastQuery + "&new=false");
            }
        };

        $("#search_quick_date").datepicker(
            {
                dateFormat: "dd-mm-yy"
            }
        );

        $("#search_date_long").datepicker(
            {
                dateFormat: "dd-mm-yy"
            }
        );

    }
);
/**
 * Override default posting of form and use AJAX instead
 */
function addFormListener(form) {
    form.submit(function (e) {
        table.find("td").remove();
        lastQuery = form.serialize();
        queryNewRows(lastQuery);
        e.preventDefault(); // avoid to execute the actual submit of the form.
    });
}

function queryNewRows(query) {
    $.ajax({
        type: "POST",
        url: url,
        data: query, // serializes the form's elements.
        success: function (data) {
            table.find('tbody').append(data);
            table.trigger("update");
        }
    });
}

<|endoftext|>


<commit_before>const bot = require('./bot');
const functions = require('./functions');
const music = require('./music');
const bf2 = require('./bf2');
const bf2142 = require('./bf2142');
const Discord = require('discord.js')

bot.on('message', message => {
    if (!message.content.startsWith('~')) {
        return;
    } //base case
    var cmd = message.content.split(' ')[0].substring(1).toLowerCase();
    commands[cmd].exec(message);
});
var commands = {
    'pong': {
        description: 'reply with a pong',
        syntax: '~ping',
        exec: function(message) {
            message.reply('pong');
        }
    },
    'yo': {
        description: 'reply with a yo bro',
        syntax: '~yo',
        exec: function(message) {
            message.reply('yo bro');
        }
    },
    'link': {
        description: 'link revive account to this discord account',
        syntax: '~link',
        exec: function(message) {
            functions.integrate(message.author);
        }
    },
    'refresh': {
        description: 'refresh a user discord link status',
        syntax: '~refresh',
        exec: function(message) {
            if (message.content.substring(9).trim() == 'all' &&
                message.guild.name == 'Revive Netowrk Dev') {
                functions.refreshAll(bot.guilds.get('184536578654339072').members.array())
            } else {
                functions.refreshUser(message.author);
            }
        }
    },
    'bf2': {
        description: 'finds a bf2 player',
        syntax: '~bf2 <PlayerName>',
        exec: function(message) {
            var nick = message.content.substring(5).trim();
            var plist = bf2.getPlayers(nick);
            console.log("BF2 in index.js gets executed");
            if (plist == null) {
                message.channel.sendMessage("API Down or invalid search");
                return;
            }
            if (plist.length >= 1) {
                //checking for exact matches
                var exact = plist.find(o => o.nick.toUpperCase().trim() === nick.toUpperCase());
                console.log(exact);
                var res = "**S.no.\tName \t PID \t Score**";
            }
			    if (plist.length == 0) {
                message.channel.sendMessage("Player not found"); return;
            }
            var start = 0;
            var past = 0;
            if (exact != null) {
                res = res + "\n" + (1) + "\t" + "\t" + exact.str();
                start++;
            }
            for (var i = start; i < plist.length; i++) {
                if (exact != null && i == plist.indexOf(exact)) {
                    past++;
                    continue;
                }
                if (i == 26) {
                    res = res + "\n" + (plist.length - 25) +
                        " more players found to Get a full list of players \n" +
                        "<https://battlelog.co/player_search.php?q=" + nick + ">";
                    break;
                } else {
                    res = res + " \n" + (i + 1 - past) +
                        "\t" + "\t" + plist[i].str();
                }
            }
			message.channel.sendMessage(res);
			console.log(res);
        }
    },
    'bf2142': {
        description: 'finds a bf2142 player',
        syntax: '~bf2142 <PlayerName>',
        exec: function(message) {

            var nick = message.content.substring(7).trim();
            var plist = bf2142.getPlayers(nick);
            console.log("BF2142 in index.js gets executed");
            if (plist == null) {
                message.channel.sendMessage("API Down or invalid search");
                return;
            }
            if (plist.length >= 1) {
                //checking for exact matches
                var exact = plist.find(o => o.nick.toUpperCase().trim() === nick.toUpperCase());
                console.log(exact);
                var res = "**S.no.\tName \t PID**";
            }
			if (plist.length == 0) {
                message.channel.sendMessage("Player not found");return;
            }
            var start = 0;
            var past = 0;
            if (exact != null) {
                res = res + "\n" + (1) + "\t" + "\t" + exact.str();
                start++;
            }
            for (var i = start; i < plist.length; i++) {
                if (exact != null && i == plist.indexOf(exact)) {
                    past++;
                    continue;
                }
                if (i == 26) {
                    res = res + "\n" + (plist.length - 25) +
                        " more players found to Get a full list of players \n" +
                        "<https://battlelog.co/player_search.php?q=" + nick + ">";
                    break;
                } else {
                    res = res + " \n" + (i + 1 - past) +
                        "\t" + "\t" + plist[i].str();
                }
            }
			message.channel.sendMessage(res);
			console.log(res);
        }
    },
    'cookie': {
        description: 'eats a cookie',
        syntax: '~cookie',
        exec: function(message) {
            message.reply('crunch crunch');
        }
    },
    'add': {
        description: 'adds a person to a role',
        syntax: '~add <UserMention> to <roleName>',
        exec: function(message) {
            if (!message.member.hasPermission("MANAGE_ROLES_OR_PERMISSIONS")) {
                message.channel.sendMessage("You aren't Worthy");
                return;
            }
            var member = message.guild.member(message.mentions.users.first());
            var msg = message.content.split("to ");
            member.addRole(message.guild.roles.find("name", msg[msg.length - 1]));
            message.reply('done');
        }
    },
    'remove': {
        description: 'removes a person to a role',
        syntax: '~remove <UserMention> from <roleName>',
        exec: function(message) {
            if (!message.member.hasPermission("MANAGE_ROLES_OR_PERMISSIONS")) {
                message.channel.sendMessage("You aren't Worthy");
                return;
            }
            var member = message.guild.member(message.mentions.users.first());
            var msg = message.content.split("to ");
            member.removeRole(message.guild.roles.find("name", msg[msg.length - 1]));
            message.reply('done');
        }
    },
    'help': {
        description: 'displays help',
        syntax: '~help',
        exec: function(message) {
			var embed = new Discord.RichEmbed().setTitle('HELP').setColor("#FF7F50");
            for (cmd in commands) {
                embed.addField(cmd,"Description: " + commands[cmd].description + "\n"+ "Syntax: " + commands[cmd].syntax);
			}
			//embed.addField('Music',"Description: Access the music bot using - as the prefix" + "\n"+ "Syntax: -help");
            message.channel.sendEmbed(embed);
        }
    },
	'play': {
        description: 'plays the youtube url specified',
        syntax: '~play <youtube_url>',
        exec: function(message) {
			url = message.content.substring(6).trim();
			music.play(url,message.member);
        }
    },
	'pause': {
        description: 'pauses the voice stream',
        syntax: '~pause',
        exec: function(message) {
			music.pause();
        }
    },
	'resume': {
        description: 'resumes the voice stream',
        syntax: '~resume',
        exec: function(message) {
			music.resume();
        }
    },
	'clear': {
        description: 'clears the playlist',
        syntax: '~clear',
        exec: function(message) {
			music.clear(message);
        }
    },
	'playNext': {
        description: 'plays the next song',
        syntax: '~playNext',
        exec: function(message) {
			music.playNext();
        }
    },
	'setVol': {
        description: 'sets the play volume',
        syntax: '~setVol',
        exec: function(message) {
			music.setVol(message.content.substring(7).trim());
        }
    }
}
<commit_msg>Added queue<commit_after>const bot = require('./bot');
const functions = require('./functions');
const music = require('./music');
const bf2 = require('./bf2');
const bf2142 = require('./bf2142');
const Discord = require('discord.js')

bot.on('message', message => {
    if (!message.content.startsWith('~')) {
        return;
    } //base case
    var cmd = message.content.split(' ')[0].substring(1).toLowerCase();
    commands[cmd].exec(message);
});
var commands = {
    'pong': {
        description: 'reply with a pong',
        syntax: '~ping',
        exec: function(message) {
            message.reply('pong');
        }
    },
    'yo': {
        description: 'reply with a yo bro',
        syntax: '~yo',
        exec: function(message) {
            message.reply('yo bro');
        }
    },
    'link': {
        description: 'link revive account to this discord account',
        syntax: '~link',
        exec: function(message) {
            functions.integrate(message.author);
        }
    },
    'refresh': {
        description: 'refresh a user discord link status',
        syntax: '~refresh',
        exec: function(message) {
            if (message.content.substring(9).trim() == 'all' &&
                message.guild.name == 'Revive Netowrk Dev') {
                functions.refreshAll(bot.guilds.get('184536578654339072').members.array())
            } else {
                functions.refreshUser(message.author);
            }
        }
    },
    'bf2': {
        description: 'finds a bf2 player',
        syntax: '~bf2 <PlayerName>',
        exec: function(message) {
            var nick = message.content.substring(5).trim();
            var plist = bf2.getPlayers(nick);
            console.log("BF2 in index.js gets executed");
            if (plist == null) {
                message.channel.sendMessage("API Down or invalid search");
                return;
            }
            if (plist.length >= 1) {
                //checking for exact matches
                var exact = plist.find(o => o.nick.toUpperCase().trim() === nick.toUpperCase());
                console.log(exact);
                var res = "**S.no.\tName \t PID \t Score**";
            }
			    if (plist.length == 0) {
                message.channel.sendMessage("Player not found"); return;
            }
            var start = 0;
            var past = 0;
            if (exact != null) {
                res = res + "\n" + (1) + "\t" + "\t" + exact.str();
                start++;
            }
            for (var i = start; i < plist.length; i++) {
                if (exact != null && i == plist.indexOf(exact)) {
                    past++;
                    continue;
                }
                if (i == 26) {
                    res = res + "\n" + (plist.length - 25) +
                        " more players found to Get a full list of players \n" +
                        "<https://battlelog.co/player_search.php?q=" + nick + ">";
                    break;
                } else {
                    res = res + " \n" + (i + 1 - past) +
                        "\t" + "\t" + plist[i].str();
                }
            }
			message.channel.sendMessage(res);
			console.log(res);
        }
    },
    'bf2142': {
        description: 'finds a bf2142 player',
        syntax: '~bf2142 <PlayerName>',
        exec: function(message) {

            var nick = message.content.substring(7).trim();
            var plist = bf2142.getPlayers(nick);
            console.log("BF2142 in index.js gets executed");
            if (plist == null) {
                message.channel.sendMessage("API Down or invalid search");
                return;
            }
            if (plist.length >= 1) {
                //checking for exact matches
                var exact = plist.find(o => o.nick.toUpperCase().trim() === nick.toUpperCase());
                console.log(exact);
                var res = "**S.no.\tName \t PID**";
            }
			if (plist.length == 0) {
                message.channel.sendMessage("Player not found");return;
            }
            var start = 0;
            var past = 0;
            if (exact != null) {
                res = res + "\n" + (1) + "\t" + "\t" + exact.str();
                start++;
            }
            for (var i = start; i < plist.length; i++) {
                if (exact != null && i == plist.indexOf(exact)) {
                    past++;
                    continue;
                }
                if (i == 26) {
                    res = res + "\n" + (plist.length - 25) +
                        " more players found to Get a full list of players \n" +
                        "<https://battlelog.co/player_search.php?q=" + nick + ">";
                    break;
                } else {
                    res = res + " \n" + (i + 1 - past) +
                        "\t" + "\t" + plist[i].str();
                }
            }
			message.channel.sendMessage(res);
			console.log(res);
        }
    },
    'cookie': {
        description: 'eats a cookie',
        syntax: '~cookie',
        exec: function(message) {
            message.reply('crunch crunch');
        }
    },
    'add': {
        description: 'adds a person to a role',
        syntax: '~add <UserMention> to <roleName>',
        exec: function(message) {
            if (!message.member.hasPermission("MANAGE_ROLES_OR_PERMISSIONS")) {
                message.channel.sendMessage("You aren't Worthy");
                return;
            }
            var member = message.guild.member(message.mentions.users.first());
            var msg = message.content.split("to ");
            member.addRole(message.guild.roles.find("name", msg[msg.length - 1]));
            message.reply('done');
        }
    },
    'remove': {
        description: 'removes a person to a role',
        syntax: '~remove <UserMention> from <roleName>',
        exec: function(message) {
            if (!message.member.hasPermission("MANAGE_ROLES_OR_PERMISSIONS")) {
                message.channel.sendMessage("You aren't Worthy");
                return;
            }
            var member = message.guild.member(message.mentions.users.first());
            var msg = message.content.split("to ");
            member.removeRole(message.guild.roles.find("name", msg[msg.length - 1]));
            message.reply('done');
        }
    },
    'help': {
        description: 'displays help',
        syntax: '~help',
        exec: function(message) {
			var embed = new Discord.RichEmbed().setTitle('HELP').setColor("#FF7F50");
            for (cmd in commands) {
                embed.addField(cmd,"Description: " + commands[cmd].description + "\n"+ "Syntax: " + commands[cmd].syntax);
			}
			//embed.addField('Music',"Description: Access the music bot using - as the prefix" + "\n"+ "Syntax: -help");
            message.channel.sendEmbed(embed);
        }
    },
	'play': {
        description: 'plays the youtube url specified',
        syntax: '~play <youtube_url>',
        exec: function(message) {
			url = message.content.substring(6).trim();
			music.play(url,message.member);
        }
    },
	'pause': {
        description: 'pauses the voice stream',
        syntax: '~pause',
        exec: function(message) {
			music.pause();
        }
    },
	'resume': {
        description: 'resumes the voice stream',
        syntax: '~resume',
        exec: function(message) {
			music.resume();
        }
    },
	'clear': {
        description: 'clears the playlist',
        syntax: '~clear',
        exec: function(message) {
			music.clear(message);
        }
    },
	'playNext': {
        description: 'plays the next song',
        syntax: '~playNext',
        exec: function(message) {
			music.playNext();
        }
    },
	'setVol': {
        description: 'sets the play volume',
        syntax: '~setVol',
        exec: function(message) {
			music.setVol(message.content.substring(7).trim());
        }
    }
	'queue': {
        description: 'views the queue',
        syntax: '~queue',
        exec: function(message) {
			message.channel.sendMessage(music.queue.join("\n"));
        }
    }
}
<|endoftext|>


<commit_before>/**
 * @flow
 */

import chalk from 'chalk';
import simpleSpinner from '@expo/simple-spinner';

import { Project } from 'xdl';

import log from '../log';
import sendTo from '../sendTo';
import { installExitHooks } from '../exit';

type Options = {
  sendTo?: string,
  quiet?: boolean,
};

export async function action(projectDir: string, options: Options = {}) {
  let channelRe = new RegExp(/^[a-z\d][a-z\d._-]*$/);
  if (!channelRe.test(options.releaseChannel)) {
      log.error('Release channel name can only contain lowercase letters, numbers and special characters . _ and -');
      process.exit(1);
  }
  const status = await Project.currentStatus(projectDir);

  let startedOurOwn = false;
  if (status !== 'running') {
    log('Unable to find an existing exp instance for this directory, starting a new one...');
    installExitHooks(projectDir);
    await Project.startAsync(projectDir, {}, !options.quiet);
    startedOurOwn = true;
  }

  let recipient = await sendTo.getRecipient(options.sendTo);
  log('Publishing...');

  if (options.quiet) {
    simpleSpinner.start();
  }

  let result = await Project.publishAsync(projectDir, {
    releaseChannel: options.releaseChannel,
  });

  if (options.quiet) {
    simpleSpinner.stop();
  }

  log('Published');
  log('Your URL is\n\n' + chalk.underline(result.url) + '\n');
  log.raw(result.url);

  if (recipient) {
    await sendTo.sendUrlAsync(result.url, recipient);
  }

  if (startedOurOwn) {
    await Project.stopAsync(projectDir);
  }

  return result;
}

export default (program: any) => {
  program
    .command('publish [project-dir]')
    .alias('p')
    .description('Publishes your project to exp.host')
    .option('-q, --quiet', 'Suppress verbose output from the React Native packager.')
    .option('-s, --send-to [dest]', 'A phone number or e-mail address to send a link to')
    .option(
      '-c --release-channel <release channel>',
      "The release channel to publish to. Default is 'default'.",
      'default'
    )
    .allowNonInteractive()
    .asyncActionProjectDir(action, true);
};
<commit_msg>Give url with query param when publishing to release channel through exp (#1487)<commit_after>/**
 * @flow
 */

import chalk from 'chalk';
import simpleSpinner from '@expo/simple-spinner';

import { Project } from 'xdl';

import log from '../log';
import sendTo from '../sendTo';
import { installExitHooks } from '../exit';

type Options = {
  sendTo?: string,
  quiet?: boolean,
  releaseChannel?: string,
};

export async function action(projectDir: string, options: Options = {}) {
  let channelRe = new RegExp(/^[a-z\d][a-z\d._-]*$/);
  if (options.releaseChannel && !channelRe.test(options.releaseChannel)) {
    log.error(
      'Release channel name can only contain lowercase letters, numbers and special characters . _ and -'
    );
    process.exit(1);
  }
  const status = await Project.currentStatus(projectDir);

  let startedOurOwn = false;
  if (status !== 'running') {
    log('Unable to find an existing exp instance for this directory, starting a new one...');
    installExitHooks(projectDir);
    await Project.startAsync(projectDir, {}, !options.quiet);
    startedOurOwn = true;
  }

  let recipient = await sendTo.getRecipient(options.sendTo);
  log('Publishing...');

  if (options.quiet) {
    simpleSpinner.start();
  }

  let result = await Project.publishAsync(projectDir, {
    releaseChannel: options.releaseChannel,
  });

  let url = result.url;

  // Append the query param for the release channel to the URL.
  // When we integrate release channels into XDE, we can revisit this and
  // perhaps push the logic for this into xdl
  if (options.releaseChannel && options.releaseChannel !== 'default') {
    url = `${url}?release-channel=${options.releaseChannel}`;
  }

  if (options.quiet) {
    simpleSpinner.stop();
  }

  log('Published');
  log('Your URL is\n\n' + chalk.underline(url) + '\n');
  log.raw(result.url);

  if (recipient) {
    await sendTo.sendUrlAsync(url, recipient);
  }

  if (startedOurOwn) {
    await Project.stopAsync(projectDir);
  }

  return result;
}

export default (program: any) => {
  program
    .command('publish [project-dir]')
    .alias('p')
    .description('Publishes your project to exp.host')
    .option('-q, --quiet', 'Suppress verbose output from the React Native packager.')
    .option('-s, --send-to [dest]', 'A phone number or e-mail address to send a link to')
    .option(
      '-c --release-channel <release channel>',
      "The release channel to publish to. Default is 'default'.",
      'default'
    )
    .allowNonInteractive()
    .asyncActionProjectDir(action, true);
};
<|endoftext|>


<commit_before>// Fetch the site configuration
var siteConf = require('./lib/getConfig');

process.title = siteConf.uri.replace(/http:\/\/(www)?/, '');

var airbrake;
if (siteConf.airbrakeApiKey) {
	airbrake = require('airbrake').createClient(siteConf.airbrakeApiKey);
}

process.addListener('uncaughtException', function (err, stack) {
	console.log('Caught exception: '+err+'\n'+err.stack);
	console.log('\u0007'); // Terminal bell
	if (airbrake) { airbrake.notify(err); }
});

var connect = require('connect');
var express = require('express');
var assetManager = require('connect-assetmanager');
var assetHandler = require('connect-assetmanager-handlers');
var notifoMiddleware = require('connect-notifo');
var DummyHelper = require('./lib/dummy-helper');

// Session store
var RedisStore = require('connect-redis')(express);
var sessionStore = new RedisStore;

var app = module.exports = express.createServer();
app.listen(siteConf.port, null);

// Setup socket.io server
var socketIo = new require('./lib/socket-io-server.js')(app, sessionStore);
var authentication = new require('./lib/authentication.js')(app, siteConf);
// Setup groups for CSS / JS assets
var assetsSettings = {
	'js': {
		'route': /\/static\/js\/[a-z0-9]+\/.*\.js/
		, 'path': './public/js/'
		, 'dataType': 'javascript'
		, 'files': [
			'http://code.jquery.com/jquery.min.js'
			//, siteConf.uri+'/socket.io/socket.io.js' // special case since the socket.io module serves its own js
			, 'plugins.js'
			, 'ejs/ejs_production.js'
			, 'client.js'

		]
		, 'debug': true
		, 'postManipulate': {
			'^': [
				assetHandler.uglifyJsOptimize
				, function insertSocketIoPort(file, path, index, isLast, callback) {
					callback(file.replace(/.#socketIoPort#./, siteConf.port));
				}
			]
		}
	},
        'css': {
		'route': /\/static\/css\/[a-z0-9]+\/.*\.css/
		, 'path': './public/css/'
		, 'dataType': 'css'
		, 'files': ['bootstrap.less']
		, 'debug': true
                , 'preManipulate': {
                    '^': [
                      assetHandler.lessCompile // CUSTOM HANDLER written by me :)
                    ]

                }
                , 'postManipulate': {
                        '^': [
                            assetHandler.fixVendorPrefixes
			    , assetHandler.fixGradients
		            , assetHandler.replaceImageRefToBase64(__dirname+'/public')
			    , assetHandler.yuiCssOptimize
                        ]
                }
	}
};

// Add auto reload for CSS/JS/templates when in development
app.configure('development', function(){
        assetsSettings.js.files.push('jquery.frontend-development.js');
        assetsSettings.css.files.push('frontend-development.css');
	[['js', 'updatedContent'], ['css', 'updatedCss']].forEach(function(group) {
		assetsSettings[group[0]].postManipulate['^'].push(function triggerUpdate(file, path, index, isLast, callback) {
			callback(file);
			dummyHelpers[group[1]]();
		});
	});
});

var assetsMiddleware = assetManager(assetsSettings);

// Settings
app.configure(function() {
	app.set('view engine', 'ejs');
	app.set('views', __dirname+'/views');
});

// Middleware
app.configure(function() {
	app.use(express.bodyParser());
	app.use(express.cookieParser());
	app.use(assetsMiddleware);
	app.use(express.session({
		'store': sessionStore
		, 'secret': siteConf.sessionSecret
	}));
	app.use(express.logger({format: ':response-time ms - :date - :req[x-real-ip] - :method :url :user-agent / :referrer'}));
	app.use(authentication.middleware.auth());
	app.use(authentication.middleware.normalizeUserData());
	app.use(express['static'](__dirname+'/public', {maxAge: 86400000}));
	app.use(express['static'](__dirname+'/views/frontend_templates'));

	// Send notification to computer/phone @ visit. Good to use for specific events or low traffic sites.
	if (siteConf.notifoAuth) {
		app.use(notifoMiddleware(siteConf.notifoAuth, {
			'filter': function(req, res, callback) {
				callback(null, (!req.xhr && !(req.headers['x-real-ip'] || req.connection.remoteAddress).match(/192.168./)));
			}
			, 'format': function(req, res, callback) {
				callback(null, {
					'title': ':req[x-real-ip]/:remote-addr @ :req[host]'
					, 'message': ':response-time ms - :date - :req[x-real-ip]/:remote-addr - :method :user-agent / :referrer'
				});
			}
		}));
	}
});

// ENV based configuration

// Show all errors and keep search engines out using robots.txt
app.configure('development', function(){
	app.use(express.errorHandler({
		'dumpExceptions': true
		, 'showStack': true
	}));
	app.all('/robots.txt', function(req,res) {
		res.send('User-agent: *\nDisallow: /', {'Content-Type': 'text/plain'});
	});
});
// Suppress errors, allow all search engines
app.configure('production', function(){
	app.use(express.errorHandler());
	app.all('/robots.txt', function(req,res) {
		res.send('User-agent: *', {'Content-Type': 'text/plain'});
	});
});

// Template helpers
app.dynamicHelpers({
	'assetsCacheHashes': function(req, res) {
		return assetsMiddleware.cacheHashes;
	}
	, 'session': function(req, res) {
		return req.session;
	}
});

// Error handling
app.error(function(err, req, res, next){
	// Log the error to Airbreak if available, good for backtracking.
	console.log(err);
	if (airbrake) { airbrake.notify(err); }

	if (err instanceof NotFound) {
		res.render('errors/404');
	} else {
		res.render('errors/500');
	}
});
function NotFound(msg){
	this.name = 'NotFound';
	Error.call(this, msg);
	Error.captureStackTrace(this, arguments.callee);
}

// Routing
app.all('/', function(req, res) {
	// Set example session uid for use with socket.io.
	if (!req.session.uid) {
		req.session.uid = (0 | Math.random()*1000000);
	}
	res.locals({
		'key': 'value'
	});
	res.render('index');
});

// Initiate this after all other routing is done, otherwise wildcard will go crazy.
var dummyHelpers = new DummyHelper(app);

// If all fails, hit em with the 404
app.all('*', function(req, res){
	throw new NotFound;
});

console.log('Running in '+(process.env.NODE_ENV || 'development')+' mode @ '+siteConf.uri);
<commit_msg>removed redis requirement<commit_after>// Fetch the site configuration
var siteConf = require('./lib/getConfig');

process.title = siteConf.uri.replace(/http:\/\/(www)?/, '');

var airbrake;
if (siteConf.airbrakeApiKey) {
	airbrake = require('airbrake').createClient(siteConf.airbrakeApiKey);
}

process.addListener('uncaughtException', function (err, stack) {
	console.log('Caught exception: '+err+'\n'+err.stack);
	console.log('\u0007'); // Terminal bell
	if (airbrake) { airbrake.notify(err); }
});

var connect = require('connect');
var express = require('express');
var assetManager = require('connect-assetmanager');
var assetHandler = require('connect-assetmanager-handlers');
var notifoMiddleware = require('connect-notifo');
var DummyHelper = require('./lib/dummy-helper');

// Session store
//var RedisStore = require('connect-redis')(express);
//var sessionStore = new RedisStore;

var app = module.exports = express.createServer();
app.listen(siteConf.port, null);

// Setup socket.io server
//var socketIo = new require('./lib/socket-io-server.js')(app, sessionStore);
//var authentication = new require('./lib/authentication.js')(app, siteConf);
// Setup groups for CSS / JS assets
var assetsSettings = {
	'js': {
		'route': /\/static\/js\/[a-z0-9]+\/.*\.js/
		, 'path': './public/js/'
		, 'dataType': 'javascript'
		, 'files': [
			'http://code.jquery.com/jquery.min.js'
			//, siteConf.uri+'/socket.io/socket.io.js' // special case since the socket.io module serves its own js
			, 'plugins.js'
			, 'ejs/ejs_production.js'
			, 'client.js'

		]
		, 'debug': true
		, 'postManipulate': {
			'^': [
				assetHandler.uglifyJsOptimize
				, function insertSocketIoPort(file, path, index, isLast, callback) {
					callback(file.replace(/.#socketIoPort#./, siteConf.port));
				}
			]
		}
	},
        'css': {
		'route': /\/static\/css\/[a-z0-9]+\/.*\.css/
		, 'path': './public/css/'
		, 'dataType': 'css'
		, 'files': ['bootstrap.less']
		, 'debug': true
                , 'preManipulate': {
                    '^': [
                      assetHandler.lessCompile // CUSTOM HANDLER written by me :)
                    ]

                }
                , 'postManipulate': {
                        '^': [
                            assetHandler.fixVendorPrefixes
			    , assetHandler.fixGradients
		            , assetHandler.replaceImageRefToBase64(__dirname+'/public')
			    , assetHandler.yuiCssOptimize
                        ]
                }
	}
};

// Add auto reload for CSS/JS/templates when in development
app.configure('development', function(){
        /*assetsSettings.js.files.push('jquery.frontend-development.js');
        assetsSettings.css.files.push('frontend-development.css');
	[['js', 'updatedContent'], ['css', 'updatedCss']].forEach(function(group) {
		assetsSettings[group[0]].postManipulate['^'].push(function triggerUpdate(file, path, index, isLast, callback) {
			callback(file);
			dummyHelpers[group[1]]();
		});
	});*/
});

var assetsMiddleware = assetManager(assetsSettings);

// Settings
app.configure(function() {
	app.set('view engine', 'ejs');
	app.set('views', __dirname+'/views');
});

// Middleware
app.configure(function() {
	app.use(express.bodyParser());
	app.use(express.cookieParser());
	app.use(assetsMiddleware);
	/*app.use(express.session({
		'store': sessionStore
		, 'secret': siteConf.sessionSecret
	}));*/
	app.use(express.logger({format: ':response-time ms - :date - :req[x-real-ip] - :method :url :user-agent / :referrer'}));
	//app.use(authentication.middleware.auth());
	//app.use(authentication.middleware.normalizeUserData());
	app.use(express['static'](__dirname+'/public', {maxAge: 86400000}));
	app.use(express['static'](__dirname+'/views/frontend_templates'));

	// Send notification to computer/phone @ visit. Good to use for specific events or low traffic sites.
	if (siteConf.notifoAuth) {
		app.use(notifoMiddleware(siteConf.notifoAuth, {
			'filter': function(req, res, callback) {
				callback(null, (!req.xhr && !(req.headers['x-real-ip'] || req.connection.remoteAddress).match(/192.168./)));
			}
			, 'format': function(req, res, callback) {
				callback(null, {
					'title': ':req[x-real-ip]/:remote-addr @ :req[host]'
					, 'message': ':response-time ms - :date - :req[x-real-ip]/:remote-addr - :method :user-agent / :referrer'
				});
			}
		}));
	}
});

// ENV based configuration

// Show all errors and keep search engines out using robots.txt
app.configure('development', function(){
	app.use(express.errorHandler({
		'dumpExceptions': true
		, 'showStack': true
	}));
	app.all('/robots.txt', function(req,res) {
		res.send('User-agent: *\nDisallow: /', {'Content-Type': 'text/plain'});
	});
});
// Suppress errors, allow all search engines
app.configure('production', function(){
	app.use(express.errorHandler());
	app.all('/robots.txt', function(req,res) {
		res.send('User-agent: *', {'Content-Type': 'text/plain'});
	});
});

// Template helpers
app.dynamicHelpers({
	'assetsCacheHashes': function(req, res) {
		return assetsMiddleware.cacheHashes;
	}
	, 'session': function(req, res) {
		return req.session;
	}
});

// Error handling
app.error(function(err, req, res, next){
	// Log the error to Airbreak if available, good for backtracking.
	console.log(err);
	if (airbrake) { airbrake.notify(err); }

	if (err instanceof NotFound) {
		res.render('errors/404');
	} else {
		res.render('errors/500');
	}
});
function NotFound(msg){
	this.name = 'NotFound';
	Error.call(this, msg);
	Error.captureStackTrace(this, arguments.callee);
}

// Routing
app.all('/', function(req, res) {
	// Set example session uid for use with socket.io.
	if (!req.session.uid) {
		req.session.uid = (0 | Math.random()*1000000);
	}
	res.locals({
		'key': 'value'
	});
	res.render('index');
});

// Initiate this after all other routing is done, otherwise wildcard will go crazy.
var dummyHelpers = new DummyHelper(app);

// If all fails, hit em with the 404
app.all('*', function(req, res){
	throw new NotFound;
});

console.log('Running in '+(process.env.NODE_ENV || 'development')+' mode @ '+siteConf.uri);
<|endoftext|>


<commit_before>var m = [16, 16, 16, 16],
    w = 1200 - m[1] - m[3],
    h = 200 - m[0] - m[2];

var svg = d3.select("#chart").append("svg:svg")
    .attr("class", "muni")
    .attr("width", w + m[1] + m[3])
    .attr("height", h + m[0] + m[2])
var vis = svg.append("svg:g")
    .attr("transform", "translate(" + m[3] + "," + m[0] + ")");

var lastTime;
var timeScale = d3.time.scale().range([0,1020]);
var stopsScale = d3.scale.linear().domain([0,1000]).range([5,h-20]);
var axis = d3.svg.axis().scale(timeScale).orient("top")

var gtfs_route_id = "1093";
var nextbus_route = "N";
var static_endpoint = "http://localhost:8081/static";
var live_endpoint = "http://localhost:8080";

var data = [];
var ends = [];
var guides = [];

var line = d3.svg.line()
  .x(function(d) { return timeScale(d.time*1000) })
  .y(function(d) { return stopsScale(d.index) })
  .interpolate("linear");

function vehicleSymbolTransform(d) {
  var x1 = timeScale(d.one.time*1000);
  var y1 = stopsScale(d.one.index);
  var x2 = timeScale(d.two.time*1000);
  var y2 = stopsScale(d.two.index);
  var angle = Math.atan2(-(y2-y1),x2-x1)*180/Math.PI;
  return "translate(" + x2 + "," + y2 + ") rotate(" + -angle + ")";
}

function drawUnanimated() {
  subDraw();
  vis.selectAll(".vehicleSymbol")
    .style("fill", "black")
    .attr("transform", vehicleSymbolTransform);
}

function drawAnimated() {
  subDraw();
  vis.selectAll(".vehicleSymbol")
    .style("fill", "#96ff30")
    .transition()
    .duration(1000)
    .style("fill", "black")
    .attr("transform", vehicleSymbolTransform);
}

var zoom = d3.behavior.zoom()
    .scaleExtent([0.1,0.5])
    .on("zoom", drawUnanimated);

var inbound = true;
var switchG = vis.append("g").attr("transform","translate(1040,0)");
switchG.append("rect").attr("width",100).attr("height",20).style("fill","#aaa")
  .on("click", function(d) {
    d3.selectAll(".inbound").classed("hidden",!inbound);
    d3.selectAll(".outbound").classed("hidden",inbound);
    inbound = !inbound;
  });
switchG.append("text").text("Switch").attr("y",15);

var mainChartWAxis = vis.append("g").attr("transform","translate(0,0)")
mainChartWAxis.append("g")
  .attr("transform", "translate(0,10)")
  .attr("class", "time axis")

var mainChart = mainChartWAxis.append("g").attr("transform","translate(0,20)")

mainChart.append("clipPath")
  .attr("id", "clip")
  .append("rect")
    .attr("width","1020")
    .attr("height","550");

mainChart.append("rect")
  .attr("class", "pane")
  .attr("width","1020")
  .attr("height","550")
  .call(zoom);

var clipped = mainChart.append("g")
  .attr("clip-path", "url(#clip)")
var clippedBack = clipped.append("g");
var clippedMid = clipped.append("g");
var clippedFore = clipped.append("g");
var tooltip = clippedFore.append("text")
    .attr("class", "vehicleTooltip")

function subDraw () {
  clippedFore.selectAll(".vehiclePath").data(data, function(d) { return d.key }).enter()
    .append("path")
    .attr("id", function(d) { return "vp_" + d.key })
    .attr("class","vehiclePath")
    .classed("inbound", function(d) { return d.run.dir == 0 })
    .classed("outbound", function(d) { return d.run.dir == 1 })

  clippedFore.selectAll(".vehicleSymbol").data(ends, function(d) { return d.key }).enter()
    .append("polygon")
    .attr("class", "vehicleSymbol")
    .attr("points", "0,4 8,0 0,-4")
    .classed("inbound", function(d) { return d.dir == 0 })
    .classed("outbound", function(d) { return d.dir == 1 })

  vis.selectAll(".time.axis").call(axis);

  vis.selectAll(".vehiclePath").attr("d", function(d) { return line(d.run.states); })
  vis.selectAll(".guide").attr("d", function(d) { return line(d.stops) });
}

function endsWithFlattenedData(flattened) {
  var ends = [];
  for (l in flattened) {
    var states = flattened[l].run.states;
    if (states.length == 1) {
      ends.push({"key":flattened[l].key,
                 "two":states[0],
                 "one":states[0],
                 "dir":flattened[l].run.dir});
    } else {
      ends.push({"key":flattened[l].key,
                 "two":states[states.length - 1],
                 "one":states[states.length - 2],
                 "dir":flattened[l].run.dir});
    }
  }
  return ends;
}

function getPastData() {
  d3.json(live_endpoint + "/locations.json?route=" + nextbus_route, function(response) {

    var flattened = [];
    for(var key in response) {
      flattened.push({"run":response[key],"key":key});
    }

    data = flattened;

    var max = d3.max(flattened, function(run) {
      return d3.max(run.run.states, function(state) { return state.time })
    })

    lastTime = (max + 60 * 15) * 1000;
    timeScale.domain([(lastTime/1000 - 60 * 60) * 1000, lastTime]);
    zoom.x(timeScale);
    zoom.scale(0.15);
    zoom.translate([700,0]);

    ends = endsWithFlattenedData(data);
    drawUnanimated();
    d3.selectAll(".outbound").classed("hidden",!this.checked);
  });
}

function getDataSince(timestamp) {
  d3.json(live_endpoint + "/locations.json?route=" + nextbus_route + "&after=" + Math.floor(timestamp/1000), function(response) {
    // delta join.
    for (var run in response) {
      var match = data.filter(function(d) { return d.key == run})
      if (match.length > 0) {
        for (var stat in response[run].states) {
          match[0].run.states.push(response[run].states[stat]);
        }
      } else {
        data.push({"run":response[run].key,"run":response[run]});
      }
    }
    ends = endsWithFlattenedData(data);
    drawAnimated();
  });
}

getPastData();
var timestamp = new Date().getTime();
var timeTilUpdate = 9;

setInterval(function() {
  if (timeTilUpdate <= 0) {
    getDataSince(timestamp);
    timestamp = new Date().getTime();
    timeTilUpdate = 10;
  }
  timeTilUpdate--;
}, 1 * 1000)

d3.json(static_endpoint + "/schedules/" + gtfs_route_id + ".json", function(trips) {
  var min = d3.min(trips, function(trip) {
    return d3.min(trip.stops, function(stop) { return stop.time })
  })

  var midnight = new Date();
  midnight.setHours(0,0,0,0);
  var midnightUnix = midnight.getTime() / 1000;

  // if we're beyond the first departure of the day, do it for the current day
  // otherwise, midnight of yesterday
  if ((new Date()).getTime()/1000 - midnightUnix < min) {
    midnightUnix = midnightUnix - 24 * 60 * 60;
  }

  for (var trip in trips) {
    for (var stop in trips[trip].stops) {
      trips[trip].stops[stop].time = trips[trip].stops[stop].time + midnightUnix;
    }
  }
  clippedBack.selectAll(".guide").data(trips).enter().append("path")
    .attr("class","guide")
    .classed("outbound", function(d) { return d.dir == "0" })
    .classed("inbound", function(d) { return d.dir == "1" });
  d3.selectAll(".outbound").classed("hidden",!this.checked);
});

d3.json(static_endpoint + "/stops/" + gtfs_route_id + ".json", function(stops) {
  vis.append("g").attr("transform","translate(1024,23)").selectAll(".stop").data(stops).enter().append("text")
      .attr("class", "stop")
      .attr("text-anchor", "begin")
      .attr("y", function(d) { return stopsScale(d.index) })
      .text(function(d) { return d.name });
  drawUnanimated();
});

<commit_msg>frontend cleanup<commit_after>var m = [16, 16, 16, 16],
    w = 1200 - m[1] - m[3],
    h = 200 - m[0] - m[2];

var svg = d3.select("#chart").append("svg:svg")
    .attr("class", "muni")
    .attr("width", w + m[1] + m[3])
    .attr("height", h + m[0] + m[2])
var vis = svg.append("svg:g")
    .attr("transform", "translate(" + m[3] + "," + m[0] + ")");

var lastTime;
var timeScale = d3.time.scale().range([0,1020]);
var stopsScale = d3.scale.linear().domain([0,1000]).range([5,h-20]);
var axis = d3.svg.axis().scale(timeScale).orient("top")

var gtfs_route_id = "1093";
var nextbus_route = "N";
var static_endpoint = "http://localhost:8081/static";
var live_endpoint = "http://localhost:8080";

var data = [];
var ends = [];
var guides = [];

var line = d3.svg.line()
  .x(function(d) { return timeScale(d.time*1000) })
  .y(function(d) { return stopsScale(d.index) })
  .interpolate("linear");

function vehicleSymbolTransform(d) {
  var x1 = timeScale(d.one.time*1000);
  var y1 = stopsScale(d.one.index);
  var x2 = timeScale(d.two.time*1000);
  var y2 = stopsScale(d.two.index);
  var angle = Math.atan2(-(y2-y1),x2-x1)*180/Math.PI;
  return "translate(" + x2 + "," + y2 + ") rotate(" + -angle + ")";
}

function drawUnanimated() {
  subDraw();
  vis.selectAll(".vehicleSymbol")
    .style("fill", "black")
    .attr("transform", vehicleSymbolTransform);
}

function drawAnimated() {
  subDraw();
  vis.selectAll(".vehicleSymbol")
    .style("fill", "#96ff30")
    .transition()
    .duration(1000)
    .style("fill", "black")
    .attr("transform", vehicleSymbolTransform);
}

var zoom = d3.behavior.zoom()
    .scaleExtent([0.1,0.5])
    .on("zoom", drawUnanimated);

var inbound = true;
var switchG = vis.append("g").attr("transform","translate(1040,0)");
switchG.append("rect").attr("width",100).attr("height",20).style("fill","#aaa")
  .on("click", function(d) {
    d3.selectAll(".inbound").classed("hidden",!inbound);
    d3.selectAll(".outbound").classed("hidden",inbound);
    inbound = !inbound;
  });
switchG.append("text").text("Switch").attr("y",15);

var mainChartWAxis = vis.append("g").attr("transform","translate(0,0)")
mainChartWAxis.append("g")
  .attr("transform", "translate(0,10)")
  .attr("class", "time axis")

var mainChart = mainChartWAxis.append("g").attr("transform","translate(0,20)")

mainChart.append("clipPath")
  .attr("id", "clip")
  .append("rect")
    .attr("width","1020")
    .attr("height","550");

mainChart.append("rect")
  .attr("class", "pane")
  .attr("width","1020")
  .attr("height","550")
  .call(zoom);

var clipped = mainChart.append("g")
  .attr("clip-path", "url(#clip)")
var clippedBack = clipped.append("g");
var clippedFore = clipped.append("g");

function subDraw () {
  clippedFore.selectAll(".vehiclePath").data(data, function(d) { return d.key }).enter()
    .append("path")
    .attr("id", function(d) { return "vp_" + d.key })
    .attr("class","vehiclePath")
    .classed("inbound", function(d) { return d.run.dir == 0 })
    .classed("outbound", function(d) { return d.run.dir == 1 })

  clippedFore.selectAll(".vehicleSymbol").data(ends, function(d) { return d.key }).enter()
    .append("polygon")
    .attr("class", "vehicleSymbol")
    .attr("points", "0,4 8,0 0,-4")
    .classed("inbound", function(d) { return d.dir == 0 })
    .classed("outbound", function(d) { return d.dir == 1 })

  vis.selectAll(".time.axis").call(axis);
  vis.selectAll(".vehiclePath").attr("d", function(d) { return line(d.run.states); })
  vis.selectAll(".guide").attr("d", function(d) { return line(d.stops) });
}

function endsWithFlattenedData(flattened) {
  var ends = [];
  for (l in flattened) {
    var states = flattened[l].run.states;
    if (states.length == 1) {
      ends.push({"key":flattened[l].key,
                 "two":states[0],
                 "one":states[0],
                 "dir":flattened[l].run.dir});
    } else {
      ends.push({"key":flattened[l].key,
                 "two":states[states.length - 1],
                 "one":states[states.length - 2],
                 "dir":flattened[l].run.dir});
    }
  }
  return ends;
}

function getPastData() {
  d3.json(live_endpoint + "/locations.json?route=" + nextbus_route, function(response) {

    var flattened = [];
    for(var key in response) {
      flattened.push({"run":response[key],"key":key});
    }

    data = flattened;

    var max = d3.max(flattened, function(run) {
      return d3.max(run.run.states, function(state) { return state.time })
    })

    lastTime = (max + 60 * 15) * 1000;
    timeScale.domain([(lastTime/1000 - 60 * 60) * 1000, lastTime]);
    zoom.x(timeScale);
    zoom.scale(0.15);
    zoom.translate([700,0]);

    ends = endsWithFlattenedData(data);
    drawUnanimated();
    d3.selectAll(".outbound").classed("hidden",!this.checked);
  });
}

function getDataSince(timestamp) {
  d3.json(live_endpoint + "/locations.json?route=" + nextbus_route + "&after=" + Math.floor(timestamp/1000), function(response) {
    // delta join.
    for (var run in response) {
      var match = data.filter(function(d) { return d.key == run})
      if (match.length > 0) {
        for (var stat in response[run].states) {
          match[0].run.states.push(response[run].states[stat]);
        }
      } else {
        data.push({"run":response[run].key,"run":response[run]});
      }
    }
    ends = endsWithFlattenedData(data);
    drawAnimated();
  });
}

getPastData();
var timestamp = new Date().getTime();
var timeTilUpdate = 9;

setInterval(function() {
  if (timeTilUpdate <= 0) {
    getDataSince(timestamp);
    timestamp = new Date().getTime();
    timeTilUpdate = 10;
  }
  timeTilUpdate--;
}, 1 * 1000)

d3.json(static_endpoint + "/schedules/" + gtfs_route_id + ".json", function(trips) {
  var min = d3.min(trips, function(trip) {
    return d3.min(trip.stops, function(stop) { return stop.time })
  })

  var midnight = new Date();
  midnight.setHours(0,0,0,0);
  var midnightUnix = midnight.getTime() / 1000;

  // if we're beyond the first departure of the day, do it for the current day
  // otherwise, midnight of yesterday
  if ((new Date()).getTime()/1000 - midnightUnix < min) {
    midnightUnix = midnightUnix - 24 * 60 * 60;
  }

  for (var trip in trips) {
    for (var stop in trips[trip].stops) {
      trips[trip].stops[stop].time = trips[trip].stops[stop].time + midnightUnix;
    }
  }
  clippedBack.selectAll(".guide").data(trips).enter().append("path")
    .attr("class","guide")
    .classed("outbound", function(d) { return d.dir == "0" })
    .classed("inbound", function(d) { return d.dir == "1" });
  d3.selectAll(".outbound").classed("hidden",!this.checked);
});

d3.json(static_endpoint + "/stops/" + gtfs_route_id + ".json", function(stops) {
  vis.append("g").attr("transform","translate(1024,23)").selectAll(".stop").data(stops).enter().append("text")
      .attr("class", "stop")
      .attr("text-anchor", "begin")
      .attr("y", function(d) { return stopsScale(d.index) })
      .text(function(d) { return d.name });
  drawUnanimated();
});

<|endoftext|>


<commit_before>// ==UserScript==
// @name            Status Bar
// @author          xiaoxiaoflood
// @include         main
// @startup         UC.statusBar.exec(win);
// @shutdown        UC.statusBar.destroy();
// @onlyonce
// ==/UserScript==

UC.statusBar = {
  PREF_ENABLED: 'userChromeJS.statusbar.enabled',
  PREF_STATUSTEXT: 'userChromeJS.statusbar.appendStatusText',

  get enabled() {
    return xPref.get(this.PREF_ENABLED);
  },

  get textInBar() {
    return this.enabled && xPref.get(this.PREF_STATUSTEXT);
  },

  init: function () {
    xPref.set(this.PREF_ENABLED, true, true);
    xPref.set(this.PREF_STATUSTEXT, true, true);
    this.enabledListener = xPref.addListener(this.PREF_ENABLED, (isEnabled) => {
      CustomizableUI.getWidget('status-dummybar').instances.forEach(dummyBar => {
        dummyBar.node.setAttribute('collapsed', !isEnabled);
      });
    });
    this.textListener = xPref.addListener(this.PREF_STATUSTEXT, (isEnabled) => {
      if (!UC.statusBar.enabled)
        return;

      _uc.windows((doc, win) => {
        let StatusPanel = win.StatusPanel;
        if (isEnabled)
          win.statusbar.textNode.appendChild(StatusPanel._labelElement);
        else
          StatusPanel.panel.firstChild.appendChild(StatusPanel._labelElement);
      });
    });

    this.setStyle();
    _uc.sss.loadAndRegisterSheet(this.STYLE.url, this.STYLE.type);

    CustomizableUI.registerArea('status-bar', {});
  },

  exec: function (win) {
    let document = win.document;
    let StatusPanel = win.StatusPanel;

    let dummystatusbar = _uc.createElement(document, 'toolbar', {
      id: 'status-dummybar',
      toolbarname: 'Status Bar',
      hidden: 'true'
    });
    dummystatusbar.collapsed = !this.enabled;
    dummystatusbar.setAttribute = function (att, value) {
      let result = Element.prototype.setAttribute.apply(this, arguments);

      if (att == 'collapsed') {
        let StatusPanel = win.StatusPanel;
        if (value === true) {
          xPref.set(UC.statusBar.PREF_ENABLED, false);
          win.statusbar.node.setAttribute('collapsed', true);
          StatusPanel.panel.firstChild.appendChild(StatusPanel._labelElement);
          win.statusbar.node.parentNode.collapsed = true;;
        } else {
          xPref.set(UC.statusBar.PREF_ENABLED, true);
          win.statusbar.node.setAttribute('collapsed', false);
          if (UC.statusBar.textInBar)
            win.statusbar.textNode.appendChild(StatusPanel._labelElement);
          win.statusbar.node.parentNode.collapsed = false;
        }
      }

      return result;
    };
    win.gNavToolbox.appendChild(dummystatusbar);

    win.statusbar.node = _uc.createElement(document, 'toolbar', {
      id: 'status-bar',
      customizable: 'true',
      context: 'toolbar-context-menu',
      mode: 'icons'
    });

    win.statusbar.textNode = _uc.createElement(document, 'toolbaritem', {
      id: 'status-text',
      flex: '1',
      width: '100'
    });
    if (this.textInBar)
      win.statusbar.textNode.appendChild(StatusPanel._labelElement);
    win.statusbar.node.appendChild(win.statusbar.textNode);

    win.eval('Object.defineProperty(StatusPanel, "_label", {' + Object.getOwnPropertyDescriptor(StatusPanel, '_label').set.toString().replace(/^set _label/, 'set').replace(/((\s+)this\.panel\.setAttribute\("inactive", "true"\);)/, '$2this._labelElement.value = val;$1') + ', enumerable: true, configurable: true});');

    let bottomBox = document.getElementById('browser-bottombox');
    if (!this.enabled)
      bottomBox.collapsed = true;

    CustomizableUI.registerToolbarNode(win.statusbar.node);
    bottomBox.appendChild(win.statusbar.node);
    win.statusbar.node.parentNode = bottomBox;
  },

  orig: Object.getOwnPropertyDescriptor(StatusPanel, '_label').set.toString(),

  setStyle: function () {
    this.STYLE = {
      url: Services.io.newURI('data:text/css;charset=UTF-8,' + encodeURIComponent(`
        @-moz-document url('${_uc.BROWSERCHROME}') {
          #status-bar {
            color: initial !important;
            background-color: var(--toolbar-non-lwt-bgcolor);
          }
          #status-text > #statuspanel-label {
            border-top: 0 !important;
            background-color: unset !important;
            color: #444;
          }
          #wrapper-status-text label::after {
            content: "Status text" !important;
            color: red !important;
            border: 1px #aaa solid !important;
            border-radius: 3px !important;
            font-weight: bold !important;
          }
          #status-bar > #status-text {
            display: flex !important;
            justify-content: center !important;
            align-content: center !important;
            flex-direction: column !important;
            -moz-window-dragging: drag;
          }
          #browser-bottombox:not([collapsed]) {
            border-top: 1px solid var(--panel-separator-color) !important;
          }
        }
      `)),
      type: _uc.sss.USER_SHEET
    }
  },

  destroy: function () {
    xPref.removeListener(this.enabledListener);
    xPref.removeListener(this.textListener);
    CustomizableUI.unregisterArea('status-bar');
    _uc.sss.unregisterSheet(this.STYLE.url, this.STYLE.type);
    _uc.windows((doc, win) => {
      win.eval('Object.defineProperty(StatusPanel, "_label", {' + this.orig.replace(/^set _label/, 'set') + ', enumerable: true, configurable: true});');
      let StatusPanel = win.StatusPanel;
      StatusPanel.panel.firstChild.appendChild(StatusPanel._labelElement);
      doc.getElementById('status-dummybar').remove();
      win.statusbar.node.remove();
    });
    delete UC.statusBar;
  }
}

UC.statusBar.init();<commit_msg>fix statusbar initialization #124<commit_after>// ==UserScript==
// @name            Status Bar
// @author          xiaoxiaoflood
// @include         main
// @startup         UC.statusBar.exec(win);
// @shutdown        UC.statusBar.destroy();
// @onlyonce
// ==/UserScript==

UC.statusBar = {
  PREF_ENABLED: 'userChromeJS.statusbar.enabled',
  PREF_STATUSTEXT: 'userChromeJS.statusbar.appendStatusText',

  get enabled() {
    return xPref.get(this.PREF_ENABLED);
  },

  get textInBar() {
    return this.enabled && xPref.get(this.PREF_STATUSTEXT);
  },

  init: function () {
    xPref.set(this.PREF_ENABLED, true, true);
    xPref.set(this.PREF_STATUSTEXT, true, true);
    this.enabledListener = xPref.addListener(this.PREF_ENABLED, (isEnabled) => {
      CustomizableUI.getWidget('status-dummybar').instances.forEach(dummyBar => {
        dummyBar.node.setAttribute('collapsed', !isEnabled);
      });
    });
    this.textListener = xPref.addListener(this.PREF_STATUSTEXT, (isEnabled) => {
      if (!UC.statusBar.enabled)
        return;

      _uc.windows((doc, win) => {
        let StatusPanel = win.StatusPanel;
        if (isEnabled)
          win.statusbar.textNode.appendChild(StatusPanel._labelElement);
        else
          StatusPanel.panel.firstChild.appendChild(StatusPanel._labelElement);
      });
    });

    this.setStyle();
    _uc.sss.loadAndRegisterSheet(this.STYLE.url, this.STYLE.type);

    CustomizableUI.registerArea('status-bar', {});

    Services.obs.addObserver(this, 'browser-delayed-startup-finished');
  },

  exec: function (win) {
    let document = win.document;
    let StatusPanel = win.StatusPanel;

    let dummystatusbar = _uc.createElement(document, 'toolbar', {
      id: 'status-dummybar',
      toolbarname: 'Status Bar',
      hidden: 'true'
    });
    dummystatusbar.collapsed = !this.enabled;
    dummystatusbar.setAttribute = function (att, value) {
      let result = Element.prototype.setAttribute.apply(this, arguments);

      if (att == 'collapsed') {
        let StatusPanel = win.StatusPanel;
        if (value === true) {
          xPref.set(UC.statusBar.PREF_ENABLED, false);
          win.statusbar.node.setAttribute('collapsed', true);
          StatusPanel.panel.firstChild.appendChild(StatusPanel._labelElement);
          win.statusbar.node.parentNode.collapsed = true;;
        } else {
          xPref.set(UC.statusBar.PREF_ENABLED, true);
          win.statusbar.node.setAttribute('collapsed', false);
          if (UC.statusBar.textInBar)
            win.statusbar.textNode.appendChild(StatusPanel._labelElement);
          win.statusbar.node.parentNode.collapsed = false;
        }
      }

      return result;
    };
    win.gNavToolbox.appendChild(dummystatusbar);

    win.statusbar.node = _uc.createElement(document, 'toolbar', {
      id: 'status-bar',
      customizable: 'true',
      context: 'toolbar-context-menu',
      mode: 'icons'
    });

    win.statusbar.textNode = _uc.createElement(document, 'toolbaritem', {
      id: 'status-text',
      flex: '1',
      width: '100'
    });
    if (this.textInBar)
      win.statusbar.textNode.appendChild(StatusPanel._labelElement);
    win.statusbar.node.appendChild(win.statusbar.textNode);

    win.eval('Object.defineProperty(StatusPanel, "_label", {' + Object.getOwnPropertyDescriptor(StatusPanel, '_label').set.toString().replace(/^set _label/, 'set').replace(/((\s+)this\.panel\.setAttribute\("inactive", "true"\);)/, '$2this._labelElement.value = val;$1') + ', enumerable: true, configurable: true});');

    let bottomBox = document.getElementById('browser-bottombox');
    if (!this.enabled)
      bottomBox.collapsed = true;

    bottomBox.appendChild(win.statusbar.node);

    if (document.readyState === 'complete')
      this.observe(win);
  },

  observe: function (win) {
    CustomizableUI.registerToolbarNode(win.statusbar.node);
  },

  orig: Object.getOwnPropertyDescriptor(StatusPanel, '_label').set.toString(),

  setStyle: function () {
    this.STYLE = {
      url: Services.io.newURI('data:text/css;charset=UTF-8,' + encodeURIComponent(`
        @-moz-document url('${_uc.BROWSERCHROME}') {
          #status-bar {
            color: initial !important;
            background-color: var(--toolbar-non-lwt-bgcolor);
          }
          #status-text > #statuspanel-label {
            border-top: 0 !important;
            background-color: unset !important;
            color: #444;
          }
          #wrapper-status-text label::after {
            content: "Status text" !important;
            color: red !important;
            border: 1px #aaa solid !important;
            border-radius: 3px !important;
            font-weight: bold !important;
          }
          #status-bar > #status-text {
            display: flex !important;
            justify-content: center !important;
            align-content: center !important;
            flex-direction: column !important;
            -moz-window-dragging: drag;
          }
          #browser-bottombox:not([collapsed]) {
            border-top: 1px solid var(--panel-separator-color) !important;
          }
        }
      `)),
      type: _uc.sss.USER_SHEET
    }
  },

  destroy: function () {
    xPref.removeListener(this.enabledListener);
    xPref.removeListener(this.textListener);
    CustomizableUI.unregisterArea('status-bar');
    _uc.sss.unregisterSheet(this.STYLE.url, this.STYLE.type);
    _uc.windows((doc, win) => {
      win.eval('Object.defineProperty(StatusPanel, "_label", {' + this.orig.replace(/^set _label/, 'set') + ', enumerable: true, configurable: true});');
      let StatusPanel = win.StatusPanel;
      StatusPanel.panel.firstChild.appendChild(StatusPanel._labelElement);
      doc.getElementById('status-dummybar').remove();
      win.statusbar.node.remove();
    });
    Services.obs.removeObserver(this.exec, 'browser-delayed-startup-finished');
    delete UC.statusBar;
  }
}

UC.statusBar.init();
<|endoftext|>