<commit_before>
/**
 * Module dependencies.
 */

var express = require('express')
  , routes = require('./routes')
  , gzip = require('connect-gzip')
  , exec = require('child_process').exec
  , spawn = require('child_process').spawn;

var app = module.exports = express.createServer(gzip.gzip());

// For Mongo
var Db = require('mongodb').Db,
Connection = require('./node_modules/mongodb/lib/mongodb/connection/connection').Connection,
Server = require('mongodb').Server;
var mongoHost = "localhost";
var mongoPort = Connection.DEFAULT_PORT;
var db = new Db('kbase_plants', new Server(mongoHost, mongoPort, {}), {native_parser:false});

//CORS middleware
var allowCrossDomain = function(req, res, next) {
	res.header('Access-Control-Allow-Origin', '*');
	res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
	res.header('Access-Control-Allow-Headers', 'Content-Type');

	next();
}

// Configuration

app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(allowCrossDomain);
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

app.set('view options', { pretty: true })
app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
  app.use(express.errorHandler());
});

// chromosome lengths for each species
var chromosomes = { at: '[[1,30427671],[2,19698289],[3,23459830],[4,18585056],[5,26975502]]' };

// Routes

app.get('/', routes.index);
app.get('/GWAS/:study', function(req,res) {
	routes.gwas(req.params.study, res);
});

app.get('/GWAS/allpoints/:study', function(req,res) {
	routes.allpoints(req.params.study, res);
});

app.get('/chromosomes', function(req,res) {
	res.writeHead(200, {'Content-Type': 'application/json'});
	res.end(chromosomes['at']);
});

app.get('/chromosomes/:genome', function(req,res) {
	res.writeHead(200, {'Content-Type': 'application/json'});
	res.end(chromosomes[req.params.genome]);
});

app.get('/maxscore/GWAS/:study', function(req,res) {
	var cmd = '../fastbit/src/fbsql -s "max(score)" -d ../fastbit/data/GWAS/'+req.params.study;
	console.log(cmd);
	var fbsql = exec(cmd, function (error, stdout, stderr) {
		res.writeHead(200, {'Content-Type': 'application/json'});
		res.end(stdout);
	});
});

// Mongo fetches

app.get ('/phenotypes/:phenotype', function(req,res){
   db.open(function(err, db) {
        db.collection('arabidopsis2010_sample_phenotype', function(err, collection) {
          collection.find({'phenotype_name':req.params.phenotype}, {'phenotype_values':1}, function(err, cursor) {
            res.writeHead(200, {'Content-Type': 'application/json'});
  			cursor.each(function(err, doc) {
  				if (doc === null) {
  					db.close();
  				}
  				if (doc != null ){
  				    res.end(JSON.stringify(doc["phenotype_values"]));
			    }
  			});
          });
        });
   });
});

app.get ('/phenotypes/', function(req,res){
    var items=[];
   db.open(function(err, db) {
        db.collection('arabidopsis2010_sample_phenotype', function(err, collection) {
          collection.find({}, {'phenotype_name':1}, function(err, cursor) {
            res.writeHead(200, {'Content-Type': 'application/json'});
  			cursor.each(function(err, doc) {
  				if (doc === null) {
  					res.end(JSON.stringify(items));
  					db.close();
  				}
  			    if (doc != null){
  				    items.push(doc["phenotype_name"]);
			    }
  			});
          });
        });
   });
});
// GO term histogram (all genes)
app.get('/histogram/GO', function(req,res) {
		var cmd = '../fastbit/src/fbsql -s "GO_term,count(*)" -d ../fastbit/data/gene2GO';
	console.log(cmd);
	var fbsql = exec(cmd, function (error, stdout, stderr) {
		res.writeHead(200, {'Content-Type': 'application/json'});
		res.end(stdout);
	});
});

// GO term histogram for a given set of genes
app.post('/histogram/GO', function(req,res) {
	res.send(req.body);
});

// GO term histogram for a GWAS study (all snps)
app.get('/histogram/GO/GWAS/:study', function(req,res) {
	var cmd = '../fastbit/src/gwas2go -d ../fastbit/data -s '
		+ req.params.study;
	console.log(cmd);
	var join = exec(cmd, function(err,stdout,stderr) {
		res.writeHead(200, {'Content-Type': 'application/json'});
		res.end(stdout);
	});
});

// GO term histogram for a GWAS study where snps are filtered by pos or score
app.get('/histogram/GO/GWAS/:study/:where', function(req,res) {
	var cmd = '../fastbit/src/gwas2go -d ../fastbit/data -s '
		+ req.params.study
		+ ' -w "' + req.params.where + '"';
	console.log(cmd);
	var join = exec(cmd, function(err,stdout,stderr) {
		res.writeHead(200, {'Content-Type': 'application/json'});
		res.end(stdout);
	});
});

// GO term histogram given a minimum association score
app.get('/histogram/GO/phenotypes/:minscore',function(req,res) {
	res.send("minscore:"+req.params.minscore);
});
// phenotype histogram given a list of GO terms

app.post('/histogram/phenotypes/GO',function(req,res) {
	res.send(req.body);
});

// phenotype histogram given a minimum association score
app.get('/histogram/phenotypes/:minscore', function(req,res) {
	res.send("minscore:"+req.params.minscore);
});

app.get('/gene2GWAS', function(req,res) {
	var cmd = '../fastbit/src/fbsql -d ../fastbit/data/gene2GWAS -s "gene_id,score,study_id"';
	var fbsql = exec(cmd, function (error, stdout, stderr) {
		res.writeHead(200, {'Content-Type': 'application/json'});
		res.end(stdout);
	});
});

app.get('/gene2GWAS/:gene_id', function(req,res) {
	var cmd = '../fastbit/src/fbsql -d ../fastbit/data/gene2GWAS -s "score,study_id,score" -w "gene_id='+req.params.gene_id+'"';
	var fbsql = exec(cmd, function (error, stdout, stderr) {
		res.writeHead(200, {'Content-Type': 'application/json'});
		res.end(stdout);
	});
});

// scatterplot rectangles for a GWAS study on given chromosome with at most b1 x b2 boxes
app.get('/scatter/GWAS/:study/:chr/:b1/:b2', function(req,res) {
	var cmd = '../fastbit/src/scatter_new -c1 pos -c2 score -d ../fastbit/data/GWAS/' + req.params.study
		+ '/' + req.params.chr + ' -b1 ' + req.params.b1 + ' -b2 ' + req.params.b2;
		console.log(cmd);
		var scatter = exec(cmd, function (error, stdout, stderr) {
			res.writeHead(200, {'Content-Type': 'application/json'});
			res.end(stdout);
		});
});
app.get('/scatter/GWAS/:study/:chr/:b1/:b2/:n1/:x1/:n2/:x2', function(req,res) {
	var cmd = '../fastbit/src/scatter_ez -c1 pos -c2 score -d ../fastbit/data/GWAS/' + req.params.study
		+ '/' + req.params.chr + ' -b1 ' + req.params.b1 + ' -b2 ' + req.params.b2
		+ ' -n1 ' + req.params.n1 + ' -n2 ' + req.params.n2
		+ ' -x1 ' + req.params.x1 + ' -x2 ' + req.params.x2;
		console.log(cmd);
		var scatter = exec(cmd, {maxBuffer:10000*1024},function (error, stdout, stderr) {
            res.writeHead(200, {'Content-Type': 'application/json'});
			res.end(stdout);
		});
});

// scatterplot for GWAS study with no binning
app.get('/scatter/GWAS/nobinning/:study/:chr', function(req,res) {
	var cmd = '../fastbit/src/fbsql -s "pos,score" -d ../fastbit/data/GWAS/' + req.params.study + '/' + req.params.chr;
	console.log(cmd);
	var scatter = exec(cmd,{maxBuffer:10000*1024},function(error, stdout,stderr) {
		res.writeHead(200, {'Content-Type': 'application/json'});
		res.end(stdout);
	});
});

app.post('/scatter', function(req,res) {
	res.send(req.body);
});

// scatterplot for any partition comparing c1 to c2 with additional args taken from etc
app.get('/scatter/:partition/:c1/:c2/:etc', function(req,res) {
	var cmd = '../fastbit/src/scatter_new -d ../fastbit/data/' + req.params.partition
		+ ' -c1 ' + req.params.c1 + ' -c2 ' + req.params.c2
		+ ' ' + req.params.etc;
		console.log(cmd);
		var scatter = exec(cmd, function (error, stdout, stderr) {
			res.writeHead(200, {'Content-Type': 'application/json'});
			res.end(stdout);
		});
});

// testing jquery-fastbit
app.get('/jquery/fastbit',routes.jquery_fastbit);

app.listen(3001);
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
<commit_msg>modified gene2GWAS route<commit_after>
/**
 * Module dependencies.
 */

var express = require('express')
  , routes = require('./routes')
  , gzip = require('connect-gzip')
  , exec = require('child_process').exec
  , spawn = require('child_process').spawn;

var app = module.exports = express.createServer(gzip.gzip());

// For Mongo
var Db = require('mongodb').Db,
Connection = require('./node_modules/mongodb/lib/mongodb/connection/connection').Connection,
Server = require('mongodb').Server;
var mongoHost = "localhost";
var mongoPort = Connection.DEFAULT_PORT;
var db = new Db('kbase_plants', new Server(mongoHost, mongoPort, {}), {native_parser:false});

//CORS middleware
var allowCrossDomain = function(req, res, next) {
	res.header('Access-Control-Allow-Origin', '*');
	res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
	res.header('Access-Control-Allow-Headers', 'Content-Type');

	next();
}

// Configuration

