1/*** Asset: asset/js/image-position.js ***/ 2 3(function(window,document){"use strict";function clamp(value,min,max){return Math.min(max,Math.max(min,value));} 4function focalFromPosition(position){return(1-position)/2;} 5function positionFromFocal(focal){return 1-(focal*2);} 6function layerOffset(frameSize,renderedSize,position){const minOffset=Math.min(0,frameSize-renderedSize);return clamp((frameSize/2)- 7(focalFromPosition(position)*renderedSize),minOffset,0);} 8function positionFromLayerOffset(frameSize,renderedSize,offset){if(renderedSize<=frameSize){return 0;} 9return clamp(positionFromFocal(((frameSize/2)-offset)/renderedSize),-1,1);} 10function cssUrlValue(value){if(!value){return"";} 11const start=value.indexOf("url(");if(start===-1){return"";} 12let i=start+4;while(value[i]===" "){i++;} 13const quote=value[i];if(quote==='"'||quote==="'"){let out="";for(i=i+1;i<value.length;i++){const ch=value[i];if(ch==="\\"&&i+1<value.length){out+=value[++i];continue;} 14if(ch===quote){break;} 15out+=ch;} 16return out;} 17const end=value.indexOf(")",i);return value.slice(i,end===-1?value.length:end).trim();} 18function sameImageUrl(a,b){if(!a||!b){return false;} 19if(a===b){return true;} 20try{return new URL(a,document.baseURI).href===new URL(b,document.baseURI).href;}catch(e){return false;}} 21function styleImageUrl(frame){if(!frame){return"";}
22if(frame.style.backgroundImage&&frame.style.backgroundImage!=="none"){return cssUrlValue(frame.style.backgroundImage);} 23if(frame.style.background){return cssUrlValue(frame.style.background);} 24return"";} 25function getImageUrl(frame){if(!frame){return"";} 26if(frame.dataset.src){return frame.dataset.src;} 27return styleImageUrl(frame);} 28function isPlaceholderVisible(container){const placeholder=container.querySelector('[data-role="placeholder"]');if(!placeholder){return false;} 29return placeholder.style.display!=="none";} 30function isPlaceholderImage(url){return!url||url.indexOf('staff-placeholder.jpg')!==-1;} 31function computeImageLayerStyle(options){const rectWidth=options.rectWidth;const rectHeight=options.rectHeight;const naturalWidth=options.naturalWidth;const naturalHeight=options.naturalHeight;const zoom=options.zoom;const posX=options.posX;const posY=options.posY;const imageUrl=options.imageUrl;const coverScale=Math.max(rectWidth/naturalWidth,rectHeight/naturalHeight);const scale=coverScale*(zoom/100);const renderedWidth=naturalWidth*scale;const renderedHeight=naturalHeight*scale;const offsetX=layerOffset(rectWidth,renderedWidth,posX);const offsetY=layerOffset(rectHeight,renderedHeight,posY);return{position:"absolute",backgroundRepeat:"no-repeat",backgroundPosition:"center",backgroundSize:"100% 100%",willChange:"transform",width:`${renderedWidth}px`,height:`${renderedHeight}px`,left:`${offsetX}px`,top:`${offsetY}px`,backgroundImage:imageUrl?`url("${imageUrl}")`:"none",};} 32class CSImageEditor{constructor(container){this.container=container;this.frame=container.querySelector('[data-role="frame"]');this.imageLayer=container.querySelector('[data-role="image"]');this.inputs={zoom:container.querySelector('[data-input="zoom"]'),positionX:container.querySelector('[data-input="position-x"]'),positionY:container.querySelector('[data-input="position-y"]'),changed:container.querySelector('[data-input="changed"]'),};if(!this.inputs.changed&&this.inputs.zoom&&this.inputs.zoom.parentNode){const changed=document.createElement("input");changed.type="hidden";changed.name="img_position_changed";changed.value="0";changed.setAttribute("data-input","changed");this.inputs.zoom.parentNode.insertBefore(changed,this.inputs.zoom.nextSibling);this.inputs.changed=changed;} 33this.controls={zoomSlider:container.querySelector('[data-action="zoom-slider"]'),zoomDisplay:container.querySelector('[data-role="zoom-display"]'),moveableIcons:container.querySelector('[data-role="moveable-icons"]'),zoomTool:container.querySelector('[data-role="zoom-tool"]'),placeholder:container.querySelector('[data-role="placeholder"]'),resetBtn:container.querySelector('[data-action="reset"]'),};this.state={zoom:parseFloat(this.inputs.zoom?.value)||100,position:{x:parseFloat(this.inputs.positionX?.value)||0,y:parseFloat(this.inputs.positionY?.value)||0,},};this.natural={width:0,height:0,};this.dragging=false;this.start={x:0,y:0,};this._atDefaultState=true;this.init();} 34init(){if(!this.frame){return;} 35if(!this.imageLayer){return;} 36this.prepareFrame();this.loadImage(()=>{this.render();this.updateUI();});this.bind();this.watchFrame();} 37prepareFrame(){this.frame.style.overflow="hidden";this.frame.style.position="relative";this.frame.style.cursor="grab";this.frame.setAttribute("data-slideout-ignore","");if(!getImageUrl(this.frame)){this.frame.style.backgroundImage="none";}} 38loadImage(callback){const imageUrl=getImageUrl(this.frame);if(!imageUrl){this.updateUI();return;} 39const img=new Image();img.onload=()=>{this.natural.width=img.naturalWidth;this.natural.height=img.naturalHeight;requestAnimationFrame(()=>{this.render();this.updateUI();if(callback){callback();}});};img.src=imageUrl;} 40bind(){this.frame.addEventListener("mousedown",this.onDragStart.bind(this));document.addEventListener("mousemove",this.onDragMove.bind(this));document.addEventListener("mouseup",this.onDragEnd.bind(this));this.frame.addEventListener("touchstart",this.onTouchStart.bind(this),{passive:false});document.addEventListener("touchmove",this.onTouchMove.bind(this),{passive:false});document.addEventListener("touchend",this.onDragEnd.bind(this));this.container.addEventListener("click",this.onActionClick.bind(this));this.container.addEventListener("input",this.onInputChange.bind(this));} 41onActionClick(e){const actionEl=e.target.closest("[data-action]");if(!actionEl){return;} 42if(actionEl.classList.contains("disabled")){return;} 43const action=actionEl.dataset.action;switch(action){case"zoom-in":this.zoomChange(10);break;case"zoom-out":this.zoomChange(-10);break;case"reset":this.reset();break;}} 44onInputChange(e){const action=e.target.dataset.action;if(action==="zoom-slider"){this.zoomSlider(e.target.value);}} 45getCoverScale(){const rect={width:this.frame.offsetWidth,height:this.frame.offsetHeight,};return Math.max(rect.width/this.natural.width,rect.height/this.natural.height);} 46getRenderedSize(){const scale=this.getCoverScale()*(this.state.zoom/100);return{width:this.natural.width*scale,height:this.natural.height*scale,};} 47applyPreviewShape(){const box=this.container;if(!box||!this.frame||!this.frame.id){return;} 48const parts=this.frame.id.match(/^(.*)Edit(.*)$/);if(!parts){return;} 49const preview=document.getElementById(parts[1]+parts[2]);if(!preview){return;} 50const previewWidth=preview.offsetWidth;const previewHeight=preview.offsetHeight;if(!previewWidth||!previewHeight){return;} 51const width=box.offsetWidth;if(!width){return;} 52const target=Math.round(width*(previewHeight/previewWidth));if(target<40||target>1200){return;} 53if(Math.abs(box.offsetHeight-target)<1){return;} 54box.style.alignSelf="flex-start";box.style.aspectRatio="auto";box.style.height=target+"px";}
55render(){if(!this.natural.width||!this.natural.height){return;} 56this.applyPreviewShape();const rect={width:this.frame.offsetWidth,height:this.frame.offsetHeight,};if(!rect.width||!rect.height){return;} 57const imageUrl=getImageUrl(this.frame);const style=computeImageLayerStyle({rectWidth:rect.width,rectHeight:rect.height,naturalWidth:this.natural.width,naturalHeight:this.natural.height,zoom:this.state.zoom,posX:this.state.position.x,posY:this.state.position.y,imageUrl,});this.imageLayer.style.position=style.position;this.imageLayer.style.backgroundRepeat=style.backgroundRepeat;this.imageLayer.style.backgroundPosition=style.backgroundPosition;this.imageLayer.style.backgroundSize=style.backgroundSize;this.imageLayer.style.willChange=style.willChange;this.imageLayer.style.width=style.width;this.imageLayer.style.height=style.height;this.imageLayer.style.left=style.left;this.imageLayer.style.top=style.top;this.imageLayer.style.backgroundImage=style.backgroundImage;this.imageLayer.style.transition="none";this.frame.classList.toggle("cs-layer-painted",!!imageUrl);} 58save(){if(this.inputs.zoom){this.inputs.zoom.value=this.state.zoom;} 59if(this.inputs.positionX){this.inputs.positionX.value=this.state.position.x;} 60if(this.inputs.positionY){this.inputs.positionY.value=this.state.position.y;} 61if(this.controls.zoomSlider){this.controls.zoomSlider.value=this.state.zoom;} 62if(this.controls.zoomDisplay){this.controls.zoomDisplay.innerText=this.state.zoom+"%";} 63if(this._atDefaultState&&this.controls.resetBtn){this._atDefaultState=false;this.controls.resetBtn.classList.remove("disabled");}} 64markChanged(){if(this.inputs.changed){this.inputs.changed.value="1";}} 65clearChanged(){if(this.inputs.changed){this.inputs.changed.value="0";}} 66updateResetBtn(forceEval){if(!this.controls.resetBtn){return;} 67if(forceEval){this._atDefaultState=this.state.zoom===100&&this.state.position.x===0&&this.state.position.y===0;} 68if(this._atDefaultState){this.controls.resetBtn.classList.add("disabled");}else{this.controls.resetBtn.classList.remove("disabled");}} 69updateUI(){const imageUrl=getImageUrl(this.frame);const hasImage=!!imageUrl;const isStaff=this.container.dataset.editorType==="staff";const hasRealImage=hasImage&&!(isStaff&&isPlaceholderImage(imageUrl));const imageLayerHasBg=!!(this.imageLayer&&this.imageLayer.style.backgroundImage&&this.imageLayer.style.backgroundImage!=="none");const showControls=hasRealImage&&imageLayerHasBg;if(this.controls.moveableIcons){this.controls.moveableIcons.style.display=hasImage?"":"none";} 70if(this.imageLayer){this.imageLayer.style.display=imageLayerHasBg?"":"none";} 71if(this.controls.resetBtn){this.controls.resetBtn.style.display=showControls?"":"none";} 72if(this.controls.zoomTool){this.controls.zoomTool.style.display=showControls?"":"none";} 73if(this.controls.placeholder){this.controls.placeholder.style.display=imageLayerHasBg?"none":"flex";} 74if(this.controls.zoomSlider){this.controls.zoomSlider.value=this.state.zoom;} 75if(this.controls.zoomDisplay){this.controls.zoomDisplay.innerText=this.state.zoom+"%";} 76this.updateResetBtn(true);} 77onDragStart(e){if(isPlaceholderVisible(this.container)){return;} 78if(!this.natural.width||!this.natural.height){return;} 79this.dragging=true;this.start.x=e.clientX;this.start.y=e.clientY;this.frame.style.cursor="grabbing";e.preventDefault();} 80onDragMove(e){if(!this.dragging){return;} 81const deltaX=e.clientX- 82this.start.x;const deltaY=e.clientY- 83this.start.y;this.start.x=e.clientX;this.start.y=e.clientY;const frame={width:this.frame.offsetWidth,height:this.frame.offsetHeight,};const rendered=this.getRenderedSize();this.state.position.x=positionFromLayerOffset(frame.width,rendered.width,layerOffset(frame.width,rendered.width,this.state.position.x)+deltaX);this.state.position.y=positionFromLayerOffset(frame.height,rendered.height,layerOffset(frame.height,rendered.height,this.state.position.y)+deltaY);this.render();this.save();if(deltaX||deltaY){this.markChanged();}} 84onDragEnd(){this.dragging=false;this.frame.style.cursor="grab";} 85onTouchStart(e){const touch=e.touches[0];this.onDragStart({clientX:touch.clientX,clientY:touch.clientY,preventDefault(){},});e.preventDefault();e.stopPropagation();} 86onTouchMove(e){if(!this.dragging){return;} 87const touch=e.touches[0];this.onDragMove({clientX:touch.clientX,clientY:touch.clientY,});e.preventDefault();e.stopPropagation();} 88zoomChange(delta){this.state.zoom=clamp(this.state.zoom+delta,100,200);this.render();this.save();this.markChanged();} 89zoomSlider(value){this.state.zoom=clamp(parseFloat(value),100,200);this.render();this.save();this.markChanged();} 90reset(){this.state.position.x=0;this.state.position.y=0;this.state.zoom=100;this.render();this.save();this._atDefaultState=true;this.updateResetBtn();this.markChanged();} 91setImage(url){if(!url||!this.frame){return;} 92this.frame.dataset.src=url;this._lastObservedSrc=url;this.state.position.x=0;this.state.position.y=0;this.state.zoom=100;this._atDefaultState=true;if(this.inputs.zoom)this.inputs.zoom.value=100;if(this.inputs.positionX)this.inputs.positionX.value=0;if(this.inputs.positionY)this.inputs.positionY.value=0;this.updateUI();this.loadImage(null);} 93clearImage(){if(!this.frame){return;} 94this.frame.dataset.src="";this.frame.style.backgroundImage="";this.frame.style.background="";if(this.imageLayer){this.imageLayer.style.backgroundImage="";} 95this.frame.classList.remove("cs-layer-painted");this.state.position.x=0;this.state.position.y=0;this.state.zoom=100;this._atDefaultState=true;this.natural.width=0;this.natural.height=0;this._lastObservedSrc="";this._lastStyleSrc="";if(this.inputs.zoom)this.inputs.zoom.value=100;if(this.inputs.positionX)this.inputs.positionX.value=0;if(this.inputs.positionY)this.inputs.positionY.value=0;this.prepareFrame();this.updateUI();} 96watchFrame(){if(!this.frame||this._observer){return;} 97this._observer=new MutationObserver((mutations)=>{for(const mutation of mutations){if(mutation.attributeName==="data-src"){const newUrl=this.frame.dataset.src;if(newUrl&&!sameImageUrl(newUrl,this._lastObservedSrc)){this._lastObservedSrc=newUrl;this.setImage(newUrl);this.markChanged();} 98break;} 99if(mutation.attributeName==="style"){const styleUrl=styleImageUrl(this.frame);if(styleUrl&&styleUrl!==this._lastStyleSrc){this._lastStyleSrc=styleUrl;if(!this.frame.dataset.src&&(sameImageUrl(styleUrl,this._lastObservedSrc)||sameImageUrl(styleUrl,styleImageUrl(this.imageLayer)))){this.frame.dataset.src=this._lastObservedSrc||styleUrl;}else if(!sameImageUrl(styleUrl,this.frame.dataset.src)){this._lastObservedSrc=styleUrl;this.frame.dataset.src=styleUrl;this.setImage(styleUrl);}} 100break;}}});this._observer.observe(this.frame,{attributes:true,attributeFilter:["data-src","style"]});this._lastObservedSrc=this.frame.dataset.src||getImageUrl(this.frame)||"";this._lastStyleSrc=styleImageUrl(this.frame);if(typeof ResizeObserver==="undefined"||this._sizeObserver){return;} 101this._sizeObserver=new ResizeObserver(()=>{const width=this.frame.offsetWidth;const height=this.frame.offsetHeight;if(!width||!height){this._lastFrameWidth=0;this._lastFrameHeight=0;return;} 102if(width===this._lastFrameWidth&&height===this._lastFrameHeight){return;} 103this._lastFrameWidth=width;this._lastFrameHeight=height;this.render();this.updateUI();});this._sizeObserver.observe(this.frame);} 104reinit(){this.updateUI();const imageUrl=getImageUrl(this.frame);if(!imageUrl){return;} 105const img=new Image();img.onload=()=>
105{this.natural.width=img.naturalWidth;this.natural.height=img.naturalHeight;requestAnimationFrame(()=>{this.render();this.updateUI();});};img.src=imageUrl;} 106refresh(){const imageUrl=getImageUrl(this.frame);if(!imageUrl){return;} 107const img=new Image();img.onload=()=>{this.natural.width=img.naturalWidth;this.natural.height=img.naturalHeight;this.render();this.updateUI();};img.src=imageUrl;}} 108window.CSImageEditors=window.CSImageEditors||[];window.getCSImageEditorByFrameId=function(frameId){return(window.CSImageEditors.find((ed)=>ed.frame&&ed.frame.id===frameId)||null);};window.setCSImageEditorImage=function(frameId,url){const editor=window.getCSImageEditorByFrameId(frameId);if(editor){editor.setImage(url);editor.markChanged();}};window.clearCSImageEditor=function(frameId){const editor=window.getCSImageEditorByFrameId(frameId);if(!editor){return false;} 109editor.clearImage();return true;};window.initCSImageEditors=function(scope=document){const byAttr=Array.from(scope.querySelectorAll("[data-image-editor]"));const byClass=Array.from(scope.querySelectorAll(".profile-image-tool"));const containers=Array.from(new Set([...byAttr,...byClass]));containers.forEach((container)=>{if(container.dataset.csImageReady){return;} 110container.dataset.csImageReady="true";const editor=new CSImageEditor(container);window.CSImageEditors.push(editor);});};window.setCSImageEditorPosition=function(frameId,zoom,posX,posY){const editor=window.getCSImageEditorByFrameId(frameId);if(!editor){return false;} 111const parsedZoom=parseFloat(zoom);const parsedX=parseFloat(posX);const parsedY=parseFloat(posY);editor.state.zoom=clamp(isNaN(parsedZoom)?100:parsedZoom,100,200);editor.state.position.x=clamp(isNaN(parsedX)?0:parsedX,-1,1);editor.state.position.y=clamp(isNaN(parsedY)?0:parsedY,-1,1);editor.save();editor.render();editor.updateUI();editor.clearChanged();return true;};window.refreshCSImageEditors=function(scope=document){window.initCSImageEditors(scope);window.CSImageEditors=window.CSImageEditors.filter((editor)=>editor.frame&&document.contains(editor.frame));window.CSImageEditors.forEach((editor)=>{editor.refresh();});};window.initCSPreviewImages=function(scope=document){const containers=scope.querySelectorAll('.cs-preview-image');containers.forEach((container)=>{const layer=container.querySelector('.cs-preview-image-layer');if(!layer){return;} 112const image=container.dataset.image;if(!image){return;} 113const zoom=clamp(parseFloat(container.dataset.zoom)||100,100,200);const posX=clamp(parseFloat(container.dataset.posX)||0,-1,1);const posY=clamp(parseFloat(container.dataset.posY)||0,-1,1);const img=new Image();const apply=function(){if(container.dataset.image!==image){return;} 114const rect={width:container.offsetWidth,height:container.offsetHeight,};if(!rect.width||!rect.height){return;} 115const style=computeImageLayerStyle({rectWidth:rect.width,rectHeight:rect.height,naturalWidth:img.naturalWidth||img.width,naturalHeight:img.naturalHeight||img.height,zoom:zoom,posX:posX,posY:posY,imageUrl:image,});layer.style.position=style.position;layer.style.backgroundRepeat=style.backgroundRepeat;layer.style.backgroundPosition=style.backgroundPosition;layer.style.backgroundSize=style.backgroundSize;layer.style.willChange=style.willChange;layer.style.width=style.width;layer.style.height=style.height;layer.style.left=style.left;layer.style.top=style.top;layer.style.backgroundImage=style.backgroundImage;layer.style.transition="none";container.classList.add("cs-layer-painted");};img.onload=apply;container._csApplyLatest=function(){if(img.complete){apply();}};if(typeof ResizeObserver!=="undefined"&&!container._csSizeObserver){let lastWidth=0;let lastHeight=0;container._csSizeObserver=new ResizeObserver(function(){const width=container.offsetWidth;const height=container.offsetHeight;if(!width||!height){lastWidth=0;lastHeight=0;return;} 116if(width===lastWidth&&height===lastHeight){return;} 117lastWidth=width;lastHeight=height;container._csApplyLatest();});container._csSizeObserver.observe(container);} 118img.src=image;if(img.complete){apply();}});} 119document.addEventListener("DOMContentLoaded",function(){initCSImageEditors(document);});document.addEventListener("shown.bs.modal",function(e){const modal=e.target;const hasEditor=modal.querySelector("[data-image-editor], .profile-image-tool");if(!hasEditor){return;} 120initCSImageEditors(modal);
120window.CSImageEditors.forEach(function(editor){if(modal.contains(editor.container)){editor.reinit();}});});let csPreviewResizeTimer=null;window.addEventListener("resize",function(){if(csPreviewResizeTimer){clearTimeout(csPreviewResizeTimer);} 121csPreviewResizeTimer=setTimeout(function(){initCSPreviewImages();},100);});initCSPreviewImages();})(window,document);
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.