1// initialise 2var slideshowCanvas; 3var previousSlideButton; 4var nextSlideButton; 5var slideCaption; 6var slideshowCaptionBar; 7var masterSlideNumber; 8var touchStartX; 9var thisStory; 10 11var viewed = new Array(); 12var links; 13 14var available43 = null; 15var available169 = null; 16 17function startSlideshow(story, slideNumber, actuallyStart = true) { 18 // create slideshow canvas 19 slideshowCanvas = $("<div/>", {"id": "slideshow-canvas"}); 20 slideshowCanvas.html('<div id="previous-slide" onclick="previousSlide()"></div>\ 21 <div id="show-caption-bar" onclick="toggleCaptionBar()"> </div>\ 22 <div id="next-slide" onclick="nextSlide()"></div>\ 23 <a id="close-button" href="#" onclick="endSlideshow(); return false"><img src="/images/slideshow/close-button-matte.png" alt="Close" /></a>\ 24 <div id="slideshow-caption-bar">\ 25 <div id="slideshow-buttons-left">\ 26 <a href="#" onclick="toggleCaptionBar(); return false"><img src="/images/slideshow/hide-button.png" alt="Hide" /></a>\ 27 </div>\ 28 <div id="slideshow-buttons-right">\ 29 </div>\ 30 <div id="slide-caption"></div>\ 31 </div>'); 32 $(document.body).append(slideshowCanvas); 33 previousSlideButton = $("#previous-slide"); 34 nextSlideButton = $("#next-slide"); 35 slideCaption = $("#slide-caption"); 36 slideshowCaptionBar = $("#slideshow-caption-bar"); 37 masterSlideNumber = 0; 38 touchStartX = 0; 39 showProperlyStarted = false; 40 thisStory = ""; 41 slideshowCanvas.on("touchstart", touchStart); 42 slideshowCanvas.on("touchend", touchEnd); 43 fullScreenOn(); 44 45 // scan for links to convert 46 links = new Array(); 47 $("a").each(function() { 48 if (caption = $(this).attr("data-slideshow-caption")) { 49 links.push(this); 50 $(this).attr("title", caption.replace(/<br\/>/g, "").replace(/<p class="captionlinks">.*<\/p>/, "")); 51 } 52 }); 53 thisStory = story; 54 myTrackEvent("StoryView", "startSlideshow", thisStory, slideNumber); 55 masterSlideNumber = slideNumber - 1; 56 // determine whether 4:3 and 16:9 content is available, which starts show upon completion 57 if (actuallyStart) testAspectAvailability(); // this is launched from elsewhere when run direct from listings 58 return false; 59} 60 61var showProperlyStarted = false; 62 63function testAspectAvailability() { 64 var startLink = $(links[masterSlideNumber]).attr("href"); 65 const [start43, start169] = get43and169Urls(startLink); 66 // test 4:3 67 const test43 = new Image(); 68 test43.src = start43; 69 test43.onload = function() { 70 available43 = true; 71 startShowProper(); 72 }; 73 test43.onerror = function() { 74 available43 = false; 75 startShowProper(); 76 }; 77 // test 16:9 78 const test169 = new Image(); 79 test169.src = start169; 80 test169.onload = function() { 81 available169 = true; 82 startShowProper(); 83 }; 84 test169.onerror = function() { 85 available169 = false; 86 startShowProper(); 87 }; 88 89/* $.get(start43) 90 .done(function() { 91 available43 = true; 92 }) 93 .fail(function() { 94 available43 = false; 95 }) 96 .always(startShowProper); 97 $.get(start169) 98 .done(function() { 99 available169 = true; 100 }) 101 .fail(function() { 102 available169 = false; 103 }) 104 .always(startShowProper);*/ 105} 106 107function startShowProper() { 108 if (available43 !== null && available169 !== null && !showProperlyStarted) { 109 showProperlyStarted = true; 110 slideshowCanvas.css("background-size", "contain"); 111 showSlide(); 112 bindKeys(); 113 slideshowCaptionBar.show(); 114 $("#previous-slide").show(); 115 $("#next-slide").show(); 116 } 117} 118 119function endSlideshow() { 120 fullScreenOff(); 121 myTrackEvent("StoryView", "endSlideshow", thisStory, masterSlideNumber + 1); 122 var count = 0; 123 for (i = 0; i < links.length; i++) { 124 if (viewed[i]) count++; 125 } 126 var percent = Math.round(100 * count / links.length); 127 myTrackEvent("StoryView", "endSlideshowPercent", thisStory, percent); 128 if (percent == 100) { 129 myTrackEvent("StoryView", "viewedEntireSlideshow", thisStory, 0); 130 } 131 $("#quick-div").remove(); 132 slideshowCanvas.hide(); 133 slideshowCanvas.html(""); // needed to remove children, since created with inline HTML 134 try { 135 slideShowcanvas.remove(); 136 } catch (re) { 137 } 138} 139 140function bindKeys() { 141 $(document).off("keydown"); 142 $(document).keydown(function(evt) { 143 evt = evt || window.event; 144 if (evt.keyCode == 27) { 145 // escape key 146 endSlideshow(); 147 } 148 if (evt.keyCode == 37) { 149 // left arrow 150 previousSlide(); 151 } 152 if (evt.keyCode == 39) { 153 // right arrow 154 nextSlide(); 155 } 156 }); 157} 158 159function previousSlide() { 160 masterSlideNumber--; 161 if (masterSlideNumber < 0) masterSlideNumber = links.length - 1; 162 showSlide(); 163 previousSlideButton.blur(); 164} 165 166function nextSlide() { 167 masterSlideNumber++; 168 if (masterSlideNumber >= links.length) masterSlideNumber = 0; 169 showSlide(); 170 nextSlideButton.blur(); 171} 172 173const mediaQuery = window.matchMedia('(min-aspect-ratio: 1.54)'); 174mediaQuery.addListener(showSlide); 175 176function switchImage(event) { 177 var container = document.getElementById("container"); 178 if (event.matches) { 179 container.style.backgroundImage = 'url("169example.jpg")'; 180 } else { 181 container.style.backgroundImage = 'url("43example.jpg")'; 182 } 183} 184 185function showSlide() { 186 try { 187 viewed[masterSlideNumber] = true; 188 const[url43, url169] = get43and169Urls(links[masterSlideNumber].href); 189 if (mediaQuery.matches) { // i.e. we are widescreen 190 url = available169 ? url169 : url43; 191 } else { 192 url = available43 ? url43 : url169; 193 } 194 slideshowCanvas.css("background-image", "url(\"" + url +"\")");
195 slideCaption.html($(links[masterSlideNumber]).attr("data-slideshow-caption")); 196 // cache next and previous for cleaner switching 197 var nextIndex = masterSlideNumber + 1; 198 if (nextIndex >= links.length) nextIndex = 0; 199 const[next43, next169] = get43and169Urls(links[nextIndex].href); 200 if (available43) cacheImage(next43); 201 if (available169) cacheImage(next169); 202 var previousIndex = masterSlideNumber - 1; 203 if (previousIndex < 0) previousIndex = links.length - 1; 204 const[previous43, previous169] = get43and169Urls(links[previousIndex].href); 205 if (available43) cacheImage(previous43); 206 if (available169) cacheImage(previous169); 207 } catch (e) { 208 } 209} 210 211function cacheImage(im) { 212 newImage = new Image(); 213 newImage.src = im; 214} 215 216function toggleCaptionBar() { 217 slideshowCaptionBar.slideToggle(); 218 $("#previous-slide").toggleClass("slide-navigation-hidden"); 219 $("#next-slide").toggleClass("slide-navigation-hidden"); 220} 221 222function touchStart(event) 223{ 224 var touch = event.touches[0]; 225 touchStartX = touch.clientX; 226} 227 228function touchEnd(event) 229{ 230 var touch = event.changedTouches[0]; 231 touchEndX = touch.clientX; 232 var delta = Math.abs(touchEndX - touchStartX); 233 var threshold = window.innerWidth / 4; 234 if (delta > threshold) 235 { 236 if (touchEndX < touchStartX) nextSlide(); 237 else previousSlide(); 238 } 239} 240 241function fullScreenOn() { 242 var canvas = slideshowCanvas[0]; 243 if (canvas.requestFullscreen) { 244 canvas.requestFullscreen(); 245 } else if (canvas.msRequestFullscreen) { 246 canvas.msRequestFullscreen(); 247 } else if (canvas.mozRequestFullScreen) { 248 canvas.mozRequestFullScreen(); 249 } else if (canvas.webkitRequestFullscreen) { 250 canvas.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); 251 } 252} 253 254function fullScreenOff() { 255 if (document.exitFullscreen) { 256 document.exitFullscreen(); 257 } else if (document.msExitFullscreen) { 258 document.msExitFullscreen(); 259 } else if (document.mozCancelFullScreen) { 260 document.mozCancelFullScreen(); 261 } else if (document.webkitExitFullscreen) { 262 document.webkitExitFullscreen(); 263 } 264} 265 266function setSlideshowImagesRetrospectively(images) { 267 images.shift(); 268 for (var x in images) { 269 image = images[x]; 270 var link = $("<a>")[0]; 271 link.href = mediaServer + image; 272 links.push(link); 273 } 274 //slideshowCanvas.css("background-image", "url(\"" + links[masterSlideNumber].href +"\")"); 275} 276 277function setSlideshowCaptionsRetrospectively(captions) { 278 for (x = 0; x < links.length; x++) { 279 var caption = captions[x + 1]; 280 if (!caption) caption = ''; 281 caption = caption.replace(/\|/g,"<br />"); 282 if (caption && !caption.match(/^<p class="captionlinks">.*<\/p>$/)) caption += " – "; 283 caption = caption.replace(/"/g, '"'); 284 var slideText = SLIDE_NUMBER; 285 caption += slideText + " " + (x + 1); 286 $(links[x]).attr("data-slideshow-caption", caption); 287 } 288 slideCaption.html($(links[masterSlideNumber]).attr("data-slideshow-caption")); 289} 290 291function get43and169Urls(url) { 292 if (url.search(/_1024/)) { 293 url43 = url; 294 url169 = url.replace(/_1024/, '_1920').replace(/jpeg/, 'jpegw'); 295 } else { 296 url169 = url; 297 url43 = url.replace(/_1920/, '_1024').replace(/jpegw/, 'jpeg'); 298 } 299 return [url43, url169]; 300}
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.