Skip to content

Instantly share code, notes, and snippets.

@robert-carroll
Created April 22, 2020 21:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save robert-carroll/f70594aa4b6f6b8acfe7887eeb838b06 to your computer and use it in GitHub Desktop.
Save robert-carroll/f70594aa4b6f6b8acfe7887eeb838b06 to your computer and use it in GitHub Desktop.
module mashup
#module_filters {
list-style-type: none;
display: inline;
margin: 0;
}
#module_filters li {
padding: 0 .5em 0 0;
display: inline-block;
}
#module_filters li.separator::after {
content: " ";
border-left: 1px dashed grey;
padding: -1px;
}
#module_filters button {
background: none;
border: none;
border-color: transparent;
box-shadow: none;
margin: 0;
outline-style: none;
padding: 0 0 4px 0;
}
#module_filters button.active {
color: #00AC18;
}
.module_filters_hide {
display: none;
}
/* module mashup
1) allow module items to be filtered, hiding content of the selected filter, with single click
2) allow focus on specific module item, hiding all content except the active filter, with double click
3) allow all modules to be expanded and collapsed with a single button, students and teachers
todo:
4) show module completion/progress, and create a filter by progress
5) show/hide published/unpublished module items, for teachers
*/
if (/^\/courses\/\d+\/modules/.test(window.location.pathname)) {
var controls = {
filters: [
{ id: 'wiki_page', label: 'Pages', icon: 'icon-document' },
{ id: 'assignment', label: 'Assignments', icon: 'icon-assignment' },
{ id: 'quiz', label: 'Quizzes', icon: 'icon-quiz' },
{ id: 'discussion_topic', label: 'Discussion Topics', icon: 'icon-discussion' },
{ id: 'external_url', label: 'Links', icon: 'icon-link' },
{ id: 'attachment', label: 'Files', icon: 'icon-paperclip' },
{ id: 'context_external_tool', label: 'External Tools', icon: 'icon-integrations' },
],
toggles: [
{ id: 'expand_collapse', label: 'Collapse All Modules', icon: 'icon-collapse', callback: xc },
{ id: 'module_progress', label: 'Module Progress', icon: 'icon-complete', callback: mp }
]
};
// toolbar html
var filters = controls.filters.map(f => `<li><button class="btn filter active" id="${f['id']}" aria-expanded="true" title="${f['label']}"><i class="${f['icon']}"></i></button></li>`).join(' '),
divider = `<li class="separator"></li>`,
toggles = controls.toggles.map(f => `<li><button class="btn toggle active" id="${f['id']}" aria-expanded="true" title="${f['label']}"><i class="${f['icon']}"></i></button></li>`).join(' '),
html = `<div><ul id="module_filters">${filters+divider+toggles}</ul></div>`
//document.getElementById('module_filters').remove();
document.querySelector('div.header-bar').insertAdjacentHTML('beforeend', html)
const mm = {
filters: document.querySelectorAll('#module_filters button.filter'),
toggles: document.querySelectorAll('#module_filters button.toggle'),
filter: {
switch: btn => {
// console.log(btn)
let flip = btn.getAttribute('aria-expanded') == 'true' ? 'false' : 'true';
btn.setAttribute('aria-expanded', flip)
if (btn.getAttribute('aria-expanded') == 'true') {
btn.classList.add('active')
} else if (btn.classList.contains('active')) {
btn.classList.remove('active')
}
// console.log(btn)
},
},
toggle: {
all: {
click: target => {
for (var i = target.length - 1; i >= 0; i--) {
target[i].click();
}
},
collapse: items => {
console.log('collapse')
var collapse_btns = document.querySelectorAll('#context_modules span.collapse_module_link');
mm.toggle.all.click(collapse_btns)
},
expand: items => {
console.log('expand')
//console.log(mm.toggle.all.collapsed())
// on expand/collapse reset, we need to unhide anything that's hidden
document.querySelectorAll('.module_filters_hide').forEach(item => {
item.classList.remove('module_filters_hide')
})
var expand_btns = document.querySelectorAll('#context_modules .collapsed_module span.collapse_module_link');
mm.toggle.all.click(expand_btns)
// also need to reset the filter buttons to active
mm.filters.forEach(function (on) {
on.setAttribute('aria-expanded', 'true')
on.classList.add('active')
})
},
}
},
items: {
hide: items => {
items.forEach(item => {
item.classList.add('module_filters_hide')
})
},
show: items => {
items.forEach(item => {
item.classList.remove('module_filters_hide')
})
},
}
}
mm.filters.forEach(function (btn) {
// double click, toggle filter
btn.addEventListener('click', function (e) {
var is_expanded = btn.getAttribute('aria-expanded')
//console.log(`${e.type} - ${btn.id}: ${is_expanded}`)
// toggle state
switch (is_expanded) {
case 'true':
mm.items.hide(document.querySelectorAll(`li.${btn.id}`))
mm.filter.switch(btn)
break;
case 'false':
mm.items.show(document.querySelectorAll(`li.${btn.id}`))
mm.filter.switch(btn)
break;
}
// switch the state of the expand/collapse button
// if any filters are active, show the expand button
var active = document.querySelectorAll('#module_filters button[aria-expanded="false"]')
if (active.length > 0) {
console.log(active)
console.log('update xc')
document.getElementById('expand_collapse').classList.remove('active')
document.getElementById('expand_collapse').setAttribute('aria-expanded', 'false')
document.getElementById('expand_collapse').setAttribute('title', 'Expand All Modules')
}
});
// double click toggle, disable all filters and enable clicked filter
btn.addEventListener('dblclick', function (e) {
// console.log(`${e.type} - ${btn.id}`)
// toggle buttons off
mm.filters.forEach(function (off) {
off.setAttribute('aria-expanded', 'false')
off.classList.remove('active')
})
// toggle hidden items
mm.items.hide(document.querySelectorAll(`li[id^="context_module_item_"]:not(.${btn.id})`))
// show filtered items
mm.items.show(document.querySelectorAll(`li.${btn.id}.module_filters_hide`))
// active button
btn.classList.add('active')
btn.setAttribute('aria-expanded', 'true')
});
})
function xc(btn) {
console.log('xc')
console.log(btn.getAttribute('aria-expanded'))
// toggle state (true = expanded, false = collapsed)
switch (btn.getAttribute('aria-expanded')) {
case 'true':
mm.toggle.all.collapse([])
// switch state
document.getElementById('expand_collapse').classList.remove('active')
document.getElementById('expand_collapse').setAttribute('title', 'Expand All Modules')
document.getElementById('expand_collapse').setAttribute('aria-expanded', 'false')
break;
case 'false':
mm.toggle.all.expand([])
// switch state
document.getElementById('expand_collapse').classList.add('active')
document.getElementById('expand_collapse').setAttribute('title', 'Collapse All Modules')
document.getElementById('expand_collapse').setAttribute('aria-expanded', 'true')
break;
}
}
function mp(btn) {
console.log('mp')
console.log(btn.getAttribute('aria-expanded'))
}
function cb(callback, btn) {
callback(btn)
}
mm.toggles.forEach(function (btn) {
btn.addEventListener('click', function (e) {
cb(controls.toggles.filter(t => t.id == btn.id)[0].callback, btn)
});
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment