initial commit
This commit is contained in:
commit
52aad94550
94 changed files with 43651 additions and 0 deletions
669
node_modules/@materializecss/materialize/js/dropdown.js
generated
vendored
Executable file
669
node_modules/@materializecss/materialize/js/dropdown.js
generated
vendored
Executable file
|
@ -0,0 +1,669 @@
|
|||
(function($, anim) {
|
||||
'use strict';
|
||||
|
||||
let _defaults = {
|
||||
alignment: 'left',
|
||||
autoFocus: true,
|
||||
constrainWidth: true,
|
||||
container: null,
|
||||
coverTrigger: true,
|
||||
closeOnClick: true,
|
||||
hover: false,
|
||||
inDuration: 150,
|
||||
outDuration: 250,
|
||||
onOpenStart: null,
|
||||
onOpenEnd: null,
|
||||
onCloseStart: null,
|
||||
onCloseEnd: null,
|
||||
onItemClick: null
|
||||
};
|
||||
|
||||
/**
|
||||
* @class
|
||||
*/
|
||||
class Dropdown extends Component {
|
||||
constructor(el, options) {
|
||||
super(Dropdown, el, options);
|
||||
|
||||
this.el.M_Dropdown = this;
|
||||
Dropdown._dropdowns.push(this);
|
||||
|
||||
this.id = M.getIdFromTrigger(el);
|
||||
this.dropdownEl = document.getElementById(this.id);
|
||||
this.$dropdownEl = $(this.dropdownEl);
|
||||
|
||||
/**
|
||||
* Options for the dropdown
|
||||
* @member Dropdown#options
|
||||
* @prop {String} [alignment='left'] - Edge which the dropdown is aligned to
|
||||
* @prop {Boolean} [autoFocus=true] - Automatically focus dropdown el for keyboard
|
||||
* @prop {Boolean} [constrainWidth=true] - Constrain width to width of the button
|
||||
* @prop {Element} container - Container element to attach dropdown to (optional)
|
||||
* @prop {Boolean} [coverTrigger=true] - Place dropdown over trigger
|
||||
* @prop {Boolean} [closeOnClick=true] - Close on click of dropdown item
|
||||
* @prop {Boolean} [hover=false] - Open dropdown on hover
|
||||
* @prop {Number} [inDuration=150] - Duration of open animation in ms
|
||||
* @prop {Number} [outDuration=250] - Duration of close animation in ms
|
||||
* @prop {Function} onOpenStart - Function called when dropdown starts opening
|
||||
* @prop {Function} onOpenEnd - Function called when dropdown finishes opening
|
||||
* @prop {Function} onCloseStart - Function called when dropdown starts closing
|
||||
* @prop {Function} onCloseEnd - Function called when dropdown finishes closing
|
||||
*/
|
||||
this.options = $.extend({}, Dropdown.defaults, options);
|
||||
|
||||
/**
|
||||
* Describes open/close state of dropdown
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.isOpen = false;
|
||||
|
||||
/**
|
||||
* Describes if dropdown content is scrollable
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.isScrollable = false;
|
||||
|
||||
/**
|
||||
* Describes if touch moving on dropdown content
|
||||
* @type {Boolean}
|
||||
*/
|
||||
this.isTouchMoving = false;
|
||||
|
||||
this.focusedIndex = -1;
|
||||
this.filterQuery = [];
|
||||
|
||||
// Move dropdown-content after dropdown-trigger
|
||||
this._moveDropdown();
|
||||
|
||||
this._makeDropdownFocusable();
|
||||
this._resetFilterQueryBound = this._resetFilterQuery.bind(this);
|
||||
this._handleDocumentClickBound = this._handleDocumentClick.bind(this);
|
||||
this._handleDocumentTouchmoveBound = this._handleDocumentTouchmove.bind(this);
|
||||
this._handleDropdownClickBound = this._handleDropdownClick.bind(this);
|
||||
this._handleDropdownKeydownBound = this._handleDropdownKeydown.bind(this);
|
||||
this._handleTriggerKeydownBound = this._handleTriggerKeydown.bind(this);
|
||||
this._setupEventHandlers();
|
||||
}
|
||||
|
||||
static get defaults() {
|
||||
return _defaults;
|
||||
}
|
||||
|
||||
static init(els, options) {
|
||||
return super.init(this, els, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Instance
|
||||
*/
|
||||
static getInstance(el) {
|
||||
let domElem = !!el.jquery ? el[0] : el;
|
||||
return domElem.M_Dropdown;
|
||||
}
|
||||
|
||||
/**
|
||||
* Teardown component
|
||||
*/
|
||||
destroy() {
|
||||
this._resetDropdownStyles();
|
||||
this._removeEventHandlers();
|
||||
Dropdown._dropdowns.splice(Dropdown._dropdowns.indexOf(this), 1);
|
||||
this.el.M_Dropdown = undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Event Handlers
|
||||
*/
|
||||
_setupEventHandlers() {
|
||||
// Trigger keydown handler
|
||||
this.el.addEventListener('keydown', this._handleTriggerKeydownBound);
|
||||
|
||||
// Item click handler
|
||||
this.dropdownEl.addEventListener('click', this._handleDropdownClickBound);
|
||||
|
||||
// Hover event handlers
|
||||
if (this.options.hover) {
|
||||
this._handleMouseEnterBound = this._handleMouseEnter.bind(this);
|
||||
this.el.addEventListener('mouseenter', this._handleMouseEnterBound);
|
||||
this._handleMouseLeaveBound = this._handleMouseLeave.bind(this);
|
||||
this.el.addEventListener('mouseleave', this._handleMouseLeaveBound);
|
||||
this.dropdownEl.addEventListener('mouseleave', this._handleMouseLeaveBound);
|
||||
|
||||
// Click event handlers
|
||||
} else {
|
||||
this._handleClickBound = this._handleClick.bind(this);
|
||||
this.el.addEventListener('click', this._handleClickBound);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove Event Handlers
|
||||
*/
|
||||
_removeEventHandlers() {
|
||||
this.el.removeEventListener('keydown', this._handleTriggerKeydownBound);
|
||||
this.dropdownEl.removeEventListener('click', this._handleDropdownClickBound);
|
||||
|
||||
if (this.options.hover) {
|
||||
this.el.removeEventListener('mouseenter', this._handleMouseEnterBound);
|
||||
this.el.removeEventListener('mouseleave', this._handleMouseLeaveBound);
|
||||
this.dropdownEl.removeEventListener('mouseleave', this._handleMouseLeaveBound);
|
||||
} else {
|
||||
this.el.removeEventListener('click', this._handleClickBound);
|
||||
}
|
||||
}
|
||||
|
||||
_setupTemporaryEventHandlers() {
|
||||
// Use capture phase event handler to prevent click
|
||||
document.body.addEventListener('click', this._handleDocumentClickBound, true);
|
||||
document.body.addEventListener('touchmove', this._handleDocumentTouchmoveBound);
|
||||
this.dropdownEl.addEventListener('keydown', this._handleDropdownKeydownBound);
|
||||
}
|
||||
|
||||
_removeTemporaryEventHandlers() {
|
||||
// Use capture phase event handler to prevent click
|
||||
document.body.removeEventListener('click', this._handleDocumentClickBound, true);
|
||||
document.body.removeEventListener('touchmove', this._handleDocumentTouchmoveBound);
|
||||
this.dropdownEl.removeEventListener('keydown', this._handleDropdownKeydownBound);
|
||||
}
|
||||
|
||||
_handleClick(e) {
|
||||
e.preventDefault();
|
||||
this.open();
|
||||
}
|
||||
|
||||
_handleMouseEnter() {
|
||||
this.open();
|
||||
}
|
||||
|
||||
_handleMouseLeave(e) {
|
||||
let toEl = e.toElement || e.relatedTarget;
|
||||
let leaveToDropdownContent = !!$(toEl).closest('.dropdown-content').length;
|
||||
let leaveToActiveDropdownTrigger = false;
|
||||
|
||||
let $closestTrigger = $(toEl).closest('.dropdown-trigger');
|
||||
if (
|
||||
$closestTrigger.length &&
|
||||
!!$closestTrigger[0].M_Dropdown &&
|
||||
$closestTrigger[0].M_Dropdown.isOpen
|
||||
) {
|
||||
leaveToActiveDropdownTrigger = true;
|
||||
}
|
||||
|
||||
// Close hover dropdown if mouse did not leave to either active dropdown-trigger or dropdown-content
|
||||
if (!leaveToActiveDropdownTrigger && !leaveToDropdownContent) {
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
|
||||
_handleDocumentClick(e) {
|
||||
let $target = $(e.target);
|
||||
if (
|
||||
this.options.closeOnClick &&
|
||||
$target.closest('.dropdown-content').length &&
|
||||
!this.isTouchMoving
|
||||
) {
|
||||
// isTouchMoving to check if scrolling on mobile.
|
||||
setTimeout(() => {
|
||||
this.close();
|
||||
}, 0);
|
||||
} else if (
|
||||
$target.closest('.dropdown-trigger').length ||
|
||||
!$target.closest('.dropdown-content').length
|
||||
) {
|
||||
setTimeout(() => {
|
||||
this.close();
|
||||
}, 0);
|
||||
}
|
||||
this.isTouchMoving = false;
|
||||
}
|
||||
|
||||
_handleTriggerKeydown(e) {
|
||||
// ARROW DOWN OR ENTER WHEN SELECT IS CLOSED - open Dropdown
|
||||
if ((e.which === M.keys.ARROW_DOWN || e.which === M.keys.ENTER) && !this.isOpen) {
|
||||
e.preventDefault();
|
||||
this.open();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Document Touchmove
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleDocumentTouchmove(e) {
|
||||
let $target = $(e.target);
|
||||
if ($target.closest('.dropdown-content').length) {
|
||||
this.isTouchMoving = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Dropdown Click
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleDropdownClick(e) {
|
||||
// onItemClick callback
|
||||
if (typeof this.options.onItemClick === 'function') {
|
||||
let itemEl = $(e.target).closest('li')[0];
|
||||
this.options.onItemClick.call(this, itemEl);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle Dropdown Keydown
|
||||
* @param {Event} e
|
||||
*/
|
||||
_handleDropdownKeydown(e) {
|
||||
if (e.which === M.keys.TAB) {
|
||||
e.preventDefault();
|
||||
this.close();
|
||||
|
||||
// Navigate down dropdown list
|
||||
} else if ((e.which === M.keys.ARROW_DOWN || e.which === M.keys.ARROW_UP) && this.isOpen) {
|
||||
e.preventDefault();
|
||||
let direction = e.which === M.keys.ARROW_DOWN ? 1 : -1;
|
||||
let newFocusedIndex = this.focusedIndex;
|
||||
let foundNewIndex = false;
|
||||
do {
|
||||
newFocusedIndex = newFocusedIndex + direction;
|
||||
|
||||
if (
|
||||
!!this.dropdownEl.children[newFocusedIndex] &&
|
||||
this.dropdownEl.children[newFocusedIndex].tabIndex !== -1
|
||||
) {
|
||||
foundNewIndex = true;
|
||||
break;
|
||||
}
|
||||
} while (newFocusedIndex < this.dropdownEl.children.length && newFocusedIndex >= 0);
|
||||
|
||||
if (foundNewIndex) {
|
||||
// Remove active class from old element
|
||||
if (this.focusedIndex >= 0)
|
||||
this.dropdownEl.children[this.focusedIndex].classList.remove('active');
|
||||
this.focusedIndex = newFocusedIndex;
|
||||
this._focusFocusedItem();
|
||||
}
|
||||
|
||||
// ENTER selects choice on focused item
|
||||
} else if (e.which === M.keys.ENTER && this.isOpen) {
|
||||
// Search for <a> and <button>
|
||||
let focusedElement = this.dropdownEl.children[this.focusedIndex];
|
||||
let $activatableElement = $(focusedElement)
|
||||
.find('a, button')
|
||||
.first();
|
||||
|
||||
// Click a or button tag if exists, otherwise click li tag
|
||||
if (!!$activatableElement.length) {
|
||||
$activatableElement[0].click();
|
||||
} else if (!!focusedElement) {
|
||||
focusedElement.click();
|
||||
}
|
||||
|
||||
// Close dropdown on ESC
|
||||
} else if (e.which === M.keys.ESC && this.isOpen) {
|
||||
e.preventDefault();
|
||||
this.close();
|
||||
}
|
||||
|
||||
// CASE WHEN USER TYPE LETTERS
|
||||
let letter = String.fromCharCode(e.which).toLowerCase(),
|
||||
nonLetters = [9, 13, 27, 38, 40];
|
||||
if (letter && nonLetters.indexOf(e.which) === -1) {
|
||||
this.filterQuery.push(letter);
|
||||
|
||||
let string = this.filterQuery.join(''),
|
||||
newOptionEl = $(this.dropdownEl)
|
||||
.find('li')
|
||||
.filter((el) => {
|
||||
return (
|
||||
$(el)
|
||||
.text()
|
||||
.toLowerCase()
|
||||
.indexOf(string) === 0
|
||||
);
|
||||
})[0];
|
||||
|
||||
if (newOptionEl) {
|
||||
this.focusedIndex = $(newOptionEl).index();
|
||||
this._focusFocusedItem();
|
||||
}
|
||||
}
|
||||
|
||||
this.filterTimeout = setTimeout(this._resetFilterQueryBound, 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup dropdown
|
||||
*/
|
||||
_resetFilterQuery() {
|
||||
this.filterQuery = [];
|
||||
}
|
||||
|
||||
_resetDropdownStyles() {
|
||||
this.$dropdownEl.css({
|
||||
display: '',
|
||||
width: '',
|
||||
height: '',
|
||||
left: '',
|
||||
top: '',
|
||||
'transform-origin': '',
|
||||
transform: '',
|
||||
opacity: ''
|
||||
});
|
||||
}
|
||||
|
||||
// Move dropdown after container or trigger
|
||||
_moveDropdown(containerEl) {
|
||||
if (!!this.options.container) {
|
||||
$(this.options.container).append(this.dropdownEl);
|
||||
} else if (containerEl) {
|
||||
if (!containerEl.contains(this.dropdownEl)) {
|
||||
$(containerEl).append(this.dropdownEl);
|
||||
}
|
||||
} else {
|
||||
this.$el.after(this.dropdownEl);
|
||||
}
|
||||
}
|
||||
|
||||
_makeDropdownFocusable() {
|
||||
// Needed for arrow key navigation
|
||||
this.dropdownEl.tabIndex = 0;
|
||||
|
||||
// Only set tabindex if it hasn't been set by user
|
||||
$(this.dropdownEl)
|
||||
.children()
|
||||
.each(function(el) {
|
||||
if (!el.getAttribute('tabindex')) {
|
||||
el.setAttribute('tabindex', 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
_focusFocusedItem() {
|
||||
if (
|
||||
this.focusedIndex >= 0 &&
|
||||
this.focusedIndex < this.dropdownEl.children.length &&
|
||||
this.options.autoFocus
|
||||
) {
|
||||
this.dropdownEl.children[this.focusedIndex].focus({
|
||||
preventScroll: true
|
||||
});
|
||||
this.dropdownEl.children[this.focusedIndex].scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'nearest',
|
||||
inline: 'nearest'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
_getDropdownPosition(closestOverflowParent) {
|
||||
let offsetParentBRect = this.el.offsetParent.getBoundingClientRect();
|
||||
let triggerBRect = this.el.getBoundingClientRect();
|
||||
let dropdownBRect = this.dropdownEl.getBoundingClientRect();
|
||||
|
||||
let idealHeight = dropdownBRect.height;
|
||||
let idealWidth = dropdownBRect.width;
|
||||
let idealXPos = triggerBRect.left - dropdownBRect.left;
|
||||
let idealYPos = triggerBRect.top - dropdownBRect.top;
|
||||
|
||||
let dropdownBounds = {
|
||||
left: idealXPos,
|
||||
top: idealYPos,
|
||||
height: idealHeight,
|
||||
width: idealWidth
|
||||
};
|
||||
|
||||
let alignments = M.checkPossibleAlignments(
|
||||
this.el,
|
||||
closestOverflowParent,
|
||||
dropdownBounds,
|
||||
this.options.coverTrigger ? 0 : triggerBRect.height
|
||||
);
|
||||
|
||||
let verticalAlignment = 'top';
|
||||
let horizontalAlignment = this.options.alignment;
|
||||
idealYPos += this.options.coverTrigger ? 0 : triggerBRect.height;
|
||||
|
||||
// Reset isScrollable
|
||||
this.isScrollable = false;
|
||||
|
||||
if (!alignments.top) {
|
||||
if (alignments.bottom) {
|
||||
verticalAlignment = 'bottom';
|
||||
|
||||
if (!this.options.coverTrigger) {
|
||||
idealYPos -= triggerBRect.height;
|
||||
}
|
||||
} else {
|
||||
this.isScrollable = true;
|
||||
|
||||
// Determine which side has most space and cutoff at correct height
|
||||
idealHeight -= 20; // Add padding when cutoff
|
||||
if (alignments.spaceOnTop > alignments.spaceOnBottom) {
|
||||
verticalAlignment = 'bottom';
|
||||
idealHeight += alignments.spaceOnTop;
|
||||
idealYPos -= this.options.coverTrigger
|
||||
? alignments.spaceOnTop - 20
|
||||
: alignments.spaceOnTop - 20 + triggerBRect.height;
|
||||
} else {
|
||||
idealHeight += alignments.spaceOnBottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If preferred horizontal alignment is possible
|
||||
if (!alignments[horizontalAlignment]) {
|
||||
let oppositeAlignment = horizontalAlignment === 'left' ? 'right' : 'left';
|
||||
if (alignments[oppositeAlignment]) {
|
||||
horizontalAlignment = oppositeAlignment;
|
||||
} else {
|
||||
// Determine which side has most space and cutoff at correct height
|
||||
if (alignments.spaceOnLeft > alignments.spaceOnRight) {
|
||||
horizontalAlignment = 'right';
|
||||
idealWidth += alignments.spaceOnLeft;
|
||||
idealXPos -= alignments.spaceOnLeft;
|
||||
} else {
|
||||
horizontalAlignment = 'left';
|
||||
idealWidth += alignments.spaceOnRight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (verticalAlignment === 'bottom') {
|
||||
idealYPos =
|
||||
idealYPos - dropdownBRect.height + (this.options.coverTrigger ? triggerBRect.height : 0);
|
||||
}
|
||||
if (horizontalAlignment === 'right') {
|
||||
idealXPos = idealXPos - dropdownBRect.width + triggerBRect.width;
|
||||
}
|
||||
return {
|
||||
x: idealXPos,
|
||||
y: idealYPos,
|
||||
verticalAlignment: verticalAlignment,
|
||||
horizontalAlignment: horizontalAlignment,
|
||||
height: idealHeight,
|
||||
width: idealWidth
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate in dropdown
|
||||
*/
|
||||
_animateIn() {
|
||||
anim.remove(this.dropdownEl);
|
||||
anim({
|
||||
targets: this.dropdownEl,
|
||||
opacity: {
|
||||
value: [0, 1],
|
||||
easing: 'easeOutQuad'
|
||||
},
|
||||
scaleX: [0.3, 1],
|
||||
scaleY: [0.3, 1],
|
||||
duration: this.options.inDuration,
|
||||
easing: 'easeOutQuint',
|
||||
complete: (anim) => {
|
||||
if (this.options.autoFocus) {
|
||||
this.dropdownEl.focus();
|
||||
}
|
||||
|
||||
// onOpenEnd callback
|
||||
if (typeof this.options.onOpenEnd === 'function') {
|
||||
this.options.onOpenEnd.call(this, this.el);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Animate out dropdown
|
||||
*/
|
||||
_animateOut() {
|
||||
anim.remove(this.dropdownEl);
|
||||
anim({
|
||||
targets: this.dropdownEl,
|
||||
opacity: {
|
||||
value: 0,
|
||||
easing: 'easeOutQuint'
|
||||
},
|
||||
scaleX: 0.3,
|
||||
scaleY: 0.3,
|
||||
duration: this.options.outDuration,
|
||||
easing: 'easeOutQuint',
|
||||
complete: (anim) => {
|
||||
this._resetDropdownStyles();
|
||||
|
||||
// onCloseEnd callback
|
||||
if (typeof this.options.onCloseEnd === 'function') {
|
||||
this.options.onCloseEnd.call(this, this.el);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Place dropdown
|
||||
*/
|
||||
_placeDropdown() {
|
||||
/**
|
||||
* Get closest ancestor that satisfies the condition
|
||||
* @param {Element} el Element to find ancestors on
|
||||
* @param {Function} condition Function that given an ancestor element returns true or false
|
||||
* @returns {Element} Return closest ancestor or null if none satisfies the condition
|
||||
*/
|
||||
const getClosestAncestor = function(el, condition) {
|
||||
let ancestor = el.parentNode;
|
||||
while (ancestor !== null && !$(ancestor).is(document)) {
|
||||
if (condition(ancestor)) {
|
||||
return ancestor;
|
||||
}
|
||||
ancestor = ancestor.parentNode;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
// Container here will be closest ancestor with overflow: hidden
|
||||
let closestOverflowParent = getClosestAncestor(this.dropdownEl, (ancestor) => {
|
||||
return $(ancestor).css('overflow') !== 'visible';
|
||||
});
|
||||
// Fallback
|
||||
if (!closestOverflowParent) {
|
||||
closestOverflowParent = !!this.dropdownEl.offsetParent
|
||||
? this.dropdownEl.offsetParent
|
||||
: this.dropdownEl.parentNode;
|
||||
}
|
||||
if ($(closestOverflowParent).css('position') === 'static')
|
||||
$(closestOverflowParent).css('position', 'relative');
|
||||
|
||||
this._moveDropdown(closestOverflowParent);
|
||||
|
||||
// Set width before calculating positionInfo
|
||||
let idealWidth = this.options.constrainWidth
|
||||
? this.el.getBoundingClientRect().width
|
||||
: this.dropdownEl.getBoundingClientRect().width;
|
||||
this.dropdownEl.style.width = idealWidth + 'px';
|
||||
|
||||
let positionInfo = this._getDropdownPosition(closestOverflowParent);
|
||||
this.dropdownEl.style.left = positionInfo.x + 'px';
|
||||
this.dropdownEl.style.top = positionInfo.y + 'px';
|
||||
this.dropdownEl.style.height = positionInfo.height + 'px';
|
||||
this.dropdownEl.style.width = positionInfo.width + 'px';
|
||||
this.dropdownEl.style.transformOrigin = `${
|
||||
positionInfo.horizontalAlignment === 'left' ? '0' : '100%'
|
||||
} ${positionInfo.verticalAlignment === 'top' ? '0' : '100%'}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open Dropdown
|
||||
*/
|
||||
open() {
|
||||
if (this.isOpen) {
|
||||
return;
|
||||
}
|
||||
this.isOpen = true;
|
||||
|
||||
// onOpenStart callback
|
||||
if (typeof this.options.onOpenStart === 'function') {
|
||||
this.options.onOpenStart.call(this, this.el);
|
||||
}
|
||||
|
||||
// Reset styles
|
||||
this._resetDropdownStyles();
|
||||
this.dropdownEl.style.display = 'block';
|
||||
|
||||
this._placeDropdown();
|
||||
this._animateIn();
|
||||
this._setupTemporaryEventHandlers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Close Dropdown
|
||||
*/
|
||||
close() {
|
||||
if (!this.isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.isOpen = false;
|
||||
this.focusedIndex = -1;
|
||||
|
||||
// onCloseStart callback
|
||||
if (typeof this.options.onCloseStart === 'function') {
|
||||
this.options.onCloseStart.call(this, this.el);
|
||||
}
|
||||
|
||||
this._animateOut();
|
||||
this._removeTemporaryEventHandlers();
|
||||
|
||||
if (this.options.autoFocus) {
|
||||
this.el.focus();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recalculate dimensions
|
||||
*/
|
||||
recalculateDimensions() {
|
||||
if (this.isOpen) {
|
||||
this.$dropdownEl.css({
|
||||
width: '',
|
||||
height: '',
|
||||
left: '',
|
||||
top: '',
|
||||
'transform-origin': ''
|
||||
});
|
||||
this._placeDropdown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @static
|
||||
* @memberof Dropdown
|
||||
*/
|
||||
Dropdown._dropdowns = [];
|
||||
|
||||
M.Dropdown = Dropdown;
|
||||
|
||||
if (M.jQueryLoaded) {
|
||||
M.initializeJqueryWrapper(Dropdown, 'dropdown', 'M_Dropdown');
|
||||
}
|
||||
})(cash, M.anime);
|
Loading…
Add table
Add a link
Reference in a new issue