Skip to content
GitLab
Explore
Projects
Groups
Snippets
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
0263d174
Commit
0263d174
authored
7 years ago
by
Alessandro Chitolina
Committed by
XhmikosR
6 years ago
Browse files
Options
Download
Email Patches
Plain Diff
rewritten scrollspy without jquery
parent
97448865
5 merge requests
!31948
Examples/Floating-labels: fix bad behavior with autofill
,
!30064
test
,
!29779
Responsive sizing
,
!28882
fix custom-select-indicator in IE10
,
!28721
Hot test
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
js/src/dom/manipulator.js
+16
-0
js/src/dom/manipulator.js
js/src/dom/selectorEngine.js
+38
-4
js/src/dom/selectorEngine.js
js/src/scrollspy.js
+53
-38
js/src/scrollspy.js
js/tests/unit/scrollspy.js
+7
-7
js/tests/unit/scrollspy.js
js/tests/visual/scrollspy.html
+3
-0
js/tests/visual/scrollspy.html
with
117 additions
and
49 deletions
+117
-49
js/src/dom/manipulator.js
+
16
-
0
View file @
0263d174
...
...
@@ -40,6 +40,22 @@ const Manipulator = {
element
.
removeAttribute
(
`data-
${
key
.
replace
(
/
[
A-Z
]
/g
,
(
chr
)
=>
`-
${
chr
.
toLowerCase
()}
`
)}
`
)
},
offset
(
element
)
{
const
rect
=
element
.
getBoundingClientRect
()
return
{
top
:
rect
.
top
+
document
.
body
.
scrollTop
,
left
:
rect
.
left
+
document
.
body
.
scrollLeft
}
},
position
(
element
)
{
return
{
top
:
element
.
offsetTop
,
left
:
element
.
offsetLeft
}
},
toggleClass
(
element
,
className
)
{
if
(
typeof
element
===
'
undefined
'
||
element
===
null
)
{
return
...
...
This diff is collapsed.
Click to expand it.
js/src/dom/selectorEngine.js
+
38
-
4
View file @
0263d174
...
...
@@ -111,10 +111,6 @@ const SelectorEngine = (() => {
return
null
}
if
(
selector
.
indexOf
(
'
#
'
)
===
0
)
{
return
SelectorEngine
.
findOne
(
selector
,
element
)
}
return
findFn
.
call
(
element
,
selector
)
},
...
...
@@ -135,8 +131,46 @@ const SelectorEngine = (() => {
return
children
.
filter
((
child
)
=>
this
.
matches
(
child
,
selector
))
},
parents
(
element
,
selector
)
{
if
(
typeof
selector
!==
'
string
'
)
{
return
null
}
const
parents
=
[]
let
ancestor
=
element
.
parentNode
while
(
ancestor
&&
ancestor
.
nodeType
===
Node
.
ELEMENT_NODE
)
{
if
(
fnMatches
.
call
(
ancestor
,
selector
))
{
parents
.
push
(
ancestor
)
}
ancestor
=
ancestor
.
parentNode
}
return
parents
},
closest
(
element
,
selector
)
{
return
fnClosest
(
element
,
selector
)
},
prev
(
element
,
selector
)
{
if
(
typeof
selector
!==
'
string
'
)
{
return
null
}
const
siblings
=
[]
let
previous
=
element
.
previousSibling
while
(
previous
)
{
if
(
fnMatches
.
call
(
previous
,
selector
))
{
siblings
.
push
(
previous
)
}
previous
=
previous
.
previousSibling
}
return
siblings
}
}
})()
...
...
This diff is collapsed.
Click to expand it.
js/src/scrollspy.js
+
53
-
38
View file @
0263d174
...
...
@@ -5,7 +5,10 @@
* --------------------------------------------------------------------------
*/
import
$
from
'
jquery
'
import
Data
from
'
./dom/data
'
import
EventHandler
from
'
./dom/eventHandler
'
import
Manipulator
from
'
./dom/manipulator
'
import
SelectorEngine
from
'
./dom/selectorEngine
'
import
Util
from
'
./util
'
/**
...
...
@@ -19,7 +22,6 @@ const VERSION = '4.3.1'
const
DATA_KEY
=
'
bs.scrollspy
'
const
EVENT_KEY
=
`.
${
DATA_KEY
}
`
const
DATA_API_KEY
=
'
.data-api
'
const
JQUERY_NO_CONFLICT
=
$
.
fn
[
NAME
]
const
Default
=
{
offset
:
10
,
...
...
@@ -81,10 +83,12 @@ class ScrollSpy {
this
.
_activeTarget
=
null
this
.
_scrollHeight
=
0
$
(
this
.
_scrollElement
).
on
(
Event
.
SCROLL
,
(
event
)
=>
this
.
_process
(
event
))
EventHandler
.
on
(
this
.
_scrollElement
,
Event
.
SCROLL
,
(
event
)
=>
this
.
_process
(
event
))
this
.
refresh
()
this
.
_process
()
Data
.
setData
(
element
,
DATA_KEY
,
this
)
}
// Getters
...
...
@@ -114,7 +118,7 @@ class ScrollSpy {
this
.
_scrollHeight
=
this
.
_getScrollHeight
()
const
targets
=
[].
slice
.
call
(
document
.
querySelectorAll
(
this
.
_selector
))
const
targets
=
Util
.
makeArray
(
document
.
querySelectorAll
(
this
.
_selector
))
targets
.
map
((
element
)
=>
{
...
...
@@ -130,7 +134,7 @@ class ScrollSpy {
if
(
targetBCR
.
width
||
targetBCR
.
height
)
{
// TODO (fat): remove sketch reliance on jQuery position/offset
return
[
$
(
target
)
[
offsetMethod
]().
top
+
offsetBase
,
Manipulator
[
offsetMethod
](
target
).
top
+
offsetBase
,
targetSelector
]
}
...
...
@@ -146,8 +150,8 @@ class ScrollSpy {
}
dispose
()
{
$
.
removeData
(
this
.
_element
,
DATA_KEY
)
$
(
this
.
_scrollElement
).
off
(
EVENT_KEY
)
Data
.
removeData
(
this
.
_element
,
DATA_KEY
)
EventHandler
.
off
(
this
.
_scrollElement
,
EVENT_KEY
)
this
.
_element
=
null
this
.
_scrollElement
=
null
...
...
@@ -168,10 +172,10 @@ class ScrollSpy {
}
if
(
typeof
config
.
target
!==
'
string
'
)
{
let
id
=
$
(
config
.
target
).
attr
(
'
id
'
)
let
id
=
config
.
target
.
id
if
(
!
id
)
{
id
=
Util
.
getUID
(
NAME
)
$
(
config
.
target
).
attr
(
'
id
'
,
id
)
config
.
target
.
id
=
id
}
config
.
target
=
`#
${
id
}
`
}
...
...
@@ -242,32 +246,45 @@ class ScrollSpy {
this
.
_clear
()
const
queries
=
this
.
_selector
.
split
(
'
,
'
)
const
queries
=
this
.
_selector
.
split
(
'
,
'
)
.
map
((
selector
)
=>
`
${
selector
}
[data-target="
${
target
}
"],
${
selector
}
[href="
${
target
}
"]`
)
const
$link
=
$
([].
slice
.
call
(
document
.
querySelectorAll
(
queries
.
join
(
'
,
'
))))
const
link
=
SelectorEngine
.
findOne
(
queries
.
join
(
'
,
'
))
if
(
link
.
classList
.
contains
(
ClassName
.
DROPDOWN_ITEM
))
{
SelectorEngine
.
findOne
(
Selector
.
DROPDOWN_TOGGLE
,
SelectorEngine
.
closest
(
link
,
Selector
.
DROPDOWN
))
.
classList
.
add
(
ClassName
.
ACTIVE
)
if
(
$link
.
hasClass
(
ClassName
.
DROPDOWN_ITEM
))
{
$link
.
closest
(
Selector
.
DROPDOWN
).
find
(
Selector
.
DROPDOWN_TOGGLE
).
addClass
(
ClassName
.
ACTIVE
)
$link
.
addClass
(
ClassName
.
ACTIVE
)
link
.
classList
.
add
(
ClassName
.
ACTIVE
)
}
else
{
// Set triggered link as active
$link
.
addClass
(
ClassName
.
ACTIVE
)
// Set triggered links parents as active
// With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
$link
.
parents
(
Selector
.
NAV_LIST_GROUP
).
prev
(
`
${
Selector
.
NAV_LINKS
}
,
${
Selector
.
LIST_ITEMS
}
`
).
addClass
(
ClassName
.
ACTIVE
)
// Handle special case when .nav-link is inside .nav-item
$link
.
parents
(
Selector
.
NAV_LIST_GROUP
).
prev
(
Selector
.
NAV_ITEMS
).
children
(
Selector
.
NAV_LINKS
).
addClass
(
ClassName
.
ACTIVE
)
link
.
classList
.
add
(
ClassName
.
ACTIVE
)
SelectorEngine
.
parents
(
link
,
Selector
.
NAV_LIST_GROUP
)
.
forEach
((
listGroup
)
=>
{
// Set triggered links parents as active
// With both <ul> and <nav> markup a parent is the previous sibling of any nav ancestor
SelectorEngine
.
prev
(
listGroup
,
`
${
Selector
.
NAV_LINKS
}
,
${
Selector
.
LIST_ITEMS
}
`
)
.
forEach
((
item
)
=>
item
.
classList
.
add
(
ClassName
.
ACTIVE
))
// Handle special case when .nav-link is inside .nav-item
SelectorEngine
.
prev
(
listGroup
,
Selector
.
NAV_ITEMS
)
.
forEach
((
navItem
)
=>
{
SelectorEngine
.
children
(
navItem
,
Selector
.
NAV_LINKS
)
.
forEach
((
item
)
=>
item
.
classList
.
add
(
ClassName
.
ACTIVE
))
})
})
}
$
(
this
.
_scrollElement
).
trigger
(
Event
.
ACTIVATE
,
{
EventHandler
.
trigger
(
this
.
_scrollElement
,
Event
.
ACTIVATE
,
{
relatedTarget
:
target
})
}
_clear
()
{
[].
slice
.
call
(
document
.
querySelectorAll
(
this
.
_selector
))
Util
.
makeArray
(
document
.
querySelectorAll
(
this
.
_selector
))
.
filter
((
node
)
=>
node
.
classList
.
contains
(
ClassName
.
ACTIVE
))
.
forEach
((
node
)
=>
node
.
classList
.
remove
(
ClassName
.
ACTIVE
))
}
...
...
@@ -276,12 +293,11 @@ class ScrollSpy {
static
_jQueryInterface
(
config
)
{
return
this
.
each
(
function
()
{
let
data
=
$
(
this
).
data
(
DATA_KEY
)
let
data
=
Data
.
getData
(
this
,
DATA_KEY
)
const
_config
=
typeof
config
===
'
object
'
&&
config
if
(
!
data
)
{
data
=
new
ScrollSpy
(
this
,
_config
)
$
(
this
).
data
(
DATA_KEY
,
data
)
}
if
(
typeof
config
===
'
string
'
)
{
...
...
@@ -300,14 +316,9 @@ class ScrollSpy {
* ------------------------------------------------------------------------
*/
$
(
window
).
on
(
Event
.
LOAD_DATA_API
,
()
=>
{
const
scrollSpys
=
[].
slice
.
call
(
document
.
querySelectorAll
(
Selector
.
DATA_SPY
))
const
scrollSpysLength
=
scrollSpys
.
length
for
(
let
i
=
scrollSpysLength
;
i
--
;)
{
const
$spy
=
$
(
scrollSpys
[
i
])
ScrollSpy
.
_jQueryInterface
.
call
(
$spy
,
$spy
.
data
())
}
EventHandler
.
on
(
window
,
Event
.
LOAD_DATA_API
,
()
=>
{
Util
.
makeArray
(
SelectorEngine
.
find
(
Selector
.
DATA_SPY
))
.
forEach
((
spy
)
=>
new
ScrollSpy
(
spy
,
Util
.
getDataAttributes
(
spy
)))
})
/**
...
...
@@ -316,11 +327,15 @@ $(window).on(Event.LOAD_DATA_API, () => {
* ------------------------------------------------------------------------
*/
$
.
fn
[
NAME
]
=
ScrollSpy
.
_jQueryInterface
$
.
fn
[
NAME
].
Constructor
=
ScrollSpy
$
.
fn
[
NAME
].
noConflict
=
()
=>
{
$
.
fn
[
NAME
]
=
JQUERY_NO_CONFLICT
return
ScrollSpy
.
_jQueryInterface
const
$
=
Util
.
jQuery
if
(
typeof
$
!==
'
undefined
'
)
{
const
JQUERY_NO_CONFLICT
=
$
.
fn
[
NAME
]
$
.
fn
[
NAME
]
=
ScrollSpy
.
_jQueryInterface
$
.
fn
[
NAME
].
Constructor
=
ScrollSpy
$
.
fn
[
NAME
].
noConflict
=
()
=>
{
$
.
fn
[
NAME
]
=
JQUERY_NO_CONFLICT
return
ScrollSpy
.
_jQueryInterface
}
}
export
default
ScrollSpy
This diff is collapsed.
Click to expand it.
js/tests/unit/scrollspy.js
+
7
-
7
View file @
0263d174
...
...
@@ -80,7 +80,7 @@ $(function () {
.
show
()
.
find
(
'
#scrollspy-example
'
)
.
bootstrapScrollspy
({
target
:
'
#
ss-target
'
target
:
'
ss-target
'
})
$scrollspy
.
one
(
'
scroll
'
,
function
()
{
...
...
@@ -127,7 +127,7 @@ $(function () {
.
show
()
.
find
(
'
#scrollspy-example
'
)
.
bootstrapScrollspy
({
target
:
document
.
getElementById
(
'
#
ss-target
'
)
target
:
document
.
getElementById
(
'
ss-target
'
)
})
$scrollspy
.
one
(
'
scroll
'
,
function
()
{
...
...
@@ -557,7 +557,7 @@ $(function () {
$scrollspy
.
bootstrapScrollspy
({
target
:
'
#navigation
'
,
offset
:
$scrollspy
.
position
().
t
op
offset
:
$scrollspy
[
0
].
offsetT
op
})
.
one
(
'
scroll
'
,
function
()
{
assert
.
strictEqual
(
$
(
'
.active
'
).
length
,
1
,
'
"active" class on only one element present
'
)
...
...
@@ -663,11 +663,11 @@ $(function () {
method
:
'
offset
'
})
}
else
if
(
type
===
'
data
'
)
{
$
(
window
)
.
trigger
(
'
load
'
)
EventHandler
.
trigger
(
window
,
'
load
'
)
}
var
$target
=
$
(
'
#div-
'
+
type
+
'
m-2
'
)
var
scrollspy
=
$content
.
data
(
'
bs.scrollspy
'
)
var
scrollspy
=
Data
.
getData
(
$content
[
0
],
'
bs.scrollspy
'
)
assert
.
ok
(
scrollspy
.
_offsets
[
1
]
===
$target
.
offset
().
top
,
'
offset method with
'
+
type
+
'
option
'
)
assert
.
ok
(
scrollspy
.
_offsets
[
1
]
!==
$target
.
position
().
top
,
'
position method with
'
+
type
+
'
option
'
)
...
...
@@ -710,11 +710,11 @@ $(function () {
method
:
'
position
'
})
}
else
if
(
type
===
'
data
'
)
{
$
(
window
)
.
trigger
(
'
load
'
)
EventHandler
.
trigger
(
window
,
'
load
'
)
}
var
$target
=
$
(
'
#div-
'
+
type
+
'
m-2
'
)
var
scrollspy
=
$content
.
data
(
'
bs.scrollspy
'
)
var
scrollspy
=
Data
.
getData
(
$content
[
0
],
'
bs.scrollspy
'
)
assert
.
ok
(
scrollspy
.
_offsets
[
1
]
!==
$target
.
offset
().
top
,
'
offset method with
'
+
type
+
'
option
'
)
assert
.
ok
(
scrollspy
.
_offsets
[
1
]
===
$target
.
position
().
top
,
'
position method with
'
+
type
+
'
option
'
)
...
...
This diff is collapsed.
Click to expand it.
js/tests/visual/scrollspy.html
+
3
-
0
View file @
0263d174
...
...
@@ -88,7 +88,10 @@
<script
src=
"../../../node_modules/jquery/dist/jquery.slim.min.js"
></script>
<script
src=
"../../../site/docs/4.2/assets/js/vendor/popper.min.js"
></script>
<script
src=
"../../dist/dom/data.js"
></script>
<script
src=
"../../dist/dom/eventHandler.js"
></script>
<script
src=
"../../dist/dom/manipulator.js"
></script>
<script
src=
"../../dist/dom/selectorEngine.js"
></script>
<script
src=
"../../dist/util.js"
></script>
<script
src=
"../../dist/scrollspy.js"
></script>
<script
src=
"../../dist/dropdown.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
Menu
Explore
Projects
Groups
Snippets