Created
February 27, 2017 14:39
-
-
Save dobbbri/e8408bc9567e9de8a2c46d6966ccf7fa to your computer and use it in GitHub Desktop.
`v-dropdown` directive for Vue.js 2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* @usage | |
* | |
* <div v-dropdown="{autoClose: true}"> | |
* <button dropdown-toggle>Dropdown</button> | |
* <div class="dropdown-menu"> | |
* This is the dropdown menu. | |
* </div> | |
* </div> | |
* | |
* Options: | |
* - autoClose: Boolean | |
* Whether to close dropdown menu after being clicked. | |
* - click: 'toggle' (default) | 'open' | false | |
* If 'toggle', the menu will be toggled on click. | |
* If 'open', the menu will keep open on click. | |
* Otherwise ignored. | |
* - focus: 'open' | false (default) | |
* If 'open', keep open when focused. | |
* Otherwise ignored. | |
*/ | |
import Vue from 'vue'; | |
Vue.directive('dropdown', { | |
bind: function (el, binding) { | |
function doClose() { | |
if (!isOpen) return; | |
isOpen = false; | |
el.classList.remove('show'); | |
document.removeEventListener('mousedown', onClose, false); | |
} | |
function onClose(e) { | |
if (e && el.contains(e.target)) return; | |
doClose(); | |
} | |
function onOpen(_e) { | |
if (isOpen) return; | |
isOpen = true; | |
el.classList.add('show'); | |
document.addEventListener('mousedown', onClose, false); | |
} | |
function onToggle(_e) { | |
isOpen ? onClose() : onOpen(); | |
} | |
function onBlur(_e) { | |
setTimeout(() => { | |
const activeEl = document.activeElement; | |
if (activeEl !== document.body && !el.contains(activeEl)) { | |
doClose(); | |
} | |
}); | |
} | |
let isOpen = false; | |
const toggle = el.querySelector('[dropdown-toggle]'); | |
const {value} = binding; | |
const {autoClose, click='toggle', focus=false} = value || {}; | |
if (click === 'toggle') { | |
toggle.addEventListener('click', onToggle, false); | |
} else if (click === 'open') { | |
toggle.addEventListener('click', onOpen, false); | |
} | |
if (focus === 'open') { | |
toggle.addEventListener('focus', onOpen, false); | |
toggle.addEventListener('blur', onBlur, false); | |
} | |
autoClose && el.addEventListener('mouseup', doClose, false); | |
el.classList.add('dropdown'); | |
}, | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.dropdown { | |
position: relative; | |
&-menu { | |
position: absolute; | |
top: 100%; | |
left: 0; | |
// - fixed width | |
// width: 200px; | |
// - auto width without line wrap | |
// white-space: nowrap; | |
} | |
&:not(.show) .dropdown-menu { | |
display: none; | |
} | |
} | |
[dropdown-toggle] { | |
cursor: pointer; | |
user-select: none; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment