Skip to content

Instantly share code, notes, and snippets.

@sindre
Created November 6, 2014 12:37
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 sindre/cf458dedbde2474c1b83 to your computer and use it in GitHub Desktop.
Save sindre/cf458dedbde2474c1b83 to your computer and use it in GitHub Desktop.
JS jQuery ARIA open/close list
/*!
* jQuery lightweight plugin boilerplate
* based on https://github.com/jquery-boilerplate/jquery-patterns/blob/master/patterns/jquery.basic.plugin-boilerplate.js
*/
;(function ( $, window, document, undefined ) {
var pluginName = "homeToggle",
defaults = {
selection: 'a.cl',
containerclass : 'cc',
activeclass: 'active',
inactiveclass: 'inactive',
marginbottom: '0 0 1em 0',
duration: 0.3,
survillance: true,
focuslinks: false
};
function Plugin( element, options ) {
this.element = element;
this.options = $.extend( {}, defaults, options) ;
this.stat = true;
this._defaults = defaults;
this._name = pluginName;
this.init();
}
Plugin.prototype = {
init: function() {
this.container = $(this.element);
this.container.addClass('cvready');
if(this.options.survillance) {
this.getAnchor();
}
this._enableClicks();
},
getAnchor: function() {
this.anchor = unescape(self.document.location.hash.substring(1));
if(this.anchor != '') {
if($(this.anchor)) {
$(this.anchor).children().each(function(el) {
if(el.hasClass(this.options.containerclass)) {
el.addClass(this.options.activeclass);
}
}.bind(this));
}
}
},
_enableClicks: function() {
this.clicks = this.container.find(this.options.selection);
this.clicks.each(function(index, clk){
clk = $(clk);
if(clk.attr('href')) {
var clkID = clk.attr('href').split("#")[1];
if($('#'+clkID)) {
clk.id = 'button'+clkID;
clk.attr('role', 'button');
clk.attr('aria-controls', clkID);
clk.attr('id', clk.id);
clk.listitem = clk.closest('h2');
clk.container = $('#'+clkID);
clk.container.attr('role', 'region');
clk.data({
"id" : clk.id,
"listitem" : clk.listitem,
"container" : clk.container
});
if(!this.options.focuslinks) {
clk.container.attr('tabindex','-1');
}
/* if(clk.id) {
clk.container.attr('aria-labelledby',clk.id);
}*/
clk.containerheight = clk.container.height();
if(clk.container.hasClass(this.options.activeclass)) {
// clk.addClassName(this.options.activeclass);
this._show(clk.container);
this._ariaVisible(clk);
} else {
this._hide(clk.container);
this._ariaHidden(clk);
}
clk.on("click touchstart", function(event){
event.preventDefault();
this._toggle(clk);
}.bind(this));
if(this.options.focuslinks) {
clk.on("focusin", function(event){
event.preventDefault();
this._toggleFocus(clk);
}.bind(this));
clk.container.find('a').each(function(index,lnk){
lnk = $(lnk);
lnk.container = clk.container;
lnk.clk = clk;
lnk.on('focus', function(event) {
var lnk = $( event.target );
if (lnk.container.style.height == '0px') {
// this._appear(clk);
}
}.bind(this));
}.bind(this));
}
}
}
}.bind(this));
},
_toggle: function(el) {
if(this.stat) {
this.stat = false;
if (el.container.css('height') != '0px') {
this._fade(el);
} else {
this._appear(el);
}
}
},
_toggleFocus: function(el) {
if(this.stat) {
if (el.container.css('height') != '0px') {
// this._fade(clk);
} else {
this.stat = false;
this._appear(el);
}
}
},
_appear: function(el) {
el.container.animate({
height: el.containerheight+'px'
},
this.options.duration,
function() {
el.container.css("overflow",'visible')
el.container.css("margin",this.options.marginbottom);
this._ariaVisible(el);
el.container.focus();
}.bind(this)
);
},
_fade: function(el){
el.container.animate({
height: '0px'
},
this.options.duration,
function() {
el.container.removeClass(this.options.activeclass).addClass(this.options.inactiveclass);
el.container.css("overflow",'hidden')
el.container.css("margin",'0');
this._ariaHidden(el);
}.bind(this)
);
},
_show: function(el){
el.css({height:'auto',overflow:'visible',margin:this.options.marginbottom});
},
_hide: function(el){
el.css({height:'0px',overflow:'hidden',margin:'0px'});
},
_ariaVisible: function(el){
el.listitem.removeClass(this.options.inactiveclass).addClass(this.options.activeclass);
el.container.removeClass(this.options.inactiveclass).addClass(this.options.activeclass);
el.container.find('a').attr('tabindex','0');
el.container.attr('aria-expanded','true');
this.stat = true;
},
_ariaHidden: function(el){
el.listitem.removeClass(this.options.activeclass).addClass(this.options.inactiveclass);
el.container.find('a').attr('tabindex','-1');
el.container.attr('aria-expanded','false');
this.stat = true;
},
showAll: function() {
this.clicks.each(function(index,el) {
el = $(el);
clk.id = clk.data('id');
clk.listitem = clk.data('listitem');
clk.container = clk.data('container');
if(el.attr('href')) {
var elID = el.attr('href').split("#")[1];
if($(elID)) {
var elContainer = $("#"+elID);
el.data('listitem').removeClass(this.options.inactiveclass).addClass(this.options.activeclass);
this._show(elContainer);
this._ariaVisible(clk);
el.off('click touchstart');
if(this.options.focuslinks) {
el.off('focus');
}
}
}
}.bind(this));
}
};
// A really lightweight plugin wrapper around the constructor,
// preventing against multiple instantiations
$.fn[pluginName] = function ( options ) {
return this.each(function () {
if (!$.data(this, "plugin_" + pluginName)) {
$.data(this, "plugin_" + pluginName,
new Plugin( this, options ));
}
});
};
})( jQuery, window, document );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment