<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 (/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 && document.doctype && document.doctype.name == "html") {
      if (document.readyState === "complete") {
        initializeNow(document);
      } else {
        document.onreadystatechange = () => {
          if (document.readyState === "complete") {
            initializeNow(document);
          }
        }
      }
    }
  }

  function initializeNow(document) {
      // enforce init-once due to redundant callers
      if (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);
      }

      document.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++) {
            checkForVideo(node.children[i],
                          node.children[i].parentNode || parent,
                          added);
          }
        }
      }

      // Process the DOM nodes lazily
      function enqueueCheckNodes(node, parent, added) {
        const checkNodes = _ => checkForVideo(node, parent, added);
        if ('requestIdleCallback' in window) {
          requestIdleCallback(checkNodes, {timeout: 1000});
        } else {
          checkNodes();
        }
      }

      var observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
          forEach.call(mutation.addedNodes, function(node) {
            if (typeof node === "function")
              return;
            enqueueCheckNodes(node, node.parentNode || mutation.target, true);
          });
          forEach.call(mutation.removedNodes, function(node) {
            if (typeof node === "function")
              return;
            enqueueCheckNodes(node, node.parentNode || mutation.target, false);
          });
        });
      });
      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.0625);
          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) {
      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>enqueue the entire MuObs handler instead.<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 (/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 && document.doctype && document.doctype.name == "html") {
      if (document.readyState === "complete") {
        initializeNow(document);
      } else {
        document.onreadystatechange = () => {
          if (document.readyState === "complete") {
            initializeNow(document);
          }
        }
      }
    }
  }

  function initializeNow(document) {
      // enforce init-once due to redundant callers
      if (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);
      }

      document.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++) {
            checkForVideo(node.children[i],
                          node.children[i].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.0625);
          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) {
      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>var path = require('path')
var home = require('os-homedir')

var nonPrivate = require('non-private-ip')
var merge = require('deep-extend')

var RC = require('rc')

var SEC = 1e3
var MIN = 60*SEC

module.exports = function (name, override) {
  name = name || 'ssb'
  var HOME = home() || 'browser' //most probably browser
  return RC(name || 'ssb', merge({
    //just use an ipv4 address by default.
    //there have been some reports of seemingly non-private
    //ipv6 addresses being returned and not working.
    //https://github.com/ssbc/scuttlebot/pull/102
    party: true,
    host: nonPrivate.v4 || '',
    port: 8008,
    timeout: 0,
    pub: true,
    local: true,
    friends: {
      dunbar: 150,
      hops: 3
    },
    ws: {
      port: 8989
    },
    gossip: {
      connections: 3
    },
    connections: {
      incoming: {
        net: [{ port: 8008, scope: "public", "transform": "shs" }]
      },
      outgoing: {
        net: [{ transform: "shs" }]
      }
    },
    path: path.join(HOME, '.' + name),
    timers: {
      connection: 0,
      reconnect: 5*SEC,
      ping: 5*MIN,
      handshake: 5*SEC
    },
    //change these to make a test network that will not connect to the main network.
    caps: {
      //this is the key for accessing the ssb protocol.
      //this will be updated whenever breaking changes are made.
      //(see secret-handshake paper for a full explaination)
      //(generated by crypto.randomBytes(32).toString('base64'))
      shs: '1KHLiKZvAvjbY1ziZEHMXawbCEIM6qwjCDm3VYRan/s=',

      //used to sign messages
      sign: null
    },
    master: [],
    logging: { level: 'notice' },
    party: true //disable quotas
  }, override || {}))
}

<commit_msg>Use port override in connections config<commit_after>var path = require('path')
var home = require('os-homedir')

var nonPrivate = require('non-private-ip')
var merge = require('deep-extend')

var RC = require('rc')

var SEC = 1e3
var MIN = 60*SEC

module.exports = function (name, override) {
  name = name || 'ssb'
  var HOME = home() || 'browser' //most probably browser
  var port = override.port || 8008
  return RC(name || 'ssb', merge({
    //just use an ipv4 address by default.
    //there have been some reports of seemingly non-private
    //ipv6 addresses being returned and not working.
    //https://github.com/ssbc/scuttlebot/pull/102
    party: true,
    host: nonPrivate.v4 || '',
    port: port,
    timeout: 0,
    pub: true,
    local: true,
    friends: {
      dunbar: 150,
      hops: 3
    },
    ws: {
      port: 8989
    },
    gossip: {
      connections: 3
    },
    connections: {
      incoming: {
        net: [{ port: port, scope: "public", "transform": "shs" }]
      },
      outgoing: {
        net: [{ transform: "shs" }]
      }
    },
    path: path.join(HOME, '.' + name),
    timers: {
      connection: 0,
      reconnect: 5*SEC,
      ping: 5*MIN,
      handshake: 5*SEC
    },
    //change these to make a test network that will not connect to the main network.
    caps: {
      //this is the key for accessing the ssb protocol.
      //this will be updated whenever breaking changes are made.
      //(see secret-handshake paper for a full explaination)
      //(generated by crypto.randomBytes(32).toString('base64'))
      shs: '1KHLiKZvAvjbY1ziZEHMXawbCEIM6qwjCDm3VYRan/s=',

      //used to sign messages
      sign: null
    },
    master: [],
    logging: { level: 'notice' },
    party: true //disable quotas
  }, override || {}))
}

<|endoftext|>


<commit_before>// add : select a text and press a shortcut key or right click option to get the wiki for the selected text
// implement drag ? good feature or not?
// set opacity according to input range
// detect the body background and set your background accordingly to suit asthetic
// get a settings page.
// disable on a form or input element
// run only when double click gives a string
// select a text and shortcut (different) allows you to collect links from a page. when the work is done open the extension and fire all links or 1 link at a time.
// place a (less..) or up arrow/triangle on the bottom when a hidden heading is expanded to indicate hide again feature from bottom

// side panel
var div = document.createElement("div");
// resize handler
var handle = document.createElement("div");
// content
var innerDiv = document.createElement("div");
// close span
var closeSpan = document.createElement("span");
// divs to un/hide the text
var hiders;

// add class close-span
closeSpan.classList.add("extension-close-span");

// add class inner-div
innerDiv.classList.add("extension-inner-div");

// format close button
closeSpan.innerHTML = "✖";

// format resize handle
Object.assign( handle.style, {
                                bottom: "0",
                                left: "0",
                                cursor: "nesw-resize",
                                position: "absolute",
                                width: "10px",
                                height: "10px",
                                background: "red"
                              });

// format inner div
Object.assign( innerDiv.style, {
                                  position: "relative",
                                  overflowY: "auto",
                                  height: "90%",
                                  width: "100%",
                                  textAlign: "justify"
                              });

// format side panel
Object.assign(div.style , {
                            position: "absolute",
                            right: "0",
                            width: "0",
                            // background: "#28aadc",
                            background: "#2f4f4f",
                            opacity: "0",
                            overflow: "hidden",
                            boxShadow: "-8px 5px 20px -4px rgba(122,119,140,0.71)"
                          });
div.style.zIndex = "9999";
div.style.top = window.scrollY + 40 +"px";

// append resize handle to side panel and side panel to body
div.appendChild(closeSpan);
div.appendChild(handle);
div.appendChild(innerDiv);
document.body.appendChild(div);

// change the width and height of side panel according to the mouse position
function startResize(e){
  e.preventDefault();
  // console.log(e.clientY, div.offsetTop);
  div.style.width = (window.innerWidth - e.clientX - 30) + "px";
  div.style.height = (e.clientY - 100) + "px";
}

// remove events when up
function stopResize(){
  window.removeEventListener("mousemove", startResize);
  window.removeEventListener("mouseup", stopResize);
}

// checks for mousemovement and mouseup
function initResize(){
  window.addEventListener("mousemove", startResize);
  window.addEventListener("mouseup", stopResize);
}

function closePanel(){
  div.style.height = "0";
  div.style.width = "0";
  div.style.opacity = "0";
  div.style.padding = "0";
  innerDiv.style.padding = 0;
}

// check if class "hide" is added. If yes, then remove else add
function unhide(e){
  // console.log(e);
  if(e.target.localName == "h2"){
    var hide = e.srcElement.parentElement.children[1];
    if(!hide.classList.length)
      hide.classList.add("hide")
    else hide.classList.remove("hide");
  }
}

// start resizing
handle.addEventListener("mousedown", initResize);
// close the side panel
closeSpan.addEventListener("click", closePanel);

// side panel styling
function styleSidePanel(){

  // transition side panel
  div.style.width = "350px";
  div.style.height = "75vh";
  div.style.opacity = "1";
  div.style.padding = "50px 10px 0 10px";
  div.style.transition = `opacity 0.5s ease-in-out`;
  div.style.top = window.scrollY + 55 +"px";
  // div.style.transition = `translateY 1s cubic-bezier(0.68, -0.85, 0.265, 1.55)`;

  // inner div padding
  innerDiv.style.padding = "0 10px 0 10px";

}

function getString(){

  console.log(window.getSelection().toString());

  // get the word on which the event double click triggered
  var val = window.getSelection().toString();

  // format val for spaces
  val = val.trim().replace(/\s/g, "_");
  console.log("format value: ", val);

  // url to get data from
  var url = "https://en.wikipedia.org/w/api.php?action=parse&format=json&page="+val+"&prop=text&redirects=1";

  // get the data, format it and put it in the side panel
  $.getJSON(url, data => {

    console.log(data);

    // If no result returned
    if(data.error){
      alert("No result for the term");
      return;
    }

    styleSidePanel();

    // get the markup in a div container which gives htmlcollection[] object
    innerDiv.innerHTML = data.parse.text["*"];

    // convert the htmlcollection to array and remove unwanted properties
    var children = Array.from(innerDiv.children);
        children = children.filter( child => {
          // console.log(child.tagName);
          return child.tagName !== "TABLE" && child.tagName !== "DIV";
        });

    // format the array, convert it into string
    var html = children.map( child => {
                if(child.tagName === "P")
                  return `<p class="para-graph">${child.innerText}</p>`;
                else if(child.tagName === "H2")
                  return `</article></div><div id="${child.innerText.replace(/\[\w+\]/, "")}"><h2 class="heading2">${child.innerText}</h2><article class="hide">`;
                else if(child.tagName === "H3")
                  return `<h3 class="heading3">${child.innerText}</h3>`;
                else  return `<ul class="para-graph">${child.innerText}</ul>`;
              })
              .join("")
              .replace(/\[\w+\]/g, "");

    // remove extra div and article tags from the begining
    html = html.replace("

", "");

    // Get the indexes of See also , Footnotes, References, External Links and other redundant headings
    var see = html.indexOf("See also") === -1 ? html.length : html.indexOf("See also");
    var ref = html.indexOf("References") === -1 ? html.length : html.indexOf("References");
    var ext = html.indexOf("External links") === -1 ? html.length : html.indexOf("External links");
    var foot = html.indexOf("Footnotes") === -1 ? html.length : html.indexOf("Footnotes");
    // store the minimum
    var min = Math.min(see, ref, ext, foot);
    // if none of these are present in the document then -1 will be displayed
    // so using ternary operator
    var index = min === -1 ? html.length : min;
    // console.log("all",{see,ref,ext,foot});
    // console.log(index);

    // get string only till useful content
    // append formatted string into innerDiv
    innerDiv.innerHTML = html.substring(0, index);
    // innerDiv.innerHTML = html;

    // add css to innerDiv children
    /*
    var children = innerDiv.children;
    for(var i= 0; i< children.length; i++){
      children[i].style.color = "wheat";
    }*/

    // add all inner divs to un/hide
    hiders = Array.from(innerDiv.querySelectorAll("div"));
    hiders.forEach( hider => {
      // console.log(hider);
      hider.addEventListener("click", unhide);
    });
    // beginHiders;

  });
}

document.addEventListener("dblclick" , getString);

function detectKeys(e){
  // console.log(e);
  if(e.shiftKey && e.altKey && e.which === 81){
    console.log("shortcut activate");
    // console.log(window.getSelection().toString());
    getString();
  }
}

// detect shortcut / hotkey and fire getString
document.addEventListener("keydown", detectKeys);<commit_msg>inject.js: message passing successful between context menu and side panel<commit_after>// add : select a text and press a shortcut key or right click option to get the wiki for the selected text
// implement drag ? good feature or not?
// set opacity according to input range
// detect the body background and set your background accordingly to suit asthetic
// get a settings page.
// disable on a form or input element
// run only when double click gives a string
// select a text and shortcut (different) allows you to collect links from a page. when the work is done open the extension and fire all links or 1 link at a time.
// place a (less..) or up arrow/triangle on the bottom when a hidden heading is expanded to indicate hide again feature from bottom

// side panel
var div = document.createElement("div");
// resize handler
var handle = document.createElement("div");
// content
var innerDiv = document.createElement("div");
// close span
var closeSpan = document.createElement("span");
// divs to un/hide the text
var hiders;

// add class close-span
closeSpan.classList.add("extension-close-span");

// add class inner-div
innerDiv.classList.add("extension-inner-div");

// format close button
closeSpan.innerHTML = "✖";

// format resize handle
Object.assign( handle.style, {
                                bottom: "0",
                                left: "0",
                                cursor: "nesw-resize",
                                position: "absolute",
                                width: "10px",
                                height: "10px",
                                background: "red"
                              });

// format inner div
Object.assign( innerDiv.style, {
                                  position: "relative",
                                  overflowY: "auto",
                                  height: "90%",
                                  width: "100%",
                                  textAlign: "justify"
                              });

// format side panel
Object.assign(div.style , {
                            position: "absolute",
                            right: "0",
                            width: "0",
                            // background: "#28aadc",
                            background: "#2f4f4f",
                            opacity: "0",
                            overflow: "hidden",
                            boxShadow: "-8px 5px 20px -4px rgba(122,119,140,0.71)"
                          });
div.style.zIndex = "9999";
div.style.top = window.scrollY + 40 +"px";

// append resize handle to side panel and side panel to body
div.appendChild(closeSpan);
div.appendChild(handle);
div.appendChild(innerDiv);
document.body.appendChild(div);

// change the width and height of side panel according to the mouse position
function startResize(e){
  e.preventDefault();
  // console.log(e.clientY, div.offsetTop);
  div.style.width = (window.innerWidth - e.clientX - 30) + "px";
  div.style.height = (e.clientY - 100) + "px";
}

// remove events when up
function stopResize(){
  window.removeEventListener("mousemove", startResize);
  window.removeEventListener("mouseup", stopResize);
}

// checks for mousemovement and mouseup
function initResize(){
  window.addEventListener("mousemove", startResize);
  window.addEventListener("mouseup", stopResize);
}

function closePanel(){
  div.style.height = "0";
  div.style.width = "0";
  div.style.opacity = "0";
  div.style.padding = "0";
  innerDiv.style.padding = 0;
}

// check if class "hide" is added. If yes, then remove else add
function unhide(e){
  // console.log(e);
  if(e.target.localName == "h2"){
    var hide = e.srcElement.parentElement.children[1];
    if(!hide.classList.length)
      hide.classList.add("hide")
    else hide.classList.remove("hide");
  }
}

// start resizing
handle.addEventListener("mousedown", initResize);
// close the side panel
closeSpan.addEventListener("click", closePanel);

// side panel styling
function styleSidePanel(){

  // transition side panel
  div.style.width = "350px";
  div.style.height = "75vh";
  div.style.opacity = "1";
  div.style.padding = "50px 10px 0 10px";
  div.style.transition = `opacity 0.5s ease-in-out`;
  div.style.top = window.scrollY + 55 +"px";
  // div.style.transition = `translateY 1s cubic-bezier(0.68, -0.85, 0.265, 1.55)`;

  // inner div padding
  innerDiv.style.padding = "0 10px 0 10px";

}

function getString(){

  console.log(window.getSelection().toString());

  // get the word on which the event double click triggered
  var val = window.getSelection().toString();

  // format val for spaces
  val = val.trim().replace(/\s/g, "_");
  console.log("format value: ", val);

  // url to get data from
  var url = "https://en.wikipedia.org/w/api.php?action=parse&format=json&page="+val+"&prop=text&redirects=1";

  // get the data, format it and put it in the side panel
  $.getJSON(url, data => {

    // console.log(data);

    // If no result returned
    if(data.error){
      alert("No result for the term");
      return;
    }

    styleSidePanel();

    // get the markup in a div container which gives htmlcollection[] object
    innerDiv.innerHTML = data.parse.text["*"];

    // convert the htmlcollection to array and remove unwanted properties
    var children = Array.from(innerDiv.children);
        children = children.filter( child => {
          // console.log(child.tagName);
          return child.tagName !== "TABLE" && child.tagName !== "DIV";
        });

    // format the array, convert it into string
    var html = children.map( child => {
                if(child.tagName === "P")
                  return `<p class="para-graph">${child.innerText}</p>`;
                else if(child.tagName === "H2")
                  return `</article></div><div id="${child.innerText.replace(/\[\w+\]/, "")}"><h2 class="heading2">${child.innerText}</h2><article class="hide">`;
                else if(child.tagName === "H3")
                  return `<h3 class="heading3">${child.innerText}</h3>`;
                else  return `<ul class="para-graph">${child.innerText}</ul>`;
              })
              .join("")
              .replace(/\[\w+\]/g, "");

    // remove extra div and article tags from the begining
    html = html.replace("

", "");

    // Get the indexes of See also , Footnotes, References, External Links and other redundant headings
    var see = html.indexOf("See also") === -1 ? html.length : html.indexOf("See also");
    var ref = html.indexOf("References") === -1 ? html.length : html.indexOf("References");
    var ext = html.indexOf("External links") === -1 ? html.length : html.indexOf("External links");
    var foot = html.indexOf("Footnotes") === -1 ? html.length : html.indexOf("Footnotes");
    // store the minimum
    var min = Math.min(see, ref, ext, foot);
    // if none of these are present in the document then -1 will be displayed
    // so using ternary operator
    var index = min === -1 ? html.length : min;
    // console.log("all",{see,ref,ext,foot});
    // console.log(index);

    // get string only till useful content
    // append formatted string into innerDiv
    innerDiv.innerHTML = html.substring(0, index);
    // innerDiv.innerHTML = html;

    // add css to innerDiv children
    /*
    var children = innerDiv.children;
    for(var i= 0; i< children.length; i++){
      children[i].style.color = "wheat";
    }*/

    // add all inner divs to un/hide
    hiders = Array.from(innerDiv.querySelectorAll("div"));
    hiders.forEach( hider => {
      // console.log(hider);
      hider.addEventListener("click", unhide);
    });
    // beginHiders;

  });
}

document.addEventListener("dblclick" , getString);

function detectKeys(e){
  // console.log(e);
  if(e.shiftKey && e.altKey && e.which === 81){
    console.log("shortcut activate");
    // console.log(window.getSelection().toString());
    getString();
  }
}

// detect shortcut / hotkey and fire getString
document.addEventListener("keydown", detectKeys);

// receive message from background.js
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
    // console.log({request, sender, sendResponse});
    getString();
})<|endoftext|>


<commit_before>let todo

function inject (...services) {
    return function toInject (Controller) {
        Controller.$inject = services

        function doInject (...args) {
            services.forEach((name, index) => {
                this[name] = args[index]
            })
        }

        todo(Controller.prototype, doInject, 'before')
    }
}

inject.install = function (ScopeController) {
    todo = ScopeController.$$todo
    ScopeController.inject = inject
}

module.exports = inject
<commit_msg>Support to inject controller many times<commit_after>let todo

function inject (...services) {
    return function toInject (Controller) {
        if (Array.isArray(Controller.$inject)) {
            services.push(...Controller.$inject)
            services = Array.from(new Set(services))
        }
        Controller.$inject = services

        function doInject (...args) {
            services.forEach((name, index) => {
                this[name] = args[index]
            })
        }

        todo(Controller.prototype, doInject, 'before')
    }
}

inject.install = function (ScopeController) {
    todo = ScopeController.$$todo
    ScopeController.inject = inject
}

module.exports = inject
<|endoftext|>


<commit_before>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule MapView
 * @flow
 */
'use strict';

var EdgeInsetsPropType = require('EdgeInsetsPropType');
var Image = require('Image');
var NativeMethodsMixin = require('NativeMethodsMixin');
var Platform = require('Platform');
var RCTMapConstants = require('NativeModules').UIManager.RCTMap.Constants;
var React = require('React');
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
var View = require('View');

var deepDiffer = require('deepDiffer');
var insetsDiffer = require('insetsDiffer');
var merge = require('merge');
var processColor = require('processColor');
var resolveAssetSource = require('resolveAssetSource');
var requireNativeComponent = require('requireNativeComponent');

type Event = Object;
type MapRegion = {
  latitude: number;
  longitude: number;
  latitudeDelta: number;
  longitudeDelta: number;
};

var MapView = React.createClass({
  mixins: [NativeMethodsMixin],

  checkAnnotationIds: function (annotations: Array<Object>) {

    var newAnnotations = annotations.map(function (annotation) {
      if (!annotation.id) {
        // TODO: add a base64 (or similar) encoder here
        annotation.id = encodeURIComponent(JSON.stringify(annotation));
      }
      return annotation;
    });

    this.setState({
      annotations: newAnnotations
    });
  },

  checkOverlayIds: function (overlays: Array<Object>) {

    var newOverlays = overlays.map(function (overlay) {
      if (!overlay.id) {
        // TODO: add a base64 (or similar) encoder here
        overlay.id = encodeURIComponent(JSON.stringify(overlay));
      }
      return overlay;
    });

    this.setState({
      overlays: newOverlays
    });
  },

  componentWillMount: function() {
    if (this.props.annotations) {
      this.checkAnnotationIds(this.props.annotations);
    }
    if (this.props.overlays) {
      this.checkOverlayIds(this.props.overlays);
    }
  },

  componentWillReceiveProps: function(nextProps: Object) {
    if (nextProps.annotations) {
      this.checkAnnotationIds(nextProps.annotations);
    }
    if (nextProps.overlays) {
      this.checkOverlayIds(nextProps.overlays);
    }
  },

  propTypes: {
    ...View.propTypes,
    /**
     * Used to style and layout the `MapView`.  See `StyleSheet.js` and
     * `ViewStylePropTypes.js` for more info.
     */
    style: View.propTypes.style,

    /**
     * If `true` the app will ask for the user's location and focus on it.
     * Default value is `false`.
     *
     * **NOTE**: You need to add NSLocationWhenInUseUsageDescription key in
     * Info.plist to enable geolocation, otherwise it is going
     * to *fail silently*!
     */
    showsUserLocation: React.PropTypes.bool,

    /**
     * If `false` points of interest won't be displayed on the map.
     * Default value is `true`.
     * @platform ios
     */
    showsPointsOfInterest: React.PropTypes.bool,

    /**
     * If `false` compass won't be displayed on the map.
     * Default value is `true`.
     * @platform ios
     */
    showsCompass: React.PropTypes.bool,

    /**
     * If `false` the user won't be able to pinch/zoom the map.
     * Default value is `true`.
     */
    zoomEnabled: React.PropTypes.bool,

    /**
     * When this property is set to `true` and a valid camera is associated with
     * the map, the camera’s heading angle is used to rotate the plane of the
     * map around its center point. When this property is set to `false`, the
     * camera’s heading angle is ignored and the map is always oriented so
     * that true north is situated at the top of the map view
     */
    rotateEnabled: React.PropTypes.bool,

    /**
     * When this property is set to `true` and a valid camera is associated
     * with the map, the camera’s pitch angle is used to tilt the plane
     * of the map. When this property is set to `false`, the camera’s pitch
     * angle is ignored and the map is always displayed as if the user
     * is looking straight down onto it.
     */
    pitchEnabled: React.PropTypes.bool,

    /**
     * If `false` the user won't be able to change the map region being displayed.
     * Default value is `true`.
     */
    scrollEnabled: React.PropTypes.bool,

    /**
     * The map type to be displayed.
     *
     * - standard: standard road map (default)
     * - satellite: satellite view
     * - hybrid: satellite view with roads and points of interest overlayed
     */
    mapType: React.PropTypes.oneOf([
      'standard',
      'satellite',
      'hybrid',
    ]),

    /**
     * The region to be displayed by the map.
     *
     * The region is defined by the center coordinates and the span of
     * coordinates to display.
     */
    region: React.PropTypes.shape({
      /**
       * Coordinates for the center of the map.
       */
      latitude: React.PropTypes.number.isRequired,
      longitude: React.PropTypes.number.isRequired,

      /**
       * Distance between the minimun and the maximum latitude/longitude
       * to be displayed.
       */
      latitudeDelta: React.PropTypes.number.isRequired,
      longitudeDelta: React.PropTypes.number.isRequired,
    }),

    /**
     * Map annotations with title/subtitle.
     */
    annotations: React.PropTypes.arrayOf(React.PropTypes.shape({
      /**
       * The location of the annotation.
       */
      latitude: React.PropTypes.number.isRequired,
      longitude: React.PropTypes.number.isRequired,

      /**
       * Whether the pin drop should be animated or not
       */
      animateDrop: React.PropTypes.bool,

      /**
       * Annotation title/subtile.
       */
      title: React.PropTypes.string,
      subtitle: React.PropTypes.string,

      /**
       * Whether the Annotation has callout buttons.
       */
      hasLeftCallout: React.PropTypes.bool,
      hasRightCallout: React.PropTypes.bool,

      /**
       * Event handlers for callout buttons.
       */
      onLeftCalloutPress: React.PropTypes.func,
      onRightCalloutPress: React.PropTypes.func,

      /**
       * The pin color. This can be any valid color string, or you can use one
       * of the predefined PinColors constants. Applies to both standard pins
       * and custom pin images.
       *
       * Note that on iOS 8 and earlier, only the standard PinColor constants
       * are supported for regualr pins. For custom pin images, any tintColor
       * value is supported on all iOS versions.
       * @platform ios
       */
      tintColor: React.PropTypes.string,

      /**
       * Custom pin image. This must be a static image resource inside the app.
       * @platform ios
       */
      image: Image.propTypes.source,

      /**
       * annotation id
       */
      id: React.PropTypes.string,
    })),

    /**
     * Map overlays
     */
    overlays: React.PropTypes.arrayOf(React.PropTypes.shape({
      /**
       * Polyline coordinates
       */
      coordinates: React.PropTypes.arrayOf(React.PropTypes.shape({
        latitude: React.PropTypes.number.isRequired,
        longitude: React.PropTypes.number.isRequired
      })),

      /**
       * Line attributes
       */
      lineWidth: React.PropTypes.number,
      strokeColor: React.PropTypes.string,
      fillColor: React.PropTypes.string,

      /**
       * Overlay id
       */
      id: React.PropTypes.string
    })),

    /**
     * Maximum size of area that can be displayed.
     */
    maxDelta: React.PropTypes.number,

    /**
     * Minimum size of area that can be displayed.
     */
    minDelta: React.PropTypes.number,

    /**
     * Insets for the map's legal label, originally at bottom left of the map.
     * See `EdgeInsetsPropType.js` for more information.
     */
    legalLabelInsets: EdgeInsetsPropType,

    /**
     * Callback that is called continuously when the user is dragging the map.
     */
    onRegionChange: React.PropTypes.func,

    /**
     * Callback that is called once, when the user is done moving the map.
     */
    onRegionChangeComplete: React.PropTypes.func,

    /**
     * Callback that is called once, when the user taps an annotation.
     */
    onAnnotationPress: React.PropTypes.func,

    /**
     * @platform android
     */
    active: React.PropTypes.bool,
  },

  render: function() {

    let {annotations, overlays} = this.props;
    annotations = annotations && annotations.map((annotation: Object) => {
      let {tintColor, image} = annotation;
      return {
        ...annotation,
        tintColor: tintColor && processColor(tintColor),
        image: image && resolveAssetSource(image),
      };
    });
    overlays = overlays && overlays.map((overlay: Object) => {
      let {strokeColor, fillColor} = overlay;
      return {
        ...overlay,
        strokeColor: strokeColor && processColor(strokeColor),
        fillColor: fillColor && processColor(fillColor),
      };
    });

    // TODO: these should be separate events, to reduce bridge traffic
    if (annotations) {
      var onPress = (event: Event) => {
        if (!annotations) {
          return;
        }
        if (event.nativeEvent.action === 'annotation-click') {
          this.props.onAnnotationPress &&
            this.props.onAnnotationPress(event.nativeEvent.annotation);
        } else if (event.nativeEvent.action === 'callout-click') {
          // Find the annotation with the id that was pressed
          for (let i = 0, l = annotations.length; i < l; i++) {
            let annotation = annotations[i];
            if (annotation.id === event.nativeEvent.annotationId) {
              // Pass the right function
              if (event.nativeEvent.side === 'left') {
                annotation.onLeftCalloutPress &&
                  annotation.onLeftCalloutPress(event.nativeEvent);
              } else if (event.nativeEvent.side === 'right') {
                annotation.onRightCalloutPress &&
                  annotation.onRightCalloutPress(event.nativeEvent);
              }
              break;
            }
          }
        }
      };
    }

    // TODO: these should be separate events, to reduce bridge traffic
    if (this.props.onRegionChange || this.props.onRegionChangeComplete) {
      var onChange = (event: Event) => {
        if (event.nativeEvent.continuous) {
          this.props.onRegionChange &&
            this.props.onRegionChange(event.nativeEvent.region);
        } else {
          this.props.onRegionChangeComplete &&
            this.props.onRegionChangeComplete(event.nativeEvent.region);
        }
      };
    }

    return (
      <RCTMap
        {...this.props}
        annotations={annotations}
        overlays={overlays}
        onPress={onPress}
        onChange={onChange}
      />
    );
  },
});

/**
 * Standard iOS MapView pin color constants, to be used with the
 * `annotation.tintColor` property. On iOS 8 and earlier these are the
 * only supported values when using regular pins. On iOS 9 and later
 * you are not obliged to use these, but they are useful for matching
 * the standard iOS look and feel.
 */
let PinColors = RCTMapConstants && RCTMapConstants.PinColors;
MapView.PinColors = PinColors && {
  RED: PinColors.RED,
  GREEN: PinColors.GREEN,
  PURPLE: PinColors.PURPLE,
};

var RCTMap = requireNativeComponent('RCTMap', MapView, {
  nativeOnly: {onChange: true, onPress: true}
});

module.exports = MapView;
<commit_msg>Android - Fixing #4392<commit_after>/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * @providesModule MapView
 * @flow
 */
'use strict';

var EdgeInsetsPropType = require('EdgeInsetsPropType');
var Image = require('Image');
var NativeMethodsMixin = require('NativeMethodsMixin');
var Platform = require('Platform');
var RCTMap = require('UIManager').RCTMap;
var RCTMapConstants = RCTMap && RCTMap.Constants;
var React = require('React');
var ReactNativeViewAttributes = require('ReactNativeViewAttributes');
var View = require('View');

var deepDiffer = require('deepDiffer');
var insetsDiffer = require('insetsDiffer');
var merge = require('merge');
var processColor = require('processColor');
var resolveAssetSource = require('resolveAssetSource');
var requireNativeComponent = require('requireNativeComponent');

type Event = Object;
type MapRegion = {
  latitude: number;
  longitude: number;
  latitudeDelta: number;
  longitudeDelta: number;
};

var MapView = React.createClass({
  mixins: [NativeMethodsMixin],

  checkAnnotationIds: function (annotations: Array<Object>) {

    var newAnnotations = annotations.map(function (annotation) {
      if (!annotation.id) {
        // TODO: add a base64 (or similar) encoder here
        annotation.id = encodeURIComponent(JSON.stringify(annotation));
      }
      return annotation;
    });

    this.setState({
      annotations: newAnnotations
    });
  },

  checkOverlayIds: function (overlays: Array<Object>) {

    var newOverlays = overlays.map(function (overlay) {
      if (!overlay.id) {
        // TODO: add a base64 (or similar) encoder here
        overlay.id = encodeURIComponent(JSON.stringify(overlay));
      }
      return overlay;
    });

    this.setState({
      overlays: newOverlays
    });
  },

  componentWillMount: function() {
    if (this.props.annotations) {
      this.checkAnnotationIds(this.props.annotations);
    }
    if (this.props.overlays) {
      this.checkOverlayIds(this.props.overlays);
    }
  },

  componentWillReceiveProps: function(nextProps: Object) {
    if (nextProps.annotations) {
      this.checkAnnotationIds(nextProps.annotations);
    }
    if (nextProps.overlays) {
      this.checkOverlayIds(nextProps.overlays);
    }
  },

  propTypes: {
    ...View.propTypes,
    /**
     * Used to style and layout the `MapView`.  See `StyleSheet.js` and
     * `ViewStylePropTypes.js` for more info.
     */
    style: View.propTypes.style,

    /**
     * If `true` the app will ask for the user's location and focus on it.
     * Default value is `false`.
     *
     * **NOTE**: You need to add NSLocationWhenInUseUsageDescription key in
     * Info.plist to enable geolocation, otherwise it is going
     * to *fail silently*!
     */
    showsUserLocation: React.PropTypes.bool,

    /**
     * If `false` points of interest won't be displayed on the map.
     * Default value is `true`.
     * @platform ios
     */
    showsPointsOfInterest: React.PropTypes.bool,

    /**
     * If `false` compass won't be displayed on the map.
     * Default value is `true`.
     * @platform ios
     */
    showsCompass: React.PropTypes.bool,

    /**
     * If `false` the user won't be able to pinch/zoom the map.
     * Default value is `true`.
     */
    zoomEnabled: React.PropTypes.bool,

    /**
     * When this property is set to `true` and a valid camera is associated with
     * the map, the camera’s heading angle is used to rotate the plane of the
     * map around its center point. When this property is set to `false`, the
     * camera’s heading angle is ignored and the map is always oriented so
     * that true north is situated at the top of the map view
     */
    rotateEnabled: React.PropTypes.bool,

    /**
     * When this property is set to `true` and a valid camera is associated
     * with the map, the camera’s pitch angle is used to tilt the plane
     * of the map. When this property is set to `false`, the camera’s pitch
     * angle is ignored and the map is always displayed as if the user
     * is looking straight down onto it.
     */
    pitchEnabled: React.PropTypes.bool,

    /**
     * If `false` the user won't be able to change the map region being displayed.
     * Default value is `true`.
     */
    scrollEnabled: React.PropTypes.bool,

    /**
     * The map type to be displayed.
     *
     * - standard: standard road map (default)
     * - satellite: satellite view
     * - hybrid: satellite view with roads and points of interest overlayed
     */
    mapType: React.PropTypes.oneOf([
      'standard',
      'satellite',
      'hybrid',
    ]),

    /**
     * The region to be displayed by the map.
     *
     * The region is defined by the center coordinates and the span of
     * coordinates to display.
     */
    region: React.PropTypes.shape({
      /**
       * Coordinates for the center of the map.
       */
      latitude: React.PropTypes.number.isRequired,
      longitude: React.PropTypes.number.isRequired,

      /**
       * Distance between the minimun and the maximum latitude/longitude
       * to be displayed.
       */
      latitudeDelta: React.PropTypes.number.isRequired,
      longitudeDelta: React.PropTypes.number.isRequired,
    }),

    /**
     * Map annotations with title/subtitle.
     */
    annotations: React.PropTypes.arrayOf(React.PropTypes.shape({
      /**
       * The location of the annotation.
       */
      latitude: React.PropTypes.number.isRequired,
      longitude: React.PropTypes.number.isRequired,

      /**
       * Whether the pin drop should be animated or not
       */
      animateDrop: React.PropTypes.bool,

      /**
       * Annotation title/subtile.
       */
      title: React.PropTypes.string,
      subtitle: React.PropTypes.string,

      /**
       * Whether the Annotation has callout buttons.
       */
      hasLeftCallout: React.PropTypes.bool,
      hasRightCallout: React.PropTypes.bool,

      /**
       * Event handlers for callout buttons.
       */
      onLeftCalloutPress: React.PropTypes.func,
      onRightCalloutPress: React.PropTypes.func,

      /**
       * The pin color. This can be any valid color string, or you can use one
       * of the predefined PinColors constants. Applies to both standard pins
       * and custom pin images.
       *
       * Note that on iOS 8 and earlier, only the standard PinColor constants
       * are supported for regualr pins. For custom pin images, any tintColor
       * value is supported on all iOS versions.
       * @platform ios
       */
      tintColor: React.PropTypes.string,

      /**
       * Custom pin image. This must be a static image resource inside the app.
       * @platform ios
       */
      image: Image.propTypes.source,

      /**
       * annotation id
       */
      id: React.PropTypes.string,
    })),

    /**
     * Map overlays
     */
    overlays: React.PropTypes.arrayOf(React.PropTypes.shape({
      /**
       * Polyline coordinates
       */
      coordinates: React.PropTypes.arrayOf(React.PropTypes.shape({
        latitude: React.PropTypes.number.isRequired,
        longitude: React.PropTypes.number.isRequired
      })),

      /**
       * Line attributes
       */
      lineWidth: React.PropTypes.number,
      strokeColor: React.PropTypes.string,
      fillColor: React.PropTypes.string,

      /**
       * Overlay id
       */
      id: React.PropTypes.string
    })),

    /**
     * Maximum size of area that can be displayed.
     */
    maxDelta: React.PropTypes.number,

    /**
     * Minimum size of area that can be displayed.
     */
    minDelta: React.PropTypes.number,

    /**
     * Insets for the map's legal label, originally at bottom left of the map.
     * See `EdgeInsetsPropType.js` for more information.
     */
    legalLabelInsets: EdgeInsetsPropType,

    /**
     * Callback that is called continuously when the user is dragging the map.
     */
    onRegionChange: React.PropTypes.func,

    /**
     * Callback that is called once, when the user is done moving the map.
     */
    onRegionChangeComplete: React.PropTypes.func,

    /**
     * Callback that is called once, when the user taps an annotation.
     */
    onAnnotationPress: React.PropTypes.func,

    /**
     * @platform android
     */
    active: React.PropTypes.bool,
  },

  render: function() {

    let {annotations, overlays} = this.props;
    annotations = annotations && annotations.map((annotation: Object) => {
      let {tintColor, image} = annotation;
      return {
        ...annotation,
        tintColor: tintColor && processColor(tintColor),
        image: image && resolveAssetSource(image),
      };
    });
    overlays = overlays && overlays.map((overlay: Object) => {
      let {strokeColor, fillColor} = overlay;
      return {
        ...overlay,
        strokeColor: strokeColor && processColor(strokeColor),
        fillColor: fillColor && processColor(fillColor),
      };
    });

    // TODO: these should be separate events, to reduce bridge traffic
    if (annotations) {
      var onPress = (event: Event) => {
        if (!annotations) {
          return;
        }
        if (event.nativeEvent.action === 'annotation-click') {
          this.props.onAnnotationPress &&
            this.props.onAnnotationPress(event.nativeEvent.annotation);
        } else if (event.nativeEvent.action === 'callout-click') {
          // Find the annotation with the id that was pressed
          for (let i = 0, l = annotations.length; i < l; i++) {
            let annotation = annotations[i];
            if (annotation.id === event.nativeEvent.annotationId) {
              // Pass the right function
              if (event.nativeEvent.side === 'left') {
                annotation.onLeftCalloutPress &&
                  annotation.onLeftCalloutPress(event.nativeEvent);
              } else if (event.nativeEvent.side === 'right') {
                annotation.onRightCalloutPress &&
                  annotation.onRightCalloutPress(event.nativeEvent);
              }
              break;
            }
          }
        }
      };
    }

    // TODO: these should be separate events, to reduce bridge traffic
    if (this.props.onRegionChange || this.props.onRegionChangeComplete) {
      var onChange = (event: Event) => {
        if (event.nativeEvent.continuous) {
          this.props.onRegionChange &&
            this.props.onRegionChange(event.nativeEvent.region);
        } else {
          this.props.onRegionChangeComplete &&
            this.props.onRegionChangeComplete(event.nativeEvent.region);
        }
      };
    }

    return (
      <RCTMap
        {...this.props}
        annotations={annotations}
        overlays={overlays}
        onPress={onPress}
        onChange={onChange}
      />
    );
  },
});

/**
 * Standard iOS MapView pin color constants, to be used with the
 * `annotation.tintColor` property. On iOS 8 and earlier these are the
 * only supported values when using regular pins. On iOS 9 and later
 * you are not obliged to use these, but they are useful for matching
 * the standard iOS look and feel.
 */
let PinColors = RCTMapConstants && RCTMapConstants.PinColors;
MapView.PinColors = PinColors && {
  RED: PinColors.RED,
  GREEN: PinColors.GREEN,
  PURPLE: PinColors.PURPLE,
};

var RCTMap = requireNativeComponent('RCTMap', MapView, {
  nativeOnly: {onChange: true, onPress: true}
});

module.exports = MapView;
<|endoftext|>


<commit_before>M.wrap('github/jillix/bind-filter/dev/inputs.js', function (require, module, exports) {
// TODO use bind for dom interaction/manipulation
function elm(d,a){try{var b=document.createElement(d);if("object"===typeof a)for(var c in a)b.setAttribute(c,a[c]);return b}catch(e){return null}}

var getFieldLabel = require('./validate').getFieldLabel;

function fields () {
    var self = this;
    var fields = self.templates[self.template].schema;

    var df = document.createDocumentFragment();
    var locale = M.getLocale();
    for (var field in fields) {
        if (field.indexOf('_') !== 0 && !fields[field].noSearch) {
            var option = elm('option', {value: field});
            option.innerHTML = getFieldLabel.call(self, field, locale);
            df.appendChild(option);
        }
    }

    if (self.domRefs.inputs.field) {
        self.domRefs.inputs.field.innerHTML = '';
        self.domRefs.inputs.field.appendChild(df);
    }
}

function checkOperator (fieldTemplate, operator) {
    var self = this;

    if (self.config.operators[operator][1] === 'mixed' || (self.config.operators[operator][1].indexOf(fieldTemplate) > -1)) {
        return true;
    }
}

function value (field, operator, value, editMode) {
    var self = this;

    if (!self.template || !self.templates[self.template].schema[field] || !self.templates[self.template].schema[field].type) {
        return;
    }

    var fieldTemplate = self.templates[self.template].schema[field].type;
    var input;

    // refresh operators when changing the field
    if (!operator || editMode) {
        var df = document.createDocumentFragment();
        var order = self.config.ui.operatorOrder;

        for (var i in order) {
            var op = order[i];
            if (checkOperator.call(self, fieldTemplate, op)) {
                var option = elm('option', {value: op});
                option.innerHTML = self.config.i18n ? (self.config.i18n[op] || op) : op;

                // select operator
                if (operator === op) {
                    option.setAttribute('selected');
                }

                df.appendChild(option);
            }
        }

        if (self.domRefs.inputs.operator) {
            self.domRefs.inputs.operator.innerHTML = '';
            self.domRefs.inputs.operator.appendChild(df);
        }
    }

    // handle boolean input
    if (operator && self.config.operators[operator][2] === 'boolean') {
        var select = elm('select', {name: 'value'});
        var opt1 = elm('option', {value: 'true'});
        opt1.innerHTML = 'true';

        var opt2 = elm('option', {value: 'false'});
        opt2.innerHTML = 'false';

        select.appendChild(opt1);
        select.appendChild(opt2);
        select.value = value;
        input = select;

    // handle array input
    } else if (fieldTemplate === 'array' || (operator && self.config.operators[operator][2] === 'split')) {
        var array = elm('input', {name: 'value', type: 'text', value: value || ''});
        // TODO implement tag input plugin here...
        /*array.addEventListener('keyup', function (event) {
            if (event.keyCode === 13) {
                console.log(array.value);
            }
        });*/
        input = array;

    // handle number and text input
    } else if (fieldTemplate === 'number' && (operator && self.config.operators[operator][2] !== 'split')) {
        input = elm('input', {name: 'value', type: 'number', value: value || '', step: 'any'});
    } else {
        input = elm('input', {name: 'value', type: 'text', value: value || ''});
    }

    self.domRefs.inputs.value = input;

    // emit a saveFilter when pressing Enter while focused on this input
    self.domRefs.inputs.value.addEventListener('keyup', function(event) {
        if (event.keyCode === 13) {
            self.emit('saveFilter');
            self.domRefs.inputs.value.blur();
        }

        if(event.keyCode === 27) {
            self.emit('cancelFilter');
            self.domRefs.inputs.value.blur();
        }
    });

    if (self.domRefs.valueField) {
        self.domRefs.valueField.innerHTML = '';
        self.domRefs.valueField.appendChild(input);
    }
}

exports.value = value;
exports.fields = fields;

return module; });
<commit_msg>Added boolean value select also for boolean field types<commit_after>M.wrap('github/jillix/bind-filter/dev/inputs.js', function (require, module, exports) {
// TODO use bind for dom interaction/manipulation
function elm(d,a){try{var b=document.createElement(d);if("object"===typeof a)for(var c in a)b.setAttribute(c,a[c]);return b}catch(e){return null}}

var getFieldLabel = require('./validate').getFieldLabel;

function fields () {
    var self = this;
    var fields = self.templates[self.template].schema;

    var df = document.createDocumentFragment();
    var locale = M.getLocale();
    for (var field in fields) {
        if (field.indexOf('_') !== 0 && !fields[field].noSearch) {
            var option = elm('option', {value: field});
            option.innerHTML = getFieldLabel.call(self, field, locale);
            df.appendChild(option);
        }
    }

    if (self.domRefs.inputs.field) {
        self.domRefs.inputs.field.innerHTML = '';
        self.domRefs.inputs.field.appendChild(df);
    }
}

function checkOperator (fieldTemplate, operator) {
    var self = this;

    if (self.config.operators[operator][1] === 'mixed' || (self.config.operators[operator][1].indexOf(fieldTemplate) > -1)) {
        return true;
    }
}

function value (field, operator, value, editMode) {
    var self = this;

    if (!self.template || !self.templates[self.template].schema[field] || !self.templates[self.template].schema[field].type) {
        return;
    }

    var fieldTemplate = self.templates[self.template].schema[field].type;
    var input;

    // refresh operators when changing the field
    if (!operator || editMode) {
        var df = document.createDocumentFragment();
        var order = self.config.ui.operatorOrder;

        for (var i in order) {
            var op = order[i];
            if (checkOperator.call(self, fieldTemplate, op)) {
                var option = elm('option', {value: op});
                option.innerHTML = self.config.i18n ? (self.config.i18n[op] || op) : op;

                // select operator
                if (operator === op) {
                    option.setAttribute('selected');
                }

                df.appendChild(option);
            }
        }

        if (self.domRefs.inputs.operator) {
            self.domRefs.inputs.operator.innerHTML = '';
            self.domRefs.inputs.operator.appendChild(df);
        }
    }

    // handle boolean input
    if ((operator && self.config.operators[operator][2] === 'boolean') || fieldTemplate === 'boolean') {
        var select = elm('select', {name: 'value'});
        var opt1 = elm('option', {value: 'true'});
        opt1.innerHTML = 'true';

        var opt2 = elm('option', {value: 'false'});
        opt2.innerHTML = 'false';

        select.appendChild(opt1);
        select.appendChild(opt2);
        select.value = value;
        input = select;

    // handle array input
    } else if (fieldTemplate === 'array' || (operator && self.config.operators[operator][2] === 'split')) {
        var array = elm('input', {name: 'value', type: 'text', value: value || ''});
        // TODO implement tag input plugin here...
        /*array.addEventListener('keyup', function (event) {
            if (event.keyCode === 13) {
                console.log(array.value);
            }
        });*/
        input = array;

    // handle number and text input
    } else if (fieldTemplate === 'number' && (operator && self.config.operators[operator][2] !== 'split')) {
        input = elm('input', {name: 'value', type: 'number', value: value || '', step: 'any'});
    } else {
        input = elm('input', {name: 'value', type: 'text', value: value || ''});
    }

    self.domRefs.inputs.value = input;

    // emit a saveFilter when pressing Enter while focused on this input
    self.domRefs.inputs.value.addEventListener('keyup', function(event) {
        if (event.keyCode === 13) {
            self.emit('saveFilter');
            self.domRefs.inputs.value.blur();
        }

        if(event.keyCode === 27) {
            self.emit('cancelFilter');
            self.domRefs.inputs.value.blur();
        }
    });

    if (self.domRefs.valueField) {
        self.domRefs.valueField.innerHTML = '';
        self.domRefs.valueField.appendChild(input);
    }
}

exports.value = value;
exports.fields = fields;

return module; });
<|endoftext|>


<commit_before>import 'autocreate.js';
import app from './modules/app';
import './modules/loader';
import './modules/router';
import './modules/objectfit';
import './modules/collapsible';
import './modules/scrolltotop';
import './modules/scrollto';
import './modules/parallax';
import './modules/insicht';
import './modules/loadimg';
import './modules/share';
import './modules/log';
import './modules/links';
// import './modules/social';

import breakpointMatch from './modules/utils/breakpointmatch';

// use a getter for isMobile
delete app.isMobile;
Object.defineProperty(app, 'isMobile', {
  get: () => breakpointMatch('xs', 'max')
});

window.addEventListener('pageshow', e => {
  if (e.persisted) {
    window.location.reload();
  }
});

window.addEventListener('load', () => {
  try {
    app.loader.hide();
  }
  catch(err) {}
});

app.on('init', async () => {
  // request example
  const data = await app.get('https://req.dev.so');
  console.log(data);
});

document.addEventListener('DOMContentLoaded', async () => {
  await app.emit('init', null, true);
  await app.emit('init:page', null, true);
  app.initialized = true;
  if (document.readyState === 'complete') {
    try {
      app.loader.hide();
    }
    catch(err) {}
  }
  const event = document.createEvent('Event');
  event.initEvent('site-init', true, true);
  window.dispatchEvent(event);
});

window.addEventListener('site-init', () => {
  console.log('all done');
});

if (app.hasServiceWorker) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/sw.js').then(registration => {
      // Registration was successful
      console.log('ServiceWorker registration successful with scope: ', registration.scope);
    }, error => {
      // registration failed :(
      console.log('ServiceWorker registration failed: ', error);
    });
  });
}

window.app = app;
<commit_msg>remove unused import<commit_after>import 'autocreate.js';
import app from './modules/app';
import './modules/loader';
import './modules/router';
import './modules/collapsible';
import './modules/scrolltotop';
import './modules/scrollto';
import './modules/parallax';
import './modules/insicht';
import './modules/loadimg';
import './modules/share';
import './modules/log';
import './modules/links';
// import './modules/social';

import breakpointMatch from './modules/utils/breakpointmatch';

// use a getter for isMobile
delete app.isMobile;
Object.defineProperty(app, 'isMobile', {
  get: () => breakpointMatch('xs', 'max')
});

window.addEventListener('pageshow', e => {
  if (e.persisted) {
    window.location.reload();
  }
});

window.addEventListener('load', () => {
  try {
    app.loader.hide();
  }
  catch(err) {}
});

app.on('init', async () => {
  // request example
  const data = await app.get('https://req.dev.so');
  console.log(data);
});

document.addEventListener('DOMContentLoaded', async () => {
  await app.emit('init', null, true);
  await app.emit('init:page', null, true);
  app.initialized = true;
  if (document.readyState === 'complete') {
    try {
      app.loader.hide();
    }
    catch(err) {}
  }
  const event = document.createEvent('Event');
  event.initEvent('site-init', true, true);
  window.dispatchEvent(event);
});

window.addEventListener('site-init', () => {
  console.log('all done');
});

if (app.hasServiceWorker) {
  window.addEventListener('load', () => {
    navigator.serviceWorker.register('/sw.js').then(registration => {
      // Registration was successful
      console.log('ServiceWorker registration successful with scope: ', registration.scope);
    }, error => {
      // registration failed :(
      console.log('ServiceWorker registration failed: ', error);
    });
  });
}

window.app = app;
<|endoftext|>