Skip to content
This repository was archived by the owner on Nov 29, 2021. It is now read-only.
Open
Changes from all commits
Commits
Show all changes
92 commits
Select commit Hold shift + click to select a range
044ec67
Updated code style.
cschwinderg Oct 8, 2019
5db1439
Fixed a bug that was causing the app to scroll to the glossary toggle…
cschwinderg Oct 8, 2019
04ae601
Merge pull request #1 from Eastern-Research-Group/bugfix/prevent-clos…
cschwinderg Oct 8, 2019
4fb9454
Removed focus on search box when clicking on a term.
cschwinderg Nov 20, 2019
ab57961
Merge pull request #2 from Eastern-Research-Group/enhance/mobile-term…
cschwinderg Nov 20, 2019
5ee1fa7
Added a log.
cschwinderg Nov 20, 2019
3f5a8c1
Collapse all terms prior to expanding the found term.
cschwinderg Nov 20, 2019
4de9a96
Added more logs.
cschwinderg Nov 20, 2019
82bcfd9
Merge pull request #3 from Eastern-Research-Group/enhance/collapse-ac…
cschwinderg Nov 21, 2019
0990866
Revert "Enhance/collapse accordions on close"
cschwinderg Nov 21, 2019
81a8f3a
Merge pull request #4 from Eastern-Research-Group/revert-3-enhance/co…
cschwinderg Nov 21, 2019
9169eb8
Added console logs.
cschwinderg Nov 21, 2019
e240828
Set collapseOthers to true.
cschwinderg Nov 21, 2019
0e4e7a2
Added some debug code to determine which term the glossary is failing…
cschwinderg Nov 21, 2019
65f2e55
Made custom collapse code to safely handle collapsing the open items.
cschwinderg Nov 21, 2019
f6388f5
Testing
cschwinderg Nov 21, 2019
3a8381f
Moved the collapseAll call to the top of the findTerm function to wor…
cschwinderg Nov 21, 2019
e237bdc
Removed commented out code and console logs. Added code to collapse a…
cschwinderg Nov 21, 2019
dedd888
Added additional logs and moved where the collapse all occurs.
cschwinderg Nov 21, 2019
6bf05c8
Added code to collapse any terms that are expanded when a search occurs.
cschwinderg Nov 21, 2019
693be63
Changed how the collapsing of terms works.
cschwinderg Nov 21, 2019
b518a4b
Fix bug
cschwinderg Nov 21, 2019
3f15db1
Collapse on close of glossary.
cschwinderg Nov 21, 2019
22212db
Merge branch 'master' into enhance/collapse-accordions-on-close
cschwinderg Nov 21, 2019
955964b
Merge pull request #5 from Eastern-Research-Group/enhance/collapse-ac…
cschwinderg Nov 21, 2019
a4c15d6
Remove case sensitive checking.
cschwinderg Dec 10, 2019
94b88b9
Add console log
cschwinderg Dec 10, 2019
a92bba4
Remove item that makes the search lower case.
cschwinderg Dec 10, 2019
efe8043
Fix console error caused by attempting to collapse terms that aren't …
cschwinderg Dec 10, 2019
05f7a0e
Removed console log used for debugging.
cschwinderg Dec 10, 2019
d9a70de
Added a comment.
cschwinderg Dec 10, 2019
9b79a70
Merge pull request #6 from Eastern-Research-Group/bugfix/case-insensi…
cschwinderg Dec 10, 2019
e2dd370
Fixed a console error that happens when a user selects a term when th…
cschwinderg Dec 10, 2019
e29b7dd
Merge pull request #7 from Eastern-Research-Group/bugfix/case-insensi…
cschwinderg Dec 10, 2019
c84b09e
Updated the glossary component to use querySelectorAll to determine w…
cschwinderg Jan 28, 2020
e1b8e68
Merge pull request #8 from Eastern-Research-Group/bugfix/android-slow…
cschwinderg Jan 28, 2020
5b40b93
Remove search when closing the glossary.
cschwinderg Jan 29, 2020
a3ed5b2
Updated the code to also show all of the terms on close.
cschwinderg Jan 29, 2020
f82b8ab
Fixing an error.
cschwinderg Jan 29, 2020
a022bfb
adds a check to see if the parent element of the clicked target is th…
oftheheadland Jan 29, 2020
9be862f
Fixed issue with terms not showing up on hide.
cschwinderg Jan 29, 2020
d044f94
Made a show/hide all terms function.
cschwinderg Jan 29, 2020
4035131
Fixed an error.
cschwinderg Jan 29, 2020
731a566
Fixed errors
cschwinderg Jan 29, 2020
c11f16f
Fixed error.
cschwinderg Jan 29, 2020
5e78b97
Reverted back.
cschwinderg Jan 29, 2020
877118d
Merge pull request #10 from Eastern-Research-Group/enhance/remove-sea…
cschwinderg Jan 30, 2020
ceb6b57
Merge pull request #9 from Eastern-Research-Group/feature/clickable-i…
cschwinderg Jan 30, 2020
b7ff827
Updated the glossary to scroll to the top on close.
cschwinderg Jan 30, 2020
bb6ecf6
Merge pull request #11 from Eastern-Research-Group/enhance/scroll-to-top
cschwinderg Jan 30, 2020
e9aeae8
add a check that searchbox exists before setting the value to an empt…
oftheheadland Jan 30, 2020
dbe2221
Merge pull request #12 from Eastern-Research-Group/bugfix/unable-to-c…
cschwinderg Jan 31, 2020
d1e65b9
Added code to prevent duplicate terms.
cschwinderg Jun 1, 2020
fb438dd
Added buttons for troubleshooting duplicate terms issue.
cschwinderg Jun 1, 2020
08d491d
Add debug messages.
cschwinderg Jun 1, 2020
a3099c0
Changes to fix testing buttons.
cschwinderg Jun 1, 2020
449d142
Remove some of the test code.
cschwinderg Jun 1, 2020
ebea410
Added code to remove glossary terms from the DOM prior to adding glos…
cschwinderg Jun 1, 2020
d43ef54
Added more testing items.
cschwinderg Jun 1, 2020
96445aa
Fixed issue of clearTerms not working.
cschwinderg Jun 1, 2020
82e8982
Remove code used for debugging.
cschwinderg Jun 1, 2020
9b4a20b
Added some comments.
cschwinderg Jun 1, 2020
30131d9
Removed logic for preventing duplicate terms, when the parameter pass…
cschwinderg Jun 1, 2020
cde0a7a
Removed some unused code.
cschwinderg Jun 1, 2020
b46d308
Merge pull request #13 from Eastern-Research-Group/feature/prevent-du…
cschwinderg Jun 1, 2020
eed489a
fix bugs in iOS 9.3 Safari where .style is a readonly attribute and .…
oftheheadland Jul 29, 2020
56ea079
add alert with error for debugging in ipad emulator
oftheheadland Jul 29, 2020
a7af798
add alert to hide function
oftheheadland Jul 29, 2020
30c8ac2
add alert to closeopenglossary function
oftheheadland Jul 29, 2020
37bf14e
add touchstart event for ipad devices
oftheheadland Jul 29, 2020
8d0d2ab
combine click and touchstart events
oftheheadland Jul 29, 2020
a3bbc6f
remove alerts, separate touchstart and click event listeners
oftheheadland Jul 29, 2020
70df15c
Merge pull request #14 from Eastern-Research-Group/bugfix/old-ios-saf…
cschwinderg Jul 31, 2020
f5e057b
add try catch to debug
oftheheadland Aug 5, 2020
2de8cb5
add try catch to hide
oftheheadland Aug 5, 2020
22c6530
use .style.cssText instead of .style to support Safari 9
oftheheadland Aug 5, 2020
521ea49
remove try catches used for debugging
oftheheadland Aug 5, 2020
3b17ad8
Merge pull request #15 from Eastern-Research-Group/bugfix/safari-9-is…
cschwinderg Aug 5, 2020
f418320
Testing potential fix.
cschwinderg Dec 21, 2020
06fc1f8
Testing another change.
cschwinderg Dec 21, 2020
5b9d5e6
Fixing issue with last commit.
cschwinderg Dec 21, 2020
a8dbe7d
Testing a different approach.
cschwinderg Dec 21, 2020
42633a0
Fix issue with search input.
cschwinderg Dec 21, 2020
51d2821
Fixed issue with search input.
cschwinderg Dec 21, 2020
23871ff
Fixed partial match on term click.
cschwinderg Dec 21, 2020
b36979a
Merge pull request #16 from Eastern-Research-Group/feature/exact-matc…
cschwinderg Dec 21, 2020
704c715
Fixes an issue with termElm being null.
cschwinderg Apr 5, 2021
1aa62f7
Merge pull request #17 from Eastern-Research-Group/bugfix/ga-error
cschwinderg Apr 5, 2021
6adfccd
remove code that scrolls to the top of the page after closing the glo…
oftheheadland Apr 21, 2021
be946bd
Merge pull request #18 from Eastern-Research-Group/bugfix/scrolling-i…
oftheheadland Apr 21, 2021
0d14bd8
add panel scrolling back to the glossary that only affects the glossa…
oftheheadland Apr 22, 2021
e8a7a3e
Merge pull request #19 from Eastern-Research-Group/bugfix/re-add-pane…
oftheheadland Apr 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
208 changes: 166 additions & 42 deletions src/glossary.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,17 @@ var KEYCODE_ESC = 27;
// https://davidwalsh.name/element-matches-selector
function selectorMatches(el, selector) {
var p = Element.prototype;
var f = p.matches || p.webkitMatchesSelector || p.mozMatchesSelector || p.msMatchesSelector || function(s) {
return [].indexOf.call(document.querySelectorAll(s), this) !== -1;
};
var f =
p.matches ||
p.webkitMatchesSelector ||
p.mozMatchesSelector ||
p.msMatchesSelector ||
function(s) {
return [].indexOf.call(document.querySelectorAll(s), this) !== -1;
};
return f.call(el, selector);
}


