<commit_before>import { assert, stripInProduction } from 'vertical-collection/-debug/helpers';

/*
 * `SkipList` is a data structure designed with two main uses in mind:
 *
 * - Given a target value, find the index i in the list such that
 * `sum(list[0]..list[i]) <= value < sum(list[0]..list[i + 1])`
 *
 * - Given the index i (the fulcrum point) from above, get `sum(list[0]..list[i])`
 *   and `sum(list[i + 1]..list[-1])`
 *
 * The idea is that given a list of arbitrary heights or widths in pixels, we want to find
 * the index of the item such that when all of the items before it are added together, it will
 * be as close to the target (scrollTop of our container) as possible.
 *
 * This data structure acts somewhat like a Binary Search Tree. Given a list of size n, the
 * retreival time for the index is O(log n) and the update time should any values change is
 * O(log n). The space complexity is O(n log n) in bytes (using Float32Arrays helps a lot
 * here), and the initialization time is O(n log n).
 *
 * It works by constructing layer arrays, each of which is setup such that
 * `layer[i] = prevLayer[i * 2] + prevLayer[(i * 2) + 1]`. This allows us to traverse the layers
 * downward using a binary search to arrive at the index we want. We also add the values up as we
 * traverse to get the total value before and after the final index.
 */

export default class SkipList {
  constructor(length, defaultValue) {
    const values = new Float32Array(new ArrayBuffer(length * 4));

    if (typeof values.fill === 'function') {
      values.fill(defaultValue);
    } else {
      Array.prototype.fill.call(values, defaultValue);
    }

    this.length = length;
    this.defaultValue = defaultValue;

    this._initializeLayers(values, defaultValue);

    stripInProduction(() => {
      Object.preventExtensions(this);
    });
  }

  _initializeLayers(values, defaultValue) {
    const layers = [values];
    let i, length, layer, prevLayer, left, right;

    prevLayer = layer = values;
    length = values.length;

    while (length > 2) {
      length = Math.ceil(length / 2);

      layer = new Float32Array(new ArrayBuffer(length * 4));

      // TODO add explicit test
      if (defaultValue) {
        // If given a default value we assume that we can fill each
        // layer of the skip list with the previous layer's value * 2.
        // This allows us to use the `fill` method on Typed arrays, which
        // an order of magnitude faster than manually calculating each value.
        defaultValue = defaultValue * 2;
        layer.fill(defaultValue);

        left = prevLayer[(length - 1) * 2] || 0;
        right = prevLayer[((length - 1) * 2) + 1] || 0;

        // Layers are not powers of 2, and sometimes they may by odd sizes.
        // Only the last value of a layer will be different, so we calculate
        // its value manually.
        layer[length - 1] = left + right;
      } else {
        for (i = 0; i < length; i++) {
          left = prevLayer[i * 2];
          right = prevLayer[(i * 2) + 1];
          layer[i] = right ? left + right : left;
        }
      }

      layers.unshift(layer);
      prevLayer = layer;
    }

    this.total = layer.length > 0 ? layer.length > 1 ? layer[0] + layer[1] : layer[0] : 0;

    assert('total must be a number', typeof this.total === 'number');

    this.layers = layers;
    this.values = values;
  }

  find(targetValue) {
    const { layers, total, length } = this;
    const numLayers = layers.length;

    if (length === 0) {
      return { index: 0, totalBefore: 0, totalAfter: 0 };
    }

    let i, layer, left, leftIndex, rightIndex;
    let index = 0;
    let totalBefore = 0;
    let totalAfter = 0;

    targetValue = Math.min(total - 1, targetValue);

    assert('targetValue must be a number', typeof targetValue === 'number');
    assert('targetValue must be greater than or equal to 0', targetValue >= 0);
    assert('targetValue must be no more than total', targetValue < total);

    for (i = 0; i < numLayers; i++) {
      layer = layers[i];

      leftIndex = index;
      rightIndex = index + 1;

      left = layer[leftIndex];

      if (targetValue >= totalBefore + left) {
        totalBefore = totalBefore + left;
        index = rightIndex * 2;
      } else {
        index = leftIndex * 2;
      }
    }

    index = index / 2;

    totalAfter = total - totalBefore;

    assert('index must be a number', typeof index === 'number');
    assert('index must be within bounds', index >= 0 && index < this.values.length);

    return { index, totalBefore, totalAfter };
  }

  set(index, value) {
    assert('value must be a number', typeof value === 'number');
    assert('index must be a number', typeof index === 'number');
    assert('index must be within bounds', index >= 0 && index < this.values.length);

    const { layers } = this;
    const oldValue = layers[layers.length - 1][index];
    const delta = value - oldValue;

    if (delta === 0) {
      return delta;
    }

    let i, layer;

    for (i = layers.length - 1; i >= 0; i--) {
      layer = layers[i];

      layer[index] += delta;

      index = Math.floor(index / 2);
    }

    this.total += delta;

    return delta;
  }

  prepend(numPrepended) {
    const {
      values: oldValues,
      length: oldLength,
      defaultValue
    } = this;

    const newLength = numPrepended + oldLength;

    const newValues = new Float32Array(new ArrayBuffer(newLength * 4));

    newValues.set(oldValues, numPrepended);

    if (typeof newValues.fill === 'function') {
      newValues.fill(defaultValue, 0, numPrepended);
    } else {
      Array.prototype.fill.call(newValues, defaultValue, 0, numPrepended);
    }

    this.length = newLength;
    this._initializeLayers(newValues);
  }

  append(numAppended) {
    const {
      values: oldValues,
      length: oldLength,
      defaultValue
    } = this;

    const newLength = numAppended + oldLength;

    const newValues = new Float32Array(new ArrayBuffer(newLength * 4));

    newValues.set(oldValues);

    if (typeof newValues.fill === 'function') {
      newValues.fill(defaultValue, oldLength);
    } else {
      Array.prototype.fill.call(newValues, defaultValue, oldLength);
    }

    this.length = newLength;
    this._initializeLayers(newValues);
  }
}
<commit_msg>bugfix(skiplist): Don't use TypedArray.fill unless it exists (#90)<commit_after>import { assert, stripInProduction } from 'vertical-collection/-debug/helpers';

/*
 * `SkipList` is a data structure designed with two main uses in mind:
 *
 * - Given a target value, find the index i in the list such that
 * `sum(list[0]..list[i]) <= value < sum(list[0]..list[i + 1])`
 *
 * - Given the index i (the fulcrum point) from above, get `sum(list[0]..list[i])`
 *   and `sum(list[i + 1]..list[-1])`
 *
 * The idea is that given a list of arbitrary heights or widths in pixels, we want to find
 * the index of the item such that when all of the items before it are added together, it will
 * be as close to the target (scrollTop of our container) as possible.
 *
 * This data structure acts somewhat like a Binary Search Tree. Given a list of size n, the
 * retreival time for the index is O(log n) and the update time should any values change is
 * O(log n). The space complexity is O(n log n) in bytes (using Float32Arrays helps a lot
 * here), and the initialization time is O(n log n).
 *
 * It works by constructing layer arrays, each of which is setup such that
 * `layer[i] = prevLayer[i * 2] + prevLayer[(i * 2) + 1]`. This allows us to traverse the layers
 * downward using a binary search to arrive at the index we want. We also add the values up as we
 * traverse to get the total value before and after the final index.
 */

function fill(array, ...args) {
  if (typeof array.fill === 'function') {
    array.fill(...args);
  } else {
    Array.prototype.fill.call(array, args);
  }
}

export default class SkipList {
  constructor(length, defaultValue) {
    const values = new Float32Array(new ArrayBuffer(length * 4));
    fill(values, defaultValue);

    this.length = length;
    this.defaultValue = defaultValue;

    this._initializeLayers(values, defaultValue);

    stripInProduction(() => {
      Object.preventExtensions(this);
    });
  }

  _initializeLayers(values, defaultValue) {
    const layers = [values];
    let i, length, layer, prevLayer, left, right;

    prevLayer = layer = values;
    length = values.length;

    while (length > 2) {
      length = Math.ceil(length / 2);

      layer = new Float32Array(new ArrayBuffer(length * 4));

      // TODO add explicit test
      if (defaultValue) {
        // If given a default value we assume that we can fill each
        // layer of the skip list with the previous layer's value * 2.
        // This allows us to use the `fill` method on Typed arrays, which
        // an order of magnitude faster than manually calculating each value.
        defaultValue = defaultValue * 2;
        fill(layer, defaultValue);

        left = prevLayer[(length - 1) * 2] || 0;
        right = prevLayer[((length - 1) * 2) + 1] || 0;

        // Layers are not powers of 2, and sometimes they may by odd sizes.
        // Only the last value of a layer will be different, so we calculate
        // its value manually.
        layer[length - 1] = left + right;
      } else {
        for (i = 0; i < length; i++) {
          left = prevLayer[i * 2];
          right = prevLayer[(i * 2) + 1];
          layer[i] = right ? left + right : left;
        }
      }

      layers.unshift(layer);
      prevLayer = layer;
    }

    this.total = layer.length > 0 ? layer.length > 1 ? layer[0] + layer[1] : layer[0] : 0;

    assert('total must be a number', typeof this.total === 'number');

    this.layers = layers;
    this.values = values;
  }

  find(targetValue) {
    const { layers, total, length } = this;
    const numLayers = layers.length;

    if (length === 0) {
      return { index: 0, totalBefore: 0, totalAfter: 0 };
    }

    let i, layer, left, leftIndex, rightIndex;
    let index = 0;
    let totalBefore = 0;
    let totalAfter = 0;

    targetValue = Math.min(total - 1, targetValue);

    assert('targetValue must be a number', typeof targetValue === 'number');
    assert('targetValue must be greater than or equal to 0', targetValue >= 0);
    assert('targetValue must be no more than total', targetValue < total);

    for (i = 0; i < numLayers; i++) {
      layer = layers[i];

      leftIndex = index;
      rightIndex = index + 1;

      left = layer[leftIndex];

      if (targetValue >= totalBefore + left) {
        totalBefore = totalBefore + left;
        index = rightIndex * 2;
      } else {
        index = leftIndex * 2;
      }
    }

    index = index / 2;

    totalAfter = total - totalBefore;

    assert('index must be a number', typeof index === 'number');
    assert('index must be within bounds', index >= 0 && index < this.values.length);

    return { index, totalBefore, totalAfter };
  }

  set(index, value) {
    assert('value must be a number', typeof value === 'number');
    assert('index must be a number', typeof index === 'number');
    assert('index must be within bounds', index >= 0 && index < this.values.length);

    const { layers } = this;
    const oldValue = layers[layers.length - 1][index];
    const delta = value - oldValue;

    if (delta === 0) {
      return delta;
    }

    let i, layer;

    for (i = layers.length - 1; i >= 0; i--) {
      layer = layers[i];

      layer[index] += delta;

      index = Math.floor(index / 2);
    }

    this.total += delta;

    return delta;
  }

  prepend(numPrepended) {
    const {
      values: oldValues,
      length: oldLength,
      defaultValue
    } = this;

    const newLength = numPrepended + oldLength;

    const newValues = new Float32Array(new ArrayBuffer(newLength * 4));

    newValues.set(oldValues, numPrepended);
    fill(newValues, defaultValue, 0, numPrepended);

    this.length = newLength;
    this._initializeLayers(newValues);
  }

  append(numAppended) {
    const {
      values: oldValues,
      length: oldLength,
      defaultValue
    } = this;

    const newLength = numAppended + oldLength;

    const newValues = new Float32Array(new ArrayBuffer(newLength * 4));

    newValues.set(oldValues);
    fill(newValues, defaultValue, oldLength);

    this.length = newLength;
    this._initializeLayers(newValues);
  }
}
<|endoftext|>


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

	//Register a function by its name, itself (callback) and the needed time span for the check cycle
	this.RegisterLocalStorageFunction = function(name, callback) {

		//Cleanup first
		localStorage.removeItem(name);
		localStorage.removeItem(name+"Result");

		//Setting the event
		window.addEventListener('storage', function(e) {
			//Getting the params or eventually just the placeholder

			//Call the function if params are set and reset all
			if (e.key === name) {
				let result = callback(e.newValue);
				//Set result
				localStorage.setItem(name + "Result", result);
				//Reset call
				localStorage.removeItem(name);
			}
		});
	}

	this.CallLocalStorageFunction = function(name, params, callback) {
		//Check if the function is already called
		if (localStorage.getItem(name) === null && localStorage.getItem(name + "Result") === null) {

			//Call remote function
			localStorage.setItem(name, params);

			//Define timeout and event for future usage
			let timeout = {};
			let storageEvent = {};

			//Check in interval for result
			storageEvent = function(e) {
				//Check wheter the result is set
				if (e.key == name + "Result") {
					//Call callback with results
					callback(e.newValue);

					//Reset result in local storage
					localStorage.removeItem(name + "Result");

					//Dismiss listener and timeout
					clearTimeout(timeout);
					window.removeEventListener('storage', storageEvent, false);
				}
			}

			//Add listener to event
			window.addEventListener('storage', storageEvent);

			//Start timout to cancel listener if no result is set, hence no remote function was called
			timeout = setTimeout(function() {
				//Dismiss interval
				clearTimeout(timeout);
				//Clean up
				localStorage.removeItem(name);
				window.removeEventListener('storage', storageEvent, false);
			}, resultTimeout);
		}
	}
};
<commit_msg>Update communicator2.js<commit_after>"use strict";
/*
The MIT License (MIT)
Copyright (c) 2016 Astasian
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
https://github.com/Astasian/LocalStorageFunctionCall
*/
function LsFunction() {
	let resultTimeout = 500;

	//Register a function by its name, itself (callback) and the needed time span for the check cycle
	this.RegisterLocalStorageFunction = function(name, callback) {

		//Cleanup first
		localStorage.removeItem(name);
		localStorage.removeItem(name+"Result");

		//Setting the event
		window.addEventListener('storage', function(e) {
			//Getting the params or eventually just the placeholder

			//Call the function if params are set and reset all
			if (e.key === name) {
				let result = callback(e.newValue);
				//Set result
				localStorage.setItem(name + "Result", result);
				//Reset call
				localStorage.removeItem(name);
			}
		});
	}

	this.CallLocalStorageFunction = function(name, params, callback) {
		//Check if the function is already called
		if (localStorage.getItem(name) === null && localStorage.getItem(name + "Result") === null) {

			//Call remote function
			localStorage.setItem(name, params);

			//Define timeout and event for future usage
			let timeout = {};
			let storageEvent = {};

			//Check in interval for result
			storageEvent = function(e) {
				//Check wheter the result is set
				if (e.key == name + "Result") {
					//Reset result in local storage
					localStorage.removeItem(name + "Result");

					//Dismiss listener and timeout
					clearTimeout(timeout);
					window.removeEventListener('storage', storageEvent, false);

					//Call callback with results
					callback(e.newValue);
				}
			}

			//Add listener to event
			window.addEventListener('storage', storageEvent);

			//Start timout to cancel listener if no result is set, hence no remote function was called
			timeout = setTimeout(function() {
				//Dismiss interval
				clearTimeout(timeout);
				//Clean up
				localStorage.removeItem(name);
				window.removeEventListener('storage', storageEvent, false);
			}, resultTimeout);
		}
	}
};
<|endoftext|>


<commit_before>import Ember from 'ember';
import moment from 'moment';
import layout from '../templates/components/date-range-picker';

const {
  run,
  isEmpty,
  computed
} = Ember;

const noop = function() {};

export default Ember.Component.extend({
  layout,
  classNames: ['form-group'],
  attributeBindings: ['start', 'end', 'serverFormat'],
  start: undefined,
  end: undefined,
  minDate: undefined,
  maxDate: undefined,
  timePicker: false,
  timePicker24Hour: false,
  timePickerSeconds: false,
  timePickerIncrement: undefined,
  showWeekNumbers: false,
  showDropdowns: false,
  linkedCalendars: false,
  datelimit: false,
  parentEl: 'body',
  format: 'MMM D, YYYY',
  serverFormat: 'YYYY-MM-DD',
  rangeText: computed('start', 'end', function() {
    let format = this.get('format');
    let serverFormat = this.get('serverFormat');
    let start = this.get('start');
    let end = this.get('end');
    if (!isEmpty(start) && !isEmpty(end)) {
      return moment(start, serverFormat).format(format) + this.get('separator') +
        moment(end, serverFormat).format(format);
    }
    return '';
  }),
  opens: null,
  drops: null,
  separator: ' - ',
  singleDatePicker: false,
  placeholder: null,
  buttonClasses: ['btn'],
  applyClass: null,
  cancelClass: null,
  ranges: {
    'Today': [moment(), moment()],
    'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
    'Last 7 Days': [moment().subtract(6, 'days'), moment()],
    'Last 30 Days': [moment().subtract(29, 'days'), moment()],
    'This Month': [moment().startOf('month'), moment().endOf('month')],
    'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
  },
  daysOfWeek: moment.weekdaysMin(),
  monthNames: moment.monthsShort(),
  removeDropdownOnDestroy: false,
  cancelLabel: 'Cancel',
  applyLabel: 'Apply',
  customRangeLabel: 'Custom Range',
  showCustomRangeLabel: false,
  fromLabel: 'From',
  toLabel: 'To',
  hideAction: null,
  applyAction: null,
  cancelAction: null,
  autoUpdateInput: true,
  autoApply: false,
  alwaysShowCalendars: false,
  context: undefined,
  firstDay: 0,
  isInvalidDate: noop,
  isCustomDate: noop,

  // Init the dropdown when the component is added to the DOM
  didInsertElement() {
    this._super(...arguments);
    this.setupPicker();
  },

  didUpdateAttrs() {
    this._super(...arguments);
    this.setupPicker();
  },

  // Remove the hidden dropdown when this component is destroyed
  willDestroy() {
    this._super(...arguments);

    run.cancel(this._setupTimer);

    if (this.get('removeDropdownOnDestroy')) {
      Ember.$('.daterangepicker').remove();
    }
  },

  getOptions() {
    let momentStartDate = moment(this.get('start'), this.get('serverFormat'));
    let momentEndDate = moment(this.get('end'), this.get('serverFormat'));
    let startDate = momentStartDate.isValid() ? momentStartDate : undefined;
    let endDate = momentEndDate.isValid() ? momentEndDate : undefined;

    let momentMinDate = moment(this.get('minDate'), this.get('serverFormat'));
    let momentMaxDate = moment(this.get('maxDate'), this.get('serverFormat'));
    let minDate = momentMinDate.isValid() ? momentMinDate : undefined;
    let maxDate = momentMaxDate.isValid() ? momentMaxDate : undefined;

    let showCustomRangeLabel = this.get('showCustomRangeLabel');

    let options = this.getProperties(
      'isInvalidDate',
      'isCustomDate',
      'alwaysShowCalendars',
      'autoUpdateInput',
      'autoApply',
      'timePicker',
      'buttonClasses',
      'applyClass',
      'cancelClass',
      'singleDatePicker',
      'drops',
      'opens',
      'timePicker24Hour',
      'timePickerSeconds',
      'timePickerIncrement',
      'showWeekNumbers',
      'showDropdowns',
      'showCustomRangeLabel',
      'linkedCalendars',
      'dateLimit',
      'parentEl'
    );

    let localeOptions = this.getProperties(
      'applyLabel',
      'cancelLabel',
      'customRangeLabel',
      'fromLabel',
      'toLabel',
      'format',
      'firstDay',
      'daysOfWeek',
      'monthNames',
      'separator'
    );

    const defaultOptions = {
      locale: localeOptions,
      showCustomRangeLabel: showCustomRangeLabel,
      startDate: startDate,
      endDate: endDate,
      minDate: minDate,
      maxDate: maxDate,
    };

    if (!this.get('singleDatePicker')) {
      options.ranges = this.get('ranges');
    }

    return { ...options, ...defaultOptions };
  },

  setupPicker() {
    run.cancel(this._setupTimer);
    this._setupTimer = run.scheduleOnce('afterRender', this, this._setupPicker);
  },

  _setupPicker() {
    this.$('.daterangepicker-input').daterangepicker(this.getOptions());
    this.attachPickerEvents();
  },

  attachPickerEvents() {
    this.$('.daterangepicker-input').on('apply.daterangepicker', (ev, picker) => {
      this.handleDateRangePickerEvent('applyAction', picker);
    });

    this.$('.daterangepicker-input').on('hide.daterangepicker', (ev, picker) => {
      this.handleDateRangePickerEvent('hideAction', picker);
    });

    this.$('.daterangepicker-input').on('cancel.daterangepicker', () => {
      this.handleDateRangePickerEvent('cancelAction', undefined, true);
    });
  },

  handleDateRangePickerEvent(actionName, picker, isCancel = false) {
    let action = this.get(actionName);
    let start;
    let end;

    if (!isCancel) {
      start = picker.startDate.format(this.get('serverFormat'));
      end = picker.endDate.format(this.get('serverFormat'));
    }

    if (action) {
      Ember.assert(
        `${actionName} for date-range-picker must be a function`,
        typeof action === 'function'
      );
      this.sendAction(actionName, start, end, picker);
    } else {
      if (!this.isDestroyed) {
        this.setProperties({ start, end });
      }
    }
  }
});
<commit_msg>fix date ranges<commit_after>import Ember from 'ember';
import moment from 'moment';
import layout from '../templates/components/date-range-picker';

const {
  run,
  isEmpty,
  computed
} = Ember;

const noop = function() {};

export default Ember.Component.extend({
  layout,
  classNames: ['form-group'],
  attributeBindings: ['start', 'end', 'serverFormat'],
  start: undefined,
  end: undefined,
  minDate: undefined,
  maxDate: undefined,
  timePicker: false,
  timePicker24Hour: false,
  timePickerSeconds: false,
  timePickerIncrement: undefined,
  showWeekNumbers: false,
  showDropdowns: false,
  linkedCalendars: false,
  datelimit: false,
  parentEl: 'body',
  format: 'MMM D, YYYY',
  serverFormat: 'YYYY-MM-DD',
  rangeText: computed('start', 'end', function() {
    let format = this.get('format');
    let serverFormat = this.get('serverFormat');
    let start = this.get('start');
    let end = this.get('end');
    if (!isEmpty(start) && !isEmpty(end)) {
      return moment(start, serverFormat).format(format) + this.get('separator') +
        moment(end, serverFormat).format(format);
    }
    return '';
  }),
  opens: null,
  drops: null,
  separator: ' - ',
  singleDatePicker: false,
  placeholder: null,
  buttonClasses: ['btn'],
  applyClass: null,
  cancelClass: null,
  ranges: {
    'Today': [moment().startOf('day'), moment().endOf('day')],
    'Yesterday': [moment().subtract(1, 'days').startOf('day'), moment().subtract(1, 'days').endOf('day')],
    'Last 7 Days': [moment().subtract(7, 'days'), moment()],
    'Last 30 Days': [moment().subtract(30, 'days'), moment()],
    'This Month': [moment().startOf('month'), moment().endOf('month')],
    'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
  },
  daysOfWeek: moment.weekdaysMin(),
  monthNames: moment.monthsShort(),
  removeDropdownOnDestroy: false,
  cancelLabel: 'Cancel',
  applyLabel: 'Apply',
  customRangeLabel: 'Custom Range',
  showCustomRangeLabel: false,
  fromLabel: 'From',
  toLabel: 'To',
  hideAction: null,
  applyAction: null,
  cancelAction: null,
  autoUpdateInput: true,
  autoApply: false,
  alwaysShowCalendars: false,
  context: undefined,
  firstDay: 0,
  isInvalidDate: noop,
  isCustomDate: noop,

  // Init the dropdown when the component is added to the DOM
  didInsertElement() {
    this._super(...arguments);
    this.setupPicker();
  },

  didUpdateAttrs() {
    this._super(...arguments);
    this.setupPicker();
  },

  // Remove the hidden dropdown when this component is destroyed
  willDestroy() {
    this._super(...arguments);

    run.cancel(this._setupTimer);

    if (this.get('removeDropdownOnDestroy')) {
      Ember.$('.daterangepicker').remove();
    }
  },

  getOptions() {
    let momentStartDate = moment(this.get('start'), this.get('serverFormat'));
    let momentEndDate = moment(this.get('end'), this.get('serverFormat'));
    let startDate = momentStartDate.isValid() ? momentStartDate : undefined;
    let endDate = momentEndDate.isValid() ? momentEndDate : undefined;

    let momentMinDate = moment(this.get('minDate'), this.get('serverFormat'));
    let momentMaxDate = moment(this.get('maxDate'), this.get('serverFormat'));
    let minDate = momentMinDate.isValid() ? momentMinDate : undefined;
    let maxDate = momentMaxDate.isValid() ? momentMaxDate : undefined;

    let showCustomRangeLabel = this.get('showCustomRangeLabel');

    let options = this.getProperties(
      'isInvalidDate',
      'isCustomDate',
      'alwaysShowCalendars',
      'autoUpdateInput',
      'autoApply',
      'timePicker',
      'buttonClasses',
      'applyClass',
      'cancelClass',
      'singleDatePicker',
      'drops',
      'opens',
      'timePicker24Hour',
      'timePickerSeconds',
      'timePickerIncrement',
      'showWeekNumbers',
      'showDropdowns',
      'showCustomRangeLabel',
      'linkedCalendars',
      'dateLimit',
      'parentEl'
    );

    let localeOptions = this.getProperties(
      'applyLabel',
      'cancelLabel',
      'customRangeLabel',
      'fromLabel',
      'toLabel',
      'format',
      'firstDay',
      'daysOfWeek',
      'monthNames',
      'separator'
    );

    const defaultOptions = {
      locale: localeOptions,
      showCustomRangeLabel: showCustomRangeLabel,
      startDate: startDate,
      endDate: endDate,
      minDate: minDate,
      maxDate: maxDate,
    };

    if (!this.get('singleDatePicker')) {
      options.ranges = this.get('ranges');
    }

    return { ...options, ...defaultOptions };
  },

  setupPicker() {
    run.cancel(this._setupTimer);
    this._setupTimer = run.scheduleOnce('afterRender', this, this._setupPicker);
  },

  _setupPicker() {
    this.$('.daterangepicker-input').daterangepicker(this.getOptions());
    this.attachPickerEvents();
  },

  attachPickerEvents() {
    this.$('.daterangepicker-input').on('apply.daterangepicker', (ev, picker) => {
      this.handleDateRangePickerEvent('applyAction', picker);
    });

    this.$('.daterangepicker-input').on('hide.daterangepicker', (ev, picker) => {
      this.handleDateRangePickerEvent('hideAction', picker);
    });

    this.$('.daterangepicker-input').on('cancel.daterangepicker', () => {
      this.handleDateRangePickerEvent('cancelAction', undefined, true);
    });
  },

  handleDateRangePickerEvent(actionName, picker, isCancel = false) {
    let action = this.get(actionName);
    let start;
    let end;

    if (!isCancel) {
      start = picker.startDate.format(this.get('serverFormat'));
      end = picker.endDate.format(this.get('serverFormat'));
    }

    if (action) {
      Ember.assert(
        `${actionName} for date-range-picker must be a function`,
        typeof action === 'function'
      );
      this.sendAction(actionName, start, end, picker);
    } else {
      if (!this.isDestroyed) {
        this.setProperties({ start, end });
      }
    }
  }
});
<|endoftext|>


<commit_before>if (typeof(String.prototype.trim) !== "function") {
    String.prototype.trim = function (str) {
        return this.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
    };
}
<commit_msg>Array.isArray compat<commit_after>if (typeof(String.prototype.trim) !== "function") {
    String.prototype.trim = function (str) {
        return this.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
    };
}
if (typeof(Array.isArray) !== "function") {
    Array.isArray = function (a) {
        if (a instanceof Array) {
            return true;
        } else {
            return false;
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>VMC-358-modifiedStacked: Fixed calculation issue with SP execution time in execution time dril down<commit_after><|endoftext|>


<commit_before>//   _____ _
//  / ____| |
// | |    | | __ _ _________   _
// | |    | |/ _` |_  /_  / | | |
// | |____| | (_| |/ / / /| |_| |
//  \_____|_|\__,_/___/___|\__, |
//                          __/ |
// ======================= |___/
//               By Luke Phillips

(function (name, factory, context)
{
    if (typeof module !== 'undefined' && module.exports)
    {
        module.exports = factory.call(context);
    }
    else if (typeof define === 'function' && define.amd)
    {
        define(name, [], factory);
    }
    else
    {
        context[name] = factory.call(context);
    }

}) ('Clazzy', function ()
{
    'use strict';

    // We need to pass array-like objects, such as the arguments
    // object, to Function.apply, however not all implementations yet
    // allow array-like objects to be passed to it. So we need to
    // convert them to an array, this can be done using Array.slice.
    //
    // A further problem, is you can't slice array-like objects
    // directly, like so:
    //
    //    arguments.slice(0);
    //
    // As they aren't arrays, however the method will still work if
    // applied like this:
    //
    //    Array.prototype.slice.call(arguments, 0);
    var slice = Array.prototype.slice;

    // The Object.hasOwnProperty method is not protected, which
    // allows an object to override it, making using the method
    // like this:
    //
    //    object.hasOwnProperty('property');
    //
    // Very unreliable, so we need to do this instead:
    //
    //    Object.prototype.hasOwnProperty(object, 'property');
    var hasOwnProperty = Object.prototype.hasOwnProperty;

    // Keywords
    // --------------------------------------------------------------

    var SUPER       = 'super';
    var INITIALIZE  = 'initialize';
    var EXTEND      = 'extend';
    var STATIC      = 'static';
    var INCLUDE     = 'include';
    var FUNCTION    = 'function';
    var CONSTRUCTOR = 'constructor';

    // Helpers
    // --------------------------------------------------------------

    var createAnUnconstructedInstanceOfClass = (function ()
    {
        if (Object.create === undefined)
        {
            return function (clazz)
            {
				function Surrogate ()
				{
					// A surrogate function that does nothing. It
					// will allow us to create an object of a
					// prototype without running it's constructor.
				}

                Surrogate.prototype             = clazz.prototype;
                Surrogate.prototype.constructor = clazz;

                return new Surrogate();
            };
        }

        return function (clazz)
        {
            return Object.create(clazz.prototype);
        };

    }) ();

    var copyProperty = (function ()
    {
        // IE8 implements Object.defineProperty, however it only
        // works on DOM elements. So IE8 must also use a fall-back
        // method, requiring us to check for the implementation of
        // Object.defineProperties instead.
        if (Object.defineProperties === undefined)
        {
            return function (source, target, property)
            {
                target[property] = source[property];
            };
        }

        return function (source, target, property, deep)
        {
			var descriptor = getPropertyDescriptor(source, property, deep);

			if (descriptor !== undefined)
			{
				// Normally this would suffice:
				//
				//   target[signature] = methods[signature];
				//
				// However for ECMA5 getters, this wouldn't work, as it
				// would be invoked, hence assigning the value being
				// returned by the getter, rather than it's definition.
				Object.defineProperty(target, property, descriptor);
			}
        };

    }) ();

    var copyProperties = function (source, target, deep)
    {
    	for (var property in source)
    	{
    		if ( deep || hasOwnProperty.call(source, property) )
    		{
    			copyProperty(source, target, property, deep);
    		}
    	}
    };

    var getPropertyDescriptor = function (object, property, deep)
	{
		var descriptor = Object.getOwnPropertyDescriptor(object, property);

		if (descriptor !== undefined)
		{
			return descriptor;
		}

		if (deep)
		{
			var prototype = object;

			do
			{
				prototype = Object.getPrototypeOf(prototype);

				// Climb down the next kink of the prototype chain and
				// attempt to retrieve the property descriptor from
				// that kink.
				descriptor = Object.getOwnPropertyDescriptor(prototype, property);
			}
			while (prototype !== undefined && descriptor === undefined);
		}

		return descriptor;
	};

    // --------------------------------------------------------------

    var error = function ()
    {
    	throw new Error('Error calling super, this method does not override a parent method');
    };

    var wrap = function (method, signature, base)
    {
    	return function ()
    	{
    		var tmp = this[SUPER];

    		this[SUPER] = base.prototype[signature] || error;

    		var result;

    		try // to execute the method.
    		{
        		result = method.apply(
        			this, slice.call(arguments)
        		);
      		}
      		finally
      		{
      			this[SUPER] = tmp;
      		}

      		return result;
    	};
    };

    // --------------------------------------------------------------

    var Clazzy =
	{
		create : function (definition)
		{
			if (definition === undefined)
			{
				definition = {};
			}

			// Constructor
			// --------------------------------------------

			var initialize;

			function Class ()
			{
				if (includes !== undefined)
				{
					for (var i = 0, l = includes.length; i < l; ++i)
					{
						includes[i].call(this);
					}
				}

				if (initialize !== undefined)
				{
					initialize.apply(
						this, slice.call(arguments)
					);
				}
			}

			// Extend
			// --------------------------------------------

			var base = definition[EXTEND];

			if (base === undefined)
			{
				base = Object;
			}
			else
			{
				Class.prototype = createAnUnconstructedInstanceOfClass(base);

				// Default the class initializer to the base class
				// constructor.
				initialize = base.prototype.constructor;
			}

			// Include
			// --------------------------------------------

			var includes = definition[INCLUDE];

			if (includes !== undefined)
			{
				for (var i = 0, l = includes.length; i < l; ++i)
				{
					var include = createAnUnconstructedInstanceOfClass(
						includes[i]
					);

					copyProperties(include, Class.prototype, true);
				}
			}

			// Methods
			// --------------------------------------------

			for (var property in definition)
			{
				if ( hasOwnProperty.call(definition, property) )
				{
					var member = definition[property];

					switch (property)
					{
						case INITIALIZE :

							initialize = wrap(member, CONSTRUCTOR, base);

						break;

						case EXTEND  :
						case INCLUDE :

							// We have already dealt with these
							// properties.

						break;

						case STATIC :

							copyProperties(member, Class, false);

						break;

						case SUPER :

							throw new Error('Cannot create class, "super" is a reserved method name');

						default :

							if (typeof member === FUNCTION)
							{
								// Always wrap the method. Even if a
								// parent method doesn't exist at the
								// moment, as a method could later be
								// injected into the prototye.
								Class.prototype[property] = wrap(member, property, base);
							}
							else
							{
								copyProperty(definition, Class.prototype, property);
							}
					}
				}
			}

			Class.prototype.constructor = Class;

			return Class;
		},

		// ----------------------------------------------------------

		noConflict : (function (context)
		{
			var _Clazzy = context.Clazzy;

			return function ()
			{
				context.Clazzy = _Clazzy;

				return this;
			};

		}) (this)
	};

	// --------------------------------------------------------------

    return Clazzy;

}, this);<commit_msg>Converted all tabs to hard tabs.<commit_after>//   _____ _
//  / ____| |
// | |    | | __ _ _________   _
// | |    | |/ _` |_  /_  / | | |
// | |____| | (_| |/ / / /| |_| |
//  \_____|_|\__,_/___/___|\__, |
//                          __/ |
// ======================= |___/
//               By Luke Phillips

(function (name, factory, context)
{
	if (typeof module !== 'undefined' && module.exports)
	{
		module.exports = factory.call(context);
	}
	else if (typeof define === 'function' && define.amd)
	{
		define(name, [], factory);
	}
	else
	{
		context[name] = factory.call(context);
	}

}) ('Clazzy', function ()
{
	'use strict';

	// We need to pass array-like objects, such as the arguments
	// object, to Function.apply, however not all implementations yet
	// allow array-like objects to be passed to it. So we need to
	// convert them to an array, this can be done using Array.slice.
	//
	// A further problem, is you can't slice array-like objects
	// directly, like so:
	//
	//    arguments.slice(0);
	//
	// As they aren't arrays, however the method will still work if
	// applied like this:
	//
	//    Array.prototype.slice.call(arguments, 0);
	var slice = Array.prototype.slice;

	// The Object.hasOwnProperty method is not protected, which
	// allows an object to override it, making using the method
	// like this:
	//
	//    object.hasOwnProperty('property');
	//
	// Very unreliable, so we need to do this instead:
	//
	//    Object.prototype.hasOwnProperty(object, 'property');
	var hasOwnProperty = Object.prototype.hasOwnProperty;

	// Keywords
	// --------------------------------------------------------------

	var SUPER       = 'super';
	var INITIALIZE  = 'initialize';
	var EXTEND      = 'extend';
	var STATIC      = 'static';
	var INCLUDE     = 'include';
	var FUNCTION    = 'function';
	var CONSTRUCTOR = 'constructor';

	// Helpers
	// --------------------------------------------------------------

	var createAnUnconstructedInstanceOfClass = (function ()
	{
		if (Object.create === undefined)
		{
			return function (clazz)
			{
				function Surrogate ()
				{
					// A surrogate function that does nothing. It
					// will allow us to create an object of a
					// prototype without running it's constructor.
				}

				Surrogate.prototype             = clazz.prototype;
				Surrogate.prototype.constructor = clazz;

				return new Surrogate();
			};
		}

		return function (clazz)
		{
			return Object.create(clazz.prototype);
		};

	}) ();

	var copyProperty = (function ()
	{
		// IE8 implements Object.defineProperty, however it only
		// works on DOM elements. So IE8 must also use a fall-back
		// method, requiring us to check for the implementation of
		// Object.defineProperties instead.
		if (Object.defineProperties === undefined)
		{
			return function (source, target, property)
			{
				target[property] = source[property];
			};
		}

		return function (source, target, property, deep)
		{
			var descriptor = getPropertyDescriptor(source, property, deep);

			if (descriptor !== undefined)
			{
				// Normally this would suffice:
				//
				//   target[signature] = methods[signature];
				//
				// However for ECMA5 getters, this wouldn't work, as it
				// would be invoked, hence assigning the value being
				// returned by the getter, rather than it's definition.
				Object.defineProperty(target, property, descriptor);
			}
		};

	}) ();

	var copyProperties = function (source, target, deep)
	{
		for (var property in source)
		{
			if ( deep || hasOwnProperty.call(source, property) )
			{
				copyProperty(source, target, property, deep);
			}
		}
	};

	var getPropertyDescriptor = function (object, property, deep)
	{
		var descriptor = Object.getOwnPropertyDescriptor(object, property);

		if (descriptor !== undefined)
		{
			return descriptor;
		}

		if (deep)
		{
			var prototype = object;

			do
			{
				prototype = Object.getPrototypeOf(prototype);

				// Climb down the next kink of the prototype chain and
				// attempt to retrieve the property descriptor from
				// that kink.
				descriptor = Object.getOwnPropertyDescriptor(prototype, property);
			}
			while (prototype !== undefined && descriptor === undefined);
		}

		return descriptor;
	};

	// --------------------------------------------------------------

	var error = function ()
	{
		throw new Error('Error calling super, this method does not override a parent method');
	};

	var wrap = function (method, signature, base)
	{
		return function ()
		{
			var tmp = this[SUPER];

			this[SUPER] = base.prototype[signature] || error;

			var result;

			try // to execute the method.
			{
				result = method.apply(
					this, slice.call(arguments)
				);
			}
			finally
			{
				this[SUPER] = tmp;
			}

			return result;
		};
	};

	// --------------------------------------------------------------

	var Clazzy =
	{
		create : function (definition)
		{
			if (definition === undefined)
			{
				definition = {};
			}

			// Constructor
			// --------------------------------------------

			var initialize;

			function Class ()
			{
				if (includes !== undefined)
				{
					for (var i = 0, l = includes.length; i < l; ++i)
					{
						includes[i].call(this);
					}
				}

				if (initialize !== undefined)
				{
					initialize.apply(
						this, slice.call(arguments)
					);
				}
			}

			// Extend
			// --------------------------------------------

			var base = definition[EXTEND];

			if (base === undefined)
			{
				base = Object;
			}
			else
			{
				Class.prototype = createAnUnconstructedInstanceOfClass(base);

				// Default the class initializer to the base class
				// constructor.
				initialize = base.prototype.constructor;
			}

			// Include
			// --------------------------------------------

			var includes = definition[INCLUDE];

			if (includes !== undefined)
			{
				for (var i = 0, l = includes.length; i < l; ++i)
				{
					var include = createAnUnconstructedInstanceOfClass(
						includes[i]
					);

					copyProperties(include, Class.prototype, true);
				}
			}

			// Methods
			// --------------------------------------------

			for (var property in definition)
			{
				if ( hasOwnProperty.call(definition, property) )
				{
					var member = definition[property];

					switch (property)
					{
						case INITIALIZE :

							initialize = wrap(member, CONSTRUCTOR, base);

						break;

						case EXTEND  :
						case INCLUDE :

							// We have already dealt with these
							// properties.

						break;

						case STATIC :

							copyProperties(member, Class, false);

						break;

						case SUPER :

							throw new Error('Cannot create class, "super" is a reserved method name');

						default :

							if (typeof member === FUNCTION)
							{
								// Always wrap the method. Even if a
								// parent method doesn't exist at the
								// moment, as a method could later be
								// injected into the prototye.
								Class.prototype[property] = wrap(member, property, base);
							}
							else
							{
								copyProperty(definition, Class.prototype, property);
							}
					}
				}
			}

			Class.prototype.constructor = Class;

			return Class;
		},

		// ----------------------------------------------------------

		noConflict : (function (context)
		{
			var _Clazzy = context.Clazzy;

			return function ()
			{
				context.Clazzy = _Clazzy;

				return this;
			};

		}) (this)
	};

	// --------------------------------------------------------------

	return Clazzy;

}, this);<|endoftext|>


<commit_before>import Ember from 'ember';
import moment from 'moment';

export default Ember.Component.extend({
  classNames: ['form-group'],
  attributeBindings: ['start', 'end', 'serverFormat'],
  start: undefined,
  end: undefined,
  minDate: undefined,
  maxDate: undefined,
  timePicker: false,
  timePicker24Hour: false,
  timePickerSeconds: false,
  timePickerIncrement: undefined,
  showWeekNumbers: false,
  showDropdowns: false,
  linkedCalendars: false,
  parentEl: 'body',

  format: 'MMM D, YYYY',
  serverFormat: 'YYYY-MM-DD',
  rangeText: Ember.computed('start', 'end', function() {
    let format = this.get('format');
    let serverFormat = this.get('serverFormat');
    let start = this.get('start');
    let end = this.get('end');
    if (!Ember.isEmpty(start) && !Ember.isEmpty(end)) {
      return moment(start, serverFormat).format(format) + this.get('separator') +
        moment(end, serverFormat).format(format);
    }
    return '';
  }),
  opens: null,
  drops: null,
  separator: ' - ',
  singleDatePicker: false,
  placeholder: null,
  buttonClasses: ['btn'],
  applyClass: null,
  cancelClass: null,
  ranges: {
    'Today': [moment(), moment()],
    'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
    'Last 7 Days': [moment().subtract(6, 'days'), moment()],
    'Last 30 Days': [moment().subtract(29, 'days'), moment()],
    'This Month': [moment().startOf('month'), moment().endOf('month')],
    'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
  },
  removeDropdownOnDestroy: false,
  cancelLabel: 'Cancel',
  applyAction: null,
  cancelAction: null,
  autoUpdateInput: true,
  autoApply: false,

  // Init the dropdown when the component is added to the DOM
  didInsertElement() {
    let self = this;

    let momentStartDate = moment(this.get('start'), this.get('serverFormat'));
    let momentEndDate = moment(this.get('end'), this.get('serverFormat'));
    let startDate = momentStartDate.isValid() ? momentStartDate : undefined;
    let endDate = momentEndDate.isValid() ? momentEndDate : undefined;

    let momentMinDate = moment(this.get('minDate'), this.get('serverFormat'));
    let momentMaxDate = moment(this.get('maxDate'), this.get('serverFormat'));
    let minDate = momentMinDate.isValid() ? momentMinDate : undefined;
    let maxDate = momentMaxDate.isValid() ? momentMaxDate : undefined;

    let options = {
      autoUpdateInput: this.get('autoUpdateInput'),
      autoApply: this.get('autoApply'),
      locale: {
        cancelLabel: this.get('cancelLabel'),
        format: this.get('format')
      },
      startDate: startDate,
      endDate: endDate,
      minDate: minDate,
      maxDate: maxDate,
      timePicker: this.get('timePicker'),
      buttonClasses: this.get('buttonClasses'),
      applyClass: this.get('applyClass'),
      cancelClass: this.get('cancelClass'),
      separator: this.get('separator'),
      singleDatePicker: this.get('singleDatePicker'),
      drops: this.get('drops'),
      opens: this.get('opens'),
      timePicker24Hour: this.get('timePicker24Hour'),
      timePickerSeconds: this.get('timePickerSeconds'),
      timePickerIncrement: this.get('timePickerIncrement'),
      showWeekNumbers: this.get('showWeekNumbers'),
      showDropdowns: this.get('showDropdowns'),
      linkedCalendars: this.get('linkedCalendars'),
      parentEl: this.get('parentEl')
    };

    if (!this.get('singleDatePicker')) {
      options.ranges = this.get('ranges');
    }

    Ember.run.scheduleOnce('afterRender', this, function() {
      this.$('.daterangepicker-input').daterangepicker(options);
    });

    this.$('.daterangepicker-input').on('apply.daterangepicker', function(ev, picker) {
      let start = picker.startDate.format(self.get('serverFormat'));
      let end = picker.endDate.format(self.get('serverFormat'));
      let applyAction = self.get('applyAction');

      if (applyAction) {
        Ember.assert(
          'applyAction for date-range-picker must be a function',
          typeof applyAction === 'function'
        );
        self.sendAction('applyAction', start, end);
      } else {
        self.setProperties({
          start, end
        });
      }
    });

    this.$('.daterangepicker-input').on('cancel.daterangepicker', function() {
      let cancelAction = self.get('cancelAction');

      if (cancelAction) {
        Ember.assert(
          'cancelAction for date-range-picker must be a function',
          typeof cancelAction === 'function'
        );
        self.sendAction('cancelAction');
      } else {
        self.setProperties({
          start: self.get('start'),
          end: self.get('end')
        });
      }
    });
  },

  // Remove the hidden dropdown when this component is destroyed
  willDestroy() {
    if (this.get('removeDropdownOnDestroy')) {
      Ember.$('.daterangepicker').remove();
    }
  }
});
<commit_msg>Added dateLimit option<commit_after>import Ember from 'ember';
import moment from 'moment';

export default Ember.Component.extend({
  classNames: ['form-group'],
  attributeBindings: ['start', 'end', 'serverFormat'],
  start: undefined,
  end: undefined,
  minDate: undefined,
  maxDate: undefined,
  timePicker: false,
  timePicker24Hour: false,
  timePickerSeconds: false,
  timePickerIncrement: undefined,
  showWeekNumbers: false,
  showDropdowns: false,
  linkedCalendars: false,
  datelimit: false,
  parentEl: 'body',

  format: 'MMM D, YYYY',
  serverFormat: 'YYYY-MM-DD',
  rangeText: Ember.computed('start', 'end', function() {
    let format = this.get('format');
    let serverFormat = this.get('serverFormat');
    let start = this.get('start');
    let end = this.get('end');
    if (!Ember.isEmpty(start) && !Ember.isEmpty(end)) {
      return moment(start, serverFormat).format(format) + this.get('separator') +
        moment(end, serverFormat).format(format);
    }
    return '';
  }),
  opens: null,
  drops: null,
  separator: ' - ',
  singleDatePicker: false,
  placeholder: null,
  buttonClasses: ['btn'],
  applyClass: null,
  cancelClass: null,
  ranges: {
    'Today': [moment(), moment()],
    'Yesterday': [moment().subtract(1, 'days'), moment().subtract(1, 'days')],
    'Last 7 Days': [moment().subtract(6, 'days'), moment()],
    'Last 30 Days': [moment().subtract(29, 'days'), moment()],
    'This Month': [moment().startOf('month'), moment().endOf('month')],
    'Last Month': [moment().subtract(1, 'month').startOf('month'), moment().subtract(1, 'month').endOf('month')]
  },
  removeDropdownOnDestroy: false,
  cancelLabel: 'Cancel',
  applyAction: null,
  cancelAction: null,
  autoUpdateInput: true,
  autoApply: false,

  // Init the dropdown when the component is added to the DOM
  didInsertElement() {
    let self = this;

    let momentStartDate = moment(this.get('start'), this.get('serverFormat'));
    let momentEndDate = moment(this.get('end'), this.get('serverFormat'));
    let startDate = momentStartDate.isValid() ? momentStartDate : undefined;
    let endDate = momentEndDate.isValid() ? momentEndDate : undefined;

    let momentMinDate = moment(this.get('minDate'), this.get('serverFormat'));
    let momentMaxDate = moment(this.get('maxDate'), this.get('serverFormat'));
    let minDate = momentMinDate.isValid() ? momentMinDate : undefined;
    let maxDate = momentMaxDate.isValid() ? momentMaxDate : undefined;

    let options = {
      autoUpdateInput: this.get('autoUpdateInput'),
      autoApply: this.get('autoApply'),
      locale: {
        cancelLabel: this.get('cancelLabel'),
        format: this.get('format')
      },
      startDate: startDate,
      endDate: endDate,
      minDate: minDate,
      maxDate: maxDate,
      timePicker: this.get('timePicker'),
      buttonClasses: this.get('buttonClasses'),
      applyClass: this.get('applyClass'),
      cancelClass: this.get('cancelClass'),
      separator: this.get('separator'),
      singleDatePicker: this.get('singleDatePicker'),
      drops: this.get('drops'),
      opens: this.get('opens'),
      timePicker24Hour: this.get('timePicker24Hour'),
      timePickerSeconds: this.get('timePickerSeconds'),
      timePickerIncrement: this.get('timePickerIncrement'),
      showWeekNumbers: this.get('showWeekNumbers'),
      showDropdowns: this.get('showDropdowns'),
      linkedCalendars: this.get('linkedCalendars'),
      dateLimit: this.get('dateLimit'),
      parentEl: this.get('parentEl')
    };

    if (!this.get('singleDatePicker')) {
      options.ranges = this.get('ranges');
    }

    Ember.run.scheduleOnce('afterRender', this, function() {
      this.$('.daterangepicker-input').daterangepicker(options);
    });

    this.$('.daterangepicker-input').on('apply.daterangepicker', function(ev, picker) {
      let start = picker.startDate.format(self.get('serverFormat'));
      let end = picker.endDate.format(self.get('serverFormat'));
      let applyAction = self.get('applyAction');

      if (applyAction) {
        Ember.assert(
          'applyAction for date-range-picker must be a function',
          typeof applyAction === 'function'
        );
        self.sendAction('applyAction', start, end);
      } else {
        self.setProperties({
          start, end
        });
      }
    });

    this.$('.daterangepicker-input').on('cancel.daterangepicker', function() {
      let cancelAction = self.get('cancelAction');

      if (cancelAction) {
        Ember.assert(
          'cancelAction for date-range-picker must be a function',
          typeof cancelAction === 'function'
        );
        self.sendAction('cancelAction');
      } else {
        self.setProperties({
          start: self.get('start'),
          end: self.get('end')
        });
      }
    });
  },

  // Remove the hidden dropdown when this component is destroyed
  willDestroy() {
    if (this.get('removeDropdownOnDestroy')) {
      Ember.$('.daterangepicker').remove();
    }
  }
});
<|endoftext|>


<commit_before>/**
 * Component definition for the frost-time-picker component
 */
import Ember from 'ember'
import PropTypesMixin, {PropTypes} from 'ember-prop-types'
import FrostText from 'ember-frost-core/components/frost-text'
import SpreadMixin from 'ember-spread'

const {
  run: {
    scheduleOnce,
    bind
  }
} = Ember

const {
  moment
} = window

export default FrostText.extend(SpreadMixin, PropTypesMixin, {
  // == Dependencies ==========================================================

  // == PropTypes =============================================================
  propTypes: {
    hook: PropTypes.string,
    options: PropTypes.object,
    format: PropTypes.string,
    readonly: PropTypes.bool,
    placement: PropTypes.string,
    align: PropTypes.string,
    timeRegex: PropTypes.object,
    donetext: PropTypes.string,
    autoclose: PropTypes.bool,
    validator: PropTypes.func,
    onSelect: PropTypes.func,
    onError: PropTypes.func
  },

  /** @returns {Object} the default property values when not provided by consumer */
  getDefaultProps () {
    return {
      format: 'HH:mm:ss',
      readonly: false,
      placement: 'right',
      donetext: 'Done',
      autoclose: true,
      hook: 'time-picker',
      timeRegex: /^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/,
      GENERIC_ERROR: 'Invalid Time Input'
    }
  },

  // == Computed Properties ===================================================

  // == Functions =============================================================
  testRegex (value) {
    const regex = this.get('timeRegex')
    return regex.test(value)
  },
  isValid (value) {
    if (this.validator) {
      const result = this.validator(value)
      if (result !== undefined) {
        return result
      }
    }
    return this.testRegex(value)
  },
  // == DOM Events ============================================================
  afterDone () {
    const previousValue = this.get('previousValue')
    const value = this.get('value')
    if (this.isValid(value)) {
      const onSelect = this.get('onSelect')
      if (onSelect && value !== previousValue) {
        onSelect(value)
        this.set('previousValue', value)
      }
    } else {
      this.set('value', previousValue)
      const onError = this.get('onError')
      const e = this.get('GENERIC_ERROR')
      if (onError) {
        onError(e)
      } else {
        console.warn(e)
      }
    }
  },
  change () {
    const value = this.$('input').val()
    this.set('value', value)
  },
  // == Lifecycle Hooks =======================================================
  didInsertElement () {
    this._super(...arguments)
    scheduleOnce('sync', this, function () {
      const format = this.get('format')
      const value = this.get('value') || moment().format(format)

      this.set('value', value)
      this.set('previousValue', value)

      this.$().clockpicker({
        format,
        placement: this.get('placement'),
        donetext: this.get('donetext'),
        autoclose: this.get('autoclose'),
        afterDone: bind(this, this.afterDone)
      })
    })
  },
  willDestroyElement () {
    this.$().clockpicker('remove')
    this._super(...arguments)
  }
})
<commit_msg>submit on focusOut, usability improvements<commit_after>/**
 * Component definition for the frost-time-picker component
 */
import Ember from 'ember'
import PropTypesMixin, {PropTypes} from 'ember-prop-types'
import FrostText from 'ember-frost-core/components/frost-text'
import SpreadMixin from 'ember-spread'

const {
  run: {
    scheduleOnce,
    bind
  }
} = Ember

const {
  moment
} = window

export default FrostText.extend(SpreadMixin, PropTypesMixin, {
  // == Dependencies ==========================================================

  // == PropTypes =============================================================
  propTypes: {
    hook: PropTypes.string,
    options: PropTypes.object,
    format: PropTypes.string,
    readonly: PropTypes.bool,
    placement: PropTypes.string,
    align: PropTypes.string,
    timeRegex: PropTypes.object,
    donetext: PropTypes.string,
    autoclose: PropTypes.bool,
    validator: PropTypes.func,
    onSelect: PropTypes.func,
    onError: PropTypes.func
  },

  /** @returns {Object} the default property values when not provided by consumer */
  getDefaultProps () {
    return {
      format: 'HH:mm:ss',
      readonly: false,
      placement: 'right',
      donetext: 'Done',
      autoclose: true,
      hook: 'time-picker',
      timeRegex: /^([0-9]|0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/,
      GENERIC_ERROR: 'Invalid Time Input'
    }
  },

  // == Computed Properties ===================================================

  // == Functions =============================================================
  testRegex (value) {
    const regex = this.get('timeRegex')
    return regex.test(value)
  },
  isValid (value) {
    if (this.validator) {
      const result = this.validator(value)
      if (result !== undefined) {
        return result
      }
    }
    return this.testRegex(value)
  },
  syncTask (cb) {
    scheduleOnce('sync', this, cb)
  },
  // == DOM Events ============================================================
  afterDone () {
    const previousValue = this.get('previousValue')
    const value = this.get('value')
    if (this.isValid(value)) {
      const onSelect = this.get('onSelect')
      if (onSelect && value !== previousValue) {
        onSelect(value)
        this.set('previousValue', value)
      }
    } else {
      this.set('value', previousValue)
      const onError = this.get('onError')
      const e = this.get('GENERIC_ERROR')
      if (onError) {
        onError(e)
      } else {
        console.warn(e)
      }
    }
  },
  change () {
    const value = this.$('input').val()
    this.set('value', value)
  },
  focusOut () {
    this.syncTask(function () {
      this.$().clockpicker('hide')
    })
  },
  keyPress (e) {
    if (e.keyCode === 13) {
      this.syncTask(function () {
        this.$().clockpicker('hide')
      })
    }
  },
  // == Lifecycle Hooks =======================================================
  didInsertElement () {
    this._super(...arguments)
    this.syncTask(function () {
      const format = this.get('format')
      const value = this.get('value') || moment().format(format)

      this.set('value', value)
      this.set('previousValue', value)

      this.$().clockpicker({
        format,
        placement: this.get('placement'),
        donetext: this.get('donetext'),
        autoclose: this.get('autoclose'),
        afterDone: bind(this, this.afterDone)
      })
    })
  },
  willDestroyElement () {
    this.$().clockpicker('remove')
    this._super(...arguments)
  }
})
<|endoftext|>


<commit_before>/* jshint expr: true */
import Ember from 'ember';
import layout from '../templates/components/power-select-tree';
const { get, set, isBlank, computed, A, Component, $ } = Ember;

export default Component.extend({
  layout,
  classNames: ['ember-power-select-tree'],
  defaultLabelOpt: 'label',
  __selectedOptions: null,
  advancedTreeOptions: computed('treeOptions.[]', function() {
    return A(get(this, 'treeOptions'))
      .map(o => this._collapsableOption(o))
      .map(o => this._buildPath(o));
  }),
  currentOptions: computed('advancedTreeOptions.[]', '__selectedOptions.[]', function() {
    const __selectedOptions = get(this, '__selectedOptions');
    return get(this, 'advancedTreeOptions')
      .map(o => this._treeTraverse(o, (node) => this._setChecked(node, __selectedOptions)));
  }),

  groupedSelectedOptions: computed('__selectedOptions.[]', function() {
    return A(get(this, '__selectedOptions')).reduce((prev, curr) => {
      const humanPath = get(curr, 'humanPath') || '';
      const group = prev.findBy('humanPath', humanPath);
      if (group) {
        get(group, 'options').pushObject(curr);
      } else {
        prev.pushObject({
          humanPath,
          options: A([curr]),
          nodeName: get(A(humanPath.split(' > ')), 'lastObject')
        });
      }

      return prev;
    }, A()).sortBy('humanPath');
  }),

  init() {
    this._super(...arguments);

    if (!get(this, 'labelOpt')) {
      set(this, 'labelOpt', get(this, 'defaultLabelOpt'));
    }

    this._setSelectedOptions();
  },

  didReceiveAttrs({ oldAttrs, newAttrs }) {
    this._super(...arguments);
    let oldSelected;
    let newSelected;

    if (oldAttrs) {
      oldSelected = JSON.stringify(get(oldAttrs, 'selectedOptions'));
    }

    if (newAttrs) {
      newSelected = JSON.stringify(get(newAttrs, 'selectedOptions'));
    }

    if (!isBlank(get(this, 'selectedOptions')) && (oldSelected !== newSelected)) {
      this._setSelectedOptions();
    }
  },

  _setSelectedOptions() {
    const selectedOptions = A(get(this, 'selectedOptions'));
    let leaves = get(this, 'advancedTreeOptions')
      .map(o => this._treeTraverse(o, (node) => this._setChecked(node, selectedOptions)))
      .map(o => this._getLeaves(o));
    let node;
    let filteredOptions = selectedOptions.map(opt => {
      node = [].concat(...leaves).find(
        leaf => get(opt, 'key') === get(leaf, 'key') && get(opt, 'type') === get(leaf, 'type')
      );

      if (node) {
        return node;
      }

      set(opt, 'humanPath', get(opt, 'path').join(' > '));
      return opt;
    });
    set(this, '__selectedOptions', isBlank(selectedOptions) ? A() : filteredOptions);
  },

  _setChecked(o, __selectedOptions, isChecked = true) {
    if (A(__selectedOptions).find(
      opt => get(opt, 'key') === get(o, 'key') && get(opt, 'type') === get(o, 'type')
    )) {
      set(o, 'isChecked', isChecked);
    }
  },

  _buildPath(node, currPath = A()) {
    let newNode = Ember.$.extend(true, {}, node);
    const path = get(node, 'path');
    if (path && path.length) {
      set(newNode, 'humanPath', path.join(' > '));
      return newNode;
    }

    if (!get(node, 'nodeName') && currPath.length) {
      set(newNode, 'humanPath', currPath.join(' > '));
      set(newNode, 'path', currPath);
    } else {
      currPath.push(get(node, 'nodeName'));
      set(newNode, 'options', A(get(node, 'options')).map(
        o => this._buildPath(o, [].concat(...currPath)))
      );
      currPath = A();
    }

    return newNode;
  },

  _collapsableOption(opt) {
    const isSelectable = get(opt, 'isSelectable');
    const isChecked = leaf => get(leaf, 'isChecked');
    const isOptChecked = get(opt, 'isChecked');
    const groupName = get(opt, 'groupName');
    const options = get(opt, 'options') || [];
    const isCollapsed = get(opt, 'isCollapsed') || true;
    if (groupName) {
      return {
        isSelectable,
        isCollapsed,
        isChecked: options.some(isChecked) || isOptChecked || false,
        nodeName: groupName,
        options: options.map(o => this._collapsableOption(o))
      };
    }

    set(opt, 'isSelectable', true);
    set(opt, 'isChecked', !!isOptChecked);
    return opt;
  },

  _getLeaves(root, leaves = A()) {
    (get(root, 'options') || A()).forEach(
      o => !o.nodeName ? leaves.pushObject(o) : this._getLeaves(o, leaves)
    );
    return leaves;
  },

  _treeTraverse(root, visit) {
    visit(root);
    const options = A(get(root, 'options'));
    if (options.length) {
      options.forEach(o => this._treeTraverse(o, visit));
    }

    return root;
  },

  _findInternalNode(root, nameOrPath) {
    if (get(root, 'nodeName') === nameOrPath || get(root, 'humanPath') === nameOrPath) {
      return root;
    }
    let tmp, node;
    A(get(root, 'options')).forEach(o => {
      tmp = this._findInternalNode(o, nameOrPath);
      if (tmp) {
        node = tmp;
      }
    });

    return node;
  },

  onTreeSelectionChange(opts) {
    return get(this, 'onTreeSelectionChange')(opts);
  },

  scrollDropdownToSelected(el) {
    const container = $('.ember-power-select-tree-list').first();
    const scrollTop = $(el).offset().top - container.offset().top + container.scrollTop();
    return container.animate({ scrollTop }, 500);
  },

  actions: {
    handleSearch() {
      get(this, 'handleSearch')(...arguments);
      return false; // prevents default searching behaviour
    },
    onToggleGroup(group, evt) {
      // Check if checkbox or container is clicked
      const tagName = get(evt, 'target.tagName').toLowerCase();
      if (tagName === 'label' || tagName === 'input') {
        return;
      }
      set(group, 'isCollapsed', !get(group, 'isCollapsed'));

      return this.scrollDropdownToSelected(get(evt, 'target'));
    },
    removeNodeOrLeaf(nodeOrLeaf) {
      const __selectedOptions = get(this, '__selectedOptions');
      const isNode = !get(nodeOrLeaf, 'key');
      const key = isNode ? 'humanPath' : 'key';
      __selectedOptions.removeObjects(
        __selectedOptions.filterBy(key, get(nodeOrLeaf, key))
      );
      this._treeTraverse(nodeOrLeaf, o => set(o, 'isChecked', false));
      if (isNode) { // unchecks the group itself
        set(
          this._findInternalNode(
            {options: get(this, 'currentOptions')},
            get(nodeOrLeaf, 'nodeName') || get(nodeOrLeaf, 'humanPath')), 'isChecked', false
        );
      }
      set(this, '__selectedOptions', __selectedOptions);
    },
    handleChecked(nodeOrLeaf) {
      const newVal = !get(nodeOrLeaf, 'isChecked');
      const _setChecked = node => set(node, 'isChecked', newVal);
      const __selectedOptions = A(get(this, '__selectedOptions'));
      const __selectedOptionsKeys = __selectedOptions.map(o => get(o, 'key'));
      const nodeKey = get(nodeOrLeaf, 'key');
      const leaves = this._getLeaves(nodeOrLeaf);

      this._treeTraverse(nodeOrLeaf, _setChecked);

      if (get(nodeOrLeaf, 'nodeName')) {
        !newVal ?
          leaves.forEach(l => __selectedOptions.removeObject(__selectedOptions.findBy('key', get(l, 'key')))) :
          __selectedOptions.pushObjects(leaves.filter(l => !__selectedOptionsKeys.includes(get(l, 'key'))));
      } else {
        !newVal ?
          __selectedOptions.removeObject(__selectedOptions.findBy('key', nodeKey)) :
          __selectedOptions.pushObject(nodeOrLeaf);
      }

      set(this, '__selectedOptions', __selectedOptions);
      this.onTreeSelectionChange(__selectedOptions);
    }
  }
});
<commit_msg>FIX: add defaultDelimiter key<commit_after>/* jshint expr: true */
import Ember from 'ember';
import layout from '../templates/components/power-select-tree';
const { get, set, isBlank, computed, A, Component, $ } = Ember;

export default Component.extend({
  layout,
  classNames: ['ember-power-select-tree'],
  defaultLabelOpt: 'label',
  defaultDelimiter: ' > ',
  __selectedOptions: null,
  advancedTreeOptions: computed('treeOptions.[]', function() {
    return A(get(this, 'treeOptions'))
      .map(o => this._collapsableOption(o))
      .map(o => this._buildPath(o));
  }),
  currentOptions: computed('advancedTreeOptions.[]', '__selectedOptions.[]', function() {
    const __selectedOptions = get(this, '__selectedOptions');
    return get(this, 'advancedTreeOptions')
      .map(o => this._treeTraverse(o, (node) => this._setChecked(node, __selectedOptions)));
  }),

  groupedSelectedOptions: computed('__selectedOptions.[]', function() {
    return A(get(this, '__selectedOptions')).reduce((prev, curr) => {
      const humanPath = get(curr, 'humanPath') || '';
      const group = prev.findBy('humanPath', humanPath);
      if (group) {
        get(group, 'options').pushObject(curr);
      } else {
        prev.pushObject({
          humanPath,
          options: A([curr]),
          nodeName: get(A(humanPath.split(get(this, 'defaultDelimiter'))), 'lastObject')
        });
      }

      return prev;
    }, A()).sortBy('humanPath');
  }),

  init() {
    this._super(...arguments);

    if (!get(this, 'labelOpt')) {
      set(this, 'labelOpt', get(this, 'defaultLabelOpt'));
    }

    this._setSelectedOptions();
  },

  didReceiveAttrs({ oldAttrs, newAttrs }) {
    this._super(...arguments);
    let oldSelected;
    let newSelected;

    if (oldAttrs) {
      oldSelected = JSON.stringify(get(oldAttrs, 'selectedOptions'));
    }

    if (newAttrs) {
      newSelected = JSON.stringify(get(newAttrs, 'selectedOptions'));
    }

    if (!isBlank(get(this, 'selectedOptions')) && (oldSelected !== newSelected)) {
      this._setSelectedOptions();
    }
  },

  _setSelectedOptions() {
    const selectedOptions = A(get(this, 'selectedOptions'));
    let leaves = get(this, 'advancedTreeOptions')
      .map(o => this._treeTraverse(o, (node) => this._setChecked(node, selectedOptions)))
      .map(o => this._getLeaves(o));
    let node;
    let filteredOptions = selectedOptions.map(opt => {
      node = [].concat(...leaves).find(
        leaf => get(opt, 'key') === get(leaf, 'key') && get(opt, 'type') === get(leaf, 'type')
      );

      if (node) {
        return node;
      }

      set(opt, 'humanPath', get(opt, 'path').join(get(this, 'defaultDelimiter')));
      return opt;
    });
    set(this, '__selectedOptions', isBlank(selectedOptions) ? A() : filteredOptions);
  },

  _setChecked(o, __selectedOptions, isChecked = true) {
    if (A(__selectedOptions).find(
      opt => get(opt, 'key') === get(o, 'key') && get(opt, 'type') === get(o, 'type')
    )) {
      set(o, 'isChecked', isChecked);
    }
  },

  _buildPath(node, currPath = A()) {
    let newNode = Ember.$.extend(true, {}, node);
    const path = get(node, 'path');
    if (path && path.length) {
      set(newNode, 'humanPath', path.join(get(this, 'defaultDelimiter')));
      return newNode;
    }

    if (!get(node, 'nodeName') && currPath.length) {
      set(newNode, 'humanPath', currPath.join(get(this, 'defaultDelimiter')));
      set(newNode, 'path', currPath);
    } else {
      currPath.push(get(node, 'nodeName'));
      set(newNode, 'options', A(get(node, 'options')).map(
        o => this._buildPath(o, [].concat(...currPath)))
      );
      currPath = A();
    }

    return newNode;
  },

  _collapsableOption(opt) {
    const isSelectable = get(opt, 'isSelectable');
    const isChecked = leaf => get(leaf, 'isChecked');
    const isOptChecked = get(opt, 'isChecked');
    const groupName = get(opt, 'groupName');
    const options = get(opt, 'options') || [];
    const isCollapsed = get(opt, 'isCollapsed') || true;
    if (groupName) {
      return {
        isSelectable,
        isCollapsed,
        isChecked: options.some(isChecked) || isOptChecked || false,
        nodeName: groupName,
        options: options.map(o => this._collapsableOption(o))
      };
    }

    set(opt, 'isSelectable', true);
    set(opt, 'isChecked', !!isOptChecked);
    return opt;
  },

  _getLeaves(root, leaves = A()) {
    (get(root, 'options') || A()).forEach(
      o => !o.nodeName ? leaves.pushObject(o) : this._getLeaves(o, leaves)
    );
    return leaves;
  },

  _treeTraverse(root, visit) {
    visit(root);
    const options = A(get(root, 'options'));
    if (options.length) {
      options.forEach(o => this._treeTraverse(o, visit));
    }

    return root;
  },

  _findInternalNode(root, nameOrPath) {
    if (get(root, 'nodeName') === nameOrPath || get(root, 'humanPath') === nameOrPath) {
      return root;
    }
    let tmp, node;
    A(get(root, 'options')).forEach(o => {
      tmp = this._findInternalNode(o, nameOrPath);
      if (tmp) {
        node = tmp;
      }
    });

    return node;
  },

  onTreeSelectionChange(opts) {
    return get(this, 'onTreeSelectionChange')(opts);
  },

  scrollDropdownToSelected(el) {
    const container = $('.ember-power-select-tree-list').first();
    const scrollTop = $(el).offset().top - container.offset().top + container.scrollTop();
    return container.animate({ scrollTop }, 500);
  },

  actions: {
    handleSearch() {
      get(this, 'handleSearch')(...arguments);
      return false; // prevents default searching behaviour
    },
    onToggleGroup(group, evt) {
      // Check if checkbox or container is clicked
      const tagName = get(evt, 'target.tagName').toLowerCase();
      if (tagName === 'label' || tagName === 'input') {
        return;
      }
      set(group, 'isCollapsed', !get(group, 'isCollapsed'));

      return this.scrollDropdownToSelected(get(evt, 'target'));
    },
    removeNodeOrLeaf(nodeOrLeaf) {
      const __selectedOptions = get(this, '__selectedOptions');
      const isNode = !get(nodeOrLeaf, 'key');
      const key = isNode ? 'humanPath' : 'key';
      __selectedOptions.removeObjects(
        __selectedOptions.filterBy(key, get(nodeOrLeaf, key))
      );
      this._treeTraverse(nodeOrLeaf, o => set(o, 'isChecked', false));
      if (isNode) { // unchecks the group itself
        set(
          this._findInternalNode(
            {options: get(this, 'currentOptions')},
            get(nodeOrLeaf, 'nodeName') || get(nodeOrLeaf, 'humanPath')), 'isChecked', false
        );
      }
      set(this, '__selectedOptions', __selectedOptions);
    },
    handleChecked(nodeOrLeaf) {
      const newVal = !get(nodeOrLeaf, 'isChecked');
      const _setChecked = node => set(node, 'isChecked', newVal);
      const __selectedOptions = A(get(this, '__selectedOptions'));
      const __selectedOptionsKeys = __selectedOptions.map(o => get(o, 'key'));
      const nodeKey = get(nodeOrLeaf, 'key');
      const leaves = this._getLeaves(nodeOrLeaf);

      this._treeTraverse(nodeOrLeaf, _setChecked);

      if (get(nodeOrLeaf, 'nodeName')) {
        !newVal ?
          leaves.forEach(l => __selectedOptions.removeObject(__selectedOptions.findBy('key', get(l, 'key')))) :
          __selectedOptions.pushObjects(leaves.filter(l => !__selectedOptionsKeys.includes(get(l, 'key'))));
      } else {
        !newVal ?
          __selectedOptions.removeObject(__selectedOptions.findBy('key', nodeKey)) :
          __selectedOptions.pushObject(nodeOrLeaf);
      }

      set(this, '__selectedOptions', __selectedOptions);
      this.onTreeSelectionChange(__selectedOptions);
    }
  }
});
<|endoftext|>


<commit_before>'use strict';
const path = require('path');

module.exports = {
  docsDev: {
    assetsPublicPath: '/',
    // 指定 host 地址
    host: 'localhost',
    // 指定要监听请求的端口号
    port: 8080,
    // 编译完成的时候自动打开浏览器
    autoOpenBrowser: false,
    // 当出现编译错误的时候浏览器会显示一个叠加层
    errorOverlay: true,
    notifyOnErrors: true,
    poll: false,
    devtool: 'cheap-module-eval-source-map',
    cacheBusting: true,
    cssSourceMap: true,
    // env
    env: { 'NODE_ENV': JSON.stringify('development') }
  },
  docsBuild: {
    // template path
    index: path.join(__dirname, '../docs/dist/index.html'),
    assetsRoot: path.join(__dirname, '../docs/dist'),
    // 打包出来的静态文件存放的文件夹名称
    assetsSubDirectory: 'static',
    assetsPublicPath: '',
    // source maps
    sourceMap: false,
    devtool: '#source-map',
    // env
    env: { 'NODE_ENV': JSON.stringify('production') }
  }
};
<commit_msg>添加 config 注释<commit_after>'use strict';
const path = require('path');

module.exports = {
  docsDev: {
    assetsPublicPath: '/',
    // 指定 host 地址
    host: 'localhost',
    // 指定要监听请求的端口号
    port: 8080,
    // 编译完成的时候自动打开浏览器
    autoOpenBrowser: false,
    // 当出现编译错误的时候浏览器会显示一个叠加层
    errorOverlay: true,
    notifyOnErrors: true,
    poll: false,
    devtool: 'cheap-module-eval-source-map',
    cacheBusting: true,
    cssSourceMap: true,
    // env
    env: { 'NODE_ENV': JSON.stringify('development') }
  },
  docsBuild: {
    // template path
    index: path.join(__dirname, '../docs/dist/index.html'),
    assetsRoot: path.join(__dirname, '../docs/dist'),
    // 打包出来的静态文件存放的文件夹名称
    assetsSubDirectory: 'static',
    // gh-pages 只支持相对路径
    assetsPublicPath: '',
    // source maps
    sourceMap: false,
    devtool: '#source-map',
    // env
    env: { 'NODE_ENV': JSON.stringify('production') }
  }
};
<|endoftext|>


<commit_before>import Ember from 'ember';
import selectedClass from '../../mixin/selected-class';
import disabledClass from '../../mixin/disabled-class';

/**
 * Menu Component
 ```html
 ```
 */

export default Ember.Component.extend(selectedClass, disabledClass, {
	/**
	 * [tagName description]
	 */
	tagName: 'li',
	attributeBindings: ['role'],
	submenu: false,
	classNames: 'io-menu-item',
	classNamePrefix: function() {
		if (this.get('submenu')) {
			return 'io-menu-submenu-';
		}
		return 'io-menu-item-';
	}.property('submenu'),
	classNameBindings: ['submenuClass', 'mouseOverClass', 'openClass', 'selectedValueClass'],
	role: function() {
		if (this.get('submenu')) {
			return 'submenu';
		} else {
			return 'menuitem';
		}
	}.property('submenu'),
	submenuClass: function() {
		var ret = '';
		if (this.get('submenu')) {
			ret += ' io-menu-submenu';
			if (this.get('selected')) {
				ret += ' io-menu-submenu-selected';
			}
		}
		return ret;
	}.property('submenu'),
	selectedValueClass: function() {
		var selectedValue = this.get('selectedValue');
		var value = this.get('value');
		if (value && value === selectedValue) {
			return this.get('classNamePrefix') + 'selected';
		}
		return '';
 	}.property('selectedValue', 'value'),
	activeClass: function() {
		return this.get('classNamePrefix') + 'active';
	}.property('classNamePrefix'),
	mouseOver: false,
	// root menu is an inline menu
	isOpen: false,
	_setIsInlineSubmenu: function() {
		var $el = this.$();
		var $root = $el.parent('.io-menu-inline');
		if ($root.hasClass('io-menu-inline')) {
			this.set('isInlineSubmenu', true);
		} else {
			this.set('isInlineSubmenu', false);
		}
	}.on('didInsertElement'),
	mouseOverClass: function() {
		var ret = '';
		var isInlineSubmenu = this.get('isInlineSubmenu');
		if (this.get('mouseOver')) {
			ret += this.get('activeClass');
			if (this.get('submenu') && !isInlineSubmenu) {
				ret += ' ' + this.get('classNamePrefix') + 'open';
			}
		}

		if (this.get('isOpen')) {
			ret += this.get('classNamePrefix') + 'open';
		}
		return ret;
	}.property('mouseOver'),
	openClass: function() {
		var ret = '';
		var isInlineSubmenu = this.get('isInlineSubmenu');
		if (isInlineSubmenu && this.get('isOpen')) {
			ret = this.get('classNamePrefix') + 'open'
		}
		return ret;
	}.property('isOpen'),
	/**
	 * [mouseover event description]
	 * @type {[type]}
	 */
	t: null,
	mouseEnter: function() {
		clearTimeout(this.get('t'));
		this.set('mouseOver', true);
	},
	mouseLeave: function() {
		var t = setTimeout(function() {
			this.set('mouseOver', false);
		}.bind(this), 100);
		this.set('t', t);
	}
});<commit_msg>menu item 添加onClick 事件<commit_after>import Ember from 'ember';
import selectedClass from '../../mixin/selected-class';
import disabledClass from '../../mixin/disabled-class';

/**
 * Menu Component
 ```html
 ```
 */

export default Ember.Component.extend(selectedClass, disabledClass, {
	/**
	 * [tagName description]
	 */
	tagName: 'li',
	attributeBindings: ['role'],
	submenu: false,
	classNames: 'io-menu-item',
	classNamePrefix: function() {
		if (this.get('submenu')) {
			return 'io-menu-submenu-';
		}
		return 'io-menu-item-';
	}.property('submenu'),
	classNameBindings: ['submenuClass', 'mouseOverClass', 'openClass', 'selectedValueClass'],
	role: function() {
		if (this.get('submenu')) {
			return 'submenu';
		} else {
			return 'menuitem';
		}
	}.property('submenu'),
	submenuClass: function() {
		var ret = '';
		if (this.get('submenu')) {
			ret += ' io-menu-submenu';
			if (this.get('selected')) {
				ret += ' io-menu-submenu-selected';
			}
		}
		return ret;
	}.property('submenu'),
	selectedValueClass: function() {
		var selectedValue = this.get('selectedValue');
		var value = this.get('value');
		if (value && value === selectedValue) {
			return this.get('classNamePrefix') + 'selected';
		}
		return '';
 	}.property('selectedValue', 'value'),
	activeClass: function() {
		return this.get('classNamePrefix') + 'active';
	}.property('classNamePrefix'),
	mouseOver: false,
	// root menu is an inline menu
	isOpen: false,
	_setIsInlineSubmenu: function() {
		var $el = this.$();
		var $root = $el.parent('.io-menu-inline');
		if ($root.hasClass('io-menu-inline')) {
			this.set('isInlineSubmenu', true);
		} else {
			this.set('isInlineSubmenu', false);
		}
	}.on('didInsertElement'),
	mouseOverClass: function() {
		var ret = '';
		var isInlineSubmenu = this.get('isInlineSubmenu');
		if (this.get('mouseOver')) {
			ret += this.get('activeClass');
			if (this.get('submenu') && !isInlineSubmenu) {
				ret += ' ' + this.get('classNamePrefix') + 'open';
			}
		}

		if (this.get('isOpen')) {
			ret += this.get('classNamePrefix') + 'open';
		}
		return ret;
	}.property('mouseOver'),
	openClass: function() {
		var ret = '';
		var isInlineSubmenu = this.get('isInlineSubmenu');
		if (isInlineSubmenu && this.get('isOpen')) {
			ret = this.get('classNamePrefix') + 'open'
		}
		return ret;
	}.property('isOpen'),
	/**
	 * [mouseover event description]
	 * @type {[type]}
	 */
	t: null,
	mouseEnter: function() {
		clearTimeout(this.get('t'));
		this.set('mouseOver', true);
	},
	mouseLeave: function() {
		var t = setTimeout(function() {
			this.set('mouseOver', false);
		}.bind(this), 100);
		this.set('t', t);
	},
	click() {
		if (this.get('onClick')) {
			this.sendAction('onClick', this);
		}
	}
});<|endoftext|>


<commit_before>// The Client is the entry point to interacting with the Airbrake JS library.
// It stores configuration information and dispatches errors.
// window.Airbrake is an instance of Client.
function Client(getProcessor, getReporter, setupjQueryTracker) {
  var instance = this;

  var _environment;
  instance.setEnvironment = function(val) { _environment = val; };
  instance.getEnvironment = function() { return _environment; };

  var _key;
  instance.setKey = function(val) { _key = val; };
  instance.getKey = function() { return _key; };

  var _host;
  instance.setHost = function(val) { _host = val; };
  instance.getHost = function() { return _host; };

  var _errorDefaults;
  instance.setErrorDefaults = function(val) { _errorDefaults = val; };
  instance.getErrorDefaults = function() { return _errorDefaults; };

  var _guessFunctionName = false;
  instance.setGuessFunctionName = function(val) { _guessFunctionName = val; };
  instance.getGuessFunctionName = function() { return _guessFunctionName; };

  var _outputFormat = "JSON";
  instance.setOutputFormat = function(val) { _outputFormat = val; };
  instance.getOutputFormat = function() { return _outputFormat; };

  // setTrackJQ can fire a callback
  var _trackJQ = false;
  instance.setTrackJQ = function(val) {
    // fire if the status toggled from false to true and the callback is defined
    if (!_trackJQ && val && setupjQueryTracker) {
      setupjQueryTracker();
    }
    _trackJQ = val;
  };
  instance.getTrackJQ = function() { return !!_trackJQ; };

  instance.captureException = function(exception) {
    var processor = getProcessor && getProcessor(instance),
        reporter = processor && getReporter(instance);

    if (processor && reporter) {
      var data = processor.process(exception);
      reporter.report(data);
    }
  };
}

module.exports = Client;
<commit_msg>More comments for Client<commit_after>// The Client is the entry point to interacting with the Airbrake JS library.
// It stores configuration information and handles exceptions provided to it.
//
// It generates a Processor and a Reporter for each exception and uses them
// to transform an exception into data, and then to transport that data.
//
// window.Airbrake is an instance of Client
function Client(getProcessor, getReporter, setupjQueryTracker) {
  var instance = this;

  var _environment;
  instance.setEnvironment = function(val) { _environment = val; };
  instance.getEnvironment = function() { return _environment; };

  var _key;
  instance.setKey = function(val) { _key = val; };
  instance.getKey = function() { return _key; };

  var _host;
  instance.setHost = function(val) { _host = val; };
  instance.getHost = function() { return _host; };

  var _errorDefaults;
  instance.setErrorDefaults = function(val) { _errorDefaults = val; };
  instance.getErrorDefaults = function() { return _errorDefaults; };

  var _guessFunctionName = false;
  instance.setGuessFunctionName = function(val) { _guessFunctionName = val; };
  instance.getGuessFunctionName = function() { return _guessFunctionName; };

  var _outputFormat = "JSON";
  instance.setOutputFormat = function(val) { _outputFormat = val; };
  instance.getOutputFormat = function() { return _outputFormat; };

  // setTrackJQ can fire a callback
  var _trackJQ = false;
  instance.setTrackJQ = function(val) {
    // fire if the status toggled from false to true and the callback is defined
    if (!_trackJQ && val && setupjQueryTracker) {
      setupjQueryTracker();
    }
    _trackJQ = val;
  };
  instance.getTrackJQ = function() { return !!_trackJQ; };

  instance.captureException = function(exception) {
    // Get up-to-date Processor and Reporter for this exception
    var processor = getProcessor && getProcessor(instance),
        reporter = processor && getReporter(instance);

    if (processor && reporter) {
      // Transform the exception into a "standard" data format
      var data = processor.process(exception);
      // Transport data to receiver
      reporter.report(data);
    }
  };
}

module.exports = Client;
<|endoftext|>