<commit_before>/**
 * Based on the comment attachment algorithm used in espree and estraverse.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import Parser from "./index";

function last(stack) {
  return stack[stack.length - 1];
}

const pp = Parser.prototype;

pp.addComment = function (comment) {
  this.state.trailingComments.push(comment);
  this.state.leadingComments.push(comment);
};

pp.processComment = function (node) {
  if (node.type === "Program" && node.body.length > 0) return;

  var stack = this.state.commentStack;

  var lastChild, trailingComments, i;

  if (this.state.trailingComments.length > 0) {
    // If the first comment in trailingComments comes after the
    // current node, then we're good - all comments in the array will
    // come after the node and so it's safe to add then as official
    // trailingComments.
    if (this.state.trailingComments[0].start >= node.end) {
      trailingComments = this.state.trailingComments;
      this.state.trailingComments = [];
    } else {
      // Otherwise, if the first comment doesn't come after the
      // current node, that means we have a mix of leading and trailing
      // comments in the array and that leadingComments contains the
      // same items as trailingComments. Reset trailingComments to
      // zero items and we'll handle this by evaluating leadingComments
      // later.
      this.state.trailingComments.length = 0;
    }
  } else {
    var lastInStack = last(stack);
    if (stack.length > 0 && lastInStack.trailingComments && lastInStack.trailingComments[0].start >= node.end) {
      trailingComments = lastInStack.trailingComments;
      lastInStack.trailingComments = null;
    }
  }

  // Eating the stack.
  while (stack.length > 0 && last(stack).start >= node.start) {
    lastChild = stack.pop();
  }

  if (lastChild) {
    if (lastChild.leadingComments) {
      if (lastChild !== node && last(lastChild.leadingComments).end <= node.start) {
        node.leadingComments = lastChild.leadingComments;
        lastChild.leadingComments = null;
      } else {
        // A leading comment for an anonymous class had been stolen by its first MethodDefinition,
        // so this takes back the leading comment.
        // See also: https://github.com/eslint/espree/issues/158
        for (i = lastChild.leadingComments.length - 2; i >= 0; --i) {
          if (lastChild.leadingComments[i].end <= node.start) {
            node.leadingComments = lastChild.leadingComments.splice(0, i + 1);
            break;
          }
        }
      }
    }
  } else if (this.state.leadingComments.length > 0) {
    if (last(this.state.leadingComments).end <= node.start) {
      node.leadingComments = this.state.leadingComments;
      this.state.leadingComments = [];
    } else {
      // https://github.com/eslint/espree/issues/2
      //
      // In special cases, such as return (without a value) and
      // debugger, all comments will end up as leadingComments and
      // will otherwise be eliminated. This this step runs when the
      // commentStack is empty and there are comments left
      // in leadingComments.
      //
      // This loop figures out the stopping point between the actual
      // leading and trailing comments by finding the location of the
      // first comment that comes after the given node.
      for (i = 0; i < this.state.leadingComments.length; i++) {
        if (this.state.leadingComments[i].end > node.start) {
          break;
        }
      }

      // Split the array based on the location of the first comment
      // that comes after the node. Keep in mind that this could
      // result in an empty array, and if so, the array must be
      // deleted.
      node.leadingComments = this.state.leadingComments.slice(0, i);
      if (node.leadingComments.length === 0) {
        node.leadingComments = null;
      }

      // Similarly, trailing comments are attached later. The variable
      // must be reset to null if there are no trailing comments.
      trailingComments = this.state.leadingComments.slice(i);
      if (trailingComments.length === 0) {
        trailingComments = null;
      }
    }
  }

  if (trailingComments) {
    if (trailingComments.length && trailingComments[0].start >= node.start && last(trailingComments).end <= node.end) {
      node.innerComments = trailingComments;
    } else {
      node.trailingComments = trailingComments;
    }
  }

  stack.push(node);
};
<commit_msg>fix typos<commit_after>/**
 * Based on the comment attachment algorithm used in espree and estraverse.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 * * Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import Parser from "./index";

function last(stack) {
  return stack[stack.length - 1];
}

const pp = Parser.prototype;

pp.addComment = function (comment) {
  this.state.trailingComments.push(comment);
  this.state.leadingComments.push(comment);
};

pp.processComment = function (node) {
  if (node.type === "Program" && node.body.length > 0) return;

  var stack = this.state.commentStack;

  var lastChild, trailingComments, i;

  if (this.state.trailingComments.length > 0) {
    // If the first comment in trailingComments comes after the
    // current node, then we're good - all comments in the array will
    // come after the node and so it's safe to add them as official
    // trailingComments.
    if (this.state.trailingComments[0].start >= node.end) {
      trailingComments = this.state.trailingComments;
      this.state.trailingComments = [];
    } else {
      // Otherwise, if the first comment doesn't come after the
      // current node, that means we have a mix of leading and trailing
      // comments in the array and that leadingComments contains the
      // same items as trailingComments. Reset trailingComments to
      // zero items and we'll handle this by evaluating leadingComments
      // later.
      this.state.trailingComments.length = 0;
    }
  } else {
    var lastInStack = last(stack);
    if (stack.length > 0 && lastInStack.trailingComments && lastInStack.trailingComments[0].start >= node.end) {
      trailingComments = lastInStack.trailingComments;
      lastInStack.trailingComments = null;
    }
  }

  // Eating the stack.
  while (stack.length > 0 && last(stack).start >= node.start) {
    lastChild = stack.pop();
  }

  if (lastChild) {
    if (lastChild.leadingComments) {
      if (lastChild !== node && last(lastChild.leadingComments).end <= node.start) {
        node.leadingComments = lastChild.leadingComments;
        lastChild.leadingComments = null;
      } else {
        // A leading comment for an anonymous class had been stolen by its first MethodDefinition,
        // so this takes back the leading comment.
        // See also: https://github.com/eslint/espree/issues/158
        for (i = lastChild.leadingComments.length - 2; i >= 0; --i) {
          if (lastChild.leadingComments[i].end <= node.start) {
            node.leadingComments = lastChild.leadingComments.splice(0, i + 1);
            break;
          }
        }
      }
    }
  } else if (this.state.leadingComments.length > 0) {
    if (last(this.state.leadingComments).end <= node.start) {
      node.leadingComments = this.state.leadingComments;
      this.state.leadingComments = [];
    } else {
      // https://github.com/eslint/espree/issues/2
      //
      // In special cases, such as return (without a value) and
      // debugger, all comments will end up as leadingComments and
      // will otherwise be eliminated. This step runs when the
      // commentStack is empty and there are comments left
      // in leadingComments.
      //
      // This loop figures out the stopping point between the actual
      // leading and trailing comments by finding the location of the
      // first comment that comes after the given node.
      for (i = 0; i < this.state.leadingComments.length; i++) {
        if (this.state.leadingComments[i].end > node.start) {
          break;
        }
      }

      // Split the array based on the location of the first comment
      // that comes after the node. Keep in mind that this could
      // result in an empty array, and if so, the array must be
      // deleted.
      node.leadingComments = this.state.leadingComments.slice(0, i);
      if (node.leadingComments.length === 0) {
        node.leadingComments = null;
      }

      // Similarly, trailing comments are attached later. The variable
      // must be reset to null if there are no trailing comments.
      trailingComments = this.state.leadingComments.slice(i);
      if (trailingComments.length === 0) {
        trailingComments = null;
      }
    }
  }

  if (trailingComments) {
    if (trailingComments.length && trailingComments[0].start >= node.start && last(trailingComments).end <= node.end) {
      node.innerComments = trailingComments;
    } else {
      node.trailingComments = trailingComments;
    }
  }

  stack.push(node);
};
<|endoftext|>


<commit_before>module.exports = function(robot){

	var thankYouResponses = [
		"You're welcome!",
		"No problem."
	];

	robot.hear(/(thanks|thank you) bocbot/i, function(res){
		var index = Math.floor(Math.random() * thankYouResponses.length);
		res.reply(thankYouResponses[index]);
	});

	robot.hear(/I like pie/i, function(res){
		robot.send('I like pie too');
	});

	robot.respond(/open (.*) door/i, function(res){
		var doorType = res.match[1];
		if (doorType == 'pod bay')
			res.reply("I'm afraid I can't let you do that.");
		else
			res.reply('Opening ' + doorType + ' doors.');
	});

	robot.respond(/(you are|you're)(.*) slow/i, function(res){
		setTimeout(function(){
			res.reply('Who you callin\' slow?');
		}, 1000 * 15);
	});

	robot.respond(/(have|drink|consume)(.*) beer/i, function(res){
		var beersHad = robot.brain.get('totalBeersHad') || 0;
		if (beersHad > 4){
			var lastBeerFrom = robot.brain.get('lastBeerFrom');
			res.reply("I think I've had too many.  " + lastBeerFrom + " got me too drunk.  I need to sleep it off first.");
		}
		else{
			res.reply("Sure thing!  _chugs beer_");
			robot.brain.set('totalBeersHad', beersHad + 1);
			robot.brain.set('lastBeerFrom', res.message.user.name);
		}
	});

	robot.respond(/sleep it off/i, function(res){
		robot.brain.set('totalBeersHad', 0);
		res.reply('zzzzz');
	});

	robot.respond(/who am i/, function(res){
		if (robot.auth.isAdmin(res.message.user))
			res.reply(res.message.user.name);
	});

}<commit_msg>Allow everyone to use whoami<commit_after>module.exports = function(robot){

	var thankYouResponses = [
		"You're welcome!",
		"No problem."
	];

	robot.hear(/(thanks|thank you) bocbot/i, function(res){
		var index = Math.floor(Math.random() * thankYouResponses.length);
		res.reply(thankYouResponses[index]);
	});

	robot.hear(/I like pie/i, function(res){
		robot.send('I like pie too');
	});

	robot.respond(/open (.*) door/i, function(res){
		var doorType = res.match[1];
		if (doorType == 'pod bay')
			res.reply("I'm afraid I can't let you do that.");
		else
			res.reply('Opening ' + doorType + ' doors.');
	});

	robot.respond(/(you are|you're)(.*) slow/i, function(res){
		setTimeout(function(){
			res.reply('Who you callin\' slow?');
		}, 1000 * 15);
	});

	robot.respond(/(have|drink|consume)(.*) beer/i, function(res){
		var beersHad = robot.brain.get('totalBeersHad') || 0;
		if (beersHad > 4){
			var lastBeerFrom = robot.brain.get('lastBeerFrom');
			res.reply("I think I've had too many.  " + lastBeerFrom + " got me too drunk.  I need to sleep it off first.");
		}
		else{
			res.reply("Sure thing!  _chugs beer_");
			robot.brain.set('totalBeersHad', beersHad + 1);
			robot.brain.set('lastBeerFrom', res.message.user.name);
		}
	});

	robot.respond(/sleep it off/i, function(res){
		robot.brain.set('totalBeersHad', 0);
		res.reply('zzzzz');
	});

	robot.respond(/who am i/, function(res){
		res.reply(res.message.user.name);
	});

}<|endoftext|>


<commit_before>var BASE_URL = "http://ws.audioscrobbler.com/2.0/?api_key=198aaad97ed3a7ae97043ccc5a327ba6&format=json";

angular.module('lastfmService', ['ngResource'])
	.factory('artistSearch', function($resource) {
		return $resource(BASE_URL + '&method=artist.search&artist=:artist', {}, {
			query: { method: 'GET', params: {}, isArray: false }
		});
	});<commit_msg>added artistGetSimilar factory<commit_after>var BASE_URL = "http://ws.audioscrobbler.com/2.0/?api_key=198aaad97ed3a7ae97043ccc5a327ba6&format=json";

angular.module('lastfmService', ['ngResource'])
    .factory('artistSearch', function($resource) {
        return $resource(BASE_URL + '&method=artist.search&artist=:artist', {}, {
            query: { method: 'GET', params: {}, isArray: false }
        });
    }).factory('artistGetSimilar', function($resource) {
        return $resource(BASE_URL + '&method=artist.getSimilar&artist=:artist', {}, {
            query: { method: 'GET', params: {}, isArray: false }
        });
    });<|endoftext|>


<commit_before>/**
	_moon.Clock_ is a control that displays system clock information.

	Example:
		{kind:"moon.Clock"}
*/
enyo.kind({
	name: "moon.Clock",
	kind: "enyo.Control",
	classes: "moon-clock moon-header-font",
	published: {
		//* Refresh time in sec.
		refresh: 1000,
		//* Manual date. If it is undefined, _moon.Clock_ will use system date.
		date: undefined,
		/**
			ilib locale info instance. It gives information about the paarticular locale.
		*/
		ilibLocaleInfo: null,
		/**
			Current locale used for formatting. May be set after the control is
			created, in which case the control will be updated to reflect the
			new value.  Only valid if ilib is loaded.
		*/
		locale: ""
	},
	components: [
		{kind: "enyo.Control", name: "hour", classes: "moon-header-text moon-clock-hour"},
		{name: "right", classes: "moon-clock-right", components: [
			{kind: "enyo.Control", name: "top", classes: "moon-header-text moon-clock-top"},
			{name: "divider", classes: "moon-clock-divider"},
			{kind: "enyo.Control", name: "bottom", classes: "moon-body-text moon-clock-bottom"}
		]}
	],
	months: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
	_timeDiff: 0,
	create: function() {
		this.inherited(arguments);
		this.initDefaults();
		this.refreshJob();
	},
	initILib: function() {
		this.ilibLocaleInfo = new ilib.LocaleInfo(this.locale || undefined);
		var clockPref = this.ilibLocaleInfo.getClock();
		var clock = clockPref !== "locale" ? clockPref : undefined;
		var dateLen, fmtMin;

		if (this.ilibLocaleInfo.locale.spec === "en-US") {
			dateLen = "long";
			fmtMin = "m";
			this.$.right.addRemoveClass("mini", false);
			this.$.hour.show();
		} else {
			dateLen = "full";
			fmtMin = "hma";
			this.$.right.addRemoveClass("mini", true);
			this.$.hour.hide();
		}

		var fmtHourParams = {
			locale: this.locale,
			type: "time",
			time: "h",
			clock: clock,
			timezone: "local"
		};
		var fmtMinuteParams = {
			locale: this.locale,
			type: "time",
			time: fmtMin,
			clock: clock,
			timezone: "local"
		};
		var fmtMonthDayParams = {
			locale: this.locale,
			type: "date",
			date: "md",
			length: dateLen,
			timezone: "local"
		};

		this._hf = new ilib.DateFmt(fmtHourParams);
		this._mf = new ilib.DateFmt(fmtMinuteParams);
		this._mdf = new ilib.DateFmt(fmtMonthDayParams);
	},
	initDefaults: function() {
		// Attempt to use the ilib lib
		if (typeof ilib !== "undefined") {
			this.initILib();
		}
	},
	refreshChanged: function() {
		this.startJob("refresh", this.bindSafely("refreshJob"), this.getRefresh());
	},
	dateChanged: function() {
		if(this.date && this.date instanceof Date) {
			this._timeDiff = this.date.getTime() - Date.now();
		} else {
			this._timeDiff = 0;
		}
		this.refreshJob();
	},
	refreshJob: function() {
		var d = new Date(Date.now() + this._timeDiff);
		var h = d.getHours();
		this.updateHour(d, h);
		this.updateMinute(d, h);
		this.updateMonthDay(d);
		this.startJob("refresh", this.bindSafely("refreshJob"), this.getRefresh());
	},
	_formatNumber: function(inValue) {
		// Used when ilib is not present
		return (inValue) ? (String(inValue).length < 2) ? "0"+inValue : inValue : "00";
	},
	localeChanged: function() {
		this._refresh();
	},
	_refresh: function() {
		if (this._hf) {
			delete this._hf;
		}
		if (this._mf) {
			delete this._mf;
		}
		if (this._mdf) {
			delete this._mdf;
		}
		this.initDefaults();
	},
	updateHour: function(inDate, inHour) {
		inHour = inHour > 12 ? inHour-12: inHour;
		var hour = this._hf ? this._hf.format(new ilib.Date.GregDate({unixtime: inDate.getTime(), timezone:"UTC"})) : inHour;
		this.$.hour.setContent(hour);
	},
	updateMinute: function(inDate, inHour) {
		var m = this._mf ? this._mf.format(new ilib.Date.GregDate({unixtime: inDate.getTime(), timezone:"UTC"})) : this._formatNumber(inDate.getMinutes());
		var meridiem;
		if (!this.ilibLocaleInfo || this.ilibLocaleInfo.locale.spec === "en-US") {
			meridiem = inHour > 11 ? " pm" : " am";
			m += meridiem;
		}
		this.$.top.setContent(m);
	},
	updateMonthDay: function(inDate) {
		var md = this._mdf ? this._mdf.format(new ilib.Date.GregDate({unixtime: inDate.getTime(), timezone:"UTC"})) : this.months[inDate.getMonth()] + " " + this._formatNumber(inDate.getUTCDate());
		this.$.bottom.setContent(md);
	}
});<commit_msg>Add onlocalechange event<commit_after>/**
	_moon.Clock_ is a control that displays system clock information.

	Example:
		{kind:"moon.Clock"}
*/
enyo.kind({
	name: "moon.Clock",
	kind: "enyo.Control",
	classes: "moon-clock moon-header-font",
	published: {
		//* Refresh time in sec.
		refresh: 1000,
		//* Manual date. If it is undefined, _moon.Clock_ will use system date.
		date: undefined,
		/**
			ilib locale info instance. It gives information about the paarticular locale.
		*/
		ilibLocaleInfo: null,
		/**
			Current locale used for formatting. May be set after the control is
			created, in which case the control will be updated to reflect the
			new value.  Only valid if ilib is loaded.
		*/
		locale: ""
	},
	components: [
		{kind: "enyo.Control", name: "hour", classes: "moon-header-text moon-clock-hour"},
		{name: "right", classes: "moon-clock-right", components: [
			{kind: "enyo.Control", name: "top", classes: "moon-header-text moon-clock-top"},
			{name: "divider", classes: "moon-clock-divider"},
			{kind: "enyo.Control", name: "bottom", classes: "moon-body-text moon-clock-bottom"}
		]},
		{kind: "enyo.Signals", onlocalechange: "handleLocaleChangeEvent"}
	],
	months: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
	_timeDiff: 0,
	create: function() {
		this.inherited(arguments);
		this.initDefaults();
		this.refreshJob();
	},
	initILib: function() {
		this.ilibLocaleInfo = new ilib.LocaleInfo(this.locale || undefined);
		var clockPref = this.ilibLocaleInfo.getClock();
		var clock = clockPref !== "locale" ? clockPref : undefined;
		var dateLen, fmtMin;

		if (this.ilibLocaleInfo.locale.spec === "en-US") {
			dateLen = "long";
			fmtMin = "m";
			this.$.right.addRemoveClass("mini", false);
			this.$.hour.show();
		} else {
			dateLen = "full";
			fmtMin = "hma";
			this.$.right.addRemoveClass("mini", true);
			this.$.hour.hide();
		}

		var fmtHourParams = {
			locale: this.locale,
			type: "time",
			time: "h",
			clock: clock,
			timezone: "local"
		};
		var fmtMinuteParams = {
			locale: this.locale,
			type: "time",
			time: fmtMin,
			clock: clock,
			timezone: "local"
		};
		var fmtMonthDayParams = {
			locale: this.locale,
			type: "date",
			date: "md",
			length: dateLen,
			timezone: "local"
		};

		this._hf = new ilib.DateFmt(fmtHourParams);
		this._mf = new ilib.DateFmt(fmtMinuteParams);
		this._mdf = new ilib.DateFmt(fmtMonthDayParams);
	},
	initDefaults: function() {
		// Attempt to use the ilib lib
		if (typeof ilib !== "undefined") {
			this.initILib();
		}
	},
	refreshChanged: function() {
		this.startJob("refresh", this.bindSafely("refreshJob"), this.getRefresh());
	},
	dateChanged: function() {
		if(this.date && this.date instanceof Date) {
			this._timeDiff = this.date.getTime() - Date.now();
		} else {
			this._timeDiff = 0;
		}
		this.refreshJob();
	},
	refreshJob: function() {
		var d = new Date(Date.now() + this._timeDiff);
		var h = d.getHours();
		this.updateHour(d, h);
		this.updateMinute(d, h);
		this.updateMonthDay(d);
		this.startJob("refresh", this.bindSafely("refreshJob"), this.getRefresh());
	},
	_formatNumber: function(inValue) {
		// Used when ilib is not present
		return (inValue) ? (String(inValue).length < 2) ? "0"+inValue : inValue : "00";
	},
	localeChanged: function() {
		this._refresh();
	},
	_refresh: function() {
		if (this._hf) {
			delete this._hf;
		}
		if (this._mf) {
			delete this._mf;
		}
		if (this._mdf) {
			delete this._mdf;
		}
		this.initDefaults();
	},
	updateHour: function(inDate, inHour) {
		inHour = inHour > 12 ? inHour-12: inHour;
		var hour = this._hf ? this._hf.format(new ilib.Date.GregDate({unixtime: inDate.getTime(), timezone:"UTC"})) : inHour;
		this.$.hour.setContent(hour);
	},
	updateMinute: function(inDate, inHour) {
		var m = this._mf ? this._mf.format(new ilib.Date.GregDate({unixtime: inDate.getTime(), timezone:"UTC"})) : this._formatNumber(inDate.getMinutes());
		var meridiem;
		if (!this.ilibLocaleInfo || this.ilibLocaleInfo.locale.spec === "en-US") {
			meridiem = inHour > 11 ? " pm" : " am";
			m += meridiem;
		}
		this.$.top.setContent(m);
	},
	updateMonthDay: function(inDate) {
		var md = this._mdf ? this._mdf.format(new ilib.Date.GregDate({unixtime: inDate.getTime(), timezone:"UTC"})) : this.months[inDate.getMonth()] + " " + this._formatNumber(inDate.getUTCDate());
		this.$.bottom.setContent(md);
	},
	handleLocaleChangeEvent: function() {
		this._refresh();
	}
});<|endoftext|>


<commit_before>var miio = require('./lib');

// var vacuum = python.import('mirobot/protocol');

class MiHome {

  constructor (name, ip, port, token, model) {
    this.ip = ip;
    this.port = port
    this.token = token;
    this.name = name
    this.model = model
    this.device = null;
  }

  load () {
    var that = this;

    return that.loading = new Promise(function(resolve, reject){

      if (that.model == 'vacuum') {
        that.device = miio.createDevice({
          address: that.ip,
          token: that.token,
          model: 'rockrobo.vacuum.v1'
        });

        that.device.init()
        .then(() => {
          console.log(that.model + " init success");
          resolve(that);
        })
        .catch(err => {
          console.error(that.model + " init error: " + err);
          reject(err);
        });
      }
      else {

        if (that.token == null) {
          var para = { address: that.ip };
        }
        else {
          var para = { address: that.ip, token: that.token };
        };

        miio.device(para)
          .then(device => {
              that.device = device;
              console.log(that.name + " " + that.device.type + " init success");
              resolve(that);
            })
          .catch(err => {
          console.error(that.name + " init error: " + err);
          reject(err);
        });
      }
    });
  }

  exec(cmd) {
    var that = this;

    if (cmd == 'Stop') {
      cmd = 'Charge';
    }

    switch (cmd) {
      case 'Start':

        if (this.device.type == 'vacuum') {
          this.device.start()
            .then(res => console.log(this.name + " start result : " + res))
            .catch(err => console.error(this.name + " start error: " + err));
        }

        break;

      case 'Charge':

        if (this.device.type == 'vacuum') {
          this.device.charge()
            .then(res => console.log(this.name + " charge result : " + res))
            .catch(err => console.error(this.name + " charge error: " + err));
        }

        break;

      case 'Pause':

        if (this.device.type == 'vacuum') {
          this.device.pause()
            .then(res => console.log(this.name + " pause result : " + res))
            .catch(err => console.error(this.name + " pause error: " + err));
        }

        break;

      case 'List':
        if (this.device.type == 'gateway') {
          this.list();
        }

        break;

      case 'PowerOff':
        if (this.device.type == 'light') {
          this.device.setPower(false)
            .then(res => console.log(this.name + " PowerOff result : " + res))
            .catch(err => console.error(this.name + " PowerOff error: " + err));
        }
        else {
          this.powerSet(false);
        }

        break;
      case 'PowerOn':

        if (this.device.type == 'light') {
          this.device.setPower(true)
            .then(res => console.log(this.name + " PowerOn result : " + res))
            .catch(err => console.error(this.name + " PowerOn error: " + err));
        }
        else {
          this.powerSet(true);
        }
        break;

      case 'PowerStatus':
        this.powerStatus();
        break;

      case 'LightStatus':
        if (this.device.type == 'light') {
          console.log(this.name + " Mode : " + this.device.colorMode());
        }
        break;

      default:
        console.log('Invalid type:' + cmd);
    }

    return;

  }

