Web slideshow in JavaScript

Posted by: Xav in Untagged  on

Introduction

C'est moi, Xav. Let's take a break from .NET for a little while, and try out some web design instead. When you're making a site, especially a personal site, you often need to display multiple pictures. However, we need to choose the best way to make them, to ensure both compatibility and appearance meet the standards.

In the old days of the web, slideshows were boring. They were simply a bunch of images on a page. Does the job, but not well. This was accomplished by using an  tag, perhaps within a of a table to line them up.

Then came along Flash. Everything looked very nice, but there were large problems:
  • Incompatibility with older browsers, or ones without Flash plugins.
  • Loading times.
  • Performance drains on computers.
  • Awful for SEO if the whole page was in Flash.

It was clearly a nice idea, but it had a few drawbacks. Lucklily, there is another approach - JavaScript.


The JS Way

JavaScript is a client-side, lightweight programming language. It is executed on the client (browser) side, not the server side, so it is a lot faster than a technology such as PHP or ASP, both of which are server-side languages.

JavaScript (JS for short) is implemented by using < script> tags. You can either put the JS code straight into the tag, or put it in a JS file (with the extension .js) and link to it. Either way, the browser runs the JS code when it finds the tag in the HTML code.

Note that browsers can be set to disable JavaScript, but most are not, so you shouldn't have many problems.


The Library

We could program a slideshow ourselves, but this is a lot of work and unnecessary. Fortunately, using the linking method described earlier, we can use JS file that other people have produced. These are known as libraries. There are many such libraries dedicated to producing slideshows, but I particularly like the one made by TripTracker.

http://slideshow.triptracker.net

The library is called slide.js. We should usually copy this file into our own website project folder, but in this case we should simply link to it from the TripTracker (TT) website, because TT regularly provide updates and fixes for the library, adding more functionality onto it (such as support for IE8).

So, open your HTML page where you want the slideshow to be. Add the following code:

XHTML


 

  1. <script type="text/javascript mce_tsrc=" http:="" slideshow.triptracker.net="" slide.js="">

Or, if you're in HTML:


 

  1. <script type="text/javascript src="http://slideshow.triptracker.net/slide.js"></script>

This code should be fairly familiar. We are telling the browser to reference the TripTracker Slideshow library, so that we can call its functions.

The "src" attribute specifies the location of the script (in this case, a library), which the browser will use if any specific object classes are referenced that are not part of the JavaScript DOM. Note that if we link it this way, any updates/fixes to the library will immediately take effect, but if for some reason the TripTracker website goes down, your scripts will not work. This is unlikely, though, as it has lots of uses, making it important for TT to maintain the site, and particular, the slideshow domain.

This is the library used for the TripTracker slideshow:


 

  1. </p><pre>/*
  2.  * (c) Copyright 2006, Klika, all rights reserved.
  3.  *
  4.  * This code is the property of Klika d.o.o. The code
  5.  * may not be included in, invoked from, or otherwise
  6.  * used in any software, service, device, or process
  7.  * which is sold, exchanged for profit, or for which
  8.  * a license, subscription, or royalty fee is charged.
  9.  *
  10.  * Permission is granted to use this code for personal,
  11.  * educational, research, or commercial purposes, provided
  12.  * this notice is included, and provided this code is not
  13.  * used as described in the above paragraph.
  14.  *
  15.  * This code may not be modified without express
  16.  * permission of Klika. You may not delete, disable, or in
  17.  * any manner alter distinctive brand features rendered
  18.  * by the code. The use of this code in derivative work is
  19.  * permitted, provided that the code and this notice are
  20.  * included in full, and provided that the code is used in
  21.  * accordance with these terms.
  22.  *
  23.  * Email: info at triptracker.net
  24.  * Web:   http://slideshow.triptracker.net
  25.  */
  26.  
  27. var MESSAGES = {
  28.   "format.date":                     "MM/dd/yyyy",
  29.   "format.time":                     "h:mm a",
  30.  
  31.   "photoviewer.toolbar.first":       "Go to Start (Home)",
  32.   "photoviewer.toolbar.prev":        "Previous Photo (Left arrow)",
  33.   "photoviewer.toolbar.slideShow":   "Start/Pause Slide Show (Space)",
  34.   "photoviewer.toolbar.next":        "Next Photo (Right arrow)",
  35.   "photoviewer.toolbar.last":        "Go to End (End)",
  36.   "photoviewer.toolbar.email":       "Email Photo",
  37.   "photoviewer.toolbar.permalink":   "Link to Photo",
  38.   "photoviewer.toolbar.close":       "Close (Esc)",
  39.   "photoviewer.email.subject.photo": "Photo",
  40.  
  41.   "gallery.nophotos":                "No photos",
  42.   "gallery.thumbs.start":            "Start",
  43.   "gallery.thumbs.end":              "End",
  44.   "gallery.toolbar.first":           "First Photo",
  45.   "gallery.toolbar.prev":            "Previous Photo",
  46.   "gallery.toolbar.view":            "View Photo",
  47.   "gallery.toolbar.next":            "Next Photo",
  48.   "gallery.toolbar.last":            "Last Photo",
  49.   "gallery.view.full":               "Maximize Window",
  50.   "gallery.view.photo":              "Show Photo Only",
  51.   "gallery.view.text":               "Show Description Only",
  52.   "gallery.view.close":              "Close Window"
  53. }
  54.  
  55. var agent=navigator.userAgent.toLowerCase()var IE=(agent.indexOf("msie")!=-1&&agent.indexOf("opera")==-1)var IE7=(agent.indexOf("msie 7")!=-1)var OPERA=(agent.indexOf("opera")!=-1)var SAFARI=(agent.indexOf("safari")!=-1)var FIREFOX=(agent.indexOf("gecko")!=-1)var STRICT_MODE=(document.compatMode=="CSS1Compat")var _DOMAIN=undefinedvar GALLERY_W=650var GALLERY_H=530if(USE_GOOGLE_MAPS==undefined){var USE_GOOGLE_MAPS=true}
  56. var USE_OLD_MAPS=!USE_GOOGLE_MAPSvar TESTING=falsevar log=getLogger()if(document.location.href.indexOf("#jslog")!=-1)
  57. log.enable()function Logger(){this.enable=loggerEnablethis.clear=loggerClearthis.log=loggerLogthis.debug=loggerDebugthis.info=loggerInfothis.error=loggerErrorvar console=undefinedtry{console=document.createElement("textarea")console.style.display="none"console.style.position="absolute"console.style.right="2px"console.style.bottom="2px"console.style.width="23em"console.style.height="40em"console.style.fontFamily="monospace"console.style.fontSize="9px"console.style.color="#000000"setOpacity(console,0.7)console.border="1px solid #808080"console.ondblclick=clearLogger}catch(e){}
  58. this.console=consolethis.enabled=falsethis.logTimeStart=getTimeMillis()}
  59. function getLogger(){var log=undefinedvar win=windowwhile(log==undefined){try{log=win.document.log}catch(e){break}
  60. if(win==win.parent)
  61. breakwin=win.parent}
  62. if(log==undefined){log=new Logger()document.log=log}
  63. return log}
  64. function clearLogger(){getLogger().clear()}
  65. function loggerEnable(){if(this.enabledthis.console==undefined)
  66. returnif(window.document.body!=undefined){window.document.body.appendChild(this.console)this.console.style.display=""this.enabled=true}}
  67. function loggerDebug(msg){this.log("DEBUG",msg)}
  68. function loggerInfo(msg){this.log("INFO",msg)}
  69. function loggerError(msg,e){this.log("ERROR",msg,e)}
  70. function loggerLog(level,msg,e){if(!this.enabledthis.console==undefined)
  71. returnvar millis=(getTimeMillis()-this.logTimeStart)+""while(millis.length<6)
  72. millis+=" "var m=millis+" "if(msg!=undefined)
  73. m+=msg+" "if(e!=undefined)
  74. m+=e.name+": "+e.messagethis.console.value+=m+"n"}
  75. function loggerClear(){if(!this.enabledthis.console==undefined)
  76. returnthis.console.value=""}
  77. function getTimeMillis(){var t=new Date()return Date.UTC(t.getFullYear(),t.getMonth(),t.getDay(),t.getHours(),t.getMinutes(),t.getSeconds(),t.getMilliseconds())}
  78. function getEvent(event){return(event!=undefined?event:window.event)}
  79. function preventDefault(event){if(event.preventDefault){event.preventDefault()event.stopPropagation()}else{event.returnValue=falseevent.cancelBubble=true}}
  80. function getEventTarget(event){if(event==undefined)
  81. return undefinedif(event.srcElement!=undefined)
  82. return event.srcElementelse
  83. return event.target}
  84. function getResponse(url,async,getXML,callback,data){var req=undefinedtry{req=new ActiveXObject("Msxml2.XMLHTTP")}catch(e1){try{req=new ActiveXObject("Microsoft.XMLHTTP")}catch(e2){req=new XMLHttpRequest()}}
  85. if(req==undefined){log.error("Failed to initialize XML/HTTP")return undefined}
  86. req.open("GET",url,async)if(!async){req.send(undefined)if(req.readyState!=4){log.error("Request failed: "+req.readyState)return undefined}
  87. if(!getXML)
  88. return req.responseTextelse
  89. return req.responseXML}else{pollResponse(req,callback,data)req.send(undefined)return undefined}}
  90. function pollResponse(req,callback,data){if(req.readyState!=4)
  91. window.setTimeout(function(){pollResponse(req,callback,data)},100)else
  92. callback(req,data)}
  93. function getElementsByTagName(node,tag){if(node==undefined)
  94. return undefinedif(IE){return node.getElementsByTagName(tag)}
  95. if(tag.indexOf(":")!=-1){tag=tag.split(":")[1]}
  96. return node.getElementsByTagNameNS("*",tag)}
  97. function getFirstElementsValue(node,tag){if(node==undefined)
  98. return undefinedvar nodes=getElementsByTagName(node,tag)if(nodes.length===0)
  99. return undefinedelse
  100. return getElementValue(nodes[0])}
  101. function findDOMElement(id){var el=undefinedvar win=windowwhile(el==undefined){try{el=win.document.getElementById(id)}catch(e){break}
  102. if(win===win.parent){break}
  103. win=win.parent}
  104. return el}
  105. function getElementValue(node){var ivar val=""for(i=0i<node.childnodes.lengthi++){if(node.childnodes[i].nodevalue!==null)>
  106. val+=node.childNodes[i].nodeValue}
  107. return val}
  108. function trim(str){if(str==undefined)
  109. return undefinedreturn str.replace(/^s*([sS]*S+)s*$^s*$/,'$1')}
  110. function trimToLen(str,len){if(str==undefined){return undefined}
  111. if(str.length>len){str=str.substring(0,len)+"..."}
  112. return str}
  113. function getRootWindow(){var win=windowwhile(win!=undefined){try{if(win===win.parent){break}else if(win.parent!=undefined&&win.parent.document.location.href.indexOf("/selenium-server/")!=-1){break}
  114. win=win.parent}catch(e){win.permissionDenied=truebreak}}
  115. return win}
  116. function getURLParams(){var i,params=[]var url=window.location.searchif(url==undefinedurl.length===0)
  117. return undefinedurl=url.substring(1)var namevals=url.replace(/+/g," ").split("&")for(i=0i<namevals.lengthi++){var name,valvar="" pos="namevals[i].indexOf(&quot=&quot)if(pos!=-1){name=namevals[i].substring(0,pos)val=unescape(namevals[i].substring(pos+1))}else{name=namevals[i]val=undefined}<br">params[name]=val}
  118. return params}
  119. function joinLists(list1,list2){var ivar size=0var result=[]if(list1!=undefined&&list1.length>0){for(i=0i<list1.lengthi++)>
  120. result[i]=list1[i]size=list1.length}
  121. if(list2!=undefined&&list2.length>0){for(i=0i<list2.lengthi++)>
  122. result[i+size]=list2[i]}
  123. return result}
  124. function setCookie(name,value,expire){var expiry=(expire==undefined)?"":(" expires="+expire.toGMTString())document.cookie=name+"="+value+expiry}
  125. function getCookie(name){if(document.cookie==undefineddocument.cookie.length===0)
  126. return undefinedvar search=name+"="var index=document.cookie.indexOf(search)if(index!=-1){index+=search.lengthvar end=document.cookie.indexOf("",index)if(end==-1)
  127. end=document.cookie.lengthreturn unescape(document.cookie.substring(index,end))}}
  128. function removeCookie(name){var today=new Date()var expires=new Date()expires.setTime(today.getTime()-1)setCookie(name,"",expires)}
  129. function getMessage(id){if(MESSAGES[id]==undefined){return"("+id+")"}else{return MESSAGES[id]}}
  130. function localizeNodeAttribs(node){var iif(node==undefined)
  131. returnif(node.alt!=undefined&&node.alt.indexOf("#")===0){node.alt=getMessage(node.alt.substring(1))}
  132. if(node.title!=undefined&&node.title.indexOf("#")===0){node.title=getMessage(node.title.substring(1))}
  133. if(node.childNodes!=undefined){for(i=0i<node.childnodes.lengthi++){localizenodeattribs(node.childnodes[i])}}}>
  134. function padNumber(n,pad){n=n+""while(n.length<pad){n="0"+n}>
  135. return n}
  136. function isArray(obj){if(obj instanceof Array)
  137. return trueelse
  138. return false}
  139. function simpleDateFormatter(date,pattern){var d=patternd=d.replace(/yyyy/g,date.getFullYear())d=d.replace(/yy/g,padNumber(date.getFullYear()%100,2))d=d.replace(/MM/g,padNumber(date.getMonth()+1,2))d=d.replace(/M/g,date.getMonth()+1)d=d.replace(/dd/g,padNumber(date.getDate(),2))d=d.replace(/d/g,date.getDate())d=d.replace(/HH/g,padNumber(date.getHours(),2))d=d.replace(/H/g,date.getHours())d=d.replace(/hh/g,padNumber(date.getHours()%12,2))d=d.replace(/h/g,date.getHours()%12)d=d.replace(/mm/g,padNumber(date.getMinutes(),2))d=d.replace(/m/g,date.getMinutes())d=d.replace(/ss/g,padNumber(date.getSeconds(),2))d=d.replace(/s/g,date.getSeconds())var am=(date.getHours()<12?"AM":"PM")d=d.replace(/a/g,am)return d}
  140. function formatDateTime(date){if(date==undefined)
  141. return undefinedreturn formatDate(date)+" "+formatTime(date)}
  142. function formatDate(date){var datePattern=getMessage("format.date")return simpleDateFormatter(date,datePattern)}
  143. function formatTime(date){var timePattern=getMessage("format.time")return simpleDateFormatter(date,timePattern)}
  144. function parseISOTime(strTime){if(strTime==undefined)
  145. return undefinedvar isoRE=/^(d{4})-(dd)-(dd)T(dd):(dd):(dd)(.d{3})?([Z+-])?(dd)?:?(dd)?$/if(!isoRE.test(strTime)){return undefined}else{return new Date(RegExp.$1,RegExp.$2-1,RegExp.$3,RegExp.$4,RegExp.$5,RegExp.$6)}}
  146. function setOpacity(elt,opacity){if(IE){elt.style.filter="alpha(opacity="+parseInt(opacity*100)+")"}
  147. elt.style.KhtmlOpacity=opacityelt.style.opacity=opacity}
  148. function validCoordinates(lat,lon){if(Math.abs(lat)>90Math.abs(lon)>180){return false}
  149. if(lat===0.0&&lon===0.0){return false}
  150. return true}
  151. function isHosted(){var host=document.location.hostif(host==undefined)
  152. host=""return((host.indexOf("triptracker.net")==-1host.indexOf("slideshow.triptracker.net")!=-1)&&host.indexOf("rtvslo.si")==-1&&!checkDomain())}
  153. function checkDomain(){try{if(_DOMAIN==undefined)
  154. return falsevar protocol=document.location.protocolif(protocol==undefined)
  155. protocol="http:"var host=document.location.hostif(host==undefined)
  156. host=""host=host.toLowerCase()if(protocol.toLowerCase().indexOf("file")===0){return true}
  157. var pos=host.lastIndexOf(":")if(pos!=-1){host=host.substring(0,pos)}
  158. if(host.indexOf("www.")===0){host=host.substring(4)}
  159. if(host===""host=="localhost"host=="127.0.0.1")
  160. return truevar domain=_DOMAIN.toLowerCase()pos=domain.indexOf("://")if(pos!=-1){domain=domain.substring(pos+3)}
  161. pos=domain.indexOf("/")if(pos!=-1){domain=domain.substring(0,pos)}
  162. if(domain.indexOf("www.")===0){domain=domain.substring(4)}
  163. if(host==domain){return true}else if(new RegExp(domain).test(host)){return true}
  164. return false}catch(e){return true}}
  165. function getWindowSize(win){var availW=win.innerWidthif(availW==undefinedavailW===0isNaN(availW))
  166. availW=win.document.documentElement.clientWidthif(availW==undefinedavailW===0isNaN(availW))
  167. availW=win.document.body.clientWidthvar availH=win.innerHeightif(availH==undefinedavailH===0isNaN(availH))
  168. availH=win.document.documentElement.clientHeightif(availH==undefinedavailH===0isNaN(availH))
  169. availH=win.document.body.clientHeightreturn{w:availW,h:availH}}
  170. function getDocumentSize(win){var winSize=getWindowSize(win)var scrollPos=getScrollPos(win)var w=winSize.w+scrollPos.leftvar h=winSize.h+scrollPos.topw=Math.max(w,win.document.body.offsetWidth)h=Math.max(h,win.document.body.offsetHeight)w=Math.max(w,win.document.body.scrollWidth)h=Math.max(h,win.document.body.scrollHeight)return{w:w,h:h}}
  171. function getScrollPos(win){var scrollTop=win.pageYOffsetif(scrollTop==undefinedscrollTop===0)
  172. scrollTop=win.document.documentElement.scrollTopif(scrollTop==undefinedscrollTop===0)
  173. scrollTop=win.document.body.scrollTopvar scrollLeft=win.pageXOffsetif(scrollLeft==undefinedscrollLeft===0)
  174. scrollLeft=win.document.documentElement.scrollLeftif(scrollLeft==undefinedscrollLeft===0)
  175. scrollLeft=win.document.body.scrollLeftreturn{top:scrollTop,left:scrollLeft}}
  176. var CLEAR_EVENTS=["onclick","ondblclick","onkeydown","onkeypress","onmousedown","onmouseup","onmousemove","onmouseover","onmouseout","onmousewheeldown","oncontextmenu"]function clearEvents(){var i,jvar count=0if(document.all==undefined)
  177. returnfor(i=0i<document.all.lengthi++){for(j=0j><clear_events.lengthj++){var event="document.all[i][CLEAR_EVENTS[j]]if(event!=undefined){document.all[i][CLEAR_EVENTS[j]]=nullcount++}}}}<br">if(window.attachEvent)
  178. window.attachEvent("onunload",clearEvents)function getGallery(){var gallery=undefinedvar win=windowwhile(gallery==undefined){try{gallery=win.document.gallery}catch(e){break}
  179. var tmpWin=winwin=win.parentif(tmpWin===win){break}}
  180. return gallery}
  181. function getMap(){if(this.map!=undefined)
  182. return this.maptry{if(document.map!=undefined)
  183. return document.map}catch(e){}
  184. try{if(window.parent.document.map!=undefined)
  185. return window.parent.document.map}catch(e){}
  186. return undefined}
  187. function viewerCloseCallback(photoIndex){var i,j,n=0var gallery=getGallery()for(i=0i<gallery.sets.lengthi++){for(j=0j><gallery.sets[i].photos.lengthj++){var p="gallery.sets[i].photos[j]if(p==undefinedp.orig==undefinedp.orig.src==undefined)<br">continueif(n==photoIndex){gallery.setIndex=igallery.photoIndex=jgallery.renderPhotos()gallery.win.focus()return}
  188. n++}}}
  189. var VIEWER_INDEX=0var SLIDE_DURATION=4000var SLIDE_OFFSET=50var SLIDE_PHOTOS=truevar FADE_BORDER=falsevar FADE_STEPS=10var MOVE_STEP=1var PRELOAD_TIMEOUT=60000var BORDER_WIDTH=5var FONT_SIZE=10var LINE_HEIGHT="0.7em"var OFFSET_LEFT=0var OFFSET_TOP=0var REST_URL="/rest/"var P_IMG_ROOT="http://static.triptracker.net/jsmap/images/photoviewer"var TOOLBAR_IMG="toolbar.png"var TOOLBAR_IMG_RUNNING="toolbar2.png"var TOOLBAR_IMG_BACK="toolbar-back"var TOOLBAR_IMG_MASK="toolbar-mask.png"var TOOLBAR_IMG_LOADING="loading-anim.gif"var TOOLBAR_W=440var TOOLBAR_H=75var TOOLBAR_IMG_W=420var TOOLBAR_IMG_H=44var TOOLBAR_LINK="http://slideshow.triptracker.net"var TOOLBAR_OPACITY=0.7var TOOLBAR_FONT_COLOR="#c0c0c0"var TOOLBAR_FONT_STYLE="tahoma, verdana, arial, helvetica, sans-serif"var BYLINE_FONT_COLOR=TOOLBAR_FONT_COLORvar BYLINE_FONT_STYLE=TOOLBAR_FONT_STYLEvar BYLINE_POSITION_RIGHT=5var BYLINE_POSITION_BOTTOM=5var VIEWER_ID_PREFIX="PhotoViewer"var VIEWER_ID_BACK=VIEWER_ID_PREFIX+"Back"var VIEWER_ID_TOOLBAR=VIEWER_ID_PREFIX+"Toolbar"var VIEWER_ID_TOOLBAR_MAP=VIEWER_ID_PREFIX+"ToolbarMap"var VIEWER_ID_TOOLBAR_IMG=VIEWER_ID_PREFIX+"ToolbarImg"var VIEWER_ID_LOADING=VIEWER_ID_PREFIX+"Loading"var VIEWER_ID_TIME=VIEWER_ID_PREFIX+"Time"var VIEWER_ID_TITLE=VIEWER_ID_PREFIX+"Title"var VIEWER_ID_BYLINE=VIEWER_ID_PREFIX+"Byline"var VIEWER_ID_PHOTO=VIEWER_ID_PREFIX+"Photo"var TITLE_MAX_LENGTH=140var TOOLBAR_IMG_LOADING_LEFT=273var TOOLBAR_IMG_LOADING_TOP=24function PhotoViewer(win,handleKeys){this.setImageRoot=setImageRootthis.add=addPhotothis.show=showPhotothis.close=closePhotothis.isShown=isPhotoShownthis.setBackground=setPhotoBackgroundthis.setShowToolbar=setShowToolbarthis.setToolbarImage=setToolbarImagethis.setShowCallback=setShowCallbackthis.setCloseCallback=setCloseCallbackthis.setEndCallback=setEndCallbackthis.setLoading=setPhotoLoadingthis.addBackShade=addBackShadethis.addToolbar=addToolbarthis.addCaptions=addCaptionsthis.next=nextPhotothis.prev=prevPhotothis.first=firstPhotothis.last=lastPhotothis.slideShow=slideShowthis.slideShowStop=slideShowStopthis.startSlideShow=startSlideShowthis.handleKey=viewerHandleKeythis.checkStartFragmentIdentifier=checkStartFragmentIdentifierthis.checkStopFragmentIdentifier=checkStopFragmentIdentifierthis.setStartFragmentIdentifier=setStartFragmentIdentifierthis.setStopFragmentIdentifier=setStopFragmentIdentifierthis.email=emailPhotothis.favorite=favoritePhotothis.permalink=linkPhotothis.setBackgroundColor=setBackgroundColorthis.setBorderWidth=setBorderWidththis.setSlideDuration=setSlideDurationthis.disablePanning=disablePanningthis.enablePanning=enablePanningthis.disableFading=disableFadingthis.enableFading=enableFadingthis.disableShade=disableShadethis.enableShade=enableShadethis.setShadeColor=setShadeColorthis.setShadeOpacity=setShadeOpacitythis.setFontSize=setFontSizethis.setFont=setFontthis.enableAutoPlay=enableAutoPlaythis.disableAutoPlay=disableAutoPlaythis.enableEmailLink=enableEmailLinkthis.disableEmailLink=disableEmailLinkthis.enablePhotoLink=enablePhotoLinkthis.disablePhotoLink=disablePhotoLinkthis.setOnClickEvent=setOnClickEventthis.enableLoop=enableLoopthis.disableLoop=disableLoopthis.enableToolbarAnimator=enableToolbarAnimatorthis.disableToolbarAnimator=disableToolbarAnimatorthis.enableToolbar=enableToolbarthis.disableToolbar=disableToolbarthis.setControlsImageMap=setControlsImageMapthis.setOverrideToolbarStyles=setOverrideToolbarStylesthis.setNoPadding=setNoPaddingthis.hideOverlappingElements=hideOverlappingElementsthis.showOverlappingElements=showOverlappingElementsthis.id=VIEWER_ID_PREFIX+VIEWER_INDEXVIEWER_INDEX++this.photos=[]this.index=0this.win=(win!=undefined?win:window)this.shown=falsethis.showToolbar=truethis.backgroundColor="#000000"this.shadeColor="#000000"this.shadeOpacity=0.7this.borderColor="#000000"this.shadeColor="#000000"this.shadeOpacity=0.7this.borderWidth=BORDER_WIDTHthis.backgroundShade=truethis.fadePhotos=truethis.autoPlay=falsethis.enableEmailLink=truethis.enablePhotoLink=truethis.slideDuration=SLIDE_DURATIONthis.panPhotos=SLIDE_PHOTOSthis.fontSize=FONT_SIZEthis.font=undefinedif(handleKeys==undefinedhandleKeys){if(this.win.addEventListener){this.win.addEventListener("keydown",viewerHandleKey,false)}else{this.win.document.attachEvent("onkeydown",viewerHandleKey)}}
  190. this.win.document.viewer=thisif(OPERA)
  191. this.disableFading()}
  192. function PhotoImg(id,src,w,h,time,title,byline){this.id=idthis.src=srcthis.w=parseInt(w)this.h=parseInt(h)this.time=timethis.title=titlethis.byline=byline}
  193. function getViewer(){var viewer=undefinedvar win=windowwhile(viewer==undefined){try{viewer=win.document.viewer}catch(e){break}
  194. if(win===win.parent){break}
  195. win=win.parent}
  196. return viewer}
  197. function setImageRoot(root){P_IMG_ROOT=root}
  198. function addPhoto(photo,title,time,byline){var type=typeof photoif(typeof photo=="string"){photo=new PhotoImg(undefined,photo,undefined,undefined,time,title,byline)}
  199. this.photos.push(photo)}
  200. function setPhotoBackground(color,border,doShade){if(color!=undefined)
  201. this.backgroundColor=colorif(border!=undefined)
  202. this.borderColor=borderif(doShade!=undefined)
  203. this.backgroundShade=doShade}
  204. function setPhotoLoading(isLoading){this.isLoading=isLoadingvar elt=this.win.document.getElementById(VIEWER_ID_LOADING)if(elt==undefined)
  205. returnelt.style.display=isLoading?"":"none"}
  206. function setBackgroundColor(color){this.backgroundColor=colorthis.borderColor=color}
  207. function setBorderWidth(width){this.borderWidth=width}
  208. function setSlideDuration(duration){this.slideDuration=duration}
  209. function disableShade(){this.backgroundShade=false}
  210. function enableShade(){this.backgroundShade=true}
  211. function setShadeColor(color){this.shadeColor=color}
  212. function setShadeOpacity(opacity){this.shadeOpacity=opacity}
  213. function disableFading(){this.fadePhotos=false}
  214. function enableFading(){this.fadePhotos=true}
  215. function disablePanning(){this.panPhotos=false}
  216. function enablePanning(){this.panPhotos=true}
  217. function setFontSize(size){this.fontSize=size}
  218. function setFont(font){this.font=font}
  219. function enableAutoPlay(){this.autoPlay=true}
  220. function disableAutoPlay(){this.autoPlay=false}
  221. function enableEmailLink(){this.enableEmailLink=true}
  222. function disableEmailLink(){this.enableEmailLink=false}
  223. function enablePhotoLink(){this.enablePhotoLink=true}
  224. function disablePhotoLink(){this.enablePhotoLink=false}
  225. function setOnClickEvent(newfunc){this.customOnClickEvent=newfunc}
  226. function enableLoop(){this.loop=true}
  227. function disableLoop(){this.loop=false}
  228. function enableToolbar(){this.showToolbar=true}
  229. function disableToolbar(){this.showToolbar=false}
  230. function enableToolbarAnimator(){this.toolbarAnimator=new ToolbarAnimator(this)}
  231. function disableToolbarAnimator(){if(this.toolbarAnimator!=undefined){this.toolbarAnimator.reset()this.toolbarAnimator=undefined}}
  232. function setControlsImageMap(imagemap){this.customImageMap=imagemap}
  233. function setOverrideToolbarStyles(overrideToolbarStyles){this.overrideToolbarStyles=overrideToolbarStyles}
  234. function setNoPadding(nopadding){this.nopadding=nopadding}
  235. function showPhoto(index,cropWidth,opacity){if(this.photos.length===0){return true}
  236. if(getRootWindow().permissionDenied&&this.badgeMode==undefined&&!getRootWindow().livemode){this.setStartFragmentIdentifier(index)return true}
  237. if(index!=undefined)
  238. this.index=indexif(this.index<0this.index>=this.photos.length){log.error("Invalid photo index")return true}
  239. var doc=this.win.documentvar firstShow=falseif(!this.shown){firstShow=truedoc.viewer=thistry{this.hideOverlappingElements()}catch(e){}}
  240. var zIndex=16384var winSize=getWindowSize(this.win)var availW=winSize.w-(this.nopadding?this.borderWidth*2:20)var availH=winSize.h-(this.nopadding?this.borderWidth*2:20)var scrollPos=getScrollPos(this.win)var scrollLeft=scrollPos.leftvar scrollTop=scrollPos.topthis.addBackShade(zIndex)if(this.showToolbar){this.addToolbar(availW,zIndex)this.addCaptions()}
  241. var photo=this.photos[this.index]if(isNaN(photo.w)isNaN(photo.h)){if(photo.preloadImage!=undefined){if(isNaN(photo.w)&&photo.preloadImage.width>0)
  242. photo.w=photo.preloadImage.widthif(isNaN(photo.h)&&photo.preloadImage.height>0)
  243. photo.h=photo.preloadImage.height}else{this.index--this.next()return false}}
  244. this.shown=truevar offset=(this.nopadding?0:20)var pw=-1var ph=-1if(parseInt(photo.w)>availWparseInt(photo.h)>availH){if(parseInt(photo.w)/availW>parseInt(photo.h)/availH){pw=availW-offsetph=parseInt(pw*photo.h/photo.w)}else{ph=availH-offsetpw=parseInt(ph*photo.w/photo.h)}}else{pw=parseInt(photo.w)ph=parseInt(photo.h)}
  245. if(pw<=0ph<=0){if(!this.showToolbar)
  246. throw"Missing photo dimension"}
  247. if(cropWidth==undefined)
  248. cropWidth=0var photoDiv=doc.createElement("div")photoDiv.id=VIEWER_ID_PHOTOphotoDiv.style.visibility="hidden"photoDiv.style.position="absolute"photoDiv.style.zIndex=zIndexphotoDiv.style.overflow="hidden"photoDiv.style.border=this.borderWidth+"px solid "+this.borderColorphotoDiv.style.textAlign="center"photoDiv.style.backgroundColor=this.backgroundColorvar photoElt=doc.createElement("img")photoElt.style.visibility="hidden"photoElt.style.position="relative"photoElt.style.backgroundColor=this.backgroundColorphotoElt.style.border="none"photoElt.style.cursor="pointer"photoElt.style.zIndex=(parseInt(photoDiv.style.zIndex)+1)+""photoElt.onclick=onClickEventif(opacity!=undefined&&this.fadePhotos){var fadeElt=(FADE_BORDER?photoDiv:photoElt)setOpacity(fadeElt,opacity)}
  249. var left=parseInt((availW-pw)/2)+(this.nopadding?0:OFFSET_LEFT)photoDiv.style.left=(left+scrollLeft+cropWidth/2)+"px"var top=parseInt((availH-ph)/2)+(this.nopadding?0:OFFSET_TOP)photoDiv.style.top=(top+scrollTop)+"px"photoElt.style.visibility="hidden"photoDiv.style.width=(pw-cropWidth>0?pw-cropWidth:pw)+"px"photoDiv.style.height=ph+"px"photoElt.style.width=pw+"px"photoElt.style.height=ph+"px"photoElt.src=photo.srcphotoDiv.style.visibility="visible"photoElt.style.visibility="visible"photoDiv.appendChild(photoElt)doc.body.appendChild(photoDiv)if(this.photoDiv!=undefined){try{doc.body.removeChild(this.photoDiv)}catch(e){}}
  250. this.photoDiv=photoDivthis.photoImg=photoEltthis.setLoading(false)if(this.showCallback!=undefined)
  251. this.showCallback(this.index)if(firstShow&&this.autoPlay){this.slideShow(true)}
  252. return false}
  253. function isPhotoShown(){return this.shown}
  254. function closeViewer(){getViewer().close()}
  255. function onPhotoLoad(event){var viewer=getViewer()if(viewer!=undefined){if(flickrHack(viewer,viewer.index)){viewer.setLoading(false)viewer.index--viewer.next()return}
  256. viewer.show()}}
  257. function closePhoto(){var win=this.winif(win==undefined)
  258. win=windowvar doc=win.documentvar elt=this.photoDivif(elt!=undefined)
  259. doc.body.removeChild(elt)elt=doc.getElementById(VIEWER_ID_BACK)if(elt!=undefined)
  260. doc.body.removeChild(elt)elt=doc.getElementById(VIEWER_ID_TOOLBAR)if(elt!=undefined)
  261. doc.body.removeChild(elt)elt=doc.getElementById(VIEWER_ID_BYLINE)if(elt!=undefined)
  262. doc.body.removeChild(elt)this.shown=falsethis.slideShowRunning=falsethis.slideShowPaused=falsetry{this.showOverlappingElements()}catch(e){log.error(e)}
  263. if(this.toolbarAnimator!=undefined){this.toolbarAnimator.reset()}
  264. if(this.closeCallback!=undefined)
  265. this.closeCallback(this.index)}
  266. function nextPhoto(n){if(this.isLoading)
  267. returnif(n==undefined)
  268. n=1var oldIndex=this.indexif(this.index+n>=this.photos.length){if(this.loop&&n!=this.photos.length){this.index=0}else{this.index=this.photos.length-1}}else if(this.index+n<0){if(n<-1)
  269. this.index=0else if(this.loop)
  270. this.index=this.photos.length-1else
  271. return}else{this.index+=n}
  272. if(this.index==oldIndex)
  273. returnthis.slideShowStop()var img=new Image()this.photos[this.index].preloadImage=imgthis.setLoading(true)img.onload=onPhotoLoadimg.onerror=onPhotoLoadif(this.photos[this.index].src!=undefined){img.src=this.photos[this.index].src}else{onPhotoLoad()}}
  274. function prevPhoto(n){if(n==undefined)
  275. n=1this.next(-n)}
  276. function firstPhoto(){this.prev(this.photos.length)}
  277. function lastPhoto(){this.next(this.photos.length)}
  278. function startSlideShow(){getViewer().slideShow(true)}
  279. var slideTimeoutvar slidePreloadImageLoaded=falsevar slidePreloadTime=undefinedfunction slideShow(start){if(this.toolbarAnimator!=undefined)
  280. this.toolbarAnimator.slideshowAction()var nextIndex=this.index+1if(nextIndex>=this.photos.length){if(this.loop)
  281. nextIndex=0else if(!this.slideShowPaused&&!this.slideShowRunning){this.setToolbarImage(P_IMG_ROOT+"/"+TOOLBAR_IMG)return}}
  282. var doc=this.win.documentvar viewer=thisvar photoElt=this.photoImgif(photoElt==undefined)
  283. returnvar photoDiv=this.photoDivvar fadeElt=(FADE_BORDER?photoDiv:photoElt)if(start!=undefined&&start===true){if(this.slideShowPaused){this.slideShowPaused=falsethis.setToolbarImage(P_IMG_ROOT+"/"+TOOLBAR_IMG_RUNNING)return}else if(this.slideShowRunning){this.slideShowPaused=truethis.setToolbarImage(P_IMG_ROOT+"/"+TOOLBAR_IMG)return}else{this.slideShowRunning=truethis.slideShowPaused=falsethis.slideFirstPhoto=truethis.setToolbarImage(P_IMG_ROOT+"/"+TOOLBAR_IMG_RUNNING)}
  284. if(this.isLoadingthis.index>this.photos.length-1){return}}else if(this.slideShowPaused){window.setTimeout(function(){viewer.slideShow(false)},200)return}else if(!this.slideShowRunning){this.setToolbarImage(P_IMG_ROOT+"/"+TOOLBAR_IMG)return}
  285. var left=0if(photoElt.leftOffset!=undefined){left=parseFloat(photoElt.leftOffset)}
  286. if(left===0){if(nextIndex<this.photos.length){slidepreloadimageloaded=falsevar slidepreloadimage="new" image()this.photos[nextindex].preloadimage="slidePreloadImageslidePreloadTime=getTimeMillis()slidePreloadImage.onload=onSlideLoadslidePreloadImage.onerror=onSlideLoadslidePreloadImage.src=this.photos[nextIndex].src}}<br">if(left>-SLIDE_OFFSET){left-=MOVE_STEPif(-left<=FADE_STEPS){if(fadeElt.style.opacity!=undefined&&parseFloat(fadeElt.style.opacity)<1){if(this.fadePhotos&&this.photos[this.index].src!=undefined)
  287. setOpacity(fadeElt,-left/FADE_STEPS)}}else if(left+SLIDE_OFFSET<fade_steps){if(nextindex><this.photos.length&&!slidepreloadimageloaded){if(slidepreloadtime!=undefined&&gettimemillis()-slidepreloadtime>PRELOAD_TIMEOUT)
  288. slidePreloadImageLoaded=trueleft++this.setLoading(true)}else{if(nextIndex<this.photos.length&&this.fadephotos&&this.photos[this.index].src!=undefined)>
  289. setOpacity(fadeElt,(left+SLIDE_OFFSET)/FADE_STEPS)}}
  290. photoElt.leftOffset=leftif(this.panPhotos&&!this.slideFirstPhoto){photoElt.style.left=left+"px"}}else{if(nextIndex>=this.photos.length){this.slideShowRunning=falsethis.slideShowPaused=falsethis.setToolbarImage(P_IMG_ROOT+"/"+TOOLBAR_IMG)if(this.toolbarAnimator!=undefined)
  291. this.toolbarAnimator.reset()if(this.endCallback!=undefined)
  292. this.endCallback()return}
  293. this.index=nextIndexthis.slideFirstPhoto=falsethis.show(undefined,(this.panPhotos?SLIDE_OFFSET:0),0)fadeElt=(FADE_BORDER?this.photoDiv:this.photoImg)if(this.fadePhotos)
  294. setOpacity(fadeElt,0)this.photoImg.leftOffset=0if(this.panPhotos)
  295. this.photoImg.style.left="0px"}
  296. var pause=this.slideDuration/SLIDE_OFFSETif(this.slideFirstPhoto){pause/=2}
  297. slideTimeout=window.setTimeout(function(){viewer.slideShow(false)},pause)}
  298. function onSlideLoad(event){var viewer=getViewer()if(viewer!=undefined){if(flickrHack(viewer,viewer.index+1)){var slidePreloadImage=viewer.photos[viewer.index+1].preloadImageslidePreloadImage.src=viewer.photos[viewer.index+1].srcslidePreloadTime=getTimeMillis()return}
  299. slidePreloadImageLoaded=trueviewer.setLoading(false)}}
  300. function slideShowStop(){this.slideShowRunning=falsethis.slideShowPaused=falsevar doc=this.win.documentvar photoElt=this.photoImgif(photoElt!=undefined){if(this.fadePhotos){var fadeElt=(FADE_BORDER?this.photoDiv:photoElt)setOpacity(fadeElt,1)}
  301. photoElt.style.left="0px"}}
  302. function addBackShade(zIndex){var doc=this.win.documentif(doc.getElementById(VIEWER_ID_BACK)!=undefined){return}
  303. var photoBack=doc.createElement("div")photoBack.id=VIEWER_ID_BACKphotoBack.style.top="0px"photoBack.style.left="0px"photoBack.style.bottom="0px"photoBack.style.right="0px"photoBack.style.margin="0"photoBack.style.padding="0"photoBack.style.border="none"photoBack.style.cursor="pointer"if(IE&&!(IE7&&STRICT_MODE)){photoBack.style.position="absolute"var docSize=getDocumentSize(this.win)photoBack.style.width=(docSize.w-21)+"px"photoBack.style.height=(docSize.h-4)+"px"}else{photoBack.style.position="fixed"photoBack.style.width="100%"photoBack.style.height="100%"}
  304. photoBack.style.zIndex=zIndex-1photoBack.style.backgroundColor=this.shadeColorif(this.backgroundShade)
  305. setOpacity(photoBack,this.shadeOpacity)else
  306. setOpacity(photoBack,0.0)photoBack.onclick=onClickEventdoc.body.appendChild(photoBack)}
  307. function addToolbar(availW,zIndex){var doc=this.win.documentvar iif(doc.getElementById(VIEWER_ID_TOOLBAR)!=undefined)
  308. returnvar photoToolbar=doc.createElement("div")photoToolbar.id=VIEWER_ID_TOOLBARsetOpacity(photoToolbar,TOOLBAR_OPACITY)photoToolbar.style.zIndex=zIndex+1var imgBack=TOOLBAR_IMG_BACKif(!isHosted()){imgBack+="-nologo"}
  309. if(IE&&!IE7){imgBack+="-indexed"}
  310. imgBack+=".png"if(!this.overrideToolbarStyles){var bottom=10if(IE&&!(IE7&&STRICT_MODE)){photoToolbar.style.position="absolute"if(IE7){var top=getWindowSize(this.win).h+getScrollPos(this.win).topphotoToolbar.style.top=(top-TOOLBAR_H-10)+"px"}else{photoToolbar.style.bottom=bottom+"px"}}else{photoToolbar.style.position="fixed"photoToolbar.style.bottom=bottom+"px"}
  311. photoToolbar.style.left=(availW-TOOLBAR_W+10)/2+"px"photoToolbar.style.width=TOOLBAR_W+"px"photoToolbar.style.height=TOOLBAR_H+"px"photoToolbar.style.textAlign="center"photoToolbar.style.backgroundImage="url('"+P_IMG_ROOT+"/"+imgBack+"')"photoToolbar.style.backgroundPosition="50% 0%"photoToolbar.style.backgroundRepeat="no-repeat"photoToolbar.style.lineHeight=LINE_HEIGHT}
  312. var toolbarMask=undefinedif(!this.enableEmailLink&&TOOLBAR_IMG_MASK!=undefined){toolbarMask=doc.createElement("img")toolbarMask.style.position="absolute"toolbarMask.style.width=44toolbarMask.style.height=44toolbarMask.style.left="289px"toolbarMask.style.top="0px"toolbarMask.src=P_IMG_ROOT+"/"+TOOLBAR_IMG_MASKphotoToolbar.appendChild(toolbarMask)}
  313. if(!this.enablePhotoLink&&TOOLBAR_IMG_MASK!=undefined){toolbarMask=doc.createElement("img")toolbarMask.style.position="absolute"toolbarMask.style.width=44toolbarMask.style.height=44toolbarMask.style.left="339px"toolbarMask.style.top="0px"toolbarMask.src=P_IMG_ROOT+"/"+TOOLBAR_IMG_MASKphotoToolbar.appendChild(toolbarMask)}
  314. var imgMap=this.customImageMapif(imgMap===undefined){imgMap=doc.createElement("map")var areas=[]areas.push(["getViewer().first()","17",getMessage("photoviewer.toolbar.first")])areas.push(["getViewer().prev()","68",getMessage("photoviewer.toolbar.prev")])areas.push(["getViewer().slideShow(true)","122",getMessage("photoviewer.toolbar.slideShow")])areas.push(["getViewer().next()","175",getMessage("photoviewer.toolbar.next")])areas.push(["getViewer().last()","227",getMessage("photoviewer.toolbar.last")])if(this.enableEmailLink)
  315. areas.push(["getViewer().email()","300",getMessage("photoviewer.toolbar.email")])if(this.enablePhotoLink)
  316. areas.push(["getViewer().permalink()","350",getMessage("photoviewer.toolbar.permalink")])areas.push(["getViewer().close()","402",getMessage("photoviewer.toolbar.close")])for(i=0i<areas.lengthi++){var area="doc.createElement(&quotarea&quot)area.href=&quotjavascript:void(0)&quot" mce_href="javascript:void(0)" area.alt="areas[i][2]area.title=area.altarea.shape=&quotcircle&quotarea.coords=areas[i][1]+&quot," 21,="" 22="" area.onclick="buildAreaMapClosure(areas[i][0])imgMap.appendChild(area)}}<br">imgMap.name=VIEWER_ID_TOOLBAR_MAPimgMap.id=VIEWER_ID_TOOLBAR_MAPvar img=doc.createElement("img")img.id=VIEWER_ID_TOOLBAR_IMGimg.src=P_IMG_ROOT+"/"+TOOLBAR_IMGimg.width=TOOLBAR_IMG_Wimg.height=TOOLBAR_IMG_Himg.style.border="none"img.style.background="none"if(STRICT_MODE){img.style.margin="4px 0px 0px 0px"}else{img.style.margin="4px"}
  317. img.useMap="#"+VIEWER_ID_TOOLBAR_MAPphotoToolbar.appendChild(imgMap)photoToolbar.appendChild(img)if(isHosted()){var ttLink=doc.createElement("a")ttLink.style.position="absolute"t