@@ -59,41 +59,50 @@ class Accordion extends Plugin {
59
59
60
60
$content . attr ( { 'role' : 'tabpanel' , 'aria-labelledby' : linkId , 'aria-hidden' : true , 'id' : id } ) ;
61
61
} ) ;
62
+
62
63
var $initActive = this . $element . find ( '.is-active' ) . children ( '[data-tab-content]' ) ;
63
- this . firstTimeInit = true ;
64
- if ( $initActive . length ) {
65
- this . down ( $initActive , this . firstTimeInit ) ;
66
- this . firstTimeInit = false ;
64
+ if ( $initActive . length ) {
65
+ // Save up the initial hash to return to it later when going back in history
66
+ this . _initialAnchor = $initActive . prev ( 'a' ) . attr ( 'href' ) ;
67
+ this . _openSingleTab ( $initActive ) ;
67
68
}
68
69
69
70
this . _checkDeepLink = ( ) => {
70
71
var anchor = window . location . hash ;
71
- //need a hash and a relevant anchor in this tabset
72
- if ( anchor . length ) {
73
- var $link = this . $element . find ( '[href$="' + anchor + '"]' ) ,
74
- $anchor = $ ( anchor ) ;
75
-
76
- if ( $link . length && $anchor ) {
77
- if ( ! $link . parent ( '[data-accordion-item]' ) . hasClass ( 'is-active' ) ) {
78
- this . down ( $anchor , this . firstTimeInit ) ;
79
- this . firstTimeInit = false ;
80
- } ;
81
-
82
- //roll up a little to show the titles
83
- if ( this . options . deepLinkSmudge ) {
84
- var _this = this ;
85
- onLoad ( $ ( window ) , function ( ) {
86
- var offset = _this . $element . offset ( ) ;
87
- $ ( 'html, body' ) . animate ( { scrollTop : offset . top } , _this . options . deepLinkSmudgeDelay ) ;
88
- } ) ;
89
- }
90
-
91
- /**
92
- * Fires when the zplugin has deeplinked at pageload
93
- * @event Accordion#deeplink
94
- */
95
- this . $element . trigger ( 'deeplink.zf.accordion' , [ $link , $anchor ] ) ;
96
- }
72
+
73
+ // If there is no anchor, return to the initial panel
74
+ if ( ! anchor . length && this . _initialAnchor ) {
75
+ anchor = this . _initialAnchor ;
76
+ }
77
+
78
+ var $anchor = anchor && $ ( anchor ) ;
79
+ var $link = anchor && this . $element . find ( `[href$="${ anchor } "]` ) ;
80
+
81
+ // If there is an anchor for the hash, open it (if not already active)
82
+ if ( $anchor && $link && $link . length ) {
83
+ if ( ! $link . parent ( '[data-accordion-item]' ) . hasClass ( 'is-active' ) ) {
84
+ this . _openSingleTab ( $anchor ) ;
85
+ } ;
86
+ }
87
+ // Otherwise, close everything
88
+ else {
89
+ this . _closeAllTabs ( ) ;
90
+ }
91
+
92
+ // Roll up a little to show the titles
93
+ if ( this . options . deepLinkSmudge ) {
94
+ onLoad ( $ ( window ) , ( ) => {
95
+ var offset = this . $element . offset ( ) ;
96
+ $ ( 'html, body' ) . animate ( { scrollTop : offset . top } , this . options . deepLinkSmudgeDelay ) ;
97
+ } ) ;
98
+ }
99
+
100
+ if ( $anchor && $link ) {
101
+ /**
102
+ * Fires when the plugin has deeplinked at pageload
103
+ * @event Accordion#deeplink
104
+ */
105
+ this . $element . trigger ( 'deeplink.zf.accordion' , [ $link , $anchor ] ) ;
97
106
}
98
107
}
99
108
@@ -180,80 +189,130 @@ class Accordion extends Plugin {
180
189
/**
181
190
* Opens the accordion tab defined by `$target`.
182
191
* @param {jQuery } $target - Accordion pane to open (`.accordion-content`).
183
- * @param {Boolean } firstTime - flag to determine if reflow should happen.
184
192
* @fires Accordion#down
185
193
* @function
186
194
*/
187
- down ( $target , firstTime ) {
188
- /**
189
- * checking firstTime allows for initial render of the accordion
190
- * to render preset is-active panes.
191
- */
192
- if ( $target . closest ( '[data-accordion]' ) . is ( '[disabled]' ) && ! firstTime ) {
195
+ down ( $target ) {
196
+ if ( $target . closest ( '[data-accordion]' ) . is ( '[disabled]' ) ) {
193
197
console . info ( 'Cannot call down on an accordion that is disabled.' ) ;
194
198
return ;
195
199
}
196
- $target
197
- . attr ( 'aria-hidden' , false )
198
- . parent ( '[data-tab-content]' )
199
- . addBack ( )
200
- . parent ( ) . addClass ( 'is-active' ) ;
201
-
202
- if ( ! this . options . multiExpand && ! firstTime ) {
203
- var $currentActive = this . $element . children ( '.is-active' ) . children ( '[data-tab-content]' ) ;
204
- if ( $currentActive . length ) {
205
- this . up ( $currentActive . not ( $target ) ) ;
206
- }
200
+
201
+ if ( this . options . multiExpand )
202
+ this . _openTab ( $target ) ;
203
+ else
204
+ this . _openSingleTab ( $target ) ;
205
+ }
206
+
207
+ /**
208
+ * Closes the tab defined by `$target`.
209
+ * It may be ignored if the Accordion options don't allow it.
210
+ *
211
+ * @param {jQuery } $target - Accordion tab to close (`.accordion-content`).
212
+ * @fires Accordion#up
213
+ * @function
214
+ */
215
+ up ( $target ) {
216
+ if ( this . $element . is ( '[disabled]' ) ) {
217
+ console . info ( 'Cannot call up on an accordion that is disabled.' ) ;
218
+ return ;
219
+ }
220
+
221
+ // Don't close the item if it is already closed
222
+ const $targetItem = $target . parent ( ) ;
223
+ if ( ! $targetItem . hasClass ( 'is-active' ) ) return ;
224
+
225
+ // Don't close the item if there is no other active item (unless with `allowAllClosed`)
226
+ const $othersItems = $targetItem . siblings ( ) ;
227
+ if ( ! this . options . allowAllClosed && ! $othersItems . hasClass ( 'is-active' ) ) return ;
228
+
229
+ this . _closeTab ( $target ) ;
230
+ }
231
+
232
+ /**
233
+ * Make the tab defined by `$target` the only opened tab, closing all others tabs.
234
+ * @param {jQuery } $target - Accordion tab to open (`.accordion-content`).
235
+ * @function
236
+ * @private
237
+ */
238
+ _openSingleTab ( $target ) {
239
+ // Close all the others active tabs.
240
+ const $activeContents = this . $element . children ( '.is-active' ) . children ( '[data-tab-content]' ) ;
241
+ if ( $activeContents . length ) {
242
+ this . _closeTab ( $activeContents . not ( $target ) ) ;
207
243
}
208
244
245
+ // Then open the target.
246
+ this . _openTab ( $target ) ;
247
+ }
248
+
249
+ /**
250
+ * Opens the tab defined by `$target`.
251
+ * @param {jQuery } $target - Accordion tab to open (`.accordion-content`).
252
+ * @fires Accordion#down
253
+ * @function
254
+ * @private
255
+ */
256
+ _openTab ( $target ) {
257
+ const $targetItem = $target . parent ( ) ;
258
+ const targetContentId = $target . attr ( 'aria-labelledby' ) ;
259
+
260
+ $target . attr ( 'aria-hidden' , false ) ;
261
+ $targetItem . addClass ( 'is-active' ) ;
262
+
263
+ $ ( `#${ targetContentId } ` ) . attr ( {
264
+ 'aria-expanded' : true ,
265
+ 'aria-selected' : true
266
+ } ) ;
267
+
209
268
$target . slideDown ( this . options . slideSpeed , ( ) => {
210
269
/**
211
270
* Fires when the tab is done opening.
212
271
* @event Accordion#down
213
272
*/
214
273
this . $element . trigger ( 'down.zf.accordion' , [ $target ] ) ;
215
274
} ) ;
216
-
217
- $ ( `#${ $target . attr ( 'aria-labelledby' ) } ` ) . attr ( {
218
- 'aria-expanded' : true ,
219
- 'aria-selected' : true
220
- } ) ;
221
275
}
222
276
223
277
/**
224
278
* Closes the tab defined by `$target`.
225
279
* @param {jQuery } $target - Accordion tab to close (`.accordion-content`).
226
280
* @fires Accordion#up
227
281
* @function
282
+ * @private
228
283
*/
229
- up ( $target ) {
230
- if ( $target . closest ( '[data-accordion]' ) . is ( '[disabled]' ) ) {
231
- console . info ( 'Cannot call up on an accordion that is disabled.' ) ;
232
- return ;
233
- }
284
+ _closeTab ( $target ) {
285
+ const $targetItem = $target . parent ( ) ;
286
+ const targetContentId = $target . attr ( 'aria-labelledby' ) ;
234
287
235
- var $aunts = $ target. parent ( ) . siblings ( ) ,
236
- _this = this ;
288
+ $ target. attr ( 'aria-hidden' , true )
289
+ $targetItem . removeClass ( 'is-active' ) ;
237
290
238
- if ( ( ! this . options . allowAllClosed && ! $aunts . hasClass ( 'is-active' ) ) || ! $target . parent ( ) . hasClass ( 'is-active' ) ) {
239
- return ;
240
- }
291
+ $ ( `#${ targetContentId } ` ) . attr ( {
292
+ 'aria-expanded' : false ,
293
+ 'aria-selected' : false
294
+ } ) ;
241
295
242
- $target . slideUp ( _this . options . slideSpeed , function ( ) {
296
+ $target . slideUp ( this . options . slideSpeed , ( ) => {
243
297
/**
244
298
* Fires when the tab is done collapsing up.
245
299
* @event Accordion#up
246
300
*/
247
- _this . $element . trigger ( 'up.zf.accordion' , [ $target ] ) ;
301
+ this . $element . trigger ( 'up.zf.accordion' , [ $target ] ) ;
248
302
} ) ;
303
+ }
249
304
250
- $target . attr ( 'aria-hidden' , true )
251
- . parent ( ) . removeClass ( 'is-active' ) ;
252
-
253
- $ ( `#${ $target . attr ( 'aria-labelledby' ) } ` ) . attr ( {
254
- 'aria-expanded' : false ,
255
- 'aria-selected' : false
256
- } ) ;
305
+ /**
306
+ * Closes all active tabs
307
+ * @fires Accordion#up
308
+ * @function
309
+ * @private
310
+ */
311
+ _closeAllTabs ( ) {
312
+ var $activeTabs = this . $element . children ( '.is-active' ) . children ( '[data-tab-content]' ) ;
313
+ if ( $activeTabs . length ) {
314
+ this . _closeTab ( $activeTabs ) ;
315
+ }
257
316
}
258
317
259
318
/**
0 commit comments