<commit_before>chrome.runtime.sendMessage({}, function(response) {
  var tc = {
    settings: {
      speed: 1.0,           // default 1x
      resetSpeed: 1.0,      // default 1x
      speedStep: 0.1,       // default 0.1x
      fastSpeed: 1.8,       // default 1.8x
      rewindTime: 10,       // default 10s
      advanceTime: 10,      // default 10s
      resetKeyCode:  82,    // default: R
      slowerKeyCode: 83,    // default: S
      fasterKeyCode: 68,    // default: D
      rewindKeyCode: 90,    // default: Z
      advanceKeyCode: 88,   // default: X
      displayKeyCode: 86,   // default: V
      fastKeyCode: 71,      // default: G
      rememberSpeed: false, // default: false
      startHidden: false,   // default: false
      blacklist: `
        www.instagram.com
        twitter.com
        vine.co
        imgur.com
      `.replace(/^\s+|\s+$/gm,'')
    }
  };

  chrome.storage.sync.get(tc.settings, function(storage) {
    tc.settings.speed = Number(storage.speed);
    tc.settings.resetSpeed = Number(storage.resetSpeed);
    tc.settings.speedStep = Number(storage.speedStep);
    tc.settings.fastSpeed = Number(storage.fastSpeed);
    tc.settings.rewindTime = Number(storage.rewindTime);
    tc.settings.advanceTime = Number(storage.advanceTime);
    tc.settings.resetKeyCode = Number(storage.resetKeyCode);
    tc.settings.rewindKeyCode = Number(storage.rewindKeyCode);
    tc.settings.slowerKeyCode = Number(storage.slowerKeyCode);
    tc.settings.fasterKeyCode = Number(storage.fasterKeyCode);
    tc.settings.fastKeyCode = Number(storage.fastKeyCode);
    tc.settings.displayKeyCode = Number(storage.displayKeyCode);
    tc.settings.advanceKeyCode = Number(storage.advanceKeyCode);
    tc.settings.rememberSpeed = Boolean(storage.rememberSpeed);
    tc.settings.startHidden = Boolean(storage.startHidden);
    tc.settings.blacklist = String(storage.blacklist);

    initializeWhenReady(document);
  });

  var forEach = Array.prototype.forEach;

  function defineVideoController() {
    tc.videoController = function(target, parent) {
      if (target.dataset['vscid']) {
        return;
      }

      this.video = target;
      this.parent = target.parentElement || parent;
      this.document = target.ownerDocument;
      this.id = Math.random().toString(36).substr(2, 9);
      if (!tc.settings.rememberSpeed) {
        tc.settings.speed = 1.0;
        tc.settings.resetSpeed = tc.settings.fastSpeed;
      }
      this.initializeControls();

      target.addEventListener('play', function(event) {
        target.playbackRate = tc.settings.speed;
      });

      target.addEventListener('ratechange', function(event) {
        // Ignore ratechange events on unitialized videos.
        // 0 == No information is available about the media resource.
        if (event.target.readyState > 0) {
          var speed = this.getSpeed();
          this.speedIndicator.textContent = speed;
          tc.settings.speed = speed;
          chrome.storage.sync.set({'speed': speed}, function() {
            console.log('Speed setting saved: ' + speed);
          });
        }
      }.bind(this));

      target.playbackRate = tc.settings.speed;
    };

    tc.videoController.prototype.getSpeed = function() {
      return parseFloat(this.video.playbackRate).toFixed(2);
    }

    tc.videoController.prototype.remove = function() {
      this.parentElement.removeChild(this);
    }

    tc.videoController.prototype.initializeControls = function() {
      var document = this.document;
      var speed = parseFloat(tc.settings.speed).toFixed(2),
        top = Math.max(this.video.offsetTop, 0) + "px",
        left = Math.max(this.video.offsetLeft, 0) + "px";

      var prevent = function(e) {
        e.preventDefault();
        e.stopPropagation();
      }

      var wrapper = document.createElement('div');
      wrapper.classList.add('vsc-controller');
      wrapper.dataset['vscid'] = this.id;
      wrapper.addEventListener('dblclick', prevent, true);
      wrapper.addEventListener('mousedown', prevent, true);
      wrapper.addEventListener('click', prevent, true);

      if (tc.settings.startHidden) {
        wrapper.classList.add('vsc-hidden');
      }

      var shadow = wrapper.createShadowRoot();
      var shadowTemplate = `

          ${speed}

            <button data-action="rewind" class="rw">«</button>
            <button data-action="slower">-</button>
            <button data-action="faster">+</button>
            <button data-action="advance" class="rw">»</button>
            <button data-action="display" class="hideButton">x</button>

      `;
      shadow.innerHTML = shadowTemplate;
      shadow.querySelector('.draggable').addEventListener('mousedown', (e) => {
        runAction(e.target.dataset['action'], document, false, e);
      });

      forEach.call(shadow.querySelectorAll('button'), function(button) {
        button.onclick = (e) => {
          runAction(e.target.dataset['action'], document, false, e);
        }
      });

      this.speedIndicator = shadow.querySelector('span');
      var fragment = document.createDocumentFragment();
      fragment.appendChild(wrapper);

      this.video.classList.add('vsc-initialized');
      this.video.dataset['vscid'] = this.id;

      switch (true) {
        case (location.hostname == 'www.amazon.com'):
        case (location.hostname == 'www.reddit.com'):
        case (/hbogo\./).test(location.hostname):
          // insert before parent to bypass overlay
          this.parent.parentElement.insertBefore(fragment, this.parent);
          break;

        default:
          // Note: when triggered via a MutationRecord, it's possible that the
          // target is not the immediate parent. This appends the controller as
          // the first element of the target, which may not be the parent.
          this.parent.insertBefore(fragment, this.parent.firstChild);
      }
    }
  }

  function initializeWhenReady(document) {
    escapeStringRegExp.matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
    function escapeStringRegExp(str) {
      return str.replace(escapeStringRegExp.matchOperatorsRe, '\\$&');
    }

    var blacklisted = false;
    tc.settings.blacklist.split("\n").forEach(match => {
      match = match.replace(/^\s+|\s+$/g,'')
      if (match.length == 0) {
        return;
      }

      var regexp = new RegExp(escapeStringRegExp(match));
      if (regexp.test(location.href)) {
        blacklisted = true;
        return;
      }
    })

    if (blacklisted)
      return;

    window.onload = () => {
      initializeNow(window.document)
    };
    if (document) {
      if (document.readyState === "complete") {
        initializeNow(document);
      } else {
        document.onreadystatechange = () => {
          if (document.readyState === "complete") {
            initializeNow(document);
          }
        }
      }
    }
  }
  function inIframe () {
    try {
      return window.self !== window.top;
    } catch (e) {
      return true;
    }
  }
  function initializeNow(document) {
      // enforce init-once due to redundant callers
      if (!document.body || document.body.classList.contains('vsc-initialized')) {
        return;
      }
      document.body.classList.add('vsc-initialized');

      if (document === window.document) {
        defineVideoController();
      } else {
        var link = document.createElement('link');
        link.href = chrome.runtime.getURL('inject.css');
        link.type = 'text/css';
        link.rel = 'stylesheet';
        document.head.appendChild(link);
      }
      var docs = Array(document)
      if(inIframe())
        docs.push(window.top.document);

      docs.forEach(function(doc) {
        doc.addEventListener('keydown', function(event) {
          var keyCode = event.keyCode;

          // Ignore if following modifier is active.
          if (!event.getModifierState
              || event.getModifierState("Alt")
              || event.getModifierState("Control")
              || event.getModifierState("Fn")
              || event.getModifierState("Meta")
              || event.getModifierState("Hyper")
              || event.getModifierState("OS")) {
            return;
          }

          // Ignore keydown event if typing in an input box
          if ((document.activeElement.nodeName === 'INPUT'
                && document.activeElement.getAttribute('type') === 'text')
              || document.activeElement.nodeName === 'TEXTAREA'
              || document.activeElement.isContentEditable) {
            return false;
          }

          if (keyCode == tc.settings.rewindKeyCode) {
            runAction('rewind', document, true)
          } else if (keyCode == tc.settings.advanceKeyCode) {
            runAction('advance', document, true)
          } else if (keyCode == tc.settings.fasterKeyCode) {
            runAction('faster', document, true)
          } else if (keyCode == tc.settings.slowerKeyCode) {
            runAction('slower', document, true)
          } else if (keyCode == tc.settings.resetKeyCode) {
            runAction('reset', document, true)
          } else if (keyCode == tc.settings.displayKeyCode) {
            runAction('display', document, true)
          } else if (keyCode == tc.settings.fastKeyCode) {
            runAction('fast', document, true);
          }

          return false;
        }, true);
      });

      function checkForVideo(node, parent, added) {
        if (node.nodeName === 'VIDEO') {
          if (added) {
            new tc.videoController(node, parent);
          } else {
            if (node.classList.contains('vsc-initialized')) {
              let id = node.dataset['vscid'];
              let ctrl = document.querySelector(`div[data-vscid="${id}"]`)
              if (ctrl) {
                ctrl.remove();
              }
              node.classList.remove('vsc-initialized');
              delete node.dataset['vscid'];
            }
          }
        } else if (node.children != undefined) {
          for (var i = 0; i < node.children.length; i++) {
            const child = node.children[i];
            checkForVideo(child, child.parentNode || parent, added);
          }
        }
      }

      var observer = new MutationObserver(function(mutations) {
        // Process the DOM nodes lazily
        requestIdleCallback(_ => {
          mutations.forEach(function(mutation) {
            forEach.call(mutation.addedNodes, function(node) {
              if (typeof node === "function")
                return;
              checkForVideo(node, node.parentNode || mutation.target, true);
            });
            forEach.call(mutation.removedNodes, function(node) {
              if (typeof node === "function")
                return;
              checkForVideo(node, node.parentNode || mutation.target, false);
            });
          });
        }, {timeout: 1000});
      });
      observer.observe(document, { childList: true, subtree: true });

      var videoTags = document.getElementsByTagName('video');
      forEach.call(videoTags, function(video) {
        new tc.videoController(video);
      });

      var frameTags = document.getElementsByTagName('iframe');
      forEach.call(frameTags, function(frame) {
        // Ignore frames we don't have permission to access (different origin).
        try { var childDocument = frame.contentDocument } catch (e) { return }
        initializeWhenReady(childDocument);
      });
  }

  function runAction(action, document, keyboard, e) {
    var videoTags = document.getElementsByTagName('video');
    videoTags.forEach = Array.prototype.forEach;

    videoTags.forEach(function(v) {
      var id = v.dataset['vscid'];
      var controller = document.querySelector(`div[data-vscid="${id}"]`);

      showController(controller);

      if (!v.classList.contains('vsc-cancelled')) {
        if (action === 'rewind') {
          v.currentTime -= tc.settings.rewindTime;
        } else if (action === 'advance') {
          v.currentTime += tc.settings.advanceTime;
        } else if (action === 'faster') {
          // Maximum playback speed in Chrome is set to 16:
          // https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp?l=168
          var s = Math.min( (v.playbackRate < 0.1 ? 0.0 : v.playbackRate) + tc.settings.speedStep, 16);
          v.playbackRate = Number(s.toFixed(2));
        } else if (action === 'slower') {
          // Video min rate is 0.0625:
          // https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp?l=167
          var s = Math.max(v.playbackRate - tc.settings.speedStep, 0.07);
          v.playbackRate = Number(s.toFixed(2));
        } else if (action === 'reset') {
          resetSpeed(v, 1.0);
        } else if (action === 'display') {
          controller.classList.add('vsc-manual');
          controller.classList.toggle('vsc-hidden');
        } else if (action === 'drag') {
          handleDrag(v, controller, e);
        } else if (action === 'fast') {
          resetSpeed(v, tc.settings.fastSpeed);
        }
      }
    });
  }

  function resetSpeed(v, target) {
    if (v.playbackRate === target) {
      if(v.playbackRate === tc.settings.resetSpeed)
      {
        if (target !== 1.0) {
          v.playbackRate = 1.0;
        } else {
          v.playbackRate = tc.settings.fastSpeed;
        }
      }
      else
      {
        v.playbackRate = tc.settings.resetSpeed;
      }
    } else {
      tc.settings.resetSpeed = v.playbackRate;
      chrome.storage.sync.set({'resetSpeed': v.playbackRate});
      v.playbackRate = target;
    }
  }

  function handleDrag(video, controller, e) {
    const shadowController = controller.shadowRoot.querySelector('#controller');

    // Find nearest parent of same size as video parent.
    var parentElement = controller.parentElement;
    while (parentElement.parentNode &&
      parentElement.parentNode.offsetHeight === parentElement.offsetHeight &&
      parentElement.parentNode.offsetWidth === parentElement.offsetWidth) {
      parentElement = parentElement.parentNode;
    }

    video.classList.add('vcs-dragging');
    shadowController.classList.add('dragging');

    const initialMouseXY = [e.clientX, e.clientY];
    const initialControllerXY = [
      parseInt(shadowController.style.left),
      parseInt(shadowController.style.top)
    ];

    const startDragging = (e) => {
      let style = shadowController.style;
      let dx = e.clientX - initialMouseXY[0];
      let dy = e.clientY -initialMouseXY[1];
      style.left = (initialControllerXY[0] + dx) + 'px';
      style.top  = (initialControllerXY[1] + dy) + 'px';
    }

    const stopDragging = () => {
      parentElement.removeEventListener('mousemove', startDragging);
      parentElement.removeEventListener('mouseup', stopDragging);
      parentElement.removeEventListener('mouseleave', stopDragging);

      shadowController.classList.remove('dragging');
      video.classList.remove('vcs-dragging');
    }

    parentElement.addEventListener('mouseup',stopDragging);
    parentElement.addEventListener('mouseleave',stopDragging);
    parentElement.addEventListener('mousemove', startDragging);
  }

  var timer;
  var animation = false;
  function showController(controller) {
    controller.classList.add('vcs-show');

    if (animation)
      clearTimeout(timer);

    animation = true;
    timer = setTimeout(function() {
      controller.classList.remove('vcs-show');
      animation = false;
    }, 2000);
  }
});
<commit_msg>Update inject.js (#346)<commit_after>chrome.runtime.sendMessage({}, function(response) {
  var tc = {
    settings: {
      speed: 1.0,           // default 1x
      resetSpeed: 1.0,      // default 1x
      speedStep: 0.1,       // default 0.1x
      fastSpeed: 1.8,       // default 1.8x
      rewindTime: 10,       // default 10s
      advanceTime: 10,      // default 10s
      resetKeyCode:  82,    // default: R
      slowerKeyCode: 83,    // default: S
      fasterKeyCode: 68,    // default: D
      rewindKeyCode: 90,    // default: Z
      advanceKeyCode: 88,   // default: X
      displayKeyCode: 86,   // default: V
      fastKeyCode: 71,      // default: G
      rememberSpeed: false, // default: false
      startHidden: false,   // default: false
      blacklist: `
        www.instagram.com
        twitter.com
        vine.co
        imgur.com
      `.replace(/^\s+|\s+$/gm,'')
    }
  };

  chrome.storage.sync.get(tc.settings, function(storage) {
    tc.settings.speed = Number(storage.speed);
    tc.settings.resetSpeed = Number(storage.resetSpeed);
    tc.settings.speedStep = Number(storage.speedStep);
    tc.settings.fastSpeed = Number(storage.fastSpeed);
    tc.settings.rewindTime = Number(storage.rewindTime);
    tc.settings.advanceTime = Number(storage.advanceTime);
    tc.settings.resetKeyCode = Number(storage.resetKeyCode);
    tc.settings.rewindKeyCode = Number(storage.rewindKeyCode);
    tc.settings.slowerKeyCode = Number(storage.slowerKeyCode);
    tc.settings.fasterKeyCode = Number(storage.fasterKeyCode);
    tc.settings.fastKeyCode = Number(storage.fastKeyCode);
    tc.settings.displayKeyCode = Number(storage.displayKeyCode);
    tc.settings.advanceKeyCode = Number(storage.advanceKeyCode);
    tc.settings.rememberSpeed = Boolean(storage.rememberSpeed);
    tc.settings.startHidden = Boolean(storage.startHidden);
    tc.settings.blacklist = String(storage.blacklist);

    initializeWhenReady(document);
  });

  var forEach = Array.prototype.forEach;

  function defineVideoController() {
    tc.videoController = function(target, parent) {
      if (target.dataset['vscid']) {
        return;
      }

      this.video = target;
      this.parent = target.parentElement || parent;
      this.document = target.ownerDocument;
      this.id = Math.random().toString(36).substr(2, 9);
      if (!tc.settings.rememberSpeed) {
        tc.settings.speed = 1.0;
        tc.settings.resetSpeed = tc.settings.fastSpeed;
      }
      this.initializeControls();

      target.addEventListener('play', function(event) {
        target.playbackRate = tc.settings.speed;
      });

      target.addEventListener('ratechange', function(event) {
        // Ignore ratechange events on unitialized videos.
        // 0 == No information is available about the media resource.
        if (event.target.readyState > 0) {
          var speed = this.getSpeed();
          this.speedIndicator.textContent = speed;
          tc.settings.speed = speed;
          chrome.storage.sync.set({'speed': speed}, function() {
            console.log('Speed setting saved: ' + speed);
          });
        }
      }.bind(this));

      target.playbackRate = tc.settings.speed;
    };

    tc.videoController.prototype.getSpeed = function() {
      return parseFloat(this.video.playbackRate).toFixed(2);
    }

    tc.videoController.prototype.remove = function() {
      this.parentElement.removeChild(this);
    }

    tc.videoController.prototype.initializeControls = function() {
      var document = this.document;
      var speed = parseFloat(tc.settings.speed).toFixed(2),
        top = Math.max(this.video.offsetTop, 0) + "px",
        left = Math.max(this.video.offsetLeft, 0) + "px";

      var prevent = function(e) {
        e.preventDefault();
        e.stopPropagation();
      }

      var wrapper = document.createElement('div');
      wrapper.classList.add('vsc-controller');
      wrapper.dataset['vscid'] = this.id;
      wrapper.addEventListener('dblclick', prevent, true);
      wrapper.addEventListener('mousedown', prevent, true);
      wrapper.addEventListener('click', prevent, true);

      if (tc.settings.startHidden) {
        wrapper.classList.add('vsc-hidden');
      }

      var shadow = wrapper.createShadowRoot();
      var shadowTemplate = `

          ${speed}

            <button data-action="rewind" class="rw">«</button>
            <button data-action="slower">-</button>
            <button data-action="faster">+</button>
            <button data-action="advance" class="rw">»</button>
            <button data-action="display" class="hideButton">x</button>

      `;
      shadow.innerHTML = shadowTemplate;
      shadow.querySelector('.draggable').addEventListener('mousedown', (e) => {
        runAction(e.target.dataset['action'], document, false, e);
      });

      forEach.call(shadow.querySelectorAll('button'), function(button) {
        button.onclick = (e) => {
          runAction(e.target.dataset['action'], document, false, e);
        }
      });

      this.speedIndicator = shadow.querySelector('span');
      var fragment = document.createDocumentFragment();
      fragment.appendChild(wrapper);

      this.video.classList.add('vsc-initialized');
      this.video.dataset['vscid'] = this.id;

      switch (true) {
        case (location.hostname == 'www.amazon.com'):
        case (location.hostname == 'www.reddit.com'):
        case (/hbogo\./).test(location.hostname):
          // insert before parent to bypass overlay
          this.parent.parentElement.insertBefore(fragment, this.parent);
          break;

        default:
          // Note: when triggered via a MutationRecord, it's possible that the
          // target is not the immediate parent. This appends the controller as
          // the first element of the target, which may not be the parent.
          this.parent.insertBefore(fragment, this.parent.firstChild);
      }
    }
  }

  function initializeWhenReady(document) {
    escapeStringRegExp.matchOperatorsRe = /[|\\{}()[\]^$+*?.]/g;
    function escapeStringRegExp(str) {
      return str.replace(escapeStringRegExp.matchOperatorsRe, '\\$&');
    }

    var blacklisted = false;
    tc.settings.blacklist.split("\n").forEach(match => {
      match = match.replace(/^\s+|\s+$/g,'')
      if (match.length == 0) {
        return;
      }

      var regexp = new RegExp(escapeStringRegExp(match));
      if (regexp.test(location.href)) {
        blacklisted = true;
        return;
      }
    })

    if (blacklisted)
      return;

    window.onload = () => {
      initializeNow(window.document)
    };
    if (document) {
      if (document.readyState === "complete") {
        initializeNow(document);
      } else {
        document.onreadystatechange = () => {
          if (document.readyState === "complete") {
            initializeNow(document);
          }
        }
      }
    }
  }
  function inIframe () {
    try {
      return window.self !== window.top;
    } catch (e) {
      return true;
    }
  }
  function initializeNow(document) {
      // enforce init-once due to redundant callers
      if (!document.body || document.body.classList.contains('vsc-initialized')) {
        return;
      }
      document.body.classList.add('vsc-initialized');

      if (document === window.document) {
        defineVideoController();
      } else {
        var link = document.createElement('link');
        link.href = chrome.runtime.getURL('inject.css');
        link.type = 'text/css';
        link.rel = 'stylesheet';
        document.head.appendChild(link);
      }
      var docs = Array(document)
      try {
        if (inIframe())
          docs.push(window.top.document);
      } catch (e) {
      }

      docs.forEach(function(doc) {
        doc.addEventListener('keydown', function(event) {
          var keyCode = event.keyCode;

          // Ignore if following modifier is active.
          if (!event.getModifierState
              || event.getModifierState("Alt")
              || event.getModifierState("Control")
              || event.getModifierState("Fn")
              || event.getModifierState("Meta")
              || event.getModifierState("Hyper")
              || event.getModifierState("OS")) {
            return;
          }

          // Ignore keydown event if typing in an input box
          if ((document.activeElement.nodeName === 'INPUT'
                && document.activeElement.getAttribute('type') === 'text')
              || document.activeElement.nodeName === 'TEXTAREA'
              || document.activeElement.isContentEditable) {
            return false;
          }

          if (keyCode == tc.settings.rewindKeyCode) {
            runAction('rewind', document, true)
          } else if (keyCode == tc.settings.advanceKeyCode) {
            runAction('advance', document, true)
          } else if (keyCode == tc.settings.fasterKeyCode) {
            runAction('faster', document, true)
          } else if (keyCode == tc.settings.slowerKeyCode) {
            runAction('slower', document, true)
          } else if (keyCode == tc.settings.resetKeyCode) {
            runAction('reset', document, true)
          } else if (keyCode == tc.settings.displayKeyCode) {
            runAction('display', document, true)
          } else if (keyCode == tc.settings.fastKeyCode) {
            runAction('fast', document, true);
          }

          return false;
        }, true);
      });

      function checkForVideo(node, parent, added) {
        if (node.nodeName === 'VIDEO') {
          if (added) {
            new tc.videoController(node, parent);
          } else {
            if (node.classList.contains('vsc-initialized')) {
              let id = node.dataset['vscid'];
              let ctrl = document.querySelector(`div[data-vscid="${id}"]`)
              if (ctrl) {
                ctrl.remove();
              }
              node.classList.remove('vsc-initialized');
              delete node.dataset['vscid'];
            }
          }
        } else if (node.children != undefined) {
          for (var i = 0; i < node.children.length; i++) {
            const child = node.children[i];
            checkForVideo(child, child.parentNode || parent, added);
          }
        }
      }

      var observer = new MutationObserver(function(mutations) {
        // Process the DOM nodes lazily
        requestIdleCallback(_ => {
          mutations.forEach(function(mutation) {
            forEach.call(mutation.addedNodes, function(node) {
              if (typeof node === "function")
                return;
              checkForVideo(node, node.parentNode || mutation.target, true);
            });
            forEach.call(mutation.removedNodes, function(node) {
              if (typeof node === "function")
                return;
              checkForVideo(node, node.parentNode || mutation.target, false);
            });
          });
        }, {timeout: 1000});
      });
      observer.observe(document, { childList: true, subtree: true });

      var videoTags = document.getElementsByTagName('video');
      forEach.call(videoTags, function(video) {
        new tc.videoController(video);
      });

      var frameTags = document.getElementsByTagName('iframe');
      forEach.call(frameTags, function(frame) {
        // Ignore frames we don't have permission to access (different origin).
        try { var childDocument = frame.contentDocument } catch (e) { return }
        initializeWhenReady(childDocument);
      });
  }

  function runAction(action, document, keyboard, e) {
    var videoTags = document.getElementsByTagName('video');
    videoTags.forEach = Array.prototype.forEach;

    videoTags.forEach(function(v) {
      var id = v.dataset['vscid'];
      var controller = document.querySelector(`div[data-vscid="${id}"]`);

      showController(controller);

      if (!v.classList.contains('vsc-cancelled')) {
        if (action === 'rewind') {
          v.currentTime -= tc.settings.rewindTime;
        } else if (action === 'advance') {
          v.currentTime += tc.settings.advanceTime;
        } else if (action === 'faster') {
          // Maximum playback speed in Chrome is set to 16:
          // https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp?l=168
          var s = Math.min( (v.playbackRate < 0.1 ? 0.0 : v.playbackRate) + tc.settings.speedStep, 16);
          v.playbackRate = Number(s.toFixed(2));
        } else if (action === 'slower') {
          // Video min rate is 0.0625:
          // https://cs.chromium.org/chromium/src/third_party/WebKit/Source/core/html/media/HTMLMediaElement.cpp?l=167
          var s = Math.max(v.playbackRate - tc.settings.speedStep, 0.07);
          v.playbackRate = Number(s.toFixed(2));
        } else if (action === 'reset') {
          resetSpeed(v, 1.0);
        } else if (action === 'display') {
          controller.classList.add('vsc-manual');
          controller.classList.toggle('vsc-hidden');
        } else if (action === 'drag') {
          handleDrag(v, controller, e);
        } else if (action === 'fast') {
          resetSpeed(v, tc.settings.fastSpeed);
        }
      }
    });
  }

  function resetSpeed(v, target) {
    if (v.playbackRate === target) {
      if(v.playbackRate === tc.settings.resetSpeed)
      {
        if (target !== 1.0) {
          v.playbackRate = 1.0;
        } else {
          v.playbackRate = tc.settings.fastSpeed;
        }
      }
      else
      {
        v.playbackRate = tc.settings.resetSpeed;
      }
    } else {
      tc.settings.resetSpeed = v.playbackRate;
      chrome.storage.sync.set({'resetSpeed': v.playbackRate});
      v.playbackRate = target;
    }
  }

  function handleDrag(video, controller, e) {
    const shadowController = controller.shadowRoot.querySelector('#controller');

    // Find nearest parent of same size as video parent.
    var parentElement = controller.parentElement;
    while (parentElement.parentNode &&
      parentElement.parentNode.offsetHeight === parentElement.offsetHeight &&
      parentElement.parentNode.offsetWidth === parentElement.offsetWidth) {
      parentElement = parentElement.parentNode;
    }

    video.classList.add('vcs-dragging');
    shadowController.classList.add('dragging');

    const initialMouseXY = [e.clientX, e.clientY];
    const initialControllerXY = [
      parseInt(shadowController.style.left),
      parseInt(shadowController.style.top)
    ];

    const startDragging = (e) => {
      let style = shadowController.style;
      let dx = e.clientX - initialMouseXY[0];
      let dy = e.clientY -initialMouseXY[1];
      style.left = (initialControllerXY[0] + dx) + 'px';
      style.top  = (initialControllerXY[1] + dy) + 'px';
    }

    const stopDragging = () => {
      parentElement.removeEventListener('mousemove', startDragging);
      parentElement.removeEventListener('mouseup', stopDragging);
      parentElement.removeEventListener('mouseleave', stopDragging);

      shadowController.classList.remove('dragging');
      video.classList.remove('vcs-dragging');
    }

    parentElement.addEventListener('mouseup',stopDragging);
    parentElement.addEventListener('mouseleave',stopDragging);
    parentElement.addEventListener('mousemove', startDragging);
  }

  var timer;
  var animation = false;
  function showController(controller) {
    controller.classList.add('vcs-show');

    if (animation)
      clearTimeout(timer);

    animation = true;
    timer = setTimeout(function() {
      controller.classList.remove('vcs-show');
      animation = false;
    }, 2000);
  }
});
<|endoftext|>


<commit_before>// Primitive operations on inline content

import * as style from "./style"
import Node from "./node"
import Pos from "./pos"
import {stitchTextNodes} from "./join"
import Transform from "./transform"
import * as slice from "./slice"

function addInline(node, child) {
  node.push(child)
  stitchTextNodes(node, node.content.length - 1)
}

function copyStructure(node, from, to, f, depth = 0) {
  if (node.type.contains == "inline") {
    return f(node, from, to)
  } else {
    let copy = node.copy()
    let start = from ? from.path[depth] : 0
    let end = to ? to.path[depth] : node.content.length - 1
    copy.pushFrom(node, 0, start)
    if (start == end) {
      copy.push(copyStructure(node.content[start], from, to, f, depth + 1))
    } else {
      copy.push(copyStructure(node.content[start], from, null, f, depth + 1))
      for (let i = start + 1; i < end; i++)
        copy.push(copyStructure(node.content[i], null, null, f, depth + 1))
      copy.push(copyStructure(node.content[end], null, to, f, depth + 1))
    }
    copy.pushFrom(node, end + 1)
    return copy
  }
}

function copyInline(node, from, to, f) {
  let copy = node.copy()
  let start = from ? from.offset : 0
  let end = to ? to.offset : node.size
  for (let ch = 0, i = 0; i < node.content.length; i++) {
    let child = node.content[i], size = child.size
    if (ch < start) {
      if (ch + size <= start) {
        copy.push(child)
      } else {
        copy.push(child.slice(0, start - ch))
        if (ch + size <= end) {
          addInline(copy, f(child.slice(start - ch)))
        } else {
          addInline(copy, f(child.slice(start - ch, end - ch)))
          addInline(copy, child.slice(end - ch))
        }
      }
    } else if (ch < end) {
      if (ch + size <= end) {
        addInline(copy, f(child))
      } else {
        addInline(copy, f(child.slice(0, end - ch)))
        addInline(copy, child.slice(end - ch))
      }
    } else {
      addInline(copy, child)
    }
    ch += size
  }
  return copy
}

export function addStyle(doc, from, to, add) {
  return copyStructure(doc, from, to, (node, from, to) => {
    return copyInline(node, from, to, node => {
      return new Node.Inline(node.type, style.add(node.styles, add),
                             node.text, node.attrs)
    })
  })
}

export function removeStyle(doc, from, to, rm) {
  return copyStructure(doc, from, to, (node, from, to) => {
    return copyInline(node, from, to, node => {
      return new Node.Inline(node.type, style.remove(node.styles, rm),
                             node.text, node.attrs)
    })
  })
}

function inlineNodeAtOrBefore(parent, offset) {
  for (let i = 0;; i++) {
    let child = parent.content[i]
    offset -= child.size
    if (offset <= 0)
      return {node: child, offset: i, innerOffset: offset + child.size}
  }
}

export function hasStyle(doc, pos, st) {
  let {node} = inlineNodeAtOrBefore(doc.path(pos.path), pos.offset)
  return style.contains(node.styles, st)
}

export function insertText(doc, pos, text) {
  if (!text) return Transform.identity(doc)

  let copy = slice.around(doc, pos)
  let parent = copy.path(pos.path)
  let {node, offset, innerOffset} = inlineNodeAtOrBefore(parent, pos.offset)
  if (node.type == Node.types.text) {
    let newText = node.text.slice(0, innerOffset) + text + node.text.slice(innerOffset)
    parent.content[offset] = new Node.Inline(node.type, node.styles, newText, node.attrs)
  } else {
    let newNode = new Node.Inline(Node.types.text, node.styles, text)
    if (innerOffset == 0) {
      parent.content.unshift(newNode)
    } else {
      parent.content.splice(offset + 1, 0, newNode)
      stitchTextNodes(parent, offset + 2)
    }
  }
  let parentSize = copy.size

  let transform = new Transform(doc, copy, pos)
  let end = new Pos(pos.path, parentSize)
  transform.chunk(end, pos => new Pos(pos.path, pos.offset + text.length))
  transform.chunk(null, pos => pos)
  return transform
}
<commit_msg>Wire in some basic commands<commit_after>// Primitive operations on inline content

import * as style from "./style"
import Node from "./node"
import Pos from "./pos"
import {stitchTextNodes} from "./join"
import Transform from "./transform"
import * as slice from "./slice"

function addInline(node, child) {
  node.push(child)
  stitchTextNodes(node, node.content.length - 1)
}

function copyStructure(node, from, to, f, depth = 0) {
  if (node.type.contains == "inline") {
    return f(node, from, to)
  } else {
    let copy = node.copy()
    let start = from ? from.path[depth] : 0
    let end = to ? to.path[depth] : node.content.length - 1
    copy.pushFrom(node, 0, start)
    if (start == end) {
      copy.push(copyStructure(node.content[start], from, to, f, depth + 1))
    } else {
      copy.push(copyStructure(node.content[start], from, null, f, depth + 1))
      for (let i = start + 1; i < end; i++)
        copy.push(copyStructure(node.content[i], null, null, f, depth + 1))
      copy.push(copyStructure(node.content[end], null, to, f, depth + 1))
    }
    copy.pushFrom(node, end + 1)
    return copy
  }
}

function copyInline(node, from, to, f) {
  let copy = node.copy()
  let start = from ? from.offset : 0
  let end = to ? to.offset : node.size
  for (let ch = 0, i = 0; i < node.content.length; i++) {
    let child = node.content[i], size = child.size
    if (ch < start) {
      if (ch + size <= start) {
        copy.push(child)
      } else {
        copy.push(child.slice(0, start - ch))
        if (ch + size <= end) {
          addInline(copy, f(child.slice(start - ch)))
        } else {
          addInline(copy, f(child.slice(start - ch, end - ch)))
          addInline(copy, child.slice(end - ch))
        }
      }
    } else if (ch < end) {
      if (ch + size <= end) {
        addInline(copy, f(child))
      } else {
        addInline(copy, f(child.slice(0, end - ch)))
        addInline(copy, child.slice(end - ch))
      }
    } else {
      addInline(copy, child)
    }
    ch += size
  }
  return copy
}

export function addStyle(doc, from, to, add) {
  return copyStructure(doc, from, to, (node, from, to) => {
    return copyInline(node, from, to, node => {
      return new Node.Inline(node.type, style.add(node.styles, add),
                             node.text, node.attrs)
    })
  })
}

export function removeStyle(doc, from, to, rm) {
  return copyStructure(doc, from, to, (node, from, to) => {
    return copyInline(node, from, to, node => {
      return new Node.Inline(node.type, style.remove(node.styles, rm),
                             node.text, node.attrs)
    })
  })
}

function inlineNodeAtOrBefore(parent, offset) {
  for (let i = 0; i < parent.content.length; i++) {
    let child = parent.content[i]
    offset -= child.size
    if (offset <= 0)
      return {node: child, offset: i, innerOffset: offset + child.size}
  }
  return {node: null, offset: 0, innerOffset: 0}
}

export function hasStyle(doc, pos, st) {
  let {node} = inlineNodeAtOrBefore(doc.path(pos.path), pos.offset)
  return style.contains(node ? node.styles : [], st)
}

export function insertNode(doc, pos, node) {
  let copy = slice.around(doc, pos)
  let parent = copy.path(pos.path)
  let parentSize = parent.size, nodeSize = node.size
  let {node: near, offset, innerOffset} = inlineNodeAtOrBefore(parent, pos.offset)
  if (innerOffset && innerOffset != near.size) {
    parent.content.splice(offset, 1, near.slice(0, innerOffset), near.slice(innerOffset))
    offset += 1
  } else if (innerOffset) {
    offset += 1
  }
  parent.content.splice(offset, 0, new Node.Inline(node.type, near ? near.styles : [],
                                                   node.text, node.attrs))
  if (node.type == Node.types.text) {
    stitchTextNodes(parent, offset + 1)
    stitchTextNodes(parent, offset)
  }

  let transform = new Transform(doc, copy, pos)
  let end = new Pos(pos.path, parentSize)
  transform.chunk(end, pos => new Pos(pos.path, pos.offset + nodeSize))
  transform.chunk(null, pos => pos)
  return transform
}

export function insertText(doc, pos, text) {
  if (!text) return Transform.identity(doc)

  return insertNode(doc, pos, new Node.Inline(Node.types.text, null, text))
}
<|endoftext|>


<commit_before>'use strict';

var Writable = require('readable-stream/writable');
var path = require('path');
var url = require('url');
var util = require('util');
var async = require('async');
var spawn = require('child_process').spawn;
var once = require('one-time');
var fs = require('fs');
var os = require('os');
var uuid = require('uuid');
var nerfGun = require('nerf-gun')
var semver = require('semver');
var bl = require('bl');
var debug = require('diagnostics')('registry-migrate:insert');

// prevent fallthrough to the global registry
var npmrc_global_file = path.join(__dirname, 'npmrc-global');

module.exports = Insert;

util.inherits(Insert, Writable);

function Insert(opts) {
  Writable.call(this, { objectMode: true });

  this.destination = opts.destination || opts;
  if (typeof this.destination !== 'string')
    throw new Error('destination must be a string');

  this.parsed =  url.parse(this.destination);
  if (opts.auth || this.parsed.auth)
    this.auth = new Buffer(opts.auth || this.parsed.auth, 'utf8').toString('base64');
  this.parsed.auth = undefined;
  this.destination = this.parsed.format().replace(/\/+$/, '');

}

/**
 * Implement a writable stream that publishes packages in version order
 */
Insert.prototype._write = function (data, enc, callback) {
  var name = data.name;
  var versions = data.versions;
  var keys = Object.keys(versions).sort(compare);

  debug('publishing %d versions of %s', keys.length, name);

  async.eachSeries(keys, (version, next) => {
    this.publish(versions[version], next);
  }, callback);
};

Insert.prototype.publish = function (dir, callback) {
  var fn = once(callback);
  // create a temporary .npmrc file so we can auth safely against a registry
  var user = '';
  var pass = '';
  if (this.auth) {
    var parsed_auth = new Buffer(this.auth, 'base64').toString('utf8');
    var parts = /^([^:]*)(?:[:]([\s\S]*))?$/.exec(parsed_auth);
    user = parts[1];
    pass = parts[2] ? new Buffer(parts[2]).toString('base64') : '';
  }

  var nerfdart = nerfGun(this.destination);

  var npmrc = `# generated by github.com/jcrugzz/registry-migrate
    _auth=${this.auth||''}
    registry=${this.destination}
    loglevel=info
    always-auth=false
    ${nerfdart}:_auth=${this.auth||''}
    ${nerfdart}:username=${user}
    ${nerfdart}:_password=${pass}
    ${nerfdart}:always-auth=false
    # email is required by npm, .invalid is a banned TLD, info purposes only
    ${nerfdart}:email=jcrugzz+registry-migrate@github.com.invalid
    `;

  var npmrc_file = path.join(os.tmpdir(),uuid());
  fs.writeFile(npmrc_file, npmrc, {mode:0o400}, function (write_npmrc_err) {
    if (write_npmrc_err) { return fn(write_npmrc_err); }
    // best effort delete of tmp .npmrc file, don't care if it fails really
    var oldfn = fn;
    fn = function () {
      fs.unlink(npmrc_file, err => {});
      return oldfn.apply(this, arguments);
    };

    //
    // Publish a package. This should hit destination without issue
    // since we remove any possible `.npmrc` we may want to use a path to an
    // `.npmrc` if this is not sufficient
    //
    var args = [
      'publish',
      '--ignore-scripts',
      `--userconfig=${npmrc_file}`,
      `--globalconfig=${npmrc_global_file}`
    ];

    var env = {
      PATH:process.env.PATH,
      HOME:process.env.HOME
    };

    var child = spawn('npm', args, {
      env: env,
      stdio: ['ignore', 'ignore', 'pipe'],
      cwd: dir
    });

    child.on('error', fn);

    child.stderr.pipe(bl(function (err, data) {
      if (err) { return fn(err); }
      if (data && data.length) {
        debug('Stderr output %s', data.toString());
      }
    }));

    child.on('exit', function (code, signal) {
      if (code !== 0) {
        return fn(new Error(`Child exited with code ${code} and Signal ${signal || 'none'}`));
      }
      fn();
    });

  });

};

function compare(a, b) {
  return semver.lt(a, b) ? -1 : 1;
}
<commit_msg>[fix] add email to base npmrc to match what existing valid npmrc<commit_after>'use strict';

var Writable = require('readable-stream/writable');
var path = require('path');
var url = require('url');
var util = require('util');
var async = require('async');
var spawn = require('child_process').spawn;
var once = require('one-time');
var fs = require('fs');
var os = require('os');
var uuid = require('uuid');
var nerfGun = require('nerf-gun')
var semver = require('semver');
var bl = require('bl');
var debug = require('diagnostics')('registry-migrate:insert');

// prevent fallthrough to the global registry
var npmrc_global_file = path.join(__dirname, 'npmrc-global');

module.exports = Insert;

util.inherits(Insert, Writable);

function Insert(opts) {
  Writable.call(this, { objectMode: true });

  this.destination = opts.destination || opts;
  if (typeof this.destination !== 'string')
    throw new Error('destination must be a string');

  this.parsed =  url.parse(this.destination);
  if (opts.auth || this.parsed.auth)
    this.auth = new Buffer(opts.auth || this.parsed.auth, 'utf8').toString('base64');
  this.parsed.auth = undefined;
  this.destination = this.parsed.format().replace(/\/+$/, '');

}

/**
 * Implement a writable stream that publishes packages in version order
 */
Insert.prototype._write = function (data, enc, callback) {
  var name = data.name;
  var versions = data.versions;
  var keys = Object.keys(versions).sort(compare);

  debug('publishing %d versions of %s', keys.length, name);

  async.eachSeries(keys, (version, next) => {
    this.publish(versions[version], next);
  }, callback);
};

Insert.prototype.publish = function (dir, callback) {
  var fn = once(callback);
  // create a temporary .npmrc file so we can auth safely against a registry
  var user = '';
  var pass = '';
  if (this.auth) {
    var parsed_auth = new Buffer(this.auth, 'base64').toString('utf8');
    var parts = /^([^:]*)(?:[:]([\s\S]*))?$/.exec(parsed_auth);
    user = parts[1];
    pass = parts[2] ? new Buffer(parts[2]).toString('base64') : '';
  }

  var nerfdart = nerfGun(this.destination);

  var npmrc = `# generated by github.com/jcrugzz/registry-migrate
    _auth=${this.auth||''}
    # email is required by npm, .invalid is a banned TLD, info purposes only
    email=jcrugzz+registry-migrate@github.com.invalid
    registry=${this.destination}
    loglevel=info
    always-auth=false
    ${nerfdart}:_auth=${this.auth||''}
    ${nerfdart}:username=${user}
    ${nerfdart}:_password=${pass}
    ${nerfdart}:always-auth=false
    ${nerfdart}:email=jcrugzz+registry-migrate@github.com.invalid
    `;

  var npmrc_file = path.join(os.tmpdir(),uuid());
  fs.writeFile(npmrc_file, npmrc, {mode:0o400}, function (write_npmrc_err) {
    if (write_npmrc_err) { return fn(write_npmrc_err); }
    // best effort delete of tmp .npmrc file, don't care if it fails really
    var oldfn = fn;
    fn = function () {
      fs.unlink(npmrc_file, err => {});
      return oldfn.apply(this, arguments);
    };

    //
    // Publish a package. This should hit destination without issue
    // since we remove any possible `.npmrc` we may want to use a path to an
    // `.npmrc` if this is not sufficient
    //
    var args = [
      'publish',
      '--ignore-scripts',
      `--userconfig=${npmrc_file}`,
      `--globalconfig=${npmrc_global_file}`
    ];

    var env = {
      PATH:process.env.PATH,
      HOME:process.env.HOME
    };

    var child = spawn('npm', args, {
      env: env,
      stdio: ['ignore', 'ignore', 'pipe'],
      cwd: dir
    });

    child.on('error', fn);

    child.stderr.pipe(bl(function (err, data) {
      if (err) { return fn(err); }
      if (data && data.length) {
        debug('Stderr output %s', data.toString());
      }
    }));

    child.on('exit', function (code, signal) {
      if (code !== 0) {
        return fn(new Error(`Child exited with code ${code} and Signal ${signal || 'none'}`));
      }
      fn();
    });

  });

};

function compare(a, b) {
  return semver.lt(a, b) ? -1 : 1;
}
<|endoftext|>


<commit_before>// Easify.JS
// Author: Sam Webb
// Copyright: 2015
// License: MIT
// Version: 0.0.4

// Dependencies: N/A

// Start with semicolon in case other libraries
// don't end with one.
;(function(global){
  // Creating new easify object:
  // var e = Easify();
  // or the preferred method
  // var e = $E();
  // Will be using e variable throughout the code

  // Variables
  var validateString,
      validateNum,
      randomNumberFromItemLength;

  // Private Functions

  // Returns a random number from 0 to the length of
  // the passed in array or string
  randomNumberFromItemLength = function(item) {
    return Math.floor(Math.random() * item.length)
  }

  // For validating strings
  // Always use this if method takes a string artument
  validateString = function(str) {
    // If str can be coerced to false, it will fail
    if (!str) {
      return false;
    }
    // If str is not of type "string" it will fail
    if (typeof str === "string") {
      return true;
    } else {
      return false;
    }
  }

  // For validating numbers
  // Always use this if method takes a number argument
  validateNum = function(num) {
    // If num is not of type "number" it will fail
    if(typeof num !== "number") {
      return false;
    }
    return true;
  }

  // End of private functions

  // 'new' Easify object
  var Easify = function() {
    return new Easify.init();
  }

  Easify.VERSION = '0.0.3';

  // Function that actually creates object
  // to remove 'new' keyword for users
  Easify.init = function() {
    var self = this;
  }

  // Universal methods and properties of Easify
  // on the protorype
  Easify.prototype = {

    // **************
    // **************
    // STRING METHODS
    // **************
    // **************

    capitalize: function(str) {
      if (validateString(str)) {
        var strList = str.split('');
        strList[0] = strList[0].toUpperCase();
        str = strList.join('');
        return str;
      } else {
        throw 'String validation failed.'
      }
    },

    isString: function(str) {
      return validateString(str);
    },

    // Easy way to grab the last letter of a string
    //
    // Takes 1 argument(string)
    // e.last('hello'); //=> "o"
    last: function(str) {
      if (validateString(str)) {
        return str[str.length - 1];
      } else {
        throw 'String validation failed.'
      }
    },

    // Randomly removes a specified amount of characters from
    // a string
    //
    // Takes 2 arguments(string, number)
    // e.remove('hello', 2); //=> 'hlo'
    // Honestly can't see a use case for this but it's here
    remove: function(str, amount) {
      if (validateString(str) && validateNum(amount)){
        // Protects amount from being larger than the string
        // argument's length
        if (amount > str.length) {
          amount = str.length;
        }
        // Split the string into an array
        var arr = str.split('');
        // Set some variables
        var newString = '';
        var num;
        // Iterate to remove each letter
        for (var i = 0; i < amount; i++) {
          // Set random number from 0 to 1 below array length
          num = randomNumberFromItemLength(arr);
          // Remove random letter from the array
          arr.splice(num, 1)[0];
        }
        newString = arr.join('');
        return newString;
      } else {
        throw 'Argument validation failed.';
      }

    },

    // Removes all occurances of the specified letter from
    // the string
    //
    // Takes 2 arguments(string, string)
    // e.removeAll('hello', 'l'); //=> 'heo'
    removeAll: function(str, letter) {
      if (validateString(str) && validateString(letter)) {
        // Makes sure the letter argument is 1 character long
        if (letter.length !== 1) {
          throw 'The letter argument should not be greater or less than 1.'
        }
        // Sets some variables.
        var newString;
        var arr = str.split('');
        // Loops over the array to check the letters
        for (var i = 0; i < arr.length; i++) {
          // If the letter in the array matches the letter
          // argument, this will run
          if (arr[i] === letter) {
            // Removes letter
            arr.splice(i, 1);
            // Small code to make sure when something is removed,
            // the loop doesn't skip the next letter
            i = i - 1;
          }
        }
        // Join the array back together
        newString = arr.join('');
        return newString;
      } else {
        throw 'String validation failed.'
      }
    },

    // Returns a randomized version of a passed in string
    //
    // Takes 1 argument(string)
    // e.randomize("Hello"); //=> "olelH"
    randomize: function(str) {
      if (validateString(str)) {
        // Split the string into an array
        var arr = str.split('');
        // Set some variables
        var newString = '';
        var num;
        // Array will get shortened by 1 for each iteration
        while (arr.length > 0) {
          // Set random number from 0 to 1 below array length
          num = randomNumberFromItemLength(arr);
          // Add letter to newString
          newString += arr[num];
          // Remove the letter from the array
          arr.splice(num, 1);
        }
        return newString;
      } else {
        throw 'String validation failed.'
      }
    },

    // Repeat the same string multiple times, trimming off
    // extra white space at the beginning or end
    //
    // Takes 2 arguments(string, number)
    // e.repeat('hello ', 4); //=> "hello hello hello hello"
    repeat: function(str, count) {
      if(validateString(str) && validateNum(count)) {
        // Variable to store the created string
        var repeatedString = '';
        // Add input string to the variable however many
        // times, specified in count variable.
        // If count is 0, an empty string will be returned.
        for (var i = 0; i < count; i++) {
          repeatedString += str;
        }
        return repeatedString.trim();
      } else {
        throw 'Argument validation failed.'
      }
    },

    // Reverse a string
    //
    // Takes 1 argument(string)
    // e.reverse('hello'); //=> 'olleh'
    reverse: function(str) {
      if(validateString(str)) {
        // Break string up into an array of characters
        // including spaces.
        var arr = str.split('');
        // Reverse array
        arr = arr.reverse();
        // Rejoin array into string
        str = arr.join('');
        return str;
      } else {
        throw 'String validation failed.'
      }
    },

    // Wrap a string in a specified element
    //
    // Takes 2 arguments(string, string)
    // e.wrap('Hello', 'h1'); //=> "
Hello
"
    wrap: function(str, element) {
      // String validation
      if (validateString(str) && validateString(element)) {
        return '<' + element + '>' + str + '</' + element + '>';
      } else {
        throw 'String validation failed.'
      }
    },

    // *************
    // *************
    // ARRAY METHODS
    // *************
    // *************

    // Checks the type of each element contained in the passed
    // in array
    //
    // Takes 1 argument(array)
    // e.checkTypes([1, 'hello', [], {}, function(){}, true])
    // returns
    // ['number', 'string', 'array', 'object', 'function', 'boolean']
    checkTypes: function(arr) {
      if (Array.isArray(arr) === true) {
        var returnedArray = [];
        for (var i = 0; i < arr.length; i++) {
          // Method depends on checkType() method
          returnedArray.push(this.checkType(arr[i]));
        }
        return returnedArray;
      }
      throw 'checkTypes() requires an array argument'
    },

    // Returns true if the passed in value is inside of the array
    contains: function(arr, value) {
      if (Array.isArray(arr) === true) {
        var isIn = false;
        for (var i = 0; i < arr.length; i++) {
          if (arr[i] === value) {
            isIn = true;
          }
        }
        return isIn;
      }
      throw 'contains() requires an array argument'
    },

    // Checks if input value is an array
    isArray: function(arr) {
      if (Array.isArray(arr) === true) {
        return true;
      } else {
        return false;
      }
    },

    // **************
    // **************
    // OBJECT METHODS
    // **************
    // **************

    // Checks if input value returns 'object' and not 'array'
    isObject: function(obj) {
      if (Array.isArray(obj) === true) {
        return false;
      } else if (obj === null) {
        return false;
      } else if (typeof obj === 'object') {
        return true;
      } else {
        return false;
      }
    },

    // ***********
    // ***********
    // DOM METHODS
    // ***********
    // ***********

    // Insert HTML into the selected HTML element
    //
    // Takes 4 arguments(string, string, string, number)
    // e.insertHTML('id', 'home-link', 'Home');
    // The previous code will insert the text 'Home' inside
    // of the element on your page with an id of #home-link.
    // Any valid HTML can also be be the input value.
    //
    // Arguments
    // ----------
    // The selectorType argument is expecting a string of
    // either 'id' or 'class'
    //
    // The selector artument is expecting a string that
    // corrisponds to the name provided in the HTML
    //
    // The input argument can be any valid HTML or text
    //
    // The amount argument is an optional argument and is
    // used when a selector which returns multiple elements
    // is selected. You can set an amount of elements to
    // add your HTML to. It will go in order starting from
    // the first element. If no amount is selected, all
    // elements will get the change.
    // ----------
    insertHTML: function(selectorType, selector, input, amount) {
      // Makes sure first 3 arguments valid
      if (validateString(selectorType) && validateString(selector) && validateString(input)) {

        // Sets some variables
        var element;
        var elements = [];
        var num = 0;

        // Checking the selector type for 'id'
        if (selectorType.toLowerCase() === "id") {
          element = document.getElementById(selector);
          element.innerHTML = input;
        // Checking the selector type of 'class'
        } else if (selectorType.toLowerCase() === "class") {
          // If amount validates to be a number, set the num
          // variable to amount
          if (validateNum(amount)) { num = amount }
          elements = document.getElementsByClassName(selector);
          // Iterates over the elements array and adds the html
          // to every element contained in it
          for (var i = 0; i < ( amount || elements.length ); i++) {
            // Prevents error if amount is higher than the length of
            // elements
            if (i === elements.length) {
              break;
            }
            element = elements[i];
            element.innerHTML = input;
          }
        } else {
          throw 'You must pass either "id" or "class" as the selectorType argument to insertHTML function.'
        }
        // Returns true if successful
        return true;
      }
      // Returns false if unsuccessful
      throw 'insertHTML arguments are invalid.'
      return false;
      // Does not check if there is a matching HTML element. YET!
    },

    // Returns the DOM element with the passed in ID
    elementFromId: function(id) {
      return document.getElementById(id);
    },

    // Returns a list of DOM elements with the passed in class
    elementsFromClass: function(classname) {
      return document.getElementsByClassName(classname);
    },

    // Returns a list of DOM elements with the passed in tag
    elementsFromTag: function(tag) {
      return document.getElementsByTagName(tag);
    },

    elementsFromName: function(name) {
      return document.getElementsByName(name);
    },

    // *****************
    // *****************
    // UNIVERSAL METHODS
    // *****************
    // *****************

    // Returns true if arguments are equal.
    isEqual: function(a, b) {
      return a === b;
    },

    // Returns true if arguments are not equal.
    isNotEqual: function(a, b) {
      return a !== b;
    },

    // Returns true if arguments can be coerced to equal.
    isSimilar: function(a, b) {
      return a == b;
    },

    // Returns true if arguments can not be coreced to equal.
    isNotSimilar: function(a, b) {
      return a != b;
    },

    // Checks if the argument is a truthy value
    isTruthy: function(a) {
      if (a) {
        return true;
      } else {
        return false;
      }
    },

    // Checks if the argument is a falsey value
    isFalsey: function(a) {
      if(!a) {
        return true;
      } else {
        return false;
      }
    },

    // Runs callback if comparison returns true
    ifTrue: function(comparison, callback){
      if(comparison) {
        callback();
      }
    },

    // Runs callback if comparison returns false
    ifFalse: function(comparison, callback) {
      if(!comparison) {
        callback();
      }
    },

    // Checks the type of a passed in value
    checkType: function(a) {
      // Specific check for arrays since they return from
      // typeof as 'object'
      if (Array.isArray(a) === true) {
        return 'array';
      // Check for null since null returns from typeof as
      // 'object'
      } else if (a === null) {
        return 'null';
      } {
        // Checks for everything else with typeof
        switch (typeof a) {
          case 'string':
            return 'string';
          case 'number':
            return 'number';
          case 'boolean':
            return 'boolean';
          case 'function':
            return 'function';
          case 'object':
            return 'object';
          case 'undefined':
            return 'undefined';
          default:
            return null;
        }
      }
    }

  }

  // **********
  // **********
  // ALTERNATES
  // **********
  // **********

  // Alternate name for isEqual method
  Easify.prototype.equals = Easify.prototype.isEqual;

  // ******************************

  // Point init prototype to the Easify prototype
  Easify.init.prototype = Easify.prototype;

  // Sets up global variables
  global.Easify = global.$E = Easify

  console.log("Easify loaded!");
}(window));<commit_msg>correct versioning from now on<commit_after>// Easify.JS
// Author: Sam Webb
// Copyright: 2015
// License: MIT
// Version: 0.1.0

// Dependencies: N/A

// Start with semicolon in case other libraries
// don't end with one.
;(function(global){
  // Creating new easify object:
  // var e = Easify();
  // or the preferred method
  // var e = $E();
  // Will be using e variable throughout the code

  // Variables
  var validateString,
      validateNum,
      randomNumberFromItemLength;

  // Private Functions

  // Returns a random number from 0 to the length of
  // the passed in array or string
  randomNumberFromItemLength = function(item) {
    return Math.floor(Math.random() * item.length)
  }

  // For validating strings
  // Always use this if method takes a string artument
  validateString = function(str) {
    // If str can be coerced to false, it will fail
    if (!str) {
      return false;
    }
    // If str is not of type "string" it will fail
    if (typeof str === "string") {
      return true;
    } else {
      return false;
    }
  }

  // For validating numbers
  // Always use this if method takes a number argument
  validateNum = function(num) {
    // If num is not of type "number" it will fail
    if(typeof num !== "number") {
      return false;
    }
    return true;
  }

  // End of private functions

  // 'new' Easify object
  var Easify = function() {
    return new Easify.init();
  }

  Easify.VERSION = '0.0.3';

  // Function that actually creates object
  // to remove 'new' keyword for users
  Easify.init = function() {
    var self = this;
  }

  // Universal methods and properties of Easify
  // on the protorype
  Easify.prototype = {

    // **************
    // **************
    // STRING METHODS
    // **************
    // **************

    capitalize: function(str) {
      if (validateString(str)) {
        var strList = str.split('');
        strList[0] = strList[0].toUpperCase();
        str = strList.join('');
        return str;
      } else {
        throw 'String validation failed.'
      }
    },

    isString: function(str) {
      return validateString(str);
    },

    // Easy way to grab the last letter of a string
    //
    // Takes 1 argument(string)
    // e.last('hello'); //=> "o"
    last: function(str) {
      if (validateString(str)) {
        return str[str.length - 1];
      } else {
        throw 'String validation failed.'
      }
    },

    // Randomly removes a specified amount of characters from
    // a string
    //
    // Takes 2 arguments(string, number)
    // e.remove('hello', 2); //=> 'hlo'
    // Honestly can't see a use case for this but it's here
    remove: function(str, amount) {
      if (validateString(str) && validateNum(amount)){
        // Protects amount from being larger than the string
        // argument's length
        if (amount > str.length) {
          amount = str.length;
        }
        // Split the string into an array
        var arr = str.split('');
        // Set some variables
        var newString = '';
        var num;
        // Iterate to remove each letter
        for (var i = 0; i < amount; i++) {
          // Set random number from 0 to 1 below array length
          num = randomNumberFromItemLength(arr);
          // Remove random letter from the array
          arr.splice(num, 1)[0];
        }
        newString = arr.join('');
        return newString;
      } else {
        throw 'Argument validation failed.';
      }

    },

    // Removes all occurances of the specified letter from
    // the string
    //
    // Takes 2 arguments(string, string)
    // e.removeAll('hello', 'l'); //=> 'heo'
    removeAll: function(str, letter) {
      if (validateString(str) && validateString(letter)) {
        // Makes sure the letter argument is 1 character long
        if (letter.length !== 1) {
          throw 'The letter argument should not be greater or less than 1.'
        }
        // Sets some variables.
        var newString;
        var arr = str.split('');
        // Loops over the array to check the letters
        for (var i = 0; i < arr.length; i++) {
          // If the letter in the array matches the letter
          // argument, this will run
          if (arr[i] === letter) {
            // Removes letter
            arr.splice(i, 1);
            // Small code to make sure when something is removed,
            // the loop doesn't skip the next letter
            i = i - 1;
          }
        }
        // Join the array back together
        newString = arr.join('');
        return newString;
      } else {
        throw 'String validation failed.'
      }
    },

    // Returns a randomized version of a passed in string
    //
    // Takes 1 argument(string)
    // e.randomize("Hello"); //=> "olelH"
    randomize: function(str) {
      if (validateString(str)) {
        // Split the string into an array
        var arr = str.split('');
        // Set some variables
        var newString = '';
        var num;
        // Array will get shortened by 1 for each iteration
        while (arr.length > 0) {
          // Set random number from 0 to 1 below array length
          num = randomNumberFromItemLength(arr);
          // Add letter to newString
          newString += arr[num];
          // Remove the letter from the array
          arr.splice(num, 1);
        }
        return newString;
      } else {
        throw 'String validation failed.'
      }
    },

    // Repeat the same string multiple times, trimming off
    // extra white space at the beginning or end
    //
    // Takes 2 arguments(string, number)
    // e.repeat('hello ', 4); //=> "hello hello hello hello"
    repeat: function(str, count) {
      if(validateString(str) && validateNum(count)) {
        // Variable to store the created string
        var repeatedString = '';
        // Add input string to the variable however many
        // times, specified in count variable.
        // If count is 0, an empty string will be returned.
        for (var i = 0; i < count; i++) {
          repeatedString += str;
        }
        return repeatedString.trim();
      } else {
        throw 'Argument validation failed.'
      }
    },

    // Reverse a string
    //
    // Takes 1 argument(string)
    // e.reverse('hello'); //=> 'olleh'
    reverse: function(str) {
      if(validateString(str)) {
        // Break string up into an array of characters
        // including spaces.
        var arr = str.split('');
        // Reverse array
        arr = arr.reverse();
        // Rejoin array into string
        str = arr.join('');
        return str;
      } else {
        throw 'String validation failed.'
      }
    },

    // Wrap a string in a specified element
    //
    // Takes 2 arguments(string, string)
    // e.wrap('Hello', 'h1'); //=> "
Hello
"
    wrap: function(str, element) {
      // String validation
      if (validateString(str) && validateString(element)) {
        return '<' + element + '>' + str + '</' + element + '>';
      } else {
        throw 'String validation failed.'
      }
    },

    // *************
    // *************
    // ARRAY METHODS
    // *************
    // *************

    // Checks the type of each element contained in the passed
    // in array
    //
    // Takes 1 argument(array)
    // e.checkTypes([1, 'hello', [], {}, function(){}, true])
    // returns
    // ['number', 'string', 'array', 'object', 'function', 'boolean']
    checkTypes: function(arr) {
      if (Array.isArray(arr) === true) {
        var returnedArray = [];
        for (var i = 0; i < arr.length; i++) {
          // Method depends on checkType() method
          returnedArray.push(this.checkType(arr[i]));
        }
        return returnedArray;
      }
      throw 'checkTypes() requires an array argument'
    },

    // Returns true if the passed in value is inside of the array
    contains: function(arr, value) {
      if (Array.isArray(arr) === true) {
        var isIn = false;
        for (var i = 0; i < arr.length; i++) {
          if (arr[i] === value) {
            isIn = true;
          }
        }
        return isIn;
      }
      throw 'contains() requires an array argument'
    },

    // Checks if input value is an array
    isArray: function(arr) {
      if (Array.isArray(arr) === true) {
        return true;
      } else {
        return false;
      }
    },

    // **************
    // **************
    // OBJECT METHODS
    // **************
    // **************

    // Checks if input value returns 'object' and not 'array'
    isObject: function(obj) {
      if (Array.isArray(obj) === true) {
        return false;
      } else if (obj === null) {
        return false;
      } else if (typeof obj === 'object') {
        return true;
      } else {
        return false;
      }
    },

    // ***********
    // ***********
    // DOM METHODS
    // ***********
    // ***********

    // Insert HTML into the selected HTML element
    //
    // Takes 4 arguments(string, string, string, number)
    // e.insertHTML('id', 'home-link', 'Home');
    // The previous code will insert the text 'Home' inside
    // of the element on your page with an id of #home-link.
    // Any valid HTML can also be be the input value.
    //
    // Arguments
    // ----------
    // The selectorType argument is expecting a string of
    // either 'id' or 'class'
    //
    // The selector artument is expecting a string that
    // corrisponds to the name provided in the HTML
    //
    // The input argument can be any valid HTML or text
    //
    // The amount argument is an optional argument and is
    // used when a selector which returns multiple elements
    // is selected. You can set an amount of elements to
    // add your HTML to. It will go in order starting from
    // the first element. If no amount is selected, all
    // elements will get the change.
    // ----------
    insertHTML: function(selectorType, selector, input, amount) {
      // Makes sure first 3 arguments valid
      if (validateString(selectorType) && validateString(selector) && validateString(input)) {

        // Sets some variables
        var element;
        var elements = [];
        var num = 0;

        // Checking the selector type for 'id'
        if (selectorType.toLowerCase() === "id") {
          element = document.getElementById(selector);
          element.innerHTML = input;
        // Checking the selector type of 'class'
        } else if (selectorType.toLowerCase() === "class") {
          // If amount validates to be a number, set the num
          // variable to amount
          if (validateNum(amount)) { num = amount }
          elements = document.getElementsByClassName(selector);
          // Iterates over the elements array and adds the html
          // to every element contained in it
          for (var i = 0; i < ( amount || elements.length ); i++) {
            // Prevents error if amount is higher than the length of
            // elements
            if (i === elements.length) {
              break;
            }
            element = elements[i];
            element.innerHTML = input;
          }
        } else {
          throw 'You must pass either "id" or "class" as the selectorType argument to insertHTML function.'
        }
        // Returns true if successful
        return true;
      }
      // Returns false if unsuccessful
      throw 'insertHTML arguments are invalid.'
      return false;
      // Does not check if there is a matching HTML element. YET!
    },

    // Returns the DOM element with the passed in ID
    elementFromId: function(id) {
      return document.getElementById(id);
    },

    // Returns a list of DOM elements with the passed in class
    elementsFromClass: function(classname) {
      return document.getElementsByClassName(classname);
    },

    // Returns a list of DOM elements with the passed in tag
    elementsFromTag: function(tag) {
      return document.getElementsByTagName(tag);
    },

    elementsFromName: function(name) {
      return document.getElementsByName(name);
    },

    // *****************
    // *****************
    // UNIVERSAL METHODS
    // *****************
    // *****************

    // Returns true if arguments are equal.
    isEqual: function(a, b) {
      return a === b;
    },

    // Returns true if arguments are not equal.
    isNotEqual: function(a, b) {
      return a !== b;
    },

    // Returns true if arguments can be coerced to equal.
    isSimilar: function(a, b) {
      return a == b;
    },

    // Returns true if arguments can not be coreced to equal.
    isNotSimilar: function(a, b) {
      return a != b;
    },

    // Checks if the argument is a truthy value
    isTruthy: function(a) {
      if (a) {
        return true;
      } else {
        return false;
      }
    },

    // Checks if the argument is a falsey value
    isFalsey: function(a) {
      if(!a) {
        return true;
      } else {
        return false;
      }
    },

    // Runs callback if comparison returns true
    ifTrue: function(comparison, callback){
      if(comparison) {
        callback();
      }
    },

    // Runs callback if comparison returns false
    ifFalse: function(comparison, callback) {
      if(!comparison) {
        callback();
      }
    },

    // Checks the type of a passed in value
    checkType: function(a) {
      // Specific check for arrays since they return from
      // typeof as 'object'
      if (Array.isArray(a) === true) {
        return 'array';
      // Check for null since null returns from typeof as
      // 'object'
      } else if (a === null) {
        return 'null';
      } {
        // Checks for everything else with typeof
        switch (typeof a) {
          case 'string':
            return 'string';
          case 'number':
            return 'number';
          case 'boolean':
            return 'boolean';
          case 'function':
            return 'function';
          case 'object':
            return 'object';
          case 'undefined':
            return 'undefined';
          default:
            return null;
        }
      }
    }

  }

  // **********
  // **********
  // ALTERNATES
  // **********
  // **********

  // Alternate name for isEqual method
  Easify.prototype.equals = Easify.prototype.isEqual;

  // ******************************

  // Point init prototype to the Easify prototype
  Easify.init.prototype = Easify.prototype;

  // Sets up global variables
  global.Easify = global.$E = Easify

  console.log("Easify loaded!");
}(window));<|endoftext|>