  powerOn() {
    var that = this;

    if(this.device.hasCapability('power')) {
      this.device.setPower(true)
        .then(console.log(this.name + ":Power On"))
        .catch(console.error(this.name + "Failed to Power On"));
    }

  }

  _deviecPowerSet(inputDevice, cmd) {
    var that = this;

    for (var i=0; i<inputDevice.powerChannels.length; i++) {
      console.log("Chan " + i);
      inputDevice.setPower(i, cmd)
      .then(power => console.log(inputDevice.type + " Power " + power))
      .catch(err => console.error(inputDevice.type + " Failed: " + err));
    }
  }

  _deviecPowerStatus(inputDevice) {
    var that = this;

    for (var i=0; i<inputDevice.powerChannels.length; i++) {
      console.log(inputDevice.type + " power " + inputDevice.power(JSON.stringify(i)));
    }
  }

  powerSet(cmd) {
    var that = this;

    if(that.device.type == 'gateway') {
      that.device.on('deviceAvailable', subDevice => {
        if (subDevice.type == 'power-plug') {

          that._deviecPowerSet(subDevice,cmd);
        }

        return;
      });
    }
    else {
      that._deviecPowerSet(that.device,cmd);
    }
  }

  powerStatus() {
    var that = this;

    if(that.device.type == 'gateway') {
      that.device.on('deviceAvailable', subDevice => {
        if (subDevice.type == 'power-plug') {

          that._deviecPowerStatus(subDevice);
        }

        return;
      });
    }
    else {
      that._deviecPowerStatus(that.device);
    }
  }

  list() {
    var that = this;
    console.log('All SubDevice:');

    that.device.on('deviceAvailable', subDevice => {
      console.log('ID: ' + subDevice.id + ' Model:' + subDevice.model + ' Type:' + subDevice.type );
      return;

    });

    if(that.device.devices) {

      that.device.devices.forEach(function(item){
        console.log('-' + item);
      })
    }

  }

};

module.exports = MiHome;<commit_msg>add light power function<commit_after>var miio = require('./lib');

// var vacuum = python.import('mirobot/protocol');

class MiHome {

  constructor (name, ip, port, token, model) {
    this.ip = ip;
    this.port = port
    this.token = token;
    this.name = name
    this.model = model
    this.device = null;
  }

  load () {
    var that = this;

    return that.loading = new Promise(function(resolve, reject){

      if (that.model == 'vacuum') {
        that.device = miio.createDevice({
          address: that.ip,
          token: that.token,
          model: 'rockrobo.vacuum.v1'
        });

        that.device.init()
        .then(() => {
          console.log(that.model + " init success");
          resolve(that);
        })
        .catch(err => {
          console.error(that.model + " init error: " + err);
          reject(err);
        });
      }
      else {

        if (that.token == null) {
          var para = { address: that.ip };
        }
        else {
          var para = { address: that.ip, token: that.token };
        };

        miio.device(para)
          .then(device => {
              that.device = device;
              console.log(that.name + " " + that.device.type + " init success");
              resolve(that);
            })
          .catch(err => {
          console.error(that.name + " init error: " + err);
          reject(err);
        });
      }
    });
  }

  exec(cmd) {
    var that = this;

    if (cmd == 'Stop') {
      cmd = 'Charge';
    }

    switch (cmd) {
      case 'Start':

        if (this.device.type == 'vacuum') {
          this.device.start()
            .then(res => console.log(this.name + " start result : " + res))
            .catch(err => console.error(this.name + " start error: " + err));
        }

        break;

      case 'Charge':

        if (this.device.type == 'vacuum') {
          this.device.charge()
            .then(res => console.log(this.name + " charge result : " + res))
            .catch(err => console.error(this.name + " charge error: " + err));
        }

        break;

      case 'Pause':

        if (this.device.type == 'vacuum') {
          this.device.pause()
            .then(res => console.log(this.name + " pause result : " + res))
            .catch(err => console.error(this.name + " pause error: " + err));
        }

        break;

      case 'List':
        if (this.device.type == 'gateway') {
          this.list();
        }

        break;

      case 'PowerOff':
        if (this.device.type == 'light') {
          this.device.setPower(false)
            .then(res => console.log(this.name + " PowerOff result : " + res))
            .catch(err => console.error(this.name + " PowerOff error: " + err));
        }
        else {
          this.powerSet(false);
        }

        break;
      case 'PowerOn':

        if (this.device.type == 'light') {
          this.device.setPower(true)
            .then(res => console.log(this.name + " PowerOn result : " + res))
            .catch(err => console.error(this.name + " PowerOn error: " + err));
        }
        else {
          this.powerSet(true);
        }
        break;

      case 'PowerStatus':
        this.powerStatus();
        break;

      case 'LightStatus':
        if (this.device.type == 'light') {
          console.log(this.name + " Mode : " + this.device.colorTemperature);
        }
        break;

      default:
        console.log('Invalid type:' + cmd);
    }

    return;

  }

  powerOn() {
    var that = this;

    if(this.device.hasCapability('power')) {
      this.device.setPower(true)
        .then(console.log(this.name + ":Power On"))
        .catch(console.error(this.name + "Failed to Power On"));
    }

  }

  _deviecPowerSet(inputDevice, cmd) {
    var that = this;

    for (var i=0; i<inputDevice.powerChannels.length; i++) {
      console.log("Chan " + i);
      inputDevice.setPower(i, cmd)
      .then(power => console.log(inputDevice.type + " Power " + power))
      .catch(err => console.error(inputDevice.type + " Failed: " + err));
    }
  }

  _deviecPowerStatus(inputDevice) {
    var that = this;

    for (var i=0; i<inputDevice.powerChannels.length; i++) {
      console.log(inputDevice.type + " power " + inputDevice.power(JSON.stringify(i)));
    }
  }

  powerSet(cmd) {
    var that = this;

    if(that.device.type == 'gateway') {
      that.device.on('deviceAvailable', subDevice => {
        if (subDevice.type == 'power-plug') {

          that._deviecPowerSet(subDevice,cmd);
        }

        return;
      });
    }
    else {
      that._deviecPowerSet(that.device,cmd);
    }
  }

  powerStatus() {
    var that = this;

    if(that.device.type == 'gateway') {
      that.device.on('deviceAvailable', subDevice => {
        if (subDevice.type == 'power-plug') {

          that._deviecPowerStatus(subDevice);
        }

        return;
      });
    }
    else {
      that._deviecPowerStatus(that.device);
    }
  }

  list() {
    var that = this;
    console.log('All SubDevice:');

    that.device.on('deviceAvailable', subDevice => {
      console.log('ID: ' + subDevice.id + ' Model:' + subDevice.model + ' Type:' + subDevice.type );
      return;

    });

    if(that.device.devices) {

      that.device.devices.forEach(function(item){
        console.log('-' + item);
      })
    }

  }

};

module.exports = MiHome;<|endoftext|>


<commit_before><commit_msg>Fix lint issue.<commit_after><|endoftext|>


<commit_before>'use strict';
var expect = chai.expect;

function run(scope,done) {
  done();
}

describe('StatusCtrl', function(){
  var rootScope, scope, controller_injector, dependencies, ctrl;

  beforeEach(module("rp"));
  beforeEach(inject(function($rootScope, $controller, $q) {
    rootScope = rootScope;
    scope = $rootScope.$new();
    controller_injector = $controller;

    dependencies = {
      $scope: scope,
      $element: null
    }

    ctrl = controller_injector("StatusCtrl", dependencies);
  }));

  it('should initialize properly', function (done) {
    assert.isNotNull(ctrl);
    run(scope,done);
  });

  describe('public functions on $scope', function () {

    it('should toggle the secondary', function (done) {
      assert.isFunction(scope.toggle_secondary);
      run(scope,done);
    });

    it('should logout', function (done) {
      assert.isFunction(scope.logout);
      run(scope,done);
    });
  });

  describe('private functions', function() {

    it('should set the connection status', function (done) {
      assert.isFunction(ctrl.setConnectionStatus);
      run(scope,done);
    });

    it('should enqueue', function (done) {
      assert.isFunction(ctrl.enqueue);
      run(scope,done);
    });

    it('should tick', function (done) {
      assert.isFunction(ctrl.tick);
      run(scope,done);
    });

  });
});
<commit_msg>[CHORE] Test that sinon is set up in statusControllerSpec.<commit_after>'use strict';
var expect = chai.expect;

function run(scope,done) {
  done();
}

describe('StatusCtrl', function(){
  var rootScope, scope, controller_injector, dependencies, ctrl;

  beforeEach(module("rp"));
  beforeEach(inject(function($rootScope, $controller, $q) {
    rootScope = rootScope;
    scope = $rootScope.$new();
    controller_injector = $controller;

    dependencies = {
      $scope: scope,
      $element: null
    }

    ctrl = controller_injector("StatusCtrl", dependencies);
  }));

  it('should initialize properly', function (done) {
    assert.isNotNull(ctrl);
    run(scope,done);
  });

  it('should be set up with sinon', function (done) {
    assert.isNotNull(sinon);
    assert.isFunction(sinon.spy);
    run(scope,done);
  });

  describe('public functions on $scope', function () {

    it('should toggle the secondary', function (done) {
      assert.isFunction(scope.toggle_secondary);
      run(scope,done);
    });

    it('should logout', function (done) {
      assert.isFunction(scope.logout);
      run(scope,done);
    });
  });

  describe('private functions', function() {

    it('should set the connection status', function (done) {
      assert.isFunction(ctrl.setConnectionStatus);
      run(scope,done);
    });

    it('should enqueue', function (done) {
      assert.isFunction(ctrl.enqueue);
      run(scope,done);
    });

    it('should tick', function (done) {
      assert.isFunction(ctrl.tick);
      run(scope,done);
    });

  });
});
<|endoftext|>


<commit_before>// ==========================================================================
// Project:   xTuple Postbooks - Business Management System Framework
// Copyright: ©2012 OpenMFG LLC, d/b/a xTuple
// ==========================================================================

