
I have a simple blog component that is written in jQuery. I would like to convert it to plain JavaScript as part of my effort to completely remove jQuery from my portfolio website.
export default { textboxHeight: '', init() { $('.post-difficulty .header-info').click(this.toggle.bind(this)); // get initial box height and add it as variable let $textbox = $('.post-difficulty .difficulty-information'); this.textboxHeight = $textbox.outerHeight(); $textbox.css({ 'height': 0, 'padding': 0, }); }, toggle() { let isOut = $('.post-difficulty').attr('aria-toggled') == 'true'; if(isOut) { $('.post-difficulty').attr('aria-toggled', 'false'); $('.post-difficulty .toggle-icon').removeClass('fa-caret-up'); $('.post-difficulty .toggle-icon').addClass('fa-caret-down'); // toggle and style the information back on $('.post-difficulty .difficulty-information').css({ 'opacity': 0, 'height': 0, 'padding': 0, }) } else { $('.post-difficulty').attr('aria-toggled', 'true'); $('.post-difficulty .toggle-icon').removeClass('fa-caret-down'); $('.post-difficulty .toggle-icon').addClass('fa-caret-up'); // toggle and style the information back on $('.post-difficulty .difficulty-information').css({ 'opacity': 1, 'height': this.textboxHeight, 'padding': '15px', }) } }, }
Here’s what the code does in order.
init()
on .header-info
click, call the toggle
method. Get the initial textbox height and store it as a variable on the current object. Set height and padding to 0 to set the initial state of hidden on the toggleable portion.
toggle()
if aria-toggled
is true, we can assume the component is toggled and expanded. If it’s out, set aria-toggled
to the opposite value and update the toggle icon. Set the css of the toggleable portion to be hidden again. If aria-toggled
is false, we need to expand the component. Do this by setting the aria-toggled
prop to true, update the icon class and set the appropriate values, and set the textboxHeight
.
Let’s get to refactoring this!
export default { textboxHeight: '', init() { if (!document.querySelectorAll('.post-difficulty').length) return document.querySelector('.post-difficulty .header-info').addEventListener( 'click', this.toggle.bind(this) ) // get initial box height and add it as variable const $textbox = document.querySelector('.post-difficulty .difficulty-information') this.textboxHeight = $textbox.clientHeight $textbox.style.height = 0 $textbox.style.padding = 0 }, toggle() { const $difficulty = document.querySelector('.post-difficulty') const $icon = document.querySelector('.post-difficulty .toggle-icon') const $difficultyInformation = document.querySelector('.post-difficulty .difficulty-information') if($difficulty.getAttribute('aria-toggled') === 'true') { $difficulty.setAttribute('aria-toggled', 'false') $icon.classList.remove('fa-caret-up') $icon.classList.add('fa-caret-down') // toggle and style the information back on $difficultyInformation.style.opacity = 0 $difficultyInformation.style.height = 0 $difficultyInformation.style.padding = 0 } else { $difficulty.setAttribute('aria-toggled', 'true') $icon.classList.remove('fa-caret-down') $icon.classList.add('fa-caret-up') // toggle and style the information back on $difficultyInformation.style.opacity = 1 $difficultyInformation.style.height = this.textboxHeight + 'px' $difficultyInformation.style.padding = '15px' } }, }
Refactoring this was very straightforward and the resulting code isn’t noticeably longer. I opted to declare style selectors as variables because document.querySelectorAll
can get a bit lengthy(and were often referenced multiple times anyways).