juxtapose.min.js 17 KB

1234
  1. /* juxtapose - v1.2.1 - 2019-04-18
  2. * Copyright (c) 2019 Alex Duner and Northwestern University Knight Lab
  3. */
  4. (function(document,window){var juxtapose={sliders:[],OPTIMIZATION_ACCEPTED:1,OPTIMIZATION_WAS_CONSTRAINED:2};var flickr_key="d90fc2d1f4acc584e08b8eaea5bf4d6c";var FLICKR_SIZE_PREFERENCES=["Large","Medium"];function Graphic(properties,slider){var self=this;this.image=new Image;this.loaded=false;this.image.onload=function(){self.loaded=true;slider._onLoaded()};this.image.src=properties.src;this.image.alt=properties.alt||"";this.label=properties.label||false;this.credit=properties.credit||false}function FlickrGraphic(properties,slider){var self=this;this.image=new Image;this.loaded=false;this.image.onload=function(){self.loaded=true;slider._onLoaded()};this.flickrID=this.getFlickrID(properties.src);this.callFlickrAPI(this.flickrID,self);this.label=properties.label||false;this.credit=properties.credit||false}FlickrGraphic.prototype={getFlickrID:function(url){if(url.match(/flic.kr\/.+/i)){var encoded=url.split("/").slice(-1)[0];return base58Decode(encoded)}var idx=url.indexOf("flickr.com/photos/");var pos=idx+"flickr.com/photos/".length;var photo_info=url.substr(pos);if(photo_info.indexOf("/")==-1)return null;if(photo_info.indexOf("/")===0)photo_info=photo_info.substr(1);id=photo_info.split("/")[1];return id},callFlickrAPI:function(id,self){var url="https://api.flickr.com/services/rest/?method=flickr.photos.getSizes"+"&api_key="+flickr_key+"&photo_id="+id+"&format=json&nojsoncallback=1";var request=new XMLHttpRequest;request.open("GET",url,true);request.onload=function(){if(request.status>=200&&request.status<400){data=JSON.parse(request.responseText);var flickr_url=self.bestFlickrUrl(data.sizes.size);self.setFlickrImage(flickr_url)}else{console.error("There was an error getting the picture from Flickr")}};request.onerror=function(){console.error("There was an error getting the picture from Flickr")};request.send()},setFlickrImage:function(src){this.image.src=src},bestFlickrUrl:function(ary){var dict={};for(var i=0;i<ary.length;i++){dict[ary[i].label]=ary[i].source}for(var j=0;j<FLICKR_SIZE_PREFERENCES.length;j++){if(FLICKR_SIZE_PREFERENCES[j]in dict){return dict[FLICKR_SIZE_PREFERENCES[j]]}}return ary[0].source}};function getNaturalDimensions(DOMelement){if(DOMelement.naturalWidth&&DOMelement.naturalHeight){return{width:DOMelement.naturalWidth,height:DOMelement.naturalHeight}}var img=new Image;img.src=DOMelement.src;return{width:img.width,height:img.height}}function getImageDimensions(img){var dimensions={width:getNaturalDimensions(img).width,height:getNaturalDimensions(img).height,aspect:function(){return this.width/this.height}};return dimensions}function addClass(element,c){if(element.classList){element.classList.add(c)}else{element.className+=" "+c}}function removeClass(element,c){element.className=element.className.replace(/(\S+)\s*/g,function(w,match){if(match===c){return""}return w}).replace(/^\s+/,"")}function setText(element,text){if(document.body.textContent){element.textContent=text}else{element.innerText=text}}function getComputedWidthAndHeight(element){if(window.getComputedStyle){return{width:parseInt(getComputedStyle(element).width,10),height:parseInt(getComputedStyle(element).height,10)}}else{w=element.getBoundingClientRect().right-element.getBoundingClientRect().left;h=element.getBoundingClientRect().bottom-element.getBoundingClientRect().top;return{width:parseInt(w,10)||0,height:parseInt(h,10)||0}}}function viewport(){var e=window,a="inner";if(!("innerWidth"in window)){a="client";e=document.documentElement||document.body}return{width:e[a+"Width"],height:e[a+"Height"]}}function getPageX(e){var pageX;if(e.pageX){pageX=e.pageX}else if(e.touches){pageX=e.touches[0].pageX}else{pageX=e.clientX+document.body.scrollLeft+document.documentElement.scrollLeft}return pageX}function getPageY(e){var pageY;if(e.pageY){pageY=e.pageY}else if(e.touches){pageY=e.touches[0].pageY}else{pageY=e.clientY+document.body.scrollTop+document.documentElement.scrollTop}return pageY}function checkFlickr(url){if(url.match(/flic.kr\/.+/i)){return true}var idx=url.indexOf("flickr.com/photos/");if(idx==-1){return false}else{return true}}function base58Decode(encoded){var alphabet="123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ",base=alphabet.length;if(typeof encoded!=="string"){throw'"base58Decode" only accepts strings.'}var decoded=0;while(encoded){var alphabetPosition=alphabet.indexOf(encoded[0]);if(alphabetPosition<0){throw'"base58Decode" can\'t find "'+encoded[0]+'" in the alphabet: "'+alphabet+'"'}var powerOf=encoded.length-1;decoded+=alphabetPosition*Math.pow(base,powerOf);encoded=encoded.substring(1)}return decoded.toString()}function getLeftPercent(slider,input){if(typeof input==="string"||typeof input==="number"){leftPercent=parseInt(input,10)}else{var sliderRect=slider.getBoundingClientRect();var offset={top:sliderRect.top+document.body.scrollTop+document.documentElement.scrollTop,left:sliderRect.left+document.body.scrollLeft+document.documentElement.scrollLeft};var width=slider.offsetWidth;var pageX=getPageX(input);var relativeX=pageX-offset.left;leftPercent=relativeX/width*100}return leftPercent}function getTopPercent(slider,input){if(typeof input==="string"||typeof input==="number"){topPercent=parseInt(input,10)}else{var sliderRect=slider.getBoundingClientRect();var offset={top:sliderRect.top+document.body.scrollTop+document.documentElement.scrollTop,left:sliderRect.left+document.body.scrollLeft+document.documentElement.scrollLeft};var width=slider.offsetHeight;var pageY=getPageY(input);var relativeY=pageY-offset.top;topPercent=relativeY/width*100}return topPercent}var BOOLEAN_OPTIONS={animate:true,showLabels:true,showCredits:true,makeResponsive:true};function interpret_boolean(x){if(typeof x!="string"){return Boolean(x)}return!(x==="false"||x==="")}function JXSlider(selector,images,options){this.selector=selector;var i;this.options={animate:true,showLabels:true,showCredits:true,makeResponsive:true,startingPosition:"50%",mode:"horizontal",callback:null};for(i in this.options){if(i in options){if(i in BOOLEAN_OPTIONS){this.options[i]=interpret_boolean(options[i])}else{this.options[i]=options[i]}}}if(images.length==2){if(checkFlickr(images[0].src)){this.imgBefore=new FlickrGraphic(images[0],this)}else{this.imgBefore=new Graphic(images[0],this)}if(checkFlickr(images[1].src)){this.imgAfter=new FlickrGraphic(images[1],this)}else{this.imgAfter=new Graphic(images[1],this)}}else{console.warn("The images parameter takes two Image objects.")}if(this.imgBefore.credit||this.imgAfter.credit){this.options.showCredits=true}else{this.options.showCredits=false}}JXSlider.prototype={updateSlider:function(input,animate){var leftPercent,rightPercent;if(this.options.mode==="vertical"){leftPercent=getTopPercent(this.slider,input)}else{leftPercent=getLeftPercent(this.slider,input)}leftPercent=leftPercent.toFixed(2)+"%";leftPercentNum=parseFloat(leftPercent);rightPercent=100-leftPercentNum+"%";if(leftPercentNum>0&&leftPercentNum<100){removeClass(this.handle,"transition");removeClass(this.rightImage,"transition");removeClass(this.leftImage,"transition");if(this.options.animate&&animate){addClass(this.handle,"transition");addClass(this.leftImage,"transition");addClass(this.rightImage,"transition")}if(this.options.mode==="vertical"){this.handle.style.top=leftPercent;this.leftImage.style.height=leftPercent;this.rightImage.style.height=rightPercent}else{this.handle.style.left=leftPercent;this.leftImage.style.width=leftPercent;this.rightImage.style.width=rightPercent}this.sliderPosition=leftPercent}},getPosition:function(){return this.sliderPosition},displayLabel:function(element,labelText){label=document.createElement("div");label.className="jx-label";label.setAttribute("tabindex",0);setText(label,labelText);element.appendChild(label)},displayCredits:function(){credit=document.createElement("div");credit.className="jx-credit";text="<em>Photo Credits:</em>";if(this.imgBefore.credit){text+=" <em>Before</em> "+this.imgBefore.credit}if(this.imgAfter.credit){text+=" <em>After</em> "+this.imgAfter.credit}credit.innerHTML=text;this.wrapper.appendChild(credit)},setStartingPosition:function(s){this.options.startingPosition=s},checkImages:function(){if(getImageDimensions(this.imgBefore.image).aspect()==getImageDimensions(this.imgAfter.image).aspect()){return true}else{return false}},calculateDims:function(width,height){var ratio=getImageDimensions(this.imgBefore.image).aspect();if(width){height=width/ratio}else if(height){width=height*ratio}return{width:width,height:height,ratio:ratio}},responsivizeIframe:function(dims){if(dims.height<window.innerHeight){if(dims.ratio>=1){this.wrapper.style.paddingTop=parseInt((window.innerHeight-dims.height)/2)+"px"}}else if(dims.height>window.innerHeight){dims=this.calculateDims(0,window.innerHeight);this.wrapper.style.paddingLeft=parseInt((window.innerWidth-dims.width)/2)+"px"}if(this.options.showCredits){dims.height-=13}return dims},setWrapperDimensions:function(){var wrapperWidth=getComputedWidthAndHeight(this.wrapper).width;var wrapperHeight=getComputedWidthAndHeight(this.wrapper).height;var dims=this.calculateDims(wrapperWidth,wrapperHeight);if(window.location!==window.parent.location&&!this.options.makeResponsive){dims=this.responsivizeIframe(dims)}this.wrapper.style.height=parseInt(dims.height)+"px";this.wrapper.style.width=parseInt(dims.width)+"px"},optimizeWrapper:function(maxWidth){var result=juxtapose.OPTIMIZATION_ACCEPTED;if(this.imgBefore.image.naturalWidth>=maxWidth&&this.imgAfter.image.naturalWidth>=maxWidth){this.wrapper.style.width=maxWidth+"px";result=juxtapose.OPTIMIZATION_WAS_CONSTRAINED}else if(this.imgAfter.image.naturalWidth<maxWidth){this.wrapper.style.width=this.imgAfter.image.naturalWidth+"px"}else{this.wrapper.style.width=this.imgBefore.image.naturalWidth+"px"}this.setWrapperDimensions();return result},_onLoaded:function(){if(this.imgBefore&&this.imgBefore.loaded===true&&this.imgAfter&&this.imgAfter.loaded===true){this.wrapper=document.querySelector(this.selector);addClass(this.wrapper,"juxtapose");this.wrapper.style.width=getNaturalDimensions(this.imgBefore.image).width;this.setWrapperDimensions();this.slider=document.createElement("div");this.slider.className="jx-slider";this.wrapper.appendChild(this.slider);if(this.options.mode!="horizontal"){addClass(this.slider,this.options.mode)}this.handle=document.createElement("div");this.handle.className="jx-handle";this.rightImage=document.createElement("div");this.rightImage.className="jx-image jx-right";this.rightImage.appendChild(this.imgAfter.image);this.leftImage=document.createElement("div");this.leftImage.className="jx-image jx-left";this.leftImage.appendChild(this.imgBefore.image);this.labCredit=document.createElement("a");this.labCredit.setAttribute("href","http://juxtapose.knightlab.com");this.labCredit.setAttribute("target","_blank");this.labCredit.className="jx-knightlab";this.labLogo=document.createElement("div");this.labLogo.className="knightlab-logo";this.labCredit.appendChild(this.labLogo);this.projectName=document.createElement("span");this.projectName.className="juxtapose-name";setText(this.projectName,"JuxtaposeJS");this.labCredit.appendChild(this.projectName);this.slider.appendChild(this.handle);this.slider.appendChild(this.leftImage);this.slider.appendChild(this.rightImage);this.slider.appendChild(this.labCredit);this.leftArrow=document.createElement("div");this.rightArrow=document.createElement("div");this.control=document.createElement("div");this.controller=document.createElement("div");this.leftArrow.className="jx-arrow jx-left";this.rightArrow.className="jx-arrow jx-right";this.control.className="jx-control";this.controller.className="jx-controller";this.controller.setAttribute("tabindex",0);this.controller.setAttribute("role","slider");this.controller.setAttribute("aria-valuenow",50);this.controller.setAttribute("aria-valuemin",0);this.controller.setAttribute("aria-valuemax",100);this.handle.appendChild(this.leftArrow);this.handle.appendChild(this.control);this.handle.appendChild(this.rightArrow);this.control.appendChild(this.controller);this._init()}},_init:function(){if(this.checkImages()===false){console.warn(this,"Check that the two images have the same aspect ratio for the slider to work correctly.")}this.updateSlider(this.options.startingPosition,false);if(this.options.showLabels===true){if(this.imgBefore.label){this.displayLabel(this.leftImage,this.imgBefore.label)}if(this.imgAfter.label){this.displayLabel(this.rightImage,this.imgAfter.label)}}if(this.options.showCredits===true){this.displayCredits()}var self=this;window.addEventListener("resize",function(){self.setWrapperDimensions()});this.slider.addEventListener("mousedown",function(e){e=e||window.event;e.preventDefault();self.updateSlider(e,true);animate=true;this.addEventListener("mousemove",function(e){e=e||window.event;e.preventDefault();if(animate){self.updateSlider(e,false)}});this.addEventListener("mouseup",function(e){e=e||window.event;e.preventDefault();e.stopPropagation();this.removeEventListener("mouseup",arguments.callee);animate=false})});this.slider.addEventListener("touchstart",function(e){e=e||window.event;e.preventDefault();e.stopPropagation();self.updateSlider(e,true);this.addEventListener("touchmove",function(e){e=e||window.event;e.preventDefault();e.stopPropagation();self.updateSlider(event,false)})});this.handle.addEventListener("keydown",function(e){e=e||window.event;var key=e.which||e.keyCode;var ariaValue=parseFloat(this.style.left);if(key==37){ariaValue=ariaValue-1;var leftStart=parseFloat(this.style.left)-1;self.updateSlider(leftStart,false);self.controller.setAttribute("aria-valuenow",ariaValue)}if(key==39){ariaValue=ariaValue+1;var rightStart=parseFloat(this.style.left)+1;self.updateSlider(rightStart,false);self.controller.setAttribute("aria-valuenow",ariaValue)}});this.leftImage.addEventListener("keydown",function(event){var key=event.which||event.keyCode;if(key==13||key==32){self.updateSlider("90%",true);self.controller.setAttribute("aria-valuenow",90)}});this.rightImage.addEventListener("keydown",function(event){var key=event.which||event.keyCode;if(key==13||key==32){self.updateSlider("10%",true);self.controller.setAttribute("aria-valuenow",10)}});juxtapose.sliders.push(this);if(this.options.callback&&typeof this.options.callback=="function"){this.options.callback(this)}}};juxtapose.makeSlider=function(element,idx){if(typeof idx=="undefined"){idx=juxtapose.sliders.length}var w=element;var images=w.querySelectorAll("img");var options={};if(w.getAttribute("data-animate")){options.animate=w.getAttribute("data-animate")}if(w.getAttribute("data-showlabels")){options.showLabels=w.getAttribute("data-showlabels")}if(w.getAttribute("data-showcredits")){options.showCredits=w.getAttribute("data-showcredits")}if(w.getAttribute("data-startingposition")){options.startingPosition=w.getAttribute("data-startingposition")}if(w.getAttribute("data-mode")){options.mode=w.getAttribute("data-mode")}if(w.getAttribute("data-makeresponsive")){options.mode=w.getAttribute("data-makeresponsive")}specificClass="juxtapose-"+idx;addClass(element,specificClass);selector="."+specificClass;if(w.innerHTML){w.innerHTML=""}else{w.innerText=""}slider=new juxtapose.JXSlider(selector,[{src:images[0].src,label:images[0].getAttribute("data-label"),credit:images[0].getAttribute("data-credit"),alt:images[0].alt},{src:images[1].src,label:images[1].getAttribute("data-label"),credit:images[1].getAttribute("data-credit"),alt:images[1].alt}],options)};juxtapose.scanPage=function(){var elements=document.querySelectorAll(".juxtapose");for(var i=0;i<elements.length;i++){juxtapose.makeSlider(elements[i],i)}};juxtapose.JXSlider=JXSlider;window.juxtapose=juxtapose;juxtapose.scanPage()})(document,window);!window.addEventListener&&function(WindowPrototype,DocumentPrototype,ElementPrototype,addEventListener,removeEventListener,dispatchEvent,registry){WindowPrototype[addEventListener]=DocumentPrototype[addEventListener]=ElementPrototype[addEventListener]=function(type,listener){var target=this;registry.unshift([target,type,listener,function(event){event.currentTarget=target;event.preventDefault=function(){event.returnValue=false};event.stopPropagation=function(){event.cancelBubble=true};event.target=event.srcElement||target;listener.call(target,event)}]);this.attachEvent("on"+type,registry[0][3])};WindowPrototype[removeEventListener]=DocumentPrototype[removeEventListener]=ElementPrototype[removeEventListener]=function(type,listener){for(var index=0,register;register=registry[index];++index){if(register[0]==this&&register[1]==type&&register[2]==listener){return this.detachEvent("on"+type,registry.splice(index,1)[0][3])}}};WindowPrototype[dispatchEvent]=DocumentPrototype[dispatchEvent]=ElementPrototype[dispatchEvent]=function(eventObject){return this.fireEvent("on"+eventObject.type,eventObject)}}(Window.prototype,HTMLDocument.prototype,Element.prototype,"addEventListener","removeEventListener","dispatchEvent",[]);