Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
justinhunt committed Dec 19, 2022
2 parents 0a1b399 + 207064e commit 89766de
Show file tree
Hide file tree
Showing 4 changed files with 737 additions and 2 deletions.
313 changes: 313 additions & 0 deletions accordion.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,313 @@
/**
* Replica of jQuery UI accordion function for Moodle
*
* @author Alex Morris <[email protected]>
* @copyright 2022 Catalyst IT
*/
define(['jquery'],
function($) {
$.fn.extend({
uniqueId: (function() {
var uuid = 0;

return function() {
return this.each(function() {
if (!this.id) {
this.id = "ui-id-" + (++uuid);
}
});
};
})(),

removeUniqueId: function() {
return this.each(function() {
if (/^ui-id-\d+$/.test(this.id)) {
$(this).removeAttr("id");
}
});
}
});

/**
* Add accordion function to jQuery. Initial header and panel setup.
*/
$.fn.accordion = function() {
var headers = null;
var panels = null;
var active = null;
var activeIndex = 0;
var prevShow = null;
var prevHide = null;
var hideProps = {
borderTopWidth: "hide",
borderBottomWidth: "hide",
paddingTop: "hide",
paddingBottom: "hide",
height: "hide"
};
var showProps = {
borderTopWidth: "show",
borderBottomWidth: "show",
paddingTop: "show",
paddingBottom: "show",
height: "show"
};

/**
* Find tab headers
*
* @param elem
* @returns {*}
*/
var findHeaders = function(elem) {
return elem.find("> h3");
};

/**
* Get active header by index
*
* @param index
* @returns {*|jQuery|HTMLElement}
*/
var findActive = function(index) {
return typeof index === "number" ? headers.eq(index) : $();
};

/**
* Add icon next to header
*/
var createIcons = function() {
var icon = $("<span>");
icon.addClass(['ui-accordion-header-icon', 'ui-icon', 'ui-icon-triangle-1-e']);
icon.prependTo(headers);
var children = active.children(".ui-accordion-header-icon");
children.removeClass('ui-icon-triangle-1-e').addClass('ui-icon-triangle-1-s');
headers.addClass('ui-accordion-icons');
};

/**
* Animate opening and closing of the panels.
*
* @param toShow
* @param toHide
* @param data
* @returns {*}
*/
var animate = function(toShow, toHide, data) {
var complete = function() {
var toHide = data.oldPanel;
var prev = toHide.prev();

toHide.removeClass('ui-accordion-content-active');
prev.removeClass('ui-accordion-header-active');
prev.addClass('ui-accordion-header-collapsed');

activate(data);
};

if (!toHide.length) {
return toShow.animate(showProps, {complete: complete});
}
if (!toShow.length) {
return toHide.animate(hideProps, {complete: complete});
}

toHide.animate(hideProps, {
step: function(now, fx) {
fx.now = Math.round(now);
}
});
var adjust = 0;
var boxSizing = toShow.css('box-sizing');
toShow.hide().animate(showProps, {
complete: complete,
step: function(now, fx) {
fx.now = Math.round(now);
if (fx.prop !== "height") {
if (boxSizing === "content-box") {
adjust += fx.now;
}
}
}
});
};

/**
* Confirm header is active.
*
* @param index
*/
var activate = function(index) {
var toActive = findActive(index)[0];

if (toActive === active[0]) {
return;
}

toActive = toActive || active[0];

eventHandler({
target: toActive,
currentTarget: toActive,
preventDefault: $.noop
});
};

/**
* Toggle header & panel
*
* @param data
*/
var toggle = function(data) {
var toShow = data.newPanel;
var toHide = prevShow.length ? prevShow : data.oldPanel;
prevShow.add(prevHide).stop(true, true);
prevShow = toShow;
prevHide = toHide;

animate(toShow, toHide, data);

toHide.attr("aria-hidden", "true");
toHide.prev().attr({
"aria-selected": "false",
"aria-expanded": "false"
});

if (toShow.length && toHide.length) {
toHide.prev().attr({
"tabIndex": -1,
"aria-expanded": "false"
});
} else if (toShow.length) {
headers.attributeFilter(function() {
return parseInt($(this).attr("tabIndex"), 10) === 0;
}).attr("tabIndex", -1);
}

toShow.attr("aria-hidden", "false")
.prev()
.attr({
"aria-selected": "true",
"aria-expanded": "true",
tabIndex: 0
});
};

/**
* Toggle event called
*
* @param event
*/
var eventHandler = function(event) {
var clicked = $(event.currentTarget);
var clickedIsActive = clicked[0] === active[0];
var oldActive = active;
var toShowElement = clickedIsActive ? $() : clicked.next();
var toHideElement = active.next();
var data = {
oldHeader: oldActive,
oldPanel: toHideElement,
newHeader: clickedIsActive ? $() : clicked,
newPanel: toShowElement
};

event.preventDefault();

// Clicked on active header.
if (clickedIsActive) {
return;
}

activeIndex = clickedIsActive ? false : headers.index(clicked);
active = clickedIsActive ? $() : clicked;

toggle(data);

// Switch CSS classes.
oldActive.removeClass(['ui-accordion-header-active', 'ui-state-active']);
oldActive.children('.ui-accordion-header-icon').removeClass('ui-icon-triangle-1-s').addClass('ui-icon-triangle-1-e');
if (!clickedIsActive) {
clicked.removeClass('ui-accordion-header-collapsed').addClass(['ui-accordion-header-active', 'ui-state-active']);
clicked.children('.ui-accordion-header-icon').removeClass('ui-icon-triangle-1-e').addClass('ui-icon-triangle-1-s');
clicked.next().addClass('ui-accordion-content-active');
}
};

/**
* Setup event listeners
*/
var setupEvents = function() {
headers.on("click", eventHandler);
// TODO: Setup event listeners for arrows and enter keys.
};

/**
* Set up headers and panels.
*/
var refresh = function() {
// Find active header, show content.
active = findActive(activeIndex);
active.addClass(['ui-accordion-header-active', 'ui-state-active']);
active.removeClass('ui-accordion-header-collapsed');
active.next().addClass('ui-accordion-content-active');
active.next().show();

headers.attr("role", "tab")
.each(function() {
var header = $(this);
var headerId = header.uniqueId().attr("id");
var panel = header.next();
var panelId = panel.uniqueId().attr("id");
header.attr("aria-controls", panelId);
panel.attr("aria-labelledby", headerId);
})
.next()
.attr("role", "tabpanel");

headers.not(active)
.attr({
"aria-selected": "false",
"aria-expanded": "false",
tabIndex: -1
})
.next()
.attr("aria-hidden", "true")
.hide();

if (!active.length) {
headers.eq(0).attr("tabIndex", 0);
} else {
active.attr({
"aria-selected": "true",
"aria-expanded": "true",
tabIndex: 0
})
.next()
.attr("aria-hidden", "false");
}

createIcons();

setupEvents();
};

// Initialise accordion.
prevShow = prevHide = $();
this.addClass(['ui-accordion', 'ui-widget', 'ui-helper-reset']);
this.attr("role", "tablist");

headers = findHeaders(this);

headers.each(function(i, elem) {
$(elem).addClass(['ui-accordion-header', 'ui-accordion-header-collapsed', 'ui-state-default']);
});

panels = headers.next().filter(":not(.ui-accordion-content-active)").hide();
panels.each(function(i, elem) {
$(elem).addClass(['ui-accordion-content', 'ui-helper-reset', 'ui-widget-content']);
});

refresh();
};
}
);
2 changes: 1 addition & 1 deletion presets/accordian.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"key":"accordian","name":"accordian","instructions":"Between the accordian tags enter as many accordian item tags as you need","requirecss":"//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css","requirejs":"//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js","shim":"","defaults":"","amd":"1","body":"<div id=\"@@AUTOID@@\">","bodyend":"</div>","script":" $(function() {\n $( \"#\" + @@AUTOID@@).accordion({\n header: \"h3\",\n heightStyle: \"content\"\n })\n});","style":"","dataset":"","datasetvars":"","alternate":"","alternateend":"","version":"1.0.1"}
{"key":"accordian","name":"accordian","instructions":"Between the accordian tags enter as many accordian item tags as you need","requirecss":"//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css","requirejs":"filter/generico/accordion.js","shim":"","defaults":"","amd":"1","body":"<div id=\"@@AUTOID@@\">","bodyend":"</div>","script":" $(function() {\n $( \"#\" + @@AUTOID@@).accordion({\n header: \"h3\",\n heightStyle: \"content\"\n })\n});","style":"","dataset":"","datasetvars":"","alternate":"","alternateend":"","version":"1.0.1"}
2 changes: 1 addition & 1 deletion presets/tabs.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"key":"tabs","name":"Tabs","instructions":"Tabs separate content by heading and are an efficient way to organize data and avoid lots of scrolling. Between the Generico tab tags nest as many Generico tabitem tags as you need. ","requirecss":"//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css","requirejs":"//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js","shim":"","defaults":"","amd":"1","body":"<div id=\"@@AUTOID@@\">\n<div class=\"filter_generico_tabs_container\">\n<ul class=\"filter_generico_tabs\"></ul>","bodyend":"</div>\n</div>","script":"var theul = $(\"#\" + @@AUTOID@@ + \" ul.filter_generico_tabs\");\n//because users may copy/paste/massage the tab items, we get html junk\n//so move any span nested tab items to directly under tabs\n$(\".filter_generico_tabitem\", $(\"#\" + @@AUTOID@@)).each(function () {\n $(this).unwrap('span');\n});\n\n//create li items for each tab item, ignore the (important) ul element and remove html junk\n$(\"#\" + @@AUTOID@@ + \" .filter_generico_tabs_container\").children().each(function () {\n if($(this).is(\".filter_generico_tabitem\")){\n theul.append(\"<li><a href='#\" + this.id + \"'><span>\"+this.title+\"</span></a></li>\");\n //$(this).appendTo('#' + @@AUTOID@@); \n //end of if is tabitem\n}else if(!$(this).is('ul.filter_generico_tabs')){\n this.remove();\n}\n});\n\n//finally create the tabs\n$( \"#\" + @@AUTOID@@ + \" .filter_generico_tabs_container\").tabs();","style":"","dataset":"","datasetvars":"","alternate":"","alternateend":"","version":"1.0.3"}
{"key":"tabs","name":"Tabs","instructions":"Tabs separate content by heading and are an efficient way to organize data and avoid lots of scrolling. Between the Generico tab tags nest as many Generico tabitem tags as you need. ","requirecss":"//cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.css","requirejs":"/filter/generico/tabs.js","shim":"","defaults":"","amd":"1","body":"<div id=\"@@AUTOID@@\">\n<div class=\"filter_generico_tabs_container\">\n<ul class=\"filter_generico_tabs\"></ul>","bodyend":"</div>\n</div>","script":"var theul = $(\"#\" + @@AUTOID@@ + \" ul.filter_generico_tabs\");\n//because users may copy/paste/massage the tab items, we get html junk\n//so move any span nested tab items to directly under tabs\n$(\".filter_generico_tabitem\", $(\"#\" + @@AUTOID@@)).each(function () {\n $(this).unwrap('span');\n});\n\n//create li items for each tab item, ignore the (important) ul element and remove html junk\n$(\"#\" + @@AUTOID@@ + \" .filter_generico_tabs_container\").children().each(function () {\n if($(this).is(\".filter_generico_tabitem\")){\n theul.append(\"<li><a href='#\" + this.id + \"'><span>\"+this.title+\"</span></a></li>\");\n //$(this).appendTo('#' + @@AUTOID@@); \n //end of if is tabitem\n}else if(!$(this).is('ul.filter_generico_tabs')){\n this.remove();\n}\n});\n\n//finally create the tabs\n$( \"#\" + @@AUTOID@@ + \" .filter_generico_tabs_container\").tabs();","style":"","dataset":"","datasetvars":"","alternate":"","alternateend":"","version":"1.0.3"}
Loading

0 comments on commit 89766de

Please sign in to comment.