<commit_before>/**
* Datepicker lets you select dates.
* @name DatePicker
* @class DatePicker
* @augments ch.Controls
* @requires ch.Calendar
* @see ch.Controls
* @see ch.Calendar
* @memberOf ch
* @param {Object} [conf] Object with configuration properties.
* @param {String} [conf.format] Sets the date format. By default is "DD/MM/YYYY".
* @param {String} [conf.selected] Sets a date that should be selected by default. By default is the date of today.
* @param {String} [conf.from] Set a maximum selectable date.
* @param {String} [conf.to] Set a minimum selectable date.
* @param {String} [conf.points] Points to be positioned. See Positioner component. By default is "ct cb".
* @param {Array} [conf.monthsNames] By default is ["Enero", ... , "Diciembre"].
* @param {Array} [conf.weekdays] By default is ["Dom", ... , "Sab"].
* @param {Boolean} [conf.closable] Defines if floated component will be closed when a date is selected or not. By default it's "true".
* @returns itself
* @factorized
* @exampleDescription Create a new datePicker.
* @example
* var widget = $(".example").datePicker();
* @exampleDescription Create a new Date Picker with configuration.
* @example
* var widget = $(".example").datePicker({
*	 "format": "MM/DD/YYYY",
*	 "selected": "2011/12/25",
*	 "from": "2010/12/25",
*	 "to": "2012/12/25",
*	 "monthsNames": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
*	 "weekdays": ["Su", "Mo", "Tu", "We", "Thu", "Fr", "Sa"]
* });
*/

ch.datePicker = function (conf) {

	/**
	* Reference to a internal component instance, saves all the information and configuration properties.
	* @private
	* @name ch.DatePicker#that
	* @type object
	*/
	var that = this;

	conf = ch.clon(conf);

	// Configuration by default
	conf.format = conf.format || "DD/MM/YYYY";
	conf.points = conf.points || "ct cb";
	conf.closable = ch.utils.hasOwn(conf, "closable") ? conf.closable : true;

	that.conf = conf;

/**
*	Inheritance
*/

	that = ch.controls.call(that);
	that.parent = ch.clon(that);

/**
*	Private Members
*/

/**
*	Protected Members
*/

	/**
	* Pick a date in the Calendar and updates the input data.
	* @protected
	* @function
	* @name ch.DatePicker#process
	*/
	that.process = function (event) {

		// Day selection
		if (event.target.nodeName !== "TD" || event.target.className.indexOf("ch-disabled") !== -1 || event.target.className.indexOf("ch-calendar-other") !== -1) { return; }

		// Select the day and update input value with selected date
		that.element.value = that.calendar.selectDay(event.target.innerHTML);

		// Hide float
		if (conf.closable) { that["float"].innerHide(); }

		/**
		* Callback function
		* @public
		* @name ch.DatePicker#select
		* @event
		*/
		// Old callback system
		that.callbacks("onSelect");
		// New callback
		that.trigger("select");

	};

	/**
	* Reference to the Calendar component instance.
	* @protected
	* @type Object
	* @name ch.DatePicker#calendar
	*/
	that.calendar = $("
")
		// Add functionality for date selection
		.bind("click", function (event) { that.process(event); })
		// Instance Calendar component
		.calendar({
			"format": conf.format,
			"from": conf.from,
			"to": conf.to,
			"selected": conf.selected,
			"monthsNames": conf.monthsNames,
			"weekdays": conf.weekdays
		});

	/**
	* Reference to the Float component instanced.
	* @protected
	* @type Object
	* @name ch.DatePicker#float
	*/
	that["float"] = that.createFloat({
		"$element": $("

").insertAfter(that.element),
		"content": that.calendar.element,
		"points": conf.points,
		"offset": "0 10",
		"aria": {
			"role": "tooltip",
			"identifier": "aria-describedby"
		},
		"closeButton": false,
		"cone": true
	});

/**
*  Public Members
*/

	/**
	* @borrows ch.Object#uid as ch.Menu#uid
	*/

	/**
	* @borrows ch.Object#element as ch.Menu#element
	*/

	/**
	* @borrows ch.Object#type as ch.Menu#type
	*/

	/**
	* Triggers the innerShow method and returns the public scope to keep method chaining.
	* @public
	* @name ch.DatePicker#show
	* @function
	* @returns itself
	* @exampleDescription Following the first example, using widget as modal's instance controller:
	* @example
	* widget.show();
	*/
	that["public"].show = function () {
		that["float"].innerShow();

		return that["public"];
	};

	/**
	* Triggers the innerHide method and returns the public scope to keep method chaining.
	* @public
	* @name ch.DatePicker#show
	* @function
	* @returns itself
	* @exampleDescription Following the first example, using widget as modal's instance controller:
	* @example
	* widget.hide();
	*/
	that["public"].hide = function () {
		that["float"].innerHide();

		return that["public"];
	};

	/**
	* Select a specific date or returns the selected date.
	* @public
	* @since 0.9
	* @name ch.DatePicker#select
	* @function
	* @param {string} "YYYY/MM/DD".
	* @return itself
	*/
	that["public"].select = function (date) {
		// Select the day and update input value with selected date
		// Setter
		if (date) {
			that.calendar.select(date);
			that.element.value = that.calendar.select();

			return that["public"];
		}

		// Getter
		return that.calendar.select();
	};

	/**
	* Returns date of today
	* @public
	* @since 0.9
	* @name ch.DatePicker#today
	* @function
	* @return date
	*/
	that["public"].today = function () {
		return that.calendar.today();
	};

	/**
	* Move to the next month or year. If it isn't specified, it will be moved to next month.
	* @public
	* @function
	* @name ch.DatePicker#next
	* @param {String} time A string that allows specify if it should move to next month or year.
	* @return itself
	* @default Next month
	*/
	that["public"].next = function (time) {
		that.calendar.next(time);

		return that["public"];
	};

	/**
	* Move to the previous month or year. If it isn't specified, it will be moved to previous month.
	* @public
	* @function
	* @name ch.DatePicker#prev
	* @param {String} time A string that allows specify if it should move to previous month or year.
	* @return itself
	* @default Previous month
	*/
	that["public"].prev = function (time) {
		that.calendar.prev(time);

		return that["public"];
	};

	/**
	* Reset the Date Picker to date of today
	* @public
	* @name ch.DatePicker#reset
	* @function
	* @return itself
	*/
	that["public"].reset = function () {

		// Delete input value
		that.element.value = "";

		that.calendar.reset();

		return that["public"];
	};

	/**
	* Set a minimum selectable date.
	* @public
	* @name ch.DatePicker#from
	* @function
	* @param {string} "YYYY/MM/DD".
	* @return itself
	*/
	that["public"].from = function (date) {
		that.calendar.from(date);

		return that["public"];
	};

	/**
	* Set a maximum selectable date.
	* @public
	* @name ch.DatePicker#to
	* @function
	* @param {string} "YYYY/MM/DD".
	* @return itself
	*/
	that["public"].to = function (date) {
		that.calendar.to(date);

		return that["public"];
	};

/**
*	Default event delegation
*/

	// Change type of input to "text"
	that.element.type = "text";

	// Change value of input if there are a selected date
	that.element.value = (conf.selected) ? that.calendar.select() : that.element.value;

	// Add show behaivor to float's trigger.
	that["float"].$element
		.css("cursor", "pointer")
		.bind("click", function (event) { that["float"].innerShow(event); });

	/**
	* Triggers when the component is ready to use (Since 0.8.0).
	* @name ch.DatePicker#ready
	* @event
	* @public
	* @exampleDescription Following the first example, using widget as Date Picker's instance controller:
	* @example
	* widget.on("ready", function () {
	* 	this.show();
	* });
	*/
	setTimeout(function () { that.trigger("ready"); }, 50);

	return that;
};

ch.factory("datePicker");<commit_msg>Update the offset of Layer triggered by Date Picker<commit_after>/**
* Datepicker lets you select dates.
* @name DatePicker
* @class DatePicker
* @augments ch.Controls
* @requires ch.Calendar
* @see ch.Controls
* @see ch.Calendar
* @memberOf ch
* @param {Object} [conf] Object with configuration properties.
* @param {String} [conf.format] Sets the date format. By default is "DD/MM/YYYY".
* @param {String} [conf.selected] Sets a date that should be selected by default. By default is the date of today.
* @param {String} [conf.from] Set a maximum selectable date.
* @param {String} [conf.to] Set a minimum selectable date.
* @param {String} [conf.points] Points to be positioned. See Positioner component. By default is "ct cb".
* @param {Array} [conf.monthsNames] By default is ["Enero", ... , "Diciembre"].
* @param {Array} [conf.weekdays] By default is ["Dom", ... , "Sab"].
* @param {Boolean} [conf.closable] Defines if floated component will be closed when a date is selected or not. By default it's "true".
* @returns itself
* @factorized
* @exampleDescription Create a new datePicker.
* @example
* var widget = $(".example").datePicker();
* @exampleDescription Create a new Date Picker with configuration.
* @example
* var widget = $(".example").datePicker({
*	 "format": "MM/DD/YYYY",
*	 "selected": "2011/12/25",
*	 "from": "2010/12/25",
*	 "to": "2012/12/25",
*	 "monthsNames": ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
*	 "weekdays": ["Su", "Mo", "Tu", "We", "Thu", "Fr", "Sa"]
* });
*/

ch.datePicker = function (conf) {

	/**
	* Reference to a internal component instance, saves all the information and configuration properties.
	* @private
	* @name ch.DatePicker#that
	* @type object
	*/
	var that = this;

	conf = ch.clon(conf);

	// Configuration by default
	conf.format = conf.format || "DD/MM/YYYY";
	conf.points = conf.points || "ct cb";
	conf.closable = ch.utils.hasOwn(conf, "closable") ? conf.closable : true;

	that.conf = conf;

/**
*	Inheritance
*/

	that = ch.controls.call(that);
	that.parent = ch.clon(that);

/**
*	Private Members
*/

/**
*	Protected Members
*/

	/**
	* Pick a date in the Calendar and updates the input data.
	* @protected
	* @function
	* @name ch.DatePicker#process
	*/
	that.process = function (event) {

		// Day selection
		if (event.target.nodeName !== "TD" || event.target.className.indexOf("ch-disabled") !== -1 || event.target.className.indexOf("ch-calendar-other") !== -1) { return; }

		// Select the day and update input value with selected date
		that.element.value = that.calendar.selectDay(event.target.innerHTML);

		// Hide float
		if (conf.closable) { that["float"].innerHide(); }

		/**
		* Callback function
		* @public
		* @name ch.DatePicker#select
		* @event
		*/
		// Old callback system
		that.callbacks("onSelect");
		// New callback
		that.trigger("select");

	};

	/**
	* Reference to the Calendar component instance.
	* @protected
	* @type Object
	* @name ch.DatePicker#calendar
	*/
	that.calendar = $("
")
		// Add functionality for date selection
		.bind("click", function (event) { that.process(event); })
		// Instance Calendar component
		.calendar({
			"format": conf.format,
			"from": conf.from,
			"to": conf.to,
			"selected": conf.selected,
			"monthsNames": conf.monthsNames,
			"weekdays": conf.weekdays
		});

	/**
	* Reference to the Float component instanced.
	* @protected
	* @type Object
	* @name ch.DatePicker#float
	*/
	that["float"] = that.createFloat({
		"$element": $("

").insertAfter(that.element),
		"content": that.calendar.element,
		"points": conf.points,
		"offset": "0 5",
		"aria": {
			"role": "tooltip",
			"identifier": "aria-describedby"
		},
		"closeButton": false,
		"cone": true
	});

/**
*  Public Members
*/

	/**
	* @borrows ch.Object#uid as ch.Menu#uid
	*/

	/**
	* @borrows ch.Object#element as ch.Menu#element
	*/

	/**
	* @borrows ch.Object#type as ch.Menu#type
	*/

	/**
	* Triggers the innerShow method and returns the public scope to keep method chaining.
	* @public
	* @name ch.DatePicker#show
	* @function
	* @returns itself
	* @exampleDescription Following the first example, using widget as modal's instance controller:
	* @example
	* widget.show();
	*/
	that["public"].show = function () {
		that["float"].innerShow();

		return that["public"];
	};

	/**
	* Triggers the innerHide method and returns the public scope to keep method chaining.
	* @public
	* @name ch.DatePicker#show
	* @function
	* @returns itself
	* @exampleDescription Following the first example, using widget as modal's instance controller:
	* @example
	* widget.hide();
	*/
	that["public"].hide = function () {
		that["float"].innerHide();

		return that["public"];
	};

	/**
	* Select a specific date or returns the selected date.
	* @public
	* @since 0.9
	* @name ch.DatePicker#select
	* @function
	* @param {string} "YYYY/MM/DD".
	* @return itself
	*/
	that["public"].select = function (date) {
		// Select the day and update input value with selected date
		// Setter
		if (date) {
			that.calendar.select(date);
			that.element.value = that.calendar.select();

			return that["public"];
		}

		// Getter
		return that.calendar.select();
	};

	/**
	* Returns date of today
	* @public
	* @since 0.9
	* @name ch.DatePicker#today
	* @function
	* @return date
	*/
	that["public"].today = function () {
		return that.calendar.today();
	};

	/**
	* Move to the next month or year. If it isn't specified, it will be moved to next month.
	* @public
	* @function
	* @name ch.DatePicker#next
	* @param {String} time A string that allows specify if it should move to next month or year.
	* @return itself
	* @default Next month
	*/
	that["public"].next = function (time) {
		that.calendar.next(time);

		return that["public"];
	};

	/**
	* Move to the previous month or year. If it isn't specified, it will be moved to previous month.
	* @public
	* @function
	* @name ch.DatePicker#prev
	* @param {String} time A string that allows specify if it should move to previous month or year.
	* @return itself
	* @default Previous month
	*/
	that["public"].prev = function (time) {
		that.calendar.prev(time);

		return that["public"];
	};

	/**
	* Reset the Date Picker to date of today
	* @public
	* @name ch.DatePicker#reset
	* @function
	* @return itself
	*/
	that["public"].reset = function () {

		// Delete input value
		that.element.value = "";

		that.calendar.reset();

		return that["public"];
	};

	/**
	* Set a minimum selectable date.
	* @public
	* @name ch.DatePicker#from
	* @function
	* @param {string} "YYYY/MM/DD".
	* @return itself
	*/
	that["public"].from = function (date) {
		that.calendar.from(date);

		return that["public"];
	};

	/**
	* Set a maximum selectable date.
	* @public
	* @name ch.DatePicker#to
	* @function
	* @param {string} "YYYY/MM/DD".
	* @return itself
	*/
	that["public"].to = function (date) {
		that.calendar.to(date);

		return that["public"];
	};

/**
*	Default event delegation
*/

	// Change type of input to "text"
	that.element.type = "text";

	// Change value of input if there are a selected date
	that.element.value = (conf.selected) ? that.calendar.select() : that.element.value;

	// Add show behaivor to float's trigger.
	that["float"].$element
		.css("cursor", "pointer")
		.bind("click", function (event) { that["float"].innerShow(event); });

	/**
	* Triggers when the component is ready to use (Since 0.8.0).
	* @name ch.DatePicker#ready
	* @event
	* @public
	* @exampleDescription Following the first example, using widget as Date Picker's instance controller:
	* @example
	* widget.on("ready", function () {
	* 	this.show();
	* });
	*/
	setTimeout(function () { that.trigger("ready"); }, 50);

	return that;
};

ch.factory("datePicker");<|endoftext|>


<commit_before>import { Dispatcher } from 'flux';

const debug = require('debug')('uwave:dispatcher');

class UWaveDispatcher extends Dispatcher {
  dispatch(payload) {
    debug('dispatch', payload.action, payload);
    super.dispatch(payload);
  }
}

const dispatcher = new UWaveDispatcher();

export default dispatcher;
export const dispatch = ::dispatcher.dispatch;
<commit_msg>debug: add normal/error debug message styles to dispatcher<commit_after>import { Dispatcher } from 'flux';

const debugOk = require('debug')('uwave:dispatcher');
const debugError = require('debug')('uwave:dispatcher');
debugError.log = ::console.error;

class UWaveDispatcher extends Dispatcher {
  dispatch(action) {
    const { type, payload, error, meta } = action;
    const debug = error ? debugError : debugOk;
    debug(type, payload, meta || '');
    super.dispatch(action);
  }
}

const dispatcher = new UWaveDispatcher();

export default dispatcher;
export const dispatch = ::dispatcher.dispatch;
<|endoftext|>


<commit_before>var LocaleStore = require('../stores/LocaleStore');

var _ = require('underscore');
var strings = require('../intl/strings').strings;

var getDefaultLocale = LocaleStore.getDefaultLocale;

var fallbackMap = {
  'zh_TW': 'zh_CN'
};

// lets change underscores template settings so it interpolates
// things like "{branchName} does not exist".
var templateSettings = _.clone(_.templateSettings);
templateSettings.interpolate = /\{(.+?)\}/g;
var template = exports.template = function(str, params) {
  return _.template(str, params, templateSettings);
};

var str = exports.str = function(key, params) {
  params = params || {};
  // this function takes a key like "error-branch-delete"
  // and parameters like {branchName: 'bugFix', num: 3}.
  //
  // it sticks those into a translation string like:
  //   'en': 'You can not delete the branch {branchName} because' +
  //         'you are currently on that branch! This is error number + {num}'
  //
  // to produce:
  //
  // 'You can not delete the branch bugFix because you are currently on that branch!
  //  This is error number 3'

  var locale = LocaleStore.getLocale();
  if (!strings[key]) {
    console.warn('NO INTL support for key ' + key);
    return 'NO INTL support for key ' + key;
  }

  if (!strings[key][locale]) {
    // try falling back to another locale if in the map
    locale = fallbackMap[locale] || getDefaultLocale();
  }

  if (!strings[key][locale]) {
    if (key !== 'error-untranslated') {
      return str('error-untranslated');
    }
    return 'No translation for the key "' + key + '"';
  }

  return template(
    strings[key][locale],
    params
  );
};

var getIntlKey = exports.getIntlKey = function(obj, key) {
  if (!obj || !obj[key]) {
    throw new Error('that key ' + key + 'doesnt exist in this blob' + obj);
  }
  if (!obj[key][getDefaultLocale()]) {
    console.warn(
      'WARNING!! This blob does not have intl support:',
      obj,
      'for this key',
      key
    );
  }

  return obj[key][LocaleStore.getLocale()];
};

exports.todo = function(str) {
  return str;
};

exports.getDialog = function(obj) {
  return getIntlKey(obj, 'dialog') || obj.dialog[getDefaultLocale()];
};

exports.getHint = function(level) {
  return getIntlKey(level, 'hint') || str('error-untranslated');
};

exports.getName = function(level) {
  return getIntlKey(level, 'name') || str('error-untranslated');
};

exports.getStartDialog = function(level) {
  var startDialog = getIntlKey(level, 'startDialog');
  if (startDialog) { return startDialog; }

  // this level translation isnt supported yet, so lets add
  // an alert to the front and give the english version.
  var errorAlert = {
    type: 'ModalAlert',
    options: {
      markdown: str('error-untranslated')
    }
  };
  var startCopy = _.clone(
    level.startDialog[getDefaultLocale()] || level.startDialog
  );
  startCopy.childViews.unshift(errorAlert);

  return startCopy;
};
<commit_msg>PR #269 do better job of showing untranslated hints or level names<commit_after>var LocaleStore = require('../stores/LocaleStore');

var _ = require('underscore');
var strings = require('../intl/strings').strings;

var getDefaultLocale = LocaleStore.getDefaultLocale;

var fallbackMap = {
  'zh_TW': 'zh_CN'
};

// lets change underscores template settings so it interpolates
// things like "{branchName} does not exist".
var templateSettings = _.clone(_.templateSettings);
templateSettings.interpolate = /\{(.+?)\}/g;
var template = exports.template = function(str, params) {
  return _.template(str, params, templateSettings);
};

var str = exports.str = function(key, params) {
  params = params || {};
  // this function takes a key like "error-branch-delete"
  // and parameters like {branchName: 'bugFix', num: 3}.
  //
  // it sticks those into a translation string like:
  //   'en': 'You can not delete the branch {branchName} because' +
  //         'you are currently on that branch! This is error number + {num}'
  //
  // to produce:
  //
  // 'You can not delete the branch bugFix because you are currently on that branch!
  //  This is error number 3'

  var locale = LocaleStore.getLocale();
  if (!strings[key]) {
    console.warn('NO INTL support for key ' + key);
    return 'NO INTL support for key ' + key + '. this is probably a dev error';
  }

  if (!strings[key][locale]) {
    // try falling back to another locale if in the map
    locale = fallbackMap[locale] || getDefaultLocale();
  }

  if (!strings[key][locale]) {
    if (key !== 'error-untranslated') {
      return str('error-untranslated');
    }
    return 'No translation for the key "' + key + '"';
  }

  return template(
    strings[key][locale],
    params
  );
};

var getIntlKey = exports.getIntlKey = function(obj, key, overrideLocale) {
  if (!obj || !obj[key]) {
    throw new Error('that key ' + key + 'doesnt exist in this blob' + obj);
  }
  if (!obj[key][getDefaultLocale()]) {
    console.warn(
      'WARNING!! This blob does not have intl support:',
      obj,
      'for this key',
      key
    );
  }

  var locale = overrideLocale || LocaleStore.getLocale();
  return obj[key][locale];
};

exports.todo = function(str) {
  return str;
};

exports.getDialog = function(obj) {
  return getIntlKey(obj, 'dialog') || obj.dialog[getDefaultLocale()];
};

exports.getHint = function(level) {
  if (!getIntlKey(level, 'hint')) {
    return getIntlKey(level, 'hint', getDefaultLocale()) + ' -- ' + str('error-untranslated');
  }
  return getIntlKey(level, 'hint');
};

exports.getName = function(level) {
  if (!getIntlKey(level, 'name')) {
    return getIntlKey(level, 'name', getDefaultLocale()) + ' -- ' + str('error-untranslated');
  }
  return getIntlKey(level, 'name');
};

exports.getStartDialog = function(level) {
  var startDialog = getIntlKey(level, 'startDialog');
  if (startDialog) { return startDialog; }

  // this level translation isnt supported yet, so lets add
  // an alert to the front and give the english version.
  var errorAlert = {
    type: 'ModalAlert',
    options: {
      markdown: str('error-untranslated')
    }
  };
  var startCopy = _.clone(
    level.startDialog[getDefaultLocale()] || level.startDialog
  );
  startCopy.childViews.unshift(errorAlert);

  return startCopy;
};
<|endoftext|>


<commit_before>'use strict';

/* global defaults */

/**
 * @exports localfile
 */
const localfile = {
  async init () {
    const body = document.querySelector('body');
    const { local_file }  = await browser.storage.local.get({ local_file : defaults.local_file });

    // The file has been uploaded by the user. Therefore, the user wants the content, regardless of possible problems
    // eslint-disable-next-line no-unsanitized/method
    body.insertAdjacentHTML('beforeend', local_file);
  }
};

localfile.init();
<commit_msg>fixed ESLint issue<commit_after>'use strict';

/* global defaults */

/**
 * @exports localfile
 */
const localfile = {
  async init () {
    const body = document.querySelector('body');
    const { local_file } = await browser.storage.local.get({ local_file : defaults.local_file });

    // The file has been uploaded by the user. Therefore, the user wants the content, regardless of possible problems
    // eslint-disable-next-line no-unsanitized/method
    body.insertAdjacentHTML('beforeend', local_file);
  }
};

localfile.init();
<|endoftext|>


<commit_before>// @flow weak

import TrendsAPI from '../api/TrendsAPI';
import type { Term, Geo, Filter, TrendsAPITopTopics } from '../util/types';
import terms from '../data/terms';
import countries from '../data/countries';
import icons from '../util/icons';
import { map, pickRandomIndex } from '../util/util';
import homeIconsList from '../data/homeIconsList';
import * as d3 from 'd3';
import $ from 'jquery';
import log from 'loglevel';
import '../../sass/home.scss';

export default class Home {

  data: {
    geo: Geo,
    disease: Term,
    topTopics: TrendsAPITopTopics[],
  }
  trendsAPI: TrendsAPI;
  countryContainer: HTMLElement;
  topTopicsList: HTMLElement;
  homeLoop: number;

  constructor(parentContainer: HTMLElement, trendsAPI: TrendsAPI) {
    const self = this;
    self.homeLoop = 0;
    self.data ={
      geo: { iso: '', name: ''},
      disease: { name: '', entity: ''},
      topTopics: [],
    }
    self.trendsAPI = trendsAPI;``
    const disease = self.getRandomDisease();
    const country = self.getUserCountry(function(geo) {
      self.updateData({ disease, geo });
      self.getTrendsAPITopTopics();
    });
    this.createElements(parentContainer);
  }

  getRandomDisease(ignore?: string) {
    let topTerms = ['Acne', 'Allergy', 'Infection', 'Headache', 'Fever', 'Influenza'];
    if (ignore) {
      topTerms = topTerms.filter(t => t !== ignore);
    }
    const i = Math.floor(Math.random() * topTerms.length);
    const disease = terms.find(t => t.name === topTerms[i]);
    return disease;
  }

  countryToGeo(country: string):Geo {
    return countries.find(c => c.iso === country);
  }

  getPrevMonth() {
    const prevMonthDate = new Date();
    prevMonthDate.setMonth(prevMonthDate.getMonth() - 1);
    const year = prevMonthDate.getFullYear();
    let month = (new Date()).getMonth();
    month = month < 10 ? `0${month}` : month;
    return `${year}-${month}`;
  }

  getUserCountry(callback) {
    log.info('getUserCountry');
    const self = this;
    $.get("https://ipinfo.io", function(response) {
      if (response) {
        const { country } = response;
        const geo = self.countryToGeo(country);
        callback(geo);
      }
    }, 'jsonp')
    .fail(function() {
      callback('US');
    });
  }

  getTrendsAPITopTopics(){
    log.info('getTrendsAPITopTopics');
    const { geo, disease } = this.data;
    const self = this;
    const filter = {
      terms: [disease],
      geo,
      startDate: self.getPrevMonth(),
    };
    self.trendsAPI.getTopTopics(filter, function(val){
      log.info('From Google Trends: ', val);
      const { item } = val;
      if (item && item.length > 0) {
        self.updateData({ topTopics: item });
      } else if (geo && geo.iso !== 'US') {
        const defaultGeo = self.countryToGeo('US');
        self.updateData({ geo: defaultGeo });
        self.getTrendsAPITopTopics();
      } else if (disease) {
        self.updateData({ disease: self.getRandomDisease(disease.name) });
        self.getTrendsAPITopTopics();
      }
    });
  }

  createBgIcons(self: Home) {
    const { disease, topTopics } = self.data;
    const { topTopicsList, homeLoop } = self;
    const diseaseIconsList = homeIconsList[disease.name];
    const width = window.innerWidth;
    const height = window.innerHeight;
    const spacing = width < 600 ? 70 : 140;
    let i = 0;
    let line = 0;
    if (topTopics.length > 0) {
      topTopicsList.innerHTML = '';
      for (let y=0; y < height; y += spacing) {
        for (let x = (line % 2 === 0) ? 0 : -spacing/2 ; x < width; x += spacing) {
          const iconContainer = document.createElement('div');
          const n = i % diseaseIconsList.length;
          const iconName = diseaseIconsList[n];
          const distToCenter = Math.abs(height/2 - y);
          const opacity = map(distToCenter, 0, height/2, 0.24, 0.8);
          iconContainer.classList.add('icon');
          iconContainer.innerHTML = icons[iconName];
          iconContainer.style.top = `${y}px`;
          iconContainer.style.left = `${x}px`;
          iconContainer.style.opacity = opacity;
          topTopicsList.appendChild(iconContainer);

          const p = document.createElement('p');
          const randomTopic = topTopics[Math.floor(Math.random()*topTopics.length)];
          p.innerHTML = randomTopic.title;
          iconContainer.appendChild(p);

          i++;
        }
        line++;
      }
      clearInterval(self.homeLoop);
      self.homeLoop = 0;
      self.homeLoop = setInterval(this.showRandomTopic, 1500);
    }
  }

  showRandomTopic() {
    const iconContainers = document.querySelectorAll('#home.page .top-topics-list .icon');
    if(iconContainers.length > 0) {
      const i = Math.floor(Math.random()*iconContainers.length);
      const randomIcon = iconContainers[pickRandomIndex(iconContainers.length)];
      let svg, p;
      svg = randomIcon.querySelector('svg');
      p = randomIcon.querySelector('p');
      if (svg && p) {
        svg.classList.add('flipped');
        p.classList.add('flipped');

        setTimeout(function() {
          svg.classList.remove('flipped');
          p.classList.remove('flipped');
        }, 4000);
      }
    }
  }

  checkScroll(scrollY: number, self: Home) {
    const mainContainer= document.querySelector('.main-container');
    if (mainContainer) {
      const mainContainerTop = mainContainer.offsetTop;
      if (scrollY > mainContainerTop) {
        clearInterval(self.homeLoop);
        self.homeLoop = 0;
      }
    }
  }

  updateData(obj) {
    const { data } = this;
    Object.assign(data, obj);
    log.info(this.data);
    this.updateElements();
  }

  createElements(parentContainer: HTMLElement) {

    const elementsContainer = document.createElement('div');
    elementsContainer.id = 'home';
    elementsContainer.classList.add('page');
    elementsContainer.style.height = `${window.innerHeight*1.5}px`;
    parentContainer.appendChild(elementsContainer);

    const titleContainer = document.createElement('div');
    titleContainer.classList.add('title-container');
    elementsContainer.appendChild(titleContainer);

    const title = document.createElement('h1');
    title.innerHTML = 'I\'m not
feeling well';
    titleContainer.appendChild(title);
    setTimeout(function() {
      titleContainer.classList.add('enter');
    }, 1000);

    const projectDescription = document.createElement('p');
    projectDescription.classList.add('project-description', 'container');
    projectDescription.innerHTML = 'To everything there is a season, and diseases are no different. Google search patterns show us what health issues people worry about, when they worry about them, and how epidemics spread through the world.';
    titleContainer.appendChild(projectDescription);

    const logosContainer = document.createElement('div');
    logosContainer.classList.add('logos-container');
    titleContainer.appendChild(logosContainer);

    const gabriel = document.createElement('p');
    gabriel.classList.add('gabriel');
    gabriel.innerHTML = 'Gabriel Gianordoli';
    logosContainer.appendChild(gabriel);

    const forSpan = document.createElement('span');
    forSpan.innerHTML = 'for';
    logosContainer.appendChild(forSpan);

    const gnl = document.createElement('div');
    gnl.classList.add('google-news-lab-logo');
    gnl.innerHTML = icons.googleNewsLabLogo;
    logosContainer.appendChild(gnl);

    this.countryContainer = document.createElement('div');
    this.countryContainer.classList.add('country-container');
    elementsContainer.appendChild(this.countryContainer);

    this.topTopicsList = document.createElement('div');
    this.topTopicsList.classList.add('top-topics-list');
    elementsContainer.appendChild(this.topTopicsList);
  }

  updateElements() {
    const { geo, disease, topTopics } = this.data;
    const { countryContainer, topTopicsList, homeLoop } = this;
    if (topTopics.length > 0) {

      let span = document.createElement('span');
      span.innerHTML = 'Searches for ';
      countryContainer.append(span);

      const diseaseContainer = document.createElement('span');
      diseaseContainer.classList.add('disease-container');
      diseaseContainer.innerHTML = disease.name.toLowerCase();
      countryContainer.appendChild(diseaseContainer);

      countryContainer.appendChild(document.createElement('br'));

      span = document.createElement('span');
      span.innerHTML = 'in ';
      countryContainer.appendChild(span);

      const country = document.createElement('span');
      country.classList.add('country');
      country.innerHTML = geo.name;
      countryContainer.appendChild(country);

      this.createBgIcons(this);
    }
  }
}
<commit_msg>Home fixes<commit_after>// @flow weak

import TrendsAPI from '../api/TrendsAPI';
import type { Term, Geo, Filter, TrendsAPITopTopics } from '../util/types';
import terms from '../data/terms';
import countries from '../data/countries';
import icons from '../util/icons';
import { map, pickRandomIndex } from '../util/util';
import homeIconsList from '../data/homeIconsList';
import * as d3 from 'd3';
import $ from 'jquery';
import log from 'loglevel';
import '../../sass/home.scss';

export default class Home {

  data: {
    geo: Geo,
    disease: Term,
    topTopics: TrendsAPITopTopics[],
  }
  trendsAPI: TrendsAPI;
  countryContainer: HTMLElement;
  topTopicsList: HTMLElement;
  homeLoop: number;

  constructor(parentContainer: HTMLElement, trendsAPI: TrendsAPI) {
    const self = this;
    self.homeLoop = 0;
    self.data ={
      geo: { iso: '', name: ''},
      disease: { name: '', entity: ''},
      topTopics: [],
    }
    self.trendsAPI = trendsAPI;``
    const disease = self.getRandomDisease();
    const country = self.getUserCountry(function(geo) {
      self.updateData({ disease, geo });
      self.getTrendsAPITopTopics();
    });
    this.createElements(parentContainer);
  }

  getRandomDisease(ignore?: string) {
    let topTerms = ['Acne', 'Allergy', 'Infection', 'Headache', 'Fever', 'Influenza'];
    if (ignore) {
      topTerms = topTerms.filter(t => t !== ignore);
    }
    const i = Math.floor(Math.random() * topTerms.length);
    const disease = terms.find(t => t.name === topTerms[i]);
    return disease;
  }

  countryToGeo(country: string):Geo {
    return countries.find(c => c.iso === country);
  }

  getPrevMonth() {
    const prevMonthDate = new Date();
    prevMonthDate.setMonth(prevMonthDate.getMonth() - 1);
    const year = prevMonthDate.getFullYear();
    let month = (new Date()).getMonth();
    month = month < 10 ? `0${month}` : month;
    return `${year}-${month}`;
  }

  getUserCountry(callback) {
    log.info('getUserCountry');
    const self = this;
    $.get("https://ipinfo.io", function(response) {
      if (response) {
        const { country } = response;
        const geo = self.countryToGeo(country);
        callback(geo);
      }
    }, 'jsonp')
    .fail(function() {
      callback('US');
    });
  }

  getTrendsAPITopTopics(){
    log.info('getTrendsAPITopTopics');
    const { geo, disease } = this.data;
    const self = this;
    const filter = {
      terms: [disease],
      geo,
      startDate: self.getPrevMonth(),
    };
    self.trendsAPI.getTopTopics(filter, function(val){
      log.info('From Google Trends: ', val);
      const { item } = val;
      if (item && item.length > 0) {
        self.updateData({ topTopics: item });
      } else if (geo && geo.iso !== 'US') {
        const defaultGeo = self.countryToGeo('US');
        self.updateData({ geo: defaultGeo });
        self.getTrendsAPITopTopics();
      } else if (disease) {
        self.updateData({ disease: self.getRandomDisease(disease.name) });
        self.getTrendsAPITopTopics();
      }
    });
  }

  createBgIcons(self: Home) {
    const { disease, topTopics } = self.data;
    const { topTopicsList, homeLoop } = self;
    const diseaseIconsList = homeIconsList[disease.name];
    const width = window.innerWidth;
    const height = window.innerHeight;
    const spacing = width < 600 ? 70 : 140;
    let i = 0;
    let line = 0;
    if (topTopics.length > 0) {
      topTopicsList.innerHTML = '';
      for (let y=0; y < height; y += spacing) {
        for (let x = (line % 2 === 0) ? 0 : -spacing/2 ; x < width; x += spacing) {
          const iconContainer = document.createElement('div');
          const n = i % diseaseIconsList.length;
          const iconName = diseaseIconsList[n];
          const distToCenter = Math.abs(height/2 - y);
          const opacity = map(distToCenter, 0, height/2, 0.24, 0.8);
          iconContainer.classList.add('icon');
          iconContainer.innerHTML = icons[iconName];
          iconContainer.style.top = `${y}px`;
          iconContainer.style.left = `${x}px`;
          iconContainer.style.opacity = opacity;
          topTopicsList.appendChild(iconContainer);

          const p = document.createElement('p');
          const randomTopic = topTopics[Math.floor(Math.random()*topTopics.length)];
          p.innerHTML = randomTopic.title;
          iconContainer.appendChild(p);

          i++;
        }
        line++;
      }
      clearInterval(self.homeLoop);
      self.homeLoop = 0;
      self.homeLoop = setInterval(this.showRandomTopic, 1500);
    }
  }

  showRandomTopic() {
    const iconContainers = document.querySelectorAll('#home.page .top-topics-list .icon');
    if(iconContainers.length > 0) {
      const i = Math.floor(Math.random()*iconContainers.length);
      const randomIcon = iconContainers[pickRandomIndex(iconContainers.length)];
      let svg, p;
      svg = randomIcon.querySelector('svg');
      p = randomIcon.querySelector('p');
      if (svg && p) {
        svg.classList.add('flipped');
        p.classList.add('flipped');

        setTimeout(function() {
          svg.classList.remove('flipped');
          p.classList.remove('flipped');
        }, 4000);
      }
    }
  }

  checkScroll(scrollY: number, self: Home) {
    const mainContainer= document.querySelector('.main-container');
    if (mainContainer) {
      const mainContainerTop = mainContainer.offsetTop;
      if (scrollY > mainContainerTop) {
        clearInterval(self.homeLoop);
        self.homeLoop = 0;
      }
    }
  }

  updateData(obj) {
    const { data } = this;
    Object.assign(data, obj);
    log.info(this.data);
    this.updateElements();
  }

  createElements(parentContainer: HTMLElement) {

    const elementsContainer = document.createElement('div');
    elementsContainer.id = 'home';
    elementsContainer.classList.add('page');
    elementsContainer.style.height = `${window.innerHeight*1.5}px`;
    parentContainer.appendChild(elementsContainer);

    const titleContainer = document.createElement('div');
    titleContainer.classList.add('title-container');
    elementsContainer.appendChild(titleContainer);

    const title = document.createElement('h1');
    title.innerHTML = 'I\'m not
feeling well';
    titleContainer.appendChild(title);
    setTimeout(function() {
      titleContainer.classList.add('enter');
    }, 500);

    const projectDescription = document.createElement('p');
    projectDescription.classList.add('project-description', 'container');
    projectDescription.innerHTML = 'To everything there is a season, and diseases are no different. Google search patterns show us what health issues people worry about, when they worry about them, and how epidemics spread through the world.';
    titleContainer.appendChild(projectDescription);

    const logosContainer = document.createElement('div');
    logosContainer.classList.add('logos-container');
    titleContainer.appendChild(logosContainer);

    const gabriel = document.createElement('p');
    gabriel.classList.add('gabriel');
    gabriel.innerHTML = 'Gabriel Gianordoli';
    logosContainer.appendChild(gabriel);

    const forSpan = document.createElement('span');
    forSpan.innerHTML = 'for';
    logosContainer.appendChild(forSpan);

    const gnl = document.createElement('div');
    gnl.classList.add('google-news-lab-logo');
    gnl.innerHTML = icons.googleNewsLabLogo;
    logosContainer.appendChild(gnl);

    this.countryContainer = document.createElement('div');
    this.countryContainer.classList.add('country-container');
    elementsContainer.appendChild(this.countryContainer);

    this.topTopicsList = document.createElement('div');
    this.topTopicsList.classList.add('top-topics-list');
    elementsContainer.appendChild(this.topTopicsList);
  }

  updateElements() {
    const { geo, disease, topTopics } = this.data;
    const { countryContainer, topTopicsList, homeLoop } = this;
    if (topTopics.length > 0) {

      let span = document.createElement('span');
      span.innerHTML = 'Searches for ';
      countryContainer.append(span);

      const diseaseContainer = document.createElement('span');
      diseaseContainer.classList.add('disease-container');
      diseaseContainer.innerHTML = disease.name.toLowerCase();
      countryContainer.appendChild(diseaseContainer);

      countryContainer.appendChild(document.createElement('br'));

      span = document.createElement('span');
      span.innerHTML = 'in ';
      countryContainer.appendChild(span);

      const country = document.createElement('span');
      country.classList.add('country');
      country.innerHTML = geo.name;
      countryContainer.appendChild(country);

      this.createBgIcons(this);
    }
  }
}
<|endoftext|>


<commit_before>// Load wetfish basic
var $ = require('wetfish-basic');

// Load other stuff
var extend = require('extend');

var TextMagick = function(text, options)
{
    var defaults =
    {
        size: 50,
        color: '#fff',
        border:
        {
            enabled: true,
            size: 8,
            color: '#000'
        }
    };

    this.text = text || this.text;
    this.options = extend(true, defaults, options);
    this.init();

    return this;
}

TextMagick.prototype.text = 'sample text';
TextMagick.prototype.element = {};

TextMagick.prototype.init = function()
{
    this.element.wrapper = $('.preload .textmagick').clone();

    this.element.svg = $(this.element.wrapper).find('svg').el[0];
    this.element.text = $(this.element.wrapper).find('text.text').el[0];
    this.element.stroke = $(this.element.wrapper).find('text.stroke').el[0];

    this.setText();
    this.refresh();

    return this.element.svg;
}

TextMagick.prototype.setText = function(text)
{
    text = text || this.text;

    this.element.text.innerHTML = text.replace(/</g, '<');
    this.element.stroke.innerHTML = text.replace(/</g, '<');
}

TextMagick.prototype.setOptions = function(options)
{
    // Combine currently used options with new options
    this.options = extend(true, this.options, options);
    this.refresh();
}

TextMagick.prototype.refresh = function()
{
    this.element.text.setAttribute('font-size', this.options.size);
    this.element.stroke.setAttribute('font-size', this.options.size);

    this.element.text.setAttribute('fill', this.options.color);

    this.element.stroke.setAttribute('stroke', this.options.border.color);
    this.element.stroke.setAttribute('stroke-width', this.options.border.size);
}

TextMagick.prototype.resize = function()
{
    var size = this.element.stroke.getBBox();

    // Add the stroke size if stroke is enabled
    if(this.options.border.enabled)
    {
        size.height += this.options.border.size;
        size.width += this.options.border.size;
    }

    this.element.svg.setAttribute('width', size.width);
    this.element.svg.setAttribute('height', size.height);
}

TextMagick.prototype.getElement = function()
{
    return this.element.wrapper;
}

module.exports = TextMagick;

<commit_msg>Fixed explosions when text has a border<commit_after>// Load wetfish basic
var $ = require('wetfish-basic');

// Load other stuff
var extend = require('extend');

var TextMagick = function(text, options)
{
    var defaults =
    {
        size: 50,
        color: '#fff',
        border:
        {
            enabled: true,
            size: 8,
            color: '#000'
        }
    };

    this.text = text || this.text;
    this.options = extend(true, defaults, options);
    this.init();

    return this;
}

TextMagick.prototype.text = 'sample text';
TextMagick.prototype.element = {};

TextMagick.prototype.init = function()
{
    this.element.wrapper = $('.preload .textmagick').clone();

    this.element.svg = $(this.element.wrapper).find('svg').el[0];
    this.element.text = $(this.element.wrapper).find('text.text').el[0];
    this.element.stroke = $(this.element.wrapper).find('text.stroke').el[0];

    this.setText();
    this.refresh();

    return this.element.svg;
}

TextMagick.prototype.setText = function(text)
{
    text = text || this.text;

    this.element.text.innerHTML = text.replace(/</g, '<');
    this.element.stroke.innerHTML = text.replace(/</g, '<');
}

TextMagick.prototype.setOptions = function(options)
{
    // Combine currently used options with new options
    this.options = extend(true, this.options, options);
    this.refresh();
}

TextMagick.prototype.refresh = function()
{
    this.element.text.setAttribute('font-size', this.options.size);
    this.element.stroke.setAttribute('font-size', this.options.size);

    this.element.text.setAttribute('fill', this.options.color);

    this.element.stroke.setAttribute('stroke', this.options.border.color);
    this.element.stroke.setAttribute('stroke-width', this.options.border.size);
}

TextMagick.prototype.resize = function()
{
    var size = this.element.stroke.getBBox();

    // Add the stroke size if stroke is enabled
    if(this.options.border.enabled)
    {
        size.height += parseInt(this.options.border.size);
        size.width += parseInt(this.options.border.size);
    }

    this.element.svg.setAttribute('width', size.width);
    this.element.svg.setAttribute('height', size.height);
}

TextMagick.prototype.getElement = function()
{
    return this.element.wrapper;
}

module.exports = TextMagick;

<|endoftext|>


<commit_before>var $ = require('wetfish-basic');
var storage = require('../app/storage');
var helper = require('../app/helper');

var animate =
{
    active: false,
    element: false,
    object: false,
    frame: 0,
    frames: [],
    animation: false,
    duration: 1000,
    iterations: Infinity,
    playing: false,

    init: function()
    {
        // Save the default element notification text
        animate.defaultText = $('.menu .animate .element').el[0].textContent;

        $('body').on('click', '.workspace .content, .workspace .content *', function()
        {
            var element = this;

            // If we clicked on a child element
            if(!$(element).hasClass('content'))
            {
                // Find the parent content element
                element = $(this).parents('.content').el[0];
            }

            if(animate.active)
            {
                animate.element = element;
                animate.populate();
                animate.menu();
            }
        });

        $('.animate .new').on('click', function()
        {
             var name = prompt("Please enter a memorable name for this animation.");

             if(animate.object.animation !== undefined && animate.object.animation[name] !== undefined)
             {
                var replace = confirm("An animation named '" + name + "' already exists. Are you sure you want to overwrite it?");

                if(!replace)
                {
                    return;
                }
             }

            animate.name = name;
            animate.frame = 0;
            animate.frames = [];

            animate.populate();
            animate.persist();
        });

        $('.animate .animations select').on('change', function(event)
        {
            var animation = $(this).value();

            // Only trigger when an actual animation is selected
            if(animation)
            {
                animate.name = animation;
                animate.frame = 0;
                animate.frames = animate.object.animation[animate.name].frames;

                $('.animation-selected').removeClass('hidden');

                $('#frame').value(0);
                $('#frame').attr('max', animate.frames.length - 1);

                if(animate.object.animation[animate.name].iterations == 'Infinity')
                {
                    $('.animate .loop').prop('checked', true);
                }
                else
                {
                    $('.animate .loop').prop('checked', false);
                }

                $('#duration').value(animate.object.animation[animate.name].duration).trigger('change');

                if(animate.object.animations.indexOf(animation) > -1)
                {
                    $('.animate .enabled').prop('checked', true).trigger('change');
                }
                else
                {
                    $('.animate .enabled').prop('checked', false).trigger('change');
                }

                animate.update();
            }
            else
            {
                $('.animation-selected').addClass('hidden');
                helper.hover.enabled = false;
            }
        });

        $('.animate .new-frame').on('click', function()
        {
            // Add a new frame after the current position
            animate.frames.splice(animate.frame + 1, 0, {});
            animate.frame++;

            $('#frame').attr('max', animate.frames.length - 1);
            $('#frame').value(animate.frame);

            animate.persist();
        });

        $('#duration').on('input change', function()
        {
            animate.duration = parseInt($(this).value());
            animate.persist();
            animate.refresh();
        });

        $('#frame').on('input change', function()
        {
            // If the frame has changed and there is more than one frame
            if(animate.frame != $(this).value())
            {

                // Set the current time of the animation to match the value of the slider
                animate.frame = parseInt($(this).value());
                animate.update();
            }
        });

        // Delete an entire animation
        $('.animate .delete').on('click', function()
        {
            storage.animation.delete(animate.element, animate.name);
            animate.populate();
        });

        $('.animate .enabled').on('click change', function()
        {
            if(this.checked)
            {
                animate.play();
            }
            else
            {
                animate.pause();
            }

            animate.persist();
        });

        $('.animate .loop').on('click change', function()
        {
            if(this.checked)
            {
                animate.iterations = Infinity;
            }
            else
            {
                animate.iterations = 1;
            }

            animate.persist();
            animate.refresh();
        });

        $('.workspace').on('content-updated', function(event)
        {
            var updatedElement = event.detail;

            if(animate.element == updatedElement)
            {
                animate.persist();
            }
        });
    },

    // Populate data from saved object
    populate: function()
    {
        var id = $(animate.element).attr('id');
        var object = storage.getObject(id);

        animate.object = object;

        var  desc = object.desc || 'untitled ' + object.type;
        $('.menu .animate .element').text(desc);

        if(object.animation !== undefined && Object.keys(object.animation).length)
        {
            // Remove any previously created animations
            $('.animate .animations .custom').remove();
            $('.animate .animations').removeClass('hidden');
            $('.animate select option').eq(0).prop('selected', true);

            // Loop through saved animatinos and populate the dropdown
            Object.keys(object.animation).forEach(function(name)
            {
                var option = document.createElement('option');
                $(option).addClass('custom');
                $(option).text(name);
                $('.animate .animations select').append(option).trigger('change');
            });
        }
        else
        {
            $('.animate .animations').addClass('hidden');
        }
    },

    // Save current transform data
    persist: function()
    {
        // If the animation is not currently playing
        if(!animate.animation || (animate.animation && animate.animation.playState != 'running'))
        {
            // Get the current computed transform style
            var transform = $(animate.element).style('transform');

            // Update the saved animation object
            animate.frames[animate.frame] = JSON.parse(JSON.stringify({'computed': transform, 'basic': animate.element.transform}));
            animate.object.animation[animate.name] = animate.frames;
        }

        // Build object of data to be saved
        var data =
        {
            duration: animate.duration,
            iterations: animate.iterations,
            frames: animate.frames,
            playing: animate.playing
        };

        if(animate.iterations === Infinity)
        {
            data.iterations = 'Infinity';
        }

        storage.animation.save(animate.element, animate.name, data);
    },

    // Update animation element with the values of the current frame
    update: function()
    {
        var frame = animate.frames[animate.frame];
        $(animate.element).transform(frame.basic);
    },

    play: function()
    {
        try
        {
            var frames = [];

            animate.frames.forEach(function(frame)
            {
                frames.push(frame.computed);
            });

            if(animate.animation)
            {
                animate.animation.cancel();
            }

            animate.animation = animate.element.animate({'transform': frames}, {'duration': animate.duration, 'iterations': animate.iterations, 'fill': 'forwards'});

            var durationPerFrame = animate.duration / (animate.frames.length - 1);
            var currentTime = durationPerFrame * animate.frame;

            if(currentTime > 1)
            {
                currentTime--;
            }

            animate.animation.currentTime = currentTime;
            helper.hover.enabled = false;
            animate.playing = true;
        }
        catch(exception)
        {
            console.log(exception);

            animate.animation = false;
            helper.hover.enabled = true;
            animate.playing = false;
        }
    },

    // Refresh animation if currently playing
    refresh: function()
    {
        if(animate.animation && animate.animation.playState == 'running')
        {
            animate.play();
        }
    },

    pause: function()
    {
        if(animate.animation)
        {
            animate.animation.cancel();
            helper.hover.enabled = true;
            animate.playing = false;
        }
    },

    // Display menu options based on the current animation state
    menu: function()
    {
        if(animate.element)
        {
            $('.element-selected').removeClass('hidden');
        }
        else
        {
            $('.element-selected').addClass('hidden');
        }
    },

    start: function()
    {
        $('.workspace').addClass('highlight-content');
        animate.active = true;
        helper.storage.update = false;
    },

    stop: function()
    {
        $('.workspace').removeClass('highlight-content');
        $('.element-selected').addClass('hidden');
        $('.animation-selected').addClass('hidden');

        animate.pause();
        animate.active = false;
        animate.element = false;
        animate.object = false;
        helper.storage.update = true;

        $('.menu .animate .element').text(animate.defaultText);
    }
};

module.exports = animate;
<commit_msg>Automatically switch to new animation after creating<commit_after>var $ = require('wetfish-basic');
var storage = require('../app/storage');
var helper = require('../app/helper');

var animate =
{
    active: false,
    element: false,
    object: false,
    frame: 0,
    frames: [],
    animation: false,
    duration: 1000,
    iterations: Infinity,
    playing: false,

    init: function()
    {
        // Save the default element notification text
        animate.defaultText = $('.menu .animate .element').el[0].textContent;

        $('body').on('click', '.workspace .content, .workspace .content *', function()
        {
            var element = this;

            // If we clicked on a child element
            if(!$(element).hasClass('content'))
            {
                // Find the parent content element
                element = $(this).parents('.content').el[0];
            }

            if(animate.active)
            {
                animate.element = element;
                animate.populate();
                animate.menu();
            }
        });

        $('.animate .new').on('click', function()
        {
             var name = prompt("Please enter a memorable name for this animation.");

             if(animate.object.animation !== undefined && animate.object.animation[name] !== undefined)
             {
                var replace = confirm("An animation named '" + name + "' already exists. Are you sure you want to overwrite it?");

                if(!replace)
                {
                    return;
                }
            }
            else
            {
                animate.object.animation = {};
            }

            animate.name = name;
            animate.frame = 0;
            animate.frames = [];

            animate.persist();
            animate.populate();
        });

        $('.animate .animations select').on('change', function(event)
        {
            var animation = $(this).value();

            // Only trigger when an actual animation is selected
            if(animation)
            {
                animate.name = animation;
                animate.frame = 0;
                animate.frames = animate.object.animation[animate.name].frames;

                $('.animation-selected').removeClass('hidden');

                $('#frame').value(0);
                $('#frame').attr('max', animate.frames.length - 1);

                if(animate.object.animation[animate.name].iterations == 'Infinity')
                {
                    $('.animate .loop').prop('checked', true);
                }
                else
                {
                    $('.animate .loop').prop('checked', false);
                }

                $('#duration').value(animate.object.animation[animate.name].duration).trigger('change');

                if(animate.object.animations.indexOf(animation) > -1)
                {
                    $('.animate .enabled').prop('checked', true).trigger('change');
                }
                else
                {
                    $('.animate .enabled').prop('checked', false).trigger('change');
                }

                animate.update();
            }
            else
            {
                $('.animation-selected').addClass('hidden');
                helper.hover.enabled = false;
            }
        });

        $('.animate .new-frame').on('click', function()
        {
            // Add a new frame after the current position
            animate.frames.splice(animate.frame + 1, 0, {});
            animate.frame++;

            $('#frame').attr('max', animate.frames.length - 1);
            $('#frame').value(animate.frame);

            animate.persist();
        });

        $('#duration').on('input change', function()
        {
            animate.duration = parseInt($(this).value());
            animate.persist();
            animate.refresh();
        });

        $('#frame').on('input change', function()
        {
            // If the frame has changed and there is more than one frame
            if(animate.frame != $(this).value())
            {

                // Set the current time of the animation to match the value of the slider
                animate.frame = parseInt($(this).value());
                animate.update();
            }
        });

        // Delete an entire animation
        $('.animate .delete').on('click', function()
        {
            storage.animation.delete(animate.element, animate.name);
            animate.populate();
        });

        $('.animate .enabled').on('click change', function()
        {
            if(this.checked)
            {
                animate.play();
            }
            else
            {
                animate.pause();
            }

            animate.persist();
        });

        $('.animate .loop').on('click change', function()
        {
            if(this.checked)
            {
                animate.iterations = Infinity;
            }
            else
            {
                animate.iterations = 1;
            }

            animate.persist();
            animate.refresh();
        });

        $('.workspace').on('content-updated', function(event)
        {
            var updatedElement = event.detail;

            if(animate.element == updatedElement)
            {
                animate.persist();
            }
        });
    },

    // Populate data from saved object
    populate: function()
    {
        var id = $(animate.element).attr('id');
        var object = storage.getObject(id);

        animate.object = object;

        var  desc = object.desc || 'untitled ' + object.type;
        $('.menu .animate .element').text(desc);

        if(object.animation !== undefined && Object.keys(object.animation).length)
        {
            // Remove any previously created animations
            $('.animate .animations .custom').remove();
            $('.animate .animations').removeClass('hidden');
            $('.animate select option').eq(0).prop('selected', true);

            // Loop through saved animatinos and populate the dropdown
            Object.keys(object.animation).forEach(function(name)
            {
                var option = document.createElement('option');
                $(option).addClass('custom');
                $(option).text(name);
                $('.animate select').append(option);

                // Make sure the current option is selected
                if(name == animate.name)
                {
                    $('.animate select').value(name).trigger('change');
                }
            });
        }
        else
        {
            $('.animate .animations').addClass('hidden');
        }
    },

    // Save current transform data
    persist: function()
    {
        // If the animation is not currently playing
        if(!animate.animation || (animate.animation && animate.animation.playState != 'running'))
        {
            // Get the current computed transform style
            var transform = $(animate.element).style('transform');

            // Update the saved animation object
            animate.frames[animate.frame] = JSON.parse(JSON.stringify({'computed': transform, 'basic': animate.element.transform}));
            animate.object.animation[animate.name] = animate.frames;
        }

        // Build object of data to be saved
        var data =
        {
            duration: animate.duration,
            iterations: animate.iterations,
            frames: animate.frames,
            playing: animate.playing
        };

        if(animate.iterations === Infinity)
        {
            data.iterations = 'Infinity';
        }

        storage.animation.save(animate.element, animate.name, data);
    },

    // Update animation element with the values of the current frame
    update: function()
    {
        var frame = animate.frames[animate.frame];
        $(animate.element).transform(frame.basic);
    },

    play: function()
    {
        try
        {
            var frames = [];

            animate.frames.forEach(function(frame)
            {
                frames.push(frame.computed);
            });

            if(animate.animation)
            {
                animate.animation.cancel();
            }

            animate.animation = animate.element.animate({'transform': frames}, {'duration': animate.duration, 'iterations': animate.iterations, 'fill': 'forwards'});

            var durationPerFrame = animate.duration / (animate.frames.length - 1);
            var currentTime = durationPerFrame * animate.frame;

            if(currentTime > 1)
            {
                currentTime--;
            }

            animate.animation.currentTime = currentTime;
            helper.hover.enabled = false;
            animate.playing = true;
        }
        catch(exception)
        {
            console.log(exception);

            animate.animation = false;
            helper.hover.enabled = true;
            animate.playing = false;
        }
    },

    // Refresh animation if currently playing
    refresh: function()
    {
        if(animate.animation && animate.animation.playState == 'running')
        {
            animate.play();
        }
    },

    pause: function()
    {
        if(animate.animation)
        {
            animate.animation.cancel();
            helper.hover.enabled = true;
            animate.playing = false;
        }
    },

    // Display menu options based on the current animation state
    menu: function()
    {
        if(animate.element)
        {
            $('.element-selected').removeClass('hidden');
        }
        else
        {
            $('.element-selected').addClass('hidden');
        }
    },

    start: function()
    {
        $('.workspace').addClass('highlight-content');
        animate.active = true;
        helper.storage.update = false;
    },

    stop: function()
    {
        $('.workspace').removeClass('highlight-content');
        $('.element-selected').addClass('hidden');
        $('.animation-selected').addClass('hidden');

        animate.pause();
        animate.active = false;
        animate.element = false;
        animate.object = false;
        helper.storage.update = true;

        $('.menu .animate .element').text(animate.defaultText);
    }
};

module.exports = animate;
<|endoftext|>


<commit_before>import Container from 'react-container';
import dialogs from 'cordova-dialogs';
import React from 'react';
import Tappable from 'react-tappable';
import { UI } from 'touchstonejs';

const scrollable = Container.initScrollable();

// html5 input types for testing
// omitted: button, checkbox, radio, image, hidden, reset, submit
const HTML5_INPUT_TYPES = ['color', 'date', 'datetime', 'datetime-local', 'email', 'file', 'month', 'number', 'password', 'range', 'search', 'tel', 'text', 'time', 'url', 'week'];
const FLAVOURS = [
	{ label: 'Vanilla',    value: 'vanilla' },
	{ label: 'Chocolate',  value: 'chocolate' },
	{ label: 'Caramel',    value: 'caramel' },
	{ label: 'Strawberry', value: 'strawberry' }
];

module.exports = React.createClass({
	statics: {
		navigationBar: 'main',
		getNavigation () {
			return {
				title: 'Forms'
			}
		}
	},

	getInitialState () {
		return {
			flavourLabelSelect: 'chocolate',
			flavourRadioList: 'chocolate',
			switchValue: true
		}
	},

	handleRadioListChange (key, newValue) {
		console.log('handleFlavourChange:', key, newValue);
		let newState = {};
		newState[key] = newValue;

		this.setState(newState);
	},

	handleLabelSelectChange (key, event) {
		console.log('handleFlavourChange:', key, event.target.value);
		let newState = {};
		newState[key] = event.target.value;

		this.setState(newState);
	},

	handleSwitch (key, event) {
		let newState = {};
		newState[key] = !this.state[key];

		this.setState(newState);
	},

	alert (message) {
		dialogs.alert(message, function() {}, null)
	},

	// used for testing
	renderInputTypes () {
		return HTML5_INPUT_TYPES.map(type => {
			return <UI.LabelInput key={type} type={type} label={type} placeholder={type} />;
		});
	},

	render () {

		return (
			<Container scrollable={scrollable}>
				{/*<UI.Group>
					<UI.GroupHeader>Input Type Experiment</UI.GroupHeader>
					<UI.GroupBody>
						{this.renderInputTypes()}
					</UI.GroupBody>
				</UI.Group>*/}
				<UI.Group>
					<UI.GroupHeader>Checkbox</UI.GroupHeader>
					<UI.GroupBody>
						<UI.Item>
							<UI.ItemInner>
								<UI.FieldLabel>Switch</UI.FieldLabel>
								<UI.Switch onTap={this.handleSwitch.bind(this, 'switchValue')} on={this.state.switchValue} />
							</UI.ItemInner>
						</UI.Item>
						<UI.Item>
							<UI.ItemInner>
								<UI.FieldLabel>Disabled</UI.FieldLabel>
								<UI.Switch disabled />
							</UI.ItemInner>
						</UI.Item>
					</UI.GroupBody>
				</UI.Group>
				<UI.Group>
					<UI.GroupHeader>Radio</UI.GroupHeader>
					<UI.GroupBody>
						<UI.RadioList value={this.state.flavourRadioList} onChange={this.handleRadioListChange.bind(this, 'flavourRadioList')} options={FLAVOURS} />
					</UI.GroupBody>
				</UI.Group>
				<UI.Group>
					<UI.GroupHeader>Inputs</UI.GroupHeader>
					<UI.GroupBody>
						<UI.Input placeholder="Default" />
						<UI.Input defaultValue="With Value" placeholder="Placeholder" />
						<UI.Textarea defaultValue="Longtext is good for bios etc." placeholder="Longtext" />
					</UI.GroupBody>
				</UI.Group>
				<UI.Group>
					<UI.GroupHeader>Labelled Inputs</UI.GroupHeader>
					<UI.GroupBody>
						<UI.LabelInput type="email" label="Email"   placeholder="your.name@example.com" />
						<UI.LabelInput type="url"   label="URL"     placeholder="http://www.yourwebsite.com" />
						<UI.LabelInput noedit       label="No Edit" defaultValue="Un-editable, scrollable, selectable content" />
						<UI.LabelSelect label="Flavour" value={this.state.flavourLabelSelect} onChange={this.handleLabelSelectChange.bind(this, 'flavourLabelSelect')} options={FLAVOURS} />
					</UI.GroupBody>
				</UI.Group>
				<UI.Button type="primary" onTap={this.alert.bind(this, 'You clicked the Primary Button')}>
					Primary Button
				</UI.Button>
				<UI.Button onTap={this.alert.bind(this, 'You clicked the Default Button')}>
					Default Button
				</UI.Button>
				<UI.Button type="danger" onTap={this.alert.bind(this, 'You clicked the Danger Button')}>
					Danger Button
				</UI.Button>
				<UI.Button type="danger" onTap={this.alert.bind(this, 'You clicked the Danger Button')} disabled>
					Disabled Button
				</UI.Button>
			</Container>
		);
	}
});
<commit_msg>Add DatePicker demo in forms tab.<commit_after>import Container from 'react-container';
import dialogs from 'cordova-dialogs';
import React from 'react';
import Tappable from 'react-tappable';
import { UI } from 'touchstonejs';

const scrollable = Container.initScrollable();

// html5 input types for testing
// omitted: button, checkbox, radio, image, hidden, reset, submit
const HTML5_INPUT_TYPES = ['color', 'date', 'datetime', 'datetime-local', 'email', 'file', 'month', 'number', 'password', 'range', 'search', 'tel', 'text', 'time', 'url', 'week'];
const FLAVOURS = [
	{ label: 'Vanilla',    value: 'vanilla' },
	{ label: 'Chocolate',  value: 'chocolate' },
	{ label: 'Caramel',    value: 'caramel' },
	{ label: 'Strawberry', value: 'strawberry' }
];

module.exports = React.createClass({
	statics: {
		navigationBar: 'main',
		getNavigation () {
			return {
				title: 'Forms'
			}
		}
	},

	getInitialState () {
		return {
			flavourLabelSelect: 'chocolate',
			flavourRadioList: 'chocolate',
			switchValue: true
		}
	},

	handleRadioListChange (key, newValue) {
		console.log('handleFlavourChange:', key, newValue);
		let newState = {};
		newState[key] = newValue;

		this.setState(newState);
	},

	handleLabelSelectChange (key, event) {
		console.log('handleFlavourChange:', key, event.target.value);
		let newState = {};
		newState[key] = event.target.value;

		this.setState(newState);
	},

	handleSwitch (key, event) {
		let newState = {};
		newState[key] = !this.state[key];

		this.setState(newState);
	},

	alert (message) {
		dialogs.alert(message, function() {}, null)
	},

	// used for testing
	renderInputTypes () {
		return HTML5_INPUT_TYPES.map(type => {
			return <UI.LabelInput key={type} type={type} label={type} placeholder={type} />;
		});
	},

	showDatePicker () {
		this.setState({datePicker: true});
	},

	handleDatePickerChange (d) {
		console.log('onchange: ', d);
		this.setState({datePicker: false, date: d});
	},

	formatDate (date) {
		if (date) {
			return date.getFullYear() + '-' + (date.getMonth() + 1) + '-' + date.getDate();
		}
	},

	render () {

		return (
			<Container fill>
				<Container scrollable={scrollable}>
					{/*<UI.Group>
						<UI.GroupHeader>Input Type Experiment</UI.GroupHeader>
						<UI.GroupBody>
							{this.renderInputTypes()}
						</UI.GroupBody>
					</UI.Group>*/}
					<UI.Group>
						<UI.GroupHeader>Checkbox</UI.GroupHeader>
						<UI.GroupBody>
							<UI.Item>
								<UI.ItemInner>
									<UI.FieldLabel>Switch</UI.FieldLabel>
									<UI.Switch onTap={this.handleSwitch.bind(this, 'switchValue')} on={this.state.switchValue} />
								</UI.ItemInner>
							</UI.Item>
							<UI.Item>
								<UI.ItemInner>
									<UI.FieldLabel>Disabled</UI.FieldLabel>
									<UI.Switch disabled />
								</UI.ItemInner>
							</UI.Item>
						</UI.GroupBody>
					</UI.Group>
					<UI.Group>
						<UI.GroupHeader>Radio</UI.GroupHeader>
						<UI.GroupBody>
							<UI.RadioList value={this.state.flavourRadioList} onChange={this.handleRadioListChange.bind(this, 'flavourRadioList')} options={FLAVOURS} />
						</UI.GroupBody>
					</UI.Group>
					<UI.Group>
						<UI.GroupHeader>Inputs</UI.GroupHeader>
						<UI.GroupBody>
							<UI.Input placeholder="Default" />
							<UI.Input defaultValue="With Value" placeholder="Placeholder" />
							<UI.Textarea defaultValue="Longtext is good for bios etc." placeholder="Longtext" />
						</UI.GroupBody>
					</UI.Group>
					<UI.Group>
						<UI.GroupHeader>Labelled Inputs</UI.GroupHeader>
						<UI.GroupBody>
							<UI.LabelInput type="email" label="Email"   placeholder="your.name@example.com" />
							<Tappable component="label" onTap={this.showDatePicker}>
								<UI.LabelValue label="Date" value={this.formatDate(this.state.date)} placeholder="Select a date" />
							</Tappable>
							<UI.LabelInput type="url"   label="URL"     placeholder="http://www.yourwebsite.com" />
							<UI.LabelInput noedit       label="No Edit" defaultValue="Un-editable, scrollable, selectable content" />
							<UI.LabelSelect label="Flavour" value={this.state.flavourLabelSelect} onChange={this.handleLabelSelectChange.bind(this, 'flavourLabelSelect')} options={FLAVOURS} />
						</UI.GroupBody>
					</UI.Group>
					<UI.Button type="primary" onTap={this.alert.bind(this, 'You clicked the Primary Button')}>
						Primary Button
					</UI.Button>
					<UI.Button onTap={this.alert.bind(this, 'You clicked the Default Button')}>
						Default Button
					</UI.Button>
					<UI.Button type="danger" onTap={this.alert.bind(this, 'You clicked the Danger Button')}>
						Danger Button
					</UI.Button>
					<UI.Button type="danger" onTap={this.alert.bind(this, 'You clicked the Danger Button')} disabled>
						Disabled Button
					</UI.Button>
				</Container>
				<UI.DatePickerPopup visible={this.state.datePicker} date={this.state.date} onChange={this.handleDatePickerChange}/>
			</Container>
		);
	}
});
<|endoftext|>


<commit_before>/*
Language: PHP
Author: Victor Karamzin <Victor.Karamzin@enterra-inc.com>
Contributors: Evgeny Stepanischev <imbolk@gmail.com>
*/

hljs.LANGUAGES.php = {
  case_insensitive: true,
  defaultMode: {
    keywords: {
      'and': 1, 'include_once': 1, 'list': 1, 'abstract': 1, 'global': 1,
      'private': 1, 'echo': 1, 'interface': 1, 'as': 1, 'static': 1,
      'endswitch': 1, 'array': 1, 'null': 1, 'if': 1, 'endwhile': 1, 'or': 1,
      'const': 1, 'for': 1, 'endforeach': 1, 'self': 1, 'var': 1, 'while': 1,
      'isset': 1, 'public': 1, 'protected': 1, 'exit': 1, 'foreach': 1,
      'throw': 1, 'elseif': 1, 'extends': 1, 'include': 1, '__FILE__': 1,
      'empty': 1, 'require_once': 1, 'function': 1, 'do': 1, 'xor': 1,
      'return': 1, 'implements': 1, 'parent': 1, 'clone': 1, 'use': 1,
      '__CLASS__': 1, '__LINE__': 1, 'else': 1, 'break': 1, 'print': 1,
      'eval': 1, 'new': 1, 'catch': 1, '__METHOD__': 1, 'class': 1, 'case': 1,
      'exception': 1, 'php_user_filter': 1, 'default': 1, 'die': 1,
      'require': 1, '__FUNCTION__': 1, 'enddeclare': 1, 'final': 1, 'try': 1,
      'this': 1, 'switch': 1, 'continue': 1, 'endfor': 1, 'endif': 1,
      'declare': 1, 'unset': 1, 'true': 1, 'false': 1, 'namespace': 1, 'trait':1,
      'goto':1, 'instanceof':1, '__DIR__':1, '__NAMESPACE__':1, '__halt_compiler':1
    },
    contains: [
      hljs.C_LINE_COMMENT_MODE,
      hljs.HASH_COMMENT_MODE,
      {
        className: 'comment',
        begin: '/\\*', end: '\\*/',
        contains: [{
            className: 'phpdoc',
            begin: '\\s@[A-Za-z]+',
            relevance: 10
        }]
      },
      {
          className: 'comment',
          excludeBegin: true,
          begin: '__halt_compiler[^;]+;', end: '[\\n\\r]$'
      },
      {
        className: 'number',
        begin: '\\b(0b[01]+|0[xX]9[A-Fa-f0-9]+|\\d+(\\.\\d+)?([eE][\\-\\+]?\\d+)?)',
        relevance: 0
      },
      hljs.inherit(hljs.APOS_STRING_MODE, {illegal: null}),
      hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null}),
      {
        className: 'variable',
        begin: '\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'
      },
      {
        className: 'preprocessor',
        begin: '<\\?php',
        relevance: 10
      },
      {
        className: 'preprocessor',
        begin: '\\?>'
      }
    ]
  }
};
<commit_msg>binary string added (PHP 5.2.1+)<commit_after>/*
Language: PHP
Author: Victor Karamzin <Victor.Karamzin@enterra-inc.com>
Contributors: Evgeny Stepanischev <imbolk@gmail.com>
*/

hljs.LANGUAGES.php = {
  case_insensitive: true,
  defaultMode: {
    keywords: {
      'and': 1, 'include_once': 1, 'list': 1, 'abstract': 1, 'global': 1,
      'private': 1, 'echo': 1, 'interface': 1, 'as': 1, 'static': 1,
      'endswitch': 1, 'array': 1, 'null': 1, 'if': 1, 'endwhile': 1, 'or': 1,
      'const': 1, 'for': 1, 'endforeach': 1, 'self': 1, 'var': 1, 'while': 1,
      'isset': 1, 'public': 1, 'protected': 1, 'exit': 1, 'foreach': 1,
      'throw': 1, 'elseif': 1, 'extends': 1, 'include': 1, '__FILE__': 1,
      'empty': 1, 'require_once': 1, 'function': 1, 'do': 1, 'xor': 1,
      'return': 1, 'implements': 1, 'parent': 1, 'clone': 1, 'use': 1,
      '__CLASS__': 1, '__LINE__': 1, 'else': 1, 'break': 1, 'print': 1,
      'eval': 1, 'new': 1, 'catch': 1, '__METHOD__': 1, 'class': 1, 'case': 1,
      'exception': 1, 'php_user_filter': 1, 'default': 1, 'die': 1,
      'require': 1, '__FUNCTION__': 1, 'enddeclare': 1, 'final': 1, 'try': 1,
      'this': 1, 'switch': 1, 'continue': 1, 'endfor': 1, 'endif': 1,
      'declare': 1, 'unset': 1, 'true': 1, 'false': 1, 'namespace': 1, 'trait':1,
      'goto':1, 'instanceof':1, '__DIR__':1, '__NAMESPACE__':1, '__halt_compiler':1
    },
    contains: [
      hljs.C_LINE_COMMENT_MODE,
      hljs.HASH_COMMENT_MODE,
      {
        className: 'comment',
        begin: '/\\*', end: '\\*/',
        contains: [{
            className: 'phpdoc',
            begin: '\\s@[A-Za-z]+',
            relevance: 10
        }]
      },
      {
          className: 'comment',
          excludeBegin: true,
          begin: '__halt_compiler[^;]+;', end: '[\\n\\r]$'
      },
      {
        className: 'number',
        begin: '\\b(0b[01]+|0[xX]9[A-Fa-f0-9]+|\\d+(\\.\\d+)?([eE][\\-\\+]?\\d+)?)',
        relevance: 0
      },
      hljs.inherit(hljs.APOS_STRING_MODE, {illegal: null}),
      hljs.inherit(hljs.QUOTE_STRING_MODE, {illegal: null}),
      {
        className: 'string',
        begin: 'b"', end: '"',
        contains: [hljs.BACKSLASH_ESCAPE],
      },
      {
        className: 'string',
        begin: 'b\'', end: '\'',
        contains: [hljs.BACKSLASH_ESCAPE],
      },
      {
        className: 'variable',
        begin: '\\$[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*'
      },
      {
        className: 'preprocessor',
        begin: '<\\?php',
        relevance: 10
      },
      {
        className: 'preprocessor',
        begin: '\\?>'
      }
    ]
  }
};
<|endoftext|>


<commit_before>import React from 'react';
import PropTypes from 'prop-types';
import graphql from 'graphql';
import Header from '../components/Header';
import Footer from '../components/Footer';
import styled, { ThemeProvider } from 'styled-components';
import theme from '../themes/theme';
import {getMessages} from '../data/messages';

import {addLocaleData, IntlProvider} from 'react-intl';
import en from 'react-intl/locale-data/en';
import fr from 'react-intl/locale-data/fr';
import pt from 'react-intl/locale-data/pt';

import 'intl';
import 'intl/locale-data/jsonp/en';
import 'intl/locale-data/jsonp/fr';
import 'intl/locale-data/jsonp/pt';

import {
  getLangs,
  getUrlForLang,
  getCurrentLangKey,
  isHomePage
} from 'ptz-i18n';

// Performance Measurement
//
// import Perf from 'react-addons-perf';

// if (typeof window !== 'undefined') {
//   window.Perf = Perf;
//   console.log('start perf');
//   Perf.start();
//   setTimeout(() => {
//     console.log('stop perf');
//     Perf.stop();
//     console.log(Perf.printWasted());
//     console.log(Perf.printOperations());
//   }, 5000);
// }

addLocaleData([...en, ...fr, ...pt]);

const Background = styled.div`
  background-color: ${props => props.theme.bg};
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  min-height: 100%;
  overflow-x: hidden;
`;

const BodyContainer = styled.div`
  font-family: ${props => props.theme.fontFamily};
  color: ${props => props.theme.color};
  background-color: ${props => props.theme.bg};
  padding: ${props => props.theme.padding};
  margin: ${props => props.theme.margin};
  max-width: ${props => props.theme.maxWidth};

  font-feature-settings: "calt" 1, "clig" 1, "dlig" 1, "kern" 1, "liga" 1, "salt" 1;
`;

const Wrapper = (props) => {
  const { children, location } = props;
  const url = location.pathname;
  const isHome = isHomePage(url);

  console.log('props: ', props);

  const {langs, defaultLangKey} = props.data.site.siteMetadata.languages;
  const langKey = getCurrentLangKey(langs, defaultLangKey, url);

  const homeLink = `/${langKey}/`;
  const langsMenu = getLangs(langs, langKey, getUrlForLang(homeLink, url));

  const {menu, author, sourceCodeLink} = props.data.site.siteMetadata;

  return (
    <ThemeProvider theme={theme}>
      <IntlProvider
        locale={langKey}
        messages={getMessages(langKey)}
      >
        <Background>
          <BodyContainer>
            <Header
              isHome={isHome}
              langs={langsMenu}
              homeLink={homeLink}
              url={url}
              menu={menu}
            />
            <main>
              {children()}
            </main>
            <Footer
              currentLangKey={langKey}
              author={author}
              sourceCodeLink={sourceCodeLink}
            />
          </BodyContainer>
        </Background>
      </IntlProvider>
    </ThemeProvider>
  );
};

Wrapper.propTypes = {
  children: PropTypes.func.isRequired,
  location: PropTypes.object.isRequired,
  data: PropTypes.object.isRequired
};

export default Wrapper;

export const pageQuery = graphql`
  query Layout {
    site {
      siteMetadata {
        languages {
          defaultLangKey
          langs
        }
        author {
          name
          homeCity
          email
          defaultLink
        }
        sourceCodeLink
        menu {
          label
          link
          slug
        }
      }
    }
  }
`;
<commit_msg>Add es locale<commit_after>import React from 'react';
import PropTypes from 'prop-types';
import graphql from 'graphql';
import Header from '../components/Header';
import Footer from '../components/Footer';
import styled, { ThemeProvider } from 'styled-components';
import theme from '../themes/theme';
import {getMessages} from '../data/messages';

import {addLocaleData, IntlProvider} from 'react-intl';
import en from 'react-intl/locale-data/en';
import fr from 'react-intl/locale-data/fr';
import pt from 'react-intl/locale-data/pt';
import es from 'react-intl/locale-data/es';

import 'intl';
import 'intl/locale-data/jsonp/en';
import 'intl/locale-data/jsonp/fr';
import 'intl/locale-data/jsonp/pt';
import 'intl/locale-data/jsonp/es';

import {
  getLangs,
  getUrlForLang,
  getCurrentLangKey,
  isHomePage
} from 'ptz-i18n';

// Performance Measurement
//
// import Perf from 'react-addons-perf';

// if (typeof window !== 'undefined') {
//   window.Perf = Perf;
//   console.log('start perf');
//   Perf.start();
//   setTimeout(() => {
//     console.log('stop perf');
//     Perf.stop();
//     console.log(Perf.printWasted());
//     console.log(Perf.printOperations());
//   }, 5000);
// }

addLocaleData([...en, ...fr, ...pt, ...es]);

const Background = styled.div`
  background-color: ${props => props.theme.bg};
  top: 0;
  right: 0;
  left: 0;
  bottom: 0;
  min-height: 100%;
  overflow-x: hidden;
`;

const BodyContainer = styled.div`
  font-family: ${props => props.theme.fontFamily};
  color: ${props => props.theme.color};
  background-color: ${props => props.theme.bg};
  padding: ${props => props.theme.padding};
  margin: ${props => props.theme.margin};
  max-width: ${props => props.theme.maxWidth};

  font-feature-settings: "calt" 1, "clig" 1, "dlig" 1, "kern" 1, "liga" 1, "salt" 1;
`;

const Wrapper = (props) => {
  const { children, location } = props;
  const url = location.pathname;
  const isHome = isHomePage(url);

  console.log('props: ', props);

  const {langs, defaultLangKey} = props.data.site.siteMetadata.languages;
  const langKey = getCurrentLangKey(langs, defaultLangKey, url);

  const homeLink = `/${langKey}/`;
  const langsMenu = getLangs(langs, langKey, getUrlForLang(homeLink, url));

  const {menu, author, sourceCodeLink} = props.data.site.siteMetadata;

  return (
    <ThemeProvider theme={theme}>
      <IntlProvider
        locale={langKey}
        messages={getMessages(langKey)}
      >
        <Background>
          <BodyContainer>
            <Header
              isHome={isHome}
              langs={langsMenu}
              homeLink={homeLink}
              url={url}
              menu={menu}
            />
            <main>
              {children()}
            </main>
            <Footer
              currentLangKey={langKey}
              author={author}
              sourceCodeLink={sourceCodeLink}
            />
          </BodyContainer>
        </Background>
      </IntlProvider>
    </ThemeProvider>
  );
};

Wrapper.propTypes = {
  children: PropTypes.func.isRequired,
  location: PropTypes.object.isRequired,
  data: PropTypes.object.isRequired
};

export default Wrapper;

export const pageQuery = graphql`
  query Layout {
    site {
      siteMetadata {
        languages {
          defaultLangKey
          langs
        }
        author {
          name
          homeCity
          email
          defaultLink
        }
        sourceCodeLink
        menu {
          label
          link
          slug
        }
      }
    }
  }
`;
<|endoftext|>


<commit_before>import React from 'react'
import PropTypes from 'prop-types'
import Link from 'gatsby-link'
import Img from 'gatsby-image'
import Helmet from 'react-helmet'
import { injectGlobal } from 'emotion'
import { ThemeProvider } from 'emotion-theming'
import { normalize } from 'polished'
import t from 'tachyons-js'

import { theme } from '../utils/theme'
import Container from '../components/atoms/container'
import Header from '../components/organisms/header'
import Footer from '../components/organisms/footer'

injectGlobal`
  ${normalize()}

  html {
    overflow-y: scroll;
  }

  *,
  *::before,
  *::after {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }

  body {
    font-family: ${theme.sansSerif};
    font-size: ${theme.fontSize6}
    line-height: ${theme.lineHeightCopy};
    font-kerning: normal;
    font-feature-settings: 'kern', 'liga', 'clig', 'calt';
    color: ${theme.darkGray};
  }

  img {
    max-width: 100%;
  }

  h1,
  h2,
  h3,
  h4,
  h5,
  h6 {
    margin-top: ${theme.spacingExtraLarge};
    margin-bottom: ${theme.spacingMediumLarge};
    font-family: ${theme.sansSerifDisplay};
    text-rendering: optimizeLegibility;
    letter-spacing: -0.02rem;
    color: ${theme.nearBlack};
  }

  h1 {
    font-size: ${theme.fontSize1};
    line-height: calc(80 / 64);
  }

  h2 {
    font-size: ${theme.fontSize3};
    line-height: calc(48 / 30);
  }

  h3 {
    font-size: ${theme.fontSize4};
    line-height: calc(32 / 24);
  }

  h4 {
    font-size: ${theme.fontSize5};
    line-height: calc(24 / 20);
  }

  h5 {
    font-size: ${theme.fontSize6};
    line-height: calc(24 / 18);
  }

  h6 {
    font-size: ${theme.fontSize7};
    line-height: calc(24 / 16);
  }
`

const DefaultLayout = ({ children, data }) =>

      <Helmet
        title="James Lutley — Designer, Developer, Maker"
        meta={[
          { name: 'description', content: 'Sample' },
          { name: 'keywords', content: 'sample, something' },
        ]}
        link={[
          { rel: 'stylesheet', href: 'https://use.typekit.net/uon4clj.css' }
        ]}
      />
      <ThemeProvider theme={theme}>

          {children()}

      </ThemeProvider>

export const query = graphql`
  query LayoutQuery {
    site {
      siteMetadata {
        title
      }
    }
    file(relativePath: { eq: "images/jameslutley.jpg"}) {
      childImageSharp {
        resolutions(width: 72, height: 72) {
          ...GatsbyImageSharpResolutions
        }
      }
    }
  },
`

DefaultLayout.propTypes = {
  children: PropTypes.func.isRequired,
  data: PropTypes.object.isRequired,
}

export default DefaultLayout
<commit_msg>fixed indentation<commit_after>import React from 'react'
import PropTypes from 'prop-types'
import Link from 'gatsby-link'
import Img from 'gatsby-image'
import Helmet from 'react-helmet'
import { injectGlobal } from 'emotion'
import { ThemeProvider } from 'emotion-theming'
import { normalize } from 'polished'
import t from 'tachyons-js'

import { theme } from '../utils/theme'
import Container from '../components/atoms/container'
import Header from '../components/organisms/header'
import Footer from '../components/organisms/footer'

injectGlobal`
  ${normalize()}

  html {
    overflow-y: scroll;
  }

  *,
  *::before,
  *::after {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
  }

  body {
    font-family: ${theme.sansSerif};
    font-size: ${theme.fontSize6}
    line-height: ${theme.lineHeightCopy};
    font-kerning: normal;
    font-feature-settings: 'kern', 'liga', 'clig', 'calt';
    color: ${theme.darkGray};
  }

  img {
    max-width: 100%;
  }

  h1,
  h2,
  h3,
  h4,
  h5,
  h6 {
    margin-top: ${theme.spacingExtraLarge};
    margin-bottom: ${theme.spacingMediumLarge};
    font-family: ${theme.sansSerifDisplay};
    text-rendering: optimizeLegibility;
    letter-spacing: -0.02rem;
    color: ${theme.nearBlack};
  }

  h1 {
    font-size: ${theme.fontSize1};
    line-height: calc(80 / 64);
  }

  h2 {
    font-size: ${theme.fontSize3};
    line-height: calc(48 / 30);
  }

  h3 {
    font-size: ${theme.fontSize4};
    line-height: calc(32 / 24);
  }

  h4 {
    font-size: ${theme.fontSize5};
    line-height: calc(24 / 20);
  }

  h5 {
    font-size: ${theme.fontSize6};
    line-height: calc(24 / 18);
  }

  h6 {
    font-size: ${theme.fontSize7};
    line-height: calc(24 / 16);
  }
`

const DefaultLayout = ({ children, data }) =>

    <Helmet
      title="James Lutley — Designer, Developer, Maker"
      meta={[
        { name: 'description', content: 'Sample' },
        { name: 'keywords', content: 'sample, something' },
      ]}
      link={[
        { rel: 'stylesheet', href: 'https://use.typekit.net/uon4clj.css' }
      ]}
    />
    <ThemeProvider theme={theme}>

        {children()}

    </ThemeProvider>

export const query = graphql`
  query LayoutQuery {
    site {
      siteMetadata {
        title
      }
    }
    file(relativePath: { eq: "images/jameslutley.jpg"}) {
      childImageSharp {
        resolutions(width: 72, height: 72) {
          ...GatsbyImageSharpResolutions
        }
      }
    }
  },
`

DefaultLayout.propTypes = {
  children: PropTypes.func.isRequired,
  data: PropTypes.object.isRequired,
}

export default DefaultLayout
<|endoftext|>