<commit_before>var express = require('express');
var fs = require('fs');
var request = require('request');
var cheerio = require('cheerio');
var expressapp     = express();
var bodyParser = require('body-parser');
var moment = require('moment');
var poly = require('babel-polyfill')

//Configuring middleware
expressapp.use(bodyParser())

expressapp.get('/', function(req, res){
    var file = fs.readFileSync('index.html','UTF-8');
    res.send(file);
})

expressapp.get('/data', function(req, res){
    var file = fs.readFileSync('output.json','UTF-8');
    res.send(file);
})

//Demo of Request to hit a URL
expressapp.get('/generate', function(req, res){

var a = moment('2016-01-01');
var b = moment('2017-01-01');
var allHolidays = {}

// pure function ;-)
var makeUrl = function(momentDate) {
    var date = momentDate.format('MM/DD/YYYY')
        return {
            url: "https://www.checkiday.com/" + date,
            date: date
        };
};

var makeRequestPromise = function(url, date) {
    return new Promise(function(resolve, reject) {
        request(url, function(error, response, html){
            if(error){
                return reject(error);
            }

            var $ = cheerio.load(html);
            var name, description, conditional;
            var json = { name : "", description : "", conditional: null};
            var holidays = [];

            $('#middle_content').each(function(){
                var data = $(this);
                var total = data.children('2').children()._root['0'].children[4].next.children.length - 4;
                var parseMe = data.children('2').children()._root['0'].children[4].next.children;

                for (i =1; i <= total; i += 2) {
                    name = parseMe[i].children[1].children[1].attribs.title.toString();
                   // source = parseMe[i].children[1].children[1].attribs.href.toString();
                    console.log(name)
                    var nameRegex = /is\s(.*)!/g;
                    json.name = name.indexOf('!') > -1 ? nameRegex.exec(name)[1] : null;
                    //json.source = source;
                    holidays.push(json)
                    json = { name : "", description : "", conditional: null};
                }

            });

              allHolidays[date.substring(0,5)] = holidays; //m.format('MM-DD-YYYY')
                var dataToWrite = JSON.stringify(allHolidays, null, 4);
                fs.writeFileSync('output.json', dataToWrite, 'utf8');
              // finish promise
          resolve('File write successfull ' + url);
        });
    });
};

var promises = [];

for (var m = a; m.isBefore(b); m.add( 1, 'days')) {
    var mUrlObject = makeUrl(m)
    promises.push(
        makeRequestPromise( mUrlObject.url, mUrlObject.date )
    );
}

Promise.all(promises)
  .catch(function(err){ return console.error('Error in Promises.all()',err); })
  .then(function(msg) {
        // ^^ 'msg' param is an array of returned values
    console.log(msg); // array of resolve(msg) from above..
  });

    res.write('Output file is being generated for the year, should be ready within a few minutes :)');
    res.end();
})

//Sets up the listener for the express app
expressapp.listen('8081')

//Splash screen including the Node JS logo ascii art
console.log('................................................................................\n.....................................=====......................................\n..................................===========...................................\n...............................=================................................\n............................===========.===========.............................\n..........................==========.......==========...........................\n.......................===========...........===========........................\n....................===========.................===========.....................\n.................===========.......................===========..................\n...............==========.............................==========................\n............==========...................................==========.............\n.........===========.......................................===========..........\n.......==========.............................................==========........\n......========...................................................========.......\n......=====.........................................................=====.......\n......=====.........................................................=====.......\n......=====..............======........=================............=====.......\n......=====..............======......=====================..........=====.......\n......=====..............======....=========================........=====.......\n......=====..............======....======............=======........=====.......\n......=====..............======...======...............======.......=====.......\n......=====..............======...======................=====.......=====.......\n......=====..............======...========..........................=====.......\n......=====..............======....================.................=====.......\n......=====..............======.....======================..........=====.......\n......=====..............======........=====================........=====.......\n......=====..............======..............================.......=====.......\n......=====..............======........................=======......=====.......\n......=====..............======..======.................======......=====.......\n......=====..............======..======.................======......=====.......\n......=====..............======...======................======......=====.......\n......=====..............======...=========..........========.......=====.......\n......=====..............======.....========================........=====.......\n......=====..............======.......====================..........=====.......\n......=====..............======...........============..............=====.......\n......======.............======.....................................=====.......\n......========...........======..................................========.......\n.......==========........======...............................==========........\n.........===========...=======.............................===========..........\n............==================..........................===========.............\n...............==============.........................==========................\n..................========.........................==========...................\n................................................==========......................\n.............................=====...........===========........................\n...........................==========.....===========...........................\n.............................==========.==========..............................\n................................===============.................................\n...................................==========...................................\n.....................................=====......................................\n................................................................................\n');
console.log('          Node Holiday Data Scraper Started at localhost:8081');

exports = module.exports = expressapp;<commit_msg>firebase integrations<commit_after>var express = require('express');
var fs = require('fs');
var request = require('request');
var cheerio = require('cheerio');
var expressapp     = express();
var bodyParser = require('body-parser');
var moment = require('moment');
var poly = require('babel-polyfill');
var Firebase = require('firebase');

//Configuring middleware
expressapp.use(bodyParser())

expressapp.get('/', function(req, res){
    var file = fs.readFileSync('index.html','UTF-8');
    res.send(file);
})

expressapp.get('/data', function(req, res){
    var file = fs.readFileSync('output.json','UTF-8');
    res.send(file);
})

//Demo of Request to hit a URL
expressapp.get('/generate', function(req, res){
var dataRef = new Firebase('https://holidays.firebaseio.com/');
var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
var a = moment('2016-04-01');
var b = moment('2016-04-05');
var allHolidays = {};

// pure function ;-)
var makeUrl = function(momentDate) {
    var date = momentDate.format('MM/DD/YYYY')
        return {
            url: "https://www.checkiday.com/" + date,
            date: date
        };
};

var makeRequestPromise = function(url, date) {
    return new Promise(function(resolve, reject) {
        request(url, function(error, response, html){
            if(error){
                return reject(error);
            }

            var $ = cheerio.load(html);
            var name, description, conditional;
            var json = { name : "", description : "", image : "", conditional: false};
            var holidays = [];

            $('#middle_content').each(function(){
                var data = $(this);
                var total = data.children('2').children()._root['0'].children[4].next.children.length - 4;
                var parseMe = data.children('2').children()._root['0'].children[4].next.children;

                for (i =1; i <= total; i += 2) {
                    name = parseMe[i].children[1].children[1].attribs.title.toString();
                   // source = parseMe[i].children[1].children[1].attribs.href.toString();
                    console.log(name)
                    var nameRegex = /is\s(.*)!/g;
                    json.name = name.indexOf('!') > -1 ? nameRegex.exec(name)[1] : null;
                    //json.source = source;
                    holidays.push(json)
                    json = { name : "", description : "", image : "", conditional: false};
                }

            });
            //Setup the month
            var month = months[date.substring(0,2)-1]
            var day = date.substring(3,5)
            var dataToSync = {}
            dataToSync[month] = {}
            dataToSync[month][day] = holidays
            dataRef.set(dataToSync);
                // var dataToWrite = JSON.stringify(allHolidays, null, 4);
                // fs.writeFileSync('output.json', dataToWrite, 'utf8');
              // finish promise
          resolve('File write successfull ' + url);
        });
    });
};

var promises = [];

for (var m = a; m.isBefore(b); m.add( 1, 'days')) {
    var mUrlObject = makeUrl(m)
    promises.push(
        makeRequestPromise( mUrlObject.url, mUrlObject.date )
    );
}

Promise.all(promises)
  .catch(function(err){ return console.error('Error in Promises.all()',err); })
  .then(function(msg) {
        // ^^ 'msg' param is an array of returned values
    console.log(msg); // array of resolve(msg) from above..
  });

    res.write('Output file is being generated for the year, should be ready within a few minutes :)');
    res.end();
})

//Sets up the listener for the express app
expressapp.listen('8081')

//Splash screen including the Node JS logo ascii art
console.log('................................................................................\n.....................................=====......................................\n..................................===========...................................\n...............................=================................................\n............................===========.===========.............................\n..........................==========.......==========...........................\n.......................===========...........===========........................\n....................===========.................===========.....................\n.................===========.......................===========..................\n...............==========.............................==========................\n............==========...................................==========.............\n.........===========.......................................===========..........\n.......==========.............................................==========........\n......========...................................................========.......\n......=====.........................................................=====.......\n......=====.........................................................=====.......\n......=====..............======........=================............=====.......\n......=====..............======......=====================..........=====.......\n......=====..............======....=========================........=====.......\n......=====..............======....======............=======........=====.......\n......=====..............======...======...............======.......=====.......\n......=====..............======...======................=====.......=====.......\n......=====..............======...========..........................=====.......\n......=====..............======....================.................=====.......\n......=====..............======.....======================..........=====.......\n......=====..............======........=====================........=====.......\n......=====..............======..............================.......=====.......\n......=====..............======........................=======......=====.......\n......=====..............======..======.................======......=====.......\n......=====..............======..======.................======......=====.......\n......=====..............======...======................======......=====.......\n......=====..............======...=========..........========.......=====.......\n......=====..............======.....========================........=====.......\n......=====..............======.......====================..........=====.......\n......=====..............======...........============..............=====.......\n......======.............======.....................................=====.......\n......========...........======..................................========.......\n.......==========........======...............................==========........\n.........===========...=======.............................===========..........\n............==================..........................===========.............\n...............==============.........................==========................\n..................========.........................==========...................\n................................................==========......................\n.............................=====...........===========........................\n...........................==========.....===========...........................\n.............................==========.==========..............................\n................................===============.................................\n...................................==========...................................\n.....................................=====......................................\n................................................................................\n');
console.log('          Node Holiday Data Scraper Started at localhost:8081');

exports = module.exports = expressapp;<|endoftext|>


<commit_before>// load Google's JS API and setup the init function
google.load("gdata", "2.x");
google.setOnLoadCallback(main);

var contactsService = null;
var contactsServiceScope = 'https://www.google.com/m8/feeds';
var countryprefix = '';

/**
 * The init function that initializes everything
 */
function main() {
    var hdr = document.getElementById('header');

    if(google.accounts.user.checkLogin(contactsServiceScope)){
        // we're logged in already, create logout button
        var btn = document.createElement('button');
        btn.innerText = 'Switch Account';
        btn.onclick   = google.accounts.user.logout;
        hdr.innerHTML = '';
        hdr.appendChild(btn);

        // initialize the global contact service
        contactsService = new google.gdata.contacts.ContactsService('splitbrain.org-phonefix-1.0');

        // show the init screen
        startGUI();
    }else{
        // make a login button
        var btn = document.createElement('button');
        btn.innerText = 'Logout';
        btn.onclick   = function(){
            var token = google.accounts.user.login(contactsServiceScope);
        };
        hdr.innerHTML = '';
        hdr.appendChild(btn);
    }
}

function startGUI() {
    var out = document.getElementById('output');
    out.innerHTML = '
Default Country Prefix: '+
                    '<input type="text" id="countryprefix" value="+49" size="3" />
';
    var btn = document.createElement('button');
    btn.innerText = 'Load contacts and preview fixed contacts...';
    btn.onclick = function(){
        // set global prefix
        countryprefix = document.getElementById('countryprefix').value;

        // load the contacts
        loadContacts();
    }
    out.appendChild(btn);
}

/**
 * Load all the contacts
 */
function loadContacts() {
    var contactsFeedUri = 'https://www.google.com/m8/feeds/contacts/default/full';
    var query = new google.gdata.contacts.ContactQuery(contactsFeedUri);

    // set a throbber
    var out = document.getElementById('output');
    out.innerHTML = 'Loading contacts...';

    // FIXME set maximum
    query.setMaxResults(50);
    contactsService.getContactFeed(query, handleContacts, handleError);
}

/**
 * Callback for loadContacts
 *
 * Display the contact results.
 */
function handleContacts(result){
    var out = document.getElementById('output');
    out.innerHTML = '';

    var table = document.createElement('table');
    out.appendChild(table);

    var entries = result.feed.entry;
    for (var i = 0; i < entries.length; i++) {
        var contactEntry = entries[i];

        try {
            var name = contactEntry.getName().getFullName().getValue();
        }catch(err){
            continue; //skip entries without a name
        }

        var numbers = contactEntry.getPhoneNumbers();
        if(numbers.length == 0) continue; //skip entries without phone

        for (var j = 0; j < numbers.length; j++) {
            var th, tr, td, tx;

            tr = document.createElement('tr');

            th = document.createElement('th');
            th.innerText = name;
            tr.appendChild(th);

            td = document.createElement('td');
            td.innerText = numbers[j].getValue();
            tr.appendChild(td);

            td = document.createElement('td');
            tx = document.createElement('input');
            tx.value = phoneClean(numbers[j].getValue());
            // remember tree references in the DOM object
            tx.contactEntry = contactEntry;
            tx.phoneNumber  = numbers[j];
            td.appendChild(tx);
            tr.appendChild(td);

            table.appendChild(tr);
        }
    }

    var btn = document.createElement('button');
    btn.innerText = 'Apply all Changes';
    btn.id = 'applybutton';
    btn.onclick = applyChanges;

    out.appendChild(btn);
}

/**
 * Go through all fields and save the phone number back to Google Contacts
 */
function applyChanges(){
    var out = document.getElementById('output');
    var fields = out.getElementsByTagName('input');

    // disable the apply button
    document.getElementById('applybutton').style.display = 'none';

    // go through all phone number entries
    for(i=0; i<fields.length; i++){
        if(fields[i].value == fields[i].phoneNumber.getValue()){
            //phone numbers are the same, we're done
            fields[i].className = 'done';
        }else{
            fields[i].phoneNumber.setValue(fields[i].value);
            fields[i].contactEntry.updateEntry(function(){
                fields[i].className = 'done';
            }, handleError);
            return; // FIXME we only do the first one now
        }
    }
}

/**
 * Clean the given phone number
 */
function phoneClean(number){
    var prefix = countryprefix+' ';

    number = number.replace(/[\.\-_]/g,' '); // spaces only
    number = number.replace(/^00/,'+');      // 00 is the plus sign
    number = number.replace(/^0/,prefix);    // add prefix
    number = number.replace(/  +/g,' ');     // single spaces only

    // see if we have area codes for that number
    var ctry = RECOUNTRYCODE.exec(number);
    if(ctry && ctry.length){
        ctry = ctry[1];
        var re = new RegExp('^(\\+'+ctry+' ?'+AREAPREFIX[ctry]+' ?)');
        number = number.replace(re,'+'+ctry+' $2 ');
    }
    return number;
}

/**
 * Callback. Display an error
 */
function handleError(error){
    var out = document.getElementById('output');
    var err = document.createElement('div');
    err.className = 'error';
    err.innerText = error;
    out.appendChild(error);
}
<commit_msg>increased the number of contacts fetched to 5000<commit_after>// load Google's JS API and setup the init function
google.load("gdata", "2.x");
google.setOnLoadCallback(main);

var contactsService = null;
var contactsServiceScope = 'https://www.google.com/m8/feeds';
var countryprefix = '';

/**
 * The init function that initializes everything
 */
function main() {
    var hdr = document.getElementById('header');

    if(google.accounts.user.checkLogin(contactsServiceScope)){
        // we're logged in already, create logout button
        var btn = document.createElement('button');
        btn.innerText = 'Switch Account';
        btn.onclick   = google.accounts.user.logout;
        hdr.innerHTML = '';
        hdr.appendChild(btn);

        // initialize the global contact service
        contactsService = new google.gdata.contacts.ContactsService('splitbrain.org-phonefix-1.0');

        // show the init screen
        startGUI();
    }else{
        // make a login button
        var btn = document.createElement('button');
        btn.innerText = 'Logout';
        btn.onclick   = function(){
            var token = google.accounts.user.login(contactsServiceScope);
        };
        hdr.innerHTML = '';
        hdr.appendChild(btn);
    }
}

function startGUI() {
    var out = document.getElementById('output');
    out.innerHTML = '
Default Country Prefix: '+
                    '<input type="text" id="countryprefix" value="+49" size="3" />
';
    var btn = document.createElement('button');
    btn.innerText = 'Load contacts and preview fixed contacts...';
    btn.onclick = function(){
        // set global prefix
        countryprefix = document.getElementById('countryprefix').value;

        // load the contacts
        loadContacts();
    }
    out.appendChild(btn);
}

/**
 * Load all the contacts
 */
function loadContacts() {
    var contactsFeedUri = 'https://www.google.com/m8/feeds/contacts/default/full';
    var query = new google.gdata.contacts.ContactQuery(contactsFeedUri);

    // set a throbber
    var out = document.getElementById('output');
    out.innerHTML = 'Loading contacts...';

    // FIXME set maximum
    query.setMaxResults(5000);
    contactsService.getContactFeed(query, handleContacts, handleError);
}

/**
 * Callback for loadContacts
 *
 * Display the contact results.
 */
function handleContacts(result){
    var out = document.getElementById('output');
    out.innerHTML = '';

    var table = document.createElement('table');
    out.appendChild(table);

    var entries = result.feed.entry;
    for (var i = 0; i < entries.length; i++) {
        var contactEntry = entries[i];

        try {
            var name = contactEntry.getName().getFullName().getValue();
        }catch(err){
            continue; //skip entries without a name
        }

        var numbers = contactEntry.getPhoneNumbers();
        if(numbers.length == 0) continue; //skip entries without phone

        for (var j = 0; j < numbers.length; j++) {
            var th, tr, td, tx;

            tr = document.createElement('tr');

            th = document.createElement('th');
            th.innerText = name;
            tr.appendChild(th);

            td = document.createElement('td');
            td.innerText = numbers[j].getValue();
            tr.appendChild(td);

            td = document.createElement('td');
            tx = document.createElement('input');
            tx.value = phoneClean(numbers[j].getValue());
            // remember tree references in the DOM object
            tx.contactEntry = contactEntry;
            tx.phoneNumber  = numbers[j];
            td.appendChild(tx);
            tr.appendChild(td);

            table.appendChild(tr);
        }
    }

    var btn = document.createElement('button');
    btn.innerText = 'Apply all Changes';
    btn.id = 'applybutton';
    btn.onclick = applyChanges;

    out.appendChild(btn);
}

/**
 * Go through all fields and save the phone number back to Google Contacts
 */
function applyChanges(){
    var out = document.getElementById('output');
    var fields = out.getElementsByTagName('input');

    // disable the apply button
    document.getElementById('applybutton').style.display = 'none';

    // go through all phone number entries
    for(i=0; i<fields.length; i++){
        if(fields[i].value == fields[i].phoneNumber.getValue()){
            //phone numbers are the same, we're done
            fields[i].className = 'done';
        }else{
            fields[i].phoneNumber.setValue(fields[i].value);
            fields[i].contactEntry.updateEntry(function(){
                fields[i].className = 'done';
            }, handleError);
            return; // FIXME we only do the first one now
        }
    }
}

/**
 * Clean the given phone number
 */
function phoneClean(number){
    var prefix = countryprefix+' ';

    number = number.replace(/[\.\-_]/g,' '); // spaces only
    number = number.replace(/^00/,'+');      // 00 is the plus sign
    number = number.replace(/^0/,prefix);    // add prefix
    number = number.replace(/  +/g,' ');     // single spaces only

    // see if we have area codes for that number
    var ctry = RECOUNTRYCODE.exec(number);
    if(ctry && ctry.length){
        ctry = ctry[1];
        var re = new RegExp('^(\\+'+ctry+' ?'+AREAPREFIX[ctry]+' ?)');
        number = number.replace(re,'+'+ctry+' $2 ');
    }
    return number;
}

/**
 * Callback. Display an error
 */
function handleError(error){
    var out = document.getElementById('output');
    var err = document.createElement('div');
    err.className = 'error';
    err.innerText = error;
    out.appendChild(error);
}
<|endoftext|>


<commit_before>d3.round = function(x, n) { var ten_n = Math.pow(10,n); return Math.round(x * ten_n) / ten_n; }

