<commit_before>/**********
 * The source code for my snake clone-, er, I mean, original game.
 * Author: Bronzdragon
 * Date: May 25th, 2017
 **********/

/**
 * Constants/settings for our game.
 */
var STARTSPEED = 0.1 * 1000;
var ACCELERATION = 0.9;
var GRIDSIZE = 10;
var GROWTH = 18;
var HEADCOLOUR = "#800000"
var BODYCOLOUR = "#FF0000"
var FOODCOLOUR = "#6666FF"

/**
 * Initialises/starts our game object
 */

var game = new Game();

function init(){
	if(game.init())
		game.start();
}

/**
 * Repository for all the images used in our game. Using a repository like this
 * means we only need to store each image once. Might not need this for Snake.
 */

var imageRepository = new function() {
	this.empty = null;

	this.background = new Image();
	this.background.src = "images/background.png";
}

/**
 * Creates the Drawable object, which will serve as the base class for all
 * drawable objects in the game.
 */

function Drawable() {
	this.init = function(x, y) {
		this.x = x;
		this.y = y;
	}
	this.canvasWidth = 0;
	this.canvasHeight = 0;

	this.draw = function() {};
}

 /**
 * The object that contains our here, Mr. Snake!
 */

function Snake() {
	this.speed = STARTSPEED; // time between updates in miliseconds

	this.direction = DirectionEnum.RIGHT;
	this.segments = [];

	this.lastMoved = Date.now();

	this.update = function (){
		if (Date.now() > this.lastMoved + this.speed){
			this.lastMoved = Date.now();
			this.move();
		}
	};

	this.move = function (){
		switch (this.direction){ // Move the 'head' (IE, this class)
			case DirectionEnum.LEFT:
				this.x--;
				if (this.x < 0) this.x = game.grid.width - 1;
				break;
			case DirectionEnum.UP:
				this.y--;
				if (this.y < 0) this.y = game.grid.height - 1;
				break;
			case DirectionEnum.RIGHT:
				this.x++;
				if (this.x > game.grid.width - 1) this.x = 0;
				break;
			case DirectionEnum.DOWN:
				this.y++;
				if (this.y > game.grid.height - 1) this.y = 0;
				break;
			default:
				break;
		} // end switch

		// when we touch the food
		if (this.x == game.food.x && this.y == game.food.y) {
			game.food = new Food();
			game.food.init();

			this.speed *= ACCELERATION;

			for(var counter = 0; counter < GROWTH; counter++){
				var segment = new SnakeSegment();
				segment.init(this.x, this.y);
				this.segments.unshift(segment);
			}

			//this.draw();
		}

		// Check if we are colliding with any segment.
		//console.log("Head is at ", this.x, this.y);
		this.segments.forEach(function(segment) {
			if (segment.x == this.x && segment.y == this.y){
				window.alert("You have died!");
			} else {
			}
		});

		// Start by clearing the last of the tail
		var tail = this.segments.shift();
		tail.clear();

		// Create a new head segment.
		var segment = new SnakeSegment();

		segment.init(this.x, this.y);

		this.segments[this.segments.length - 1].draw(false); // draw the 'neck'
		segment.draw(true); // draw the head
		this.segments.push(segment); //insert the new head.
	};

	this.draw = function (){ // redraw the whole snake.
		for(var counter = 0; counter < this.segments.length; counter++){
			this.segments[counter].draw();
		}
	};

	this.init = function(x, y){
		this.x = x; this.y = y;
		//this.prototype.init.call(x, y);
		//Drawable.init.call(this, x, y);

		// create three segments on spawn
		for(var temp = 0; temp < 3; temp++){
			var segment = new SnakeSegment();
			segment.init(1, 1 + temp);
			this.segments.push(segment);
		}
		for(var temp = 0; temp < 3; temp++){
			this.move();
		}
	}
}
Snake.prototype = new Drawable();

/**
 * A piece of the body of Mr. Snake.
 */

function SnakeSegment() {
	this.draw = function(bIsHead) {  // implement the earlier absctract function
		//this.context.rect(this.x, this.y, 25, 25);
		if (bIsHead == true){
			this.context.fillStyle=HEADCOLOUR;
		} else {
			this.context.fillStyle=BODYCOLOUR;
		}

		this.context.fillRect((this.x * game.grid.blockSize) + 1 , (this.y * game.grid.blockSize) + 1, game.grid.blockSize - 2, game.grid.blockSize - 2);
	}

	this.clear = function () {
		this.context.clearRect(this.x * game.grid.blockSize, this.y * game.grid.blockSize, game.grid.blockSize, game.grid.blockSize);
	}
}
SnakeSegment.prototype = new Drawable();

/**
 * A piece of food. If the snake head touches it, it should be consumed.
 */

function Food() {
	this.draw = function() {
		this.context.fillStyle=FOODCOLOUR;
		this.context.fillRect((this.x * game.grid.blockSize) + 1 , (this.y * game.grid.blockSize) + 1, game.grid.blockSize - 2, game.grid.blockSize - 2);
	}

	// Clear should not be required. The snake clears it as it moves over it.
	this.clear = function () {
		this.context.clearRect(this.x * game.grid.blockSize, this.y * game.grid.blockSize, game.grid.blockSize, game.grid.blockSize);
	}

	this.init = function(){
		this.x = Math.floor(Math.random() * (game.grid.width - 1));
		this.y = Math.floor(Math.random() * (game.grid.height - 1));

		console.log("Food is at ", this.x, ", ", this.y, ".");

		this.draw();
	}
}
Food.prototype = new Drawable();

/**
 * Grid on which our snake moves, and our food is drawn.
 */
function Grid() {
	this.blockSize = 25; //25;
	this.width  = 0; //600 / this.blockSize;
	this.height = 0; //350 / this.blockSize;

	this.init = function(stage_width, stage_height, size) {
		if (size == null)
			size = this.blockSize;

		this.width = Math.floor(stage_width/size);
		this.height = Math.floor(stage_height/size);

		this.blockSize = size;
	};
}

/**
 * Definition of our game object
 */
function Game() {
	// See if the canvas object is supported
	this.init = function(){
		this.bgCanvas = document.getElementById('background');
		this.playArea = document.getElementById('playarea');

		if (this.bgCanvas.getContext){

			this.grid = null;
			this.snake = null;
			this.food = null;

			this.bgContext = this.bgCanvas.getContext('2d');

			Snake.prototype.context = this.playArea.getContext('2d');
			Snake.prototype.canvasWidth = this.playArea.width;
			Snake.prototype.canvasHeight = this.playArea.height;

			SnakeSegment.prototype.context = this.playArea.getContext('2d');
			SnakeSegment.prototype.canvasWidth = this.playArea.width;
			SnakeSegment.prototype.canvasHeight = this.playArea.height;

			Food.prototype.context = this.playArea.getContext('2d');
			Food.prototype.canvasWidth = this.playArea.width;
			Food.prototype.canvasHeight = this.playArea.height;

			this.grid = new Grid();
			this.grid.init(this.playArea.width, this.playArea.height, GRIDSIZE);

			this.food = new Food();
			this.food.init();

			this.snake = new Snake();
			this.snake.init(1, 1);

			return true;
		} else { return false; }
	};

	this.start = function () {
		// Set the background once:
		this.bgContext.drawImage(imageRepository.background, 0, 0);

		// Main animation/fucntion loop. It'll request a call-back of itself
		animate();
	};
}

/**
 * The actual game loop. Requests that this function is called back when the
 * next frame should be called back next frame.
 */
function animate() {
	requestAnimFrame(animate);

	// animate/update the
	game.snake.update();
	//game.snake.draw();
	//game.food.draw();
}

/**
 * Keyboard input handeling goes here.
 */
window.addEventListener("keydown", function (event) {
	switch (event.key) {
		case "ArrowDown":
			game.snake.direction = DirectionEnum.DOWN;
			break;
		case "ArrowUp":
			game.snake.direction = DirectionEnum.UP;
			break;
		case "ArrowLeft":
			game.snake.direction = DirectionEnum.LEFT;
			break;
		case "ArrowRight":
			game.snake.direction = DirectionEnum.RIGHT;
			break;
		default:
			return;
	}

	event.preventDefault();
}, true);

var DirectionEnum = {
	DOWN: "down",
	UP: "up",
	LEFT: "left",
	RIGHT: "right"
};

/**
 * requestAnim shim layer by Paul Irish
 * Finds the first API that works to optimize the animation loop,
 * otherwise defaults to setTimeout().
 */
window.requestAnimFrame = (function(){
	return  window.requestAnimationFrame       ||
			window.webkitRequestAnimationFrame ||
			window.mozRequestAnimationFrame    ||
			window.oRequestAnimationFrame      ||
			window.msRequestAnimationFrame     ||
			function(/* function */ callback, /* DOMElement */ element){
			window.setTimeout(callback, 1000 / 60);
			};
})();

<commit_msg>Death is functional now<commit_after>/**********
 * The source code for my snake clone-, er, I mean, original game.
 * Author: Bronzdragon
 * Date: May 25th, 2017
 **********/

/**
 * Constants/settings for our game.
 */
var STARTSPEED = 0.1 * 1000;
var ACCELERATION = 0.9;
var GRIDSIZE = 10;
var GROWTH = 3;
var HEADCOLOUR = "#800000"
var BODYCOLOUR = "#FF0000"
var FOODCOLOUR = "#6666FF"

/**
 * Initialises/starts our game object
 */

var game = new Game();

function init(){
	if(game.init())
		game.start();
}

/**
 * Repository for all the images used in our game. Using a repository like this
 * means we only need to store each image once. Might not need this for Snake.
 */

var imageRepository = new function() {
	this.empty = null;

	this.background = new Image();
	this.background.src = "images/background.png";
}

/**
 * Creates the Drawable object, which will serve as the base class for all
 * drawable objects in the game.
 */

function Drawable() {
	this.init = function(x, y) {
		this.x = x;
		this.y = y;
	}
	this.canvasWidth = 0;
	this.canvasHeight = 0;

	this.draw = function() {};
}

 /**
 * The object that contains our here, Mr. Snake!
 */

function Snake() {
	this.speed = STARTSPEED; // time between updates in miliseconds

	this.direction = DirectionEnum.RIGHT;
	this.segments = [];

	this.lastMoved = Date.now();

	this.update = function (){
		if (Date.now() > this.lastMoved + this.speed){
			this.lastMoved = Date.now();
			this.move();
		}
	};

	this.move = function (){
		switch (this.direction){ // Move the 'head' (IE, this class)
			case DirectionEnum.LEFT:
				this.x--;
				if (this.x < 0) this.x = game.grid.width - 1;
				break;
			case DirectionEnum.UP:
				this.y--;
				if (this.y < 0) this.y = game.grid.height - 1;
				break;
			case DirectionEnum.RIGHT:
				this.x++;
				if (this.x > game.grid.width - 1) this.x = 0;
				break;
			case DirectionEnum.DOWN:
				this.y++;
				if (this.y > game.grid.height - 1) this.y = 0;
				break;
			default:
				break;
		} // end switch

		// Check if we are colliding with any segment (and thus should die).
		this.segments.forEach(function(segment) {
			if (segment.x == this.x && segment.y == this.y){
				window.alert("You have died!");
			}
		}, this);

		// when we touch the food
		if (this.x == game.food.x && this.y == game.food.y) {
			game.food = new Food();
			game.food.init();

			this.speed *= ACCELERATION;

			for(var counter = 0; counter < GROWTH; counter++){
				var segment = new SnakeSegment();
				segment.init(this.x, this.y);
				this.segments.unshift(segment);
			}

			//this.draw();
		}

		// Start by clearing the last of the tail
		var tail = this.segments.shift();
		tail.clear();

		// Create a new head segment.
		var segment = new SnakeSegment();

		segment.init(this.x, this.y);

		this.segments[this.segments.length - 1].draw(false); // draw the 'neck'
		segment.draw(true); // draw the head
		this.segments.push(segment); //insert the new head.
	};

	this.draw = function (){ // redraw the whole snake.
		for(var counter = 0; counter < this.segments.length; counter++){
			this.segments[counter].draw();
		}
	};

	this.init = function(x, y){
		this.x = x; this.y = y;
		//this.prototype.init.call(x, y);
		//Drawable.init.call(this, x, y);

		// create three segments on spawn
		for(var temp = 0; temp < 3; temp++){
			var segment = new SnakeSegment();
			segment.init(1, 1 + temp);
			this.segments.push(segment);
		}
		for(var temp = 0; temp < 3; temp++){
			this.move();
		}
	}
}
Snake.prototype = new Drawable();

/**
 * A piece of the body of Mr. Snake.
 */

function SnakeSegment() {
	this.draw = function(bIsHead) {  // implement the earlier absctract function
		//this.context.rect(this.x, this.y, 25, 25);
		if (bIsHead == true){
			this.context.fillStyle=HEADCOLOUR;
		} else {
			this.context.fillStyle=BODYCOLOUR;
		}

		this.context.fillRect((this.x * game.grid.blockSize) + 1 , (this.y * game.grid.blockSize) + 1, game.grid.blockSize - 2, game.grid.blockSize - 2);
	}

	this.clear = function () {
		this.context.clearRect(this.x * game.grid.blockSize, this.y * game.grid.blockSize, game.grid.blockSize, game.grid.blockSize);
	}
}
SnakeSegment.prototype = new Drawable();

/**
 * A piece of food. If the snake head touches it, it should be consumed.
 */

function Food() {
	this.draw = function() {
		this.context.fillStyle=FOODCOLOUR;
		this.context.fillRect((this.x * game.grid.blockSize) + 1 , (this.y * game.grid.blockSize) + 1, game.grid.blockSize - 2, game.grid.blockSize - 2);
	}

	// Clear should not be required. The snake clears it as it moves over it.
	this.clear = function () {
		this.context.clearRect(this.x * game.grid.blockSize, this.y * game.grid.blockSize, game.grid.blockSize, game.grid.blockSize);
	}

	this.init = function(){
		this.x = Math.floor(Math.random() * (game.grid.width - 1));
		this.y = Math.floor(Math.random() * (game.grid.height - 1));

		console.log("Food is at ", this.x, ", ", this.y, ".");

		this.draw();
	}
}
Food.prototype = new Drawable();

/**
 * Grid on which our snake moves, and our food is drawn.
 */
function Grid() {
	this.blockSize = 25; //25;
	this.width  = 0; //600 / this.blockSize;
	this.height = 0; //350 / this.blockSize;

	this.init = function(stage_width, stage_height, size) {
		if (size == null)
			size = this.blockSize;

		this.width = Math.floor(stage_width/size);
		this.height = Math.floor(stage_height/size);

		this.blockSize = size;
	};
}

/**
 * Definition of our game object
 */
function Game() {
	// See if the canvas object is supported
	this.init = function(){
		this.bgCanvas = document.getElementById('background');
		this.playArea = document.getElementById('playarea');

		if (this.bgCanvas.getContext){

			this.grid = null;
			this.snake = null;
			this.food = null;

			this.bgContext = this.bgCanvas.getContext('2d');

			Snake.prototype.context = this.playArea.getContext('2d');
			Snake.prototype.canvasWidth = this.playArea.width;
			Snake.prototype.canvasHeight = this.playArea.height;

			SnakeSegment.prototype.context = this.playArea.getContext('2d');
			SnakeSegment.prototype.canvasWidth = this.playArea.width;
			SnakeSegment.prototype.canvasHeight = this.playArea.height;

			Food.prototype.context = this.playArea.getContext('2d');
			Food.prototype.canvasWidth = this.playArea.width;
			Food.prototype.canvasHeight = this.playArea.height;

			this.grid = new Grid();
			this.grid.init(this.playArea.width, this.playArea.height, GRIDSIZE);

			this.food = new Food();
			this.food.init();

			this.snake = new Snake();
			this.snake.init(1, 1);

			return true;
		} else { return false; }
	};

	this.start = function () {
		// Set the background once:
		this.bgContext.drawImage(imageRepository.background, 0, 0);

		// Main animation/fucntion loop. It'll request a call-back of itself
		animate();
	};
}

/**
 * The actual game loop. Requests that this function is called back when the
 * next frame should be called back next frame.
 */
function animate() {
	requestAnimFrame(animate);

	// animate/update the
	game.snake.update();
	//game.snake.draw();
	//game.food.draw();
}

/**
 * Keyboard input handeling goes here.
 */
window.addEventListener("keydown", function (event) {
	switch (event.key) {
		case "ArrowDown":
			game.snake.direction = DirectionEnum.DOWN;
			break;
		case "ArrowUp":
			game.snake.direction = DirectionEnum.UP;
			break;
		case "ArrowLeft":
			game.snake.direction = DirectionEnum.LEFT;
			break;
		case "ArrowRight":
			game.snake.direction = DirectionEnum.RIGHT;
			break;
		default:
			return;
	}

	event.preventDefault();
}, true);

var DirectionEnum = {
	DOWN: "down",
	UP: "up",
	LEFT: "left",
	RIGHT: "right"
};

/**
 * requestAnim shim layer by Paul Irish
 * Finds the first API that works to optimize the animation loop,
 * otherwise defaults to setTimeout().
 */
window.requestAnimFrame = (function(){
	return  window.requestAnimationFrame       ||
			window.webkitRequestAnimationFrame ||
			window.mozRequestAnimationFrame    ||
			window.oRequestAnimationFrame      ||
			window.msRequestAnimationFrame     ||
			function(/* function */ callback, /* DOMElement */ element){
			window.setTimeout(callback, 1000 / 60);
			};
})();

<|endoftext|>


<commit_before>/*global app, $*/
"use strict";

var HumanModel = require('human-model');

module.exports = HumanModel.define({
    initialize: function () {
        var self = this;
        $(window).blur(function () {
            self.focused = false;
        });
        $(window).focus(function () {
            self.focused = true;
            self.markActive();
        });
        if (window.macgap) {
            document.addEventListener('sleep', function () {
                clearTimeout(this.idleTimer);
                self.markInactive();
            }, true);
        }

        this.markActive();
    },
    session: {
        focused: ['bool', true, true],
        active: ['bool', true, false],
        connected: ['bool', true, false],
        hasConnected: ['bool', true, false],
        idleTimeout: ['number', true, 600000],
        idleSince: 'date',
        allowAlerts: ['bool', true, false],
        badge: ['string', true, ''],
        pageTitle: ['string', true, '']
    },
    derived: {
        title: {
            deps: ['pageTitle', 'badge'],
            fn: function () {
                var base = this.pageTitle ? 'Otalk - ' + this.pageTitle : 'Otalk';
                if (this.badge) {
                    return this.badge + ' • ' + base;
                }
                return base;
            }
        }
    },
    markActive: function () {
        clearTimeout(this.idleTimer);

        var wasInactive = !this.active;
        this.active = true;
        this.idleSince = new Date(Date.now());

        this.idleTimer = setTimeout(this.markInactive.bind(this), this.idleTimeout);
    },
    markInactive: function () {
        if (this.focused) {
            return this.markActive();
        }

        this.active = false;
        this.idleSince = new Date(Date.now());
    }
});
<commit_msg>Reset unread count for active contact on focus.<commit_after>/*global app, $, me*/
"use strict";

var HumanModel = require('human-model');

module.exports = HumanModel.define({
    initialize: function () {
        var self = this;
        $(window).blur(function () {
            self.focused = false;
        });
        $(window).focus(function () {
            self.focused = true;
            if (me._activeContact) {
                me.setActiveContact(me._activeContact);
            }
            self.markActive();
        });
        if (window.macgap) {
            document.addEventListener('sleep', function () {
                clearTimeout(this.idleTimer);
                console.log('went to sleep');
                self.markInactive();
            }, true);
        }

        this.markActive();
    },
    session: {
        focused: ['bool', true, true],
        active: ['bool', true, false],
        connected: ['bool', true, false],
        hasConnected: ['bool', true, false],
        idleTimeout: ['number', true, 600000],
        idleSince: 'date',
        allowAlerts: ['bool', true, false],
        badge: ['string', true, ''],
        pageTitle: ['string', true, '']
    },
    derived: {
        title: {
            deps: ['pageTitle', 'badge'],
            fn: function () {
                var base = this.pageTitle ? 'Otalk - ' + this.pageTitle : 'Otalk';
                if (this.badge) {
                    return this.badge + ' • ' + base;
                }
                return base;
            }
        }
    },
    markActive: function () {
        clearTimeout(this.idleTimer);

        var wasInactive = !this.active;
        this.active = true;
        this.idleSince = new Date(Date.now());

        this.idleTimer = setTimeout(this.markInactive.bind(this), this.idleTimeout);
    },
    markInactive: function () {
        if (this.focused) {
            return this.markActive();
        }

        this.active = false;
        this.idleSince = new Date(Date.now());
    }
});
<|endoftext|>


<commit_before>import Operation from '../../core/operation.js';
export class ExportDrawing extends Operation {
  constructor(SL, config) {
    super(SL, config);
    this.configure(config);
  }
  configure(config) {
    config = super.configure(config);
    if (!config.Content) {
      config.Content = {};
    }
    if (!config.Content.types) {
      config.Content.types = ['Stamp', 'Line', 'Text'];
    }
    if (!config.format) {
      config.format = {};
    }
    if (config.format.defaultPretty == undefined) {
      config.format.defaultPretty = 0;
    }
  }
  static canRun(args={}) {
    if (args.download && (!Blob || !saveAs)) {
      return false;
    }
    return true;
  }
  getExportID(args) {
    return (new Date()).getDateTimeStamp();
  }
  downloadFile(filename, content) {
    if (Blob && saveAs) {
      let blob = new Blob([content], {type: 'text/json;charset=utf-8'});
      saveAs(blob, filename);
      return true;
    }
    return false;
  }
  contentToJSON(content, args) {
    return JSON.stringify(content, null, (typeof args.pretty != 'undefined' ? args.pretty : this.config.format.defaultPretty));
  }
  canExport(type) {
    return (type && this.config.Content.types.indexOf(type) != -1);
  }
  export(args) {
    return new Promise((resolve, reject) => {
      let result = {
        id: this.getExportID(args),
        content: undefined
      };

      // collect the content items and definitions
      let contentItems = {};
      let definitions = {};
      let loaders = [];
      this.SL.Paper.Item.forEachOfClass('Content', (item) => {
        let itemType = (item && item.data && item.data.Type);
        if (itemType && this.canExport(itemType)) {
          let into = {};
          this.SL.Paper.emit('Content.Export', {into}, item);
          if (into.Content) {
            if (!contentItems[itemType]) {
              contentItems[itemType] = [];
            }
            contentItems[itemType].push(into.Content);
          }
          if (into.Definition) {
            if (!definitions[itemType]) {
              definitions[itemType] = [];
            }
            let definition = definitions[itemType].find((check) => {
              return (check.id == into.Definition.id);
            });
            if (!definition) {
              definitions[itemType].push(into.Definition);
            }
          }
          if (into.Loaders) {
            loaders.push(...into.Loaders);
          }
        }
      });
      let configs = {};
      this.SL.Paper.emit('Config.Export', {into: configs}, configs);

      // build the content object
      let content = {
        Content: [],
        Definitions: definitions,
        Config: configs
      };
      let contentTypes = (this.config && this.config.Content && this.config.Content.types) || Object.keys(contentItems);
      if (contentTypes) {
        for (let itemType of contentTypes) {
          if (contentItems[itemType] && Array.isArray(contentItems[itemType])) {
            content.Content.push(...contentItems[itemType]);
          }
        }
      }
      result.content = content;

      // wait for loaders to finish before resolving
      Promise.all(loaders)
        .then(() => {
          resolve(result);
        })
        .catch(() => {
          // same as .then() because Promise.finally not supported by all browsers
          resolve(result);
        });
    });
  }
  exportDownload(args) {
    return new Promise((resolve, reject) => {
      this.export(args).then((data) => {
        if (data) {
          let filename = 'StampLines'+(data.id ? `-${data.id}` : '') + '.json';
          let content = this.contentToJSON(data.content, args) + '\n';
          resolve(this.downloadFile(filename, content));
        }
        else {
          reject('No data was exported.');
        }
      });
    });
  }
  exportJSON(args) {
    return new Promise((resolve, reject) => {
      this.export(args).then((data) => {
        if (data) {
          resolve({
            id: data.id,
            json: this.contentToJSON(data.content, args)
          });
        }
        else {
          reject('No data was exported.');
        }
      });
    });
  }
  run(args) {
    if (args.download) {
      return this.exportDownload(args);
    }
    if (args.json) {
      return this.exportJSON(args);
    }
    return this.export(args);
  }
}
<commit_msg>Adds indexing/sorting to ExportDrawing<commit_after>import Operation from '../../core/operation.js';
export class ExportDrawing extends Operation {
  constructor(SL, config) {
    super(SL, config);
    this.configure(config);
  }
  configure(config) {
    config = super.configure(config);
    if (!config.Content) {
      config.Content = {};
    }
    if (!config.Content.types) {
      config.Content.types = ['Stamp', 'Line', 'Text'];
    }
    if (!config.format) {
      config.format = {};
    }
    if (config.format.defaultPretty == undefined) {
      config.format.defaultPretty = 0;
    }
  }
  static canRun(args={}) {
    if (args.download && (!Blob || !saveAs)) {
      return false;
    }
    return true;
  }
  getExportID(args) {
    return (new Date()).getDateTimeStamp();
  }
  downloadFile(filename, content) {
    if (Blob && saveAs) {
      let blob = new Blob([content], {type: 'text/json;charset=utf-8'});
      saveAs(blob, filename);
      return true;
    }
    return false;
  }
  contentToJSON(content, args) {
    return JSON.stringify(content, null, (typeof args.pretty != 'undefined' ? args.pretty : this.config.format.defaultPretty));
  }
  canExport(type) {
    return (type && this.config.Content.types.indexOf(type) != -1);
  }
  export(args) {
    return new Promise((resolve, reject) => {
      let result = {
        id: this.getExportID(args),
        content: undefined
      };

      // collect the content items and definitions
      let contentItems = {};
      let definitions = {};
      let loaders = [];
      this.SL.Paper.Item.forEachOfClass('Content', (item) => {
        let itemType = (item && item.data && item.data.Type);
        if (itemType && this.canExport(itemType)) {
          let into = {};
          this.SL.Paper.emit('Content.Export', {into}, item);
          if (into.Content) {
            if (!contentItems[itemType]) {
              contentItems[itemType] = [];
            }
            into.Content.index = ((item.index || item.index === 0) ? item.index : -1);
            contentItems[itemType].push(into.Content);
          }
          if (into.Definition) {
            if (!definitions[itemType]) {
              definitions[itemType] = [];
            }
            let definition = definitions[itemType].find((check) => {
              return (check.id == into.Definition.id);
            });
            if (!definition) {
              definitions[itemType].push(into.Definition);
            }
          }
          if (into.Loaders) {
            loaders.push(...into.Loaders);
          }
        }
      });
      let configs = {};
      this.SL.Paper.emit('Config.Export', {into: configs}, configs);

      // build the content object
      let content = {
        Content: [],
        Definitions: definitions,
        Config: configs
      };
      let contentTypes = (this.config && this.config.Content && this.config.Content.types) || Object.keys(contentItems);
      if (contentTypes) {
        for (let itemType of contentTypes) {
          if (contentItems[itemType] && Array.isArray(contentItems[itemType])) {
            content.Content.push(...contentItems[itemType]);
          }
        }
      }
      content.Content.sort((item1, item2) => {
        let index1 = ((item1.index || item1.index === 0) ? item1.index : -1);
        let index2 = ((item2.index || item2.index === 0) ? item2.index : -1);
        return (index1 - index2);
      });
      result.content = content;

      // wait for loaders to finish before resolving
      Promise.all(loaders)
        .then(() => {
          resolve(result);
        })
        .catch(() => {
          // same as .then() because Promise.finally not supported by all browsers
          resolve(result);
        });
    });
  }
  exportDownload(args) {
    return new Promise((resolve, reject) => {
      this.export(args).then((data) => {
        if (data) {
          let filename = 'StampLines'+(data.id ? `-${data.id}` : '') + '.json';
          let content = this.contentToJSON(data.content, args) + '\n';
          resolve(this.downloadFile(filename, content));
        }
        else {
          reject('No data was exported.');
        }
      });
    });
  }
  exportJSON(args) {
    return new Promise((resolve, reject) => {
      this.export(args).then((data) => {
        if (data) {
          resolve({
            id: data.id,
            json: this.contentToJSON(data.content, args)
          });
        }
        else {
          reject('No data was exported.');
        }
      });
    });
  }
  run(args) {
    if (args.download) {
      return this.exportDownload(args);
    }
    if (args.json) {
      return this.exportJSON(args);
    }
    return this.export(args);
  }
}
<|endoftext|>


<commit_before>/*********************************************************************
* #### CI File Browser Awesome v01 ####
* Coded by Ican Bachors 2015.
* https://github.com/bachors/CI-FIle-Browser-Awesome
* Updates will be posted to this site.
*********************************************************************/

// Setting: Base_URL/Controllers_name
var baseurl = 'http://your-domain.com/file';

/* Testing di localhost */
var fix = /\\/;

/* atau jika tombol back bermasalah ketika sudah di hosting gunakan script dibawah ini:
var fix = /\//;
*/

var value = getParameterByName('dir');
if(value != ''){
	ibc_fba(scan,sub=value,fix);
}else{
	ibc_fba(baseurl,sub="",fix)
}

function ibc_fba(baseurl,sub,fix) {
	$.ajax( {
		url:baseurl+'/map?sub='+sub,
		crossDomain:true,
		dataType:"json"
	}).done(function(data) {
		var r="";
		r+="
";
		r+='

Name	Size	Last Modified

';
		if(data.back!="") {
			r+='
 '+data.root+"
"
		}
		$.each(data.items,function(i,item) {
			var size=ibc_ukurana(data.items[i].size);
			if(data.items[i].type=="folder") {
				r+='
 '+data.items[i].name+'	'+data.items[i].items.length+' item	'+data.items[i].modif+"
"
			} else {
				var s=data.items[i].path.substr(data.items[i].path.lastIndexOf(".")+1);
				switch(s) {
					// List read file. Custom/add example case"asp":case"jsp" etc
					case"html":
					case"php":
					case"js":
					case"css":
					case"txt":
					r+='
 '+data.items[i].name+'	'+size+'	'+data.items[i].modif+"
";
					break;
					// List download file
					default:
					r+='
 '+data.items[i].name+'	'+size+'	'+data.items[i].modif+"
"
				}
			}
		});
		r+='
'+unescape("%3C%61%20%68%72%65%66%3D%22%68%74%74%70%3A%2F%2F%69%62%61%63%6F%72%2E%63%6F%6D%2F%6C%61%62%73%2F%6A%71%75%65%72%79%2D%66%69%6C%65%2D%62%72%6F%77%73%65%72%2D%61%77%65%73%6F%6D%65%2F%22%20%74%61%72%67%65%74%3D%22%5F%42%4C%41%4E%4B%22%3E%46%69%6C%65%20%42%72%6F%77%73%65%72%20%41%77%65%73%6F%6D%65%3C%2F%61%3E")+"
";
		r+="

";
		$(".ibc_fba").html(r);
		$("#ibc_fba_file").html('');
		$(".sub").click(function() {
			var t=$(this).data("sub");
			ibc_fba(baseurl,t,fix);
			window.history.pushState(null, null, "?dir="+t);
			return false
		});
		$(".bsub").click(function() {
			var t=$(this).data("bsub");
			ibc_fba(baseurl,t,fix);
			window.history.pushState(null, null, "?dir="+t);
			return false
		});
		$(".rfile").click(function() {
			var file=$(this).data("rfile");
			ibc_fba_file(baseurl,file);
			return false
		});
	});
}

function ibc_fba_file(baseurl,file) {
	$.ajax( {
		url:baseurl+'/read?file='+file,
		crossDomain:true,
		dataType:"json"
	}).done(function(data) {
		var t='
 Ctrl-F / Cmd-F: Start searching, Ctrl-G / Cmd-G: Find next, Shift-Ctrl-G / Shift-Cmd-G: Find previous, Shift-Ctrl-F / Cmd-Option-F: Replace, Shift-Ctrl-R / Shift-Cmd-Option-F: Replace all
<textarea id="text" name="text">'+data.text+'</textarea>';
		$("#ibc_fba_file").html(t)
	});
}

function ibc_ukurana(e) {
	var t=["Bytes","KB","MB","GB","TB"];
	if(e==0)return"0 Bytes";
	var n=parseInt(Math.floor(Math.log(e)/Math.log(1024)));
	return Math.round(e/Math.pow(1024,n),2)+" "+t[n]
}

function getParameterByName(name) {
	name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
	var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
	results = regex.exec(location.search);
	return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
<commit_msg>Update fba.js<commit_after>/*********************************************************************
* #### CI File Browser Awesome v01 ####
* Coded by Ican Bachors 2015.
* https://github.com/bachors/CI-FIle-Browser-Awesome
* Updates will be posted to this site.
*********************************************************************/

// Setting: Base_URL/Controllers_name
var baseurl = 'http://your-domain.com/file';

/* Testing di localhost */
var fix = /\\/;

/* atau jika tombol back bermasalah ketika sudah di hosting gunakan script dibawah ini:
var fix = /\//;
*/

var value = getParameterByName('dir');
if(value != ''){
	ibc_fba(scan,sub=value,fix);
}else{
	ibc_fba(baseurl,sub="",fix)
}

function ibc_fba(baseurl,sub,fix) {
	$.ajax( {
		url:baseurl+'/map?sub='+sub,
		crossDomain:true,
		dataType:"json"
	}).done(function(data) {
		var r="";
		r+="
";
		r+='

Name	Size	Last Modified

';
		if(data.back!="") {
			r+='
 '+data.root+'
';
		}
		$.each(data.items,function(i,item) {
			var size=ibc_ukurana(data.items[i].size);
			if(data.items[i].type=="folder") {
				r+='
 '+data.items[i].name+'	'+data.items[i].items.length+' item	'+data.items[i].modif+"
"
			} else {
				var s=data.items[i].path.substr(data.items[i].path.lastIndexOf(".")+1);
				switch(s) {
					// List read file. Custom/add example case"asp":case"jsp" etc
					case"html":
					case"php":
					case"js":
					case"css":
					case"txt":
					r+='
 '+data.items[i].name+'	'+size+'	'+data.items[i].modif+"
";
					break;
					// List download file
					default:
					r+='
 '+data.items[i].name+'	'+size+'	'+data.items[i].modif+"
"
				}
			}
		});
		r+='
'+unescape("%3C%61%20%68%72%65%66%3D%22%68%74%74%70%3A%2F%2F%69%62%61%63%6F%72%2E%63%6F%6D%2F%6C%61%62%73%2F%6A%71%75%65%72%79%2D%66%69%6C%65%2D%62%72%6F%77%73%65%72%2D%61%77%65%73%6F%6D%65%2F%22%20%74%61%72%67%65%74%3D%22%5F%42%4C%41%4E%4B%22%3E%46%69%6C%65%20%42%72%6F%77%73%65%72%20%41%77%65%73%6F%6D%65%3C%2F%61%3E")+"
";
		r+="

";
		$(".ibc_fba").html(r);
		$("#ibc_fba_file").html('');
		$(".sub").click(function() {
			var t=$(this).data("sub");
			ibc_fba(baseurl,t,fix);
			window.history.pushState(null, null, "?dir="+t);
			return false
		});
		$(".bsub").click(function() {
			var t=$(this).data("bsub");
			ibc_fba(baseurl,t,fix);
			window.history.pushState(null, null, "?dir="+t);
			return false
		});
		$(".rfile").click(function() {
			var file=$(this).data("rfile");
			ibc_fba_file(baseurl,file);
			return false
		});
	});
}

function ibc_fba_file(baseurl,file) {
	$.ajax( {
		url:baseurl+'/read?file='+file,
		crossDomain:true,
		dataType:"json"
	}).done(function(data) {
		var t='
 Ctrl-F / Cmd-F: Start searching, Ctrl-G / Cmd-G: Find next, Shift-Ctrl-G / Shift-Cmd-G: Find previous, Shift-Ctrl-F / Cmd-Option-F: Replace, Shift-Ctrl-R / Shift-Cmd-Option-F: Replace all
<textarea id="text" name="text">'+data.text+'</textarea>';
		$("#ibc_fba_file").html(t)
	});
}

function ibc_ukurana(e) {
	var t=["Bytes","KB","MB","GB","TB"];
	if(e==0)return"0 Bytes";
	var n=parseInt(Math.floor(Math.log(e)/Math.log(1024)));
	return Math.round(e/Math.pow(1024,n),2)+" "+t[n]
}

function getParameterByName(name) {
	name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
	var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
	results = regex.exec(location.search);
	return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
}
<|endoftext|>


<commit_before>const fs = require('fs');
const url = require('url');

const gulp = require('gulp');
const config = require('../config.js');

const connect = require('gulp-connect');

const pkey = fs.readFileSync('./frontend/certs/server/my-server.key.pem');
const pcert = fs.readFileSync('./frontend/certs/server/my-server.crt.pem');
const pca = fs.readFileSync('./frontend/certs/server/my-private-root-ca.crt.pem');

const serverOptions = {
  root: config.DEST_PATH,
  livereload: false,
  host: '0.0.0.0',
  port: config.SERVER_PORT,
  middleware: (connect, ops) => [
    // Rewrite /path to /path/index.html
    (req, res, next) => {
      const parsed = url.parse(req.url);
      const { pathname } = parsed;
      // If no dot or trailing slash, try rewriting
      if (pathname.indexOf('.') === -1 &&
          pathname.substring(pathname.length - 1) !== '/') {
        parsed.pathname = pathname + '/index.html';
        req.url = url.format(parsed);
      }
      next();
    }
  ]
};

if (config.USE_HTTPS) {
  serverOptions.https = {
    key: pkey,
    cert: pcert,
    ca: pca,
    passphrase: ''
  };
}

gulp.task('server', () => {
  connect.server(serverOptions);
});
<commit_msg>Fix a bug introduced by pull request #2315<commit_after>const fs = require('fs');
const url = require('url');

const gulp = require('gulp');
const config = require('../config.js');

const connect = require('gulp-connect');

const pkey = fs.readFileSync('./frontend/certs/server/my-server.key.pem');
const pcert = fs.readFileSync('./frontend/certs/server/my-server.crt.pem');
const pca = fs.readFileSync('./frontend/certs/server/my-private-root-ca.crt.pem');

const serverOptions = {
  root: config.DEST_PATH,
  livereload: false,
  host: '0.0.0.0',
  port: config.SERVER_PORT,
  middleware: (connect, ops) => [
    // Rewrite /path to /path/index.html
    (req, res, next) => {
      const parsed = url.parse(req.url);
      const { pathname } = parsed;
      // If no dot and trailing slash, try rewriting
      if (pathname.indexOf('.') === -1 &&
          pathname.substring(pathname.length - 1) !== '/') {
        parsed.pathname = pathname + '/index.html';
        req.url = url.format(parsed);
      }
      // Rewrite /static/addon/latest to /static/addon/addon.xpi
      if (pathname === '/static/addon/latest') {
        parsed.pathname = '/static/addon/addon.xpi';
        req.url = url.format(parsed);
      }
      next();
    }
  ]
};

if (config.USE_HTTPS) {
  serverOptions.https = {
    key: pkey,
    cert: pcert,
    ca: pca,
    passphrase: ''
  };
}

gulp.task('server', () => {
  connect.server(serverOptions);
});
<|endoftext|>


<commit_before>// Copyright, 2013-2014, by Tomas Korcak. <korczis@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

(function () {
    'use strict';

    var define = require('amdefine')(module);

    /**
     * Array of modules this one depends on.
     * @type {Array}
     */
    var deps = [
        '../helpers'
    ];

    define(deps, function(Helpers) {

        /**
         * In Memory Queue Class
         * @class
         */
        function QueueMemory(opts) {
            opts = opts || {};

            this.queue = {
                requested: [],
                processing: [],
                done: [],
                failed: []
            };
        }

        /**
         * Enqueue new URL and specify processor to parse page (and optionally the data passed)
         *
         * Procedure is following:
         *
         * * Checks if wasAlreadyEnqueued() and returns if co
         * * Generates boxing structure wih following info
         *   * guid - generated using Helpers.guid()
         *   * url - url to be processed
         *   * processor - name of previously registered processor to parse results
         *
         * @param url Url to be enqueued
         * @param processor Name of processor to be used for processing result page
         * @param data Optional data to pass to processor
         * @returns {boolean} True if newly queued, false if already queued (or processing, done, failed ...)
         */
        QueueMemory.prototype.enqueueUrl = function(url, processor, data) {
            if(this.wasAlreadyEnqueued(url, processor)) {
                return false;
            }

            /*
            if(Object.prototype.toString.call(url) !== '[object Array]') {
            }
            //*/

            var item = {
                guid: Helpers.guid(),
                url: url,
                processor: processor
            };

            if(data) {
                item.data = data;
            }

            this.queue.requested.push(item);
            return true;
        };

        /**
         * Process finished request
         *
         * It means following:
         *
         * * Remove item from this.queue.processing
         * * Add item to this.queue.done
         *
         * @param item Item to be moved from this.queue.processing to this.queue.done
         * @returns {boolean} True if the move happened
         */
        QueueMemory.prototype.finishRequested = function(item) {
            for(var i = 0; i < this.queue.processing.length; i++) {
                var tmp = this.queue.processing[i];
                if(tmp.guid !== item.guid) {
                    continue;
                }

                this.queue.processing.splice(i, 1);
                this.queue.done.push(item);
                return true;
            }

            return false;
        };

        /**
         * Returns true if all request were processed
         *
         * It means following:
         *
         * * this.queue.requested is empty
         * * this.queue.processing is empty
         *
         * TODO: Decide how to handle failed items
         *
         * @returns {boolean} True if everything was processed
         */
        QueueMemory.prototype.isDone = function() {
            return this.queue.requested.length === 0 &&
                this.queue.processing.length === 0;
        };

        QueueMemory.prototype.getNextRequested = function() {
            // TODO: This must be 'atomic'
            if(this.queue.requested.length > 0) {
                var item = this.queue.requested.shift();
                return item;
            }

            return null;
        };

        QueueMemory.prototype.addProcessing = function(item) {
            this.queue.processing.push(item);
        };

        /**
         * Checks if specified combination of url and processor was already enqueued
         * @param url Url to be enqueued
         * @param processor Processor to be used for processing url
         * @returns {boolean} True if already enqueued (or processing, or done ..)
         */
        QueueMemory.prototype.wasAlreadyEnqueued = function(url, processor) {
            var queues = [
                this.queue.requested,
                this.queue.processing,
                this.queue.done,
                this.queue.failed
            ];

            // TODO: This is *VERY* naive implementation with unnecessary O(n) complexity
            //       It will be much better if there will be some parallel and synchronized
            //       container with better access complexity. Not important for now. (21/4/2014)
            for(var i = 0; i < queues.length; i++) {
                var queue = queues[i];
                for(var j = 0; j < queue.length; j++) {
                    var item = queue[j];
                    if(item.url === url && item.processor === processor) {
                        return true;
                    }
                }
            }

            return false;
        };

        // TODO: Implement following
        // * get(queue) - get item from queue, queue can be object or name
        // * put(item, queue) - put item to queue specified, queue can be object or name
        // * count(queue) - get count of items in queue, queue can be object or name
        // * move(item, from, to) - move item from 'fromQueue' to 'toQueue'

        module.exports = QueueMemory;
    });
}());<commit_msg>Subclass of QueueBase now<commit_after>// Copyright, 2013-2014, by Tomas Korcak. <korczis@gmail.com>
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

(function () {
    'use strict';

    var define = require('amdefine')(module);

    /**
     * Array of modules this one depends on.
     * @type {Array}
     */
    var deps = [
        'util',
        '../helpers'
    ];

    define(deps, function(util, Helpers) {
        var QueueBase = require('./queueBase');

        /**
         * In Memory Queue Class
         * @class
         */
        function QueueMemory(opts) {
            opts = opts || {};

            this.queue = {
                requested: [],
                processing: [],
                done: [],
                failed: []
            };
        }

        util.inherits(QueueMemory, QueueBase);

        /**
         * Enqueue new URL and specify processor to parse page (and optionally the data passed)
         *
         * Procedure is following:
         *
         * * Checks if wasAlreadyEnqueued() and returns if co
         * * Generates boxing structure wih following info
         *   * guid - generated using Helpers.guid()
         *   * url - url to be processed
         *   * processor - name of previously registered processor to parse results
         *
         * @param url Url to be enqueued
         * @param processor Name of processor to be used for processing result page
         * @param data Optional data to pass to processor
         * @returns {boolean} True if newly queued, false if already queued (or processing, done, failed ...)
         */
        QueueMemory.prototype.enqueueUrl = function(url, processor, data) {
            if(this.wasAlreadyEnqueued(url, processor)) {
                return false;
            }

            /*
            if(Object.prototype.toString.call(url) !== '[object Array]') {
            }
            //*/

            var item = {
                guid: Helpers.guid(),
                url: url,
                processor: processor
            };

            if(data) {
                item.data = data;
            }

            this.queue.requested.push(item);
            return true;
        };

        /**
         * Process finished request
         *
         * It means following:
         *
         * * Remove item from this.queue.processing
         * * Add item to this.queue.done
         *
         * @param item Item to be moved from this.queue.processing to this.queue.done
         * @returns {boolean} True if the move happened
         */
        QueueMemory.prototype.finishRequested = function(item) {
            for(var i = 0; i < this.queue.processing.length; i++) {
                var tmp = this.queue.processing[i];
                if(tmp.guid !== item.guid) {
                    continue;
                }

                this.queue.processing.splice(i, 1);
                this.queue.done.push(item);
                return true;
            }

            return false;
        };

        /**
         * Returns true if all request were processed
         *
         * It means following:
         *
         * * this.queue.requested is empty
         * * this.queue.processing is empty
         *
         * TODO: Decide how to handle failed items
         *
         * @returns {boolean} True if everything was processed
         */
        QueueMemory.prototype.isDone = function() {
            return this.queue.requested.length === 0 &&
                this.queue.processing.length === 0;
        };

        QueueMemory.prototype.getNextRequested = function() {
            // TODO: This must be 'atomic'
            if(this.queue.requested.length > 0) {
                var item = this.queue.requested.shift();
                return item;
            }

            return null;
        };

        QueueMemory.prototype.addProcessing = function(item) {
            this.queue.processing.push(item);
        };

        /**
         * Checks if specified combination of url and processor was already enqueued
         * @param url Url to be enqueued
         * @param processor Processor to be used for processing url
         * @returns {boolean} True if already enqueued (or processing, or done ..)
         */
        QueueMemory.prototype.wasAlreadyEnqueued = function(url, processor) {
            var queues = [
                this.queue.requested,
                this.queue.processing,
                this.queue.done,
                this.queue.failed
            ];

            // TODO: This is *VERY* naive implementation with unnecessary O(n) complexity
            //       It will be much better if there will be some parallel and synchronized
            //       container with better access complexity. Not important for now. (21/4/2014)
            for(var i = 0; i < queues.length; i++) {
                var queue = queues[i];
                for(var j = 0; j < queue.length; j++) {
                    var item = queue[j];
                    if(item.url === url && item.processor === processor) {
                        return true;
                    }
                }
            }

            return false;
        };

        module.exports = QueueMemory;
    });
}());<|endoftext|>


<commit_before>/**
 * Production environment settings
 *
 * This file can include shared settings for a production environment,
 * such as API keys or remote database passwords.  If you're using
 * a version control solution for your Sails app, this file will
 * be committed to your repository unless you add it to your .gitignore
 * file.  If your repository will be publicly viewable, don't add
 * any private information to this file!
 *
 */

module.exports = {

    /***************************************************************************
     * Set the default database connection for models in the production        *
     * environment (see config/connections.js and config/models.js )           *
     ***************************************************************************/

    models: {
        connection: 'prodMySQL',
        migrate: 'safe'
    },

    /***************************************************************************
     * Set the port in the production environment to 80                        *
     ***************************************************************************/

    port: 80,

    /***************************************************************************
     * Set the log level in production environment to "silent"                 *
     ***************************************************************************/

    log: {
        level: "silent"
    }
};
<commit_msg>Prod issues<commit_after>/**
 * Production environment settings
 *
 * This file can include shared settings for a production environment,
 * such as API keys or remote database passwords.  If you're using
 * a version control solution for your Sails app, this file will
 * be committed to your repository unless you add it to your .gitignore
 * file.  If your repository will be publicly viewable, don't add
 * any private information to this file!
 *
 */

module.exports = {

    /***************************************************************************
     * Set the default database connection for models in the production        *
     * environment (see config/connections.js and config/models.js )           *
     ***************************************************************************/

    models: {
        connection: 'prodMySQL',
        migrate: 'safe'
    },

    /***************************************************************************
     * Set the port in the production environment to 80                        *
     ***************************************************************************/

    port: 80,

    /***************************************************************************
     * Set the log level in production environment to "silent"                 *
     ***************************************************************************/

    //log: {
      //  level: "silent"
    //}
};
<|endoftext|>


<commit_before>/* global videojs */
import React from 'react'
import { webcastPropType } from '../../utils/webcastUtils'

export default class EmbedHtml5 extends React.Component {
  static propTypes = {
    webcast: webcastPropType.isRequired,
  }

  componentDidMount() {
    videojs(this.props.webcast.id, {
      width: '100%',
      height: '100%',
      autoplay: true,
    })
  }

  render() {
    return (
      <video
        controls
        id={this.props.webcast.id}
        className="video-js vjs-default-skin"
      >
        <source src={this.props.webcast.channel} type="application/x-mpegurl" />
      </video>
    )
  }
}
<commit_msg>Set cross origin tag for html5 embeds<commit_after>/* global videojs */
import React from 'react'
import { webcastPropType } from '../../utils/webcastUtils'

export default class EmbedHtml5 extends React.Component {
  static propTypes = {
    webcast: webcastPropType.isRequired,
  }

  componentDidMount() {
    videojs(this.props.webcast.id, {
      width: '100%',
      height: '100%',
      autoplay: true,
    })
  }

  render() {
    return (
      <video
        controls
        crossorigin="anonymous"
        id={this.props.webcast.id}
        className="video-js vjs-default-skin"
      >
        <source src={this.props.webcast.channel} type="application/x-mpegurl" />
      </video>
    )
  }
}
<|endoftext|>


<commit_before>var expect = require("expect.js");

var util = require("../../lib/util");

describe("util", function() {
  var pusher;

  describe(".toOrderedArray", function() {
    it("should return an empty array for an empty object", function() {
      expect(util.toOrderedArray({})).to.eql([]);
    });

    it("should return a one-element array for an object with one key", function() {
      expect(util.toOrderedArray({ xxx: 123 })).to.eql(["xxx=123"]);
    });

    it("should return an array sorted by object keys for an object with multiple keys", function() {
      expect(util.toOrderedArray({ xxx: 123, aaa: 1, foo: "string" })).to.eql(
        ["aaa=1", "foo=string", "xxx=123"]
      );
    });
  });
});
<commit_msg>Remove util tests, they are covered by other tests<commit_after><|endoftext|>


<commit_before>module.exports = function(app, db) {

  //*****************************// Index //**********************************//
  app.get('/api/features', function(req, res) {
    var cb = function(error, features) {
      if (!error) {
        res.json(features); // Write the jsonified features to the response object
      } else {
        res.json(error);
      }
    };
    features = db.feature.findAll(cb);
  });

  //******************************// Show //**********************************//
  app.get('/api/features/:id', function(req, res) {
    db.feature.find({
        id: req.params.id
      },
      function(error, feature) {
        if (!error) {
          if (feature.length) {
            res.json(feature[0]);
          } else {
            res.json({
              message: 'Object Not Found'
            });
          }
        } else {
          res.json(error);
        }
      });
  });

  //*****************************// Create //*********************************//
  app.post('/api/features', function(req, res) {
    var data = req.body;

    db.feature.create({
      message: data.message,
      action: data.action,
      image: data.image, //we save the InkBLob of the image to delete it when the project is deleted
      InkBlob: (data.InkBlob && typeof data.InkBlob === "object")?  JSON.stringify(data.InkBlob) : data.InkBlob,
      published: data.published
    }, function(error, feature) {
      if (!error) {
        res.json(feature);
      } else {
        res.json(error);
      }
    });
  });

  //*****************************// Update //*********************************//
  app.put('/api/features/:id', function(req, res) {
    var data = req.body;
    db.feature.update(req.params.id, req.body, function(error, feature) {
      if (error) {
        return res.send(error);
      } else {
        res.json(feature);
      }
    });
  });

  //*****************************// Destroy //********************************//
  app.del('/api/features/:id', function (req, res){
    return db.feature.remove(req.params.id, function (error) {
        if (!error) {
          res.send('');
        } else {
          res.send(error);
        }
      });
    });

};
<commit_msg>Add Action URL to the features API<commit_after>module.exports = function(app, db) {

  //*****************************// Index //**********************************//
  app.get('/api/features', function(req, res) {
    var cb = function(error, features) {
      if (!error) {
        res.json(features); // Write the jsonified features to the response object
      } else {
        res.json(error);
      }
    };
    features = db.feature.findAll(cb);
  });

  //******************************// Show //**********************************//
  app.get('/api/features/:id', function(req, res) {
    db.feature.find({
        id: req.params.id
      },
      function(error, feature) {
        if (!error) {
          if (feature.length) {
            res.json(feature[0]);
          } else {
            res.json({
              message: 'Object Not Found'
            });
          }
        } else {
          res.json(error);
        }
      });
  });

  //*****************************// Create //*********************************//
  app.post('/api/features', function(req, res) {
    var data = req.body;

    db.feature.create({
      message: data.message,
      action: data.action,
      actionUrl: data.actionUrl,
      image: data.image, //we save the InkBLob of the image to delete it when the project is deleted
      InkBlob: (data.InkBlob && typeof data.InkBlob === "object")?  JSON.stringify(data.InkBlob) : data.InkBlob,
      published: data.published
    }, function(error, feature) {
      if (!error) {
        res.json(feature);
      } else {
        res.json(error);
      }
    });
  });

  //*****************************// Update //*********************************//
  app.put('/api/features/:id', function(req, res) {
    var data = req.body;
    db.feature.update(req.params.id, req.body, function(error, feature) {
      if (error) {
        return res.send(error);
      } else {
        res.json(feature);
      }
    });
  });

  //*****************************// Destroy //********************************//
  app.del('/api/features/:id', function (req, res){
    return db.feature.remove(req.params.id, function (error) {
        if (!error) {
          res.send('');
        } else {
          res.send(error);
        }
      });
    });

};
<|endoftext|>


<commit_before>class RcdXmlElement {
    constructor(tagName) {
        this.tagName = tagName;
        this.attributes = {};
        this.text;
        this.children = [];
    }

    setAttribute(key, value) {
        this.attributes[key] = value;
        return this;
    }

    setText(text) {
        this.text = text;
        return this;
    }

    addChild(child) {
        this.children.push(child);
        return this;
    }

    removeChild(child) {
        var index = this.children.indexOf(child);
        if (index > -1) {
            this.children.splice(index, 1);
        }
        return this;
    }
}

class RcdDomElement extends RcdXmlElement {
    constructor(name) {
        super(name);
        this.domElement = document.createElement(name);
    }

    getDomElement() {
        return this.domElement;
    }

    setAttribute(key, value) {
        super.setAttribute(key, value);
        this.domElement.setAttribute(key, value);
        return this;
    }

    setText(text) {
        super.setText(text);
        this.domElement.innerHTML = text;
        return this;
    }

    addChild(child) {
        super.addChild(child);
        this.domElement.appendChild(child.getDomElement());
        return this;
    }

    removeChild(child) {
        super.removeChild(child);
        this.domElement.removeChild(child.getDomElement());
        return this;
    }

    removeAllChildren() {
        var children = this.children.slice();
        children.forEach((child) => this.removeChild(child));
        return this;
    }

    clear() {
        this.domElement.innerHTML = '';
    }

    show(parent = document.body) {
        if (parent instanceof RcdDomElement) {
            parent.getDomElement().appendChild(this.getDomElement());
        } else {
            parent.appendChild(this.getDomElement());
        }
        return this;
    }

    hide(parent = document.body) {
        if (parent instanceof RcdDomElement) {
            parent.getDomElement().removeChild(this.getDomElement());
        } else {
            parent.removeChild(this.getDomElement());
        }
    }
}

class RcdHtmlElement extends RcdDomElement {
    constructor(name) {
        super(name);
        this.classes = [];
        this.clickListeners = []; //TODO Make it event generic
    }

    init() {
        return this;
    }

    setId(id) {
        this.setAttribute('id', id);
        return this;
    }

    hasClass(aClass) {
        return this.classes.indexOf(aClass) != -1;
    }

    addClass(aClass) {
        if (!this.hasClass(aClass)) {
            this.classes.push(aClass);
            this.setAttribute("class", this.classes.join(' '));
        }
        return this;
    }

    removeClass(aClass) {
        var index = this.classes.indexOf(aClass);
        if (index != -1) {
            this.classes.splice(index, 1);
            this.setAttribute("class", this.classes.join(' '));
        }
        return this;
    }

    addEventListener(type, listener) {
        this.domElement.addEventListener(type, listener);
        return this;
    }

    removeEventListener(type, listener) {
        this.domElement.removeEventListener(type, listener);
        return this;
    }

    setClickListener(listener) {
        this.clickListeners.forEach((clickListener) => this.removeClickListener(clickListener));
        return this.addClickListener(listener);
    }

    addClickListener(listener) {
        this.clickListeners.push(listener);
        return this.addEventListener('click', listener);
    }

    addMouseOverListener(listener) {
        return this.addEventListener('mouseover', listener);
    }

    addMouseOutListener(listener) {
        return this.addEventListener('mouseout', listener);
    }

    addChangeListener(listener) {
        return this.addEventListener('change', listener);
    }

    removeClickListener(listener) {
        var index = this.clickListeners.indexOf(listener);
        if (index > -1) {
            this.clickListeners.splice(index, 1);
        }
        return this.removeEventListener('click', listener);
    }

    addKeyUpListener(key, listener) {
        return this.addEventListener('keyup', (event)=> {
            if (!key || key == event.key) {
                listener(event);
            }
        });
    }

    isSelected() {
        return this.classes.indexOf('selected') != -1;
    }

    select(selected) {
        if (selected) {
            this.addClass('selected');
        } else {
            this.removeClass('selected');
        }
        return this;
    }

    click() {
        this.getDomElement().click();
        return this;
    }

    setTooltip(tooltip) {
        this.setAttribute('title', tooltip);
        return this;
    }

    setPosition(left, top) {
        this.domElement.style.position = 'absolute';
        this.domElement.style.left = left + 'px';
        this.domElement.style.top = top + 'px';
        return this;
    }

    focus() {
        this.domElement.focus();
        return this;
    }
}

class RcdDivElement extends RcdHtmlElement {
    constructor() {
        super('div');
    }

    focus() {
        this.setAttribute('tabindex', 0);
        super.focus();
        return this;
    }
}

class RcdPElement extends RcdHtmlElement {
    constructor() {
        super('p');
    }
}

class RcdHeaderElement extends RcdHtmlElement {
    constructor() {
        super('header');
    }
}

class RcdIElement extends RcdHtmlElement {
    constructor() {
        super('i');
    }
}

class RcdSpanElement extends RcdHtmlElement {
    constructor() {
        super('span');
    }
}

class RcdMainElement extends RcdHtmlElement {
    constructor() {
        super('main');
    }
}

class RcdNavElement extends RcdHtmlElement {
    constructor() {
        super('nav');
    }
}

class RcdTableElement extends RcdHtmlElement {
    constructor() {
        super('table');
    }
}

class RcdTheadElement extends RcdHtmlElement {
    constructor() {
        super('thead');
    }
}

class RcdTbodyElement extends RcdHtmlElement {
    constructor() {
        super('tbody');
    }
}

class RcdTfootElement extends RcdHtmlElement {
    constructor() {
        super('tfoot');
    }
}

class RcdTrElement extends RcdHtmlElement {
    constructor() {
        super('tr');
    }
}

class RcdThElement extends RcdHtmlElement {
    constructor() {
        super('th');
    }
}

class RcdTdElement extends RcdHtmlElement {
    constructor() {
        super('td');
    }
}

class RcdFormElement extends RcdHtmlElement {
    constructor() {
        super('form');
    }

    submit() {
        this.getDomElement().submit();
    }
}

class RcdSelectElement extends RcdHtmlElement {
    constructor() {
        super('select');
        this.options = [];
    }

    addOptions(optionTexts) {
        optionTexts.forEach(optionText => this.addOption(optionText));
        return this;
    }

    addOption(optionText) {
        var optionElement = this.createOptionElement(optionText);
        this.options.push(optionElement);
        return this.addChild(optionElement)
    }

    createOptionElement(optionText) {
        return new RcdOptionElement(optionText).
            init().
            setValue(optionText).
            setText(optionText);
    }

    getSelectedIndex() {
        return this.domElement.selectedIndex
    }

    getValue() {
        return this.options[this.getSelectedIndex()].getValue();
    }
}

class RcdOptionElement extends RcdHtmlElement {
    constructor() {
        super('option');
    }

    getValue() {
        return this.domElement.value;
    }

    setValue(value) {
        this.domElement.value = value;
        return this;
    }
}

class RcdInputElement extends RcdHtmlElement {
    constructor(placeholder) {
        super('input');
        this.placeholder = placeholder
    }

    init() {
        this.domElement.placeholder = this.placeholder;
        return this;
    }

    getValue() {
        return this.domElement.value;
    }

    setValue(value) {
        this.domElement.value = value;
        return this;
    }

    select() {
        this.domElement.select();
        return this;
    }
}

<commit_msg>Display with boolean as parameter<commit_after>class RcdXmlElement {
    constructor(tagName) {
        this.tagName = tagName;
        this.attributes = {};
        this.text;
        this.children = [];
    }

    setAttribute(key, value) {
        this.attributes[key] = value;
        return this;
    }

    setText(text) {
        this.text = text;
        return this;
    }

    addChild(child) {
        this.children.push(child);
        return this;
    }

    removeChild(child) {
        var index = this.children.indexOf(child);
        if (index > -1) {
            this.children.splice(index, 1);
        }
        return this;
    }
}

class RcdDomElement extends RcdXmlElement {
    constructor(name) {
        super(name);
        this.domElement = document.createElement(name);
    }

    getDomElement() {
        return this.domElement;
    }

    setAttribute(key, value) {
        super.setAttribute(key, value);
        this.domElement.setAttribute(key, value);
        return this;
    }

    setText(text) {
        super.setText(text);
        this.domElement.innerHTML = text;
        return this;
    }

    addChild(child) {
        super.addChild(child);
        this.domElement.appendChild(child.getDomElement());
        return this;
    }

    removeChild(child) {
        super.removeChild(child);
        this.domElement.removeChild(child.getDomElement());
        return this;
    }

    removeAllChildren() {
        var children = this.children.slice();
        children.forEach((child) => this.removeChild(child));
        return this;
    }

    clear() {
        this.domElement.innerHTML = '';
    }

    show(parent = document.body) {
        if (parent instanceof RcdDomElement) {
            parent.getDomElement().appendChild(this.getDomElement());
        } else {
            parent.appendChild(this.getDomElement());
        }
        return this;
    }

    hide(parent = document.body) {
        if (parent instanceof RcdDomElement) {
            parent.getDomElement().removeChild(this.getDomElement());
        } else {
            parent.removeChild(this.getDomElement());
        }
    }
}

class RcdHtmlElement extends RcdDomElement {
    constructor(name) {
        super(name);
        this.classes = [];
        this.clickListeners = []; //TODO Make it event generic
    }

    init() {
        return this;
    }

    setId(id) {
        this.setAttribute('id', id);
        return this;
    }

    hasClass(aClass) {
        return this.classes.indexOf(aClass) != -1;
    }

    addClass(aClass) {
        if (!this.hasClass(aClass)) {
            this.classes.push(aClass);
            this.setAttribute("class", this.classes.join(' '));
        }
        return this;
    }

    removeClass(aClass) {
        var index = this.classes.indexOf(aClass);
        if (index != -1) {
            this.classes.splice(index, 1);
            this.setAttribute("class", this.classes.join(' '));
        }
        return this;
    }

    addEventListener(type, listener) {
        this.domElement.addEventListener(type, listener);
        return this;
    }

    removeEventListener(type, listener) {
        this.domElement.removeEventListener(type, listener);
        return this;
    }

    setClickListener(listener) {
        this.clickListeners.forEach((clickListener) => this.removeClickListener(clickListener));
        return this.addClickListener(listener);
    }

    addClickListener(listener) {
        this.clickListeners.push(listener);
        return this.addEventListener('click', listener);
    }

    addMouseOverListener(listener) {
        return this.addEventListener('mouseover', listener);
    }

    addMouseOutListener(listener) {
        return this.addEventListener('mouseout', listener);
    }

    addChangeListener(listener) {
        return this.addEventListener('change', listener);
    }

    removeClickListener(listener) {
        var index = this.clickListeners.indexOf(listener);
        if (index > -1) {
            this.clickListeners.splice(index, 1);
        }
        return this.removeEventListener('click', listener);
    }

    addKeyUpListener(key, listener) {
        return this.addEventListener('keyup', (event)=> {
            if (!key || key == event.key) {
                listener(event);
            }
        });
    }

    isSelected() {
        return this.classes.indexOf('selected') != -1;
    }

    select(selected) {
        if (selected) {
            this.addClass('selected');
        } else {
            this.removeClass('selected');
        }
        return this;
    }

    click() {
        this.getDomElement().click();
        return this;
    }

    setTooltip(tooltip) {
        this.setAttribute('title', tooltip);
        return this;
    }

    setPosition(left, top) {
        this.domElement.style.position = 'absolute';
        this.domElement.style.left = left + 'px';
        this.domElement.style.top = top + 'px';
        return this;
    }

    focus() {
        this.domElement.focus();
        return this;
    }

    display(display) {
        if (display) {
            this.removeClass('rcd-hidden');
        } else {
            this.addClass('rcd-hidden');
        }
    }
}

class RcdDivElement extends RcdHtmlElement {
    constructor() {
        super('div');
    }

    focus() {
        this.setAttribute('tabindex', 0);
        super.focus();
        return this;
    }
}

class RcdPElement extends RcdHtmlElement {
    constructor() {
        super('p');
    }
}

class RcdHeaderElement extends RcdHtmlElement {
    constructor() {
        super('header');
    }
}

class RcdIElement extends RcdHtmlElement {
    constructor() {
        super('i');
    }
}

class RcdSpanElement extends RcdHtmlElement {
    constructor() {
        super('span');
    }
}

class RcdMainElement extends RcdHtmlElement {
    constructor() {
        super('main');
    }
}

class RcdNavElement extends RcdHtmlElement {
    constructor() {
        super('nav');
    }
}

class RcdTableElement extends RcdHtmlElement {
    constructor() {
        super('table');
    }
}

class RcdTheadElement extends RcdHtmlElement {
    constructor() {
        super('thead');
    }
}

class RcdTbodyElement extends RcdHtmlElement {
    constructor() {
        super('tbody');
    }
}

class RcdTfootElement extends RcdHtmlElement {
    constructor() {
        super('tfoot');
    }
}

class RcdTrElement extends RcdHtmlElement {
    constructor() {
        super('tr');
    }
}

class RcdThElement extends RcdHtmlElement {
    constructor() {
        super('th');
    }
}

class RcdTdElement extends RcdHtmlElement {
    constructor() {
        super('td');
    }
}

class RcdFormElement extends RcdHtmlElement {
    constructor() {
        super('form');
    }

    submit() {
        this.getDomElement().submit();
    }
}

class RcdSelectElement extends RcdHtmlElement {
    constructor() {
        super('select');
        this.options = [];
    }

    addOptions(optionTexts) {
        optionTexts.forEach(optionText => this.addOption(optionText));
        return this;
    }

    addOption(optionText) {
        var optionElement = this.createOptionElement(optionText);
        this.options.push(optionElement);
        return this.addChild(optionElement)
    }

    createOptionElement(optionText) {
        return new RcdOptionElement(optionText).
            init().
            setValue(optionText).
            setText(optionText);
    }

    getSelectedIndex() {
        return this.domElement.selectedIndex
    }

    getValue() {
        return this.options[this.getSelectedIndex()].getValue();
    }
}

class RcdOptionElement extends RcdHtmlElement {
    constructor() {
        super('option');
    }

    getValue() {
        return this.domElement.value;
    }

    setValue(value) {
        this.domElement.value = value;
        return this;
    }
}

class RcdInputElement extends RcdHtmlElement {
    constructor(placeholder) {
        super('input');
        this.placeholder = placeholder
    }

    init() {
        this.domElement.placeholder = this.placeholder;
        return this;
    }

    getValue() {
        return this.domElement.value;
    }

    setValue(value) {
        this.domElement.value = value;
        return this;
    }

    select() {
        this.domElement.select();
        return this;
    }
}

<|endoftext|>


<commit_before>import { isFunction, uniqueId, remove, find, isNumber, isString, keys, noop, isEqual, pick } from 'lodash'
import { getNodes } from '../utils/context'
import { contains } from '../utils/dom'

let clickHandlerBindings = []
const clickBindingKey = '__veui_click_outside__'
document.addEventListener('click', e => {
  clickHandlerBindings.forEach(item => {
    item[clickBindingKey] && item[clickBindingKey].handler(e)
  })
}, true)

let hoverHandlerBindings = []
const hoverBindingKey = '__veui_hover_outside__'
document.addEventListener('mouseout', e => {
  hoverHandlerBindings.forEach(item => {
    item[hoverBindingKey] && item[hoverBindingKey].handler(e)
  })
})

function getElementsByRefs (refs, context) {
  const elements = []
  refs.forEach((ref) => {
    elements.push(...getNodes(ref, context))
  })
  return elements
}

function parseParams (el, arg, modifiers, value, context) {
  let refs
  let handler
  let trigger
  // delay 表示如果鼠标移动到 includeTargets 元素之外多少秒之后，才会触发 handler
  let delay

  // 如果 value 是 Function 的话，其余参数就尽量从 modifier、arg 里面去解析
  // 否则从value里面去解析
  if (isFunction(value)) {
    handler = value

    refs = arg ? arg.split(',') : []

    trigger = modifiers.hover ? 'hover' : 'click'

    delay = find(keys(modifiers), key => isNumber(parseInt(key, 10)) && modifiers[key])
    delay = delay ? parseInt(delay, 10) : 0
  } else {
    const normalizedValue = value || {}
    handler = isFunction(normalizedValue.handler) ? normalizedValue.handler : noop

    refs = Array.isArray(normalizedValue.refs) ? normalizedValue.refs
      : (isString(normalizedValue.refs) ? normalizedValue.refs.split(',') : [normalizedValue.refs])

    trigger = normalizedValue.trigger === 'hover' ? 'hover' : 'click'

    delay = parseInt(normalizedValue.delay, 10)
    if (isNaN(delay)) {
      delay = 0
    }
  }

  return {
    refs,
    handler,
    trigger,
    delay
  }
}

function generate (el, { handler, trigger, delay, refs }, context) {
  if (trigger === 'click') {
    return function (e) {
      // click 模式，直接判断元素包含情况
      let includeTargets = [el, ...getElementsByRefs(refs, context)]
      if (e.type === trigger && !includeTargets.some(element => contains(element, e.target))) {
        handler(e)
      }
    }
  }

  if (trigger === 'hover') {
    if (!delay) {
      return function (e) {
        let includeTargets = [el, ...getElementsByRefs(refs, context)]
        // 从 includeTargets 区域移到外面去了，果断触发 handler
        if (includeTargets.some(target => contains(target, e.target)) &&
          !includeTargets.some(target => contains(target, e.relatedTarget))
        ) {
          handler(e)
        }
      }
    }

    let hoverDelayData = {
      state: 'ready' // 'ready' | 'out' | 'in'
    }
    return function (e) {
      let includeTargets = [el, ...getElementsByRefs(refs, context)]
      let isTargetIn = includeTargets.some(target => contains(target, e.target))
      let isRelatedTargetIn = includeTargets.some(target => contains(target, e.relatedTarget))
      if (isTargetIn && !isRelatedTargetIn) {
        hoverDelayData.state = 'out'

        el[hoverBindingKey].timer = setTimeout(() => {
          if (hoverDelayData.state === 'out') {
            handler(e)
          }
        }, delay)
      } else if (!isTargetIn && isRelatedTargetIn) {
        hoverDelayData.state = 'in'
      }
    }
  }
}

function clear (el) {
  if (el[clickBindingKey]) {
    remove(clickHandlerBindings, item => item[clickBindingKey].id === el[clickBindingKey].id)
    el[clickBindingKey] = null
  }

  if (el[hoverBindingKey]) {
    remove(hoverHandlerBindings, item => item[hoverBindingKey].id === el[hoverBindingKey].id)
    clearTimeout(el[hoverBindingKey].timer)
    el[hoverBindingKey] = null
  }
}

function refresh (el, { value, arg, modifiers, oldValue }, vnode) {
  const params = parseParams(el, arg, modifiers, value, vnode.context)

  // 真正发生了变化，才重刷
  let fields = params.trigger === 'click'
    ? ['refs', 'trigger']
    : ['refs', 'trigger', 'delay']
  if (isEqual(pick(el[params.trigger === 'click' ? clickBindingKey : hoverBindingKey], fields), pick(params, fields))) {
    return
  }

  clear(el)
  if (params.trigger === 'click') {
    el[clickBindingKey] = {
      id: uniqueId('veui-outside-'),
      handler: generate(el, params, vnode.context),
      trigger: 'click',
      refs: params.refs
    }
    clickHandlerBindings.push(el)
  } else if (params.trigger === 'hover') {
    el[hoverBindingKey] = {
      id: uniqueId('veui-outside-'),
      handler: generate(el, params, vnode.context),
      trigger: 'hover',
      delay: params.delay,
      refs: params.refs
    }
    hoverHandlerBindings.push(el)
  }
}

export default {
  bind: refresh,
  componentUpdated: refresh,
  unbind: clear
}
<commit_msg>加点注释说明<commit_after>import { isFunction, uniqueId, remove, find, isNumber, isString, keys, noop, isEqual, pick } from 'lodash'
import { getNodes } from '../utils/context'
import { contains } from '../utils/dom'

let clickHandlerBindings = []
const clickBindingKey = '__veui_click_outside__'
document.addEventListener('click', e => {
  clickHandlerBindings.forEach(item => {
    item[clickBindingKey] && item[clickBindingKey].handler(e)
  })
}, true)

let hoverHandlerBindings = []
const hoverBindingKey = '__veui_hover_outside__'
document.addEventListener('mouseout', e => {
  hoverHandlerBindings.forEach(item => {
    item[hoverBindingKey] && item[hoverBindingKey].handler(e)
  })
})

function getElementsByRefs (refs, context) {
  const elements = []
  refs.forEach((ref) => {
    elements.push(...getNodes(ref, context))
  })
  return elements
}

function parseParams (el, arg, modifiers, value, context) {
  let refs
  let handler
  let trigger
  // delay 表示如果鼠标移动到 includeTargets 元素之外多少秒之后，才会触发 handler
  let delay

  // 如果 value 是 Function 的话，其余参数就尽量从 modifier、arg 里面去解析
  // 否则从value里面去解析
  if (isFunction(value)) {
    handler = value

    refs = arg ? arg.split(',') : []

    trigger = modifiers.hover ? 'hover' : 'click'

    delay = find(keys(modifiers), key => isNumber(parseInt(key, 10)) && modifiers[key])
    delay = delay ? parseInt(delay, 10) : 0
  } else {
    const normalizedValue = value || {}
    handler = isFunction(normalizedValue.handler) ? normalizedValue.handler : noop

    refs = Array.isArray(normalizedValue.refs) ? normalizedValue.refs
      : (isString(normalizedValue.refs) ? normalizedValue.refs.split(',') : [normalizedValue.refs])

    trigger = normalizedValue.trigger === 'hover' ? 'hover' : 'click'

    delay = parseInt(normalizedValue.delay, 10)
    if (isNaN(delay)) {
      delay = 0
    }
  }

  return {
    refs,
    handler,
    trigger,
    delay
  }
}

/**
 * 判断 element 在 DOM 树结构上是否被包含在 elements 里面
 *
 * @param {Element} element 待判断的元素
 * @param {Array.<Element>} elements 元素范围
 */
function isElementIn (element, elements) {
  return elements.some(elm => contains(elm, element))
}

function generate (el, { handler, trigger, delay, refs }, context) {
  if (trigger === 'click') {
    return function (e) {
      // click 模式，直接判断元素包含情况
      let includeTargets = [el, ...getElementsByRefs(refs, context)]
      if (e.type === trigger && !isElementIn(e.target, includeTargets)) {
        handler(e)
      }
    }
  }

  if (trigger === 'hover') {
    if (!delay) {
      // 如果没有设置 delay 参数，只要检查到鼠标移到 includeTargets 外面去了，就果断触发 outside handler 。
      return function handleOutsideWithoutDelay (e) {
        let includeTargets = [el, ...getElementsByRefs(refs, context)]
        // 从 includeTargets 区域移到外面去了，果断触发 handler
        if (isElementIn(e.target, includeTargets) && !isElementIn(e.relatedTarget, includeTargets)) {
          handler(e)
        }
      }
    }

    let hoverDelayData = {
      state: 'ready' // 'ready' | 'out' | 'in'
    }
    // 如果设置了 delay ，在鼠标移出 includeTargets 之后设个计时器，并且标明已经移出去了（ `out` ）。
    // 如果鼠标在计时器计时结束之前，移回了 includeTargets ，就把标记改为 `in` 。
    // 如果鼠标在计时器计时结束时，还没有移回 includeTargets 内，对应的标记位还会是 `out` ，此时就可以出发 outside handler 了。
    return function handleOutsideWithDelay (e) {
      let includeTargets = [el, ...getElementsByRefs(refs, context)]
      let isTargetIn = isElementIn(e.target, includeTargets)
      let isRelatedTargetIn = isElementIn(e.relatedTarget, includeTargets)
      if (isTargetIn && !isRelatedTargetIn) {
        hoverDelayData.state = 'out'

        el[hoverBindingKey].timer = setTimeout(() => {
          if (hoverDelayData.state === 'out') {
            handler(e)
          }
        }, delay)
      } else if (!isTargetIn && isRelatedTargetIn) {
        hoverDelayData.state = 'in'
      }
    }
  }
}

function clear (el) {
  if (el[clickBindingKey]) {
    remove(clickHandlerBindings, item => item[clickBindingKey].id === el[clickBindingKey].id)
    el[clickBindingKey] = null
  }

  if (el[hoverBindingKey]) {
    remove(hoverHandlerBindings, item => item[hoverBindingKey].id === el[hoverBindingKey].id)
    clearTimeout(el[hoverBindingKey].timer)
    el[hoverBindingKey] = null
  }
}

function refresh (el, { value, arg, modifiers, oldValue }, vnode) {
  const params = parseParams(el, arg, modifiers, value, vnode.context)

  // 真正发生了变化，才重刷
  let fields = params.trigger === 'click'
    ? ['refs', 'trigger']
    : ['refs', 'trigger', 'delay']
  if (isEqual(pick(el[params.trigger === 'click' ? clickBindingKey : hoverBindingKey], fields), pick(params, fields))) {
    return
  }

  clear(el)
  if (params.trigger === 'click') {
    el[clickBindingKey] = {
      id: uniqueId('veui-outside-'),
      handler: generate(el, params, vnode.context),
      trigger: 'click',
      refs: params.refs
    }
    clickHandlerBindings.push(el)
  } else if (params.trigger === 'hover') {
    el[hoverBindingKey] = {
      id: uniqueId('veui-outside-'),
      handler: generate(el, params, vnode.context),
      trigger: 'hover',
      delay: params.delay,
      refs: params.refs
    }
    hoverHandlerBindings.push(el)
  }
}

export default {
  bind: refresh,
  componentUpdated: refresh,
  unbind: clear
}
<|endoftext|>


<commit_before>/**
* Functions
*/
function nodelistToArray( nodelist ) {
	var array = [];

	for (var i = 0; i < nodelist.length; i++ ) {
		var currentPost = nodelist[i];  // the node for the current post

		// Add node to array
		array.push( currentPost );
	}

	return array;
}

var makePostObject = function( currentPost ) {
	var postLinkNode,
		commentURL,
		postObject;

	postLinkNode = currentPost.children[0].children[0];
	commentURL = currentPost.children[4].children[0].getAttribute("href");

	// construct post object
	postObject = {
		"link": postLinkNode,
		"commentURL": commentURL
	}

	return postObject;
}

// send comment url
var messenger = function( message ) {
	chrome.runtime.sendMessage( message );
}

var addPostListener = function( currentPost ) {
	var link,
		comment;

	link = currentPost.link;
	comment = currentPost.commentURL;

	console.log("link: " + link);
	console.log("comment: " + comment);

	link.addEventListener( "click", messenger.bind( null, comment ), false);
}

var main = function() {
	var postList,
		postArray,
		postObjectArray;

	// get nodelist of post elements and convert to array
	postList = document.querySelectorAll( "div.hit div.title_url" );
	postArray = nodelistToArray( postList );

	// map to array of objects with useful inforation
	postObjectArray = postArray.map( makePostObject );

	// add listeners to each post
	postObjectArray.forEach( addPostListener );
}

window.onload = main;
<commit_msg>Seems to be working!<commit_after>/**
* Functions
*/
function nodelistToArray( nodelist ) {
	var array = [];

	for (var i = 0; i < nodelist.length; i++ ) {
		var currentPost = nodelist[i];  // the node for the current post

		// Add node to array
		array.push( currentPost );
	}

	return array;
}

var makePostObject = function( currentPost ) {
	var postLinkNode,
		commentURL,
		commentID,
		postObject;

	postLinkNode = currentPost.children[0].children[0];
	commentURL = currentPost.children[4].children[0].getAttribute("href");
	commentID = "item?id=" + /\d{1,}$/.exec( commentURL );

	// construct post object
	postObject = {
		"link": postLinkNode,
		"commentURL": commentID
	}

	return postObject;
}

// send comment url
var messenger = function( message ) {
	chrome.runtime.sendMessage( message );
}

var addPostListener = function( currentPost ) {
	var link,
		comment;

	link = currentPost.link;
	comment = currentPost.commentURL;

	link.addEventListener( "click", messenger.bind( null, comment ), false);
}

var main = function() {
	var postList,
		postArray,
		postObjectArray;

	// get nodelist of post elements and convert to array
	postList = document.querySelectorAll( "div.hit div.title_url" );
	postArray = nodelistToArray( postList );

	// map to array of objects with useful inforation
	postObjectArray = postArray.map( makePostObject );

	// add listeners to each post
	postObjectArray.forEach( addPostListener );
}

window.onload = main;
<|endoftext|>


<commit_before>const React = require('react');
const render = require('react-dom');
const _ = require('lodash');
const request = require('superagent');
const moment = require('moment');
const { ArrowBottom } = require('react-bytesize-icons');

const Header = () => (

Turboclean

);

class Task extends React.Component{
  constructor(props) {
    super(props);
    this.state = { collapsed: true };

    this.toggle = this.toggle.bind(this);
  }

  toggle(){
    this.setState({ collapsed: !this.state.collapsed });
  }

  render() {
    const taskClass = (value, other) => {
      switch (value) {
        case value > 0.67:
          return "red " + other;
        case value > 0.33:
          return "orange " + other;
        default:
          return "green " + other;
      }
    };

    const collapsedClass = other => ( this.state.collapsed ? other : `${other} expanded` );

    return (

Room { this.props.task.name }

Trash: { this.props.task.trashFullness } %

Dirtyness: { this.props.task.dirtyness } %

        <ArrowBottom color="#ccc"/>

Location: 7th floor, east

Last cleaned: { moment( this.props.task.updatedAt ).calendar() }

Used after cleaned: XXX

          Press to complete

    );
  }

}

class Tasklist extends React.Component {
  constructor(props) {
    super(props);
  }

  toggle(event){

  }

  handleClick(){

  }

  render() {
    return (

        { _.map(this.props.tasks, row => <Task task={ row } />) }

    );
  }
}

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { targets: [] };
  }

  componentDidMount() {
    request.get('/api/targets').end((err,res) => {
      this.setState({ targets: res.body });
      console.log(res.body);
    });

  }

  render() {
    return (

        <Tasklist tasks={ this.state.targets }/>

    );
  }
}
<commit_msg>Task details<commit_after>const React = require('react');
const render = require('react-dom');
const _ = require('lodash');
const request = require('superagent');
const moment = require('moment');
const { ArrowBottom } = require('react-bytesize-icons');

const Header = () => (

Turboclean

);

class Task extends React.Component{
  constructor(props) {
    super(props);
    this.state = { collapsed: true };

    this.toggle = this.toggle.bind(this);
  }

  toggle(){
    this.setState({ collapsed: !this.state.collapsed });
  }

  render() {
    const taskClass = (value, other) => {
      switch (value) {
        case value > 0.67:
          return "red " + other;
        case value > 0.33:
          return "orange " + other;
        default:
          return "green " + other;
      }
    };

    const collapsedClass = other => ( this.state.collapsed ? other : `${other} expanded` );

    return (

Room { this.props.task.name }

Trash: { this.props.task.trashFullness } %

Dirtyness: { this.props.task.dirtyness } %

        <ArrowBottom color="#ccc"/>

Location: 7th floor, east

Last cleaned: { moment( _.head (_.maxBy(this.props.task.cleanings, 'time') ) ).calendar() }

Used after cleaned: { Math.round(this.props.task.usageHours) } hours

          Press to complete

    );
  }

}

class Tasklist extends React.Component {
  constructor(props) {
    super(props);
  }

  toggle(event){

  }

  handleClick(){

  }

  render() {
    return (

        { _.map(this.props.tasks, row => <Task task={ row } />) }

    );
  }
}

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { targets: [] };
  }

  componentDidMount() {
    request.get('/api/targets').end((err,res) => {
      this.setState({ targets: res.body });
      console.log(res.body);
    });

  }

  render() {
    return (

        <Tasklist tasks={ this.state.targets }/>

    );
  }
}
<|endoftext|>