Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Bootstrap
bootstrap
Commits
90261b48
Commit
90261b48
authored
7 years ago
by
Johann-S
Committed by
XhmikosR
6 years ago
Browse files
Options
Download
Email Patches
Plain Diff
Dropdown without jQuery
parent
330a2973
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
js/src/dom/eventHandler.js
+2
-3
js/src/dom/eventHandler.js
js/src/dom/manipulator.js
+12
-0
js/src/dom/manipulator.js
js/src/dropdown.js
+98
-97
js/src/dropdown.js
js/tests/unit/dom/eventHandler.js
+0
-1
js/tests/unit/dom/eventHandler.js
js/tests/unit/dropdown.js
+104
-81
js/tests/unit/dropdown.js
js/tests/visual/dropdown.html
+9
-0
js/tests/visual/dropdown.html
with
225 additions
and
182 deletions
+225
-182
js/src/dom/eventHandler.js
+
2
-
3
View file @
90261b48
...
...
@@ -334,7 +334,7 @@ const EventHandler = (() => {
let
defaultPrevented
=
false
if
(
inNamespace
&&
typeof
$
!==
'
undefined
'
)
{
jQueryEvent
=
new
$
.
Event
(
event
,
args
)
jQueryEvent
=
$
.
Event
(
event
,
args
)
$
(
element
).
trigger
(
jQueryEvent
)
bubbles
=
!
jQueryEvent
.
isPropagationStopped
()
...
...
@@ -342,8 +342,7 @@ const EventHandler = (() => {
defaultPrevented
=
jQueryEvent
.
isDefaultPrevented
()
}
let
evt
=
null
let
evt
=
null
if
(
isNative
)
{
evt
=
document
.
createEvent
(
'
HTMLEvents
'
)
evt
.
initEvent
(
typeEvent
,
bubbles
,
true
)
...
...
This diff is collapsed.
Click to expand it.
js/src/dom/manipulator.js
+
12
-
0
View file @
90261b48
...
...
@@ -38,6 +38,18 @@ const Manipulator = {
}
element
.
removeAttribute
(
`data-
${
key
.
replace
(
/
[
A-Z
]
/g
,
(
chr
)
=>
`-
${
chr
.
toLowerCase
()}
`
)}
`
)
},
toggleClass
(
element
,
className
)
{
if
(
typeof
element
===
'
undefined
'
||
element
===
null
)
{
return
}
if
(
element
.
classList
.
contains
(
className
))
{
element
.
classList
.
remove
(
className
)
}
else
{
element
.
classList
.
add
(
className
)
}
}
}
...
...
This diff is collapsed.
Click to expand it.
js/src/dropdown.js
+
98
-
97
View file @
90261b48
...
...
@@ -5,8 +5,11 @@
* --------------------------------------------------------------------------
*/
import
$
from
'
jquery
'
import
Data
from
'
./dom/data
'
import
EventHandler
from
'
./dom/eventHandler
'
import
Manipulator
from
'
./dom/manipulator
'
import
Popper
from
'
popper.js
'
import
SelectorEngine
from
'
./dom/selectorEngine
'
import
Util
from
'
./util
'
/**
...
...
@@ -20,7 +23,6 @@ const VERSION = '4.3.1'
const
DATA_KEY
=
'
bs.dropdown
'
const
EVENT_KEY
=
`.
${
DATA_KEY
}
`
const
DATA_API_KEY
=
'
.data-api
'
const
JQUERY_NO_CONFLICT
=
$
.
fn
[
NAME
]
const
ESCAPE_KEYCODE
=
27
// KeyboardEvent.which value for Escape (Esc) key
const
SPACE_KEYCODE
=
32
// KeyboardEvent.which value for space key
const
TAB_KEYCODE
=
9
// KeyboardEvent.which value for tab key
...
...
@@ -120,12 +122,12 @@ class Dropdown {
// Public
toggle
()
{
if
(
this
.
_element
.
disabled
||
$
(
this
.
_element
).
hasClas
s
(
ClassName
.
DISABLED
))
{
if
(
this
.
_element
.
disabled
||
this
.
_element
.
classList
.
contain
s
(
ClassName
.
DISABLED
))
{
return
}
const
parent
=
Dropdown
.
_getParentFromElement
(
this
.
_element
)
const
isActive
=
$
(
this
.
_menu
).
hasClas
s
(
ClassName
.
SHOW
)
const
isActive
=
this
.
_menu
.
classList
.
contain
s
(
ClassName
.
SHOW
)
Dropdown
.
_clearMenus
()
...
...
@@ -136,11 +138,9 @@ class Dropdown {
const
relatedTarget
=
{
relatedTarget
:
this
.
_element
}
const
showEvent
=
$
.
Event
(
Event
.
SHOW
,
relatedTarget
)
const
showEvent
=
Event
Handler
.
trigger
(
parent
,
Event
.
SHOW
,
relatedTarget
)
$
(
parent
).
trigger
(
showEvent
)
if
(
showEvent
.
isDefaultPrevented
())
{
if
(
showEvent
.
defaultPrevented
)
{
return
}
...
...
@@ -171,7 +171,7 @@ class Dropdown {
// to allow the menu to "escape" the scroll parent's boundaries
// https://github.com/twbs/bootstrap/issues/24251
if
(
this
.
_config
.
boundary
!==
'
scrollParent
'
)
{
$
(
parent
).
addClass
(
ClassName
.
POSITION_STATIC
)
parent
.
classList
.
add
(
ClassName
.
POSITION_STATIC
)
}
this
.
_popper
=
new
Popper
(
referenceElement
,
this
.
_menu
,
this
.
_getPopperConfig
())
}
...
...
@@ -181,68 +181,64 @@ class Dropdown {
// only needed because of broken event delegation on iOS
// https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html
if
(
'
ontouchstart
'
in
document
.
documentElement
&&
$
(
parent
).
closest
(
Selector
.
NAVBAR_NAV
).
length
===
0
)
{
$
(
document
.
body
).
children
().
on
(
'
mouseover
'
,
null
,
$
.
noop
)
!
Util
.
makeArray
(
SelectorEngine
.
closest
(
parent
,
Selector
.
NAVBAR_NAV
)).
length
)
{
Util
.
makeArray
(
document
.
body
.
children
)
.
forEach
((
elem
)
=>
EventHandler
.
on
(
elem
,
'
mouseover
'
,
null
,
Util
.
noop
()))
}
this
.
_element
.
focus
()
this
.
_element
.
setAttribute
(
'
aria-expanded
'
,
true
)
$
(
this
.
_menu
).
toggleClass
(
ClassName
.
SHOW
)
$
(
parent
)
.
toggleClass
(
ClassName
.
SHOW
)
.
trigger
(
$
.
Event
(
Event
.
SHOWN
,
relatedTarget
))
Manipulator
.
toggleClass
(
this
.
_menu
,
ClassName
.
SHOW
)
Manipulator
.
toggleClass
(
parent
,
ClassName
.
SHOW
)
EventHandler
.
trigger
(
parent
,
Event
.
SHOWN
,
relatedTarget
)
}
show
()
{
if
(
this
.
_element
.
disabled
||
$
(
this
.
_element
).
hasClas
s
(
ClassName
.
DISABLED
)
||
$
(
this
.
_menu
).
hasClas
s
(
ClassName
.
SHOW
))
{
if
(
this
.
_element
.
disabled
||
this
.
_element
.
classList
.
contain
s
(
ClassName
.
DISABLED
)
||
this
.
_menu
.
classList
.
contain
s
(
ClassName
.
SHOW
))
{
return
}
const
parent
=
Dropdown
.
_getParentFromElement
(
this
.
_element
)
const
relatedTarget
=
{
relatedTarget
:
this
.
_element
}
const
showEvent
=
$
.
Event
(
Event
.
SHOW
,
relatedTarget
)
const
parent
=
Dropdown
.
_getParentFromElement
(
this
.
_element
)
$
(
parent
).
trigger
(
showEven
t
)
const
showEvent
=
EventHandler
.
trigger
(
parent
,
Event
.
SHOW
,
relatedTarge
t
)
if
(
showEvent
.
isD
efaultPrevented
()
)
{
if
(
showEvent
.
d
efaultPrevented
)
{
return
}
$
(
this
.
_menu
).
toggleClass
(
ClassName
.
SHOW
)
$
(
parent
)
.
toggleClass
(
ClassName
.
SHOW
)
.
trigger
(
$
.
Event
(
Event
.
SHOWN
,
relatedTarget
))
Manipulator
.
toggleClass
(
this
.
_menu
,
ClassName
.
SHOW
)
Manipulator
.
toggleClass
(
parent
,
ClassName
.
SHOW
)
EventHandler
.
trigger
(
parent
,
Event
.
SHOWN
,
relatedTarget
)
}
hide
()
{
if
(
this
.
_element
.
disabled
||
$
(
this
.
_element
).
hasClas
s
(
ClassName
.
DISABLED
)
||
!
$
(
this
.
_menu
).
hasClas
s
(
ClassName
.
SHOW
))
{
if
(
this
.
_element
.
disabled
||
this
.
_element
.
classList
.
contain
s
(
ClassName
.
DISABLED
)
||
!
this
.
_menu
.
classList
.
contain
s
(
ClassName
.
SHOW
))
{
return
}
const
parent
=
Dropdown
.
_getParentFromElement
(
this
.
_element
)
const
relatedTarget
=
{
relatedTarget
:
this
.
_element
}
const
hideEvent
=
$
.
Event
(
Event
.
HIDE
,
relatedTarget
)
const
parent
=
Dropdown
.
_getParentFromElement
(
this
.
_element
)
$
(
parent
).
trigger
(
hideEven
t
)
const
hideEvent
=
EventHandler
.
trigger
(
parent
,
Event
.
HIDE
,
relatedTarge
t
)
if
(
hideEvent
.
isD
efaultPrevented
()
)
{
if
(
hideEvent
.
d
efaultPrevented
)
{
return
}
$
(
this
.
_menu
).
toggleClass
(
ClassName
.
SHOW
)
$
(
parent
)
.
toggleClass
(
ClassName
.
SHOW
)
.
trigger
(
$
.
Event
(
Event
.
HIDDEN
,
relatedTarget
))
Manipulator
.
toggleClass
(
this
.
_menu
,
ClassName
.
SHOW
)
Manipulator
.
toggleClass
(
parent
,
ClassName
.
SHOW
)
EventHandler
.
trigger
(
parent
,
Event
.
SHOWN
,
relatedTarget
)
}
dispose
()
{
$
.
removeData
(
this
.
_element
,
DATA_KEY
)
$
(
this
.
_element
).
off
(
EVENT_KEY
)
Data
.
removeData
(
this
.
_element
,
DATA_KEY
)
EventHandler
.
off
(
this
.
_element
,
EVENT_KEY
)
this
.
_element
=
null
this
.
_menu
=
null
if
(
this
.
_popper
!==
null
)
{
...
...
@@ -261,7 +257,7 @@ class Dropdown {
// Private
_addEventListeners
()
{
$
(
this
.
_element
).
on
(
Event
.
CLICK
,
(
event
)
=>
{
EventHandler
.
on
(
this
.
_element
,
Event
.
CLICK
,
(
event
)
=>
{
event
.
preventDefault
()
event
.
stopPropagation
()
this
.
toggle
()
...
...
@@ -271,7 +267,7 @@ class Dropdown {
_getConfig
(
config
)
{
config
=
{
...
this
.
constructor
.
Default
,
...
$
(
this
.
_element
)
.
data
()
,
...
Util
.
getDataAttributes
(
this
.
_element
),
...
config
}
...
...
@@ -296,27 +292,27 @@ class Dropdown {
}
_getPlacement
()
{
const
$
parentDropdown
=
$
(
this
.
_element
.
parentNode
)
let
placement
=
AttachmentMap
.
BOTTOM
const
parentDropdown
=
this
.
_element
.
parentNode
let
placement
=
AttachmentMap
.
BOTTOM
// Handle dropup
if
(
$
parentDropdown
.
hasClas
s
(
ClassName
.
DROPUP
))
{
if
(
parentDropdown
.
classList
.
contain
s
(
ClassName
.
DROPUP
))
{
placement
=
AttachmentMap
.
TOP
if
(
$
(
this
.
_menu
).
hasClas
s
(
ClassName
.
MENURIGHT
))
{
if
(
this
.
_menu
.
classList
.
contain
s
(
ClassName
.
MENURIGHT
))
{
placement
=
AttachmentMap
.
TOPEND
}
}
else
if
(
$
parentDropdown
.
hasClas
s
(
ClassName
.
DROPRIGHT
))
{
}
else
if
(
parentDropdown
.
classList
.
contain
s
(
ClassName
.
DROPRIGHT
))
{
placement
=
AttachmentMap
.
RIGHT
}
else
if
(
$
parentDropdown
.
hasClas
s
(
ClassName
.
DROPLEFT
))
{
}
else
if
(
parentDropdown
.
classList
.
contain
s
(
ClassName
.
DROPLEFT
))
{
placement
=
AttachmentMap
.
LEFT
}
else
if
(
$
(
this
.
_menu
).
hasClas
s
(
ClassName
.
MENURIGHT
))
{
}
else
if
(
this
.
_menu
.
classList
.
contain
s
(
ClassName
.
MENURIGHT
))
{
placement
=
AttachmentMap
.
BOTTOMEND
}
return
placement
}
_detectNavbar
()
{
return
$
(
this
.
_element
).
closest
(
'
.navbar
'
).
length
>
0
return
Util
.
makeArray
(
SelectorEngine
.
closest
(
this
.
_element
,
'
.navbar
'
)
)
.
length
>
0
}
_getOffset
()
{
...
...
@@ -364,22 +360,26 @@ class Dropdown {
// Static
static
_jQueryInterface
(
config
)
{
return
this
.
each
(
function
()
{
let
data
=
$
(
this
).
data
(
DATA_KEY
)
const
_config
=
typeof
config
===
'
object
'
?
config
:
null
static
_dropdownInterface
(
element
,
config
)
{
let
data
=
Data
.
getData
(
element
,
DATA_KEY
)
const
_config
=
typeof
config
===
'
object
'
?
config
:
null
if
(
!
data
)
{
data
=
new
Dropdown
(
this
,
_config
)
$
(
this
).
data
(
DATA_KEY
,
data
)
}
if
(
!
data
)
{
data
=
new
Dropdown
(
element
,
_config
)
Data
.
setData
(
element
,
DATA_KEY
,
data
)
}
if
(
typeof
config
===
'
string
'
)
{
if
(
typeof
data
[
config
]
===
'
undefined
'
)
{
throw
new
TypeError
(
`No method named "
${
config
}
"`
)
}
data
[
config
]()
if
(
typeof
config
===
'
string
'
)
{
if
(
typeof
data
[
config
]
===
'
undefined
'
)
{
throw
new
Error
(
`No method named "
${
config
}
"`
)
}
data
[
config
]()
}
}
static
_jQueryInterface
(
config
)
{
return
this
.
each
(
function
()
{
Dropdown
.
_dropdownInterface
(
this
,
config
)
})
}
...
...
@@ -389,11 +389,10 @@ class Dropdown {
return
}
const
toggles
=
[].
slice
.
call
(
document
.
querySelectorAll
(
Selector
.
DATA_TOGGLE
))
const
toggles
=
Util
.
makeArray
(
SelectorEngine
.
find
(
Selector
.
DATA_TOGGLE
))
for
(
let
i
=
0
,
len
=
toggles
.
length
;
i
<
len
;
i
++
)
{
const
parent
=
Dropdown
.
_getParentFromElement
(
toggles
[
i
])
const
context
=
$
(
toggles
[
i
]
).
data
(
DATA_KEY
)
const
parent
=
Dropdown
.
_getParentFromElement
(
toggles
[
i
])
const
context
=
Data
.
getData
(
toggles
[
i
]
,
DATA_KEY
)
const
relatedTarget
=
{
relatedTarget
:
toggles
[
i
]
}
...
...
@@ -407,34 +406,34 @@ class Dropdown {
}
const
dropdownMenu
=
context
.
_menu
if
(
!
$
(
parent
).
hasClas
s
(
ClassName
.
SHOW
))
{
if
(
!
parent
.
classList
.
contain
s
(
ClassName
.
SHOW
))
{
continue
}
if
(
event
&&
(
event
.
type
===
'
click
'
&&
/input|textarea/i
.
test
(
event
.
target
.
tagName
)
||
event
.
type
===
'
keyup
'
&&
event
.
which
===
TAB_KEYCODE
)
&&
$
.
contains
(
parent
,
event
.
target
))
{
/input|textarea/i
.
test
(
event
.
target
.
tagName
)
||
event
.
type
===
'
keyup
'
&&
event
.
which
===
TAB_KEYCODE
)
&&
parent
.
contains
(
event
.
target
))
{
continue
}
const
hideEvent
=
$
.
Event
(
Event
.
HIDE
,
relatedTarget
)
$
(
parent
).
trigger
(
hideEvent
)
if
(
hideEvent
.
isDefaultPrevented
())
{
const
hideEvent
=
EventHandler
.
trigger
(
parent
,
Event
.
HIDE
,
relatedTarget
)
if
(
hideEvent
.
defaultPrevented
)
{
continue
}
// If this is a touch-enabled device we remove the extra
// empty mouseover listeners we added for iOS support
if
(
'
ontouchstart
'
in
document
.
documentElement
)
{
$
(
document
.
body
).
children
().
off
(
'
mouseover
'
,
null
,
$
.
noop
)
Util
.
makeArray
(
document
.
body
.
children
)
.
forEach
((
elem
)
=>
EventHandler
.
off
(
elem
,
'
mouseover
'
,
null
,
Util
.
noop
()))
}
toggles
[
i
].
setAttribute
(
'
aria-expanded
'
,
'
false
'
)
$
(
dropdownMenu
).
removeClass
(
ClassName
.
SHOW
)
$
(
parent
)
.
removeClass
(
ClassName
.
SHOW
)
.
trigger
(
$
.
Event
(
Event
.
HIDDEN
,
relatedTarget
))
dropdownMenu
.
classList
.
remove
(
ClassName
.
SHOW
)
parent
.
classList
.
remove
(
ClassName
.
SHOW
)
EventHandler
.
trigger
(
parent
,
Event
.
HIDDEN
,
relatedTarget
)
}
}
...
...
@@ -468,26 +467,25 @@ class Dropdown {
event
.
preventDefault
()
event
.
stopPropagation
()
if
(
this
.
disabled
||
$
(
this
).
hasClas
s
(
ClassName
.
DISABLED
))
{
if
(
this
.
disabled
||
this
.
classList
.
contain
s
(
ClassName
.
DISABLED
))
{
return
}
const
parent
=
Dropdown
.
_getParentFromElement
(
this
)
const
isActive
=
$
(
parent
).
hasClas
s
(
ClassName
.
SHOW
)
const
isActive
=
parent
.
classList
.
contain
s
(
ClassName
.
SHOW
)
if
(
!
isActive
||
isActive
&&
(
event
.
which
===
ESCAPE_KEYCODE
||
event
.
which
===
SPACE_KEYCODE
))
{
if
(
event
.
which
===
ESCAPE_KEYCODE
)
{
const
toggle
=
parent
.
querySelector
(
Selector
.
DATA_TOGGLE
)
$
(
toggle
).
trigger
(
'
focus
'
)
EventHandler
.
trigger
(
SelectorEngine
.
findOne
(
Selector
.
DATA_TOGGLE
,
parent
),
'
focus
'
)
}
$
(
this
)
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
this
,
'
click
'
)
return
}
const
items
=
[].
slice
.
call
(
parent
.
querySelectorAll
(
Selector
.
VISIBLE_ITEMS
))
if
(
items
.
length
===
0
)
{
if
(
!
items
.
length
)
{
return
}
...
...
@@ -515,31 +513,34 @@ class Dropdown {
* ------------------------------------------------------------------------
*/
$
(
document
)
.
on
(
Event
.
KEYDOWN_DATA_API
,
Selector
.
DATA_TOGGLE
,
Dropdown
.
_dataApiKeydownHandler
)
.
on
(
Event
.
KEYDOWN_DATA_API
,
Selector
.
MENU
,
Dropdown
.
_dataApiKeydownHandler
)
.
on
(
`
${
Event
.
CLICK_DATA_API
}
${
Event
.
KEYUP_DATA_API
}
`
,
Dropdown
.
_clearMenus
)
.
on
(
Event
.
CLICK_DATA_API
,
Selector
.
DATA_TOGGLE
,
function
(
event
)
{
event
.
preventDefault
()
event
.
stopPropagation
()
Dropdown
.
_jQueryInterface
.
call
(
$
(
this
),
'
toggle
'
)
})
.
on
(
Event
.
CLICK_DATA_API
,
Selector
.
FORM_CHILD
,
(
e
)
=>
{
e
.
stopPropagation
()
})
EventHandler
.
on
(
document
,
Event
.
KEYDOWN_DATA_API
,
Selector
.
DATA_TOGGLE
,
Dropdown
.
_dataApiKeydownHandler
)
EventHandler
.
on
(
document
,
Event
.
KEYDOWN_DATA_API
,
Selector
.
MENU
,
Dropdown
.
_dataApiKeydownHandler
)
EventHandler
.
on
(
document
,
Event
.
CLICK_DATA_API
,
Dropdown
.
_clearMenus
)
EventHandler
.
on
(
document
,
Event
.
KEYUP_DATA_API
,
Dropdown
.
_clearMenus
)
EventHandler
.
on
(
document
,
Event
.
CLICK_DATA_API
,
Selector
.
DATA_TOGGLE
,
function
(
event
)
{
event
.
preventDefault
()
event
.
stopPropagation
()
Dropdown
.
_dropdownInterface
(
this
,
'
toggle
'
)
})
EventHandler
.
on
(
document
,
Event
.
CLICK_DATA_API
,
Selector
.
FORM_CHILD
,
(
e
)
=>
e
.
stopPropagation
())
/**
* ------------------------------------------------------------------------
* jQuery
* ------------------------------------------------------------------------
* add .dropdown to jQuery only if jQuery is present
*/
$
.
fn
[
NAME
]
=
Dropdown
.
_jQueryInterface
$
.
fn
[
NAME
].
Constructor
=
Dropdown
$
.
fn
[
NAME
].
noConflict
=
()
=>
{
$
.
fn
[
NAME
]
=
JQUERY_NO_CONFLICT
return
Dropdown
.
_jQueryInterface
const
$
=
Util
.
jQuery
if
(
typeof
$
!==
'
undefined
'
)
{
const
JQUERY_NO_CONFLICT
=
$
.
fn
[
NAME
]
$
.
fn
[
NAME
]
=
Dropdown
.
_jQueryInterface
$
.
fn
[
NAME
].
Constructor
=
Dropdown
$
.
fn
[
NAME
].
noConflict
=
()
=>
{
$
.
fn
[
NAME
]
=
JQUERY_NO_CONFLICT
return
Dropdown
.
_jQueryInterface
}
}
export
default
Dropdown
This diff is collapsed.
Click to expand it.
js/tests/unit/dom/eventHandler.js
+
0
-
1
View file @
90261b48
...
...
@@ -336,6 +336,5 @@ $(function () {
assert
.
ok
(
i
===
5
,
'
listener removed again
'
)
document
.
body
.
removeChild
(
element
)
})
})
This diff is collapsed.
Click to expand it.
js/tests/unit/dropdown.js
+
104
-
81
View file @
90261b48
...
...
@@ -28,6 +28,7 @@ $(function () {
QUnit
.
test
(
'
should throw explicit error on undefined method
'
,
function
(
assert
)
{
assert
.
expect
(
1
)
var
$el
=
$
(
'
<div/>
'
)
$el
.
appendTo
(
'
#qunit-fixture
'
)
$el
.
bootstrapDropdown
()
try
{
$el
.
bootstrapDropdown
(
'
noMethod
'
)
...
...
@@ -39,6 +40,7 @@ $(function () {
QUnit
.
test
(
'
should return jquery collection containing the element
'
,
function
(
assert
)
{
assert
.
expect
(
2
)
var
$el
=
$
(
'
<div/>
'
)
$el
.
appendTo
(
'
#qunit-fixture
'
)
var
$dropdown
=
$el
.
bootstrapDropdown
()
assert
.
ok
(
$dropdown
instanceof
$
,
'
returns jquery collection
'
)
assert
.
strictEqual
(
$dropdown
[
0
],
$el
[
0
],
'
collection contains element
'
)
...
...
@@ -129,13 +131,14 @@ $(function () {
.
appendTo
(
'
#qunit-fixture
'
)
.
find
(
'
[data-toggle="dropdown"]
'
)
.
bootstrapDropdown
()
$dropdown
.
parent
(
'
.dropdown
'
)
.
on
(
'
shown.bs.dropdown
'
,
function
()
{
assert
.
strictEqual
(
$dropdown
.
attr
(
'
aria-expanded
'
),
'
true
'
,
'
aria-expanded is set to string "true" on click
'
)
done
()
})
$dropdown
.
trigger
(
'
click
'
)
var
dropdownParent
=
$dropdown
.
parent
(
'
.dropdown
'
)[
0
]
EventHandler
.
on
(
dropdownParent
,
'
shown.bs.dropdown
'
,
function
()
{
assert
.
strictEqual
(
$dropdown
.
attr
(
'
aria-expanded
'
),
'
true
'
,
'
aria-expanded is set to string "true" on click
'
)
done
()
})
EventHandler
.
trigger
(
$dropdown
[
0
],
'
click
'
)
})
QUnit
.
test
(
'
should set aria-expanded="false" on target when dropdown menu is hidden
'
,
function
(
assert
)
{
...
...
@@ -157,15 +160,15 @@ $(function () {
.
find
(
'
[data-toggle="dropdown"]
'
)
.
bootstrapDropdown
()
$dropdown
.
parent
(
'
.dropdown
'
)
.
on
(
'
hidden.bs.dropdown
'
,
function
()
{
assert
.
strictEqual
(
$dropdown
.
attr
(
'
aria-expanded
'
),
'
false
'
,
'
aria-expanded is set to string "false" on hide
'
)
done
()
})
var
dropdownParent
=
$dropdown
.
parent
(
'
.dropdown
'
)[
0
]
$dropdown
.
trigger
(
'
click
'
)
$
(
document
.
body
).
trigger
(
'
click
'
)
EventHandler
.
one
(
dropdownParent
,
'
hidden.bs.dropdown
'
,
function
()
{
assert
.
strictEqual
(
$dropdown
.
attr
(
'
aria-expanded
'
),
'
false
'
,
'
aria-expanded is set to string "false" on hide
'
)
done
()
})
EventHandler
.
trigger
(
$dropdown
[
0
],
'
click
'
)
EventHandler
.
trigger
(
document
.
body
,
'
click
'
)
})
QUnit
.
test
(
'
should not open dropdown if target is disabled via class
'
,
function
(
assert
)
{
...
...
@@ -197,23 +200,26 @@ $(function () {
var
done
=
assert
.
async
()
var
dropdownHTML
=
'
<div class="tabs">
'
+
'
<div class="dropdown">
'
+
'
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>
'
+
'
<div class="dropdown-menu">
'
+
'
<a class="dropdown-item" href="#">Secondary link</a>
'
+
'
<a class="dropdown-item" href="#">Something else here</a>
'
+
'
<div class="divider"/>
'
+
'
<a class="dropdown-item" href="#">Another link</a>
'
+
'
</div>
'
+
'
</div>
'
+
'
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown</a>
'
+
'
<div class="dropdown-menu">
'
+
'
<a class="dropdown-item" href="#">Secondary link</a>
'
+
'
<a class="dropdown-item" href="#">Something else here</a>
'
+
'
<div class="divider"/>
'
+
'
<a class="dropdown-item" href="#">Another link</a>
'
+
'
</div>
'
+
'
</div>
'
+
'
</div>
'
var
$dropdown
=
$
(
dropdownHTML
).
find
(
'
[data-toggle="dropdown"]
'
).
bootstrapDropdown
()
$
(
dropdownHTML
).
appendTo
(
'
#qunit-fixture
'
)
var
$dropdown
=
$
(
'
#qunit-fixture
'
).
find
(
'
[data-toggle="dropdown"]
'
).
bootstrapDropdown
()
$dropdown
.
parent
(
'
.dropdown
'
)
.
on
(
'
shown.bs.dropdown
'
,
function
()
{
assert
.
ok
(
$dropdown
.
parent
(
'
.dropdown
'
).
hasClass
(
'
show
'
),
'
"show" class added on click
'
)
done
()
})
$dropdown
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$dropdown
[
0
],
'
click
'
)
})
QUnit
.
test
(
'
should remove "show" class if body is clicked
'
,
function
(
assert
)
{
...
...
@@ -244,7 +250,8 @@ $(function () {
assert
.
ok
(
!
$dropdown
.
parent
(
'
.dropdown
'
).
hasClass
(
'
show
'
),
'
"show" class removed
'
)
done
()
})
$dropdown
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$dropdown
[
0
],
'
click
'
)
})
QUnit
.
test
(
'
should remove "show" class if tabbing outside of menu
'
,
function
(
assert
)
{
...
...
@@ -269,14 +276,17 @@ $(function () {
.
parent
(
'
.dropdown
'
)
.
on
(
'
shown.bs.dropdown
'
,
function
()
{
assert
.
ok
(
$dropdown
.
parent
(
'
.dropdown
'
).
hasClass
(
'
show
'
),
'
"show" class added on click
'
)
var
e
=
$
.
Event
(
'
keyup
'
)
e
.
which
=
9
// Tab
$
(
document
.
body
).
trigger
(
e
)
}).
on
(
'
hidden.bs.dropdown
'
,
function
()
{
EventHandler
.
trigger
(
document
.
body
,
'
keyup
'
,
{
which
:
9
// Tab
})
})
.
on
(
'
hidden.bs.dropdown
'
,
function
()
{
assert
.
ok
(
!
$dropdown
.
parent
(
'
.dropdown
'
).
hasClass
(
'
show
'
),
'
"show" class removed
'
)
done
()
})
$dropdown
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$dropdown
[
0
],
'
click
'
)
})
QUnit
.
test
(
'
should remove "show" class if body is clicked, with multiple dropdowns
'
,
function
(
assert
)
{
...
...
@@ -310,7 +320,7 @@ $(function () {
$
(
document
.
body
).
trigger
(
'
click
'
)
}).
on
(
'
hidden.bs.dropdown
'
,
function
()
{
assert
.
strictEqual
(
$
(
'
#qunit-fixture .dropdown-menu.show
'
).
length
,
0
,
'
"show" class removed
'
)
$last
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$last
[
0
],
'
click
'
)
})
$last
.
parent
(
'
.btn-group
'
)
...
...
@@ -322,7 +332,7 @@ $(function () {
assert
.
strictEqual
(
$
(
'
#qunit-fixture .dropdown-menu.show
'
).
length
,
0
,
'
"show" class removed
'
)
done
()
})
$first
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$first
[
0
],
'
click
'
)
})
QUnit
.
test
(
'
should remove "show" class if body if tabbing outside of menu, with multiple dropdowns
'
,
function
(
assert
)
{
...
...
@@ -353,26 +363,26 @@ $(function () {
.
on
(
'
shown.bs.dropdown
'
,
function
()
{
assert
.
strictEqual
(
$first
.
parents
(
'
.show
'
).
length
,
1
,
'
"show" class added on click
'
)
assert
.
strictEqual
(
$
(
'
#qunit-fixture .dropdown-menu.show
'
).
length
,
1
,
'
only one dropdown is shown
'
)
var
e
=
$
.
Event
(
'
keyup
'
)
e
.
which
=
9
// Tab
$
(
document
.
body
).
trigger
(
e
)
EventHandler
.
trigger
(
document
.
body
,
'
keyup
'
,
{
which
:
9
// Tab
}
)
}).
on
(
'
hidden.bs.dropdown
'
,
function
()
{
assert
.
strictEqual
(
$
(
'
#qunit-fixture .dropdown-menu.show
'
).
length
,
0
,
'
"show" class removed
'
)
$last
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$last
[
0
],
'
click
'
)
})
$last
.
parent
(
'
.btn-group
'
)
.
on
(
'
shown.bs.dropdown
'
,
function
()
{
assert
.
strictEqual
(
$last
.
parent
(
'
.show
'
).
length
,
1
,
'
"show" class added on click
'
)
assert
.
strictEqual
(
$
(
'
#qunit-fixture .dropdown-menu.show
'
).
length
,
1
,
'
only one dropdown is shown
'
)
var
e
=
$
.
Event
(
'
keyup
'
)
e
.
which
=
9
// Tab
$
(
document
.
body
).
trigger
(
e
)
EventHandler
.
trigger
(
document
.
body
,
'
keyup
'
,
{
which
:
9
// Tab
}
)
}).
on
(
'
hidden.bs.dropdown
'
,
function
()
{
assert
.
strictEqual
(
$
(
'
#qunit-fixture .dropdown-menu.show
'
).
length
,
0
,
'
"show" class removed
'
)
done
()
})
$first
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$first
[
0
],
'
click
'
)
})
QUnit
.
test
(
'
should fire show and hide event
'
,
function
(
assert
)
{
...
...
@@ -405,8 +415,8 @@ $(function () {
done
()
})
$dropdown
.
trigger
(
'
click
'
)
$
(
document
.
body
).
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$dropdown
[
0
],
'
click
'
)
EventHandler
.
trigger
(
document
.
body
,
'
click
'
)
})
QUnit
.
test
(
'
should fire shown and hidden event
'
,
function
(
assert
)
{
...
...
@@ -439,8 +449,8 @@ $(function () {
done
()
})
$dropdown
.
trigger
(
'
click
'
)
$
(
document
.
body
).
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$dropdown
[
0
],
'
click
'
)
EventHandler
.
trigger
(
document
.
body
,
'
click
'
)
})
QUnit
.
test
(
'
should fire shown and hidden event with a relatedTarget
'
,
function
(
assert
)
{
...
...
@@ -472,7 +482,7 @@ $(function () {
$
(
document
.
body
).
trigger
(
'
click
'
)
})
$dropdown
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$dropdown
[
0
],
'
click
'
)
})
QUnit
.
test
(
'
should fire hide and hidden event with a clickEvent
'
,
function
(
assert
)
{
...
...
@@ -586,7 +596,7 @@ $(function () {
done
()
})
$dropdown
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$dropdown
[
0
],
'
click
'
)
})
QUnit
.
test
(
'
should skip disabled element when using keyboard navigation
'
,
function
(
assert
)
{
...
...
@@ -621,7 +631,7 @@ $(function () {
assert
.
ok
(
!
$
(
document
.
activeElement
).
is
(
'
:disabled
'
),
'
:disabled is not focused
'
)
done
()
})
$dropdown
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$dropdown
[
0
],
'
click
'
)
})
QUnit
.
test
(
'
should focus next/previous element when using keyboard navigation
'
,
function
(
assert
)
{
...
...
@@ -645,23 +655,24 @@ $(function () {
.
parent
(
'
.dropdown
'
)
.
on
(
'
shown.bs.dropdown
'
,
function
()
{
assert
.
ok
(
true
,
'
shown was fired
'
)
$dropdown
.
trigger
(
$
.
Event
(
'
keydown
'
,
{
EventHandler
.
trigger
(
$dropdown
[
0
],
'
keydown
'
,
{
which
:
40
})
)
})
assert
.
ok
(
$
(
document
.
activeElement
).
is
(
$
(
'
#item1
'
)),
'
item1 is focused
'
)
$
(
document
.
activeElement
).
trigger
(
$
.
Event
(
'
keydown
'
,
{
EventHandler
.
trigger
(
document
.
activeElement
,
'
keydown
'
,
{
which
:
40
})
)
})
assert
.
ok
(
$
(
document
.
activeElement
).
is
(
$
(
'
#item2
'
)),
'
item2 is focused
'
)
$
(
document
.
activeElement
).
trigger
(
$
.
Event
(
'
keydown
'
,
{
EventHandler
.
trigger
(
document
.
activeElement
,
'
keydown
'
,
{
which
:
38
})
)
})
assert
.
ok
(
$
(
document
.
activeElement
).
is
(
$
(
'
#item1
'
)),
'
item1 is focused
'
)
done
()
})
$dropdown
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$dropdown
[
0
],
'
click
'
)
})
QUnit
.
test
(
'
should not close the dropdown if the user clicks on a text field
'
,
function
(
assert
)
{
...
...
@@ -688,9 +699,9 @@ $(function () {
.
parent
(
'
.dropdown
'
)
.
on
(
'
shown.bs.dropdown
'
,
function
()
{
assert
.
ok
(
$dropdown
.
parent
(
'
.dropdown
'
).
hasClass
(
'
show
'
),
'
dropdown menu is shown
'
)
$textfield
.
trigger
(
$
.
Event
(
'
click
'
)
)
EventHandler
.
trigger
(
$textfield
[
0
],
'
click
'
)
})
$dropdown
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$dropdown
[
0
],
'
click
'
)
})
QUnit
.
test
(
'
should not close the dropdown if the user clicks on a textarea
'
,
function
(
assert
)
{
...
...
@@ -717,9 +728,9 @@ $(function () {
.
parent
(
'
.dropdown
'
)
.
on
(
'
shown.bs.dropdown
'
,
function
()
{
assert
.
ok
(
$dropdown
.
parent
(
'
.dropdown
'
).
hasClass
(
'
show
'
),
'
dropdown menu is shown
'
)
$textarea
.
trigger
(
$
.
Event
(
'
click
'
)
)
EventHandler
.
trigger
(
$textarea
[
0
],
'
click
'
)
})
$dropdown
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$dropdown
[
0
],
'
click
'
)
})
QUnit
.
test
(
'
Dropdown should not use Popper.js in navbar
'
,
function
(
assert
)
{
...
...
@@ -748,7 +759,7 @@ $(function () {
assert
.
ok
(
typeof
$dropdownMenu
.
attr
(
'
style
'
)
===
'
undefined
'
,
'
No inline style applied by Popper.js
'
)
done
()
})
$triggerDropdown
.
trigger
(
$
.
Event
(
'
click
'
)
)
EventHandler
.
trigger
(
$triggerDropdown
[
0
],
'
click
'
)
})
QUnit
.
test
(
'
should ignore keyboard events for <input>s and <textarea>s within dropdown-menu, except for escape key
'
,
function
(
assert
)
{
...
...
@@ -810,14 +821,16 @@ $(function () {
assert
.
ok
(
$
(
document
.
activeElement
)[
0
]
===
$textarea
[
0
],
'
textarea still focused
'
)
// Key escape
$input
.
trigger
(
'
focus
'
).
trigger
(
$
.
Event
(
'
keydown
'
,
{
$input
.
trigger
(
'
focus
'
)
EventHandler
.
trigger
(
$input
[
0
],
'
keydown
'
,
{
which
:
27
}))
})
assert
.
ok
(
!
$dropdown
.
parent
(
'
.dropdown
'
).
hasClass
(
'
show
'
),
'
dropdown menu is not shown
'
)
done
()
})
$dropdown
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$dropdown
[
0
],
'
click
'
)
})
QUnit
.
test
(
'
should ignore space key events for <input>s within dropdown, and accept up, down and escape
'
,
function
(
assert
)
{
...
...
@@ -857,35 +870,40 @@ $(function () {
assert
.
ok
(
$
(
document
.
activeElement
).
is
(
$input
),
'
input is still focused
'
)
// Key escape
$input
.
trigger
(
'
focus
'
).
trigger
(
$
.
Event
(
'
keydown
'
,
{
$input
.
trigger
(
'
focus
'
)
EventHandler
.
trigger
(
$input
[
0
],
'
keydown
'
,
{
which
:
27
})
)
})
assert
.
ok
(
!
$dropdown
.
parent
(
'
.dropdown
'
).
hasClass
(
'
show
'
),
'
dropdown menu is not shown
'
)
$dropdown
.
parent
(
'
.dropdown
'
)
.
one
(
'
shown.bs.dropdown
'
,
function
()
{
assert
.
ok
(
true
,
'
shown was fired
'
)
// Key down
$input
.
trigger
(
'
focus
'
).
trigger
(
$
.
Event
(
'
keydown
'
,
{
$input
.
trigger
(
'
focus
'
)
EventHandler
.
trigger
(
$input
[
0
],
'
keydown
'
,
{
which
:
40
})
)
})
assert
.
ok
(
document
.
activeElement
===
$
(
'
#item1
'
)[
0
],
'
item1 is focused
'
)
$dropdown
.
parent
(
'
.dropdown
'
)
.
one
(
'
shown.bs.dropdown
'
,
function
()
{
// Key up
$input
.
trigger
(
'
focus
'
).
trigger
(
$
.
Event
(
'
keydown
'
,
{
$input
.
trigger
(
'
focus
'
)
EventHandler
.
trigger
(
$input
[
0
],
'
keydown
'
,
{
which
:
38
})
)
})
assert
.
ok
(
document
.
activeElement
===
$
(
'
#item1
'
)[
0
],
'
item1 is focused
'
)
done
()
}).
bootstrapDropdown
(
'
toggle
'
)
$input
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$input
[
0
],
'
click
'
)
})
$input
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$input
[
0
],
'
click
'
)
})
$input
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$input
[
0
],
'
click
'
)
})
QUnit
.
test
(
'
should ignore space key events for <textarea>s within dropdown, and accept up, down and escape
'
,
function
(
assert
)
{
...
...
@@ -925,35 +943,40 @@ $(function () {
assert
.
ok
(
$
(
document
.
activeElement
).
is
(
$textarea
),
'
textarea is still focused
'
)
// Key escape
$textarea
.
trigger
(
'
focus
'
).
trigger
(
$
.
Event
(
'
keydown
'
,
{
$textarea
.
trigger
(
'
focus
'
)
EventHandler
.
trigger
(
$textarea
[
0
],
'
keydown
'
,
{
which
:
27
})
)
})
assert
.
ok
(
!
$dropdown
.
parent
(
'
.dropdown
'
).
hasClass
(
'
show
'
),
'
dropdown menu is not shown
'
)
$dropdown
.
parent
(
'
.dropdown
'
)
.
one
(
'
shown.bs.dropdown
'
,
function
()
{
assert
.
ok
(
true
,
'
shown was fired
'
)
// Key down
$textarea
.
trigger
(
'
focus
'
).
trigger
(
$
.
Event
(
'
keydown
'
,
{
$textarea
.
trigger
(
'
focus
'
)
EventHandler
.
trigger
(
$textarea
[
0
],
'
keydown
'
,
{
which
:
40
})
)
})
assert
.
ok
(
document
.
activeElement
===
$
(
'
#item1
'
)[
0
],
'
item1 is focused
'
)
$dropdown
.
parent
(
'
.dropdown
'
)
.
one
(
'
shown.bs.dropdown
'
,
function
()
{
// Key up
$textarea
.
trigger
(
'
focus
'
).
trigger
(
$
.
Event
(
'
keydown
'
,
{
$textarea
.
trigger
(
'
focus
'
)
EventHandler
.
trigger
(
$textarea
[
0
],
'
keydown
'
,
{
which
:
38
})
)
})
assert
.
ok
(
document
.
activeElement
===
$
(
'
#item1
'
)[
0
],
'
item1 is focused
'
)
done
()
}).
bootstrapDropdown
(
'
toggle
'
)
$textarea
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$textarea
[
0
],
'
click
'
)
})
$textarea
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$textarea
[
0
],
'
click
'
)
})
$textarea
.
trigger
(
'
click
'
)
EventHandler
.
trigger
(
$textarea
[
0
],
'
click
'
)
})
QUnit
.
test
(
'
should not use Popper.js if display set to static
'
,
function
(
assert
)
{
...
...
This diff is collapsed.
Click to expand it.
js/tests/visual/dropdown.html
+
9
-
0
View file @
90261b48
...
...
@@ -61,6 +61,12 @@
<div
class=
"row"
>
<div
class=
"col-sm-12 mt-4"
>
<div
class=
"dropdown"
>
<button
type=
"button"
class=
"btn btn-secondary"
data-toggle=
"dropdown"
aria-expanded=
"false"
>
Dropdown
</button>
<div
class=
"dropdown-menu"
>
<input
id=
"textField"
type=
"text"
>
</div>
</div>
<div
class=
"btn-group dropup"
>
<button
type=
"button"
class=
"btn btn-secondary"
>
Dropup split
</button>
<button
type=
"button"
class=
"btn btn-secondary dropdown-toggle"
data-toggle=
"dropdown"
aria-expanded=
"false"
>
...
...
@@ -206,6 +212,9 @@
<script
src=
"../../../node_modules/jquery/dist/jquery.slim.min.js"
></script>
<script
src=
"../../../node_modules/popper.js/dist/umd/popper.min.js"
></script>
<script
src=
"../../dist/dom/eventHandler.js"
></script>
<script
src=
"../../dist/dom/data.js"
></script>
<script
src=
"../../dist/dom/selectorEngine.js"
></script>
<script
src=
"../../dist/dom/manipulator.js"
></script>
<script
src=
"../../dist/util.js"
></script>
<script
src=
"../../dist/dropdown.js"
></script>
<script
src=
"../../dist/collapse.js"
></script>
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment