I have only added the JQuery using CDN, I placed the code in the head, in _head.html.erb which is this one :
<script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
Then I used this code, and placed it somewhere in the show.html.erb
<script>
var carouselWidth = $('.carousel-inner')[0].scrollWidth;
var cardWidth = $('.carousel-item').width();
var scrollPosition = 0;
$('.carousel-control-next').on('click', function(){
console.log('next');
scrollPosition = scrollPosition + cardWidth;
$('.carousel-inner').animate({scrollLeft: scrollPosition}, 600);
});
</script>
I'm not sure where else to place the jquery code, but when I open the console in the browser, I get this error:
menu-f19d6842a068966109ba6a8b3de0283869f632ec673afe222888bbeba8442401.js:7 Uncaught TypeError: Cannot read properties of null (reading 'addEventListener')
at addToggleListener (menu-f19d6842a068966109ba6a8b3de0283869f632ec673afe222888bbeba8442401.js:7:26)
at HTMLDocument.<anonymous> (menu-f19d6842a068966109ba6a8b3de0283869f632ec673afe222888bbeba8442401.js:15:9)
at S (turbo.es2017-esm.js:344:34)
at Object.notifyApplicationAfterPageLoad (turbo.es2017-esm.js:3158:16)
at Object.pageBecameInteractive (turbo.es2017-esm.js:3080:14)
at he.pageIsInteractive (turbo.es2017-esm.js:2486:27)
at he.pageIsComplete (turbo.es2017-esm.js:2490:14)
at HTMLDocument.interpretReadyState (turbo.es2017-esm.js:2458:22)
addToggleListener @ menu-f19d6842a068966109ba6a8b3de0283869f632ec673afe222888bbeba8442401.js:7
(anonymous) @ menu-f19d6842a068966109ba6a8b3de0283869f632ec673afe222888bbeba8442401.js:15
S @ turbo.es2017-esm.js:344
notifyApplicationAfterPageLoad @ turbo.es2017-esm.js:3158
pageBecameInteractive @ turbo.es2017-esm.js:3080
pageIsInteractive @ turbo.es2017-esm.js:2486
pageIsComplete @ turbo.es2017-esm.js:2490
interpretReadyState @ turbo.es2017-esm.js:2458
Edit
the menu.js file :
function addToggleListener(selected_id, menu_id, toggle_class) {
let selected_element = document.querySelector(`#${selected_id}`);
selected_element.addEventListener('click', function(event){
event.preventDefault();
let menu = document.querySelector(`#${menu_id}`)
menu.classList.toggle(toggle_class);
});
}
document.addEventListener('turbo:load', function(){
addToggleListener('hamburger', 'navbar-menu', 'collapse');
addToggleListener('account', 'dropdown-menu', 'active');
});
You're trying to add a listener to an element selected_element.addEventListener
and you don't have "hamburger" or "account" element on the page. Using event delegation is a much better approach with Turbo:
// menu.js
function toggleMenu(event, selectedId, menuId, toggleClass) {
const selected = event.target.closest(selectedId)
if (selected) {
event.preventDefault();
const menu = document.querySelector(menuId)
menu.classList.toggle(toggleClass);
}
}
document.addEventListener("click", function(event){
toggleMenu(event, "#hamburger", "#navbar-menu", "collapse");
toggleMenu(event, "#account", "#dropdown-menu", "active");
});
You might want to consider using data
attributes to control the behavior from your templates. This way you won't have to add more toggleMenu
calls:
// menu.js
document.addEventListener("click", function(event){
const toggler = event.target.closest("[data-toggle]")
if (toggler) {
event.preventDefault();
const menu = document.querySelector(toggler.dataset.toggle)
menu.classList.toggle(toggler.dataset.toggleClass);
}
});
<div data-toggle="#navbar-menu" data-toggle-class="collapse">hamburger</div>
<div id="navbar-menu" class="collapse">navbar menu</div>
<div data-toggle="#dropdown-menu" data-toggle-class="active">hamburger</div>
<div id="dropdown-menu" class="active">account menu</div>
https://turbo.hotwired.dev/handbook/building#installing-javascript-behavior https://learn.jquery.com/events/event-delegation/