mirror of https://github.com/rancher/ui.git
208 lines
4.9 KiB
JavaScript
208 lines
4.9 KiB
JavaScript
import Component from '@ember/component';
|
|
import layout from './template';
|
|
import { cancel, later } from '@ember/runloop';
|
|
import { oneWay } from '@ember/object/computed';
|
|
import { get, set } from '@ember/object';
|
|
import calculatePosition from 'shared/utils/calculate-position';
|
|
import { inject as service } from '@ember/service'
|
|
import $ from 'jquery';
|
|
import { isEmpty } from '@ember/utils';
|
|
|
|
export default Component.extend({
|
|
router: service(),
|
|
layout,
|
|
delay: 200,
|
|
renderInPlace: true,
|
|
publicDropdownApi: null,
|
|
dropdownCloseDelay: 150,
|
|
ddCloseDelayTimer: null,
|
|
|
|
openDelay: oneWay('delay'),
|
|
closeDelay: oneWay('delay'),
|
|
|
|
init() {
|
|
this._super(...arguments);
|
|
|
|
this.router.on('routeWillChange', (/* transition */) => {
|
|
if (!isEmpty(this.publicDropdownApi) && !isEmpty(get(this, 'publicDropdownApi.actions.close'))) {
|
|
this.publicDropdownApi.actions.close();
|
|
|
|
set(this, 'publicDropdownApi', null);
|
|
}
|
|
});
|
|
},
|
|
|
|
actions: {
|
|
registerAPI(dd) {
|
|
this.registerAPI(dd);
|
|
},
|
|
|
|
open(forContent, dropdown) {
|
|
if (get(this, 'closeTimer') || this.isTransitioning()) {
|
|
cancel(get(this, 'closeTimer'));
|
|
|
|
set(this, 'closeTimer', null);
|
|
} else {
|
|
let openFn = () => {
|
|
set(this, 'openTimer', null);
|
|
|
|
this.openDropdown.call(this, forContent, dropdown);
|
|
};
|
|
|
|
let openDelay = get(this, 'openDelay');
|
|
|
|
if (openDelay) {
|
|
set(this, 'openTimer', later(openFn, openDelay));
|
|
} else {
|
|
openFn();
|
|
}
|
|
}
|
|
},
|
|
|
|
close(forContent, dropdown) {
|
|
if (this.openTimer || this.isTransitioning()) {
|
|
cancel(this.openTimer);
|
|
|
|
set(this, 'openTimer', null);
|
|
} else {
|
|
let closeFn = () => {
|
|
set(this, 'closeTimer', null);
|
|
|
|
this.closeDropdown.call(this, forContent, dropdown);
|
|
};
|
|
|
|
let closeDelay = get(this, 'closeDelay');
|
|
|
|
if (closeDelay) {
|
|
set(this, 'closeTimer', later(closeFn, closeDelay));
|
|
} else {
|
|
closeFn();
|
|
}
|
|
}
|
|
},
|
|
|
|
prevent() {
|
|
return false;
|
|
},
|
|
|
|
calculatePosition,
|
|
},
|
|
|
|
openDropdown(forContent, dropdown) {
|
|
if ( forContent ) {
|
|
if (this.onBeforeOpen) {
|
|
this.onBeforeOpen(dropdown);
|
|
}
|
|
}
|
|
|
|
dropdown.actions.open();
|
|
|
|
if ( forContent ) {
|
|
if (this.onOpen) {
|
|
this.onOpen(dropdown);
|
|
}
|
|
}
|
|
},
|
|
|
|
closeDropdown(forContent, dropdown, skipFocus = true) {
|
|
if ( forContent ) {
|
|
if (this.onBeforeClose) {
|
|
this.onBeforeClose(dropdown);
|
|
}
|
|
}
|
|
|
|
// signature - event, skipfocus
|
|
dropdown.actions.close(null, skipFocus);
|
|
|
|
if ( forContent ) {
|
|
if (this.onClose) {
|
|
this.onClose(dropdown);
|
|
}
|
|
}
|
|
},
|
|
|
|
isTransitioning() {
|
|
if (this.router._routerMicrolib && this.router._routerMicrolib.activeTransition && this.router._routerMicrolib.activeTransition.isTransition) {
|
|
return true
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
registerAPI(publicDropdown) {
|
|
set(this, 'publicDropdownApi', publicDropdown);
|
|
},
|
|
|
|
focusIn() {
|
|
if (this.ddCloseDelayTimer) {
|
|
clearTimeout(this.ddCloseDelayTimer);
|
|
}
|
|
},
|
|
|
|
focusOut() {
|
|
if (this.publicDropdownApi && this.publicDropdownApi.isOpen) {
|
|
set(this, 'ddCloseDelayTimer', setTimeout(() => {
|
|
if (this.isDestroyed || this.isDestroying) {
|
|
return;
|
|
}
|
|
set(this, 'ddCloseDelayTimer', null);
|
|
|
|
this.closeDropdown(null, this.publicDropdownApi);
|
|
}, this.dropdownCloseDelay));
|
|
}
|
|
},
|
|
|
|
keyUp(e) {
|
|
const code = e.keyCode;
|
|
const { publicDropdownApi } = this;
|
|
|
|
if (!publicDropdownApi) {
|
|
return;
|
|
}
|
|
|
|
let tabList = $(`#ember-basic-dropdown-content-${ publicDropdownApi.uniqueId } > LI > a:first-child`);
|
|
let currentFocusIndex = tabList.index(e.target);
|
|
|
|
switch (code) {
|
|
case 27: {
|
|
if (publicDropdownApi && publicDropdownApi.isOpen) {
|
|
this.closeDropdown(null, publicDropdownApi, false);
|
|
}
|
|
break;
|
|
}
|
|
case 38: {
|
|
// up
|
|
let nextIndex = currentFocusIndex - 1;
|
|
|
|
if (nextIndex >= tabList.length) {
|
|
tabList.eq(tabList.length).focus();
|
|
} else {
|
|
tabList.eq(nextIndex).focus();
|
|
}
|
|
|
|
break;
|
|
}
|
|
case 40: {
|
|
// down
|
|
if (publicDropdownApi && publicDropdownApi.isOpen) {
|
|
let nextIndex = currentFocusIndex + 1;
|
|
|
|
if (nextIndex >= tabList.length) {
|
|
tabList.eq(0).focus();
|
|
} else {
|
|
tabList.eq(nextIndex).focus();
|
|
}
|
|
} else if (publicDropdownApi && !publicDropdownApi.isOpen) {
|
|
this.openDropdown(null, publicDropdownApi);
|
|
|
|
later(() => {
|
|
$(`#ember-basic-dropdown-content-${ publicDropdownApi.uniqueId } > LI > a:first-child`).first().focus();
|
|
}, 10)
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
}
|
|
},
|
|
});
|