<commit_before>const Moment = require('moment-timezone');
const Park = require('../park');

const sParkID = Symbol('Park ID');
const sAuthToken = Symbol('Authentication Token String');
const sApiBase = Symbol('Park API Base URL');
const sRideTypes = Symbol('Ride Types to return');

// this used to be "SeaWorld Park" base, but now it seems SeaWorld have dropped TE2, so refactor this for their other clients.

/**
 * Implements the The Experience Engine API framework.
 * @class
 * @extends Park
 */
class TE2Park extends Park {
  /**
   * Create new TE2Park Object.
   * This object should not be called directly, but rather extended for each of the individual TE2 parks
   * @param {Object} options
   * @param {String} options.park_id ID of the park to access the API for
   * @param {String} [options.auth_token] Auth token to use to connect to the API
   * @param {String} [options.api_base] Base URL to access the API
   * @param {String[]} [options.ride_types] Array of types that denote rides at the park (to avoid listing restaurants/toilets etc. as rides)
   */
  constructor(options = {}) {
    options.name = options.name || 'TE2 Park';

    // inherit from base class
    super(options);

    // assign park configurations
    if (!options.park_id) throw new Error("Missing park's API ID");
    this[sParkID] = options.park_id;

    // accept API options to override defaults if needed
    this[sAuthToken] = options.auth_token || '***REMOVED***';
    this[sApiBase] = options.api_base || 'https://seas.te2.biz/v1/rest/';

    // array of valid ride types. Some implementations of the API use various types to declare rides (eg. Family/Kid/Thrill etc.)
    this[sRideTypes] = options.ride_types || ['Ride', 'Coasters', 'Family', 'ThrillRides', 'Kids'];
  }

  FetchWaitTimes() {
    // first make sure we have our ride names
    return this.GetRideNames().then(rideNames => this.GetAPIUrl({
      url: `${this[sApiBase]}venue/${this[sParkID]}/poi/all/status`,
      mock: `${this.ParkID}_poistatus`,
    }).then((waitTimeData) => {
      waitTimeData.forEach((ride) => {
        // find/create this ride object (only if we have a name for it)
        if (rideNames[ride.id]) {
          let waittime = -1;

          if (ride.status) {
            // update ride wait time
            if (ride.status.waitTime) {
              waittime = ride.status.waitTime;
            } else {
              waittime = ride.status.isOpen ? 0 : -1;
            }
          }

          this.UpdateRide(ride.id, {
            name: rideNames[ride.id],
            waitTime: waittime,
          });
        }
      });

      return Promise.resolve();
    }));
  }

  FetchOpeningTimes() {
    return this.GetAPIUrl({
      url: `${this[sApiBase]}venue/${this[sParkID]}/hours/${Moment().tz(this.Timezone).format('YYYY-MM-DD')}`,
      data: {
        days: 30,
      },
      mock: `${this.ParkID}_hours`,
    }).then((scheduleData) => {
      scheduleData.forEach((day) => {
        const thisDay = Moment(day.date, 'YYYY-MM-DD');
        this.Schedule.SetDate({
          date: thisDay,
          openingTime: day.open ? Moment(day.open, 'YYYY-MM-DDTHH:mm:ss.SSSZZ').tz(this.Timezone) : thisDay,
          closingTime: day.close ? Moment(day.close, 'YYYY-MM-DDTHH:mm:ss.SSSZZ').tz(this.Timezone) : thisDay,
          type: day.isOpen ? 'Operating' : 'Closed',
        });
      });

      return Promise.resolve();
    });
  }

  /**
   * Get cached (or fresh fetch) of ride names
   * @returns {Promise<Object>} Object of RideID => Ride name in English
   */
  GetRideNames() {
    return new Promise(((resolve, reject) => {
      // wrap cache request (cache ride names for 24 hours)
      this.Cache.Wrap('ridenames', this.FetchRideNames.bind(this), 60 * 60 * 24).then(resolve, reject);
    }));
  }

  /**
   * Fetch all the rides and ride names for this park from the API (skip the cache)
   * @returns {Promise<Object>} Object of RideID => Ride name in English
   */
  FetchRideNames() {
    this.Log(`Fetching ride names for ${this.Name}`);

    // fetch POI (points-of-interest) data from API
    return this.GetAPIUrl({
      url: `${this[sApiBase]}venue/${this[sParkID]}/poi/all`,
      mock: `${this.ParkID}_poi`,
    }).then((rideData) => {
      if (!rideData) return Promise.reject(new Error('No POI data returned from TE2 API'));

      const rideNames = {};
      rideData.forEach((poi) => {
        // only include POI data for rides
        if (this[sRideTypes].indexOf(poi.type) >= 0) {
          // grab "label", which is the English title for each POI
          rideNames[poi.id] = poi.label;
        }
      });

      return Promise.resolve(rideNames);
    });
  }

  GetAPIUrl(requestObject) {
    // make sure headers exist if they weren't set already
    if (!requestObject.headers) requestObject.headers = [];
    requestObject.headers.Authorization = `Basic ${Buffer.from(this[sAuthToken]).toString('base64')}`;

    // make sure we get JSON back
    requestObject.forceJSON = true;

    // send network request
    return this.HTTP(requestObject);
  }

  /**
   * Get the park ID used by the SeaWorld/Cedar Fair API
   * @type {String}
   * */
  get ParkID() {
    return this[sParkID];
  }

  /**
   * Get this park's API Base URL
   * @type {String}
   * */
  get APIBase() {
    return this[sApiBase];
  }
}

module.exports = TE2Park;
<commit_msg>[~] Stop using custom new Promise, just return the Cache Promise<commit_after>const Moment = require('moment-timezone');
const Park = require('../park');

const sParkID = Symbol('Park ID');
const sAuthToken = Symbol('Authentication Token String');
const sApiBase = Symbol('Park API Base URL');
const sRideTypes = Symbol('Ride Types to return');

// this used to be "SeaWorld Park" base, but now it seems SeaWorld have dropped TE2, so refactor this for their other clients.

/**
 * Implements the The Experience Engine API framework.
 * @class
 * @extends Park
 */
class TE2Park extends Park {
  /**
   * Create new TE2Park Object.
   * This object should not be called directly, but rather extended for each of the individual TE2 parks
   * @param {Object} options
   * @param {String} options.park_id ID of the park to access the API for
   * @param {String} [options.auth_token] Auth token to use to connect to the API
   * @param {String} [options.api_base] Base URL to access the API
   * @param {String[]} [options.ride_types] Array of types that denote rides at the park (to avoid listing restaurants/toilets etc. as rides)
   */
  constructor(options = {}) {
    options.name = options.name || 'TE2 Park';

    // inherit from base class
    super(options);

    // assign park configurations
    if (!options.park_id) throw new Error("Missing park's API ID");
    this[sParkID] = options.park_id;

    // accept API options to override defaults if needed
    this[sAuthToken] = options.auth_token || '***REMOVED***';
    this[sApiBase] = options.api_base || 'https://seas.te2.biz/v1/rest/';

    // array of valid ride types. Some implementations of the API use various types to declare rides (eg. Family/Kid/Thrill etc.)
    this[sRideTypes] = options.ride_types || ['Ride', 'Coasters', 'Family', 'ThrillRides', 'Kids'];
  }

  FetchWaitTimes() {
    // first make sure we have our ride names
    return this.GetRideNames().then(rideNames => this.GetAPIUrl({
      url: `${this[sApiBase]}venue/${this[sParkID]}/poi/all/status`,
      mock: `${this.ParkID}_poistatus`,
    }).then((waitTimeData) => {
      waitTimeData.forEach((ride) => {
        // find/create this ride object (only if we have a name for it)
        if (rideNames[ride.id]) {
          let waittime = -1;

          if (ride.status) {
            // update ride wait time
            if (ride.status.waitTime) {
              waittime = ride.status.waitTime;
            } else {
              waittime = ride.status.isOpen ? 0 : -1;
            }
          }

          this.UpdateRide(ride.id, {
            name: rideNames[ride.id],
            waitTime: waittime,
          });
        }
      });

      return Promise.resolve();
    }));
  }

  FetchOpeningTimes() {
    return this.GetAPIUrl({
      url: `${this[sApiBase]}venue/${this[sParkID]}/hours/${Moment().tz(this.Timezone).format('YYYY-MM-DD')}`,
      data: {
        days: 30,
      },
      mock: `${this.ParkID}_hours`,
    }).then((scheduleData) => {
      scheduleData.forEach((day) => {
        const thisDay = Moment(day.date, 'YYYY-MM-DD');
        this.Schedule.SetDate({
          date: thisDay,
          openingTime: day.open ? Moment(day.open, 'YYYY-MM-DDTHH:mm:ss.SSSZZ').tz(this.Timezone) : thisDay,
          closingTime: day.close ? Moment(day.close, 'YYYY-MM-DDTHH:mm:ss.SSSZZ').tz(this.Timezone) : thisDay,
          type: day.isOpen ? 'Operating' : 'Closed',
        });
      });

      return Promise.resolve();
    });
  }

  /**
   * Get cached (or fresh fetch) of ride names
   * @returns {Promise<Object>} Object of RideID => Ride name in English
   */
  GetRideNames() {
    // wrap cache request (cache ride names for 24 hours)
    return this.Cache.Wrap('ridenames', this.FetchRideNames.bind(this), 60 * 60 * 24);
  }

  /**
   * Fetch all the rides and ride names for this park from the API (skip the cache)
   * @returns {Promise<Object>} Object of RideID => Ride name in English
   */
  FetchRideNames() {
    this.Log(`Fetching ride names for ${this.Name}`);

    // fetch POI (points-of-interest) data from API
    return this.GetAPIUrl({
      url: `${this[sApiBase]}venue/${this[sParkID]}/poi/all`,
      mock: `${this.ParkID}_poi`,
    }).then((rideData) => {
      if (!rideData) return Promise.reject(new Error('No POI data returned from TE2 API'));

      const rideNames = {};
      rideData.forEach((poi) => {
        // only include POI data for rides
        if (this[sRideTypes].indexOf(poi.type) >= 0) {
          // grab "label", which is the English title for each POI
          rideNames[poi.id] = poi.label;
        }
      });

      return Promise.resolve(rideNames);
    });
  }

  GetAPIUrl(requestObject) {
    // make sure headers exist if they weren't set already
    if (!requestObject.headers) requestObject.headers = [];
    requestObject.headers.Authorization = `Basic ${Buffer.from(this[sAuthToken]).toString('base64')}`;

    // make sure we get JSON back
    requestObject.forceJSON = true;

    // send network request
    return this.HTTP(requestObject);
  }

  /**
   * Get the park ID used by the SeaWorld/Cedar Fair API
   * @type {String}
   * */
  get ParkID() {
    return this[sParkID];
  }

  /**
   * Get this park's API Base URL
   * @type {String}
   * */
  get APIBase() {
    return this[sApiBase];
  }
}

module.exports = TE2Park;
<|endoftext|>


<commit_before>/*! jQuery Caret plugin v1.1.0 | (c) 2012, 2013 Andrew C. Dvorak | github.com/acdvorak/jquery.caret */
(function($, undefined) {

    var _input = document.createElement('input');

    var _support = {
        setSelectionRange: ('setSelectionRange' in _input) || ('selectionStart' in _input),
        createTextRange: ('createTextRange' in _input) || ('selection' in document)
    };

	/**
	 * @class
	 * @constructor
	 */
	var Range = function() {
		this.start = 0;
		this.end = 0;
		this.length = 0;
		this.text = '';
	};

	var _getCaretW3 = function(input) {
		return input.selectionStart;
	};

	/**
	 * @see http://stackoverflow.com/q/6943000/467582
	 */
	var _getCaretIE = function(input) {
		var caret, normalizedValue, range, textInputRange, len, endRange;

		// Yeah, you have to focus twice for IE 7 and 8.  *cries*
		input.focus();
		input.focus();

		range = document.selection.createRange();

		if (range && range.parentElement() == input) {
			len = input.value.length;
			normalizedValue = input.value.replace(/\r\n/g, '');

			// Create a working TextRange that lives only in the input
			textInputRange = input.createTextRange();
			textInputRange.moveToBookmark(range.getBookmark());

			// Check if the start and end of the selection are at the very end
			// of the input, since moveStart/moveEnd doesn't return what we want
			// in those cases
			endRange = input.createTextRange();
			endRange.collapse(false);

			if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
				caret = input.value.replace(/\r\n/g, '\n').length;
			} else {
				caret = -textInputRange.moveStart("character", -len);
				caret += normalizedValue.slice(0, caret).split("\n").length - 1;
			}

			return caret;
		}

		alert("Your browser is incredibly stupid.  I don't know what else to say.");

		return 0;
	};

	/**
	 * Gets the position of the caret in the given input.
	 * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element
	 * @returns {Number}
	 * @see http://stackoverflow.com/questions/263743/how-to-get-cursor-position-in-textarea/263796#263796
	 */
	var _getCaret = function(input) {
		if (!input) {
			return undefined;
		}

		// Mozilla, et al.
		if (_support.setSelectionRange) {
			return _getCaretW3(input);
		}
		// IE
		else if (_support.createTextRange) {
			return _getCaretIE(input);
		}

		return undefined;
	};

	var _setCaretW3 = function(input, pos) {
		input.setSelectionRange(pos, pos);
	};

	var _setCaretIE = function(input, pos) {
		var range = input.createTextRange();
		range.move('character', pos);
		range.select();
	};

	/**
	 * Sets the position of the caret in the given input.
	 * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element
	 * @param {Number} pos
	 * @see http://parentnode.org/javascript/working-with-the-cursor-position/
	 */
	var _setCaret = function(input, pos) {
		input.focus();

		// Mozilla, et al.
		if (_support.setSelectionRange) {
			_setCaretW3(input, pos);
		}
		// IE
		else if (_support.createTextRange) {
			_setCaretIE(input, pos);
		}
	};

	/**
	 * Inserts the specified text at the current caret position in the given input.
	 * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element
	 * @param {String} text
	 * @see http://parentnode.org/javascript/working-with-the-cursor-position/
	 */
	var _insertAtCaret = function(input, text) {
		var curPos = _getCaret(input);

		var newLength = +(curPos + text.length + (input.value.length - curPos));
		var maxLength = +input.getAttribute('maxlength');

		if(input.hasAttribute('maxlength') && newLength > maxLength) {
			var delta = text.length - (newLength - maxLength);
			text = text.substr(0, delta);
		}

		input.value = input.value.substr(0, curPos) + text + input.value.substr(curPos);

		_setCaret(input, curPos + text.length);
	};

	var _getInputRangeW3 = function(input) {
		var range = new Range();

		range.start = input.selectionStart;
		range.end = input.selectionEnd;

		var min = Math.min(range.start, range.end);
		var max = Math.max(range.start, range.end);

		range.length = max - min;
		range.text = input.value.substring(min, max);

		return range;
	};

	var _getInputRangeIE = function(input) {
		var range = new Range();

		input.focus();

		var sr = document.selection.createRange();

		if (!sr) {
			return range;
		}

		var tr_beginning = input.createTextRange();
		var tr_selection = tr_beginning.duplicate();

		tr_selection.moveToBookmark(sr.getBookmark());
		tr_beginning.setEndPoint('EndToStart', tr_selection);

		var text_selected_fixed = sr.text.replace(/[\r\n]/g, '.'); // for some reason IE doesn't always count the \n and \r in the length
		var text_entire_fixed = input.value.replace(/[\r\n]/g, '.');

		range.start = tr_beginning.text.length;
		range.end = range.start + text_selected_fixed.length;

		range.length = text_selected_fixed.length;
		range.text = sr.text;

		if(range.length === 0) {
			range.start = range.end = _getCaret(input);
		}

		return range;
	};

	/**
	 * Gets the selected text range of the given input.
	 * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element
	 * @returns {Range}
	 * @see http://stackoverflow.com/a/263796/467582
	 * @see http://stackoverflow.com/a/2966703/467582
	 */
	var _getInputRange = function(input) {
		if (!input) {
			return undefined;
		}

		// Mozilla, et al.
		if (_support.setSelectionRange) {
			return _getInputRangeW3(input);
		}
		// IE
		else if (_support.createTextRange) {
			return _getInputRangeIE(input);
		}

		return undefined;
	};

	var _setInputRangeW3 = function(input, startPos, endPos) {
		input.setSelectionRange(startPos, endPos);
	};

	var _setInputRangeIE = function(input, startPos, endPos) {
		var i;
		var tr = input.createTextRange();

		// Fix IE from counting the newline characters as two separate characters
		var stop_it = startPos;

		for (i = 0; i < stop_it; i++) {
			if (input.value.substr(i, 1).search(/[\r\n]/) !== -1) {
				startPos = startPos - 0.5;
			}
		}

		stop_it = endPos;

		for (i = 0; i < stop_it; i++) {
			if (input.value.substr(i, 1).search(/[\r\n]/) !== -1) {
				endPos = endPos - 0.5;
			}
		}

		tr.moveEnd('textedit', -1);
		tr.moveStart('character', startPos);
		tr.moveEnd('character', endPos - startPos);
		tr.select();
	};

	/**
	 * Sets the selected text range of (i.e., highlights text in) the given input.
	 * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element
	 * @param {Number} startPos Zero-based index
	 * @param {Number} endPos Zero-based index
	 * @see http://parentnode.org/javascript/working-with-the-cursor-position/
	 * @see http://stackoverflow.com/a/2966703/467582
	 */
	var _setInputRange = function(input, startPos, endPos) {
		// Mozilla, et al.
		if (_support.setSelectionRange) {
			_setInputRangeW3(input, startPos, endPos);
		}
		// IE
		else if (_support.createTextRange) {
			_setInputRangeIE(input, startPos, endPos);
		}
	};

	/**
	 * Replaces the currently selected text with the given string.
	 * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element
	 * @param {String} text New text that will replace the currently selected text.
	 * @see http://parentnode.org/javascript/working-with-the-cursor-position/
	 */
	var _replaceInputRange = function(input, text) {
		var $input = $(input);

		var oldValue = $input.val();
		var selection = _getInputRange(input);

		// TODO: This throws an error in IE7
		var newLength = +(selection.start + text.length + (oldValue.length - selection.end));
		var maxLength = +$input.attr('maxlength');

		if($input.is('[maxlength]') && newLength > maxLength) {
			var delta = text.length - (newLength - maxLength);
			text = text.substr(0, delta);
		}

		// Now that we know what the user selected, we can replace it
		var startText = oldValue.substr(0, selection.start);
		var endText = oldValue.substr(selection.end);
		$input.val(startText + text + endText);

		// Reset the selection
		var startPos = selection.start;
		var endPos = startPos + text.length;

		_setInputRange(input, selection.length ? startPos : endPos, endPos);
	};

	var _selectAllW3 = function(elem) {
		var selection = window.getSelection();
		var range = document.createRange();
		range.selectNodeContents(elem);
		selection.removeAllRanges();
		selection.addRange(range);
	};

	var _selectAllIE = function(elem) {
		var range = document.body.createTextRange();
		range.moveToElementText(elem);
		range.select();
	};

	/**
	 * Select all text in the given element.
	 * @param {HTMLElement} elem Any block or inline element other than a form element.
	 */
	var _highlight = function(elem) {
		// Mozilla, et al.
		if (_support.setSelectionRange) {
			_selectAllW3(elem);
		}
		// IE
		else if (_support.createTextRange) {
			_selectAllIE(elem);
		}
	};

    $.fn.extend({

        /**
		 * Gets or sets the position of the caret or inserts text at the current caret position in an input or textarea element.
		 * @returns {Number|jQuery} The current caret position if invoked as a getter (with no arguments)
		 * or this jQuery object if invoked as a setter or inserter.
		 * @see http://web.archive.org/web/20080704185920/http://parentnode.org/javascript/working-with-the-cursor-position/
		 * @since 1.0.0
         * @example
		 *

		 *    // Get position
         *    var pos = $('input:first').caret();
		 *

         * @example
		 *

         *    // Set position
         *    $('input:first').caret(15);
		 *

         * @example
		 *

         *    // Insert text at current position
         *    $('input:first').caret('Some text');
		 *

         */
        caret: function() {
			var $inputs = this.filter('input, textarea');

			// getCaret()
            if (arguments.length === 0) {
				var input = $inputs.get(0);
				return _getCaret(input);
            }
            // setCaret(position)
            else if ($.isNumeric(arguments[0])) {
				var pos = Math.floor(arguments[0]);
				return this.each(function(_i, input) {
					_setCaret(input, pos);
				});
            }
            // insertAtCaret(text)
            else {
				var text = arguments[0];
				return this.each(function(_i, input) {
					_insertAtCaret(input, text);
				});
            }
        },

		/**
		 * Gets or sets the selection range or replaces the currently selected text in an input or textarea element.
		 * @returns {Range|jQuery} The current selection range if invoked as a getter (with no arguments)
		 * or this jQuery object if invoked as a setter or replacer.
		 * @see http://stackoverflow.com/a/2966703/467582
		 * @since 1.0.0
		 * @example
		 *

		 *    // Get selection range
		 *    var range = $('input:first').range();
		 *

		 * @example
		 *

		 *    // Set selection range
		 *    $('input:first').range(15, 20);
		 *

		 * @example
		 *

		 *    // Replace the currently selected text
		 *    $('input:first').range('Replacement text');
		 *

		 */
        range: function() {
			var $inputs = this.filter('input, textarea');

            // getRange() = { start: pos, end: pos }
            if (arguments.length === 0) {
				var input = $inputs.get(0);
                return _getInputRange(input);
            }
            // setRange(startPos, endPos)
            else if ($.isNumeric(arguments[0])) {
				var startPos = Math.floor(arguments[0]),
					endPos = Math.floor(arguments[1]);
				return this.each(function(_i, input) {
					_setInputRange(input, startPos, endPos);
				});
            }
            // replaceRange(text)
            else {
				var text = arguments[0];
				return this.each(function(_i, input) {
					_replaceInputRange(input, text);
				});
            }
        },

		/**
		 * Highlights (selects) all text in each element of this jQuery object.
		 * @returns {jQuery} This jQuery object
		 * @see http://stackoverflow.com/a/11128179/467582
		 * @since 1.1.0
		 * @example
		 *

		 *     // Highlight the contents of span elements when clicked
		 *     $('span').on('click', function() { $(this).highlight(); });
		 *

		 */
		highlight: function() {
			return this.each(function(_i, elem) {
				_highlight(elem);
			});
		}

    });
}(jQuery));<commit_msg>Fixed bug - use strict typeof === 'number' check instead of loose $.isNumeric() to detect whether the plugin method was invoked as a setter or inserter/replacer<commit_after>/*! jQuery Caret plugin v1.1.0 | (c) 2012, 2013 Andrew C. Dvorak | github.com/acdvorak/jquery.caret */
(function($, undefined) {

    var _input = document.createElement('input');

    var _support = {
        setSelectionRange: ('setSelectionRange' in _input) || ('selectionStart' in _input),
        createTextRange: ('createTextRange' in _input) || ('selection' in document)
    };

	/**
	 * @class
	 * @constructor
	 */
	var Range = function() {
		this.start = 0;
		this.end = 0;
		this.length = 0;
		this.text = '';
	};

	var _getCaretW3 = function(input) {
		return input.selectionStart;
	};

	/**
	 * @see http://stackoverflow.com/q/6943000/467582
	 */
	var _getCaretIE = function(input) {
		var caret, normalizedValue, range, textInputRange, len, endRange;

		// Yeah, you have to focus twice for IE 7 and 8.  *cries*
		input.focus();
		input.focus();

		range = document.selection.createRange();

		if (range && range.parentElement() == input) {
			len = input.value.length;
			normalizedValue = input.value.replace(/\r\n/g, '');

			// Create a working TextRange that lives only in the input
			textInputRange = input.createTextRange();
			textInputRange.moveToBookmark(range.getBookmark());

			// Check if the start and end of the selection are at the very end
			// of the input, since moveStart/moveEnd doesn't return what we want
			// in those cases
			endRange = input.createTextRange();
			endRange.collapse(false);

			if (textInputRange.compareEndPoints("StartToEnd", endRange) > -1) {
				caret = input.value.replace(/\r\n/g, '\n').length;
			} else {
				caret = -textInputRange.moveStart("character", -len);
				caret += normalizedValue.slice(0, caret).split("\n").length - 1;
			}

			return caret;
		}

		alert("Your browser is incredibly stupid.  I don't know what else to say.");

		return 0;
	};

	/**
	 * Gets the position of the caret in the given input.
	 * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element
	 * @returns {Number}
	 * @see http://stackoverflow.com/questions/263743/how-to-get-cursor-position-in-textarea/263796#263796
	 */
	var _getCaret = function(input) {
		if (!input) {
			return undefined;
		}

		// Mozilla, et al.
		if (_support.setSelectionRange) {
			return _getCaretW3(input);
		}
		// IE
		else if (_support.createTextRange) {
			return _getCaretIE(input);
		}

		return undefined;
	};

	var _setCaretW3 = function(input, pos) {
		input.setSelectionRange(pos, pos);
	};

	var _setCaretIE = function(input, pos) {
		var range = input.createTextRange();
		range.move('character', pos);
		range.select();
	};

	/**
	 * Sets the position of the caret in the given input.
	 * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element
	 * @param {Number} pos
	 * @see http://parentnode.org/javascript/working-with-the-cursor-position/
	 */
	var _setCaret = function(input, pos) {
		input.focus();

		// Mozilla, et al.
		if (_support.setSelectionRange) {
			_setCaretW3(input, pos);
		}
		// IE
		else if (_support.createTextRange) {
			_setCaretIE(input, pos);
		}
	};

	/**
	 * Inserts the specified text at the current caret position in the given input.
	 * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element
	 * @param {String} text
	 * @see http://parentnode.org/javascript/working-with-the-cursor-position/
	 */
	var _insertAtCaret = function(input, text) {
		var curPos = _getCaret(input);

		var newLength = +(curPos + text.length + (input.value.length - curPos));
		var maxLength = +input.getAttribute('maxlength');

		if(input.hasAttribute('maxlength') && newLength > maxLength) {
			var delta = text.length - (newLength - maxLength);
			text = text.substr(0, delta);
		}

		input.value = input.value.substr(0, curPos) + text + input.value.substr(curPos);

		_setCaret(input, curPos + text.length);
	};

	var _getInputRangeW3 = function(input) {
		var range = new Range();

		range.start = input.selectionStart;
		range.end = input.selectionEnd;

		var min = Math.min(range.start, range.end);
		var max = Math.max(range.start, range.end);

		range.length = max - min;
		range.text = input.value.substring(min, max);

		return range;
	};

	var _getInputRangeIE = function(input) {
		var range = new Range();

		input.focus();

		var sr = document.selection.createRange();

		if (!sr) {
			return range;
		}

		var tr_beginning = input.createTextRange();
		var tr_selection = tr_beginning.duplicate();

		tr_selection.moveToBookmark(sr.getBookmark());
		tr_beginning.setEndPoint('EndToStart', tr_selection);

		var text_selected_fixed = sr.text.replace(/[\r\n]/g, '.'); // for some reason IE doesn't always count the \n and \r in the length
		var text_entire_fixed = input.value.replace(/[\r\n]/g, '.');

		range.start = tr_beginning.text.length;
		range.end = range.start + text_selected_fixed.length;

		range.length = text_selected_fixed.length;
		range.text = sr.text;

		if(range.length === 0) {
			range.start = range.end = _getCaret(input);
		}

		return range;
	};

	/**
	 * Gets the selected text range of the given input.
	 * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element
	 * @returns {Range}
	 * @see http://stackoverflow.com/a/263796/467582
	 * @see http://stackoverflow.com/a/2966703/467582
	 */
	var _getInputRange = function(input) {
		if (!input) {
			return undefined;
		}

		// Mozilla, et al.
		if (_support.setSelectionRange) {
			return _getInputRangeW3(input);
		}
		// IE
		else if (_support.createTextRange) {
			return _getInputRangeIE(input);
		}

		return undefined;
	};

	var _setInputRangeW3 = function(input, startPos, endPos) {
		input.setSelectionRange(startPos, endPos);
	};

	var _setInputRangeIE = function(input, startPos, endPos) {
		var i;
		var tr = input.createTextRange();

		// Fix IE from counting the newline characters as two separate characters
		var stop_it = startPos;

		for (i = 0; i < stop_it; i++) {
			if (input.value.substr(i, 1).search(/[\r\n]/) !== -1) {
				startPos = startPos - 0.5;
			}
		}

		stop_it = endPos;

		for (i = 0; i < stop_it; i++) {
			if (input.value.substr(i, 1).search(/[\r\n]/) !== -1) {
				endPos = endPos - 0.5;
			}
		}

		tr.moveEnd('textedit', -1);
		tr.moveStart('character', startPos);
		tr.moveEnd('character', endPos - startPos);
		tr.select();
	};

	/**
	 * Sets the selected text range of (i.e., highlights text in) the given input.
	 * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element
	 * @param {Number} startPos Zero-based index
	 * @param {Number} endPos Zero-based index
	 * @see http://parentnode.org/javascript/working-with-the-cursor-position/
	 * @see http://stackoverflow.com/a/2966703/467582
	 */
	var _setInputRange = function(input, startPos, endPos) {
		// Mozilla, et al.
		if (_support.setSelectionRange) {
			_setInputRangeW3(input, startPos, endPos);
		}
		// IE
		else if (_support.createTextRange) {
			_setInputRangeIE(input, startPos, endPos);
		}
	};

	/**
	 * Replaces the currently selected text with the given string.
	 * @param {HTMLInputElement|HTMLTextAreaElement} input input or textarea element
	 * @param {String} text New text that will replace the currently selected text.
	 * @see http://parentnode.org/javascript/working-with-the-cursor-position/
	 */
	var _replaceInputRange = function(input, text) {
		var $input = $(input);

		var oldValue = $input.val();
		var selection = _getInputRange(input);

		// TODO: This throws an error in IE7
		var newLength = +(selection.start + text.length + (oldValue.length - selection.end));
		var maxLength = +$input.attr('maxlength');

		if($input.is('[maxlength]') && newLength > maxLength) {
			var delta = text.length - (newLength - maxLength);
			text = text.substr(0, delta);
		}

		// Now that we know what the user selected, we can replace it
		var startText = oldValue.substr(0, selection.start);
		var endText = oldValue.substr(selection.end);
		$input.val(startText + text + endText);

		// Reset the selection
		var startPos = selection.start;
		var endPos = startPos + text.length;

		_setInputRange(input, selection.length ? startPos : endPos, endPos);
	};

	var _selectAllW3 = function(elem) {
		var selection = window.getSelection();
		var range = document.createRange();
		range.selectNodeContents(elem);
		selection.removeAllRanges();
		selection.addRange(range);
	};

	var _selectAllIE = function(elem) {
		var range = document.body.createTextRange();
		range.moveToElementText(elem);
		range.select();
	};

	/**
	 * Select all text in the given element.
	 * @param {HTMLElement} elem Any block or inline element other than a form element.
	 */
	var _highlight = function(elem) {
		// Mozilla, et al.
		if (_support.setSelectionRange) {
			_selectAllW3(elem);
		}
		// IE
		else if (_support.createTextRange) {
			_selectAllIE(elem);
		}
	};

    $.fn.extend({

        /**
		 * Gets or sets the position of the caret or inserts text at the current caret position in an input or textarea element.
		 * @returns {Number|jQuery} The current caret position if invoked as a getter (with no arguments)
		 * or this jQuery object if invoked as a setter or inserter.
		 * @see http://web.archive.org/web/20080704185920/http://parentnode.org/javascript/working-with-the-cursor-position/
		 * @since 1.0.0
         * @example
		 *

		 *    // Get position
         *    var pos = $('input:first').caret();
		 *

         * @example
		 *

         *    // Set position
         *    $('input:first').caret(15);
		 *

         * @example
		 *

         *    // Insert text at current position
         *    $('input:first').caret('Some text');
		 *

         */
        caret: function() {
			var $inputs = this.filter('input, textarea');

			// getCaret()
            if (arguments.length === 0) {
				var input = $inputs.get(0);
				return _getCaret(input);
            }
            // setCaret(position)
            else if (typeof arguments[0] === 'number') {
				var pos = Math.floor(arguments[0]);
				return this.each(function(_i, input) {
					_setCaret(input, pos);
				});
            }
            // insertAtCaret(text)
            else {
				var text = arguments[0];
				return this.each(function(_i, input) {
					_insertAtCaret(input, text);
				});
            }
        },

		/**
		 * Gets or sets the selection range or replaces the currently selected text in an input or textarea element.
		 * @returns {Range|jQuery} The current selection range if invoked as a getter (with no arguments)
		 * or this jQuery object if invoked as a setter or replacer.
		 * @see http://stackoverflow.com/a/2966703/467582
		 * @since 1.0.0
		 * @example
		 *

		 *    // Get selection range
		 *    var range = $('input:first').range();
		 *

		 * @example
		 *

		 *    // Set selection range
		 *    $('input:first').range(15, 20);
		 *

		 * @example
		 *

		 *    // Replace the currently selected text
		 *    $('input:first').range('Replacement text');
		 *

		 */
        range: function() {
			var $inputs = this.filter('input, textarea');

            // getRange() = { start: pos, end: pos }
            if (arguments.length === 0) {
				var input = $inputs.get(0);
                return _getInputRange(input);
            }
            // setRange(startPos, endPos)
            else if (typeof arguments[0] === 'number') {
				var startPos = Math.floor(arguments[0]),
					endPos = Math.floor(arguments[1]);
				return this.each(function(_i, input) {
					_setInputRange(input, startPos, endPos);
				});
            }
            // replaceRange(text)
            else {
				var text = arguments[0];
				return this.each(function(_i, input) {
					_replaceInputRange(input, text);
				});
            }
        },

		/**
		 * Highlights (selects) all text in each element of this jQuery object.
		 * @returns {jQuery} This jQuery object
		 * @see http://stackoverflow.com/a/11128179/467582
		 * @since 1.1.0
		 * @example
		 *

		 *     // Highlight the contents of span elements when clicked
		 *     $('span').on('click', function() { $(this).highlight(); });
		 *

		 */
		highlight: function() {
			return this.each(function(_i, elem) {
				_highlight(elem);
			});
		}

    });
}(jQuery));<|endoftext|>


