<commit_before>'use strict'
var isNode = typeof window !== 'undefined'

module.exports = exports = function (_ua, obj) {
  _ua = _ua.toLowerCase()
  if (obj === true) {
    obj = exports
  }
  if (!obj) {
    obj = {}
  }
  // _ua = 'webos; linux - large screen'
  var _ff = 'firefox'
  var _android = 'android'
  var _mobile = '.+mobile'
  var _webkit = 'webkit'
  var _ps = 'playstation'
  var _xbox = 'xbox'
  var _linux = 'linux'
  var _castDetect = 'crkey'
  var _chromecast = 'chromecast'
  var _tablet = 'tablet'
  var _windows = 'windows'
  var _phone = 'phone'

  /**
   * browser detection
   */
  test.call(obj, _ua,
    function (query, arr) {
      obj.browser = arr[ 2 ] || query
      var _v = _ua.match(
        new RegExp('((([\\/ ]version|' + arr[ 0 ] + '(?!.+version))[\/ ])| rv:)([0-9]{1,4}\\.[0-9]{0,2})')
      )
      obj.version = _v ? Number(_v[ 4 ]) : 0
      obj.prefix = arr[ 1 ]
      // TODO: add prefix for opera v>12.15;
      // TODO: windows check for ie 11 may be too general;
    },
    [ true, _webkit ],
    [ '\\(windows', 'ms', 'ie' ],
    [ 'safari', _webkit ],
    [ _ff, 'Moz' ],
    [ 'opera', 'O' ],
    [ 'msie', 'ms', 'ie' ],
    [ 'chrome|crios\/', _webkit, 'chrome' ]
  )

  /**
   * platform detection
   */
  test.call(obj, _ua, 'platform',
    [ true, _windows ],
    [ _linux, _linux ],
    [ 'lg.{0,3}netcast', 'lg' ], // TODO:propably need to add more!
    [ _ff + _mobile, _ff ],
    [ 'mac os x', 'mac' ], [ 'iphone|ipod|ipad', 'ios' ],
    [ _xbox, _xbox ],
    [ _ps, _ps ],
    [ _android, _android ],
    [ _windows, _windows ],
    [ _castDetect, _chromecast ],
    [ 'smart-tv;|;samsung;smarttv', 'samsung' ] // SmartTV2013
  )

  /**
   * device detection
   */
  test.call(obj, _ua, 'device',
    [ true, 'desktop' ],
    [ _windows + '.+touch|ipad|' + _android, _tablet ],
    [
      'iphone|(' +
      _android + _mobile + ')|(' + _ff + _mobile +
      ')|' + _windows + ' phone|iemobile', _phone
    ],
    [ _xbox + '|' + _ps, 'console' ], [ 'tv|smarttv|googletv|appletv|hbbtv|pov_tv|netcast.tv|webos.+large', 'tv' ],
    [ _castDetect, _chromecast ], [ 'amazon-fireos', _tablet ]
  )
  // TODO: amazon firetv and phone

  // iphone6plus used as boundary for "phone sized"
  var iphone6plus = 414 * 736
  if (
    obj.platform === _android &&
    !isNode && obj.device === _phone &&
    window.innerWidth * window.innerHeight > iphone6plus
    // && ~_ua.indexOf('crosswalk')
  ) {
    obj.device = 'tablet'
  }
  return obj
}

/**
 * test
 * search for regexps in the userAgent
 * fn is a on succes callback
 * check http://www.useragentstring.com/ to test for userAgents
 * @method
 */
function test (_ua, fn) {
  for (var tests = arg(arguments, 1), i = tests.length - 1, query = tests[i][0]; query !== true && !new RegExp(query).test(_ua); query = tests[--i][0]); //eslint-disable-line
  if (fn.slice || fn.call(this, query, tests[i])) {
    this[ fn ] = tests[ i ][ 1 ]
  }
}

function arg (args, slice) {
  return Array.prototype.slice.call(args, slice)
}
<commit_msg>js-standard<commit_after>'use strict'
var isNode = typeof window !== 'undefined'

module.exports = exports = function (_ua, obj) {
  _ua = _ua.toLowerCase()
  if (obj === true) {
    obj = exports
  }
  if (!obj) {
    obj = {}
  }
  // _ua = 'webos; linux - large screen'
  var _ff = 'firefox'
  var _android = 'android'
  var _mobile = '.+mobile'
  var _webkit = 'webkit'
  var _ps = 'playstation'
  var _xbox = 'xbox'
  var _linux = 'linux'
  var _castDetect = 'crkey'
  var _chromecast = 'chromecast'
  var _tablet = 'tablet'
  var _windows = 'windows'
  var _phone = 'phone'

  /**
   * browser detection
   */
  test.call(obj, _ua,
    function (query, arr) {
      obj.browser = arr[ 2 ] || query
      var _v = _ua.match(
        new RegExp('((([\\/ ]version|' + arr[ 0 ] + '(?!.+version))[\/ ])| rv:)([0-9]{1,4}\\.[0-9]{0,2})')
      )
      obj.version = _v ? Number(_v[ 4 ]) : 0
      obj.prefix = arr[ 1 ]
      // TODO: add prefix for opera v>12.15;
      // TODO: windows check for ie 11 may be too general;
    },
    [ true, _webkit ],
    [ '\\(windows', 'ms', 'ie' ],
    [ 'safari', _webkit ],
    [ _ff, 'Moz' ],
    [ 'opera', 'O' ],
    [ 'msie', 'ms', 'ie' ],
    [ 'chrome|crios\/', _webkit, 'chrome' ]
  )

  /**
   * platform detection
   */
  test.call(obj, _ua, 'platform',
    [ true, _windows ],
    [ _linux, _linux ],
    [ 'lg.{0,3}netcast', 'lg' ], // TODO:propably need to add more!
    [ _ff + _mobile, _ff ],
    [ 'mac os x', 'mac' ], [ 'iphone|ipod|ipad', 'ios' ],
    [ _xbox, _xbox ],
    [ _ps, _ps ],
    [ _android, _android ],
    [ _windows, _windows ],
    [ _castDetect, _chromecast ],
    [ 'smart-tv;|;samsung;smarttv', 'samsung' ] // SmartTV2013
  )

  /**
   * device detection
   */
  test.call(obj, _ua, 'device',
    [ true, 'desktop' ],
    [ _windows + '.+touch|ipad|' + _android, _tablet ],
    [
      'iphone|(' +
      _android + _mobile + ')|(' + _ff + _mobile +
      ')|' + _windows + ' phone|iemobile', _phone
    ],
    [ _xbox + '|' + _ps, 'console' ],
    [ 'tv|smarttv|googletv|appletv|hbbtv|pov_tv|netcast.tv|webos.+large', 'tv' ],
    [ _castDetect, _chromecast ], [ 'amazon-fireos', _tablet ]
  )
  // TODO: amazon firetv and phone

  // iphone6plus used as boundary for "phone sized"
  var iphone6plus = 414 * 736
  if (
    obj.platform === _android &&
    !isNode && obj.device === _phone &&
    window.innerWidth * window.innerHeight > iphone6plus
    // && ~_ua.indexOf('crosswalk')
  ) {
    obj.device = 'tablet'
  }
  return obj
}

/**
 * test
 * search for regexps in the userAgent
 * fn is a on succes callback
 * check http://www.useragentstring.com/ to test for userAgents
 * @method
 */
function test (_ua, fn) {
  for (var tests = arg(arguments, 1), i = tests.length - 1, query = tests[i][0]; query !== true && !new RegExp(query).test(_ua); query = tests[--i][0]); //eslint-disable-line
  if (fn.slice || fn.call(this, query, tests[i])) {
    this[ fn ] = tests[ i ][ 1 ]
  }
}

function arg (args, slice) {
  return Array.prototype.slice.call(args, slice)
}
<|endoftext|>


<commit_before>// From: hammerjs.github.io/touch-emulator/
(function(window, document, exportName, undefined) {
    "use strict";

    var isMultiTouch = false;
    var multiTouchStartPos;
    var eventTarget;
    var touchElements = {};

    // polyfills
    if(!document.createTouch) {
        document.createTouch = function(view, target, identifier, pageX, pageY, screenX, screenY, clientX, clientY) {
            // auto set
            if(clientX == undefined || clientY == undefined) {
                clientX = pageX - window.pageXOffset;
                clientY = pageY - window.pageYOffset;
            }

            return new Touch(target, identifier, {
                pageX: pageX,
                pageY: pageY,
                screenX: screenX,
                screenY: screenY,
                clientX: clientX,
                clientY: clientY
            });
        };
    }

    if(!document.createTouchList) {
        document.createTouchList = function() {
            var touchList = new TouchList();
            for (var i = 0; i < arguments.length; i++) {
                touchList[i] = arguments[i];
            }
            touchList.length = arguments.length;
            return touchList;
        };
    }

    /**
     * create an touch point
     * @constructor
     * @param target
     * @param identifier
     * @param pos
     * @param deltaX
     * @param deltaY
     * @returns {Object} touchPoint
     */
    function Touch(target, identifier, pos, deltaX, deltaY) {
        deltaX = deltaX || 0;
        deltaY = deltaY || 0;

        this.identifier = identifier;
        this.target = target;
        this.clientX = pos.clientX + deltaX;
        this.clientY = pos.clientY + deltaY;
        this.screenX = pos.screenX + deltaX;
        this.screenY = pos.screenY + deltaY;
        this.pageX = pos.pageX + deltaX;
        this.pageY = pos.pageY + deltaY;
    }

    /**
     * create empty touchlist with the methods
     * @constructor
     * @returns touchList
     */
    function TouchList() {
        var touchList = [];

        touchList.item = function(index) {
            return this[index] || null;
        };

        // specified by Mozilla
        touchList.identifiedTouch = function(id) {
            return this[id + 1] || null;
        };

        return touchList;
    }

    /**
     * Simple trick to fake touch event support
     * this is enough for most libraries like Modernizr and Hammer
     */
    function fakeTouchSupport() {
        var objs = [window, document.documentElement];
        var props = ['ontouchstart', 'ontouchmove', 'ontouchcancel', 'ontouchend'];

        for(var o=0; o<objs.length; o++) {
            for(var p=0; p<props.length; p++) {
                if(objs[o] && objs[o][props[p]] == undefined) {
                    objs[o][props[p]] = null;
                }
            }
        }
    }

    /**
     * we don't have to emulate on a touch device
     * @returns {boolean}
     */
    function hasTouchSupport() {
        return ("ontouchstart" in window) || // touch events
               (window.Modernizr && window.Modernizr.touch) || // modernizr
               (navigator.msMaxTouchPoints || navigator.maxTouchPoints) > 2; // pointer events
    }

    /**
     * disable mouseevents on the page
     * @param ev
     */
    function preventMouseEvents(ev) {
        ev.preventDefault();
        ev.stopPropagation();
    }

    /**
     * only trigger touches when the left mousebutton has been pressed
     * @param touchType
     * @returns {Function}
     */
    function onMouse(touchType) {
        return function(ev) {
            // prevent mouse events
            preventMouseEvents(ev);

            if (ev.which !== 1) {
                return;
            }

            // The EventTarget on which the touch point started when it was first placed on the surface,
            // even if the touch point has since moved outside the interactive area of that element.
            // also, when the target doesnt exist anymore, we update it
            if (ev.type == 'mousedown' || !eventTarget || (eventTarget && !eventTarget.dispatchEvent)) {
                eventTarget = ev.target;
            }

            // shiftKey has been lost, so trigger a touchend
            if (isMultiTouch && !ev.shiftKey) {
                triggerTouch('touchend', ev);
                isMultiTouch = false;
            }

            triggerTouch(touchType, ev);

            // we're entering the multi-touch mode!
            if (!isMultiTouch && ev.shiftKey) {
                isMultiTouch = true;
                multiTouchStartPos = {
                    pageX: ev.pageX,
                    pageY: ev.pageY,
                    clientX: ev.clientX,
                    clientY: ev.clientY,
                    screenX: ev.screenX,
                    screenY: ev.screenY
                };
                triggerTouch('touchstart', ev);
            }

            // reset
            if (ev.type == 'mouseup') {
                multiTouchStartPos = null;
                isMultiTouch = false;
                eventTarget = null;
            }
        }
    }

    /**
     * trigger a touch event
     * @param eventName
     * @param mouseEv
     */
    function triggerTouch(eventName, mouseEv) {
        var touchEvent = document.createEvent('Event');
        touchEvent.initEvent(eventName, true, true);

        touchEvent.altKey = mouseEv.altKey;
        touchEvent.ctrlKey = mouseEv.ctrlKey;
        touchEvent.metaKey = mouseEv.metaKey;
        touchEvent.shiftKey = mouseEv.shiftKey;

        touchEvent.touches = getActiveTouches(mouseEv, eventName);
        touchEvent.targetTouches = getActiveTouches(mouseEv, eventName);
        touchEvent.changedTouches = getChangedTouches(mouseEv, eventName);

        eventTarget.dispatchEvent(touchEvent);
    }

    /**
     * create a touchList based on the mouse event
     * @param mouseEv
     * @returns {TouchList}
     */
    function createTouchList(mouseEv) {
        var touchList = new TouchList();

        if (isMultiTouch) {
            var f = TouchEmulator.multiTouchOffset;
            var deltaX = multiTouchStartPos.pageX - mouseEv.pageX;
            var deltaY = multiTouchStartPos.pageY - mouseEv.pageY;

            touchList.push(new Touch(eventTarget, 1, multiTouchStartPos, (deltaX*-1) - f, (deltaY*-1) + f));
            touchList.push(new Touch(eventTarget, 2, multiTouchStartPos, deltaX+f, deltaY-f));
        } else {
            touchList.push(new Touch(eventTarget, 1, mouseEv, 0, 0));
        }

        return touchList;
    }

    /**
     * receive all active touches
     * @param mouseEv
     * @returns {TouchList}
     */
    function getActiveTouches(mouseEv, eventName) {
        // empty list
        if (mouseEv.type == 'mouseup') {
            return new TouchList();
        }

        var touchList = createTouchList(mouseEv);
        if(isMultiTouch && mouseEv.type != 'mouseup' && eventName == 'touchend') {
            touchList.splice(1, 1);
        }
        return touchList;
    }

    /**
     * receive a filtered set of touches with only the changed pointers
     * @param mouseEv
     * @param eventName
     * @returns {TouchList}
     */
    function getChangedTouches(mouseEv, eventName) {
        var touchList = createTouchList(mouseEv);

        // we only want to return the added/removed item on multitouch
        // which is the second pointer, so remove the first pointer from the touchList
        //
        // but when the mouseEv.type is mouseup, we want to send all touches because then
        // no new input will be possible
        if(isMultiTouch && mouseEv.type != 'mouseup' &&
            (eventName == 'touchstart' || eventName == 'touchend')) {
            touchList.splice(0, 1);
        }

        return touchList;
    }

    /**
     * show the touchpoints on the screen
     */
    function showTouches(ev) {
        var touch, i, el, styles;

        // first all visible touches
        for(i = 0; i < ev.touches.length; i++) {
            touch = ev.touches[i];
            el = touchElements[touch.identifier];
            if(!el) {
                el = touchElements[touch.identifier] = document.createElement("div");
                document.body.appendChild(el);
            }

            styles = TouchEmulator.template(touch);
            for(var prop in styles) {
                el.style[prop] = styles[prop];
            }
        }

        // remove all ended touches
        if(ev.type == 'touchend' || ev.type == 'touchcancel') {
            for(i = 0; i < ev.changedTouches.length; i++) {
                touch = ev.changedTouches[i];
                el = touchElements[touch.identifier];
                if(el) {
                    el.parentNode.removeChild(el);
                    delete touchElements[touch.identifier];
                }
            }
        }
    }

    /**
     * TouchEmulator initializer
     */
    function TouchEmulator() {
        if (hasTouchSupport()) {
            return;
        }

        fakeTouchSupport();

        window.addEventListener("mousedown", onMouse('touchstart'), true);
        window.addEventListener("mousemove", onMouse('touchmove'), true);
        window.addEventListener("mouseup", onMouse('touchend'), true);

        window.addEventListener("mouseenter", preventMouseEvents, true);
        window.addEventListener("mouseleave", preventMouseEvents, true);
        window.addEventListener("mouseout", preventMouseEvents, true);
        window.addEventListener("mouseover", preventMouseEvents, true);

        // it uses itself!
        window.addEventListener("touchstart", showTouches, false);
        window.addEventListener("touchmove", showTouches, false);
        window.addEventListener("touchend", showTouches, false);
        window.addEventListener("touchcancel", showTouches, false);
    }

    // start distance when entering the multitouch mode
    TouchEmulator.multiTouchOffset = 75;

    /**
     * css template for the touch rendering
     * @param touch
     * @returns object
     */
    TouchEmulator.template = function(touch) {
        var size = 30;
        var transform = 'translate('+ (touch.clientX-(size/2)) +'px, '+ (touch.clientY-(size/2)) +'px)';
        return {
            position: 'fixed',
            left: 0,
            top: 0,
            background: '#fff',
            border: 'solid 1px #999',
            opacity: .6,
            borderRadius: '100%',
            height: size + 'px',
            width: size + 'px',
            padding: 0,
            margin: 0,
            display: 'block',
            overflow: 'hidden',
            pointerEvents: 'none',
            webkitUserSelect: 'none',
            mozUserSelect: 'none',
            userSelect: 'none',
            webkitTransform: transform,
            mozTransform: transform,
            transform: transform
        }
    };

    // export
    if (typeof define == "function" && define.amd) {
        define(function() {
            return TouchEmulator;
        });
    } else if (typeof module != "undefined" && module.exports) {
        module.exports = TouchEmulator;
    } else {
        window[exportName] = TouchEmulator;
    }
})(window, document, "TouchEmulator");
<commit_msg>Fix touch emulation to work with Movable elements<commit_after>// From: hammerjs.github.io/touch-emulator/
(function(window, document, exportName, undefined) {
    "use strict";

    var isMultiTouch = false;
    var multiTouchStartPos;
    var eventTarget;
    var touchElements = {};

    // polyfills
    if(!document.createTouch) {
        document.createTouch = function(view, target, identifier, pageX, pageY, screenX, screenY, clientX, clientY) {
            // auto set
            if(clientX == undefined || clientY == undefined) {
                clientX = pageX - window.pageXOffset;
                clientY = pageY - window.pageYOffset;
            }

            return new Touch(target, identifier, {
                pageX: pageX,
                pageY: pageY,
                screenX: screenX,
                screenY: screenY,
                clientX: clientX,
                clientY: clientY
            });
        };
    }

    if(!document.createTouchList) {
        document.createTouchList = function() {
            var touchList = new TouchList();
            for (var i = 0; i < arguments.length; i++) {
                touchList[i] = arguments[i];
            }
            touchList.length = arguments.length;
            return touchList;
        };
    }

    /**
     * create an touch point
     * @constructor
     * @param target
     * @param identifier
     * @param pos
     * @param deltaX
     * @param deltaY
     * @returns {Object} touchPoint
     */
    function Touch(target, identifier, pos, deltaX, deltaY) {
        deltaX = deltaX || 0;
        deltaY = deltaY || 0;

        this.identifier = identifier;
        this.target = target;
        this.clientX = pos.clientX + deltaX;
        this.clientY = pos.clientY + deltaY;
        this.screenX = pos.screenX + deltaX;
        this.screenY = pos.screenY + deltaY;
        this.pageX = pos.pageX + deltaX;
        this.pageY = pos.pageY + deltaY;
    }

    /**
     * create empty touchlist with the methods
     * @constructor
     * @returns touchList
     */
    function TouchList() {
        var touchList = [];

        touchList.item = function(index) {
            return this[index] || null;
        };

        // specified by Mozilla
        touchList.identifiedTouch = function(id) {
            return this[id + 1] || null;
        };

        return touchList;
    }

    /**
     * Simple trick to fake touch event support
     * this is enough for most libraries like Modernizr and Hammer
     */
    function fakeTouchSupport() {
        var objs = [window, document.documentElement];
        var props = ['ontouchstart', 'ontouchmove', 'ontouchcancel', 'ontouchend'];

        for(var o=0; o<objs.length; o++) {
            for(var p=0; p<props.length; p++) {
                if(objs[o] && objs[o][props[p]] == undefined) {
                    objs[o][props[p]] = null;
                }
            }
        }
    }

    /**
     * we don't have to emulate on a touch device
     * @returns {boolean}
     */
    function hasTouchSupport() {
        return ("ontouchstart" in window) || // touch events
               (window.Modernizr && window.Modernizr.touch) || // modernizr
               (navigator.msMaxTouchPoints || navigator.maxTouchPoints) > 2; // pointer events
    }

    /**
     * disable mouseevents on the page
     * @param ev
     */
    function preventMouseEvents(ev) {
        ev.preventDefault();
        ev.stopPropagation();
    }

    /**
     * only trigger touches when the left mousebutton has been pressed
     * @param touchType
     * @returns {Function}
     */
    function onMouse(touchType) {
        return function(ev) {
            // prevent mouse events
            preventMouseEvents(ev);

            if (ev.which !== 1) {
                return;
            }

            // The EventTarget on which the touch point started when it was first placed on the surface,
            // even if the touch point has since moved outside the interactive area of that element.
            // also, when the target doesnt exist anymore, we update it
            if (ev.type == 'mousedown' || !eventTarget || (eventTarget && !eventTarget.dispatchEvent)) {
                eventTarget = ev.target;
            }

            // shiftKey has been lost, so trigger a touchend
            if (isMultiTouch && !ev.shiftKey) {
                triggerTouch('touchend', ev);
                isMultiTouch = false;
            }

            triggerTouch(touchType, ev);

            // we're entering the multi-touch mode!
            if (!isMultiTouch && ev.shiftKey) {
                isMultiTouch = true;
                multiTouchStartPos = {
                    pageX: ev.pageX,
                    pageY: ev.pageY,
                    clientX: ev.clientX,
                    clientY: ev.clientY,
                    screenX: ev.screenX,
                    screenY: ev.screenY
                };
                triggerTouch('touchstart', ev);
            }

            // reset
            if (ev.type == 'mouseup') {
                multiTouchStartPos = null;
                isMultiTouch = false;
                eventTarget = null;
            }
        }
    }

    /**
     * trigger a touch event
     * @param eventName
     * @param mouseEv
     */
    function triggerTouch(eventName, mouseEv) {
        var touchEvent = document.createEvent('Event');
        touchEvent.initEvent(eventName, true, true);

        touchEvent.altKey = mouseEv.altKey;
        touchEvent.ctrlKey = mouseEv.ctrlKey;
        touchEvent.metaKey = mouseEv.metaKey;
        touchEvent.shiftKey = mouseEv.shiftKey;
        touchEvent.which = 0;

        touchEvent.touches = getActiveTouches(mouseEv, eventName);
        touchEvent.targetTouches = getActiveTouches(mouseEv, eventName);
        touchEvent.changedTouches = getChangedTouches(mouseEv, eventName);

        eventTarget.dispatchEvent(touchEvent);
    }

    /**
     * create a touchList based on the mouse event
     * @param mouseEv
     * @returns {TouchList}
     */
    function createTouchList(mouseEv) {
        var touchList = new TouchList();

        if (isMultiTouch) {
            var f = TouchEmulator.multiTouchOffset;
            var deltaX = multiTouchStartPos.pageX - mouseEv.pageX;
            var deltaY = multiTouchStartPos.pageY - mouseEv.pageY;

            touchList.push(new Touch(eventTarget, 1, multiTouchStartPos, (deltaX*-1) - f, (deltaY*-1) + f));
            touchList.push(new Touch(eventTarget, 2, multiTouchStartPos, deltaX+f, deltaY-f));
        } else {
            touchList.push(new Touch(eventTarget, 1, mouseEv, 0, 0));
        }

        return touchList;
    }

    /**
     * receive all active touches
     * @param mouseEv
     * @returns {TouchList}
     */
    function getActiveTouches(mouseEv, eventName) {
        // empty list
        if (mouseEv.type == 'mouseup') {
            return new TouchList();
        }

        var touchList = createTouchList(mouseEv);
        if(isMultiTouch && mouseEv.type != 'mouseup' && eventName == 'touchend') {
            touchList.splice(1, 1);
        }
        return touchList;
    }

    /**
     * receive a filtered set of touches with only the changed pointers
     * @param mouseEv
     * @param eventName
     * @returns {TouchList}
     */
    function getChangedTouches(mouseEv, eventName) {
        var touchList = createTouchList(mouseEv);

        // we only want to return the added/removed item on multitouch
        // which is the second pointer, so remove the first pointer from the touchList
        //
        // but when the mouseEv.type is mouseup, we want to send all touches because then
        // no new input will be possible
        if(isMultiTouch && mouseEv.type != 'mouseup' &&
            (eventName == 'touchstart' || eventName == 'touchend')) {
            touchList.splice(0, 1);
        }

        return touchList;
    }

    /**
     * show the touchpoints on the screen
     */
    function showTouches(ev) {
        var touch, i, el, styles;

        // first all visible touches
        for(i = 0; i < ev.touches.length; i++) {
            touch = ev.touches[i];
            el = touchElements[touch.identifier];
            if(!el) {
                el = touchElements[touch.identifier] = document.createElement("div");
                document.body.appendChild(el);
            }

            styles = TouchEmulator.template(touch);
            for(var prop in styles) {
                el.style[prop] = styles[prop];
            }
        }

        // remove all ended touches
        if(ev.type == 'touchend' || ev.type == 'touchcancel') {
            for(i = 0; i < ev.changedTouches.length; i++) {
                touch = ev.changedTouches[i];
                el = touchElements[touch.identifier];
                if(el) {
                    el.parentNode.removeChild(el);
                    delete touchElements[touch.identifier];
                }
            }
        }
    }

    /**
     * TouchEmulator initializer
     */
    function TouchEmulator() {
        if (hasTouchSupport()) {
            return;
        }

        fakeTouchSupport();

        window.addEventListener("mousedown", onMouse('touchstart'), true);
        window.addEventListener("mousemove", onMouse('touchmove'), true);
        window.addEventListener("mouseup", onMouse('touchend'), true);

        window.addEventListener("mouseenter", preventMouseEvents, true);
        window.addEventListener("mouseleave", preventMouseEvents, true);
        window.addEventListener("mouseout", preventMouseEvents, true);
        window.addEventListener("mouseover", preventMouseEvents, true);

        // it uses itself!
        window.addEventListener("touchstart", showTouches, false);
        window.addEventListener("touchmove", showTouches, false);
        window.addEventListener("touchend", showTouches, false);
        window.addEventListener("touchcancel", showTouches, false);
    }

    // start distance when entering the multitouch mode
    TouchEmulator.multiTouchOffset = 75;

    /**
     * css template for the touch rendering
     * @param touch
     * @returns object
     */
    TouchEmulator.template = function(touch) {
        var size = 30;
        var transform = 'translate('+ (touch.clientX-(size/2)) +'px, '+ (touch.clientY-(size/2)) +'px)';
        return {
            position: 'fixed',
            left: 0,
            top: 0,
            background: '#fff',
            border: 'solid 1px #999',
            opacity: .6,
            borderRadius: '100%',
            height: size + 'px',
            width: size + 'px',
            padding: 0,
            margin: 0,
            display: 'block',
            overflow: 'hidden',
            pointerEvents: 'none',
            webkitUserSelect: 'none',
            mozUserSelect: 'none',
            userSelect: 'none',
            webkitTransform: transform,
            mozTransform: transform,
            transform: transform,
        }
    };

    // export
    if (typeof define == "function" && define.amd) {
        define(function() {
            return TouchEmulator;
        });
    } else if (typeof module != "undefined" && module.exports) {
        module.exports = TouchEmulator;
    } else {
        window[exportName] = TouchEmulator;
    }
})(window, document, "TouchEmulator");
<|endoftext|>


<commit_before>var level = require('level')
var pull = require('pull-stream')
var Write = require('pull-write')
var pl = require('pull-level')
var query = require('./query')
var select = require('./select')

var bytewise = require('bytewise')

var u = require('./util')
//sorted index.

function has (key, obj) {
  return !!obj[key]
  Object.hasOwnProperty(obj, key)
}

module.exports = function (path, indexes, links, version, codec) {
  codec = codec || require('bytewise')
  var db = level(path)

  if('string' !== typeof path)
    throw new Error('must provide path for leveldb instance')
  if(!Array.isArray(indexes))
    throw new Error('must provide an array of indexes')
  if('function' !== typeof links)
    throw new Error('must provide links function')
  if('number' !== typeof version)
    throw new Error('must provide version number')

  //always write metada to the lowest key,
  //so the indexes do not interfeer
  //we don't want to encode this with the codec,
  //because then we can't change the codec safely
  //(prehaps the encoding of META is also some indexed value in another codec?)
  var META = '\x00'

  return {
    init: function (cb) {
      db.get(META, function (err, value) {
        if(value)
          try { value = JSON.parse(value) }
          catch (err) { return cb(null, 0) }

        if(err) //first time this was run
          cb(null, 0)

        //if the view has changed, rebuild entire index.
        //else, read current version.

        else if(version && value.version !== version)
          level.destroy(path, function (err) {
            if(err) return cb(err)
            db = level(path)
            cb(null, 0)
          })
        else
          cb(null, value.since || 0)
      })
    },
    write: function (cb) {
      return pull(
        Write(function (batch, cb) {
          db.batch(batch, cb)
        }, function (batch, data) {
          if(data.sync) return batch
          if(!batch)
            batch = [{
              key: META,
              value: {version: version, since: data.ts},
              valueEncoding: 'json',
              type: 'put'
            }]

          function push(ary) {
            batch.push({key: codec.encode(ary), value: ' ', type: 'put'})
          }

          links(data, function (link) {
            indexes.forEach(function (index) {
              var a = [index.key]
              for(var i = 0; i < index.value.length; i++) {
                var key = index.value[i]
                if(!has(key, link)) return
                a.push(link[key])
              }
              push(a)
            })
          })
          batch[0].value.since = data.ts || data.timestamp
          return batch
        }, 100, cb)
      )
    },
    close: function (cb) {
      db.close(cb)
    },
    //get the raw indexes, for debugging.
    dump: function () {
      return pl.read(db, {keyEncoding: codec, gt: '\x00'})
    },
    //read all the messages out, via matching ranges.
    read: function (opts) {
      if(!opts) opts = {query: {}}
      if(!opts.query) opts.query = {}
      var index = select(indexes, opts.query)
      var opts = query(index, opts.query)

      opts.values = false
      opts.keys = true
      opts.keyEncoding = codec

      return pull(
        pl.read(db, opts),
        //this just reads the index, suitable for links.
        pull.map(function (e) {
          var o = {}
          for(var i = 0; i < index.value.length; i++)
            o[index.value[i]] = e[i+1]
          return o
        })
      )
    }
  }
}

<commit_msg>must close the db before destroying it<commit_after>var level = require('level')
var pull = require('pull-stream')
var Write = require('pull-write')
var pl = require('pull-level')
var query = require('./query')
var select = require('./select')

var bytewise = require('bytewise')

//sorted index.

function has (key, obj) {
  return !!obj[key]
  Object.hasOwnProperty(obj, key)
}

module.exports = function (path, indexes, links, version, codec) {
  codec = codec || require('bytewise')
  var db = level(path)

  if('string' !== typeof path)
    throw new Error('must provide path for leveldb instance')
  if(!Array.isArray(indexes))
    throw new Error('must provide an array of indexes')
  if('function' !== typeof links)
    throw new Error('must provide links function')
  if('number' !== typeof version)
    throw new Error('must provide version number')

  //always write metada to the lowest key,
  //so the indexes do not interfeer
  //we don't want to encode this with the codec,
  //because then we can't change the codec safely
  //(prehaps the encoding of META is also some indexed value in another codec?)
  var META = '\x00'

  return {
    init: function (cb) {
      db.get(META, function (err, value) {
        if(value)
          try { value = JSON.parse(value) }
          catch (err) { return cb(null, 0) }

        if(err) //first time this was run
          cb(null, 0)

        //if the view has changed, rebuild entire index.
        //else, read current version.

        else if(version && value.version !== version) {
          db.close(function () {
            level.destroy(path, function (err) {
              if(err) return cb(err)
              db = level(path)
              cb(null, 0)
            })
          })
        }
        else
          cb(null, value.since || 0)
      })
    },
    write: function (cb) {
      return pull(
        Write(function (batch, cb) {
          db.batch(batch, cb)
        }, function (batch, data) {
          if(data.sync) return batch
          if(!batch)
            batch = [{
              key: META,
              value: {version: version, since: data.ts},
              valueEncoding: 'json',
              type: 'put'
            }]

          function push(ary) {
            batch.push({key: codec.encode(ary), value: ' ', type: 'put'})
          }

          links(data, function (link) {
            indexes.forEach(function (index) {
              var a = [index.key]
              for(var i = 0; i < index.value.length; i++) {
                var key = index.value[i]
                if(!has(key, link)) return
                a.push(link[key])
              }
              push(a)
            })
          })
          batch[0].value.since = data.ts || data.timestamp
          return batch
        }, 100, cb)
      )
    },
    close: function (cb) {
      db.close(cb)
    },
    //get the raw indexes, for debugging.
    dump: function () {
      return pl.read(db, {keyEncoding: codec, gt: '\x00'})
    },
    //read all the messages out, via matching ranges.
    read: function (opts) {
      if(!opts) opts = {query: {}}
      if(!opts.query) opts.query = {}
      var index = select(indexes, opts.query)
      var opts = query(index, opts.query)

      opts.values = false
      opts.keys = true
      opts.keyEncoding = codec

      return pull(
        pl.read(db, opts),
        //this just reads the index, suitable for links.
        pull.map(function (e) {
          var o = {}
          for(var i = 0; i < index.value.length; i++)
            o[index.value[i]] = e[i+1]
          return o
        })
      )
    }
  }
}

<|endoftext|>


<commit_before>'use strict';

let util = require('util');
let url = require('url');
let grpc = require('grpc');
let co = require('co');

/**
 * Name of the transport
 * @const
 */
const NAME = 'grpc';

/**
 * call wraps the method of conn into an endpoint.
 * @param  {Object} conn   A gRPC Client.
 * @param  {string} method The endpoint method name of the service.
 * @return {function*}        The endpoint.
 */
function call(conn, method) {
  if (!conn[method]) {
    throw new Error(util.format('conn has no method %s', method));
  }
  return function*(request, context) {
    let options = {
      //deadline: Date.now() + 1000
    };

    function call() {
      return function(callback) {
        conn[method](request, options, callback);
      };
    }
    try {
      let result = yield call();
      let response = {
        error: null,
        data: result,
      };
      return response;
    } catch (err) {
      let resp;
      switch (err.code) {
        case grpc.status.OK:
        case grpc.status.CANCELLED:
          resp = {
            error: new Error('operation was cancelled'),
          };
          break;
        case grpc.status.INVALID_ARGUMENT:
          resp = {
            error: new Error('invalid argument'),
          };
          break;
        case grpc.status.NOT_FOUND:
          resp = {
            error: new Error('not found'),
          };
          break;
        case grpc.status.ALREADY_EXISTS:
          resp = {
            error: new Error('already exists'),
          };
          break;
        case grpc.status.PERMISSION_DENIED:
          resp = {
            error: new Error('permission denied'),
          };
          break;
        case grpc.status.UNAUTHENTICATED:
          resp = {
            error: new Error('unauthenticated'),
          };
          break;
        case grpc.status.FAILED_PRECONDITION:
          resp = {
            error: new Error('failed precondition'),
          };
          break;
        case grpc.status.ABORTED:
          resp = {
            error: new Error('aborted'),
          };
          break;
        case grpc.status.OUT_OF_RANGE:
          resp = {
            error: new Error('out of range'),
          };
          break;
        case grpc.status.UNIMPLEMENTED:
          resp = {
            error: new Error('unimplemented'),
          };
          break;
        case grpc.status.RESOURCE_EXHAUSTED:
          resp = {
            error: new Error('resource exhausted'),
          };
          break;
        case grpc.status.DEADLINE_EXCEEDED:
          resp = {
            error: new Error('deadline exceeded'),
          };
          break;
        case grpc.status.UNKNOWN:
          resp = {
            error: new Error('unknown'),
          };
          break;
        case grpc.status.INTERNAL:
          resp = {
            error: new Error('internal'),
          };
          break;
        case grpc.status.UNAVAILABLE:
          resp = {
            error: new Error('unavailable'),
          };
          break;
        case grpc.status.DATA_LOSS:
          resp = {
            error: new Error('data loss'),
          };
          break;
        default:
          throw err;
      }
      if (resp.error.message !== err.message) {
        resp.error.details = err.message;
      }
      return resp;
    }
  }
}

/**
 * serve wraps the endpoint to provide a gRPC service method.
 * @param  {function*} endpoint Endpoint which will be served as a gRPC service method.
 * @return {[function]}          The function can be used as a gRPC service method.
 */
function serve(endpoint) {
  return function(call, callback) {
    let req = call.request;
    if (!endpoint) {
      callback({
        code: grpc.status.NOT_IMPLEMENTED
      });
    }
    co(function*() {
      let resp = yield endpoint(req);
      callback(null, resp);
    }).catch(function(err) {
      let code;
      // match message to grpc code
      // only service errors
      switch (err.message) {
        case 'operation was cancelled':
          code = grpc.status.CANCELLED;
          break;
        case 'invalid argument':
          code = grpc.status.INVALID_ARGUMENT;
          break;
        case 'not found':
          code = grpc.status.NOT_FOUND;
          break;
        case 'already exists':
          code = grpc.status.ALREADY_EXISTS;
          break;
        case 'permission denied':
          code = grpc.status.PERMISSION_DENIED;
          break;
        case 'unauthenticated':
          code = grpc.status.UNAUTHENTICATED;
          break;
        case 'failed precondition':
          code = grpc.status.FAILED_PRECONDITION;
          break;
        case 'aborted':
          code = grpc.status.ABORTED;
          break;
        case 'out of range':
          code = grpc.status.OUT_OF_RANGE;
          break;
        case 'unimplemented':
          code = grpc.status.UNIMPLEMENTED;
          break;
      }
      if (!code) {
        code = grpc.status.INTERNAL;
      }
      let details = err.message;
      if (err.details) {
        details = err.details;
      }
      callback({
        code: code,
        details: details,
      }, null);
    });
  };
}

/**
 * Server is a gRPC transport provider for serving.
 * @param {Object} config Configuration object.
 * Requires properties:addr,package,proto,service
 * Optional properties: credentials.ssl.certs
 */
function Server(config) {
  this._server = new grpc.Server();
  this._config = config;
  this._proto = grpc.load(process.cwd() + config.proto);
  this._service = this._proto[this._config.package][this._config.service].service;
  this.name = NAME;
}

/**
 * bind maps the service to gRPC methods and binds the address.
 * @param  {Object} service Business logic
 */
Server.prototype.bind = function*(service) {
  // wrap all service methods
  let binding = {};
  Object.getOwnPropertyNames(service).forEach(function(name) {
    binding[name] = serve(service[name]);
  });

  this._server.addProtoService(this._service, binding);

  let credentials = grpc.ServerCredentials.createInsecure();
  if (this._config.credentials) {
    if (this._config.credentials.ssl) {
      credentials = grpc.credentials.createSsl(this._config.credentials.ssl.certs);
    }
  }
  this._server.bind(this._config.addr, credentials);
}

/**
 * start launches the gRPC server and provides the service endpoints.
 */
Server.prototype.start = function*() {
  this._server.start();
}

/**
 * end stops the gRPC server and no longer provides the service endpoints.
 */
Server.prototype.end = function*() {
  this._server.tryShutdown();
}

/**
 * Client is a gRPC transport provider for calling endpoints.
 * @param {Object} config Configuration object.
 * Requires properties: package,proto,service
 * Optional properties: timeout
 */
function Client(config) {
  this.name = NAME;
  this.config = config;
  let proto = grpc.load(process.cwd() + config.proto);
  this._service = proto[config.package][config.service];
}

Client.prototype.makeEndpoint = function*(method, instance) {
  let u = url.parse(instance, true, true);
  if (u.protocol !== 'grpc:') {
    throw new Error('not a grpc instance URL');
  }
  let host = u.host;
  let credentials = grpc.credentials.createInsecure();
  if (this.config.credentials) {
    if (this.config.credentials.ssl) {
      let certs = this.config.credentials.ssl.certs;
      let key = this.config.credentials.ssl.key;
      let chain = this.config.credentials.ssl.chain;
      credentials = grpc.credentials.createSsl(certs, key, chain);
    }
  }
  let self = this;
  let conn = new this._service(host, credentials);
  if (this.config.timeout) {
    let deadline = Date.now() + this.config.timeout;
    grpc.waitForClientReady(conn, deadline, function(err) {
      if (err) {
        let chan = grpc.getClientChannel(conn);
        chan.close();
      }
    });
  }
  return call(conn, method);
}

module.exports.Name = NAME;
module.exports.Client = Client;
module.exports.Server = Server;
module.exports.serve = serve;
module.exports.call = call;
<commit_msg>Add grpc transport timeout option to context<commit_after>'use strict';

let util = require('util');
let url = require('url');
let grpc = require('grpc');
let co = require('co');

/**
 * Name of the transport
 * @const
 */
const NAME = 'grpc';

/**
 * call wraps the method of conn into an endpoint.
 * @param  {Object} conn   A gRPC Client.
 * @param  {string} method The endpoint method name of the service.
 * @return {function*}        The endpoint.
 */
function call(conn, method) {
  if (!conn[method]) {
    throw new Error(util.format('conn has no method %s', method));
  }
  return function*(request, context) {
    let options = {};
    if (context && context.timeout) {
      options.deadline = Date.now() + context.timeout;
    }

    function call() {
      return function(callback) {
        conn[method](request, options, callback);
      };
    }
    try {
      let result = yield call();
      let response = {
        error: null,
        data: result,
      };
      return response;
    } catch (err) {
      let resp;
      switch (err.code) {
        case grpc.status.OK:
        case grpc.status.CANCELLED:
          resp = {
            error: new Error('operation was cancelled'),
          };
          break;
        case grpc.status.INVALID_ARGUMENT:
          resp = {
            error: new Error('invalid argument'),
          };
          break;
        case grpc.status.NOT_FOUND:
          resp = {
            error: new Error('not found'),
          };
          break;
        case grpc.status.ALREADY_EXISTS:
          resp = {
            error: new Error('already exists'),
          };
          break;
        case grpc.status.PERMISSION_DENIED:
          resp = {
            error: new Error('permission denied'),
          };
          break;
        case grpc.status.UNAUTHENTICATED:
          resp = {
            error: new Error('unauthenticated'),
          };
          break;
        case grpc.status.FAILED_PRECONDITION:
          resp = {
            error: new Error('failed precondition'),
          };
          break;
        case grpc.status.ABORTED:
          resp = {
            error: new Error('aborted'),
          };
          break;
        case grpc.status.OUT_OF_RANGE:
          resp = {
            error: new Error('out of range'),
          };
          break;
        case grpc.status.UNIMPLEMENTED:
          resp = {
            error: new Error('unimplemented'),
          };
          break;
        case grpc.status.RESOURCE_EXHAUSTED:
          resp = {
            error: new Error('resource exhausted'),
          };
          break;
        case grpc.status.DEADLINE_EXCEEDED:
          resp = {
            error: new Error('deadline exceeded'),
          };
          break;
        case grpc.status.UNKNOWN:
          resp = {
            error: new Error('unknown'),
          };
          break;
        case grpc.status.INTERNAL:
          resp = {
            error: new Error('internal'),
          };
          break;
        case grpc.status.UNAVAILABLE:
          resp = {
            error: new Error('unavailable'),
          };
          break;
        case grpc.status.DATA_LOSS:
          resp = {
            error: new Error('data loss'),
          };
          break;
        default:
          throw err;
      }
      if (resp.error.message !== err.message) {
        resp.error.details = err.message;
      }
      return resp;
    }
  }
}

/**
 * serve wraps the endpoint to provide a gRPC service method.
 * @param  {function*} endpoint Endpoint which will be served as a gRPC service method.
 * @return {[function]}          The function can be used as a gRPC service method.
 */
function serve(endpoint) {
  return function(call, callback) {
    let req = call.request;
    if (!endpoint) {
      callback({
        code: grpc.status.NOT_IMPLEMENTED
      });
    }
    co(function*() {
      let resp = yield endpoint(req);
      callback(null, resp);
    }).catch(function(err) {
      let code;
      // match message to grpc code
      // only service errors
      switch (err.message) {
        case 'operation was cancelled':
          code = grpc.status.CANCELLED;
          break;
        case 'invalid argument':
          code = grpc.status.INVALID_ARGUMENT;
          break;
        case 'not found':
          code = grpc.status.NOT_FOUND;
          break;
        case 'already exists':
          code = grpc.status.ALREADY_EXISTS;
          break;
        case 'permission denied':
          code = grpc.status.PERMISSION_DENIED;
          break;
        case 'unauthenticated':
          code = grpc.status.UNAUTHENTICATED;
          break;
        case 'failed precondition':
          code = grpc.status.FAILED_PRECONDITION;
          break;
        case 'aborted':
          code = grpc.status.ABORTED;
          break;
        case 'out of range':
          code = grpc.status.OUT_OF_RANGE;
          break;
        case 'unimplemented':
          code = grpc.status.UNIMPLEMENTED;
          break;
      }
      if (!code) {
        code = grpc.status.INTERNAL;
      }
      let details = err.message;
      if (err.details) {
        details = err.details;
      }
      callback({
        code: code,
        details: details,
      }, null);
    });
  };
}

/**
 * Server is a gRPC transport provider for serving.
 * @param {Object} config Configuration object.
 * Requires properties:addr,package,proto,service
 * Optional properties: credentials.ssl.certs
 */
function Server(config) {
  this._server = new grpc.Server();
  this._config = config;
  this._proto = grpc.load(process.cwd() + config.proto);
  this._service = this._proto[this._config.package][this._config.service].service;
  this.name = NAME;
}

/**
 * bind maps the service to gRPC methods and binds the address.
 * @param  {Object} service Business logic
 */
Server.prototype.bind = function*(service) {
  // wrap all service methods
  let binding = {};
  Object.getOwnPropertyNames(service).forEach(function(name) {
    binding[name] = serve(service[name]);
  });

  this._server.addProtoService(this._service, binding);

  let credentials = grpc.ServerCredentials.createInsecure();
  if (this._config.credentials) {
    if (this._config.credentials.ssl) {
      credentials = grpc.credentials.createSsl(this._config.credentials.ssl.certs);
    }
  }
  this._server.bind(this._config.addr, credentials);
}

/**
 * start launches the gRPC server and provides the service endpoints.
 */
Server.prototype.start = function*() {
  this._server.start();
}

/**
 * end stops the gRPC server and no longer provides the service endpoints.
 */
Server.prototype.end = function*() {
  this._server.tryShutdown();
}

/**
 * Client is a gRPC transport provider for calling endpoints.
 * @param {Object} config Configuration object.
 * Requires properties: package,proto,service
 * Optional properties: timeout
 */
function Client(config) {
  this.name = NAME;
  this.config = config;
  let proto = grpc.load(process.cwd() + config.proto);
  this._service = proto[config.package][config.service];
}

Client.prototype.makeEndpoint = function*(method, instance) {
  let u = url.parse(instance, true, true);
  if (u.protocol !== 'grpc:') {
    throw new Error('not a grpc instance URL');
  }
  let host = u.host;
  let credentials = grpc.credentials.createInsecure();
  if (this.config.credentials) {
    if (this.config.credentials.ssl) {
      let certs = this.config.credentials.ssl.certs;
      let key = this.config.credentials.ssl.key;
      let chain = this.config.credentials.ssl.chain;
      credentials = grpc.credentials.createSsl(certs, key, chain);
    }
  }
  let self = this;
  let conn = new this._service(host, credentials);
  if (this.config.timeout) {
    let deadline = Date.now() + this.config.timeout;
    grpc.waitForClientReady(conn, deadline, function(err) {
      if (err) {
        let chan = grpc.getClientChannel(conn);
        chan.close();
      }
    });
  }
  return call(conn, method);
}

module.exports.Name = NAME;
module.exports.Client = Client;
module.exports.Server = Server;
module.exports.serve = serve;
module.exports.call = call;
<|endoftext|>


<commit_before>'use strict'

var globby = require('globby')
var Path = require('path')
var errorEx = require('error-ex')
var Util = require('util')

var RequireError = errorEx('JSONError')

function requireGlobArrayCore(sync, patterns, opts) {
  if (typeof patterns === 'object' && !Array.isArray(patterns) &&
    opts === undefined) {

    opts = patterns
    patterns = null
  }
  opts = opts || {}
  var returnPath = opts.returnPath
  if (!patterns) {
    patterns = ['**/*.js']
  }

  function processPath(path) {
    try {
      var cwd = opts.cwd || '.'
      var req = require(Path.resolve(process.cwd(), cwd, path))
      if (returnPath) {
        return [path, req]
      }
      return req
    }
    catch (err) {
      let newErr = new RequireError("Error requiring file", {
        path: errorEx.append("%s"),
        errMessage: errorEx.line("%s")
      })
      newErr.err = err
      newErr.path = path
      newErr.errMessage = err.message
      throw newErr
    }
  }

  if (sync) {
    return globby.sync(patterns, opts).map(processPath)
  }
  return globby(patterns, opts).then(function(result) {
    return result.map(processPath)
  })
}

module.exports = function requireGlobArray(patterns, opts) {
  return requireGlobArrayCore(true, patterns, opts)
}

module.exports.async = function requireGlobArrayAsync(patterns, opts) {
  return requireGlobArrayCore(false, patterns, opts)
}

module.exports.RequireError = RequireError

Util.inherits(RequireError, CompositeError)
<commit_msg>remove inherits line<commit_after>'use strict'

var globby = require('globby')
var Path = require('path')
var errorEx = require('error-ex')

var RequireError = errorEx('JSONError')

function requireGlobArrayCore(sync, patterns, opts) {
  if (typeof patterns === 'object' && !Array.isArray(patterns) &&
    opts === undefined) {

    opts = patterns
    patterns = null
  }
  opts = opts || {}
  var returnPath = opts.returnPath
  if (!patterns) {
    patterns = ['**/*.js']
  }

  function processPath(path) {
    try {
      var cwd = opts.cwd || '.'
      var req = require(Path.resolve(process.cwd(), cwd, path))
      if (returnPath) {
        return [path, req]
      }
      return req
    }
    catch (err) {
      let newErr = new RequireError("Error requiring file", {
        path: errorEx.append("%s"),
        errMessage: errorEx.line("%s")
      })
      newErr.err = err
      newErr.path = path
      newErr.errMessage = err.message
      throw newErr
    }
  }

  if (sync) {
    return globby.sync(patterns, opts).map(processPath)
  }
  return globby(patterns, opts).then(function(result) {
    return result.map(processPath)
  })
}

module.exports = function requireGlobArray(patterns, opts) {
  return requireGlobArrayCore(true, patterns, opts)
}

module.exports.async = function requireGlobArrayAsync(patterns, opts) {
  return requireGlobArrayCore(false, patterns, opts)
}

module.exports.RequireError = RequireError
<|endoftext|>


<commit_before>/**
 * External dependencies.
 */

var mongoose = require('mongoose');

/**
 * Drop all known mongoose collections before
 * each test.
 *
 * @param {Object} hydro
 * @api public
 */

module.exports = function(hydro) {
  hydro.on('pre:test', function(file, done) {
    var collections = Object.keys(mongoose.connection.collections);
    var len = collections.length;
    if (len === 0) return done();
    collections.forEach(function(collection) {
      mongoose.connection.collections[collection].drop(function() {
        if (--len === 0) done();
      });
    });
  });
};
<commit_msg>Throw an error if dropping the collections took more than 2s<commit_after>/**
 * External dependencies.
 */

var mongoose = require('mongoose');

/**
 * Drop all known mongoose collections before
 * each test.
 *
 * @param {Object} hydro
 * @api public
 */

module.exports = function(hydro) {
  hydro.on('pre:test', function(file, done) {
    var collections = Object.keys(mongoose.connection.collections);
    var len = collections.length;
    if (len === 0) return done();

    var timeout = setTimeout(function() {
      throw new Error('mongoose collections drop took more than 2s. Make sure that you have established a database connection');
    }, 2000);

    var end = function() {
      clearTimeout(timeout);
      done();
    };

    collections.forEach(function(collection) {
      mongoose.connection.collections[collection].drop(function() {
        if (--len === 0) end();
      });
    });
  });
};
<|endoftext|>


<commit_before>'use strict'

var isFile = require('file-exists')

function getMetadata (options) {
  var generatorModule
  var generator

  if (!options) {
    throw new Error('Missing required input: options')
  }
  if (!options.generator) {
    throw new Error('Missing required input: options.generator')
  }

  generatorModule = './lib/' + options.generator

  if (!isFile(generatorModule + '.js')) {
    throw new Error('supplied generator does not exist')
  }

  generator = require(generatorModule)

  return generator(options)
}

module.exports = getMetadata
<commit_msg>Update index.js<commit_after>'use strict'

var isFile = require('file-exists')

function getMetadata (options) {
  var generatorModule
  var generator

  if (!options) {
    throw new Error('Missing required input: options')
  }
  if (!options.generator) {
    throw new Error('Missing required input: options.generator')
  }

  generatorModule = __dirname + '/lib/' + options.generator

  if (!isFile(generatorModule + '.js')) {
    throw new Error('supplied generator does not exist')
  }

  generator = require(generatorModule)

  return generator(options)
}

module.exports = getMetadata
<|endoftext|>


<commit_before>var request = require('request')
var fs = require('fs')
var Writable = require('stream').Writable
var extend = require('util-extend')

var ENDPOINT = 'https://upload.twitter.com/1.1/media/upload.json'

function twitterVideo (path, oauth, cb) {
  // Caution!
  // https://dev.twitter.com/overview/api/twitter-ids-json-and-snowflake
  var media_id
  var oauthReq = {
    consumer_key: oauth.consumer_key,
    consumer_secret: oauth.consumer_secret,
    token: oauth.access_token,
    token_secret: oauth.access_token_secret
  }

  var baseReq = {
    url: ENDPOINT,
    oauth: oauthReq,
    json: true
  }

  var initReq = extend({
    formData: {
      media_type: 'video/mp4',
      command: 'INIT'
    }
  }, baseReq)

  var finalReq = extend({
    formData: {
      command: 'FINALIZE'
    }
  }, baseReq)

  fs.stat(path, function (err, stats) {
    if (err) return cb(err)
    initReq.formData.total_bytes = stats.size
    request.post(initReq, function cb (err, res, body) {
      debugger
      if (err) return cb(err)
      console.log(body)
      media_id = body.media_id_string
      finalReq.formData.media_id = media_id

      console.log(finalReq)

      var twitAppend = twitterUpload(media_id, baseReq)
      var fileStream = fs.createReadStream(path)

      twitAppend.on('error', function streamError (err) {
        return cb(err)
      })
      twitAppend.on('finish', function finalize () {
        request.post(finalReq, function (err, res, body) {
          return cb(err, media_id)
        })
      })
      fileStream.pipe(twitAppend)
    })
  })
}

function counter () {
  var i = 0
  return function aCounter () {
    return i++
  }
}

function twitterUpload (media_id, baseReq) {
  var c = counter()
  var append = Writable()
  append._write = function write (chunk, enc, next) {
    var appendReq = extend({ formData: {
        segment_index: c(),
        command: 'APPEND',
        media_id: media_id,
        media: chunk
      }
    }, baseReq)
    console.log(appendReq)
    request.post(appendReq, function append (err, res, body) {
      next(err)
    })
  }
  return append
}

module.exports = twitterVideo
<commit_msg>Fixed stupid stupid bug<commit_after>var request = require('request')
var fs = require('fs')
var Writable = require('stream').Writable
var extend = require('util-extend')

var ENDPOINT = 'https://upload.twitter.com/1.1/media/upload.json'

function twitterVideo (path, oauth, cb) {
  // Caution!
  // https://dev.twitter.com/overview/api/twitter-ids-json-and-snowflake
  var media_id
  var oauthReq = {
    consumer_key: oauth.consumer_key,
    consumer_secret: oauth.consumer_secret,
    token: oauth.access_token,
    token_secret: oauth.access_token_secret
  }

  var baseReq = {
    url: ENDPOINT,
    oauth: oauthReq,
    json: true
  }

  var initReq = extend({
    formData: {
      media_type: 'video/mp4',
      command: 'INIT'
    }
  }, baseReq)

  var finalReq = extend({
    formData: {
      command: 'FINALIZE'
    }
  }, baseReq)

  fs.stat(path, function (err, stats) {
    if (err) return cb(err)
    initReq.formData.total_bytes = stats.size
    request.post(initReq, function initCb (err, res, body) {
      if (err) return cb(err)
      media_id = body.media_id_string
      finalReq.formData.media_id = media_id

      var twitAppend = twitterUpload(media_id, baseReq)
      var fileStream = fs.createReadStream(path)

      twitAppend.on('error', function streamError (err) {
        return cb(err)
      })
      twitAppend.on('finish', function finalize () {
        request.post(finalReq, function (err, res, body) {
          return cb(err, media_id)
        })
      })
      fileStream.pipe(twitAppend)
    })
  })
}

function counter () {
  var i = 0
  return function aCounter () {
    return i++
  }
}

function twitterUpload (media_id, baseReq) {
  var c = counter()
  var append = Writable()
  append._write = function write (chunk, enc, next) {
    var appendReq = extend({ formData: {
        segment_index: c(),
        command: 'APPEND',
        media_id: media_id,
        media: chunk
      }
    }, baseReq)
    console.log(appendReq)
    request.post(appendReq, function append (err, res, body) {
      next(err)
    })
  }
  return append
}

module.exports = twitterVideo
<|endoftext|>


<commit_before>/*
Copyright (c) Django Software Foundation and individual contributors.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice,
       this list of conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.

    3. Neither the name of Django nor the names of its contributors may be used
       to endorse or promote products derived from this software without
       specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * Translation Maps
 */
var LATIN_MAP = {
      'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE', 'Ç':
      'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I', 'Î': 'I',
      'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O', 'Õ': 'O', 'Ö':
      'O', 'Ő': 'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U', 'Ü': 'U', 'Ű': 'U',
      'Ý': 'Y', 'Þ': 'TH', 'ß': 'ss', 'à':'a', 'á':'a', 'â': 'a', 'ã': 'a', 'ä':
      'a', 'å': 'a', 'æ': 'ae', 'ç': 'c', 'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e',
      'ì': 'i', 'í': 'i', 'î': 'i', 'ï': 'i', 'ð': 'd', 'ñ': 'n', 'ò': 'o', 'ó':
      'o', 'ô': 'o', 'õ': 'o', 'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u',
      'û': 'u', 'ü': 'u', 'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y'
    }
  , LATIN_SYMBOLS_MAP = {
      '©':'(c)'
    }
  , GREEK_MAP = {
      'α':'a', 'β':'b', 'γ':'g', 'δ':'d', 'ε':'e', 'ζ':'z', 'η':'h', 'θ':'8',
      'ι':'i', 'κ':'k', 'λ':'l', 'μ':'m', 'ν':'n', 'ξ':'3', 'ο':'o', 'π':'p',
      'ρ':'r', 'σ':'s', 'τ':'t', 'υ':'y', 'φ':'f', 'χ':'x', 'ψ':'ps', 'ω':'w',
      'ά':'a', 'έ':'e', 'ί':'i', 'ό':'o', 'ύ':'y', 'ή':'h', 'ώ':'w', 'ς':'s',
      'ϊ':'i', 'ΰ':'y', 'ϋ':'y', 'ΐ':'i',
      'Α':'A', 'Β':'B', 'Γ':'G', 'Δ':'D', 'Ε':'E', 'Ζ':'Z', 'Η':'H', 'Θ':'8',
      'Ι':'I', 'Κ':'K', 'Λ':'L', 'Μ':'M', 'Ν':'N', 'Ξ':'3', 'Ο':'O', 'Π':'P',
      'Ρ':'R', 'Σ':'S', 'Τ':'T', 'Υ':'Y', 'Φ':'F', 'Χ':'X', 'Ψ':'PS', 'Ω':'W',
      'Ά':'A', 'Έ':'E', 'Ί':'I', 'Ό':'O', 'Ύ':'Y', 'Ή':'H', 'Ώ':'W', 'Ϊ':'I',
      'Ϋ':'Y'
    }
  , TURKISH_MAP = {
      'ş':'s', 'Ş':'S', 'ı':'i', 'İ':'I', 'ç':'c', 'Ç':'C', 'ü':'u', 'Ü':'U',
      'ö':'o', 'Ö':'O', 'ğ':'g', 'Ğ':'G'
    }
  , RUSSIAN_MAP = {
      'а':'a', 'б':'b', 'в':'v', 'г':'g', 'д':'d', 'е':'e', 'ё':'yo', 'ж':'zh',
      'з':'z', 'и':'i', 'й':'j', 'к':'k', 'л':'l', 'м':'m', 'н':'n', 'о':'o',
      'п':'p', 'р':'r', 'с':'s', 'т':'t', 'у':'u', 'ф':'f', 'х':'h', 'ц':'c',
      'ч':'ch', 'ш':'sh', 'щ':'sh', 'ъ':'', 'ы':'y', 'ь':'', 'э':'e', 'ю':'yu',
      'я':'ya',
      'А':'A', 'Б':'B', 'В':'V', 'Г':'G', 'Д':'D', 'Е':'E', 'Ё':'Yo', 'Ж':'Zh',
      'З':'Z', 'И':'I', 'Й':'J', 'К':'K', 'Л':'L', 'М':'M', 'Н':'N', 'О':'O',
      'П':'P', 'Р':'R', 'С':'S', 'Т':'T', 'У':'U', 'Ф':'F', 'Х':'H', 'Ц':'C',
      'Ч':'Ch', 'Ш':'Sh', 'Щ':'Sh', 'Ъ':'', 'Ы':'Y', 'Ь':'', 'Э':'E', 'Ю':'Yu',
      'Я':'Ya'
    }
  , UKRAINIAN_MAP = {
      'Є':'Ye', 'І':'I', 'Ї':'Yi', 'Ґ':'G', 'є':'ye', 'і':'i', 'ї':'yi', 'ґ':'g'
    }
  , CZECH_MAP = {
      'č':'c', 'ď':'d', 'ě':'e', 'ň': 'n', 'ř':'r', 'š':'s', 'ť':'t', 'ů':'u',
      'ž':'z', 'Č':'C', 'Ď':'D', 'Ě':'E', 'Ň': 'N', 'Ř':'R', 'Š':'S', 'Ť':'T',
      'Ů':'U', 'Ž':'Z'
    }
  , POLISH_MAP = {
      'ą':'a', 'ć':'c', 'ę':'e', 'ł':'l', 'ń':'n', 'ó':'o', 'ś':'s', 'ź':'z',
      'ż':'z', 'Ą':'A', 'Ć':'C', 'Ę':'e', 'Ł':'L', 'Ń':'N', 'Ó':'o', 'Ś':'S',
      'Ź':'Z', 'Ż':'Z'
    }
  , LATVIAN_MAP = {
      'ā':'a', 'č':'c', 'ē':'e', 'ģ':'g', 'ī':'i', 'ķ':'k', 'ļ':'l', 'ņ':'n',
      'š':'s', 'ū':'u', 'ž':'z', 'Ā':'A', 'Č':'C', 'Ē':'E', 'Ģ':'G', 'Ī':'i',
      'Ķ':'k', 'Ļ':'L', 'Ņ':'N', 'Š':'S', 'Ū':'u', 'Ž':'Z'
    }
  , ALL_DOWNCODE_MAPS = [
      LATIN_MAP
    , LATIN_SYMBOLS_MAP
    , GREEK_MAP
    , TURKISH_MAP
    , RUSSIAN_MAP
    , UKRAINIAN_MAP
    , CZECH_MAP
    , POLISH_MAP
    , LATVIAN_MAP
    ]
  ;
/**
 * @private
 * character map precompiler
 */
var Downcoder = (function(){
  var d = {};

  d.map = {}
  d.chars = '' ;
  for(var i in ALL_DOWNCODE_MAPS) {
    var lookup = ALL_DOWNCODE_MAPS[i]
    for (var c in lookup) {
      d.map[c] = lookup[c] ;
      d.chars += c;
    }
  }
  d.regex = new RegExp('[' + d.chars + ']|[^' + d.chars + ']+','g');

  return d;
})();

var downcode = function(slug) {
  var downcoded = ""
    , pieces = slug.match(Downcoder.regex);

  if (pieces) {
    for (var i = 0 ; i < pieces.length ; i++) {
      if (pieces[i].length == 1) {
        var mapped = Downcoder.map[pieces[i]] ;
        if (mapped != null) {
          downcoded+=mapped;
          continue ;
        }
      }
      downcoded+=pieces[i];
    }
  } else {
    downcoded = slug;
  }
  return downcoded;
}

/**
 * Makes a string URL frendly
 * @param  {String}  s         input string
 * @param  {Integer} num_chars output max length
 * @return {String}            urlified string
 */
module.exports = function(s, num_chars) {
  // changes, e.g., "Petty theft" to "petty_theft"
  // remove all these words from the string before urlifying
  s = downcode(s)
                                // if downcode doesn't hit, the char will be stripped here
    .replace(/[^-\w\s]/g, '')   // remove unneeded chars
    .replace(/^\s+|\s+$/g, '')  // trim leading/trailing spaces
    .replace(/[-\s]+/g, '-')    // convert spaces to one hyphen
    .toLowerCase();             // convert to lowercase
  return (!!num_chars)
    ? s.substring(0, num_chars).replace(/-$/, '') // trim to first num_chars chars
    : s
}
<commit_msg>Made syntax and whitespace consistent<commit_after>/*
Copyright (c) Django Software Foundation and individual contributors.
All rights reserved.

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

    1. Redistributions of source code must retain the above copyright notice,
       this list of conditions and the following disclaimer.

    2. Redistributions in binary form must reproduce the above copyright
       notice, this list of conditions and the following disclaimer in the
       documentation and/or other materials provided with the distribution.

    3. Neither the name of Django nor the names of its contributors may be used
       to endorse or promote products derived from this software without
       specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * Translation Maps
 */
var LATIN_MAP = {
      'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE', 'Ç':
      'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I', 'Î': 'I',
      'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O', 'Õ': 'O', 'Ö':
      'O', 'Ő': 'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U', 'Ü': 'U', 'Ű': 'U',
      'Ý': 'Y', 'Þ': 'TH', 'ß': 'ss', 'à':'a', 'á':'a', 'â': 'a', 'ã': 'a', 'ä':
      'a', 'å': 'a', 'æ': 'ae', 'ç': 'c', 'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e',
      'ì': 'i', 'í': 'i', 'î': 'i', 'ï': 'i', 'ð': 'd', 'ñ': 'n', 'ò': 'o', 'ó':
      'o', 'ô': 'o', 'õ': 'o', 'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u',
      'û': 'u', 'ü': 'u', 'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y'
    }
  , LATIN_SYMBOLS_MAP = {
      '©':'(c)'
    }
  , GREEK_MAP = {
      'α':'a', 'β':'b', 'γ':'g', 'δ':'d', 'ε':'e', 'ζ':'z', 'η':'h', 'θ':'8',
      'ι':'i', 'κ':'k', 'λ':'l', 'μ':'m', 'ν':'n', 'ξ':'3', 'ο':'o', 'π':'p',
      'ρ':'r', 'σ':'s', 'τ':'t', 'υ':'y', 'φ':'f', 'χ':'x', 'ψ':'ps', 'ω':'w',
      'ά':'a', 'έ':'e', 'ί':'i', 'ό':'o', 'ύ':'y', 'ή':'h', 'ώ':'w', 'ς':'s',
      'ϊ':'i', 'ΰ':'y', 'ϋ':'y', 'ΐ':'i',
      'Α':'A', 'Β':'B', 'Γ':'G', 'Δ':'D', 'Ε':'E', 'Ζ':'Z', 'Η':'H', 'Θ':'8',
      'Ι':'I', 'Κ':'K', 'Λ':'L', 'Μ':'M', 'Ν':'N', 'Ξ':'3', 'Ο':'O', 'Π':'P',
      'Ρ':'R', 'Σ':'S', 'Τ':'T', 'Υ':'Y', 'Φ':'F', 'Χ':'X', 'Ψ':'PS', 'Ω':'W',
      'Ά':'A', 'Έ':'E', 'Ί':'I', 'Ό':'O', 'Ύ':'Y', 'Ή':'H', 'Ώ':'W', 'Ϊ':'I',
      'Ϋ':'Y'
    }
  , TURKISH_MAP = {
      'ş':'s', 'Ş':'S', 'ı':'i', 'İ':'I', 'ç':'c', 'Ç':'C', 'ü':'u', 'Ü':'U',
      'ö':'o', 'Ö':'O', 'ğ':'g', 'Ğ':'G'
    }
  , RUSSIAN_MAP = {
      'а':'a', 'б':'b', 'в':'v', 'г':'g', 'д':'d', 'е':'e', 'ё':'yo', 'ж':'zh',
      'з':'z', 'и':'i', 'й':'j', 'к':'k', 'л':'l', 'м':'m', 'н':'n', 'о':'o',
      'п':'p', 'р':'r', 'с':'s', 'т':'t', 'у':'u', 'ф':'f', 'х':'h', 'ц':'c',
      'ч':'ch', 'ш':'sh', 'щ':'sh', 'ъ':'', 'ы':'y', 'ь':'', 'э':'e', 'ю':'yu',
      'я':'ya',
      'А':'A', 'Б':'B', 'В':'V', 'Г':'G', 'Д':'D', 'Е':'E', 'Ё':'Yo', 'Ж':'Zh',
      'З':'Z', 'И':'I', 'Й':'J', 'К':'K', 'Л':'L', 'М':'M', 'Н':'N', 'О':'O',
      'П':'P', 'Р':'R', 'С':'S', 'Т':'T', 'У':'U', 'Ф':'F', 'Х':'H', 'Ц':'C',
      'Ч':'Ch', 'Ш':'Sh', 'Щ':'Sh', 'Ъ':'', 'Ы':'Y', 'Ь':'', 'Э':'E', 'Ю':'Yu',
      'Я':'Ya'
    }
  , UKRAINIAN_MAP = {
      'Є':'Ye', 'І':'I', 'Ї':'Yi', 'Ґ':'G', 'є':'ye', 'і':'i', 'ї':'yi', 'ґ':'g'
    }
  , CZECH_MAP = {
      'č':'c', 'ď':'d', 'ě':'e', 'ň': 'n', 'ř':'r', 'š':'s', 'ť':'t', 'ů':'u',
      'ž':'z', 'Č':'C', 'Ď':'D', 'Ě':'E', 'Ň': 'N', 'Ř':'R', 'Š':'S', 'Ť':'T',
      'Ů':'U', 'Ž':'Z'
    }
  , POLISH_MAP = {
      'ą':'a', 'ć':'c', 'ę':'e', 'ł':'l', 'ń':'n', 'ó':'o', 'ś':'s', 'ź':'z',
      'ż':'z', 'Ą':'A', 'Ć':'C', 'Ę':'e', 'Ł':'L', 'Ń':'N', 'Ó':'o', 'Ś':'S',
      'Ź':'Z', 'Ż':'Z'
    }
  , LATVIAN_MAP = {
      'ā':'a', 'č':'c', 'ē':'e', 'ģ':'g', 'ī':'i', 'ķ':'k', 'ļ':'l', 'ņ':'n',
      'š':'s', 'ū':'u', 'ž':'z', 'Ā':'A', 'Č':'C', 'Ē':'E', 'Ģ':'G', 'Ī':'i',
      'Ķ':'k', 'Ļ':'L', 'Ņ':'N', 'Š':'S', 'Ū':'u', 'Ž':'Z'
    }
  , ALL_DOWNCODE_MAPS = [
      LATIN_MAP
    , LATIN_SYMBOLS_MAP
    , GREEK_MAP
    , TURKISH_MAP
    , RUSSIAN_MAP
    , UKRAINIAN_MAP
    , CZECH_MAP
    , POLISH_MAP
    , LATVIAN_MAP
    ]
  ;
/**
 * @private
 * character map precompiler
 */
var Downcoder = (function() {
  var d = {}, i, lookup, c;

  d.map = {};
  d.chars = '' ;
  for (i in ALL_DOWNCODE_MAPS) {
    lookup = ALL_DOWNCODE_MAPS[i];
    for (c in lookup) {
      d.map[c] = lookup[c];
      d.chars += c;
    }
  }
  d.regex = new RegExp('[' + d.chars + ']|[^' + d.chars + ']+', 'g');

  return d;
})();

var downcode = function(slug) {
  var downcoded = ''
    , pieces = slug.match(Downcoder.regex);

  if (pieces) {
    for (var i = 0 ; i < pieces.length ; i++) {
      if (pieces[i].length == 1) {
        var mapped = Downcoder.map[pieces[i]];
        if (mapped != null) {
          downcoded += mapped;
          continue;
        }
      }
      downcoded+=pieces[i];
    }
  } else {
    downcoded = slug;
  }
  return downcoded;
};

/**
 * Makes a string URL frendly
 * @param  {String}  s         input string
 * @param  {Integer} num_chars output max length
 * @return {String}            urlified string
 */
module.exports = function(s, num_chars) {
  // changes, e.g., "Petty theft" to "petty-theft"
  // remove all these words from the string before urlifying
  s = downcode(s)
                                // if downcode doesn't hit, the char will be stripped here
    .replace(/[^-\w\s]/g, '')   // remove unneeded chars
    .replace(/^\s+|\s+$/g, '')  // trim leading/trailing spaces
    .replace(/[-\s]+/g, '-')    // convert spaces to one hyphen
    .toLowerCase();             // convert to lowercase
  return (!!num_chars)
    ? s.substring(0, num_chars).replace(/-$/, '') // trim to first num_chars chars
    : s;
};
<|endoftext|>


<commit_before>const self = require("sdk/self");
var _ = require("sdk/l10n").get;

const {Hotkey} = require("sdk/hotkeys");
const {Panel} = require("sdk/panel");
const Prefs = require("sdk/simple-prefs");
const {SessionStorage} = require("lib/storage/session");
const {ToggleButton} = require("sdk/ui/button/toggle");
const WindowUtils = require("sdk/window/utils");

function TabGroups() {
  this._groupsPanel = null;
  this._hotkey = null;
  this._panelButton = null;

  this._storage = new SessionStorage();

  this.init();
  this.bindEvents();
}

TabGroups.prototype = {
  init: function() {
    this.createPanelButton();
    this.createGroupsPanel();
    this.createHotkey();
  },

  bindEvents: function() {
    this.bindHotkeyPreference();
    this.bindPanelButtonEvents();
    this.bindPanelEvents();
  },

  createGroupsPanel: function() {
    this._groupsPanel = Panel({
      contentURL: self.data.url("groupspanel.html")
    });
  },

  createPanelButton: function() {
    this._panelButton = ToggleButton({
      id: "tabgroups-show",
      icon: {
        "32": self.data.url("assets/images/icon-32.png"),
        "64": self.data.url("assets/images/icon-64.png")
      },
      label: _("panelButton_label")
    });
  },

  createHotkey: function() {
    if (!Prefs.prefs.bindPanoramaShortcut) {
      return;
    }

    this._hotkey = Hotkey({
      combo: "accel-shift-e",
      onPress: () => {
        if (this._groupsPanel.isShowing) {
          this._groupsPanel.hide();
        } else {
          this._groupsPanel.show({position: this._panelButton});
          this._panelButton.state("window", {checked: true});
        }
      }
    });
  },

  bindHotkeyPreference: function() {
    if (Prefs.prefs.bindPanoramaShortcut) {
      this.createHotkey();
    }

    Prefs.on("bindPanoramaShortcut", () => {
      if (Prefs.prefs.bindPanoramaShortcut) {
        if (!this._hotkey) {
          this.createHotkey();
        }
      } else if (this._hotkey) {
        this._hotkey.destroy();
        this._hotkey = null;
      }
    });
  },

  bindPanelButtonEvents: function() {
    this._panelButton.on("change", (state) => {
      if (!state.checked) {
        return;
      }

      this._groupsPanel.show({position: this._panelButton});
    });
  },

  bindPanelEvents: function() {
    this._groupsPanel.on("hide", () => {
      this._panelButton.state("window", {checked: false});
    });

    this._groupsPanel.on("show", () => {
      let currentWindow = WindowUtils.getMostRecentBrowserWindow();
      let groups = this._storage.getGroups(currentWindow);
      let tabs = this._storage.getGroupedTabs(currentWindow);

      this._groupsPanel.port.emit("TabgroupsChanged", groups.map((group) => {
        group.tabs = tabs[group.id];
        return group;
      }));
    });
  }
};

new TabGroups();
<commit_msg>Ensure the panel gets closed<commit_after>const self = require("sdk/self");
var _ = require("sdk/l10n").get;

const {Hotkey} = require("sdk/hotkeys");
const {Panel} = require("sdk/panel");
const Prefs = require("sdk/simple-prefs");
const {SessionStorage} = require("lib/storage/session");
const {ToggleButton} = require("sdk/ui/button/toggle");
const WindowUtils = require("sdk/window/utils");

function TabGroups() {
  this._groupsPanel = null;
  this._hotkey = null;
  this._panelButton = null;

  this._storage = new SessionStorage();

  this.init();
  this.bindEvents();
}

TabGroups.prototype = {
  init: function() {
    this.createPanelButton();
    this.createGroupsPanel();
    this.createHotkey();
  },

  bindEvents: function() {
    this.bindHotkeyPreference();
    this.bindPanelButtonEvents();
    this.bindPanelEvents();
  },

  createGroupsPanel: function() {
    this._groupsPanel = Panel({
      contentURL: self.data.url("groupspanel.html")
    });
  },

  createPanelButton: function() {
    this._panelButton = ToggleButton({
      id: "tabgroups-show",
      icon: {
        "32": self.data.url("assets/images/icon-32.png"),
        "64": self.data.url("assets/images/icon-64.png")
      },
      label: _("panelButton_label")
    });
  },

  createHotkey: function() {
    if (!Prefs.prefs.bindPanoramaShortcut) {
      return;
    }

    this._hotkey = Hotkey({
      combo: "accel-shift-e",
      onPress: () => {
        if (this._groupsPanel.isShowing) {
          this._groupsPanel.hide();
        } else {
          this._groupsPanel.show({position: this._panelButton});
          this._panelButton.state("window", {checked: true});
        }
      }
    });
  },

  bindHotkeyPreference: function() {
    if (Prefs.prefs.bindPanoramaShortcut) {
      this.createHotkey();
    }

    Prefs.on("bindPanoramaShortcut", () => {
      if (Prefs.prefs.bindPanoramaShortcut) {
        if (!this._hotkey) {
          this.createHotkey();
        }
      } else if (this._hotkey) {
        this._hotkey.destroy();
        this._hotkey = null;
      }
    });
  },

  bindPanelButtonEvents: function() {
    this._panelButton.on("change", (state) => {
      if (!state.checked) {
        this._groupsPanel.hide();
      } else {
        this._groupsPanel.show({position: this._panelButton});
      }
    });
  },

  bindPanelEvents: function() {
    this._groupsPanel.on("hide", () => {
      this._panelButton.state("window", {checked: false});
    });

    this._groupsPanel.on("show", () => {
      let currentWindow = WindowUtils.getMostRecentBrowserWindow();
      let groups = this._storage.getGroups(currentWindow);
      let tabs = this._storage.getGroupedTabs(currentWindow);

      this._groupsPanel.port.emit("TabgroupsChanged", groups.map((group) => {
        group.tabs = tabs[group.id];
        return group;
      }));
    });
  }
};

new TabGroups();
<|endoftext|>


<commit_before>// respond to qustion
// http://tutorhelp.uvu.edu/api_data.php?action=respondquestion&questionId=18321&tutorUvid=10704736
// finish
// http://tutorhelp.uvu.edu/api_data.php?action=finishquestion&questionId=18321

var _ = require('lodash');
var fs = require('fs');
var http = require('http');
const readline = require('readline');

// TODO: use enpoints and this readline interface to respond and finish answering questions.
const rl = readline.createInterface({
    input: process.stdin,
      output: process.stout
});

var savedQuestions = [];
var uvid = '';
var tutorHelping = 0;

getQueue();

rl.on('line', cmd => {
    var index = parseInt(cmd) - 1;
    if ( tutorHelping ) {
        http.get(`http://tutorhelp.uvu.edu/api_data.php?action=finishquestion&questionId=${tutorHelping}`, (res) => {
            res.setEncoding('utf8');
            tutorHelping = 0;
            getQueue();
            });
    } else {
        if ( index < savedQuestions.length ) {
            console.log('\033c');
            http.get(`http://tutorhelp.uvu.edu/api_data.php?action=respondquestion&questionId=${savedQuestions[index].id}&tutorUvid=${uvid}`, (res) => {
                res.setEncoding('utf8');
                res.on('data', (chunk) => { console.log(`Helping ${savedQuestions[index].studentName}`) });
                tutorHelping = savedQuestions[index].id;
                });
        }
    }
});

function getQueue() {
    if ( tutorHelping ) { return; }
    // set id equal to your student id
    http.get('http://tutorhelp.uvu.edu/api_data.php?action=getquestions&tutorid=' + uvid + '&center=4', (res) => {
            res.setEncoding('utf8');
            res.on('data', (chunk) => {
                var data = JSON.parse(chunk);
                // TODO: change these condidtions to a more simple and lightweight one
                if ( !data.questions.length ) { printQuestions(data.questions); }
                if ( _.differenceWith(data.questions, savedQuestions, _.isEqual ).length > 0) {
                    process.stdout.write('\x07');
                    printQuestions(data.questions);
                } else if ( _.differenceWith(savedQuestions, data.questions, _.isEqual ).length > 0) {
                    printQuestions(data.questions);
                }
            });
            }).on('error', (e) => { console.log(`Got error: ${e.message}`); });
}

function printQuestions(questions) {
    console.log('\033c');
    savedQuestions = _.cloneDeep(questions);
    console.log("Name\t\t\t\tClass\t\t\tTable\t\t\tQuestion");
    console.log("-----------------------------------------------------------------");
    _.forEach(questions, o => {
        console.log(`${o.studentName}\t\t\t${o.class}\t\t${o.table}\t\t\t${o.question}`);
    });
}

fs.readFile('uvid.txt', (err, data) => {
    if (err) throw err;
    uvid = data.toString();
});

setInterval(getQueue, 5000);
<commit_msg>added beep on error<commit_after>// respond to qustion
// http://tutorhelp.uvu.edu/api_data.php?action=respondquestion&questionId=18321&tutorUvid=10704736
// finish
// http://tutorhelp.uvu.edu/api_data.php?action=finishquestion&questionId=18321

var _ = require('lodash');
var fs = require('fs');
var http = require('http');
const readline = require('readline');

// TODO: use enpoints and this readline interface to respond and finish answering questions.
const rl = readline.createInterface({
    input: process.stdin,
      output: process.stout
});

var savedQuestions = [];
var uvid = '';
var tutorHelping = 0;

getQueue();

rl.on('line', cmd => {
    var index = parseInt(cmd) - 1;
    if ( tutorHelping ) {
        http.get(`http://tutorhelp.uvu.edu/api_data.php?action=finishquestion&questionId=${tutorHelping}`, (res) => {
            res.setEncoding('utf8');
            tutorHelping = 0;
            getQueue();
            });
    } else {
        if ( index < savedQuestions.length ) {
            console.log('\033c');
            http.get(`http://tutorhelp.uvu.edu/api_data.php?action=respondquestion&questionId=${savedQuestions[index].id}&tutorUvid=${uvid}`, (res) => {
                res.setEncoding('utf8');
                res.on('data', (chunk) => { console.log(`Helping ${savedQuestions[index].studentName}`) });
                tutorHelping = savedQuestions[index].id;
                });
        }
    }
});

function getQueue() {
    if ( tutorHelping ) { return; }
    // set id equal to your student id
    http.get('http://tutorhelp.uvu.edu/api_data.php?action=getquestions&tutorid=' + uvid + '&center=4', (res) => {
            res.setEncoding('utf8');
            res.on('data', (chunk) => {
                var data = JSON.parse(chunk);
                // TODO: change these condidtions to a more simple and lightweight one
                if ( !data.questions.length ) { printQuestions(data.questions); }
                if ( _.differenceWith(data.questions, savedQuestions, _.isEqual ).length > 0) {
                    process.stdout.write('\x07');
                    printQuestions(data.questions);
                } else if ( _.differenceWith(savedQuestions, data.questions, _.isEqual ).length > 0) {
                    printQuestions(data.questions);
                }
            });
            }).on('error', (e) => {
		    console.log(`Got error: ${e.message}`);
		    console.log('\x07');
	    });
}

function printQuestions(questions) {
    console.log('\033c');
    savedQuestions = _.cloneDeep(questions);
    console.log("Name\t\t\t\tClass\t\t\tTable\t\t\tQuestion");
    console.log("-----------------------------------------------------------------");
    _.forEach(questions, o => {
        console.log(`${o.studentName}\t\t\t${o.class}\t\t${o.table}\t\t\t${o.question}`);
    });
}

fs.readFile('uvid.txt', (err, data) => {
    if (err) throw err;
    uvid = data.toString();
});

setInterval(getQueue, 5000);
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

var PluginBase = require('ember-cli-deploy-plugin');
var Promise = require('ember-cli/lib/ext/promise');
var readFileSync = require('fs').readFileSync;
var joinPath = require('path').join;

var API = require('./lib/api');
var uploadAsset = require('./lib/upload-asset');
var fetchCommit = require('./lib/fetch-commit');
var findFile = require('./lib/find-file');

var PAGEFRONTRC = '.pagefrontrc';
var INDEX = 'index.html';

function mungeRelease(release) {
  return {
    revision: release.attributes.version,
    version: 'v' + release.attributes.version,
    timestamp: new Date(release.attributes.created_at).getTime(),
    active: false
  };
}

module.exports = {
  name: 'ember-cli-deploy-pagefront',

  createDeployPlugin: function(options) {
    var Plugin = PluginBase.extend({
      name: options.name,
      requiredConfig: ['app', 'key'],
      defaultConfig: {
        key: function() {
          var rawPagefrontrc = readFileSync(findFile(PAGEFRONTRC));

          return JSON.parse(rawPagefrontrc).key
        }
      },

      configure: function(context) {
        this._super.configure.call(this, context);
        this.api = new API(this.readConfig('key'));
      },

      fetchRevisions: function(context) {
        var app = this.readConfig('app');

        return this.api.listReleases(app).then(function(payload) {
          context.revisions = payload.map(mungeRelease);

          if (context.revisions.length) {
            context.revisions[0].active = true;
          }
        });
      },

      activate: function(context) {
        var app = this.readConfig('app');
        var revision = context.commandOptions.revision;
        var didActivate = this._didActivate.bind(this, revision);

        return this.api.createRelease(app, {
          release: revision
        }).then(didActivate);
      },

      upload: function(context) {
        var app = this.readConfig('app');
        var manifestPath = joinPath(context.distDir, context.manifestPath);
        var manifest = readFileSync(manifestPath).toString().split("\n");
        var indexPath = joinPath(context.distDir, INDEX);
        var index = readFileSync(indexPath).toString();
        var uploadAssets = this._uploadAssets.bind(this, context.distDir);
        var didUploadAssets = this._didUploadAssets.bind(this);
        var uploadIndex = this._uploadIndex.bind(this, app, manifest, index);
        var didUploadIndex = this._didUploadIndex.bind(this);

        return this._createDifference(app, manifest)
          .then(uploadAssets)
          .then(didUploadAssets)
          .then(uploadIndex)
          .then(didUploadIndex);
      },

      _createDifference: function(app, manifest) {
        return this.api.createDifference(app, {
          manifest: manifest
        });
      },

      _uploadAssets: function(distDir, diff) {
        var uploads = diff.attributes.missing.map(function(asset) {
          return uploadAsset(distDir, asset);
        });

        return Promise.all(uploads);
      },

      _didUploadAssets: function(assets) {
        this.log('uploaded ' + assets.length + ' assets');
      },

      _uploadIndex: function(app, manifest, index) {
        var commit = fetchCommit();

        return this.api.createRelease(app, {
          index: index,
          commit_sha: commit.sha,
          commit_message: commit.message,
          manifest: manifest
        });
      },

      _didUploadIndex: function(release) {
        this.log('released v' + release.attributes.version);
      },

      _didActivate: function(version) {
        this.log('activated v' + version);
      }
    });

    return new Plugin();
  }
};
<commit_msg>add pagefrontapp url to output of successful deploy<commit_after>/* jshint node: true */
'use strict';

var PluginBase = require('ember-cli-deploy-plugin');
var Promise = require('ember-cli/lib/ext/promise');
var readFileSync = require('fs').readFileSync;
var joinPath = require('path').join;

var API = require('./lib/api');
var uploadAsset = require('./lib/upload-asset');
var fetchCommit = require('./lib/fetch-commit');
var findFile = require('./lib/find-file');

var PAGEFRONTRC = '.pagefrontrc';
var INDEX = 'index.html';

function mungeRelease(release) {
  return {
    revision: release.attributes.version,
    version: 'v' + release.attributes.version,
    timestamp: new Date(release.attributes.created_at).getTime(),
    active: false
  };
}

module.exports = {
  name: 'ember-cli-deploy-pagefront',

  createDeployPlugin: function(options) {
    var Plugin = PluginBase.extend({
      name: options.name,
      requiredConfig: ['app', 'key'],
      defaultConfig: {
        key: function() {
          var rawPagefrontrc = readFileSync(findFile(PAGEFRONTRC));

          return JSON.parse(rawPagefrontrc).key
        }
      },

      configure: function(context) {
        this._super.configure.call(this, context);
        this.api = new API(this.readConfig('key'));
      },

      fetchRevisions: function(context) {
        var app = this.readConfig('app');

        return this.api.listReleases(app).then(function(payload) {
          context.revisions = payload.map(mungeRelease);

          if (context.revisions.length) {
            context.revisions[0].active = true;
          }
        });
      },

      activate: function(context) {
        var app = this.readConfig('app');
        var revision = context.commandOptions.revision;
        var didActivate = this._didActivate.bind(this, revision);

        return this.api.createRelease(app, {
          release: revision
        }).then(didActivate);
      },

      upload: function(context) {
        var app = this.readConfig('app');
        var manifestPath = joinPath(context.distDir, context.manifestPath);
        var manifest = readFileSync(manifestPath).toString().split("\n");
        var indexPath = joinPath(context.distDir, INDEX);
        var index = readFileSync(indexPath).toString();
        var uploadAssets = this._uploadAssets.bind(this, context.distDir);
        var didUploadAssets = this._didUploadAssets.bind(this);
        var uploadIndex = this._uploadIndex.bind(this, app, manifest, index);
        var didUploadIndex = this._didUploadIndex.bind(this);

        return this._createDifference(app, manifest)
          .then(uploadAssets)
          .then(didUploadAssets)
          .then(uploadIndex)
          .then(didUploadIndex);
      },

      _createDifference: function(app, manifest) {
        return this.api.createDifference(app, {
          manifest: manifest
        });
      },

      _uploadAssets: function(distDir, diff) {
        var uploads = diff.attributes.missing.map(function(asset) {
          return uploadAsset(distDir, asset);
        });

        return Promise.all(uploads);
      },

      _didUploadAssets: function(assets) {
        this.log('uploaded ' + assets.length + ' assets');
      },

      _uploadIndex: function(app, manifest, index) {
        var commit = fetchCommit();

        return this.api.createRelease(app, {
          index: index,
          commit_sha: commit.sha,
          commit_message: commit.message,
          manifest: manifest
        });
      },

      _didUploadIndex: function(release) {
        var url = 'https://' + this.readConfig('app') + '.pagefrontapp.com';

        this.log('released v' + release.attributes.version + ' to ' + url);
      },

      _didActivate: function(version) {
        this.log('activated v' + version);
      }
    });

    return new Plugin();
  }
};
<|endoftext|>