<commit_before>/**
 * @module Components
 *
 */
import { assert } from '@ember/debug';
import { loc } from '@ember/string';
import { isNone, isEmpty } from '@ember/utils';
import { computed, get, set } from '@ember/object';
import Component from '@ember/component';
import layout from '../templates/components/bc-select';
import BindOutsideClick from '../mixins/bind-outside-click';

/**
 * `Component/BCSelect`
 * Component select menu for displaying a list of items to a user.
 *
 * @class BCSelect
 * @namespace Components
 *
 * @property model {array} Array of key-value pair objects
 * @property itemLabel {string} The key of the key-value pair to display in the option list.
 * @property defaultLabel {string} The start label to display in the select menu. `Default: Select`
 * @property defaultFirstOption {boolean} True if the first option in the model array should be displayed. `Default: false`
 * @property menuTitle {string} This should be set if the select menu doesn't change titles when selected. This option overrides defaultLabel and defaultFirstOption.
 * @property onSelect {string} The function name to call when an item is selected. onSelect will pass the selected item to the listener.
 * @property targetObject {object} The View where the onSelect function can be called. `Default: controller`
 */
export default Component.extend(BindOutsideClick, {
	layout,

	classNames: ['bc-select'],
	classNameBindings: ['isOpen:active', 'isTop:top', 'small'],

	/**
	 * isOpen tracks the menu open state
	 *
	 * @private
	 * @property isOpen
	 * @type boolean
	 */
	isOpen: false,
	isTop: false,
	small: false,
	openTop: false,
	highlightSlected: true,

	model: null,

	/**
	 * internal use to track the current selected item from the list
	 *
	 * @private
	 * @property selectedItem
	 * @type object
	 */
	selectedItem: computed('model.@each._selected', 'model.[]', function() {
		let selected = null;
		if (!isNone(this.get('model'))) {
			selected = this.getSelected();
		}
		return selected;
	}),

	/**
	 * Initializes the listItem array
	 *
	 * @private
	 * @method setup
	 * @returns {void}
	 */
	didRender() {
		this._super();

		if (this.$()) {
			// call bindClick on the ClickedOffComponent mixin
			// to bind a click event to close the dialog
			this.bindClick('closeMenu');
		}
	},

	getSelected() {
		const items = this.get('model');
		let selected = null;
		if (typeof items === 'object' && typeof items.forEach === 'function') {
			items.forEach(item => {
				if (get(item, '_selected')) {
					selected = item;
				}
			});
		} else {
			Object.keys(items).forEach(key => {
				if (get(items[key], '_selected')) {
					selected = items[key];
				}
			});
		}
		return selected;
	},

	itemLabel: '',
	defaultLabel: loc('Select'),
	defaultFirstOption: false,

	menuTitle: computed('selectedItem', function() {
		let label = this.get('defaultLabel');
		let selectedItem = this.get('selectedItem');

		assert('"itemLabel" must be set to a property of the model', !isEmpty(this.get('itemLabel')));

		if (!isNone(selectedItem)) {
			label = get(selectedItem, this.get('itemLabel'));
		} else if (this.get('defaultFirstOption')) {
			selectedItem = this.get('model').objectAt(0);
			label = get(selectedItem, this.get('itemLabel'));
		}
		return label;
	}),

	/**
	 * click event handler
	 *
	 * @private
	 * @method click
	 * @returns {void}
	 */
	click() {
		this.send('openMenu');
	},

	checkPosition(elem) {
		let isBottom = false;
		if (elem === undefined || elem.get(0).tagName === 'HTML') {
			return isBottom;
		}

		const overflow = window.getComputedStyle(elem.get(0))['overflow-y'];
		const hasOverflow = (overflow === 'auto' || overflow === 'scroll');

		if (hasOverflow || elem.get(0).tagName === 'BODY') {
			let menuHeightTop = elem.height() - (elem.height() - (this.$().offset().top - elem.offset().top)) - 20; // height of the container minus the the bottom space from the top of the button.
			let menuHeightBot = elem.height() - ((this.$().offset().top + this.$().height()) - elem.offset().top) - 20; // height of the container minus the bottom of the select button.
			const maxHeight = parseInt(window.getComputedStyle(this.$('.select-container').get(0))['max-height'], 10);
<commit_msg>fix(component): bc-select not stoping propagation on menu clicks<commit_after>/**
 * @module Components
 *
 */
import { assert } from '@ember/debug';
import { loc } from '@ember/string';
import { isNone, isEmpty } from '@ember/utils';
import { computed, get, set } from '@ember/object';
import Component from '@ember/component';
import layout from '../templates/components/bc-select';
import BindOutsideClick from '../mixins/bind-outside-click';

/**
 * `Component/BCSelect`
 * Component select menu for displaying a list of items to a user.
 *
 * @class BCSelect
 * @namespace Components
 *
 * @property model {array} Array of key-value pair objects
 * @property itemLabel {string} The key of the key-value pair to display in the option list.
 * @property defaultLabel {string} The start label to display in the select menu. `Default: Select`
 * @property defaultFirstOption {boolean} True if the first option in the model array should be displayed. `Default: false`
 * @property menuTitle {string} This should be set if the select menu doesn't change titles when selected. This option overrides defaultLabel and defaultFirstOption.
 * @property onSelect {string} The function name to call when an item is selected. onSelect will pass the selected item to the listener.
 * @property targetObject {object} The View where the onSelect function can be called. `Default: controller`
 */
export default Component.extend(BindOutsideClick, {
	layout,

	classNames: ['bc-select'],
	classNameBindings: ['isOpen:active', 'isTop:top', 'small'],

	/**
	 * isOpen tracks the menu open state
	 *
	 * @private
	 * @property isOpen
	 * @type boolean
	 */
	isOpen: false,
	isTop: false,
	small: false,
	openTop: false,
	highlightSlected: true,

	model: null,

	/**
	 * internal use to track the current selected item from the list
	 *
	 * @private
	 * @property selectedItem
	 * @type object
	 */
	selectedItem: computed('model.@each._selected', 'model.[]', function() {
		let selected = null;
		if (!isNone(this.get('model'))) {
			selected = this.getSelected();
		}
		return selected;
	}),

	/**
	 * Initializes the listItem array
	 *
	 * @private
	 * @method setup
	 * @returns {void}
	 */
	didRender() {
		this._super();

		if (this.$()) {
			// call bindClick on the ClickedOffComponent mixin
			// to bind a click event to close the dialog
			this.bindClick('closeMenu');
		}
	},

	getSelected() {
		const items = this.get('model');
		let selected = null;
		if (typeof items === 'object' && typeof items.forEach === 'function') {
			items.forEach(item => {
				if (get(item, '_selected')) {
					selected = item;
				}
			});
		} else {
			Object.keys(items).forEach(key => {
				if (get(items[key], '_selected')) {
					selected = items[key];
				}
			});
		}
		return selected;
	},

	itemLabel: '',
	defaultLabel: loc('Select'),
	defaultFirstOption: false,

	menuTitle: computed('selectedItem', function() {
		let label = this.get('defaultLabel');
		let selectedItem = this.get('selectedItem');

		assert('"itemLabel" must be set to a property of the model', !isEmpty(this.get('itemLabel')));

		if (!isNone(selectedItem)) {
			label = get(selectedItem, this.get('itemLabel'));
		} else if (this.get('defaultFirstOption')) {
			selectedItem = this.get('model').objectAt(0);
			label = get(selectedItem, this.get('itemLabel'));
		}
		return label;
	}),

	/**
	 * click event handler
	 *
	 * @private
	 * @method click
	 * @returns {void}
	 */
	click(evt) {
		evt.stopPropagation();
		this.send('openMenu');

		return false;
	},

	checkPosition(elem) {
		let isBottom = false;
		if (elem === undefined || elem.get(0).tagName === 'HTML') {
			return isBottom;
		}

		const overflow = window.getComputedStyle(elem.get(0))['overflow-y'];
		const hasOverflow = (overflow === 'auto' || overflow === 'scroll');

		if (hasOverflow || elem.get(0).tagName === 'BODY') {
			let menuHeightTop = elem.height() - (elem.height() - (this.$().offset().top - elem.offset().top)) - 20; // height of the container minus the the bottom space from the top of the button.
			let menuHeightBot = elem.height() - ((this.$().offset().top + this.$().height()) - elem.offset().top) - 20; // height of the container minus the bottom of the select button.
			const maxHeight = parseInt(window.getComputedStyle(this.$('.select-container').get(0))['max-height'], 10);

{'fraction_non_alphanumeric': 0.1501519046506193, 'fraction_numerical': 0.002570694087403599, 'mean_word_length': 3.835593220338983, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7460256', 'n_tokens_mistral': 2782, 'n_tokens_neox': 2519, 'n_words': 812}