<commit_before>'use strict';
const commander = require('commander');
const fs = require('fs');
const _ = require('lodash');
const moment = require('moment');
const {min, max, floor, ceil} = Math;

commander
    .option('--source [path]', '(required) Source tsv file')
    .option('--output [path]', 'Output file path (default: stdout)')
    .option('--start [date]', '(required) Start date (e.g, 2017-04-01)')
    .option('--end [date]', '(required) End date (e.g., 2017-05-01)')
    .parse(process.argv);

if (!commander.source || !commander.start || !commander.end) {
    process.stderr.write(commander.helpInformation());
    process.exit(1);
}

const sourcePath = commander.source;
const outputPath = commander.output;
const startDate = commander.start;
const endDate = commander.end;

const source = loadTsv(sourcePath);

const timelines = convertToTimeline(source, startDate, endDate);

const outstr = convertToTsv(timelines);

if (outputPath) {
    fs.writeFileSync(outputPath, outstr);
    console.log(`${outputPath} was created`);
} else {
    console.log(outstr);
}

function loadTsv (path) {
    const contents = fs.readFileSync(path, 'utf8');
    const lines = contents.split('\n').filter(x => x).map(line => line.split('\t'));
    const header = lines.shift();
    return lines.map(line => _.zipObject(header, line));
}

function convertToTimeline (src, startDate, endDate) {
    const taskIds = _.chain(src).map('taskId').uniq().value();
    const timelines = {}; // timelines[taskId][elapsed hour] = continuous work time
    const startMoment = moment(startDate);
    const endMoment = moment(endDate);
    const duration = endMoment.diff(startMoment, 'hours') + 1;

    taskIds.forEach(taskId => {
        const works = _.sortBy(src.filter(work => work.taskId === taskId), 'startTime');
        const timeline = Array(duration).fill(0);

        works.forEach(work => {
            const workStartMoment = moment(work.startTime);
            const workEndMoment = moment(work.endTime);
            const s = floor(max(min(endMoment.diff(workStartMoment, 'seconds') / 60 / 60, duration - 1), 0));
            const e = floor(max(min(endMoment.diff(workEndMoment, 'seconds') / 60 / 60 + 1, duration - 1), 0));
            const e2 = ceil(max(min(endMoment.diff(workEndMoment, 'seconds') / 60 / 60 + 1, duration - 1), 0));
            for (let i = floor(s), lim = ceil(e); i < lim; ++i) {
                timeline[i] += 1;
            }

            const diff = workEndMoment.diff(workStartMoment, 'seconds') / 60 / 60;
            timeline[e2] += diff - floor(diff);
        });

        let sum = 0;
        for (let i = 0; i < duration; ++i) {
            if (timeline[i]) {
                if (i) {
                    timeline[i - 1] = sum;
                }
                sum += timeline[i];
                timeline[i] = sum;
            } else {
                timeline[i] = null;
            }
        }

        timelines[taskId] = timeline;
    });

    return timelines;
}

function convertToTsv (timelines) {
    const taskIds = Object.keys(timelines);
    if (!taskIds.length) { return ''; }

    const lines = [['Days'].concat(taskIds.slice())];
    const n = timelines[taskIds[0]].length;

    for (let i = 0; i < n; ++i) {
        const line = taskIds.map(taskId => timelines[taskId][i]);
        const days = floor(i / 24);
        const hours = i % 24;
        line.unshift(`${days}:${hours}`);
        lines.push(line);
    }

    return lines.map(line => line.join('\t')).join('\n');
}
<commit_msg>add filter of work timeline generator<commit_after>'use strict';
const commander = require('commander');
const fs = require('fs');
const _ = require('lodash');
const moment = require('moment');
const {min, max, floor, ceil} = Math;
const db = require('../../../lib/schemes');

commander
    .option('--source [path]', '(required) Source tsv file')
    .option('--output [path]', 'Output file path (default: stdout)')
    .option('--start [date]', '(required) Start date (e.g, 2017-04-01)')
    .option('--end [date]', '(required) End date (e.g., 2017-05-01)')
    .parse(process.argv);

if (!commander.source || !commander.start || !commander.end) {
    process.stderr.write(commander.helpInformation());
    process.exit(1);
}

main(commander)
    .then(() => {
        console.log('Completed.\n');
        process.exit(0);
    })
    .catch(e => {
        console.error(e);
        process.exit(1);
    });

async function main ({source: sourcePath, output: outputPath, start: startDate, end: endDate}) {
    const works = loadTsv(sourcePath);

    await expandWorks(works);

    const usernames = _.uniq(works.map(x => x.user.username));
    const costValues = _.uniq(works.map(x => x.cost.value));

    for (let username of usernames) {
        for (let costValue of costValues) {
            const filteredWorks = works.filter(x => x.user.username === username && x.cost.value === costValue);
            if (!filteredWorks.length) { continue; }

            const timelines = convertToTimeline(filteredWorks, startDate, endDate);

            const outstr = convertToTsv(timelines);

            if (outputPath) {
                const matched = outputPath.match(/(.*)\.(\w+)$/);
                let path;
                if (matched) {
                    path = `${matched[1]}_${username}_${costValue}.${matched[2]}`;
                } else {
                    path = `${outputPath}_${username}_${costValue}`;
                }

                fs.writeFileSync(path, outstr);
                console.log(`${path} was created`);
            } else {
                console.log(outstr);
            }
        }
    }
}

async function expandWorks (works) {
    const memoTasks = {};
    const memoUsers = {};
    const memoCosts = {};

    for (let work of works) {
        const {taskId, userId} = work;

        let task = memoTasks[taskId];
        if (!task) {
            task = (await db.Task.findOne({where: {id: taskId}})).toJSON();
            memoTasks[taskId] = task;
        }

        let user = memoUsers[userId];
        if (!user) {
            user = (await db.User.findOne({where: {id: userId}})).toJSON();
            memoUsers[userId] = user;
        }

        const costId = task.costId;
        let cost = memoCosts[costId];
        if (!cost) {
            cost = (await db.Cost.findOne({where: {id: costId}})).toJSON();
            memoCosts[costId] = cost;
        }

        work.task = task;
        work.user = user;
        work.cost = cost;
    }
}

function loadTsv (path) {
    const contents = fs.readFileSync(path, 'utf8');
    const lines = contents.split('\n').filter(x => x).map(line => line.split('\t'));
    const header = lines.shift();
    return lines.map(line => _.zipObject(header, line));
}

function convertToTimeline (src, startDate, endDate) {
    const taskIds = _.chain(src).map('taskId').uniq().value();
    const timelines = {}; // timelines[taskId][elapsed hour] = continuous work time
    const startMoment = moment(startDate);
    const endMoment = moment(endDate);
    const duration = endMoment.diff(startMoment, 'hours') + 1;

    taskIds.forEach(taskId => {
        const works = _.sortBy(src.filter(work => work.taskId === taskId), 'startTime');
        const timeline = Array(duration).fill(0);

        works.forEach(work => {
            const workStartMoment = moment(work.startTime);
            const workEndMoment = moment(work.endTime);
            const s = floor(max(min(endMoment.diff(workStartMoment, 'seconds') / 60 / 60, duration - 1), 0));
            const e = floor(max(min(endMoment.diff(workEndMoment, 'seconds') / 60 / 60 + 1, duration - 1), 0));
            const e2 = ceil(max(min(endMoment.diff(workEndMoment, 'seconds') / 60 / 60 + 1, duration - 1), 0));
            for (let i = floor(s), lim = ceil(e); i < lim; ++i) {
                timeline[i] += 1;
            }

            const diff = workEndMoment.diff(workStartMoment, 'seconds') / 60 / 60;
            timeline[e2] += diff - floor(diff);
        });

        let sum = 0;
        for (let i = 0; i < duration; ++i) {
            if (timeline[i]) {
                if (i) {
                    timeline[i - 1] = sum;
                }
                sum += timeline[i];
                timeline[i] = sum;
            } else {
                timeline[i] = null;
            }
        }

        timelines[taskId] = timeline;
    });

    return timelines;
}

function convertToTsv (timelines) {
    const taskIds = Object.keys(timelines);
    if (!taskIds.length) { return ''; }

    const lines = [['Days'].concat(taskIds.slice())];
    const n = timelines[taskIds[0]].length;

    for (let i = 0; i < n; ++i) {
        const line = taskIds.map(taskId => timelines[taskId][i]);
        const days = floor(i / 24);
        const hours = i % 24;
        line.unshift(`${days}:${hours}`);
        lines.push(line);
    }

    return lines.map(line => line.join('\t')).join('\n');
}
<|endoftext|>


<commit_before>/**
 * @fileOverview Apply the middleware pattern to a given Object.
 */

var __ = require('lodash');
var Promise = require('bluebird');

var middlewarify = module.exports = {};

var noopMidd = function(cb) {if (__.isFunction(cb)) cb();};

/** @enum {string} middleware types */
middlewarify.Type = {
  BEFORE: 'before',
  AFTER: 'after',
  USE: 'use',
};

/**
 * Apply the middleware pattern to the provided object's propert.
 *
 * @param {Object} obj An Object.
 * @param {string} prop The property to apply the middleware pattern on.
 * @param {Function=} optFinalCb Last middleware to call.
 * @param {Object=} optParams Optional parameters.
 *   @param {boolean=} beforeAfter set to true to add Before/After hooks
 *     instead of the single use hook.
 */
middlewarify.make = function(obj, prop, optFinalCb, optParams) {

  var middObj = Object.create(null);
  middObj.mainCallback = noopMidd;

  /**
   * The default parameters object.
   *
   * @type {Object}
   */
  var defaultParams = {
    beforeAfter: false,
  };

  if (__.isFunction(optFinalCb)) {
    middObj.mainCallback = optFinalCb;
  }

  var params;
  if (__.isObject(optFinalCb)) {
    params = optFinalCb;
  }
  if (__.isObject(optParams)) {
    params = optParams;
  }
  middObj.params = __.extend(defaultParams, params);

  obj[prop] = middlewarify._invokeMiddleware.bind(null, middObj);

  if (middObj.params.beforeAfter) {
    middObj.beforeMidds = [];
    middObj.afterMidds = [];
    obj[prop].before = middlewarify._use.bind(null, middObj, middlewarify.Type.BEFORE);
    obj[prop].after = middlewarify._use.bind(null, middObj, middlewarify.Type.AFTER);
  } else {
    middObj.midds = [];
    obj[prop].use = middlewarify._use.bind(null, middObj, middlewarify.Type.USE);
  }
};

/**
 * Invokes all the middleware.
 * @param  {Object} middObj Internal midd object.
 * @param  {*...} varArgs Any number of arguments
 * @param  {Function=} optCb last argument is callback
 * @return {Object} the -master- callback using done(fn).
 * @private
 */
middlewarify._invokeMiddleware = function(middObj) {
  var args = Array.prototype.slice.call(arguments, 1);
  return new Promise(function(resolve, reject) {
    var midds;
    if (middObj.params.beforeAfter) {
      midds = Array.prototype.slice.call(middObj.beforeMidds);
      midds.push(middObj.mainCallback);
      midds = midds.concat(middObj.afterMidds);
    } else {
      midds = Array.prototype.slice.call(middObj.midds);
      midds.push(middObj.mainCallback);
    }
    middlewarify._fetchAndInvoke(midds, args, middObj.params, resolve, reject);
  });
};

/**
 * Fetch a middleware ensuring FIFO and invoke it.
 *
 * @param {Array.<Function>} midds The array with the middleware.
 * @param {Array} args An array of arbitrary arguments, can be empty.
 * @param {Object} params Parameters passed by the user.
 * @param {Function} resolve resolving Callback.
 * @param {Function} reject rejecting Callback.
 * @private
 */
middlewarify._fetchAndInvoke = function(midds, args, params, resolve, reject) {
  if (0 === midds.length) {
    return resolve();
  }

  var midd = midds.shift();

  var arity = midd.length;
  var argsLen = args.length;
  /** @type {boolean} User defined callback */
  var hasCb = false;

  // check if there's a callback defined, be explicit expect arity
  // to be args.length + 1
  if (arity - argsLen === 1) {
    hasCb = true;
  }

  function userCb(err) {
    if (err) {
      reject(err);
    } else {
      middlewarify._fetchAndInvoke(midds, args, params, resolve, reject);
    }
  }

  var invokeArgs = Array.prototype.slice.call(args);

  if (hasCb) {
    invokeArgs.push(userCb);
  }

  try {
    var maybePromise = midd.apply(null, invokeArgs);
    if (hasCb) {
      return;
    }

    if (Promise.is(maybePromise)) {
      return maybePromise.then(function() {
        middlewarify._fetchAndInvoke(midds, args, params, resolve, reject);
      }, function(err) {
        reject(err);
      });
    }

    // it is a synchronous middleware
    middlewarify._fetchAndInvoke(midds, args, params, resolve, reject);
  } catch(ex) {
    reject(ex);
  }
};

/**
 * Add middleware.
 *
 * @param {Object} middObj Internal midd object.
 * @param {middlewarify.Type} middType Middleware type.
 * @param {Function|Array.<Function>...} Any combination of function containers.
 * @private
 */
middlewarify._use = function(middObj, middType) {
  var middlewares = Array.prototype.slice.call(arguments, 2);

  var len = middlewares.length;
  if (0 === len) return;

  function pushMidd(fn) {
    switch(middType) {
    case middlewarify.Type.BEFORE:
      middObj.beforeMidds.push(fn);
      break;
    case middlewarify.Type.AFTER:
      middObj.afterMidds.push(fn);
      break;
    case middlewarify.Type.USE:
      middObj.midds.push(fn);
      break;
    }
  }

  middlewares.forEach(function(middleware) {
    if (Array.isArray(middleware)) {
      middleware.forEach(function(argFn) {
        if (__.isFunction(argFn)) {
          pushMidd(argFn);
        }
      });
    } else if (__.isFunction(middleware)) {
      pushMidd(middleware);
    }
  });
};
<commit_msg>Optimization<commit_after>/**
 * @fileOverview Apply the middleware pattern to a given Object.
 */

var __ = require('lodash');
var Promise = require('bluebird');

var middlewarify = module.exports = {};

var noopMidd = function(cb) {if (__.isFunction(cb)) cb();};

/** @enum {string} middleware types */
middlewarify.Type = {
  BEFORE: 'before',
  AFTER: 'after',
  USE: 'use',
};

/**
 * Apply the middleware pattern to the provided object's propert.
 *
 * @param {Object} obj An Object.
 * @param {string} prop The property to apply the middleware pattern on.
 * @param {Function=} optFinalCb Last middleware to call.
 * @param {Object=} optParams Optional parameters.
 *   @param {boolean=} beforeAfter set to true to add Before/After hooks
 *     instead of the single use hook.
 */
middlewarify.make = function(obj, prop, optFinalCb, optParams) {

  var middObj = Object.create(null);
  middObj.mainCallback = noopMidd;

  /**
   * The default parameters object.
   *
   * @type {Object}
   */
  var defaultParams = {
    beforeAfter: false,
  };

  if (__.isFunction(optFinalCb)) {
    middObj.mainCallback = optFinalCb;
  }

  var params;
  if (__.isObject(optFinalCb)) {
    params = optFinalCb;
  }
  if (__.isObject(optParams)) {
    params = optParams;
  }
  middObj.params = __.extend(defaultParams, params);

  obj[prop] = middlewarify._invokeMiddleware.bind(null, middObj);

  if (middObj.params.beforeAfter) {
    middObj.beforeMidds = [];
    middObj.afterMidds = [];
    obj[prop].before = middlewarify._use.bind(null, middObj, middlewarify.Type.BEFORE);
    obj[prop].after = middlewarify._use.bind(null, middObj, middlewarify.Type.AFTER);
  } else {
    middObj.midds = [];
    obj[prop].use = middlewarify._use.bind(null, middObj, middlewarify.Type.USE);
  }
};

/**
 * Invokes all the middleware.
 * @param  {Object} middObj Internal midd object.
 * @param  {*...} varArgs Any number of arguments
 * @param  {Function=} optCb last argument is callback
 * @return {Object} the -master- callback using done(fn).
 * @private
 */
middlewarify._invokeMiddleware = function(middObj) {
  var args = Array.prototype.slice.call(arguments, 1);
  return new Promise(function(resolve, reject) {
    var deferred = Promise.defer();
    deferred.promise.then(resolve, reject);
    var midds;
    if (middObj.params.beforeAfter) {
      midds = Array.prototype.slice.call(middObj.beforeMidds);
      midds.push(middObj.mainCallback);
      midds = midds.concat(middObj.afterMidds);
    } else {
      midds = Array.prototype.slice.call(middObj.midds);
      midds.push(middObj.mainCallback);
    }
    middlewarify._fetchAndInvoke(midds, args, deferred);
  });
};

/**
 * Fetch a middleware ensuring FIFO and invoke it.
 *
 * @param {Array.<Function>} midds The array with the middleware.
 * @param {Array} args An array of arbitrary arguments, can be empty.
 * @param {Promise.Defer} deferred Deferred object.
 * @private
 */
middlewarify._fetchAndInvoke = function(midds, args, deferred) {
  if (midds.length === 0) {
    return deferred.resolve();
  }

  var midd = midds.shift();

  var arity = midd.length;
  var argsLen = args.length;
  /** @type {boolean} User defined callback */
  var hasCb = false;

  // check if there's a callback defined, be explicit expect arity
  // to be args.length + 1
  if (arity - argsLen === 1) {
    hasCb = true;
  }

  function userCb(err) {
    if (err) {
      deferred.reject(err);
    } else {
      middlewarify._fetchAndInvoke(midds, args, deferred);
    }
  }

  var invokeArgs = Array.prototype.slice.call(args);

  if (hasCb) {
    invokeArgs.push(userCb);
  }

  middlewarify._invoke(midd, invokeArgs, function(err) {
    if (err) {
      return deferred.reject(err);
    }
    if (!hasCb) {
      middlewarify._fetchAndInvoke(midds, args, deferred);
    }
  });
};

/**
 * The actual invocation of the middleware happens here.
 *
 * @param {Function} midd The middleware to invoke.
 * @param {Array} invokeArgs Arguments to invoke middleware with.
 * @param {Function(Error=)} cb callback.
 * @private
 */
middlewarify._invoke = function(midd, invokeArgs, cb) {
  try {
    var maybePromise = midd.apply(null, invokeArgs);
    if (Promise.is(maybePromise)) {
      return maybePromise.then(cb, function(err) {
        cb(err || new Error());
      });
    }
    cb();
  } catch(ex) {
    cb(ex);
  }
};

/**
 * Add middleware.
 *
 * @param {Object} middObj Internal midd object.
 * @param {middlewarify.Type} middType Middleware type.
 * @param {Function|Array.<Function>...} Any combination of function containers.
 * @private
 */
middlewarify._use = function(middObj, middType) {
  var middlewares = Array.prototype.slice.call(arguments, 2);

  var len = middlewares.length;
  if (0 === len) return;

  function pushMidd(fn) {
    switch(middType) {
    case middlewarify.Type.BEFORE:
      middObj.beforeMidds.push(fn);
      break;
    case middlewarify.Type.AFTER:
      middObj.afterMidds.push(fn);
      break;
    case middlewarify.Type.USE:
      middObj.midds.push(fn);
      break;
    }
  }

  middlewares.forEach(function(middleware) {
    if (Array.isArray(middleware)) {
      middleware.forEach(function(argFn) {
        if (__.isFunction(argFn)) {
          pushMidd(argFn);
        }
      });
    } else if (__.isFunction(middleware)) {
      pushMidd(middleware);
    }
  });
};
<|endoftext|>


<commit_before>import React, {
	Component
} from 'react';

import '../../style/index/list.scss';

export default class ListComponent extends Component {
	constructor(props) {
		super(props);
		// this.state = {
		// 	isLayin: props.isLayin
		// };
		// this.handleTouch = this.handleTouch.bind(this);
	}
	componentDidMount() {
		// console.log(this.props.isLayin);
		// this.setState({
		// 	isLayin: this.props.isLayin
		// });
	}
	stop(event) {
		event.stopPropagation();
	}
	switchList() {
		// this.setState((prevState) => ({
		// 	isLayin: prevState.isLayin
		// }));
	}
	handleTouch(index) {
		// this.props.restart(index);
		// console.log(index);
		console.log('2');
	}
	render() {
		let className = 'list-component aside ';
		if (this.props.isLayin) {
			className += 'slide-in';
		} else {
			className += 'slide-out';
		}
		return (

					{this.props.items.map((item, index) => {
						return

										{item.title}

					})}

				{this.props.items.length <= 0 &&

播放列表为空~

尝试把音乐文件拖拽进来吧

				}

		);
	}
}<commit_msg>bind(this, index)<commit_after>import React, {
	Component
} from 'react';

import '../../style/index/list.scss';

export default class ListComponent extends Component {
	constructor(props) {
		super(props);
		// this.state = {
		// 	isLayin: props.isLayin
		// };
	}
	componentDidMount() {
		// console.log(this.props.isLayin);
		// this.setState({
		// 	isLayin: this.props.isLayin
		// });
	}
	stop(event) {
		event.stopPropagation();
	}
	switchList() {
		// this.setState((prevState) => ({
		// 	isLayin: prevState.isLayin
		// }));
	}
	handleTouch(index) {
		this.props.restart(index);
	}
	render() {
		let className = 'list-component aside ';
		if (this.props.isLayin) {
			className += 'slide-in';
		} else {
			className += 'slide-out';
		}
		return (

					{this.props.items.map((item, index) => {
						return

										{item.title}

					})}

				{this.props.items.length <= 0 &&

播放列表为空~

尝试把音乐文件拖拽进来吧

				}

		);
	}
}<|endoftext|>


<commit_before>/* global angular, $, google */

'use strict';

var directives = angular.module('directives', []);

/**
 * parallax directive. Logic to move a parallax effect into an angular directive
   Example:

*/
directives.directive('parallax', ['$window', '$timeout', function($window, $timeout) {

    return {
        restrict: 'A',
        link: function(scope) {
            var windowWidth = $(window).width(),
                MOBILE_WIDTH = 760,
                FixedHeader;

            function resetValues() {
                $('article').find('.progress-bar').css('width', '0%');
            }

            function skillsHandler() {
                var section3Top = $('#skills').offset().top,
                    $article = $('.skills-section').find('article').find('.progress-bar');

                if ($(document).scrollTop() >= section3Top) {
                    $article.each(function() {
                        $(this).css('width', $(this).find('span').text());
                    });
                }
            }

            function languagesHandler() {
                var section6Top = $('#languages').offset().top,
                    $article = $('.languages-section').find('article').find('.progress-bar');
                if ($(document).scrollTop() >= section6Top) {
                    $article.each(function() {
                        $(this).css('width', $(this).find('span').text());
                    });
                }
            }

            function photographHandler(scroll) {
                var $photograph = $('#photograph'),
                    $document = $(document),
                    startPhotograph = $('#experience').offset().top / 5,
                    endPhotograph = $('#skills').offset().top - ($('#experience').offset().top / 2);

                if (windowWidth <= MOBILE_WIDTH) {
                    return;
                }

                if (scroll && $photograph.hasClass('photograph')) {
                    $photograph.css('visibility', 'visible');
                    $photograph.removeClass('photograph');
                    $photograph.addClass('photographFixed');

                } else if (!scroll && $photograph.hasClass('photographFixed')) {
                    $photograph.removeClass('photographFixed');
                    $photograph.addClass('photograph');
                }

                if (($document.scrollTop() >= startPhotograph) && ($document.scrollTop() <= endPhotograph)) {
                    $('#photograph img').addClass('fade-in');
                    $('#photograph img').removeClass('fade-out');
                } else {
                    $('#photograph img').addClass('fade-out');
                    $('#photograph img').removeClass('fade-in');
                }
            }

            /* Scroll the background layers */
            function parallaxScroll() {
                /*var scrolled = $(window).scrollTop();
                $('#parallax-bg1').css('top', (0 - (scrolled * 0.25)) + 'px');
                $('#parallax-bg2').css('top', (0 - (scrolled * 0.5)) + 'px');
                $('#parallax-bg3').css('top', (0 - (scrolled * 0.75)) + 'px');*/
            }

            /* Set navigation dots to an active state as the user scrolls */
            function redrawDotNav() {
                var section1Top = 0;
                // The top of each section is offset by half the distance to the previous section.
                var section2Top = $('#experience').offset().top;
                var section3Top = $('#skills').offset().top;
                var section4Top = $('#training').offset().top;
                var section5Top = $('#languages').offset().top;
                var section6Top = $('#contact').offset().top;

                $('nav#primary a').removeClass('active');
                $('#main-nav li').removeClass('current_page_item');

                if ($(document).scrollTop() >= section1Top && $(document).scrollTop() <= section1Top) {
                    $('nav#primary a.main').addClass('active');
                    $('#main-nav li.menu-item-main').addClass('current_page_item');
                } else if ($(document).scrollTop() >= section2Top && $(document).scrollTop() < section3Top) {
                    $('nav#primary a.experience').addClass('active');
                    $('#main-nav li.menu-item-experience').addClass('current_page_item');
                } else if ($(document).scrollTop() >= section3Top && $(document).scrollTop() < section4Top) {
                    $('nav#primary a.skills').addClass('active');
                    $('#main-nav li.menu-item-skills').addClass('current_page_item');
                } else if ($(document).scrollTop() >= section4Top && $(document).scrollTop() < section5Top) {
                    $('nav#primary a.training').addClass('active');
                    $('#main-nav li.menu-item-training').addClass('current_page_item');
                } else if ($(document).scrollTop() >= section5Top && $(document).scrollTop() < section6Top) {
                    $('nav#primary a.languages').addClass('active');
                    $('#main-nav li.menu-item-languages').addClass('current_page_item');
                } else if ($(document).scrollTop() >= section6Top) {
                    $('nav#primary a.contact').addClass('active');
                    $('#main-nav li.menu-item-contact').addClass('current_page_item');
                }

            }

            function _onScroll() {
                parallaxScroll();
                redrawDotNav();
            }

            // Fixed Header
            FixedHeader = {
                init: function() {
                    this.headerHeight = $('#header hgroup').outerHeight() - $('#nav-bar').outerHeight();
                    if ($('body').hasClass('ie')) {
                        $('html, body').addClass('iefix');
                    }

                    $(window).scroll(this.activate);

                },
                activate: function() {
                    if ($(window).scrollTop() <= FixedHeader.headerHeight) {
                        FixedHeader.scrollDisabled();
                    } else {
                        FixedHeader.scrollEnabled();
                    }
                },
                scrollDisabled: function() {
                    $('#nav-bar').removeClass('fixed-nav-bar');
                    $('body').removeClass('fixed-header-on');
                    photographHandler(false);
                    resetValues();

                },
                scrollEnabled: function() {
                    $('#nav-bar').addClass('fixed-nav-bar');
                    $('body').addClass('fixed-header-on');
                    photographHandler(true);
                    skillsHandler();
                    languagesHandler();
                }
            };

            function hideMenu() {
                if (windowWidth > MOBILE_WIDTH) {
                    return;
                }

                $('#main-nav').fadeOut();
                $('#wrapper #top-nav').hide();
                $('body #menu-icon').removeClass('active');
            }

            function setSectionAbsolutePositions() {
                var sections = ['experience', 'skills', 'training', 'languages', 'contact'],
                    totalHeight = 0,
                    height = 0,
                    i = 0,
                    j;

                $timeout(function() {

                    for (j = 1; j <= sections.length; j++) {
                        height = $('#' + sections[i]).outerHeight() + totalHeight;
                        $('#' + sections[j]).css('top', height);
                        totalHeight = height;
                        i += 1;
                    }

                    $('body').css('height', totalHeight + $('#header').outerHeight());

                }, 0);
            }

            /* Main Menu */
            $('body #menu-icon').click(function(event) {
                event.preventDefault();
                $('#main-nav').fadeToggle();
                $('#wrapper #top-nav').hide();
                $(this).toggleClass('active');
            });

            /* Next/prev and primary nav btn click handlers */
            $('a.main').click(function() {
                hideMenu();
                $('html, body').animate({
                    scrollTop: 0
                }, 1000, function() {
                    parallaxScroll(); // Callback is required for iOS
                });
                return false;
            });
            $('a.experience').click(function() {
                hideMenu();
                $('html, body').animate({
                    scrollTop: $('#experience').offset().top
                }, 1000, function() {
                    parallaxScroll();
                });
                return false;
            });
            $('a.skills').click(function() {
                hideMenu();
                $('html, body').animate({
                    scrollTop: $('#skills').offset().top
                }, 1000, function() {
                    parallaxScroll();
                });
                return false;
            });
            $('a.training').click(function() {
                hideMenu();
                $('html, body').animate({
                    scrollTop: $('#training').offset().top
                }, 1000, function() {
                    parallaxScroll();
                });
                return false;
            });
            $('a.languages').click(function() {
                hideMenu();
                $('html, body').animate({
                    scrollTop: $('#languages').offset().top
                }, 1000, function() {
                    parallaxScroll();
                });
                return false;
            });
            $('a.contact').click(function() {
                hideMenu();
                $('html, body').animate({
                    scrollTop: $('#contact').offset().top
                }, 1000, function() {
                    parallaxScroll();
                });
                return false;
            });

            /* Show/hide dot lav labels on hover */
            $('nav#primary a').hover(
                function() {
                    $(this).prev('h1').show();
                },
                function() {
                    $(this).prev('h1').hide();
                }
            );

            /* Scroll event handler */
            $window.addEventListener('scroll', _onScroll);

            function init() {
                setSectionAbsolutePositions();
                redrawDotNav();
                FixedHeader.init();
            }

            scope.$watch('cvData', function(value) {
                if (value) {
                    init();
                }
            }, true);

        }
    };
}]);

/**
 * background directive. It Preloads a background image
   Just call to the directive in the HTML tag you want to show a background
*/

directives.directive('background', function ($q) {
    return {
        restrict: 'A',
        link: function(scope, element) {
            var urlBase = '../../images/',
                images = ['background1.jpg', 'background2.png', 'background4.jpg'],
                num = Math.floor(Math.random() * images.length),
                randomImage = images[num],
                backgroundImage = urlBase + randomImage;

            scope.preload = function(url) {
                var deffered = $q.defer(),
                    image = new Image();

                image.src = url;

                if (image.complete) {

                    deffered.resolve();

                } else {

                    image.addEventListener('load', function() {
                        deffered.resolve();
                    });

                    image.addEventListener('error', function() {
                        deffered.reject();
                    });
                }

                return deffered.promise;
            };

            scope.preload(backgroundImage).then(function() {
                element.css({
                    'background-image': 'url("' + backgroundImage + '")'
                });
                element.fadeIn();
            });
        }
    };
});

/**
 * include templates directive
   Example:
   <includetmpl template="page.html"></includetmpl>
   <includetmpl template="page.html" ng-show="true"></includetmpl>
*/

directives.directive('includetmpl', ['$compile', '$http', '$templateCache', function($compile, $http, $templateCache) {

    return {
        restrict: 'E',
        link: function(scope, element, attrs) {
            var tmpl,
                tplURL = attrs.template,
                templateLoader = $http.get(tplURL, {
                    cache: $templateCache
                });

            templateLoader.success(function(html) {
                tmpl = $compile(html)(scope);
                element.empty();
                element.append(tmpl);
            });
        }
    };
}]);

/**
 * googleMaps directive
   optional map-options param: object to extend the maps options. See all availble options in https://developers.google.com/maps/documentation/javascript/
   optional markers param: objects array with markers info. Every object has this properties
        {
            city: '',
            desc: '',
            lat: 41.3133735,     // Latitude
            long: -71.0571571    // Longitude
        }
   Example:

*/
directives.directive('googleMaps', ['$parse', function($parse) {

    return {
        restrict: 'A',
        template: '

',
        link: function(scope, element, attrs) {
            var i,
                cities = $parse(attrs.markers)(scope) || [],
                mapOptions = $parse(attrs.mapOptions)(scope) || {},
                mapOptionsDefaults = {
                    zoom: 1,
                    center: new google.maps.LatLng(40.0000, -66.0000), //39.4107137,-66.6334351,4.75z
                    mapTypeId: google.maps.MapTypeId.TERRAIN,
                    streetViewControl: false,
                    mapTypeControl: false
                },
                markers = [],
                infoWindow = new google.maps.InfoWindow();

            angular.extend(mapOptionsDefaults, mapOptions);

            scope.map = new google.maps.Map(document.getElementById('map'), mapOptionsDefaults);

            scope.openInfoWindow = function(e, selectedMarker) {
                e.preventDefault();
                google.maps.event.trigger(selectedMarker, 'click');
            };

            function createMarker(info) {
                var marker = new google.maps.Marker({
                    map: scope.map,
                    position: new google.maps.LatLng(info.lat, info.long),
                    title: info.city
                });
                marker.content = '
' + info.desc + '
';

                google.maps.event.addListener(marker, 'click', function() {
                    infoWindow.setContent('
' + marker.title + '
' + marker.content);
                    infoWindow.open(scope.map, marker);
                });

                markers.push(marker);

            }

            for (i = 0; i < cities.length; i++) {
                createMarker(cities[i]);
            }
        }
    };
}]);

/**
 * animatedPhoneDiv directive

   Example:

*/
directives.directive('animatedPhoneDiv', ['$timeout', function($timeout) {

    return {
        restrict: 'A',
        template: '
' +
            '
' +
            '

' +
            '
' +
            '

' +
            '
' +
            '
' +
            '
',
        link: function(scope, element) {

            function addContent(model) {
                var content = '';

                angular.forEach(model.personalData.phones, function(phone) {
                    content += '' + phone + '
';
                });

                element.find('#phone-wrapper').html(content);
            }

            function addAnimate() {
                $timeout(function() {
                    $('.phone-link').attr('onclick', 'document.querySelector("#flip-toggle").classList.toggle("hover")');
                }, 0);
            }

            scope.$watch('cvData', function(value) {
                if (value) {
                    addContent(value);
                    addAnimate();
                }
            }, true);

        }
    };
}]);
<commit_msg>FIX error in dots position calculation<commit_after>/* global angular, $, google */

'use strict';

var directives = angular.module('directives', []);

/**
 * parallax directive. Logic to move a parallax effect into an angular directive
   Example:

*/
directives.directive('parallax', ['$window', '$timeout', function($window, $timeout) {

    return {
        restrict: 'A',
        link: function(scope) {
            var windowWidth = $(window).width(),
                MOBILE_WIDTH = 760,
                FixedHeader;

            function resetValues() {
                $('article').find('.progress-bar').css('width', '0%');
            }

            function skillsHandler() {
                var section3Top = $('#skills').offset().top,
                    $article = $('.skills-section').find('article').find('.progress-bar');

                if ($(document).scrollTop() >= section3Top) {
                    $article.each(function() {
                        $(this).css('width', $(this).find('span').text());
                    });
                }
            }

            function languagesHandler() {
                var section6Top = $('#languages').offset().top,
                    $article = $('.languages-section').find('article').find('.progress-bar');
                if ($(document).scrollTop() >= section6Top) {
                    $article.each(function() {
                        $(this).css('width', $(this).find('span').text());
                    });
                }
            }

            function photographHandler(scroll) {
                var $photograph = $('#photograph'),
                    $document = $(document),
                    startPhotograph = $('#experience').offset().top / 5,
                    endPhotograph = $('#skills').offset().top - ($('#experience').offset().top / 2);

                if (windowWidth <= MOBILE_WIDTH) {
                    return;
                }

                if (scroll && $photograph.hasClass('photograph')) {
                    $photograph.css('visibility', 'visible');
                    $photograph.removeClass('photograph');
                    $photograph.addClass('photographFixed');

                } else if (!scroll && $photograph.hasClass('photographFixed')) {
                    $photograph.removeClass('photographFixed');
                    $photograph.addClass('photograph');
                }

                if (($document.scrollTop() >= startPhotograph) && ($document.scrollTop() <= endPhotograph)) {
                    $('#photograph img').addClass('fade-in');
                    $('#photograph img').removeClass('fade-out');
                } else {
                    $('#photograph img').addClass('fade-out');
                    $('#photograph img').removeClass('fade-in');
                }
            }

            /* Set navigation dots to an active state as the user scrolls */
            function redrawDotNav() {
                var section1Top = 0;
                // The top of each section is offset by half the distance to the previous section.
                var section2Top = $('#experience').offset().top - 1;
                var section3Top = $('#skills').offset().top - 1;
                var section4Top = $('#training').offset().top - 1;
                var section5Top = $('#languages').offset().top - 1;
                var section6Top = $('#contact').offset().top - 1;

                $('nav#primary a').removeClass('active');
                $('#main-nav li').removeClass('current_page_item');

                if ($(document).scrollTop() >= section1Top && $(document).scrollTop() <= section1Top) {
                    $('nav#primary a.main').addClass('active');
                    $('#main-nav li.menu-item-main').addClass('current_page_item');
                } else if ($(document).scrollTop() >= section2Top && $(document).scrollTop() < section3Top) {
                    $('nav#primary a.experience').addClass('active');
                    $('#main-nav li.menu-item-experience').addClass('current_page_item');
                } else if ($(document).scrollTop() >= section3Top && $(document).scrollTop() < section4Top) {
                    $('nav#primary a.skills').addClass('active');
                    $('#main-nav li.menu-item-skills').addClass('current_page_item');
                } else if ($(document).scrollTop() >= section4Top && $(document).scrollTop() < section5Top) {
                    $('nav#primary a.training').addClass('active');
                    $('#main-nav li.menu-item-training').addClass('current_page_item');
                } else if ($(document).scrollTop() >= section5Top && $(document).scrollTop() < section6Top) {
                    $('nav#primary a.languages').addClass('active');
                    $('#main-nav li.menu-item-languages').addClass('current_page_item');
                } else if ($(document).scrollTop() >= section6Top) {
                    $('nav#primary a.contact').addClass('active');
                    $('#main-nav li.menu-item-contact').addClass('current_page_item');
                }

            }

            function _onScroll() {
                redrawDotNav();
            }

            // Fixed Header
            FixedHeader = {
                init: function() {
                    this.headerHeight = $('#header hgroup').outerHeight() - $('#nav-bar').outerHeight();
                    if ($('body').hasClass('ie')) {
                        $('html, body').addClass('iefix');
                    }

                    $(window).scroll(this.activate);

                },
                activate: function() {
                    if ($(window).scrollTop() <= FixedHeader.headerHeight) {
                        FixedHeader.scrollDisabled();
                    } else {
                        FixedHeader.scrollEnabled();
                    }
                },
                scrollDisabled: function() {
                    $('#nav-bar').removeClass('fixed-nav-bar');
                    $('body').removeClass('fixed-header-on');
                    photographHandler(false);
                    resetValues();

                },
                scrollEnabled: function() {
                    $('#nav-bar').addClass('fixed-nav-bar');
                    $('body').addClass('fixed-header-on');
                    photographHandler(true);
                    skillsHandler();
                    languagesHandler();
                }
            };

            function hideMenu() {
                if (windowWidth > MOBILE_WIDTH) {
                    return;
                }

                $('#main-nav').fadeOut();
                $('#wrapper #top-nav').hide();
                $('body #menu-icon').removeClass('active');
            }

            function setSectionAbsolutePositions() {
                var sections = ['experience', 'skills', 'training', 'languages', 'contact'],
                    totalHeight = 0,
                    height = 0,
                    i = 0,
                    j;

                $timeout(function() {

                    for (j = 1; j <= sections.length; j++) {
                        height = $('#' + sections[i]).outerHeight() + totalHeight;
                        $('#' + sections[j]).css('top', height);
                        totalHeight = height;
                        i += 1;
                    }

                    $('body').css('height', totalHeight + $('#header').outerHeight());

                }, 0);
            }

            /* Main Menu */
            $('body #menu-icon').click(function(event) {
                event.preventDefault();
                $('#main-nav').fadeToggle();
                $('#wrapper #top-nav').hide();
                $(this).toggleClass('active');
            });

            /* Next/prev and primary nav btn click handlers */
            $('a.main').click(function() {
                hideMenu();
                $('html, body').animate({
                    scrollTop: 0
                }, 1000);
                return false;
            });
            $('a.experience').click(function() {
                hideMenu();
                $('html, body').animate({
                    scrollTop: $('#experience').offset().top
                }, 1000);
                return false;
            });
            $('a.skills').click(function() {
                hideMenu();
                $('html, body').animate({
                    scrollTop: $('#skills').offset().top
                }, 1000);
                return false;
            });
            $('a.training').click(function() {
                hideMenu();
                $('html, body').animate({
                    scrollTop: $('#training').offset().top
                }, 1000);
                return false;
            });
            $('a.languages').click(function() {
                hideMenu();
                $('html, body').animate({
                    scrollTop: $('#languages').offset().top
                }, 1000);
                return false;
            });
            $('a.contact').click(function() {
                hideMenu();
                $('html, body').animate({
                    scrollTop: $('#contact').offset().top
                }, 1000);
                return false;
            });

            /* Show/hide dot lav labels on hover */
            $('nav#primary a').hover(
                function() {
                    $(this).prev('h1').show();
                },
                function() {
                    $(this).prev('h1').hide();
                }
            );

            /* Scroll event handler */
            $window.addEventListener('scroll', _onScroll);

            function init() {
                setSectionAbsolutePositions();
                redrawDotNav();
                FixedHeader.init();
            }

            scope.$watch('cvData', function(value) {
                if (value) {
                    init();
                }
            }, true);

        }
    };
}]);

/**
 * background directive. It Preloads a background image
   Just call to the directive in the HTML tag you want to show a background
*/

directives.directive('background', function ($q) {
    return {
        restrict: 'A',
        link: function(scope, element) {
            var urlBase = '../../images/',
                images = ['background1.jpg', 'background2.png', 'background4.jpg'],
                num = Math.floor(Math.random() * images.length),
                randomImage = images[num],
                backgroundImage = urlBase + randomImage;

            scope.preload = function(url) {
                var deffered = $q.defer(),
                    image = new Image();

                image.src = url;

                if (image.complete) {

                    deffered.resolve();

                } else {

                    image.addEventListener('load', function() {
                        deffered.resolve();
                    });

                    image.addEventListener('error', function() {
                        deffered.reject();
                    });
                }

                return deffered.promise;
            };

            scope.preload(backgroundImage).then(function() {
                element.css({
                    'background-image': 'url("' + backgroundImage + '")'
                });
                element.fadeIn();
            });
        }
    };
});

/**
 * include templates directive
   Example:
   <includetmpl template="page.html"></includetmpl>
   <includetmpl template="page.html" ng-show="true"></includetmpl>
*/

directives.directive('includetmpl', ['$compile', '$http', '$templateCache', function($compile, $http, $templateCache) {

    return {
        restrict: 'E',
        link: function(scope, element, attrs) {
            var tmpl,
                tplURL = attrs.template,
                templateLoader = $http.get(tplURL, {
                    cache: $templateCache
                });

            templateLoader.success(function(html) {
                tmpl = $compile(html)(scope);
                element.empty();
                element.append(tmpl);
            });
        }
    };
}]);

/**
 * googleMaps directive
   optional map-options param: object to extend the maps options. See all availble options in https://developers.google.com/maps/documentation/javascript/
   optional markers param: objects array with markers info. Every object has this properties
        {
            city: '',
            desc: '',
            lat: 41.3133735,     // Latitude
            long: -71.0571571    // Longitude
        }
   Example:

*/
directives.directive('googleMaps', ['$parse', function($parse) {

    return {
        restrict: 'A',
        template: '

',
        link: function(scope, element, attrs) {
            var i,
                cities = $parse(attrs.markers)(scope) || [],
                mapOptions = $parse(attrs.mapOptions)(scope) || {},
                mapOptionsDefaults = {
                    zoom: 1,
                    center: new google.maps.LatLng(40.0000, -66.0000), //39.4107137,-66.6334351,4.75z
                    mapTypeId: google.maps.MapTypeId.TERRAIN,
                    streetViewControl: false,
                    mapTypeControl: false
                },
                markers = [],
                infoWindow = new google.maps.InfoWindow();

            angular.extend(mapOptionsDefaults, mapOptions);

            scope.map = new google.maps.Map(document.getElementById('map'), mapOptionsDefaults);

            scope.openInfoWindow = function(e, selectedMarker) {
                e.preventDefault();
                google.maps.event.trigger(selectedMarker, 'click');
            };

            function createMarker(info) {
                var marker = new google.maps.Marker({
                    map: scope.map,
                    position: new google.maps.LatLng(info.lat, info.long),
                    title: info.city
                });
                marker.content = '
' + info.desc + '
';

                google.maps.event.addListener(marker, 'click', function() {
                    infoWindow.setContent('
' + marker.title + '
' + marker.content);
                    infoWindow.open(scope.map, marker);
                });

                markers.push(marker);

            }

            for (i = 0; i < cities.length; i++) {
                createMarker(cities[i]);
            }
        }
    };
}]);

/**
 * animatedPhoneDiv directive

   Example:

*/
directives.directive('animatedPhoneDiv', ['$timeout', function($timeout) {

    return {
        restrict: 'A',
        template: '
' +
            '
' +
            '

' +
            '
' +
            '

' +
            '
' +
            '
' +
            '
',
        link: function(scope, element) {

            function addContent(model) {
                var content = '';

                angular.forEach(model.personalData.phones, function(phone) {
                    content += '' + phone + '
';
                });

                element.find('#phone-wrapper').html(content);
            }

            function addAnimate() {
                $timeout(function() {
                    $('.phone-link').attr('onclick', 'document.querySelector("#flip-toggle").classList.toggle("hover")');
                }, 0);
            }

            scope.$watch('cvData', function(value) {
                if (value) {
                    addContent(value);
                    addAnimate();
                }
            }, true);

        }
    };
}]);
<|endoftext|>


<commit_before>odoo.define('web.Registry', function (require) {
"use strict";

var Class = require('web.Class');

/**
 * The registry is really pretty much only a mapping from some keys to some
 * values. The Registry class only add a few simple methods around that to make
 * it nicer and slightly safer.
 *
 * Note that registries have a fundamental problem: the value that you try to
 * get in a registry might not have been added yet, so of course, you need to
 * make sure that your dependencies are solid.  For this reason, it is a good
 * practice to avoid using the registry if you can simply import what you need
 * with the 'require' statement.
 *
 * However, on the flip side, sometimes you cannot just simply import something
 * because we would have a dependency cycle.  In that case, registries might
 * help.
 */
var Registry = Class.extend({
    /**
     * @constructor
     * @param {Object} [mapping] the initial data in the registry
     */
    init: function (mapping) {
        this.map = Object.create(mapping || null);
        this._scoreMapping = Object.create(null);
        this._sortedKeys = null;
        this.listeners = []; // listening callbacks on newly added items.
    },

    //--------------------------------------------------------------------------
    // Public
    //--------------------------------------------------------------------------

    /**
     * Add a key (and a value) to the registry.
     *
     * Notify the listeners on newly added item in the registry.
     *
     * @param {string} key
     * @param {any} value
     * @param {[number]} score if given, this value will be used to order keys
     * @returns {Registry} can be used to chain add calls.
     */
    add: function (key, value, score) {
        this._scoreMapping[key] = score === undefined ? key : score;
        this._sortedKeys = null;
        this.map[key] = value;
        _.each(this.listeners, function (callback) {
            callback(key, value);
        });
        return this;
    },
    /**
     * Check if the registry contains the key
     *
     * @param {string} key
     * @returns {boolean}
     */
    contains: function (key) {
        return (key in this.map);
    },
    /**
     * Returns the content of the registry (an object mapping keys to values)
     *
     * @returns {Object}
     */
    entries: function () {
        return Object.create(this.map);
    },
    /**
     * Returns the value associated to the given key.
     *
     * @param {string} key
     * @returns {any}
     */
    get: function (key) {
        return this.map[key];
    },
    /**
     * Tries a number of keys, and returns the first object matching one of
     * the keys.
     *
     * @param {string[]} keys a sequence of keys to fetch the object for
     * @returns {any} the first result found matching an object
     */
    getAny: function (keys) {
        for (var i=0; i<keys.length; i++) {
            if (keys[i] in this.map) {
                return this.map[keys[i]];
            }
        }
        return null;
    },
    /**
     * Return the list of keys in map object.
     *
     * The registry guarantees that the keys have a consistent order, defined by
     * the 'score' value when the item has been added.
     *
     * @returns {string[]}
     */
    keys: function () {
        var self = this;
        if (!this._sortedKeys) {
            this._sortedKeys = _.sortBy(Object.keys(this.map), function (key) {
                return self._scoreMapping[key] || 0;
            });
        }
        return this._sortedKeys;
    },
    /**
     * Register a callback to execute when items are added to the registry.
     *
     * @param {function} callback function with parameters (key, value).
     */
    onAdd: function (callback) {
        this.listeners.push(callback);
    },
    /**
     * Return the list of values in map object
     *
     * @returns {string[]}
     */
    values: function () {
        var self = this;
        return this.keys().map(function (key) {
            return self.map[key];
        });
    },
});

return Registry;

});

<commit_msg>[FIX] web: allow to build the doc<commit_after>odoo.define('web.Registry', function (require) {
"use strict";

var Class = require('web.Class');

/**
 * The registry is really pretty much only a mapping from some keys to some
 * values. The Registry class only add a few simple methods around that to make
 * it nicer and slightly safer.
 *
 * Note that registries have a fundamental problem: the value that you try to
 * get in a registry might not have been added yet, so of course, you need to
 * make sure that your dependencies are solid.  For this reason, it is a good
 * practice to avoid using the registry if you can simply import what you need
 * with the 'require' statement.
 *
 * However, on the flip side, sometimes you cannot just simply import something
 * because we would have a dependency cycle.  In that case, registries might
 * help.
 */
var Registry = Class.extend({
    /**
     * @constructor
     * @param {Object} [mapping] the initial data in the registry
     */
    init: function (mapping) {
        this.map = Object.create(mapping || null);
        this._scoreMapping = Object.create(null);
        this._sortedKeys = null;
        this.listeners = []; // listening callbacks on newly added items.
    },

    //--------------------------------------------------------------------------
    // Public
    //--------------------------------------------------------------------------

    /**
     * Add a key (and a value) to the registry.
     *
     * Notify the listeners on newly added item in the registry.
     *
     * @param {string} key
     * @param {any} value
     * @param {number} [score] if given, this value will be used to order keys
     * @returns {Registry} can be used to chain add calls.
     */
    add: function (key, value, score) {
        this._scoreMapping[key] = score === undefined ? key : score;
        this._sortedKeys = null;
        this.map[key] = value;
        _.each(this.listeners, function (callback) {
            callback(key, value);
        });
        return this;
    },
    /**
     * Check if the registry contains the key
     *
     * @param {string} key
     * @returns {boolean}
     */
    contains: function (key) {
        return (key in this.map);
    },
    /**
     * Returns the content of the registry (an object mapping keys to values)
     *
     * @returns {Object}
     */
    entries: function () {
        return Object.create(this.map);
    },
    /**
     * Returns the value associated to the given key.
     *
     * @param {string} key
     * @returns {any}
     */
    get: function (key) {
        return this.map[key];
    },
    /**
     * Tries a number of keys, and returns the first object matching one of
     * the keys.
     *
     * @param {string[]} keys a sequence of keys to fetch the object for
     * @returns {any} the first result found matching an object
     */
    getAny: function (keys) {
        for (var i=0; i<keys.length; i++) {
            if (keys[i] in this.map) {
                return this.map[keys[i]];
            }
        }
        return null;
    },
    /**
     * Return the list of keys in map object.
     *
     * The registry guarantees that the keys have a consistent order, defined by
     * the 'score' value when the item has been added.
     *
     * @returns {string[]}
     */
    keys: function () {
        var self = this;
        if (!this._sortedKeys) {
            this._sortedKeys = _.sortBy(Object.keys(this.map), function (key) {
                return self._scoreMapping[key] || 0;
            });
        }
        return this._sortedKeys;
    },
    /**
     * Register a callback to execute when items are added to the registry.
     *
     * @param {function} callback function with parameters (key, value).
     */
    onAdd: function (callback) {
        this.listeners.push(callback);
    },
    /**
     * Return the list of values in map object
     *
     * @returns {string[]}
     */
    values: function () {
        var self = this;
        return this.keys().map(function (key) {
            return self.map[key];
        });
    },
});

return Registry;

});

<|endoftext|>


<commit_before>/**
    Framework for building object relational database apps
    Copyright (C) 2016  John Rogelstad

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**/

(function (exports) {
  "strict";
  var conn,
    pg = require("pg"),
    controller = require("./controller"),
    readPgConfig = require("./pgconfig"),
    registered = {
      GET: {},
      POST: {},
      PUT: {},
      PATCH: {},
      DELETE: {}
    },
    that = {};

  /**
    Request.

    Example payload:
        {
           "name": "Contact",
           "method": "POST",
           "data": {
             "id": "1f8c8akkptfe",
             "created": "2015-04-26T12:57:57.896Z",
             "createdBy": "admin",
             "updated": "2015-04-26T12:57:57.896Z",
             "updatedBy": "admin",
             "fullName": "John Doe",
             "birthDate": "1970-01-01T00:00:00.000Z",
             "isMarried": true,
             "dependentes": 2
           }
        }

    @param {Object} Payload
    @param {String} [payload.name] Name of feather or function
    @param {String} [payload.method] Method to perform: "GET", "POST",
      "PUT", "PATCH" or "DELETE"
    @param {String} [payload.id] Identifier for "GET", "PATCH" ond "DELETE"
    @param {String} [payload.data] Data for "POST" and "PATCH" or functions
    @param {Object} [payload.client] Database client. If undefined one will
      be intialized by default and wrapped in a transaction if necessary.
    @param {String} [payload.callback] Callback
    @param {Boolean} Bypass authorization checks. Default = false.
    @return receiver
  */
  that.request = function (obj, isSuperUser) {
    isSuperUser = isSuperUser === undefined ? false : isSuperUser;

    var client, done, transaction, connect, isChild,
      doRequest, afterTransaction, afterRequest,
      callback = obj.callback,
      externalClient = false,
      wrap = false;

    connect = function () {
      pg.connect(conn, function (err, c, d) {
        client = c;
        done = d;

        // handle an error from the connection
        if (err) {
          controller.setCurrentUser(undefined);
          console.error("Could not connect to server", err);
          obj.callback(err);
          return;
        }

        doRequest();
      });
    };

    doRequest = function (err) {
      if (err) {
        afterRequest(err);
        return;
      }

      if (!obj.user) {
        obj.callback("User undefined.");
        return;
      }
      client.currentUser = obj.user;

      // If registered function, execute it
      if (typeof registered[obj.method][obj.name] === "function") {
        wrap = !obj.client;
        obj.data = obj.data || {};
        obj.data.id = obj.data.id || obj.id;
        obj.data.client = client;
        transaction = registered[obj.method][obj.name];
        obj = obj.data;

      // Otherwise handle as model
      } else {
        obj.client = client;
        isChild = false;

        switch (obj.method) {
        case "GET":
          obj.callback = afterRequest;
          controller.doSelect(obj, false, isSuperUser);
          return;
        case "POST":
          if (obj.id) {
            transaction = controller.doUpsert;
          } else {
            transaction = controller.doInsert;
          }
          break;
        case "PATCH":
          transaction = controller.doUpdate;
          break;
        case "DELETE":
          transaction = controller.doDelete;
          break;
        default:
          obj.callback("method \"" + obj.method + "\" unknown");
        }
      }

      // Wrap transactions
      if (wrap) {
        obj.callback = afterTransaction;
        client.query("BEGIN;", function (err) {
          if (err) {
            obj.callback(err);
            return;
          }

          transaction(obj, false, isSuperUser);
        });
        return;
      }

      // Passed client must handle its own transaction wrapping
      obj.callback = afterRequest;
      transaction(obj, isChild, isSuperUser);
    };

    afterTransaction = function (err, resp) {
      if (err) {
        client.query("ROLLBACK;", function () {
          afterRequest(err);
        });

        return;
      }

      client.query("COMMIT;", function (err) {
        if (err) {
          afterRequest(err);
          return;
        }

        afterRequest(null, resp);
      });
    };

    afterRequest = function (err, resp) {
      // Passed client will handle it's own connection
      if (!externalClient) { done(); }

      // Format errors into objects that can be handled by server
      if (err) {
        console.error(err);
        if (typeof err === "object") {
          err = {message: err.message, statusCode: err.statusCode || 500};
        } else {
          err = {message: err, statusCode: 500};
        }
        err.isError = true;
        callback(err);
        return;
      }

      // Otherwise return response
      callback(null, resp);
    };

    if (obj.client) {
      externalClient = true;
      client = obj.client;
      doRequest();
      return;
    }

    if (conn) {
      connect();
      return;
    }

    // Read configuration if necessary
    readPgConfig(function (config) {
      conn = "postgres://" +
        config.user + ":" +
        config.password + "@" +
        config.server + "/" +
        config.database;
      connect();
    });

    return this;
  };

  /**
    Register a function that can be called by a method type. Use
    this to expose function calls via `request`. As a rule, all
    functions must accept an object as an argument whose properties
    can be used to calculate the result. The object should be passed
    as `data` on the request.

    The object should include a callback to forward a response on
    completion. The callback should accept an error as the first
    argument and a response as the second.

    The request will automatically append an active client to the object
    to use for executing queries.

      var fn, callback, datasource = require(./datasource);

      // Create a function that queries something
      fn = function (obj) {
        var sql = "SELECT foo FROM bar WHERE id=$1;",
          params = [obj.id];

        obj.client.query(sql, params, function (err, resp) {
          if (err) {
            obj.callback(err);
            return;
          }

          obj.callback(null, resp.rows);
        })
      }

      // Register the function
      datasource.registerFunction("GET", "myQuery", fn);

      // Define a callback to use when calling our function
      callback = function (err, resp) {
        if (err) {
          console.error(err);
          return;
        }

        console.log("Query rows->", resp);
      }

      // Execute a request that calls our function and sends a response
      // via the callback
      datasource.request({
        method: "GET",
        name: "myQuery",
        callback: callback,
        data: {
          id: "HTJ28n"
        }
      });

    @param {String} Function name
    @param {String} Method. "GET", "POST", "PUT", "PATCH", or "DELETE"
    @param {Function} Function
    @return receiver
  */
  that.registerFunction = function (method, name, func) {
    registered[method][name] = func;
    return this;
  };

  /**
    @return {Object} Object listing register functions
  */
  that.registeredFunctions = function () {
    var keys = Object.keys(registered),
      result = {};

    keys.forEach(function (key) {
      result[key] = Object.keys(registered[key]);
    });

    return result;
  };

  // Set properties on exports
  Object.keys(that).forEach(function (key) {
    exports[key] = that[key];
  });

  // Register certain functions
  that.registerFunction("GET", "getAuthorization", controller.getAuthorization);
  that.registerFunction("GET", "getControllers", controller.getControllers);
  that.registerFunction("GET", "getFeather", controller.getFeather);
  that.registerFunction("GET", "getModules", controller.getModules);
  that.registerFunction("GET", "getRoutes", controller.getRoutes);
  that.registerFunction("GET", "getSettings", controller.getSettings);
  that.registerFunction("GET", "getWorkbook", controller.getWorkbook);
  that.registerFunction("GET", "getWorkbooks", controller.getWorkbooks);
  that.registerFunction("GET", "isAuthorized", controller.isAuthorized);
  that.registerFunction("GET", "isSuperUser", controller.isSuperUser);
  that.registerFunction("POST", "doInsert", controller.doInsert);
  that.registerFunction("POST", "doUpsert", controller.doUpsert);
  that.registerFunction("PUT", "saveAuthorization",
    controller.saveAuthorization);
  that.registerFunction("PUT", "saveFeather", controller.saveFeather);
  that.registerFunction("PUT", "saveSettings", controller.saveSettings);
  that.registerFunction("PUT", "setSuperUser", controller.setSuperUser);
  that.registerFunction("PUT", "saveWorkbook", controller.saveWorkbook);
  that.registerFunction("DELETE", "deleteFeather", controller.deleteFeather);
  that.registerFunction("DELETE", "deleteWorkbook", controller.deleteWorkbook);

}(exports));

<commit_msg>Be smarter about inferring user<commit_after>/**
    Framework for building object relational database apps
    Copyright (C) 2016  John Rogelstad

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
**/

(function (exports) {
  "strict";
  var conn,
    pg = require("pg"),
    controller = require("./controller"),
    readPgConfig = require("./pgconfig"),
    registered = {
      GET: {},
      POST: {},
      PUT: {},
      PATCH: {},
      DELETE: {}
    },
    that = {};

  /**
    Request.

    Example payload:
        {
           "name": "Contact",
           "method": "POST",
           "data": {
             "id": "1f8c8akkptfe",
             "created": "2015-04-26T12:57:57.896Z",
             "createdBy": "admin",
             "updated": "2015-04-26T12:57:57.896Z",
             "updatedBy": "admin",
             "fullName": "John Doe",
             "birthDate": "1970-01-01T00:00:00.000Z",
             "isMarried": true,
             "dependentes": 2
           }
        }

    @param {Object} Payload
    @param {String} [payload.name] Name of feather or function
    @param {String} [payload.method] Method to perform: "GET", "POST",
      "PUT", "PATCH" or "DELETE"
    @param {String} [payload.id] Identifier for "GET", "PATCH" ond "DELETE"
    @param {String} [payload.data] Data for "POST" and "PATCH" or functions
    @param {Object} [payload.client] Database client. If undefined one will
      be intialized by default and wrapped in a transaction if necessary.
    @param {String} [payload.callback] Callback
    @param {Boolean} Bypass authorization checks. Default = false.
    @return receiver
  */
  that.request = function (obj, isSuperUser) {
    isSuperUser = isSuperUser === undefined ? false : isSuperUser;

    var client, done, transaction, connect, isChild,
      doRequest, afterTransaction, afterRequest,
      callback = obj.callback,
      externalClient = false,
      wrap = false;

    connect = function () {
      pg.connect(conn, function (err, c, d) {
        client = c;
        done = d;

        // handle an error from the connection
        if (err) {
          controller.setCurrentUser(undefined);
          console.error("Could not connect to server", err);
          obj.callback(err);
          return;
        }

        doRequest();
      });
    };

    doRequest = function (err) {
      if (err) {
        afterRequest(err);
        return;
      }

      if (!client.currentUser && !obj.user) {
        obj.callback("User undefined." + obj.method + obj.name);
        return;
      } else if (!client.currentUser) {
        client.currentUser = obj.user;
      }

      // If registered function, execute it
      if (typeof registered[obj.method][obj.name] === "function") {
        wrap = !obj.client;
        obj.data = obj.data || {};
        obj.data.id = obj.data.id || obj.id;
        obj.data.client = client;
        transaction = registered[obj.method][obj.name];
        obj = obj.data;

      // Otherwise handle as model
      } else {
        obj.client = client;
        isChild = false;

        switch (obj.method) {
        case "GET":
          obj.callback = afterRequest;
          controller.doSelect(obj, false, isSuperUser);
          return;
        case "POST":
          if (obj.id) {
            transaction = controller.doUpsert;
          } else {
            transaction = controller.doInsert;
          }
          break;
        case "PATCH":
          transaction = controller.doUpdate;
          break;
        case "DELETE":
          transaction = controller.doDelete;
          break;
        default:
          obj.callback("method \"" + obj.method + "\" unknown");
        }
      }

      // Wrap transactions
      if (wrap) {
        obj.callback = afterTransaction;
        client.query("BEGIN;", function (err) {
          if (err) {
            obj.callback(err);
            return;
          }

          transaction(obj, false, isSuperUser);
        });
        return;
      }

      // Passed client must handle its own transaction wrapping
      obj.callback = afterRequest;
      transaction(obj, isChild, isSuperUser);
    };

    afterTransaction = function (err, resp) {
      if (err) {
        client.query("ROLLBACK;", function () {
          afterRequest(err);
        });

        return;
      }

      client.query("COMMIT;", function (err) {
        if (err) {
          afterRequest(err);
          return;
        }

        afterRequest(null, resp);
      });
    };

    afterRequest = function (err, resp) {
      // Passed client will handle it's own connection
      if (!externalClient) { done(); }

      // Format errors into objects that can be handled by server
      if (err) {
        console.error(err);
        if (typeof err === "object") {
          err = {message: err.message, statusCode: err.statusCode || 500};
        } else {
          err = {message: err, statusCode: 500};
        }
        err.isError = true;
        callback(err);
        return;
      }

      // Otherwise return response
      callback(null, resp);
    };

    if (obj.client) {
      externalClient = true;
      client = obj.client;
      doRequest();
      return;
    }

    if (conn) {
      connect();
      return;
    }

    // Read configuration if necessary
    readPgConfig(function (config) {
      conn = "postgres://" +
        config.user + ":" +
        config.password + "@" +
        config.server + "/" +
        config.database;
      connect();
    });

    return this;
  };

  /**
    Register a function that can be called by a method type. Use
    this to expose function calls via `request`. As a rule, all
    functions must accept an object as an argument whose properties
    can be used to calculate the result. The object should be passed
    as `data` on the request.

    The object should include a callback to forward a response on
    completion. The callback should accept an error as the first
    argument and a response as the second.

    The request will automatically append an active client to the object
    to use for executing queries.

      var fn, callback, datasource = require(./datasource);

      // Create a function that queries something
      fn = function (obj) {
        var sql = "SELECT foo FROM bar WHERE id=$1;",
          params = [obj.id];

        obj.client.query(sql, params, function (err, resp) {
          if (err) {
            obj.callback(err);
            return;
          }

          obj.callback(null, resp.rows);
        })
      }

      // Register the function
      datasource.registerFunction("GET", "myQuery", fn);

      // Define a callback to use when calling our function
      callback = function (err, resp) {
        if (err) {
          console.error(err);
          return;
        }

        console.log("Query rows->", resp);
      }

      // Execute a request that calls our function and sends a response
      // via the callback
      datasource.request({
        method: "GET",
        name: "myQuery",
        callback: callback,
        data: {
          id: "HTJ28n"
        }
      });

    @param {String} Function name
    @param {String} Method. "GET", "POST", "PUT", "PATCH", or "DELETE"
    @param {Function} Function
    @return receiver
  */
  that.registerFunction = function (method, name, func) {
    registered[method][name] = func;
    return this;
  };

  /**
    @return {Object} Object listing register functions
  */
  that.registeredFunctions = function () {
    var keys = Object.keys(registered),
      result = {};

    keys.forEach(function (key) {
      result[key] = Object.keys(registered[key]);
    });

    return result;
  };

  // Set properties on exports
  Object.keys(that).forEach(function (key) {
    exports[key] = that[key];
  });

  // Register certain functions
  that.registerFunction("GET", "getAuthorization", controller.getAuthorization);
  that.registerFunction("GET", "getControllers", controller.getControllers);
  that.registerFunction("GET", "getFeather", controller.getFeather);
  that.registerFunction("GET", "getModules", controller.getModules);
  that.registerFunction("GET", "getRoutes", controller.getRoutes);
  that.registerFunction("GET", "getSettings", controller.getSettings);
  that.registerFunction("GET", "getWorkbook", controller.getWorkbook);
  that.registerFunction("GET", "getWorkbooks", controller.getWorkbooks);
  that.registerFunction("GET", "isAuthorized", controller.isAuthorized);
  that.registerFunction("GET", "isSuperUser", controller.isSuperUser);
  that.registerFunction("POST", "doInsert", controller.doInsert);
  that.registerFunction("POST", "doUpsert", controller.doUpsert);
  that.registerFunction("PUT", "saveAuthorization",
    controller.saveAuthorization);
  that.registerFunction("PUT", "saveFeather", controller.saveFeather);
  that.registerFunction("PUT", "saveSettings", controller.saveSettings);
  that.registerFunction("PUT", "setSuperUser", controller.setSuperUser);
  that.registerFunction("PUT", "saveWorkbook", controller.saveWorkbook);
  that.registerFunction("DELETE", "deleteFeather", controller.deleteFeather);
  that.registerFunction("DELETE", "deleteWorkbook", controller.deleteWorkbook);

}(exports));

<|endoftext|>


<commit_before>import React from 'react';
import { render } from 'react-dom';
import { combineReducers, createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import header from 'App/components/Header/redux';
import App from 'App/App';

const appReducer = combineReducers({
  header
});

const store = applyMiddleware(thunk)(createStore)(appReducer);

function Demo() {
  return (
    <Provider store={store}>
      <App />
    </Provider>
  );
}

render(
  <Demo />,
  document.getElementById('demo')
);
<commit_msg>Add Promise polyfill to Demo<commit_after>import es6promise from 'es6-promise';
import React from 'react';
import { render } from 'react-dom';
import { combineReducers, createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { Provider } from 'react-redux';
import header from 'App/components/Header/redux';
import App from 'App/App';

es6promise.polyfill(); // Required, because `Promise` is undefined in IE.

const appReducer = combineReducers({
  header
});

const store = applyMiddleware(thunk)(createStore)(appReducer);

function Demo() {
  return (
    <Provider store={store}>
      <App />
    </Provider>
  );
}

render(
  <Demo />,
  document.getElementById('demo')
);
<|endoftext|>


<commit_before>;(function (global) {

if ("EventSource" in global) return;

var reTrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;

var EventSource = function (url) {
  var eventsource = this,
      interval = 500, // polling interval
      lastEventId = null,
      cache = '';

  if (!url || typeof url != 'string') {
    throw new SyntaxError('Not enough arguments');
  }

  this.URL = url;
  this.readyState = this.CONNECTING;
  this._pollTimer = null;
  this._xhr = null;

  function pollAgain(interval) {
    eventsource._pollTimer = setTimeout(function () {
      poll.call(eventsource);
    }, interval);
  }

  function poll() {
    try { // force hiding of the error message... insane?
      if (eventsource.readyState == eventsource.CLOSED) return;

      // NOTE: IE7 and upwards support
      var xhr = new XMLHttpRequest();
      xhr.open('GET', eventsource.URL, true);
      xhr.setRequestHeader('Accept', 'text/event-stream');
      xhr.setRequestHeader('Cache-Control', 'no-cache');
      // we must make use of this on the server side if we're working with Android - because they don't trigger
      // readychange until the server connection is closed
      xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

      if (lastEventId != null) xhr.setRequestHeader('Last-Event-ID', lastEventId);
      cache = '';

      xhr.timeout = 50000;
      xhr.onreadystatechange = function () {
        if ((this.readyState == 3 || this.readyState == 4) && this.status == 200) {
          // on success
          if (eventsource.readyState == eventsource.CONNECTING) {
            eventsource.readyState = eventsource.OPEN;
            eventsource.dispatchEvent('open', { type: 'open' });
          }

          var responseText = '';
          try {
            responseText = this.responseText || '';
          } catch (e) {}

          // process this.responseText
          var parts = responseText.substr(cache.length).split("\n"),
              eventType = 'message',
              data = [],
              i = 0,
              line = '';

          cache = responseText;

          // TODO handle 'event' (for buffer name), retry
          for (; i < parts.length; i++) {
            line = parts[i].replace(reTrim, '');
            if (line.indexOf('event') == 0) {
              eventType = line.replace(/event:?\s*/, '');
            } else if (line.indexOf('retry') == 0) {
              retry = parseInt(line.replace(/retry:?\s*/, ''));
              if(!isNaN(retry)) { interval = retry; }
            } else if (line.indexOf('data') == 0) {
              data.push(line.replace(/data:?\s*/, ''));
            } else if (line.indexOf('id:') == 0) {
              lastEventId = line.replace(/id:?\s*/, '');
            } else if (line.indexOf('id') == 0) { // this resets the id
              lastEventId = null;
            } else if (line == '') {
              if (data.length) {
                var event = new MessageEvent(data.join('\n'), eventsource.url, lastEventId);
                eventsource.dispatchEvent(eventType, event);
                data = [];
                eventType = 'message';
              }
            }
          }

          if (this.readyState == 4) pollAgain(interval);
          // don't need to poll again, because we're long-loading
        } else if (eventsource.readyState !== eventsource.CLOSED) {
          if (this.readyState == 4) { // and some other status
            // dispatch error
            eventsource.readyState = eventsource.CONNECTING;
            eventsource.dispatchEvent('error', { type: 'error' });
            pollAgain(interval);
          } else if (this.readyState == 0) { // likely aborted
            pollAgain(interval);
          } else {
          }
        }
      };

      xhr.send();

      setTimeout(function () {
        if (true || xhr.readyState == 3) xhr.abort();
      }, xhr.timeout);

      eventsource._xhr = xhr;

    } catch (e) { // in an attempt to silence the errors
      eventsource.dispatchEvent('error', { type: 'error', data: e.message }); // ???
    }
  };

  poll(); // init now
};

EventSource.prototype = {
  close: function () {
    // closes the connection - disabling the polling
    this.readyState = this.CLOSED;
    clearInterval(this._pollTimer);
    this._xhr.abort();
  },
  CONNECTING: 0,
  OPEN: 1,
  CLOSED: 2,
  dispatchEvent: function (type, event) {
    var handlers = this['_' + type + 'Handlers'];
    if (handlers) {
      for (var i = 0; i < handlers.length; i++) {
        handlers[i].call(this, event);
      }
    }

    if (this['on' + type]) {
      this['on' + type].call(this, event);
    }
  },
  addEventListener: function (type, handler) {
    if (!this['_' + type + 'Handlers']) {
      this['_' + type + 'Handlers'] = [];
    }

    this['_' + type + 'Handlers'].push(handler);
  },
  removeEventListener: function () {
    // TODO
  },
  onerror: null,
  onmessage: null,
  onopen: null,
  readyState: 0,
  URL: ''
};

var MessageEvent = function (data, origin, lastEventId) {
  this.data = data;
  this.origin = origin;
  this.lastEventId = lastEventId || '';
};

MessageEvent.prototype = {
  data: null,
  type: 'message',
  lastEventId: '',
  origin: ''
};

if ('module' in global) module.exports = EventSource;
global.EventSource = EventSource;

})(this);
<commit_msg>add `removeEventListener`, fixes #6<commit_after>;(function (global) {

if ("EventSource" in global) return;

var reTrim = /^(\s|\u00A0)+|(\s|\u00A0)+$/g;

var EventSource = function (url) {
  var eventsource = this,
      interval = 500, // polling interval
      lastEventId = null,
      cache = '';

  if (!url || typeof url != 'string') {
    throw new SyntaxError('Not enough arguments');
  }

  this.URL = url;
  this.readyState = this.CONNECTING;
  this._pollTimer = null;
  this._xhr = null;

  function pollAgain(interval) {
    eventsource._pollTimer = setTimeout(function () {
      poll.call(eventsource);
    }, interval);
  }

  function poll() {
    try { // force hiding of the error message... insane?
      if (eventsource.readyState == eventsource.CLOSED) return;

      // NOTE: IE7 and upwards support
      var xhr = new XMLHttpRequest();
      xhr.open('GET', eventsource.URL, true);
      xhr.setRequestHeader('Accept', 'text/event-stream');
      xhr.setRequestHeader('Cache-Control', 'no-cache');
      // we must make use of this on the server side if we're working with Android - because they don't trigger
      // readychange until the server connection is closed
      xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');

      if (lastEventId != null) xhr.setRequestHeader('Last-Event-ID', lastEventId);
      cache = '';

      xhr.timeout = 50000;
      xhr.onreadystatechange = function () {
        if ((this.readyState == 3 || this.readyState == 4) && this.status == 200) {
          // on success
          if (eventsource.readyState == eventsource.CONNECTING) {
            eventsource.readyState = eventsource.OPEN;
            eventsource.dispatchEvent('open', { type: 'open' });
          }

          var responseText = '';
          try {
            responseText = this.responseText || '';
          } catch (e) {}

          // process this.responseText
          var parts = responseText.substr(cache.length).split("\n"),
              eventType = 'message',
              data = [],
              i = 0,
              line = '';

          cache = responseText;

          // TODO handle 'event' (for buffer name), retry
          for (; i < parts.length; i++) {
            line = parts[i].replace(reTrim, '');
            if (line.indexOf('event') == 0) {
              eventType = line.replace(/event:?\s*/, '');
            } else if (line.indexOf('retry') == 0) {
              retry = parseInt(line.replace(/retry:?\s*/, ''));
              if(!isNaN(retry)) { interval = retry; }
            } else if (line.indexOf('data') == 0) {
              data.push(line.replace(/data:?\s*/, ''));
            } else if (line.indexOf('id:') == 0) {
              lastEventId = line.replace(/id:?\s*/, '');
            } else if (line.indexOf('id') == 0) { // this resets the id
              lastEventId = null;
            } else if (line == '') {
              if (data.length) {
                var event = new MessageEvent(data.join('\n'), eventsource.url, lastEventId);
                eventsource.dispatchEvent(eventType, event);
                data = [];
                eventType = 'message';
              }
            }
          }

          if (this.readyState == 4) pollAgain(interval);
          // don't need to poll again, because we're long-loading
        } else if (eventsource.readyState !== eventsource.CLOSED) {
          if (this.readyState == 4) { // and some other status
            // dispatch error
            eventsource.readyState = eventsource.CONNECTING;
            eventsource.dispatchEvent('error', { type: 'error' });
            pollAgain(interval);
          } else if (this.readyState == 0) { // likely aborted
            pollAgain(interval);
          } else {
          }
        }
      };

      xhr.send();

      setTimeout(function () {
        if (true || xhr.readyState == 3) xhr.abort();
      }, xhr.timeout);

      eventsource._xhr = xhr;

    } catch (e) { // in an attempt to silence the errors
      eventsource.dispatchEvent('error', { type: 'error', data: e.message }); // ???
    }
  };

  poll(); // init now
};

EventSource.prototype = {
  close: function () {
    // closes the connection - disabling the polling
    this.readyState = this.CLOSED;
    clearInterval(this._pollTimer);
    this._xhr.abort();
  },
  CONNECTING: 0,
  OPEN: 1,
  CLOSED: 2,
  dispatchEvent: function (type, event) {
    var handlers = this['_' + type + 'Handlers'];
    if (handlers) {
      for (var i = 0; i < handlers.length; i++) {
        handlers[i].call(this, event);
      }
    }

    if (this['on' + type]) {
      this['on' + type].call(this, event);
    }
  },
  addEventListener: function (type, handler) {
    if (!this['_' + type + 'Handlers']) {
      this['_' + type + 'Handlers'] = [];
    }

    this['_' + type + 'Handlers'].push(handler);
  },
  removeEventListener: function (type, handler) {
    var handlers = this['_' + type + 'Handlers'];
    if (!handlers) {
      return;
    }
    for (var i = handlers.length - 1; i >= 0; --i) {
      if (handlers[i] === handler) {
        handlers.splice(i, 1);
        break;
      }
    }
  },
  onerror: null,
  onmessage: null,
  onopen: null,
  readyState: 0,
  URL: ''
};

var MessageEvent = function (data, origin, lastEventId) {
  this.data = data;
  this.origin = origin;
  this.lastEventId = lastEventId || '';
};

MessageEvent.prototype = {
  data: null,
  type: 'message',
  lastEventId: '',
  origin: ''
};

if ('module' in global) module.exports = EventSource;
global.EventSource = EventSource;

})(this);
<|endoftext|>


<commit_before>'use strict';

angular.module('emuwebApp')
  .directive('trackmouse', function () {
    return {
      restrict: 'A',
      link: function (scope, element) {

        var curMouseSample;
        var dragStartSample;
        var dragEndSample;

        element.bind('mousedown', function (event) {
          dragStartSample = Math.round(scope.dhs.getX(event) * scope.vs.getPCMpp(event) + scope.vs.curViewPort.sS);
          dragEndSample = dragStartSample;
          scope.vs.select(dragStartSample, dragStartSample);
          scope.$apply();
        });

        element.bind('mousemove', function (event) {
          switch (event.which) {
          case 0:
            if (!scope.vs.getdragBarActive()) {
              // console.log(event);
              var mouseX = scope.dhs.getX(event);
              scope.vs.curMousePosSample = Math.round(scope.vs.curViewPort.sS + mouseX / element[0].width * (scope.vs.curViewPort.eS - scope.vs.curViewPort.sS));
              scope.$digest();
            }
            break;

          case 1:
            if (!scope.vs.getdragBarActive()) {
              setSelectDrag(event);
            }
            break;
          }
        });

        element.bind('mouseup', function (event) {
          if (!scope.vs.getdragBarActive()) {
            setSelectDrag(event);
          }
        });

        function setSelectDrag(event) {
          curMouseSample = Math.round(scope.dhs.getX(event) * scope.vs.getPCMpp(event) + scope.vs.curViewPort.sS);
          if (curMouseSample > dragStartSample) {
            dragEndSample = curMouseSample;
            scope.vs.select(dragStartSample, dragEndSample);
          } else {
            dragStartSample = curMouseSample;
            scope.vs.select(dragStartSample, dragEndSample);
          }
          scope.$apply();
        }

      }
    };
  });<commit_msg>back to apply<commit_after>'use strict';

angular.module('emuwebApp')
  .directive('trackmouse', function () {
    return {
      restrict: 'A',
      link: function (scope, element) {

        var curMouseSample;
        var dragStartSample;
        var dragEndSample;

        element.bind('mousedown', function (event) {
          dragStartSample = Math.round(scope.dhs.getX(event) * scope.vs.getPCMpp(event) + scope.vs.curViewPort.sS);
          dragEndSample = dragStartSample;
          scope.vs.select(dragStartSample, dragStartSample);
          scope.$apply();
        });

        element.bind('mousemove', function (event) {
          switch (event.which) {
          case 0:
            if (!scope.vs.getdragBarActive()) {
              // console.log(event);
              var mouseX = scope.dhs.getX(event);
              scope.vs.curMousePosSample = Math.round(scope.vs.curViewPort.sS + mouseX / element[0].width * (scope.vs.curViewPort.eS - scope.vs.curViewPort.sS));
              scope.$apply();
            }
            break;

          case 1:
            if (!scope.vs.getdragBarActive()) {
              setSelectDrag(event);
            }
            break;
          }
        });

        element.bind('mouseup', function (event) {
          if (!scope.vs.getdragBarActive()) {
            setSelectDrag(event);
          }
        });

        function setSelectDrag(event) {
          curMouseSample = Math.round(scope.dhs.getX(event) * scope.vs.getPCMpp(event) + scope.vs.curViewPort.sS);
          if (curMouseSample > dragStartSample) {
            dragEndSample = curMouseSample;
            scope.vs.select(dragStartSample, dragEndSample);
          } else {
            dragStartSample = curMouseSample;
            scope.vs.select(dragStartSample, dragEndSample);
          }
          scope.$apply();
        }

      }
    };
  });<|endoftext|>


<commit_before>import React, {PropTypes} from 'react';
import {Link} from 'react-router';
import Ratings from '../utils/Ratings';

const RestaurantListItem = ({item, activeItem, setActiveItemOnClick}) => {
  const name = item.name;
  const address = item.address;
  const city = item.city;
  const zip = item.zip;
  const phone = item.phone;
  const id = item.id;
  const rating = Ratings.getRatings(item.rating);

  //TODO: move to style sheet
  const style = {display: 'inline'};

  const clickHandler = () => setActiveItemOnClick(id, false);
  // const clickHandlerNoScroll = () => setActiveItemNoRenderOnClick(id);

  return (

{name}

          {address}

          {city}, WA {zip}

           {phone}

{rating.string}

<Link to={"/details/"+id} onClick={clickHandler}>History </Link>

  );
};

RestaurantListItem.propTypes = {
  item: PropTypes.object.isRequired,
  activeItem: PropTypes.bool,
  setActiveItemOnClick: PropTypes.func
};

export default RestaurantListItem;
<commit_msg>Adding scroll proptype<commit_after>import React, {PropTypes} from 'react';
import {Link} from 'react-router';
import Ratings from '../utils/Ratings';

const RestaurantListItem = ({item, activeItem, setActiveItemOnClick}) => {
  const name = item.name;
  const address = item.address;
  const city = item.city;
  const zip = item.zip;
  const phone = item.phone;
  const id = item.id;
  const rating = Ratings.getRatings(item.rating);

  //TODO: move to style sheet
  const style = {display: 'inline'};

  const clickHandler = () => setActiveItemOnClick(id, false);

  return (

{name}

          {address}

          {city}, WA {zip}

           {phone}

{rating.string}

<Link to={"/details/"+id} onClick={clickHandler}>History </Link>

  );
};

RestaurantListItem.propTypes = {
  item: PropTypes.object.isRequired,
  activeItem: PropTypes.bool,
  setActiveItemOnClick: PropTypes.func,
  scroll: PropTypes.bool
};

export default RestaurantListItem;
<|endoftext|>