function renderBuildCounts(container, data) {
	var valueLabelWidth = 40; // space reserved for value labels (right)
	var barHeight = 20; // height of one bar
	var barLabelWidth = 130; // space reserved for bar labels
	var barLabelPadding = 5; // padding between bar and bar labels (left)
	var gridLabelHeight = 18; // space reserved for gridline labels
	var gridChartOffset = 3; // space between start of grid and first bar
	var maxBarWidth = 420; // width of the bar with the max value

	// accessor functions
	var barValue = function(d) { return d.value; };

	// scales
	var yScale = d3.scaleBand().domain(d3.range(0, data.length)).range([0, data.length * barHeight]);
	var y = function(d, i) { return yScale(i); };
	var yText = function(d, i) { return y(d, i) + yScale(1) / 2; };
	var x = d3.scaleLinear().domain([0, d3.max(data, barValue)]).range([0, maxBarWidth]);

	// svg container element
	var chart = d3.select(container).html('').append("svg")
		.attr('width', maxBarWidth + barLabelWidth + valueLabelWidth)
		.attr('height', gridLabelHeight + gridChartOffset + data.length * barHeight);

	// grid line labels
	var gridContainer = chart.append('g')
		.attr('transform', 'translate(' + barLabelWidth + ',' + gridLabelHeight + ')');
	gridContainer.selectAll("text").data(x.ticks(10)).enter().append("text")
		.attr("x", x)
		.attr("dy", -3)
		.attr("text-anchor", "middle")
		.text(String);

	// vertical grid lines
	gridContainer.selectAll("line").data(x.ticks(10)).enter().append("line")
		.attr("x1", x)
		.attr("x2", x)
		.attr("y1", 0)
		.attr("y2", yScale(1) + gridChartOffset)
		.style("stroke", "#ccc");

	// bar labels
	var labelsContainer = chart.append('g')
		.attr('transform', 'translate(' + (barLabelWidth - barLabelPadding) + ',' + (gridLabelHeight + gridChartOffset) + ')');
		labelsContainer.selectAll('text').data(data).enter().append('text')
		.attr('y', yText)
		.attr("dy", ".35em") // vertical-align: middle
		.attr('text-anchor', 'end')
		.text(function(d) { return d.key; });

	// bars
	var barsContainer = chart.append('g')
		.attr('transform', 'translate(' + barLabelWidth + ',' + (gridLabelHeight + gridChartOffset) + ')');
	barsContainer.selectAll("rect").data(data).enter().append("rect")
		.attr('y', y)
		.attr('height', yScale(1))
		.attr('width', function(d) { return x(barValue(d)); })
		.attr('stroke', 'white')
		.attr('fill', 'steelblue');

	// bar value labels
	barsContainer.selectAll("text").data(data).enter().append("text")
		.attr("x", function(d) { return x(barValue(d)); })
		.attr("y", yText)
		.attr("dx", 3) // padding-left
		.attr("dy", ".35em") // vertical-align: middle
		.attr("text-anchor", "start") // text-align: right
		.attr("fill", "black")
		.attr("stroke", "none")
		.text(function(d) { return d3.round(barValue(d), 2); });

	// start line
	barsContainer.append("line")
		.attr("y1", -gridChartOffset)
		.attr("y2", yScale(1) + gridChartOffset)
		.style("stroke", "#000");
}

function renderBuildTimes(container, barValue, data, baseUrl) {
	var paddingLeft = 5; // space to the left of the bars
	var paddingRight = 10; // space to the right of the bars
	var barHeight = 5; // height of one bar
	var barPaddingV = 1; // vertical padding between bars
	var gridLabelHeight = 18; // space reserved for gridline labels
	var gridChartOffset = 3; // space between start of grid and first bar
	var maxBarWidth = 450; // width of the bar with the max value

	// scales
	var yScale = d3.scaleBand()
		.domain(d3.range(0, data.length))
		.range([0, data.length * (barHeight+barPaddingV)]);
	var y = function(d, i) { return yScale(i) + barPaddingV*i; };
	var yText = function(d, i) { return y(d, i) + yScale.rangeBand() / 2; };
	var x = d3.scaleLinear()
		.domain([0, d3.max(data, barValue)])
		.range([0, maxBarWidth]);

	// svg container element
	var chart = d3.select(container).html('').append("svg")
		.attr('width', maxBarWidth + paddingLeft + paddingRight)
		.attr('height', gridLabelHeight + gridChartOffset + data.length * (barHeight+barPaddingV*2));

	// grid line labels
	var gridContainer = chart.append('g')
		.attr('transform', 'translate(' + paddingLeft + ',' + gridLabelHeight + ')');
	gridContainer.selectAll("text").data(x.ticks(10)).enter().append("text")
		.attr("x", x)
		.attr("dy", -3)
		.attr("text-anchor", "middle")
		.text(String);

	// vertical grid lines
	gridContainer.selectAll("line").data(x.ticks(10)).enter().append("line")
		.attr("x1", x)
		.attr("x2", x)
		.attr("y1", 0)
		.attr("y2", yScale(1) + gridChartOffset + barPaddingV*data.length)
		.style("stroke", "#ccc");

	// bars
	var barsContainer = chart.append('g')
		.attr('transform', 'translate(' + paddingLeft + ',' + (gridLabelHeight + gridChartOffset) + ')');
	barsContainer.selectAll("rect").data(data).enter().append("rect")
		.attr('y', y)
		.attr('height', yScale(1))
		.attr('width', function(d) { return x(barValue(d)); })
		.attr('stroke', 'white')
		.attr('class', 'build-time-bar')
		.attr('fill', function(d) {
			return d.result === 0 ? '#038035' : '#CC0000';
		})
		.on('click', function(d) {
			window.open(baseUrl + d.id);
		});
}

function getBuildDate(build) {
	var dt = new Date(Date.parse(build.started_at));
	return dt.toDateString();
}

function updateChart() {
	var repoName = document.getElementById('repo-name').value;

	// need at least "a/a"
	if (repoName.length < 3) {
		return;
	}

	var baseUrl = 'https://travis-ci.org/' + repoName + '/builds/';

	var buildsUrl = 'https://api.travis-ci.org/repos/' + repoName + '/builds?event_type=push';

	var builds = [];

	var oldestBuild = Infinity;
	var i=0, n=20;

	var buildCounts = {};

	function updateCount(build) {
		var buildDate = getBuildDate(build);

		if (!buildCounts[buildDate]) {
			buildCounts[buildDate] = 1;
		} else {
			buildCounts[buildDate] += 1;
		}
	}

	function filterBuilds(rawBuilds) {
		if (typeof rawBuilds.length === 'undefined') {
			alert('invalid repository: ' + repoName);
			return;
		}

		var curOldestBuild = oldestBuild;

		rawBuilds.forEach(function(build) {
			var buildNr = Number(build.number);
			if (buildNr < curOldestBuild) {
				curOldestBuild = buildNr;
			}

			if (build.branch !== 'master' || build.state !== 'finished') {
				return;
			}

			updateCount(build);
			builds.push(build);
		});

		function getDuration(build) {
			return build.duration/60;
		}

		function getClockTime(build) {
			var started_at = Date.parse(build.started_at);
			var finished_at = Date.parse(build.finished_at);

			return (finished_at - started_at) / 60000;
		}

		renderBuildTimes('#build-times-duration', getDuration, builds, baseUrl);
		renderBuildTimes('#build-times', getClockTime, builds, baseUrl);
		renderBuildCounts('#build-counts', d3.entries(buildCounts), baseUrl);

		if (++i < n && curOldestBuild < oldestBuild) {
			oldestBuild = curOldestBuild;
			d3.json(buildsUrl + '&after_number=' + oldestBuild, filterBuilds);
		}
	}

	d3.json(buildsUrl, filterBuilds);
}

function updateInputViaHash() {
	document.getElementById('repo-name').value = window.location.hash.substr(1);
}

function updateHashViaInput() {
	window.location.hash = '#' + document.getElementById('repo-name').value;
}

d3.select(window).on('hashchange', updateInputViaHash);

d3.select('form').on('submit', function() {
	d3.event.preventDefault();

	updateHashViaInput();
	updateChart();
});

updateInputViaHash();
updateChart();
<commit_msg>Extract API endpoints into variables<commit_after>var travis_endpoint = 'travis-ci.org';
var travis_api_endpoint = 'api.travis-ci.org';

d3.round = function(x, n) { var ten_n = Math.pow(10,n); return Math.round(x * ten_n) / ten_n; }

function renderBuildCounts(container, data) {
	var valueLabelWidth = 40; // space reserved for value labels (right)
	var barHeight = 20; // height of one bar
	var barLabelWidth = 130; // space reserved for bar labels
	var barLabelPadding = 5; // padding between bar and bar labels (left)
	var gridLabelHeight = 18; // space reserved for gridline labels
	var gridChartOffset = 3; // space between start of grid and first bar
	var maxBarWidth = 420; // width of the bar with the max value

	// accessor functions
	var barValue = function(d) { return d.value; };

	// scales
	var yScale = d3.scaleBand().domain(d3.range(0, data.length)).range([0, data.length * barHeight]);
	var y = function(d, i) { return yScale(i); };
	var yText = function(d, i) { return y(d, i) + yScale(1) / 2; };
	var x = d3.scaleLinear().domain([0, d3.max(data, barValue)]).range([0, maxBarWidth]);

	// svg container element
	var chart = d3.select(container).html('').append("svg")
		.attr('width', maxBarWidth + barLabelWidth + valueLabelWidth)
		.attr('height', gridLabelHeight + gridChartOffset + data.length * barHeight);

	// grid line labels
	var gridContainer = chart.append('g')
		.attr('transform', 'translate(' + barLabelWidth + ',' + gridLabelHeight + ')');
	gridContainer.selectAll("text").data(x.ticks(10)).enter().append("text")
		.attr("x", x)
		.attr("dy", -3)
		.attr("text-anchor", "middle")
		.text(String);

	// vertical grid lines
	gridContainer.selectAll("line").data(x.ticks(10)).enter().append("line")
		.attr("x1", x)
		.attr("x2", x)
		.attr("y1", 0)
		.attr("y2", yScale(1) + gridChartOffset)
		.style("stroke", "#ccc");

	// bar labels
	var labelsContainer = chart.append('g')
		.attr('transform', 'translate(' + (barLabelWidth - barLabelPadding) + ',' + (gridLabelHeight + gridChartOffset) + ')');
		labelsContainer.selectAll('text').data(data).enter().append('text')
		.attr('y', yText)
		.attr("dy", ".35em") // vertical-align: middle
		.attr('text-anchor', 'end')
		.text(function(d) { return d.key; });

	// bars
	var barsContainer = chart.append('g')
		.attr('transform', 'translate(' + barLabelWidth + ',' + (gridLabelHeight + gridChartOffset) + ')');
	barsContainer.selectAll("rect").data(data).enter().append("rect")
		.attr('y', y)
		.attr('height', yScale(1))
		.attr('width', function(d) { return x(barValue(d)); })
		.attr('stroke', 'white')
		.attr('fill', 'steelblue');

	// bar value labels
	barsContainer.selectAll("text").data(data).enter().append("text")
		.attr("x", function(d) { return x(barValue(d)); })
		.attr("y", yText)
		.attr("dx", 3) // padding-left
		.attr("dy", ".35em") // vertical-align: middle
		.attr("text-anchor", "start") // text-align: right
		.attr("fill", "black")
		.attr("stroke", "none")
		.text(function(d) { return d3.round(barValue(d), 2); });

	// start line
	barsContainer.append("line")
		.attr("y1", -gridChartOffset)
		.attr("y2", yScale(1) + gridChartOffset)
		.style("stroke", "#000");
}

function renderBuildTimes(container, barValue, data, baseUrl) {
	var paddingLeft = 5; // space to the left of the bars
	var paddingRight = 10; // space to the right of the bars
	var barHeight = 5; // height of one bar
	var barPaddingV = 1; // vertical padding between bars
	var gridLabelHeight = 18; // space reserved for gridline labels
	var gridChartOffset = 3; // space between start of grid and first bar
	var maxBarWidth = 450; // width of the bar with the max value

	// scales
	var yScale = d3.scaleBand()
		.domain(d3.range(0, data.length))
		.range([0, data.length * (barHeight+barPaddingV)]);
	var y = function(d, i) { return yScale(i) + barPaddingV*i; };
	var yText = function(d, i) { return y(d, i) + yScale.rangeBand() / 2; };
	var x = d3.scaleLinear()
		.domain([0, d3.max(data, barValue)])
		.range([0, maxBarWidth]);

	// svg container element
	var chart = d3.select(container).html('').append("svg")
		.attr('width', maxBarWidth + paddingLeft + paddingRight)
		.attr('height', gridLabelHeight + gridChartOffset + data.length * (barHeight+barPaddingV*2));

	// grid line labels
	var gridContainer = chart.append('g')
		.attr('transform', 'translate(' + paddingLeft + ',' + gridLabelHeight + ')');
	gridContainer.selectAll("text").data(x.ticks(10)).enter().append("text")
		.attr("x", x)
		.attr("dy", -3)
		.attr("text-anchor", "middle")
		.text(String);

	// vertical grid lines
	gridContainer.selectAll("line").data(x.ticks(10)).enter().append("line")
		.attr("x1", x)
		.attr("x2", x)
		.attr("y1", 0)
		.attr("y2", yScale(1) + gridChartOffset + barPaddingV*data.length)
		.style("stroke", "#ccc");

	// bars
	var barsContainer = chart.append('g')
		.attr('transform', 'translate(' + paddingLeft + ',' + (gridLabelHeight + gridChartOffset) + ')');
	barsContainer.selectAll("rect").data(data).enter().append("rect")
		.attr('y', y)
		.attr('height', yScale(1))
		.attr('width', function(d) { return x(barValue(d)); })
		.attr('stroke', 'white')
		.attr('class', 'build-time-bar')
		.attr('fill', function(d) {
			return d.result === 0 ? '#038035' : '#CC0000';
		})
		.on('click', function(d) {
			window.open(baseUrl + d.id);
		});
}

function getBuildDate(build) {
	var dt = new Date(Date.parse(build.started_at));
	return dt.toDateString();
}

function updateChart() {
	var repoName = document.getElementById('repo-name').value;

	// need at least "a/a"
	if (repoName.length < 3) {
		return;
	}

	var baseUrl = 'https://' + travis_endpoint + '/' + repoName + '/builds/';

	var buildsUrl = 'https://' + travis_api_endpoint + '/repos/' + repoName + '/builds?event_type=push';

	var builds = [];

	var oldestBuild = Infinity;
	var i=0, n=20;

	var buildCounts = {};

	function updateCount(build) {
		var buildDate = getBuildDate(build);

		if (!buildCounts[buildDate]) {
			buildCounts[buildDate] = 1;
		} else {
			buildCounts[buildDate] += 1;
		}
	}

	function filterBuilds(rawBuilds) {
		if (typeof rawBuilds.length === 'undefined') {
			alert('invalid repository: ' + repoName);
			return;
		}

		var curOldestBuild = oldestBuild;

		rawBuilds.forEach(function(build) {
			var buildNr = Number(build.number);
			if (buildNr < curOldestBuild) {
				curOldestBuild = buildNr;
			}

			if (build.branch !== 'master' || build.state !== 'finished') {
				return;
			}

			updateCount(build);
			builds.push(build);
		});

		function getDuration(build) {
			return build.duration/60;
		}

		function getClockTime(build) {
			var started_at = Date.parse(build.started_at);
			var finished_at = Date.parse(build.finished_at);

			return (finished_at - started_at) / 60000;
		}

		renderBuildTimes('#build-times-duration', getDuration, builds, baseUrl);
		renderBuildTimes('#build-times', getClockTime, builds, baseUrl);
		renderBuildCounts('#build-counts', d3.entries(buildCounts), baseUrl);

		if (++i < n && curOldestBuild < oldestBuild) {
			oldestBuild = curOldestBuild;
			d3.json(buildsUrl + '&after_number=' + oldestBuild, filterBuilds);
		}
	}

	d3.json(buildsUrl, filterBuilds);
}

function updateInputViaHash() {
	document.getElementById('repo-name').value = window.location.hash.substr(1);
}

function updateHashViaInput() {
	window.location.hash = '#' + document.getElementById('repo-name').value;
}

d3.select(window).on('hashchange', updateInputViaHash);

d3.select('form').on('submit', function() {
	d3.event.preventDefault();

	updateHashViaInput();
	updateChart();
});

updateInputViaHash();
updateChart();
<|endoftext|>


<commit_before>const { makeExecutableSchema } = require('graphql-tools')
const DataLoader = require('dataloader')
const { getItem, getUser, getTopStories } = require('../hnclient')

const typeDefs = [`
  type User {
    about: String
    created: Int
    delay: Int,
    id: String!
    karma: Int!
    submitted: [Item]
  }

  enum ITEM_TYPE {
    JOB
    STORY
    COMMENT
    POLL
    POLLOPT
  }

  type Item {
    id: Int!
    by: User!
    kids: [Item]
    score: Int!
    time: Int
    title: String
    type: ITEM_TYPE
    url: String
    text: String
    dead: Boolean
  }

  type Query {
    item(id: Int!): Item
    stories(page: Int, count: Int): [Item]
    user(id: String!): User
  }

  schema {
    query: Query
  }
`]

const resolvers = {
  Query: {
    item (_, { id }) {
      return itemLoader.load(id)
    },

    async stories (_, { page, count }) {
      return topStoriesLoader.load({ page, count })
    },

    user (_, { id }) {
      return getUser(id)
    }
  },
  Item: {
    by ({ by }) {
      return getUser(by)
    },
    kids ({ kids }) {
      return itemLoader.loadMany(kids)
    },
    type ({ type }) {
      return type.toUpperCase()
    }
  },
  User: {
    submitted ({ submitted }) {
      return itemLoader.loadMany(submitted.slice(0, 10))
    }
  }
}

const itemLoader = new DataLoader(ids => Promise.all(ids.map(getItem)))

const allTopStoriesLoader = new DataLoader(keys => Promise.all(keys.map(getTopStories)))

const topStoriesLoader = new DataLoader(async params => Promise.all(params.map(async ({ page, count } = {}) => {
  const stories = await allTopStoriesLoader.load('all')
  return itemLoader.loadMany(page && count
    ? stories.slice(page * count, (page * count) + count)
    : stories)
})))

module.exports = makeExecutableSchema({ typeDefs, resolvers })
<commit_msg>Create userLoader<commit_after>const { makeExecutableSchema } = require('graphql-tools')
const DataLoader = require('dataloader')
const { getItem, getUser, getTopStories } = require('../hnclient')

const typeDefs = [`
  type User {
    about: String
    created: Int
    delay: Int,
    id: String!
    karma: Int!
    submitted: [Item]
  }

  enum ITEM_TYPE {
    JOB
    STORY
    COMMENT
    POLL
    POLLOPT
  }

  type Item {
    id: Int!
    by: User!
    kids: [Item]
    score: Int!
    time: Int
    title: String
    type: ITEM_TYPE
    url: String
    text: String
    dead: Boolean
  }

  type Query {
    item(id: Int!): Item
    stories(page: Int, count: Int): [Item]
    user(id: String!): User
  }

  schema {
    query: Query
  }
`]

const resolvers = {
  Query: {
    item (_, { id }) {
      return itemLoader.load(id)
    },

    async stories (_, { page, count }) {
      return topStoriesLoader.load({ page, count })
    },

    user (_, { id }) {
      return userLoader.load(id)
    }
  },
  Item: {
    by ({ by }) {
      return userLoader.load(by)
    },
    kids ({ kids }) {
      return itemLoader.loadMany(kids)
    },
    type ({ type }) {
      return type.toUpperCase()
    }
  },
  User: {
    submitted ({ submitted }) {
      return itemLoader.loadMany(submitted.slice(0, 10))
    }
  }
}

const itemLoader = new DataLoader(ids => Promise.all(ids.map(getItem)))

const allTopStoriesLoader = new DataLoader(keys => Promise.all(keys.map(getTopStories)))

const topStoriesLoader = new DataLoader(async params => Promise.all(params.map(async ({ page, count } = {}) => {
  const stories = await allTopStoriesLoader.load('all')
  return itemLoader.loadMany(page && count
    ? stories.slice(page * count, (page * count) + count)
    : stories)
})))

const userLoader = new DataLoader(ids => Promise.all(ids.map(getUser)))

module.exports = makeExecutableSchema({ typeDefs, resolvers })
<|endoftext|>


<commit_before>/**
 * Created by zarges on 23/06/15.
 */
'use strict';
angular.module('mwResponseToastHandler', ['mwResponseHandler', 'mwI18n', 'mwToast'])

  .provider('ResponseToastHandler', function ($provide, ResponseHandlerProvider) {
    var _registeredIds = [],
        _registeredToastOptions = {
          DEFAULT: {
            type: 'default',
            autoHide: false
          }
        };

    var _getNoftificationCallback = function (messages, id, options) {
      options = options || {};
      var factoryName = _.uniqueId('notification_factory');
      $provide.factory(factoryName, ['Toast', 'i18n', function (Toast, i18n) {
        return function (response) {
          var prevToast = Toast.findToast(id),
            data = response.data || {},
            messageStr = prevToast ? messages.plural : messages.singular,
            message,
            toastOptions = {
              id: id
            };

          data.$count = prevToast ? prevToast.replaceCount+1 : 0;
          data.$count++;

          if(options.preProcess && typeof options.preProcess=== 'function'){
            message = options.preProcess.call(this, messageStr, data, i18n);
          } else {
            if(data.results && data.results.length > 0 ){
              data = data.results[0];
            }
            message = i18n.get(messageStr, data);
          }

          if(options.toastType){
            var opts = _registeredToastOptions[options.toastType];
            if(opts){
              _.extend(toastOptions, opts);
            } else {
              throw new Error('Type '+options.toastType+' is not available. Make sure you have configured it first')
            }
          } else {
            _.extend(toastOptions, _registeredToastOptions.DEFAULT);
          }

          Toast.addToast(message, toastOptions);
        };
      }]);
      return factoryName;
    };

    this.registerToastType = function(typeId, toastOptions){
      if(_registeredToastOptions[typeId]){

      } else {
        _registeredToastOptions[typeId] = toastOptions;
      }
    };

    this.registerToast = function (route, messages, options) {
      var msgId = options.id || route + '_' + options.method,
        callbackFactory = _getNoftificationCallback(messages, msgId, options);

      if(_registeredIds.indexOf(msgId)>-1){
        throw new Error('You can not define a second message for the route '+route+' and method '+ options.method + ' because you have already registered one!');
      } else {
        _registeredIds.push(msgId);
        return ResponseHandlerProvider.registerAction(route, callbackFactory, options);
      }
    };

    this.$get = function () {};

  });<commit_msg>adds functionality<commit_after>/**
 * Created by zarges on 23/06/15.
 */
'use strict';
angular.module('mwResponseToastHandler', ['mwResponseHandler', 'mwI18n', 'mwToast'])

  .provider('ResponseToastHandler', function ($provide, ResponseHandlerProvider) {
    var _registeredIds = [],
      _registeredToastOptions = {
        DEFAULT: {
          type: 'default',
          autoHide: false
        }
      };

    var _getNoftificationCallback = function (messages, id, options) {
      options = options || {};
      var factoryName = _.uniqueId('notification_factory');
      $provide.factory(factoryName, ['Toast', 'i18n', function (Toast, i18n) {
        return function (response) {
          if(!messages){
            return;
          }

          var prevToast = Toast.findToast(id),
            data = response.data || {},
            messageStr = prevToast ? messages.plural : messages.singular,
            message,
            toastOptions = {
              id: id
            };

          data.$count = prevToast ? prevToast.replaceCount+1 : 0;
          data.$count++;

          if(options.preProcess && typeof options.preProcess=== 'function'){
            message = options.preProcess.call(this, messageStr, data, i18n);
          } else {
            if(data.results && data.results.length > 0 ){
              data = data.results[0];
            }
            message = i18n.get(messageStr, data);
          }

          if(options.toastType){
            var opts = _registeredToastOptions[options.toastType];
            if(opts){
              _.extend(toastOptions, opts);
            } else {
              throw new Error('Type '+options.toastType+' is not available. Make sure you have configured it first')
            }
          } else {
            _.extend(toastOptions, _registeredToastOptions.DEFAULT);
          }

          Toast.addToast(message, toastOptions);
        };
      }]);
      return factoryName;
    };

    this.registerToastType = function(typeId, toastOptions){
      if(_registeredToastOptions[typeId]){

      } else {
        _registeredToastOptions[typeId] = toastOptions;
      }
    };

    this.registerToast = function (route, messages, options) {
      var msgId = options.id || route + '_' + options.method,
        callbackFactory = _getNoftificationCallback(messages, msgId, options);

      if(_registeredIds.indexOf(msgId)>-1){
        throw new Error('You can not define a second message for the route '+route+' and method '+ options.method + ' because you have already registered one!');
      } else {
        _registeredIds.push(msgId);
        return ResponseHandlerProvider.registerAction(route, callbackFactory, options);
      }
    };

    this.$get = function () {};

  });<|endoftext|>


<commit_before>const _ = require('underscore');
const Backbone = require('backbone');
const checkAndBuildOpts = require('cartodb3/helpers/required-opts');

const REQUIRED_OPTS = [
  'userModel'
];
const GRANT_TYPES = {
  APIS: 'apis',
  DATABASE: 'database'
};

module.exports = Backbone.Model.extend({
  defaults: {
    name: '',
    token: '',
    apis: {
      maps: false,
      sql: false
    },
    tables: []
  },

  initialize: function (models, options) {
    checkAndBuildOpts(options, REQUIRED_OPTS, this);
  },

  regenerate: function () {
    const options = {
      url: `${this.url()}/token/regenerate`,
      type: 'POST',
      success: (data) => this.set(data)
    };

    return this.sync(null, this, options);
  },

  parse: function (data) {
    const { grants, ...attrs } = data;
    const apis = this._parseApiGrants(grants);
    const tables = this._parseTableGrants(grants);

    return { ...attrs, apis, tables, id: attrs.name };
  },

  toJSON: function () {
    const { apis, ...attrs } = this.attributes;

    // TODO: Refactor
    const grants = [
      { type: GRANT_TYPES.APIS, apis: this.getApiGrants() },
      { type: GRANT_TYPES.DATABASE, tables: this.getTablesGrants() }
    ];

    return { ...attrs, grants };
  },

  getApiGrants: function () {
    const apis = this.get('apis');
    return Object.keys(apis).filter(name => apis[name]);
  },

  getTablesGrants: function () {
    return _.map(this.get('tables'), (value, key) => ({
      name: key,
      schema: this._userModel.isInsideOrg() ? this._userModel.get('username') : 'public', // TODO: Does this work?
      permissions: Object.keys(value.permissions).filter(name => value.permissions[name])
    }));
  },

  _parseApiGrants: function (grants) {
    const apis = grants.find(grant => grant.type === GRANT_TYPES.APIS).apis;
    const apisObj = this._arrayToObj(apis);

    return Object.assign({}, this.defaults.apis, apisObj);
  },

  _parseTableGrants: function (grants) {
    const tables = grants.find(grant => grant.type === GRANT_TYPES.DATABASE).tables;
    const tablesObj = tables.reduce((total, table) => {
      const permissions = this._arrayToObj(table.permissions);
      return Object.assign(total, { [table.name]: { ...table, permissions } });
    }, {});

    return tablesObj;
  },

  _arrayToObj: function (arr) {
    return arr.reduce((total, item) => Object.assign(total, { [item]: true }), {});
  },

  hasPermissionsSelected: function () {
    return _.some(this.getTablesGrants().map(table => !_.isEmpty(table.permissions)));
  }
});
<commit_msg>Encode api key name to avoid problems when using it as id<commit_after>const _ = require('underscore');
const Backbone = require('backbone');
const checkAndBuildOpts = require('cartodb3/helpers/required-opts');

const REQUIRED_OPTS = [
  'userModel'
];
const GRANT_TYPES = {
  APIS: 'apis',
  DATABASE: 'database'
};

module.exports = Backbone.Model.extend({
  defaults: {
    name: '',
    token: '',
    apis: {
      maps: false,
      sql: false
    },
    tables: []
  },

  initialize: function (models, options) {
    checkAndBuildOpts(options, REQUIRED_OPTS, this);
  },

  regenerate: function () {
    const options = {
      url: `${this.url()}/token/regenerate`,
      type: 'POST',
      success: (data) => this.set(data)
    };

    return this.sync(null, this, options);
  },

  parse: function (data) {
    const { grants, name, ...attrs } = data;
    const apis = this._parseApiGrants(grants);
    const tables = this._parseTableGrants(grants);

    return {
      ...attrs,
      apis,
      tables,
      id: name,
      name: decodeURIComponent(name)
    };
  },

  toJSON: function () {
    const { apis, name, ...attrs } = this.attributes;

    // TODO: Refactor
    const grants = [
      { type: GRANT_TYPES.APIS, apis: this.getApiGrants() },
      { type: GRANT_TYPES.DATABASE, tables: this.getTablesGrants() }
    ];

    return { ...attrs, name: encodeURIComponent(name), grants };
  },

  getApiGrants: function () {
    const apis = this.get('apis');
    return Object.keys(apis).filter(name => apis[name]);
  },

  getTablesGrants: function () {
    return _.map(this.get('tables'), (value, key) => ({
      name: key,
      schema: this._userModel.isInsideOrg() ? this._userModel.get('username') : 'public', // TODO: Does this work?
      permissions: Object.keys(value.permissions).filter(name => value.permissions[name])
    }));
  },

  _parseApiGrants: function (grants) {
    const apis = grants.find(grant => grant.type === GRANT_TYPES.APIS).apis;
    const apisObj = this._arrayToObj(apis);

    return Object.assign({}, this.defaults.apis, apisObj);
  },

  _parseTableGrants: function (grants) {
    const tables = grants.find(grant => grant.type === GRANT_TYPES.DATABASE).tables;
    const tablesObj = tables.reduce((total, table) => {
      const permissions = this._arrayToObj(table.permissions);
      return Object.assign(total, { [table.name]: { ...table, permissions } });
    }, {});

    return tablesObj;
  },

  _arrayToObj: function (arr) {
    return arr.reduce((total, item) => Object.assign(total, { [item]: true }), {});
  },

  hasPermissionsSelected: function () {
    return _.some(this.getTablesGrants().map(table => !_.isEmpty(table.permissions)));
  }
});
<|endoftext|>


<commit_before>import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TextInput,
  TouchableNativeFeedback,
  Image,
  TouchableOpacity,
} from 'react-native';

const MIN_PASSWORD_LENGTH = 1;

class Signup extends Component {
    constructor(props){
        super(props);
        this.state = {
            email: '',
            passwordPlainText: '', //not sure how else to store the state...
            confirmPasswordPlainText: ''
        };
        this.onSignup = this._onSignup.bind(this);
    }

    _hashString(s){
        //do some initial hashing work so we don't send passwords over the network in the clear, I guess

        //ideally we'd be using some other library etc. etc. for user auth
        //but we're running out of time in the semester soOOoooO we're going with quick hacks
        //across the board :(
        var hash = 0, i, chr, len;
        if (s.length === 0) return hash;
        for (i = 0, len = s.length; i < len; i++) {
          chr   = s.charCodeAt(i);
          hash  = ((hash << 5) - hash) + chr;
          hash |= 0; // Convert to 32bit integer
        }
        return hash+""; //Convert final result back to a string
    }

    _onSignup(){
        if(this.state.passwordPlainText && (this.state.passwordPlainText.length >= MIN_PASSWORD_LENGTH) &&
            (this.state.passwordPlainText === this.state.confirmPasswordPlainText) && this.state.email) {
                this.props.onSignup();
        }
    }

    render() {
        var TouchableElement = TouchableNativeFeedback;

        var validMatchingPasswordsText = "Password and confirm password field " + (
            ((this.state.passwordPlainText === this.state.confirmPasswordPlainText) &&
                this.state.passwordPlainText.length >= MIN_PASSWORD_LENGTH) ? "" : "do not ") +
            "match and meet the requirements";

        return (
        <View style={styles.container}>
            <View>
                <Text>(unstyled) signup page</Text>
                <Text>Email:</Text>
                <TextInput
                    style={{height: 40}}
                    onChangeText={(text)=>{this.setState({email: text})}}
                    value={this.state.email}
                />
                <Text>Password:</Text>
                <TextInput
                    style={{height: 40}}
                    onChangeText={(text)=>{this.setState({passwordPlainText: text})}}
                    secureTextEntry={true}
                />
                <Text>Confirm password:</Text>
                <TextInput
                    style={{height: 40}}
                    onChangeText={(text)=>{this.setState({confirmPasswordPlainText: text})}}
                    secureTextEntry={true}
                />
                <Text>...</Text>
                <Text>{validMatchingPasswordsText}</Text>
                <TouchableElement onPress={this.onSignup}>
                    <View><Text>SIGN ME UP</Text></View>
                </TouchableElement>
            </View>
        </View>

        );
        }

}