<commit_before>"use strict";

var assert = require("assert");
var utils = require("./utils.js");

/**
  ### Shrink functions
*/

// Blessing: i.e adding prototype
/* eslint-disable no-use-before-define */
function shrinkProtoIsoMap(shrink) {
  return function (f, g) {
    return shrinkBless(function (value) {
      return shrink(g(value)).map(f);
    });
  };
}
/* eslint-enable no-use-before-define */

function shrinkBless(shrink) {
  shrink.isomap = shrinkProtoIsoMap(shrink);
  return shrink;
}

/**
  - `shrink.noop(x: a): array a`
*/
var shrinkNoop = shrinkBless(function shrinkNoop() {
  return [];
});

/**
  - `shrink.tuple(shrinks: (a -> array a, b -> array b...), x: (a, b...)): array (a, b...)`
*/
function shrinkTuple(shrinks) {
  var result = shrinkBless(function (tup) {
    assert(shrinks.length === tup.length, "there should be as much shrinks as values in the tuple");

    var shrinked = new Array(tup.length);

    for (var i = 0; i < tup.length; i++) {
      /* jshint -W083 */
      /* eslint-disable no-loop-func */
      shrinked[i] = shrinks[i](tup[i]).map(function (x) {
        var c = tup.slice(); // clone array
        c[i] = x;
        return c;
      });
      /* eslint-enable no-loop-func */
      /* jshint +W083 */
    }

    return Array.prototype.concat.apply([], shrinked);
  });

  return utils.curried2(result, arguments);
}

function shrinkArrayWithMinimumSize(size) {
  function shrinkArrayImpl(shrink) {
    var result = shrinkBless(function (arr) {
      if (arr.length <= size) {
        return [];
      } else {
        var x = arr[0];
        var xs = arr.slice(1);

        return [xs].concat(
          shrink(x).map(function (xp) { return [xp].concat(xs); }),
          shrinkArrayImpl(shrink, xs).map(function (xsp) { return [x].concat(xsp); })
        );
      }
    });

    return utils.curried2(result, arguments);
  }

  return shrinkArrayImpl;
}

/**
  - `shrink.array(shrink: a -> array a, x: array a): array (array a)`
*/
var shrinkArray = shrinkArrayWithMinimumSize(0);

/**
  - `shrink.nearray(shrink: a -> nearray a, x:  nearray a): array (nearray a)`
*/
var shrinkNEArray = shrinkArrayWithMinimumSize(1);

/**
  - `shrink.record(shrinks: { key: a -> string... }, x: { key: a... }): array { key: a... }`
*/
function shrinkRecord(shrinksRecord) {
  var result = shrinkBless(function (record) {
    var keys = Object.keys(record);
    var values = keys.map(function (k) { return record[k]; });
    var shrinks = keys.map(function (k) { return shrinksRecord[k]; });

    var shrinked = shrinkTuple(shrinks, values);

    return shrinked.map(function (s) {
      var res = {};
      keys.forEach(function (k, i) {
        res[k] = s[i];
      });
      return res;
    });
  });

  return utils.curried2(result, arguments);
}

module.exports = {
  noop: shrinkNoop,
  tuple: shrinkTuple,
  array: shrinkArray,
  nearray: shrinkNEArray,
  record: shrinkRecord,
  bless: shrinkBless,
};
<commit_msg>Make shrinkProto use this<commit_after>"use strict";

var assert = require("assert");
var utils = require("./utils.js");

/**
  ### Shrink functions
*/

// Blessing: i.e adding prototype
/* eslint-disable no-use-before-define */
function shrinkProtoIsoMap(f, g) {
  /* jshint validthis:true */
  var shrink = this;
  return shrinkBless(function (value) {
    return shrink(g(value)).map(f);
  });
}
/* eslint-enable no-use-before-define */

function shrinkBless(shrink) {
  shrink.isomap = shrinkProtoIsoMap;
  return shrink;
}

/**
  - `shrink.noop(x: a): array a`
*/
var shrinkNoop = shrinkBless(function shrinkNoop() {
  return [];
});

/**
  - `shrink.tuple(shrinks: (a -> array a, b -> array b...), x: (a, b...)): array (a, b...)`
*/
function shrinkTuple(shrinks) {
  var result = shrinkBless(function (tup) {
    assert(shrinks.length === tup.length, "there should be as much shrinks as values in the tuple");

    var shrinked = new Array(tup.length);

    for (var i = 0; i < tup.length; i++) {
      /* jshint -W083 */
      /* eslint-disable no-loop-func */
      shrinked[i] = shrinks[i](tup[i]).map(function (x) {
        var c = tup.slice(); // clone array
        c[i] = x;
        return c;
      });
      /* eslint-enable no-loop-func */
      /* jshint +W083 */
    }

    return Array.prototype.concat.apply([], shrinked);
  });

  return utils.curried2(result, arguments);
}

function shrinkArrayWithMinimumSize(size) {
  function shrinkArrayImpl(shrink) {
    var result = shrinkBless(function (arr) {
      if (arr.length <= size) {
        return [];
      } else {
        var x = arr[0];
        var xs = arr.slice(1);

        return [xs].concat(
          shrink(x).map(function (xp) { return [xp].concat(xs); }),
          shrinkArrayImpl(shrink, xs).map(function (xsp) { return [x].concat(xsp); })
        );
      }
    });

    return utils.curried2(result, arguments);
  }

  return shrinkArrayImpl;
}

/**
  - `shrink.array(shrink: a -> array a, x: array a): array (array a)`
*/
var shrinkArray = shrinkArrayWithMinimumSize(0);

/**
  - `shrink.nearray(shrink: a -> nearray a, x:  nearray a): array (nearray a)`
*/
var shrinkNEArray = shrinkArrayWithMinimumSize(1);

/**
  - `shrink.record(shrinks: { key: a -> string... }, x: { key: a... }): array { key: a... }`
*/
function shrinkRecord(shrinksRecord) {
  var result = shrinkBless(function (record) {
    var keys = Object.keys(record);
    var values = keys.map(function (k) { return record[k]; });
    var shrinks = keys.map(function (k) { return shrinksRecord[k]; });

    var shrinked = shrinkTuple(shrinks, values);

    return shrinked.map(function (s) {
      var res = {};
      keys.forEach(function (k, i) {
        res[k] = s[i];
      });
      return res;
    });
  });

  return utils.curried2(result, arguments);
}

module.exports = {
  noop: shrinkNoop,
  tuple: shrinkTuple,
  array: shrinkArray,
  nearray: shrinkNEArray,
  record: shrinkRecord,
  bless: shrinkBless,
};
<|endoftext|>


<commit_before>(function(factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['jquery'], factory);
    } else if (typeof module === 'object' && module.exports) {
        module.exports = factory(require('jquery'));
    } else {
        // Browser globals
        factory(jQuery);
    }
}(function($) {
    var pluginName = 'carro',
        defaults = {
            autoPlay: false,
            buttons: '',
            fitToLimits: false,
            fluid: false,
            index: 0,
            interval: 5000,
            offset: 0,
            slideActiveClass: '',
            buttonActiveClass: '',
            slidesFilter: '*',
            trayFilter: '*'
        };

    function Plugin(element, options) {
        this.element = element;
        this.settings = $.extend({}, defaults, options);

        this.init();
    }

    Plugin.prototype = {
        init: function() {
            var self = this;

            this.$element = $(this.element);
            this.$tray = this.$element.children(this.settings.trayFilter).first();
            this.$slides = this.$tray.children(this.settings.slidesFilter);

            //Events
            if (this.settings.enter) {
                this.$slides.on('enter.' + pluginName, this.settings.enter);
            }

            if (this.settings.leave) {
                this.$slides.on('leave.' + pluginName, this.settings.leave);
            }

            if (this.settings.slideActiveClass) {
                this.$slides.on('leave.' + pluginName, function() {
                    $(this).removeClass(self.settings.slideActiveClass);
                });
                this.$slides.on('enter.' + pluginName, function() {
                    $(this).addClass(self.settings.slideActiveClass);
                });
            }

            //Buttons
            if (this.settings.buttons) {
                if ($.isFunction(this.settings.buttons)) {
                    this.$buttons = $.proxy(this.settings.buttons, this.$element)();
                } else {
                    this.$buttons = $(this.settings.buttons);
                }

                this.$buttons.on('click.' + pluginName, function() {
                    self['goto']($(this).attr('data-carro'));
                    return false;
                });

                if (this.settings.buttonActiveClass) {
                    this.$slides.on('enter.' + pluginName, function() {
                        self.$buttons.filter('[data-carro="' + $(this).index() + '"]').addClass(self.settings.buttonActiveClass);
                    });

                    this.$slides.on('leave.' + pluginName, function() {
                        self.$buttons.filter('[data-carro="' + $(this).index() + '"]').removeClass(self.settings.buttonActiveClass);
                    });
                }
            }

            //Go to
            this.index = this.settings.index || 0;
            this['goto'](this.index);

            //Autoplay
            if (this.settings.autoPlay) {
                this.play();
            }
        },

        goto: function(position) {
            var $target = this.getSlide(position);

            if ($target && $target.length) {
                this.getSlide('current').trigger('leave');

                var x = 0;

                $target.prevAll().each(function() {
                    x -= $(this).outerWidth(true);
                });

                //offset
                if (this.settings.offset === 'center') {
                    x += (this.$element.width() - $target.width()) / 2;
                } else {
                    x += this.settings.offset || 0;
                }

                //fitToLimits
                if (this.settings.fitToLimits) {
                    var lastx = this.$element.width();

                    this.getSlide('last').prevAll().addBack().each(function() {
                        lastx -= $(this).outerWidth(true);
                    });

                    if (!this.settings.fluid) {
                        this.index = $target.index();
                    }

                    if (x > 0) {
                        x = 0;
                    } else if (x < lastx) {
                        x = lastx;
                    } else {
                        this.index = $target.index();
                    }
                } else {
                    this.index = $target.index();
                }

                $target.trigger('enter');

                this.$tray.css('transform', 'translateX(' + x + 'px)');
            }
        },

        getSlides: function() {
            return this.$slides;
        },

        getSlide: function(position) {
            if (position === undefined || position === 'current') {
                return this._eq(this.index);
            }

            if (typeof position === 'object' && position.jquery && position.parent().is(this.$tray)) {
                return position;
            }

            if (position === 'first') {
                return this.$slides.first();
            }

            if (position === 'last') {
                return this.$slides.last();
            }

            if (typeof position === 'number') {
                return this._eq(position);
            }

            if (/^[0-9]+$/.test(position)) {
                return this._eq(parseInt(position));
            }

            if (/^\+[0-9]+$/.test(position)) {
                position = this.index + (parseInt(position.substr(1), 10));

                return this._eq(position);
            }

            if (/^\-[0-9]+$/.test(position)) {
                position = this.index - (parseInt(position.substr(1), 10));

                return this._eq(position);
            }
        },

        _eq: function(position) {
            if (position < 0) {
                return this.$slides.first();
            }

            if (position >= this.$slides.length) {
                return this.$slides.last();
            }

            return this.$slides.eq(position);
        },

        play: function() {
            var that = this,
                index = '+1';

            var interval = function() {
                if (that.getSlide('last').index() === that.index) {
                    index = '-1';
                } else if (that.index === 0) {
                    index = '+1';
                }

                that['goto'](index);

                that.timeout = setTimeout(interval, that.settings.interval);
            };

            this.timeout = setTimeout(interval, this.settings.interval);
        },

        stop: function() {
            clearTimeout(this.timeout);
        },

        destroy: function() {
            this.$slides.off('.' + pluginName);

            if (this.$buttons) {
                this.$buttons.off('.' + pluginName);
            }
        }
    };

    $.fn[pluginName] = function(options) {
        if ((options === undefined) || (typeof options === 'object')) {
            return this.each(function() {
                if (!$.data(this, 'plugin_' + pluginName)) {
                    $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
                }
            });
        }

        if ((typeof options === 'string') && (options[0] !== '_') && (options !== 'init')) {
            var returns, args = arguments;

            this.each(function() {
                var instance = $.data(this, 'plugin_' + pluginName);

                if ((instance instanceof Plugin) && (typeof instance[options] === 'function')) {
                    returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));
                }

                if (options === 'destroy') {
                    $.data(this, 'plugin_' + pluginName, null);
                }
            });

            return returns !== undefined ? returns : this;
        }
    };
}));<commit_msg>fixed autoplay combined with buttons<commit_after>(function(factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define(['jquery'], factory);
    } else if (typeof module === 'object' && module.exports) {
        module.exports = factory(require('jquery'));
    } else {
        // Browser globals
        factory(jQuery);
    }
}(function($) {
    var pluginName = 'carro',
        defaults = {
            autoPlay: false,
            buttons: '',
            fitToLimits: false,
            fluid: false,
            index: 0,
            interval: 5000,
            offset: 0,
            slideActiveClass: '',
            buttonActiveClass: '',
            slidesFilter: '*',
            trayFilter: '*'
        };

    function Plugin(element, options) {
        this.timeout = null;
        this.playing = false;
        this.element = element;
        this.settings = $.extend({}, defaults, options);

        this.init();
    }

    Plugin.prototype = {
        init: function() {
            var self = this;

            this.$element = $(this.element);
            this.$tray = this.$element.children(this.settings.trayFilter).first();
            this.$slides = this.$tray.children(this.settings.slidesFilter);

            //Events
            if (this.settings.enter) {
                this.$slides.on('enter.' + pluginName, this.settings.enter);
            }

            if (this.settings.leave) {
                this.$slides.on('leave.' + pluginName, this.settings.leave);
            }

            if (this.settings.slideActiveClass) {
                this.$slides.on('leave.' + pluginName, function() {
                    $(this).removeClass(self.settings.slideActiveClass);
                });
                this.$slides.on('enter.' + pluginName, function() {
                    $(this).addClass(self.settings.slideActiveClass);
                });
            }

            //Buttons
            if (this.settings.buttons) {
                if ($.isFunction(this.settings.buttons)) {
                    this.$buttons = $.proxy(this.settings.buttons, this.$element)();
                } else {
                    this.$buttons = $(this.settings.buttons);
                }

                this.$buttons.on('click.' + pluginName, function() {
                    self['goto']($(this).attr('data-carro'));
                    return false;
                });

                if (this.settings.buttonActiveClass) {
                    this.$slides.on('enter.' + pluginName, function() {
                        self.$buttons.filter('[data-carro="' + $(this).index() + '"]').addClass(self.settings.buttonActiveClass);
                    });

                    this.$slides.on('leave.' + pluginName, function() {
                        self.$buttons.filter('[data-carro="' + $(this).index() + '"]').removeClass(self.settings.buttonActiveClass);
                    });
                }
            }

            //Go to
            this.index = this.settings.index || 0;
            this['goto'](this.index);

            //Autoplay
            if (this.settings.autoPlay) {
                this.play();
            }
        },

        goto: function(position) {
            var $target = this.getSlide(position);

            if ($target && $target.length) {
                this.getSlide('current').trigger('leave');

                var x = 0;

                $target.prevAll().each(function() {
                    x -= $(this).outerWidth(true);
                });

                //offset
                if (this.settings.offset === 'center') {
                    x += (this.$element.width() - $target.width()) / 2;
                } else {
                    x += this.settings.offset || 0;
                }

                //fitToLimits
                if (this.settings.fitToLimits) {
                    var lastx = this.$element.width();

                    this.getSlide('last').prevAll().addBack().each(function() {
                        lastx -= $(this).outerWidth(true);
                    });

                    if (!this.settings.fluid) {
                        this.index = $target.index();
                    }

                    if (x > 0) {
                        x = 0;
                    } else if (x < lastx) {
                        x = lastx;
                    } else {
                        this.index = $target.index();
                    }
                } else {
                    this.index = $target.index();
                }

                $target.trigger('enter');

                this.$tray.css('transform', 'translateX(' + x + 'px)');

                if (this.playing) {
                    this.stop();
                    this.play();
                }
            }
        },

        getSlides: function() {
            return this.$slides;
        },

        getSlide: function(position) {
            if (position === undefined || position === 'current') {
                return this._eq(this.index);
            }

            if (typeof position === 'object' && position.jquery && position.parent().is(this.$tray)) {
                return position;
            }

            if (position === 'first') {
                return this.$slides.first();
            }

            if (position === 'last') {
                return this.$slides.last();
            }

            if (typeof position === 'number') {
                return this._eq(position);
            }

            if (/^[0-9]+$/.test(position)) {
                return this._eq(parseInt(position));
            }

            if (/^\+[0-9]+$/.test(position)) {
                position = this.index + (parseInt(position.substr(1), 10));

                return this._eq(position);
            }

            if (/^\-[0-9]+$/.test(position)) {
                position = this.index - (parseInt(position.substr(1), 10));

                return this._eq(position);
            }
        },

        _eq: function(position) {
            if (position < 0) {
                return this.$slides.first();
            }

            if (position >= this.$slides.length) {
                return this.$slides.last();
            }

            return this.$slides.eq(position);
        },

        play: function() {
            var that = this,
                index = '+1';

            var go = function() {
                if (that.getSlide('last').index() === that.index) {
                    index = '-1';
                } else if (that.index === 0) {
                    index = '+1';
                }

                that['goto'](index);
            };

            this.playing = true;
            this.timeout = setTimeout(go, this.settings.interval);
        },

        stop: function() {
            clearTimeout(this.timeout);
            this.playing = false;
        },

        destroy: function() {
            this.$slides.off('.' + pluginName);

            if (this.$buttons) {
                this.$buttons.off('.' + pluginName);
            }
        }
    };

    $.fn[pluginName] = function(options) {
        if ((options === undefined) || (typeof options === 'object')) {
            return this.each(function() {
                if (!$.data(this, 'plugin_' + pluginName)) {
                    $.data(this, 'plugin_' + pluginName, new Plugin(this, options));
                }
            });
        }

        if ((typeof options === 'string') && (options[0] !== '_') && (options !== 'init')) {
            var returns, args = arguments;

            this.each(function() {
                var instance = $.data(this, 'plugin_' + pluginName);

                if ((instance instanceof Plugin) && (typeof instance[options] === 'function')) {
                    returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));
                }

                if (options === 'destroy') {
                    $.data(this, 'plugin_' + pluginName, null);
                }
            });

            return returns !== undefined ? returns : this;
        }
    };
}));<|endoftext|>


<commit_before>const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPLugin = require('html-webpack-plugin')
const OfflinePlugin = require('offline-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const autoprefixer = require('autoprefixer')
const SvgSpritePlugin = require('svg-sprite-loader/plugin')

const debug = process.env.NODE_ENV !== 'production'

module.exports = {
  context: path.join(__dirname, 'src'),
  devtool: debug ? 'cheap-module-eval-source-map' : 'source-map',
  entry: {
    app: [
      'react-hot-loader/patch',
      './client.js',
    ],
  },
  output: {
    path: path.join(__dirname, 'public'),
    filename: debug ? '[name].js' : '[name].[chunkhash].js',
    publicPath: '/',
  },
  performance: {
    hints: false,
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader',
      },
      {
        test: /\.scss$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              minimize: true,
              importLoaders: 2,
              modules: true,
              localIdentName: debug ? '[folder]__[local]--[hash:base64:5]' : null,
            },
          },
          {
            loader: 'postcss-loader',
            options: {
              plugins: [
                autoprefixer(),
              ],
            },
          },
          'sass-loader',
        ],
      },
      {
        test: /\.svg$/,
        loader: {
          loader: 'svg-sprite-loader',
          options: {
            symbolId: '[name]',
          },
        },
      },
    ],
  },
  stats: {
    children: false,
    chunks: false,
    chunkModules: false,
    chunkOrigins: false,
    modules: false,
    maxModules: 0,
  },
  devServer: {
    host: '0.0.0.0',
    contentBase: path.join(__dirname, 'public'),
    historyApiFallback: true,
    hot: true,
    quiet: true,
    disableHostCheck: true,
  },
  plugins: debug ? [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(),
    new FriendlyErrorsPlugin(),
    new SvgSpritePlugin(),
    new HtmlWebpackPLugin({
      template: './index.html',
    }),
  ] : [
    new webpack.NamedModulesPlugin(),
    new SvgSpritePlugin(),
    new HtmlWebpackPLugin({
      template: './index.html',
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: module => module.context && module.context.indexOf('node_modules') !== -1,
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      minChunks: Infinity,
    }),
    new OfflinePlugin({
      version: '[hash]',
      AppCache: false,
      ServiceWorker: {
        events: true,
      },
    }),
  ],
}
<commit_msg>Minify html<commit_after>const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPLugin = require('html-webpack-plugin')
const OfflinePlugin = require('offline-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const autoprefixer = require('autoprefixer')
const SvgSpritePlugin = require('svg-sprite-loader/plugin')

const debug = process.env.NODE_ENV !== 'production'

module.exports = {
  entry: {
    app: [
      'react-hot-loader/patch',
      './client.js',
    ],
  },
  output: {
    path: path.join(__dirname, 'public'),
    filename: debug ? '[name].js' : '[name].[chunkhash].js',
    publicPath: '/',
  },
  context: path.join(__dirname, 'src'),
  devtool: debug ? 'cheap-module-eval-source-map' : 'source-map',
  performance: {
    hints: false,
  },
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules)/,
        loader: 'babel-loader',
      },
      {
        test: /\.scss$/,
        use: [
          'style-loader',
          {
            loader: 'css-loader',
            options: {
              minimize: true,
              importLoaders: 2,
              modules: true,
              localIdentName: debug ? '[folder]__[local]--[hash:base64:5]' : null,
            },
          },
          {
            loader: 'postcss-loader',
            options: {
              plugins: [
                autoprefixer(),
              ],
            },
          },
          'sass-loader',
        ],
      },
      {
        test: /\.svg$/,
        loader: {
          loader: 'svg-sprite-loader',
          options: {
            symbolId: '[name]',
          },
        },
      },
    ],
  },
  stats: {
    children: false,
    chunks: false,
    chunkModules: false,
    chunkOrigins: false,
    modules: false,
    maxModules: 0,
  },
  devServer: {
    host: '0.0.0.0',
    contentBase: path.join(__dirname, 'public'),
    historyApiFallback: true,
    hot: true,
    quiet: true,
    disableHostCheck: true,
  },
  plugins: debug ? [
    new webpack.HotModuleReplacementPlugin(),
    new webpack.NamedModulesPlugin(),
    new FriendlyErrorsPlugin(),
    new SvgSpritePlugin(),
    new HtmlWebpackPLugin({
      template: './index.html',
    }),
  ] : [
    new webpack.NamedModulesPlugin(),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'vendor',
      minChunks: module => module.context && module.context.indexOf('node_modules') !== -1,
    }),
    new webpack.optimize.CommonsChunkPlugin({
      name: 'manifest',
      minChunks: Infinity,
    }),
    new SvgSpritePlugin(),
    new HtmlWebpackPLugin({
      template: './index.html',
      minify: {
        collapseWhitespace: true,
        preserveLineBreaks: true,
      },
    }),
    new OfflinePlugin({
      version: '[hash]',
      AppCache: false,
      ServiceWorker: {
        events: true,
      },
    }),
  ],
}
<|endoftext|>


<commit_before>// Copyright 2012 Joyent, Inc.  All rights reserved.

var assert = require('assert-plus');
var crypto = require('crypto');
var http = require('http');

var sprintf = require('util').format;

///--- Globals

var Algorithms = {
  'rsa-sha1': true,
  'rsa-sha256': true,
  'rsa-sha512': true,
  'dsa-sha1': true,
  'hmac-sha1': true,
  'hmac-sha256': true,
  'hmac-sha512': true
};

var Authorization =
  'Signature keyId="%s",algorithm="%s",headers="%s",signature="%s"';

///--- Specific Errors

function MissingHeaderError(message) {
    this.name = 'MissingHeaderError';
    this.message = message;
    this.stack = (new Error()).stack;
}
MissingHeaderError.prototype = new Error();

function InvalidAlgorithmError(message) {
    this.name = 'InvalidAlgorithmError';
    this.message = message;
    this.stack = (new Error()).stack;
}
InvalidAlgorithmError.prototype = new Error();

function StrictParsingError(message) {
    this.name = 'StrictParsingError';
    this.message = message;
    this.stack = (new Error()).stack;
}

StrictParsingError.prototype = new Error();

///--- Internal Functions

function _pad(val) {
  if (parseInt(val, 10) < 10) {
    val = '0' + val;
  }
  return val;
}

function _rfc1123() {
  var date = new Date();

  var months = ['Jan',
                'Feb',
                'Mar',
                'Apr',
                'May',
                'Jun',
                'Jul',
                'Aug',
                'Sep',
                'Oct',
                'Nov',
                'Dec'];
  var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
  return days[date.getUTCDay()] + ', ' +
    _pad(date.getUTCDate()) + ' ' +
    months[date.getUTCMonth()] + ' ' +
    date.getUTCFullYear() + ' ' +
    _pad(date.getUTCHours()) + ':' +
    _pad(date.getUTCMinutes()) + ':' +
    _pad(date.getUTCSeconds()) +
    ' GMT';
}

///--- Exported API

module.exports = {

  /**
   * Adds an 'Authorization' header to an http.ClientRequest object.
   *
   * Note that this API will add a Date header if it's not already set. Any
   * other headers in the options.headers array MUST be present, or this
   * will throw.
   *
   * You shouldn't need to check the return type; it's just there if you want
   * to be pedantic.
   *
   * The optional flag indicates whether parsing should use strict enforcement
   * of the version draft-cavage-http-signatures-04 of the spec or beyond.
   * The default is to be loose and support
   * older versions for compatibility.
   *
   * @param {Object} request an instance of http.ClientRequest.
   * @param {Object} options signing parameters object:
   *                   - {String} keyId required.
   *                   - {String} key required (either a PEM or HMAC key).
   *                   - {Array} headers optional; defaults to ['date'].
   *                   - {String} algorithm optional; defaults to 'rsa-sha256'.
   *                   - {String} httpVersion optional; defaults to '1.1'.
   *                   - {Boolean} strict optional; defaults to 'false'.
   * @return {Boolean} true if Authorization (and optionally Date) were added.
   * @throws {TypeError} on bad parameter types (input).
   * @throws {InvalidAlgorithmError} if algorithm was bad.
   * @throws {MissingHeaderError} if a header to be signed was specified but
   *                              was not present.
   */
  signRequest: function signRequest(request, options) {
    assert.object(request, 'request');
    assert.object(options, 'options');
    assert.optionalString(options.algorithm, 'options.algorithm');
    assert.string(options.keyId, 'options.keyId');
    assert.optionalArrayOfString(options.headers, 'options.headers');
    assert.optionalString(options.httpVersion, 'options.httpVersion');

    if (!request.getHeader('Date'))
      request.setHeader('Date', _rfc1123());
    if (!options.headers)
      options.headers = ['date'];
    if (!options.algorithm)
      options.algorithm = 'rsa-sha256';
    if (!options.httpVersion)
      options.httpVersion = '1.1';

    options.algorithm = options.algorithm.toLowerCase();

    if (!Algorithms[options.algorithm])
      throw new InvalidAlgorithmError(options.algorithm + ' is not supported');

    var i;
    var stringToSign = '';
    for (i = 0; i < options.headers.length; i++) {
      if (typeof (options.headers[i]) !== 'string')
        throw new TypeError('options.headers must be an array of Strings');

      var h = options.headers[i].toLowerCase();

      if (h === 'request-line') {
        if (!options.strict) {
          /**
           * We allow headers from the older spec drafts if strict parsing isn't
           * specified in options.
           */
          stringToSign +=
            request.method + ' ' + request.path + ' HTTP/' +
            options.httpVersion;
        } else {
          /* Strict parsing doesn't allow older draft headers. */
          throw (new StrictParsingError('request-line is not a valid header ' +
            'with strict parsing enabled.'));
        }
      } else if (h === '(request-target)') {
        stringToSign +=
          '(request-target): ' + request.method.toLowerCase() + ' ' +
          request.path;
      } else {
        var value = request.getHeader(h);
        if (value === undefined || value === '') {
          throw new MissingHeaderError(h + ' was not in the request');
        }
        stringToSign += h + ': ' + value;
      }

      if ((i + 1) < options.headers.length)
        stringToSign += '\n';
    }

    var alg = options.algorithm.match(/(hmac|rsa)-(\w+)/);
    var signature;
    if (alg[1] === 'hmac') {
      var hmac = crypto.createHmac(alg[2].toUpperCase(), options.key);
      hmac.update(stringToSign);
      signature = hmac.digest('base64');
    } else {
      var signer = crypto.createSign(options.algorithm.toUpperCase());
      signer.update(stringToSign);
      signature = signer.sign(options.key, 'base64');
      assert.notStrictEqual(signature, '', 'empty signature produced');
    }

    request.setHeader('Authorization', sprintf(Authorization,
                                               options.keyId,
                                               options.algorithm,
                                               options.headers.join(' '),
                                               signature));

    return true;
  }

};
<commit_msg>Clean up Error subclasses in signer.js<commit_after>// Copyright 2012 Joyent, Inc.  All rights reserved.

var assert = require('assert-plus');
var crypto = require('crypto');
var http = require('http');
var util = require('util');

var sprintf = require('util').format;

///--- Globals

var Algorithms = {
  'rsa-sha1': true,
  'rsa-sha256': true,
  'rsa-sha512': true,
  'dsa-sha1': true,
  'hmac-sha1': true,
  'hmac-sha256': true,
  'hmac-sha512': true
};

var Authorization =
  'Signature keyId="%s",algorithm="%s",headers="%s",signature="%s"';

///--- Specific Errors

function HttpSignatureError(message, caller) {
  if (Error.captureStackTrace)
    Error.captureStackTrace(this, caller || HttpSignatureError);

  this.message = message;
  this.name = caller.name;
}
util.inherits(HttpSignatureError, Error);

function MissingHeaderError(message) {
  HttpSignatureError.call(this, message, MissingHeaderError);
}
util.inherits(MissingHeaderError, HttpSignatureError);

function StrictParsingError(message) {
  HttpSignatureError.call(this, message, StrictParsingError);
}
util.inherits(StrictParsingError, HttpSignatureError);

function InvalidAlgorithmError(message) {
  HttpSignatureError.call(this, message, InvalidAlgorithmError);
}
util.inherits(InvalidAlgorithmError, HttpSignatureError);

///--- Internal Functions

function _pad(val) {
  if (parseInt(val, 10) < 10) {
    val = '0' + val;
  }
  return val;
}

function _rfc1123() {
  var date = new Date();

  var months = ['Jan',
                'Feb',
                'Mar',
                'Apr',
                'May',
                'Jun',
                'Jul',
                'Aug',
                'Sep',
                'Oct',
                'Nov',
                'Dec'];
  var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
  return days[date.getUTCDay()] + ', ' +
    _pad(date.getUTCDate()) + ' ' +
    months[date.getUTCMonth()] + ' ' +
    date.getUTCFullYear() + ' ' +
    _pad(date.getUTCHours()) + ':' +
    _pad(date.getUTCMinutes()) + ':' +
    _pad(date.getUTCSeconds()) +
    ' GMT';
}

///--- Exported API

module.exports = {

  /**
   * Adds an 'Authorization' header to an http.ClientRequest object.
   *
   * Note that this API will add a Date header if it's not already set. Any
   * other headers in the options.headers array MUST be present, or this
   * will throw.
   *
   * You shouldn't need to check the return type; it's just there if you want
   * to be pedantic.
   *
   * The optional flag indicates whether parsing should use strict enforcement
   * of the version draft-cavage-http-signatures-04 of the spec or beyond.
   * The default is to be loose and support
   * older versions for compatibility.
   *
   * @param {Object} request an instance of http.ClientRequest.
   * @param {Object} options signing parameters object:
   *                   - {String} keyId required.
   *                   - {String} key required (either a PEM or HMAC key).
   *                   - {Array} headers optional; defaults to ['date'].
   *                   - {String} algorithm optional; defaults to 'rsa-sha256'.
   *                   - {String} httpVersion optional; defaults to '1.1'.
   *                   - {Boolean} strict optional; defaults to 'false'.
   * @return {Boolean} true if Authorization (and optionally Date) were added.
   * @throws {TypeError} on bad parameter types (input).
   * @throws {InvalidAlgorithmError} if algorithm was bad.
   * @throws {MissingHeaderError} if a header to be signed was specified but
   *                              was not present.
   */
  signRequest: function signRequest(request, options) {
    assert.object(request, 'request');
    assert.object(options, 'options');
    assert.optionalString(options.algorithm, 'options.algorithm');
    assert.string(options.keyId, 'options.keyId');
    assert.optionalArrayOfString(options.headers, 'options.headers');
    assert.optionalString(options.httpVersion, 'options.httpVersion');

    if (!request.getHeader('Date'))
      request.setHeader('Date', _rfc1123());
    if (!options.headers)
      options.headers = ['date'];
    if (!options.algorithm)
      options.algorithm = 'rsa-sha256';
    if (!options.httpVersion)
      options.httpVersion = '1.1';

    options.algorithm = options.algorithm.toLowerCase();

    if (!Algorithms[options.algorithm])
      throw new InvalidAlgorithmError(options.algorithm + ' is not supported');

    var i;
    var stringToSign = '';
    for (i = 0; i < options.headers.length; i++) {
      if (typeof (options.headers[i]) !== 'string')
        throw new TypeError('options.headers must be an array of Strings');

      var h = options.headers[i].toLowerCase();

      if (h === 'request-line') {
        if (!options.strict) {
          /**
           * We allow headers from the older spec drafts if strict parsing isn't
           * specified in options.
           */
          stringToSign +=
            request.method + ' ' + request.path + ' HTTP/' +
            options.httpVersion;
        } else {
          /* Strict parsing doesn't allow older draft headers. */
          throw (new StrictParsingError('request-line is not a valid header ' +
            'with strict parsing enabled.'));
        }
      } else if (h === '(request-target)') {
        stringToSign +=
          '(request-target): ' + request.method.toLowerCase() + ' ' +
          request.path;
      } else {
        var value = request.getHeader(h);
        if (value === undefined || value === '') {
          throw new MissingHeaderError(h + ' was not in the request');
        }
        stringToSign += h + ': ' + value;
      }

      if ((i + 1) < options.headers.length)
        stringToSign += '\n';
    }

    var alg = options.algorithm.match(/(hmac|rsa)-(\w+)/);
    var signature;
    if (alg[1] === 'hmac') {
      var hmac = crypto.createHmac(alg[2].toUpperCase(), options.key);
      hmac.update(stringToSign);
      signature = hmac.digest('base64');
    } else {
      var signer = crypto.createSign(options.algorithm.toUpperCase());
      signer.update(stringToSign);
      signature = signer.sign(options.key, 'base64');
      assert.notStrictEqual(signature, '', 'empty signature produced');
    }

    request.setHeader('Authorization', sprintf(Authorization,
                                               options.keyId,
                                               options.algorithm,
                                               options.headers.join(' '),
                                               signature));

    return true;
  }

};
<|endoftext|>


<commit_before>/*
 * JavaScript DOM tools library
 * 2014-11-14
 * v0.1.6
 *
 * By mysegfault <maxime.alexandre@mobile-spot.com>, https://github.com/mysegfault/js-dom-tools
 *
 * MIT Licence
 */

require.config({
	map: {
		'*': {
			'css': 'require-css/css'
		}
	}
});

define([], function() {

	function loadAsyncScript(src, id, callback) {
		if (typeof src !== 'string') {
			console.error('src parameter is invalid: [' + src + ']');
			return;
		}
		var tag = document.createElement('script');
		tag.src = src;
		tag.async = true;
		if (typeof id === 'string' && isEmpty(id) === false) {
			tag.id = id;
		}

		if (typeof callback === 'function') {
			tag.addEventListener("load", function load(event) {
				tag.removeEventListener("load", load, false);
				callback(event);
			}, false);
		}

		document.body.appendChild(tag);
	}

	function loadAsyncCss(src, callback) {
		if (typeof src !== 'string') {
			console.error('src parameter is invalid: [' + src + ']');
			return;
		}

		require(['css!' + src], function() {
			if (typeof callback === 'function') {
				callback();
			}
		});

//		var tag = document.createElement('link');
//		tag.rel = 'stylesheet';
//		tag.href = src;
//		tag.async = true;

//		if (typeof callback === 'function') {
//			var called = false;
//			tag.onload = function() {
//				if (called === false) {
//					called = true;
//					callback(event);
//				}
//				tag.onload = null;
//			};

//			tag.addEventListener('load', function load(event) {
//				if (called === false) {
//					called = true;
//					callback(event);
//				}
//				tag.removeEventListener('load', load, false);
//			}, false);
//		}

//		document.head.appendChild(tag);
	}

	function findParentNodeWithNodeName(element, nodeName) {
		if (element === null || typeof element !== 'object') {
			return null;
		}
		if (typeof nodeName !== 'string') {
			console.error('className parameter is not valid: ' + nodeName);
			return null;
		}

		if (element.nodeName.toLowerCase() === 'body') {
			return null;
		}

		if (element.nodeName.toLowerCase() === nodeName.toLowerCase()) {
			return element;
		}
		else {
			return findParentNodeWithNodeName(element.parentNode, nodeName);
		}
	}

	function findParentNodeWithClassName(element, className) {

		if (element === null || typeof element !== 'object') {
			return null;
		}
		if (typeof className !== 'string') {
			console.error('className parameter is not valid: ' + className);
			return null;
		}

		if (element.nodeName.toLowerCase() === 'body') {
			return null;
		}

		if (element.classList.contains(className) === true) {
			return element;
		}
		else {
			return findParentNodeWithClassName(element.parentNode, className);
		}
	}

	function findParentNodeWithAttribute(element, attributeName) {

		if (element === null || typeof element !== 'object') {
			return null;
		}
		if (typeof attributeName !== 'string') {
			console.error('attributeName parameter is not valid: ' + attributeName);
			return null;
		}
		if (typeof element.getAttribute !== 'function') {
			return null;
		}

		if (element.getAttribute(attributeName) !== null) {
			return element;
		}
		else {
			return findParentNodeWithAttribute(element.parentNode, attributeName);
		}
	}

	function objectTotalLength(object) {

		if (typeof object !== 'object') {
			console.error('objectTotalLength: object is not an object. ', object);
			return 0;
		}

		if ('length' in object) {
			return object.length;
		}
		if (typeof object !== 'object') {
			return 0;
		}

		var totalLength = 0;
		for (var i in object) {
			totalLength += objectTotalLength(object[i]);
		}
		return totalLength;
	}

	function getOffsetSum(elem) {
		var top = 0, left = 0;

		while (elem) {
			top = top + parseInt(elem.offsetTop);
			left = left + parseInt(elem.offsetLeft);
			elem = elem.offsetParent;
		}

		return {top: top, left: left};
	}

	function isEmpty(data) {
		if (data === null || typeof data === 'undefined') {
			return true;
		}
		if (typeof data.length === 'number' && data.length === 0) {
			return true;
		}
		if (typeof data === 'string' && data.trim() === '') {
			return true;
		}

		// if it's a DOM element, returns true because not null
		// needed for iOS
		if (typeof data === 'object' && isDOMElement(data) === true) {
			return false;
		}
		if (typeof data === 'object' && Object.getOwnPropertyNames(data).length === 0) {
			return true;
		}

		return false;
	}

	function getItemHeight(element) {
		if (typeof element === 'undefined' || element === null) {
			console.error('getItemHeight: item is invalid', element);
			return 0;
		}
		var cs = window.getComputedStyle(element, null);
		if (isEmpty(cs) === true) {
			console.error('Could not get getComputedStyle of ', element);
			return 0;
		}
		if (cs.height === 'auto') {
			return 0;
		}
		var height = parseInt(cs.height.replace('px', ''));
		if (isNaN(height) === true) {
			console.error('getItemHeight: item height is invalid', element);
			height = 0;
		}
		return height;
	}

	function getItemWidth(element) {
		if (typeof element === 'undefined' || element === null) {
			console.error('getItemHeight: item is invalid', element);
			return 0;
		}
		var cs = window.getComputedStyle(element, null);
		if (isEmpty(cs) === true) {
			console.error('Could not get getComputedStyle of ', element);
			return 0;
		}
		if (cs.width === 'auto') {
			return 0;
		}
		var width = parseInt(cs.width.replace('px', ''));
		if (isNaN(width) === true) {
			console.error('getItemWidth: item width is invalid', element);
			width = 0;
		}
		return width;
	}

	function removeElement(element) {
		if (isEmpty(element) === true) {
			return;
		}
		var parent = element.parentNode;
		if (isEmpty(parent) === true) {
			console.error('This item has not parent', element, ' so it cannot be removed.');
			return;
		}
		parent.removeChild(element);
	}

	function loadAsyncImage(src, id, callback) {
		if (typeof src !== 'string') {
			console.error('src parameter is invalid: [' + src + ']');
			return;
		}
		var tag = document.createElement('img');
		tag.src = src;
		tag.async = true;
		tag.style.visibility = 'hidden';
		tag.style.position = 'absolute';
		if (typeof id === 'string' && isEmpty(id) === false) {
			tag.id = id;
		}

		if (typeof callback === 'function') {
			tag.addEventListener('load', function load(event) {
				tag.removeEventListener('load', load, false);
				callback(event);
			}, false);
		}

		document.body.appendChild(tag);
	}

	// see http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object
	function isDOMElement(obj) {
		try {
			//Using W3 DOM2 (works for FF, Opera and Chrom)
			return obj instanceof HTMLElement;
		}
		catch (e) {
			//Browsers not supporting W3 DOM2 don't have HTMLElement and
			//an exception is thrown and we end up here. Testing some
			//properties that all elements have. (works on IE7)
			return (typeof obj === "object") &&
				(obj.nodeType === 1) && (typeof obj.style === "object") &&
				(typeof obj.ownerDocument === "object");
		}
	}

	return {
		loadAsyncScript: loadAsyncScript,
		loadAsyncCss: loadAsyncCss,
		findParentNodeWithNodeName: findParentNodeWithNodeName,
		findParentNodeWithClassName: findParentNodeWithClassName,
		findParentNodeWithAttribute: findParentNodeWithAttribute,
		objectTotalLength: objectTotalLength,
		getOffsetSum: getOffsetSum,
		isEmpty: isEmpty,
		getItemHeight: getItemHeight,
		getItemWidth: getItemWidth,
		removeElement: removeElement,
		loadAsyncImage: loadAsyncImage,
		isDOMElement: isDOMElement
	};

});
<commit_msg>fix: IE 10 + 11 do not manage isEmpty() on object... (IE9 does)... OMG!<commit_after>/*
 * JavaScript DOM tools library
 * 2014-11-14
 * v0.1.6
 *
 * By mysegfault <maxime.alexandre@mobile-spot.com>, https://github.com/mysegfault/js-dom-tools
 *
 * MIT Licence
 */

require.config({
	map: {
		'*': {
			'css': 'require-css/css'
		}
	}
});

define([], function() {

	function loadAsyncScript(src, id, callback) {
		if (typeof src !== 'string') {
			console.error('src parameter is invalid: [' + src + ']');
			return;
		}
		var tag = document.createElement('script');
		tag.src = src;
		tag.async = true;
		if (typeof id === 'string' && isEmpty(id) === false) {
			tag.id = id;
		}

		if (typeof callback === 'function') {
			tag.addEventListener("load", function load(event) {
				tag.removeEventListener("load", load, false);
				callback(event);
			}, false);
		}

		document.body.appendChild(tag);
	}

	function loadAsyncCss(src, callback) {
		if (typeof src !== 'string') {
			console.error('src parameter is invalid: [' + src + ']');
			return;
		}

		require(['css!' + src], function() {
			if (typeof callback === 'function') {
				callback();
			}
		});

//		var tag = document.createElement('link');
//		tag.rel = 'stylesheet';
//		tag.href = src;
//		tag.async = true;

//		if (typeof callback === 'function') {
//			var called = false;
//			tag.onload = function() {
//				if (called === false) {
//					called = true;
//					callback(event);
//				}
//				tag.onload = null;
//			};

//			tag.addEventListener('load', function load(event) {
//				if (called === false) {
//					called = true;
//					callback(event);
//				}
//				tag.removeEventListener('load', load, false);
//			}, false);
//		}

//		document.head.appendChild(tag);
	}

	function findParentNodeWithNodeName(element, nodeName) {
		if (element === null || typeof element !== 'object') {
			return null;
		}
		if (typeof nodeName !== 'string') {
			console.error('className parameter is not valid: ' + nodeName);
			return null;
		}

		if (element.nodeName.toLowerCase() === 'body') {
			return null;
		}

		if (element.nodeName.toLowerCase() === nodeName.toLowerCase()) {
			return element;
		}
		else {
			return findParentNodeWithNodeName(element.parentNode, nodeName);
		}
	}

	function findParentNodeWithClassName(element, className) {

		if (element === null || typeof element !== 'object') {
			return null;
		}
		if (typeof className !== 'string') {
			console.error('className parameter is not valid: ' + className);
			return null;
		}

		if (element.nodeName.toLowerCase() === 'body') {
			return null;
		}

		if (element.classList.contains(className) === true) {
			return element;
		}
		else {
			return findParentNodeWithClassName(element.parentNode, className);
		}
	}

	function findParentNodeWithAttribute(element, attributeName) {

		if (element === null || typeof element !== 'object') {
			return null;
		}
		if (typeof attributeName !== 'string') {
			console.error('attributeName parameter is not valid: ' + attributeName);
			return null;
		}
		if (typeof element.getAttribute !== 'function') {
			return null;
		}

		if (element.getAttribute(attributeName) !== null) {
			return element;
		}
		else {
			return findParentNodeWithAttribute(element.parentNode, attributeName);
		}
	}

	function objectTotalLength(object) {

		if (typeof object !== 'object') {
			console.error('objectTotalLength: object is not an object. ', object);
			return 0;
		}

		if ('length' in object) {
			return object.length;
		}
		if (typeof object !== 'object') {
			return 0;
		}

		var totalLength = 0;
		for (var i in object) {
			totalLength += objectTotalLength(object[i]);
		}
		return totalLength;
	}

	function getOffsetSum(elem) {
		var top = 0, left = 0;

		while (elem) {
			top = top + parseInt(elem.offsetTop);
			left = left + parseInt(elem.offsetLeft);
			elem = elem.offsetParent;
		}

		return {top: top, left: left};
	}

	function isEmpty(data) {
		if (data === null || typeof data === 'undefined') {
			return true;
		}
		if (typeof data.length === 'number' && data.length === 0) {
			return true;
		}
		if (typeof data === 'string' && data.trim() === '') {
			return true;
		}

		// if it's a DOM element, returns true because not null
		// needed for iOS
		if (typeof data === 'object' && isDOMElement(data) === true) {
			return false;
		}
		if (typeof data === 'object' && Object.getOwnPropertyNames(data).length === 0) {
			return true;
		}

		return false;
	}

	function getItemHeight(element) {
		if (typeof element === 'undefined' || element === null) {
			console.error('getItemHeight: item is invalid', element);
			return 0;
		}
		try {
			var cs = window.getComputedStyle(element, null);
		}
		catch (error) {
			console.error('Could not get getComputedStyle of ', element, error);
			return 0;
		}
		if (typeof cs.height !== 'string') {
			console.error('Could not get getComputedStyle of ', element, cs);
			return 0;
		}
		if (cs.height === 'auto') {
			return 0;
		}
		var height = parseInt(cs.height.replace('px', ''));
		if (isNaN(height) === true) {
			console.error('getItemHeight: item height is invalid', element);
			height = 0;
		}
		return height;
	}

	function getItemWidth(element) {
		if (typeof element === 'undefined' || element === null) {
			console.error('getItemHeight: item is invalid', element);
			return 0;
		}
		try {
			var cs = window.getComputedStyle(element, null);
		}
		catch (error) {
			console.error('Could not get getComputedStyle of ', element, error);
			return 0;
		}
		if (typeof cs.height !== 'string') {
			console.error('Could not get getComputedStyle of ', element, cs);
			return 0;
		}
		if (cs.width === 'auto') {
			return 0;
		}
		var width = parseInt(cs.width.replace('px', ''));
		if (isNaN(width) === true) {
			console.error('getItemWidth: item width is invalid', element);
			width = 0;
		}
		return width;
	}

	function removeElement(element) {
		if (isEmpty(element) === true) {
			return;
		}
		var parent = element.parentNode;
		if (isEmpty(parent) === true) {
			console.error('This item has not parent', element, ' so it cannot be removed.');
			return;
		}
		parent.removeChild(element);
	}

	function loadAsyncImage(src, id, callback) {
		if (typeof src !== 'string') {
			console.error('src parameter is invalid: [' + src + ']');
			return;
		}
		var tag = document.createElement('img');
		tag.src = src;
		tag.async = true;
		tag.style.visibility = 'hidden';
		tag.style.position = 'absolute';
		if (typeof id === 'string' && isEmpty(id) === false) {
			tag.id = id;
		}

		if (typeof callback === 'function') {
			tag.addEventListener('load', function load(event) {
				tag.removeEventListener('load', load, false);
				callback(event);
			}, false);
		}

		document.body.appendChild(tag);
	}

	// see http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object
	function isDOMElement(obj) {
		try {
			//Using W3 DOM2 (works for FF, Opera and Chrom)
			return obj instanceof HTMLElement;
		}
		catch (e) {
			//Browsers not supporting W3 DOM2 don't have HTMLElement and
			//an exception is thrown and we end up here. Testing some
			//properties that all elements have. (works on IE7)
			return (typeof obj === "object") &&
				(obj.nodeType === 1) && (typeof obj.style === "object") &&
				(typeof obj.ownerDocument === "object");
		}
	}

	return {
		loadAsyncScript: loadAsyncScript,
		loadAsyncCss: loadAsyncCss,
		findParentNodeWithNodeName: findParentNodeWithNodeName,
		findParentNodeWithClassName: findParentNodeWithClassName,
		findParentNodeWithAttribute: findParentNodeWithAttribute,
		objectTotalLength: objectTotalLength,
		getOffsetSum: getOffsetSum,
		isEmpty: isEmpty,
		getItemHeight: getItemHeight,
		getItemWidth: getItemWidth,
		removeElement: removeElement,
		loadAsyncImage: loadAsyncImage,
		isDOMElement: isDOMElement
	};

});
<|endoftext|>


<commit_before>const webpack           = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const BabiliPlugin      = require('babili-webpack-plugin');

const path = require('path');

module.exports = {
    entry: {
        main: ['./src/js/main.js']
    },
    target: 'electron',
    output: {
        path: './src/dist',
        filename: 'bundle.js',
        publicPath: ''
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                loader: 'babel',
                exclude: /node_modules/
            },
            {
                test: /\.json$/,
                loader: 'json',
            },
            {
                test: /\.css$/,
                loader: ExtractTextPlugin.extract('css-loader')
            },
            {
                test: /\.scss$/,
                loader: ExtractTextPlugin.extract('css-loader!sass-loader')
            },
            {
                test: /\.(eot|woff|ttf)([\?]?.*)$/,
                loader: 'url-loader?name=fonts/[name].[ext]',
            },
            {
                test: /\.(png|jpg)([\?]?.*)$/,
                loader: 'file-loader?name=img/[name].[ext]',
                exclude: /node_modules/
            },
            {
                test: /\.svg$/,
                loader: 'svg-inline',
                include: path.resolve(__dirname, 'src')
            },
            {
                test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
                loader: 'url?mimetype=image/svg+xml',
                include: /node_modules/
            }
        ]
    },
    plugins: [
        new BabiliPlugin(),
        new webpack.DefinePlugin({ 'process.env': { 'NODE_ENV': '"production"' } }),
        new ExtractTextPlugin('main.css', { allChunks: true }),
    ]
};
<commit_msg>Fix eslint<commit_after>const webpack           = require('webpack');
const ExtractTextPlugin = require('extract-text-webpack-plugin');
const BabiliPlugin      = require('babili-webpack-plugin');

const path = require('path');

module.exports = {
    entry: {
        main: ['./src/js/main.js']
    },
    target: 'electron',
    output: {
        path: './src/dist',
        filename: 'bundle.js',
        publicPath: ''
    },
    module: {
        loaders: [
            {
                test: /\.js$/,
                loader: 'babel',
                exclude: /node_modules/
            },
            {
                test: /\.json$/,
                loader: 'json',
            },
            {
                test: /\.css$/,
                loader: ExtractTextPlugin.extract('css-loader')
            },
            {
                test: /\.scss$/,
                loader: ExtractTextPlugin.extract('css-loader!sass-loader')
            },
            {
                test: /\.(eot|woff|ttf)([?]?.*)$/,
                loader: 'url-loader?name=fonts/[name].[ext]',
            },
            {
                test: /\.(png|jpg)([?]?.*)$/,
                loader: 'file-loader?name=img/[name].[ext]',
                exclude: /node_modules/
            },
            {
                test: /\.svg$/,
                loader: 'svg-inline',
                include: path.resolve(__dirname, 'src')
            },
            {
                test: /\.svg(\?v=\d+\.\d+\.\d+)?$/,
                loader: 'url?mimetype=image/svg+xml',
                include: /node_modules/
            }
        ]
    },
    plugins: [
        new BabiliPlugin(),
        new webpack.DefinePlugin({ 'process.env': { 'NODE_ENV': '"production"' } }),
        new ExtractTextPlugin('main.css', { allChunks: true }),
    ]
};
<|endoftext|>


<commit_before>var path = require('path')
var webpack = require('webpack')

module.exports = {
  entry: {
    example: ['./example'],
  },

  output: {
    path: './dist',
    publicPath: '/dist/',
    filename: "[name].js",
  },

  resolve: {
    root: path.join(__dirname, 'node_modules'),
    alias: {
    },
    extensions: ['', '.js', '.vue', '.json'],
  },

  module: {
    loaders: [
      {
        test: /\.vue$/,
        loader: 'vue'
      },
      {
        test: /\.js$/,
        loader: 'babel',
        exclude: /node_modules/
      },
      {
        test: /\.json$/,
        loader: 'json'
      },
      {
        test: /\.html$/,
        loader: 'vue-html'
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'url',
        query: {
          limit: 10000,
          name: '[name].[ext]?[hash]'
        }
      }
    ]
  },

  babel: {
    presets: ['es2015', 'stage-0'],
    plugins: ['transform-runtime', 'transform-vue-jsx'],
  },

  devServer: {
    historyApiFallback: true,
    noInfo: true
  },
  devtool: '#eval-source-map'
}

if (process.env.NODE_ENV === 'production') {
  module.exports.devtool = '#source-map'
  // http://vuejs.github.io/vue-loader/workflow/production.html
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    }),

    new webpack.optimize.OccurenceOrderPlugin()
  ])
}
<commit_msg>fix devtool<commit_after>var path = require('path')
var webpack = require('webpack')

module.exports = {
  entry: {
    example: ['./example'],
  },

  output: {
    path: './dist',
    publicPath: '/dist/',
    filename: "[name].js",
  },

  resolve: {
    root: path.join(__dirname, 'node_modules'),
    alias: {
    },
    extensions: ['', '.js', '.vue', '.json'],
  },

  module: {
    loaders: [
      {
        test: /\.vue$/,
        loader: 'vue'
      },
      {
        test: /\.js$/,
        loader: 'babel',
        exclude: /node_modules/
      },
      {
        test: /\.json$/,
        loader: 'json'
      },
      {
        test: /\.html$/,
        loader: 'vue-html'
      },
      {
        test: /\.(png|jpg|gif|svg)$/,
        loader: 'url',
        query: {
          limit: 10000,
          name: '[name].[ext]?[hash]'
        }
      }
    ]
  },

  babel: {
    presets: ['es2015', 'stage-0'],
    plugins: ['transform-runtime', 'transform-vue-jsx'],
  },

  devServer: {
    historyApiFallback: true,
    noInfo: true
  },
  devtool: 'eval-source-map'
}

if (process.env.NODE_ENV === 'production') {
  module.exports.devtool = 'source-map'
  // http://vuejs.github.io/vue-loader/workflow/production.html
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    }),

    new webpack.optimize.OccurenceOrderPlugin()
  ])
}
<|endoftext|>