<commit_before>/**
 * List of full easings
 * @namespace TWEEN.Easing
 * @example
 * import {Tween, Easing} from 'es6-tween'
 *
 * // then set via new Tween({x:0}).to({x:100}, 1000).easing(Easing.Quadratic.InOut).start()
 */
const Easing = {
  Linear: {
    None (k) {
      return k
    }
  },

  Quadratic: {
    In (k) {
      return k * k
    },

    Out (k) {
      return k * (2 - k)
    },

    InOut (k) {
      if ((k *= 2) < 1) {
        return 0.5 * k * k
      }

      return -0.5 * (--k * (k - 2) - 1)
    }
  },

  Cubic: {
    In (k) {
      return k * k * k
    },

    Out (k) {
      return --k * k * k + 1
    },

    InOut (k) {
      if ((k *= 2) < 1) {
        return 0.5 * k * k * k
      }

      return 0.5 * ((k -= 2) * k * k + 2)
    }
  },

  Quartic: {
    In (k) {
      return k * k * k * k
    },

    Out (k) {
      return 1 - --k * k * k * k
    },

    InOut (k) {
      if ((k *= 2) < 1) {
        return 0.5 * k * k * k * k
      }

      return -0.5 * ((k -= 2) * k * k * k - 2)
    }
  },

  Quintic: {
    In (k) {
      return k * k * k * k * k
    },

    Out (k) {
      return --k * k * k * k * k + 1
    },

    InOut (k) {
      if ((k *= 2) < 1) {
        return 0.5 * k * k * k * k * k
      }

      return 0.5 * ((k -= 2) * k * k * k * k + 2)
    }
  },

  Sinusoidal: {
    In (k) {
      return 1 - Math.cos(k * Math.PI / 2)
    },

    Out (k) {
      return Math.sin(k * Math.PI / 2)
    },

    InOut (k) {
      return 0.5 * (1 - Math.cos(Math.PI * k))
    }
  },

  Exponential: {
    In (k) {
      return k === 0 ? 0 : Math.pow(1024, k - 1)
    },

    Out (k) {
      return k === 1 ? 1 : 1 - Math.pow(2, -10 * k)
    },

    InOut (k) {
      if (k === 0) {
        return 0
      }

      if (k === 1) {
        return 1
      }

      if ((k *= 2) < 1) {
        return 0.5 * Math.pow(1024, k - 1)
      }

      return 0.5 * (-Math.pow(2, -10 * (k - 1)) + 2)
    }
  },

  Circular: {
    In (k) {
      return 1 - Math.sqrt(1 - k * k)
    },

    Out (k) {
      return Math.sqrt(1 - --k * k)
    },

    InOut (k) {
      if ((k *= 2) < 1) {
        return -0.5 * (Math.sqrt(1 - k * k) - 1)
      }

      return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1)
    }
  },

  Elastic: {
    In (k) {
      if (k === 0) {
        return 0
      }

      if (k === 1) {
        return 1
      }

      return -Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI)
    },

    Out (k) {
      if (k === 0) {
        return 0
      }

      if (k === 1) {
        return 1
      }

      return Math.pow(2, -10 * k) * Math.sin((k - 0.1) * 5 * Math.PI) + 1
    },

    InOut (k) {
      if (k === 0) {
        return 0
      }

      if (k === 1) {
        return 1
      }

      k *= 2

      if (k < 1) {
        return (
          -0.5 * Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI)
        )
      }

      return (
        0.5 * Math.pow(2, -10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI) + 1
      )
    }
  },

  Back: {
    In (k) {
      const s = 1.70158

      return k * k * ((s + 1) * k - s)
    },

    Out (k) {
      const s = 1.70158

      return --k * k * ((s + 1) * k + s) + 1
    },

    InOut (k) {
      const s = 1.70158 * 1.525

      if ((k *= 2) < 1) {
        return 0.5 * (k * k * ((s + 1) * k - s))
      }

      return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2)
    }
  },

  Bounce: {
    In (k) {
      return 1 - Easing.Bounce.Out(1 - k)
    },

    Out (k) {
      if (k < 1 / 2.75) {
        return 7.5625 * k * k
      } else if (k < 2 / 2.75) {
        return 7.5625 * (k -= 1.5 / 2.75) * k + 0.75
      } else if (k < 2.5 / 2.75) {
        return 7.5625 * (k -= 2.25 / 2.75) * k + 0.9375
      } else {
        return 7.5625 * (k -= 2.625 / 2.75) * k + 0.984375
      }
    },

    InOut (k) {
      if (k < 0.5) {
        return Easing.Bounce.In(k * 2) * 0.5
      }

      return Easing.Bounce.Out(k * 2 - 1) * 0.5 + 0.5
    }
  },

  Stepped: {
    steps: steps => k => ((k * steps) | 0) / steps
  }
}

export default Easing
<commit_msg>Some changes for more easy to read the code.<commit_after>/**
 * List of full easings
 * @namespace TWEEN.Easing
 * @example
 * import {Tween, Easing} from 'es6-tween'
 *
 * // then set via new Tween({x:0}).to({x:100}, 1000).easing(Easing.Quadratic.InOut).start()
 */
const Easing = {
  Linear: {
    None (k) {
      return k
    }
  },

  Quadratic: {
    In (k) {
      return Math.pow(k, 2)
    },

    Out (k) {
      return k * (2 - k)
    },

    InOut (k) {
      if ((k *= 2) < 1) {
        return 0.5 * Math.pow(k, 2)
      }

      return -0.5 * (--k * (k - 2) - 1)
    }
  },

  Cubic: {
    In (k) {
      return Math.pow(k,3)
    },

    Out (k) {
      return --k * k * k + 1
    },

    InOut (k) {
      if ((k *= 2) < 1) {
        return 0.5 * Math.pow(k,3)
      }

      return 0.5 * ((k -= 2) * k * k + 2)
    }
  },

  Quartic: {
    In (k) {
      return Math.pow(k,4)
    },

    Out (k) {
      return 1 - --k * k * k * k
    },

    InOut (k) {
      if ((k *= 2) < 1) {
        return 0.5 * Math.pow(k,4)
      }

      return -0.5 * ((k -= 2) * k * k * k - 2)
    }
  },

  Quintic: {
    In (k) {
      return Math.pow(k,5)
    },

    Out (k) {
      return --k * k * k * k * k + 1
    },

    InOut (k) {
      if ((k *= 2) < 1) {
        return 0.5 * Math.pow(k,5)
      }

      return 0.5 * ((k -= 2) * k * k * k * k + 2)
    }
  },

  Sinusoidal: {
    In (k) {
      return 1 - Math.cos(k * Math.PI / 2)
    },

    Out (k) {
      return Math.sin(k * Math.PI / 2)
    },

    InOut (k) {
      return 0.5 * (1 - Math.cos(Math.PI * k))
    }
  },

  Exponential: {
    In (k) {
      return k === 0 ? 0 : Math.pow(1024, k - 1)
    },

    Out (k) {
      return k === 1 ? 1 : 1 - Math.pow(2, -10 * k)
    },

    InOut (k) {
      if (k === 0) {
        return 0
      }

      if (k === 1) {
        return 1
      }

      if ((k *= 2) < 1) {
        return 0.5 * Math.pow(1024, k - 1)
      }

      return 0.5 * (-Math.pow(2, -10 * (k - 1)) + 2)
    }
  },

  Circular: {
    In (k) {
      return 1 - Math.sqrt(1 - k * k)
    },

    Out (k) {
      return Math.sqrt(1 - --k * k)
    },

    InOut (k) {
      if ((k *= 2) < 1) {
        return -0.5 * (Math.sqrt(1 - k * k) - 1)
      }

      return 0.5 * (Math.sqrt(1 - (k -= 2) * k) + 1)
    }
  },

  Elastic: {
    In (k) {
      if (k === 0) {
        return 0
      }

      if (k === 1) {
        return 1
      }

      return -Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI)
    },

    Out (k) {
      if (k === 0) {
        return 0
      }

      if (k === 1) {
        return 1
      }

      return Math.pow(2, -10 * k) * Math.sin((k - 0.1) * 5 * Math.PI) + 1
    },

    InOut (k) {
      if (k === 0) {
        return 0
      }

      if (k === 1) {
        return 1
      }

      k *= 2

      if (k < 1) {
        return (
          -0.5 * Math.pow(2, 10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI)
        )
      }

      return (
        0.5 * Math.pow(2, -10 * (k - 1)) * Math.sin((k - 1.1) * 5 * Math.PI) + 1
      )
    }
  },

  Back: {
    In (k) {
      const s = 1.70158

      return k * k * ((s + 1) * k - s)
    },

    Out (k) {
      const s = 1.70158

      return --k * k * ((s + 1) * k + s) + 1
    },

    InOut (k) {
      const s = 1.70158 * 1.525

      if ((k *= 2) < 1) {
        return 0.5 * (k * k * ((s + 1) * k - s))
      }

      return 0.5 * ((k -= 2) * k * ((s + 1) * k + s) + 2)
    }
  },

  Bounce: {
    In (k) {
      return 1 - Easing.Bounce.Out(1 - k)
    },

    Out (k) {
      let x = 2.75
      let y = 7.5625

      if (k < 1 / x) {
        return y * k * k
      } else if (k < 2 / x) {
        return y * (k -= 1.5 / x) * k + 0.75
      } else if (k < 2.5 / x) {
        return y * (k -= 2.25 / x) * k + 0.9375
      } else {
        return y * (k -= 2.625 / x) * k + 0.984375
      }
    },

    InOut (k) {
      if (k < 0.5) {
        return Easing.Bounce.In(k * 2) * 0.5
      }

      return Easing.Bounce.Out(k * 2 - 1) * 0.5 + 0.5
    }
  },

  Stepped: {
    steps: steps => k => ((k * steps) | 0) / steps
  }
}

export default Easing
<|endoftext|>


<commit_before>/*
 *  Effect.js
 *  2014/07/10
 *  @auther minimo
 *  This Program is MIT license.
 */
tds.Effect = [];

(function() {

//p[eBN
tm.define("tds.Effect.Particle", {
    superClass: "tm.display.Shape",
    layer: LAYER_EFFECT_UPPER,

    alpha: 1.0,
    alphaDecayRate: 0.85,
    size: 0,

    image: null,
    isEffect: true,
    isUpper: true,

    init: function(size, initialAlpha, alphaDecayRate) {
        this.superInit();
        size = size || 100;
        if (initialAlpha === undefined) initialAlpha = 1;
        if (alphaDecayRate === undefined) alphaDecayRate = 0.9;

        this.width = this.height = this.size = size;
        this.alpha = initialAlpha;
        this.alphaDecayRate = alphaDecayRate;
        this.blendMode = "lighter";

        var c = this.canvas;
        c.setFillStyle(
            tm.graphics.RadialGradient(size/4, size/4, 0, size/4, size/4, size/4)
                .addColorStopList([
                    {offset:0.0, color: "hsla({0}, 60%, 50%, 0.8)".format(0)},
                    {offset:0.5, color: "hsla({0}, 60%, 50%, 0.4)".format(0)},
                    {offset:1.0, color: "hsla({0}, 60%, 50%, 0.0)".format(0)},
                ]).toStyle()
            )
            .fillRect(0, 0, 50, 50);
    },
    update: function(app) {
        this.alpha *= this.alphaDecayRate;
        if (this.alpha < 0.01) {
            this.remove();
        } else if (1.0 < this.alpha) {
            this.alpha = 1.0;
        }
    },
});

tm.define("tds.Effect.Aura", {
    superClass: "tm.display.Shape",
    layer: LAYER_EFFECT_UPPER,

    init: function(target, size, alphaDecayRate) {
        this.superInit();

        size = size || 100;
        if (alphaDecayRate === undefined) alphaDecayRate = 0.9;

        this.width = this.height = this.size = size;
        this.alpha = 0.02;
        this.alphaDecayRate = alphaDecayRate;
        this.blendMode = "lighter";
        this.tweener.clear().to({alpha:1},200).to({alpha:0},2000);

        this.target = target;
        this.vanish = false;

        this.setScale(size*0.01);

        var c = this.canvas;
        c.setFillStyle(
            tm.graphics.RadialGradient(25, 25, 0, 25, 25, 25)
                .addColorStopList([
                    {offset:0.0, color: "hsla({0}, 60%, 50%, 0.4)".format(200)},
                    {offset:0.5, color: "hsla({0}, 60%, 50%, 0.2)".format(240)},
                    {offset:1.0, color: "hsla({0}, 60%, 50%, 0.0)".format(240)},
                ]).toStyle()
            )
            .fillRect(0, 0, 50, 50);
    },

    update: function() {
//        this.alpha *= this.alphaDecayRate;
        if (this.alpha < 0.01) {
            this.remove();
        } else if (1.0 < this.alpha) {
            this.alpha = 1.0;
        }
        if (this.target.mouseON && !this.vanish) {
             this.x += this.vx;
             this.y += this.vy;
//              this.x += (this.target.x-this.x)*0.05;
//              this.y += (this.target.y-this.y)*0.05;
        } else {
             this.vanish = true;
             this.x -= this.vx*3;
             this.y -= this.vy*3;
        }
        var x = this.target.x;
        var y = this.target.y;
        if (this.x-2 < x && x < this.x+2 && this.y-2 < y && y < this.y+2) {
            this.remove();
        }
        this.scaleX *= 0.98;
        this.scaleY *= 0.98;
    },
});

})();<commit_msg>bug fix<commit_after>/*
 *  Effect.js
 *  2014/07/10
 *  @auther minimo
 *  This Program is MIT license.
 */
tds.Effect = [];

(function() {

//p[eBN
tm.define("tds.Effect.Particle", {
    superClass: "tm.display.Shape",
    layer: LAYER_EFFECT_UPPER,

    alpha: 1.0,
    alphaDecayRate: 0.85,
    size: 0,

    image: null,
    isEffect: true,
    isUpper: true,

    init: function(size, initialAlpha, alphaDecayRate) {
        this.superInit();
        size = size || 100;
        if (initialAlpha === undefined) initialAlpha = 1;
        if (alphaDecayRate === undefined) alphaDecayRate = 0.9;

        this.width = this.height = this.size = size;
        this.alpha = initialAlpha;
        this.alphaDecayRate = alphaDecayRate;
        this.blendMode = "lighter";

        var c = this.canvas;
        c.setFillStyle(
            tm.graphics.RadialGradient(size/4, size/4, 0, size/4, size/4, size/4)
                .addColorStopList([
                    {offset:0.0, color: "hsla({0}, 60%, 50%, 0.8)".format(0)},
                    {offset:0.5, color: "hsla({0}, 60%, 50%, 0.4)".format(0)},
                    {offset:1.0, color: "hsla({0}, 60%, 50%, 0.0)".format(0)},
                ]).toStyle()
            )
            .fillRect(0, 0, 50, 50);
    },
    update: function(app) {
        this.alpha *= this.alphaDecayRate;
        if (this.alpha < 0.01) {
            this.remove();
        } else if (1.0 < this.alpha) {
            this.alpha = 1.0;
        }
    },
});

tm.define("tds.Effect.Aura", {
    superClass: "tm.display.Shape",
    layer: LAYER_EFFECT_UPPER,

    init: function(target, size, alphaDecayRate) {
        this.superInit();

        size = size || 100;
        if (alphaDecayRate === undefined) alphaDecayRate = 0.9;

        this.width = this.height = this.size = size;
        this.alpha = 0.02;
        this.alphaDecayRate = alphaDecayRate;
        this.blendMode = "lighter";
        this.tweener.clear().to({alpha:1},200).to({alpha:0},2000);

        this.target = target;
        this.vanish = false;

        this.setScale(size*0.01);

        var c = this.canvas;
        c.setFillStyle(
            tm.graphics.RadialGradient(25, 25, 0, 25, 25, 25)
                .addColorStopList([
                    {offset:0.0, color: "hsla({0}, 60%, 50%, 0.4)".format(200)},
                    {offset:0.5, color: "hsla({0}, 60%, 50%, 0.2)".format(240)},
                    {offset:1.0, color: "hsla({0}, 60%, 50%, 0.0)".format(240)},
                ]).toStyle()
            )
            .fillRect(0, 0, 50, 50);
    },

    update: function() {
//        this.alpha *= this.alphaDecayRate;
        if (this.alpha < 0.01) {
            this.remove();
            return;
        } else if (1.0 < this.alpha) {
            this.alpha = 1.0;
        }
        if (this.target.mouseON && !this.vanish) {
             this.x += this.vx;
             this.y += this.vy;
//              this.x += (this.target.x-this.x)*0.05;
//              this.y += (this.target.y-this.y)*0.05;
        } else {
             this.vanish = true;
             this.x -= this.vx*3;
             this.y -= this.vy*3;
        }
        var x = this.target.x;
        var y = this.target.y;
        if (this.x-2 < x && x < this.x+2 && this.y-2 < y && y < this.y+2) {
            this.remove();
            return;
        }
        this.scaleX *= 0.98;
        this.scaleY *= 0.98;
    },
});

})();<|endoftext|>


<commit_before>import React from 'react';

class Header extends React.Component {
  render() {
    return
Awesome List
;
  }
}

export default Header;
<commit_msg>convert Header to stateless functional component<commit_after>import React from 'react';

function Header() {
  return
Awesome List
;
}

export default Header;
<|endoftext|>


<commit_before>Cut.Loader.load(function(root, container) {

  Cut.Mouse.subscribe(root, container);

  root.viewbox(500, 300);

  var row = Cut.row(0.5).appendTo(root).pin("align", 0.5).spacing(1);

  var colors = [ "green", "blue", "purple", "red", "orange", "yellow" ];
  for (var i = 0; i < colors.length; i++) {
    var color = colors[i];

    Cut.image("color:" + color).appendTo(row)
      .on(Cut.Mouse.CLICK, function(ev, point) {
        this.tween().clear().pin({
          scaleX : Cut.Math.random(0.8, 1.6),
          scaleY : Cut.Math.random(0.8, 1.6)
        });
        return true;
      });
  }

});

Cut.addTexture({
  name : "color",
  imagePath : "colors.png",
  cutouts : [
    { name : "red",    x : 0,   y : 0, width : 30, height : 30 },
    { name : "purple", x : 30,  y : 0, width : 30, height : 30 },
    { name : "blue",   x : 60,  y : 0, width : 30, height : 30 },
    { name : "orange", x : 90,  y : 0, width : 30, height : 30 },
    { name : "yellow", x : 120, y : 0, width : 30, height : 30 },
    { name : "green",  x : 150, y : 0, width : 30, height : 30 }
  ]
});<commit_msg>update sample code<commit_after>// Create new app
Cut.Loader.load(function(root, container) {

  // Subscribe to Cut.Mouse
  Cut.Mouse.subscribe(root, container);

  // Set view box
  root.viewbox(500, 300);

  // Create an image node
  Cut.image("base:box").appendTo(row)
    // on mouse click on this node
    .on(Cut.Mouse.CLICK, function(ev, point) {
      // Tween scaleX/Y value of this node
      this.tween().clear().pin({
        scaleX : Math.random() + 0.5,
        scaleY : Math.random() + 0.5
      });
      return true;
    });

});

// Register an image texture
Cut.addTexture({
  name : "base",
  imagePath : "base.png",
  cutouts : [
    { name : "box", x : 0, y : 0, width : 30, height : 30 }
  ]
});<|endoftext|>