1var slider = { 2 instances: [], 3 4 init: function(opts) { 5 if (typeof opts == 'undefined') 6 opts = {}; 7 if (typeof opts.selector == 'undefined') 8 opts.selector = '.slider'; 9 if (typeof opts.drag == 'undefined') 10 opts.drag = 2; 11 if (typeof opts.min_speed == 'undefined') 12 opts.min_speed = 1; 13 if (typeof opts.slide_spacing == 'undefined') 14 opts.slide_spacing = 0; 15 if (typeof opts.move_to_nearest_mode == 'undefined') 16 opts.move_to_nearest_mode = 'center'; 17 if (typeof opts.infinite_scroll == 'undefined') 18 opts.infinite_scroll = true; 19 if (typeof opts.after_create == 'undefined') 20 opts.after_create = function(slider_instance) {}; 21 if (typeof opts.index_update == 'undefined') 22 opts.index_update = function(slider_instance, index) {}; 23 if (typeof opts.show_prev_next == 'undefined') 24 opts.show_prev_next = true; 25 if (typeof opts.show_buttons == 'undefined') 26 opts.show_buttons = true; 27 if (typeof opts.zoom_button == 'undefined') 28 opts.zoom_button = false; 29 if (typeof opts.fullscreen_button == 'undefined') 30 opts.fullscreen_button = false; 31 if (typeof opts.auto_rotate == 'undefined') 32 opts.auto_rotate = false; 33 if (typeof opts.auto_rotate_delay == 'undefined') 34 opts.auto_rotate_delay = 6000; 35 36 jQuery(opts.selector).each(function() { 37 slider.instances.push(new slider.slider_instance(jQuery(this), opts)); 38 }); 39 }, 40 41 slider_instance: function(jq, opts) { 42 if (jq.hasClass('slider-init')) 43 return; 44 45 var me = this; 46 47 var slides = []; 48 var jq_width = 0; 49 var container = jq.find('ul'); 50 var jq_win = jQuery(window); 51 var jq_btns = false; 52 var left_position = 0; 53 var tmr_impulse = 0; 54 var tmr_nearest = 0; 55 var max_position = 0; 56 var max_item_position = 0; 57 var extra_before = []; 58 var extra_before_width = 0; 59 var extra_after = []; 60 var extra_after_width = 0; 61 var tmr_auto_rotate = 0; 62 63 me.get_jq = function() { 64 return jq; 65 }; 66 67 var busy = false; 68 me.prev = function() { 69 if (busy) 70 return; 71 var cur = this.get_current_index(); 72 var prev_index = cur - 1; 73 if (prev_index < 0) 74 prev_index = slides.length - 1; 75 76 if (opts.infinite_scroll) 77 me.move_to_index(prev_index, -1); 78 else 79 me.move_to_index(prev_index, prev_index < cur ? -1 : 1) 80 }; 81 82 me.next = function() { 83 if (busy) 84 return; 85 var cur = this.get_current_index(); 86 var next_index = cur + 1; 87 if (next_index >= slides.length) 88 next_index = 0; 89 if (opts.infinite_scroll) 90 me.move_to_index(next_index, 1); 91 else 92 me.move_to_index(next_index, next_index < cur ? -1 : 1) 93 }; 94 95 /* 96 direction - 1 - closest position to right 97 -1 - closest position to left 98 */ 99 me.move_to_index = function(new_index, direction, instant) { 100 if (busy) 101 return; 102 busy = true; 103 setTimeout(function() { 104 busy = false; 105 }, 1000); 106 107 if (slides.length < 2) 108 return; 109 if (typeof instant == 'undefined') 110 instant = false; 111 112 var cur_index = this.get_current_index(); 113 if (cur_index == new_index && !instant) { 114 return; 115 } 116 117 var distance_from_left = new_index < cur_index ? (cur_index - new_index) : (slides.length + cur_index - new_index); 118 var distance_from_right = new_index > cur_index ? (new_index - cur_index) : (slides.length + new_index - cur_index); 119 120 var total_length = 0; 121 if (direction == 1) { 122 var i = cur_index; 123 for(var n=0; n<distance_from_right; n++) { 124 total_length += slides[i].width() + opts.slide_spacing; 125 i++; 126 if (i >= slides.length) { 127 i = 0; 128 } 129 } 130 } else { 131 var i = cur_index; 132 for(var n=0; n<distance_from_left; n++) { 133 total_length -= slides[i].width() + opts.slide_spacing; 134 i--; 135 if (i < 0) { 136 i = slides.length - 1; 137 } 138 } 139 } 140 141 move_to_nearest_animation(left_position - total_length, instant); 142 143 me.update_index(new_index); 144 } 145 146 me.get_slides = function() { 147 return slides; 148 }; 149 150 me.update_index = function(new_index) { 151 if (typeof new_index == 'undefined') { 152 new_index = me.get_current_index(); 153 } 154 if (opts.show_buttons && jq_btns) { 155 jq_btns.find('.active').removeClass('active'); 156 jq_btns.find('a:nth-child(' + (new_index+1) + ')').addClass('active'); 157 } 158 159 opts.index_update(me, new_index); 160 } 161 me.impulse = function(amt) { 162 impulse(amt); 163 } 164 165 me.get_current_index = function() {
166 var min_index = 0; 167 168 if (opts.move_to_nearest_mode == 'center') { 169 var center_pos = jq_width/2 - left_position; 170 var min_distance = -1; 171 for(var i in slides) { 172 var slide_pos = slides[i].position().left + slides[i].width()/2; 173 var dist = Math.abs(center_pos - slide_pos); 174 if (min_distance == -1 || dist < min_distance) { 175 min_distance = dist; 176 min_index = i; 177 } 178 } 179 if (extra_before.length) { 180 for(var i in extra_before) { 181 var slide_pos = extra_before[i].position().left + extra_before[i].width()/2; 182 var dist = Math.abs(center_pos - slide_pos); 183 if (dist < min_distance) { 184 min_index = (slides.length - (i % slides.length)); 185 min_distance = dist; 186 } 187 } 188 } 189 if (extra_after.length) { 190 for(var i in extra_after) { 191 var slide_pos = extra_after[i].position().left + extra_after[i].width()/2; 192 var dist = Math.abs(center_pos - slide_pos); 193 if (dist < min_distance) { 194 min_index = i % slides.length; 195 min_distance = dist; 196 } 197 } 198 } 199 } else if (opts.move_to_nearest_mode == 'left') { 200 var left_pos = -left_position; 201 var min_distance = -1; 202 for(var i in slides) { 203 var slide_pos = slides[i].position().left; 204 var dist = Math.abs(left_pos - slide_pos); 205 if (min_distance == -1 || dist < min_distance) { 206 min_distance = dist; 207 min_index = i; 208 } 209 } 210 if (extra_before.length) { 211 for(var i in extra_before) { 212 var slide_pos = extra_before[i].position().left; 213 var dist = Math.abs(left_pos - slide_pos); 214 if (dist < min_distance) { 215 min_index = (slides.length - (i % slides.length)); 216 min_distance = dist; 217 } 218 } 219 } 220 if (extra_after.length) { 221 for(var i in extra_after) { 222 var slide_pos = extra_after[i].position().left; 223 var dist = Math.abs(left_pos - slide_pos); 224 if (dist < min_distance) { 225 min_index = i % slides.length; 226 min_distance = dist; 227 } 228 } 229 } 230 } 231 232 return ~~min_index; 233 }; 234 function create_zoom_button(slide) { 235 var btn_zoom = jQuery('<a href="#" class="btn-zoom"></a>'); 236 btn_zoom.click(function(ev) { 237 var src = slide.css('background-image'); 238 src = src.replace('url(','').replace(')','').replace(/\"/g, "").replace(/\'/g, ""); 239 240 new image_zoom(jq, src); 241 242 ev.stopPropagation(); 243 ev.preventDefault(); 244 return false; 245 }); 246 247 return btn_zoom; 248 } 249 250 function create_fullscreen_button() { 251 var is_fullscreen = false; 252 var btn = jQuery('<a href="#" class="btn-fullscreen"></a>'); 253 btn.click(function() { 254 is_fullscreen = !is_fullscreen; 255 256 if (is_fullscreen) { 257 jq.addClass('fullscreen'); 258 var index = me.get_current_index(); 259 jq.css({ 260 position: 'fixed', 261 top: 0, 262 left: 0, 263 right: 0, 264 bottom: 0, 265 height: 'auto', 266 width: 'auto' 267 }); 268 jq.find('.container').css('height', '100%'); 269 jq.find('ul').css('height', '100%'); 270 jq.find('li').each(function() { 271 jQuery(this).css({width: '100%'}); 272 }); 273 jq_width = 0; 274 jq_win.resize(); 275 me.move_to_index(index, 1, true); 276 impulse(0.5); 277 } else { 278 jq.removeClass('fullscreen'); 279 var index = me.get_current_index(); 280 jq.css({ 281 position: '', 282 top: '', 283 left: '', 284 right: '', 285 bottom: '', 286 height: '', 287 width: '' 288 }); 289 jq.find('.container').css('height', ''); 290 jq.find('ul').css('height', '100%'); 291 jq.find('li').each(function() { 292 jQuery(this).css({width: ''}); 293 }); 294 jq_width = 0; 295 jq_win.resize(); 296 me.move_to_index(index, 1, true); 297 impulse(0.5); 298 } 299 return false; 300 }); 301 302 jq.append(btn); 303 } 304 function init() { 305 jq.addClass('slider-init').css('position', 'relative'); 306 container.css({ 307 position: 'absolute', 308 top: 0, 309 left: 0, 310 transform: 'translateX(0px)', 311 width: '100%', 312 height: '100%', 313 display: 'block', 314 'list-style': 'none' 315 }); 316 container.wrap('<div class="container" style="position:relative;overflow:hidden;width:100%;" />'); 317 318 container.find('li').each(function() { 319 var slide = jQuery(this); 320 slide.css({ 321 position: 'absolute', 322 'list-style':'none', 323 display: 'block', 324 height: '100%', 325 'background-size':'cover', 326 'background-repeat':'no-repeat', 327 'background-position':'center' 328 }); 329 slides.push(slide); 330 331 if (opts.zoom_button) { 332 slide.append(create_zoom_button(slide)); 333 } 334 }); 335 336 if (opts.fullscreen_button) { 337 create_fullscreen_button(); 338 } 339 340 calculate(); 341 342 position(); 343 344 width_listener(); 345 346 touch_listener(); 347 348 adjust_left_position(); 349 350 move_to_nearest(true, true); 351 352 check_infinite_slides(); 353 354 create_navigation_buttons(); 355 356 opts.after_create(me); 357 358 if (opts.auto_rotate) { 359 tmr_auto_rotate = setInterval(function() { 360 me.next(); 361 }, opts.auto_rotate_delay); 362 } 363 } 364 function cancel_auto_rotate() { 365 if (tmr_auto_rotate) { 366 clearInterval(tmr_auto_rotate); 367 tmr_auto_rotate = 0; 368 } 369 } 370 function create_navigation_buttons() { 371 if (opts.show_prev_next && slides.length > 1) { 372 var btn_prev = jQuery('<a href="#" class="btn-prev"></a>'); 373 btn_prev.click(function() { 374 cancel_auto_rotate(); 375 me.prev(); 376 return false;
377 }); 378 379 var btn_next = jQuery('<a href="#" class="btn-next"></a>'); 380 btn_next.click(function() { 381 cancel_auto_rotate(); 382 me.next(); 383 return false; 384 }); 385 jq.append(btn_prev, btn_next); 386 } 387 if (opts.show_buttons && slides.length > 1) { 388 function create_button(index) { 389 var btn = jQuery('<a href="#"></a>'); 390 btn.click(function() { 391 cancel_auto_rotate(); 392 me.move_to_index(index, index > me.get_current_index() ? 1 : -1); 393 return false; 394 }); 395 if (index == 0) 396 btn.addClass('active'); 397 return btn; 398 } 399 400 jq_btns = jQuery('<div class="buttons" />'); 401 for(var i=0; i<slides.length; i++) { 402 jq_btns.append(create_button(i)); 403 } 404 jq.append(jq_btns); 405 } 406 } 407 function check_infinite_slides() { 408 if (opts.infinite_scroll && slides.length) { 409 extra_before_width = 0; 410 for(var i in extra_before) { 411 var w = extra_before[i].width() + opts.slide_spacing; 412 extra_before[i].css({left: -extra_before_width - w}); 413 extra_before_width += w; 414 } 415 while(extra_before_width < jq_width*2) { 416 var next_index = slides.length - 1 - extra_before.length; 417 while(next_index < 0) 418 next_index += slides.length; 419 420 var new_slide = slides[next_index].clone(true,true); 421 new_slide.addClass('extra' + extra_before.length); 422 container.prepend(new_slide); 423 var w = new_slide.width() + opts.slide_spacing;
424 if (w <= opts.slide_spacing) 425 return; 426 new_slide.css({left: -extra_before_width -w}); 427 extra_before_width += w; 428 extra_before.push(new_slide); 429 } 430 431 extra_after_width = 0; 432 for(var i in extra_after) { 433 extra_after[i].css({left:max_position + extra_after_width}); 434 var w = extra_after[i].width() + opts.slide_spacing 435 extra_after_width += w; 436 } 437 while(extra_after_width < jq_width*2) { 438 var next_index = extra_after.length; 439 while(next_index >= slides.length) 440 next_index -= slides.length; 441 442 var new_slide = slides[next_index].clone(true,true); 443 new_slide.addClass('extra' + extra_after.length); 444 container.append(new_slide); 445 new_slide.css({left:max_position + extra_after_width}); 446 var w = new_slide.width() + opts.slide_spacing; 447 if (w <= opts.slide_spacing) 448 return; 449 extra_after_width += w; 450 extra_after.push(new_slide); 451 } 452 } 453 } 454 455 function move_container(left) { 456 457 if (!opts.infinite_scroll) { 458 if (left > 0) 459 left = 0; 460 if (left < -max_item_position) 461 left = -max_item_position; 462 } 463 container.css({ 464 transform: 'translateX(' + ~~left + 'px)' 465 }); 466 if (typeof opts.x_update != 'undefined') 467 opts.x_update(~~left, max_position); 468 } 469 function move_to_nearest_animation(new_position, instant) { 470 if (instant) { 471 left_position = new_position; 472 move_container(left_position); 473 me.update_index(); 474 } else { 475 var iterations = 20; 476 var move_delta = (new_position - left_position) / iterations; 477 if (move_delta < 1 && move_delta > 0) { 478 move_delta = 1; 479 } else if (move_delta > -1 && move_delta < 0) { 480 move_delta = -1; 481 } 482 var i = 0; 483 clearInterval(tmr_nearest); 484 tmr_nearest = setInterval(function() { 485 if (i < iterations) { 486 left_position += move_delta; 487 adjust_left_position(); 488 i++; 489 move_container(left_position); 490 } else { 491 me.update_index(); 492 clearInterval(tmr_nearest); 493 } 494 }, 16); 495 } 496 } 497 function move_to_nearest(instant, first_index) { 498 if (typeof instant == 'undefined') 499 instant = false; 500 if (typeof first_index == 'undefined') 501 first_index = false; 502 503 if (opts.move_to_nearest_mode == 'center') { 504 var center_pos = jq_width/2 - left_position; 505 var min_distance = -1; 506 var min_slide_pos = 0; 507 for(var i in slides) { 508 var slide_pos = slides[i].position().left + slides[i].width()/2; 509 var dist = Math.abs(center_pos - slide_pos); 510 if (first_index) { 511 min_slide_pos = slide_pos; 512 break; 513 } else if (min_distance == -1 || dist < min_distance) { 514 min_distance = dist; 515 min_slide_pos = slide_pos; 516 } 517 } 518 if (!first_index) { 519 if (extra_before.length) { 520 for(var i in extra_before) { 521 var slide_pos = extra_before[i].position().left + extra_before[i].width()/2; 522 var dist = Math.abs(center_pos - slide_pos); 523 if (dist < min_distance) { 524 min_slide_pos = slide_pos; 525 min_distance = dist; 526 } 527 } 528 } 529 if (extra_after.length) { 530 for(var i in extra_after) { 531 var slide_pos = extra_after[i].position().left + extra_after[i].width()/2; 532 var dist = Math.abs(center_pos - slide_pos); 533 if (dist < min_distance) { 534 min_slide_pos = slide_pos; 535 min_distance = dist; 536 } 537 } 538 } 539 } 540 541 move_to_nearest_animation(-min_slide_pos + jq_width/2, instant); 542 } else if (opts.move_to_nearest_mode == 'left') { 543 var left_pos = -left_position; 544 var min_distance = -1; 545 var min_slide_pos = 0; 546 for(var i in slides) { 547 var slide_pos = slides[i].position().left; 548 var dist = Math.abs(left_pos - slide_pos); 549 if (first_index) { 550 min_slide_pos = slide_pos 551 break; 552 } else if (min_distance == -1 || dist < min_distance) { 553 min_distance = dist; 554 min_slide_pos = slide_pos; 555 } 556 } 557 if (!first_index) { 558 if (extra_before.length) { 559 for(var i in extra_before) { 560 var slide_pos = extra_before[i].position().left; 561 var dist = Math.abs(left_pos - slide_pos); 562 if (dist < min_distance) { 563 min_slide_pos = slide_pos; 564 min_distance = dist; 565 } 566 } 567 } 568 if (extra_after.length) { 569 for(var i in extra_after) { 570 var slide_pos = extra_after[i].position().left; 571 var dist = Math.abs(left_pos - slide_pos); 572 if (dist < min_distance) { 573 min_slide_pos = slide_pos; 574 min_distance = dist; 575 } 576 } 577 } 578 } 579 580 move_to_nearest_animation(-min_slide_pos, instant); 581 } 582 } 583 function calculate() { 584 jq_width = jq_win.width(); 585 } 586 function position() { 587 var left = 0; 588 for(var i in slides) { 589 slides[i].css({left: left}); 590 591 max_item_position = left; 592 left += slides[i].width() + opts.slide_spacing; 593 } 594 595 max_position = left; 596 } 597 function width_listener() { 598 jq_win.resize(function() { 599 var last_width = jq_width; 600 calculate(); 601 602 if (last_width != jq_width) { 603 position(); 604 move_to_nearest(true); 605 check_infinite_slides(); 606 } 607 }); 608 } 609 function adjust_left_position() { 610 if (opts.infinite_scroll && slides.length) { 611 if (left_position > 0) { 612 left_position -= max_position; 613 } else if (left_position < -max_position) { 614 left_position += max_position; 615 } 616 } 617 } 618 function impulse(speed) { 619 if (speed > 4) 620 speed = 4; 621 else if (speed < -4) 622 speed = -4; 623 624 speed *= (1000 / 32); 625 626 var drag = speed > 0 ? opts.drag : -opts.drag; 627 stop_impulse(); 628 tmr_impulse = setInterval(function() { 629 if ((drag > 0 && speed < opts.min_speed) || (drag < 0 && speed > -opts.min_speed)) { 630 stop_impulse(); 631 move_to_nearest(); 632 me.update_index(); 633 } else { 634 if (isNaN(speed) || isNaN(drag)) { 635 speed = 0.1; 636 drag = 0.1; 637 } 638 speed -= drag; 639 left_position += speed; 640 adjust_left_position(); 641 move_container(left_position); 642 } 643 644 }, 16); 645 } 646 function stop_impulse() { 647 clearInterval(tmr_impulse); 648 } 649 function touch_listener() { 650 var start_x = 0; 651 var start_time = 0; 652 var last_delta = 0; 653 var tmr_stop = 0; 654 655 track_movement(jq.children('.container'), 656 function(x, y) { 657 start_x = x; 658 last_delta = 0; 659 start_time = Date.now(); 660 stop_impulse(); 661 clearInterval(tmr_nearest); 662 }, 663 function (x_delta, y_delta, x, y) { 664 last_delta = x - start_x; 665 move_container(left_position + last_delta); 666 jq.addClass('dragging');
667 clearTimeout(tmr_stop); 668 cancel_auto_rotate(); 669 }, 670 function() { 671 if (last_delta == 0) 672 return; 673 left_position += last_delta; 674 var elapsed = Date.now() - start_time; 675 if (elapsed < 500) { 676 var speed = last_delta / elapsed; 677 impulse(speed); 678 } else { 679 adjust_left_position(); 680 move_to_nearest(); 681 } 682 683 tmr_stop = setTimeout(function() { 684 jq.removeClass('dragging'); 685 }, 35); 686 }, 687 true, true 688 ); 689 } 690 691 init(); 692 693 me.update_index(0); 694 695 return me; 696 } 697} 698function wait_for_dimensions(jq, callback, iterations) { 699 if (typeof iterations == 'undefined') 700 iterations = 0; 701 702 var item = jq.get(0); 703 if (typeof item.naturalWidth != 'undefined' && item.naturalWidth > 0) { 704 callback(item.naturalWidth, item.naturalHeight, iterations); 705 } else { 706 var me = this; 707 //slowly increase the time between each call 708 setTimeout(function () { 709 wait_for_dimensions(jq, callback, ++iterations); 710 }, iterations + 1); 711 } 712} 713function image_zoom(container, src) { 714 var min_zoom = 1.5; 715 var max_zoom = 2.5; 716 var zoom = jQuery('<div class="image-zoom" style="position: absolute;z-index: 10000;top: 0;left: 0;right: 0;bottom: 0;overflow: hidden;background:black;"/>'); 717 var img = jQuery('<img src="' + src + '" style="position:absolute;top:0;left:0;">'); 718 var btn_close = jQuery('<div class="image-zoom-close" style="position:absolute;z-index:10001;top:0;right:0;cursor:pointer;"><span>X</span></div>'); 719 var running = true; 720 721 zoom.append(img, btn_close); 722 container.append(zoom); 723 724 btn_close.click(function () { 725 if (running) { 726 running = false; 727 zoom.remove(); 728 } 729 }); 730 731 wait_for_dimensions(img, function (width, height) { 732 var container_width = zoom.width(); 733 var container_height = zoom.height(); 734 735 var max_width = container_width * max_zoom; 736 var max_height = container_height * max_zoom; 737 var min_width = container_width * min_zoom; 738 var min_height = container_height * min_zoom; 739 740 if (width > max_width) { 741 height = (max_width / width) * height; 742 width = max_width; 743 } else if (width < min_width) { 744 height = (min_width / width) * height; 745 width = min_width; 746 } 747 if (height > max_height) { 748 width = (max_height / height) * width; 749 height = max_height; 750 } else if (height < min_height) { 751 width = (min_height / height) * width; 752 height = min_height; 753 } 754 755 var top = (container_height - height) / 2; 756 var left = (container_width - width) / 2; 757 var min_left = -width + container_width; 758 var min_top = -height + container_height; 759 var updated_left = 0; 760 var updated_top = 0; 761 762 img.css({ 763 width: width, 764 height: height, 765 top: top, 766 left: left 767 }); 768 769 track_movement(zoom, function () { 770 771 }, function (x_delta, y_delta) { 772 updated_top = top + y_delta; 773 updated_left = left + x_delta; 774 775 if (updated_top > 0) 776 updated_top = 0; 777 else if (updated_top < min_top) 778 updated_top = min_top; 779 if (updated_left > 0) 780 updated_left = 0; 781 else if (updated_left < min_left) 782 updated_left = min_left; 783 784 img.css({ 785 top: updated_top, 786 left: updated_left 787 }); 788 }, function () { 789 top = updated_top; 790 left = updated_left; 791 }, true); 792 }); 793} 794 795function track_movement(jq, start_callback, move_callback, release_callback, track_mouse, ignore_y) { 796 var is_down = false; 797 var start_x = 0; 798 var start_y = 0; 799 if (typeof ignore_y == 'undefined') 800 ignore_y = false; 801 if (typeof track_mouse == 'undefined') 802 track_mouse = false; 803 if (track_mouse) 804 jq.mouseleave(function () { 805 if (is_down) { 806 is_down = false; 807 setTimeout(function () { 808 jq.removeClass('noclick'); 809 }, 125); 810 release_callback(); 811 } 812 }); 813 if (track_mouse) 814 jq.on('mousedown', function (ev) { 815 is_down = true; 816 start_x = ev.clientX; 817 start_y = ev.clientY; 818 start_callback(start_x, start_y); 819 return false; 820 }); 821 if (track_mouse) 822 jq.on('mouseup', function (ev) { 823 if (is_down) { 824 is_down = false; 825 setTimeout(function () { 826 jq.removeClass('noclick'); 827 }, 125); 828 release_callback(); 829 } 830 }); 831 if (track_mouse) 832 jq.on('mousemove', function (ev) { 833 if (is_down) { 834 var x_delta = ev.clientX - start_x; 835 var y_delta = ev.clientY - start_y; 836 move_callback(x_delta, y_delta, ev.clientX, ev.clientY); 837 jq.addClass('noclick'); 838 return false;
839 } 840 }); 841 jq.on('touchstart', function (ev) { 842 var touches = ev.originalEvent.touches; 843 if (touches.length >= 1) { 844 start_x = touches[0].clientX; 845 start_y = touches[0].clientY; 846 is_down = true; 847 start_callback(start_x, start_y); 848 } 849 }); 850 jq.on('touchend', function (ev) { 851 if (is_down) { 852 is_down = false; 853 release_callback(); 854 } 855 }); 856 jq.on('touchmove', function (ev) { 857 var touches = ev.originalEvent.touches; 858 if (touches.length >= 1) { 859 var x_delta = touches[0].clientX - start_x; 860 var y_delta = touches[0].clientY - start_y; 861 if (ignore_y && (Math.abs(y_delta) > Math.abs(x_delta))) { 862 return true; 863 } 864 move_callback(x_delta, y_delta, touches[0].clientX, touches[0].clientY); 865 ev.stopImmediatePropagation(); 866 ev.preventDefault(); 867 return false; 868 } 869 }); 870} 871 872 873var FormRules = { 874 //form has fld-form-rules 875 //fields have .fld-validate-me and data-validate-type 876 ruleSets: [], 877 878 init: function () { 879 var me = this; 880 jQuery('form.fld-form-rules').each(function (index, value) { 881 jQuery(this).attr('data-validation-id', index); 882 me.ruleSets[index] = { 883 form: jQuery(this), 884 fields: [], 885 }; 886 me.ruleSets[index].form.find('.fld-validate-me:not(.customselect)').each(function (fieldIndex, fieldValue) { 887 var field = jQuery(this); 888 field.attr('data-validation-id', fieldIndex); 889 890 var type = field.data('validate-type'); 891 892 if (typeof type == "undefined" || type == "") { 893 var field_type = field.attr('type'); 894 if (field.is('select')) { 895 type = 'dropdown'; 896 } else if (field_type == 'email') { 897 type = 'email'; 898 } else if (field_type == 'checkbox') { 899 type = 'checkbox'; 900 } else { 901 type = 'text'; 902 } 903 } 904 905 906 var msg = ''; 907 908 if (type == 'email') { 909 msg = '*Oops! That’s not a valid email address.'; 910 } else if (type == 'text') { 911 msg = '*Please fill out this field.'; 912 } else if (type == 'checkbox' || type == 'checklist') { 913 msg = '*This is a required field.'; 914 } else if (type == 'dropdown') { 915 msg = '*Please select an item in the list.'; 916 } else if (type == 'credit_card') { 917 msg = '*Oops! That’s not a valid credit card number. Please enter the number only, no spaces or dashes.'; 918 } 919 920 var error_text = false; 921 if (msg.length > 0) { 922 error_text = jQuery('<span class="error-text" style="display:none">' + msg + '</span>'); 923 if (type == 'checklist' && !jQuery(this).hasClass('selection-boxes')) { 924 jQuery(this).append(error_text); 925 } else if (type == 'checkbox' || type == 'dropdown') { 926 //jQuery(this).parent().after(error_text); 927 jQuery(this).after(error_text); 928 } else { 929 jQuery(this).after(error_text); 930 } 931 } 932 933 me.ruleSets[index].fields[fieldIndex] = { 934 field: field, 935 type: type, //text, dropdown, email, credit_card, checkbox, checklist 936 error_text: error_text 937 }; 938 field.blur(function () { 939 me.validateField(me.ruleSets[index].fields[fieldIndex], false); 940 }); 941 field.change(function () { 942 me.validateField(me.ruleSets[index].fields[fieldIndex], false); 943 }); 944 field.keyup(function () { 945 me.validateField(me.ruleSets[index].fields[fieldIndex], false); 946 }); 947 }); 948 }); 949 }, 950 951 validate: function (formJq) { 952 var me = this; 953 var ruleSet = formJq.data('validation-id'); 954 var valid = true; 955 for (var i = 0; i < me.ruleSets[ruleSet].fields.length; i++) { 956 var data = me.ruleSets[ruleSet].fields[i]; 957 var result = me.validateField(data, valid); 958 if (!result) { 959 valid = false; 960 } 961 } 962 963 return valid; 964 }, 965 966 validateField: function (data, bFocus) { 967 var field = data.field; 968 var field_val = ""; 969 970 if (typeof data.type == 'undefined') { 971 data.type = 'text'; 972 } 973 974 if (field.data('validate-if-visible')) { 975 if (!field.is(':visible')) { 976 if (data.error_text) { 977 data.error_text.hide(); 978 } 979 return true; 980 } 981 } 982 983 984 if (data.type == 'text' || data.type == 'dropdown' || data.type == 'email' || data.type == 'credit_card') { 985 field_val = field.val(); 986 987 if (field.data('default_text') == field_val) { 988 field_val = ""; 989 } 990 991 } else if (data.type == 'checkbox') { 992 if (field.prop('checked')) 993 field_val = field.val(); 994 else 995 field_val = ""; 996 } else if (data.type == 'checklist') { 997 var list = field.find('input'); 998 var values = []; 999 for (var i = 0; i < list.length; i++) { 1000 var chk = jQuery(list[i]); 1001 if (chk.prop('checked')) 1002 values.push(chk.attr('value')); 1003 } 1004 } 1005
1006 var valid = false; 1007 if (data.error_text) { 1008 data.error_text.hide(); 1009 } 1010 1011 if (data.type == 'dropdown') { 1012 if (field_val == "") { 1013 field.addClass('error'); 1014 if (field.parent().children('.customselect').length > 0) 1015 field.parent().children('.customselect').addClass('error'); 1016 valid = false; 1017 if (bFocus) 1018 field.focus(); 1019 } else { 1020 field.removeClass('error'); 1021 if (field.parent().children('.customselect').length > 0) 1022 field.parent().children('.customselect').removeClass('error'); 1023 valid = true; 1024 } 1025 } else if (data.type == 'text') { 1026 if ((field_val == "") || 1027 (typeof data.minlength != 'undefined' && field_val.length < data.minlength)) { 1028 field.addClass('error'); 1029 valid = false; 1030 if (bFocus) 1031 field.focus(); 1032 } else { 1033 field.removeClass('error'); 1034 valid = true; 1035 } 1036 } else if (data.type == 'credit_card') { 1037 if (field_val == "" || !this.is_credit_card(field_val)) { 1038 field.addClass('error'); 1039 valid = false; 1040 if (bFocus) 1041 field.focus(); 1042 } else { 1043 field.removeClass('error'); 1044 valid = true; 1045 } 1046 } else if (data.type == 'email') { 1047 valid = true; 1048 if (field_val == "") { 1049 valid = false; 1050 } else { 1051 var exp = /^([\w-\.]+@([\w-]+\.)+[\w-]{2,16})?$/; 1052 var re = new RegExp(exp); 1053 var match = re.exec(field_val); 1054 if (match == null) 1055 valid = false; 1056 } 1057 1058 if (valid) { 1059 field.removeClass('error'); 1060 } else { 1061 field.addClass('error'); 1062 if (bFocus) 1063 field.focus(); 1064 } 1065 } else if (data.type == 'checkbox') { 1066 var fld = field.parent('label'); 1067 if (field_val == "") { 1068 fld.addClass('error'); 1069 valid = false; 1070 if (bFocus) 1071 field.focus(); 1072 } else { 1073 fld.removeClass('error'); 1074 valid = true; 1075 } 1076 } else if (data.type == 'checklist') { 1077 if (values.length == 0) { 1078 field.addClass('error'); 1079 valid = false; 1080 if (bFocus) { 1081 var pos = field.find('input').parent(); 1082 jQuery('body,html').scrollTop(pos.offset().top - 140); 1083 } 1084 } else { 1085 field.removeClass('error'); 1086 valid = true; 1087 } 1088 } 1089 1090 if (!valid && data.error_text) { 1091 data.error_text.css('display', 'block'); 1092 } 1093 1094 field.trigger('fld-error-response'); 1095 return valid; 1096 }, 1097 1098 is_credit_card: function (number) { 1099 var sum = 0; 1100 var mul = 1; 1101 1102 for (var i = 0; i < number.length; i++) { 1103 var digit = number.substring(number.length - i - 1, number.length - i); 1104 var tproduct = parseInt(digit, 10) * mul; 1105 if (tproduct >= 10) 1106 sum += (tproduct % 10) + 1; 1107 else 1108 sum += tproduct; 1109 1110 mul = 3 - mul; 1111 } 1112 1113 if ((sum % 10) == 0) 1114 return true; 1115 else 1116 return false; 1117 } 1118}; 1119 1120var FormValidationErrorResponse = { 1121 //for error response after input field, just add .error:after css with the message 1122 errorBoxes: [], 1123 1124 init: function () { 1125 var me = this; 1126 jQuery('form.fld-error-response').each(function (index, value) { 1127 var form = jQuery(this); 1128 me.errorBoxes[index] = jQuery('#' + form.data('error-response-box')).length == 0 ? null : jQuery('#' + form.data('error-response-box')); 1129 1130 form.find('.fld-validate-me').each(function (fieldIndex, fieldValue) { 1131 var field = jQuery(this); 1132 field.on('fld-error-response', function () { 1133 if (field.hasClass('error')) { 1134 if (me.errorBoxes[index] != null) { 1135 if (me.errorBoxes[index].find('.' + field.attr('name')).length == 0) { 1136 me.errorBoxes[index].append('<div class="' + field.attr('name') + ' error-response">' + field.data('error-response-text') + '</div>'); 1137 } 1138 } 1139 1140 } else { 1141 if (me.errorBoxes[index] != null) { 1142 me.errorBoxes[index].find('.' + field.attr('name')).remove(); 1143 } 1144 } 1145 }); 1146 }); 1147 }); 1148 }, 1149} 1150 1151function getPageScroll() { 1152 return document.body.scrollTop || jQuery(window).scrollTop(); 1153} 1154 1155function wait_for_visible(jq, callback, delay_callback) { 1156 if (jq.length == 0) 1157 return; 1158 1159 if (typeof delay_callback == 'undefined') 1160 delay_callback = 10; 1161 1162 var jq_win = jQuery(window); 1163 1164 var chk_timer = setInterval(function () { 1165 if (jq.is(':visible')) { 1166 var t = getPageScroll(); 1167 var h = jq_win.height(); 1168 var item_pos = jq.offset().top; 1169 if (item_pos > t && item_pos < t + h) { 1170 clearInterval(chk_timer); 1171 setTimeout(function () { 1172 callback(jq); 1173 }, delay_callback); 1174 } 1175 } 1176 }, 250); 1177 1178 return chk_timer; 1179} 1180 1181(function () { 1182 var lastTime = 0; 1183 var vendors = ['ms', 'moz', 'webkit', 'o']; 1184 for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { 1185 window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame']; 1186 window.cancelAnimationFrame = window[vendors[x] + 'CancelAnimationFrame'] 1187 || window[vendors[x] + 'CancelRequestAnimationFrame']; 1188 } 1189 1190 if (!window.requestAnimationFrame) 1191 window.requestAnimationFrame = function (callback, element) { 1192 var currTime = new Date().getTime(); 1193 var timeToCall = Math.max(0, 16 - (currTime - lastTime)); 1194 var id = window.setTimeout(function () { callback(currTime + timeToCall); }, 1195 timeToCall); 1196 lastTime = currTime + timeToCall; 1197 return id; 1198 }; 1199 1200 if (!window.cancelAnimationFrame) 1201 window.cancelAnimationFrame = function (id) { 1202 clearTimeout(id); 1203 }; 1204}()); 1205 1206(function () { 1207 // Reasonable defaults 1208 var PIXEL_STEP = 10; 1209 var LINE_HEIGHT = 40; 1210 var PAGE_HEIGHT = 800; 1211 1212 window.normalizeWheel = function (/*object*/ event) /*object*/ { 1213 1214 var sX = 0, sY = 0, // spinX, spinY 1215 pX = 0, pY = 0; // pixelX, pixelY 1216 1217 // Legacy 1218 if ('detail' in event) { sY = event.detail; } 1219 if ('wheelDelta' in event) { sY = -event.wheelDelta / 120; } 1220 if ('wheelDeltaY' in event) { sY = -event.wheelDeltaY / 120; } 1221 if ('wheelDeltaX' in event) { sX = -event.wheelDeltaX / 120; } 1222 1223 // side scrolling on FF with DOMMouseScroll 1224 if ('axis' in event && event.axis === event.HORIZONTAL_AXIS) { 1225 sX = sY; 1226 sY = 0; 1227 } 1228 1229 pX = sX * PIXEL_STEP; 1230 pY = sY * PIXEL_STEP; 1231 1232 if ('deltaY' in event) { pY = event.deltaY; } 1233 if ('deltaX' in event) { pX = event.deltaX; } 1234 1235 if ((pX || pY) && event.deltaMode) { 1236 if (event.deltaMode == 1) { // delta in LINE units 1237 pX *= LINE_HEIGHT; 1238 pY *= LINE_HEIGHT; 1239 } else { // delta in PAGE units 1240 pX *= PAGE_HEIGHT; 1241 pY *= PAGE_HEIGHT; 1242 } 1243 } 1244 1245 // Fall-back if spin cannot be determined 1246 if (pX && !sX) { sX = (pX < 1) ? -1 : 1; } 1247 if (pY && !sY) { sY = (pY < 1) ? -1 : 1; } 1248 1249 return { 1250 spinX: sX, 1251 spinY: sY, 1252 pixelX: pX, 1253 pixelY: pY 1254 }; 1255 }; 1256})(); 1257 1258var video = { 1259 // Instances are indexed by the video id rather than 1,2,3,etc so that videos are able to be 1260 // accessed if they get shuffled around in the UI 1261 instances: new Object(), 1262 1263 // Initialize the videos 1264 // opts - an object of options for the videos. With no options set, the videos will default 1265 // - to a looping, muted background video 1266 init: function (opts) { 1267 if (typeof opts.selector == 'undefined') 1268 opts.selector = '.fld-video'; 1269 if (typeof opts.autoplay == 'undefined') 1270 opts.autoplay = true; 1271 if (typeof opts.controls == 'undefined') 1272 opts.controls = 'none'; 1273 if (typeof opts.loop == 'undefined') 1274 opts.loop = true; 1275 if (typeof opts.muted == 'undefined') 1276 opts.muted = true; 1277 if (typeof opts.playBtn == 'undefined') { 1278 opts.playBtn = 'images/play-btn.svg'; 1279 } 1280 if (typeof opts.pauseBtn == 'undefined') { 1281 opts.pauseBtn = 'images/pause-btn.svg'; 1282 } 1283 1284 jQuery(opts.selector).each(function () { 1285 video.buildVideoHTML(jQuery(this), opts); 1286 }); 1287 1288 // Hover In: 1289 // - Requests a gif of the video, and displays it once it is ready. 1290 // - If the gif already exists, show the gif 1291 // Hover Out: 1292 // - Hide the gif 1293 jQuery(opts.selector).hover(function () { 1294 var previews = jQuery(this).find('.video-previews'); 1295 var gif = jQuery(this).find('.gif'); 1296 if (jQuery(window).width() > 760 && gif.length == 0) { 1297 var id = jQuery(this).data('id'); 1298 var gif = jQuery('<img class="gif" src="https://videodelivery.net/' + id + '/thumbnails/thumbnail.gif?time=0s&duration=1s">'); 1299 gif.on('load', function () { 1300 previews.append(gif); 1301 }); 1302 } else { 1303 previews.find('.gif').show(); 1304 } 1305 }, function () { 1306 var previews = jQuery(this).find('.video-previews'); 1307 previews.find('.gif').hide(); 1308 }); 1309 1310 // Hides the video previews (thumbnail and gif) and filter and plays the video 1311 jQuery(opts.selector).click(function () { 1312 var id = jQuery(this).data('id'); 1313 jQuery(this).addClass('playing'); 1314 // video.instances[id].player.play().catch(function() { 1315 // video.instances[id].player.muted = true; 1316 // video.instances[id].player.play(); 1317 // }); 1318 }); 1319 1320 }, 1321 1322 // Create the HTML of the video previews and video. Video properties have defaults, 1323 // but can be changed by setting the data-{property} attriutes 1324 // jq - a jQuery object of an instance of the selector specified in the init function 1325 // opts - an object of options for the videos. 1326 buildVideoHTML: function (jq, opts) { 1327 if (jq.data('id') !== undefined) { 1328 var id = jq.data('id'); 1329 var html = jQuery('<div class="filter"><div class="button" style="background-image: url(' + opts.playBtn + ')"></div></div><div class="video-previews"><img class="still" src="https://videodelivery.net/' + id + '/thumbnails/thumbnail.jpg?time=0s&fit=fill"></div><iframe class="video" src="https://iframe.videodelivery.net/' + id + '" allow="autoplay; accelerometer; gyroscope; encrypted-media; picture-in-picture;" allowfullscreen="true"></iframe>'); 1330 jq.append(html); 1331 video.instances[id] = { 1332 jq: jq, 1333 player: Stream(jq.find('.video')[0]), 1334 playBtn: opts.playBtn, 1335 pauseBtn: opts.pauseBtn 1336 } 1337 var controls = (typeof jq.data('controls') !== 'undefined' ? jq.data('controls') : opts.c
1337ontrols); 1338 if (controls == 'full') { 1339 video.instances[id].player.controls = true; 1340 } else { 1341 video.instances[id].player.controls = false; 1342 } 1343 // video.instances[id].player.controls = (typeof jq.data('controls') !== 'undefined' ? jq.data('controls') : opts.controls); 1344 video.instances[id].player.autoplay = (typeof jq.data('autoplay') !== 'undefined' ? jq.data('autoplay') : opts.autoplay); 1345 video.instances[id].player.muted = (typeof jq.data('muted') !== 'undefined' ? jq.data('muted') : opts.muted); 1346 video.instances[id].player.loop = (typeof jq.data('loop') !== 'undefined' ? jq.data('loop') : opts.loop); 1347 1348 if (video.instances[id].player.autoplay) { 1349 video.instances[id].player.play(); 1350 } 1351 1352 if (controls == 'none') { 1353 jq.find('.filter').remove(); 1354 1355 video.instances[id].player.addEventListener('canplay', function () { 1356 jq.find('.video-previews').remove(); 1357 }); 1358 } else if (controls == 'limited') { 1359 jq.find('.filter').css('pointer-events', 'all'); 1360 1361 jq.find('.filter').click(function () { 1362 if (video.instances[id].player.paused) { 1363 video.instances[id].player.play(); 1364 } else { 1365 video.instances[id].player.pause(); 1366 } 1367 }); 1368 } else if (controls == 'full') { 1369 jq.find('.filter').click(function () { 1370 jQuery(this).remove(); 1371 video.instances[id].player.play(); 1372 }); 1373 } 1374 1375 video.instances[id].player.addEventListener('play', function () { 1376 video.onPlay(video.instances[id]); 1377 }); 1378 video.instances[id].player.addEventListener('pause', function () { 1379 video.onPause(video.instances[id]); 1380 }); 1381 } 1382 }, 1383 1384 onPlay: function (instance) { 1385 instance.jq.removeClass('paused'); 1386 instance.jq.find('.button').css('background-image', 'url("' + instance.pauseBtn + '")'); 1387 }, 1388 onPause: function (instance) { 1389 instance.jq.addClass('paused'); 1390 instance.jq.find('.button').css('background-image', 'url("' + instance.playBtn + '")'); 1391 } 1392} 1393 1394 1395 1396const isInViewport = (elem, direction) => { 1397 var bounding = elem.getBoundingClientRect(); 1398 1399 if (direction === 'left') { 1400 return ( 1401 bounding.right >= 0 1402 ); 1403 } else { 1404 return ( 1405 bounding.left <= window.innerWidth 1406 ); 1407 } 1408};
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.