1/*! Frame Carousel - v0.1.0 - 2017-02-17 2 * http://www.eastros.com/frame-carousel/ 3 * Copyright (c) 2017 Umar Ashfaq; Licensed MIT */ 4/*! Frame Carousel - v0.1.0 - 2015-06-09 5 * http://www.eastros.com/frame-carousel/ 6 * Copyright (c) 2015 Umar Ashfaq; Licensed MIT */ 7 8(function($) { 9 var template = 10 "<div class='fc-controls'>" + 11 "<a href='#' rel='go-left' class='fc-btn fc-btn-left'></a>" + 12 "<a href='#' rel='go-right' class='fc-btn fc-btn-right'></a>" + 13 "</div>" + 14 "<div class='fc-pagination'>" + 15 "<div class='fc-pagination-inner'>" + 16 "</div>" + 17 "</div>" + 18 "<div class='fc-image-mask'>" + 19 "<div class='fc-film'></div>" + 20 "</div>", 21 events = { 22 touchstart: "touchstart mousedown", 23 touchmove: "touchmove mousemove", 24 touchend: "touchend mouseup", 25 touchcancel: "touchcancel", 26 touchleave: "touchleave mouseout", 27 transitionend: 28 "transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd" 29 }, 30 /* 31 getPercentage = function($el, property) { 32 var v = $el[0].style[property], 33 iop = v.indexOf('%'); 34 35 if ( iop ) { 36 v = v.substring(0, iop); 37 } 38 39 return parseFloat(v); 40 }, 41 */ 42 43 /** 44 * A utility function that gives access to a CSS 'background-image'. 45 * Used internally. 46 */ 47 getImage = function(path) { 48 var tempImg = $("<img />"), 49 d = $.Deferred(); 50 51 tempImg.hide(); //hide image 52 tempImg.bind("load", function() { 53 d.resolve($(this)); 54 }); 55 $("body").append(tempImg); // add to DOM before </body> 56 tempImg.attr("src", path); 57 $("#tempImg").remove(); //remove from DOM 58 59 return d; 60 }, 61 getPosition = function(e) { 62 var event = e.originalEvent || e, 63 r; 64 65 if (event.touches && event.touches.length) { 66 r = { 67 x: event.touches[0].pageX, 68 y: event.touches[0].pageY 69 }; 70 } else if (event.changedTouches && event.changedTouches.length) { 71 r = { 72 x: event.changedTouches[0].pageX, 73 y: event.changedTouches[0].pageY 74 }; 75 } else if (event.pageX !== undefined) { 76 r = { 77 x: event.pageX, 78 y: event.pageY 79 }; 80 } else { 81 r = { 82 x: event.clientX, 83 y: event.clientY 84 }; 85 } 86 87 return r; 88 }, 89 getValidFrameSize = function() { 90 // current screen width 91 var csw = $(window).width(), 92 isValid = function(fs) { 93 var r = false; 94 95 if (fs.minScreenWidth && fs.maxScreenWidth) { 96 r = csw >= fs.minScreenWidth && csw <= fs.maxScreenWidth; 97 } else if (fs.maxScreenWidth) { 98 r = csw <= fs.maxScreenWidth; 99 } else if (fs.minScreenWidth) { 100 r = csw >= fs.minScreenWidth; 101 } else { 102 r = true; 103 } 104 105 return r; 106 }, 107 r; 108 109 this.options.frameSize.every(function(fs) { 110 if (isValid(fs)) { 111 r = fs; 112 return false; 113 } 114 115 return true; 116 }, this); 117 118 return r; 119 }, 120 setupDefaults = function() { 121 var dirSample = 122 $('script[src*="frame-carousel"]') 123 .attr("src") // the js file path 124 .replace("jquery.frame-carousel.js", "") 125 .replace("jquery.frame-carousel.min.js", "") + "sample/"; 126 127 this.options = $.extend( 128 { 129 first: 0, 130 debug: false, 131 name: ["OYA School"], 132 link: "#", 133 swipeThreshold: 10, 134 frame: dirSample + "frame.png", 135 frameSize: [ 136 { width: 600, minScreenWidth: 1200 }, 137 { width: 500, maxScreenWidth: 1199, minScreenWidth: 768 }, 138 { width: 300, maxScreenWidth: 767 } 139 ], 140 boundingBox: { 141 left: "4.3%", 142 top: "4.48%", 143 width: "91.4%", 144 height: "61.1%" 145 }, 146 collapseThreshold: 319, 147 images: (function() { 148 return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(function(n) { 149 return dirSample + n + ".jpg"; 150 }); 151 })(), 152 controlsPosition: { 153 top: "35%" 154 }, 155 autoplay: false, 156 autoplayInterval: 2000 157 }, 158 this.options 159 ); 160 161 return getImage(this.options.frame).then( 162 $.proxy(function($img) { 163 // update frameSize array 164 165 // original frame size 166 var ofs = { 167 width: $img.width(), 168 height: $img.height() 169 }, 170 // original frame aspect ratio 171 ofar = ofs.width / ofs.height; 172 173 this.options.frameSize = this.options.frameSize.map(function(fs) { 174 // set 1 175 // case: height / width 176 // case: height / no width 177 // case: width / no height 178 // case: no width / no height 179 if (fs.width && fs.height) { 180 } else if (!fs.width && fs.height) { 181 fs.width = fs.height * ofar; 182 } else if (fs.width && !fs.height) { 183 fs.height = fs.width / ofar; 184 } else if (!fs.width && !fs.height) { 185 fs.width = ofs.width; 186 fs.height = ofs.height; 187 } 188 189 return fs; 190 }); 191 192 this.options.frameSize.push(ofs); 193 194 this.attributes = $.extend(this.attributes, { 195 originalFrameSize: ofs, 196 current: 0, 197 id: new Date().getTime(), 198 originalStyleValue: this.$el.attr("style") || "", 199 originalClassValue: this.$el.attr("class") || "" 200 }); 201 }, this) 202 ); 203 }, 204 onClickGoLeft = function() { 205 this.previous(); 206 return false;
207 }, 208 onClickGoRight = function() { 209 this.next(); 210 return false; 211 }, 212 onSwipeBegin = function(event) { 213 var p = getPosition(event), 214 sw = this.elements.$mask.width(), 215 sc = this.elements.$images.length, 216 sp = 100 / sc, 217 so = sp * this.attributes.current; 218 219 $.extend(this.attributes, { 220 swipeStartPosition: p, 221 screenWidth: sw, 222 screenCount: sc, 223 screenWidthAsPercentageOfFilm: sp, 224 screenOffset: so, 225 thresholdAsPercentageOfFilm: (this.options.swipeThreshold / 100) * sp, 226 hasTouchStarted: true 227 }); 228 229 return false; 230 }, 231 onSwipeMove = function(event) { 232 if (!this.attributes.hasTouchStarted) { 233 return false; 234 } 235 236 var p = getPosition(event); 237 238 this.attributes.swipeDisplacement = { 239 x: 240 ((this.attributes.swipeStartPosition.x - p.x) / 241 this.attributes.screenWidth) * 242 this.attributes.screenWidthAsPercentageOfFilm, 243 y: this.attributes.swipeStartPosition.y - p.y 244 }; 245 246 this.attributes.swipeCompoundDisplacement = { 247 x: this.attributes.swipeDisplacement.x + this.attributes.screenOffset, 248 y: this.attributes.swipeDisplacement.y 249 }; 250 251 if (this.attributes.swipeCompoundDisplacement.x < 0) { 252 this.attributes.swipeCompoundDisplacement.x = 0; 253 } 254 255 if ( 256 this.attributes.swipeCompoundDisplacement.x + 257 this.attributes.screenWidthAsPercentageOfFilm > 258 100 259 ) { 260 this.attributes.swipeCompoundDisplacement.x = 261 this.attributes.screenWidthAsPercentageOfFilm * 262 (this.attributes.screenCount - 1); 263 } 264 265 this.goto(this.attributes.current, { 266 animate: false, 267 updateStates: false, 268 distance: this.attributes.swipeCompoundDisplacement.x 269 }); 270 271 return false; 272 }, 273 onSwipeEnd = function() { 274 if (!this.attributes.hasTouchStarted) { 275 return false; 276 } 277 278 delete this.attributes.hasTouchStarted; 279 280 var screensToMove = Math.abs( 281 Math.ceil( 282 this.attributes.swipeDisplacement.x / 283 this.attributes.screenWidthAsPercentageOfFilm 284 ) 285 ); 286 287 // if distance is past certain threshold, go to next screen 288 // otherwise return to this screen 289 290 if ( 291 Math.abs(this.attributes.swipeDisplacement.x) > 292 this.attributes.thresholdAsPercentageOfFilm 293 ) { 294 if (this.attributes.swipeDisplacement.x < 0) { 295 this.goto(this.attributes.current - screensToMove - 1); 296 } else { 297 this.goto(this.attributes.current + screensToMove); 298 } 299 } else { 300 this.goto(this.attributes.current); 301 } 302 303 return false; 304 }, 305 onSwipeCancel = function() { 306 delete this.attributes.hasTouchStarted; 307 308 // return to this screen 309 this.goto(this.attributes.current); 310 }, 311 onAnimationComplete = function() { 312 // alert('Animation complete') 313 this.attributes.is_animating = false; 314 this.elements.$film.css("transition", "all 0s"); 315 }, 316 onWindowResizeWrapper = function() { 317 clearTimeout(this.attributes.resizeTimeout); 318 this.attributes.resizeTimeout = setTimeout( 319 $.proxy(onWindowResize, this), 320 500 321 ); 322 }, 323 onWindowResize = function() { 324 // console.log('Resize detected ...'); 325 this.$el 326 .css(getValidFrameSize.call(this)) 327 [ 328 $(window).width() > this.options.collapseThreshold 329 ? "removeClass" 330 : "addClass" 331 ]("fc-collapsed"); 332 }, 333 updateButtonStates = function() { 334 this.elements.$btn_go_left.fcRemoveClass("disabled"); 335 this.elements.$btn_go_right.fcRemoveClass("disabled"); 336 337 if (this.attributes.current === 0) { 338 this.elements.$btn_go_left.fcAddClass("disabled"); 339 } else if (this.attributes.current === this.elements.$images.length - 1) { 340 this.elements.$btn_go_right.fcAddClass("disabled"); 341 } 342 }, 343 onAutoplayStep = function() { 344 this.goto((this.attributes.current + 1) % this.count()); 345 }, 346 setupHTML = function() { 347 $(window).resize($.proxy(onWindowResizeWrapper, this)); 348 349 this.$el 350 .fcAddClass("fc") 351 .fcAddClass("fc-" + this.attributes.id) 352 .css({ 353 "background-image": "url('" + this.options.frame + "')" 354 }) 355 .append(template); 356 357 if (this.options.debug) { 358 this.$el.fcAddClass("fc-debug"); 359 } 360 361 this.$el 362 .css(getValidFrameSize.call(this)) 363 [ 364 $(window).width() > this.options.collapseThreshold 365 ? "removeClass" 366 : "addClass" 367 ]("fc-collapsed"); 368 369 this.elements = $.extend(this.elements, { 370 $controls: this.$(".fc-controls"), 371 $pgn_inner: this.$(".fc-pagination-inner"), 372 $mask: this.$(".fc-image-mask"), 373 $film: this.$(".fc-film"), 374 $btn_go_left: this.$("a[rel=go-left]"), 375 $btn_go_right: this.$el.find("a[rel=go-right]") 376 }); 377 378 if (this.options.controlsPosition) { 379 this.elements.$controls.css(this.options.controlsPosition); 380 } 381 382 // add mask element 383 this.elements.$mask.css( 384 this.options.boundingBox 385 ); /* 386 }, this), 387 threshold:0, 388 fingers:'all' 389 }); 390 */ 391 // .on(events.mousedown, $.proxy(onSwipeBegin, this)); 392 393 /* 394 .swipe({ 395 swipeStatus:$.proxy(function(event, phase) { 396 if(phase===$.fn.swipe.phases.PHASE_START) { 397 onSwipeBegin.call(this, event); 398 } 399 /* 400 else if(phase===$.fn.swipe.phases.PHASE_MOVE) { 401 onSwipeMove.call(this, event); 402 } 403 else if ( phase===$.fn.swipe.phases.PHASE_END ) { 404 onSwipeEnd.call(this, event); 405 } 406 else if ( phase===$.fn.swipe.phases.PHASE_CANCEL ) { 407 onSwipeCancel.call(this, event); 408 } 409 */ var eventTarget = (this.attributes.touchEventTarget = 410 ".fc-" + this.attributes.id + " .fc-image-mask"); 411 412 $("body") 413 .on(events.touchstart, eventTarget, $.proxy(onSwipeBegin, this)) 414 .on(events.touchmove, eventTarget, $.proxy(onSwipeMove, this)) 415 .on(events.touchend, eventTarget, $.proxy(onSwipeEnd, this)) 416 .on(events.touchcancel, eventTarget, $.proxy(onSwipeCancel, this)) 417 .on(events.touchleave, eventTarget, $.proxy(onSwipeEnd, this)); 418 419 this.elements.$film 420 .css({ 421 width: this.options.images.length * 100 + "%" 422 }) 423 .on(events.transitionend, $.proxy(onAnimationComplete, this)); 424 425 // add screenshots 426 var countImg = 0; 427 $.each( 428 this.options.images, 429 $.proxy(function(index, image) { 430 var $bullet = $("<a/>") 431 .attr({ 432 href: "#" 433 }) 434 .html(" ") 435 .click( 436 $.proxy(function() { 437 this.goto(index); 438 return false;
439 }, this) 440 ) 441 .appendTo(this.elements.$pgn_inner); 442 443 appending_link = 444 '<div class="d-flex justify-content-center college-slider-name"><span>' + 445 this.options.name[countImg] + 446 "</span></div>"; 447 $("<a/>") 448 .fcAddClass("fc-image-masked") 449 .fcAddClass("fc-animate") 450 .fcAddClass("slide-university") 451 .attr("data-name", this.options.name[countImg]) 452 .attr("href", this.options.link[countImg]) 453 .css( 454 $.extend( 455 { 456 "background-image": "url('" + image + "')" 457 }, 458 this.options.boundingBox, 459 { 460 // 'margin-left': (index * 100) + '%', 461 width: 100 / this.options.images.length + "%", 462 height: "100%", 463 left: index * 100 + "%" 464 } 465 ) 466 ) 467 .appendTo(this.elements.$film) 468 .on( 469 "change:class", 470 $.proxy(function(e) { 471 if (e.className === "active") { 472 $bullet[e.changeType]("active"); 473 } 474 }, this) 475 ) 476 .append(appending_link); 477 478 countImg++; 479 }, this) 480 ); 481 482 this.elements.$images = this.$(".fc-image-masked"); 483 this.elements.$btn_go_left.click($.proxy(onClickGoLeft, this)); 484 this.elements.$btn_go_right.click($.proxy(onClickGoRight, this)); 485 }; 486 487 function FrameCarousel(el, options) { 488 $.extend(this, { 489 el: el, 490 $el: $(el).data("frameCarousel", this), 491 $: $.proxy($.fn.find, $(el)), 492 options: options || {}, 493 attributes: {}, 494 elements: {} 495 }); 496 497 setupDefaults.call(this).then( 498 $.proxy(function() { 499 setupHTML.call(this); 500 501 this.goto(this.options.first, { 502 animate: false, 503 isInitialCall: true 504 }); 505 506 this.$el.trigger("fc-ready"); 507 508 if (this.options.autoplay) { 509 this.play(); 510 } 511 }, this) 512 ); 513 } 514 515 $.extend(FrameCarousel.prototype, { 516 debug: function(msg) { 517 if (this.options.debug) { 518 this.$el.attr("data-debug", msg); 519 } 520 }, 521 522 count: function() { 523 var $imgs = this.$el.find(".fc-image-masked"); 524 return $imgs.length; 525 }, 526 527 goto: function(n, options) { 528 options = options || {}; 529 options = $.extend( 530 { 531 animate: true, 532 updateStates: true, 533 534 // distance is in percentage relative to $film size 535 distance: n * (100 / this.elements.$images.length) 536 }, 537 options 538 ); 539 540 if ( 541 this.attributes.is_animating || 542 n < 0 || 543 n > this.elements.$images.length - 1 544 ) { 545 return; 546 } 547 548 if (options.animate) { 549 this.attributes.is_animating = true; 550 } 551 552 var // distance = (n - this._current ) * this.$images.eq(0).width(), 553 distance = options.distance, 554 x = 0 - distance + "%", 555 cssMap = { 556 transform: "translate3d(" + x + ", 0, 0)" 557 }, 558 from = this.attributes.current; 559 560 // this.$el.attr('data-debug', 'translate3d('+x+', 0, 0)'); 561 // console.log('[goto] $film.x: '+x); 562 563 if (options.animate) { 564 cssMap["transition"] = "all .4s ease-out"; 565 } 566 567 if (!options.isInitialCall) { 568 this.$el.trigger("fc-transition-start", [from, n]); 569 } 570 571 this.elements.$film.css(cssMap); 572 573 if (options.animate) { 574 setTimeout( 575 $.proxy(function() { 576 if (this.attributes.is_animating) { 577 this.attributes.is_animating = false; 578 this.$el.trigger("fc-transition-end", [from, n]); 579 } 580 }, this), 581 1000 582 ); 583 } 584 585 if (options.updateStates) { 586 this.attributes.current = n; 587 this.elements.$images.fcRemoveClass("active"); 588 this.elements.$images.eq(n).fcAddClass("active"); 589 590 updateButtonStates.call(this); 591 } 592 593 // this.$el.attr('data-debug', this.$film.css('transition')); 594 // console.log('[goto] current_screen: '+this._current); 595 }, 596 next: function(options) { 597 this.goto(this.attributes.current + 1, options); 598 }, 599 previous: function(options) { 600 this.goto(this.attributes.current - 1, options); 601 }, 602 resize: function() {}, 603 removeFrame: function() {}, 604 play: function() { 605 this.attributes.timeoutID = setInterval( 606 $.proxy(onAutoplayStep, this), 607 this.options.autoplayInterval 608 ); 609 }, 610 stop: function() { 611 if (this.attributes.timeoutID) { 612 clearTimeout(this.attributes.timeoutID); 613 delete this.attributes.timeoutID; 614 } 615 }, 616 destroy: function() { 617 var eventTarget = this.attributes.touchEventTarget; 618 619 $("body") 620 .off(events.touchstart, eventTarget, onSwipeBegin) 621 .off(events.touchmove, eventTarget, onSwipeMove) 622 .off(events.touchend, eventTarget, onSwipeEnd) 623 .off(events.touchcancel, eventTarget, onSwipeCancel) 624 .off(events.touchleave, eventTarget, onSwipeEnd); 625 626 $(window).off("resize", onWindowResizeWrapper); 627 628 this.$el 629 .empty() 630 .attr({ 631 class: this.attributes.originalClassValue, 632 style: this.attributes.originalStyleValue 633 }) 634 .trigger("fc-destroy"); 635 } 636 }); 637 638 $.extend($.fn, { 639 frameCarousel: function(options) { 640 return this.each(function() { 641 return new FrameCarousel(this, options); 642 }); 643 }, 644 645 /** 646 * An extension of $.fn.addClass that also throws an event when invoked. 647 * Used internally. 648 */ 649 fcAddClass: function(className) { 650 var r = $.fn.addClass.apply(this, arguments); 651 652 $(this).trigger( 653 $.Event("change:class", { 654 target: this, 655 changeType: "addClass", 656 className: className 657 }) 658 ); 659 660 return r; 661 }, 662 663 /** 664 * An extension of $.fn.removeClass that also throws an event when invoked. 665 * Used internally. 666 */ 667 fcRemoveClass: function(className) { 668 var r = $.fn.removeClass.apply(this, arguments); 669 670 $(this).trigger( 671 $.Event("change:class", { 672 target: this, 673 changeType: "removeClass", 674 className: className 675 }) 676 ); 677 678 return r; 679 } 680 }); 681})(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.