5

ACCELERATING

MEDTECH

Discover The Evolution of MedTech Partnership.

Intech, Tyber Medical, and Resolve Surgical Technologies have united. We are now one global platform, moving beyond the traditional CDMO model to become your essential Tier-1 strategic partner for end-to-end OEM solutions.

Discover The Evolution of MedTech Partnership.

Intech, Tyber Medical, and Resolve Surgical Technologies have united. We are now one global platform, moving beyond the traditional CDMO model to become your essential Tier-1 strategic partner for end-to-end OEM solutions.

script for magic scroll
document.addEventListener('DOMContentLoaded', function() { const items = 4; // Total number of items const scrollHeight = document.querySelector('.scroll-spacer').offsetHeight; window.addEventListener('scroll', function() { const scrolled = window.pageYOffset; const maxScroll = scrollHeight - window.innerHeight; const scrollProgress = scrolled / maxScroll; // Calculate which item should show (1 to items) let currentIndex = Math.ceil(scrollProgress * items); if (currentIndex items) currentIndex = items; // Update all items at once document.querySelectorAll('.fade-item').forEach(item => { if (item.dataset.index == currentIndex) { item.classList.add('active'); } else { item.classList.remove('active'); } }); }); });
scramble
class TextScramble { constructor(el) { this.el = el; this.chars = '!-_\\/[]{}—=+*^?#________'; this.update = this.update.bind(this); } setText(newText) { const oldText = this.el.innerText; const length = Math.max(oldText.length, newText.length); const promise = new Promise((resolve) => this.resolve = resolve); this.queue = []; for (let i = 0; i < length; i++) { const from = oldText[i] || ''; const to = newText[i] || ''; const start = Math.floor(Math.random() * 40); const end = start + Math.floor(Math.random() * 40); this.queue.push({ from, to, start, end }); } cancelAnimationFrame(this.frameRequest); this.frame = 0; this.update(); return promise; } update() { let output = ''; let complete = 0; for (let i = 0, n = this.queue.length; i = end) { complete++; output += to; } else if (this.frame >= start) { if (!char || Math.random() { // Skip if already initialized if (element.hasAttribute('data-scramble-init')) return; // Get the original text - prioritize data-text attribute if it exists // Otherwise use the actual text content let originalText = element.getAttribute('data-text') || element.textContent || element.innerText; // Clean up the text (remove extra whitespace) originalText = originalText.trim(); // Mark as initialized element.setAttribute('data-scramble-init', 'true'); // Store original text element.setAttribute('data-text', originalText); // Clear text initially element.textContent = ''; // Find the parent fade-item element const fadeItem = element.closest('.fade-item'); if (fadeItem) { // Track if currently animating to prevent overlapping animations let isAnimating = false; // Create MutationObserver to watch for class changes const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { if (mutation.type === 'attributes' && mutation.attributeName === 'class') { // Check if 'active' class was added if (fadeItem.classList.contains('active') && !isAnimating) { // Set animating flag isAnimating = true; // Create scramble effect instance const fx = new TextScramble(element); // Small delay to sync with fade-in setTimeout(() => { element.classList.add('visible'); fx.setText(originalText).then(() => { // Optional: Add glow effect after animation completes element.classList.add('glowing'); setTimeout(() => { element.classList.remove('glowing'); }, 500); }); }, 100); // Adjust delay as needed } // Reset when active class is removed else if (!fadeItem.classList.contains('active') && isAnimating) { // Reset for re-animation isAnimating = false; element.textContent = ''; element.classList.remove('visible'); element.classList.remove('glowing'); } } }); }); // Start observing the fade-item for class changes observer.observe(fadeItem, { attributes: true, attributeFilter: ['class'] }); // Check if already active on page load if (fadeItem.classList.contains('active')) { setTimeout(() => { isAnimating = true; const fx = new TextScramble(element); element.classList.add('visible'); fx.setText(originalText); }, 100); } } else { // If not inside a fade-item, use Intersection Observer as fallback const observerOptions = { threshold: 0.2, rootMargin: '0px' }; const scrambleObserver = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting && !element.hasAttribute('data-scramble-animated')) { element.setAttribute('data-scramble-animated', 'true'); const fx = new TextScramble(element); element.classList.add('visible'); fx.setText(originalText).then(() => { element.classList.add('glowing'); setTimeout(() => { element.classList.remove('glowing'); }, 500); }); scrambleObserver.unobserve(element); } }); }, observerOptions); scrambleObserver.observe(element); } }); } // Initialize on DOMContentLoaded document.addEventListener('DOMContentLoaded', function() { // Small delay to ensure your scroll script runs first setTimeout(initScrambleEffect, 100); }); // Also initialize when Elementor loads new content (for popup, tabs, etc.) if (typeof jQuery !== 'undefined' && window.elementorFrontend) { jQuery(window).on('elementor/frontend/init', function() { elementorFrontend.hooks.addAction('frontend/element_ready/widget', initScrambleEffect); }); } // For Elementor: Re-run on Elementor preview refresh if (window.elementor) { window.elementor.on('preview:loaded', function() { // Re-initialize for preview mode const elements = document.querySelectorAll('.scramble-text'); elements.forEach((element) => { const fx = new TextScramble(element); const originalText = element.getAttribute('data-text'); if (originalText) { element.innerText = ''; element.classList.remove('visible'); setTimeout(() => { element.classList.add('visible'); fx.setText(originalText); }, 500); } }); }); }
svg
(function() { // Prevent multiple initializations if (window.animationInitialized) { console.log('Animation already initialized, skipping...'); return; } window.animationInitialized = true; console.log('Script loaded at:', new Date().toISOString()); let initAttempts = 0; const maxAttempts = 20; let animationStarted = false; // Additional flag to prevent multiple starts function initAnimation() { // Check if animation already started if (animationStarted) { console.log('Animation already started, skipping initialization'); return; } initAttempts++; console.log(`Initialization attempt ${initAttempts}/${maxAttempts}`); try { // Check if elements exist const svg = document.querySelector('.my-animated-svg'); const container = document.querySelector('.svg-container'); const targetImage = document.querySelector('.target-image'); console.log('Element check:', { svg: svg ? 'Found' : 'Not found', container: container ? 'Found' : 'Not found', targetImage: targetImage ? 'Found' : 'Not found' }); if (!svg || !container || !targetImage) { if (initAttempts < maxAttempts) { console.log('Elements not ready, retrying in 500ms...'); setTimeout(initAnimation, 500); } else { console.error('Max attempts reached. Elements not found.'); } return; } // Check if elements are visible const containerRect = container.getBoundingClientRect(); if (containerRect.width === 0 || containerRect.height === 0) { console.log('Container has no dimensions, waiting...'); if (initAttempts < maxAttempts) { setTimeout(initAnimation, 500); return; } } // Mark animation as started to prevent multiple runs animationStarted = true; console.log('All elements found and ready! Starting animation...'); // ===== CONFIGURATION ===== const config = { svgSelector: '.my-animated-svg', containerSelector: '.svg-container', targetImageSelector: '.target-image', taglineSelector: '.tagline', relativePosition: { fromTop: 70, fromLeft: 100 }, numberOfPasses: 3, initialSpeed: 3000, speedReduction: 0.5, fadeInDuration: 0, finalScale: 0.35, explosionScale: 3, explosionDuration: 2500, fadeInTargetImage: true, gradientSlowPulse: 10000, gradientPauseBeforeRestart: 1000, containerResizeDelay: 0, containerResizeDuration: 2000, containerFinalHeight: '100vh', showCountdown: true, countdownStart: 5, countdownOpacity: 0.3 }; // Get additional elements const taglines = document.querySelectorAll(config.taglineSelector); const countdown = document.querySelector('.countdown-number'); console.log('Additional elements:', { taglines: taglines.length + ' found', countdown: countdown ? 'Found' : 'Not found' }); // Store original dimensions const originalWidth = svg.offsetWidth || svg.getBoundingClientRect().width; const originalHeight = svg.offsetHeight || svg.getBoundingClientRect().height; console.log('SVG dimensions:', { width: originalWidth, height: originalHeight }); if (originalWidth === 0 || originalHeight === 0) { console.error('SVG has no dimensions! Retrying...'); animationStarted = false; // Reset flag to allow retry if (initAttempts < maxAttempts) { setTimeout(initAnimation, 500); return; } } let isAnimating = false; // Hide target image initially if fade-in is enabled if (config.fadeInTargetImage) { targetImage.style.opacity = '0'; targetImage.style.transition = `opacity ${config.explosionDuration}ms ease-in`; } // Calculate final position relative to target image function calculateFinalPosition() { const targetRect = targetImage.getBoundingClientRect(); const containerRect = container.getBoundingClientRect(); const targetRelativeTop = targetRect.top - containerRect.top; const targetRelativeLeft = targetRect.left - containerRect.left; const finalLeft = targetRelativeLeft + config.relativePosition.fromLeft; const finalTop = targetRelativeTop + config.relativePosition.fromTop; return { top: finalTop, left: finalLeft }; } // Main animation sequence async function animateSequence() { if (isAnimating) return; isAnimating = true; console.log('Starting progressive speed animation...'); const containerWidth = container.offsetWidth; const svgWidth = originalWidth; // Calculate total animation duration for countdown let countdownTotalDuration = config.fadeInDuration; let tempSpeed = config.initialSpeed; for (let i = 0; i { currentNumber--; if (currentNumber > 0) { countdown.textContent = currentNumber; countdown.style.transform = 'scale(1.3)'; countdown.style.transition = 'transform 0.5s ease-out'; setTimeout(() => { countdown.style.transform = 'scale(1)'; }, 50); } else { countdown.style.opacity = '0'; countdown.style.visibility = 'hidden'; countdown.textContent = ''; clearInterval(countdownTimer); } }, countdownInterval); } // Start with slow gradient pulse container.style.animation = `gradientShift ${config.gradientSlowPulse}ms ease-in-out infinite`; // Calculate scale reduction per pass const totalPasses = config.numberOfPasses + 1; const scaleReductionPerPass = (1 - config.finalScale) / totalPasses; // Setup initial position svg.style.left = `-${svgWidth}px`; svg.style.top = '50%'; svg.style.transition = 'none'; // Phase 1: Fade in console.log('Phase 1: Fading in...'); svg.style.opacity = '1'; await delay(config.fadeInDuration); // Phase 2: Multiple passes let currentSpeed = config.initialSpeed; let currentScale = 1; for (let pass = 1; pass 0) { const taglineDuration = config.explosionDuration + config.gradientPauseBeforeRestart; taglines.forEach(tagline => { tagline.style.transition = `opacity ${taglineDuration}ms ease-out, filter ${taglineDuration}ms ease-out`; tagline.style.opacity = '1'; tagline.style.filter = 'blur(0px)'; }); } if (config.fadeInTargetImage) { targetImage.style.opacity = '1'; } svg.style.transition = `transform ${config.explosionDuration}ms cubic-bezier(0, 0, 0.2, 1), opacity ${config.explosionDuration}ms ease-out`; svg.style.transform = `translate(-50%, -50%) scale(${config.finalScale * config.explosionScale})`; svg.style.opacity = '0'; await delay(config.explosionDuration); await delay(config.gradientPauseBeforeRestart); container.style.animation = `gradientShiftSlow ${config.gradientSlowPulse}ms ease-in-out infinite`; await delay(config.containerResizeDelay); console.log('Resizing container...'); container.style.transition = `min-height ${config.containerResizeDuration}ms ease-in-out`; container.style.minHeight = config.containerFinalHeight; await delay(config.containerResizeDuration); console.log('Animation complete!'); isAnimating = false; } // Helper function for delays function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } // Start animation ONLY ONCE animateSequence(); // Click to restart container.addEventListener('click', function() { if (isAnimating) return; console.log('Restarting animation...'); svg.style.transition = 'none'; svg.style.opacity = '0'; svg.style.left = `-${originalWidth}px`; svg.style.top = '50%'; svg.style.transform = 'translateY(-50%)'; svg.style.width = `${originalWidth}px`; svg.style.height = `${originalHeight}px`; svg.style.animation = 'none'; svg.classList.remove('blur-light', 'blur-medium', 'blur-heavy', 'blur-extreme', 'blur-super'); if (config.fadeInTargetImage) { targetImage.style.transition = 'none'; targetImage.style.opacity = '0'; targetImage.offsetHeight; targetImage.style.transition = `opacity ${config.explosionDuration}ms ease-in`; } if (taglines && taglines.length > 0) { taglines.forEach(tagline => { tagline.style.transition = 'none'; tagline.style.opacity = '0'; tagline.style.filter = 'blur(10px)'; tagline.offsetHeight; }); } if (countdown) { countdown.style.opacity = '0'; countdown.style.visibility = 'hidden'; countdown.textContent = ''; } container.style.animation = `gradientShift ${config.gradientSlowPulse}ms ease-in-out infinite`; container.style.transition = 'none'; container.style.minHeight = '100vh'; container.offsetHeight; container.style.transition = `min-height ${config.containerResizeDuration}ms ease-in-out`; svg.offsetHeight; setTimeout(animateSequence, 100); }); // Resize handler window.addEventListener('resize', function() { if (!isAnimating && svg.style.transform.includes('translate(-50%, -50%)')) { const finalPosition = calculateFinalPosition(); svg.style.left = `${finalPosition.left}px`; svg.style.top = `${finalPosition.top}px`; } }); } catch (error) { console.error('Animation error:', error); console.error('Error stack:', error.stack); } } // Only ONE initialization method - wait for page to be ready if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', function() { console.log('DOMContentLoaded - waiting 2s before init'); setTimeout(initAnimation, 2000); }); } else { // Document already loaded console.log('Document already loaded - waiting 2s before init'); setTimeout(initAnimation, 2000); } })();
test
console.log('=== SIMPLE TEST SCRIPT LOADED ==='); document.addEventListener('DOMContentLoaded', function() { console.log('=== DOM CONTENT LOADED ==='); alert('Script is working!'); });