text:
// Copyright (c) 2011-2012 Turbulenz Limited

/*global window*/
/*global Touch: false*/
/*global TouchEvent: false*/
/*global TurbulenzEngine: false*/

//
// WebGLInputDevice
//
class WebGLInputDevice implements InputDevice
{
    static version = 1;

    // We'd like to use { [key: string]: number }, but it doesn't
    // allow keyCodes.A, etc.  See comment in InputDevice decl.

    keyCodes                     : any; // prototype
    mouseCodes                   : any; // prototype
    padCodes                     : any; // prototype

    lastX                        : number;
    lastY                        : number;

    isMouseLocked                : boolean;
    isHovering                   : boolean;
    isWindowFocused              : boolean;
    isCursorHidden               : boolean;
    isOutsideEngine              : boolean;

    touches                      : any;

    boundFunctions               : any;
    elementEventFlags            : any;

    canvas                       : any;
    previousCursor               : string;
    ignoreNextMouseMoves         : number;
    ignoreNextBlur               : boolean;

    // Used to screen out auto-repeats, dictionary from keycode to
    // boolean, true for each key currently pressed down
    pressedKeys                  : any;

    keyMap                       : any;
    mouseMap                     : any; //{ 0: number; 1: number; 2: number; };

    padButtons                   : number[];
    padMap                       : any;
    padAxisDeadZone              : number;
    maxAxisRange                 : number;
    padTimestampUpdate           : number;

    keyCodeToUnicode             : any;

    private macosx               : boolean;
    private webkit               : boolean;

    private requestBrowserLock   : () => void;
    private requestBrowserUnlock : () => void;
    private onPointerLockChanged : () => void;
    private onPointerLockError   : () => void;
    private setEventHandlersPointerLock: () => void;
    private setEventHandlersPointerUnlock: () => void;

    // Game event handlers.  TODO: introduce types
    handlers:
    {
        keydown : any[];
        keyup : any[];

        mousedown : any[];
        mouseup : any[];
        mousewheel : any[];
        mouseover : any[];
        mousemove : any[];

        paddown : any[];
        padup : any[];
        padmove : any[];

        mouseenter : any[];
        mouseleave : any[];
        focus : any[];
        blur : any[];
        mouselocklost : any[];

        touchstart : any[];
        touchend : any[];
        touchenter : any[];
        touchleave : any[];
        touchmove : any[];
        touchcancel : any[];
    };

    // Public API

    update()
    {
        if (!this.isWindowFocused)
        {
            return;
        }

        this.updateGamePad();
    }

    addEventListener(eventType, eventListener)
    {
        var i;
        var length;
        var eventHandlers;

        if (this.handlers.hasOwnProperty(eventType))
        {
            eventHandlers = this.handlers[eventType];

            if (eventListener)
            {
                // Check handler is not already stored
                length = eventHandlers.length;
                for (i = 0; i < length; i += 1)
                {
                    if (eventHandlers[i] === eventListener)
                    {
                        // Event handler has already been added
                        return;
                    }
                }

                eventHandlers.push(eventListener);
            }
        }
    }

    removeEventListener(eventType, eventListener)
    {
        var i;
        var length;
        var eventHandlers;

        if (this.handlers.hasOwnProperty(eventType))
        {
            eventHandlers = this.handlers[eventType];

            if (eventListener)
            {
                length = eventHandlers.length;
                for (i = 0; i < length; i += 1)
                {
                    if (eventHandlers[i] === eventListener)
                    {
                        eventHandlers.splice(i, 1);
                        break;
                    }
                }
            }
        }
    }

    lockMouse()
    {
        if (this.isHovering &&
            this.isWindowFocused)
        {
            this.isMouseLocked = true;
            this.hideMouse();

            this.requestBrowserLock();

            this.setEventHandlersLock();

            return true;
        }
        else
        {
            return false;
        }
    }

    unlockMouse()
    {
        if (this.isMouseLocked)
        {
            this.isMouseLocked = false;
            this.showMouse();

            this.requestBrowserUnlock();

            this.setEventHandlersUnlock();

            if (this.isOutsideEngine)
            {
                this.isOutsideEngine = false;

                this.isHovering = false;

                this.setEventHandlersMouseLeave();

                // Send mouseout event
                this.sendEventToHandlers(this.handlers.mouseleave);
            }

            // Send mouselocklost event
            this.sendEventToHandlers(this.handlers.mouselocklost);

            return true;
        }
        else
        {
            return false;
        }
    }

    isLocked()
    {
        return this.isMouseLocked;
    }

    hideMouse()
    {
        if (this.isHovering)
        {
            if (!this.isCursorHidden)
            {
                this.isCursorHidden = true;
                this.previousCursor = document.body.style.cursor;
                document.body.style.cursor = 'none';
                if (this.webkit)
                {
                    this.ignoreNextMouseMoves = 2;
                }
            }

            return true;
        }
        else
        {
            return false;
        }
    }

    showMouse()
    {
        if (this.isCursorHidden &&
            !this.isMouseLocked)
        {
            this.isCursorHidden = false;
            document.body.style.cursor = this.previousCursor;
            return true;
        }
        else
        {
            return false;
        }
    }

    isHidden()
    {
        return this.isCursorHidden;
    }

    isFocused()
    {
        return this.isWindowFocused;
    }

    // Cannot convert keycodes to unicode in javascript so return empty strings
    convertToUnicode(keyCodeArray: number[]): { [code: number]: string }
    {
        var keyCodeToUnicode = this.keyCodeToUnicode;
        var result = {};
        var length = keyCodeArray.length;
        var i;
        var keyCode;

        for (i = 0; i < length; i += 1)
        {
            keyCode = keyCodeArray[i];
            result[keyCode] = keyCodeToUnicode[keyCode] || "";
        }

        return result;
    }

    // Private API

    sendEventToHandlers(eventHandlers, arg0?, arg1?, arg2?, arg3?, arg4?, arg5?)
    {
        var i;
        var length = eventHandlers.length;

        if (length)
        {
            for (i = 0; i < length; i += 1)
            {
                eventHandlers[i](arg0, arg1, arg2, arg3, arg4, arg5);
            }
        }
    }

    sendEventToHandlersASync(handlers, a0?, a1?, a2?, a3?, a4?, a5?)
    {
        var sendEvent = WebGLInputDevice.prototype.sendEventToHandlers;
        TurbulenzEngine.setTimeout(function callSendEventToHandlersFn() {
            sendEvent(handlers, a0, a1, a2, a3, a4, a5);
        }, 0);
    }

    updateGamePad()
    {
        var magnitude;
        var normalizedMagnitude;

        var gamepads = (navigator.gamepads ||
                        navigator.webkitGamepads ||
                        (navigator.getGamepads && navigator.getGamepads()) ||
                        (navigator.webkitGetGamepads && navigator.webkitGetGamepads()));

        if (gamepads)
        {
            var deadZone = this.padAxisDeadZone;
            var maxAxisRange = this.maxAxisRange;
            var sendEvent = this.sendEventToHandlersASync;
            var handlers = this.handlers;
            var padButtons = this.padButtons;
            var padMap = this.padMap;
            var leftThumbX = 0;
            var leftThumbY = 0;
            var rightThumbX = 0;
            var rightThumbY = 0;

            var numGamePads = gamepads.length;
            for (var i = 0; i < numGamePads; i += 1)
            {
                var gamepad = gamepads[i];
                if (gamepad)
                {
                    // Update button states

                    var buttons = gamepad.buttons;

                    if (this.padTimestampUpdate < gamepad.timestamp)
                    {
                        this.padTimestampUpdate = gamepad.timestamp;

                        var numButtons = buttons.length;
                        for (var n = 0; n < numButtons; n += 1)
                        {
                            var value = buttons[n];
                            if (typeof value === "object")
                            {
                                value = value.value;
                            }
                            if (padButtons[n] !== value)
                            {
                                padButtons[n] = value;

                                var padCode = padMap[n];
                                if (padCode !== undefined)
                                {
                                    if (value)
                                    {
                                        sendEvent(handlers.paddown, padCode);
                                    }
                                    else
                                    {
                                        sendEvent(handlers.padup, padCode);
                                    }
                                }
                            }
                        }
                    }

                    // Update axes states

                    var axes = gamepad.axes;
                    if (axes.length <= 4)
                    {
                        // Axis 1 & 2
                        var lX = axes[0];
                        var lY = -axes[1];
                        magnitude = ((lX * lX) + (lY * lY));

                        if (magnitude > (deadZone * deadZone))
                        {
                            magnitude = Math.sqrt(magnitude);

                            // Normalize lX and lY
                            lX = (lX / magnitude);
                            lY = (lY / magnitude);

                            // Clip the magnitude at its max possible value
                            if (magnitude > maxAxisRange)
                            {
                                magnitude = maxAxisRange;
                            }

                            // Adjust magnitude relative to the end of the dead zone
                            magnitude -= deadZone;

                            // Normalize the magnitude
                            normalizedMagnitude = (magnitude / (maxAxisRange - deadZone));

                            leftThumbX = (lX * normalizedMagnitude);
                            leftThumbY = (lY * normalizedMagnitude);
                        }

                        // Axis 3 & 4
                        var rX = axes[2];
                        var rY = -axes[3];
                        magnitude = ((rX * rX) + (rY * rY));

                        if (magnitude > (deadZone * deadZone))
                        {
                            magnitude = Math.sqrt(magnitude);

                            // Normalize lX and lY
                            rX = (rX / magnitude);
                            rY = (rY / magnitude);

                            // Clip the magnitude at its max possible value
                            if (magnitude > maxAxisRange)
                            {
                                magnitude = maxAxisRange;
                            }

                            // Adjust magnitude relative to the end of the dead zone
                            magnitude -= deadZone;

                            // Normalize the magnitude
                            normalizedMagnitude = (magnitude / (maxAxisRange - deadZone));

                            rightThumbX = (rX * normalizedMagnitude);
                            rightThumbY = (rY * normalizedMagnitude);
                        }

                        sendEvent(handlers.padmove,
                                  leftThumbX, leftThumbY, buttons[6],
                                  rightThumbX, rightThumbY, buttons[7]);
                    }

                    // Our API only supports one active pad...
                    break;
                }
            }
        }
    }

    // Cannot detect locale in canvas mode
    getLocale()
    {
        return "";
    }

    // Returns the local coordinates of the event (i.e. position in
    // Canvas coords)
    getCanvasPosition(event, position)
    {
        if (event.offsetX !== undefined)
        {
            position.x = event.offsetX;
            position.y = event.offsetY;
        }
        else if (event.layerX !== undefined)
        {
            position.x = event.layerX;
            position.y = event.layerY;
        }
    }

    // Called when blurring
    resetKeyStates()
    {
        var k;
        var pressedKeys = this.pressedKeys;
        var keyUpHandlers = this.handlers.keyup;

        for (k in pressedKeys)
        {
            if (pressedKeys.hasOwnProperty(k) && pressedKeys[k])
            {
                k = parseInt(k, 10);
                pressedKeys[k] = false;
                this.sendEventToHandlers(keyUpHandlers, k);
            }
        }
    }

    // Private mouse event methods

    onMouseOver(event)
    {
        var position :
        {
            x?: number;
            y?: number;
        } = {};
        var mouseOverHandlers = this.handlers.mouseover;

        event.stopPropagation();
        event.preventDefault();

        this.getCanvasPosition(event, position);

        this.lastX = event.screenX;
        this.lastY = event.screenY;

        this.sendEventToHandlers(mouseOverHandlers, position.x, position.y);
    }

    onMouseMove(event)
    {
        var mouseMoveHandlers = this.handlers.mousemove;

        var deltaX, deltaY;

        event.stopPropagation();
        event.preventDefault();

        if (this.ignoreNextMouseMoves)
        {
            this.ignoreNextMouseMoves -= 1;
            return;
        }

        if (event.movementX !== undefined)
        {
            deltaX = event.movementX;
            deltaY = event.movementY;
        }
        else if (event.mozMovementX !== undefined)
        {
            deltaX = event.mozMovementX;
            deltaY = event.mozMovementY;
        }
        else if (event.webkitMovementX !== undefined)
        {
            deltaX = event.webkitMovementX;
            deltaY = event.webkitMovementY;
        }
        else
        {
            deltaX = (event.screenX - this.lastX);
            deltaY = (event.screenY - this.lastY);
            if (0 === deltaX && 0 === deltaY)
            {
                return;
            }
        }

        this.lastX = event.screenX;
        this.lastY = event.screenY;

        this.sendEventToHandlers(mouseMoveHandlers, deltaX, deltaY);
    }

    onWheel(event)
    {
        var mouseWheelHandlers = this.handlers.mousewheel;

        var scrollDelta;

        event.stopPropagation();
        event.preventDefault();

        if (event.wheelDelta)
        {
            if (window.opera)
            {
                scrollDelta = event.wheelDelta < 0 ? 1 : -1;
            }
            else
            {
                scrollDelta = event.wheelDelta > 0 ? 1 : -1;
            }
        }
        else
        {
            scrollDelta = event.detail < 0 ? 1 : -1;
        }

        this.sendEventToHandlers(mouseWheelHandlers, scrollDelta);
    }

    emptyEvent(event)
    {
        event.stopPropagation();
        event.preventDefault();
    }

    onWindowFocus()
    {
        if (this.isHovering &&
            window.document.activeElement === this.canvas)
        {
            this.addInternalEventListener(window, 'mousedown', this.onMouseDown);
        }
    }

    onFocus()
    {
        var canvas = this.canvas;
        var handlers = this.handlers;
        var focusHandlers = handlers.focus;

        if (!this.isWindowFocused)
        {
            this.isWindowFocused = true;

            window.focus();
            canvas.focus();

            this.setEventHandlersFocus();

            canvas.oncontextmenu = function () {
                return false;
            };

            this.sendEventToHandlers(focusHandlers);
        }
    }

    onBlur()
    {
        if (this.ignoreNextBlur)
        {
            this.ignoreNextBlur = false;
            return;
        }

        var canvas = this.canvas;
        var handlers = this.handlers;
        var blurHandlers = handlers.blur;

        if (this.isMouseLocked)
        {
            this.unlockMouse();
        }

        if (this.isWindowFocused)
        {
            this.isWindowFocused = false;

            this.resetKeyStates();
            this.setEventHandlersBlur();
            canvas.oncontextmenu = null;

            this.sendEventToHandlers(blurHandlers);
        }
    }

    onMouseDown(event)
    {
        var handlers = this.handlers;

        if (this.isHovering)
        {
            var mouseDownHandlers = handlers.mousedown;
            var button = event.button;
            var position  :
            {
                x?: number;
                y?: number;
            }= {};

            this.onFocus();

            event.stopPropagation();
            event.preventDefault();

            if (button < 3)
            {
                button = this.mouseMap[button];
            }

            this.getCanvasPosition(event, position);

            this.sendEventToHandlers(mouseDownHandlers, button, position.x, position.y);
        }
        else
        {
            this.onBlur();
        }
    }

    onMouseUp(event)
    {
        var mouseUpHandlers = this.handlers.mouseup;

        if (this.isHovering)
        {
            var button = event.button;
            var position  :
            {
                x?: number;
                y?: number;
            } = {};

            event.stopPropagation();
            event.preventDefault();

            if (button < 3)
            {
                button = this.mouseMap[button];
            }

            this.getCanvasPosition(event, position);

            this.sendEventToHandlers(mouseUpHandlers, button, position.x, position.y);
        }
    }

    // Private key event methods

    onKeyDown(event)
    {
        var keyDownHandlers = this.handlers.keydown;
        var pressedKeys = this.pressedKeys;
        var keyCodes = this.keyCodes;

        event.stopPropagation();
        event.preventDefault();

        var keyCode = event.keyCode;
        keyCode = this.keyMap[keyCode];

        if (undefined !== keyCode &&
           (keyCodes.ESCAPE !== keyCode))
        {
            // Handle left / right key locations
            //   DOM_KEY_LOCATION_STANDARD = 0x00;
            //   DOM_KEY_LOCATION_LEFT     = 0x01;
            //   DOM_KEY_LOCATION_RIGHT    = 0x02;
            //   DOM_KEY_LOCATION_NUMPAD   = 0x03;
            //   DOM_KEY_LOCATION_MOBILE   = 0x04;
            //   DOM_KEY_LOCATION_JOYSTICK = 0x05;

            var keyLocation = (typeof event.location === "number" ? event.location : event.keyLocation);
            if (2 === keyLocation)
            {
                // The Turbulenz KeyCodes are such that CTRL, SHIFT
                // and ALT have their RIGHT versions exactly one above
                // the LEFT versions.
                keyCode = keyCode + 1;
            }
            if (!pressedKeys[keyCode])
            {
                pressedKeys[keyCode] = true;
                this.sendEventToHandlers(keyDownHandlers, keyCode);
            }
        }
    }

    onKeyUp(event)
    {
        var keyUpHandlers = this.handlers.keyup;
        var pressedKeys = this.pressedKeys;
        var keyCodes = this.keyCodes;

        event.stopPropagation();
        event.preventDefault();

        var keyCode = event.keyCode;
        keyCode = this.keyMap[keyCode];

        if (keyCode === keyCodes.ESCAPE)
        {
            this.unlockMouse();

            // Some apps environments will not exit fullscreen automatically on ESCAPE
            if (document.fullscreenElement ||
                document.webkitFullscreenElement ||
                document.mozFullScreenElement ||
                document.msFullscreenElement)
            {
                if (document.webkitCancelFullScreen)
                {
                    document.webkitCancelFullScreen();
                }
                else if (document.cancelFullScreen)
                {
                    document.cancelFullScreen();
                }
                else if (document['mozCancelFullScreen'])
                {
                    document['mozCancelFullScreen']();
                }
                else if (document.msExitFullscreen)
                {
                    document.msExitFullscreen();
                }
                else if (document.exitFullscreen)
                {
                    document.exitFullscreen();
                }
            }
        }
        else if (undefined !== keyCode)
        {
            // Handle LEFT / RIGHT.  (See OnKeyDown)

            var keyLocation = (typeof event.location === "number" ? event.location : event.keyLocation);
            if (2 === keyLocation)
            {
                keyCode = keyCode + 1;
            }
            if (pressedKeys[keyCode])
            {
                pressedKeys[keyCode] = false;
                this.sendEventToHandlers(keyUpHandlers, keyCode);

                // Nasty hack for mac to deal with the missing KeyUp
                // signals when CMD is released.  #1016.

                if ((627 === keyCode || 628 === keyCode) && (this.macosx))
                {
                    this.resetKeyStates();
                }
            }
        }
    }

    // Private touch event methods

    onTouchStart(event)
    {
        var eventHandlers = this.handlers.touchstart;

        event.preventDefault();

        // Store new touches
        this.addTouches(event.changedTouches);

        event = this.convertW3TouchEventToTurbulenzTouchEvent(event);

        this.sendEventToHandlers(eventHandlers, event);
    }

    onTouchEnd(event)
    {
        var eventHandlers = this.handlers.touchend;

        event.preventDefault();

        event = this.convertW3TouchEventToTurbulenzTouchEvent(event);

        // Remove ended touches
        this.removeTouches(event.changedTouches);

        this.sendEventToHandlers(eventHandlers, event);
    }

    onTouchMove(event)
    {
        var eventHandlers = this.handlers.touchmove;

        event.preventDefault();

        this.addTouches(event.changedTouches);

        event = this.convertW3TouchEventToTurbulenzTouchEvent(event);

        this.sendEventToHandlers(eventHandlers, event);
    }

    onTouchEnter(event)
    {
        var eventHandlers = this.handlers.touchenter;

        event.preventDefault();

        event = this.convertW3TouchEventToTurbulenzTouchEvent(event);

        this.sendEventToHandlers(eventHandlers, event);
    }

    onTouchLeave(event)
    {
        var eventHandlers = this.handlers.touchleave;

        event.preventDefault();

        event = this.convertW3TouchEventToTurbulenzTouchEvent(event);

        this.sendEventToHandlers(eventHandlers, event);
    }

    onTouchCancel(event)
    {
        var eventHandlers = this.handlers.touchcancel;

        event.preventDefault();

        event = this.convertW3TouchEventToTurbulenzTouchEvent(event);

        // Remove canceled touches
        this.removeTouches(event.changedTouches);

        this.sendEventToHandlers(eventHandlers, event);
    }

    convertW3TouchEventToTurbulenzTouchEvent(w3TouchEvent)
    {
        // Initialize changedTouches
        var changedTouches = this.convertW3TouchListToTurbulenzTouchList(w3TouchEvent.changedTouches);

        // Initialize gameTouches
        var gameTouches = this.convertW3TouchListToTurbulenzTouchList(w3TouchEvent.targetTouches);

        // Initialize touches
        var touches = this.convertW3TouchListToTurbulenzTouchList(w3TouchEvent.touches);

        var touchEventParams =
        {
            changedTouches  : changedTouches,
            gameTouches     : gameTouches,
            touches         : touches
        };

        return WebGLTouchEvent.create(touchEventParams);
    }

    convertW3TouchListToTurbulenzTouchList(w3TouchList)
    {
        // Set changedTouches
        var w3TouchListLength = w3TouchList.length;
        var touchList = [];

        var touch;
        var touchIndex;

        touchList.length = w3TouchListLength;

        for (touchIndex = 0; touchIndex < w3TouchListLength; touchIndex += 1)
        {
            touch = this.getTouchById(w3TouchList[touchIndex].identifier);
            touchList[touchIndex] = touch;
        }

        return touchList;
    }

    convertW3TouchToTurbulenzTouch(w3Touch)
    {
        var canvasElement   = this.canvas;
        var canvasRect      = canvasElement.getBoundingClientRect();

        var touchParams =
        {
            force           : (w3Touch.force || w3Touch.webkitForce || 0),
            identifier      : w3Touch.identifier,
            isGameTouch     : (w3Touch.target === canvasElement),
            positionX       : (w3Touch.pageX - canvasRect.left),
            positionY       : (w3Touch.pageY - canvasRect.top),
            radiusX         : (w3Touch.radiusX || w3Touch.webkitRadiusX || 1),
            radiusY         : (w3Touch.radiusY || w3Touch.webkitRadiusY || 1),
            rotationAngle   : (w3Touch.rotationAngle || w3Touch.webkitRotationAngle || 0)
        };

        return Touch.create(touchParams);
    }

    addTouches(w3TouchList)
    {
        var w3TouchListLength = w3TouchList.length;

        var touchIndex;
        var touch;

        for (touchIndex = 0; touchIndex < w3TouchListLength; touchIndex += 1)
        {
            touch = this.convertW3TouchToTurbulenzTouch(w3TouchList[touchIndex]);
            this.addTouch(touch);
        }
    }

    removeTouches(w3TouchList)
    {
        var w3TouchListLength = w3TouchList.length;

        var touchIndex;
        var touchId;

        for (touchIndex = 0; touchIndex < w3TouchListLength; touchIndex += 1)
        {
            touchId = w3TouchList[touchIndex].identifier;
            this.removeTouchById(touchId);
        }
    }

    addTouch(touch)
    {
        this.touches[touch.identifier] = touch;
    }

    getTouchById(id)
    {
        return this.touches[id];
    }

    removeTouchById(id)
    {
        delete this.touches[id];
    }

    // Canvas event handlers

    canvasOnMouseOver(event)
    {
        var mouseEnterHandlers = this.handlers.mouseenter;

        if (!this.isMouseLocked)
        {
            this.isHovering = true;

            this.lastX = event.screenX;
            this.lastY = event.screenY;

            this.setEventHandlersMouseEnter();

            // Send mouseover event
            this.sendEventToHandlers(mouseEnterHandlers);
        }
        else
        {
            this.isOutsideEngine = false;
        }
    }

    canvasOnMouseOut(/* event */)
    {
        var mouseLeaveHandlers = this.handlers.mouseleave;

        if (!this.isMouseLocked)
        {
            this.isHovering = false;

            if (this.isCursorHidden)
            {
                this.showMouse();
            }

            this.setEventHandlersMouseLeave();

            // Send mouseout event
            this.sendEventToHandlers(mouseLeaveHandlers);
        }
        else
        {
            this.isOutsideEngine = true;
        }
    }

    // This is required in order to detect hovering when we missed the
    // initial mouseover event
    canvasOnMouseDown(event)
    {
        var mouseEnterHandlers = this.handlers.mouseenter;

        this.canvas.onmousedown = null;

        if (!this.isHovering)
        {
            this.isHovering = true;

            this.lastX = event.screenX;
            this.lastY = event.screenY;

            this.setEventHandlersMouseEnter();

            this.sendEventToHandlers(mouseEnterHandlers);

            this.onMouseDown(event);
        }

        return false;
    }

    // Window event handlers

    onFullscreenChanged(/* event */)
    {
        if (this.isMouseLocked)
        {
            if (document.fullscreenElement ||
                document.webkitFullscreenElement ||
                document.mozFullScreenElement ||
                document.msFullscreenElement)
            {
                this.ignoreNextMouseMoves = 2; // Some browsers will send 2 mouse events with a massive delta
                this.requestBrowserLock();
            }
            else
            {
                // Browsers capture the escape key whilst in fullscreen
                this.unlockMouse();
            }
        }
    }

    // Set event handler methods

    setEventHandlersMouseEnter()
    {
        // Add event listener to get focus event
        if (!this.isFocused())
        {
            this.addInternalEventListener(window, 'mousedown', this.onMouseDown);
        }

        this.addInternalEventListener(window, 'mouseup', this.onMouseUp);
        this.addInternalEventListener(window, 'mousemove', this.onMouseOver);
        this.addInternalEventListener(window, 'DOMMouseScroll', this.onWheel);
        this.addInternalEventListener(window, 'mousewheel', this.onWheel);
        this.addInternalEventListener(window, 'click', this.emptyEvent);
    }

    setEventHandlersMouseLeave()
    {
        // We do not need a mousedown listener if not focused
        if (!this.isFocused())
        {
            this.removeInternalEventListener(window, 'mousedown', this.onMouseDown);
        }

        // Remove mouse event listeners
        this.removeInternalEventListener(window, 'mouseup', this.onMouseUp);
        this.removeInternalEventListener(window, 'mousemove', this.onMouseOver);
        this.removeInternalEventListener(window, 'DOMMouseScroll', this.onWheel);
        this.removeInternalEventListener(window, 'mousewheel', this.onWheel);
        this.removeInternalEventListener(window, 'click', this.emptyEvent);
    }

    setEventHandlersFocus()
    {
        this.addInternalEventListener(window, 'keydown', this.onKeyDown);
        this.addInternalEventListener(window, 'keyup', this.onKeyUp);
    }

    setEventHandlersBlur()
    {
        this.removeInternalEventListener(window, 'keydown', this.onKeyDown);
        this.removeInternalEventListener(window, 'keyup', this.onKeyUp);
        this.removeInternalEventListener(window, 'mousedown', this.onMouseDown);
    }

    setEventHandlersLock()
    {
        this.removeInternalEventListener(window, 'mousemove', this.onMouseOver);

        this.addInternalEventListener(window, 'mousemove', this.onMouseMove);

        this.addInternalEventListener(document, 'fullscreenchange', this.onFullscreenChanged);
        this.addInternalEventListener(document, 'mozfullscreenchange', this.onFullscreenChanged);
        this.addInternalEventListener(document, 'webkitfullscreenchange', this.onFullscreenChanged);
        this.addInternalEventListener(document, 'MSFullscreenChange', this.onFullscreenChanged);
    }

    setEventHandlersUnlock()
    {
        this.removeInternalEventListener(document, 'webkitfullscreenchange', this.onFullscreenChanged);
        this.removeInternalEventListener(document, 'mozfullscreenchange', this.onFullscreenChanged);
        this.removeInternalEventListener(document, 'MSFullscreenChange', this.onFullscreenChanged);

        this.removeInternalEventListener(window, 'mousemove', this.onMouseMove);

        this.addInternalEventListener(window, 'mousemove', this.onMouseOver);
    }

    setEventHandlersCanvas()
    {
        var canvas = this.canvas;

        this.addInternalEventListener(canvas, 'mouseover', this.canvasOnMouseOver);
        this.addInternalEventListener(canvas, 'mouseout', this.canvasOnMouseOut);
        this.addInternalEventListener(canvas, 'mousedown', this.canvasOnMouseDown);
    }

    setEventHandlersWindow()
    {
        this.addInternalEventListener(window, 'blur', this.onBlur);
        this.addInternalEventListener(window, 'focus', this.onWindowFocus);
    }

    removeEventHandlersWindow()
    {
        this.removeInternalEventListener(window, 'blur', this.onBlur);
        this.removeInternalEventListener(window, 'focus', this.onWindowFocus);
    }

    setEventHandlersTouch()
    {
        var canvas = this.canvas;

        this.addInternalEventListener(canvas, 'touchstart', this.onTouchStart);
        this.addInternalEventListener(canvas, 'touchend', this.onTouchEnd);
        this.addInternalEventListener(canvas, 'touchenter', this.onTouchEnter);
        this.addInternalEventListener(canvas, 'touchleave', this.onTouchLeave);
        this.addInternalEventListener(canvas, 'touchmove', this.onTouchMove);
        this.addInternalEventListener(canvas, 'touchcancel', this.onTouchCancel);
    }

    // Helper methods

    addInternalEventListener(element, eventName, eventHandler)
    {
        var elementEventFlag = this.elementEventFlags[element];
        if (!elementEventFlag)
        {
            this.elementEventFlags[element] = elementEventFlag = {};
        }

        if (!elementEventFlag[eventName])
        {
            elementEventFlag[eventName] = true;

            var boundEventHandler = this.boundFunctions[eventHandler];
            if (!boundEventHandler)
            {
                this.boundFunctions[eventHandler] = boundEventHandler = eventHandler.bind(this);
            }

            element.addEventListener(eventName, boundEventHandler, false);
        }
    }

    removeInternalEventListener(element, eventName, eventHandler)
    {
        var elementEventFlag = this.elementEventFlags[element];
        if (elementEventFlag)
        {
            if (elementEventFlag[eventName])
            {
                elementEventFlag[eventName] = false;

                var boundEventHandler = this.boundFunctions[eventHandler];

                element.removeEventListener(eventName, boundEventHandler, false);
            }
        }
    }

    destroy()
    {
        // Remove all event listeners
        if (this.isLocked())
        {
            this.setEventHandlersUnlock();
        }

        if (this.isHovering)
        {
            this.setEventHandlersMouseLeave();
        }

        if (this.isWindowFocused)
        {
            this.setEventHandlersBlur();
        }

        this.removeEventHandlersWindow();

        var canvas = this.canvas;
        canvas.onmouseover = null;
        canvas.onmouseout = null;
        canvas.onmousedown = null;
    }

    isSupported(name)
    {
        var canvas = this.canvas;

        if ((canvas) && (name === "POINTER_LOCK"))
        {
            var havePointerLock = ('pointerLockElement' in document) ||
                                  ('mozPointerLockElement' in document) ||
                                  ('webkitPointerLockElement' in document);

            var requestPointerLock = (canvas.requestPointerLock ||
                                      canvas.mozRequestPointerLock ||
                                      canvas.webkitRequestPointerLock);

            if (havePointerLock && requestPointerLock)
            {
                return true;
            }
        }

        return false;
    }

    static create(canvas: any /*, params: any */)
    {
        var id = new WebGLInputDevice();

        id.lastX = 0;
        id.lastY = 0;

        id.touches = {};

        id.boundFunctions = {};
        id.elementEventFlags = {};

        id.canvas = canvas;
        id.isMouseLocked = false;
        id.isHovering = false;
        id.isWindowFocused = false;
        id.isCursorHidden = false;
        id.isOutsideEngine = false; // Used for determining where we are when unlocking
        id.previousCursor = '';
        id.ignoreNextMouseMoves = 0;
        id.ignoreNextBlur = false;

        // Used to screen out auto-repeats, dictionary from keycode to boolean,
        // true for each key currently pressed down
        id.pressedKeys = {};

        // Game event handlers
        id.handlers =
            {
                keydown : [],
                keyup : [],

                mousedown : [],
                mouseup : [],
                mousewheel : [],
                mouseover : [],
                mousemove : [],

                paddown : [],
                padup : [],
                padmove : [],

                mouseenter : [],
                mouseleave : [],
                focus : [],
                blur : [],
                mouselocklost : [],

                touchstart : [],
                touchend : [],
                touchenter : [],
                touchleave : [],
                touchmove : [],
                touchcancel : []
            };

        // Populate the keyCodeToUnicodeTable.  Just use the 'key' part of
        // the keycodes, overriding some special cases.

        var keyCodeToUnicodeTable = {};
        var keyCodes = id.keyCodes;
        for (var k in keyCodes)
        {
            if (keyCodes.hasOwnProperty(k))
            {
                var code = keyCodes[k];
                keyCodeToUnicodeTable[code] = k;
            }
        }
        keyCodeToUnicodeTable[keyCodes.SPACE] = ' ';
        keyCodeToUnicodeTable[keyCodes.NUMBER_0] = '0';
        keyCodeToUnicodeTable[keyCodes.NUMBER_1] = '1';
        keyCodeToUnicodeTable[keyCodes.NUMBER_2] = '2';
        keyCodeToUnicodeTable[keyCodes.NUMBER_3] = '3';
        keyCodeToUnicodeTable[keyCodes.NUMBER_4] = '4';
        keyCodeToUnicodeTable[keyCodes.NUMBER_5] = '5';
        keyCodeToUnicodeTable[keyCodes.NUMBER_6] = '6';
        keyCodeToUnicodeTable[keyCodes.NUMBER_7] = '7';
        keyCodeToUnicodeTable[keyCodes.NUMBER_8] = '8';
        keyCodeToUnicodeTable[keyCodes.NUMBER_9] = '9';
        keyCodeToUnicodeTable[keyCodes.GRAVE] = '`';
        keyCodeToUnicodeTable[keyCodes.MINUS] = '-';
        keyCodeToUnicodeTable[keyCodes.EQUALS] = '=';
        keyCodeToUnicodeTable[keyCodes.LEFT_BRACKET] = '[';
        keyCodeToUnicodeTable[keyCodes.RIGHT_BRACKET] = ']';
        keyCodeToUnicodeTable[keyCodes.SEMI_COLON] = ';';
        keyCodeToUnicodeTable[keyCodes.APOSTROPHE] = "'";
        keyCodeToUnicodeTable[keyCodes.COMMA] = ',';
        keyCodeToUnicodeTable[keyCodes.PERIOD] = '.';
        keyCodeToUnicodeTable[keyCodes.SLASH] = '/';
        keyCodeToUnicodeTable[keyCodes.BACKSLASH] = '\\';

        // KeyMap: Maps JavaScript keycodes to Turbulenz keycodes - some
        // keycodes are consistent across all browsers and some mappings
        // are browser specific.
        var keyMap = {};

        // A-Z
        keyMap[65] = 0; // A
        keyMap[66] = 1; // B
        keyMap[67] = 2; // C
        keyMap[68] = 3; // D
        keyMap[69] = 4; // E
        keyMap[70] = 5; // F
        keyMap[71] = 6; // G
        keyMap[72] = 7; // H
        keyMap[73] = 8; // I
        keyMap[74] = 9; // J
        keyMap[75] = 10; // K
        keyMap[76] = 11; // L
        keyMap[77] = 12; // M
        keyMap[78] = 13; // N
        keyMap[79] = 14; // O
        keyMap[80] = 15; // P
        keyMap[81] = 16; // Q
        keyMap[82] = 17; // R
        keyMap[83] = 18; // S
        keyMap[84] = 19; // T
        keyMap[85] = 20; // U
        keyMap[86] = 21; // V
        keyMap[87] = 22; // X
        keyMap[88] = 23; // W
        keyMap[89] = 24; // Y
        keyMap[90] = 25; // Z

        // 0-9
        keyMap[48] = 100; // 0
        keyMap[49] = 101; // 1
        keyMap[50] = 102; // 2
        keyMap[51] = 103; // 3
        keyMap[52] = 104; // 4
        keyMap[53] = 105; // 5
        keyMap[54] = 106; // 6
        keyMap[55] = 107; // 7
        keyMap[56] = 108; // 8
        keyMap[57] = 109; // 9

        // Arrow keys
        keyMap[37] = 200; // LEFT
        keyMap[39] = 201; // RIGHT
        keyMap[38] = 202; // UP
        keyMap[40] = 203; // DOWN

        // Modifier keys
        keyMap[16] = 300; // LEFT_SHIFT
        //keyMap[16] = 301; // RIGHT_SHIFT
        keyMap[17] = 302; // LEFT_CONTROL
        //keyMap[17] = 303; // RIGHT_CONTROL
        keyMap[18] = 304; // LEFT_ALT
        keyMap[0] = 305; // RIGHT_ALT

        // Special keys
        keyMap[27] = 400; // ESCAPE
        keyMap[9] = 401; // TAB
        keyMap[32] = 402; // SPACE
        keyMap[8] = 403; // BACKSPACE
        keyMap[13] = 404; // RETURN

        // Punctuation keys
        keyMap[223] = 500; // GRAVE
        keyMap[173] = 501; // MINUS (mozilla - gecko)
        keyMap[189] = 501; // MINUS (ie + webkit)
        keyMap[61] = 502; // EQUALS (mozilla - gecko)
        keyMap[187] = 502; // EQUALS (ie + webkit)
        keyMap[219] = 503; // LEFT_BRACKET
        keyMap[221] = 504; // RIGHT_BRACKET
        keyMap[59] = 505; // SEMI_COLON (mozilla - gecko)
        keyMap[186] = 505; // SEMI_COLON (ie + webkit)
        keyMap[192] = 500; // GRAVE
        keyMap[188] = 507; // COMMA
        keyMap[190] = 508; // PERIOD
        keyMap[222] = 506; // APOSTROPHE

        // if Mac OS GRAVE can sometimes come through as 0
        if (navigator.appVersion.indexOf("Mac") !== -1)
        {
            keyMap[0] = 500; // GRAVE (mac gecko + safari 5.1)
        }

        // Non-standard keys
        keyMap[112] = 600; // F1
        keyMap[113] = 601; // F2
        keyMap[114] = 602; // F3
        keyMap[115] = 603; // F4
        keyMap[116] = 604; // F5
        keyMap[117] = 605; // F6
        keyMap[118] = 606; // F7
        keyMap[119] = 607; // F8
        keyMap[120] = 608; // F9
        keyMap[121] = 609; // F10
        keyMap[122] = 610; // F11
        keyMap[123] = 611; // F12
        //keyMap[45 : 612, // NUMPAD_0 (numlock on/off)
        keyMap[96] = 612; // NUMPAD_0 (numlock on/off)
        //keyMap[35] = 613;, // NUMPAD_1 (numlock on/off)
        keyMap[97] = 613; // NUMPAD_1 (numlock on/off)
        //keyMap[40] = 614; // NUMPAD_2 (numlock on/off)
        keyMap[98] = 614; // NUMPAD_2 (numlock on/off)
        //keyMap[34] = 615; // NUMPAD_3 (numlock on/off)
        keyMap[99] = 615; // NUMPAD_3 (numlock on/off)
        //keyMap[37] = 616;, // NUMPAD_4 (numlock on/off)
        keyMap[100] = 616; // NUMPAD_4 (numlock on/off)
        keyMap[12] = 617; // NUMPAD_5 (numlock on/off)
        keyMap[101] = 617; // NUMPAD_5 (numlock on/off)
        keyMap[144] = 617; // NUMPAD_5 (numlock on/off) and NUMPAD_NUM
        //keyMap[39] = 618; // NUMPAD_6 (numlock on/off)
        keyMap[102] = 618; // NUMPAD_6 (numlock on/off)
        //keyMap[36] = 619; // NUMPAD_7 (numlock on/off)
        keyMap[103] = 619; // NUMPAD_7 (numlock on/off)
        //keyMap[38] = 620; // NUMPAD_8 (numlock on/off)
        keyMap[104] = 620; // NUMPAD_8 (numlock on/off)
        //keyMap[33] = 621; // NUMPAD_9 (numlock on/off)
        keyMap[105] = 621; // NUMPAD_9 (numlock on/off)
        //keyMap[13] = 622; // NUMPAD_ENTER (numlock on/off)
        keyMap[111] = 623; // NUMPAD_DIVIDE (numlock on/off)
        keyMap[191] = 623; // NUMPAD_DIVIDE (numlock on/off), mac chrome
        keyMap[106] = 624; // NUMPAD_MULTIPLY (numlock on/off)
        keyMap[107] = 625; // NUMPAD_ADD (numlock on/off)
        keyMap[109] = 626; // NUMPAD_SUBTRACT (numlock on/off)
        keyMap[91] = 627; // LEFT_WIN
        keyMap[224] = 627; // LEFT_WIN (mac, firefox)
        keyMap[92] = 628; // RIGHT_WIN
        keyMap[93] = 628; // RIGHT_WIN (mac, chrome)
        //: 629, // LEFT_OPTION
        //: 630, // RIGHT_OPTION
        keyMap[20] = 631; // CAPS_LOCK
        keyMap[45] = 632; // INSERT
        keyMap[46] = 633; // DELETE
        keyMap[36] = 634; // HOME
        keyMap[35] = 635; // END
        keyMap[33] = 636; // PAGE_UP
        keyMap[34] = 637; // PAGE_DOWN

        id.keyMap = keyMap;

        // MouseMap: Maps current mouse controls to new controls
        var mouseMap =
            {
                0 : 0,
                1 : 2,
                2 : 1
            };

        id.mouseMap = mouseMap;

        // padMap: Maps current pad buttons to new buttons
        var padMap =
            {
                0 : 4, // A
                1 : 5, // B
                2 : 6, // X
                3 : 7, // Y

                4 : 10, // LEFT_SHOULDER
                5 : 11, // RIGHT_SHOULDER

                8 : 19, // BACK
                9 : 18, // START

                10 : 12, // LEFT_THUMB
                11 : 15, // RIGHT_THUMB

                12 : 0, // UP
                13 : 2, // DOWN
                14 : 1, // LEFT
                15 : 3  // RIGHT
            };

        id.padMap = padMap;

        id.keyCodeToUnicode = keyCodeToUnicodeTable;

        id.padButtons = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        id.padMap = padMap;
        id.padAxisDeadZone = 0.26;
        id.maxAxisRange = 1.0;
        id.padTimestampUpdate = 0;

        // Pointer locking
        var requestPointerLock = (canvas.requestPointerLock    ||
                                  canvas.mozRequestPointerLock ||
                                  canvas.webkitRequestPointerLock);
        if (requestPointerLock)
        {
            var exitPointerLock = (document.exitPointerLock    ||
                                   document.mozExitPointerLock ||
                                   document.webkitExitPointerLock);

            id.onPointerLockChanged = function onPointerLockChangedFn(/* event */)
            {
                var pointerLockElement = (document.pointerLockElement    ||
                                          document.mozPointerLockElement ||
                                          document.webkitPointerLockElement);
                if (pointerLockElement !== id.canvas)
                {
                    id.unlockMouse();
                }
            };

            id.onPointerLockError = function onPointerLockErrorFn(/* event */)
            {
                id.unlockMouse();
            };

            // We need to set pointerlockchanged events because browsers consume the ESCAPE key without notification
            if ('mozPointerLockElement' in document)
            {
                id.setEventHandlersPointerLock = function setEventHandlersPointerLockFn()
                {
                    // firefox changes focus when requesting lock...
                    this.ignoreNextBlur = true;
                    document.addEventListener('mozpointerlockchange', this.onPointerLockChanged, false);
                    document.addEventListener('mozpointerlockerror', this.onPointerLockError, false);
                };

                id.setEventHandlersPointerUnlock = function setEventHandlersPointerUnlockFn()
                {
                    this.ignoreNextBlur = false;
                    document.removeEventListener('mozpointerlockchange', this.onPointerLockChanged, false);
                    document.removeEventListener('mozpointerlockerror', this.onPointerLockError, false);
                };
            }
            else if ('webkitPointerLockElement' in document)
            {
                id.setEventHandlersPointerLock = function setEventHandlersPointerLockFn()
                {
                    document.addEventListener('webkitpointerlockchange', this.onPointerLockChanged, false);
                    document.addEventListener('webkitpointerlockerror', this.onPointerLockError, false);
                };

                id.setEventHandlersPointerUnlock = function setEventHandlersPointerUnlockFn()
                {
                    document.removeEventListener('webkitpointerlockchange', this.onPointerLockChanged, false);
                    document.removeEventListener('webkitpointerlockerror', this.onPointerLockError, false);
                };
            }
            else if ('pointerLockElement' in document)
            {
                id.setEventHandlersPointerLock = function setEventHandlersPointerLockFn()
                {
                    document.addEventListener('pointerlockchange', this.onPointerLockChanged, false);
                    document.addEventListener('pointerlockerror', this.onPointerLockError, false);
                };

                id.setEventHandlersPointerUnlock = function setEventHandlersPointerUnlockFn()
                {
                    document.removeEventListener('pointerlockchange', this.onPointerLockChanged, false);
                    document.removeEventListener('pointerlockerror', this.onPointerLockError, false);
                };
            }

            id.requestBrowserLock = function requestBrowserLockFn()
            {
                var pointerLockElement = (document.pointerLockElement    ||
                                          document.mozPointerLockElement ||
                                          document.webkitPointerLockElement);
                if (pointerLockElement !== canvas)
                {
                    this.setEventHandlersPointerLock();

                    requestPointerLock.call(canvas);
                }
            };

            id.requestBrowserUnlock = function requestBrowserUnlockFn()
            {
                this.setEventHandlersPointerUnlock();

                var pointerLockElement = (document.pointerLockElement    ||
                                          document.mozPointerLockElement ||
                                          document.webkitPointerLockElement);
                if (pointerLockElement === canvas)
                {
                    exitPointerLock.call(document);
                }
            };
        }
        else
        {
            var pointer = (navigator.pointer || navigator.webkitPointer);
            if (pointer)
            {
                id.requestBrowserLock = function requestBrowserLockFn()
                {
                    if (!pointer.isLocked)
                    {
                        pointer.lock(canvas);
                    }
                };

                id.requestBrowserUnlock = function requestBrowserUnlockFn()
                {
                    if (pointer.isLocked)
                    {
                        pointer.unlock();
                    }
                };
            }
            else
            {
                id.requestBrowserLock = function requestBrowserLockFn() {};
                id.requestBrowserUnlock = function requestBrowserUnlockFn() {};
            }
        }

        // Add canvas mouse event listeners
        id.setEventHandlersCanvas();

        // Add window blur event listener
        id.setEventHandlersWindow();

        // Add canvas touch event listeners
        id.setEventHandlersTouch();

        // Record the platforms so that we can enable workarounds, etc.
        var sysInfo = TurbulenzEngine.getSystemInfo();
        id.macosx = ("Darwin" === sysInfo.osName);
        id.webkit = (/WebKit/.test(navigator.userAgent));

        return id;
    }
}

// KeyCodes: List of key codes and their values

WebGLInputDevice.prototype.keyCodes = {
    A : 0,
    B : 1,
    C : 2,
    D : 3,
    E : 4,
    F : 5,
    G : 6,
    H : 7,
    I : 8,
    J : 9,
    K : 10,
    L : 11,
    M : 12,
    N : 13,
    O : 14,
    P : 15,
    Q : 16,
    R : 17,
    S : 18,
    T : 19,
    U : 20,
    V : 21,
    W : 22,
    X : 23,
    Y : 24,
    Z : 25,
    NUMBER_0 : 100,
    NUMBER_1 : 101,
    NUMBER_2 : 102,
    NUMBER_3 : 103,
    NUMBER_4 : 104,
    NUMBER_5 : 105,
    NUMBER_6 : 106,
    NUMBER_7 : 107,
    NUMBER_8 : 108,
    NUMBER_9 : 109,
    LEFT : 200,
    RIGHT : 201,
    UP : 202,
    DOWN : 203,
    LEFT_SHIFT : 300,
    RIGHT_SHIFT : 301,
    LEFT_CONTROL : 302,
    RIGHT_CONTROL : 303,
    LEFT_ALT : 304,
    RIGHT_ALT : 305,
    ESCAPE : 400,
    TAB : 401,
    SPACE :    402,
    BACKSPACE : 403,
    RETURN : 404,
    GRAVE : 500,
    MINUS : 501,
    EQUALS : 502,
    LEFT_BRACKET : 503,
    RIGHT_BRACKET : 504,
    SEMI_COLON : 505,
    APOSTROPHE : 506,
    COMMA : 507,
    PERIOD : 508,
    SLASH: 509,
    BACKSLASH: 510,
    F1 : 600,
    F2 : 601,
    F3 : 602,
    F4 : 603,
    F5 : 604,
    F6 : 605,
    F7 : 606,
    F8 : 607,
    F9 : 608,
    F10 : 609,
    F11 : 610,
    F12 : 611,
    NUMPAD_0 : 612,
    NUMPAD_1 : 613,
    NUMPAD_2 : 614,
    NUMPAD_3 : 615,
    NUMPAD_4 : 616,
    NUMPAD_5 : 617,
    NUMPAD_6 : 618,
    NUMPAD_7 : 619,
    NUMPAD_8 : 620,
    NUMPAD_9 : 621,
    NUMPAD_ENTER : 622,
    NUMPAD_DIVIDE : 623,
    NUMPAD_MULTIPLY : 624,
    NUMPAD_ADD : 625,
    NUMPAD_SUBTRACT : 626,
    LEFT_WIN : 627,
    RIGHT_WIN : 628,
    LEFT_OPTION : 629,
    RIGHT_OPTION : 630,
    CAPS_LOCK : 631,
    INSERT : 632,
    DELETE : 633,
    HOME : 634,
    END : 635,
    PAGE_UP: 636,
    PAGE_DOWN: 637,
    BACK: 638
};

WebGLInputDevice.prototype.mouseCodes = {
    BUTTON_0 : 0,
    BUTTON_1 : 1,
    BUTTON_2 : 2,
    DELTA_X : 100,
    DELTA_Y : 101,
    MOUSE_WHEEL : 102
};

WebGLInputDevice.prototype.padCodes = {
    UP : 0,
    LEFT : 1,
    DOWN : 2,
    RIGHT : 3,
    A : 4,
    B : 5,
    X : 6,
    Y : 7,
    LEFT_TRIGGER : 8,
    RIGHT_TRIGGER : 9,
    LEFT_SHOULDER : 10,
    RIGHT_SHOULDER : 11,
    LEFT_THUMB : 12,
    LEFT_THUMB_X : 13,
    LEFT_THUMB_Y : 14,
    RIGHT_THUMB : 15,
    RIGHT_THUMB_X : 16,
    RIGHT_THUMB_Y : 17,
    START : 18,
    BACK : 19
};


text:
package org.aspenos.util.ats;

import java.util.*;
import java.io.*;

import org.aspenos.util.*;
import org.aspenos.mail.*;
import org.aspenos.mail.exception.*;
import org.aspenos.logging.*;

/**
 *
 */
public class SendMail extends Task {

	public void handleTask() {

		logDebugMsg("(Task)SendMail: starting");

		String mt_path = getString("mt_path");
		String jar_path = getString("jar_path");
		String rich_text = getString("rich_text");

		TemplateLoader tl = null;
		MailTemplate mt = null;

		if (jar_path == null) {
			tl = new TemplateLoader();
			tl.useJar(false);
		} else {
			tl = new TemplateLoader(jar_path);
			tl.useJar(true);
		}

		if (mt_path == null) {
			logErr("(Task)SendMail: mt_path not specified, can't send!");
			return;
		}

		LoggerWrapper lw = getLogger();
		if (lw == null)
			mt = new MailTemplate(tl);
		else
			mt = new MailTemplate(tl, lw);

		logDebugMsg("(Task)SendMail: loading template from: " + mt_path);
		mt.loadDirect(mt_path);

		mt.setTagTable(getProperties());

		// send the mail template
		try {
			logDebugMsg("(Task)SendMail: sending message");
			if (rich_text != null && rich_text.equals("true"))
				mt.send(true);
			else
				mt.send(false);
		} catch (MailerException mex) {
			logErr("(Task)SendMail: Cannot send: ", mex);
		}
	}
}

redpajama_set_name: RedPajamaGithub


text:
[![GoDoc](https://godoc.org/github.com/anacrolix/utp?status.svg)](https://godoc.org/github.com/anacrolix/utp)

Package utp implements uTP, the micro transport protocol as used with Bittorrent. It opts for simplicity and reliability over strict adherence to the (poor) spec.

## Supported

 * Multiple uTP connections switched on a single PacketConn, including those initiated locally.
 * Raw access to the PacketConn for non-uTP purposes, like sharing the PacketConn with a DHT implementation.

## Implementation characteristics

 * Receive window size is used to limit out of order packets received.
 * There is no MTU path discovery. The minimum size is always used.
 * A fixed 64 slot selective ack window is used in both sending and receiving.
 * All received non-ACK packets are ACKed in response.

Patches welcomed.


text:
// Generated by CoffeeScript 1.6.3
/*!
@author Branko Vukelic <branko@brankovukelic.com>
@license MIT
*/

var define;

define = (function(root) {
  var require,
    _this = this;
  if (typeof root.define === 'function' && root.define.amd) {
    return root.define;
  } else {
    require = function(dep) {
      return (function() {
        switch (dep) {
          case 'ribcage/views/template':
            return root.ribcage.views.templateView;
          default:
            return null;
        }
      })() || (function() {
        throw new Error("Unmet dependency " + dep);
      })();
    };
    return function(factory) {
      var module;
      module = factory(require);
      root.ribcage.views.tabbedView = module;
      root.ribcage.views.TabbedView = module.View;
      return root.ribcage.viewMixins.TabbedView = module.mixin;
    };
  }
})(this);

define(function(require) {
  var TabbedView, TemplateView, tabbedViewMixin;
  TemplateView = require('ribcage/views/template').View;
  tabbedViewMixin = {
    MAIN_TEMPLATE: "
TABS
\n
TCONTENTS
",
    TAB_TEMPLATE: "
\nLABEL\n
",
    CONTENT_TEMPLATE: "
\nPLACEHOLDER\n
",
    tabs: [],
    views: {},
    contentPlaceholder: '',
    getContentPlaceholder: function() {
      return this.contentPlaceholder;
    },
    initialize: function(settings) {
      if (settings != null ? settings.views : void 0) {
        return this.views = settings.views;
      }
    },
    template: function() {
      var contents, navs, tab;
      navs = ((function() {
        var _i, _len, _ref, _results;
        _ref = this.tabs;
        _results = [];
        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
          tab = _ref[_i];
          _results.push(this.TAB_TEMPLATE.replace(/ID/g, tab.id).replace('LABEL', tab.label));
        }
        return _results;
      }).call(this)).join('');
      contents = ((function() {
        var _i, _len, _ref, _results;
        _ref = this.tabs;
        _results = [];
        for (_i = 0, _len = _ref.length; _i < _len; _i++) {
          tab = _ref[_i];
          _results.push(this.CONTENT_TEMPLATE.replace('ID', tab.id).replace('PLACEHOLDER', this.getContentPlaceholder()));
        }
        return _results;
      }).call(this)).join('');
      return this.MAIN_TEMPLATE.replace('TABS', navs).replace('TCONTENTS', contents);
    },
    afterRender: function() {
      var idx, tab, _i, _len, _ref, _ref1;
      _ref = this.tabs;
      for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) {
        tab = _ref[idx];
        tab.nav = this.$el.find('#' + tab.id + '_tab');
        tab.container = this.$el.find('#' + tab.id);
        if (idx === 0) {
          tab.nav.addClass('active');
          tab.container.show();
        } else {
          tab.nav.removeClass('active');
          tab.container.hide();
        }
        if ((_ref1 = this.view) != null ? _ref1[tab.id] : void 0) {
          this.views[tab.id].render().$el.appendTo(tab.container);
        }
        tab.nav.data('meta', tab);
      }
      this.tabnavContents = this.$('div.tabnav-content');
      this.tabnavTabsLi = this.$('li.tabnav-tab');
      return this.tabnavTabs = this.$('li.tabnav-tab a');
    },
    onTabClick: function(e) {
      var clickTarget, nav, tab;
      this.tabnavTabsLi.removeClass('active');
      this.tabnavContents.hide();
      clickTarget = this.$(e.target);
      if (clickTarget.hasClass('tabnav-tab')) {
        nav = clickTarget;
      } else {
        nav = clickTarget.parents('.tabnav-tab');
      }
      tab = nav.data('meta');
      nav.addClass('active');
      tab.container.show();
      if (typeof tab.show === 'function') {
        return tab.show(tab);
      }
    },
    events: {
      'click .tabnav-tab': 'onTabClick'
    }
  };
  TabbedView = TemplateView.extend(tabbedViewMixin);
  return {
    mixin: tabbedViewMixin,
    View: TabbedView
  };
});


text:
namespace chromeos {

namespace {

// Resource ID of the image to use as stub image.
const int kStubImageResourceID = IDR_PROFILE_PICTURE_LOADING;

// Returns account name portion of an email.
std::string GetUserName(const std::string& email) {
  std::string::size_type i = email.find('@');
  if (i == 0 || i == std::string::npos) {
    return email;
  }
  return email.substr(0, i);
}

}  // namespace

// The demo user is represented by a domainless username.
const char kDemoUser[] = "demouser";
// Incognito user is represented by an empty string (since some code already
// depends on that and it's hard to figure out what).
const char kGuestUser[] = "";

User::User(const std::string& email)
    : email_(email),
      user_image_(*ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
          kDefaultImageResources[0])),
      oauth_token_status_(OAUTH_TOKEN_STATUS_UNKNOWN),
      image_index_(kInvalidImageIndex),
      image_is_stub_(false) {
  // The email address of a demo user is for internal purposes only,
  // never meant for display.
  if (!is_demo_user())
    display_email_ = email;
}

User::~User() {}

void User::SetImage(const UserImage& user_image, int image_index) {
  user_image_ = user_image;
  image_index_ = image_index;
  image_is_stub_ = false;
}

void User::SetImageURL(const GURL& image_url) {
  user_image_.set_url(image_url);
}

void User::SetStubImage(int image_index) {
  user_image_.SetImage(*ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
      kStubImageResourceID));
  image_index_ = image_index;
  image_is_stub_ = true;
}

void User::SetWallpaperThumbnail(const SkBitmap& wallpaper_thumbnail) {
  wallpaper_thumbnail_ = wallpaper_thumbnail;
}

std::string User::GetAccountName(bool use_display_email) const {
  if (use_display_email && !display_email_.empty())
    return GetUserName(display_email_);
  else
    return GetUserName(email_);
}

string16 User::GetDisplayName() const {
  // Fallback to the email account name in case display name haven't been set.
  return display_name_.empty() ?
      UTF8ToUTF16(GetAccountName(true)) :
      display_name_;
}

}  // namespace chromeos


text:
#include "Math\MathFunc.h"

using namespace ME3D;

Vector3 MathFunc::ToDegrees( Vector3& value )
{
	return Vector3( glm::degrees( value.GetSelf() ) );
}

float MathFunc::ToDegrees( float value )
{
	return glm::degrees(value);
}

Vector3 MathFunc::ToRadians( Vector3& value )
{
	return Vector3( glm::radians( value.GetSelf() ) );
}

float MathFunc::ToRadians( float value )
{
	return glm::radians(value);
}

float MathFunc::Max( float value1, float value2 )
{
	return glm::max(value1, value2);
}

float MathFunc::Min( float value1, float value2 )
{
	return glm::min(value1, value2);
}

float MathFunc::Tan( float value )
{
	return glm::tan(value);
}

float MathFunc::Cos( float value )
{
	return glm::cos(value);
}

float MathFunc::Sin( float value )
{
	return glm::sin(value);
}

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

float MathFunc::S_Tan( float value )
{
	return Tan(value);
}

float MathFunc::S_Cos( float value )
{
	return Cos(value);
}

float MathFunc::S_Sin( float value )
{
	return Sin(value);
}

float MathFunc::S_Max( float value1, float value2 )
{
	return Max(value1, value2);
}

float MathFunc::S_Min( float value1, float value2 )
{
	return Min(value1, value2);
}


text:
package ca.krasnay.panelized;

import org.apache.wicket.markup.html.form.CheckBox;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.FormComponent;
import org.apache.wicket.markup.html.form.validation.AbstractFormValidator;
import org.apache.wicket.markup.html.form.validation.IFormValidator;
import org.apache.wicket.model.IModel;
import org.apache.wicket.util.string.Strings;
import org.apache.wicket.util.visit.IVisit;
import org.apache.wicket.util.visit.IVisitor;

/**
 * Container panel with special validation to enforce minimum/maximum number of
 * selections.
 *
 * Note that for this to work it must be under a form that supports the
 * {@link FormValidatable} interface.
 *
 * This panel currently doesn't work with nested checkboxes, i.e. checkboxes
 * underneath a {@link CheckBoxPanel}. It treats all checkboxes under this panel
 * as equivalent.
 *
 * @author John Krasnay
 */
public class CheckBoxContainerPanel extends ContainerPanel implements FormValidatable {

    private int maxSelections = Integer.MAX_VALUE;

    private IModel<String> maxSelectionsError;

    private int minSelections;

    private IModel<String> minSelectionsError;

    public CheckBoxContainerPanel(String id) {
        this(id, null);
    }

    public CheckBoxContainerPanel(String id, IModel<?> model) {
        super(id, model);
    }

    private CheckBox findFirstCheckBox() {
        return visitChildren(CheckBox.class, new IVisitor<CheckBox, CheckBox>() {
            @Override
            public void component(CheckBox object, IVisit<CheckBox> visit) {
                visit.stop(object);
            }
        });
    }

    @Override
    public IFormValidator getFormValidator() {

        final CheckBox firstCheckBox = findFirstCheckBox();

        if (firstCheckBox != null && (minSelections > 0 || maxSelections > 0)) {

            return new AbstractFormValidator() {

                @Override
                public FormComponent<?>[] getDependentFormComponents() {
                    return null;
                }

                @Override
                public void validate(Form<?> form) {

                    if (!CheckBoxContainerPanel.this.isEnabled()) {
                        return;
                    }

                    int count = getSelectionCount();

                    if (isVisibleInHierarchy() && count > maxSelections) {
                        firstCheckBox.error(maxSelectionsError.getObject());
                    }

                    if (isVisibleInHierarchy() && count < minSelections) {
                        firstCheckBox.error(minSelectionsError.getObject());
                    }

                }
            };

        } else {
            return null;
        }

    }

    private int getSelectionCount() {

        final int[] checkedCount = new int[1];

        visitChildren(CheckBox.class, new IVisitor<CheckBox, Void>() {
            @Override
            public void component(CheckBox checkBox, IVisit<Void> visit) {
                if (Strings.isTrue(checkBox.getValue())) {
                    checkedCount[0]++;
                }
                visit.dontGoDeeper();
            }
        });

        return checkedCount[0];
    }

    public CheckBoxContainerPanel setMaxSelections(int maxSelections, IModel<String> errorMessage) {
        this.maxSelections = maxSelections;
        this.maxSelectionsError = errorMessage;
        // TODO I think we need to do something more here to localize the message,
        // e.g. bind it to this component. See ResourceModel for more info.
        return this;
    }

    public CheckBoxContainerPanel setMinSelections(int minSelections, IModel<String> errorMessage) {
        this.minSelections = minSelections;
        this.minSelectionsError = errorMessage;
        // TODO I think we need to do something more here to localize the message,
        // e.g. bind it to this component. See ResourceModel for more info.
        return this;
    }

}


text:
<?php

namespace Application\ShopAdminBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class TransactionType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('company')
            ->add('email')
            ->add('billing_firstname')
            ->add('billing_lastname')
            ->add('billing_phone')
            ->add('billing_fax')
            ->add('billing_address')
            ->add('billing_address2')
            ->add('billing_city')
            ->add('billing_country')
            ->add('billing_zipcode')
            ->add('shipping_firstname')
            ->add('shipping_lastname')
            ->add('shipping_phone')
            ->add('shipping_fax')
            ->add('shipping_address')
            ->add('shipping_address2')
            ->add('shipping_city')
            ->add('shipping_country')
            ->add('shipping_zipcode')
            ->add('quantity')
            //->add('payment_method')
            ->add('payment_method', 'choice', array(
                'choices' => array(
                    'bank-transfer' => 'Bank transfer',
                    'payu' => 'PayU',
                    'paypal' => 'PayPal',
                    'cash-delivery' => 'Cash on delivery'
                ),
                'expanded' => true
            ))
            ->add('shipping_cost')
            //->add('shipping_method')
            ->add('shipping_method', 'choice', array(
                'choices' => array('post' => 'Post', 'dhl' => 'DHL', 'reception-pack' => 'Reception pack'),
                'expanded' => true
            ))
            ->add('status')
            ->add('created_at', 'date', array(
            	'widget' => 'single_text',
            	'attr' => array('placeholder' => 'YYYY-MM-DD'),
            ))
            ->add('user')
        ;
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Application\ShopAdminBundle\Entity\Transaction'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'application_shopadminbundle_transaction';
    }
}


text:
namespace java {
  namespace lang {
    class String;
    class Class;
  }
}
template<class T> class JArray;

namespace org {
  namespace apache {
    namespace lucene {
      namespace index {

        class ReaderSlice : public ::java::lang::Object {
        public:
          enum {
            mid_init$_d3236aa4,
            mid_toString_14c7b5c5,
            max_mid
          };

          enum {
            fid_length,
            fid_readerIndex,
            fid_start,
            max_fid
          };

          static ::java::lang::Class *class$;
          static jmethodID *mids$;
          static jfieldID *fids$;
          static bool live$;
          static jclass initializeClass(bool);

          explicit ReaderSlice(jobject obj) : ::java::lang::Object(obj) {
            if (obj != NULL)
              env->getClass(initializeClass);
          }
          ReaderSlice(const ReaderSlice& obj) : ::java::lang::Object(obj) {}

          static JArray< ReaderSlice > *EMPTY_ARRAY;

          jint _get_length() const;
          jint _get_readerIndex() const;
          jint _get_start() const;

          ReaderSlice(jint, jint, jint);

          ::java::lang::String toString() const;
        };
      }
    }
  }
}

#include <Python.h>

namespace org {
  namespace apache {
    namespace lucene {
      namespace index {
        extern PyTypeObject PY_TYPE(ReaderSlice);

        class t_ReaderSlice {
        public:
          PyObject_HEAD
          ReaderSlice object;
          static PyObject *wrap_Object(const ReaderSlice&);
          static PyObject *wrap_jobject(const jobject&);
          static void install(PyObject *module);
          static void initialize(PyObject *module);
        };
      }
    }
  }
}

#endif


text:
from sklearn import svm
from sklearn import datasets

clf = svm.SVC()
iris = datasets.load_iris()
X, y = iris.data, iris.target
clf.fit(X, y)

import pickle
s = pickle.dumps(clf)


text:
import datetime

from django.utils.timezone import utc

class Cacher(object):
    '''
    Caching object for data
    '''
    _cache = {}
    _caching_time = 10  # seconds
    _debug = False

    def __init__(self, initial_cache_dir):
        self._cache = initial_cache_dir

    def __getitem__(self, key):
        cache = getattr(self, '_cache')
        return cache[key]

    def __setitem__(self, key, value):
        cache = getattr(self, '_cache')
        cache[key] = value
        return setattr(self, '_cache', cache)

    def get(self, key, default=False):
        if self._cache.get(key, False):
            return self._cache.get(key, False)
        else:
            return default

    def store(self, section, hashkey, value, howlong=_caching_time):
        if not section or not hashkey or not value:
            return False

        if not self._cache.get(section, False):
            self._cache[section] = {}

        self._cache[section][hashkey] = {'data': value, 'when': (datetime.datetime.utcnow().replace(tzinfo=utc) + datetime.timedelta(seconds=howlong))}
        return True

    def fetch(self, section, hashkey):
        try:
            cache_object = self._cache[section].get(hashkey, None)
        except:
            if self._debug:
                print "Cache MISS for %s %s (with error)" % (section, hashkey)
            return False

        if cache_object and cache_object.get('when', False) >= datetime.datetime.utcnow().replace(tzinfo=utc):
            cached_data = self._cache[section][hashkey]['data']
            if self._debug:
                print "Cache HIT for %s %s" % (section, hashkey)
            return cached_data
        else:
            if self._debug:
                print "Cache MISS for %s %s" % (section, hashkey)
            return False

    def purge(self, section):
        '''
        Removed cached contents for section
        '''
        if self._cache.get(section, False):
            self._cache[section] = {}
            return True

    def setDebug(self, flag):
        self._debug = flag


text:
/*
 * DataView.prototype built-in description
 */

#include "ecma-builtin-helpers-macro-defines.inc.h"

#if JERRY_BUILTIN_DATAVIEW

/* Object properties:
 *  (property name, object pointer getter) */

/* ECMA-262 v6, 24.2.3 */
OBJECT_VALUE (LIT_MAGIC_STRING_CONSTRUCTOR,
              ECMA_BUILTIN_ID_DATAVIEW,
              ECMA_PROPERTY_CONFIGURABLE_WRITABLE)

/* ECMA-262 v6, 23.2.4.21 */
STRING_VALUE (LIT_GLOBAL_SYMBOL_TO_STRING_TAG,
              LIT_MAGIC_STRING_DATAVIEW_UL,
              ECMA_PROPERTY_FLAG_CONFIGURABLE)

/* Routine properties:
 *  (property name, C routine name, arguments number or NON_FIXED, value of the routine's length property) */
ROUTINE (LIT_MAGIC_STRING_GET_FLOAT_32_UL, ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT32, 2, 1)
#if JERRY_NUMBER_TYPE_FLOAT64
ROUTINE (LIT_MAGIC_STRING_GET_FLOAT_64_UL, ECMA_DATAVIEW_PROTOTYPE_GET_FLOAT64, 2, 1)
#endif /* JERRY_NUMBER_TYPE_FLOAT64 */
ROUTINE (LIT_MAGIC_STRING_GET_INT8_UL, ECMA_DATAVIEW_PROTOTYPE_GET_INT8, 1, 1)
ROUTINE (LIT_MAGIC_STRING_GET_INT16_UL, ECMA_DATAVIEW_PROTOTYPE_GET_INT16, 2, 1)
ROUTINE (LIT_MAGIC_STRING_GET_INT32_UL, ECMA_DATAVIEW_PROTOTYPE_GET_INT32, 2, 1)
ROUTINE (LIT_MAGIC_STRING_GET_UINT8_UL, ECMA_DATAVIEW_PROTOTYPE_GET_UINT8, 2, 1)
ROUTINE (LIT_MAGIC_STRING_GET_UINT16_UL, ECMA_DATAVIEW_PROTOTYPE_GET_UINT16, 2, 1)
ROUTINE (LIT_MAGIC_STRING_GET_UINT32_UL, ECMA_DATAVIEW_PROTOTYPE_GET_UINT32, 2, 1)
ROUTINE (LIT_MAGIC_STRING_SET_FLOAT_32_UL, ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT32, 2, 2)
#if JERRY_NUMBER_TYPE_FLOAT64
ROUTINE (LIT_MAGIC_STRING_SET_FLOAT_64_UL, ECMA_DATAVIEW_PROTOTYPE_SET_FLOAT64, 2, 2)
#endif /* JERRY_NUMBER_TYPE_FLOAT64 */
ROUTINE (LIT_MAGIC_STRING_SET_INT8_UL, ECMA_DATAVIEW_PROTOTYPE_SET_INT8, 1, 2)
ROUTINE (LIT_MAGIC_STRING_SET_INT16_UL, ECMA_DATAVIEW_PROTOTYPE_SET_INT16, 2, 2)
ROUTINE (LIT_MAGIC_STRING_SET_INT32_UL, ECMA_DATAVIEW_PROTOTYPE_SET_INT32, 2, 2)
ROUTINE (LIT_MAGIC_STRING_SET_UINT8_UL, ECMA_DATAVIEW_PROTOTYPE_SET_UINT8, 2, 2)
ROUTINE (LIT_MAGIC_STRING_SET_UINT16_UL, ECMA_DATAVIEW_PROTOTYPE_SET_UINT16, 2, 2)
ROUTINE (LIT_MAGIC_STRING_SET_UINT32_UL, ECMA_DATAVIEW_PROTOTYPE_SET_UINT32, 2, 2)
#if JERRY_BUILTIN_BIGINT
ROUTINE (LIT_MAGIC_STRING_GET_BIGINT64, ECMA_DATAVIEW_PROTOTYPE_GET_BIGINT64, 2, 1)
ROUTINE (LIT_MAGIC_STRING_GET_BIGUINT64, ECMA_DATAVIEW_PROTOTYPE_GET_BIGUINT64, 2, 1)
ROUTINE (LIT_MAGIC_STRING_SET_BIGINT64, ECMA_DATAVIEW_PROTOTYPE_SET_BIGINT64, 2, 2)
ROUTINE (LIT_MAGIC_STRING_SET_BIGUINT64, ECMA_DATAVIEW_PROTOTYPE_SET_BIGUINT64, 2, 2)
#endif /* JERRY_BUILTIN_BIGINT */

/* ECMA-262 v6, 24.2.4.1 */
ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BUFFER,
                    ECMA_DATAVIEW_PROTOTYPE_BUFFER_GETTER,
                    ECMA_PROPERTY_FLAG_CONFIGURABLE)

/* ECMA-262 v6, 24.2.4.2 */
ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BYTE_LENGTH_UL,
                    ECMA_DATAVIEW_PROTOTYPE_BYTE_LENGTH_GETTER,
                    ECMA_PROPERTY_FLAG_CONFIGURABLE)

/* ECMA-262 v6, 24.2.4.3 */
ACCESSOR_READ_ONLY (LIT_MAGIC_STRING_BYTE_OFFSET_UL,
                    ECMA_DATAVIEW_PROTOTYPE_BYTE_OFFSET_GETTER,
                    ECMA_PROPERTY_FLAG_CONFIGURABLE)

#endif /* JERRY_BUILTIN_DATAVIEW */

#include "ecma-builtin-helpers-macro-undefs.inc.h"


text:
/*global QUnit */
sap.ui.define(["sap/base/util/isWindow"], function(isWindow) {
	"use strict";

	QUnit.module("Object isWindow");

	QUnit.test("tests for window object", function(assert) {
		assert.notOk(isWindow({}), "not a window");
		assert.notOk(isWindow(), "not a window");
		assert.notOk(isWindow(null), "not a window");
		assert.notOk(isWindow(0), "not a window");
		assert.notOk(isWindow(1), "not a window");
		assert.notOk(isWindow(undefined), "not a window");

		assert.ok(typeof window === 'undefined' || isWindow(window), "is a window");
	});
});


text:
package org.springframework.boot.test.web.reactive.server;

import java.util.List;

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.core.annotation.MergedAnnotations.SearchStrategy;
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.ContextCustomizer;
import org.springframework.test.context.ContextCustomizerFactory;
import org.springframework.util.ClassUtils;

/**
 * {@link ContextCustomizerFactory} for {@code WebTestClient}.
 *
 * @author Stephane Nicoll
 */
class WebTestClientContextCustomizerFactory implements ContextCustomizerFactory {

	private static final String WEB_TEST_CLIENT_CLASS = "org.springframework.web.reactive.function.client.WebClient";

	@Override
	public ContextCustomizer createContextCustomizer(Class<?> testClass,
			List<ContextConfigurationAttributes> configAttributes) {
		MergedAnnotations annotations = MergedAnnotations.from(testClass,
				SearchStrategy.INHERITED_ANNOTATIONS);
		if (isWebClientPresent() && annotations.isPresent(SpringBootTest.class)) {
			return new WebTestClientContextCustomizer();
		}
		return null;
	}

	private boolean isWebClientPresent() {
		return ClassUtils.isPresent(WEB_TEST_CLIENT_CLASS, getClass().getClassLoader());
	}

}


text:
#include "sync_clock.h"

#include <asm/byteorder.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <linux/usbdevice_fs.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/inotify.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>

#ifdef __ANDROID__
    #include <android/log.h>
    #define  LOGD(...)  __android_log_print(ANDROID_LOG_VERBOSE, "ClockSyncNative", __VA_ARGS__)
#else
    #define  LOGD(...)  printf(__VA_ARGS__)
#endif

// How many times to repeat the 1..9 digit sequence it's a tradeoff between
// precision and how long it takes.
// TODO: investigate better combination of constants for repeats and wait times
const int kSyncRepeats = 7;
const int kMillion = 1000000;

/**
uptimeMicros() - returns microseconds elapsed since boot.
Same time as Android's SystemClock.uptimeMillis() but in microseconds.

Adapted from Android:
platform/system/core/libutils/Timers.cpp
platform/system/core/include/utils/Timers.h

See:
http://developer.android.com/reference/android/os/SystemClock.html
https://android.googlesource.com/platform/system/core/+/master/libutils/Timers.cpp
*/
int64_t uptimeMicros() {
    struct timespec ts = {0};
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return ((int64_t)ts.tv_sec) * kMillion + ts.tv_nsec / 1000;
}

// Sleeps us microseconds
int microsleep(int us) {
    struct timespec ts = {0};
    ts.tv_sec = us / kMillion;
    us %= kMillion;
    ts.tv_nsec = us*1000;
    nanosleep(&ts, NULL);
    return 0;
}

// *********************** Generic USB functions *******************************

static int send_char_async(int fd, int endpoint, char msg, char * label) {
    // TODO: Do we really need a buffer longer than 1 char here?
    char buffer[256] = {0};
    buffer[0] = msg;
    int length = 1;

    // TODO: free() the memory used for URBs.
    // Circular buffer of URBs? Cleanup at the end of clock sync?
    // Several may be used simultaneously, no signal when done.
    struct usbdevfs_urb *urb = calloc(1, sizeof(struct usbdevfs_urb));
    memset(urb, 0, sizeof(struct usbdevfs_urb));

    int res;
    urb->status = -1;
    urb->buffer = buffer;
    urb->buffer_length = length;
    urb->endpoint = endpoint;
    urb->type = USBDEVFS_URB_TYPE_BULK;
    urb->usercontext = label; // This is hackish
    do {
        res = ioctl(fd, USBDEVFS_SUBMITURB, urb);
    } while((res < 0) && (errno == EINTR));
    return res;
}

// Send or read using USBDEVFS_BULK. Allows to set a timeout.
static int bulk_talk(int fd, int endpoint, char * buffer, int length) {
    // Set some reasonable timeout. 20ms is plenty time for most transfers but
    // short enough to fail quickly if all transfers and retries fail with
    // timeout.
    const int kTimeoutMs = 20;
    struct usbdevfs_bulktransfer ctrl = {0};
    // TODO: need to limit request size to avoid EINVAL

    ctrl.ep = endpoint;
    ctrl.len = length;
    ctrl.data = buffer;
    ctrl.timeout = kTimeoutMs;
    int ret = ioctl(fd, USBDEVFS_BULK, &ctrl);
    return ret;
}

/*******************************************************************************
* Clock sync specific stuff below.
* Most data is stored in the clock_connection struct variable.
*/

// Send a single character to the remote in a blocking mode
int send_cmd(struct clock_connection *clk, char cmd) {
    return bulk_talk(clk->fd, clk->endpoint_out, &cmd, 1);
}

// Schedule a single character to be sent to the remote - async.
int send_async(struct clock_connection *clk, char cmd) {
    return send_char_async(clk->fd, clk->endpoint_out, cmd, NULL);
}

int bulk_read(struct clock_connection *clk) {
    memset(clk->buffer, 0, sizeof(clk->buffer));
    int ret = bulk_talk(clk->fd, clk->endpoint_in, clk->buffer, sizeof(clk->buffer));
    return ret;
}

// microseconds elapsed since clk->t_base
int micros(struct clock_connection *clk) {
    return uptimeMicros() - clk->t_base;
}

// Clear all incoming data that's already waiting somewhere in kernel buffers
// and discard it.
void flush_incoming(struct clock_connection *clk) {
    // When bulk_read times out errno = ETIMEDOUT=110, retval =-1
    // should we check for this?

    while(bulk_read(clk) >= 0) {
        // TODO: fail nicely if waiting too long to avoid hangs
    }
}

// Ask the remote to send its timestamps
// for the digits previously sent to it.
void read_remote_timestamps(struct clock_connection *clk, int * times_remote) {
    int i;
    int t_remote;
    // Go over the digits [1, 2 ... 9]
    for (i = 0; i < 9; i++) {
        char digit = i + '1';
        send_cmd(clk, CMD_SYNC_READOUT);
        bulk_read(clk);
        if (clk->buffer[0] != digit) {
            LOGD("Error, bad reply for R%d: %s", i+1, clk->buffer);
        }
        // The reply string looks like digit + space + timestamp
        // Offset by 2 to ignore the digit and the space
        t_remote = atoi(clk->buffer + 2);
        times_remote[i] = t_remote;
    }
}

// Preliminary rough sync with a single message - CMD_SYNC_ZERO = 'Z'.
// This is not strictly necessary but greatly simplifies debugging
// by removing the need to look at very long numbers.
void zero_remote(struct clock_connection *clk) {
    flush_incoming(clk);
    clk->t_base = uptimeMicros();
    send_cmd(clk, CMD_SYNC_ZERO);
    bulk_read(clk); // TODO, make sure we got 'z'
    clk->maxE = micros(clk);
    clk->minE = 0;

    LOGD("Sent a 'Z', reply '%c' in %d us\n", clk->buffer[0], clk->maxE);
}

void improve_minE(struct clock_connection *clk) {
    int times_local_sent[9] = {0};
    int times_remote_received[9] = {0};

    // Set sleep time as 1/kSleepTimeDivider of the current bounds interval,
    // but never less or more than k(Min/Max)SleepUs. All pretty random
    // numbers that could use some tuning and may behave differently on
    // different devices.
    const int kMaxSleepUs = 700;
    const int kMinSleepUs = 70;
    const int kSleepTimeDivider = 10;
    int minE = clk->minE;
    int sleep_time = (clk->maxE - minE) / kSleepTimeDivider;
    if(sleep_time > kMaxSleepUs) sleep_time = kMaxSleepUs;
    if(sleep_time < kMinSleepUs) sleep_time = kMinSleepUs;

    flush_incoming(clk);
    // Send digits to remote side
    int i;
    for (i = 0; i < 9; i++) {
        char c = i + '1';
        times_local_sent[i] = micros(clk);
        send_async(clk, c);
        microsleep(sleep_time);
    }

    // Read out receive times from the other side
    read_remote_timestamps(clk, times_remote_received);

    // Do stats
    for (i = 0; i < 9; i++) {
        int tls = times_local_sent[i];
        int trr = times_remote_received[i];

        int dt;

        // Look at outgoing digits
        dt = tls - trr;
        if (tls != 0 && trr != 0 && dt > minE) {
            minE = dt;
        }

    }

    clk->minE = minE;

    LOGD("E is between %d and %d us, sleep_time=%d\n", clk->minE, clk->maxE, sleep_time);
}

void improve_maxE(struct clock_connection *clk) {
    int times_remote_sent[9] = {0};
    int times_local_received[9] = {0};

    // Tell the remote to send us digits with delays
    // TODO: try tuning / configuring the delay time on remote side
    send_async(clk, CMD_SYNC_SEND);

    // Read and timestamp the incoming digits, they may arrive out of order.
    // TODO: Try he same with USBDEVFS_REAPURB, it might be faster
    int i;
    for (i = 0; i < 9; ++i) {
        int retval = bulk_read(clk);
        // TODO: deal with retval = (bytes returned) > 1. shouldn't happen.
        // Can it happen on some devices?
        int t_local = micros(clk);
        int digit = atoi(clk->buffer);
        if (digit <=0 || digit > 9) {
            LOGD("Error, bad incoming digit: %s\n", clk->buffer);
        }
        times_local_received[digit-1] = t_local;
    }

    // Flush whatever came after the digits. As of this writing, it's usually
    // a single linefeed character.
    flush_incoming(clk);
    // Read out the remote timestamps of when the digits were sent
    read_remote_timestamps(clk, times_remote_sent);

    // Do stats
    int maxE = clk->maxE;
    for (i = 0; i < 9; i++) {
        int trs = times_remote_sent[i];
        int tlr = times_local_received[i];
        int dt = tlr - trs;
        if (tlr != 0 && trs != 0 && dt < maxE) {
            maxE = dt;
        }
    }

    clk->maxE = maxE;

    LOGD("E is between %d and %d us\n", clk->minE, clk->maxE);
}

void improve_bounds(struct clock_connection *clk) {
    improve_minE(clk);
    improve_maxE(clk);
}

// get minE and maxE again after some time to check for clock drift
void update_bounds(struct clock_connection *clk) {
    // Reset the bounds to some unrealistically large numbers
    int i;
    clk->minE = -1e7;
    clk->maxE =  1e7;
    // Talk to remote to get bounds on minE and maxE
    for (i=0; i < kSyncRepeats; i++) {
        improve_bounds(clk);
    }
}

void sync_clocks(struct clock_connection *clk) {
    // Send CMD_SYNC_ZERO to remote for rough initial sync
    zero_remote(clk);

    int rep;
    for (rep=0; rep < kSyncRepeats; rep++) {
        improve_bounds(clk);
    }

    // Shift the base time to set minE = 0
    clk->t_base += clk->minE;
    clk->maxE -= clk->minE;
    clk->minE = 0;
    LOGD("Base time shifted for zero minE\n");
}


text:
@extends('admin.layouts.admin')

@section('title',"Teilnehmer Import" )

@section('content')

            {{ Form::open(['route'=>['admin.anmeldung.import'],'method' => 'post','class'=>'form-horizontal form-label-left', 'files' => true]) }}

                {!! Form::label('CSV Datei') !!}
                {!! Form::file('File', null) !!}

                        <button type="submit" class="btn btn-success"> Import start </button>

            {{ Form::close() }}

@endsection

@section('styles')
    @parent
    {{ Html::style(mix('assets/admin/css/users/edit.css')) }}
@endsection

@section('scripts')
    @parent
    {{ Html::script(mix('assets/admin/js/users/edit.js')) }}
@endsection


text:
class CardsController < ApplicationController
  include RequireParentOrganisation

  prepend_before_action :authenticate_user!
  before_action :set_card, only: %i[show edit update destroy]

  # GET /cards
  def index
    @cards = @organisation.cards.group_by_state
    @columns = Card::OPEN_STATES.map do |state_name, _closed|
      state = @cards.find { |g| g[:_id] == state_name.to_s }
      {
        state_name: state_name,
        state_display_name: state_name.to_s.humanize.sub('Qa', 'QA'),
        card_count: state[:count],
        cards: state[:cards]
      }
    end
  end

  # GET /cards/new
  def new
    @card = @organisation.cards.build(creator: current_user)
  end

  # POST /cards
  def create
    @card = @organisation.cards.build(card_params)
    @card.creator = current_user

    if @card.save
      redirect_to card_url, notice: 'Card was successfully created.'
    else
      render :new
    end
  end

  # PATCH/PUT /cards/1
  def update
    if @card.update(card_params)
      redirect_to card_url, notice: 'Card was successfully updated.'
    else
      render :edit
    end
  end

  # DELETE /cards/1
  def destroy
    @card.destroy
    redirect_to cards_url(@organisation.to_param), notice: 'Card was successfully destroyed.'
  end

  private

    def set_card
      @card = @organisation.cards.find_by(number: params[:id])
    end

    # Only allow a trusted parameter "white list" through.
    def card_params
      params.require(:card).permit(:title, :description)
    end

    def card_url
      organisation_card_url @organisation, @card.number
    end
end