-
Notifications
You must be signed in to change notification settings - Fork 104
/
Copy pathshow-hide-content.js
166 lines (136 loc) · 4.92 KB
/
show-hide-content.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
;(function (global) {
'use strict'
var $ = global.jQuery
var GOVUK = global.GOVUK || {}
function ShowHideContent () {
var self = this
// Radio and Checkbox selectors
var selectors = {
namespace: 'ShowHideContent',
radio: '[data-target] > input[type="radio"]',
checkbox: '[data-target] > input[type="checkbox"]'
}
// Adds ARIA attributes to control + associated content
function initToggledContent () {
var $control = $(this)
var $content = getToggledContent($control)
// Set aria-controls and defaults
if ($content.length) {
$control.attr('aria-controls', $content.attr('id'))
$control.attr('aria-expanded', 'false')
$content.attr('aria-hidden', 'true')
}
}
// Return toggled content for control
function getToggledContent ($control) {
var id = $control.attr('aria-controls')
// ARIA attributes aren't set before init
if (!id) {
id = $control.closest('[data-target]').data('target')
}
// Find show/hide content by id
return $('#' + id)
}
// Show toggled content for control
function showToggledContent ($control, $content) {
// Show content
if ($content.hasClass('js-hidden')) {
$content.removeClass('js-hidden')
$content.attr('aria-hidden', 'false')
// If the controlling input, update aria-expanded
if ($control.attr('aria-controls')) {
$control.attr('aria-expanded', 'true')
}
}
}
// Hide toggled content for control
function hideToggledContent ($control, $content) {
$content = $content || getToggledContent($control)
// Hide content
if (!$content.hasClass('js-hidden')) {
$content.addClass('js-hidden')
$content.attr('aria-hidden', 'true')
// If the controlling input, update aria-expanded
if ($control.attr('aria-controls')) {
$control.attr('aria-expanded', 'false')
}
}
}
// Handle radio show/hide
function handleRadioContent ($control, $content) {
// All radios in this group which control content
var selector = selectors.radio + '[name="' + $control.attr('name') + '"][aria-controls]'
var $form = $control.closest('form')
var $radios = $form.length ? $form.find(selector) : $(selector)
// Hide content for radios in group
$radios.each(function () {
hideToggledContent($(this))
})
// Select content for this control
if ($control.is('[aria-controls]')) {
showToggledContent($control, $content)
}
}
// Handle checkbox show/hide
function handleCheckboxContent ($control, $content) {
// Show checkbox content
if ($control.is(':checked')) {
showToggledContent($control, $content)
} else { // Hide checkbox content
hideToggledContent($control, $content)
}
}
// Set up event handlers etc
function init ($container, elementSelector, eventSelectors, handler) {
$container = $container || $(document.body)
// Handle control clicks
function deferred () {
var $control = $(this)
handler($control, getToggledContent($control))
}
// Prepare ARIA attributes
var $controls = $(elementSelector)
$controls.each(initToggledContent)
// Handle events
$.each(eventSelectors, function (idx, eventSelector) {
$container.on('click.' + selectors.namespace, eventSelector, deferred)
})
// Any already :checked on init?
if ($controls.is(':checked')) {
$controls.filter(':checked').each(deferred)
}
}
// Get event selectors for all radio groups
function getEventSelectorsForRadioGroups () {
var radioGroups = []
// Build an array of radio group selectors
return $(selectors.radio).map(function () {
var groupName = $(this).attr('name')
if ($.inArray(groupName, radioGroups) === -1) {
radioGroups.push(groupName)
return 'input[type="radio"][name="' + $(this).attr('name') + '"]'
}
return null
})
}
// Set up radio show/hide content for container
self.showHideRadioToggledContent = function ($container) {
init($container, selectors.radio, getEventSelectorsForRadioGroups(), handleRadioContent)
}
// Set up checkbox show/hide content for container
self.showHideCheckboxToggledContent = function ($container) {
init($container, selectors.checkbox, [selectors.checkbox], handleCheckboxContent)
}
// Remove event handlers
self.destroy = function ($container) {
$container = $container || $(document.body)
$container.off('.' + selectors.namespace)
}
}
ShowHideContent.prototype.init = function ($container) {
this.showHideRadioToggledContent($container)
this.showHideCheckboxToggledContent($container)
}
GOVUK.ShowHideContent = ShowHideContent
global.GOVUK = GOVUK
})(window)