/*globals XM */

sc_require('mixins/_incident');

/**
  @class

  @extends XM.Document
  @extends XM.CoreDocuments
*/
XM.Incident = XM.Document.extend(XM._Incident, XM.CoreDocuments,
  /** @scope XM.Incident.prototype */ {

  numberPolicy: XM.AUTO_NUMBER,

  // .................................................
  // CALCULATED PROPERTIES
  //

  /**
    @type String
  */
  incidentStatus: SC.Record.attr(String, {
    defaultValue: 'N'
  }),

  /* @private */
  accountsLength: 0,

  /* @private */
  accountsLengthBinding: SC.Binding.from('*incidents.length').noDelay(),

  /* @private */
  incidentsLength: 0,

  /* @private */
  incidentsLengthBinding: SC.Binding.from('*incidents.length').noDelay(),

  //..................................................
  // METHODS
  //

  //..................................................
  // OBSERVERS
  //

  validate: function() {
    var isErr, errors = arguments.callee.base.apply(this, arguments);

    // Validate assignee
    isErr = this.get('incidentStatus') === XM.Incident.STATUS_ASSIGNED &&
            !this.get('assignedTo');
    err = XM.errors.findProperty('code', 'xt1025');
    this.updateErrors(err, isErr);

    return errors;
  }.observes('assignedTo', 'incidentStatus'),

  /* @private */
  _xm_assignedToDidChange: function() {
    var assignedTo = this.get('assignedTo'),
        status = this.get('status');

    if(status & SC.Record.READY && assignedTo) this.set('incidentStatus','A');
  }.observes('assignedTo'),

  /* @private */
  _xm_accountsDidChange: function() {
    var documents = this.get('documents'),
        accounts = this.get('accounts');

    documents.addEach(accounts);
  }.observes('accountsLength'),

  /* @private */
  _xm_incidentsDidChange: function() {
    var documents = this.get('documents'),
        incidents = this.get('incidents');

    documents.addEach(incidents);
  }.observes('incidentsLength')

});

XM.Incident.mixin( /** @scope XM.Incident */ {

/**
  New status.

  @static
  @constant
  @type String
  @default N
*/
  STATUS_NEW: 'N',

/**
  Feedback status.

  @static
  @constant
  @type String
  @default F
*/
  STATUS_FEEDBACK: 'F',

/**
  Confirmed Status.

  @static
  @constant
  @type String
  @default I
*/
  STATUS_CONFIRMED: 'C',

/**
  Assigned status.

  @static
  @constant
  @type String
  @default A
*/
  STATUS_ASSIGNED: 'A',

/**
  Resolved status.

  @static
  @constant
  @type String
  @default R
*/
  STATUS_RESOLVED: 'R',

/**
  Closed status.

  @static
  @constant
  @type String
  @default L
*/
  STATUS_CLOSED: 'L'

});
<commit_msg>only set incident status when record status is appropriate.<commit_after>// ==========================================================================
// Project:   xTuple Postbooks - Business Management System Framework
// Copyright: ©2012 OpenMFG LLC, d/b/a xTuple
// ==========================================================================

/*globals XM */

sc_require('mixins/_incident');

/**
  @class

  @extends XM.Document
  @extends XM.CoreDocuments
*/
XM.Incident = XM.Document.extend(XM._Incident, XM.CoreDocuments,
  /** @scope XM.Incident.prototype */ {

  numberPolicy: XM.AUTO_NUMBER,

  // .................................................
  // CALCULATED PROPERTIES
  //

  /**
    @type String
  */
  incidentStatus: SC.Record.attr(String, {
    defaultValue: 'N'
  }),

  /* @private */
  accountsLength: 0,

  /* @private */
  accountsLengthBinding: SC.Binding.from('*incidents.length').noDelay(),

  /* @private */
  incidentsLength: 0,

  /* @private */
  incidentsLengthBinding: SC.Binding.from('*incidents.length').noDelay(),

  //..................................................
  // METHODS
  //

  //..................................................
  // OBSERVERS
  //

  validate: function() {
    var isErr, errors = arguments.callee.base.apply(this, arguments);

    // Validate assignee
    isErr = this.get('incidentStatus') === XM.Incident.STATUS_ASSIGNED &&
            !this.get('assignedTo');
    err = XM.errors.findProperty('code', 'xt1025');
    this.updateErrors(err, isErr);

    return errors;
  }.observes('assignedTo', 'incidentStatus'),

  /* @private */
  _xm_assignedToDidChange: function() {
    var assignedTo = this.get('assignedTo'),
        status = this.get('status');

    if(assignedTo &&
      (status == SC.Record.READY_DIRTY || status == SC.Record.READY_NEW))
      this.set('incidentStatus','A');
  }.observes('assignedTo'),

  /* @private */
  _xm_accountsDidChange: function() {
    var documents = this.get('documents'),
        accounts = this.get('accounts');

    documents.addEach(accounts);
  }.observes('accountsLength'),

  /* @private */
  _xm_incidentsDidChange: function() {
    var documents = this.get('documents'),
        incidents = this.get('incidents');

    documents.addEach(incidents);
  }.observes('incidentsLength')

});

XM.Incident.mixin( /** @scope XM.Incident */ {

/**
  New status.

  @static
  @constant
  @type String
  @default N
*/
  STATUS_NEW: 'N',

/**
  Feedback status.

  @static
  @constant
  @type String
  @default F
*/
  STATUS_FEEDBACK: 'F',

/**
  Confirmed Status.

  @static
  @constant
  @type String
  @default I
*/
  STATUS_CONFIRMED: 'C',

/**
  Assigned status.

  @static
  @constant
  @type String
  @default A
*/
  STATUS_ASSIGNED: 'A',

/**
  Resolved status.

  @static
  @constant
  @type String
  @default R
*/
  STATUS_RESOLVED: 'R',

/**
  Closed status.

  @static
  @constant
  @type String
  @default L
*/
  STATUS_CLOSED: 'L'

});
<|endoftext|>


<commit_before>var LATIN_MAP = {
    'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE', 'Ç':
    'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I', 'Î': 'I',
    'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O', 'Õ': 'O', 'Ö':
    'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U', 'Ü': 'U', 'Ý': 'Y', 'Þ': 'TH',
    'ß': 'ss', 'à':'a', 'á':'a', 'â': 'a', 'ã': 'a', 'ä': 'a', 'å': 'a', 'æ':
    'ae', 'ç': 'c', 'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e', 'ì': 'i', 'í': 'i',
    'î': 'i', 'ï': 'i', 'ð': 'o', 'ñ': 'n', 'ò': 'o', 'ó': 'o', 'ô': 'o', 'õ':
    'o', 'ö': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u', 'û': 'u', 'ü': 'u', 'ý': 'y',
    'þ': 'th', 'ÿ': 'y'
}
var LATIN_SYMBOLS_MAP = {
    '©':'(c)'
}
var GREEK_MAP = {
    'α':'a', 'β':'b', 'γ':'g', 'δ':'d', 'ε':'e', 'ζ':'z', 'η':'h', 'θ':'8',
    'ι':'i', 'κ':'k', 'λ':'l', 'μ':'m', 'ν':'n', 'ξ':'3', 'ο':'o', 'π':'p',
    'ρ':'r', 'σ':'s', 'τ':'t', 'υ':'y', 'φ':'f', 'χ':'x', 'ψ':'ps', 'ω':'w',
    'ά':'a', 'έ':'e', 'ί':'i', 'ό':'o', 'ύ':'y', 'ή':'h', 'ώ':'w', 'ς':'s',
    'ϊ':'i', 'ΰ':'y', 'ϋ':'y', 'ΐ':'i',
    'Α':'A', 'Β':'B', 'Γ':'G', 'Δ':'D', 'Ε':'E', 'Ζ':'Z', 'Η':'H', 'Θ':'8',
    'Ι':'I', 'Κ':'K', 'Λ':'L', 'Μ':'M', 'Ν':'N', 'Ξ':'3', 'Ο':'O', 'Π':'P',
    'Ρ':'R', 'Σ':'S', 'Τ':'T', 'Υ':'Y', 'Φ':'F', 'Χ':'X', 'Ψ':'PS', 'Ω':'W',
    'Ά':'A', 'Έ':'E', 'Ί':'I', 'Ό':'O', 'Ύ':'Y', 'Ή':'H', 'Ώ':'W', 'Ϊ':'I',
    'Ϋ':'Y'
}
var TURKISH_MAP = {
    'ş':'s', 'Ş':'S', 'ı':'i', 'İ':'I', 'ç':'c', 'Ç':'C', 'ü':'u', 'Ü':'U',
    'ö':'o', 'Ö':'O', 'ğ':'g', 'Ğ':'G'
}
var RUSSIAN_MAP = {
    'а':'a', 'б':'b', 'в':'v', 'г':'g', 'д':'d', 'е':'e', 'ё':'yo', 'ж':'zh',
    'з':'z', 'и':'i', 'й':'j', 'к':'k', 'л':'l', 'м':'m', 'н':'n', 'о':'o',
    'п':'p', 'р':'r', 'с':'s', 'т':'t', 'у':'u', 'ф':'f', 'х':'h', 'ц':'c',
    'ч':'ch', 'ш':'sh', 'щ':'sh', 'ъ':'', 'ы':'y', 'ь':'', 'э':'e', 'ю':'yu',
    'я':'ya',
    'А':'A', 'Б':'B', 'В':'V', 'Г':'G', 'Д':'D', 'Е':'E', 'Ё':'Yo', 'Ж':'Zh',
    'З':'Z', 'И':'I', 'Й':'J', 'К':'K', 'Л':'L', 'М':'M', 'Н':'N', 'О':'O',
    'П':'P', 'Р':'R', 'С':'S', 'Т':'T', 'У':'U', 'Ф':'F', 'Х':'H', 'Ц':'C',
    'Ч':'Ch', 'Ш':'Sh', 'Щ':'Sh', 'Ъ':'', 'Ы':'Y', 'Ь':'', 'Э':'E', 'Ю':'Yu',
    'Я':'Ya'
}

var ALL_DOWNCODE_MAPS=new Array()
ALL_DOWNCODE_MAPS[0]=LATIN_MAP
ALL_DOWNCODE_MAPS[1]=LATIN_SYMBOLS_MAP
ALL_DOWNCODE_MAPS[2]=GREEK_MAP
ALL_DOWNCODE_MAPS[3]=TURKISH_MAP
ALL_DOWNCODE_MAPS[4]=RUSSIAN_MAP

var Downcoder = new Object();
Downcoder.Initialize = function()
{
    if (Downcoder.map) // already made
        return ;
    Downcoder.map ={}
    Downcoder.chars = '' ;
    for(var i in ALL_DOWNCODE_MAPS)
    {
        var lookup = ALL_DOWNCODE_MAPS[i]
        for (var c in lookup)
        {
            Downcoder.map[c] = lookup[c] ;
            Downcoder.chars += c ;
        }
     }
    Downcoder.regex = new RegExp('[' + Downcoder.chars + ']|[^' + Downcoder.chars + ']+','g') ;
}

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

function URLify(s, num_chars) {
    // changes, e.g., "Petty theft" to "petty_theft"
    // remove all these words from the string before urlifying
    s = downcode(s);
    removelist = ["a", "an", "as", "at", "before", "but", "by", "for", "from",
                  "is", "in", "into", "like", "of", "off", "on", "onto", "per",
                  "since", "than", "the", "this", "that", "to", "up", "via",
                  "with"];
    r = new RegExp('\\b(' + removelist.join('|') + ')\\b', 'gi');
    s = s.replace(r, '');
    // if downcode doesn't hit, the char will be stripped here
    s = s.replace(/[^-\w\s]/g, '');  // remove unneeded chars
    s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces
    s = s.replace(/[-\s]+/g, '-');   // convert spaces to hyphens
    s = s.toLowerCase();             // convert to lowercase
    return s.substring(0, num_chars);// trim to first num_chars chars
}

<commit_msg>Fixed #4775 -- Added some missing Hungarian accents to the urlify.js LATIN_MAP. Thanks, Pistahh <szekeres@iii.hu>.<commit_after>var LATIN_MAP = {
    'À': 'A', 'Á': 'A', 'Â': 'A', 'Ã': 'A', 'Ä': 'A', 'Å': 'A', 'Æ': 'AE', 'Ç':
    'C', 'È': 'E', 'É': 'E', 'Ê': 'E', 'Ë': 'E', 'Ì': 'I', 'Í': 'I', 'Î': 'I',
    'Ï': 'I', 'Ð': 'D', 'Ñ': 'N', 'Ò': 'O', 'Ó': 'O', 'Ô': 'O', 'Õ': 'O', 'Ö':
    'O', 'Ő': 'O', 'Ø': 'O', 'Ù': 'U', 'Ú': 'U', 'Û': 'U', 'Ü': 'U', 'Ű': 'U',
    'Ý': 'Y', 'Þ': 'TH', 'ß': 'ss', 'à':'a', 'á':'a', 'â': 'a', 'ã': 'a', 'ä':
    'a', 'å': 'a', 'æ': 'ae', 'ç': 'c', 'è': 'e', 'é': 'e', 'ê': 'e', 'ë': 'e',
    'ì': 'i', 'í': 'i', 'î': 'i', 'ï': 'i', 'ð': 'o', 'ñ': 'n', 'ò': 'o', 'ó':
    'o', 'ô': 'o', 'õ': 'o', 'ö': 'o', 'ő': 'o', 'ø': 'o', 'ù': 'u', 'ú': 'u',
    'û': 'u', 'ü': 'u', 'ű': 'u', 'ý': 'y', 'þ': 'th', 'ÿ': 'y'
}
var LATIN_SYMBOLS_MAP = {
    '©':'(c)'
}
var GREEK_MAP = {
    'α':'a', 'β':'b', 'γ':'g', 'δ':'d', 'ε':'e', 'ζ':'z', 'η':'h', 'θ':'8',
    'ι':'i', 'κ':'k', 'λ':'l', 'μ':'m', 'ν':'n', 'ξ':'3', 'ο':'o', 'π':'p',
    'ρ':'r', 'σ':'s', 'τ':'t', 'υ':'y', 'φ':'f', 'χ':'x', 'ψ':'ps', 'ω':'w',
    'ά':'a', 'έ':'e', 'ί':'i', 'ό':'o', 'ύ':'y', 'ή':'h', 'ώ':'w', 'ς':'s',
    'ϊ':'i', 'ΰ':'y', 'ϋ':'y', 'ΐ':'i',
    'Α':'A', 'Β':'B', 'Γ':'G', 'Δ':'D', 'Ε':'E', 'Ζ':'Z', 'Η':'H', 'Θ':'8',
    'Ι':'I', 'Κ':'K', 'Λ':'L', 'Μ':'M', 'Ν':'N', 'Ξ':'3', 'Ο':'O', 'Π':'P',
    'Ρ':'R', 'Σ':'S', 'Τ':'T', 'Υ':'Y', 'Φ':'F', 'Χ':'X', 'Ψ':'PS', 'Ω':'W',
    'Ά':'A', 'Έ':'E', 'Ί':'I', 'Ό':'O', 'Ύ':'Y', 'Ή':'H', 'Ώ':'W', 'Ϊ':'I',
    'Ϋ':'Y'
}
var TURKISH_MAP = {
    'ş':'s', 'Ş':'S', 'ı':'i', 'İ':'I', 'ç':'c', 'Ç':'C', 'ü':'u', 'Ü':'U',
    'ö':'o', 'Ö':'O', 'ğ':'g', 'Ğ':'G'
}
var RUSSIAN_MAP = {
    'а':'a', 'б':'b', 'в':'v', 'г':'g', 'д':'d', 'е':'e', 'ё':'yo', 'ж':'zh',
    'з':'z', 'и':'i', 'й':'j', 'к':'k', 'л':'l', 'м':'m', 'н':'n', 'о':'o',
    'п':'p', 'р':'r', 'с':'s', 'т':'t', 'у':'u', 'ф':'f', 'х':'h', 'ц':'c',
    'ч':'ch', 'ш':'sh', 'щ':'sh', 'ъ':'', 'ы':'y', 'ь':'', 'э':'e', 'ю':'yu',
    'я':'ya',
    'А':'A', 'Б':'B', 'В':'V', 'Г':'G', 'Д':'D', 'Е':'E', 'Ё':'Yo', 'Ж':'Zh',
    'З':'Z', 'И':'I', 'Й':'J', 'К':'K', 'Л':'L', 'М':'M', 'Н':'N', 'О':'O',
    'П':'P', 'Р':'R', 'С':'S', 'Т':'T', 'У':'U', 'Ф':'F', 'Х':'H', 'Ц':'C',
    'Ч':'Ch', 'Ш':'Sh', 'Щ':'Sh', 'Ъ':'', 'Ы':'Y', 'Ь':'', 'Э':'E', 'Ю':'Yu',
    'Я':'Ya'
}

var ALL_DOWNCODE_MAPS=new Array()
ALL_DOWNCODE_MAPS[0]=LATIN_MAP
ALL_DOWNCODE_MAPS[1]=LATIN_SYMBOLS_MAP
ALL_DOWNCODE_MAPS[2]=GREEK_MAP
ALL_DOWNCODE_MAPS[3]=TURKISH_MAP
ALL_DOWNCODE_MAPS[4]=RUSSIAN_MAP

var Downcoder = new Object();
Downcoder.Initialize = function()
{
    if (Downcoder.map) // already made
        return ;
    Downcoder.map ={}
    Downcoder.chars = '' ;
    for(var i in ALL_DOWNCODE_MAPS)
    {
        var lookup = ALL_DOWNCODE_MAPS[i]
        for (var c in lookup)
        {
            Downcoder.map[c] = lookup[c] ;
            Downcoder.chars += c ;
        }
     }
    Downcoder.regex = new RegExp('[' + Downcoder.chars + ']|[^' + Downcoder.chars + ']+','g') ;
}

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

function URLify(s, num_chars) {
    // changes, e.g., "Petty theft" to "petty_theft"
    // remove all these words from the string before urlifying
    s = downcode(s);
    removelist = ["a", "an", "as", "at", "before", "but", "by", "for", "from",
                  "is", "in", "into", "like", "of", "off", "on", "onto", "per",
                  "since", "than", "the", "this", "that", "to", "up", "via",
                  "with"];
    r = new RegExp('\\b(' + removelist.join('|') + ')\\b', 'gi');
    s = s.replace(r, '');
    // if downcode doesn't hit, the char will be stripped here
    s = s.replace(/[^-\w\s]/g, '');  // remove unneeded chars
    s = s.replace(/^\s+|\s+$/g, ''); // trim leading/trailing spaces
    s = s.replace(/[-\s]+/g, '-');   // convert spaces to hyphens
    s = s.toLowerCase();             // convert to lowercase
    return s.substring(0, num_chars);// trim to first num_chars chars
}

<|endoftext|>


<commit_before>"use strict";

const setupTask = require('utils').setupTask;
const calcTasks = require("calcTasks");

module.exports = {
	getGettingTask : function(creep){
        //here the prioritization of one source is missing
		var room = creep.room;
		var creepsByTask = _(Game.creeps).filter( (c) => c.task && c.task.roomName == room.name).groupBy('task.type').value();
        var getEnergyTasks = calcTasks.calcGetEnergyTasks(room,creepsByTask);
        var myIndex = -1;
        myIndex = _.findIndex(getEnergyTasks, (t) => t.amountAvailable == Game.getObjectById(t.id).storeCapacity);
        if(myIndex != -1){
            creep.task=getEnergyTasks[myIndex];
            return OK;
        }
        var pickupTasks = calcTasks.calcPickupTasks(room,creepsByTask);
        myIndex = _.findIndex(pickupTasks,(t) => t.amountLeft > 50); //here a better check than > 50 would be nice
        if(myIndex != -1){
            creep.task=pickupTasks[myIndex];
            return OK;
        }
        myIndex = _.findIndex(getEnergyTasks,(t) => t.amountAvailable >= (creep.carryCapacity - creep.carry.energy));
        if(myIndex != -1){
            creep.task=getEnergyTasks[myIndex];
            return OK;
        }
        //this should work now that we do creep-based tasks, but should reset when empty
        if(creep.room.storage && creep.room.storage.store.energy >= (creep.carryCapacity - creep.carry.energy)){
            creep.task= setupTask(TASK_GET_ENERGY,creep.room.storage);
			return OK;
        }
    },

    getBuildingTask : function(creep){
		var room = creep.room;
		var creepsByTask = _(Game.creeps).filter( (c) => c.task && c.task.roomName == room.name).groupBy('task.type').value();
        var buildList = calcTasks.calcBuildTasks(room,creepsByTask);
        var myIndex = _.findIndex(buildList, (t) => t.progressLeft > 0);
        if(myIndex != -1){
            creep.task=buildList[myIndex];
            return OK;
        }
    },

    getUpgradingTask : function(creep){
		var room = _.get(Game.rooms, creep.memory.homeRoom, creep.room);
		var creepsByTask = _(Game.creeps).filter( (c) => c.task && c.task.roomName == room.name).groupBy('task.type').value();
        var upgradeList = calcTasks.calcUpgradeTasks(room,creepsByTask);
        var myIndex = _.findIndex(upgradeList, (t) => true);
        if(myIndex != -1){
            creep.task=upgradeList[myIndex];
            return OK;
        }
    },

    getRepairingTask : function(creep){
        var repairList = _.get(creep.room.memory,"tasks." + TASK_REPAIR,[]);
        var myIndex = _.findIndex(repairList, (t) => t.repairNeeded > 0);
        if(myIndex != -1){
			repairList[myIndex].repairNeeded -= creep.carry.energy;
            creep.task=repairList[myIndex];
            return OK;
        }
    },

    getWallRepairingTask : function(creep){
		var repairWallList = _.get(creep.room.memory,"tasks." + TASK_REPAIR_WALL,[]);
		var myIndex = _.findIndex(repairWallList, (t) => t.repairNeeded > 0);
        if(myIndex != -1){
			repairWallList[myIndex].repairNeeded -= creep.carry.energy;
            creep.task=repairWallList[myIndex];
            return OK;
        }
    },

	getMiningTask : function(creep){
		var room = creep.room;
		var creepsByTask = _(Game.creeps).filter( (c) => c.task && c.task.roomName == room.name).groupBy('task.type').value();
		var mineTasks = calcTasks.calcMineTasks(room,creepsByTask);
		var myIndex = _.min(_.keys(mineTasks), function(k) { return mineTasks[k].assigned;})
		if(myIndex != -1){
			creep.task = mineTasks[myIndex];
			creep.task.containerId = undefined; //civilians ignore containers
			return OK;
		}
		else{
			return;
		}
	},

	getTowerFillingTask : function(creep){
		var deliverList = creep.room.memory.tasks[TASK_FILL];
		var myIndex = _.findIndex(deliverList, (x) => x.structureType == STRUCTURE_TOWER && x.amountNeeded >= 200);
		if(myIndex != -1){
			deliverList[myIndex].amountNeeded -= creep.carry.energy;
            creep.task=deliverList[myIndex];
            creep.room.memory.tasks[TASK_FILL] = deliverList;
            return OK;
		}
		else{
			return;
		}
	},

    run : function(creep){
        if(creep.memory.working && creep.carry.energy == 0) {
            creep.memory.working = false;
			creep.task = undefined;
            creep.say('getting');
	    }
	    if(!creep.memory.working && creep.carry.energy == creep.carryCapacity) {
	        creep.memory.working = true;
            creep.task = undefined;
	        creep.say('working');
		}

        if(!creep.task){
            if(creep.memory.working){
                var check;
				var creepsByTask =  _(Game.creeps).filter( (c) => c.task && c.task.roomName == creep.room.name).groupBy('task.type').value();
				var upgradeCreeps = creepsByTask[TASK_UPGRADE] || [];
				var repairCreeps = creepsByTask[TASK_REPAIR] || [];
				var repairWallCreeps = creepsByTask[TASK_REPAIR_WALL] || [];
				if(upgradeCreeps.length < 1 && Game.rooms[creep.memory.homeRoom].controller.ticksToDowngrade < 5000){ //is missing some safety checks
                    check = this.getUpgradingTask(creep);
                }
				if(check != OK && creep.room.memory.underAttack){
					check = this.getTowerFillingTask(creep);
				}
                if(check != OK){
                    check = this.getBuildingTask(creep);
                }
                if(check != OK && repairCreeps.length < 1){ //at most 1 creep on repairing duties
                    check = this.getRepairingTask(creep);
				}
                if(check != OK && repairWallCreeps.length < 1){ //should allow more creeps to repair in emergency
                    check = this.getWallRepairingTask(creep);
                }
                if(check != OK && Game.rooms[creep.memory.homeRoom].controller.level < 8){
                    check = this.getUpgradingTask(creep);
                }
            }
            else{
                if(creep.ticksToLive < 150 && creep.room.find(FIND_MY_STRUCTURES,{filter: (s) => s.structureType == STRUCTURE_SPAWN}).length > 0){
                    creep.role = ROLE_RECYCLER;
                }
                else{
                    var status = this.getGettingTask(creep);
					if(status != OK){
						this.getMiningTask(creep);
					}
                }
            }
        }

    }
}
<commit_msg>fixed colonists crashing from undefined room.tasks<commit_after>"use strict";

const setupTask = require('utils').setupTask;
const calcTasks = require("calcTasks");

module.exports = {
	getGettingTask : function(creep){
        //here the prioritization of one source is missing
		var room = creep.room;
		var creepsByTask = _(Game.creeps).filter( (c) => c.task && c.task.roomName == room.name).groupBy('task.type').value();
        var getEnergyTasks = calcTasks.calcGetEnergyTasks(room,creepsByTask);
        var myIndex = -1;
        myIndex = _.findIndex(getEnergyTasks, (t) => t.amountAvailable == Game.getObjectById(t.id).storeCapacity);
        if(myIndex != -1){
            creep.task=getEnergyTasks[myIndex];
            return OK;
        }
        var pickupTasks = calcTasks.calcPickupTasks(room,creepsByTask);
        myIndex = _.findIndex(pickupTasks,(t) => t.amountLeft > 50); //here a better check than > 50 would be nice
        if(myIndex != -1){
            creep.task=pickupTasks[myIndex];
            return OK;
        }
        myIndex = _.findIndex(getEnergyTasks,(t) => t.amountAvailable >= (creep.carryCapacity - creep.carry.energy));
        if(myIndex != -1){
            creep.task=getEnergyTasks[myIndex];
            return OK;
        }
        //this should work now that we do creep-based tasks, but should reset when empty
        if(creep.room.storage && creep.room.storage.store.energy >= (creep.carryCapacity - creep.carry.energy)){
            creep.task= setupTask(TASK_GET_ENERGY,creep.room.storage);
			return OK;
        }
    },

    getBuildingTask : function(creep){
		var room = creep.room;
		var creepsByTask = _(Game.creeps).filter( (c) => c.task && c.task.roomName == room.name).groupBy('task.type').value();
        var buildList = calcTasks.calcBuildTasks(room,creepsByTask);
        var myIndex = _.findIndex(buildList, (t) => t.progressLeft > 0);
        if(myIndex != -1){
            creep.task=buildList[myIndex];
            return OK;
        }
    },

    getUpgradingTask : function(creep){
		var room = _.get(Game.rooms, creep.memory.homeRoom, creep.room);
		var creepsByTask = _(Game.creeps).filter( (c) => c.task && c.task.roomName == room.name).groupBy('task.type').value();
        var upgradeList = calcTasks.calcUpgradeTasks(room,creepsByTask);
        var myIndex = _.findIndex(upgradeList, (t) => true);
        if(myIndex != -1){
            creep.task=upgradeList[myIndex];
            return OK;
        }
    },

    getRepairingTask : function(creep){
        var repairList = _.get(creep.room.memory,"tasks." + TASK_REPAIR,[]);
        var myIndex = _.findIndex(repairList, (t) => t.repairNeeded > 0);
        if(myIndex != -1){
			repairList[myIndex].repairNeeded -= creep.carry.energy;
            creep.task=repairList[myIndex];
            return OK;
        }
    },

    getWallRepairingTask : function(creep){
		var repairWallList = _.get(creep.room.memory,"tasks." + TASK_REPAIR_WALL,[]);
		var myIndex = _.findIndex(repairWallList, (t) => t.repairNeeded > 0);
        if(myIndex != -1){
			repairWallList[myIndex].repairNeeded -= creep.carry.energy;
            creep.task=repairWallList[myIndex];
            return OK;
        }
    },

	getMiningTask : function(creep){
		var room = creep.room;
		var creepsByTask = _(Game.creeps).filter( (c) => c.task && c.task.roomName == room.name).groupBy('task.type').value();
		var mineTasks = calcTasks.calcMineTasks(room,creepsByTask);
		var myIndex = _.min(_.keys(mineTasks), function(k) { return mineTasks[k].assigned;})
		if(myIndex != -1){
			creep.task = mineTasks[myIndex];
			creep.task.containerId = undefined; //civilians ignore containers
			return OK;
		}
		else{
			return;
		}
	},

	getTowerFillingTask : function(creep){
		var deliverList = _.get(creep.room.memory, "tasks."+ TASK_FILL,[]);
		var myIndex = _.findIndex(deliverList, (x) => x.structureType == STRUCTURE_TOWER && x.amountNeeded >= 200);
		if(myIndex != -1){
			deliverList[myIndex].amountNeeded -= creep.carry.energy;
            creep.task=deliverList[myIndex];
            creep.room.memory.tasks[TASK_FILL] = deliverList;
            return OK;
		}
		else{
			return;
		}
	},

    run : function(creep){
        if(creep.memory.working && creep.carry.energy == 0) {
            creep.memory.working = false;
			creep.task = undefined;
            creep.say('getting');
	    }
	    if(!creep.memory.working && creep.carry.energy == creep.carryCapacity) {
	        creep.memory.working = true;
            creep.task = undefined;
	        creep.say('working');
		}

        if(!creep.task){
            if(creep.memory.working){
                var check;
				var creepsByTask =  _(Game.creeps).filter( (c) => c.task && c.task.roomName == creep.room.name).groupBy('task.type').value();
				var upgradeCreeps = creepsByTask[TASK_UPGRADE] || [];
				var repairCreeps = creepsByTask[TASK_REPAIR] || [];
				var repairWallCreeps = creepsByTask[TASK_REPAIR_WALL] || [];
				if(upgradeCreeps.length < 1 && Game.rooms[creep.memory.homeRoom].controller.ticksToDowngrade < 5000){ //is missing some safety checks
                    check = this.getUpgradingTask(creep);
                }
				if(check != OK && creep.room.memory.underAttack){
					check = this.getTowerFillingTask(creep);
				}
                if(check != OK){
                    check = this.getBuildingTask(creep);
                }
                if(check != OK && repairCreeps.length < 1){ //at most 1 creep on repairing duties
                    check = this.getRepairingTask(creep);
				}
                if(check != OK && repairWallCreeps.length < 1){ //should allow more creeps to repair in emergency
                    check = this.getWallRepairingTask(creep);
                }
                if(check != OK && Game.rooms[creep.memory.homeRoom].controller.level < 8){
                    check = this.getUpgradingTask(creep);
                }
            }
            else{
                if(creep.ticksToLive < 150 && creep.room.find(FIND_MY_STRUCTURES,{filter: (s) => s.structureType == STRUCTURE_SPAWN}).length > 0){
                    creep.role = ROLE_RECYCLER;
                }
                else{
                    var status = this.getGettingTask(creep);
					if(status != OK){
						this.getMiningTask(creep);
					}
                }
            }
        }

    }
}
<|endoftext|>


<commit_before>define(
  'ephox.echo.api.AriaRegister',

  [
    'ephox.classify.Type',
    'ephox.compass.Arr',
    'ephox.compass.Obj',
    'ephox.echo.api.Styles',
    'ephox.epithet.Id',
    'ephox.peanut.Fun',
    'ephox.sugar.api.Attr',
    'ephox.sugar.api.Class',
    'ephox.sugar.api.Element',
    'ephox.sugar.api.Insert'
  ],

  function (Type, Arr, Obj, Styles, Id, Fun, Attr, Class, Element, Insert) {
    var helpStyle = Styles.resolve('aria-help');
    var helpVisibleStyle = Styles.resolve('aria-help-visible');

    var presentation = function (element) {
      Attr.setAll(element, {
        'role': 'presentation',
        'aria-hidden': 'true'
      });
    };

    var editor = function (container, editor, label, ariaHelp, showHelpHint) {
      Attr.setAll(container, {
        'role': 'application',
        'aria-label': label
      });

      var labelId = Id.generate('ephox-aria');
      var aria = Element.fromTag('span');
      Insert.append(aria, Element.fromText(ariaHelp));
      Attr.set(aria, 'id', labelId);
      Class.add(aria, helpStyle);
      if (showHelpHint === true) Class.add(aria, helpVisibleStyle);
      Insert.append(container, aria);

      // content attributes - surprisingly helps in both classic and inline
      var attrs = {
        'aria-multiline': 'true',
        'aria-label': label,
        title: label,
        'aria-describedby': labelId
      };

      Attr.setAll(editor, attrs);

      var destroy = function () {
        Arr.each(Obj.keys(attrs), Fun.curry(Attr.remove, editor));
      };

      return {
        destroy: destroy
      };
    };

    var toolbar = function (element, label) {
      Attr.setAll(element, {
        'role': 'group',
        'aria-label': label
      });
    };

    var menu = function (element, label) {
      Attr.setAll(element, {
        'role': 'menu',
        'aria-label': label
      });
    };

    var toolbarButton = function (element, label, hasPopup, isToggle) {
      Attr.setAll(element, {
        'role': 'button',
        'aria-label': label,
        'aria-haspopup': '' + hasPopup
      });
      if (isToggle) Attr.set(element, 'aria-pressed', 'false');
      if (hasPopup) Attr.set(element, 'aria-expanded', 'false');
    };

    var toolbarGroup = function (element, label) {
      // TODO: duplicated from 'ephox.polish.alien.Query', consolidate isEmpty();
      var isEmpty = function (val) {
        // TODO: Move to compass Arr and violin Strings
        return (val === null) || (val === undefined) || (val === '') || (Type.isArray(val) && val.length === 0);
      };
      // End TODO

      Attr.set(element, 'role', 'toolbar');

      // customer groups may have empty label, don't use it
      if (!isEmpty(label)) {
        Attr.set(element, 'aria-label', label);
      }
    };

    var menuItem = function (element, label, hasPopup) {
      Attr.setAll(element, {
        'role': 'menuitem',
        'aria-label': label,
        'aria-haspopup': hasPopup === true ? 'true' : 'false'
      });
    };

    var menuItemCheckbox = function (element, label) {
      Attr.setAll(element, {
        'role': 'menuitemcheckbox',
        'aria-label': label,
        'aria-checked': false
      });
    };

    var dialog = function (element, label) {
      Attr.setAll(element, {
        'role': 'dialog',
        'aria-label': label
      });
    };

    var button = function (element, label) {
      Attr.setAll(element, {
        'aria-label': label,
        'role': 'button'
      });
    };

    var textarea = function (element) {
      Attr.setAll(element, {
        'aria-multiline': 'true',
        'role': 'textbox'
      });
    };

    var widget = function (element) {
      Attr.set(element, 'role', 'widget');
    };

    var listBox = function (element) {
      Attr.set(element, 'role', 'listbox');
    };

    var tabList = function (element) {
      Attr.set(element, 'role', 'tablist');
    };

    var tabButton = function (element, label) {
      Attr.setAll(element, {
        'aria-label': label,
        'role': 'tab'
      });
    };

    var tabPanel = function (element /*, label */) {
      Attr.setAll(element, {
        'role': 'tabpanel'
        // 'aria-label': label // Doesn't seem to be read by JAWS or VoiceOver, so giving up
      });
    };

    var linkTabToPanel = function (tab, panel) {
      // I couldn't hear any difference with this, but the concept is linking buttons to the panel that will show
      var id = Id.generate('ephox-aria');
      Attr.set(panel, 'id', id);
      Attr.setAll(tab, {
        'aria-controls': id,
        'aria-owns': id
      });
    };

    var describedBy = function (element, id) {
      Attr.set(element, 'aria-describedby', id);
    };

    var labelledBy = function (element, id) {
      Attr.set(element, 'aria-labelledby', id);
    };

    var live = function (element, id, _priority) {
      var priority = _priority ? _priority : 'polite';
      Attr.setAll(element, {
        'aria-live': priority,
        'id': id
      });
    };

    var controls = function (element, id) {
      Attr.set(element, 'aria-controls', id);
    };

    var required = function (element) {
      Attr.set(element, 'aria-required', 'true');
    };

    // TODO: Implement form ARIA support
    // var form = function (element, label) {
    //   throw 'Form ARIA support not implemented yet.';
    // };

    var input = function (element, label) {
      Attr.set(element, 'aria-label', label);
    };

    // TODO: Implement textarea ARIA support
    // var textarea = function (element, label, required) {
    //   throw 'Textarea ARIA support not implemented yet.';
    // };

    // TODO: Implement link ARIA support
    // var link = function (element) {
    //   throw 'Link ARIA support not implemented yet.';
    // };

    // TODO: Implement other ARIA support
    // var other = function () {
    //   throw 'Other ARIA support not implemented yet.';
    // };

    return {
      presentation: presentation,
      controls: controls,
      editor: editor,
      toolbar: toolbar,
      toolbarGroup: toolbarGroup,
      toolbarButton: toolbarButton,
      menu: menu,
      menuItem: menuItem,
      menuItemCheckbox: menuItemCheckbox,
      dialog: dialog,
      button: button,
      textarea: textarea,
      input: input,
      widget: widget,
      listBox: listBox,
      live: live,
      tabList: tabList,
      tabButton: tabButton,
      tabPanel: tabPanel,
      linkTabToPanel: linkTabToPanel,
      describedBy: describedBy,
      labelledBy: labelledBy,
      required: required
    };
  }
);<commit_msg>TBIO-2648: remove TODO comment, because done<commit_after>define(
  'ephox.echo.api.AriaRegister',

  [
    'ephox.classify.Type',
    'ephox.compass.Arr',
    'ephox.compass.Obj',
    'ephox.echo.api.Styles',
    'ephox.epithet.Id',
    'ephox.peanut.Fun',
    'ephox.sugar.api.Attr',
    'ephox.sugar.api.Class',
    'ephox.sugar.api.Element',
    'ephox.sugar.api.Insert'
  ],

  function (Type, Arr, Obj, Styles, Id, Fun, Attr, Class, Element, Insert) {
    var helpStyle = Styles.resolve('aria-help');
    var helpVisibleStyle = Styles.resolve('aria-help-visible');

    var presentation = function (element) {
      Attr.setAll(element, {
        'role': 'presentation',
        'aria-hidden': 'true'
      });
    };

    var editor = function (container, editor, label, ariaHelp, showHelpHint) {
      Attr.setAll(container, {
        'role': 'application',
        'aria-label': label
      });

      var labelId = Id.generate('ephox-aria');
      var aria = Element.fromTag('span');
      Insert.append(aria, Element.fromText(ariaHelp));
      Attr.set(aria, 'id', labelId);
      Class.add(aria, helpStyle);
      if (showHelpHint === true) Class.add(aria, helpVisibleStyle);
      Insert.append(container, aria);

      // content attributes - surprisingly helps in both classic and inline
      var attrs = {
        'aria-multiline': 'true',
        'aria-label': label,
        title: label,
        'aria-describedby': labelId
      };

      Attr.setAll(editor, attrs);

      var destroy = function () {
        Arr.each(Obj.keys(attrs), Fun.curry(Attr.remove, editor));
      };

      return {
        destroy: destroy
      };
    };

    var toolbar = function (element, label) {
      Attr.setAll(element, {
        'role': 'group',
        'aria-label': label
      });
    };

    var menu = function (element, label) {
      Attr.setAll(element, {
        'role': 'menu',
        'aria-label': label
      });
    };

    var toolbarButton = function (element, label, hasPopup, isToggle) {
      Attr.setAll(element, {
        'role': 'button',
        'aria-label': label,
        'aria-haspopup': '' + hasPopup
      });
      if (isToggle) Attr.set(element, 'aria-pressed', 'false');
      if (hasPopup) Attr.set(element, 'aria-expanded', 'false');
    };

    var toolbarGroup = function (element, label) {
      // TODO: duplicated from 'ephox.polish.alien.Query', consolidate isEmpty();
      var isEmpty = function (val) {
        // TODO: Move to compass Arr and violin Strings
        return (val === null) || (val === undefined) || (val === '') || (Type.isArray(val) && val.length === 0);
      };
      // End TODO

      Attr.set(element, 'role', 'toolbar');

      // customer groups may have empty label, don't use it
      if (!isEmpty(label)) {
        Attr.set(element, 'aria-label', label);
      }
    };

    var menuItem = function (element, label, hasPopup) {
      Attr.setAll(element, {
        'role': 'menuitem',
        'aria-label': label,
        'aria-haspopup': hasPopup === true ? 'true' : 'false'
      });
    };

    var menuItemCheckbox = function (element, label) {
      Attr.setAll(element, {
        'role': 'menuitemcheckbox',
        'aria-label': label,
        'aria-checked': false
      });
    };

    var dialog = function (element, label) {
      Attr.setAll(element, {
        'role': 'dialog',
        'aria-label': label
      });
    };

    var button = function (element, label) {
      Attr.setAll(element, {
        'aria-label': label,
        'role': 'button'
      });
    };

    var textarea = function (element) {
      Attr.setAll(element, {
        'aria-multiline': 'true',
        'role': 'textbox'
      });
    };

    var widget = function (element) {
      Attr.set(element, 'role', 'widget');
    };

    var listBox = function (element) {
      Attr.set(element, 'role', 'listbox');
    };

    var tabList = function (element) {
      Attr.set(element, 'role', 'tablist');
    };

    var tabButton = function (element, label) {
      Attr.setAll(element, {
        'aria-label': label,
        'role': 'tab'
      });
    };

    var tabPanel = function (element /*, label */) {
      Attr.setAll(element, {
        'role': 'tabpanel'
        // 'aria-label': label // Doesn't seem to be read by JAWS or VoiceOver, so giving up
      });
    };

    var linkTabToPanel = function (tab, panel) {
      // I couldn't hear any difference with this, but the concept is linking buttons to the panel that will show
      var id = Id.generate('ephox-aria');
      Attr.set(panel, 'id', id);
      Attr.setAll(tab, {
        'aria-controls': id,
        'aria-owns': id
      });
    };

    var describedBy = function (element, id) {
      Attr.set(element, 'aria-describedby', id);
    };

    var labelledBy = function (element, id) {
      Attr.set(element, 'aria-labelledby', id);
    };

    var live = function (element, id, _priority) {
      var priority = _priority ? _priority : 'polite';
      Attr.setAll(element, {
        'aria-live': priority,
        'id': id
      });
    };

    var controls = function (element, id) {
      Attr.set(element, 'aria-controls', id);
    };

    var required = function (element) {
      Attr.set(element, 'aria-required', 'true');
    };

    // TODO: Implement form ARIA support
    // var form = function (element, label) {
    //   throw 'Form ARIA support not implemented yet.';
    // };

    var input = function (element, label) {
      Attr.set(element, 'aria-label', label);
    };

    // TODO: Implement link ARIA support
    // var link = function (element) {
    //   throw 'Link ARIA support not implemented yet.';
    // };

    // TODO: Implement other ARIA support
    // var other = function () {
    //   throw 'Other ARIA support not implemented yet.';
    // };

    return {
      presentation: presentation,
      controls: controls,
      editor: editor,
      toolbar: toolbar,
      toolbarGroup: toolbarGroup,
      toolbarButton: toolbarButton,
      menu: menu,
      menuItem: menuItem,
      menuItemCheckbox: menuItemCheckbox,
      dialog: dialog,
      button: button,
      textarea: textarea,
      input: input,
      widget: widget,
      listBox: listBox,
      live: live,
      tabList: tabList,
      tabButton: tabButton,
      tabPanel: tabPanel,
      linkTabToPanel: linkTabToPanel,
      describedBy: describedBy,
      labelledBy: labelledBy,
      required: required
    };
  }
);<|endoftext|>


<commit_before>import Plugin from '../Plugin'
import dragDrop from 'drag-drop'
import Dashboard from './Dashboard'
import { defaultTabIcon } from './icons'

/**
 * Modal Dialog & Dashboard
 */
export default class DashboardUI extends Plugin {
  constructor (core, opts) {
    super(core, opts)
    this.id = 'DashboardUI'
    this.title = 'Dashboard UI'
    this.type = 'orchestrator'

    // set default options
    const defaultOptions = {
      target: 'body',
      defaultTabIcon: defaultTabIcon(),
      panelSelectorPrefix: 'UppyDashboardContent-panel',
      showProgressDetails: true
    }

    // merge default options with the ones set by user
    this.opts = Object.assign({}, defaultOptions, opts)

    this.hideModal = this.hideModal.bind(this)
    this.showModal = this.showModal.bind(this)

    this.addTarget = this.addTarget.bind(this)
    this.actions = this.actions.bind(this)
    this.hideAllPanels = this.hideAllPanels.bind(this)
    this.showPanel = this.showPanel.bind(this)
    this.initEvents = this.initEvents.bind(this)
    this.render = this.render.bind(this)
    this.install = this.install.bind(this)
  }

  addTarget (plugin) {
    const callerPluginId = plugin.constructor.name
    const callerPluginName = plugin.title || callerPluginId
    const callerPluginIcon = plugin.icon || this.opts.defaultTabIcon
    const callerPluginType = plugin.type

    if (callerPluginType !== 'acquirer' &&
        callerPluginType !== 'progressindicator' &&
        callerPluginType !== 'presenter') {
      let msg = 'Error: Modal can only be used by plugins of types: acquirer, progressindicator, presenter'
      this.core.log(msg)
      return
    }

    const target = {
      id: callerPluginId,
      name: callerPluginName,
      icon: callerPluginIcon,
      type: callerPluginType,
      focus: plugin.focus,
      render: plugin.render,
      isHidden: true
    }

    const modal = this.core.getState().modal
    const newTargets = modal.targets.slice()
    newTargets.push(target)

    this.core.setState({
      modal: Object.assign({}, modal, {
        targets: newTargets
      })
    })

    return this.opts.target
  }

  hideAllPanels () {
    const modal = this.core.getState().modal

    const newTargets = modal.targets.map((target) => {
      const isAcquirer = target.type === 'acquirer'
      return Object.assign({}, target, {
        isHidden: isAcquirer
      })
    })

    this.core.setState({modal: Object.assign({}, modal, {
      targets: newTargets
    })})
  }

  showPanel (id) {
    const modal = this.core.getState().modal

    // hide all panels, except the one that matches current id
    const newTargets = modal.targets.map((target) => {
      if (target.type === 'acquirer') {
        if (target.id === id) {
          target.focus()
          return Object.assign({}, target, {
            isHidden: false
          })
        }
        return Object.assign({}, target, {
          isHidden: true
        })
      }
      return target
    })

    this.core.setState({modal: Object.assign({}, modal, {
      targets: newTargets
    })})
  }

  hideModal () {
    const modal = this.core.getState().modal

    this.core.setState({
      modal: Object.assign({}, modal, {
        isHidden: true
      })
    })

    document.body.classList.remove('is-UppyDashboard-open')
  }

  showModal () {
    const modal = this.core.getState().modal

    this.core.setState({
      modal: Object.assign({}, modal, {
        isHidden: false
      })
    })

    // add class to body that sets position fixed
    document.body.classList.add('is-UppyDashboard-open')
    // focus on modal inner block
    document.querySelector('*[tabindex="0"]').focus()
  }

  initEvents () {
    const modal = document.querySelector(`${this.opts.target} .UppyDashboard`)
    // Modal open button
    const showModalTrigger = document.querySelector(this.opts.trigger)
    showModalTrigger.addEventListener('click', this.showModal)

    // Close the Modal on esc key press
    document.body.addEventListener('keyup', (event) => {
      if (event.keyCode === 27) {
        this.hideModal()
      }
    })

    // Close on click outside modal or close buttons
    document.addEventListener('click', (e) => {
      if (e.target.classList.contains('js-UppyDashboard-close')) {
        this.hideModal()
      }
    })

    // Drag Drop
    dragDrop(`${this.opts.target} .UppyDashboard`, (files) => {
      this.handleDrop(files)
      this.core.log(files)
    })

    // @TODO Exprimental, work in progress
    // Paste from clipboard
    modal.addEventListener('paste', this.handlePaste.bind(this))
  }

  // @TODO Exprimental, work in progress
  // no names, weird API, Chrome-only http://stackoverflow.com/a/22940020
  handlePaste (ev) {
    const files = ev.clipboardData.items

    for (let i = 0; i < files.length; i++) {
      const file = files[i]

      if (file.kind === 'file') {
        const blob = file.getAsFile()
        console.log(blob)
        this.core.emitter.emit('file-add', {
          source: this.id,
          name: file.name,
          type: file.type,
          data: blob
        })
      }
    }
  }

  actions () {
    const bus = this.core.emitter

    bus.on('file-add', () => {
      this.hideAllPanels()
    })

    bus.on('dashboard:file-card', (fileId) => {
      const modal = this.core.getState().modal

      this.core.setState({
        modal: Object.assign({}, modal, {
          showFileCard: fileId || false
        })
      })
    })

    bus.on('all-uploads-complete', (uploadedCount) => {
      bus.emit(
        'informer',
        `${this.core.i18n('files', {'smart_count': uploadedCount})} files have been successfully uploaded, Sir!`,
        'info',
        8000
      )
    })

    // setInterval(() => {
    //   const isOnline = navigator.onLine
    //   if (!isOnline) {
    //     bus.emit('informer', 'No internet connection', 'error', 0)
    //   } else {
    //     bus.emit('informer-hide')
    //   }
    // }, 10000)
  }

  handleDrop (files) {
    this.core.log('All right, someone dropped something...')

    files.forEach((file) => {
      this.core.emitter.emit('file-add', {
        source: this.id,
        name: file.name,
        type: file.type,
        data: file
      })
    })
  }

  render (state) {
    const bus = this.core.emitter
    return Dashboard({
      state: state,
      autoProceed: this.core.opts.autoProceed,
      container: this.opts.target,
      hideModal: this.hideModal,
      panelSelectorPrefix: this.opts.panelSelectorPrefix,
      showProgressDetails: this.opts.showProgressDetails,
      handleInputChange: this.handleInputChange,
      showPanel: this.showPanel,
      hideAllPanels: this.hideAllPanels,
      log: this.core.log
    }, bus)
  }

  install () {
    // Set default state for Modal
    this.core.setState({modal: {
      isHidden: true,
      showFileCard: false,
      targets: []
    }})

    const target = this.opts.target
    const plugin = this
    this.target = this.mount(target, plugin)

    this.initEvents()
    this.actions()
  }
}
<commit_msg>update text and timing for `all-uploads-complete` informer<commit_after>import Plugin from '../Plugin'
import dragDrop from 'drag-drop'
import Dashboard from './Dashboard'
import { defaultTabIcon } from './icons'

/**
 * Modal Dialog & Dashboard
 */
export default class DashboardUI extends Plugin {
  constructor (core, opts) {
    super(core, opts)
    this.id = 'DashboardUI'
    this.title = 'Dashboard UI'
    this.type = 'orchestrator'

    // set default options
    const defaultOptions = {
      target: 'body',
      defaultTabIcon: defaultTabIcon(),
      panelSelectorPrefix: 'UppyDashboardContent-panel',
      showProgressDetails: true
    }

    // merge default options with the ones set by user
    this.opts = Object.assign({}, defaultOptions, opts)

    this.hideModal = this.hideModal.bind(this)
    this.showModal = this.showModal.bind(this)

    this.addTarget = this.addTarget.bind(this)
    this.actions = this.actions.bind(this)
    this.hideAllPanels = this.hideAllPanels.bind(this)
    this.showPanel = this.showPanel.bind(this)
    this.initEvents = this.initEvents.bind(this)
    this.render = this.render.bind(this)
    this.install = this.install.bind(this)
  }

  addTarget (plugin) {
    const callerPluginId = plugin.constructor.name
    const callerPluginName = plugin.title || callerPluginId
    const callerPluginIcon = plugin.icon || this.opts.defaultTabIcon
    const callerPluginType = plugin.type

    if (callerPluginType !== 'acquirer' &&
        callerPluginType !== 'progressindicator' &&
        callerPluginType !== 'presenter') {
      let msg = 'Error: Modal can only be used by plugins of types: acquirer, progressindicator, presenter'
      this.core.log(msg)
      return
    }

    const target = {
      id: callerPluginId,
      name: callerPluginName,
      icon: callerPluginIcon,
      type: callerPluginType,
      focus: plugin.focus,
      render: plugin.render,
      isHidden: true
    }

    const modal = this.core.getState().modal
    const newTargets = modal.targets.slice()
    newTargets.push(target)

    this.core.setState({
      modal: Object.assign({}, modal, {
        targets: newTargets
      })
    })

    return this.opts.target
  }

  hideAllPanels () {
    const modal = this.core.getState().modal

    const newTargets = modal.targets.map((target) => {
      const isAcquirer = target.type === 'acquirer'
      return Object.assign({}, target, {
        isHidden: isAcquirer
      })
    })

    this.core.setState({modal: Object.assign({}, modal, {
      targets: newTargets
    })})
  }

  showPanel (id) {
    const modal = this.core.getState().modal

    // hide all panels, except the one that matches current id
    const newTargets = modal.targets.map((target) => {
      if (target.type === 'acquirer') {
        if (target.id === id) {
          target.focus()
          return Object.assign({}, target, {
            isHidden: false
          })
        }
        return Object.assign({}, target, {
          isHidden: true
        })
      }
      return target
    })

    this.core.setState({modal: Object.assign({}, modal, {
      targets: newTargets
    })})
  }

  hideModal () {
    const modal = this.core.getState().modal

    this.core.setState({
      modal: Object.assign({}, modal, {
        isHidden: true
      })
    })

    document.body.classList.remove('is-UppyDashboard-open')
  }

  showModal () {
    const modal = this.core.getState().modal

    this.core.setState({
      modal: Object.assign({}, modal, {
        isHidden: false
      })
    })

    // add class to body that sets position fixed
    document.body.classList.add('is-UppyDashboard-open')
    // focus on modal inner block
    document.querySelector('*[tabindex="0"]').focus()
  }

  initEvents () {
    const modal = document.querySelector(`${this.opts.target} .UppyDashboard`)
    // Modal open button
    const showModalTrigger = document.querySelector(this.opts.trigger)
    showModalTrigger.addEventListener('click', this.showModal)

    // Close the Modal on esc key press
    document.body.addEventListener('keyup', (event) => {
      if (event.keyCode === 27) {
        this.hideModal()
      }
    })

    // Close on click outside modal or close buttons
    document.addEventListener('click', (e) => {
      if (e.target.classList.contains('js-UppyDashboard-close')) {
        this.hideModal()
      }
    })

    // Drag Drop
    dragDrop(`${this.opts.target} .UppyDashboard`, (files) => {
      this.handleDrop(files)
      this.core.log(files)
    })

    // @TODO Exprimental, work in progress
    // Paste from clipboard
    modal.addEventListener('paste', this.handlePaste.bind(this))
  }

  // @TODO Exprimental, work in progress
  // no names, weird API, Chrome-only http://stackoverflow.com/a/22940020
  handlePaste (ev) {
    const files = ev.clipboardData.items

    for (let i = 0; i < files.length; i++) {
      const file = files[i]

      if (file.kind === 'file') {
        const blob = file.getAsFile()
        console.log(blob)
        this.core.emitter.emit('file-add', {
          source: this.id,
          name: file.name,
          type: file.type,
          data: blob
        })
      }
    }
  }

  actions () {
    const bus = this.core.emitter

    bus.on('file-add', () => {
      this.hideAllPanels()
    })

    bus.on('dashboard:file-card', (fileId) => {
      const modal = this.core.getState().modal

      this.core.setState({
        modal: Object.assign({}, modal, {
          showFileCard: fileId || false
        })
      })
    })

    bus.on('all-uploads-complete', (uploadedCount) => {
      bus.emit(
        'informer',
        `${this.core.i18n('files', {'smart_count': uploadedCount})} successfully uploaded, Sir!`,
        'info',
        6000
      )
    })

    // setInterval(() => {
    //   const isOnline = navigator.onLine
    //   if (!isOnline) {
    //     bus.emit('informer', 'No internet connection', 'error', 0)
    //   } else {
    //     bus.emit('informer-hide')
    //   }
    // }, 10000)
  }

  handleDrop (files) {
    this.core.log('All right, someone dropped something...')

    files.forEach((file) => {
      this.core.emitter.emit('file-add', {
        source: this.id,
        name: file.name,
        type: file.type,
        data: file
      })
    })
  }

  render (state) {
    const bus = this.core.emitter
    return Dashboard({
      state: state,
      autoProceed: this.core.opts.autoProceed,
      container: this.opts.target,
      hideModal: this.hideModal,
      panelSelectorPrefix: this.opts.panelSelectorPrefix,
      showProgressDetails: this.opts.showProgressDetails,
      handleInputChange: this.handleInputChange,
      showPanel: this.showPanel,
      hideAllPanels: this.hideAllPanels,
      log: this.core.log
    }, bus)
  }

  install () {
    // Set default state for Modal
    this.core.setState({modal: {
      isHidden: true,
      showFileCard: false,
      targets: []
    }})

    const target = this.opts.target
    const plugin = this
    this.target = this.mount(target, plugin)

    this.initEvents()
    this.actions()
  }
}
<|endoftext|>