module.exports = Signup;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
  button: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
  textEdit: {
    height: 40,
    width: 200,
    borderColor: 'grey',
    backgroundColor: 'white',
    borderWidth: 1
  },
});
<commit_msg>Make signup page take email input too<commit_after>import React, { Component } from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  TextInput,
  TouchableNativeFeedback,
  Image,
  TouchableOpacity,
} from 'react-native';

const MIN_PASSWORD_LENGTH = 1;

class Signup extends Component {
    constructor(props){
        super(props);
        this.state = {
            email: '',
            passwordPlainText: '', //not sure how else to store the state...
            confirmPasswordPlainText: ''
        };
        this.onSignup = this._onSignup.bind(this);
    }

    _hashString(s){
        //do some initial hashing work so we don't send passwords over the network in the clear, I guess

        //ideally we'd be using some other library etc. etc. for user auth
        //but we're running out of time in the semester soOOoooO we're going with quick hacks
        //across the board :(
        var hash = 0, i, chr, len;
        if (s.length === 0) return hash;
        for (i = 0, len = s.length; i < len; i++) {
          chr   = s.charCodeAt(i);
          hash  = ((hash << 5) - hash) + chr;
          hash |= 0; // Convert to 32bit integer
        }
        return hash+""; //Convert final result back to a string
    }

    _onSignup(){
        if(this.state.passwordPlainText && (this.state.passwordPlainText.length >= MIN_PASSWORD_LENGTH) &&
            (this.state.passwordPlainText === this.state.confirmPasswordPlainText) && this.state.email) {
                this.props.onSignup();
        }
    }

    render() {
        var TouchableElement = TouchableNativeFeedback;

        var validMatchingPasswordsText = "Password and confirm password field " + (
            ((this.state.passwordPlainText === this.state.confirmPasswordPlainText) &&
                this.state.passwordPlainText.length >= MIN_PASSWORD_LENGTH) ? "" : "do not ") +
            "match and meet the requirements";

        return (
        <View style={styles.container}>
            <View>
                <Text>(unstyled) signup page</Text>
                <Text>Email:</Text>
                <TextInput
                    style={{height: 40}}
                    onChangeText={(text)=>{this.setState({email: text})}}
                    value={this.state.email}
                    keyboardType={"email-address"}
                />
                <Text>Password:</Text>
                <TextInput
                    style={{height: 40}}
                    onChangeText={(text)=>{this.setState({passwordPlainText: text})}}
                    secureTextEntry={true}
                />
                <Text>Confirm password:</Text>
                <TextInput
                    style={{height: 40}}
                    onChangeText={(text)=>{this.setState({confirmPasswordPlainText: text})}}
                    secureTextEntry={true}
                />
                <Text>...</Text>
                <Text>{validMatchingPasswordsText}</Text>
                <TouchableElement onPress={this.onSignup}>
                    <View><Text>SIGN ME UP</Text></View>
                </TouchableElement>
            </View>
        </View>

        );
        }

}

module.exports = Signup;

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  welcome: {
    fontSize: 20,
    textAlign: 'center',
    margin: 10,
  },
  instructions: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
  button: {
    textAlign: 'center',
    color: '#333333',
    marginBottom: 5,
  },
  textEdit: {
    height: 40,
    width: 200,
    borderColor: 'grey',
    backgroundColor: 'white',
    borderWidth: 1
  },
});
<|endoftext|>


<commit_before>// This example displays a marker at the center of Australia.
// When the user clicks the marker, an info window opens.
var map, myPos, myMarker, myInfoWindow;
var myFirebaseRef = new Firebase("https://googlemapmessages.firebaseio.com/");
var mode = "text";
var id = 0;

function initMap() {
  var center = {lat: -0, lng: 0};

  map = new google.maps.Map(document.getElementById('map'), {
    zoom: 4,
    center: center,
    disableDefaultUI: true,
    minZoom: 2
  });

  myInfowindow = new google.maps.InfoWindow({map: map});

  myPos = {lat:0,lng:0};
  // Try HTML5 geolocation.
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(position) {
      myPos = {
        lat: position.coords.latitude,
        lng: position.coords.longitude
      };

      myInfowindow.setPosition(myPos);
      myInfowindow.setContent('
TextDraw

<textarea id="message"></textarea><button onclick="saveMessage()">Save</button>
');
      map.setCenter(myPos);
      myMarker = new google.maps.Marker({
        position: myPos,
        map: map,
      });
      myInfowindow.open(map,myMarker);

    }, function() {
      handleLocationError(true, myInfowindow, map.getCenter());
    });
  } else {
    // Browser doesn't support Geolocation
    handleLocationError(false, myInfowindow, map.getCenter());
  }

  google.maps.event.addListener(map, 'click', function(event) {
    placeMarker(event.latLng);
  });

  myFirebaseRef.on("child_added", function(snapshot) {
    console.log(snapshot.val());
    newMessage(snapshot.val());
  }, function (errorObject) {
    console.log("The read failed: " + errorObject.code);
  });
}

function placeMarker(location) {
  console.log(location)
  myMarker.setMap(null)
  mode = 'text';
  myPos = {lat:location.lat(), lng:location.lng()};

  myMarker = new google.maps.Marker({
    position: myPos,
    map: map,
  });
  myInfowindow = new google.maps.InfoWindow({
    content: '
TextDraw

<textarea id="message"></textarea><button onclick="saveMessage()">Save</button>
'
  });
  myInfowindow.open(map,myMarker);
  document.getElementById('message').focus()

  myMarker.addListener('click', function() {
    myInfowindow.open(map,myMarker);
    document.getElementById('message').focus()
  });
}

function handleLocationError(browserHasGeolocation, infoWindow, pos) {
  infoWindow.setPosition(pos);
  infoWindow.setContent(browserHasGeolocation ?
    'Error: The Geolocation service failed.' :
    'Error: Your browser doesn\'t support geolocation.');
  }

  function saveMessage(){
    var pos = myPos
    if(mode =='text'){
      myFirebaseRef.push({
        type:'text',
        message: _.escape(document.getElementById('message').value),
        location: pos
      });
    } else {
      imageData = $('#simple_sketch')[0].toDataURL('image/png').replace(/^data:image\/(png|jpg);base64,/, "");
      $.ajax({
        url: 'https://api.imgur.com/3/image',
        headers: {
          'Authorization': 'Client-ID a2bb58386e94eb0'
        },
        type: 'POST',
        data: {
          'image': imageData
        },
        success: function(data) { myFirebaseRef.push({
          type:'image',
          message: data.data.link,
          location: pos
        }); }
      });
    }
    myMarker.setMap(null)
  }
  function draw(){
    $('#messageArea').html('<canvas id="simple_sketch" width="300" height="100"></canvas><button onclick="saveMessage()">Save</button>')
    $(function() {
      $('#simple_sketch').sketch();
    });
    mode = 'draw';
  }
  function text(){
    $('#messageArea').html('<textarea id="message"></textarea><button onclick="saveMessage()">Save</button>')
    mode = 'text';
  }

  function newMessage(data){
    console.log(data)

    var marker = new google.maps.Marker({
      position: data.location,
      map: map,
      animation: google.maps.Animation.DROP,
      icon:'http://i.imgur.com/UYAVMth.png'
    });

    if(data.type != 'image'){
      var infoWindow = new google.maps.InfoWindow({
        content: _.unescape(_.escape(data.message)).split('\n').join('
')

      });
      $('#log').append('
lat '+data.location.lat+' lng '+data.location.lng+''+_.unescape(_.escape(data.message)).split('\n').join('
')+'
')

    } else {
      var infoWindow = new google.maps.InfoWindow({
        content: ''
      });
      $('#log').append('
lat '+data.location.lat+' lng '+data.location.lng+'
')

    }
    marker.addListener('click', function() {
      infoWindow.open(map, marker);
    });

    $('#message'+id).click(function(){
      infoWindow.open(map,marker)
    })
    id+=1;
  }

  function centerMap(location){
    map.setCenter(location);
  }
<commit_msg>fix if user doesn't allow geolocation<commit_after>// This example displays a marker at the center of Australia.
// When the user clicks the marker, an info window opens.
var map, myPos, myMarker, myInfoWindow;
var myFirebaseRef = new Firebase("https://googlemapmessages.firebaseio.com/");
var mode = "text";
var id = 0;

function initMap() {
  var center = {lat: -0, lng: 0};

  map = new google.maps.Map(document.getElementById('map'), {
    zoom: 4,
    center: center,
    disableDefaultUI: true,
    minZoom: 2
  });

  myInfowindow = new google.maps.InfoWindow({map: map});

  myPos = {lat:0,lng:0};
  // Try HTML5 geolocation.
  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(function(position) {
      myPos = {
        lat: position.coords.latitude,
        lng: position.coords.longitude
      };

      myInfowindow.setPosition(myPos);
      myInfowindow.setContent('
TextDraw

<textarea id="message"></textarea><button onclick="saveMessage()">Save</button>
');
      map.setCenter(myPos);
      myMarker = new google.maps.Marker({
        position: myPos,
        map: map,
      });
      myInfowindow.open(map,myMarker);

    }, function() {
      myPos = {
        lat: map.getCenter().lat(),
        lng: map.getCenter().lng()
      };

      myInfowindow.setPosition(myPos);
      myInfowindow.setContent('
TextDraw

<textarea id="message"></textarea><button onclick="saveMessage()">Save</button>
');
      map.setCenter(myPos);
      myMarker = new google.maps.Marker({
        position: myPos,
        map: map,
      });
      myInfowindow.open(map,myMarker);
    });
  } else {
    // Browser doesn't support Geolocation
    handleLocationError(false, myInfowindow, map.getCenter());
  }

  google.maps.event.addListener(map, 'click', function(event) {
    placeMarker(event.latLng);
  });

  myFirebaseRef.on("child_added", function(snapshot) {
    console.log(snapshot.val());
    newMessage(snapshot.val());
  }, function (errorObject) {
    console.log("The read failed: " + errorObject.code);
  });
}

function placeMarker(location) {
  console.log(location)
  myMarker.setMap(null)
  mode = 'text';
  myPos = {lat:location.lat(), lng:location.lng()};

  myMarker = new google.maps.Marker({
    position: myPos,
    map: map,
  });
  myInfowindow = new google.maps.InfoWindow({
    content: '
TextDraw

<textarea id="message"></textarea><button onclick="saveMessage()">Save</button>
'
  });
  myInfowindow.open(map,myMarker);
  document.getElementById('message').focus()

  myMarker.addListener('click', function() {
    myInfowindow.open(map,myMarker);
    document.getElementById('message').focus()
  });
}

function handleLocationError(browserHasGeolocation, infoWindow, pos) {
  infoWindow.setPosition(pos);
  infoWindow.setContent(browserHasGeolocation ?
    'Error: The Geolocation service failed.' :
    'Error: Your browser doesn\'t support geolocation.');
  }

  function saveMessage(){
    var pos = myPos
    if(mode =='text'){
      myFirebaseRef.push({
        type:'text',
        message: _.escape(document.getElementById('message').value),
        location: pos
      });
    } else {
      imageData = $('#simple_sketch')[0].toDataURL('image/png').replace(/^data:image\/(png|jpg);base64,/, "");
      $.ajax({
        url: 'https://api.imgur.com/3/image',
        headers: {
          'Authorization': 'Client-ID a2bb58386e94eb0'
        },
        type: 'POST',
        data: {
          'image': imageData
        },
        success: function(data) { myFirebaseRef.push({
          type:'image',
          message: data.data.link,
          location: pos
        }); }
      });
    }
    myMarker.setMap(null)
  }
  function draw(){
    $('#messageArea').html('<canvas id="simple_sketch" width="300" height="100"></canvas><button onclick="saveMessage()">Save</button>')
    $(function() {
      $('#simple_sketch').sketch();
    });
    mode = 'draw';
  }
  function text(){
    $('#messageArea').html('<textarea id="message"></textarea><button onclick="saveMessage()">Save</button>')
    mode = 'text';
  }

  function newMessage(data){
    console.log(data)

    var marker = new google.maps.Marker({
      position: data.location,
      map: map,
      animation: google.maps.Animation.DROP,
      icon:'http://i.imgur.com/UYAVMth.png'
    });

    if(data.type != 'image'){
      var infoWindow = new google.maps.InfoWindow({
        content: _.unescape(_.escape(data.message)).split('\n').join('
')

      });
      $('#log').append('
lat '+data.location.lat+' lng '+data.location.lng+''+_.unescape(_.escape(data.message)).split('\n').join('
')+'
')

    } else {
      var infoWindow = new google.maps.InfoWindow({
        content: ''
      });
      $('#log').append('
lat '+data.location.lat+' lng '+data.location.lng+'
')

    }
    marker.addListener('click', function() {
      infoWindow.open(map, marker);
    });

    $('#message'+id).click(function(){
      infoWindow.open(map,marker)
    })
    id+=1;
  }

  function centerMap(location){
    map.setCenter(location);
  }
<|endoftext|>


<commit_before>var mapstraction;
var geocoder;
var address;
var locs = [];
var dates = [];
function initialize() {
  mapstraction = new Mapstraction('map_canvas','google');
  mapstraction.setCenterAndZoom(new LatLonPoint(50,0), 3);
  geocoder = new MapstractionGeocoder(geocode_return, 'google');
  mapstraction.addControls({pan:true,zoom:'small',map_type:true});
  var x = document.getElementById('upcoming');
  var rows = x.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
  for(var i=0;i<rows.length;i++){
    var loc = rows[i].getElementsByTagName('td')[2];
    dates.push(rows[i].getElementsByTagName('td')[0].innerHTML);
    var o = rows[i].innerHTML;
    geocoder.geocode({address:loc.innerHTML},o);
  }
  $('#upcoming').tablesorter({sortList:[[0,0]]});
  $('#past').tablesorter({sortList:[[0,0]]});
}

function geocode_return(geocoded_location,o) {
  var marker = new Marker(geocoded_location.point);
  marker.setInfoBubble('
'+o.replace(/td>/g,'li>')+'
');
  mapstraction.addMarker(marker);
}

window.addEventListener('load',function(event){
  initialize();
},false);
<commit_msg>bug 668322 duh. new column changes order of location<commit_after>var mapstraction;
var geocoder;
var address;
var locs = [];
var dates = [];
function initialize() {
  mapstraction = new Mapstraction('map_canvas','google');
  mapstraction.setCenterAndZoom(new LatLonPoint(50,0), 3);
  geocoder = new MapstractionGeocoder(geocode_return, 'google');
  mapstraction.addControls({pan:true,zoom:'small',map_type:true});
  var x = document.getElementById('upcoming');
  var rows = x.getElementsByTagName('tbody')[0].getElementsByTagName('tr');
  for(var i=0;i<rows.length;i++){
    var loc = rows[i].getElementsByTagName('td')[3];
    dates.push(rows[i].getElementsByTagName('td')[0].innerHTML);
    var o = rows[i].innerHTML;
    geocoder.geocode({address:loc.innerHTML},o);
  }
  $('#upcoming').tablesorter({sortList:[[0,0]]});
  $('#past').tablesorter({sortList:[[0,0]]});
}

function geocode_return(geocoded_location,o) {
  var marker = new Marker(geocoded_location.point);
  marker.setInfoBubble('
'+o.replace(/td>/g,'li>')+'
');
  mapstraction.addMarker(marker);
}

window.addEventListener('load',function(event){
  initialize();
},false);
<|endoftext|>


<commit_before>// require esphinx/support/jquery
// require esphinx/support/ajax
// require esphinx/support/string
// require esphinx/support/array

"use strict";

var
    jQuery,
    Ajax,
    esPhinx;

(function ($) {

    $.prototype.autocomplete = function (nodeObject, options, callback) {

        const
            CSS_CLASS = "esphinx ui";

        var
            self = this,
            ajax = Ajax,
            nonCharacterKeysPattern = new RegExp(esPhinx
                .nonCharacterKeysPattern()),

            inline = false,
            remote = false,
            offlineEventLinked = false,

            resolveAmountChar = function (options) {
                if (options.afterAmountChar) {
                    return options.afterAmountChar;
                } else {
                    return 1;
                }

                return
            },

            map = function (textBox, nodeText, nodeTextAsArr) {
                var
                    textBoxContentArr = textBox.value().toLowerCase().trim()
                        .split(" "),
                    mapped = {};

                if (matches(textBoxContentArr, nodeText)) {
                    textBoxContentArr.forEach(function (value) {
                        nodeTextAsArr.pieceIndex(value)
                            .forEach(function (i) {
                            // spanize on iterator
                            // mapped[i] = spanize(value);
                            mapped[i] = value;
                        });
                    });

                    return mapped;
                }

                return false;
            },

            matches = function (textBoxContentAsArr, comparatedText) {
                var
                    i = 0,
                    count = 0,
                    searchIndex;

                while (true) {
                    searchIndex = comparatedText.search(textBoxContentAsArr[i]);
                    if (searchIndex !== -1) {
                        count += 1;
                    }

                    i += 1;
                    if (i === textBoxContentAsArr.length) {
                        break;
                    }

                }

                if (count === textBoxContentAsArr.length) {
                    return true;
                }

                return false;
            },

            resolveAnswer = function (nodeCollection, order = "desc") {
            // resolveAnswer = function (nodeCollection, order) {
                // if (order !== "desc") {order = "asc";}
                var
                    found = {nodes: $(), maps: []},
                    nodesFound = $(),
                    maps = [],
                    tagName = nodeCollection.tagName().toLowerCase(),
                    mapped,
                    composed,
                    nodeText,
                    nodeTextAsArr;

                nodeCollection.childNodes().sort(order).each(function (node) {
                    nodeText = $(node).text().toLowerCase().trim();
                    nodeTextAsArr = nodeText.split(" ");
                    mapped = map(self, nodeText, nodeTextAsArr);
                    if (mapped) {
                        // composed = composeMatch(mapped, nodeText,
                        //     nodeTextAsArr);
                        // debugger
                        // found.concat(true, composeName(composed, node));

                        found.nodes.push(node);
                        found.maps.push(mapped);
                    }

                });

                return found;
            },

            offlineSearch = function (nodeObject, options) {
                var
                    amountChar = resolveAmountChar(options),
                    resolvedAnswer;

                if (!offlineEventLinked) {
                    offlineEventLinked = true;
                    self.on("keyup", function (e) {
                        if (self.value()) {
                            if (self.value().length >= amountChar
                                && !nonCharacterKeysPattern.test(e.key)
                                && !remote) {
                                inline = true;
                            } else {
                                inline = false;
                            }
                            resolvedAnswer = resolveAnswer(nodeObject,
                                options.order);
                            callback.call(self, resolvedAnswer.nodes,
                                resolvedAnswer.maps, e);
                        } else {
                            callback.call(self, $(), e);
                        }
                    });
                }
            },

            remoteSearch = function (options) {
                var
                    amountChar = resolveAmountChar(options),
                    nodeObject,
                    params,
                    resolvedAnswer;

                self.on("keyup", function (e) {
                    if (self.value().length === amountChar
                        && !nonCharacterKeysPattern.test(e.key)
                        && !inline) {

                        if (options.remote) {
                            $(e.target).on("keypress", function (e) {
                                e.preventDefault();
                            });

                            if (options.remote.params) {
                                params = options.remote.params.call(self);
                            }
                            if (!remote) {
                                remote = true;
                                ajax.new(options.remote.url.call(self), {
                                    params: params,
                                    complete: function () {
                                        // debugger
                                        remote = false;
                                        $(e.target).off("keypress");
                                    },
                                    success: function (a) {
                                        nodeObject = $(a);
                                        resolvedAnswer = resolveAnswer(
                                            nodeObject, options.order);
                                        // debugger
                                        callback.call(self,
                                            resolvedAnswer.nodes,
                                            resolvedAnswer.maps, e);
                                        if (nodeObject.length) {
                                            // debugger
                                            offlineSearch(nodeObject, options);
                                        }
                                    }
                                })
                                .processing(function (xhr) {
                                    if (options.remote.processing) {
                                        options.remote.processing(xhr, e);
                                    }
                                });
                            }
                        }
                    } else if (self.value().length > amountChar) {
                        remote = false;
                    }
                });
            };

        // init
        if (nodeObject.constructor !== Object) {
            offlineSearch(nodeObject, options);
        } else {
            options = nodeObject;
            remoteSearch(options);
        }
    };

})(esPhinx);
<commit_msg>improves autocomplete<commit_after>// require esphinx/support/jquery
// require esphinx/support/ajax
// require esphinx/support/string
// require esphinx/support/array

"use strict";

var
    jQuery,
    Ajax,
    esPhinx;

(function ($) {

    $.prototype.autocomplete = function (nodeObject, options, callback) {

        const
            CSS_CLASS = "esphinx ui";

        var
            self = this,
            ajax = Ajax,
            nonCharacterKeysPattern = new RegExp(esPhinx
                .nonCharacterKeysPattern()),

            inline = false,
            remote = false,
            offlineEventLinked = false,

            resolveAmountChar = function (options) {
                if (options.afterAmountChar) {
                    return options.afterAmountChar;
                } else {
                    return 1;
                }

                return
            },

            map = function (searchTextBox, nodeText, nodeTextAsArr) {
                var
                    textBoxContentArr = searchTextBox.value().toLowerCase()
                        .trim().split(" "),
                    mapped = {};

                if (matches(textBoxContentArr, nodeText)) {
                    textBoxContentArr.forEach(function (value) {
                        nodeTextAsArr.pieceIndex(value)
                            .forEach(function (i) {
                            mapped[i] = value;
                        });
                    });

                    return mapped;
                }

                return false;
            },

            matches = function (textBoxContentAsArr, comparatedText) {
                var
                    i = 0,
                    count = 0,
                    searchIndex;

                while (true) {
                    searchIndex = comparatedText.search(textBoxContentAsArr[i]);
                    if (searchIndex !== -1) {
                        count += 1;
                    }

                    i += 1;
                    if (i === textBoxContentAsArr.length) {
                        break;
                    }

                }

                if (count === textBoxContentAsArr.length) {
                    return true;
                }

                return false;
            },

            resolveAnswer = function (nodeCollection, order = "desc") {
            // resolveAnswer = function (nodeCollection, order) {
                // if (order !== "desc") {order = "asc";}
                var
                    found = {nodes: $(), maps: []},
                    nodeText,
                    mapped,
                    nodeTextAsArr;

                nodeCollection.childNodes().sort(order).each(function (node) {
                    nodeText = $(node).text().toLowerCase().trim();
                    nodeTextAsArr = nodeText.split(" ");
                    mapped = map(self, nodeText, nodeTextAsArr);
                    if (mapped) {
                        // composed = composeMatch(mapped, nodeText,
                        //     nodeTextAsArr);
                        // debugger
                        // found.concat(true, composeName(composed, node));

                        found.nodes.push(node);
                        found.maps.push(mapped);
                    }

                });

                return found;
            },

            offlineSearch = function (nodeObject, options) {
                var
                    amountChar = resolveAmountChar(options),
                    resolvedAnswer;

                if (!offlineEventLinked) {
                    offlineEventLinked = true;
                    self.on("keyup", function (e) {
                        if (self.value()) {
                            if (self.value().length >= amountChar
                                && !nonCharacterKeysPattern.test(e.key)
                                && !remote) {
                                inline = true;
                            } else {
                                inline = false;
                            }
                            resolvedAnswer = resolveAnswer(nodeObject,
                                options.order);
                            callback.call(self, resolvedAnswer.nodes,
                                resolvedAnswer.maps, e);
                        } else {
                            callback.call(self, $(), e);
                        }
                    });
                }
            },

            remoteSearch = function (options) {
                var
                    amountChar = resolveAmountChar(options),
                    nodeObject,
                    params,
                    resolvedAnswer;

                self.on("keyup", function (e) {
                    if (self.value().length === amountChar
                        && !nonCharacterKeysPattern.test(e.key)
                        && !inline) {

                        if (options.remote) {
                            $(e.target).on("keypress", function (e) {
                                e.preventDefault();
                            });

                            if (options.remote.params) {
                                params = options.remote.params.call(self);
                            }
                            if (!remote) {
                                remote = true;
                                ajax.new(options.remote.url.call(self), {
                                    params: params,
                                    complete: function () {
                                        // debugger
                                        remote = false;
                                        $(e.target).off("keypress");
                                    },
                                    success: function (a) {
                                        nodeObject = $(a);
                                        resolvedAnswer = resolveAnswer(
                                            nodeObject, options.order);
                                        // debugger
                                        callback.call(self,
                                            resolvedAnswer.nodes,
                                            resolvedAnswer.maps, e);
                                        if (nodeObject.length) {
                                            // debugger
                                            offlineSearch(nodeObject, options);
                                        }
                                    }
                                })
                                .processing(function (xhr) {
                                    if (options.remote.processing) {
                                        options.remote.processing(xhr, e);
                                    }
                                });
                            }
                        }
                    } else if (self.value().length > amountChar) {
                        remote = false;
                    }
                });
            };

        // init
        if (nodeObject.constructor !== Object) {
            offlineSearch(nodeObject, options);
        } else {
            options = nodeObject;
            remoteSearch(options);
        }
    };

})(esPhinx);
<|endoftext|>


<commit_before>var connect    = require("connect") ;
var path       = require("path") ;
var fs         = require("fs") ;
var qs         = require("querystring") ;

var sys        = require("sys") ;
var exec       = require("child_process").exec ;

// CONSTANTS
var LOG_VERBOSE = false ;

// get process id
var pid        = process.getgid() ;

var log = function(message) {

    var clrBlack     = "\x1b[30m" ; // Black
    var clrGrey      = "\x1b[90m" ; // Grey
    var clrLightGrey = "\x1b[37m" ; // Light Grey
    var clrWhite     = "\x1b[39m" ; // White
    var clrRed       = "\x1b[31m" ; // Red
    var clrGreen     = "\x1b[32m" ; // Green
    var clrBlue      = "\x1b[34m" ; // Blue
    var clrYellow    = "\x1b[33m" ; // Yellow
    var clrViolet    = "\x1b[35m" ; // Violet
    var clrCyan      = "\x1b[36m" ; // Cyan

    console.log(clrGrey + pid + ":" + clrLightGrey + message) ;
}

// commandline must contain a project name
var project      = process.argv[2] || process.exit(1) ;

// set the port to listen for http traffic on
//    : use 8888 as default if none provided
var port         = process.argv[3] || 8888 ;

// set the port to listen for github hooks on
//    : use next incremental port number if none provided
var gitHookPort  = process.argv[4] || 1 + port * 1 ;

// documentRoot is the folder http content is served from.
var documentRoot = path.join(__dirname, project) ;

log("pageserver.js") ;

// verify documentRoot exists
fs.stat(documentRoot, function(err, stats) {

    if (stats && stats.isDirectory()) {

        // The folder exists
        // launch static page http daemon
        connect.createServer(
            connect.logger({ format: "\x1b[35m" + project + ":\x1b[37m :remote-addr :method :status :url :response-time" })
          , connect.compress()
          , connect.static(documentRoot)
        ).listen(port) ;
        log("static content serving from " + documentRoot ) ;
        log("http on " + port ) ;

        // launch github webhook api listener
        connect.createServer(
            connect.favicon()
          , connect.logger({ format: "\x1b[31mgithub:\x1b[39m :remote-addr :method :status :url :response-time" })
          , connect.bodyParser()
          , function(request, response) {
              var postReceiveMessage = JSON.parse(request.body.payload || {} ) ;
              LOG_VERBOSE && log(JSON.stringify(postReceiveMessage)) ;
              if (postReceiveMessage.repository.name !== project) {
                  response.writeHead(404, {
                      "Content-Type": "text/plain"
                  });
                  response.write("404 Not Found\n") ;
                  response.end() ;
              } else {
                  log("githook trigger for " + postReceiveMessage.repository.name) ;
                  process.chdir(documentRoot) ;
                  child = exec("git pull", function (error, stdout, stderr) {
                    LOG_VERBOSE && log("stdout: " + stdout) ;
                    LOG_VERBOSE && log("stderr: " + stderr) ;
                    if (error !== null) {
                        log("exec error: " + error) ;
                    } else {
                        log(postReceiveMessage.repository.name + " updated") ;
                    } ;
                  }) ;
                  process.chdir(__dirname) ;
              }
            }
        ).listen(gitHookPort) ;
        log("githook listener on " + gitHookPort ) ;

    } else {
        log("\x1b[31mInvalid project:\x1b[39m" + project ) ;
    }
}) ; <commit_msg>minor edits<commit_after>var connect    = require("connect") ;
var path       = require("path") ;
var fs         = require("fs") ;
var qs         = require("querystring") ;

var sys        = require("sys") ;
var exec       = require("child_process").exec ;

// CONSTANTS
var LOG_VERBOSE = true ;

// get process id
var pid        = process.getgid() ;

var log = function(message) {

    var clrBlack     = "\x1b[30m" ; // Black
    var clrGrey      = "\x1b[90m" ; // Grey
    var clrLightGrey = "\x1b[37m" ; // Light Grey
    var clrWhite     = "\x1b[39m" ; // White
    var clrRed       = "\x1b[31m" ; // Red
    var clrGreen     = "\x1b[32m" ; // Green
    var clrBlue      = "\x1b[34m" ; // Blue
    var clrYellow    = "\x1b[33m" ; // Yellow
    var clrViolet    = "\x1b[35m" ; // Violet
    var clrCyan      = "\x1b[36m" ; // Cyan

    console.log(clrGrey + pid + ":" + clrLightGrey + message) ;
}

// commandline must contain a project name
var project      = process.argv[2] || process.exit(1) ;

// set the port to listen for http traffic on
//    : use 8888 as default if none provided
var port         = process.argv[3] || 8888 ;

// set the port to listen for github hooks on
//    : use next incremental port number if none provided
var gitHookPort  = process.argv[4] || 1 + port * 1 ;

var workspace = path.resolve(__dirname, '..') ;

// documentRoot is the folder http content is served from.
var documentRoot = path.join(workspace, project) ;

log("pageserver.js") ;

// verify documentRoot exists
fs.stat(documentRoot, function(err, stats) {

    if (stats && stats.isDirectory()) {

        // The folder exists
        // launch static page http daemon
        connect.createServer(
            connect.logger({ format: "\x1b[35m" + project + ":\x1b[37m :remote-addr :method :status :url :response-time" })
          , connect.compress()
          , connect.static(documentRoot)
        ).listen(port) ;
        log("static content serving from " + documentRoot ) ;
        log("http on " + port ) ;

        // launch github webhook api listener
        connect.createServer(
            connect.favicon()
          , connect.logger({ format: "\x1b[31mgithub:\x1b[39m :remote-addr :method :status :url :response-time" })
          , connect.bodyParser()
          , function(request, response) {
              var postReceiveMessage = JSON.parse(request.body.payload || {} ) ;
              LOG_VERBOSE && log(JSON.stringify(postReceiveMessage)) ;
              if (postReceiveMessage.repository.name !== project) {
                  response.writeHead(404, {
                      "Content-Type": "text/plain"
                  });
                  response.write("404 Not Found\n") ;
                  response.end() ;
              } else {
                  log("githook trigger for " + postReceiveMessage.repository.name) ;
                  process.chdir(documentRoot) ;
                  child = exec("git pull", function (error, stdout, stderr) {
                    LOG_VERBOSE && log("stdout: " + stdout) ;
                    LOG_VERBOSE && log("stderr: " + stderr) ;
                    if (error !== null) {
                        log("exec error: " + error) ;
                    } else {
                        log(postReceiveMessage.repository.name + " updated") ;
                    } ;
                  }) ;
                  process.chdir(__dirname) ;
              }
            }
        ).listen(gitHookPort) ;
        log("githook listener on " + gitHookPort ) ;

    } else {
        log("\x1b[31mInvalid project:\x1b[39m" + project + " : " + documentRoot) ;
    }
}) ; <|endoftext|>