Skip to content

Commit 426e21b

Browse files
committed
New Feature closeOnScroll zurb#351
1 parent 9568c8c commit 426e21b

File tree

6 files changed

+126
-21
lines changed

6 files changed

+126
-21
lines changed

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,11 @@ Collection object shown with defaults:
213213
// If null is used then it will not split the string & search in the whole line
214214
// default value is /\s+/ means it will split on whitespace when this is not specified
215215
autocompleteSeparator: /\s+/,
216+
217+
218+
// An option to hide the tribute when scrolled
219+
// defaults to false, can accept true, or a container to bind the scroll event to.
220+
closeOnScroll: true,
216221
}
217222
```
218223

src/Tribute.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ class Tribute {
3030
spaceSelectsMatch = false,
3131
searchOpts = {},
3232
menuItemLimit = null,
33-
menuShowMinLength = 0
33+
menuShowMinLength = 0,
34+
closeOnScroll = false,
3435
}) {
3536
this.autocompleteMode = autocompleteMode;
3637
this.autocompleteSeparator = autocompleteSeparator;
@@ -44,6 +45,7 @@ class Tribute {
4445
this.positionMenu = positionMenu;
4546
this.hasTrailingSpace = false;
4647
this.spaceSelectsMatch = spaceSelectsMatch;
48+
this.closeOnScroll = closeOnScroll;
4749

4850
if (this.autocompleteMode) {
4951
trigger = "";

src/TributeMenuEvents.js

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,12 @@ class TributeMenuEvents {
2626
false
2727
);
2828

29+
this.closeOnScrollEvent = this.debounce(() => {
30+
if (this.tribute.isActive) {
31+
this.tribute.hideMenu()
32+
}
33+
}, 10, false)
34+
2935
// fixes IE11 issues with mousedown
3036
this.tribute.range
3137
.getDocument()
@@ -35,14 +41,16 @@ class TributeMenuEvents {
3541
.addEventListener("mousedown", this.menuClickEvent, false);
3642
window.addEventListener("resize", this.windowResizeEvent);
3743

38-
if (this.menuContainer) {
39-
this.menuContainer.addEventListener(
40-
"scroll",
41-
this.menuContainerScrollEvent,
42-
false
43-
);
44+
if (this.tribute.closeOnScroll == true) {
45+
window.addEventListener('scroll', this.closeOnScrollEvent)
46+
} else if (this.tribute.closeOnScroll != false) {
47+
this.tribute.closeOnScroll.addEventListener('scroll', this.closeOnScrollEvent, false)
4448
} else {
45-
window.addEventListener("scroll", this.menuContainerScrollEvent);
49+
if (this.menuContainer) {
50+
this.menuContainer.addEventListener('scroll', this.menuContainerScrollEvent, false)
51+
} else {
52+
window.addEventListener('scroll', this.menuContainerScrollEvent)
53+
}
4654
}
4755
}
4856

@@ -55,14 +63,16 @@ class TributeMenuEvents {
5563
.removeEventListener("MSPointerDown", this.menuClickEvent, false);
5664
window.removeEventListener("resize", this.windowResizeEvent);
5765

58-
if (this.menuContainer) {
59-
this.menuContainer.removeEventListener(
60-
"scroll",
61-
this.menuContainerScrollEvent,
62-
false
63-
);
66+
if (this.tribute.closeOnScroll === true) {
67+
window.removeEventListener('scroll', this.closeOnScrollEvent)
68+
} else if (this.tribute.closeOnScroll != false) {
69+
this.tribute.closeOnScroll.removeEventListener('scroll', this.closeOnScrollEvent)
6470
} else {
65-
window.removeEventListener("scroll", this.menuContainerScrollEvent);
71+
if (this.menuContainer) {
72+
this.menuContainer.removeEventListener('scroll', this.menuContainerScrollEvent, false)
73+
} else {
74+
window.removeEventListener('scroll', this.menuContainerScrollEvent)
75+
}
6676
}
6777
}
6878

test/spec/test.js

Lines changed: 86 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,7 @@
22

33
import bigList from "./utils/bigList.json";
44

5-
import {
6-
clearDom,
7-
createDomElement,
8-
fillIn,
9-
simulateMouseClick
10-
} from "./utils/dom-helpers";
5+
import {clearDom, createDomElement, fillIn, simulateMouseClick, simulateElementScroll} from './utils/dom-helpers';
116

127
import { attachTribute, detachTribute } from "./utils/tribute-helpers";
138

@@ -892,3 +887,88 @@ describe("Tribute disabled items cases", function() {
892887
});
893888

894889
});
890+
891+
892+
describe('closeOnScroll tests', function() {
893+
afterEach(function () {
894+
clearDom();
895+
});
896+
897+
it('Tribute should close when the window is scrolled', () => {
898+
let input = createDomElement();
899+
900+
let collectionObject = {
901+
trigger: '@',
902+
closeOnScroll: true,
903+
values: [
904+
{ key: 'Jordan Humphreys', value: 'Jordan Humphreys', email: 'getstarted@zurb.com' },
905+
{ key: 'Sir Walter Riley', value: 'Sir Walter Riley', email: 'getstarted+riley@zurb.com' }
906+
],
907+
};
908+
909+
let tribute = attachTribute(collectionObject, input.id);
910+
fillIn(input, '@');
911+
912+
expect(tribute.isActive).toBe(true);
913+
simulateElementScroll(window);
914+
915+
// Need a slight delay otherwise we'll check for the result to fast
916+
setTimeout(() => {
917+
expect(tribute.isActive).toBe(false);
918+
}, 50)
919+
920+
detachTribute(tribute, input.id);
921+
});
922+
923+
it('Tribute should close when the container is scrolled', () => {
924+
let input = createDomElement();
925+
let container = document.createElement('div');
926+
927+
let collectionObject = {
928+
trigger: '@',
929+
closeOnScroll: container,
930+
values: [
931+
{ key: 'Jordan Humphreys', value: 'Jordan Humphreys', email: 'getstarted@zurb.com' },
932+
{ key: 'Sir Walter Riley', value: 'Sir Walter Riley', email: 'getstarted+riley@zurb.com' }
933+
],
934+
};
935+
936+
let tribute = attachTribute(collectionObject, input.id);
937+
fillIn(input, '@');
938+
939+
expect(tribute.isActive).toBe(true);
940+
simulateElementScroll(container);
941+
942+
// Need a slight delay otherwise we'll check for the result to fast
943+
setTimeout(() => {
944+
expect(tribute.isActive).toBe(false);
945+
}, 50)
946+
947+
detachTribute(tribute, input.id);
948+
});
949+
950+
it('Tribute should not close when scrolled without the closeOnScroll set', () => {
951+
let input = createDomElement();
952+
953+
let collectionObject = {
954+
trigger: '@',
955+
values: [
956+
{ key: 'Jordan Humphreys', value: 'Jordan Humphreys', email: 'getstarted@zurb.com' },
957+
{ key: 'Sir Walter Riley', value: 'Sir Walter Riley', email: 'getstarted+riley@zurb.com' }
958+
],
959+
};
960+
961+
let tribute = attachTribute(collectionObject, input.id);
962+
fillIn(input, '@');
963+
964+
expect(tribute.isActive).toBe(true);
965+
simulateElementScroll(window);
966+
967+
// Need a slight delay otherwise we'll check for the result to fast
968+
setTimeout(() => {
969+
expect(tribute.isActive).toBe(true);
970+
}, 50)
971+
972+
detachTribute(tribute, input.id);
973+
});
974+
});

test/spec/utils/dom-helpers.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,7 @@ export const simulateMouseClick = function(targetNode) {
4040
triggerMouseEvent(targetNode, eventType);
4141
});
4242
}
43+
44+
export const simulateElementScroll = function(container) {
45+
container.dispatchEvent(new Event('scroll'));
46+
}

tributejs.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ export type TributeCollection<T extends {}> = {
8787

8888
// specify if the current match should be selected when the spacebar is hit
8989
spaceSelectsMatch?: boolean;
90+
91+
// specify whether to close when scrolled, and optionally an element to bind
92+
// the scroll event to.
93+
closeOnScroll?: any
9094
};
9195

9296
export type TributeOptions<T> =

0 commit comments

Comments
 (0)