<commit_before>var Table = require('./table');
var TileMap = require('./tilemap');
var Keyboard = require('./keyboard');
var Hangul = require('./hangul');
var parser = require('./parser');
var TileAction = require('./action');
var Interpreter = require('./interpreter');

var UtilityKeyBinding = [
  [
    {
      name: "복사",
      exec: function() {
        // TODO yes, yes. I know. This code is like a 30 days old spaghetti
        // in the garbage can that smells like rotten ActiveX.
        // Which means... it needs to be fixed.
        this.clipboard = {
          command: this.tile.command,
          direction: this.tile.direction,
          data: this.tile.data
        }
      }
    },
    {
      name: "자르기",
      exec: function() {
        this.clipboard = {
          command: this.tile.command,
          direction: this.tile.direction,
          data: this.tile.data
        }
        this.undomachine.run(new TileAction(this.tile, this.tileX, this.tileY,
          {
            command: 'none',
            direction: 'none',
            breakpoint: false
          }, this.renderer));
      }
    },
    {
      name: "붙이기",
      exec: function() {
        this.undomachine.run(new TileAction(this.tile, this.tileX, this.tileY,
          this.clipboard, this.renderer));
      }
    },
    {
      name: "중단점",
      exec: function() {
        this.undomachine.run(new TileAction(this.tile, this.tileX, this.tileY,
          {
            breakpoint: !this.tile.breakpoint
          }, this.renderer));
      }
    }
  ]
];

var PushKeyBinding = [
  [0, 2, 3, 4, 5],
  [6, 7, 8, 9]
];

var FinalKeyBinding = [
  ' ㄱㄴㄷㄹㄲㄳㄵㄶ'.split(''),
  'ㅁㅂㅅㅇㅈㄺㄻㄼㄽ'.split(''),
  'ㅊㅋㅌㅍㅎㄾㄿㅀㅄㅆ'.split('')
];

// Generate keymap from table
var UtilityBindingMap = Keyboard.createKeyMap(UtilityKeyBinding,
  Keyboard.KeyNumberLayout);
var PushKeyBindingMap = Keyboard.createKeyMap(PushKeyBinding);
var FinalKeyBindingMap = Keyboard.createKeyMap(FinalKeyBinding);

function ContextMenu(container, element, pushElement, finalElement,
  renderer, clickCallback,
  keyboard, undomachine) {
  this.container = container;
  this.element = element;
  this.pushElement = pushElement;
  this.finalElement = finalElement;
  this.hideEvent = this.hide.bind(this);
  this.init();
  this.renderer = renderer;
  this.clickCallback = clickCallback;
  this.keyboard = keyboard;
  this.undomachine = undomachine;
  this.tileX = null;
  this.tileY = null;
  this.tile = null;
  this.clipboard = {};
}

ContextMenu.prototype.update = function() {
  if(this.clickCallback) this.clickCallback(this.tileX, this.tileY, this.tile);
}

ContextMenu.prototype.init = function() {
  var self = this;
  var tilemap = TileMap.fromArray(PushKeyBinding);
  // TODO no getElementById in class
  // This is exactly same situation as toolbox
  var viewport = document.getElementById('push-table');
  var pushTable = new Table(viewport, tilemap, function(node, tile, x, y) {
    if(tile == null) {
      node.parentNode.removeChild(node);
      return;
    }
    node.id = 'push-table-'+tile;
    node.appendChild(document.createTextNode(tile));
    var divNode = document.createElement('div');
    divNode.className = 'key';
    divNode.appendChild(document.createTextNode(Keyboard.KeyLayout[y][x]));
    node.appendChild(divNode);
    node.addEventListener('click', function() {
      self.undomachine.run(new TileAction(self.tile, self.tileX, self.tileY,
        {
          data: tile
        }, self.renderer));
      self.update();
    });
  });
  var tilemap = TileMap.fromArray(FinalKeyBinding);
  // ... No Ctrl+C, Ctrl+V Please?
  var viewport = document.getElementById('final-table');
  var pushTable = new Table(viewport, tilemap, function(node, tile, x, y) {
    if(tile == null) {
      node.parentNode.removeChild(node);
      return;
    }
    node.id = 'final-table-'+tile;
    node.appendChild(document.createTextNode(tile));
    var divNode = document.createElement('div');
    divNode.className = 'key';
    divNode.appendChild(document.createTextNode(Keyboard.KeyShiftLayout[y][x]));
    node.appendChild(divNode);
    node.addEventListener('click', function() {
      self.undomachine.run(new TileAction(self.tile, self.tileX, self.tileY,
        {
          data: Hangul.final.indexOf(tile)
        }, self.renderer));
      self.update();
    });
  });
  var tilemap = TileMap.fromArray(UtilityKeyBinding);
  var viewport = document.getElementById('utility-table');
  var utilityTable = new Table(viewport, tilemap, function(node, tile, x, y) {
    if(tile == null) {
      node.parentNode.removeChild(node);
      return;
    }
    node.id = 'utility-table-'+tile;
    node.appendChild(document.createTextNode(tile.name));
    var divNode = document.createElement('div');
    divNode.className = 'key';
    divNode.appendChild(document.createTextNode(Keyboard.KeyNumberLayout[y][x]));
    node.appendChild(divNode);
    node.addEventListener('click', function() {
      tile.exec.call(self);
      self.update();
    });
  });
}

ContextMenu.prototype.show = function(x, y) {
  var self = this;
  this.container.style.display = 'block';
  this.element.style.display = 'block';
  setTimeout(function() {
    self.element.style.top = y+'px';
    self.element.style.left = Math.max(0,
      Math.min(window.innerWidth - self.element.offsetWidth,
      x-self.element.offsetWidth/2+self.renderer.width/2))+'px';
    self.container.addEventListener('click', self.hideEvent);
    self.container.addEventListener('contextmenu', self.hideEvent);
  }, 0);
  var self = this;
  // Prevent going more
  this.keyboard.push(null);
  this.keyboard.push({
    map: UtilityBindingMap,
    callback: function(data) {
      data.exec.call(self);
      self.update();
      self.hide();
    }
  });
  // TODO it could be better really.
  if(this.tile.command == 'push') {
    this.finalElement.style.display = 'none';
    this.pushElement.style.display = 'block';
    // Push keyboard state
    this.keyboard.push({
      map: PushKeyBindingMap,
      callback: function(data) {
        self.undomachine.run(new TileAction(self.tile, self.tileX, self.tileY,
          {
            data: data
          }, self.renderer));
        self.update();
        self.hide();
      }
    });
  } else if(Interpreter.CommandMap[this.tile.command] &&
    Interpreter.CommandMap[this.tile.command].argument){
    this.finalElement.style.display = 'block';
    this.pushElement.style.display = 'none';
    // Push keyboard state
    this.keyboard.push({
      map: FinalKeyBindingMap,
      callback: function(data) {
        self.undomachine.run(new TileAction(self.tile, self.tileX, self.tileY,
          {
            data: Hangul.final.indexOf(data)
          }, self.renderer));
        self.update();
        self.hide();
      }
    });
  } else {
    // Hide all
    this.finalElement.style.display = 'none';
    this.pushElement.style.display = 'none';
    // Push keyboard state
    this.keyboard.push(null);
  }
}

ContextMenu.prototype.hide = function(e) {
  this.container.removeEventListener('click', this.hideEvent);
  this.container.removeEventListener('contextmenu', this.hideEvent);
  this.container.style.display = 'none';
  this.element.style.display = 'none';
  this.keyboard.pop();
  this.keyboard.pop();
  this.keyboard.pop();
  if(e) {
    e.preventDefault();
    return false;
  }
}

module.exports = ContextMenu;
<commit_msg>Really fix for chrome<commit_after>var Table = require('./table');
var TileMap = require('./tilemap');
var Keyboard = require('./keyboard');
var Hangul = require('./hangul');
var parser = require('./parser');
var TileAction = require('./action');
var Interpreter = require('./interpreter');

var UtilityKeyBinding = [
  [
    {
      name: "복사",
      exec: function() {
        // TODO yes, yes. I know. This code is like a 30 days old spaghetti
        // in the garbage can that smells like rotten ActiveX.
        // Which means... it needs to be fixed.
        this.clipboard = {
          command: this.tile.command,
          direction: this.tile.direction,
          data: this.tile.data
        }
      }
    },
    {
      name: "자르기",
      exec: function() {
        this.clipboard = {
          command: this.tile.command,
          direction: this.tile.direction,
          data: this.tile.data
        }
        this.undomachine.run(new TileAction(this.tile, this.tileX, this.tileY,
          {
            command: 'none',
            direction: 'none',
            breakpoint: false
          }, this.renderer));
      }
    },
    {
      name: "붙이기",
      exec: function() {
        this.undomachine.run(new TileAction(this.tile, this.tileX, this.tileY,
          this.clipboard, this.renderer));
      }
    },
    {
      name: "중단점",
      exec: function() {
        this.undomachine.run(new TileAction(this.tile, this.tileX, this.tileY,
          {
            breakpoint: !this.tile.breakpoint
          }, this.renderer));
      }
    }
  ]
];

var PushKeyBinding = [
  [0, 2, 3, 4, 5],
  [6, 7, 8, 9]
];

var FinalKeyBinding = [
  ' ㄱㄴㄷㄹㄲㄳㄵㄶ'.split(''),
  'ㅁㅂㅅㅇㅈㄺㄻㄼㄽ'.split(''),
  'ㅊㅋㅌㅍㅎㄾㄿㅀㅄㅆ'.split('')
];

// Generate keymap from table
var UtilityBindingMap = Keyboard.createKeyMap(UtilityKeyBinding,
  Keyboard.KeyNumberLayout);
var PushKeyBindingMap = Keyboard.createKeyMap(PushKeyBinding);
var FinalKeyBindingMap = Keyboard.createKeyMap(FinalKeyBinding);

function ContextMenu(container, element, pushElement, finalElement,
  renderer, clickCallback,
  keyboard, undomachine) {
  this.container = container;
  this.element = element;
  this.pushElement = pushElement;
  this.finalElement = finalElement;
  this.hideEvent = this.hide.bind(this);
  this.init();
  this.renderer = renderer;
  this.clickCallback = clickCallback;
  this.keyboard = keyboard;
  this.undomachine = undomachine;
  this.tileX = null;
  this.tileY = null;
  this.tile = null;
  this.clipboard = {};
}

ContextMenu.prototype.update = function() {
  if(this.clickCallback) this.clickCallback(this.tileX, this.tileY, this.tile);
}

ContextMenu.prototype.init = function() {
  var self = this;
  self.container.addEventListener('contextmenu', function(e) {
    e.preventDefault();
    return false;
  });
  var tilemap = TileMap.fromArray(PushKeyBinding);
  // TODO no getElementById in class
  // This is exactly same situation as toolbox
  var viewport = document.getElementById('push-table');
  var pushTable = new Table(viewport, tilemap, function(node, tile, x, y) {
    if(tile == null) {
      node.parentNode.removeChild(node);
      return;
    }
    node.id = 'push-table-'+tile;
    node.appendChild(document.createTextNode(tile));
    var divNode = document.createElement('div');
    divNode.className = 'key';
    divNode.appendChild(document.createTextNode(Keyboard.KeyLayout[y][x]));
    node.appendChild(divNode);
    node.addEventListener('click', function() {
      self.undomachine.run(new TileAction(self.tile, self.tileX, self.tileY,
        {
          data: tile
        }, self.renderer));
      self.update();
    });
  });
  var tilemap = TileMap.fromArray(FinalKeyBinding);
  // ... No Ctrl+C, Ctrl+V Please?
  var viewport = document.getElementById('final-table');
  var pushTable = new Table(viewport, tilemap, function(node, tile, x, y) {
    if(tile == null) {
      node.parentNode.removeChild(node);
      return;
    }
    node.id = 'final-table-'+tile;
    node.appendChild(document.createTextNode(tile));
    var divNode = document.createElement('div');
    divNode.className = 'key';
    divNode.appendChild(document.createTextNode(Keyboard.KeyShiftLayout[y][x]));
    node.appendChild(divNode);
    node.addEventListener('click', function() {
      self.undomachine.run(new TileAction(self.tile, self.tileX, self.tileY,
        {
          data: Hangul.final.indexOf(tile)
        }, self.renderer));
      self.update();
    });
  });
  var tilemap = TileMap.fromArray(UtilityKeyBinding);
  var viewport = document.getElementById('utility-table');
  var utilityTable = new Table(viewport, tilemap, function(node, tile, x, y) {
    if(tile == null) {
      node.parentNode.removeChild(node);
      return;
    }
    node.id = 'utility-table-'+tile;
    node.appendChild(document.createTextNode(tile.name));
    var divNode = document.createElement('div');
    divNode.className = 'key';
    divNode.appendChild(document.createTextNode(Keyboard.KeyNumberLayout[y][x]));
    node.appendChild(divNode);
    node.addEventListener('click', function() {
      tile.exec.call(self);
      self.update();
    });
  });
}

ContextMenu.prototype.show = function(x, y) {
  var self = this;
  this.container.style.display = 'block';
  this.element.style.display = 'block';
  setTimeout(function() {
    self.element.style.top = y+'px';
    self.element.style.left = Math.max(0,
      Math.min(window.innerWidth - self.element.offsetWidth,
      x-self.element.offsetWidth/2+self.renderer.width/2))+'px';
    self.container.addEventListener('click', self.hideEvent);
    self.container.addEventListener('contextmenu', self.hideEvent);
  }, 0);
  var self = this;
  // Prevent going more
  this.keyboard.push(null);
  this.keyboard.push({
    map: UtilityBindingMap,
    callback: function(data) {
      data.exec.call(self);
      self.update();
      self.hide();
    }
  });
  // TODO it could be better really.
  if(this.tile.command == 'push') {
    this.finalElement.style.display = 'none';
    this.pushElement.style.display = 'block';
    // Push keyboard state
    this.keyboard.push({
      map: PushKeyBindingMap,
      callback: function(data) {
        self.undomachine.run(new TileAction(self.tile, self.tileX, self.tileY,
          {
            data: data
          }, self.renderer));
        self.update();
        self.hide();
      }
    });
  } else if(Interpreter.CommandMap[this.tile.command] &&
    Interpreter.CommandMap[this.tile.command].argument){
    this.finalElement.style.display = 'block';
    this.pushElement.style.display = 'none';
    // Push keyboard state
    this.keyboard.push({
      map: FinalKeyBindingMap,
      callback: function(data) {
        self.undomachine.run(new TileAction(self.tile, self.tileX, self.tileY,
          {
            data: Hangul.final.indexOf(data)
          }, self.renderer));
        self.update();
        self.hide();
      }
    });
  } else {
    // Hide all
    this.finalElement.style.display = 'none';
    this.pushElement.style.display = 'none';
    // Push keyboard state
    this.keyboard.push(null);
  }
}

ContextMenu.prototype.hide = function(e) {
  this.container.removeEventListener('click', this.hideEvent);
  this.container.removeEventListener('contextmenu', this.hideEvent);
  this.container.style.display = 'none';
  this.element.style.display = 'none';
  this.keyboard.pop();
  this.keyboard.pop();
  this.keyboard.pop();
  if(e) {
    e.preventDefault();
    return false;
  }
}

module.exports = ContextMenu;
<|endoftext|>


<commit_before>/**
* _Internal Class_, not generally used outside of the engine's internals.
*
* @class Common
*/

var Common = {};

(function() {

    /**
     * Description
     * @method extend
     * @param {} obj, obj, obj...
     * @return {} obj extended
     */
    Common.extend = function(obj) {
        var args = Array.prototype.slice.call(arguments, 1);

        for (var i = 0; i < args.length; i++) {
            var source = args[i];

            if (source) {
                for (var prop in source) {
                    if (source[prop].constructor === Object) {
                        if (!obj[prop] || obj[prop].constructor === Object) {
                            obj[prop] = obj[prop] || {};
                            Common.extend(obj[prop], source[prop]);
                        } else {
                            obj[prop] = source[prop];
                        }
                    } else {
                        obj[prop] = source[prop];
                    }
                }
            }
        }

        return obj;
    };

    /**
     * Description
     * @method keys
     * @param {} obj
     * @return {string[]} keys
     */
    Common.keys = function(obj) {
        if (Object.keys)
            return Object.keys(obj);

        // avoid hasOwnProperty for performance
        var keys = [];
        for (var key in obj)
            keys.push(key);
        return keys;
    };

    /**
     * Description
     * @method values
     * @param {} obj
     * @return {array} Array of the objects property values
     */
    Common.values = function(obj) {
        var values = [];

        if (Object.keys) {
            var keys = Object.keys(obj);
            for (var i = 0; i < keys.length; i++) {
                values.push(obj[keys[i]]);
            }
            return values;
        }

        // avoid hasOwnProperty for performance
        for (var key in obj)
            values.push(obj[key]);
        return values;
    };

    /**
     * Description
     * @method shadeColor
     * @param {string} color
     * @param {number} percent
     * @return {string} A hex colour string made by lightening or darkening color by percent
     */
    Common.shadeColor = function(color, percent) {
        // http://stackoverflow.com/questions/5560248/programmatically-lighten-or-darken-a-hex-color
        var colorInteger = parseInt(color.slice(1),16),
            amount = Math.round(2.55 * percent),
            R = (colorInteger >> 16) + amount,
            B = (colorInteger >> 8 & 0x00FF) + amount,
            G = (colorInteger & 0x0000FF) + amount;
        return "#" + (0x1000000 + (R < 255 ? R < 1 ? 0 : R :255) * 0x10000
                + (B < 255 ? B < 1 ? 0 : B : 255) * 0x100
                + (G < 255 ? G < 1 ? 0 : G : 255)).toString(16).slice(1);
    };

    /**
     * Description
     * @method shuffle
     * @param {array} array
     * @return {array} array shuffled randomly
     */
    Common.shuffle = function(array) {
        for (var i = array.length - 1; i > 0; i--) {
            var j = Math.floor(Math.random() * (i + 1));
            var temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
        return array;
    };

    /**
     * Description
     * @method choose
     * @param {array} choices
     * @return {object} A random choice object from the array
     */
    Common.choose = function(choices) {
        return choices[Math.floor(Math.random() * choices.length)];
    };

    /**
     * Description
     * @method isElement
     * @param {object} obj
     * @return {boolean} True if the object is a HTMLElement, otherwise false
     */
    Common.isElement = function(obj) {
        // http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object
        try {
            return obj instanceof HTMLElement;
        }
        catch(e){
            return (typeof obj==="object") &&
              (obj.nodeType===1) && (typeof obj.style === "object") &&
              (typeof obj.ownerDocument ==="object");
        }
    };

    /**
     * Description
     * @method clamp
     * @param {number} value
     * @param {number} min
     * @param {number} max
     * @return {number} The value clamped between min and max inclusive
     */
    Common.clamp = function(value, min, max) {
        if (value < min)
            return min;
        if (value > max)
            return max;
        return value;
    };

    /**
     * Description
     * @method sign
     * @param {number} value
     * @return {number} -1 if negative, +1 if 0 or positive
     */
    Common.sign = function(value) {
        return value < 0 ? -1 : 1;
    };

    /**
     * Description
     * @method now
     * @return {Date} the current DateTime
     */
    Common.now = Date.now || function() {
        // http://stackoverflow.com/questions/221294/how-do-you-get-a-timestamp-in-javascript
        return +(new Date());
    };

    /**
     * Description
     * @method random
     * @param {number} min
     * @param {number} max
     * @return {number} A random number between min and max inclusive
     */
    Common.random = function(min, max) {
        return min + Math.random() * (max - min);
    };

})();<commit_msg>added clone method to common, extend now has option to disable deep<commit_after>/**
* _Internal Class_, not generally used outside of the engine's internals.
*
* @class Common
*/

var Common = {};

(function() {

    /**
     * Description
     * @method extend
     * @param {} obj
     * @param {boolean} deep
     * @return {} obj extended
     */
    Common.extend = function(obj, deep) {
        var argsStart,
            args,
            deepClone;

        if (typeof deep === 'boolean') {
            argsStart = 2;
            deepClone = deep;
        } else {
            argsStart = 1;
            deepClone = true;
        }

        args = Array.prototype.slice.call(arguments, argsStart);

        for (var i = 0; i < args.length; i++) {
            var source = args[i];

            if (source) {
                for (var prop in source) {
                    if (deepClone && source[prop].constructor === Object) {
                        if (!obj[prop] || obj[prop].constructor === Object) {
                            obj[prop] = obj[prop] || {};
                            Common.extend(obj[prop], deepClone, source[prop]);
                        } else {
                            obj[prop] = source[prop];
                        }
                    } else {
                        obj[prop] = source[prop];
                    }
                }
            }
        }

        return obj;
    };

    /**
     * Creates a new clone of the object, if deep is true references will also be cloned
     * @method clone
     * @param {} obj
     * @param {bool} deep
     * @return {} obj cloned
     */
    Common.clone = function(obj, deep) {
        return Common.extend({}, deep, obj);
    };

    /**
     * Description
     * @method keys
     * @param {} obj
     * @return {string[]} keys
     */
    Common.keys = function(obj) {
        if (Object.keys)
            return Object.keys(obj);

        // avoid hasOwnProperty for performance
        var keys = [];
        for (var key in obj)
            keys.push(key);
        return keys;
    };

    /**
     * Description
     * @method values
     * @param {} obj
     * @return {array} Array of the objects property values
     */
    Common.values = function(obj) {
        var values = [];

        if (Object.keys) {
            var keys = Object.keys(obj);
            for (var i = 0; i < keys.length; i++) {
                values.push(obj[keys[i]]);
            }
            return values;
        }

        // avoid hasOwnProperty for performance
        for (var key in obj)
            values.push(obj[key]);
        return values;
    };

    /**
     * Description
     * @method shadeColor
     * @param {string} color
     * @param {number} percent
     * @return {string} A hex colour string made by lightening or darkening color by percent
     */
    Common.shadeColor = function(color, percent) {
        // http://stackoverflow.com/questions/5560248/programmatically-lighten-or-darken-a-hex-color
        var colorInteger = parseInt(color.slice(1),16),
            amount = Math.round(2.55 * percent),
            R = (colorInteger >> 16) + amount,
            B = (colorInteger >> 8 & 0x00FF) + amount,
            G = (colorInteger & 0x0000FF) + amount;
        return "#" + (0x1000000 + (R < 255 ? R < 1 ? 0 : R :255) * 0x10000
                + (B < 255 ? B < 1 ? 0 : B : 255) * 0x100
                + (G < 255 ? G < 1 ? 0 : G : 255)).toString(16).slice(1);
    };

    /**
     * Description
     * @method shuffle
     * @param {array} array
     * @return {array} array shuffled randomly
     */
    Common.shuffle = function(array) {
        for (var i = array.length - 1; i > 0; i--) {
            var j = Math.floor(Math.random() * (i + 1));
            var temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
        return array;
    };

    /**
     * Description
     * @method choose
     * @param {array} choices
     * @return {object} A random choice object from the array
     */
    Common.choose = function(choices) {
        return choices[Math.floor(Math.random() * choices.length)];
    };

    /**
     * Description
     * @method isElement
     * @param {object} obj
     * @return {boolean} True if the object is a HTMLElement, otherwise false
     */
    Common.isElement = function(obj) {
        // http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object
        try {
            return obj instanceof HTMLElement;
        }
        catch(e){
            return (typeof obj==="object") &&
              (obj.nodeType===1) && (typeof obj.style === "object") &&
              (typeof obj.ownerDocument ==="object");
        }
    };

    /**
     * Description
     * @method clamp
     * @param {number} value
     * @param {number} min
     * @param {number} max
     * @return {number} The value clamped between min and max inclusive
     */
    Common.clamp = function(value, min, max) {
        if (value < min)
            return min;
        if (value > max)
            return max;
        return value;
    };

    /**
     * Description
     * @method sign
     * @param {number} value
     * @return {number} -1 if negative, +1 if 0 or positive
     */
    Common.sign = function(value) {
        return value < 0 ? -1 : 1;
    };

    /**
     * Description
     * @method now
     * @return {Date} the current DateTime
     */
    Common.now = Date.now || function() {
        // http://stackoverflow.com/questions/221294/how-do-you-get-a-timestamp-in-javascript
        return +(new Date());
    };

    /**
     * Description
     * @method random
     * @param {number} min
     * @param {number} max
     * @return {number} A random number between min and max inclusive
     */
    Common.random = function(min, max) {
        return min + Math.random() * (max - min);
    };

})();<|endoftext|>


<commit_before>import querystring from 'querystring';
import fetch from 'cross-fetch';
import { btoa, removeUndefined } from '../../utils/index';

/**
 * To perform fetch request
 * @param {Object} args
 * @param {String} args.method
 * @param {String} args.path
 * @param {Object} args.params
 * @param {Object} args.body
 */
function fetchRequest(args) {
  return new Promise((resolve, reject) => {
    const parsedArgs = removeUndefined(args);
    try {
      const {
 method, path, params, body,
} = parsedArgs;
      let bodyCopy = body;
      const contentType = path.endsWith('msearch') || path.endsWith('bulk')
          ? 'application/x-ndjson'
          : 'application/json';
      const headers = Object.assign(
        {},
        {
          Accept: 'application/json',
          'Content-Type': contentType,
        },
        this.headers,
      );
      const timestamp = Date.now();
      if (this.credentials) {
        headers.Authorization = `Basic ${btoa(this.credentials)}`;
      }
      const requestOptions = {
        method,
        headers,
      };
      if (Array.isArray(bodyCopy)) {
        let arrayBody = '';
        bodyCopy.forEach((item) => {
          arrayBody += JSON.stringify(item);
          arrayBody += '\n';
        });

        bodyCopy = arrayBody;
      } else {
        bodyCopy = JSON.stringify(bodyCopy) || {};
      }

      if (Object.keys(bodyCopy).length !== 0) {
        requestOptions.body = bodyCopy;
      }

      const handleTransformRequest = (res) => {
        if (this.transformRequest && typeof this.transformRequest === 'function') {
          const tarnsformRequestPromise = this.transformRequest(res);
          return tarnsformRequestPromise instanceof Promise
            ? tarnsformRequestPromise
            : Promise.resolve(tarnsformRequestPromise);
        }
        return Promise.resolve(res);
      };

      let responseHeaders = {};

      let paramsString = '';
      if (params) {
        paramsString = `?${querystring.stringify(
          params,
        )}`;
      }
      const finalURL = `${this.protocol}://${this.url}/${this.app}/${path}${paramsString}`;
      return handleTransformRequest(
        Object.assign(
          {},
          {
            url: finalURL,
          },
          requestOptions,
        ),
      )
        .then((ts) => {
          const transformedRequest = Object.assign({}, ts);
          const { url } = transformedRequest;
          delete transformedRequest.url;
          return fetch(url || finalURL, transformedRequest)
            .then((res) => {
              if (res.status >= 500) {
                return reject(res);
              }
              responseHeaders = res.headers;
              return res.json().then((data) => {
                if (res.status >= 400) {
                  return reject(res);
                }
                // Handle error from RS API RESPONSE
                if (data && Object.prototype.toString.call(data) === '[object Object]') {
                  // Object.keys(data).forEach(entry => )
                  let allResponses;
                  let errorResponses = 0;
                  if (body.query) {
                    allResponses = body.query.length;
                    body.query.forEach((query) => {
                      if (data[query.id] && Object.prototype.hasOwnProperty.call(data[query.id], 'error')) {
                        errorResponses += 1;
                      }
                    });
                  }
                  // reject only when all responses has error
                  if (allResponses === errorResponses) {
                    return reject(data);
                  }
                }

                // Handle error from _msearch response
                if (data && data.responses instanceof Array) {
                  const allResponses = data.responses.length;
                  const errorResponses = data.responses.filter(entry => Object.prototype.hasOwnProperty.call(entry, 'error')).length;
                  // reject only when all responses has error
                  if (allResponses === errorResponses) {
                    return reject(data);
                  }
                }
                const response = Object.assign({}, data, {
                  _timestamp: timestamp,
                  _headers: responseHeaders,
                });
                return resolve(response);
              });
            })
            .catch(e => reject(e));
        })
        .catch(err => reject(err));
    } catch (e) {
      return reject(e);
    }
  });
}
export default fetchRequest;
<commit_msg>fix: error handling with reactivesearch route<commit_after>import querystring from 'querystring';
import fetch from 'cross-fetch';
import { btoa, removeUndefined } from '../../utils/index';

/**
 * To perform fetch request
 * @param {Object} args
 * @param {String} args.method
 * @param {String} args.path
 * @param {Object} args.params
 * @param {Object} args.body
 */
function fetchRequest(args) {
  return new Promise((resolve, reject) => {
    const parsedArgs = removeUndefined(args);
    try {
      const {
 method, path, params, body,
} = parsedArgs;
      let bodyCopy = body;
      const contentType = path.endsWith('msearch') || path.endsWith('bulk')
          ? 'application/x-ndjson'
          : 'application/json';
      const headers = Object.assign(
        {},
        {
          Accept: 'application/json',
          'Content-Type': contentType,
        },
        this.headers,
      );
      const timestamp = Date.now();
      if (this.credentials) {
        headers.Authorization = `Basic ${btoa(this.credentials)}`;
      }
      const requestOptions = {
        method,
        headers,
      };
      if (Array.isArray(bodyCopy)) {
        let arrayBody = '';
        bodyCopy.forEach((item) => {
          arrayBody += JSON.stringify(item);
          arrayBody += '\n';
        });

        bodyCopy = arrayBody;
      } else {
        bodyCopy = JSON.stringify(bodyCopy) || {};
      }

      if (Object.keys(bodyCopy).length !== 0) {
        requestOptions.body = bodyCopy;
      }

      const handleTransformRequest = (res) => {
        if (
          this.transformRequest
          && typeof this.transformRequest === 'function'
        ) {
          const tarnsformRequestPromise = this.transformRequest(res);
          return tarnsformRequestPromise instanceof Promise
            ? tarnsformRequestPromise
            : Promise.resolve(tarnsformRequestPromise);
        }
        return Promise.resolve(res);
      };

      let responseHeaders = {};

      let paramsString = '';
      if (params) {
        paramsString = `?${querystring.stringify(params)}`;
      }
      const finalURL = `${this.protocol}://${this.url}/${this.app}/${path}${paramsString}`;
      return handleTransformRequest(
        Object.assign(
          {},
          {
            url: finalURL,
          },
          requestOptions,
        ),
      )
        .then((ts) => {
          const transformedRequest = Object.assign({}, ts);
          const { url } = transformedRequest;
          delete transformedRequest.url;
          return fetch(url || finalURL, transformedRequest)
            .then((res) => {
              if (res.status >= 500) {
                return reject(res);
              }
              responseHeaders = res.headers;
              return res.json().then((data) => {
                if (res.status >= 400) {
                  return reject(res);
                }
                if (data && data.error) {
                  return reject(data);
                }
                // Handle error from RS API RESPONSE
                if (
                  data
                  && Object.prototype.toString.call(data) === '[object Object]'
                ) {
                  // Object.keys(data).forEach(entry => )
                  let allResponses = 0;
                  let errorResponses = 0;
                  if (body.query) {
                    allResponses = body.query.filter(
                      q => q.execute || q.execute === undefined,
                    ).length;
                  }
                  if (data) {
                    Object.keys(data).forEach((key) => {
                      if (
                        data[key]
                        && Object.prototype.hasOwnProperty.call(data[key], 'error')
                      ) {
                        errorResponses += 1;
                      }
                    });
                  }
                  // reject only when all responses has error
                  if (allResponses === errorResponses) {
                    return reject(data);
                  }
                }

                // Handle error from _msearch response
                if (data && data.responses instanceof Array) {
                  const allResponses = data.responses.length;
                  const errorResponses = data.responses.filter(entry => Object.prototype.hasOwnProperty.call(entry, 'error')).length;
                  // reject only when all responses has error
                  if (allResponses === errorResponses) {
                    return reject(data);
                  }
                }
                const response = Object.assign({}, data, {
                  _timestamp: timestamp,
                  _headers: responseHeaders,
                });
                return resolve(response);
              });
            })
            .catch(e => reject(e));
        })
        .catch(err => reject(err));
    } catch (e) {
      return reject(e);
    }
  });
}
export default fetchRequest;
<|endoftext|>


<commit_before>import fs from 'fs';
import path from 'path';

import {cloneRepository, buildRepository, setUpLocalAndRemoteRepositories} from '../helpers';

import FileSystemChangeObserver from '../../lib/models/file-system-change-observer';

describe('FileSystemChangeObserver', function() {
  let observer, changeSpy;

  beforeEach(function() {
    changeSpy = sinon.spy();
  });

  function createObserver(repository) {
    observer = new FileSystemChangeObserver(repository);
    observer.onDidChange(changeSpy);
    return observer;
  }

  afterEach(async function() {
    if (observer) {
      await observer.destroy();
    }
  });

  it('emits an event when a project file is modified, created, or deleted', async function() {
    const workdirPath = await cloneRepository('three-files');
    const repository = await buildRepository(workdirPath);
    observer = createObserver(repository);
    await observer.start();

    fs.writeFileSync(path.join(workdirPath, 'a.txt'), 'a change\n');
    await assert.async.isTrue(changeSpy.called);

    changeSpy.resetHistory();
    fs.writeFileSync(path.join(workdirPath, 'new-file.txt'), 'a change\n');
    await assert.async.isTrue(changeSpy.called);

    changeSpy.resetHistory();
    fs.unlinkSync(path.join(workdirPath, 'a.txt'));
    await assert.async.isTrue(changeSpy.called);
  });

  it('emits an event when a file is staged or unstaged', async function() {
    const workdirPath = await cloneRepository('three-files');
    const repository = await buildRepository(workdirPath);
    observer = createObserver(repository);
    await observer.start();

    fs.writeFileSync(path.join(workdirPath, 'a.txt'), 'a change\n');
    await repository.git.exec(['add', 'a.txt']);
    await assert.async.isTrue(changeSpy.called);

    changeSpy.resetHistory();
    await repository.git.exec(['reset', 'a.txt']);
    await assert.async.isTrue(changeSpy.called);
  });

  it('emits an event when a branch is checked out', async function() {
    const workdirPath = await cloneRepository('three-files');
    const repository = await buildRepository(workdirPath);
    observer = createObserver(repository);
    await observer.start();

    await repository.git.exec(['checkout', '-b', 'new-branch']);
    await assert.async.isTrue(changeSpy.called);
  });

  it('emits an event when commits are pushed', async function() {
    const {localRepoPath} = await setUpLocalAndRemoteRepositories();
    const repository = await buildRepository(localRepoPath);
    observer = createObserver(repository);
    await observer.start();

    await repository.git.exec(['commit', '--allow-empty', '-m', 'new commit']);

    changeSpy.resetHistory();
    await repository.git.exec(['push', 'origin', 'master']);
    await assert.async.isTrue(changeSpy.called);
  });

  it('emits an event when a new tracking branch is added after pushing', async function() {
    const {localRepoPath} = await setUpLocalAndRemoteRepositories();
    const repository = await buildRepository(localRepoPath);
    observer = createObserver(repository);
    await observer.start();

    await repository.git.exec(['checkout', '-b', 'new-branch']);

    changeSpy.resetHistory();
    await repository.git.exec(['push', '--set-upstream', 'origin', 'new-branch']);
    await assert.async.isTrue(changeSpy.called);
  });

  it('emits an event when commits have been fetched', async function() {
    const {localRepoPath} = await setUpLocalAndRemoteRepositories({remoteAhead: true});
    const repository = await buildRepository(localRepoPath);
    observer = createObserver(repository);
    await observer.start();

    await repository.git.exec(['fetch', 'origin', 'master']);
    await assert.async.isTrue(changeSpy.called);
  });
});
<commit_msg>Stress-test that flaky test<commit_after>import fs from 'fs';
import path from 'path';

import {cloneRepository, buildRepository, setUpLocalAndRemoteRepositories} from '../helpers';

import FileSystemChangeObserver from '../../lib/models/file-system-change-observer';

describe('FileSystemChangeObserver', function() {
  let observer, changeSpy;

  beforeEach(function() {
    changeSpy = sinon.spy();
  });

  function createObserver(repository) {
    observer = new FileSystemChangeObserver(repository);
    observer.onDidChange(changeSpy);
    return observer;
  }

  afterEach(async function() {
    if (observer) {
      await observer.destroy();
    }
  });

  it.stress(50, 'emits an event when a project file is modified, created, or deleted', async function() {
    const workdirPath = await cloneRepository('three-files');
    const repository = await buildRepository(workdirPath);
    observer = createObserver(repository);
    await observer.start();

    fs.writeFileSync(path.join(workdirPath, 'a.txt'), 'a change\n');
    await assert.async.isTrue(changeSpy.called);

    changeSpy.resetHistory();
    fs.writeFileSync(path.join(workdirPath, 'new-file.txt'), 'a change\n');
    await assert.async.isTrue(changeSpy.called);

    changeSpy.resetHistory();
    fs.unlinkSync(path.join(workdirPath, 'a.txt'));
    await assert.async.isTrue(changeSpy.called);
  });

  it('emits an event when a file is staged or unstaged', async function() {
    const workdirPath = await cloneRepository('three-files');
    const repository = await buildRepository(workdirPath);
    observer = createObserver(repository);
    await observer.start();

    fs.writeFileSync(path.join(workdirPath, 'a.txt'), 'a change\n');
    await repository.git.exec(['add', 'a.txt']);
    await assert.async.isTrue(changeSpy.called);

    changeSpy.resetHistory();
    await repository.git.exec(['reset', 'a.txt']);
    await assert.async.isTrue(changeSpy.called);
  });

  it('emits an event when a branch is checked out', async function() {
    const workdirPath = await cloneRepository('three-files');
    const repository = await buildRepository(workdirPath);
    observer = createObserver(repository);
    await observer.start();

    await repository.git.exec(['checkout', '-b', 'new-branch']);
    await assert.async.isTrue(changeSpy.called);
  });

  it('emits an event when commits are pushed', async function() {
    const {localRepoPath} = await setUpLocalAndRemoteRepositories();
    const repository = await buildRepository(localRepoPath);
    observer = createObserver(repository);
    await observer.start();

    await repository.git.exec(['commit', '--allow-empty', '-m', 'new commit']);

    changeSpy.resetHistory();
    await repository.git.exec(['push', 'origin', 'master']);
    await assert.async.isTrue(changeSpy.called);
  });

  it('emits an event when a new tracking branch is added after pushing', async function() {
    const {localRepoPath} = await setUpLocalAndRemoteRepositories();
    const repository = await buildRepository(localRepoPath);
    observer = createObserver(repository);
    await observer.start();

    await repository.git.exec(['checkout', '-b', 'new-branch']);

    changeSpy.resetHistory();
    await repository.git.exec(['push', '--set-upstream', 'origin', 'new-branch']);
    await assert.async.isTrue(changeSpy.called);
  });

  it('emits an event when commits have been fetched', async function() {
    const {localRepoPath} = await setUpLocalAndRemoteRepositories({remoteAhead: true});
    const repository = await buildRepository(localRepoPath);
    observer = createObserver(repository);
    await observer.start();

    await repository.git.exec(['fetch', 'origin', 'master']);
    await assert.async.isTrue(changeSpy.called);
  });
});
<|endoftext|>


<commit_before>var fs = require('fs')
var path = require('path')
var packager = require('electron-packager')
var fse = require('fs-extra')
var spawn = require('child_process').spawn
var platform = require('os').platform()
var zipFolder = require('zip-folder')

var compiler = require('electron-compile')

var paths = {
  packageJson: path.join(__dirname, 'package.json'),
  cache      : path.join(__dirname, 'cache')
}

var pathModule = 'node_modules/wcjs-player/node_modules/wcjs-renderer/node_modules/'
var webchimera = {
  darwin: {
    path: `/PelisTime.app/Contents/Resources/app/${pathModule}`,
    ico : 'img/osx.icns',
    arch: 'x64'
  },
  win32 : {
    path: `/resources/app/${pathModule}`,
    ico : 'img/windows.ico',
    arch: 'all'
  },
  linux : {
    path: `/resources/app/${pathModule}`,
    ico : 'img/windows.ico',
    arch: 'x64'
  }
}

var packageJson = JSON.parse(fs.readFileSync(paths.packageJson, 'utf8'))
var arrayModules = Object.keys(packageJson.dependencies).map(function(dependencie) { return `node_modules/${dependencie}` })
var accetedModules = 'wcjs-player|peerflix|read-torrent|torrent-health|q'

var nodeModuleIgnores = [ 'js', 'binVideo', 'css', 'dist', 'docs', 'fonts', 'img' ].concat(arrayModules)

compiler.init(paths.cache)
compiler.compileAll('static')
fs.writeFileSync(
  path.join(paths.cache, 'settings.json'),
  JSON.stringify(compiler.collectCompilerInformation())
)

packager({
  dir             : '.',
  name            : packageJson.name,
  platform        : platform,
  icon            : webchimera[ platform ].ico,
  arch            : webchimera[ platform ].arch,
  version         : require('electron-prebuilt/package.json').version,
  'build-version' : packageJson.version,
  'version-string': {
    CompanyName   : 'PelisTime inc.',
    InternalName  : packageJson.name,
    ProductName   : packageJson.name,
    ProductVersion: require('electron-prebuilt/package.json').version
  },
  overwrite       : true,
  prune           : true,
  ignore          : new RegExp(`^/(?!node_modules/(${accetedModules}))(${nodeModuleIgnores.join('|')})$`),
  // asar: true,
  out             : 'dist'
}, function(err, appPath) {
  if (err) return console.error(err)
  appPath.forEach(function(dir) {
    if(dir.indexOf('linux') !== -1) {
      var unzip = require('unzip')
      fs.createReadStream('./binVideo/linux-64bits.zip').pipe(unzip.Extract({ path: `./${dir}${webchimera[ platform ].path}webchimera.js/Release/` }))
      zipFolder(`./${dir}`, './dist/Pelistime-linux-64bits.zip', function(err) {
        if(err)
          console.log('error')
        else
          console.log('finished')
      })
    }else {
      fse.remove(`${dir}${webchimera[ platform ].path}webchimera.js/`, function(err) {
        if(dir.indexOf('darwin') !== -1) {
          var unzip  = spawn('unzip', [ './binVideo/osx-64bits.zip', '-d', `${dir}${webchimera[ platform ].path}` ])
          unzip.stdout.on('data', function(output) {
            console.log('data: ', output.toString('utf8'))
          })
          unzip.stderr.on('data', function(err) {
            console.log('Error: ', err.toString('utf8'))
          })
          unzip.on('exit', function(code) {
            console.log('Package osx finished.')
          })
        }else if(dir.indexOf('win32') !== -1) {
          var unzip = require('unzip')
          if(dir.indexOf('ia32') !== -1) {
            fs.createReadStream('./binVideo/win-ia32.zip').pipe(unzip.Extract({ path: `./${dir}${webchimera[ platform ].path}` }))
          }else {
            fs.createReadStream('./binVideo/win-64bits.zip').pipe(unzip.Extract({ path: `./${dir}${webchimera[ platform ].path}` }))
          }
        }
      })
    }
  })
})

<commit_msg>[ ADD ] automatic binaries download support<commit_after>var fs = require('fs')
var Q = require('q')
var url = require('url')
var path = require('path')
var https = require('https')
var packager = require('electron-packager')
var fse = require('fs-extra')
var spawn = require('child_process').spawn
var platform = require('os').platform()
var zipFolder = require('zip-folder')
var compiler = require('electron-compile')

function downloadAsync(downloadFile, path) {
  return Q.Promise(function(resolve, reject) {
    download(downloadFile, path, function(err, done) {
      err ? reject(err) : resolve(done)
    })
  })
}

function download(downloadFile, path, cb) {
  var host = url.parse(downloadFile).hostname
  var pathname = url.parse(downloadFile).path

  var dlprogress = 0
  var total = 0
  var intervalo
  var content = ''

  https.request({
    hostname: host,
    path    : pathname,
    agent   : false
  }, function(res) {
    if(res.statusCode == 302) {
      return download(res.headers.location, path, cb)
    }else if(res.statusCode != 200) {
      return cb('non-OK status: ' + res.statusCode)
    }

    res.setEncoding('binary')

    total = res.headers[ 'content-length' ]

    intervalo = setInterval(function() {
      // console.log('Download progress: ' + dlprogress + ' bytes')
      console.log((dlprogress * 100 / total).toFixed(0) + '%')
      if(dlprogress == total) {
        clearInterval(intervalo)
      }
    }, 1000)

    res.on('data', function(chunk) {
      dlprogress += chunk.length
      content += chunk
    })

    res.on('end', function() {
      fs.writeFile(path, content, 'binary', function(err) {
        if(err) return cb(err)
        else {
          clearInterval(intervalo)
          cb(null, 'done')
        }
      })
    })
  }).on('error', function(err) {
    cb(err)
  }).end()
}

var paths = {
  packageJson: path.join(__dirname, 'package.json'),
  cache      : path.join(__dirname, 'cache')
}

var pathModule = 'node_modules/wcjs-player/node_modules/wcjs-renderer/node_modules/'
var listSourcesWebchimera = {
  darwin: {
    path : `/PelisTime.app/Contents/Resources/app/${pathModule}`,
    ico  : 'img/osx.icns',
    arch : 'x64',
    bin64: './binVideo/osx-64bits.zip',
    url  : 'https://github.com/ghondar/PelisTime/releases/download/V1.0.3/osx-64bits.zip'
  },
  win32 : {
    path : `/resources/app/${pathModule}`,
    ico  : 'img/windows.ico',
    arch : 'all',
    bin32: './binVideo/win-ia32.zip',
    bin64: './binVideo/win-64bits.zip'
  },
  linux : {
    path : `/resources/app/${pathModule}`,
    ico  : 'img/windows.ico',
    arch : 'x64',
    bin64: './dist/Pelistime-linux-64bits.zip',
    url  : 'https://github.com/ghondar/PelisTime/releases/download/V1.0.3/linux-64bits.zip'
  }
}

var sourceWebchimera = listSourcesWebchimera[ platform ]

var packageJson = JSON.parse(fs.readFileSync(paths.packageJson, 'utf8'))
var arrayModules = Object.keys(packageJson.dependencies).map(function(dependencie) { return `node_modules/${dependencie}` })
var accetedModules = 'wcjs-player|peerflix|read-torrent|torrent-health|q'

var nodeModuleIgnores = [ 'js', 'binVideo', 'css', 'dist', 'docs', 'fonts', 'img' ].concat(arrayModules)

compiler.init(paths.cache)
compiler.compileAll('static')
fs.writeFileSync(
  path.join(paths.cache, 'settings.json'),
  JSON.stringify(compiler.collectCompilerInformation())
)

packager({
  dir             : '.',
  name            : packageJson.name,
  platform        : platform,
  icon            : sourceWebchimera.ico,
  arch            : sourceWebchimera.arch,
  version         : require('electron-prebuilt/package.json').version,
  'build-version' : packageJson.version,
  'version-string': {
    CompanyName   : 'PelisTime inc.',
    InternalName  : packageJson.name,
    ProductName   : packageJson.name,
    ProductVersion: require('electron-prebuilt/package.json').version
  },
  overwrite       : true,
  prune           : true,
  ignore          : new RegExp(`^/(?!node_modules/(${accetedModules}))(${nodeModuleIgnores.join('|')})$`),
  // asar: true,
  out             : 'dist'
}, function(err, appPath) {
  if (err) return console.error(err)
  appPath.forEach(function(dir) {
    if(dir.indexOf('linux') !== -1) {
      var unzip = require('unzip')
      Q.nfcall(fs.stat, sourceWebchimera.bin64)
        .catch(() => downloadAsync(sourceWebchimera.url, sourceWebchimera.bin64))
        .finally(() => {
          var extract = fs.createReadStream(sourceWebchimera.bin64).pipe(unzip.Extract({ path: `./${dir}${sourceWebchimera.path}webchimera.js/Release/` }))
          extract.on('close', function() {
            zipFolder(`./${dir}`, './dist/Pelistime-linux-64bits.zip', function(err) {
              console.log(err ? err : 'finished')
            })
          })
        })
    }else {
      Q.nfcall(fse.remove, `${dir}${sourceWebchimera.path}webchimera.js/`)
        .then(() => {
          if(dir.indexOf('darwin') !== -1) {
            Q.nfcall(fs.stat, sourceWebchimera.bin64)
              .catch(() => downloadAsync(sourceWebchimera.url, sourceWebchimera.bin64))
              .finally(() => {
                var unzip  = spawn('unzip', [ sourceWebchimera.bin64, '-d', `${dir}${sourceWebchimera.path}` ])
                unzip.stdout.on('data', output => {
                  console.log('data: ', output.toString('utf8'))
                })
                unzip.stderr.on('data', err => {
                  console.log('Error: ', err.toString('utf8'))
                })
                unzip.on('exit', code => {
                  console.log('Package osx finished.')
                })
              })
          }else if(dir.indexOf('win32') !== -1) {
            var unzip = require('unzip')
            fs.createReadStream(sourceWebchimera[ dir.indexOf('ia32') !== -1 ? 'bin32' : 'bin64' ])
              .pipe(unzip.Extract({ path: `./${dir}${sourceWebchimera.path}` }))
          }
        })
        .catch(err => {
          console.log(err)
        })
    }
  })
})

<|endoftext|>


<commit_before>define(function (require) {

  var Utils = require('./Utils'),
      Router = require('../Router'),
      Constants = require('constants/QuotaRequestConstants'),
      QuotaRequest = require('models/QuotaRequest');

  return {
    update: function(params) {
      var request = params.request,
          response = params.response,
          quota = params.quota,
          status = params.status;

      var newAttributes = {
        admin_message: response,
        quota: quota,
        status: status
      };

      request.set(newAttributes);
      Router.getInstance().transitionTo("admin");
      request.save(newAttributes, {patch: true}).done(function() {
        Utils.dispatch(Constants.UPDATE, {model: request});
        Utils.dispatch(Constants.REMOVE, {model: request});
      });
    }
  };

});
<commit_msg>Removed "QuotaActions." Replaced with ResourceActions<commit_after><|endoftext|>


<commit_before>/* global Promise, screen */
var initMetaTags = require('./metaTags').inject;
var initWakelock = require('./wakelock');
var re = require('../a-register-element');
var systems = require('../system').systems;
var THREE = require('../../lib/three');
var TWEEN = require('tween.js');
var utils = require('../../utils/');
// Require after.
var AEntity = require('../a-entity');
var ANode = require('../a-node');
var initPostMessageAPI = require('./postMessage');

var bind = utils.bind;
var checkHeadsetConnected = utils.checkHeadsetConnected;
var registerElement = re.registerElement;
var isIOS = utils.isIOS();
var isMobile = utils.isMobile();
var warn = utils.debug('core:a-scene:warn');

/**
 * Scene element, holds all entities.
 *
 * @member {number} animationFrameID
 * @member {array} behaviors - Component instances that have registered themselves to be
           updated on every tick.
 * @member {object} camera - three.js Camera object.
 * @member {object} canvas
 * @member {bool} isScene - Differentiates as scene entity as opposed to other entites.
 * @member {bool} isMobile - Whether browser is mobile (via UA detection).
 * @member {object} object3D - Root three.js Scene object.
 * @member {object} renderer
 * @member {bool} renderStarted
 * @member (object) effect - three.js VREffect
 * @member {object} systems - Registered instantiated systems.
 * @member {number} time
 */
module.exports = registerElement('a-scene', {
  prototype: Object.create(AEntity.prototype, {
    defaultComponents: {
      value: {
        'canvas': '',
        'inspector': '',
        'keyboard-shortcuts': '',
        'vr-mode-ui': ''
      }
    },

    createdCallback: {
      value: function () {
        this.isIOS = isIOS;
        this.isMobile = isMobile;
        this.isScene = true;
        this.object3D = new THREE.Scene();
        this.render = bind(this.render, this);
        this.systems = {};
        this.time = 0;

        this.init();
      }
    },

    init: {
      value: function () {
        this.behaviors = [];
        this.hasLoaded = false;
        this.isPlaying = false;
        this.originalHTML = this.innerHTML;
        this.addEventListener('render-target-loaded', function () {
          this.setupRenderer();
          this.resize();
        });
        this.addFullScreenStyles();
        initPostMessageAPI(this);
      },
      writable: true
    },

    addFullScreenStyles: {
      value: function () {
        var htmlEl = document.documentElement;
        htmlEl.classList.add('a-html');
        document.body.classList.add('a-body');
        this.classList.add('fullscreen');
      }
    },

    removeFullScreenStyles: {
      value: function () {
        var htmlEl = document.documentElement;
        htmlEl.classList.remove('a-html');
        document.body.classList.remove('a-body');
        this.classList.remove('fullscreen');
      }
    },

    attachedCallback: {
      value: function () {
        var resize = bind(this.resize, this);
        initMetaTags(this);
        initWakelock(this);
        this.initSystems();

        window.addEventListener('load', resize);
        window.addEventListener('resize', resize);
        this.play();
      },
      writable: window.debug
    },

    initSystems: {
      value: function () {
        Object.keys(systems).forEach(bind(this.initSystem, this));
      }
    },

    initSystem: {
      value: function (name) {
        var system;
        if (this.systems[name]) { return; }
        system = this.systems[name] = new systems[name](this);
        system.init();
      }
    },

    /**
     * Shuts down scene on detach.
     */
    detachedCallback: {
      value: function () {
        window.cancelAnimationFrame(this.animationFrameID);
        this.animationFrameID = null;
      }
    },

    /**
     * @param {object} behavior - Generally a component. Must implement a .update() method to
     *        be called on every tick.
     */
    addBehavior: {
      value: function (behavior) {
        var behaviors = this.behaviors;
        if (behaviors.indexOf(behavior) !== -1) { return; }
        behaviors.push(behavior);
      }
    },

    enterVR: {
      value: function (event) {
        var self = this;
        if (this.is('vr-mode')) { return; }
        if (checkHeadsetConnected() || this.isMobile) {
          return this.effect.requestPresent().then(enterVRSuccess, enterVRFailure);
        }
        enterVRSuccess();

        function enterVRSuccess () {
          self.addState('vr-mode');
          self.emit('enter-vr', event);

          // Lock to landscape orientation on mobile.
          if (self.isMobile && screen.orientation && screen.orientation.lock) {
            screen.orientation.lock('landscape');
          }
          self.addFullScreenStyles();

          // On mobile, the polyfill handles fullscreen.
          // TODO: 07/16 Chromium builds break when `requestFullscreen`ing on a canvas
          // that we are also `requestPresent`ing. Until then, don't fullscreen if headset
          // connected.
          if (!self.isMobile && !checkHeadsetConnected()) { requestFullscreen(self.canvas); }
          self.resize();
        }

        function enterVRFailure (err) {
          if (err && err.message) {
            throw new Error('Failed to enter VR mode (`requestPresent`): ' + err.message);
          } else {
            throw new Error('Failed to enter VR mode (`requestPresent`).');
          }
        }
      }
    },

    exitVR: {
      value: function () {
        var self = this;
        if (!this.is('vr-mode')) { return Promise.resolve(); }
        if (checkHeadsetConnected() || this.isMobile) {
          return this.effect.exitPresent().then(exitVRSuccess, exitVRFailure);
        }
        exitVRSuccess();
        function exitVRSuccess () {
          var embedded = self.getAttribute('embedded');
          self.removeState('vr-mode');
          // Lock to landscape orientation on mobile.
          if (self.isMobile && screen.orientation && screen.orientation.unlock) {
            screen.orientation.unlock();
          }
          // Exiting VR in embedded mode, no longer need fullscreen styles.
          if (embedded) { self.removeFullScreenStyles(); }
          self.resize();
          if (self.isIOS) { utils.forceCanvasResizeSafariMobile(this.canvas); }
          self.emit('exit-vr', {target: self});
        }
        function exitVRFailure (err) {
          if (err && err.message) {
            throw new Error('Failed to exit VR mode (`exitPresent`): ' + err.message);
          } else {
            throw new Error('Failed to exit VR mode (`exitPresent`).');
          }
        }
      }
    },

    /**
     * Wraps Entity.getAttribute to take into account for systems.
     * If system exists, then return system data rather than possible component data.
     */
    getAttribute: {
      value: function (attr) {
        var system = this.systems[attr];
        if (system) { return system.data; }
        return AEntity.prototype.getAttribute.call(this, attr);
      }
    },

    /**
     * `getAttribute` used to be `getDOMAttribute` and `getComputedAttribute` used to be
     * what `getAttribute` is now. Now legacy code.
     */
    getComputedAttribute: {
      value: function (attr) {
        warn('`getComputedAttribute` is deprecated. Use `getAttribute` instead.');
        this.getAttribute(attr);
      }
    },

    /**
     * Wraps Entity.getDOMAttribute to take into account for systems.
     * If system exists, then return system data rather than possible component data.
     */
    getDOMAttribute: {
      value: function (attr) {
        var system = this.systems[attr];
        if (system) { return system.data; }
        return AEntity.prototype.getDOMAttribute.call(this, attr);
      }
    },

    /**
     * Wraps Entity.setAttribute to take into account for systems.
     * If system exists, then skip component initialization checks and do a normal
     * setAttribute.
     */
    setAttribute: {
      value: function (attr, value, componentPropValue) {
        var system = this.systems[attr];
        if (system) {
          ANode.prototype.setAttribute.call(this, attr, value);
          return;
        }
        AEntity.prototype.setAttribute.call(this, attr, value, componentPropValue);
      }
    },

    /**
     * @param {object} behavior - Generally a component. Has registered itself to behaviors.
     */
    removeBehavior: {
      value: function (behavior) {
        var behaviors = this.behaviors;
        var index = behaviors.indexOf(behavior);
        if (index === -1) { return; }
        behaviors.splice(index, 1);
      }
    },

    resize: {
      value: function () {
        var camera = this.camera;
        var canvas = this.canvas;
        var embedded = this.getAttribute('embedded') && !this.is('vr-mode');
        var size;
        // Possible camera or canvas not injected yet.
        // ON MOBILE the webvr-polyfill relies on the fullscreen API to enter
        // VR mode. The canvas is resized by VREffect following the values returned
        // by getEyeParameters. We don't want to overwrite the size with the
        // windows width and height.
        if (!camera || !canvas || this.is('vr-mode') && isMobile) { return; }
        // Update camera.
        size = getCanvasSize(canvas, embedded);
        camera.aspect = size.width / size.height;
        camera.updateProjectionMatrix();
        // Notify renderer of size change.
        this.renderer.setSize(size.width, size.height);
      },
      writable: window.debug
    },

    setupRenderer: {
      value: function () {
        var canvas = this.canvas;
        // Set at startup. To enable/disable antialias
        // at runttime we would have to recreate the whole context
        var antialias = this.getAttribute('antialias') === 'true';
        var renderer = this.renderer = new THREE.WebGLRenderer({
          canvas: canvas,
          antialias: antialias || window.hasNativeWebVRImplementation,
          alpha: true
        });
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.sortObjects = false;
        this.effect = new THREE.VREffect(renderer);
      },
      writable: window.debug
    },

    /**
     * Handler attached to elements to help scene know when to kick off.
     * Scene waits for all entities to load.
     */
    play: {
      value: function () {
        var self = this;
        if (this.renderStarted) {
          AEntity.prototype.play.call(this);
          return;
        }

        this.addEventListener('loaded', function () {
          AEntity.prototype.play.call(this);  // .play() *before* render.

          // Wait for camera if necessary before rendering.
          if (this.camera) {
            startRender(this);
            return;
          }
          this.addEventListener('camera-set-active', function () { startRender(this); });

          function startRender (sceneEl) {
            if (sceneEl.renderStarted) { return; }

            sceneEl.resize();

            // Kick off render loop.
            if (sceneEl.renderer) {
              if (window.performance) {
                window.performance.mark('render-started');
              }
              sceneEl.render(0);
              sceneEl.renderStarted = true;
              sceneEl.emit('renderstart');
            }
          }
        });

        // setTimeout to wait for all nodes to attach and run their callbacks.
        setTimeout(function () {
          AEntity.prototype.load.call(self);
        });
      }
    },

    /**
     * Reload the scene to the original DOM content.
     *
     * @param {bool} doPause - Whether to reload the scene with all dynamic behavior paused.
     */
    reload: {
      value: function (doPause) {
        var self = this;
        if (doPause) { this.pause(); }
        this.innerHTML = this.originalHTML;
        this.init();
        ANode.prototype.load.call(this, play);
        function play () {
          if (!self.isPlaying) { return; }
          AEntity.prototype.play.call(self);
        }
      }
    },

    /**
     * Behavior-updater meant to be called from scene render.
     * Abstracted to a different function to facilitate unit testing (`scene.tick()`) without
     * needing to render.
     */
    tick: {
      value: function (time, timeDelta) {
        var systems = this.systems;

        // Animations.
        TWEEN.update(time);
        // Components.
        this.behaviors.forEach(function (component) {
          if (!component.el.isPlaying) { return; }
          component.tick(time, timeDelta);
        });
        // Systems.
        Object.keys(systems).forEach(function (key) {
          if (!systems[key].tick) { return; }
          systems[key].tick(time, timeDelta);
        });
      }
    },

    /**
     * The render loop.
     *
     * Updates animations.
     * Updates behaviors.
     * Renders with request animation frame.
     */
    render: {
      value: function (time) {
        var effect = this.effect;
        var timeDelta = time - this.time;

        if (this.isPlaying) { this.tick(time, timeDelta); }

        this.animationFrameID = effect.requestAnimationFrame(this.render);
        effect.render(this.object3D, this.camera);
        this.time = time;
      },
      writable: true
    }
  })
});

/**
 * Return the canvas size where the scene will be rendered
 * It will be always the window size except when the scene
 * is embedded. The parent size will be returned in that case
 *
 * @param {object} canvasEl - the canvas element
 * @param {boolean} embedded - Is the scene embedded?
 */
function getCanvasSize (canvasEl, embedded) {
  if (embedded) {
    return {
      height: canvasEl.parentElement.offsetHeight,
      width: canvasEl.parentElement.offsetWidth
    };
  }
  return {
    height: window.innerHeight,
    width: window.innerWidth
  };
}

function requestFullscreen (canvas) {
  var requestFullscreen =
    canvas.requestFullScreen ||
    canvas.webkitRequestFullScreen ||
    canvas.mozRequestFullScreen;
  requestFullscreen.apply(canvas);
}
<commit_msg>fix typos in requestFullscreen calls (fixes #1962) (#1963)<commit_after>/* global Promise, screen */
var initMetaTags = require('./metaTags').inject;
var initWakelock = require('./wakelock');
var re = require('../a-register-element');
var systems = require('../system').systems;
var THREE = require('../../lib/three');
var TWEEN = require('tween.js');
var utils = require('../../utils/');
// Require after.
var AEntity = require('../a-entity');
var ANode = require('../a-node');
var initPostMessageAPI = require('./postMessage');

var bind = utils.bind;
var checkHeadsetConnected = utils.checkHeadsetConnected;
var registerElement = re.registerElement;
var isIOS = utils.isIOS();
var isMobile = utils.isMobile();
var warn = utils.debug('core:a-scene:warn');

/**
 * Scene element, holds all entities.
 *
 * @member {number} animationFrameID
 * @member {array} behaviors - Component instances that have registered themselves to be
           updated on every tick.
 * @member {object} camera - three.js Camera object.
 * @member {object} canvas
 * @member {bool} isScene - Differentiates as scene entity as opposed to other entites.
 * @member {bool} isMobile - Whether browser is mobile (via UA detection).
 * @member {object} object3D - Root three.js Scene object.
 * @member {object} renderer
 * @member {bool} renderStarted
 * @member (object) effect - three.js VREffect
 * @member {object} systems - Registered instantiated systems.
 * @member {number} time
 */
module.exports = registerElement('a-scene', {
  prototype: Object.create(AEntity.prototype, {
    defaultComponents: {
      value: {
        'canvas': '',
        'inspector': '',
        'keyboard-shortcuts': '',
        'vr-mode-ui': ''
      }
    },

    createdCallback: {
      value: function () {
        this.isIOS = isIOS;
        this.isMobile = isMobile;
        this.isScene = true;
        this.object3D = new THREE.Scene();
        this.render = bind(this.render, this);
        this.systems = {};
        this.time = 0;

        this.init();
      }
    },

    init: {
      value: function () {
        this.behaviors = [];
        this.hasLoaded = false;
        this.isPlaying = false;
        this.originalHTML = this.innerHTML;
        this.addEventListener('render-target-loaded', function () {
          this.setupRenderer();
          this.resize();
        });
        this.addFullScreenStyles();
        initPostMessageAPI(this);
      },
      writable: true
    },

    addFullScreenStyles: {
      value: function () {
        var htmlEl = document.documentElement;
        htmlEl.classList.add('a-html');
        document.body.classList.add('a-body');
        this.classList.add('fullscreen');
      }
    },

    removeFullScreenStyles: {
      value: function () {
        var htmlEl = document.documentElement;
        htmlEl.classList.remove('a-html');
        document.body.classList.remove('a-body');
        this.classList.remove('fullscreen');
      }
    },

    attachedCallback: {
      value: function () {
        var resize = bind(this.resize, this);
        initMetaTags(this);
        initWakelock(this);
        this.initSystems();

        window.addEventListener('load', resize);
        window.addEventListener('resize', resize);
        this.play();
      },
      writable: window.debug
    },

    initSystems: {
      value: function () {
        Object.keys(systems).forEach(bind(this.initSystem, this));
      }
    },

    initSystem: {
      value: function (name) {
        var system;
        if (this.systems[name]) { return; }
        system = this.systems[name] = new systems[name](this);
        system.init();
      }
    },

    /**
     * Shuts down scene on detach.
     */
    detachedCallback: {
      value: function () {
        window.cancelAnimationFrame(this.animationFrameID);
        this.animationFrameID = null;
      }
    },

    /**
     * @param {object} behavior - Generally a component. Must implement a .update() method to
     *        be called on every tick.
     */
    addBehavior: {
      value: function (behavior) {
        var behaviors = this.behaviors;
        if (behaviors.indexOf(behavior) !== -1) { return; }
        behaviors.push(behavior);
      }
    },

    enterVR: {
      value: function (event) {
        var self = this;
        if (this.is('vr-mode')) { return; }
        if (checkHeadsetConnected() || this.isMobile) {
          return this.effect.requestPresent().then(enterVRSuccess, enterVRFailure);
        }
        enterVRSuccess();

        function enterVRSuccess () {
          self.addState('vr-mode');
          self.emit('enter-vr', event);

          // Lock to landscape orientation on mobile.
          if (self.isMobile && screen.orientation && screen.orientation.lock) {
            screen.orientation.lock('landscape');
          }
          self.addFullScreenStyles();

          // On mobile, the polyfill handles fullscreen.
          // TODO: 07/16 Chromium builds break when `requestFullscreen`ing on a canvas
          // that we are also `requestPresent`ing. Until then, don't fullscreen if headset
          // connected.
          if (!self.isMobile && !checkHeadsetConnected()) { requestFullscreen(self.canvas); }
          self.resize();
        }

        function enterVRFailure (err) {
          if (err && err.message) {
            throw new Error('Failed to enter VR mode (`requestPresent`): ' + err.message);
          } else {
            throw new Error('Failed to enter VR mode (`requestPresent`).');
          }
        }
      }
    },

    exitVR: {
      value: function () {
        var self = this;
        if (!this.is('vr-mode')) { return Promise.resolve(); }
        if (checkHeadsetConnected() || this.isMobile) {
          return this.effect.exitPresent().then(exitVRSuccess, exitVRFailure);
        }
        exitVRSuccess();
        function exitVRSuccess () {
          var embedded = self.getAttribute('embedded');
          self.removeState('vr-mode');
          // Lock to landscape orientation on mobile.
          if (self.isMobile && screen.orientation && screen.orientation.unlock) {
            screen.orientation.unlock();
          }
          // Exiting VR in embedded mode, no longer need fullscreen styles.
          if (embedded) { self.removeFullScreenStyles(); }
          self.resize();
          if (self.isIOS) { utils.forceCanvasResizeSafariMobile(this.canvas); }
          self.emit('exit-vr', {target: self});
        }
        function exitVRFailure (err) {
          if (err && err.message) {
            throw new Error('Failed to exit VR mode (`exitPresent`): ' + err.message);
          } else {
            throw new Error('Failed to exit VR mode (`exitPresent`).');
          }
        }
      }
    },

    /**
     * Wraps Entity.getAttribute to take into account for systems.
     * If system exists, then return system data rather than possible component data.
     */
    getAttribute: {
      value: function (attr) {
        var system = this.systems[attr];
        if (system) { return system.data; }
        return AEntity.prototype.getAttribute.call(this, attr);
      }
    },

    /**
     * `getAttribute` used to be `getDOMAttribute` and `getComputedAttribute` used to be
     * what `getAttribute` is now. Now legacy code.
     */
    getComputedAttribute: {
      value: function (attr) {
        warn('`getComputedAttribute` is deprecated. Use `getAttribute` instead.');
        this.getAttribute(attr);
      }
    },

    /**
     * Wraps Entity.getDOMAttribute to take into account for systems.
     * If system exists, then return system data rather than possible component data.
     */
    getDOMAttribute: {
      value: function (attr) {
        var system = this.systems[attr];
        if (system) { return system.data; }
        return AEntity.prototype.getDOMAttribute.call(this, attr);
      }
    },

    /**
     * Wraps Entity.setAttribute to take into account for systems.
     * If system exists, then skip component initialization checks and do a normal
     * setAttribute.
     */
    setAttribute: {
      value: function (attr, value, componentPropValue) {
        var system = this.systems[attr];
        if (system) {
          ANode.prototype.setAttribute.call(this, attr, value);
          return;
        }
        AEntity.prototype.setAttribute.call(this, attr, value, componentPropValue);
      }
    },

    /**
     * @param {object} behavior - Generally a component. Has registered itself to behaviors.
     */
    removeBehavior: {
      value: function (behavior) {
        var behaviors = this.behaviors;
        var index = behaviors.indexOf(behavior);
        if (index === -1) { return; }
        behaviors.splice(index, 1);
      }
    },

    resize: {
      value: function () {
        var camera = this.camera;
        var canvas = this.canvas;
        var embedded = this.getAttribute('embedded') && !this.is('vr-mode');
        var size;
        // Possible camera or canvas not injected yet.
        // ON MOBILE the webvr-polyfill relies on the fullscreen API to enter
        // VR mode. The canvas is resized by VREffect following the values returned
        // by getEyeParameters. We don't want to overwrite the size with the
        // windows width and height.
        if (!camera || !canvas || this.is('vr-mode') && isMobile) { return; }
        // Update camera.
        size = getCanvasSize(canvas, embedded);
        camera.aspect = size.width / size.height;
        camera.updateProjectionMatrix();
        // Notify renderer of size change.
        this.renderer.setSize(size.width, size.height);
      },
      writable: window.debug
    },

    setupRenderer: {
      value: function () {
        var canvas = this.canvas;
        // Set at startup. To enable/disable antialias
        // at runttime we would have to recreate the whole context
        var antialias = this.getAttribute('antialias') === 'true';
        var renderer = this.renderer = new THREE.WebGLRenderer({
          canvas: canvas,
          antialias: antialias || window.hasNativeWebVRImplementation,
          alpha: true
        });
        renderer.setPixelRatio(window.devicePixelRatio);
        renderer.sortObjects = false;
        this.effect = new THREE.VREffect(renderer);
      },
      writable: window.debug
    },

    /**
     * Handler attached to elements to help scene know when to kick off.
     * Scene waits for all entities to load.
     */
    play: {
      value: function () {
        var self = this;
        if (this.renderStarted) {
          AEntity.prototype.play.call(this);
          return;
        }

        this.addEventListener('loaded', function () {
          AEntity.prototype.play.call(this);  // .play() *before* render.

          // Wait for camera if necessary before rendering.
          if (this.camera) {
            startRender(this);
            return;
          }
          this.addEventListener('camera-set-active', function () { startRender(this); });

          function startRender (sceneEl) {
            if (sceneEl.renderStarted) { return; }

            sceneEl.resize();

            // Kick off render loop.
            if (sceneEl.renderer) {
              if (window.performance) {
                window.performance.mark('render-started');
              }
              sceneEl.render(0);
              sceneEl.renderStarted = true;
              sceneEl.emit('renderstart');
            }
          }
        });

        // setTimeout to wait for all nodes to attach and run their callbacks.
        setTimeout(function () {
          AEntity.prototype.load.call(self);
        });
      }
    },

    /**
     * Reload the scene to the original DOM content.
     *
     * @param {bool} doPause - Whether to reload the scene with all dynamic behavior paused.
     */
    reload: {
      value: function (doPause) {
        var self = this;
        if (doPause) { this.pause(); }
        this.innerHTML = this.originalHTML;
        this.init();
        ANode.prototype.load.call(this, play);
        function play () {
          if (!self.isPlaying) { return; }
          AEntity.prototype.play.call(self);
        }
      }
    },

    /**
     * Behavior-updater meant to be called from scene render.
     * Abstracted to a different function to facilitate unit testing (`scene.tick()`) without
     * needing to render.
     */
    tick: {
      value: function (time, timeDelta) {
        var systems = this.systems;

        // Animations.
        TWEEN.update(time);
        // Components.
        this.behaviors.forEach(function (component) {
          if (!component.el.isPlaying) { return; }
          component.tick(time, timeDelta);
        });
        // Systems.
        Object.keys(systems).forEach(function (key) {
          if (!systems[key].tick) { return; }
          systems[key].tick(time, timeDelta);
        });
      }
    },

    /**
     * The render loop.
     *
     * Updates animations.
     * Updates behaviors.
     * Renders with request animation frame.
     */
    render: {
      value: function (time) {
        var effect = this.effect;
        var timeDelta = time - this.time;

        if (this.isPlaying) { this.tick(time, timeDelta); }

        this.animationFrameID = effect.requestAnimationFrame(this.render);
        effect.render(this.object3D, this.camera);
        this.time = time;
      },
      writable: true
    }
  })
});

/**
 * Return the canvas size where the scene will be rendered
 * It will be always the window size except when the scene
 * is embedded. The parent size will be returned in that case
 *
 * @param {object} canvasEl - the canvas element
 * @param {boolean} embedded - Is the scene embedded?
 */
function getCanvasSize (canvasEl, embedded) {
  if (embedded) {
    return {
      height: canvasEl.parentElement.offsetHeight,
      width: canvasEl.parentElement.offsetWidth
    };
  }
  return {
    height: window.innerHeight,
    width: window.innerWidth
  };
}

function requestFullscreen (canvas) {
  var requestFullscreen =
    canvas.requestFullscreen ||
    canvas.webkitRequestFullscreen ||
    canvas.mozRequestFullScreen ||  // The capitalized `S` is not a typo.
    canvas.msRequestFullscreen;
  requestFullscreen.apply(canvas);
}
<|endoftext|>