PageSourceSearch

https://schoolmaker.com/assets/controllers/marquee_controller-3e0d…2512cbd94b73ff67fb4c73242bc6f9af9cd5826a.js

js schoolmaker.com collected 2026-09-26 02:12:59 UTC 5,763 bytes, 1 lines download raw bytes

1import{Controller}from"@hotwired/stimulus";import{animate}from"motion";export default class extends Controller{static targets=["track","list"];static values={speed:{type:Number,default:20},hoverSpeed:{type:Number,default:0},direction:{type:String,default:"left"},clones:{type:Number,default:2}};connect(){this.connected=!0,this.isHovering=!1,this.isVisible=!("IntersectionObserver"in window),this.contentSize=0,this.lastContentSize=0,this.animation=null,this.setupFrameId=null,this.motionPreference=window.matchMedia("(prefers-reduced-motion: reduce)"),this.handleMotionPreferenceChange=this.handleMotionPreferenceChange.bind(this),this.handleVisibilityChange=this.handleVisibilityChange.bind(this),this.motionPreference.addEventListener?this.motionPreference.addEventListener("change",this.handleMotionPreferenceChange):this.motionPreference.addListener(this.handleMotionPreferenceChange),document.addEventListener("visibilitychange",this.handleVisibilityChange),this.setupMarquee(),"ResizeObserver"in window?(this.resizeObserver=new ResizeObserver(()=>this.handleResize()),this.resizeObserver.observe(this.listTarget)):window.addEventListener("resize",this.handleVisibilityChange),"IntersectionObserver"in window&&(this.visibilityObserver=new IntersectionObserver(([e])=>{this.isVisible=e.isIntersecting,this.applyPlaybackSpeed()},{rootMargin:"120px"}),this.visibilityObserver.observe(this.element))}disconnect(){this.connected=!1,this.stopAnimation(),this.removeClones(),this.resizeObserver?.disconnect(),this.visibilityObserver?.disconnect(),this.motionPreference?.removeEventListener?this.motionPreference.removeEventListener("change",this.handleMotionPreferenceChange):this.motionPreference?.removeListener(this.handleMotionPreferenceChange),document.removeEventListener("visibilitychange",this.handleVisibilityChange),window.removeEventListener("resize",this.handleVisibilityChange)}setupMarquee(e=0){this.stopAnimation(),this.removeClones(),this.listTarget.style.flexShrink="0";for(let e=0;e<this.clonesValue;e++){const e=this.listTarget.cloneNode(!0);e.setAttribute("aria-hidden","true"),e.classList.add("marquee-clone"),e.style.flexShrink="0",e.removeAttribute("data-marquee-target"),this.trackTarget.appendChild(e)}this.trackTarget.style.display="flex",this.trackTarget.style.flexWrap="nowrap",this.trackTarget.style.flexDirection=this.isVerticalDirection()?"column":"row",this.injectBaseStyles(),this.setupFrameId=requestAnimationFrame(()=>{this.setupFrameId=null;const t=this.measureContentSize();0!==t&&(this.contentSize=t,this.lastContentSize=t,this.motionPreference.matches?this.trackTarget.style.transform="none":this.startAnimation(e))})}startAnimation(e=0){const t="left"===this.directionValue||"up"===this.directionValue,i=t?0:-this.contentSize,n=t?-this.contentSize:0,s=this.transformForOffset(i),a=this.transformForOffset(n),r=Math.max(.001,this.speedValue);this.animation=animate(this.trackTarget,{transform:[s,a]},{duration:r,ease:"linear",repeat:1/0}),this.animation.time=Math.min(1,Math.max(0,e))*r,this.applyPlaybackSpeed()}stopAnimation(){null!==this.setupFrameId&&(cancelAnimationFrame(this.setupFrameId),this.setupFrameId=null),this.animation?.cancel(),this.animation=null}transformForOffset(e){return this.isVerticalDirection()?`translate3d(0, ${e}px, 0)`:`translate3d(${e}px, 0, 0)`}targetPlaybackSpeed(){return!this.isVisible||document.hidden?0:this.isHovering?0===this.hoverSpeedValue?0:Math.max(.001,this.speedValue)/Math.max(.001,this.hoverSpeedValue):1}applyPlaybackSpeed(){if(!this.animation)return;const e=this.targetPlaybackSpeed(),t=this.animation.time;0!==e?(this.animation.speed=e,this.animation.play(),Number.isFinite(t)&&(this.animation.time=t)):this.animation.pause()}isVerticalDirection(){return"up"===this.directionValue||"down"===this.directionValue}measureContentSize(){if(!this.hasListTarget)return 0;const e=this.measureSeamGap();this.trackTarget.style.gap=`${e}px`;return(this.isVerticalDirection()?this.listTarget.offsetHeight:this.listTarget.offsetWidth)+e}measureSeamGap(){const e=getComputedStyle(this.listTarget),t=this.isVerticalDirection()?e.rowGap:e.columnGap,i=Number.parseFloat(t);return Number.isFinite(i)?i:0}pauseAnimation(){this.isHovering=!0,this.applyPlaybackSpeed()}resumeAnimation(){this.isHovering=!1,this.applyPlaybackSpeed()}restartAnimation(){if(!this.hasTrackTarget||!this.hasListTarget)return;const e=this.animation&&this.animation.duration>0?this.animation.time%this.animation.duration/this.animation.duration:0;this.setupMarquee(e)}removeClones(){this.hasTrackTarget&&this.trackTarget.querySelectorAll(".marquee-clone").forEach(e
1=>e.remove())}handleResize(){if(!this.hasListTarget)return;const e=this.measureContentSize();0===e||Math.abs(e-this.lastContentSize)<.5||(this.lastContentSize=e,this.restartAnimation())}handleMotionPreferenceChange(){this.restartAnimation()}handleVisibilityChange(){this.resizeObserver||this.handleResize(),this.applyPlaybackSpeed()}injectBaseStyles(){const e="marquee-base-styles";if(document.getElementById(e))return;const t=document.createElement("style");t.id=e,t.textContent='\n      [data-marquee-target="track"] {\n        will-change: transform;\n        backface-visibility: hidden;\n      }\n\n      [data-marquee-target="list"],\n      .marquee-clone {\n        flex-shrink: 0;\n        min-width: max-content;\n        min-height: max-content;\n      }\n    ',document.head.appendChild(t)}speedValueChanged(){this.connected&&this.hasTrackTarget&&this.restartAnimation()}hoverSpeedValueChanged(){this.connected&&this.hasTrackTarget&&this.isHovering&&this.applyPlaybackSpeed()}directionValueChanged(){this.connected&&this.hasTrackTarget&&this.restartAnimation()}clonesValueChanged(){this.connected&&this.hasTrackTarget&&this.restartAnimation()}}

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.