11'use strict'
22
3- if ( ! Webflow ) {
3+ if ( ! Webflow ) {
44 var Webflow = Webflow || [ ] ;
55}
66
7- Webflow . push ( function ( ) {
8- //Allow site to load in case there's any extra integrations that require it
9- setTimeout ( function ( ) {
7+ class TabsSlider {
8+ constructor ( _tabs ) {
9+ try {
10+ this . tabsComponent = _tabs ;
11+ this . timeout = _tabs . getAttribute ( "wt-tabslider-speed" ) || 5000 ;
12+ this . tabBtns = _tabs . querySelector ( "[wt-tabslider-element='menu']" ) ;
13+ if ( ! this . tabBtns ) throw new Error ( "Tab buttons menu not found." ) ;
1014
11- let tabsComponent = document . querySelectorAll ( "[wt-tabSlider-element='tabs']" ) ;
15+ this . tb = Array . from ( this . tabBtns . children ) || [ ] ;
16+ if ( ! this . tb . length ) throw new Error ( "No tab buttons found." ) ;
1217
13- if ( tabsComponent ) {
14- tabsComponent . forEach ( tabs => {
15-
16- let timeout = tabs . getAttribute ( "wt-tabSlider-speed" ) || 5000 ;
17- let tabBtns = tabs . querySelector ( "[wt-tabSlider-element='menu']" ) ;
18- var tb = Array . from ( tabBtns . children ) ;
19- let activeElement = document . activeElement ;
18+ this . activeElement = null ;
19+ this . tabTimeout = null ;
20+ this . paused = false ;
21+ this . debounceTimeout = null ;
22+ this . init ( ) ;
23+ } catch ( err ) {
24+ console . error ( "TabsSlider initialization failed: " , err . message ) ;
25+ }
26+ }
2027
21- const tabLoop = ( tm , timeout ) => {
22- tabTimeout = setTimeout ( setTabTimeout , timeout , tm ) ; // 5 Second Rotation
23- }
28+ init ( ) {
29+ Webflow . push ( ( ) => {
30+ try {
31+ this . activeElement = document . activeElement ;
2432
25- const setTabTimeout = ( tm ) => {
26- var $next = tm . querySelector ( ".w--current" ) . nextElementSibling ;
27- if ( $next ) {
28- $next . click ( ) ; // user click resets timeout
29- } else {
30- tm . firstChild . click ( ) ;
31- }
32- if ( activeElement . nodeName === "INPUT" ) {
33- activeElement . focus ( ) ;
34- activeElement . dispatchEvent ( new KeyboardEvent ( 'keydown' , { keyCode : 40 } ) ) ;
35- }
33+ // Handle hover pause functionality
34+ const pauseOnHover = this . tabsComponent . getAttribute ( "wt-tabslider-pauseonhover" ) === "true" ;
35+ if ( pauseOnHover ) {
36+ this . tabsComponent . addEventListener ( "mouseover" , this . debounce ( this . pauseSlider . bind ( this ) , 100 ) ) ;
37+ this . tabsComponent . addEventListener ( "mouseout" , this . debounce ( this . resumeSlider . bind ( this ) , 100 ) ) ;
3638 }
3739
38- // Fix for Safari
40+ // Safari fix
3941 if ( navigator . userAgent . includes ( "Safari" ) ) {
40- tb . forEach ( ( t ) => ( t . focus = function ( ) {
41- const x = window . scrollX , y = window . scrollY ; const f = ( ) => {
42- setTimeout ( ( ) => window . scrollTo ( x , y ) , 1 ) ;
43- t . removeEventListener ( "focus" , f ) } ;
44- t . addEventListener ( "focus" , f ) ;
45- HTMLElement . prototype . focus . apply ( this , arguments )
46- } )
47- ) ;
42+ this . tb . forEach ( t => ( t . focus = this . preventScroll . bind ( this , t ) ) ) ;
4843 }
49-
50- // Reset Loops
51- tb . forEach ( tBtn => {
52- tBtn . addEventListener ( 'click' , function ( e ) {
44+
45+ this . tb . forEach ( tBtn => {
46+ tBtn . addEventListener ( 'click' , ( e ) => {
5347 e . preventDefault ( ) ;
54- clearTimeout ( tabTimeout ) ;
55- tabLoop ( tabBtns , timeout ) ;
56- } , false ) ;
57- } )
58-
59- // Start Tabs
60- var tabTimeout ;
61- clearTimeout ( tabTimeout ) ;
62- tabLoop ( tabBtns , timeout ) ;
63- } )
48+ clearTimeout ( this . tabTimeout ) ;
49+ this . tabLoop ( ) ;
50+ } ) ;
51+ } ) ;
52+
53+ this . tabLoop ( ) ;
54+ } catch ( err ) {
55+ console . error ( "TabsSlider initialization error: " , err . message ) ;
56+ }
57+ } ) ;
58+ }
59+
60+ preventScroll ( t ) {
61+ const x = window . scrollX , y = window . scrollY ;
62+ const f = ( ) => {
63+ setTimeout ( ( ) => window . scrollTo ( x , y ) , 1 ) ;
64+ t . removeEventListener ( "focus" , f ) ;
65+ } ;
66+ t . addEventListener ( "focus" , f ) ;
67+ HTMLElement . prototype . focus . apply ( t , arguments ) ;
68+ }
69+
70+ tabLoop ( ) {
71+ if ( ! this . paused ) {
72+ this . tabTimeout = setTimeout ( this . setTabTimeout . bind ( this ) , this . timeout , this . tabBtns ) ;
73+ }
74+ }
75+
76+ setTabTimeout ( tm ) {
77+ try {
78+ var $next = tm . querySelector ( ".w--current" ) . nextElementSibling ;
79+ if ( $next ) {
80+ $next . click ( ) ;
81+ } else {
82+ tm . firstChild . click ( ) ;
83+ }
84+ if ( this . activeElement && this . activeElement . nodeName === "INPUT" ) {
85+ this . activeElement . focus ( ) ;
86+ this . activeElement . dispatchEvent ( new KeyboardEvent ( 'keydown' , { keyCode : 40 } ) ) ;
87+ }
88+ } catch ( err ) {
89+ console . error ( "Tab loop error: " , err . message ) ;
6490 }
65- } , 500 )
66- } ) ;
91+ }
92+
93+ pauseSlider ( ) {
94+ clearTimeout ( this . tabTimeout ) ;
95+ this . paused = true ;
96+ }
97+
98+ resumeSlider ( ) {
99+ this . paused = false ;
100+ this . tabLoop ( ) ;
101+ }
102+
103+ debounce ( func , wait ) {
104+ return ( ...args ) => {
105+ clearTimeout ( this . debounceTimeout ) ;
106+ this . debounceTimeout = setTimeout ( ( ) => func . apply ( this , args ) , wait ) ;
107+ } ;
108+ }
109+ }
110+
111+ const InitializeTabsSlider = ( ) => {
112+ try {
113+ window . trickeries = window . trickeries || [ ] ;
114+ let tabsComponents = document . querySelectorAll ( "[wt-tabslider-element='tabs']" ) ;
115+ if ( ! tabsComponents || tabsComponents . length === 0 ) throw new Error ( "No tabs components found." ) ;
116+
117+ tabsComponents . forEach ( tabsComponent => {
118+ let instance = new TabsSlider ( tabsComponent ) ;
119+ window . trickeries . push ( { 'TabsSlider' : instance } ) ;
120+ } ) ;
121+ } catch ( err ) {
122+ console . error ( "InitializeTabsSlider error: " , err . message ) ;
123+ }
124+ }
125+
126+ if ( / c o m p l e t e | i n t e r a c t i v e | l o a d e d / . test ( document . readyState ) ) {
127+ InitializeTabsSlider ( ) ;
128+ } else {
129+ window . addEventListener ( 'DOMContentLoaded' , InitializeTabsSlider ) ;
130+ }
0 commit comments