// get nearest parent element matching selector
function closest(el, selector) {
while (el) {
Expand All @@ -33,27 +37,39 @@ function forEach(values, callback) {
}

var itemTemplate = function(values) {
return '<li class="' + values.glossaryItemClass + '">' +
'<button class="data-glossary-term ' + values.termClass + '">' +
values.term +
'</button>' +
'<div class="' + values.definitionClass + '">' + values.definition + '</div>' +
return (
'<li class="' +
values.glossaryItemClass +
'" data-glossary-term-value="' +
values.term.toLowerCase() +
'">' +
'<button class="data-glossary-term ' +
values.termClass +
'">' +
values.term +
'</button>' +
'<div class="' +
values.definitionClass +
'">' +
values.definition +
'</div>' +
'</li>'
}
);
};

var defaultSelectors = {
glossaryID: '#glossary',
toggle: '.js-glossary-toggle',
close: '.js-glossary-close',
listClass: '.js-glossary-list',
searchClass: '.js-glossary-search'
searchClass: '.js-glossary-search',
};

var defaultClasses = {
definitionClass: 'glossary__definition',
glossaryItemClass: 'glossary__item',
highlightedTerm: 'term--highlight',
termClass: 'glossary__term'
termClass: 'glossary__term',
};

function removeTabindex(elm) {
Expand All @@ -74,6 +90,17 @@ function getTabIndex(elm) {
return elm.querySelectorAll('a, button, input, [tabindex]');
}

/** Collapse visible terms */
function collapseTerms(accordion, list) {
// collapse any visible terms
list.visibleItems.forEach((term) => {
// Collapse the term if it is on the DOM
const termElm = term.elm.firstChild;
const content = termElm ? document.getElementById(termElm.getAttribute('aria-controls')) : null;
if(content) accordion.collapse(term.elm.firstChild);
})
}

/**
* Glossary widget
* @constructor
Expand All @@ -97,6 +124,7 @@ function Glossary(terms, selectors, classes) {
this.isOpen = false;

// Update DOM
this.clearTerms();
this.populate();
this.initList();
this.linkTerms();
Expand All @@ -105,15 +133,29 @@ function Glossary(terms, selectors, classes) {
removeTabindex(this.body);

// Initialize accordions
this.accordion = new Accordion(this.listElm, null, {contentPrefix: 'glossary'});
this.accordion = new Accordion(this.listElm, null, {
contentPrefix: 'glossary',
});

// Bind listeners
this.listeners = [];
this.addEventListener(this.toggleBtn, 'click', this.toggle.bind(this));
this.addEventListener(this.closeBtn, 'click', this.hide.bind(this));
this.addEventListener(this.search, 'input', this.handleInput.bind(this));
this.addEventListener(document.body, 'keyup', this.handleKeyup.bind(this));
this.addEventListener(document,'click', this.closeOpenGlossary.bind(this));
this.addEventListener(document, 'click', this.closeOpenGlossary.bind(this));
this.addEventListener(document, 'touchstart', this.closeOpenGlossary.bind(this)); // for iPads
}

/** Clears terms from the glossary list to ensure no duplication. */
Glossary.prototype.clearTerms = function() {
forEach(
document.getElementsByClassName('js-glossary-list'),
function(list) {
// remove all child elements from the parent list (i.e. <ul>)
list.innerHTML = '';
},
);
}

Glossary.prototype.populate = function() {
Expand All @@ -123,7 +165,7 @@ Glossary.prototype.populate = function() {
definition: term.definition,
definitionClass: this.classes.definitionClass,
glossaryItemClass: this.classes.glossaryItemClass,
termClass: this.classes.termClass
termClass: this.classes.termClass,
};
this.listElm.insertAdjacentHTML('beforeend', itemTemplate(opts));
}, this);
Expand All @@ -137,10 +179,9 @@ Glossary.prototype.initList = function() {
var options = {
valueNames: ['data-glossary-term'],
listClass: listClass,
searchClass: searchClass,
};
this.list = new List(glossaryId, options);
this.list.sort('data-glossary-term', {order: 'asc'});
this.list.sort('data-glossary-term', { order: 'asc' });
};

/** Add links to terms in body */
Expand All @@ -149,7 +190,10 @@ Glossary.prototype.linkTerms = function() {
forEach(terms, function(term) {
term.setAttribute('title', 'Click to define');
term.setAttribute('tabIndex', 0);
term.setAttribute('data-term', (term.getAttribute('data-term') || '').toLowerCase());
term.setAttribute(
'data-term',
(term.getAttribute('data-term') || ''),
);
});
document.body.addEventListener('click', this.handleTermTouch.bind(this));
document.body.addEventListener('keyup', this.handleTermTouch.bind(this));
Expand All @@ -159,34 +203,84 @@ Glossary.prototype.handleTermTouch = function(e) {
if (e.which === KEYCODE_ENTER || e.type === 'click') {
if (selectorMatches(e.target, '[data-term]')) {
this.show(e);
this.selectedTerm = e.target;
this.findTerm(e.target.getAttribute('data-term'));
}
else {
this.selectedTerm = this.toggleBtn;
this.findTerm(e.target.getAttribute('data-term'), true);
}

this.selectedTerm = e.target;
}
};

/** Highlight a term */
Glossary.prototype.findTerm = function(term) {
Glossary.prototype.findTerm = function(term, fromTouch = false) {
// skip find term if the search box is not on the DOM
if(!this.search) return ;

this.search.value = term;
var highlightClass = this.classes.highlightedTerm;

// Highlight the term and remove other highlights
forEach(this.body.querySelectorAll('.' + highlightClass), function(term) {
term.classList.remove(highlightClass);
});
forEach(this.body.querySelectorAll('span[data-term="' + term + '"]'), function(term) {
term.classList.add(highlightClass);
});
this.list.filter(function(item) {
return item._values['data-glossary-term'].toLowerCase() === term;
});

this.list.search();
var button = this.list.visibleItems[0].elm.querySelector('button');
this.accordion.expand(button);
forEach(
this.body.querySelectorAll('span[data-term="' + term + '"]'),
function(term) {
term.classList.add(highlightClass);
},
);

const lowerCaseTerm = term.toLowerCase();

// hide all terms
forEach(
this.body.querySelectorAll('li[class*="' + this.classes.glossaryItemClass + '"]'),
function (term) {
term.style.cssText = 'display: none;'
}
);

collapseTerms(this.accordion, this.list);

// perform a search on the provided term
const exactMatch = this.body.querySelectorAll('li[data-glossary-term-value="' + lowerCaseTerm + '"]');
const matches = this.body.querySelectorAll('li[data-glossary-term-value*="' + lowerCaseTerm + '"]');

if(fromTouch) {
if(exactMatch.length > 0) {
// show the exact match term
const term = exactMatch[0];
term.style.cssText = 'display: list-item;'

// expand the exact match term
var button = term.querySelector('button');
this.accordion.expand(button);
}
else {
// show terms that match the search criteria and store the first term that was found
let firstTerm = null;
forEach(
matches,
function (term) {
term.style.cssText = 'display: list-item;'
if(!firstTerm) firstTerm = term;
}
);

// expand the first term, only if from term touch event and not for search input
if(firstTerm) {
var button = firstTerm.querySelector('button');
this.accordion.expand(button);
}
}
} else {
// from search input, go ahead and show all partial matches
forEach(
matches,
function (term) {
term.style.cssText = 'display: list-item;'
}
);
}
};

Glossary.prototype.toggle = function() {
Expand All @@ -197,23 +291,49 @@ Glossary.prototype.toggle = function() {
Glossary.prototype.show = function() {
this.body.setAttribute('aria-hidden', 'false');
this.toggleBtn.setAttribute('aria-expanded', 'true');
this.search.focus();
this.isOpen = true;
restoreTabindex(this.body);
};

Glossary.prototype.hide = function() {
//scroll Glossary panel to the top - handle older browsers where .scrollTo is not supported
this.body.scrollTop = 0;

// remove the search criteria
if (this.search){
this.search.value = '';
}
forEach(
this.body.querySelectorAll('li[class*="' + this.classes.glossaryItemClass + '"]'),
function (term) {
// handle older browsers where .style is readonly
term.style.cssText = 'display: list-item;'
}
);

this.body.setAttribute('aria-hidden', 'true');
this.toggleBtn.setAttribute('aria-expanded', 'false');
this.selectedTerm.focus();
collapseTerms(this.accordion, this.list);
this.isOpen = false;
removeTabindex(this.body);
};

/** Remove existing filters on input */
Glossary.prototype.handleInput = function() {
if (this.list.filtered) {
this.list.filter();
Glossary.prototype.handleInput = function() {
const term = this.search.value;
if(term) {
// perform the search
this.findTerm(term);
}
else {
// display everything since the search field is empty
forEach(
this.body.querySelectorAll('li[class*="' + this.classes.glossaryItemClass + '"]'),
function (term) {
term.style.cssText = 'display: list-item;'
}
);
}
};

Expand All @@ -228,9 +348,13 @@ Glossary.prototype.handleKeyup = function(e) {

// Close glossary when clicking outside of glossary
Glossary.prototype.closeOpenGlossary = function(e) {
if ( e.target !== this.toggleBtn && this.isOpen) {
if (!(closest(e.target, this.selectors.glossaryID))) {
this.hide();
if (
(e.target !== this.toggleBtn && e.target.parentElement !== this.toggleBtn) &&
!e.target.getAttribute('data-term') &&
this.isOpen
) {
if (!closest(e.target, this.selectors.glossaryID)) {
this.hide();
}
}
};
Expand All @@ -241,7 +365,7 @@ Glossary.prototype.addEventListener = function(elm, event, callback) {
this.listeners.push({
elm: elm,
event: event,
callback: callback
callback: callback,
});
}
};
Expand Down