<commit_before>'use strict';

define(['knockout', './string-hashtable'], function (ko, StringHashtable) {

    var requestAnimationFrame = window.requestAnimationFrame,
        cancelAnimationFrame = window.cancelAnimationFrame;

    /** @constructor */
    function ElementWithBindingContext(element, bindingContext) {
        var self = this;

        self.element = element;
        self.bindingContext = bindingContext;
    }

    /** @constructor */
    function AddedItem(index, item, id, previousId) {
        var self = this;

        self.index = index;
        self.item = item;
        self.id = id;
        self.previousId = previousId;
    }

    return function Synchronizer(configuration, bindingContext) {
        var self = this,
        // extract constants from the configuration
            idSelector = configuration.idSelector,
            itemVariableName = configuration.itemVariableName,
            indexVariableName = configuration.indexVariableName,
            allowDeviation = configuration.allowDeviation,
            reportDeviation = configuration.reportDeviation,
            reportSynchronization = configuration.reportSynchronization,
            parent = configuration.parent,
            startMarker = configuration.startMarker,
            endMarker = configuration.endMarker,
            itemElementTemplate = configuration.itemElementTemplate,
        // the core state -- when a synchronization is in progress, currentItems may be more current than itemElements
            currentItems = null,
            itemElements = new StringHashtable(), // id
            synchronizedCount = 0, // the number of items for which elements are present in the DOM (may deviate from itemElements.size())
        // state of the current synchronization (if one is in progress)
            step = 0, // synchronization step counter
            cursor = null, // cursor into the DOM for phase one and two (collectNewItemsAndMarkDeados/collectCarcasses)
            animationFrameRequest = null, // request for the next step, if synchronization is incremental
            addedItems = null, // items for which no element exists (yet)
            presumedDead = null, // elements for removed items by id, may contain false positives for moved back items
            carcasses = null; // elements for definitely removed items (no false positives)

        function startNewSynchronization(newItems) {
            step = 0;
            cursor = configuration.startMarker;
            addedItems = [];
            presumedDead = new StringHashtable();

            currentItems = newItems;

            if (allowDeviation)
                initiateIncrementalSynchronization();
            else
                performImmediateSynchronization();
        }

        function performImmediateSynchronization() {
            while (performSynchronizationStep())
                ++step;
            finalizeSynchronization();
        }

        function initiateIncrementalSynchronization() {
            performIncrementalSynchronizationStep(new Date().getTime() + 15); // TODO magic number, allow configuration?
        }

        function resumeIncrementalSynchronization() {
            performIncrementalSynchronizationStep(new Date().getTime() + 40); // TODO magic number, allow configuration?
        }

        function performIncrementalSynchronizationStep(timelimit) {
            while (performSynchronizationStep()) {
                ++step;

                if (new Date().getTime() > timelimit) {
                    reportDeviation();
                    animationFrameRequest = requestAnimationFrame(resumeIncrementalSynchronization);
                    return;
                }
            }

            finalizeSynchronization();
        }

        function performSynchronizationStep() {
            if (step < currentItems.length())
                collectNewItemsAndMarkDeados(step, currentItems.get(step));
            else if (!carcasses)
                collectCarcasses();
            else if (addedItems.length)
                if (configuration.allowElementRecycling && carcasses.length)
                    performNecromancy(carcasses.pop(), addedItems.shift());
                else
                    insertElementFor(addedItems.shift());
            else
                return incinerateCarcasses() && false;

            return true;
        }

        function collectNewItemsAndMarkDeados(index, item) {
            var previousId = index ? idSelector(currentItems.get(index - 1)) : null;
            var id = idSelector(item);
            var elementWithBindingContext = itemElements.get(id);

            if (elementWithBindingContext) {
                elementWithBindingContext.element.style.display = '';
                elementWithBindingContext.bindingContext[indexVariableName](index);

                var notDeadAfterAll = presumedDead.get(id);
                if (notDeadAfterAll) {
                    presumedDead.remove(id);
                    parent.insertBefore(notDeadAfterAll, cursor.nextSibling);
                    cursor = notDeadAfterAll;
                } else {
                    while (elementWithBindingContext.element !== cursor.nextSibling)
                        presumeDead(cursor.nextSibling);
                    cursor = elementWithBindingContext.element;
                }
            } else {
                addedItems.push(new AddedItem(index, item, id, previousId));
            }
        }

        function collectCarcasses() {
            carcasses = [];
            var aliveAndKicking = currentItems.length() - addedItems.length;
            for (var i = synchronizedCount - presumedDead.size - aliveAndKicking; i > 0; --i)
                presumeDead(cursor.nextSibling);
            presumedDead.forEach(function (key, element) {
                itemElements.remove(key);
                carcasses.push(element);
            });
            presumedDead.clear();
        }

        function performNecromancy(carcass, addedItem) {
            carcass.style.display = '';
            insertNodeAfter(carcass, addedItem.previousId);
            var revivedBindingContext = ko.contextFor(carcass);
            revivedBindingContext[itemVariableName](addedItem.item);
            revivedBindingContext[indexVariableName](addedItem.index);

            itemElements.add(addedItem.id, new ElementWithBindingContext(carcass, revivedBindingContext));
        }

        function insertElementFor(newborn) {
            var element = itemElementTemplate.cloneNode(true);

            var contextExtension = {};
            contextExtension[indexVariableName] = ko.observable(newborn.index);
            contextExtension[itemVariableName] = ko.observable(newborn.item);
            var newBindingContext = bindingContext.extend(contextExtension);

            itemElements.add(newborn.id, new ElementWithBindingContext(element, newBindingContext));
            ko.applyBindings(newBindingContext, element);
            insertNodeAfter(element, newborn.previousId);

            ++synchronizedCount;
        }

        function incinerateCarcasses() {
            while (carcasses.length)
                ko.removeNode(carcasses.pop());
        }

        function finalizeSynchronization() {
            for (var i = 0; i < carcasses.length; ++i) ko.removeNode(carcasses[i]);
            synchronizedCount = currentItems.length();
            reset();
            reportSynchronization();
        }

        function reset() {
            step = 0;
            cursor = null;
            addedItems = null;
            presumedDead = null;
            carcasses = null;
        }

        function insertNodeAfter(node, previousId) {
            var before = (previousId ? itemElements.get(previousId).element : startMarker).nextSibling;
            parent.insertBefore(node, before);
        }

        function presumeDead(element) {
            presumedDead.add(idFor(element), element);
            element.style.display = 'none';
            parent.insertBefore(element, endMarker);
            return element;
        }

        function idFor(e) {
            return idSelector(ko.contextFor(e)[itemVariableName]());
        }

        self.startOrRestartSynchronization = function (newItems) {
            abortActiveSynchronization();
            startNewSynchronization(newItems);
        };

        self.abortActiveSynchronization = abortActiveSynchronization;

        function abortActiveSynchronization() {
            if (!animationFrameRequest)
                return;

            cancelAnimationFrame(animationFrameRequest);
            animationFrameRequest = null;

            for (var i = 0; carcasses !== null && i < carcasses.length; ++i) {
                var element = carcasses[i];
                itemElements.add(idFor(element), new ElementWithBindingContext(element, ko.contextFor(element)));
            }

            reset();
        }
    };
});<commit_msg>Minor bugfix: `bind`ing `window` to `requestAnimationFrame`/`cancelAnimationFrame`.<commit_after>'use strict';

define(['knockout', './string-hashtable'], function (ko, StringHashtable) {

    var requestAnimationFrame = window.requestAnimationFrame.bind(window),
        cancelAnimationFrame = window.cancelAnimationFrame.bind(window);

    /** @constructor */
    function ElementWithBindingContext(element, bindingContext) {
        var self = this;

        self.element = element;
        self.bindingContext = bindingContext;
    }

    /** @constructor */
    function AddedItem(index, item, id, previousId) {
        var self = this;

        self.index = index;
        self.item = item;
        self.id = id;
        self.previousId = previousId;
    }

    return function Synchronizer(configuration, bindingContext) {
        var self = this,
        // extract constants from the configuration
            idSelector = configuration.idSelector,
            itemVariableName = configuration.itemVariableName,
            indexVariableName = configuration.indexVariableName,
            allowDeviation = configuration.allowDeviation,
            reportDeviation = configuration.reportDeviation,
            reportSynchronization = configuration.reportSynchronization,
            parent = configuration.parent,
            startMarker = configuration.startMarker,
            endMarker = configuration.endMarker,
            itemElementTemplate = configuration.itemElementTemplate,
        // the core state -- when a synchronization is in progress, currentItems may be more current than itemElements
            currentItems = null,
            itemElements = new StringHashtable(), // id
            synchronizedCount = 0, // the number of items for which elements are present in the DOM (may deviate from itemElements.size())
        // state of the current synchronization (if one is in progress)
            step = 0, // synchronization step counter
            cursor = null, // cursor into the DOM for phase one and two (collectNewItemsAndMarkDeados/collectCarcasses)
            animationFrameRequest = null, // request for the next step, if synchronization is incremental
            addedItems = null, // items for which no element exists (yet)
            presumedDead = null, // elements for removed items by id, may contain false positives for moved back items
            carcasses = null; // elements for definitely removed items (no false positives)

        function startNewSynchronization(newItems) {
            step = 0;
            cursor = configuration.startMarker;
            addedItems = [];
            presumedDead = new StringHashtable();

            currentItems = newItems;

            if (allowDeviation)
                initiateIncrementalSynchronization();
            else
                performImmediateSynchronization();
        }

        function performImmediateSynchronization() {
            while (performSynchronizationStep())
                ++step;
            finalizeSynchronization();
        }

        function initiateIncrementalSynchronization() {
            performIncrementalSynchronizationStep(new Date().getTime() + 15); // TODO magic number, allow configuration?
        }

        function resumeIncrementalSynchronization() {
            performIncrementalSynchronizationStep(new Date().getTime() + 40); // TODO magic number, allow configuration?
        }

        function performIncrementalSynchronizationStep(timelimit) {
            while (performSynchronizationStep()) {
                ++step;

                if (new Date().getTime() > timelimit) {
                    reportDeviation();
                    animationFrameRequest = requestAnimationFrame(resumeIncrementalSynchronization);
                    return;
                }
            }

            finalizeSynchronization();
        }

        function performSynchronizationStep() {
            if (step < currentItems.length())
                collectNewItemsAndMarkDeados(step, currentItems.get(step));
            else if (!carcasses)
                collectCarcasses();
            else if (addedItems.length)
                if (configuration.allowElementRecycling && carcasses.length)
                    performNecromancy(carcasses.pop(), addedItems.shift());
                else
                    insertElementFor(addedItems.shift());
            else
                return incinerateCarcasses() && false;

            return true;
        }

        function collectNewItemsAndMarkDeados(index, item) {
            var previousId = index ? idSelector(currentItems.get(index - 1)) : null;
            var id = idSelector(item);
            var elementWithBindingContext = itemElements.get(id);

            if (elementWithBindingContext) {
                elementWithBindingContext.element.style.display = '';
                elementWithBindingContext.bindingContext[indexVariableName](index);

                var notDeadAfterAll = presumedDead.get(id);
                if (notDeadAfterAll) {
                    presumedDead.remove(id);
                    parent.insertBefore(notDeadAfterAll, cursor.nextSibling);
                    cursor = notDeadAfterAll;
                } else {
                    while (elementWithBindingContext.element !== cursor.nextSibling)
                        presumeDead(cursor.nextSibling);
                    cursor = elementWithBindingContext.element;
                }
            } else {
                addedItems.push(new AddedItem(index, item, id, previousId));
            }
        }

        function collectCarcasses() {
            carcasses = [];
            var aliveAndKicking = currentItems.length() - addedItems.length;
            for (var i = synchronizedCount - presumedDead.size - aliveAndKicking; i > 0; --i)
                presumeDead(cursor.nextSibling);
            presumedDead.forEach(function (key, element) {
                itemElements.remove(key);
                carcasses.push(element);
            });
            presumedDead.clear();
        }

        function performNecromancy(carcass, addedItem) {
            carcass.style.display = '';
            insertNodeAfter(carcass, addedItem.previousId);
            var revivedBindingContext = ko.contextFor(carcass);
            revivedBindingContext[itemVariableName](addedItem.item);
            revivedBindingContext[indexVariableName](addedItem.index);

            itemElements.add(addedItem.id, new ElementWithBindingContext(carcass, revivedBindingContext));
        }

        function insertElementFor(newborn) {
            var element = itemElementTemplate.cloneNode(true);

            var contextExtension = {};
            contextExtension[indexVariableName] = ko.observable(newborn.index);
            contextExtension[itemVariableName] = ko.observable(newborn.item);
            var newBindingContext = bindingContext.extend(contextExtension);

            itemElements.add(newborn.id, new ElementWithBindingContext(element, newBindingContext));
            ko.applyBindings(newBindingContext, element);
            insertNodeAfter(element, newborn.previousId);

            ++synchronizedCount;
        }

        function incinerateCarcasses() {
            while (carcasses.length)
                ko.removeNode(carcasses.pop());
        }

        function finalizeSynchronization() {
            for (var i = 0; i < carcasses.length; ++i) ko.removeNode(carcasses[i]);
            synchronizedCount = currentItems.length();
            reset();
            reportSynchronization();
        }

        function reset() {
            step = 0;
            cursor = null;
            addedItems = null;
            presumedDead = null;
            carcasses = null;
        }

        function insertNodeAfter(node, previousId) {
            var before = (previousId ? itemElements.get(previousId).element : startMarker).nextSibling;
            parent.insertBefore(node, before);
        }

        function presumeDead(element) {
            presumedDead.add(idFor(element), element);
            element.style.display = 'none';
            parent.insertBefore(element, endMarker);
            return element;
        }

        function idFor(e) {
            return idSelector(ko.contextFor(e)[itemVariableName]());
        }

        self.startOrRestartSynchronization = function (newItems) {
            abortActiveSynchronization();
            startNewSynchronization(newItems);
        };

        self.abortActiveSynchronization = abortActiveSynchronization;

        function abortActiveSynchronization() {
            if (!animationFrameRequest)
                return;

            cancelAnimationFrame(animationFrameRequest);
            animationFrameRequest = null;

            for (var i = 0; carcasses !== null && i < carcasses.length; ++i) {
                var element = carcasses[i];
                itemElements.add(idFor(element), new ElementWithBindingContext(element, ko.contextFor(element)));
            }

            reset();
        }
    };
});<|endoftext|>


<commit_before>const Discord = require('discord.js');
const config = require('./config.json');
const fs = require('fs');

const client = new Discord.Client({
  max_message_cache: 5,
  fetch_all_members: true,
});

const prefix = '🔨';

client.on('ready', () => {
  console.log('ready!');
});

function genLog(banner, banned, reason, channel, ban, owner) {
  fs.writeFileSync(`./out/${Date.now()}.json`, JSON.stringify({
    banner: banner.id,
    banned: banned.id,
    reason,
    messages: {
      channel,
      ban,
      owner,
    },
    date: Date.now(),
  }));
}

function hasPermission(member) {
  if (member.id === config.owner) {
    return true;
  }
  for (const role of member.roles) {
    if (config.roles.includes(role.name.toLowerCase())) {
      return true;
    }
  }
  return false;
}

function generateLolYouGotBanned(user, banner, owner, reason) {
  return [
    `Hey ${user.username},\n`,
    'you recently lost send message permissions in the discord.js help channel because a user with high authority' +
    `saw fit to do so. You may appeal to ${owner} if you wish.\n`,
    `Banner: ${banner.username}#${banner.discriminator} (${banner})`,
    `Reason: ${reason}\n`,
    'It is entirely possible this was a mistake, in this case please do contact ' +
    `${owner.username}#${owner.discriminator} ${owner} to clear this up.\n`,
    'Thank you.',
  ].join('\n');
}

function generateOwnerMessage(toBan, banner, reason) {
  return [
    `${toBan.username}#${toBan.discriminator} (${toBan}) was banned at ${Date.now()}`,
    `Banner: ${banner.username}#${banner.discriminator} (${banner}) `,
    `Reason: ${reason}`,
  ].join('\n');
}

client.on('message', message => {
  if (message.channel.id !== config.channel || !message.content.startsWith(prefix)) {
    return;
  }

  if (message.mentions.users.size === 0) {
    return;
  }

  if (!hasPermission(message.member)) {
    return;
  }

  const banMessage = message.content.split(' ').slice(2).join(' ') || 'unspecified reason';
  const owner = client.users.get(config.owner);
  const toBan = message.mentions.users.array()[0];

  if (hasPermission(message.guild.member(toBan))) {
    return message.reply('You cannot ban this user');
  }

  if (message.channel.permissionsFor(toBan) && !message.channel.permissionsFor(toBan).hasPermission('SEND_MESSAGES')) {
    return message.reply('That user is already softbanned.');
  }

  message.channel.overwritePermissions(toBan, {
    SEND_MESSAGES: false,
  })
  .then(() => {
    const channMessage = `${toBan.username} has lost send message permissions - ${owner.username} has been notified.`;
    const bannedMessage = generateLolYouGotBanned(toBan, message.author, owner, banMessage);
    const ownerMessage = generateOwnerMessage(toBan, message.author, banMessage);
    genLog(message.author, toBan, banMessage, channMessage, bannedMessage, ownerMessage);
    message.channel.sendMessage(channMessage);
    toBan.sendMessage(bannedMessage);
    owner.sendMessage(ownerMessage);
  })
  .catch(e => {
    message.reply(`Couldn't ban - ${e}`);
  });
});

client.on('error', process.exit);

client.login(config.token);
<commit_msg>update output filename<commit_after>const Discord = require('discord.js');
const config = require('./config.json');
const fs = require('fs');

const client = new Discord.Client({
  max_message_cache: 5,
  fetch_all_members: true,
});

const prefix = '🔨';

client.on('ready', () => {
  console.log('ready!');
});

function genLog(banner, banned, reason, channel, ban, owner) {
  fs.writeFileSync(`./out/${banned.username} ${Date.now()}.json`, JSON.stringify({
    banner: banner.id,
    banned: banned.id,
    reason,
    messages: {
      channel,
      ban,
      owner,
    },
    date: Date.now(),
  }));
}

function hasPermission(member) {
  if (member.id === config.owner) {
    return true;
  }
  for (const role of member.roles) {
    if (config.roles.includes(role.name.toLowerCase())) {
      return true;
    }
  }
  return false;
}

function generateLolYouGotBanned(user, banner, owner, reason) {
  return [
    `Hey ${user.username},\n`,
    'you recently lost send message permissions in the discord.js help channel because a user with high authority' +
    `saw fit to do so. You may appeal to ${owner} if you wish.\n`,
    `Banner: ${banner.username}#${banner.discriminator} (${banner})`,
    `Reason: ${reason}\n`,
    'It is entirely possible this was a mistake, in this case please do contact ' +
    `${owner.username}#${owner.discriminator} ${owner} to clear this up.\n`,
    'Thank you.',
  ].join('\n');
}

function generateOwnerMessage(toBan, banner, reason) {
  return [
    `${toBan.username}#${toBan.discriminator} (${toBan}) was banned at ${Date.now()}`,
    `Banner: ${banner.username}#${banner.discriminator} (${banner}) `,
    `Reason: ${reason}`,
  ].join('\n');
}

client.on('message', message => {
  if (message.channel.id !== config.channel || !message.content.startsWith(prefix)) {
    return;
  }

  if (message.mentions.users.size === 0) {
    return;
  }

  if (!hasPermission(message.member)) {
    return;
  }

  const banMessage = message.content.split(' ').slice(2).join(' ') || 'unspecified reason';
  const owner = client.users.get(config.owner);
  const toBan = message.mentions.users.array()[0];

  if (hasPermission(message.guild.member(toBan))) {
    return message.reply('You cannot ban this user');
  }

  if (message.channel.permissionsFor(toBan) && !message.channel.permissionsFor(toBan).hasPermission('SEND_MESSAGES')) {
    return message.reply('That user is already softbanned.');
  }

  message.channel.overwritePermissions(toBan, {
    SEND_MESSAGES: false,
  })
  .then(() => {
    const channMessage = `${toBan.username} has lost send message permissions - ${owner.username} has been notified.`;
    const bannedMessage = generateLolYouGotBanned(toBan, message.author, owner, banMessage);
    const ownerMessage = generateOwnerMessage(toBan, message.author, banMessage);
    genLog(message.author, toBan, banMessage, channMessage, bannedMessage, ownerMessage);
    message.channel.sendMessage(channMessage);
    toBan.sendMessage(bannedMessage);
    owner.sendMessage(ownerMessage);
  })
  .catch(e => {
    message.reply(`Couldn't ban - ${e}`);
  });
});

client.on('error', process.exit);

client.login(config.token);
<|endoftext|>


<commit_before>function blastedToBodies(elements) {
  return elements.map(function(elem) {
    var $elem = $(elem);
    var left = $elem.offset().left;
    var top = $elem.offset().top;
    var w = $elem.width();
    var h = $elem.height();
    var x = left + w/2; // Matter.js uses center-origin shapes
    var y = top + h/2;
    var body = Matter.Bodies.rectangle(x, y, w, h, {frictionAir: 0.1});
    body.origX = x; // save initial position
    body.origY = y;
    body.ref = elem; // keep a reference to the DOM element to transform it
    return body;
  });
}

function onTouchMove(f) {
  var hammertime = new Hammer(document.body);
  hammertime.get('pan').set({ direction: Hammer.DIRECTION_ALL });
  hammertime.on('pan', f);
}

function setPosition(body) {
  return function(e) {
    if(e.pointerType != 'mouse') {
      Matter.Body.setPosition(body, Matter.Vector.create(e.center.x, e.center.y));
    }
  }
}

function transformElementsFrom(bodies) {
  bodies.forEach(function(body) {
    if(body.isSleeping)
      return;

    var elem = body.ref;

    var dx = body.position.x - body.origX;
    var dy = body.position.y - body.origY;

    // elem.style.transform = `translate(${dx}px, ${dy}px)`;
    // why use Babel just for an interpolated string...
    elem.style.transform = 'translate(' + dx + 'px, ' + dy + 'px)';
  });
}

$(function() {
  // blast dom into .blast spans
  var blasted = $('p').blast({ delimiter: "word" }).toArray();

  // create Matter.js new engine
  var engine = Matter.Engine.create();

  // create bodies for each element
  var bodies = blastedToBodies(blasted);
  Matter.World.add(engine.world, bodies);

  // create mouseBody for "touching away" and colliding with other bodies
  var mouseBody = Matter.Bodies.circle(0, 0, 30, {isStatic: true});
  Matter.World.add(engine.world, mouseBody);

  // when moving touch event (from hammer.js) update mouseBody position
  onTouchMove(setPosition(mouseBody));

  //
  // Matter.Events.on(engine, 'afterUpdate', function() {
  //   transformElementsFrom(bodies);
  // });
  function step() {
    transformElementsFrom(bodies);
    requestAnimationFrame(step);
  }
  step();

  // start physics engine
  engine.world.gravity.scale = 0.000000000001;
  Matter.Engine.run(engine);
})
<commit_msg>added all functions inside main function for scoping<commit_after>$(function() {
  // blast dom into .blast spans
  var blasted = $('p').blast({ delimiter: "word" }).toArray();

  // create Matter.js new engine
  var engine = Matter.Engine.create();

  // create bodies for each element
  var bodies = blastedToBodies(blasted);
  Matter.World.add(engine.world, bodies);

  // create mouseBody for "touching away" and colliding with other bodies
  var mouseBody = Matter.Bodies.circle(0, 0, 30, {isStatic: true});
  Matter.World.add(engine.world, mouseBody);

  // when moving touch event (from hammer.js) update mouseBody position
  onTouchMove(setPosition(mouseBody));

  //
  // Matter.Events.on(engine, 'afterUpdate', function() {
  //   transformElementsFrom(bodies);
  // });
  function step() {
    transformElementsFrom(bodies);
    requestAnimationFrame(step);
  }
  step();

  // start physics engine
  engine.world.gravity.scale = 0.000000000001;
  Matter.Engine.run(engine);

  function blastedToBodies(elements) {
    return elements.map(function(elem) {
      var $elem = $(elem);
      var left = $elem.offset().left;
      var top = $elem.offset().top;
      var w = $elem.width();
      var h = $elem.height();
      var x = left + w/2; // Matter.js uses center-origin shapes
      var y = top + h/2;
      var body = Matter.Bodies.rectangle(x, y, w, h, {frictionAir: 0.1});
      body.origX = x; // save initial position
      body.origY = y;
      body.ref = elem; // keep a reference to the DOM element to transform it
      return body;
    });
  }

  function onTouchMove(f) {
    var hammertime = new Hammer(document.body);
    hammertime.get('pan').set({ direction: Hammer.DIRECTION_ALL });
    hammertime.on('pan', f);
  }

  function setPosition(body) {
    return function(e) {
      if(e.pointerType != 'mouse') {
        Matter.Body.setPosition(body, Matter.Vector.create(e.center.x, e.center.y));
      }
    }
  }

  function transformElementsFrom(bodies) {
    bodies.forEach(function(body) {
      if(body.isSleeping)
        return;

      var elem = body.ref;

      var dx = body.position.x - body.origX;
      var dy = body.position.y - body.origY;

      // elem.style.transform = `translate(${dx}px, ${dy}px)`;
      // why use Babel just for an interpolated string...
      elem.style.transform = 'translate(' + dx + 'px, ' + dy + 'px)';
    });
  }
})
<|endoftext|>


<commit_before>/*
* @Author: Mike Reich
* @Date:   2016-02-05 07:45:34
* @Last Modified 2016-02-20
*/
/**
 *
 * [![Build Status](https://travis-ci.org/nxus/worker-queue.svg?branch=master)](https://travis-ci.org/nxus/worker-queue)
 *
 * Using Redis for pub/sub background tasks
 *
 * ## Installation
 *
 *     > npm install @nxus/worker-queue --save
 *
 * ## Usage
 *
 * For each task, you need to define a unique task name.
 *
 * ### Register a worker handler
 *
 * ```
 * app.get('worker-queue').worker('myBackgroundTask', (msg) => {
 *   console.log("Hello", msg.hi)
 * })
 * ```
 *
 * ### Request task processing
 *
 * `app.get('worker-queue').task('myBackgroundTask', {hi: world})`
 *
 * ### Receive notifications of completed tasks
 *
 * Register two tasks, one for processing and one for notifications, and trigger the second from within the first handler.
 *
 * ```
 * app.get('worker-queue').worker('myBackgroundTask', (msg) => {
 *   console.log("Hello", msg.hi)
 *   app.get('worker-queue').task('myBackgroundTask-complete', {result: true})
 * })
 * app.get('worker-queue').worker('myBackgroundTask-complete', (msg) => {
 *   console.log("Completed", msg.result)
 * })
 * ```
 *
 * `app.get('worker-queue').task('myBackgroundTask', {hi: world})`
 *
 *
 * # API
 * ----
 */

'use strict';

import redis from 'redis'

const _defaultConfig = {
  redis_url: process.env.REDIS_URL || 'redis://localhost:6379'
}

/**
 * Worker Queue module for background tasks
 */
export default class WorkerQueue {
  constructor(app) {
    this.app = app
    this.config = Object.assign(_defaultConfig, app.config['worker-queue'])

    app.get('worker-queue').use(this)
      .gather('worker')
      .respond('task')

    app.onceAfter('load', this._connect.bind(this))
    app.once('stop', this._disconnect.bind(this))
  }

  // Handlers

  /**
   * Provide a task handler
   * @param {string} taskName Name of the task (channel) to listen for
   * @param {function} handler Handler for processing task requests
   * @example app.get('worker-queue').worker('backgroundJob', (msg) -> {})
   */

  worker (taskName, handler) {
    this.app.log.debug('Registering task worker for', taskName)
    this.subscriber.subscribe(taskName)
    this.on("worker-"+taskName, handler)
  }

  /**
   * Request handling of a background task
   * @param {string} taskName Name of the task (channel) to publish to
   * @param {object} message Options for the task worker
   * @example app.get('worker-queue').task('backgroundJob', {hi: 'world'})
   */
  task (taskName, message) {
    this.app.log.debug('Task requested', taskName)
    this.publisher.publish(taskName, JSON.stringify(message))
  }

  // Internal

  _connect () {
    // Redis needs separate connections for pub/sub
    this.publisher = redis.createClient(this.config.redis_url)
    this.publisher.on("error", (err) => {
      this.app.log.debug("Publisher error", err)
    })
    this.subscriber = redis.createClient(this.config.redis_url)
    this.subscriber.on("error", (err) => {
      this.app.log.debug("Subscriber error", err)
    })
    this.subscriber.on("message", (channel, message) => {
      message = JSON.parse(message)
      this.emit("worker-"+channel, message)
    })
    this.app.log.debug('Connected to task queue pubsub')
  }

  _disconnect () {
    if (this.publisher) {
      this.publisher.quit()
      delete this.publisher
    }
    if (this.subscriber) {
      this.subscriber.unsubscribe()
      this.subscriber.quit()
      delete this.subscriber
    }
  }
}
<commit_msg>Updated worker to initiatilize redis on construction<commit_after>/*
* @Author: Mike Reich
* @Date:   2016-02-05 07:45:34
* @Last Modified 2016-04-11
*/
/**
 *
 * [![Build Status](https://travis-ci.org/nxus/worker-queue.svg?branch=master)](https://travis-ci.org/nxus/worker-queue)
 *
 * Using Redis for pub/sub background tasks
 *
 * ## Installation
 *
 *     > npm install @nxus/worker-queue --save
 *
 * ## Usage
 *
 * For each task, you need to define a unique task name.
 *
 * ### Register a worker handler
 *
 * ```
 * app.get('worker-queue').worker('myBackgroundTask', (msg) => {
 *   console.log("Hello", msg.hi)
 * })
 * ```
 *
 * ### Request task processing
 *
 * `app.get('worker-queue').task('myBackgroundTask', {hi: world})`
 *
 * ### Receive notifications of completed tasks
 *
 * Register two tasks, one for processing and one for notifications, and trigger the second from within the first handler.
 *
 * ```
 * app.get('worker-queue').worker('myBackgroundTask', (msg) => {
 *   console.log("Hello", msg.hi)
 *   app.get('worker-queue').task('myBackgroundTask-complete', {result: true})
 * })
 * app.get('worker-queue').worker('myBackgroundTask-complete', (msg) => {
 *   console.log("Completed", msg.result)
 * })
 * ```
 *
 * `app.get('worker-queue').task('myBackgroundTask', {hi: world})`
 *
 *
 * # API
 * ----
 */

'use strict';

import redis from 'redis'

const _defaultConfig = {
  redis_url: process.env.REDIS_URL || 'redis://localhost:6379'
}

/**
 * Worker Queue module for background tasks
 */
export default class WorkerQueue {
  constructor(app) {
    this.app = app
    this.config = Object.assign(_defaultConfig, app.config['worker-queue'])

    app.get('worker-queue').use(this)
      .gather('worker')
      .respond('task')

    this._connect()
    app.once('stop', this._disconnect.bind(this))
  }

  // Handlers

  /**
   * Provide a task handler
   * @param {string} taskName Name of the task (channel) to listen for
   * @param {function} handler Handler for processing task requests
   * @example app.get('worker-queue').worker('backgroundJob', (msg) -> {})
   */

  worker (taskName, handler) {
    this.app.log.debug('Registering task worker for', taskName)
    this.subscriber.subscribe(taskName)
    this.on("worker-"+taskName, handler)
  }

  /**
   * Request handling of a background task
   * @param {string} taskName Name of the task (channel) to publish to
   * @param {object} message Options for the task worker
   * @example app.get('worker-queue').task('backgroundJob', {hi: 'world'})
   */
  task (taskName, message) {
    this.app.log.debug('Task requested', taskName)
    this.publisher.publish(taskName, JSON.stringify(message))
  }

  // Internal

  _connect () {
    // Redis needs separate connections for pub/sub
    this.publisher = redis.createClient(this.config.redis_url)
    this.publisher.on("error", (err) => {
      this.app.log.error("Publisher error", err)
    })
    this.subscriber = redis.createClient(this.config.redis_url)
    this.subscriber.on("error", (err) => {
      this.app.log.error("Subscriber error", err)
    })
    this.subscriber.on("message", (channel, message) => {
      console.log('message received', channel, message)
      message = JSON.parse(message)
      this.emit("worker-"+channel, message)
    })
    this.app.log.debug('Connected to task queue pubsub')
  }

  _disconnect () {
    if (this.publisher) {
      this.publisher.quit()
      delete this.publisher
    }
    if (this.subscriber) {
      this.subscriber.unsubscribe()
      this.subscriber.quit()
      delete this.subscriber
    }
  }
}
<|endoftext|>


<commit_before>/* @flow */

import express from 'express';
import expressGraphQL from 'express-graphql';
import schema from './schema/Schema';

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

app.use(
  '/graphql',
  expressGraphQL(req => ({
    schema,
    graphiql: true,
    context: req,
  }))
);

app.listen(port, () => {
  console.log(`App running on port ${port}`);
  console.log(`Visit http://localhost:${port}/graphql`);
});
<commit_msg>chore: change GraphiQL route to `/`<commit_after>/* @flow */

import express from 'express';
import expressGraphQL from 'express-graphql';
import schema from './schema/Schema';

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

app.use(
  '/',
  expressGraphQL(req => ({
    schema,
    graphiql: true,
    context: req,
  }))
);

app.listen(port, () => {
  console.log(`App running on port ${port}`);
  console.log(`Visit http://localhost:${port}/graphql`);
});
<|endoftext|>


<commit_before>import Vue from 'vue'
import merge from 'utils/merge'
import { error } from 'utils/console'

const middlewares = []
const callbacks = []

export function use (creator, options = {}) {
  if (typeof creator !== 'function') {
    return error('`creator` must be a function')
  }
  middlewares.push({ creator, options })
}

export function run (finale) {
  const _modules = {}
  const _routes = []

  const context = new Vue({
    data: {
      // for Vuex.Store
      modules: _modules,
      // for Vue-Router
      routes: _routes
    }
  })

  function registerModule (key, obj) {
    if (_modules[key]) {
      merge(_modules[key], obj)
    } else {
      _modules[key] = obj
    }
  }

  function registerRoutes (scope, prefix, routes) {
    function injector (module) {
      // add scope as vm.$options.__scope
      if (module) {
        if (__DEV__) {
          module._Ctor[0].options.__scope = scope
        } else {
          module.__scope = scope
        }
      }
      return module
    }
    function injectscopeToVm (component) {
      if (isFunction(component)) {
        return () => component().then(injector).catch(injector)
      } else {
        return injector(component)
      }
    }
    function addPrefixToPath (path) {
      return `/${prefix}/${path}`.replace(/\/+$/, '').replace(/\/\/+/g, '/') || '/'
    }
    function handleRoutes (prefix, arr) {
      return arr.map(r => {
        const { path, meta = {}, component, components, children } = r
        r.path = addPrefixToPath(path)
        // store original path to meta
        meta.__scope = scope
        meta.__path = path
        r.meta = meta
        // inject component and components
        if (component) {
          r.component = injectscopeToVm(component)
        }
        if (components) {
          Object.keys(components).forEach(key => {
            components[key] = injectscopeToVm(components[key])
          })
        }
        if (children) {
          r.children = handleRoutes(r.path, r.children)
        }
        return r
      })
    }
    _routes.push.apply(_routes, handleRoutes(prefix || scope, routes))
  }

  function done () {
    let callback
    while ((callback = callbacks.pop())) {
      callback(context)
    }

    if (finale) {
      finale(context)
    }
  }

  function next () {
    const { creator, options } = middlewares.shift() || {}

    if (creator) {
      // creator: fn(context, options, register)
      creator(context, options, (payload, callback) => {
        if (typeof payload === 'function') {
          callback = payload
          payload = null
        }
        // 将回调函数添加到队列
        callback && callbacks.push(callback)
        // 如果有提供配置数据，则进行 store 与 router 相关处理
        if (payload) {
          const { scope, prefix, store, routes } = payload
          if (scope) {
            store && registerModule(scope, store)
            routes && registerRoutes(scope, prefix, routes)
          } else {
            error('`scope` is required!')
          }
        }
        next()
      })
    } else {
      done()
    }
  }

  next()
}

function isFunction (val) {
  return typeof val === 'function'
}
<commit_msg>add logs to system<commit_after>import Vue from 'vue'
import merge from 'utils/merge'
import { groupEnd, group, log, error } from 'utils/console'

const middlewares = []
const callbacks = []

export function use (creator, options = {}) {
  if (typeof creator !== 'function') {
    return error('`creator` must be a function')
  }
  middlewares.push({ creator, options })
}

export function run (finale) {
  const _modules = {}
  const _routes = []

  const context = new Vue({
    data: {
      // for Vuex.Store
      modules: _modules,
      // for Vue-Router
      routes: _routes
    }
  })

  function registerModule (key, obj) {
    if (_modules[key]) {
      merge(_modules[key], obj)
    } else {
      _modules[key] = obj
    }
  }

  function registerRoutes (scope, prefix, routes) {
    function injector (module) {
      // add scope as vm.$options.__scope
      if (module) {
        if (__DEV__) {
          module._Ctor[0].options.__scope = scope
        } else {
          module.__scope = scope
        }
      }
      return module
    }
    function injectscopeToVm (component) {
      if (isFunction(component)) {
        return () => component().then(injector).catch(injector)
      } else {
        return injector(component)
      }
    }
    function addPrefixToPath (path) {
      return `/${prefix}/${path}`.replace(/\/+$/, '').replace(/\/\/+/g, '/') || '/'
    }
    function handleRoutes (prefix, arr) {
      return arr.map(r => {
        const { path, meta = {}, component, components, children } = r
        r.path = addPrefixToPath(path)
        // store original path to meta
        meta.__scope = scope
        meta.__path = path
        r.meta = meta
        // inject component and components
        if (component) {
          r.component = injectscopeToVm(component)
        }
        if (components) {
          Object.keys(components).forEach(key => {
            components[key] = injectscopeToVm(components[key])
          })
        }
        if (children) {
          r.children = handleRoutes(r.path, r.children)
        }
        return r
      })
    }
    _routes.push.apply(_routes, handleRoutes(prefix || scope, routes))
  }

  function done () {
    log('%c[PLATO] %cExecuting module callbacks', 'font-weight: bold', 'color: green; font-weight: bold')
    let callback
    while ((callback = callbacks.pop())) {
      callback(context)
    }

    if (finale) {
      finale(context)
    }
  }

  function next () {
    const { creator, options } = middlewares.shift() || {}

    if (creator) {
      // creator: fn(context, options, register)
      creator(context, options, (payload, callback) => {
        if (typeof payload === 'function') {
          callback = payload
          payload = null
        }
        // 将回调函数添加到队列
        callback && callbacks.push(callback)
        // 如果有提供配置数据，则进行 store 与 router 相关处理
        if (payload) {
          const { scope, prefix, store, routes } = payload
          if (scope) {
            log(`Module %c${scope}%c registered.`, 'color: green', 'color: inherit')
            store && registerModule(scope, store)
            routes && registerRoutes(scope, prefix, routes)
          } else {
            error('`scope` is required!')
          }
        }
        next()
      })
    } else {
      groupEnd()
      // 注册完毕，准备执行回调函数队列
      done()
    }
  }

  group('%c[PLATO] %cRegistering modules...', 'font-weight: bold', 'color: green; font-weight: bold')
  // 开始执行模块注册队列
  next()
}

function isFunction (val) {
  return typeof val === 'function'
}
<|endoftext|>


<commit_before>$(function() {

    var lineCount;

    function lineCountWrite() {
        $("aside").html("");
        lineCount = $("main").height() / 25;
        for (var i = 1; i <= lineCount; i++) {
            $("aside").append("" + i + "")
        }
    }

    $.getJSON("/data.json", function(data) {
            var codeItems = [],
                valueContent = data['meta']['quotes'],
                links = data['meta']['links'],
                newSelection = data['meta']['newSelection'],
                newLine = data['meta']['newLine'];
            $.each(data['code'], function(key, val) {
                var codeItem;
                if (jQuery.inArray(key, newSelection) != -1) {
                    codeItem = "";
                } else{
                    codeItem = "";
                }
                codeItem += '' + key + '';
                $.each(val, function(key, value) {
                    codeItem += '' + key + '';
                    if (links[key]) {
                        codeItem += '' + value + '';
                    } else {
                        if (value.indexOf("%") != -1) {
                            codeItem += '' + value.slice(0, -1) + '%';
                        } else {
                            codeItem += '' + value + '';
                        }
                    }
                    codeItem += '';
                });
                codeItem += '';
                codeItems.push(codeItem);
            });
            codeItems.push('
Thank you for reading
');
            $('pre').html(codeItems);

        })
        .done(function() {
            lineCountWrite();
            $(window).hover(function(e) {
                var pY = e.pageY;
                for (var c = 1; c <= lineCount; c++) {
                    if (pY > $("aside span:nth-child(" + c + ")").offset().top && pY < $("aside span:nth-child(" + c + ")").offset().top + 25) {
                        $("aside span:nth-child(" + c + ")").css({
                            color: "#55b5db"
                        });
                    }
                }
            }, function() {
                $("aside span").css({
                    color: "#404b53"
                });
            });
            $("code").append('');
            $("code .arrow").click(function() {
                $(this).parent().toggleClass('close');
                $(this).siblings('.code-selection').toggleClass('collapsed');
                $(".code-content", $(this).parent()).toggle();
                lineCountWrite();
            });
        })
        .fail(function() {
            alert('Error Loading, Please Refresh!');
        });

});
<commit_msg>removed line hover effect<commit_after>$(function() {

    var lineCount;

    function lineCountWrite() {
        $("aside").html("");
        lineCount = $("main").height() / 25;
        for (var i = 1; i <= lineCount; i++) {
            $("aside").append("" + i + "")
        }
    }

    $.getJSON("/data.json", function(data) {
            var codeItems = [],
                valueContent = data['meta']['quotes'],
                links = data['meta']['links'],
                newSelection = data['meta']['newSelection'],
                newLine = data['meta']['newLine'];
            $.each(data['code'], function(key, val) {
                var codeItem;
                if (jQuery.inArray(key, newSelection) != -1) {
                    codeItem = "";
                } else{
                    codeItem = "";
                }
                codeItem += '' + key + '';
                $.each(val, function(key, value) {
                    codeItem += '' + key + '';
                    if (links[key]) {
                        codeItem += '' + value + '';
                    } else {
                        if (value.indexOf("%") != -1) {
                            codeItem += '' + value.slice(0, -1) + '%';
                        } else {
                            codeItem += '' + value + '';
                        }
                    }
                    codeItem += '';
                });
                codeItem += '';
                codeItems.push(codeItem);
            });
            codeItems.push('
Thank you for reading
');
            $('pre').html(codeItems);

        })
        .done(function() {
            lineCountWrite();
            $("code").append('');
            $("code .arrow").click(function() {
                $(this).parent().toggleClass('close');
                $(this).siblings('.code-selection').toggleClass('collapsed');
                $(".code-content", $(this).parent()).toggle();
                lineCountWrite();
            });
        })
        .fail(function() {
            alert('Error Loading, Please Refresh!');
        });

});
<|endoftext|>


<commit_before>import TWEEN from 'tween.js';

const defaultOpts = {
	fill: false,
	loop: false,
	colour: '#000',
	sampleSteps: 200,
	duration: 500
};

/*
 Sample the path with given id in the given number of steps
 (Forces the path arrays into the same number of co-ordinates)
*/
function samplePath(id, sampleSteps) {
	const path = document.getElementById(id);
	const length = path.getTotalLength();
	const points = [];
	for(let i = 0; i < sampleSteps; i++) {
		points.push(path.getPointAtLength(length * i / sampleSteps));
	}
	return points;
}

/*
 Draw the path with the given points on the supplied canvas context.
 If fill = true then attempts to close the path and fill it. If the start
 and end points don't connect setting fill to true in the options could
 result in some strange shapes. Fill/stroke with supplied colour.
*/
function drawPathToCanvas(ctx, points, fill, colour) {

	ctx.fillStyle = colour;
	ctx.strokeStyle = colour;
	const end = points[points.length - 1];

	// Draw points
	ctx.beginPath();
	ctx.moveTo(end.x, end.y);
	points.map(p => ctx.lineTo(p.x, p.y));
	ctx.closePath();
	if(fill) {
		ctx.fill();
	} else {
		ctx.stroke();
	}

}

export default class PathMorph {

	constructor(opts) {

		if(!opts.canvasId && !opts.fromPathId && !opts.toPathId) {
			console.error(`PathMorph classes must be instantiated with at least:
				canvasId, fromPathId and toPathId in the supplied options`);
		}

		this.opts = Object.assign({}, defaultOpts, opts);

		// Set main information
		this.canvas = document.getElementById(this.opts.canvasId);
		this.ctx = this.canvas.getContext('2d');
		this.interpolationPoint = { percentage: 0 };

		// Sample the from and too paths
		this.pathPointsFrom = samplePath(this.opts.fromPathId, this.opts.sampleSteps);
		this.pathPointsTo = samplePath(this.opts.toPathId, this.opts.sampleSteps);

		// Draw initial path
		drawPathToCanvas(this.ctx, this.pathPointsFrom, this.opts.fill, this.opts.colour);
	}

	/*
	 Get the array of points for the current percentage transition point betweeen the paths
	*/
	interpolatePaths() {
		const points = [];
		const from = this.pathPointsFrom;
		const to = this.pathPointsTo;

		for(let i = 0; i < this.opts.sampleSteps; i++) {
			points.push({
				x: from[i].x + (to[i].x - from[i].x) * this.interpolationPoint.percentage,
				y: from[i].y + (to[i].y - from[i].y) * this.interpolationPoint.percentage
			});
		}
		return points;
	}

	/*
	 Tween the percentage interpolation value over the supplied duration. Move from 0 -> 1
	 if reverse is false, otherwise return from 1 to 0
	*/
	stepInterpolationPercentage(reverse = false) {
		new TWEEN.Tween(this.interpolationPoint)
			.to({ percentage: reverse ? 0 : 1 }, this.opts.duration)
			.easing(TWEEN.Easing.Cubic.InOut)
			.start();
	}

	/*
	 Draw the current interpolated points path and update the Tweening function
	 (keeps things in sync)
	*/
	animate(time) {
		if(performance.now() <= this.endTime) {
			this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
			drawPathToCanvas(this.ctx, this.interpolatePaths(), this.opts.fill, this.opts.colour);
			window.requestAnimationFrame(this.animate.bind(this));
			TWEEN.update(time);
		}
	}

	/*
	 Animate from the 'from' path to the 'to' path
	*/
	forwards() {
		this.stepInterpolationPercentage();
		this.endTime = performance.now() + this.opts.duration;
		this.animate();
	}

	/*
	 Animate from the 'to' path to the 'from' path
	*/
	backwards() {
		this.stepInterpolationPercentage(/* reverse */ true);
		this.endTime = performance.now() + this.opts.duration;
		this.animate();
	}

}
<commit_msg>Use Americanised 'color' 😔<commit_after>import TWEEN from 'tween.js';

const defaultOpts = {
	fill: false,
	loop: false,
	color: '#000',
	sampleSteps: 200,
	duration: 500
};

/*
 Sample the path with given id in the given number of steps
 (Forces the path arrays into the same number of co-ordinates)
*/
function samplePath(id, sampleSteps) {
	const path = document.getElementById(id);
	const length = path.getTotalLength();
	const points = [];
	for(let i = 0; i < sampleSteps; i++) {
		points.push(path.getPointAtLength(length * i / sampleSteps));
	}
	return points;
}

/*
 Draw the path with the given points on the supplied canvas context.
 If fill = true then attempts to close the path and fill it. If the start
 and end points don't connect setting fill to true in the options could
 result in some strange shapes. Fill/stroke with supplied color.
*/
function drawPathToCanvas(ctx, points, fill, color) {

	ctx.fillStyle = color;
	ctx.strokeStyle = color;
	const end = points[points.length - 1];

	// Draw points
	ctx.beginPath();
	ctx.moveTo(end.x, end.y);
	points.map(p => ctx.lineTo(p.x, p.y));
	ctx.closePath();
	if(fill) {
		ctx.fill();
	} else {
		ctx.stroke();
	}

}

export default class PathMorph {

	constructor(opts) {

		if(!opts.canvasId && !opts.fromPathId && !opts.toPathId) {
			console.error(`PathMorph classes must be instantiated with at least:
				canvasId, fromPathId and toPathId in the supplied options`);
		}

		this.opts = Object.assign({}, defaultOpts, opts);

		// Set main information
		this.canvas = document.getElementById(this.opts.canvasId);
		this.ctx = this.canvas.getContext('2d');
		this.interpolationPoint = { percentage: 0 };

		// Sample the from and to paths
		this.pathPointsFrom = samplePath(this.opts.fromPathId, this.opts.sampleSteps);
		this.pathPointsTo = samplePath(this.opts.toPathId, this.opts.sampleSteps);

		// Draw initial path
		drawPathToCanvas(this.ctx, this.pathPointsFrom, this.opts.fill, this.opts.color);
	}

	/*
	 Get the array of points for the current percentage transition point betweeen the paths
	*/
	interpolatePaths() {
		const points = [];
		const from = this.pathPointsFrom;
		const to = this.pathPointsTo;

		for(let i = 0; i < this.opts.sampleSteps; i++) {
			points.push({
				x: from[i].x + (to[i].x - from[i].x) * this.interpolationPoint.percentage,
				y: from[i].y + (to[i].y - from[i].y) * this.interpolationPoint.percentage
			});
		}
		return points;
	}

	/*
	 Tween the percentage interpolation value over the supplied duration. Move from 0 -> 1
	 if reverse is false, otherwise return from 1 to 0
	*/
	stepInterpolationPercentage(reverse = false) {
		new TWEEN.Tween(this.interpolationPoint)
			.to({ percentage: reverse ? 0 : 1 }, this.opts.duration)
			.easing(TWEEN.Easing.Cubic.InOut)
			.start();
	}

	/*
	 Draw the current interpolated points path and update the Tweening function
	 (keeps things in sync)
	*/
	animate(time) {
		if(performance.now() <= this.endTime) {
			this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
			drawPathToCanvas(this.ctx, this.interpolatePaths(), this.opts.fill, this.opts.color);
			window.requestAnimationFrame(this.animate.bind(this));
			TWEEN.update(time);
		}
	}

	/*
	 Animate from the 'from' path to the 'to' path
	*/
	forwards() {
		this.stepInterpolationPercentage();
		this.endTime = performance.now() + this.opts.duration;
		this.animate();
	}

	/*
	 Animate from the 'to' path to the 'from' path
	*/
	backwards() {
		this.stepInterpolationPercentage(/* reverse */ true);
		this.endTime = performance.now() + this.opts.duration;
		this.animate();
	}

}
<|endoftext|>


<commit_before>var apiKey2 = "http://quotesondesign.com/api/3.0/api-3.0.json?callback=";
var apiKey = "http://api.icndb.com/jokes/random?limitTo=nerdy";

var quoteSign = "

";

function parseQuoteData(data) {
    $("#quote").empty();

    $("#quote").append(data.value.joke);
}

$(document).ready(function () {

    $.getJSON(apiKey, parseQuoteData);

    $("#newQuote").on("click", function () {
        $.getJSON(apiKey, parseQuoteData);
    });
});<commit_msg>Update main.js<commit_after>var apiKey2 = "http://quotesondesign.com/api/3.0/api-3.0.json?callback=";
var apiKey = "https://api.icndb.com/jokes/random?limitTo=nerdy";

var quoteSign = "

";

function parseQuoteData(data) {
    $("#quote").empty();

    $("#quote").append(data.value.joke);
}

$(document).ready(function () {

    $.getJSON(apiKey, parseQuoteData);

    $("#newQuote").on("click", function () {
        $.getJSON(apiKey, parseQuoteData);
    });
});
<|endoftext|>


<commit_before>'use strict';

const app = require('./app');
const port = app.get('port');
const server = app.listen(port);

server.on('listening', () =>
  console.log(`Feathers application started on ${app.get('host')}:${port}`)
);<commit_msg>Fixed server host and port<commit_after>'use strict';

const app = require('./app');

app.set('port', process.env.OPENSHIFT_NODEJS_PORT || 3022);
app.set('ip', process.env.OPENSHIFT_NODEJS_IP || "127.0.0.1");

const port = app.get('port');
const ip = app.get('ip');

const server = app.listen(port, ip);

server.on('listening', () =>
  console.log(`Feathers application started on ${ip}:${port}`)
);
<|endoftext|>


<commit_before>/* Creating the character counter! */

var charactersLeft = 140;
var text = "";

$("#tweetArea").keyup(function(e){
    var characters = $("#tweetArea").val().length;
    charactersLeft = (140 - (characters));
    $("#characterCount").replaceWith("Character(s) Left: " + charactersLeft + "");
});

function modifyText() {
    text = $("#tweetArea").val();
    var newText = "";
    for (var i = 0; i < text.length + 1; i++) {
        if ((i % 2) == 0) {
            newText += text.slice(i, i + 1)
        }
    }
    window.open("https://twitter.com/intent/tweet?text=" + newText + "&hashtags=#twit_er");
}

// Tweet
<commit_msg>Fixed hashtag issue<commit_after>/* Creating the character counter! */

var charactersLeft = 140;
var text = "";

$("#tweetArea").keyup(function(e){
    var characters = $("#tweetArea").val().length;
    charactersLeft = (140 - (characters));
    $("#characterCount").replaceWith("Character(s) Left: " + charactersLeft + "");
});

function modifyText() {
    text = $("#tweetArea").val();
    var newText = "";
    for (var i = 0; i < text.length + 1; i++) {
        if ((i % 2) == 0) {
            newText += text.slice(i, i + 1)
        }
    }
    window.open("https://twitter.com/intent/tweet?text=" + newText + "%23twit_er");
}

// Tweet
<|endoftext|>


<commit_before>/* eslint prefer-template: 0 */

import React from 'react'
import PropTypes from 'prop-types'
import {
  supportMultiple,
  fileAccepted,
  allFilesAccepted,
  fileMatchSize,
  onDocumentDragOver,
  getDataTransferItems
} from './utils'
import styles from './utils/styles'

class Dropzone extends React.Component {
  constructor(props, context) {
    super(props, context)
    this.composeHandlers = this.composeHandlers.bind(this)
    this.onClick = this.onClick.bind(this)
    this.onDocumentDrop = this.onDocumentDrop.bind(this)
    this.onDragEnter = this.onDragEnter.bind(this)
    this.onDragLeave = this.onDragLeave.bind(this)
    this.onDragOver = this.onDragOver.bind(this)
    this.onDragStart = this.onDragStart.bind(this)
    this.onDrop = this.onDrop.bind(this)
    this.onFileDialogCancel = this.onFileDialogCancel.bind(this)
    this.onInputElementClick = this.onInputElementClick.bind(this)

    this.setRef = this.setRef.bind(this)
    this.setRefs = this.setRefs.bind(this)

    this.isFileDialogActive = false

    this.state = {
      draggedFiles: [],
      acceptedFiles: [],
      rejectedFiles: []
    }
  }

  componentDidMount() {
    const { preventDropOnDocument } = this.props
    this.dragTargets = []

    if (preventDropOnDocument) {
      document.addEventListener('dragover', onDocumentDragOver, false)
      document.addEventListener('drop', this.onDocumentDrop, false)
    }
    this.fileInputEl.addEventListener('click', this.onInputElementClick, false)
    // Tried implementing addEventListener, but didn't work out
    document.body.onfocus = this.onFileDialogCancel
  }

  componentWillUnmount() {
    const { preventDropOnDocument } = this.props
    if (preventDropOnDocument) {
      document.removeEventListener('dragover', onDocumentDragOver)
      document.removeEventListener('drop', this.onDocumentDrop)
    }
    if (this.fileInputEl != null) {
      this.fileInputEl.removeEventListener('click', this.onInputElementClick, false)
    }
    // Can be replaced with removeEventListener, if addEventListener works
    if (document != null) {
      document.body.onfocus = null
    }
  }

  composeHandlers(handler) {
    if (this.props.disabled) {
      return null
    }

    return handler
  }

  onDocumentDrop(evt) {
    if (this.node && this.node.contains(evt.target)) {
      // if we intercepted an event for our instance, let it propagate down to the instance's onDrop handler
      return
    }
    evt.preventDefault()
    this.dragTargets = []
  }

  onDragStart(evt) {
    if (this.props.onDragStart) {
      this.props.onDragStart.call(this, evt)
    }
  }

  onDragEnter(evt) {
    evt.preventDefault()

    // Count the dropzone and any children that are entered.
    if (this.dragTargets.indexOf(evt.target) === -1) {
      this.dragTargets.push(evt.target)
    }

    this.setState({
      isDragActive: true, // Do not rely on files for the drag state. It doesn't work in Safari.
      draggedFiles: getDataTransferItems(evt)
    })

    if (this.props.onDragEnter) {
      this.props.onDragEnter.call(this, evt)
    }
  }

  onDragOver(evt) {
    // eslint-disable-line class-methods-use-this
    evt.preventDefault()
    evt.stopPropagation()
    try {
      evt.dataTransfer.dropEffect = 'copy' // eslint-disable-line no-param-reassign
    } catch (err) {
      // continue regardless of error
    }

    if (this.props.onDragOver) {
      this.props.onDragOver.call(this, evt)
    }
    return false
  }

  onDragLeave(evt) {
    evt.preventDefault()

    // Only deactivate once the dropzone and all children have been left.
    this.dragTargets = this.dragTargets.filter(el => el !== evt.target && this.node.contains(el))
    if (this.dragTargets.length > 0) {
      return
    }

    // Clear dragging files state
    this.setState({
      isDragActive: false,
      draggedFiles: []
    })

    if (this.props.onDragLeave) {
      this.props.onDragLeave.call(this, evt)
    }
  }

  onDrop(evt) {
    const { onDrop, onDropAccepted, onDropRejected, multiple, disablePreview, accept } = this.props
    const fileList = getDataTransferItems(evt)
    const acceptedFiles = []
    const rejectedFiles = []

    // Stop default browser behavior
    evt.preventDefault()

    // Reset the counter along with the drag on a drop.
    this.dragTargets = []
    this.isFileDialogActive = false

    fileList.forEach(file => {
      if (!disablePreview) {
        try {
          file.preview = window.URL.createObjectURL(file) // eslint-disable-line no-param-reassign
        } catch (err) {
          if (process.env.NODE_ENV !== 'production') {
            console.error('Failed to generate preview for file', file, err) // eslint-disable-line no-console
          }
        }
      }

      if (
        fileAccepted(file, accept) &&
        fileMatchSize(file, this.props.maxSize, this.props.minSize)
      ) {
        acceptedFiles.push(file)
      } else {
        rejectedFiles.push(file)
      }
    })

    if (!multiple) {
      // if not in multi mode add any extra accepted files to rejected.
      // This will allow end users to easily ignore a multi file drop in "single" mode.
      rejectedFiles.push(...acceptedFiles.splice(1))
    }

    if (onDrop) {
      onDrop.call(this, acceptedFiles, rejectedFiles, evt)
    }

    if (rejectedFiles.length > 0 && onDropRejected) {
      onDropRejected.call(this, rejectedFiles, evt)
    }

    if (acceptedFiles.length > 0 && onDropAccepted) {
      onDropAccepted.call(this, acceptedFiles, evt)
    }

    // Clear files value
    this.draggedFiles = null

    // Reset drag state
    this.setState({
      isDragActive: false,
      draggedFiles: [],
      acceptedFiles,
      rejectedFiles
    })
  }

  onClick(evt) {
    const { onClick, disableClick } = this.props
    if (!disableClick) {
      evt.stopPropagation()

      if (onClick) {
        onClick.call(this, evt)
      }

      // in IE11/Edge the file-browser dialog is blocking, ensure this is behind setTimeout
      // this is so react can handle state changes in the onClick prop above above
      // see: https://github.com/react-dropzone/react-dropzone/issues/450
      setTimeout(this.open.bind(this), 0)
    }
  }

  onInputElementClick(evt) {
    evt.stopPropagation()
    if (this.props.inputProps && this.props.inputProps.onClick) {
      this.props.inputProps.onClick()
    }
  }

  onFileDialogCancel() {
    // timeout will not recognize context of this method
    const { onFileDialogCancel } = this.props
    const { fileInputEl } = this
    let { isFileDialogActive } = this
    // execute the timeout only if the onFileDialogCancel is defined and FileDialog
    // is opened in the browser
    if (onFileDialogCancel && isFileDialogActive) {
      setTimeout(() => {
        // Returns an object as FileList
        const FileList = fileInputEl.files
        if (!FileList.length) {
          isFileDialogActive = false
          onFileDialogCancel()
        }
      }, 300)
    }
  }

  setRef(ref) {
    this.node = ref
  }

  setRefs(ref) {
    this.fileInputEl = ref
  }
  /**
   * Open system file upload dialog.
   *
   * @public
   */
  open() {
    this.isFileDialogActive = true
    this.fileInputEl.value = null
    this.fileInputEl.click()
  }

  renderChildren = (children, isDragActive, isDragAccept, isDragReject) => {
    if (typeof children === 'function') {
      return children({
        ...this.state,
        isDragActive,
        isDragAccept,
        isDragReject
      })
    }
    return children
  }

  render() {
    const {
      accept,
      acceptClassName,
      activeClassName,
      children,
      disabled,
      disabledClassName,
      inputProps,
      multiple,
      name,
      rejectClassName,
      ...rest
    } = this.props

    let {
      acceptStyle,
      activeStyle,
      className,
      disabledStyle,
      rejectStyle,
      style,
      ...props // eslint-disable-line prefer-const
    } = rest

    const { isDragActive, draggedFiles } = this.state
    const filesCount = draggedFiles.length
    const isMultipleAllowed = multiple || filesCount <= 1
    const isDragAccept = filesCount > 0 && allFilesAccepted(draggedFiles, this.props.accept)
    const isDragReject = filesCount > 0 && (!isDragAccept || !isMultipleAllowed)
    className = className || ''
    const noStyles =
      !className && !style && !activeStyle && !acceptStyle && !rejectStyle && !disabledStyle

    if (isDragActive && activeClassName) {
      className += ' ' + activeClassName
    }
    if (isDragAccept && acceptClassName) {
      className += ' ' + acceptClassName
    }
    if (isDragReject && rejectClassName) {
      className += ' ' + rejectClassName
    }
    if (disabled && disabledClassName) {
      className += ' ' + disabledClassName
    }

    if (noStyles) {
      style = styles.default
      activeStyle = styles.active
      acceptStyle = style.active
      rejectStyle = styles.rejected
      disabledStyle = styles.disabled
    }

    let appliedStyle = { ...style }
    if (activeStyle && isDragActive) {
      appliedStyle = {
        ...style,
        ...activeStyle
      }
    }
    if (acceptStyle && isDragAccept) {
      appliedStyle = {
        ...appliedStyle,
        ...acceptStyle
      }
    }
    if (rejectStyle && isDragReject) {
      appliedStyle = {
        ...appliedStyle,
        ...rejectStyle
      }
    }
    if (disabledStyle && disabled) {
      appliedStyle = {
        ...style,
        ...disabledStyle
      }
    }

    const inputAttributes = {
      accept,
      disabled,
      type: 'file',
      style: { display: 'none' },
      multiple: supportMultiple && multiple,
      ref: this.setRefs,
      onChange: this.onDrop,
      autoComplete: 'off'
    }

    if (name && name.length) {
      inputAttributes.name = name
    }

    // Remove custom properties before passing them to the wrapper div element
    const customProps = [
      'acceptedFiles',
      'preventDropOnDocument',
      'disablePreview',
      'disableClick',
      'activeClassName',
      'acceptClassName',
      'rejectClassName',
      'disabledClassName',
      'onDropAccepted',
      'onDropRejected',
      'onFileDialogCancel',
      'maxSize',
      'minSize'
    ]
    const divProps = { ...props }
    customProps.forEach(prop => delete divProps[prop])

    return (
      <div
        className={className}
        style={appliedStyle}
        {...divProps /* expand user provided props first so event handlers are never overridden */}
        onClick={this.composeHandlers(this.onClick)}
        onDragStart={this.composeHandlers(this.onDragStart)}
        onDragEnter={this.composeHandlers(this.onDragEnter)}
        onDragOver={this.composeHandlers(this.onDragOver)}
        onDragLeave={this.composeHandlers(this.onDragLeave)}
        onDrop={this.composeHandlers(this.onDrop)}
        ref={this.setRef}
        aria-disabled={disabled}
      >
        {this.renderChildren(children, isDragActive, isDragAccept, isDragReject)}
        <input
          {...inputProps /* expand user provided inputProps first so inputAttributes override them */}
          {...inputAttributes}
        />
      </div>
    )
  }
}

export default Dropzone

Dropzone.propTypes = {
  /**
   * Allow specific types of files. See https://github.com/okonet/attr-accept for more information.
   * Keep in mind that mime type determination is not reliable across platforms. CSV files,
   * for example, are reported as text/plain under macOS but as application/vnd.ms-excel under
   * Windows. In some cases there might not be a mime type set at all.
   * See: https://github.com/react-dropzone/react-dropzone/issues/276
   */
  accept: PropTypes.string,

  /**
   * Contents of the dropzone
   */
  children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),

  /**
   * Disallow clicking on the dropzone container to open file dialog
   */
  disableClick: PropTypes.bool,

  /**
 * Enable/disable the dropzone entirely
 */
  disabled: PropTypes.bool,

  /**
   * Enable/disable preview generation
   */
  disablePreview: PropTypes.bool,

  /**
   * If false, allow dropped items to take over the current browser window
   */
  preventDropOnDocument: PropTypes.bool,

  /**
   * Pass additional attributes to the `<input type="file"/>` tag
   */
  inputProps: PropTypes.object,

  /**
   * Allow dropping multiple files
   */
  multiple: PropTypes.bool,

  /**
   * `name` attribute for the input tag
   */
  name: PropTypes.string,

  /**
   * Maximum file size
   */
  maxSize: PropTypes.number,

  /**
   * Minimum file size
   */
  minSize: PropTypes.number,

  /**
   * className
   */
  className: PropTypes.string,

  /**
   * className for active state
   */
  activeClassName: PropTypes.string,

  /**
   * className for accepted state
   */
  acceptClassName: PropTypes.string,

  /**
   * className for rejected state
   */
  rejectClassName: PropTypes.string,

  /**
   * className for disabled state
   */
  disabledClassName: PropTypes.string,

  /**
   * CSS styles to apply
   */
  style: PropTypes.object,

  /**
   * CSS styles to apply when drag is active
   */
  activeStyle: PropTypes.object,

  /**
   * CSS styles to apply when drop will be accepted
   */
  acceptStyle: PropTypes.object,

  /**
   * CSS styles to apply when drop will be rejected
   */
  rejectStyle: PropTypes.object,

  /**
   * CSS styles to apply when dropzone is disabled
   */
  disabledStyle: PropTypes.object,

  /**
   * onClick callback
   * @param {Event} event
   */
  onClick: PropTypes.func,

  /**
   * onDrop callback
   */
  onDrop: PropTypes.func,

  /**
   * onDropAccepted callback
   */
  onDropAccepted: PropTypes.func,

  /**
   * onDropRejected callback
   */
  onDropRejected: PropTypes.func,

  /**
   * onDragStart callback
   */
  onDragStart: PropTypes.func,

  /**
   * onDragEnter callback
   */
  onDragEnter: PropTypes.func,

  /**
   * onDragOver callback
   */
  onDragOver: PropTypes.func,

  /**
   * onDragLeave callback
   */
  onDragLeave: PropTypes.func,

  /**
   * Provide a callback on clicking the cancel button of the file dialog
   */
  onFileDialogCancel: PropTypes.func
}

Dropzone.defaultProps = {
  preventDropOnDocument: true,
  disabled: false,
  disablePreview: false,
  disableClick: false,
  multiple: true,
  maxSize: Infinity,
  minSize: 0
}
<commit_msg>style: Use default value assignment<commit_after>/* eslint prefer-template: 0 */

import React from 'react'
import PropTypes from 'prop-types'
import {
  supportMultiple,
  fileAccepted,
  allFilesAccepted,
  fileMatchSize,
  onDocumentDragOver,
  getDataTransferItems
} from './utils'
import styles from './utils/styles'

class Dropzone extends React.Component {
  constructor(props, context) {
    super(props, context)
    this.composeHandlers = this.composeHandlers.bind(this)
    this.onClick = this.onClick.bind(this)
    this.onDocumentDrop = this.onDocumentDrop.bind(this)
    this.onDragEnter = this.onDragEnter.bind(this)
    this.onDragLeave = this.onDragLeave.bind(this)
    this.onDragOver = this.onDragOver.bind(this)
    this.onDragStart = this.onDragStart.bind(this)
    this.onDrop = this.onDrop.bind(this)
    this.onFileDialogCancel = this.onFileDialogCancel.bind(this)
    this.onInputElementClick = this.onInputElementClick.bind(this)

    this.setRef = this.setRef.bind(this)
    this.setRefs = this.setRefs.bind(this)

    this.isFileDialogActive = false

    this.state = {
      draggedFiles: [],
      acceptedFiles: [],
      rejectedFiles: []
    }
  }

  componentDidMount() {
    const { preventDropOnDocument } = this.props
    this.dragTargets = []

    if (preventDropOnDocument) {
      document.addEventListener('dragover', onDocumentDragOver, false)
      document.addEventListener('drop', this.onDocumentDrop, false)
    }
    this.fileInputEl.addEventListener('click', this.onInputElementClick, false)
    // Tried implementing addEventListener, but didn't work out
    document.body.onfocus = this.onFileDialogCancel
  }

  componentWillUnmount() {
    const { preventDropOnDocument } = this.props
    if (preventDropOnDocument) {
      document.removeEventListener('dragover', onDocumentDragOver)
      document.removeEventListener('drop', this.onDocumentDrop)
    }
    if (this.fileInputEl != null) {
      this.fileInputEl.removeEventListener('click', this.onInputElementClick, false)
    }
    // Can be replaced with removeEventListener, if addEventListener works
    if (document != null) {
      document.body.onfocus = null
    }
  }

  composeHandlers(handler) {
    if (this.props.disabled) {
      return null
    }

    return handler
  }

  onDocumentDrop(evt) {
    if (this.node && this.node.contains(evt.target)) {
      // if we intercepted an event for our instance, let it propagate down to the instance's onDrop handler
      return
    }
    evt.preventDefault()
    this.dragTargets = []
  }

  onDragStart(evt) {
    if (this.props.onDragStart) {
      this.props.onDragStart.call(this, evt)
    }
  }

  onDragEnter(evt) {
    evt.preventDefault()

    // Count the dropzone and any children that are entered.
    if (this.dragTargets.indexOf(evt.target) === -1) {
      this.dragTargets.push(evt.target)
    }

    this.setState({
      isDragActive: true, // Do not rely on files for the drag state. It doesn't work in Safari.
      draggedFiles: getDataTransferItems(evt)
    })

    if (this.props.onDragEnter) {
      this.props.onDragEnter.call(this, evt)
    }
  }

  onDragOver(evt) {
    // eslint-disable-line class-methods-use-this
    evt.preventDefault()
    evt.stopPropagation()
    try {
      evt.dataTransfer.dropEffect = 'copy' // eslint-disable-line no-param-reassign
    } catch (err) {
      // continue regardless of error
    }

    if (this.props.onDragOver) {
      this.props.onDragOver.call(this, evt)
    }
    return false
  }

  onDragLeave(evt) {
    evt.preventDefault()

    // Only deactivate once the dropzone and all children have been left.
    this.dragTargets = this.dragTargets.filter(el => el !== evt.target && this.node.contains(el))
    if (this.dragTargets.length > 0) {
      return
    }

    // Clear dragging files state
    this.setState({
      isDragActive: false,
      draggedFiles: []
    })

    if (this.props.onDragLeave) {
      this.props.onDragLeave.call(this, evt)
    }
  }

  onDrop(evt) {
    const { onDrop, onDropAccepted, onDropRejected, multiple, disablePreview, accept } = this.props
    const fileList = getDataTransferItems(evt)
    const acceptedFiles = []
    const rejectedFiles = []

    // Stop default browser behavior
    evt.preventDefault()

    // Reset the counter along with the drag on a drop.
    this.dragTargets = []
    this.isFileDialogActive = false

    fileList.forEach(file => {
      if (!disablePreview) {
        try {
          file.preview = window.URL.createObjectURL(file) // eslint-disable-line no-param-reassign
        } catch (err) {
          if (process.env.NODE_ENV !== 'production') {
            console.error('Failed to generate preview for file', file, err) // eslint-disable-line no-console
          }
        }
      }

      if (
        fileAccepted(file, accept) &&
        fileMatchSize(file, this.props.maxSize, this.props.minSize)
      ) {
        acceptedFiles.push(file)
      } else {
        rejectedFiles.push(file)
      }
    })

    if (!multiple) {
      // if not in multi mode add any extra accepted files to rejected.
      // This will allow end users to easily ignore a multi file drop in "single" mode.
      rejectedFiles.push(...acceptedFiles.splice(1))
    }

    if (onDrop) {
      onDrop.call(this, acceptedFiles, rejectedFiles, evt)
    }

    if (rejectedFiles.length > 0 && onDropRejected) {
      onDropRejected.call(this, rejectedFiles, evt)
    }

    if (acceptedFiles.length > 0 && onDropAccepted) {
      onDropAccepted.call(this, acceptedFiles, evt)
    }

    // Clear files value
    this.draggedFiles = null

    // Reset drag state
    this.setState({
      isDragActive: false,
      draggedFiles: [],
      acceptedFiles,
      rejectedFiles
    })
  }

  onClick(evt) {
    const { onClick, disableClick } = this.props
    if (!disableClick) {
      evt.stopPropagation()

      if (onClick) {
        onClick.call(this, evt)
      }

      // in IE11/Edge the file-browser dialog is blocking, ensure this is behind setTimeout
      // this is so react can handle state changes in the onClick prop above above
      // see: https://github.com/react-dropzone/react-dropzone/issues/450
      setTimeout(this.open.bind(this), 0)
    }
  }

  onInputElementClick(evt) {
    evt.stopPropagation()
    if (this.props.inputProps && this.props.inputProps.onClick) {
      this.props.inputProps.onClick()
    }
  }

  onFileDialogCancel() {
    // timeout will not recognize context of this method
    const { onFileDialogCancel } = this.props
    const { fileInputEl } = this
    let { isFileDialogActive } = this
    // execute the timeout only if the onFileDialogCancel is defined and FileDialog
    // is opened in the browser
    if (onFileDialogCancel && isFileDialogActive) {
      setTimeout(() => {
        // Returns an object as FileList
        const FileList = fileInputEl.files
        if (!FileList.length) {
          isFileDialogActive = false
          onFileDialogCancel()
        }
      }, 300)
    }
  }

  setRef(ref) {
    this.node = ref
  }

  setRefs(ref) {
    this.fileInputEl = ref
  }
  /**
   * Open system file upload dialog.
   *
   * @public
   */
  open() {
    this.isFileDialogActive = true
    this.fileInputEl.value = null
    this.fileInputEl.click()
  }

  renderChildren = (children, isDragActive, isDragAccept, isDragReject) => {
    if (typeof children === 'function') {
      return children({
        ...this.state,
        isDragActive,
        isDragAccept,
        isDragReject
      })
    }
    return children
  }

  render() {
    const {
      accept,
      acceptClassName,
      activeClassName,
      children,
      disabled,
      disabledClassName,
      inputProps,
      multiple,
      name,
      rejectClassName,
      ...rest
    } = this.props

    let {
      acceptStyle,
      activeStyle,
      className = '',
      disabledStyle,
      rejectStyle,
      style,
      ...props // eslint-disable-line prefer-const
    } = rest

    const { isDragActive, draggedFiles } = this.state
    const filesCount = draggedFiles.length
    const isMultipleAllowed = multiple || filesCount <= 1
    const isDragAccept = filesCount > 0 && allFilesAccepted(draggedFiles, this.props.accept)
    const isDragReject = filesCount > 0 && (!isDragAccept || !isMultipleAllowed)
    const noStyles =
      !className && !style && !activeStyle && !acceptStyle && !rejectStyle && !disabledStyle

    if (isDragActive && activeClassName) {
      className += ' ' + activeClassName
    }
    if (isDragAccept && acceptClassName) {
      className += ' ' + acceptClassName
    }
    if (isDragReject && rejectClassName) {
      className += ' ' + rejectClassName
    }
    if (disabled && disabledClassName) {
      className += ' ' + disabledClassName
    }

    if (noStyles) {
      style = styles.default
      activeStyle = styles.active
      acceptStyle = style.active
      rejectStyle = styles.rejected
      disabledStyle = styles.disabled
    }

    let appliedStyle = { ...style }
    if (activeStyle && isDragActive) {
      appliedStyle = {
        ...style,
        ...activeStyle
      }
    }
    if (acceptStyle && isDragAccept) {
      appliedStyle = {
        ...appliedStyle,
        ...acceptStyle
      }
    }
    if (rejectStyle && isDragReject) {
      appliedStyle = {
        ...appliedStyle,
        ...rejectStyle
      }
    }
    if (disabledStyle && disabled) {
      appliedStyle = {
        ...style,
        ...disabledStyle
      }
    }

    const inputAttributes = {
      accept,
      disabled,
      type: 'file',
      style: { display: 'none' },
      multiple: supportMultiple && multiple,
      ref: this.setRefs,
      onChange: this.onDrop,
      autoComplete: 'off'
    }

    if (name && name.length) {
      inputAttributes.name = name
    }

    // Remove custom properties before passing them to the wrapper div element
    const customProps = [
      'acceptedFiles',
      'preventDropOnDocument',
      'disablePreview',
      'disableClick',
      'activeClassName',
      'acceptClassName',
      'rejectClassName',
      'disabledClassName',
      'onDropAccepted',
      'onDropRejected',
      'onFileDialogCancel',
      'maxSize',
      'minSize'
    ]
    const divProps = { ...props }
    customProps.forEach(prop => delete divProps[prop])

    return (
      <div
        className={className}
        style={appliedStyle}
        {...divProps /* expand user provided props first so event handlers are never overridden */}
        onClick={this.composeHandlers(this.onClick)}
        onDragStart={this.composeHandlers(this.onDragStart)}
        onDragEnter={this.composeHandlers(this.onDragEnter)}
        onDragOver={this.composeHandlers(this.onDragOver)}
        onDragLeave={this.composeHandlers(this.onDragLeave)}
        onDrop={this.composeHandlers(this.onDrop)}
        ref={this.setRef}
        aria-disabled={disabled}
      >
        {this.renderChildren(children, isDragActive, isDragAccept, isDragReject)}
        <input
          {...inputProps /* expand user provided inputProps first so inputAttributes override them */}
          {...inputAttributes}
        />
      </div>
    )
  }
}

export default Dropzone

Dropzone.propTypes = {
  /**
   * Allow specific types of files. See https://github.com/okonet/attr-accept for more information.
   * Keep in mind that mime type determination is not reliable across platforms. CSV files,
   * for example, are reported as text/plain under macOS but as application/vnd.ms-excel under
   * Windows. In some cases there might not be a mime type set at all.
   * See: https://github.com/react-dropzone/react-dropzone/issues/276
   */
  accept: PropTypes.string,

  /**
   * Contents of the dropzone
   */
  children: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),

  /**
   * Disallow clicking on the dropzone container to open file dialog
   */
  disableClick: PropTypes.bool,

  /**
 * Enable/disable the dropzone entirely
 */
  disabled: PropTypes.bool,

  /**
   * Enable/disable preview generation
   */
  disablePreview: PropTypes.bool,

  /**
   * If false, allow dropped items to take over the current browser window
   */
  preventDropOnDocument: PropTypes.bool,

  /**
   * Pass additional attributes to the `<input type="file"/>` tag
   */
  inputProps: PropTypes.object,

  /**
   * Allow dropping multiple files
   */
  multiple: PropTypes.bool,

  /**
   * `name` attribute for the input tag
   */
  name: PropTypes.string,

  /**
   * Maximum file size
   */
  maxSize: PropTypes.number,

  /**
   * Minimum file size
   */
  minSize: PropTypes.number,

  /**
   * className
   */
  className: PropTypes.string,

  /**
   * className for active state
   */
  activeClassName: PropTypes.string,

  /**
   * className for accepted state
   */
  acceptClassName: PropTypes.string,

  /**
   * className for rejected state
   */
  rejectClassName: PropTypes.string,

  /**
   * className for disabled state
   */
  disabledClassName: PropTypes.string,

  /**
   * CSS styles to apply
   */
  style: PropTypes.object,

  /**
   * CSS styles to apply when drag is active
   */
  activeStyle: PropTypes.object,

  /**
   * CSS styles to apply when drop will be accepted
   */
  acceptStyle: PropTypes.object,

  /**
   * CSS styles to apply when drop will be rejected
   */
  rejectStyle: PropTypes.object,

  /**
   * CSS styles to apply when dropzone is disabled
   */
  disabledStyle: PropTypes.object,

  /**
   * onClick callback
   * @param {Event} event
   */
  onClick: PropTypes.func,

  /**
   * onDrop callback
   */
  onDrop: PropTypes.func,

  /**
   * onDropAccepted callback
   */
  onDropAccepted: PropTypes.func,

  /**
   * onDropRejected callback
   */
  onDropRejected: PropTypes.func,

  /**
   * onDragStart callback
   */
  onDragStart: PropTypes.func,

  /**
   * onDragEnter callback
   */
  onDragEnter: PropTypes.func,

  /**
   * onDragOver callback
   */
  onDragOver: PropTypes.func,

  /**
   * onDragLeave callback
   */
  onDragLeave: PropTypes.func,

  /**
   * Provide a callback on clicking the cancel button of the file dialog
   */
  onFileDialogCancel: PropTypes.func
}

Dropzone.defaultProps = {
  preventDropOnDocument: true,
  disabled: false,
  disablePreview: false,
  disableClick: false,
  multiple: true,
  maxSize: Infinity,
  minSize: 0
}
<|endoftext|>


<commit_before>/**
 * ===================================================================
 * Main js
 *
 * -------------------------------------------------------------------
 */

(function($) {

	"use strict";

	/* --------------------------------------------------- */
	/* Preloader
	------------------------------------------------------ */
   $(window).load(function() {
      // will first fade out the loading animation
    	$("#loader").fadeOut("slow", function(){

        // will fade out the whole DIV that covers the website.
        $("#preloader").delay(300).fadeOut("slow");

      });
  	})

  	/*---------------------------------------------------- */
	/* FitVids
	------------------------------------------------------ */
  	$(".fluid-video-wrapper").fitVids();

	/* --------------------------------------------------- */
	/*  Vegas Slideshow
	------------------------------------------------------ */
	$(".home-slides").vegas({
		transition: 'fade',
		transitionDuration: 2500,
		delay: 5000,
    	slides: [
       	{ src: "images/slides/03.jpg" },
        	{ src: "images/slides/02.jpg" },
        	{ src: "images/slides/01.jpg" }
    	]
	});

	/* --------------------------------------------------- */
	/*  Particle JS
	------------------------------------------------------ */
	$('.home-particles').particleground({
	   dotColor: '#fff',
	   lineColor: '#555555',
	   particleRadius: 6,
	   curveLines: true,
	   density: 10000,
	   proximity: 110
	});

	/*-----------------------------------------------------*/
	/* tabs
  	-------------------------------------------------------*/
	$(".tab-content").hide();
	$(".tab-content").first().show();

	$("ul.tabs li").click(function () {
	   $("ul.tabs li").removeClass("active");
	   $(this).addClass("active");
	   $(".tab-content").hide();
	   var activeTab = $(this).attr("data-id");
	   $("#" + activeTab).fadeIn(700);
	});

	/*----------------------------------------------------*/
  	/* Smooth Scrolling
  	------------------------------------------------------*/
  	$('.smoothscroll').on('click', function (e) {

	 	e.preventDefault();

   	var target = this.hash,
    	$target = $(target);

    	$('html, body').stop().animate({
       	'scrollTop': $target.offset().top
      }, 800, 'swing', function () {
      	window.location.hash = target;
      });

  	});

  	/* --------------------------------------------------- */
	/*  Placeholder Plugin Settings
	------------------------------------------------------ */
	$('input, textarea, select').placeholder()

  	/*---------------------------------------------------- */
   /* ajaxchimp
	------------------------------------------------------ */

	// Example MailChimp url: http://xxx.xxx.list-manage.com/subscribe/post?u=xxx&id=xxx
	var mailChimpURL = 'http://facebook.us8.list-manage.com/subscribe/post?u=cdb7b577e41181934ed6a6a44&id=e65110b38d'

	$('#mc-form').ajaxChimp({

		language: 'es',
	   url: mailChimpURL

	});

	// Mailchimp translation
	//
	//  Defaults:
	//	 'submit': 'Submitting...',
	//  0: 'We have sent you a confirmation email',
	//  1: 'Please enter a value',
	//  2: 'An email address must contain a single @',
	//  3: 'The domain portion of the email address is invalid (the portion after the @: )',
	//  4: 'The username portion of the email address is invalid (the portion before the @: )',
	//  5: 'This email address looks fake or invalid. Please enter a real email address'

	$.ajaxChimp.translations.es = {
	  'submit': 'Submitting...',
	  0: ' We have sent you a confirmation email',
	  1: ' You must enter a valid e-mail address.',
	  2: ' E-mail address is not valid.',
	  3: ' E-mail address is not valid.',
	  4: ' E-mail address is not valid.',
	  5: ' E-mail address is not valid.'
	}

	/*---------------------------------------------------- */
	/*	contact form
	------------------------------------------------------ */

	/* local validation */
	$('#contactForm').validate({

		/* submit via ajax */
		submitHandler: function(form) {

			var sLoader = $('#submit-loader');

			$.ajax({

		      type: "POST",
		      url: "inc/sendEmail.php",
		      data: $(form).serialize(),
		      beforeSend: function() {

		      	sLoader.fadeIn();

		      },
		      success: function(msg) {

	            // Message was sent
	            if (msg == 'OK') {
	            	sLoader.fadeOut();
	               $('#message-warning').hide();
	               $('#contactForm').fadeOut();
	               $('#message-success').fadeIn();
	            }
	            // There was an error
	            else {
	            	sLoader.fadeOut();
	               $('#message-warning').html(msg);
		            $('#message-warning').fadeIn();
	            }

		      },
		      error: function() {

		      	sLoader.fadeOut();
		      	$('#message-warning').html("Something went wrong. Please try again.");
		         $('#message-warning').fadeIn();

		      }

	      });
  		}

	});

	/*----------------------------------------------------*/
	/* Final Countdown Settings
	------------------------------------------------------ */
	var finalDate = '2018/05/01';

	$('div#counter').countdown(finalDate)
   	.on('update.countdown', function(event) {

   		$(this).html(event.strftime('
' +
   											 '%D days' +
   										 	 '%H hours' +
   										 	 '
' +
   										 	 '
' +
   										 	 '%M mins' +
   										 	 '%S secs' +
   										 	 '
'));

   });

})(jQuery);
<commit_msg>Update main.js<commit_after>/**
 * ===================================================================
 * Main js
 *
 * -------------------------------------------------------------------
 */

(function($) {

	"use strict";

	/* --------------------------------------------------- */
	/* Preloader
	------------------------------------------------------ */
   $(window).load(function() {
      // will first fade out the loading animation
    	$("#loader").fadeOut("slow", function(){

        // will fade out the whole DIV that covers the website.
        $("#preloader").delay(300).fadeOut("slow");

      });
  	})

  	/*---------------------------------------------------- */
	/* FitVids
	------------------------------------------------------ */
  	$(".fluid-video-wrapper").fitVids();

	/* --------------------------------------------------- */
	/*  Vegas Slideshow
	------------------------------------------------------ */
	$(".home-slides").vegas({
		transition: 'fade',
		transitionDuration: 2500,
		delay: 5000,
    	slides: [
       	{ src: "images/slides/03.jpg" },
        	{ src: "images/slides/02.jpg" },
        	{ src: "images/slides/01.jpg" }
    	]
	});

	/* --------------------------------------------------- */
	/*  Particle JS
	------------------------------------------------------ */
	$('.home-particles').particleground({
	   dotColor: '#fff',
	   lineColor: '#555555',
	   particleRadius: 6,
	   curveLines: true,
	   density: 10000,
	   proximity: 110
	});

	/*-----------------------------------------------------*/
	/* tabs
  	-------------------------------------------------------*/
	$(".tab-content").hide();
	$(".tab-content").first().show();

	$("ul.tabs li").click(function () {
	   $("ul.tabs li").removeClass("active");
	   $(this).addClass("active");
	   $(".tab-content").hide();
	   var activeTab = $(this).attr("data-id");
	   $("#" + activeTab).fadeIn(700);
	});

	/*----------------------------------------------------*/
  	/* Smooth Scrolling
  	------------------------------------------------------*/
  	$('.smoothscroll').on('click', function (e) {

	 	e.preventDefault();

   	var target = this.hash,
    	$target = $(target);

    	$('html, body').stop().animate({
       	'scrollTop': $target.offset().top
      }, 800, 'swing', function () {
      	window.location.hash = target;
      });

  	});

  	/* --------------------------------------------------- */
	/*  Placeholder Plugin Settings
	------------------------------------------------------ */
	$('input, textarea, select').placeholder()

  	/*---------------------------------------------------- */
   /* ajaxchimp
	------------------------------------------------------ */

	// Example MailChimp url: http://xxx.xxx.list-manage.com/subscribe/post?u=xxx&id=xxx
	var mailChimpURL = 'http://facebook.us8.list-manage.com/subscribe/post?u=cdb7b577e41181934ed6a6a44&id=e65110b38d'

	$('#mc-form').ajaxChimp({

		language: 'es',
	   url: mailChimpURL

	});

	// Mailchimp translation
	//
	//  Defaults:
	//	 'submit': 'Submitting...',
	//  0: 'We have sent you a confirmation email',
	//  1: 'Please enter a value',
	//  2: 'An email address must contain a single @',
	//  3: 'The domain portion of the email address is invalid (the portion after the @: )',
	//  4: 'The username portion of the email address is invalid (the portion before the @: )',
	//  5: 'This email address looks fake or invalid. Please enter a real email address'

	$.ajaxChimp.translations.es = {
	  'submit': 'Submitting...',
	  0: ' We have sent you a confirmation email',
	  1: ' You must enter a valid e-mail address.',
	  2: ' E-mail address is not valid.',
	  3: ' E-mail address is not valid.',
	  4: ' E-mail address is not valid.',
	  5: ' E-mail address is not valid.'
	}

	/*---------------------------------------------------- */
	/*	contact form
	------------------------------------------------------ */

	/* local validation */
	$('#contactForm').validate({

		/* submit via ajax */
		submitHandler: function(form) {

			var sLoader = $('#submit-loader');

			$.ajax({

		      type: "POST",
		      url: "inc/sendEmail.php",
		      data: $(form).serialize(),
		      beforeSend: function() {

		      	sLoader.fadeIn();

		      },
		      success: function(msg) {

	            // Message was sent
	            if (msg == 'OK') {
	            	sLoader.fadeOut();
	               $('#message-warning').hide();
	               $('#contactForm').fadeOut();
	               $('#message-success').fadeIn();
	            }
	            // There was an error
	            else {
	            	sLoader.fadeOut();
	               $('#message-warning').html(msg);
		            $('#message-warning').fadeIn();
	            }

		      },
		      error: function() {

		      	sLoader.fadeOut();
		      	$('#message-warning').html("Something went wrong. Please try again.");
		         $('#message-warning').fadeIn();

		      }

	      });
  		}

	});

	/*----------------------------------------------------*/
	/* Final Countdown Settings
	------------------------------------------------------ */
	var finalDate = '2017/05/01';

	$('div#counter').countdown(finalDate)
   	.on('update.countdown', function(event) {

   		$(this).html(event.strftime('
' +
   											 '%D days' +
   										 	 '%H hours' +
   										 	 '
' +
   										 	 '
' +
   										 	 '%M mins' +
   										 	 '%S secs' +
   										 	 '
'));

   });

})(jQuery);
<|endoftext|>


<commit_before>import ChatBox from "./ChatBoxReducer"
import {createStore, applyMiddleware} from 'redux';
import ReactDOM from 'react-dom';
import Chat from "./ChatComponent"

let store = createStore(ChatBox);
console.log("Hello!",  ChatBox);
setInterval(() =>
            store.dispatch({type:"ADD_MESSAGE", message: "Hello hello"})
            , 1000);

const render = () => {
  ReactDOM.render(
      <Chat messages={store.getState()}/>, document.getElementById("app")
  );
}

store.subscribe(render)

<commit_msg>Get a crappy text input field.<commit_after>import ChatBox from "./ChatBoxReducer"
import {createStore, applyMiddleware} from 'redux';
import ReactDOM from 'react-dom';
import Chat from "./ChatComponent"
import React from 'react';
import TextInput from "./TextComponent";

let store = createStore(ChatBox);

const send = (value) =>{
  store.dispatch({type: "ADD_MESSAGE", message: value});
};

const render = () => {
  ReactDOM.render(
    (<div>
     <Chat messages={store.getState()} />
     <TextInput send={send} />

       </div>)
      , document.getElementById("app")
  );
}

store.subscribe(render)

store.dispatch({type:"blah"});

<|endoftext|>