1/** 2 * Plugin based on template https://css-tricks.com/lodge/learn-jquery/28-building-complex-plugin/ 3 */ 4 5export default (function($) { 6 $.ar_slider = function (el, options) { 7 8 var base = this; 9 10 // Access to jQuery and DOM versions of element 11 base.$el = $(el); 12 base.el = el; 13 14 // Find out the current browser 15 if ($.browser.name) { 16 var browserVersion = parseInt($.browser.version); 17 var browserName = $.browser.name; 18 if (browserVersion) { 19 $('body').addClass('browser-' + browserName); 20 $('body').addClass('browser-' + browserName + '-' + browserVersion); 21 } 22 }; 23 24 // Find out if device is handheld or desktop 25 var handheld_ios = false 26 var handheld_android = false 27 var handheld_device = false 28 29 base.handheld_ios_devices = function() { 30 return ( 31 //Detect iPhone 32 (navigator.platform.indexOf("iPhone") != -1) || 33 //Detect iPod 34 (navigator.platform.indexOf("iPod") != -1) || 35 //Detect iPad 36 (navigator.platform.indexOf("iPad") != -1) || 37 //Detect iPad ios 13+ 38 (navigator.platform.indexOf("MacIntel") != -1 && navigator.maxTouchPoints > 1) 39 ); 40 }; 41 42 //Detect Android 43 base.handheld_android_devices = function() { 44 return ( 45 (navigator.userAgent.toLowerCase().indexOf("android") != -1) 46 ); 47 }; 48 49 if (base.handheld_android_devices()) { 50 handheld_android = true 51 handheld_device = true 52 $('body').addClass('handheld_android'); 53 } else if (base.handheld_ios_devices()) { 54 handheld_ios = true 55 handheld_device = true 56 $('body').addClass('handheld_ios'); 57 }; 58 59 60 61 // Detect support for AR Quick Looks (ios only) 62 var ios_ar_supported_device = false 63 var test_anchor = document.createElement("a"); 64 65 if (typeof(test_anchor.relList) != 'undefined' && typeof(test_anchor.relList.supports("ar")) != 'undefined') { 66 ios_ar_supported_device = true 67 $('body').addClass('ar-supported'); 68 }; 69 70 // Detect support for AR on Android 71 var android_ar_supported_device = false; 72 if (handheld_android) { 73 var testCanvas = document.createElement('canvas'); 74 var testGl = testCanvas.getContext('webgl2') 75 76 if (testGl.getExtension('EXT_color_buffer_float')) { 77 android_ar_supported_device = true; 78 } 79 } 80 81 // Retrieve element AR_model_data 82 var AR_model_data = base.$el.attr('data-ar_model'); 83 var AR_model_data_edit = AR_model_data.replace(/'/g, '"'); 84 var AR_model_data_parse = JSON.parse(AR_model_data_edit); 85 86 var qrcode_for_artwork_page_on_mobile = AR_model_data_parse['qrcode_for_artwork_page_on_mobile'] 87 var AR_model_usdz_url = AR_model_data_parse['ar_model_usdz_url'] 88 var AR_model_gltf_url = AR_model_data_parse['ar_model_gltf_url'] 89 var AR_model_placement = AR_model_data_parse['ar_placement'] 90 91 base.init = function() { 92 base.options = $.extend({}, $.ar_slider.defaultOptions, options); 93 94 if (!$("#popup_slider_container.qr_code").length && handheld_device == false) { 95 base.setup_qr_code_html(); 96 base.respond_to_qr_code_entry(); 97 // base.setup_slide_html(); 98 } else if (!$("#popup_slider_container").length && handheld_device == true) { 99 if ((ios_ar_supported_device == true && handheld_ios) || (handheld_android && android_ar_supported_device)) { 100 // console.log("===passed ios and ios ar tests===") 101 try { 102 // Artlogic.import("galleries_js/model_viewer.js").then(() => { 103 const body = document.body; 104 const modelViewer = document.createElement('script'); 105 modelViewer.type = 'module';
106 modelViewer.src = '/lib/g/2.0/scripts/artlogic_modules/galleries_js/model_viewer.js'; 107 body.appendChild(modelViewer); 108 var ar_guidance_dismissed = base.get_local_storage_boolean(); 109 if (ar_guidance_dismissed == false) { 110 base.setup_slide_html(); 111 }; 112 base.respond_to_qr_code_entry(); 113 // }); 114 } catch (err) { 115 console.error(err); 116 } 117 } else { 118 // console.log("===failed ios and ios ar tests===") 119 base.respond_to_qr_code_entry(); 120 $(base.$el).ar_slider_destroy(); 121 } 122 }; 123 base.on_element_click(); 124 base.close_popup(); 125 base.set_button_loader(); 126 }; 127 128 // HTML INJECTION 129 base.setup_slide_html = function() { 130 131 var slide_html = ' <div id="popup_slider_container">\ 132 <div id="popup_slider_overlay"></div>\ 133 <div id="popup_slider_inner">\ 134 <div id="popup_slider_box" role="dialog" aria-modal="true" aria-label="AR popup slider" class="esc-key-listener-added focustrap-wrapper" data-popup-layer="1">\ 135 <div id="popup_slider_close_popup" class="close focustrap-focusable focustrap-item focustrap-first" role="button" tabindex="0" aria-label="Close" data-tabindex="0">\ 136 <a href="#" aria-hidden="true" tabindex="-1">Close</a>\ 137 </div>\ 138 <div id="popup_slider_slides">\ 139 <ul>\ 140 <li class="slide_1">\ 141 <div class="content_wrapper">\ 142 <ul>\ 143 <li>\ 144 <h2 class="popup_slider_main_header">AR viewer</h2>\ 145 </li>\ 146 <li>\ 147 <h3 class="popup_slider_subtitle">Preview artworks in your own home.</h3>\ 148 </li>\ 149 <li>\ 150 <div class="popup_slider_gif_container large ">\ 151 <span class="ar-slide-gif main_image"></span>\ 152 </div>\ 153 </li>\ 154 <li>\ 155 <div class="popup_slider_description">\ 156 <p>Opens your mobile device\'s built-in AR viewer. Results will depend greatly on the capabilities of your device.</p>\ 157 </div>\ 158 </li>\ 159 <li class="popup_slider_buttons_container">\ 160 <div class="button">\ 161 <a class="control_exit" role="button" href="#" tabindex="0"><span>Skip help and don\'t show again</span></a>\ 162 </div>\ 163 <div class="button">\ 164 <a class="control_next" role="button" href="#" tabindex="0">Next</a>\ 165 </div>\ 166 </li>\ 167 </ul>\ 168 </div>\ 169 </li>\ 170 <li class="slide_2">\ 171 <div class="content_wrapper">\ 172 <ul>\ 173 <li>\ 174 <h2 class="popup_slider_main_header">Tips</h2>\ 175 </li>\ 176 <li>\ 177 <div class="popup_slider_gif_container small">\ 178 <sp
178an class="ar-slide-gif gif_animate light_bulb"></span>\ 179 </div>\ 180 <div class="popup_slider_description top">\ 181 <p>Augmented reality works best in a <strong>well-lit</strong> room.</p>\ 182 </div>\ 183 </li>\ 184 <li>\ 185 <div class="popup_slider_gif_container large">\ 186 <span class="ar-slide-gif gif_animate wall_template"></span>\ 187 </div>\ 188 <div class="popup_slider_description">\ 189 <p>Use <strong>clear wall</strong>, with a view of where the wall meets the <strong>floor</strong>.</p>\ 190 </div>\ 191 </li>\ 192 <li>\ 193 <div class="popup_slider_gif_container large">\ 194 <span class="ar-slide-gif gif_animate wall_scan"></span>\ 195 </div>\ 196 <div class="popup_slider_description bottom">\ 197 <p>When asked to initially move your phone, <strong>scan the target wall and floor</strong>.</p>\ 198 </div>\ 199 </li>\ 200 <li class="popup_slider_buttons_container">\ 201 <div class="button">\ 202 <a class="control_open" role="button" tabindex="0"><span>Open AR Viewer</span></a>\ 203 </div>\ 204 </li>\ 205 </ul>\ 206 </div>\ 207 </li>\ 208 </ul>\ 209 </div>\ 210 </div>\ 211 </div>\ 212 </div>'; 213 214 $('body').append(slide_html); 215 }; 216 217 base.setup_qr_code_html = function() { 218 219 var qr_code_html = ' <div id="popup_slider_container" class="qr_code">\ 220 <div id="popup_slider_overlay"></div>\ 221 <div id="popup_slider_inner">\ 222 <div id="popup_slider_box" role="dialog" aria-modal="true" aria_label="QR code popup for viewing artworks in AR on a mobile device" class="esc-key-listener-added focustrap-wrapper" data-popup-layer="1">\ 223 <div id="popup_slider_close_popup" class="close focustrap-focusable focustrap-item focustrap-first" role="button" tabindex="0" aria-label="Close" data-tabindex="0">\ 224 <a href="#" aria-hidden="true" tabindex="-1">Close</a>\ 225 </div>\ 226 <div class="qr_code_wrapper">\ 227 <div class="qr_code_image">\ 228 <span class="ar-qr_code-label">QR Code</span>\
229 <span class="ar-qr_code-icon">\ 230 <a class="nopopup" rel="ar">\ 231 <img src="' + qrcode_for_artwork_page_on_mobile + '">\ 232 </a>\ 233 </span>\ 234 </div>\ 235 <div class="qr_code_description">\ 236 <div class="description">\ 237 Scan the QR code to open this work using your mobile device\'s built-in Augmented Reality (AR) viewer.\ 238 <div class="note">\ 239 This is only available on Android and iOS devices that support AR.\ 240 </div>\ 241 </div>\ 242 </div>\ 243 </div>\ 244 </div>\ 245 </div>\ 246 </div>'; 247 248 $('body').append(qr_code_html); 249 }; 250 251 base.inject_button_link_html = function() { 252 253 if (!$('#view-in-ar-link').length && handheld_ios && ios_ar_supported_device) { 254 if (AR_model_usdz_url && typeof(AR_model_usdz_url) != 'undefined') { 255 var button_link_html = '<div id="view-in-ar-link">\ 256 <a class="nopopup" rel="ar" href="' + AR_model_usdz_url + '">\ 257 <img src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7">\ 258 </a>\ 259 </div>' 260 base.$el.before(button_link_html) 261 } 262 } 263 }; 264 265 base.inject_model_viewer_html = function() { 266 if (!$('#ar-model-viewer-container').length && ((handheld_ios && ios_ar_supported_device) || (handheld_android && android_ar_supported_device))) { 267 if ((handheld_ios && AR_model_usdz_url && typeof(AR_model_usdz_url) != 'undefined') || (handheld_android && AR_model_gltf_url && typeof(AR_model_gltf_url) != 'undefined')) { 268 // TODO Set ar-placement based on artwork settings 269 var model_viewer_html = '<div id="ar-model-viewer-container"><model-viewer id="ar-model-viewer" src="' + AR_model_gltf_url + '" ios-src="' + AR_model_usdz_url + '" ar ar-placement="' + AR_model_placement + '" ar-modes="scene-viewer quick-look"></model-viewer></div>' 270 base.$el.before(model_viewer_html) 271 } 272 } 273 }; 274 275 // Inject button-loader html 276 base.set_button_loader = function () { 277 $('.button a.control_open').each(function() { 278 if (!$('.button_loader', this).length) { 279 $(this).append('<div class="button_loader"></div>'); 280 } 281 }); 282 $('.button_loader').each(function() { 283 if (!$('svg', this).length) { 284 $(this).append('<svg class="loader" viewBox="25 25 50 50"><circle class="path" cx="50" cy="50" r="20" fill="none" stroke-width="3" stroke-miterlimit="10"/></svg>'); 285 } 286 }); 287 }; 288 289 // Click event for plugin element 290 base.on_element_click = function() { 291 base.$el.off().click(function() { 292 if ($('li.slide_1').length) { 293 $('li.slide_1').css('display', 'block'); 294 }; 295 var ar_guidance_dismissed = base.get_local_storage_boolean(); 296 297 if (ar_guidance_dismissed == true) { 298 base.view_AR_model(); 299 } else { 300 base.open_slides_popup(); 301 }; 302 }) 303 }; 304 305 base.view_AR_model = function() { 306 // if ($("#view-in-ar-link a").length) { 307 // $("#view-in-ar-link a").get(0).click(); 308 // }; 309 310 base.inject_model_viewer_html(); 311 312 var modelViewer = document.getElementById('ar-model-viewer'); 313 modelViewer.addEventListener('error', function (e) { 314 console.error(e); 315 }); 316 317 if (modelViewer.canActivateAR) { 318 try { 319 modelViewer.activateAR(); 320 } catch (err) { 321 console.error(err); 322 } 323 } else { 324 modelViewer.addEventListener('load', function (e) { 325 modelViewer.activateAR(); 326 }); 327 328 if (handheld_ios) { 329 modelViewer.addEventListener('error', function (e) { 330 console.log(e); 331 modelViewer.activateAR(); 332 }); 333 } 334 } 335 }; 336 337 // QR code handling 338 base.respond_to_qr_code_entry = function() { 339 if (window.location.hash) { 340 if (window.location.hash == "#AR") { 341 if ((ios_ar_supported_device == true && handheld_ios)) { 342 setTimeout(function() { 343 base.view_AR_model(); 344 }, base.options.splash_screen_timeout) 345 } else if (handheld_android && android_ar_supported_device) { 346 setTimeout(function () { 347 if (!$('#popup_slider_container').length) { 348 base.setup_slide_html(); 349 } 350 base.open_slides_popup(); 351 }, base.options.splash_screen_timeout) 352 } else { 353 setTimeout(function() { 354 h.prompt('<div class="ar_mobile_prompt">\ 355 <h3>Feature not supported on this device</h3>\
356 <p>The Augmented Reality (AR) feature is currently only available on selected Android and iOS devices.</p>\ 357 </div>', { 358 buttons: { 359 'Ok': true, 360 }, 361 }); 362 }, base.options.splash_screen_timeout) 363 } 364 } 365 } 366 }; 367 368 base.open_qr_code_popup = function() { 369 base.body.addClass('popup_slider_active'); 370 371 setTimeout(function() { 372 base.body.addClass('popup_slider_visble'); 373 h.accessibility.on_popup_opening('#popup_slider_box', '#popup_slider_close_popup a', '#popup_slider_close_popup a'); 374 }, 50); 375 376 }; 377 378 // Popup and slider actions 379 base.open_slides_popup = function() { 380 381 $('body').addClass('popup_slider_active'); 382 $('li.slide_2').css('display', 'none'); 383 384 setTimeout(function() { 385 $('body').addClass('popup_slider_visble'); 386 $('li.slide_1 .popup_slider_main_header').focus(); 387 $('#popup_slider_slides ul li.slide_1 .content_wrapper').addClass('visible'); 388 //trap_element, first_focusable_element_override, close_button_element 389 h.accessibility.on_popup_opening('#popup_slider_box', '#popup_slider_close_popup a', '#popup_slider_close_popup a'); 390 }, 50); 391 392 393 $('.control_open').off().click(function() { 394 $('#popup_slider_slides ul li.slide_2 .popup_slider_buttons_container .button').addClass('loading'); 395 396 setTimeout(function() { 397 $('#popup_slider_close_popup a').trigger('click'); 398 $('#popup_slider_slides ul li.slide_2 .popup_slider_buttons_container .button').removeClass('loading'); 399 }, 3500); 400 base.view_AR_model(); 401 }); 402 403 $('.control_exit').off().click(function() { 404 base.set_local_storage_boolean(); 405 406 setTimeout(function() { 407 base.view_AR_model(); 408 $('#popup_slider_container').ar_slider_destroy(); 409 },50) 410 }); 411 412 $('.control_next').off().click(function () { 413 base.next_slide(); 414 }); 415 }; 416 417 base.next_slide = function() { 418 $('li.slide_2').css('display', 'block'); 419 $('li.slide_1').css('display', 'none'); 420 421 $('#popup_slider_slides ul li.slide_1 .content_wrapper').removeClass('visible'); 422 423 setTimeout(function() { 424 $('#popup_slider_slides ul li.slide_2 .content_wrapper').addClass('visible'); 425 $('#popup_slider_close_popup').focus(); 426 $('#popup_slider_slides ul li.slide_2 .content_wrapper') 427 .delay(300) 428 .queue(function() { 429 $('#popup_slider_slides ul li .content_wrapper.visible ul li:first-child').addClass('animate_in'); 430 $(this).dequeue(); 431 }) 432 .delay(500) 433 .queue(function() { 434 $('#popup_slider_slides ul li .content_wrapper.visible ul li:nth-child(2)').addClass('animate_in'); 435 $(this).dequeue(); 436 }) 437 .delay(900) 438 .queue(function() { 439 $('#popup_slider_slides ul li .content_wrapper.visible ul li:nth-child(3)').addClass('animate_in'); 440 $(this).dequeue(); 441 }) 442 .delay(1650) 443 .queue(function() { 444 $('#popup_slider_slides ul li .content_wrapper.visible ul li:nth-child(4)').addClass('animate_in'); 445 $(this).dequeue(); 446 }) 447 .delay(250) 448 .queue(function() { 449 $('#popup_slider_slides ul li .content_wrapper.visible ul li:nth-child(5)').addClass('animate_in'); 450 $(this).dequeue(); 451 }) 452 ; 453 }, 400); 454 }; 455 456 base.exit_slider = function() { 457 base.set_local_storage_boolean(); 458 base.view_AR_model(); 459 }; 460 461 base.close_popup = function() { 462 463 $('#popup_slider_close_popup a').off().click(function() { 464 465 $('body').removeClass('popup_slider_visble'); 466 setTimeout(function() { 467 $('body').removeClass('popup_slider_active'); 468 $('#popup_slider_slides ul li.slide_2 .content_wrapper').removeClass('visible'); 469 $('#popup_slider_slides ul li .content_wrapper ul li.animate_in').each(function() { 470 $(this).removeClass('animate_in') 471 }) 472 }, 400); 473 474 try { 475 h.accessibility.on_popup_closing(); 476 } 477 catch(error) { 478 console.log(error); 479 } 480 }) 481 }; 482 483 // Local storage GET and SET 484 base.set_local_storage_boolean = function() { 485 var ar_guidance_dismissed = true; 486 localStorage.setItem("ar_guidance_dismissed", JSON.stringify(ar_guidance_dismissed)); 487 }; 488 489 base.get_local_storage_boolean = function() { 490 491 var browser_supports_local_storage = base.run_local_storage_test(); 492 493 if (browser_supports_local_storage == true) { 494 var ar_guidance_dismissed = JSON.parse(localStorage.getItem("ar_guidance_dismissed")); 495 496 if (ar_guidance_dismissed == true) { 497 return true 498 } else { 499 return false 500 } 501 } else { 502 console.log('local_storage not supported by browser') 503 } 504 }; 505 506 // Check browser supports local storage 507 base.run_local_storage_test = function() { 508 var test = 'test'; 509 try { 510 localStorage.setItem(test, test); 511 localStorage.removeItem(test); 512 return true; 513 } catch(e) { 514 return false;
515 } 516 }; 517 518 // Run initialise 519 base.init(); 520 }; 521 522 // Destroy slider method 523 $.ar_slider_destroy = function(el) { 524 if ($(el).length) { 525 $(el).each(function() { 526 $(this).remove(); 527 }) 528 } 529 }; 530 531 $.fn.ar_slider_destroy = function() { 532 return this.each(function() { 533 (new $.ar_slider_destroy(this)) 534 }) 535 }; 536 537 // Run plugin 538 $.ar_slider.defaultOptions = { 539 'splash_screen_timeout': 0 540 }; 541 542 $.fn.ar_slider = function(options) { 543 return this.each(function() { 544 (new $.ar_slider(this, options)) 545 }) 546 }; 547 548})(jQuery);
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.