app.configure(function(){
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(allowCrossDomain);
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

app.set('view options', { pretty: true })
app.configure('development', function(){
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

app.configure('production', function(){
  app.use(express.errorHandler());
});

// chromosome lengths for each species
var chromosomes = { at: '[[1,30427671],[2,19698289],[3,23459830],[4,18585056],[5,26975502]]' };

// Routes

app.get('/', routes.index);
app.get('/GWAS/:study', function(req,res) {
	routes.gwas(req.params.study, res);
});

app.get('/GWAS/allpoints/:study', function(req,res) {
	routes.allpoints(req.params.study, res);
});

app.get('/chromosomes', function(req,res) {
	res.writeHead(200, {'Content-Type': 'application/json'});
	res.end(chromosomes['at']);
});

app.get('/chromosomes/:genome', function(req,res) {
	res.writeHead(200, {'Content-Type': 'application/json'});
	res.end(chromosomes[req.params.genome]);
});

app.get('/maxscore/GWAS/:study', function(req,res) {
	var cmd = '../fastbit/src/fbsql -s "max(score)" -d ../fastbit/data/GWAS/'+req.params.study;
	console.log(cmd);
	var fbsql = exec(cmd, function (error, stdout, stderr) {
		res.writeHead(200, {'Content-Type': 'application/json'});
		res.end(stdout);
	});
});

// Mongo fetches

app.get ('/phenotypes/:phenotype', function(req,res){
   db.open(function(err, db) {
        db.collection('arabidopsis2010_sample_phenotype', function(err, collection) {
          collection.find({'phenotype_name':req.params.phenotype}, {'phenotype_values':1}, function(err, cursor) {
            res.writeHead(200, {'Content-Type': 'application/json'});
  			cursor.each(function(err, doc) {
  				if (doc === null) {
  					db.close();
  				}
  				if (doc != null ){
  				    res.end(JSON.stringify(doc["phenotype_values"]));
			    }
  			});
          });
        });
   });
});

app.get ('/phenotypes/', function(req,res){
    var items=[];
   db.open(function(err, db) {
        db.collection('arabidopsis2010_sample_phenotype', function(err, collection) {
          collection.find({}, {'phenotype_name':1}, function(err, cursor) {
            res.writeHead(200, {'Content-Type': 'application/json'});
  			cursor.each(function(err, doc) {
  				if (doc === null) {
  					res.end(JSON.stringify(items));
  					db.close();
  				}
  			    if (doc != null){
  				    items.push(doc["phenotype_name"]);
			    }
  			});
          });
        });
   });
});
// GO term histogram (all genes)
app.get('/histogram/GO', function(req,res) {
		var cmd = '../fastbit/src/fbsql -s "GO_term,count(*)" -d ../fastbit/data/gene2GO';
	console.log(cmd);
	var fbsql = exec(cmd, function (error, stdout, stderr) {
		res.writeHead(200, {'Content-Type': 'application/json'});
		res.end(stdout);
	});
});

// GO term histogram for a given set of genes
app.post('/histogram/GO', function(req,res) {
	res.send(req.body);
});

// GO term histogram for a GWAS study (all snps)
app.get('/histogram/GO/GWAS/:study', function(req,res) {
	var cmd = '../fastbit/src/gwas2go -d ../fastbit/data -s '
		+ req.params.study;
	console.log(cmd);
	var join = exec(cmd, function(err,stdout,stderr) {
		res.writeHead(200, {'Content-Type': 'application/json'});
		res.end(stdout);
	});
});

// GO term histogram for a GWAS study where snps are filtered by pos or score
app.get('/histogram/GO/GWAS/:study/:where', function(req,res) {
	var cmd = '../fastbit/src/gwas2go -d ../fastbit/data -s '
		+ req.params.study
		+ ' -w "' + req.params.where + '"';
	console.log(cmd);
	var join = exec(cmd, function(err,stdout,stderr) {
		res.writeHead(200, {'Content-Type': 'application/json'});
		res.end(stdout);
	});
});

// GO term histogram given a minimum association score
app.get('/histogram/GO/phenotypes/:minscore',function(req,res) {
	res.send("minscore:"+req.params.minscore);
});
// phenotype histogram given a list of GO terms

app.post('/histogram/phenotypes/GO',function(req,res) {
	res.send(req.body);
});

// phenotype histogram given a minimum association score
app.get('/histogram/phenotypes/:minscore', function(req,res) {
	res.send("minscore:"+req.params.minscore);
});

app.get('/gene2GWAS', function(req,res) {
	var cmd = '../fastbit/src/fbsql -d ../fastbit/data/GWAS_snp_consequences -s "study_id,gene_id,max(score)"';
	var fbsql = exec(cmd, function (error, stdout, stderr) {
		res.writeHead(200, {'Content-Type': 'application/json'});
		res.end(stdout);
	});
});

app.get('/gene2GWAS/:gene_id', function(req,res) {
	var cmd = '../fastbit/src/fbsql -d ../fastbit/data/GWAS_snp_consequences -s "study_id,max(score)" -w "gene_id='+req.params.gene_id+'"';
	var fbsql = exec(cmd, function (error, stdout, stderr) {
		res.writeHead(200, {'Content-Type': 'application/json'});
		res.end(stdout);
	});
});

// scatterplot rectangles for a GWAS study on given chromosome with at most b1 x b2 boxes
app.get('/scatter/GWAS/:study/:chr/:b1/:b2', function(req,res) {
	var cmd = '../fastbit/src/scatter_new -c1 pos -c2 score -d ../fastbit/data/GWAS/' + req.params.study
		+ '/' + req.params.chr + ' -b1 ' + req.params.b1 + ' -b2 ' + req.params.b2;
		console.log(cmd);
		var scatter = exec(cmd, function (error, stdout, stderr) {
			res.writeHead(200, {'Content-Type': 'application/json'});
			res.end(stdout);
		});
});
app.get('/scatter/GWAS/:study/:chr/:b1/:b2/:n1/:x1/:n2/:x2', function(req,res) {
	var cmd = '../fastbit/src/scatter_ez -c1 pos -c2 score -d ../fastbit/data/GWAS/' + req.params.study
		+ '/' + req.params.chr + ' -b1 ' + req.params.b1 + ' -b2 ' + req.params.b2
		+ ' -n1 ' + req.params.n1 + ' -n2 ' + req.params.n2
		+ ' -x1 ' + req.params.x1 + ' -x2 ' + req.params.x2;
		console.log(cmd);
		var scatter = exec(cmd, {maxBuffer:10000*1024},function (error, stdout, stderr) {
            res.writeHead(200, {'Content-Type': 'application/json'});
			res.end(stdout);
		});
});

// scatterplot for GWAS study with no binning
app.get('/scatter/GWAS/nobinning/:study/:chr', function(req,res) {
	var cmd = '../fastbit/src/fbsql -s "pos,score" -d ../fastbit/data/GWAS/' + req.params.study + '/' + req.params.chr;
	console.log(cmd);
	var scatter = exec(cmd,{maxBuffer:10000*1024},function(error, stdout,stderr) {
		res.writeHead(200, {'Content-Type': 'application/json'});
		res.end(stdout);
	});
});

app.post('/scatter', function(req,res) {
	res.send(req.body);
});

// scatterplot for any partition comparing c1 to c2 with additional args taken from etc
app.get('/scatter/:partition/:c1/:c2/:etc', function(req,res) {
	var cmd = '../fastbit/src/scatter_new -d ../fastbit/data/' + req.params.partition
		+ ' -c1 ' + req.params.c1 + ' -c2 ' + req.params.c2
		+ ' ' + req.params.etc;
		console.log(cmd);
		var scatter = exec(cmd, function (error, stdout, stderr) {
			res.writeHead(200, {'Content-Type': 'application/json'});
			res.end(stdout);
		});
});

// testing jquery-fastbit
app.get('/jquery/fastbit',routes.jquery_fastbit);

app.listen(3001);
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
<|endoftext|>


<commit_before>$(function() {
  'use strict'

  var Router = {
    routes: [],
    view: $('#view'),

    index: function() {
      this.setContent('
Welcome!
')
    },

    error: function() {
      this.setContent('
404 Not Found
')
    },

    setContent(content, transitionDuration) {
      var duration = transitionDuration ? transitionDuration : 400
      this.view.fadeOut(duration, function() {
        this.view.html(content).fadeIn(duration)
      }.bind(this))
    },

    route: function(re, handler) {
      this.routes.push({ re, handler })

      return this
    },

    check: function() {
      var fragment = location.hash
      var matched = false

      if (fragment === '') {
        this.index()
      }
      else {
        this.routes.forEach(function(route) {
          var match = fragment.match(route.re)

          if (match) {
            matched = true
            match.shift()
            route.handler.apply({}, match)
          }
        })

        if (!matched) this.error()
      }

      return this
    },

    transitionTo: function(path, options) {
      var o = options ? options : { title: null, active: null }

      history.pushState(o, o.title, path)

      $('a.history-link').removeClass('active')

      if (o.active) {
        $('a.history-link[data-title="' + o.active + '"]').addClass('active')
      }
      else {
        $('a.history-link[href="/' + location.hash + '"]').addClass('active')
      }

      this.check()

      return this
    }
  }

  Router.route(/#\/posts/, function(params) {
    $.getJSON('/posts.json', function(data) {
      var html = ''
      data.forEach(function(post) {
        var title   = '
' + post.title + '
'
        var content = '
' + post.content + '
'
        html += '
' + title + content + '
'
      })
      Router.setContent(html)
    })
  })

  $('body').on('click', 'a.history-link', function(e) {
    e.preventDefault()
    Router.transitionTo($(this).attr('href'), $(this).data())
  })

  $(window).on('popstate', function(e) {
    Router.check()
  })

  Router.transitionTo(location.hash)
})
<commit_msg>Added sample login<commit_after>$(function() {
  'use strict'

  var Router = {
    routes: [],
    view: $('#view'),

    index: function() {
      this.setContent('
Welcome!
')
    },

    error: function() {
      this.setContent('
404 Not Found
')
    },

    setContent(content, transitionDuration) {
      var duration = transitionDuration ? transitionDuration : 400
      this.view.fadeOut(duration, function() {
        this.view.html(content).fadeIn(duration)
      }.bind(this))
    },

    route: function(re, handler) {
      this.routes.push({ re, handler })

      return this
    },

    check: function() {
      var fragment = location.hash
      var matched = false

      if (fragment === '') {
        this.index()
      }
      else {
        this.routes.forEach(function(route) {
          var match = fragment.match(route.re)

          if (match) {
            matched = true
            match.shift()
            route.handler.apply({}, match)
          }
        })

        if (!matched) this.error()
      }

      return this
    },

    transitionTo: function(path, options) {
      var o = options ? options : { title: null, active: null }

      history.pushState(o, o.title, path)

      $('a.history-link').removeClass('active')

      if (o.active) {
        $('a.history-link[data-title="' + o.active + '"]').addClass('active')
      }
      else {
        $('a.history-link[href="/' + location.hash + '"]').addClass('active')
      }

      this.check()

      return this
    }
  }

  Router.route(/#\/posts/, function() {
    $.getJSON('/posts.json', function(data) {
      var html = ''
      data.forEach(function(post) {
        var title   = '
' + post.title + '
'
        var content = '
' + post.content + '
'
        html += '
' + title + content + '
'
      })
      Router.setContent(html)
    })
  })

  Router.route(/#\/login/, function() {
    var fn = this

    if (localStorage.getItem('credentials')) {
      Router.setContent('
You are logged in
')
    }
    else {
      Router.setContent('<form id="login"><input name="username" type="text" /><input name="password" type="password" /><input type="submit" value="Login" />')
    }

    $('#view').on('submit', '#login', function(e) {
      e.preventDefault()

      var username = $(this).find('[name="username"]')
      var password = $(this).find('[name="password"]')

      localStorage.setItem('credentials', JSON.stringify({ username, password }))
      Router.check()
    })
  })

  $('body').on('click', 'a.history-link', function(e) {
    e.preventDefault()
    Router.transitionTo($(this).attr('href'), $(this).data())
  })

  $(window).on('popstate', function(e) {
    Router.check()
  })

  Router.transitionTo(location.hash)
})
<|endoftext|>


<commit_before>define(
  [],
  function () {
    "use strict";

    var Data = function () {};

    _.extend(Data.prototype, {});

    return Data;
  }
);<commit_msg>inMemory data layer rejects all promises<commit_after>define(
  [],
  function () {
    "use strict";

    var Data = function () {};

    _.extend(Data.prototype, {
      data: {},

      create: function (model) {
        return new $.Deferred().reject().promise();
      },

      update: function (model) {
        return new $.Deferred().reject().promise();
      },

      read: function (model) {
        return new $.Deferred().reject().promise();
      },

      readAll: function () {
        return new $.Deferred().reject().promise();
      },

      delete: function (model) {
        return new $.Deferred().reject().promise();
      },

      deleteAll: function (model) {
        return new $.Deferred().reject().promise();
      }

    });

    return Data;
  }
);<|endoftext|>


<commit_before>/*jslint browser: true*/
/*global define*/

//-----------------------------------------------------------------------

//define(['data/berlin', 'data/brandenburg', 'data/moers', 'data/wesel'], function (dataBerlin, dataBrandenburg, dataMoers, dataWesel) {
define(['data/berlin', 'data/brandenburg', 'data/moers'], function (dataBerlin, dataBrandenburg, dataMoers) {
	'use strict';

	var firstDay = 4000000000000,
		lastDay = 0,
		market,
		markets = [],
		teaserPath = '';

	function changeCI(name) {
		var docTitle = '',
			header = '',
			markets = '',
			attribution = '';

		if ('Berlin' === name) {
			docTitle = 'Weihnachtsmärkte in Berlin';
			header = 'Weihnachtsmärkte in Berlin';
			markets = '
"Berliner Weihnachtsmärkte"
CC-BY 3.0 DE
daten.berlin.de
';
			attribution = '
Charles Blume Vergnügungsbetrieb GmbH
';
			teaserPath = 'art/berlin/teaser.jpg';
		} else if ('Brandenburg' === name) {
			markets = '
"Brandenburger Weihnachtsmärkte"
CC-BY 3.0 DE
daten.berlin.de
';
		} else if ('Moers' === name) {
			docTitle = 'Weihnachten in Moers';
			header = 'Weihnachten in Moers';
			markets = '
"Veranstaltungen zur Weihnachtszeit"
DL-DE-Zero-2.0
offenedaten.moers.de
';
			attribution = '
MoersMarketing GmbH
';
			teaserPath = 'art/moers/teaser.jpg';
		} else if ('Wesel' === name) {
			markets = '
"Veranstaltungen in Wesel"
DL-DE-Zero-2.0
offenedaten.wesel.de
';
		}

		if (docTitle.length > 0) {
			document.title = docTitle;
		}
		if (header.length > 0) {
			document.querySelector('#drawer h1').innerHTML = header;
		}
		document.querySelector('#index nav ul:nth-child(6)').innerHTML += markets;
		document.querySelector('#index nav ul:nth-child(8)').innerHTML += attribution;
	}

	function addData(name, data) {
		changeCI(name);

		for (market = 0; market < data.length; ++market) {
			data[market].path = name.toLowerCase();
			if (!isNaN(Date.parse(data[market].begin))) {
				firstDay = Math.min(firstDay, Date.parse(data[market].begin));
			}
			if (!isNaN(Date.parse(data[market].end))) {
				lastDay = Math.max(lastDay, Date.parse(data[market].end));
			}
		}

		markets = markets.concat(data);
	}

	addData('Berlin', dataBerlin.data);
	addData('Brandenburg', dataBrandenburg.data);
//	addData('Moers', dataMoers.data);
//	addData('Wesel', dataWesel.data);

	return {
		timeout: 400,
		currentMarketId: 0,
		startDate: new Date(firstDay),
		endDate: new Date(lastDay + (1000 * 60 * 60 * 24)),
		views: [],
		markets: markets,
		teaserPath: teaserPath,
		userLat: null,
		userLon: null,

		getMarketByID: function (marketId) {
			var path = marketId.split('-')[0],
				uuid = parseInt(marketId.split('-')[1], 10),
				i;

			for (i = 0; i < this.markets.length; ++i) {
				if ((this.markets[i].path === path) && (this.markets[i].uuid === uuid)) {
					return this.markets[i];
				}
			}

			return null;
		}
	};
});

//-----------------------------------------------------------------------
<commit_msg>attribute new cities<commit_after>/*jslint browser: true*/
/*global define*/

//-----------------------------------------------------------------------

//define(['data/berlin', 'data/brandenburg', 'data/moers', 'data/wesel'], function (dataBerlin, dataBrandenburg, dataMoers, dataWesel) {
define(['data/berlin', 'data/brandenburg', 'data/moers'], function (dataBerlin, dataBrandenburg, dataMoers) {
	'use strict';

	var firstDay = 4000000000000,
		lastDay = 0,
		market,
		markets = [],
		teaserPath = '';

	function changeCI(name) {
		var docTitle = '',
			header = '',
			markets = '',
			attribution = '';

		if ('Berlin' === name) {
			docTitle = 'Weihnachtsmärkte in Berlin';
			header = 'Weihnachtsmärkte in Berlin';
			markets = '
"Berliner Weihnachtsmärkte"
CC-BY 3.0 DE
daten.berlin.de
';
			attribution = '
Charles Blume Vergnügungsbetrieb GmbH
';
			teaserPath = 'art/berlin/teaser.jpg';
		} else if ('Brandenburg' === name) {
			markets = '
"Brandenburger Weihnachtsmärkte"
CC-BY 3.0 DE
daten.berlin.de
';
		} else if ('Moers' === name) {
			docTitle = 'Weihnachten in Moers';
			header = 'Weihnachten in Moers';
			markets = '
"Veranstaltungen zur Weihnachtszeit"
DL-DE-Zero-2.0
offenedaten.moers.de
';
			attribution = '
MoersMarketing GmbH
';
			teaserPath = 'art/moers/teaser.jpg';
		} else if ('Wesel' === name) {
			markets = '
"Veranstaltungen in Wesel"
DL-DE-Zero-2.0
opendata.wesel.de
';
		} else if ('Krefeld' === name) {
			markets = '
"Veranstaltungskalender der Stadt Krefeld"
DL-DE-Zero-2.0
offenesdatenportal.de/organization/krefeld
';
		}

		if (docTitle.length > 0) {
			document.title = docTitle;
		}
		if (header.length > 0) {
			document.querySelector('#drawer h1').innerHTML = header;
		}
		document.querySelector('#index nav ul:nth-child(6)').innerHTML += markets;
		document.querySelector('#index nav ul:nth-child(8)').innerHTML += attribution;
	}

	function addData(name, data) {
		changeCI(name);

		for (market = 0; market < data.length; ++market) {
			data[market].path = name.toLowerCase();
			if (!isNaN(Date.parse(data[market].begin))) {
				firstDay = Math.min(firstDay, Date.parse(data[market].begin));
			}
			if (!isNaN(Date.parse(data[market].end))) {
				lastDay = Math.max(lastDay, Date.parse(data[market].end));
			}
		}

		markets = markets.concat(data);
	}

	addData('Berlin', dataBerlin.data);
	addData('Brandenburg', dataBrandenburg.data);
//	addData('Moers', dataMoers.data);
//	addData('Wesel', dataWesel.data);

	return {
		timeout: 400,
		currentMarketId: 0,
		startDate: new Date(firstDay),
		endDate: new Date(lastDay + (1000 * 60 * 60 * 24)),
		views: [],
		markets: markets,
		teaserPath: teaserPath,
		userLat: null,
		userLon: null,

		getMarketByID: function (marketId) {
			var path = marketId.split('-')[0],
				uuid = parseInt(marketId.split('-')[1], 10),
				i;

			for (i = 0; i < this.markets.length; ++i) {
				if ((this.markets[i].path === path) && (this.markets[i].uuid === uuid)) {
					return this.markets[i];
				}
			}

			return null;
		}
	};
});

//-----------------------------------------------------------------------
<|endoftext|>


<commit_before>;(function($,_,Backbone,Handlebars,window,document,config,undefined){

  Backbone.couch_connector.config.db_name = config.dbName;
  Backbone.couch_connector.config.ddoc_name = config.dbName;
  Backbone.couch_connector.config.global_changes = false;

  // The App router initializes the app by calling `UserList.fetch()`
  var App = Backbone.Router.extend({
    routes: {
      "": "initialize",
      "types/:id" : "editType",
      "types/:id/items" : "items"
    },

    initialize: function(){
      UserList.fetch();
      this.loadView(new TypeListView({collection: Types}));
    },
    editType: function(id){
      var type = Types.findWhere({ _id: id });
      this.loadView(new TypeFormView({ model: type }));
    },
    items: function(id){
      var type = Types.findWhere({_id: id});
      this.loadView(new ItemListView({collection: Items.filtered(id), current_type: type.toJSON()}));
    },
    loadView: function(view){
      this.view && (this.view.close ? this.view.close() : this.view.remove());
      this.view = view;
    }
  });

  /*
   * Utility
   */
  Backbone.View.prototype.close = function () {
    _.each(this.subViews, function(view) { view.remove(); });
    this.remove();
    this.unbind();
  };

  window.Handlebars.registerHelper('select', function( value, options ){
    var $el = $('<select />').html( options.fn(this) );
    $el.find('[value=' + value + ']').attr({'selected':'selected'});
    return $el.html();
  });

  window.Handlebars.registerHelper('adminOnly', function(context, options){
    out = '';
    if (CurrentUser.get('roles').indexOf('admin') > -1) {
      out = options.fn(context);
    }
    return out;
  });

  window.Handlebars.registerHelper('fieldValues', function(item){
    var $el, selected, checked, markup, i, len, fieldsEditable, disabled;
    if (CurrentUser.get('roles').indexOf('admin') > -1) {
      fieldsEditable = true;
    } else {
      fieldsEditable = ['status', 'price']; // TODO: add field property to set editability by non-admin users
    }
    markup = '';
    _.each(item, function(field){
      disabled = !(fieldsEditable === true || fieldsEditable.indexOf(field.name) > -1);
      if (field.type == "checkbox") {
        checked = (field.value == "on" ? ' checked' : '');
        markup += '
';
        if ( !disabled ) {
          markup += '
' +
              '
' +
                '' +
                  '<input type="checkbox" name="'+ field.name +'"'+ checked +' '+(disabled ? 'disabled' : '')+' />' +
                  ' '+ field.name +
                '' +
              '
' +
            '
';
        } else {
          markup += '' +
            field.name +': ' +
            '' +
          '

';
        }
        markup += '
';
      } else if (field.type == "select") {
        markup += '
' +
            ''+
            field.name +': ' +
            '' +
          '
';
        if ( !disabled ) {
          markup += '<select class="form-control" name="'+ field.name +'">';
          for (i = 0, len=field.options.length; i < len; i++) {
            selected = (field.value == field.options[i].value ? ' selected' : '');
            markup += '<option value="' + field.options[i].value + '"' + selected + '>' + field.options[i].label + '</option>';
          }
          markup += '</select>';
        } else {
          markup += ''+ field.value +'';
        }
        markup += '

';
      } else {
        markup += '
' +
          ''+ field.name +': ' +
          '
';
        if ( !disabled ) {
          markup += '<input type="text" class="form-control" name="'+ field.name +'" value="'+ field.value +'" />';
        } else {
          markup += ''+ field.value +'';
        }
        markup += '
' +
          '
';
      }
    });
    return markup;
  });

  window.Handlebars.registerHelper('fieldOption', function(option){
    var markup;
    markup = '
' +
        '
' +
          '<input type="text" class="form-control" name="value" value="'+option.value+'">' +
        '
' +
        '
' +
          '<input type="text" class="form-control" name="label" value="'+option.label+'">' +
          '
' +
            '<button type="button" class="delOption btn btn-danger"></button>' +
          '
' +
        '
' +
      '
';
    return markup;
  });

  window.Handlebars.registerHelper('delete', function(item){
    return '<button class="delete btn btn-danger"> Delete</button>';
  });

  // The current session will be stored in here
  var CurrentSession = null;

  // Booststrap app after delay to avoid continuous activity spinner
  _.delay(function(){

    // Destroy the current session on unload
    $(window).unload(function(){
      $.ajaxSetup({
        async : false
      });
      if(CurrentSession != null)
        CurrentSession.destroy();
    });

    Backbone.history.start();

    // Includes the couchlogin
    // check it out here: https://github.com/couchapp/couchdb-login-jquery
    $('#login').couchLogin({
      loggedIn : function(user){
        CurrentUser.set(user);
        // Only add a User if it's not already in the list
        if(!UserList.detect(function(user){return user.get("name") == CurrentUser.get("name");})){
          CurrentSession = UserList.create({
            "name" : CurrentUser.get("name"),
            "logged_in_at" : new Date().getTime()
          });
        }

        // Bootstrapping
        window.app = new App();
        app.navigate("");

        // All link clicks go to app.navigate()
        $(document).on("click", "a:not(.data-bypass)", function(e) {
          e.preventDefault();

          var href = { prop: $(this).prop("href"), attr: $(this).attr("href") };
          var root = location.protocol + "//" + location.host + app.root;
          app.navigate(href.attr, true);
        });
      },
      loggedOut : function(){
        CurrentUser.set(new UserModel().toJSON());
        CurrentUser.trigger("change:name");
        if(CurrentSession != null) CurrentSession.destroy();
        $('#list').html('');
      }
    });

  }, 100);

}(jQuery,_,Backbone,Handlebars,window,document,config));
<commit_msg>enable publishDate editable by non-admin<commit_after>;(function($,_,Backbone,Handlebars,window,document,config,undefined){

  Backbone.couch_connector.config.db_name = config.dbName;
  Backbone.couch_connector.config.ddoc_name = config.dbName;
  Backbone.couch_connector.config.global_changes = false;

  // The App router initializes the app by calling `UserList.fetch()`
  var App = Backbone.Router.extend({
    routes: {
      "": "initialize",
      "types/:id" : "editType",
      "types/:id/items" : "items"
    },

    initialize: function(){
      UserList.fetch();
      this.loadView(new TypeListView({collection: Types}));
    },
    editType: function(id){
      var type = Types.findWhere({ _id: id });
      this.loadView(new TypeFormView({ model: type }));
    },
    items: function(id){
      var type = Types.findWhere({_id: id});
      this.loadView(new ItemListView({collection: Items.filtered(id), current_type: type.toJSON()}));
    },
    loadView: function(view){
      this.view && (this.view.close ? this.view.close() : this.view.remove());
      this.view = view;
    }
  });

  /*
   * Utility
   */
  Backbone.View.prototype.close = function () {
    _.each(this.subViews, function(view) { view.remove(); });
    this.remove();
    this.unbind();
  };

  window.Handlebars.registerHelper('select', function( value, options ){
    var $el = $('<select />').html( options.fn(this) );
    $el.find('[value=' + value + ']').attr({'selected':'selected'});
    return $el.html();
  });

  window.Handlebars.registerHelper('adminOnly', function(context, options){
    out = '';
    if (CurrentUser.get('roles').indexOf('admin') > -1) {
      out = options.fn(context);
    }
    return out;
  });

  window.Handlebars.registerHelper('fieldValues', function(item){
    var $el, selected, checked, markup, i, len, fieldsEditable, disabled;
    if (CurrentUser.get('roles').indexOf('admin') > -1) {
      fieldsEditable = true;
    } else {
      fieldsEditable = ['status', 'price', 'publishDate']; // TODO: add field property to set editability by non-admin users
    }
    markup = '';
    _.each(item, function(field){
      disabled = !(fieldsEditable === true || fieldsEditable.indexOf(field.name) > -1);
      if (field.type == "checkbox") {
        checked = (field.value == "on" ? ' checked' : '');
        markup += '
';
        if ( !disabled ) {
          markup += '
' +
              '
' +
                '' +
                  '<input type="checkbox" name="'+ field.name +'"'+ checked +' '+(disabled ? 'disabled' : '')+' />' +
                  ' '+ field.name +
                '' +
              '
' +
            '
';
        } else {
          markup += '' +
            field.name +': ' +
            '' +
          '

';
        }
        markup += '
';
      } else if (field.type == "select") {
        markup += '
' +
            ''+
            field.name +': ' +
            '' +
          '
';
        if ( !disabled ) {
          markup += '<select class="form-control" name="'+ field.name +'">';
          for (i = 0, len=field.options.length; i < len; i++) {
            selected = (field.value == field.options[i].value ? ' selected' : '');
            markup += '<option value="' + field.options[i].value + '"' + selected + '>' + field.options[i].label + '</option>';
          }
          markup += '</select>';
        } else {
          markup += ''+ field.value +'';
        }
        markup += '

';
      } else {
        markup += '
' +
          ''+ field.name +': ' +
          '
';
        if ( !disabled ) {
          markup += '<input type="text" class="form-control" name="'+ field.name +'" value="'+ field.value +'" />';
        } else {
          markup += ''+ field.value +'';
        }
        markup += '
' +
          '
';
      }
    });
    return markup;
  });

  window.Handlebars.registerHelper('fieldOption', function(option){
    var markup;
    markup = '
' +
        '
' +
          '<input type="text" class="form-control" name="value" value="'+option.value+'">' +
        '
' +
        '
' +
          '<input type="text" class="form-control" name="label" value="'+option.label+'">' +
          '
' +
            '<button type="button" class="delOption btn btn-danger"></button>' +
          '
' +
        '
' +
      '
';
    return markup;
  });

  window.Handlebars.registerHelper('delete', function(item){
    return '<button class="delete btn btn-danger"> Delete</button>';
  });

  // The current session will be stored in here
  var CurrentSession = null;

  // Booststrap app after delay to avoid continuous activity spinner
  _.delay(function(){

    // Destroy the current session on unload
    $(window).unload(function(){
      $.ajaxSetup({
        async : false
      });
      if(CurrentSession != null)
        CurrentSession.destroy();
    });

    Backbone.history.start();

    // Includes the couchlogin
    // check it out here: https://github.com/couchapp/couchdb-login-jquery
    $('#login').couchLogin({
      loggedIn : function(user){
        CurrentUser.set(user);
        // Only add a User if it's not already in the list
        if(!UserList.detect(function(user){return user.get("name") == CurrentUser.get("name");})){
          CurrentSession = UserList.create({
            "name" : CurrentUser.get("name"),
            "logged_in_at" : new Date().getTime()
          });
        }

        // Bootstrapping
        window.app = new App();
        app.navigate("");

        // All link clicks go to app.navigate()
        $(document).on("click", "a:not(.data-bypass)", function(e) {
          e.preventDefault();

          var href = { prop: $(this).prop("href"), attr: $(this).attr("href") };
          var root = location.protocol + "//" + location.host + app.root;
          app.navigate(href.attr, true);
        });
      },
      loggedOut : function(){
        CurrentUser.set(new UserModel().toJSON());
        CurrentUser.trigger("change:name");
        if(CurrentSession != null) CurrentSession.destroy();
        $('#list').html('');
      }
    });

  }, 100);

}(jQuery,_,Backbone,Handlebars,window,document,config));
<|endoftext|>


<commit_before>
window._ = require('lodash');

/**
 * We'll load jQuery and the Bootstrap jQuery plugin which provides support
 * for JavaScript based Bootstrap features such as modals and tabs. This
 * code may be modified to fit the specific needs of your application.
 */

try {
    window.$ = window.jQuery = require('jquery');

    require('bootstrap-sass');
} catch (e) {}

/**
 * We'll load the axios HTTP library which allows us to easily issue requests
 * to our Laravel back-end. This library automatically handles sending the
 * CSRF token as a header based on the value of the "XSRF" token cookie.
 */

window.axios = require('axios');

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

/**
 * Next we will register the CSRF Token as a common header with Axios so that
 * all outgoing HTTP requests automatically have it attached. This is just
 * a simple convenience so we don't have to attach every token manually.
 */

let token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}

/**
 * Echo exposes an expressive API for subscribing to channels and listening
 * for events that are broadcast by Laravel. Echo and event broadcasting
 * allows your team to easily build robust real-time web applications.
 */

// import Echo from 'laravel-echo'

// window.Pusher = require('pusher-js');

// window.Echo = new Echo({
//     broadcaster: 'pusher',
//     key: 'your-pusher-key'
// });
<commit_msg>Cleaning up bootstrap.js file<commit_after>
window._ = require('lodash');

/**
 * We'll load the axios HTTP library which allows us to easily issue requests
 * to our Laravel back-end. This library automatically handles sending the
 * CSRF token as a header based on the value of the "XSRF" token cookie.
 */

window.axios = require('axios');

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';

/**
 * Next we will register the CSRF Token as a common header with Axios so that
 * all outgoing HTTP requests automatically have it attached. This is just
 * a simple convenience so we don't have to attach every token manually.
 */

let token = document.head.querySelector('meta[name="csrf-token"]');

if (token) {
    window.axios.defaults.headers.common['X-CSRF-TOKEN'] = token.content;
} else {
    console.error('CSRF token not found: https://laravel.com/docs/csrf#csrf-x-csrf-token');
}
<|endoftext|>


<commit_before>#! /usr/bin/env node

"use strict";

// mkdir comes from file.mkdir on https://github.com/gruntjs/grunt
// Like mkdir -p. Create a directory and any intermediary directories.
var pathSeparatorRe = /[\/\\]/g;
var mkdir = function(dirpath, mode) {
  // Set directory mode in a strict-mode-friendly way.
  if (mode == null) {
    mode = parseInt('0777', 8) & (~process.umask());
  }
  dirpath.split(pathSeparatorRe).reduce(function(parts, part) {
    parts += part + '/';
    var subpath = path.resolve(parts);
    if (!fs.existsSync(subpath)) {
      try {
        fs.mkdirSync(subpath, mode);
      } catch (e) {
        throw new Error('Unable to create directory "' + subpath + '" (Error code: ' + e.code + ').', e);
      }
    }
    return parts;
  }, '');
};

var fs = require("fs");
var path = require("path");
var yargs = require("yargs");

var ARGS = yargs.usage(
        "$0 tests.txt --from inputDir --to outputDir\n\n" +
        "Copies tests that are listed from an existing (test262) dir into a new dir.\n" +
        "Format input files: every line contains a path to a file to be copied."
    )
    .describe("h",    "Get help")
    .describe("from", "Path to copy tests from")
    .describe("to",   "Path to copy tests to")

    .alias("h", "help")
    .wrap(80)
    .help()

    .demand(["from", "to"])

    .argv;

if (ARGS.h || ARGS.help) {
    process.exit(0);
}

var tests = [];

// For every input file, read content and insert in hash table
for (let i = 0; i < ARGS._.length; i++) {
    tests = tests.concat(fs.readFileSync(ARGS._[i], {encoding: 'utf-8'}).split(/\n/g));
}

console.log("Found " + tests.length + " tests");

// For every hash table element, copy file from path to destination
for (let i = 0; i < tests.length; i++) {
    let dest = path.join(ARGS.to, "test", tests[i]);
    mkdir(path.dirname(dest));
    fs.writeFileSync(dest, fs.readFileSync(path.join(ARGS.from, "test", tests[i]), {encoding: 'utf-8'}));
}

var harnessFiles = fs.readdirSync(path.join(ARGS.from, "harness"));
mkdir(path.join(ARGS.to, "harness"));
for (let i = 0; i < harnessFiles.length; i++) {
    let stats = fs.statSync(path.join(ARGS.from, "harness", harnessFiles[i]));

    if (stats.isDirectory()) {
        continue;
    }

    fs.writeFileSync(path.join(ARGS.to, "harness", harnessFiles[i]), fs.readFileSync(path.join(ARGS.from, "harness", harnessFiles[i]), {encoding: 'utf-8'}));
}
<commit_msg>Clarify help in copy script<commit_after>#! /usr/bin/env node

"use strict";

// mkdir comes from file.mkdir on https://github.com/gruntjs/grunt
// Like mkdir -p. Create a directory and any intermediary directories.
var pathSeparatorRe = /[\/\\]/g;
var mkdir = function(dirpath, mode) {
  // Set directory mode in a strict-mode-friendly way.
  if (mode == null) {
    mode = parseInt('0777', 8) & (~process.umask());
  }
  dirpath.split(pathSeparatorRe).reduce(function(parts, part) {
    parts += part + '/';
    var subpath = path.resolve(parts);
    if (!fs.existsSync(subpath)) {
      try {
        fs.mkdirSync(subpath, mode);
      } catch (e) {
        throw new Error('Unable to create directory "' + subpath + '" (Error code: ' + e.code + ').', e);
      }
    }
    return parts;
  }, '');
};

var fs = require("fs");
var path = require("path");
var yargs = require("yargs");

var ARGS = yargs.usage(
        "$0 tests.txt --from inputDir --to outputDir\n\n" +
        "Copies tests that are listed from an existing (test262) dir into a new dir.\n" +
        "Format input files: every line contains a path to a file to be copied."
    )
    .describe("h",    "Get help")
    .describe("from", "Test262 root path to copy tests from")
    .describe("to",   "test262 root path to copy tests to")

    .alias("h", "help")
    .wrap(80)
    .help()

    .demand(["from", "to"])

    .argv;

if (ARGS.h || ARGS.help) {
    process.exit(0);
}

var tests = [];

// For every input file, read content and insert in hash table
for (let i = 0; i < ARGS._.length; i++) {
    tests = tests.concat(fs.readFileSync(ARGS._[i], {encoding: 'utf-8'}).split(/\n/g));
}

console.log("Found " + tests.length + " tests");

// For every hash table element, copy file from path to destination
for (let i = 0; i < tests.length; i++) {
    let dest = path.join(ARGS.to, "test", tests[i]);
    mkdir(path.dirname(dest));
    fs.writeFileSync(dest, fs.readFileSync(path.join(ARGS.from, "test", tests[i]), {encoding: 'utf-8'}));
}

var harnessFiles = fs.readdirSync(path.join(ARGS.from, "harness"));
mkdir(path.join(ARGS.to, "harness"));
for (let i = 0; i < harnessFiles.length; i++) {
    let stats = fs.statSync(path.join(ARGS.from, "harness", harnessFiles[i]));

    if (stats.isDirectory()) {
        continue;
    }

    fs.writeFileSync(path.join(ARGS.to, "harness", harnessFiles[i]), fs.readFileSync(path.join(ARGS.from, "harness", harnessFiles[i]), {encoding: 'utf-8'}));
}
<|endoftext|>


<commit_before>goog.provide('dikmax.App');

goog.require('goog.array');
goog.require('goog.dom');
goog.require('goog.dom.classlist');
goog.require('goog.dom.dataset');
goog.require('goog.dom.ViewportSizeMonitor');
goog.require('goog.events');
goog.require('goog.html.TrustedResourceUrl');
goog.require('goog.math.Size');
goog.require('goog.net.jsloader');
goog.require('goog.string');
goog.require('goog.string.Const');
goog.require('goog.style');
goog.require('goog.Timer');

dikmax.App.init = function () {
  dikmax.App.setupNavigation_();
  dikmax.App.setupPanoramas_();
  dikmax.App.setupLazyImages_();
  dikmax.App.setupLazyIframes_();
  dikmax.App.loadDisqus_();
};

dikmax.App.setupNavigation_ = function () {
  const menuButton = goog.dom.getElementByClass('navbar__menu');
  const sidebar = goog.dom.getElementByClass('sidebar');
  const sidebarPanel = goog.dom.getElementByClass('sidebar__panel');

  goog.events.listen(menuButton, goog.events.EventType.CLICK, (event) => {
    event.preventDefault();
    goog.style.setStyle(sidebar, 'display', 'block');
    goog.Timer.callOnce(() => {
      goog.dom.classlist.add(sidebar, 'sidebar_active');
      goog.dom.classlist.add(sidebarPanel, 'sidebar__panel_active');
    }, 10);
  });

  goog.events.listen(sidebar, goog.events.EventType.CLICK, () => {
    goog.dom.classlist.remove(sidebarPanel, 'sidebar__panel_active');
    goog.dom.classlist.remove(sidebar, 'sidebar_active');
    goog.events.listenOnce(sidebar, goog.events.EventType.TRANSITIONEND,
        () => {
          goog.style.setStyle(sidebar, 'display', 'none');
        }
    );
  });
};

/**
 * @param {boolean} allowEnlarge allow making image bigger.
 * @param {?number} maxWidth Max width constrain if needed.
 * @param {?number} maxHeight Max height constrain if needed.
 * @param {HTMLImageElement} image Image to constrain.
 * @return {goog.math.Size} Resulting size.
 * @private
 */
dikmax.App.constrainImage_ = function (
  allowEnlarge, maxWidth, maxHeight, image
) {
  let result = new goog.math.Size(parseInt(image.getAttribute('width'), 10),
      parseInt(image.getAttribute('height'), 10));
  if (allowEnlarge) {
    let scale = 1;
    if (maxWidth) {
      scale = Math.max(scale, maxWidth / result.width);
    }
    if (maxHeight) {
      scale = Math.max(scale, maxHeight / result.height);
    }
    result = result.scale(scale);
  }
  if (maxWidth && result.width > maxWidth) {
    result = result.scale(maxWidth / result.width);
  }
  if (maxHeight && result.height > maxHeight) {
    result = result.scale(maxHeight / result.height);
  }

  return result;
};

dikmax.App.setupLazyImages_ = function () {
  let images = goog.dom.getElementsByClass('post__figure-img_lazy');

  const vsm = new goog.dom.ViewportSizeMonitor();

  const resizeImages = function () {
    const size = vsm.getSize();
    const imageMaxWidth = size.width - 32;
    const imageMaxHeight = size.height - 60;

    goog.array.forEach(images, (image) => {
      const newSize = dikmax.App.constrainImage_(
          false, imageMaxWidth, imageMaxHeight, image);
      goog.style.setSize(image, `${newSize.width}px`, `${newSize.height}px`);
    });
  };

  const observer = new IntersectionObserver((entries) => {
    goog.array.forEach(entries, (entry) => {
      if (entry.isIntersecting) {
        const image = entry.target;
        images = goog.array.filter(images, i => i !== image);
        observer.unobserve(image);

        // Load
        goog.events.listenOnce(image, goog.events.EventType.LOAD, () => {
          goog.style.setSize(image, '', '');
        });
        image.src = goog.dom.dataset.get(image, 'src');
        image.srcset = goog.dom.dataset.get(image, 'srcset');
        goog.dom.dataset.remove(image, 'src');
        goog.dom.dataset.remove(image, 'srcset');
      }
    });
  });
  goog.array.forEach(images, (image) => {
    observer.observe(image);
  });

  goog.events.listen(vsm, goog.events.EventType.RESIZE, () => {
    resizeImages();
  });
  resizeImages();
};

dikmax.App.setupLazyIframes_ = function () {
  const iframes = goog.dom.getElementsByClass('post__embed-lazy');

  const observer = new IntersectionObserver((entries) => {
    goog.array.forEach(entries, (entry) => {
      if (entry.isIntersecting) {
        const iframe = entry.target;
        observer.unobserve(iframe);

        // Load
        iframe.src = goog.dom.dataset.get(iframe, 'src');
        goog.dom.dataset.remove(iframe, 'src');
      }
    });
  });
  goog.array.forEach(iframes, (image) => {
    observer.observe(image);
  });
};

dikmax.App.setupPanoramas_ = function () {
  const images = goog.dom.getElementsByClass('post__figure-img');

  const vsm = new goog.dom.ViewportSizeMonitor();
  const size = vsm.getSize();
  const imageMaxWidth = size.width - 32;
  const imageMaxHeight = size.height - 60;

  goog.array.forEach(images, (image) => {
    if (!(image instanceof HTMLImageElement)) {
      return;
    }
    const smallSize = dikmax.App.constrainImage_(
        false, imageMaxWidth, imageMaxHeight, image);
    const largeSize = dikmax.App.constrainImage_(
        true, null, imageMaxHeight, image);
    if (!goog.math.Size.equals(smallSize, largeSize)) {
      // There's no point to introduce panorama if size wouldn't change.
      const src = goog.dom.dataset.get(image, 'src');
      if (src !== null && goog.string.endsWith(src, '-pano.jpg')) {
        dikmax.App.handlePanorama_(image);
      }
    }
  });
};

const SVG_NS = 'http://www.w3.org/2000/svg';
const PATH_TAG = 'path';

/**
 * @return {!Element} icon.
 * @private
 */
dikmax.App.getZoomInIcon_ = function () {
  /*
   <svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
   <path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5
   3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49
   19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
   <path d="M0 0h24v24H0V0z" fill="none"/>
   <path d="M12 10h-2v2H9v-2H7V9h2V7h1v2h2v1z"/>
   </svg>
   */

  const svg = document.createElementNS(SVG_NS, 'svg');
  svg.setAttribute('viewBox', '0 0 24 24');
  svg.setAttribute('role', 'img');

  const path1 = document.createElementNS(SVG_NS, PATH_TAG);
  path1.setAttribute('d',
      'M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 ' +
      '9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28' +
      'v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5' +
      'S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z'
  );
  svg.appendChild(path1);

  const path2 = document.createElementNS(SVG_NS, PATH_TAG);
  path2.setAttribute('d', 'M0 0h24v24H0V0z');
  path2.setAttribute('fill', 'none');
  svg.appendChild(path2);

  const path3 = document.createElementNS(SVG_NS, PATH_TAG);
  path3.setAttribute('d', 'M12 10h-2v2H9v-2H7V9h2V7h1v2h2v1z');
  svg.appendChild(path3);

  return svg;
};

/**
 * @param {!HTMLImageElement} _image Element to setup pano.
 * @private
 */
dikmax.App.handlePanorama_ = function (_image) {
  const image = _image;
  let expanded = false;
  const inner = goog.dom.getParentElement(image);
  goog.style.setStyle(inner, 'cursor', 'zoom-in');

  // Adding overlay
  const overlay = goog.dom.createDom('div', 'post__figure-pano-overlay',
      dikmax.App.getZoomInIcon_());

  goog.dom.appendChild(inner, overlay);

  // Get names of bigger images
  const smallSrc = goog.dom.dataset.get(image, 'src');
  const smallSrcSet = goog.dom.dataset.get(image, 'srcset');
  const largeSrc = smallSrc.replace(/-pano\.jpg$/, '-pano-full.jpg');
  let largeSrcSet = null;
  if (smallSrcSet) {
    largeSrcSet = smallSrcSet.replace(/-pano\.jpg/g, '-pano-full.jpg');
  }
  goog.events.listen(inner, goog.events.EventType.CLICK, () => {
    expanded = !expanded;
    goog.dom.classlist.enable(image, 'post__figure-img_pano', expanded);
    goog.dom.classlist.enable(inner, 'post__figure-inner_pano', expanded);
    goog.style.setStyle(inner, 'cursor', expanded ? 'zoom-out' : 'zoom-in');
    goog.style.setElementShown(overlay, !expanded);

    image.src = expanded ? largeSrc : smallSrc;
    if (largeSrcSet && smallSrcSet) {
      image.srcset = expanded ? largeSrcSet : smallSrcSet;
    }

    if (expanded) {
      const imageTop = goog.style.getPageOffsetTop(image);
      window.scrollTo(0, imageTop - 60);

      // Scrolling image to center
      const vsm = new goog.dom.ViewportSizeMonitor();
      const size = vsm.getSize();
      const imageMaxHeight = size.height - 60;
      const largeSize = dikmax.App.constrainImage_(
          true, null, imageMaxHeight, image);

      const scrollLeft = (largeSize.width - size.width) / 2;
      if (scrollLeft >= 0) {
        inner.scrollLeft = scrollLeft;
      }
    }
  });
};

const DISQUS_URL =
  goog.html.TrustedResourceUrl.fromConstant(
    goog.string.Const.from('//dikmax.disqus.com/embed.js'));

dikmax.App.loadDisqus_ = function () {
  const observer = new IntersectionObserver((entries) => {
    goog.array.forEach(entries, (entry) => {
      if (entry.isIntersecting) {
        observer.disconnect();
        // Load script.
        goog.net.jsloader.safeLoad(DISQUS_URL);
      }
    });
  });
  const element = goog.dom.getElement('disqus_thread');
  if (element) {
    observer.observe(element);
  }
};
<commit_msg>Delay load lazy images in case of fast scroll.<commit_after>goog.provide('dikmax.App');

goog.require('goog.array');
goog.require('goog.dom');
goog.require('goog.dom.classlist');
goog.require('goog.dom.dataset');
goog.require('goog.dom.ViewportSizeMonitor');
goog.require('goog.events');
goog.require('goog.html.TrustedResourceUrl');
goog.require('goog.math.Size');
goog.require('goog.net.jsloader');
goog.require('goog.string');
goog.require('goog.string.Const');
goog.require('goog.style');
goog.require('goog.Timer');

const LOAD_DELAY = 100;

dikmax.App.init = function () {
  dikmax.App.setupNavigation_();
  dikmax.App.setupPanoramas_();
  dikmax.App.setupLazyImages_();
  dikmax.App.setupLazyIframes_();
  dikmax.App.loadDisqus_();
};

dikmax.App.setupNavigation_ = function () {
  const menuButton = goog.dom.getElementByClass('navbar__menu');
  const sidebar = goog.dom.getElementByClass('sidebar');
  const sidebarPanel = goog.dom.getElementByClass('sidebar__panel');

  goog.events.listen(menuButton, goog.events.EventType.CLICK, (event) => {
    event.preventDefault();
    goog.style.setStyle(sidebar, 'display', 'block');
    goog.Timer.callOnce(() => {
      goog.dom.classlist.add(sidebar, 'sidebar_active');
      goog.dom.classlist.add(sidebarPanel, 'sidebar__panel_active');
    }, 10);
  });

  goog.events.listen(sidebar, goog.events.EventType.CLICK, () => {
    goog.dom.classlist.remove(sidebarPanel, 'sidebar__panel_active');
    goog.dom.classlist.remove(sidebar, 'sidebar_active');
    goog.events.listenOnce(sidebar, goog.events.EventType.TRANSITIONEND,
        () => {
          goog.style.setStyle(sidebar, 'display', 'none');
        }
    );
  });
};

/**
 * @param {boolean} allowEnlarge allow making image bigger.
 * @param {?number} maxWidth Max width constrain if needed.
 * @param {?number} maxHeight Max height constrain if needed.
 * @param {HTMLImageElement} image Image to constrain.
 * @return {goog.math.Size} Resulting size.
 * @private
 */
dikmax.App.constrainImage_ = function (
  allowEnlarge, maxWidth, maxHeight, image
) {
  let result = new goog.math.Size(parseInt(image.getAttribute('width'), 10),
      parseInt(image.getAttribute('height'), 10));
  if (allowEnlarge) {
    let scale = 1;
    if (maxWidth) {
      scale = Math.max(scale, maxWidth / result.width);
    }
    if (maxHeight) {
      scale = Math.max(scale, maxHeight / result.height);
    }
    result = result.scale(scale);
  }
  if (maxWidth && result.width > maxWidth) {
    result = result.scale(maxWidth / result.width);
  }
  if (maxHeight && result.height > maxHeight) {
    result = result.scale(maxHeight / result.height);
  }

  return result;
};

dikmax.App.setupLazyImages_ = function () {
  /** @type {[HTMLImageElement, boolean]} */
  let images = goog.array.map(
    goog.dom.getElementsByClass('post__figure-img_lazy'),
    image => [image, false]
  );

  const vsm = new goog.dom.ViewportSizeMonitor();

  const resizeImages = function () {
    const size = vsm.getSize();
    const imageMaxWidth = size.width - 32;
    const imageMaxHeight = size.height - 60;

    goog.array.forEach(images, (image) => {
      const newSize = dikmax.App.constrainImage_(
          false, imageMaxWidth, imageMaxHeight, image[0]);
      goog.style.setSize(image[0], `${newSize.width}px`, `${newSize.height}px`);
    });
  };

  const observer = new IntersectionObserver((entries) => {
    goog.array.forEach(entries, (entry) => {
      const image = entry.target;
      let pair;
      goog.array.forEach(images, (i) => {
        if (i[0] === image) {
          // eslint-disable-next-line no-param-reassign
          i[1] = entry.isIntersecting;
          pair = i;
        }
      });

      if (entry.isIntersecting) {
        // Delay image load for small time in case of fast scroll.
        setTimeout(() => {
          if (!pair[1]) {
            return;
          }

          images = goog.array.filter(images, i => i !== pair);
          observer.unobserve(image);

          // Load
          goog.events.listenOnce(image, goog.events.EventType.LOAD, () => {
            goog.style.setSize(image, '', '');
          });
          image.src = goog.dom.dataset.get(image, 'src');
          image.srcset = goog.dom.dataset.get(image, 'srcset');
          goog.dom.dataset.remove(image, 'src');
          goog.dom.dataset.remove(image, 'srcset');
        }, LOAD_DELAY);
      }
    });
  });

  goog.array.forEach(images, (image) => {
    observer.observe(image[0]);
  });

  goog.events.listen(vsm, goog.events.EventType.RESIZE, () => {
    resizeImages();
  });
  resizeImages();
};

dikmax.App.setupLazyIframes_ = function () {
  const iframes = goog.dom.getElementsByClass('post__embed-lazy');

  const observer = new IntersectionObserver((entries) => {
    goog.array.forEach(entries, (entry) => {
      if (entry.isIntersecting) {
        const iframe = entry.target;
        observer.unobserve(iframe);

        // Load
        iframe.src = goog.dom.dataset.get(iframe, 'src');
        goog.dom.dataset.remove(iframe, 'src');
      }
    });
  });
  goog.array.forEach(iframes, (image) => {
    observer.observe(image);
  });
};

dikmax.App.setupPanoramas_ = function () {
  const images = goog.dom.getElementsByClass('post__figure-img');

  const vsm = new goog.dom.ViewportSizeMonitor();
  const size = vsm.getSize();
  const imageMaxWidth = size.width - 32;
  const imageMaxHeight = size.height - 60;

  goog.array.forEach(images, (image) => {
    if (!(image instanceof HTMLImageElement)) {
      return;
    }
    const smallSize = dikmax.App.constrainImage_(
        false, imageMaxWidth, imageMaxHeight, image);
    const largeSize = dikmax.App.constrainImage_(
        true, null, imageMaxHeight, image);
    if (!goog.math.Size.equals(smallSize, largeSize)) {
      // There's no point to introduce panorama if size wouldn't change.
      const src = goog.dom.dataset.get(image, 'src');
      if (src !== null && goog.string.endsWith(src, '-pano.jpg')) {
        dikmax.App.handlePanorama_(image);
      }
    }
  });
};

const SVG_NS = 'http://www.w3.org/2000/svg';
const PATH_TAG = 'path';

/**
 * @return {!Element} icon.
 * @private
 */
dikmax.App.getZoomInIcon_ = function () {
  /*
   <svg fill="#000000" height="24" viewBox="0 0 24 24" width="24" xmlns="http://www.w3.org/2000/svg">
   <path d="M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 9.5
   3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28v.79l5 4.99L20.49
   19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z"/>
   <path d="M0 0h24v24H0V0z" fill="none"/>
   <path d="M12 10h-2v2H9v-2H7V9h2V7h1v2h2v1z"/>
   </svg>
   */

  const svg = document.createElementNS(SVG_NS, 'svg');
  svg.setAttribute('viewBox', '0 0 24 24');
  svg.setAttribute('role', 'img');

  const path1 = document.createElementNS(SVG_NS, PATH_TAG);
  path1.setAttribute('d',
      'M15.5 14h-.79l-.28-.27C15.41 12.59 16 11.11 16 9.5 16 5.91 13.09 3 ' +
      '9.5 3S3 5.91 3 9.5 5.91 16 9.5 16c1.61 0 3.09-.59 4.23-1.57l.27.28' +
      'v.79l5 4.99L20.49 19l-4.99-5zm-6 0C7.01 14 5 11.99 5 9.5' +
      'S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z'
  );
  svg.appendChild(path1);

  const path2 = document.createElementNS(SVG_NS, PATH_TAG);
  path2.setAttribute('d', 'M0 0h24v24H0V0z');
  path2.setAttribute('fill', 'none');
  svg.appendChild(path2);

  const path3 = document.createElementNS(SVG_NS, PATH_TAG);
  path3.setAttribute('d', 'M12 10h-2v2H9v-2H7V9h2V7h1v2h2v1z');
  svg.appendChild(path3);

  return svg;
};

/**
 * @param {!HTMLImageElement} _image Element to setup pano.
 * @private
 */
dikmax.App.handlePanorama_ = function (_image) {
  const image = _image;
  let expanded = false;
  const inner = goog.dom.getParentElement(image);
  goog.style.setStyle(inner, 'cursor', 'zoom-in');

  // Adding overlay
  const overlay = goog.dom.createDom('div', 'post__figure-pano-overlay',
      dikmax.App.getZoomInIcon_());

  goog.dom.appendChild(inner, overlay);

  // Get names of bigger images
  const smallSrc = goog.dom.dataset.get(image, 'src');
  const smallSrcSet = goog.dom.dataset.get(image, 'srcset');
  const largeSrc = smallSrc.replace(/-pano\.jpg$/, '-pano-full.jpg');
  let largeSrcSet = null;
  if (smallSrcSet) {
    largeSrcSet = smallSrcSet.replace(/-pano\.jpg/g, '-pano-full.jpg');
  }
  goog.events.listen(inner, goog.events.EventType.CLICK, () => {
    expanded = !expanded;
    goog.dom.classlist.enable(image, 'post__figure-img_pano', expanded);
    goog.dom.classlist.enable(inner, 'post__figure-inner_pano', expanded);
    goog.style.setStyle(inner, 'cursor', expanded ? 'zoom-out' : 'zoom-in');
    goog.style.setElementShown(overlay, !expanded);

    image.src = expanded ? largeSrc : smallSrc;
    if (largeSrcSet && smallSrcSet) {
      image.srcset = expanded ? largeSrcSet : smallSrcSet;
    }

    if (expanded) {
      const imageTop = goog.style.getPageOffsetTop(image);
      window.scrollTo(0, imageTop - 60);

      // Scrolling image to center
      const vsm = new goog.dom.ViewportSizeMonitor();
      const size = vsm.getSize();
      const imageMaxHeight = size.height - 60;
      const largeSize = dikmax.App.constrainImage_(
          true, null, imageMaxHeight, image);

      const scrollLeft = (largeSize.width - size.width) / 2;
      if (scrollLeft >= 0) {
        inner.scrollLeft = scrollLeft;
      }
    }
  });
};

const DISQUS_URL =
  goog.html.TrustedResourceUrl.fromConstant(
    goog.string.Const.from('//dikmax.disqus.com/embed.js'));

dikmax.App.loadDisqus_ = function () {
  const observer = new IntersectionObserver((entries) => {
    goog.array.forEach(entries, (entry) => {
      if (entry.isIntersecting) {
        observer.disconnect();
        // Load script.
        goog.net.jsloader.safeLoad(DISQUS_URL);
      }
    });
  });
  const element = goog.dom.getElement('disqus_thread');
  if (element) {
    observer.observe(element);
  }
};
<|endoftext|>


<commit_before>#!/usr/bin/env node

var questKitVersion = "0.0.1";

var path = require("path");
var fs = require("fs");
var yaml = require("js-yaml");

String.prototype.format = function() {
    var args = arguments;
    return this.replace(/{(\d+)}/g, function(match, number) {
      return typeof args[number] != 'undefined'
        ? args[number]
        : match
      ;
    });
};

function Compiler() {
    this.language = {};

    this.process = function(inputFilename, sourcePath, options) {
        var outputPath = path.resolve(path.dirname(inputFilename));

        this.language = yaml.safeLoad(fs.readFileSync(path.join(sourcePath, "en.yaml")));

        var sections = [];

        this.processFile(sections, path.resolve(inputFilename), true);
        this.processFile(sections, this.findFile("core.yaml", outputPath, sourcePath), false);

        console.log("Loaded {0} sections".format(sections.length));
        console.log("Writing story.js");

        var jsTemplateFile = fs.readFileSync(path.join(sourcePath, "questkit.template.js"));
        var jsData = "// Created with QuestKit {0}\n// https://github.com/textadventures/questkit\n\n".format(questKitVersion) + jsTemplateFile.toString();

        var outputJsFile = [];
        outputJsFile.push(jsData);
        outputJsFile.push("\n\n");

        var game = sections.shift();

        if (!game.pov) {
            // If a player object doesn't exist already, create it in the first location

            var foundPlayer = false;
            var firstLocation;

            sections.forEach(function(section) {
                if (section["~name"] == "player") {
                    foundPlayer = true;
                    return;
                }

                if (!firstLocation && section["~type"] == "location") {
                    firstLocation = section["~name"];
                }
            });

            if (!foundPlayer) {
                sections.push({
                    "~name": "player",
                    "~type": "object",
                    parent: firstLocation
                });
            }
        }

        Object.keys(game).forEach(function(attr) {
            outputJsFile.push("set(\"{0}\", {1});\n".format(attr, JSON.stringify(game[attr])));
        });

        sections.forEach(function(section) {
            outputJsFile.push("\n");
            this.writeSection(outputJsFile, section);
        }, this);

        fs.writeFileSync(path.join(outputPath, "story.js"), outputJsFile.join(""));

        console.log("Done.");

        return outputPath;
    };

    this.processFile = function(sections, inputFilename, isFirst) {
        var compiler = this;
        var file = fs.readFileSync(inputFilename, "utf8");

        var defaultParent;
        var count = 0;

        var docs = yaml.safeLoadAll(file, function(section) {
            sections.push(section);

            // If any attribute has a sub-attribute "template", replace it with the value from the loaded language file

            Object.keys(section).forEach(function(attr) {
                if (section[attr] && section[attr].template) {
                    console.log(section[attr]);
                    section[attr] = compiler.language[section[attr].template];
                    console.log(section[attr]);
                }
            });

            if (++count == 1 && isFirst) {
                // no further processing for the game data at the top of the first file
                return;
            }

            var type = Object.keys(section)[0];
            if (!(type in compiler.sectionTypes)) {
                throw "Unknown type - {0}: {1}".format(type, section[type]);
            }

            var name = section[type];
            if (!name) name = "~" + compiler.anonymousCount++;

            if (type == "location") {
                // set default parent to this for subsequent objects, exits etc.
                defaultParent = name;

                // convert any directional attributes into exits
                Object.keys(compiler.directions).forEach(function(direction) {
                    if (!(direction in section)) return;

                    // create the exit
                    sections.push({
                        "~name": "~" + compiler.anonymousCount++,
                        "~type": "exit",
                        parent: name,
                        direction: direction,
                        to: section[direction]
                    });

                    // and the exit in the opposite direction
                    sections.push({
                        "~name": "~" + compiler.anonymousCount++,
                        "~type": "exit",
                        parent: section[direction],
                        direction: compiler.directions[direction],
                        to: name
                    });

                    delete section[direction];
                });
            }
            else {
                if (defaultParent && !section.parent) section.parent = defaultParent;
            }

            section["~type"] = type;
            section["~name"] = name;
        });
    };

    this.findFile = function(filename, outputPath, sourcePath) {
        var outputPathFile = path.join(outputPath, filename);
        if (fs.existsSync(outputPathFile)) {
            return outputPathFile;
        }
        return path.join(sourcePath, filename);
    };

    // section types and the _internal list they live in

    this.sectionTypes = {
        "command": "commands",
        "location": "objects",
        "object": "objects",
        "character": "objects",
        "exit": "exits",
    };

    // directions and their opposites

    this.directions = {
        "north": "south",
        "east": "west",
        "south": "north",
        "west": "east",
        "northeast": "southwest",
        "southeast": "northwest",
        "southwest": "northeast",
        "northwest": "southeast",
        "up": "down",
        "down": "up",
        "in": "out",
        "out": "in",
    }

    this.anonymousCount = 0;

    this.writeSection = function(outputJsFile, section) {
        var type = section["~type"];
        var name = section["~name"];
        outputJsFile.push("Quest._internal.{0}.push(\"{1}\");\n".format(this.sectionTypes[type], name));

        if (type == "command") {
            var patterns = [];
            if (!section.patterns) section.patterns = [];
            if (section.pattern) {
                section.patterns.push(section.pattern)
                delete section.pattern;
            }
            var variablesRegex = /\#(.*?)\#/g;
            var groups = [];
            while (match = variablesRegex.exec(section.patterns[0])) {
                groups.push(match[1]);
            }
            section.patterns.forEach(function(pattern) {
                pattern = pattern.replace(/\(/g, "\\(");
                pattern = pattern.replace(/\)/g, "\\)");
                pattern = pattern.replace(/\./g, "\\.");
                pattern = pattern.replace(/\?/g, "\\?");
                pattern = pattern.replace(variablesRegex, "(.*?)");
                patterns.push("/^" + pattern + "$/");
            });
            delete section.patterns;

            outputJsFile.push("Quest._internal.regexes[\"{0}\"] = {\n".format(name));
            outputJsFile.push("\tpatterns: [{0}],\n".format(patterns.join(", ")));
            outputJsFile.push("\tgroups: {0}\n".format(JSON.stringify(groups)));
            outputJsFile.push("};\n");

            if (section.action && section.action.script) {
                outputJsFile.push("Quest._internal.scripts[\"{0}.action\"] = function({1}) {\n".format(name, groups.join(", ")));
                this.writeJs(outputJsFile, 1, section.action.script);
                outputJsFile.push("};\n");

                delete section.action;
            }
        }

        var attrs = Object.keys(section).slice(0);
        attrs.shift();
        attrs.forEach(function (attr) {
            if (attr.indexOf("~") == 0) return;
            if (section[attr].script) {
                outputJsFile.push("Quest._internal.scripts[\"{0}.{1}\"] = function() {\n".format(name, attr));
                this.writeJs(outputJsFile, 1, section[attr].script);
                outputJsFile.push("};\n");
            }
            else {
                outputJsFile.push("set(\"{0}.{1}\", {2});\n".format(name, attr, JSON.stringify(section[attr])));
            }
        }, this);
    };

    this.writeJs = function(outputJsFile, tabCount, js) {
        var tabs = new Array(tabCount).join("\t");
        var lines = js.trim().replace(/\r/g, "").split("\n");
        lines.forEach(function(jsLine) {
            outputJsFile.push("{0}\t{1}\n".format(tabs, jsLine));
        });
    };
}

console.log("QuestKit " + questKitVersion);

var argv = require("yargs")
    .usage("Compiles a QuestKit script file into HTML and JavaScript.\nFor help, see http://docs.textadventures.co.uk/questkit/\nUsage: $0 filename.yaml [options]")
    .demand(1)
    .argv;

var options = {
};

var compiler = new Compiler();
var result = compiler.process(argv._[0], __dirname, options);<commit_msg>Remove extra logging<commit_after>#!/usr/bin/env node

var questKitVersion = "0.0.1";

var path = require("path");
var fs = require("fs");
var yaml = require("js-yaml");

String.prototype.format = function() {
    var args = arguments;
    return this.replace(/{(\d+)}/g, function(match, number) {
      return typeof args[number] != 'undefined'
        ? args[number]
        : match
      ;
    });
};

function Compiler() {
    this.language = {};

    this.process = function(inputFilename, sourcePath, options) {
        var outputPath = path.resolve(path.dirname(inputFilename));

        this.language = yaml.safeLoad(fs.readFileSync(path.join(sourcePath, "en.yaml")));

        var sections = [];

        this.processFile(sections, path.resolve(inputFilename), true);
        this.processFile(sections, this.findFile("core.yaml", outputPath, sourcePath), false);

        console.log("Loaded {0} sections".format(sections.length));
        console.log("Writing story.js");

        var jsTemplateFile = fs.readFileSync(path.join(sourcePath, "questkit.template.js"));
        var jsData = "// Created with QuestKit {0}\n// https://github.com/textadventures/questkit\n\n".format(questKitVersion) + jsTemplateFile.toString();

        var outputJsFile = [];
        outputJsFile.push(jsData);
        outputJsFile.push("\n\n");

        var game = sections.shift();

        if (!game.pov) {
            // If a player object doesn't exist already, create it in the first location

            var foundPlayer = false;
            var firstLocation;

            sections.forEach(function(section) {
                if (section["~name"] == "player") {
                    foundPlayer = true;
                    return;
                }

                if (!firstLocation && section["~type"] == "location") {
                    firstLocation = section["~name"];
                }
            });

            if (!foundPlayer) {
                sections.push({
                    "~name": "player",
                    "~type": "object",
                    parent: firstLocation
                });
            }
        }

        Object.keys(game).forEach(function(attr) {
            outputJsFile.push("set(\"{0}\", {1});\n".format(attr, JSON.stringify(game[attr])));
        });

        sections.forEach(function(section) {
            outputJsFile.push("\n");
            this.writeSection(outputJsFile, section);
        }, this);

        fs.writeFileSync(path.join(outputPath, "story.js"), outputJsFile.join(""));

        console.log("Done.");

        return outputPath;
    };

    this.processFile = function(sections, inputFilename, isFirst) {
        var compiler = this;
        var file = fs.readFileSync(inputFilename, "utf8");

        var defaultParent;
        var count = 0;

        var docs = yaml.safeLoadAll(file, function(section) {
            sections.push(section);

            // If any attribute has a sub-attribute "template", replace it with the value from the loaded language file

            Object.keys(section).forEach(function(attr) {
                if (section[attr] && section[attr].template) {
                    section[attr] = compiler.language[section[attr].template];
                }
            });

            if (++count == 1 && isFirst) {
                // no further processing for the game data at the top of the first file
                return;
            }

            var type = Object.keys(section)[0];
            if (!(type in compiler.sectionTypes)) {
                throw "Unknown type - {0}: {1}".format(type, section[type]);
            }

            var name = section[type];
            if (!name) name = "~" + compiler.anonymousCount++;

            if (type == "location") {
                // set default parent to this for subsequent objects, exits etc.
                defaultParent = name;

                // convert any directional attributes into exits
                Object.keys(compiler.directions).forEach(function(direction) {
                    if (!(direction in section)) return;

                    // create the exit
                    sections.push({
                        "~name": "~" + compiler.anonymousCount++,
                        "~type": "exit",
                        parent: name,
                        direction: direction,
                        to: section[direction]
                    });

                    // and the exit in the opposite direction
                    sections.push({
                        "~name": "~" + compiler.anonymousCount++,
                        "~type": "exit",
                        parent: section[direction],
                        direction: compiler.directions[direction],
                        to: name
                    });

                    delete section[direction];
                });
            }
            else {
                if (defaultParent && !section.parent) section.parent = defaultParent;
            }

            section["~type"] = type;
            section["~name"] = name;
        });
    };

    this.findFile = function(filename, outputPath, sourcePath) {
        var outputPathFile = path.join(outputPath, filename);
        if (fs.existsSync(outputPathFile)) {
            return outputPathFile;
        }
        return path.join(sourcePath, filename);
    };

    // section types and the _internal list they live in

    this.sectionTypes = {
        "command": "commands",
        "location": "objects",
        "object": "objects",
        "character": "objects",
        "exit": "exits",
    };

    // directions and their opposites

    this.directions = {
        "north": "south",
        "east": "west",
        "south": "north",
        "west": "east",
        "northeast": "southwest",
        "southeast": "northwest",
        "southwest": "northeast",
        "northwest": "southeast",
        "up": "down",
        "down": "up",
        "in": "out",
        "out": "in",
    }

    this.anonymousCount = 0;

    this.writeSection = function(outputJsFile, section) {
        var type = section["~type"];
        var name = section["~name"];
        outputJsFile.push("Quest._internal.{0}.push(\"{1}\");\n".format(this.sectionTypes[type], name));

        if (type == "command") {
            var patterns = [];
            if (!section.patterns) section.patterns = [];
            if (section.pattern) {
                section.patterns.push(section.pattern)
                delete section.pattern;
            }
            var variablesRegex = /\#(.*?)\#/g;
            var groups = [];
            while (match = variablesRegex.exec(section.patterns[0])) {
                groups.push(match[1]);
            }
            section.patterns.forEach(function(pattern) {
                pattern = pattern.replace(/\(/g, "\\(");
                pattern = pattern.replace(/\)/g, "\\)");
                pattern = pattern.replace(/\./g, "\\.");
                pattern = pattern.replace(/\?/g, "\\?");
                pattern = pattern.replace(variablesRegex, "(.*?)");
                patterns.push("/^" + pattern + "$/");
            });
            delete section.patterns;

            outputJsFile.push("Quest._internal.regexes[\"{0}\"] = {\n".format(name));
            outputJsFile.push("\tpatterns: [{0}],\n".format(patterns.join(", ")));
            outputJsFile.push("\tgroups: {0}\n".format(JSON.stringify(groups)));
            outputJsFile.push("};\n");

            if (section.action && section.action.script) {
                outputJsFile.push("Quest._internal.scripts[\"{0}.action\"] = function({1}) {\n".format(name, groups.join(", ")));
                this.writeJs(outputJsFile, 1, section.action.script);
                outputJsFile.push("};\n");

                delete section.action;
            }
        }

        var attrs = Object.keys(section).slice(0);
        attrs.shift();
        attrs.forEach(function (attr) {
            if (attr.indexOf("~") == 0) return;
            if (section[attr].script) {
                outputJsFile.push("Quest._internal.scripts[\"{0}.{1}\"] = function() {\n".format(name, attr));
                this.writeJs(outputJsFile, 1, section[attr].script);
                outputJsFile.push("};\n");
            }
            else {
                outputJsFile.push("set(\"{0}.{1}\", {2});\n".format(name, attr, JSON.stringify(section[attr])));
            }
        }, this);
    };

    this.writeJs = function(outputJsFile, tabCount, js) {
        var tabs = new Array(tabCount).join("\t");
        var lines = js.trim().replace(/\r/g, "").split("\n");
        lines.forEach(function(jsLine) {
            outputJsFile.push("{0}\t{1}\n".format(tabs, jsLine));
        });
    };
}

console.log("QuestKit " + questKitVersion);

var argv = require("yargs")
    .usage("Compiles a QuestKit script file into HTML and JavaScript.\nFor help, see http://docs.textadventures.co.uk/questkit/\nUsage: $0 filename.yaml [options]")
    .demand(1)
    .argv;

var options = {
};

var compiler = new Compiler();
var result = compiler.process(argv._[0], __dirname, options);<|endoftext|>


<commit_before>var Router = require('geddy/lib/router').Router;

router = new Router();
router.match('/').to({controller: 'Main', action: 'index'});
router.resource('users');

exports.router = router;
<commit_msg>Added various routing examples as comments.<commit_after>var Router = require('geddy/lib/router').Router;

router = new Router();
router.match('/').to({controller: 'Main', action: 'index'});

// Basic routes
// router.match('/moving/pictures/:id').to(
//    {controller: 'Moving', action: 'pictures'});
// router.match('/farewells/:farewelltype/kings/:kingid').to(
//    {controller: 'Farewells', action: 'kings'});
// Can also match specific HTTP methods only
// router.match('/xandadu', 'get').to(
//    {controller: 'Xandadu', action: 'specialHandler'});
//
// Resource-based routes
// router.resource('hemispheres');

exports.router = router;

<|endoftext|>