import "@hotwired/turbo-rails" var input_range const max_value = 180 const speed = 12 var curr_value var raf_id var random_salt = Math.random() function rand_in_range(from, to) { const rand = Math.floor(Math.random() * (to - from + 1)) + from const is_neg = Math.random() < 0.5 return is_neg ? -rand : rand } function shuffle_cards() { const cards = document.querySelectorAll('.card__container') const card_ids = Array.from(cards).map(card => card.getAttribute('data-id')) let shown_cards = JSON.parse(localStorage.getItem('shown_cards')) || []; let cards_not_shown = card_ids.filter(id => !shown_cards.includes(id)); if (cards_not_shown.length <= 0) { cards_not_shown = card_ids shown_cards = [] } const random_id = cards_not_shown[Math.floor(Math.random() * cards_not_shown.length)]; cards.forEach((card) => { if (card.getAttribute('data-id') == random_id) { card.style.zIndex = '1' card.style.transform = '' card.classList.add('active') } else { card.classList.remove('active') card.style.zIndex = 'auto' card.style.transform = `rotate(${rand_in_range(2,5)}deg) translate(${rand_in_range(2,5)}px, ${rand_in_range(2,5)}px)` } }) shown_cards.push(random_id); localStorage.setItem('shown_cards', JSON.stringify(shown_cards)); } document.addEventListener("turbo:load", ()=> { init() }) document.addEventListener("turbo:before-cache", () => { if (input_range) { input_range.value = 0; input_range.closest('.reveal__container').style.setProperty('--opacity', 1); updateRotation(input_range.value) } let images = document.querySelectorAll("img.fade-in.loaded") images.forEach(image => { image.classList.remove("loaded") }) }) function init() { random_salt = Math.random() document.querySelectorAll('.button_shuffle_cards').forEach((item, index) => { item.addEventListener('click', (e) => { shuffle_cards() }) if (index == 0) shuffle_cards() }) document.querySelectorAll('#language_select').forEach((language_select) => { language_select.addEventListener('change', (e) => { document.documentElement.lang = language_select.value }) }) // Choose language confirmation button document.querySelectorAll('#confirm_btn').forEach((confirm_btn) => { confirm_btn.addEventListener('click', (e) => { // window.location.href = '/' + document.getElementById('language_select').value Turbo.visit('/' + document.getElementById('language_select').value, {advance: 'advance'}) }) }) // Copy link to clipboard document.querySelectorAll('[data-share-title]').forEach((share_btn) => { share_btn.addEventListener('click', (e) => { if (navigator.share) { navigator.share({ title: e.currentTarget.getAttribute('data-share-title'), text: e.currentTarget.getAttribute('data-share-text'), url: window.location.href }).then(() => { console.log('Thanks for sharing!'); }) .catch(console.error); } else { navigator.clipboard.writeText(window.location.href) alert('URL copied to clipboard!') } }) }) document.querySelectorAll('.card__stack a').forEach((card_link) => { card_link.addEventListener('click', (e) => { e.preventDefault() }) }) // Open all external links in ny tab for (const link of document.links) { if (link.hostname.replace(/^www\./i, "") != window.location.hostname.replace(/^www\./i, "") && (link.protocol == 'https:' || link.protocol == 'http:')) link.target = '_blank' } input_range = document.getElementsByClassName('reveal')[0] if (input_range) { input_range.min = 0; input_range.max = max_value; } if (input_range) { input_range.addEventListener('mousedown', unlockStartHandler, false) input_range.addEventListener('touchstart', unlockStartHandler, false) input_range.addEventListener('mouseup', unlockEndHandler, false) input_range.addEventListener('touchend', unlockEndHandler, false) input_range.addEventListener("input", (e) => { e.currentTarget.closest('.reveal__container').style.setProperty('--opacity', 1 - (e.currentTarget.value/e.currentTarget.max)) updateRotation(e.currentTarget.value) }) } let images = document.querySelectorAll("img.fade-in") images.forEach(image => { image.addEventListener("load", () => { image.classList.add("loaded") }) // For cached images that may already be loaded if (image.complete) { window.requestAnimationFrame(() => { image.classList.add("loaded") }) } }) } function unlockStartHandler() { window.cancelAnimationFrame(raf_id); curr_value = +this.value; } function unlockEndHandler() { curr_value = +this.value; if (curr_value >= this.max) { const card = document.querySelector('.card__container.active') //window.location.href = card.parentNode.getAttribute('href') Turbo.visit(card.parentNode.getAttribute('href'), { action: 'advance'} ) } else { raf_id = window.requestAnimationFrame(animateHandler); } } // handle range animation function animateHandler() { input_range.value = curr_value; input_range.closest('.reveal__container').style.setProperty('--opacity', 1 - (input_range.value/input_range.max)); updateRotation(input_range.value) // continue? if (curr_value > -1) { window.requestAnimationFrame(animateHandler); } // decrement curr_value = curr_value - speed; } function updateRotation(angle) { document.documentElement.style.setProperty('--flip-deg', angle + 'deg') document.documentElement.style.setProperty('--flip-scale', calculateScaleFactor(angle)) document.documentElement.style.setProperty('--flip-rotate', calculateRotateFactor(angle) + 'deg') } function calculateScaleFactor(angle) { const radians = angle * (Math.PI / 180) return 1 + (0.1 * Math.sin(radians)) // return 1 + (0.2 * (angle / 180)) } function calculateRotateFactor(angle) { const radians = angle * (Math.PI / 180) return (4 * Math.sin(radians)) + (random_salt * 2) }