<commit_before>// heavily based on https://github.com/lmammino/norrisbot

var express = require('express');
var bodyParser = require('body-parser');
var util = require('util');
//var path = require('path');
//var fs = require('fs');
//var SQLite = require('sqlite3').verbose();
var slackbots = require('slackbots');

var hello = require('./hello');

var app = express();
var port = process.env.PORT || 3000;

// body parser middleware
app.use(bodyParser.urlencoded({ extended: true }));

// test route
app.get('/', function (req, res) { res.status(200).send('Hello world!') });

// hello world
app.post('/hello', hello);

// error handler
app.use(function (err, req, res, next) {
  console.error(err.stack);
  res.status(400).send(err.message);
});

// start listening
app.listen(port, function () {
  console.log('Stranger listening on port ' + port);
});

var Stranger = function Constructor(settings) {
    this.settings = settings;
    this.settings.name = this.settings.name || 'Stranger';

    // TODO: this.settings.defaultChannel = this.settings.defaultChannel || this.channels[0].name;

    //this.dbPath = settings.dbPath || path.resolve(__dirname, '..', 'data', 'stranger.db');
    this.user = null;
    //this.db = null;
};

// inherits methods and properties from the Bot constructor
util.inherits(Stranger, Bot);

// run the bot
Stranger.prototype.run = function () {
    Stranger.super_.call(this, this.settings);
    this.on('start', this._onStart);
    this.on('message', this._onMessage);
};

// on start
Stranger.prototype._onStart = function () {
    this._loadBotUser();
    //this._connectDb();
    this._helloWorld();
};

Stranger.prototype._helloWorld = function () {
    //this.postMessageToChannel(this.channels[0].name, 'Hello World!\nSay `' + this.name + '` to invoke me!', {as_user: true});
    this.postMessageToChannel(this.settings.defaultChannel, 'Hello Secret World!\nSay `' + this.name + '` to summon me.', {as_user: true});
};

// on message
Stranger.prototype._onMessage = function (message) {
    if (this._isChatMessage(message) && this._isChannelConversation(message) && !this._isFromStranger(message) && this._isMentioningStranger(message)) {
        this._sayHi(message);
    }
};

// simple reply
Stranger.prototype._sayHi = function (originalMessage) {
    var self = this;
    var messages = [
        "Why whisper what you can shout?",
        "Pluto is still a planet!",
        "Sour candy makes my face twitch.",
        "I stand up for what's right.",
        "I am terrified of tall people.",
        "Yeah I'm that kind of girl.",
        "Insomnia gives me time to think.",
        "Make it up as you go.",
        "I make mistakes because I'm human",
        "Home alone. Hears noise. Calls mom.",
        "The sky is not the limit."
    ];
    var channel = self._getChannelById(originalMessage.channel);
    self.postMessageToChannel(channel.name, messages[self._getRandomInt(0, messages.length - 1)], {as_user: true});
};

// load the user object representing the bot
Stranger.prototype._loadBotUser = function () {
    var self = this;
    this.user = this.users.filter(function (user) {
        return user.name === self.name;
    })[0];
};

// get the channel name from its id
Stranger.prototype._getChannelById = function (channelId) {
    return this.channels.filter(function (item) {
        return item.id === channelId;
    })[0];
};

// check if the message is a chat message
Stranger.prototype._isChatMessage = function (message) {
    return message.type === 'message' && Boolean(message.text);
};

// check if the message is a channel conversation
Stranger.prototype._isChannelConversation = function (message) {
    return typeof message.channel === 'string' && message.channel[0] === 'C';
};

// check if the message is mentioning Stranger
Stranger.prototype._isMentioningStranger = function (message) {
    return message.text.toLowerCase().indexOf('stranger') > -1 || message.text.toLowerCase().indexOf(this.name) > -1;
};

// check if the message is from Stranger themselves
Stranger.prototype._isFromStranger = function (message) {
    return message.user === this.user.id;
};

// helper function to get a random integer from a given range
Stranger.prototype._getRandomInt = function (min, max) {
  return Math.floor(Math.random() * (max - min + 1) + min);
}

// export Stranger
module.exports = Stranger

// bot config
var stranger = new Stranger({
    token: process.env.BOT_API_KEY || require('../token'),
    //dbPath: process.env.BOT_DB_PATH, // the env config not yet set: heroku config:add BOT_DB_PATH=thePath
    name: process.env.BOT_NAME,
    defaultChannel: process.env.BOT_DEFAULT_CHANNEL
});

// run stranger
stranger.run();
<commit_msg>Bot class linking fix.<commit_after>// heavily based on https://github.com/lmammino/norrisbot

var express = require('express');
var bodyParser = require('body-parser');
var util = require('util');
//var path = require('path');
//var fs = require('fs');
//var SQLite = require('sqlite3').verbose();
var Bot = require('slackbots');

var hello = require('./hello');

var app = express();
var port = process.env.PORT || 3000;

// body parser middleware
app.use(bodyParser.urlencoded({ extended: true }));

// test route
app.get('/', function (req, res) { res.status(200).send('Hello world!') });

// hello world
app.post('/hello', hello);

// error handler
app.use(function (err, req, res, next) {
  console.error(err.stack);
  res.status(400).send(err.message);
});

// start listening
app.listen(port, function () {
  console.log('Stranger listening on port ' + port);
});

var Stranger = function Constructor(settings) {
    this.settings = settings;
    this.settings.name = this.settings.name || 'Stranger';

    // TODO: this.settings.defaultChannel = this.settings.defaultChannel || this.channels[0].name;

    //this.dbPath = settings.dbPath || path.resolve(__dirname, '..', 'data', 'stranger.db');
    this.user = null;
    //this.db = null;
};

// inherits methods and properties from the Bot constructor
util.inherits(Stranger, Bot);

// run the bot
Stranger.prototype.run = function () {
    Stranger.super_.call(this, this.settings);
    this.on('start', this._onStart);
    this.on('message', this._onMessage);
};

// on start
Stranger.prototype._onStart = function () {
    this._loadBotUser();
    //this._connectDb();
    this._helloWorld();
};

Stranger.prototype._helloWorld = function () {
    //this.postMessageToChannel(this.channels[0].name, 'Hello World!\nSay `' + this.name + '` to invoke me!', {as_user: true});
    this.postMessageToChannel(this.settings.defaultChannel, 'Hello Secret World!\nSay `' + this.name + '` to summon me.', {as_user: true});
};

// on message
Stranger.prototype._onMessage = function (message) {
    if (this._isChatMessage(message) && this._isChannelConversation(message) && !this._isFromStranger(message) && this._isMentioningStranger(message)) {
        this._sayHi(message);
    }
};

// simple reply
Stranger.prototype._sayHi = function (originalMessage) {
    var self = this;
    var messages = [
        "Why whisper what you can shout?",
        "Pluto is still a planet!",
        "Sour candy makes my face twitch.",
        "I stand up for what's right.",
        "I am terrified of tall people.",
        "Yeah I'm that kind of girl.",
        "Insomnia gives me time to think.",
        "Make it up as you go.",
        "I make mistakes because I'm human",
        "Home alone. Hears noise. Calls mom.",
        "The sky is not the limit."
    ];
    var channel = self._getChannelById(originalMessage.channel);
    self.postMessageToChannel(channel.name, messages[self._getRandomInt(0, messages.length - 1)], {as_user: true});
};

// load the user object representing the bot
Stranger.prototype._loadBotUser = function () {
    var self = this;
    this.user = this.users.filter(function (user) {
        return user.name === self.name;
    })[0];
};

// get the channel name from its id
Stranger.prototype._getChannelById = function (channelId) {
    return this.channels.filter(function (item) {
        return item.id === channelId;
    })[0];
};

// check if the message is a chat message
Stranger.prototype._isChatMessage = function (message) {
    return message.type === 'message' && Boolean(message.text);
};

// check if the message is a channel conversation
Stranger.prototype._isChannelConversation = function (message) {
    return typeof message.channel === 'string' && message.channel[0] === 'C';
};

// check if the message is mentioning Stranger
Stranger.prototype._isMentioningStranger = function (message) {
    return message.text.toLowerCase().indexOf('stranger') > -1 || message.text.toLowerCase().indexOf(this.name) > -1;
};

// check if the message is from Stranger themselves
Stranger.prototype._isFromStranger = function (message) {
    return message.user === this.user.id;
};

// helper function to get a random integer from a given range
Stranger.prototype._getRandomInt = function (min, max) {
  return Math.floor(Math.random() * (max - min + 1) + min);
}

// export Stranger
module.exports = Stranger

// bot config
var stranger = new Stranger({
    token: process.env.BOT_API_KEY || require('../token'),
    //dbPath: process.env.BOT_DB_PATH, // the env config not yet set: heroku config:add BOT_DB_PATH=thePath
    name: process.env.BOT_NAME,
    defaultChannel: process.env.BOT_DEFAULT_CHANNEL
});

// run stranger
stranger.run();
<|endoftext|>


<commit_before>;var app = (function ($, undefined) {

	var $grid = $('#GridView1'),
		data  = [];

	_getData = function (url) {
		return $.ajax({
			url: url,
			dataType: 'html'
		});
	};

	_processTrainData = function (html) {
		var $grid    = $(html).find('#GridView1'),
			cols     = ['depart', 'to', 'track', 'line', 'train', 'status'],
			deferred = [];

		$grid.find('tr[style]').each( function (index, element) {
			var $row = $(this),
				obj  = {};

			if ( index == 0 || $row.find('td').length !== 6 ) return;

			obj['stopsUrl'] = '' + $row.closest('a').attr('href');

			$row.find('td').each( function (index, element) {
				obj[ cols[index] ] = $.trim( $(element).text() );
			});

			obj['stopsUrl'] = 'http://dv.njtransit.com/mobile/train_stops.aspx?sid=NP&train=' + obj['train'];

			data.push( obj );

			deferred.push( _getData( obj['stopsUrl'] ).then( _processStopsData( obj, data ) ) );
		});

		return $.when.apply( $, deferred );

	};

	_processStopsData = function (obj, data) {

		var defer = $.Deferred();

		return function (html) {
			var $grid = $(html).find('#table_stops');
				stops = [];

			$grid.find('td').each( function (index, element) {
				var text  = $.trim( $(this).find('p').text() ),
					parts = $.map( text.split(/\bat\b/), function (val) { return $.trim( val ); } );

				stops.push({ location: parts[0], arrival: parts[1] });
			});

			obj['stops'] = stops;

			return defer.resolve();
		};
	};

	_display = function () {

		var data = _filter();

		var tmpl = Handlebars.compile( $('#trains-tmpl').html() );

		$('#trains')
			.find('tbody')
			.empty()
			.append( tmpl( {trains: data} ) )
			.find('tr')
				.each( function (index) {
					$.data( this, 'stops', data[index]['stops'] );
				});

		$('#trains').on('click', 'tr', _onClickTrainRow);

	};

	_onClickTrainRow = function (evt) {
		var thisRow = this,
			tmpl    = Handlebars.compile( $('#stops-tmpl').html() );

		$('#stops')
			.find('tbody')
			.empty()
			.append( tmpl( {stops: $.data( thisRow, 'stops')} ) );
	};

	_filter = function () {

		var subset = [];

		$.each( data, function (index, train) {

			$.each( train['stops'], function ( index, stop ) {
				if ( train['line'] === 'Northeast Corrdr' && stop['location'].toLowerCase().indexOf('metropark') != -1 ) {
					subset.push( train );
					return false;
				}
			});

		});

		return subset;
	};

	init = function () {
		_getData('http://dv.njtransit.com/mobile/tid-mobile.aspx?sid=NP').then( _processTrainData ).then( _display );
	};

})( window.jQuery );<commit_msg>fixed init func<commit_after>;var app = (function ($, undefined) {

	var $grid = $('#GridView1'),
		data  = [];

	_getData = function (url) {
		return $.ajax({
			url: url,
			dataType: 'html'
		});
	};

	_processTrainData = function (html) {
		var $grid    = $(html).find('#GridView1'),
			cols     = ['depart', 'to', 'track', 'line', 'train', 'status'],
			deferred = [];

		$grid.find('tr[style]').each( function (index, element) {
			var $row = $(this),
				obj  = {};

			if ( index == 0 || $row.find('td').length !== 6 ) return;

			obj['stopsUrl'] = '' + $row.closest('a').attr('href');

			$row.find('td').each( function (index, element) {
				obj[ cols[index] ] = $.trim( $(element).text() );
			});

			obj['stopsUrl'] = 'http://dv.njtransit.com/mobile/train_stops.aspx?sid=NP&train=' + obj['train'];

			data.push( obj );

			deferred.push( _getData( obj['stopsUrl'] ).then( _processStopsData( obj, data ) ) );
		});

		return $.when.apply( $, deferred );

	};

	_processStopsData = function (obj, data) {

		var defer = $.Deferred();

		return function (html) {
			var $grid = $(html).find('#table_stops');
				stops = [];

			$grid.find('td').each( function (index, element) {
				var text  = $.trim( $(this).find('p').text() ),
					parts = $.map( text.split(/\bat\b/), function (val) { return $.trim( val ); } );

				stops.push({ location: parts[0], arrival: parts[1] });
			});

			obj['stops'] = stops;

			return defer.resolve();
		};
	};

	_display = function () {

		var data = _filter();

		var tmpl = Handlebars.compile( $('#trains-tmpl').html() );

		$('#trains')
			.find('tbody')
			.empty()
			.append( tmpl( {trains: data} ) )
			.find('tr')
				.each( function (index) {
					$.data( this, 'stops', data[index]['stops'] );
				});

		$('#trains').on('click', 'tr', _onClickTrainRow);

	};

	_onClickTrainRow = function (evt) {
		var thisRow = this,
			tmpl    = Handlebars.compile( $('#stops-tmpl').html() );

		$('#stops')
			.find('tbody')
			.empty()
			.append( tmpl( {stops: $.data( thisRow, 'stops')} ) );
	};

	_filter = function () {

		var subset = [];

		$.each( data, function (index, train) {

			$.each( train['stops'], function ( index, stop ) {
				if ( train['line'] === 'Northeast Corrdr' && stop['location'].toLowerCase().indexOf('metropark') != -1 ) {
					subset.push( train );
					return false;
				}
			});

		});

		return subset;
	};

	init = function () {
		_getData('http://dv.njtransit.com/mobile/tid-mobile.aspx?sid=NP').then( _processTrainData ).then( _display );
	};

	return {
		init: init
	};

})( window.jQuery );<|endoftext|>


<commit_before>var restify = require( 'restify' );
var bindIp = '0.0.0.0', bindPort = '8080';
var quotes = require('./model.js').model;
var ua = require('universal-analytics');
var visitor = ua('UA-2158627-15');

var og = []; var oga = []; var ogt = [];
var bg = []; var bga = []; var bgt = [];

var server = restify.createServer( {

    name: 'howmuchisthe.fish',
    handleUpgrades: true

} );

server.use( restify.queryParser() );
server.use( restify.bodyParser() );
server.use( restify.CORS() );

server.get( {path: '/json'}, noRequest );
server.get( {path: '/json/random'}, randomQuote );
server.get( {path: '/json/random/generate'}, generateQuote );
server.get( {path: '/json/daily'}, dailyQuote );
server.get( {path: '/json/perma/:quoteId'}, fixedQuote );

server.get(/.*/, restify.serveStatic({

    'directory': 'htdocs',
    'default': 'index.html'

}));

server.listen( bindPort, bindIp, function() {

    console.log( '%s listening at %s ', server.name , server.url );
    console.log( '#Quotes %s', quotes.length );
    console.log( 'Generating data for generation callback' );

    setupNLP();

    console.log( 'Ready.' );

});

function randomQuote( req, res, next ) {

    res.setHeader('Access-Control-Allow-Origin','*');

    var index = Math.floor(Math.random() * (quotes.length)) ;

    visitor.pageview("/json/quote/" + index).send();
    visitor.event("Return Quote", "Random Quote").send()

    res.send( 200, getQuote(index) );
    return next();

}

function dailyQuote( req, res, next ) {

    res.setHeader('Access-Control-Allow-Origin','*');

    var dat = new Date();
    var index = parseInt(dat.getFullYear() + dat.getMonth() + dat.getDay()) % quotes.length;

    visitor.pageview("/json/quote/" + index).send();
    visitor.event("Return Quote", "Daily Quote").send()

    res.send( 200, getQuote(index) );
    return next();

}

function fixedQuote( req, res, next ) {

    res.setHeader('Access-Control-Allow-Origin','*');

    var index = req.params.quoteId;
    if ( typeof( quotes[index] ) == 'undefined' ) {

        var error = { 'error': 'non existent' };

        visitor.event("Quote not found", "Non Existent Quote").send()

        res.send( 404, error );
        return next();

    }

    visitor.pageview("/json/quote/" + index).send();
    visitor.event("Return Quote", "Fixed Quote").send()

    res.send( 200, getQuote(index) );
    return next();

}

function generateQuote( req, res, next ) {

    res.setHeader('Access-Control-Allow-Origin','*');

    visitor.pageview("/json/quote/generated").send();
    visitor.event("Return Quote", "Generate Quote").send()

    res.send( 200, buildQuote() );
    return next();

}

function getQuote( index ) {

    var output = {
        'id': index,
        'permalink': 'http://howmuchisthe.fish/json/perma/' + index,
        'quote': quotes[index]
    };

    return output;
}

function noRequest( req, res, next ) {

    res.setHeader('Access-Control-Allow-Origin','*');

    var error = { 'error': 'no method' };

    res.send( 404, error );
    return next();

}

function setupNLP() {

    var r, t = new Date().getTime();

    r = setupNLPInner('text');
    og = r.og; bg = r.bg;

    r = setupNLPInner('track');
    ogt = r.og; bgt = r.bg;

    r = setupNLPInner('album');
    oga = r.og; bga = r.bg;

    var numtokens = og.length+bg.length+ogt.length+bgt.length+oga.length+bga.length;
    console.log("setupNLP took: " + (new Date().getTime() - t) + "ms for " + numtokens + " tokens" );
}

function setupNLPInner( akey ) {

    var corpora = "";

    for ( var i = 0 ; i < quotes.length; i++ ) {

        corpora = corpora + quotes[i][akey] + " ";

    }

    corpora = corpora.trim().toLowerCase().replace(/[^\w\s\']/gim, '');

    var aog = corpora.split(" ");
    var abg = [];

    for (var i = 0, j = aog.length - 1; i < j; i++) {

        abg[i] = aog[i] + " " + aog[i + 1]

    }

    abg = abg.length ? abg : aog;

    return { bg: abg, og: aog};

}

function buildQuote() {

    return  {
                'quote': {
                            'text': generateString( og, bg, 17, 7 ) + ".",
                            'track': generateString( og.concat(ogt), bg.concat(bgt), 9, 4 ),
                            'album': generateString( og.concat(oga), bg.concat(bga), 7, 4 ),
                            'year': Math.floor(Math.random() * (new Date().getFullYear() - 1994 + 1)) + 1994
                         }
            };

}

function generateString( aog, abg, alenmin, alenmax ) {

    var sWord = aog[Math.floor(Math.random() * aog.length-1) + 1];
    var sLength = Math.floor(Math.random() * (alenmax - alenmin + 1)) + alenmin;
    var sTokens = [];

    var searchWord = sWord;

    for (var i=0; i < sLength; i++) {

        var tokenList = [];

        for (var j = 0 ; j < abg.length; j++) {

            var token = abg[j].split(" ");
            if (token[0] == searchWord) {

                tokenList.push(token);

            }

        }

        var lToken = tokenList[Math.floor(Math.random() * tokenList.length-1) + 1];
        sTokens.push(lToken[0]);
        searchWord = lToken[1];

        if (i == sLength - 1 && lToken[0].length < 4) {

            sLength++;

        }

    }

    return sTokens.join(" ");

}<commit_msg>Make generation algorithm sentence end aware, improving quote quality<commit_after>var restify = require( 'restify' );
var bindIp = '0.0.0.0', bindPort = '8080';
var quotes = require('./model.js').model;
var ua = require('universal-analytics');
var visitor = ua('UA-2158627-15');
var testNLP = false;

var og = []; var oga = []; var ogt = [];
var bg = []; var bga = []; var bgt = [];

var server = restify.createServer( {

    name: 'howmuchisthe.fish',
    handleUpgrades: true

} );

server.use( restify.queryParser() );
server.use( restify.bodyParser() );
server.use( restify.CORS() );

server.get( {path: '/json'}, noRequest );
server.get( {path: '/json/random'}, randomQuote );
server.get( {path: '/json/random/generate'}, generateQuote );
server.get( {path: '/json/daily'}, dailyQuote );
server.get( {path: '/json/perma/:quoteId'}, fixedQuote );

server.get(/.*/, restify.serveStatic({

    'directory': 'htdocs',
    'default': 'index.html'

}));

server.listen( bindPort, bindIp, function() {

    console.log( '%s listening at %s ', server.name , server.url );
    console.log( '#Quotes %s', quotes.length );
    console.log( 'Generating data for generation callback' );

    setupNLP();

    console.log( 'Ready.' );

});

function randomQuote( req, res, next ) {

    res.setHeader('Access-Control-Allow-Origin','*');

    var index = Math.floor(Math.random() * (quotes.length)) ;

    visitor.pageview("/json/quote/" + index).send();
    visitor.event("Return Quote", "Random Quote").send()

    res.send( 200, getQuote(index) );
    return next();

}

function dailyQuote( req, res, next ) {

    res.setHeader('Access-Control-Allow-Origin','*');

    var dat = new Date();
    var index = parseInt(dat.getFullYear() + dat.getMonth() + dat.getDay()) % quotes.length;

    visitor.pageview("/json/quote/" + index).send();
    visitor.event("Return Quote", "Daily Quote").send()

    res.send( 200, getQuote(index) );
    return next();

}

function fixedQuote( req, res, next ) {

    res.setHeader('Access-Control-Allow-Origin','*');

    var index = req.params.quoteId;
    if ( typeof( quotes[index] ) == 'undefined' ) {

        var error = { 'error': 'non existent' };

        visitor.event("Quote not found", "Non Existent Quote").send()

        res.send( 404, error );
        return next();

    }

    visitor.pageview("/json/quote/" + index).send();
    visitor.event("Return Quote", "Fixed Quote").send()

    res.send( 200, getQuote(index) );
    return next();

}

function generateQuote( req, res, next ) {

    res.setHeader('Access-Control-Allow-Origin','*');

    visitor.pageview("/json/quote/generated").send();
    visitor.event("Return Quote", "Generate Quote").send()

    res.send( 200, buildQuote() );
    return next();

}

function getQuote( index ) {

    var output = {
        'id': index,
        'permalink': 'http://howmuchisthe.fish/json/perma/' + index,
        'quote': quotes[index]
    };

    return output;
}

function noRequest( req, res, next ) {

    res.setHeader('Access-Control-Allow-Origin','*');

    var error = { 'error': 'no method' };

    res.send( 404, error );
    return next();

}

function setupNLP() {

    var r, t = new Date().getTime();

    r = setupNLPInner('text');
    og = r.og; bg = r.bg;

    r = setupNLPInner('track');
    ogt = r.og; bgt = r.bg;

    r = setupNLPInner('album');
    oga = r.og; bga = r.bg;

    var numtokens = og.length+bg.length+ogt.length+bgt.length+oga.length+bga.length;
    console.log("setupNLP took: " + (new Date().getTime() - t) + "ms for " + numtokens + " tokens" );

    if (testNLP == true) {

        for ( var i = 0; i < 25; i++ ) {

            console.log( generateString( og, bg, 13, 6 ) );

        }

    }
}

function setupNLPInner( akey ) {

    var corpora = "";

    for ( var i = 0 ; i < quotes.length; i++ ) {

        corpora = corpora + quotes[i][akey] + " ";

    }

    corpora = corpora.trim().toLowerCase().replace(/[^\w\s\'\.\,]/gim, '');

    var aog = corpora.split(/[\s\,\.]+/);
    var abg = [];

    for (var i = 0, j = aog.length - 1; i < j; i++) {

        // allow dot in right, comma in left.
        if ( abg[i] != "." && abg[i + 1] != "," ) {

            abg[i] = aog[i] + " " + aog[i + 1]

        }

    }

    abg = abg.length ? abg : aog;

    return { bg: abg, og: aog};

}

function buildQuote() {

    return  {
                'quote': {
                            'text': generateString( og, bg, 13, 6 ) + ".",
                            'track': generateString( og.concat(ogt), bg.concat(bgt), 9, 4 ),
                            'album': generateString( og.concat(oga), bg.concat(bga), 7, 4 ),
                            'year': Math.floor(Math.random() * (new Date().getFullYear() - 1994 + 1)) + 1994
                         }
            };

}

function generateString( aog, abg, alenmin, alenmax ) {

    var sWord = aog[Math.floor(Math.random() * aog.length-1) + 1];
    var sLength = Math.floor(Math.random() * (alenmax - alenmin + 1)) + alenmin;
    var sTokens = [];

    var searchWord = sWord;

    for (var i=0; i < sLength; i++) {

        var tokenList = [];

        for (var j = 0 ; j < abg.length; j++) {

            var token = abg[j].split(" ");
            if (token[0] == searchWord) {

                tokenList.push(token);

            }

        }

        var lToken = tokenList[Math.floor(Math.random() * tokenList.length-1) + 1];
        sTokens.push(lToken[0]);
        searchWord = lToken[1];

        if (i == sLength - 1 && lToken[0].length < 4) {

            sLength++;

        }

        // Quit if we encounter period.
        if (searchWord == ".") {

            break;

        }

    }

    return sTokens.join(" ");

}<|endoftext|>


<commit_before>var express = require('express');
var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

// Define store object
var data_storage = require('./memory_store.js')
data_storage.init()

var app = express();

app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());

app.all('/create_route', function(req, res, next) {
  var route = req.get('route')
  var request_method = req.get('method')
  var response_code = req.get('response_code')
  var this_response = ''
  var response_header = req.headers

  res.statusCode = 200

  if(route === undefined){
    this_response += 'Route is not defined\n'
    res.statusCode = 400
  } else {
    delete response_header['route']
  }
  if(response_code === undefined){
    this_response += 'Response code is not defined\n'
    res.statusCode = 400
  } else {
    delete response_header['response_code']
  }
  if(request_method === undefined){
    this_response += 'Method is not defined\n'
    res.statusCode = 400
  } else {
    request_method = request_method.toUpperCase()
    delete response_header['request_method']
  }

  data_storage.add_route(request_method, route, response_code, response_header, req.body)
  res.send("New route" + route + " for " + request_method  + " with response code " + response_code)
});

app.all('/delete_routes', function(req, res, next) {
  var route = req.get('route')
  var request_method = req.get('method')
  res.statusCode = 200

  if(route === undefined || request_method === undefined){
    res.send("deleted all routes")
    data_storage.delete_all_routes()
  } else {
    request_method = request_method.toUpperCase()
    data_storage.delete_route(request_method, route)
    res.send("deleted route" + route + " for " + request_method)
  }
});

app.all('/get_last_request', function(req, res, next) {
  var route = req.get('route')
  var request_method = req.get('method').toUpperCase()

  if(route === undefined || request_method === undefined){
    res.statusCode = 400;
    res.set({'Content-Type': 'text/plain'})
    res.send('You forgot to define method or routing.');
  } else {
    request_method = request_method.toUpperCase()
    var last_request = data_storage.find_last_request_for_route(request_method, route)
    if (last_request !== undefined) {
      res.statusCode = 200;
      res.header = {'Content-Type': 'application/json'}
      res.send(last_request);
    } else {
      console.log("Request history not found for specified route" + route + " and method " + request_method)
      res.statusCode = 400;
      res.set({'Content-Type': 'text/plain'})
      res.send('No entry for ' + req.method + ' ' + req.url + ' yet.');
    }
  }
});

app.all('/*', function(req, res, next){
  var route = req.path
  var request_method = req.method
  var route_response = data_storage.find_route(request_method, route)
  if (route_response == undefined){
    res.statusCode = 404;
    res.set({'Content-Type': 'text/plain'})
    res.send('Cannot handle ' + req.method + ' ' + req.url);
  } else {
    data_storage.save_last_request_for_route(request_method, route, req.headers, req.body)
    res.statusCode = route_response['response_code']
    res.set(route_response['header'])
    res.send(route_response['body'])
    console.log('Request object: header - ' + req.headers + ' and body - ' + req.body)
  }
  next()
})

module.exports = app;
<commit_msg>Added route to retrieve full history for method/route combination<commit_after>var express = require('express');
var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

// Define store object
var data_storage = require('./memory_store.js')
data_storage.init()

var app = express();

app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());

app.all('/create_route', function(req, res, next) {
  var route = req.get('route')
  var request_method = req.get('method')
  var response_code = req.get('response_code')
  var this_response = ''
  var response_header = req.headers

  res.statusCode = 200

  if(route === undefined){
    this_response += 'Route is not defined\n'
    res.statusCode = 400
  } else {
    delete response_header.route
  }
  if(response_code === undefined){
    this_response += 'Response code is not defined\n'
    res.statusCode = 400
  } else {
    delete response_header.response_code
  }
  if(request_method === undefined){
    this_response += 'Method is not defined\n'
    res.statusCode = 400
  } else {
    request_method = request_method.toUpperCase()
    delete response_header.request_method
  }

  data_storage.add_route(request_method, route, response_code, response_header, req.body)
  res.send("New route" + route + " for " + request_method  + " with response code " + response_code)
});

app.all('/delete_routes', function(req, res, next) {
  var route = req.get('route')
  var request_method = req.get('method')
  res.statusCode = 200

  if(route === undefined || request_method === undefined){
    res.send("deleted all routes")
    data_storage.delete_all_routes()
  } else {
    request_method = request_method.toUpperCase()
    data_storage.delete_route(request_method, route)
    res.send("deleted route" + route + " for " + request_method)
  }
});

app.all('/get_last_request', function(req, res, next) {
  var route = req.get('route')
  var request_method = req.get('method').toUpperCase()

  if(route === undefined || request_method === undefined){
    res.statusCode = 400;
    res.set({'Content-Type': 'text/plain'})
    res.send('You forgot to define method or routing.');
  } else {
    request_method = request_method.toUpperCase()
    var last_request = data_storage.find_last_request_for_route(request_method, route)
    if (last_request !== undefined) {
      res.statusCode = 200;
      res.header = {'Content-Type': 'application/json'}
      res.send(last_request);
    } else {
      console.log("Request history not found for specified route" + route + " and method " + request_method)
      res.statusCode = 400;
      res.set({'Content-Type': 'text/plain'})
      res.send('No entry for ' + req.method + ' ' + req.url + ' yet.');
    }
  }
});

app.all('/get_request_history', function(req, res, next) {
  var route = req.get('route')
  var request_method = req.get('method').toUpperCase()

  if(route === undefined || request_method === undefined){
    res.statusCode = 400;
    res.set({'Content-Type': 'text/plain'})
    res.send('You forgot to define method or routing.');
  } else {
    request_method = request_method.toUpperCase()
    var request_history = data_storage.find_all_requests_for_route(request_method, route)
    if (request_history !== undefined) {
      res.statusCode = 200;
      res.header = {'Content-Type': 'application/json'}
      res.send(request_history);
    } else {
      console.log("Request history not found for specified route" + route + " and method " + request_method)
      res.statusCode = 400;
      res.set({'Content-Type': 'text/plain'})
      res.send('No entry for ' + req.method + ' ' + req.url + ' yet.');
    }
  }
});

app.all('/*', function(req, res, next){
  var route = req.path
  var request_method = req.method
  var route_response = data_storage.find_route(request_method, route)
  if (route_response == undefined){
    res.statusCode = 404;
    res.set({'Content-Type': 'text/plain'})
    res.send('Cannot handle ' + req.method + ' ' + req.url);
  } else {
    data_storage.save_last_request_for_route(request_method, route, req.headers, req.body)
    res.statusCode = route_response.response_code
    res.set(route_response.header)
    res.send(route_response.body)
    console.log('Request object: header - ' + req.headers + ' and body - ' + req.body)
  }
  next()
})

module.exports = app;
<|endoftext|>


<commit_before>/*
Language: Q
Author: Sergey Vidyuk <svidyuk@gmail.com>
Description: K/Q/Kdb+ from Kx Systems
*/
function(hljs) {
  var Q_KEYWORDS = {
	keyword:
		'do while select delete by update from',
	constant:
		'0b 1b',
	built_in:
		'neg not null string reciprocal floor ceiling signum mod xbar xlog and or each scan over prior mmu lsq inv md5 ltime gtime count first var dev med cov cor all any rand sums prds mins maxs fills deltas ratios avgs differ prev next rank reverse iasc idesc asc desc msum mcount mavg mdev xrank mmin mmax xprev rotate distinct group where flip type key til get value attr cut set upsert raze union inter except cross sv vs sublist enlist read0 read1 hopen hclose hdel hsym hcount peach system ltrim rtrim trim lower upper ssr view tables views cols xcols keys xkey xcol xasc xdesc fkeys meta lj aj aj0 ij pj asof uj ww wj wj1 fby xgroup ungroup ej save load rsave rload show csv parse eval min max avg wavg wsum sin cos tan sum',
	typename:
		'`float `double int `timestamp `timespan `datetime `time `boolean `symbol `char `byte `short `long `real `month `date `minute `second `guid'
  };
  return {
    case_insensitive:false,
    aliases:'k kdb',
    keywords: Q_KEYWORDS,
    contains: [
	hljs.C_LINE_COMMENT_MODE,
    	{className:'string',begin:'"',end:'"'},
        hljs.C_NUMBER_MODE
       ]
  };
}
<commit_msg>Please make indentation consistent within the file and with the rest of the code, we use 2-space indentation (no tabs). Drop case_insensitive: false, it's the default value. aliases should be a list of strings, not a space-separated string. Right now it simply breaks the script. You need a custom lexing for keywords starting with quotes and numbers. Add lexemes: /\b(`?)[A-Za-z0-9_]+\b/ after keywords. I think you could use hljs.QUOTE_STRING_MODE for your string definition, it will take care of backslash escapes.<commit_after>/*
Language: Q
Author: Sergey Vidyuk <svidyuk@gmail.com>
Description: K/Q/Kdb+ from Kx Systems
*/
function(hljs) {
  var Q_KEYWORDS = {
  keyword:
    'do while select delete by update from',
  constant:
    '0b 1b',
  built_in:
    'neg not null string reciprocal floor ceiling signum mod xbar xlog and or each scan over prior mmu lsq inv md5 ltime gtime count first var dev med cov cor all any rand sums prds mins maxs fills deltas ratios avgs differ prev next rank reverse iasc idesc asc desc msum mcount mavg mdev xrank mmin mmax xprev rotate distinct group where flip type key til get value attr cut set upsert raze union inter except cross sv vs sublist enlist read0 read1 hopen hclose hdel hsym hcount peach system ltrim rtrim trim lower upper ssr view tables views cols xcols keys xkey xcol xasc xdesc fkeys meta lj aj aj0 ij pj asof uj ww wj wj1 fby xgroup ungroup ej save load rsave rload show csv parse eval min max avg wavg wsum sin cos tan sum',
  typename:
    '`float `double int `timestamp `timespan `datetime `time `boolean `symbol `char `byte `short `long `real `month `date `minute `second `guid'
  };
  return {
  aliases:['k', 'kdb'],
  keywords: Q_KEYWORDS,
  lexemes: /\b(`?)[A-Za-z0-9_]+\b/,
  contains: [
  hljs.C_LINE_COMMENT_MODE,
    hljs.QUOTE_STRING_MODE,
    hljs.C_NUMBER_MODE
     ]
  };
}
<|endoftext|>


<commit_before>var esformatter = require('esformatter');
var stringify = require("json-literal").stringify;
var fs = require("fs");
var path = require("path");

/**
 * Class that writes an object to a file (using the `json-literal` module)
 * @param {*} `data` the javascript object,
 * @constructor
 */
function Writer(data) {
    var prettyPrint = false;

    /**
     * Enable pretty printed output
     */
    this.pretty = function () {
        prettyPrint = true;
    };

    /**
     * Write the data to a file (synchronously).
     * @param {string} `targetDir` the directory of the file
     * @param {string} `filename` the name of the file
     */
    this.writeTo = function (targetDir, filename) {
        // Remove wrapping parens which are always created by json-literal
        var node = stringify(data).replace(/^\((.*)\)$/, "$1");
        // Create a valid javascript module
        var string = "module.exports = " + node + ";";
        // If prettyprint is enabled, use esformatter to format
        // the resulting javascript.
        if (prettyPrint) {
            string = esformatter.format(string, {
                // indent is hard coded to 4 spaces at the moment
                indent: '    '
            });
        }
        // Write the data...
        var targetFile = path.join(targetDir, filename);
        console.log("Writing ", targetFile);
        fs.writeFileSync(targetFile, string, "utf-8");
        console.log("done");
    }
}

module.exports = Writer;

<commit_msg>Working prettyprinting for writer<commit_after>var esformatter = require('esformatter');
var stringify = require("json-literal").stringify;
var fs = require("fs");
var path = require("path");

/**
 * Class that writes an object to a file (using the `json-literal` module)
 * @param {*} `data` the javascript object,
 * @constructor
 */
function Writer(data) {
    var prettyPrint = false;

    /**
     * Enable pretty printed output
     */
    this.pretty = function () {
        prettyPrint = true;
        return this;
    };

    /**
     * Write the data to a file (synchronously).
     * @param {string} `targetDir` the directory of the file
     * @param {string} `filename` the name of the file
     */
    this.writeTo = function (targetDir, filename) {
        // Remove wrapping parens which are always created by json-literal
        var node = stringify(data).replace(/^\((.*)\)$/, "$1");
        // Create a valid javascript module
        var string = "module.exports = function() { return " + node + "};";
        // If prettyprint is enabled, use esformatter to format
        // the resulting javascript.
        if (prettyPrint) {
            string = esformatter.format(string, {
                // indent is hard coded to 4 spaces at the moment
                indent: {
                    value: '    '
                }
            });
        }
        // Write the data...
        var targetFile = path.join(targetDir, filename);
        console.log("Writing ", targetFile);
        fs.writeFileSync(targetFile, string, "utf-8");
        console.log("done");
    }
}

module.exports = Writer;

<|endoftext|>


<commit_before>'use strict';
// dammit, chrome, you were supposed to have the best standards support...
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

const nativeScrollbarWidth = (() => {
    let e = document.createElement('div');
    e.style.position = 'fixed';
    e.style.width    = '100px';
    e.style.height   = '100px';
    e.style.overflow = 'scroll';
    document.body.appendChild(e);
    let r = e.offsetWidth - e.clientWidth;
    document.body.removeChild(e);
    return r;
})();

let $init = {
    all(e) {
        let isElem = e instanceof Element;
        for (let f in $init) {
            if ($init.hasOwnProperty(f) && f != 'all' && f !== 'template') {
                if (isElem && e.matches(f))
                    $init[f](e);
                for (let c of e.querySelectorAll(f))
                    $init[f](c);
            }
        }
        return e;
    },

    template(id) {
        return $init.all(document.importNode(document.getElementById(id).content, true));
    },

    '[data-scrollbar]'(e) {
        if (nativeScrollbarWidth === 0 || e.style.marginRight !== '')
            return;  // native scrollbar is already floating

        let timer = null;
        let track = document.createElement('div');
        let thumb = document.createElement('div');
        thumb.classList.add('thumb');
        track.classList.add('track');
        track.appendChild(thumb);

        let hide = () => { track.style.opacity = 0; };
        let show = () => {
            if (e.scrollHeight > e.clientHeight) {
                window.clearTimeout(timer);
                let h = e.clientHeight / e.scrollHeight;
                track.style.opacity   = 1;
                track.style.transform = `translateY(${e.scrollTop}px)`;
                thumb.style.transform = `translateY(${e.scrollTop / e.scrollHeight * 100 + h * 50 - 50}%) scaleY(${h})`;
                timer = window.setTimeout(hide, 1000);
            }
        };

        let trigger = ev => {
            for (let t = ev.target; t !== null; t = t.parentElement)
                if (t.hasAttribute('data-scrollbar'))
                    return window.requestAnimationFrame(t === e ? show : hide);
        };

        e.style.overflowY   = 'scroll';
        e.style.marginRight = `${-nativeScrollbarWidth}px`;
        e.appendChild(track);
        e.addEventListener('mouseleave', _ => window.requestAnimationFrame(hide));
        e.addEventListener('mousemove',  trigger);
        e.addEventListener('scroll',     trigger);
    },

    '[data-tabs]'(e) {
        let bar = document.createElement('div');
        bar.classList.add('tabbar');
        bar.addEventListener('click', ev =>
            e.dataset.tabs = ev.target.dataset.tab || e.dataset.tabs);

        let tabs = {};
        for (let tab of e.querySelectorAll('[data-tab]')) {
            if (tab.parentElement.parentElement !== e)
                continue;
            tabs[tab.dataset.tab] = {t: tab.parentElement, b: tab};
            bar.appendChild(tab);
        }

        new MutationObserver(_ => {
            for (let id in tabs) {
                tabs[id].b.classList.remove('active');
                tabs[id].t.setAttribute('hidden', '');
            }
            let active = e.dataset.tabs;
            tabs[active].b.classList.add('active');
            tabs[active].t.removeAttribute('hidden');
        }).observe(e, {attributes: true, attributeFilter: ['data-tabs']});

        e.insertBefore(bar, e.childNodes[0]);
        e.dataset.tabs = e.dataset.tabs;
    },

    '[data-modal]'(e) {
        let parent = e.parentNode;
        let outer  = document.createElement('div');
        let inner  = document.createElement('div');
        let scroll = document.createElement('div');
        let close  = document.createElement('a');
        outer.classList.add('modal-bg');
        inner.classList.add('modal');
        close.classList.add('button');
        close.classList.add('close');
        scroll.setAttribute('data-scrollbar', '');
        scroll.appendChild(e);
        parent.appendChild(outer);
        inner.appendChild(scroll);
        inner.appendChild(close);
        outer.appendChild(inner);
        outer.addEventListener('click', (e) => e.target === e.currentTarget ? outer.remove() : 1);
        close.addEventListener('click', (e) => outer.remove());
        // if the [data-scrollbar] initializer has already run, this element would be left
        // uninitialized. good thing that particular initializer is idempotent...
        $init['[data-scrollbar]'](scroll);
    },

    'body'(e) {
        e.addEventListener('focusin', ev => {
            // focus must not escape modal dialogs.
            let modals = e.querySelectorAll('.modal-bg');
            if (modals.length === 0)
                return;
            for (let t = ev.target; t !== null; t = t.parentElement)
                if (t === modals[modals.length - 1])
                    return;
            ev.target.blur();
        });
    },

    'a[href^="/user/"]'(e) {
        let tab = {
            '/user/new':     'signup',
            '/user/login':   'login',
            '/user/restore': 'restore',
        }[e.getAttribute('href')];

        if (tab) e.addEventListener('click', ev => {
            ev.preventDefault();
            for (let p = e.parentElement; p !== null; p = p.parentElement)
                if (p.hasAttribute('data-tabs'))
                    return p.setAttribute('data-tabs', tab);

            let it = $init.template('login-form-template');
            it.querySelector('[data-tabs]').dataset.tabs = tab;
            document.body.appendChild(it);
        });
    },

    'form[data-xhrable]'(e) {
        e.addEventListener('submit', ev => {
            ev.preventDefault();
            $form.submit(e)
                 .then  (xhr => $form.onXHRSuccess(xhr, e))
                 .catch (err => $form.onXHRError(err, e));
        });
    },
};

let $form = {
    onDocumentReload(doc) {
        document.documentElement.replaceChild(doc.body, document.body);
        $init.all(document.body);
        return true;
    },

    onXHRSuccess(xhr, form) {
        try {
            $form.disable(form);
            if (xhr.responseURL === location.href && $form.onDocumentReload(xhr.response))
                return $form.enable(form);
            // TODO replace the whole `body`, like InstantClick does?
            //      gotta use `history.pushState` then, too...
        } catch (e) {
            console.log('failed to async-reload document:', e);
        }
        location.href = xhr.responseURL;
    },

    onXHRError(xhr, form) {
        form.classList.add('error');
        form.querySelector('.error').textContent =
            xhr.response ? xhr.response.getElementById('message').textContent
                         : 'Could not connect to server.';
    },

    enable(e) {
        delete e.dataset.status;
        for (let input of e.querySelectorAll('[disabled="by-$form"]'))
            input.removeAttribute('disabled', '');
    },

    disable(e) {
        e.dataset.status = 'loading';
        for (let input of e.querySelectorAll(':enabled'))
            input.setAttribute('disabled', 'by-$form');
    },

    submit: (e) => new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest();

        xhr.onload = ev => {
            $form.enable(e);
            if (xhr.status >= 300)
                reject(xhr);
            else
                resolve(xhr);
        };

        xhr.onerror = ev => {
            $form.enable(e);
            reject(xhr);
        };

        xhr.responseType = 'document';
        xhr.open(e.getAttribute('method'), e.getAttribute('action'));
        xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
        xhr.send(new FormData(e));
        $form.disable(e);
    }),
};

document.addEventListener('DOMContentLoaded', _ => $init.all(document));
<commit_msg>Keep scroll events within the innermost scrollable.<commit_after>'use strict';
// dammit, chrome, you were supposed to have the best standards support...
NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator];

const nativeScrollbarWidth = (() => {
    let e = document.createElement('div');
    e.style.position = 'fixed';
    e.style.width    = '100px';
    e.style.height   = '100px';
    e.style.overflow = 'scroll';
    document.body.appendChild(e);
    let r = e.offsetWidth - e.clientWidth;
    document.body.removeChild(e);
    return r;
})();

let $init = {
    all(e) {
        let isElem = e instanceof Element;
        for (let f in $init) {
            if ($init.hasOwnProperty(f) && f != 'all' && f !== 'template') {
                if (isElem && e.matches(f))
                    $init[f](e);
                for (let c of e.querySelectorAll(f))
                    $init[f](c);
            }
        }
        return e;
    },

    template(id) {
        return $init.all(document.importNode(document.getElementById(id).content, true));
    },

    '[data-scrollbar]'(e) {
        if (nativeScrollbarWidth === 0 || e.style.marginRight !== '')
            return;  // native scrollbar is already floating

        let timer = null;
        let track = document.createElement('div');
        let thumb = document.createElement('div');
        thumb.classList.add('thumb');
        track.classList.add('track');
        track.appendChild(thumb);

        let hide = () => { track.style.opacity = 0; };
        let show = () => {
            if (e.scrollHeight > e.clientHeight) {
                window.clearTimeout(timer);
                let h = e.clientHeight / e.scrollHeight;
                track.style.opacity   = 1;
                track.style.transform = `translateY(${e.scrollTop}px)`;
                thumb.style.transform = `translateY(${e.scrollTop / e.scrollHeight * 100 + h * 50 - 50}%) scaleY(${h})`;
                timer = window.setTimeout(hide, 1000);
            }
        };

        let innermost = ev => {
            for (let t = ev.target; t !== null; t = t.parentElement)
                if (t.hasAttribute('data-scrollbar') && t.scrollHeight > t.clientHeight)
                    return t;
        };

        let trigger = ev =>
            window.requestAnimationFrame(innermost(ev) === e ? show : hide);

        let ignoreOvershoot = ev => {
            let t = innermost(ev);
            if ((ev.deltaY > 0 && t.scrollTop >= t.scrollHeight - t.clientHeight) || (ev.deltaY < 0 && t.scrollTop === 0))
                ev.preventDefault();
        };

        e.style.overflowY   = 'scroll';
        e.style.marginRight = `${-nativeScrollbarWidth}px`;
        e.appendChild(track);
        e.addEventListener('mouseleave', _ => window.requestAnimationFrame(hide));
        e.addEventListener('mousemove',  trigger);
        e.addEventListener('scroll',     trigger);
        e.addEventListener('wheel',      ignoreOvershoot);
    },

    '[data-tabs]'(e) {
        let bar = document.createElement('div');
        bar.classList.add('tabbar');
        bar.addEventListener('click', ev =>
            e.dataset.tabs = ev.target.dataset.tab || e.dataset.tabs);

        let tabs = {};
        for (let tab of e.querySelectorAll('[data-tab]')) {
            if (tab.parentElement.parentElement !== e)
                continue;
            tabs[tab.dataset.tab] = {t: tab.parentElement, b: tab};
            bar.appendChild(tab);
        }

        new MutationObserver(_ => {
            for (let id in tabs) {
                tabs[id].b.classList.remove('active');
                tabs[id].t.setAttribute('hidden', '');
            }
            let active = e.dataset.tabs;
            tabs[active].b.classList.add('active');
            tabs[active].t.removeAttribute('hidden');
        }).observe(e, {attributes: true, attributeFilter: ['data-tabs']});

        e.insertBefore(bar, e.childNodes[0]);
        e.dataset.tabs = e.dataset.tabs;
    },

    '[data-modal]'(e) {
        let parent = e.parentNode;
        let outer  = document.createElement('div');
        let inner  = document.createElement('div');
        let scroll = document.createElement('div');
        let close  = document.createElement('a');
        outer.classList.add('modal-bg');
        inner.classList.add('modal');
        close.classList.add('button');
        close.classList.add('close');
        scroll.setAttribute('data-scrollbar', '');
        scroll.appendChild(e);
        parent.appendChild(outer);
        inner.appendChild(scroll);
        inner.appendChild(close);
        outer.appendChild(inner);
        outer.addEventListener('click', (e) => e.target === e.currentTarget ? outer.remove() : 1);
        close.addEventListener('click', (e) => outer.remove());
        // if the [data-scrollbar] initializer has already run, this element would be left
        // uninitialized. good thing that particular initializer is idempotent...
        $init['[data-scrollbar]'](scroll);
    },

    'body'(e) {
        e.addEventListener('focusin', ev => {
            // focus must not escape modal dialogs.
            let modals = e.querySelectorAll('.modal-bg');
            if (modals.length === 0)
                return;
            for (let t = ev.target; t !== null; t = t.parentElement)
                if (t === modals[modals.length - 1])
                    return;
            ev.target.blur();
        });
    },

    'a[href^="/user/"]'(e) {
        let tab = {
            '/user/new':     'signup',
            '/user/login':   'login',
            '/user/restore': 'restore',
        }[e.getAttribute('href')];

        if (tab) e.addEventListener('click', ev => {
            ev.preventDefault();
            for (let p = e.parentElement; p !== null; p = p.parentElement)
                if (p.hasAttribute('data-tabs'))
                    return p.setAttribute('data-tabs', tab);

            let it = $init.template('login-form-template');
            it.querySelector('[data-tabs]').dataset.tabs = tab;
            document.body.appendChild(it);
        });
    },

    'form[data-xhrable]'(e) {
        e.addEventListener('submit', ev => {
            ev.preventDefault();
            $form.submit(e)
                 .then  (xhr => $form.onXHRSuccess(xhr, e))
                 .catch (err => $form.onXHRError(err, e));
        });
    },
};

let $form = {
    onDocumentReload(doc) {
        document.documentElement.replaceChild(doc.body, document.body);
        $init.all(document.body);
        return true;
    },

    onXHRSuccess(xhr, form) {
        try {
            $form.disable(form);
            if (xhr.responseURL === location.href && $form.onDocumentReload(xhr.response))
                return $form.enable(form);
            // TODO replace the whole `body`, like InstantClick does?
            //      gotta use `history.pushState` then, too...
        } catch (e) {
            console.log('failed to async-reload document:', e);
        }
        location.href = xhr.responseURL;
    },

    onXHRError(xhr, form) {
        form.classList.add('error');
        form.querySelector('.error').textContent =
            xhr.response ? xhr.response.getElementById('message').textContent
                         : 'Could not connect to server.';
    },

    enable(e) {
        delete e.dataset.status;
        for (let input of e.querySelectorAll('[disabled="by-$form"]'))
            input.removeAttribute('disabled', '');
    },

    disable(e) {
        e.dataset.status = 'loading';
        for (let input of e.querySelectorAll(':enabled'))
            input.setAttribute('disabled', 'by-$form');
    },

    submit: (e) => new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest();

        xhr.onload = ev => {
            $form.enable(e);
            if (xhr.status >= 300)
                reject(xhr);
            else
                resolve(xhr);
        };

        xhr.onerror = ev => {
            $form.enable(e);
            reject(xhr);
        };

        xhr.responseType = 'document';
        xhr.open(e.getAttribute('method'), e.getAttribute('action'));
        xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
        xhr.send(new FormData(e));
        $form.disable(e);
    }),
};

document.addEventListener('DOMContentLoaded', _ => $init.all(document));
<|endoftext|>


<commit_before>/*
 * Project:
 *   glideinWMS
 *
 * File Version:
 *   $Id: frontend_support.js,v 1.2.8.1 2010/09/08 03:30:00 parag Exp $
 *
 * Support javascript module for the frontend monitoring
 * Part of the gldieinWMS package
 *
 * Original repository: http://www.uscms.org/SoftwareComputing/Grid/WMS/glideinWMS/
 *
 */

// Load FrontendStats XML file and return the object
function loadFrontendStats() {
  var request =  new XMLHttpRequest();
  request.open("GET", "frontend_status.xml",false);
  request.send(null);

  var frontendStats=request.responseXML.firstChild;
  return frontendStats;
}

// Extract group names from a frontendStats XML object
function getFrontendGroups(frontendStats) {
  groups=new Array();
  for (var elc=0; elc<frontendStats.childNodes.length; elc++) {
    var el=frontendStats.childNodes[elc];
    if ((el.nodeType==1) && (el.nodeName=="groups")) {
      for (var etc=0; etc<el.childNodes.length; etc++) {
	var group=el.childNodes[etc];
	if ((group.nodeType==1)&&(group.nodeName=="group")) {
	  var group_name=group.attributes.getNamedItem("name");
	  groups.push(group_name.value);
	}
      }
    }
  }
  return groups;
}
<commit_msg>Implement getFrontendGroupFactories - Merge from branch_v2_5_1plus_ucsd1<commit_after>/*
 * Project:
 *   glideinWMS
 *
 * File Version:
 *   $Id: frontend_support.js,v 1.2.8.2 2011/07/02 01:30:44 sfiligoi Exp $
 *
 * Support javascript module for the frontend monitoring
 * Part of the gldieinWMS package
 *
 * Original repository: http://www.uscms.org/SoftwareComputing/Grid/WMS/glideinWMS/
 *
 */

// Load FrontendStats XML file and return the object
function loadFrontendStats() {
  var request =  new XMLHttpRequest();
  request.open("GET", "frontend_status.xml",false);
  request.send(null);

  var frontendStats=request.responseXML.firstChild;
  return frontendStats;
}

// Extract group names from a frontendStats XML object
function getFrontendGroups(frontendStats) {
  groups=new Array();
  for (var elc=0; elc<frontendStats.childNodes.length; elc++) {
    var el=frontendStats.childNodes[elc];
    if ((el.nodeType==1) && (el.nodeName=="groups")) {
      for (var etc=0; etc<el.childNodes.length; etc++) {
	var group=el.childNodes[etc];
	if ((group.nodeType==1)&&(group.nodeName=="group")) {
	  var group_name=group.attributes.getNamedItem("name");
	  groups.push(group_name.value);
	}
      }
    }
  }
  return groups;
}

//Extract factory names from frontendStats XML obj
function getFrontendGroupFactories(frontendStats, group_name) {
  factories=new Array();

  if(group_name=="total") {
    for (var i=0; i<frontendStats.childNodes.length; i++) {
      var el=frontendStats.childNodes[i];
      if ((el.nodeType==1) && (el.nodeName=="factories")) {
        for (var j=0; j<el.childNodes.length; j++) {
  	  var group=el.childNodes[j];
            if ((group.nodeType==1)&&(group.nodeName=="factory")) {
              var group_name=group.attributes.getNamedItem("name");
	      factories.push(group_name.value);
	    }
          }
       }
    }
    return factories;
  }

  for (var i=0; i<frontendStats.childNodes.length; i++) {
    var el=frontendStats.childNodes[i];
    if ((el.nodeType==1) && (el.nodeName=="groups")) {
      for (var j=0; j<el.childNodes.length; j++) {
	var group=el.childNodes[j];
	if ((group.nodeType==1)&&(group.nodeName=="group")) {
	  var group_name1=group.attributes.getNamedItem("name").value;
          if(group_name1==group_name) {
             for(var k=0; k<group.childNodes.length; k++) {
               var el2 = group.childNodes[k];
               if (el2.nodeName=="factories") {
                  for(var m=0; m<el2.childNodes.length; m++) {
                     var factory = el2.childNodes[m];
                     if(factory.nodeName=="factory") {
                        factory_name=factory.attributes.getNamedItem("name");
	                factories.push(factory_name.value);
                     }
                  }
               }
             }
          }
	}
      }
    }
  }
  return factories;
}
<|endoftext|>


<commit_before>var path = require('path');
var buildAssets = require('/vagrant/apps/land-registry-elements');

buildAssets({
  'destination': path.resolve(__dirname, 'service/static/land-registry-elements'),
  'mode': 'production'
})
  .then(function(dest) {
    console.log('Done');
  })
  .catch(function(e) {
    console.error(e);
  });
<commit_msg>Specify the correct components to build for the digital-register-frontend rather than requesting everything<commit_after>var path = require('path');
var buildAssets = require('/vagrant/apps/land-registry-elements');

buildAssets({
  'destination': path.resolve(__dirname, 'service/static/land-registry-elements'),
  'mode': 'production',
  'components': [
    'pages/drv/landing-form',
    'pages/drv/search-form',
    'pages/drv/search-results',
    'pages/drv/order-confirmation',
    'pages/drv/summary',
    'pages/land-registry/error-page'
  ]
})
  .then(function(dest) {
    console.log('Done');
  })
  .catch(function(e) {
    console.error(e);
  });
<|endoftext|>


<commit_before><commit_msg>RequireJS config visual tweaks.<commit_after><|endoftext|>


<commit_before>const redditUrl = 'http://www.reddit.com';
const subRedditUrl = redditUrl+'/r/';
const userRedditUrl = redditUrl+'/user/';
const urlQueryUrl = redditUrl+'/api/info.json?url=';
const voteUrl = redditUrl+'/api/vote';
const submitUrl = redditUrl+'/submit?url='
const Bar = new _Bar;

function initialize(){
    Bar.initialize();
    Bar.update();
}

function respondToMessage(messageEvent){
	if(messageEvent.name === 'urlChanged'){
		Bar.update();
	}
}

safari.self.browserWindow.addEventListener('message', respondToMessage, false);

String.prototype.unescapeHtml = function(){
//TODO: implement this
//    var unescapeDiv = documentument.getElementById('unescape');
//
//    if(typeof(unescapeDiv) === 'undefined'){
//        return this;
//    }
//
//    unescapeDiv.innerHTML = this;
//    return unescapeDiv.childNodes[0].nodeValue;
    return this;
}

function isBlacklisted(url){
    var blacklist = safari.extension.settings.blacklist;
    if(typeof(blacklist) === 'undefined'){
        return false;
    }

	var lowerUrl = url.toLowerCase();
	var blacklistUrls = safari.extension.settings.blacklist.replace(' ', ',').split(',');
	for(i = 0; i < blacklistUrls.length; ++i){
	    var blacklistUrl = blacklistUrls[i];
		if(blacklistUrl == ''){
			continue;
		}

		if(lowerUrl.indexOf(blacklistUrl.toLowerCase()) >= 0){
			return true;
		}
	}
	return false;
}

function _Bar(){
    this.initialize = function(){
        this.icon = document.getElementById('icon');
        this.submitted = document.getElementById('submitted');
        this.icon.href = redditUrl;
        this.status = document.getElementById('status');
        this.up = document.getElementById('up');
        this.score = document.getElementById('score');
        this.down = document.getElementById('down');
        this.submit = document.getElementById('submit');
        this.story = document.getElementById('story');
        this.storyinfo = document.getElementById('storyinfo');
        this.subreddit = document.getElementById('subreddit');
        this.author = document.getElementById('author');
        this.created = document.getElementById('created');
        this.nsfw = document.getElementById('nsfw');
        this.comments = document.getElementById('comments');
        this.blacklist = document.getElementById('blacklist');
    }

    this.update = function(){
        this.submit.style.display = 'none';
        this.submitted.style.display = 'none';
        this.blacklist.style.display = 'none';

        var tab = safari.self.browserWindow.activeTab;

        //url is undefined
        if(typeof(tab.url) === 'undefined'){
            return;
        }

        //url is in blacklist
        if(isBlacklisted(tab.url)){
            this.blacklist.style.display = 'inline-block';
            return;
        }

        var thisBar = this;
        xmlhttp = new XMLHttpRequest();
        xmlhttp.open('GET', urlQueryUrl+tab.url, true);
        xmlhttp.onreadystatechange = function(){
            if(xmlhttp.readyState == 4 && xmlhttp.status == 200){
                thisBar._update(JSON.parse(xmlhttp.responseText));
            }
        }
        xmlhttp.send();
    }

    this._update = function(json){
        var tab = safari.self.browserWindow.activeTab;

        //submit story
        if(typeof(json) === 'undefined' || typeof(json.data.children[0]) === 'undefined'){
            this.submit.href = submitUrl+tab.url+'&title='+tab.title;
            this.submit.style.display = 'inline-block';
            return;
        }

        var data = json.data.children[0].data;

        //score
		this.score.innerHTML = data.score;
		this.score.title = 'ups: '+data.ups+', downs: '+data.downs;

		//arrows
		//TODO: get voting working
		if(data.likes == true){
			this.up.className = 'up-active';
			this.up.title = 'un-vote';
			//this.up.href = '#';

			this.down.className = 'down';
			this.down.title = 'vote down';
			//this.down.href = '#';
		}else if(data.likes == false){
			this.up.className = 'up';
			this.up.title = 'vote up';
			//this.up.href = '#';

			this.down.className = 'down-active';
			this.down.title = 'un-vote';
			//this.down.href = '#';
		}else{
			this.up.className = 'up';
			this.up.title = 'vote up';
			//this.up.href = '#';

			this.down.className = 'down';
			this.down.title = 'vote down';
			//this.down.href = '#';
		}

		//story
		this.story.innerHTML = data.title;
		this.story.title = data.title.unescapeHtml();
		this.story.href = redditUrl+data.permalink;

		//story info
		var creationDate = new Date(data.created*1000);
		this.subreddit.innerHTML = data.subreddit;
		this.subreddit.href = subRedditUrl+data.subreddit;
		this.author.innerHTML = data.author;
		this.author.href = userRedditUrl+data.author;
		this.created.innerHTML = creationDate.toLocaleDateString();
		this.nsfw.style.display = data.over_18 ? 'inline-block' : 'none';

    	//comments
		var commentStr = ' comment';
		if(data.num_comments > 1){
		    commentStr += 's';
		}
		if(data.num_comments > 99999){
			data.num_comments = '9999+';
		}

		this.comments.innerHTML = data.num_comments;
		this.comments.title = data.num_comments+commentStr;
		this.comments.className = 'comments'+data.num_comments.toString().length;

		this.submitted.style.display = 'inline-block';
    }
};

//TODO: add a timer to updat the extension bars,
//because the bars currently only load when a webpage is loaded<commit_msg>Displaying the story with the highest score in the extension bar<commit_after>const redditUrl = 'http://www.reddit.com';
const subRedditUrl = redditUrl+'/r/';
const userRedditUrl = redditUrl+'/user/';
const urlQueryUrl = redditUrl+'/api/info.json?url=';
const voteUrl = redditUrl+'/api/vote';
const submitUrl = redditUrl+'/submit?url='
const Bar = new _Bar;

function initialize(){
    Bar.initialize();
    Bar.update();
}

function respondToMessage(messageEvent){
	if(messageEvent.name === 'urlChanged'){
		Bar.update();
	}
}

safari.self.browserWindow.addEventListener('message', respondToMessage, false);

String.prototype.unescapeHtml = function(){
//TODO: implement this
//    var unescapeDiv = documentument.getElementById('unescape');
//
//    if(typeof(unescapeDiv) === 'undefined'){
//        return this;
//    }
//
//    unescapeDiv.innerHTML = this;
//    return unescapeDiv.childNodes[0].nodeValue;
    return this;
}

function isBlacklisted(url){
    var blacklist = safari.extension.settings.blacklist;
    if(typeof(blacklist) === 'undefined'){
        return false;
    }

	var lowerUrl = url.toLowerCase();
	var blacklistUrls = safari.extension.settings.blacklist.replace(' ', ',').split(',');
	for(i = 0; i < blacklistUrls.length; ++i){
	    var blacklistUrl = blacklistUrls[i];
		if(blacklistUrl == ''){
			continue;
		}

		if(lowerUrl.indexOf(blacklistUrl.toLowerCase()) >= 0){
			return true;
		}
	}
	return false;
}

function _Bar(){
    this.initialize = function(){
        this.icon = document.getElementById('icon');
        this.submitted = document.getElementById('submitted');
        this.icon.href = redditUrl;
        this.status = document.getElementById('status');
        this.up = document.getElementById('up');
        this.score = document.getElementById('score');
        this.down = document.getElementById('down');
        this.submit = document.getElementById('submit');
        this.story = document.getElementById('story');
        this.storyinfo = document.getElementById('storyinfo');
        this.subreddit = document.getElementById('subreddit');
        this.author = document.getElementById('author');
        this.created = document.getElementById('created');
        this.nsfw = document.getElementById('nsfw');
        this.comments = document.getElementById('comments');
        this.blacklist = document.getElementById('blacklist');
    }

    this.update = function(){
        this.submit.style.display = 'none';
        this.submitted.style.display = 'none';
        this.blacklist.style.display = 'none';

        var tab = safari.self.browserWindow.activeTab;

        //url is undefined
        if(typeof(tab.url) === 'undefined'){
            return;
        }

        //url is in blacklist
        if(isBlacklisted(tab.url)){
            this.blacklist.style.display = 'inline-block';
            return;
        }

        var thisBar = this;
        xmlhttp = new XMLHttpRequest();
        xmlhttp.open('GET', urlQueryUrl+tab.url, true);
        xmlhttp.onreadystatechange = function(){
            if(xmlhttp.readyState == 4 && xmlhttp.status == 200){
                thisBar._update(JSON.parse(xmlhttp.responseText));
            }
        }
        xmlhttp.send();
    }

    this._update = function(json){
        var tab = safari.self.browserWindow.activeTab;

        //submit story
        if(typeof(json) === 'undefined' || typeof(json.data.children[0]) === 'undefined'){
            this.submit.href = submitUrl+tab.url+'&title='+tab.title;
            this.submit.style.display = 'inline-block';
            return;
        }

        //TODO: add support for displaying all the instances of this story on reddit
        //probbaly with previous and next buttons

        var data = json.data.children[0].data;

        //display the story with the highest score
        if(json.data.children.length > 1){
            var highScore = data.score;
            for(i=1; i<json.data.children.length; ++i){
                var childData = json.data.children[i].data;
                if(childData.score > highScore){
                    highScore = childData.score;
                    data = childData;
                }
            }
        }

        //score
		this.score.innerHTML = data.score;
		this.score.title = 'ups: '+data.ups+', downs: '+data.downs;

		//arrows
		//TODO: get voting working
		if(data.likes == true){
			this.up.className = 'up-active';
			this.up.title = 'un-vote';
			//this.up.href = '#';

			this.down.className = 'down';
			this.down.title = 'vote down';
			//this.down.href = '#';
		}else if(data.likes == false){
			this.up.className = 'up';
			this.up.title = 'vote up';
			//this.up.href = '#';

			this.down.className = 'down-active';
			this.down.title = 'un-vote';
			//this.down.href = '#';
		}else{
			this.up.className = 'up';
			this.up.title = 'vote up';
			//this.up.href = '#';

			this.down.className = 'down';
			this.down.title = 'vote down';
			//this.down.href = '#';
		}

		//story
		this.story.innerHTML = data.title;
		this.story.title = data.title.unescapeHtml();
		this.story.href = redditUrl+data.permalink;

		//story info
		var creationDate = new Date(data.created*1000);
		this.subreddit.innerHTML = data.subreddit;
		this.subreddit.href = subRedditUrl+data.subreddit;
		this.author.innerHTML = data.author;
		this.author.href = userRedditUrl+data.author;
		this.created.innerHTML = creationDate.toLocaleDateString();
		this.nsfw.style.display = data.over_18 ? 'inline-block' : 'none';

    	//comments
		var commentStr = ' comment';
		if(data.num_comments > 1){
		    commentStr += 's';
		}
		if(data.num_comments > 99999){
			data.num_comments = '9999+';
		}

		this.comments.innerHTML = data.num_comments;
		this.comments.title = data.num_comments+commentStr;
		this.comments.className = 'comments'+data.num_comments.toString().length;

		this.submitted.style.display = 'inline-block';
    }
};

//TODO: add a timer to updat the extension bars,
//because the bars currently only load when a webpage is loaded<|endoftext|>


<commit_before><commit_msg>more robust ios user_name fallbacks<commit_after><|endoftext|>


<commit_before>import AbstractModel from 'hospitalrun/models/abstract';
import DS from 'ember-data';
import Ember from 'ember';

export default AbstractModel.extend({
  _attachments: DS.attr(), // Temporarily store file as attachment until it gets uploaded to the server
  coverImage: DS.attr('boolean'),
  fileName: DS.attr('string'),
  localFile: DS.attr('boolean'),
  patient: DS.belongsTo('patient', {
    async: false
  }),
  caption: DS.attr('string'),
  url: DS.attr('string'),

  downloadImageFromServer(imageRecord) {
    let me = this;
    let url = imageRecord.get('url');
    let xhr = new XMLHttpRequest();
    if (!Ember.isEmpty(url)) {
      // Make sure directory exists or is created before downloading.
      this.getPatientDirectory(imageRecord.get('patientId'));
      xhr.open('GET', url, true);
      xhr.responseType = 'blob';
      xhr.onload = function() {
        let file = new Blob([xhr.response]);
        me.addImageToFileStore(file, null, imageRecord);
      };
      xhr.send();
    }
  }
});
<commit_msg>Remove downloadImageFromServer from photo model (#887)<commit_after>import AbstractModel from 'hospitalrun/models/abstract';
import DS from 'ember-data';

export default AbstractModel.extend({
  _attachments: DS.attr(), // Temporarily store file as attachment until it gets uploaded to the server
  coverImage: DS.attr('boolean'),
  fileName: DS.attr('string'),
  localFile: DS.attr('boolean'),
  patient: DS.belongsTo('patient', {
    async: false
  }),
  caption: DS.attr('string'),
  url: DS.attr('string')
});
<|endoftext|>


<commit_before>/**
 * @file
 * Page JS for Project file attachments.
 */

// Initial objects, if for some reason they have not been.
var tc = tc || {};
tc.gam = tc.gam || {};
tc.gam.project_widgets = tc.gam.project_widgets || {};

/**
 * Add file widget for projects
 */
tc.gam.project_widgets.add_file = function(project, dom, deps, options) {
    var me = this;

    // Set options and properties (??)
    this.options = tc.jQ.extend({name:'add_file'}, options);
    this.dom = dom;
    var widget = tc.gam.widget(this, project);

    this.handlers = {};
    this.elements = { window: tc.jQ(window) };
    this.components = { merlin: null }

    // Build Merlin component (??)
    this.build_merlin = function() {
        if (this.components.merlin) {
            return;
        }
        this.components.merlin = new tc.merlin(options.app, {
            name: 'add-file',
            dom: dom.find('.merlin.add-file'),
            next_button: dom.find('a.submit'),
            first_step: 'file-info',
            use_hashchange: false,
            data: {
                project_id: null,
                title: null,
                url: null,
                main_text: ''
            },
            steps: {
                'file-info': {
                    selector: '.step.add-file-step',
                    next_step: 'file-submit',
                    inputs: {
                        title: {
                            selector:'input.file-title',
                            validators: ['min-3', 'max-50', 'required'],
                            hint: 'File title',
                            counter:{
                                selector: '.charlimit.title',
                                limit: 50
                            }
                        },
                        /*
                        file: {
                            selector: 'input.file-attach',
                            validators: ['required'],
                            hint: 'Browse for file to upload'
                        }
                        */
                    },
                    init: function(merlin, dom) {
                        merlin.current_step.inputs.title.dom
                            .removeClass('has-been-focused')
                            .removeClass('has-attempted-submit')
                            .val('')
                            .triggerHandler('keyup');
                        /*
                        merlin.current_step.inputs.file.dom
                            .removeClass('has-been-focused')
                            .removeClass('has-attempted-submit')
                            .val('')
                            .triggerHandler('keyup');
                        */

                        merlin.current_step.inputs.title.dom.val('Title');
                        //merlin.current_step.inputs.file.dom.val('File');

                    },
                    finish: function(merlin, dom) {
                        merlin.options.data = tc.jQ.extend(merlin.options.data, {
                            project_id: merlin.app.app_page.data.project.project_id,
                            title: merlin.current_step.inputs.title.dom.val(),
                            //file: merlin.current_step.inputs.file.dom.val()
                        });
                    }
                },
                'file-submit': {
                    selector: '.step.submit-file-step',
                    next_step: 'goal-info',
                    init: function(merlin, dom){
                        tc.jQ.ajax({
                            type: 'POST',
                            url: '/project/file/add',
                            data: merlin.options.data,
                            context: merlin,
                            dataType: 'text',
                            success: function(data, ts, xhr) {
                                if (data == 'False'){
                                    return false;
                                }
                                project.dom.trigger('resources-refresh', {type: 'link'});
                                window.location.hash = 'project-home';
                            }
                        });
                    }
                }
            }
        });
    };

    // Call the build step (??)
    this.build_merlin();

    // Return object
    return {
        show: function(propagate) {
            widget.show(propagate);
            if (me.components.merlin) {
                me.components.merlin.show_step('file-info');
            }

            // Scroll up to the top.
            if ((me.dom.offset().top - me.elements.window.scrollTop()) < 0) {
                me.elements.window.scrollTop(0);
            }
        },
        hide: widget.hide
    };
};<commit_msg>Cleaned up add_file js file so natural docs are better.<commit_after>/**
 * File:
 * Page JS for Project file attachments.
 */

// Initial objects, if for some reason they have not been.
var tc = tc || {};
tc.gam = tc.gam || {};
tc.gam.project_widgets = tc.gam.project_widgets || {};

/**
 * Add file widget for projects
 */
tc.gam.project_widgets.add_file = function(project, dom, deps, options) {
    var me = this;

    // Set options and properties (??)
    this.options = tc.jQ.extend({name:'add_file'}, options);
    this.dom = dom;
    var widget = tc.gam.widget(this, project);

    this.handlers = {};
    this.elements = { window: tc.jQ(window) };
    this.components = { merlin: null }

    // Build Merlin component (??)
    this.build_merlin = function() {
        if (this.components.merlin) {
            return;
        }
        this.components.merlin = new tc.merlin(options.app, {
            name: 'add-file',
            dom: dom.find('.merlin.add-file'),
            next_button: dom.find('a.submit'),
            first_step: 'file-info',
            use_hashchange: false,
            data: {
                project_id: null,
                title: null,
                url: null,
                main_text: ''
            },
            steps: {
                'file-info': {
                    selector: '.step.add-file-step',
                    next_step: 'file-submit',
                    inputs: {
                        title: {
                            selector:'input.file-title',
                            validators: ['min-3', 'max-50', 'required'],
                            hint: 'File title',
                            counter:{
                                selector: '.charlimit.title',
                                limit: 50
                            }
                        },
                    },
                    init: function(merlin, dom) {
                        merlin.current_step.inputs.title.dom
                            .removeClass('has-been-focused')
                            .removeClass('has-attempted-submit')
                            .val('')
                            .triggerHandler('keyup');

                        merlin.current_step.inputs.title.dom.val('Title');

                    },
                    finish: function(merlin, dom) {
                        merlin.options.data = tc.jQ.extend(merlin.options.data, {
                            project_id: merlin.app.app_page.data.project.project_id,
                            title: merlin.current_step.inputs.title.dom.val(),
                        });
                    }
                },
                'file-submit': {
                    selector: '.step.submit-file-step',
                    next_step: 'goal-info',
                    init: function(merlin, dom){
                        tc.jQ.ajax({
                            type: 'POST',
                            url: '/project/file/add',
                            data: merlin.options.data,
                            context: merlin,
                            dataType: 'text',
                            success: function(data, ts, xhr) {
                                if (data == 'False'){
                                    return false;
                                }
                                project.dom.trigger('resources-refresh', {type: 'link'});
                                window.location.hash = 'project-home';
                            }
                        });
                    }
                }
            }
        });
    };

    // Call the build step (??)
    this.build_merlin();

    // Return object
    return {
        show: function(propagate) {
            widget.show(propagate);
            if (me.components.merlin) {
                me.components.merlin.show_step('file-info');
            }

            // Scroll up to the top.
            if ((me.dom.offset().top - me.elements.window.scrollTop()) < 0) {
                me.elements.window.scrollTop(0);
            }
        },
        hide: widget.hide
    };
};<|endoftext|>


<commit_before>import DS from 'ember-data';

export default DS.Model.extend({
  title: DS.attr('string'),
  creatorEmail: DS.attr('string'),
  createdAt: DS.attr('date'),
  snippets: DS.hasMany('snippet')
});
<commit_msg>Mark each Story as complete or incomplete.<commit_after>import DS from 'ember-data';

export default DS.Model.extend({
  title: DS.attr('string'),
  creatorEmail: DS.attr('string'),
  createdAt: DS.attr('date'),
  complete: DS.attr('boolean'),
  snippets: DS.hasMany('snippet')
});
<|endoftext|>