PageSourceSearch

https://www.gresb.com/wp-content/themes/framework/assets/js/components/_1_responsive-sidebar.js?ver=1790907545

js gresb.com collected 2026-10-02 02:38:17 UTC 7,262 bytes, 188 lines download raw bytes

1// File#: _1_responsive-sidebar
2// Usage: codyhouse.co/license
3(function() {
4  var Sidebar = function(element) {
5		this.element = element;
6		this.triggers = document.querySelectorAll('[aria-controls="'+this.element.getAttribute('id')+'"]');
7		this.firstFocusable = null;
8		this.lastFocusable = null;
9		this.selectedTrigger = null;
10    this.showClass = "sidebar--is-visible";
11    this.staticClass = "sidebar--static";
12    this.customStaticClass = "";
13    this.readyClass = "sidebar--loaded";
14    this.layout = false; // this will be static or mobile
15    getCustomStaticClass(this); // custom classes for static version
16    initSidebar(this);
17  };
18
19  function getCustomStaticClass(element) {
20    var customClasses = element.element.getAttribute('data-static-class');
21    if(customClasses) element.customStaticClass = ' '+customClasses;
22  };
23  
24  function initSidebar(sidebar) {
25    initSidebarResize(sidebar); // handle changes in layout -> mobile to static and viceversa
26    
27		if ( sidebar.triggers ) { // open sidebar when clicking on trigger buttons - mobile layout only
28			for(var i = 0; i < sidebar.triggers.length; i++) {
29				sidebar.triggers[i].addEventListener('click', function(event) {
30					event.preventDefault();
31					if(Util.hasClass(sidebar.element, sidebar.showClass)) {
32            sidebar.selectedTrigger = event.target;
33            closeSidebar(sidebar);
34            return;
35          }
36					sidebar.selectedTrigger = event.target;
37					showSidebar(sidebar);
38					initSidebarEvents(sidebar);
39				});
40			}
41		}
42  };
43
44  function showSidebar(sidebar) { // mobile layout only
45		Util.addClass(sidebar.element, sidebar.showClass);
46		getFocusableElements(sidebar);
47		Util.moveFocus(sidebar.element);
48  };
49
50  function closeSidebar(sidebar) { // mobile layout only
51		Util.removeClass(sidebar.element, sidebar.showClass);
52		sidebar.firstFocusable = null;
53		sidebar.lastFocusable = null;
54    if(sidebar.selectedTrigger) sidebar.selectedTrigger.focus();
55    sidebar.element.removeAttribute('tabindex');
56		//remove listeners
57		cancelSidebarEvents(sidebar);
58	};
59
60  function initSidebarEvents(sidebar) { // mobile layout only
61    //add event listeners
62		sidebar.element.addEventListener('keydown', handleEvent.bind(sidebar));
63		sidebar.element.addEventListener('click', handleEvent.bind(sidebar));
64  };
65
66  function cancelSidebarEvents(sidebar) { // mobile layout only
67    //remove event listeners
68		sidebar.element.removeEventListener('keydown', handleEvent.bind(sidebar));
69		sidebar.element.removeEventListener('click', handleEvent.bind(sidebar));
70  };
71
72  function handleEvent(event) { // mobile layout only
73    switch(event.type) {
74      case 'click': {
75        initClick(this, event);
76      }
77      case 'keydown': {
78        initKeyDown(this, event);
79      }
80    }
81  };
82
83  function initKeyDown(sidebar, event) { // mobile layout only
84    if( event.keyCode && event.keyCode == 27 || event.key && event.key == 'Escape' ) {
85      //close sidebar window on esc
86      closeSidebar(sidebar);
87    } else if( event.keyCode && event.keyCode == 9 || event.key && event.key == 'Tab' ) {
88      //trap focus inside sidebar
89      trapFocus(sidebar, event);
90    }
91  };
92
93  function initClick(sidebar, event) { // mobile layout only
94    //close sidebar when clicking on close button or sidebar bg layer 
95		if( !event.target.closest('.js-sidebar__close-btn') && !Util.hasClass(event.target, 'js-sidebar') ) return;
96		event.preventDefault();
97		closeSidebar(sidebar);
98  };
99
100  function trapFocus(sidebar, event) { // mobile layout only
101    if( sidebar.firstFocusable == document.activeElement && event.shiftKey) {
102			//on Shift+Tab ->
102 focus last focusable element when focus moves out of sidebar
103			event.preventDefault();
104			sidebar.lastFocusable.focus();
105		}
106		if( sidebar.lastFocusable == document.activeElement && !event.shiftKey) {
107			//on Tab -> focus first focusable element when focus moves out of sidebar
108			event.preventDefault();
109			sidebar.firstFocusable.focus();
110		}
111  };
112
113  function initSidebarResize(sidebar) {
114    // custom event emitted when window is resized - detect only if the sidebar--static@{breakpoint} class was added
115    var beforeContent = getComputedStyle(sidebar.element, ':before').getPropertyValue('content');
116    if(beforeContent && beforeContent !='' && beforeContent !='none') {
117      checkSidebarLayout(sidebar);
118
119      sidebar.element.addEventListener('update-sidebar', function(event){
120        checkSidebarLayout(sidebar);
121      });
122    } 
123    Util.addClass(sidebar.element, sidebar.readyClass);
124  };
125
126  function checkSidebarLayout(sidebar) {
127    var layout = getComputedStyle(sidebar.element, ':before').getPropertyValue('content').replace(/\'|"/g, '');
128    if(layout == sidebar.layout) return;
129    sidebar.layout = layout;
130    if(layout != 'static') Util.addClass(sidebar.element, 'is-hidden');
131    Util.toggleClass(sidebar.element, sidebar.staticClass + sidebar.customStaticClass, layout == 'static');
132    if(layout != 'static') setTimeout(function(){Util.removeClass(sidebar.element, 'is-hidden')});
133    // reset element role 
134    (layout == 'static') ? sidebar.element.removeAttribute('role', 'alertdialog') :  sidebar.element.setAttribute('role', 'alertdialog');
135    // reset mobile behaviour
136    if(layout == 'static' && Util.hasClass(sidebar.element, sidebar.showClass)) closeSidebar(sidebar);
137  };
138
139  function getFocusableElements(sidebar) {
140    //get all focusable elements inside the drawer
141		var allFocusable = sidebar.element.querySelectorAll('[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, [tabindex]:not([tabindex="-1"]), [contenteditable], audio[controls], video[controls], summary');
142		getFirstVisible(sidebar, allFocusable);
143		getLastVisible(sidebar, allFocusable);
144  };
145
146  function getFirstVisible(sidebar, elements) {
147		//get first visible focusable element inside the sidebar
148		for(var i = 0; i < elements.length; i++) {
149			if( elements[i].offsetWidth || elements[i].offsetHeight || elements[i].getClientRects().length ) {
150				sidebar.firstFocusable = elements[i];
151				return true;
152			}
153		}
154	};
155
156	function getLastVisible(sidebar, elements) {
157		//get last visible focusable element inside the sidebar
158		for(var i = elements.length - 1; i >= 0; i--) {
159			if( elements[i].offsetWidth || elements[i].offsetHeight || elements[i].getClientRects().length ) {
160				sidebar.lastFocusable = elements[i];
161				return true;
162			}
163		}
164  };
165
166  //initialize the Sidebar objects
167	var sidebar = document.getElementsByClassName('js-sidebar');
168	if( sidebar.length > 0 ) {
169		for( var i = 0; i < sidebar.length; i++) {
170			(function(i){new Sidebar(sidebar[i]);})(i);
171    }
172    // switch from mobile to static layout
173    var customEvent = new CustomEvent('update-sidebar');
174    window.addEventListener('resize', function(event){
175      (!window.requestAnimationFrame) ? setTimeout(function(){resetLayout();}, 250) : window.requestAnimationFrame(resetLayout);
176    });
177
178    (window.requestAnimationFrame) // init sidebar layout
179      ? window.requestAnimationFrame(resetLayout)
180      : resetLayout();
181
182    function resetLayout() {
183      for( var i = 0; i < sidebar.length; i++) {
184        (function(i){sidebar[i].dispatchEvent(customEvent)})(i);
185      };
186    };
187	}
188}());

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.