1/** 2 * ------------------------------------------------------------------------ 3 * JA Slideshow Lite Module for J25 & J3.x 4 * ------------------------------------------------------------------------ 5 * Copyright (C) 2004-2018 J.O.O.M Solutions Co., Ltd. All Rights Reserved. 6 * @license - GNU/GPL, http://www.gnu.org/licenses/gpl.html 7 * Author: J.O.O.M Solutions Co., Ltd 8 * Websites: http://www.joomlart.com - http://www.joomlancers.com 9 * ------------------------------------------------------------------------ 10 */ 11 12 13var JASliderCSS = new Class({ 14 15 Implements: Options, 16 17 options: { 18 interval: 5000, 19 duration: 2000, 20 21 repeat: true, //animation repeat or not 22 autoplay: true, //auto play 23 24 navigation: false, //show navigation controls or not 25 thumbnail: false, //show thumbnail or not 26 27 urls: null, 28 targets: null 29 }, 30 31 initialize: function (element, options) { 32 var jslider = $(element); 33 34 if(!jslider){ 35 return false; 36 } 37 38 this.setOptions(options); 39 40 var options = this.options, 41 jmain = jslider.getElement('.ja-ss-items'), 42 jitems = jslider.getElements('.ja-ss-item'), 43 vars = { 44 jslider: jslider, 45 jmain: jmain, 46 jitems: jitems, 47 48 total: jitems.length, 49 curIdx: -1, 50 nextIdx: -1, 51 curImg: null, 52 53 retain: 0, 54 55 touch: 'ontouchstart' in window && !(/hp-tablet/gi).test(navigator.appVersion), 56 57 running: 0, 58 stop: 0, 59 timer: 0, 60 animFinished: this.animFinished.bind(this), 61 vendor: (function () { 62 var vendors = 't,webkitT,MozT,msT,OT'.split(','), 63 dummyStyle = document.createElement('div').style, 64 t, i = 0, l = vendors.length; 65 66 for ( ; i < l; i++ ) { 67 t = vendors[i] + 'ransform'; 68 if ( t in dummyStyle ) { 69 return vendors[i].substr(0, vendors[i].length - 1).toLowerCase(); 70 } 71 } 72 73 return false; 74 })() 75 }; 76 77 if(vars.vendor !== false && !Browser.ie9){ 78 vars.vendor = vars.vendor ? '-' + vars.vendor.toLowerCase() + '-' : ''; 79 } else { 80 vars.vendor = false; 81 } 82 83 // add a ghost item to solve the container width/height problem 84 jitems[0].clone().setStyles ({'position':'relative', 'visibility':'hidden', 'z-index': 1}).addClass('ja-ss-item-ghost').inject (jmain,'top'); 85 86 // store original class 87 jitems.each (function(item){ 88 item._className = item.className; 89 }); 90 this.vars = vars; 91 92 this.initItemAction(); 93 this.initThumbAction(); 94 this.initControlAction(); 95 this.initKbNav(); 96 97 if(vars.touch){ 98 this.initTouchDevice(); 99 } 100 101 vars.direct = 'next'; 102 jslider.setStyle('visibility', 'visible'); 103 104 this.prepare(vars.curIdx +1); 105 this.animFinished(); 106 }, 107 108 stop: function(){ 109 clearTimeout(this.vars.timer); 110 this.vars.stop = 1; 111 }, 112 113 prev: function(){ 114 var vars = this.vars; 115 if(vars.running){ 116 return false; 117 } 118 this.prepare(vars.curIdx -1); 119 }, 120 121 next: function(){ 122 var vars = this.vars; 123 if(vars.running){ 124 return false; 125 } 126 this.prepare(vars.curIdx +1); 127 }, 128 129 playback: function(){ 130 this.vars.direct = 'prev'; 131 this.vars.stop = 0; 132 this.prev(); 133 }, 134 135 play: function(){ 136 this.vars.direct = 'next'; 137 this.vars.stop = 0; 138 this.next(); 139 }, 140 141 start: function(){ 142 var vars = this.vars; 143 144 clearTimeout(vars.timer); 145 vars.timer = setTimeout(this[this.vars.direct].bind(this), this.options.interval) 146 }, 147 148 img: function(src, callback){ 149 var image = new Image(); 150 151 ['load', 'abort', 'error'].each(function(name){ 152 var type = 'on' + name; 153 154 image[type] = function(){ 155 if (!image) return; 156 157 image = image.onload = image.onabort = image.onerror = null; 158 159 if(typeOf(callback) == 'function'){ 160 callback.delay(1); 161 } 162 }; 163 }); 164 165 image.src = src; 166 if (image && image.complete){ 167 image.onload.delay(1); 168 } 169 }, 170 171 load: function(idx){ 172 var vars = this.vars; 173 vars.jitems[idx].store('loaded', 1); //mark it as loaded 174 175 vars.retain = Math.max(0, vars.retain - 1); //remove reference count to loading 176 177 if(vars.nextIdx == idx){ //check, we are waiting for the image loaded 178 this.run(idx); 179 } else if(vars.nextIdx == -1){ //already passed, do not have to check 180 if(vars.retain == 0){ 181 vars.jslider.removeClass('ja-ss-loading'); 182 } 183 } 184 }, 185 186 prepare: function(idx){ 187 var vars = this.vars, 188 options = this.options; 189 190 if(idx >= vars.total){ 191 idx = 0; 192 } 193 194 if(idx < 0){ 195 idx = vars.total - 1; 196 } 197 198 var curImg = vars.jitems[idx]; 199 if(curImg.get('tag') != 'img'){
200 curImg = curImg.getElement('img'); 201 } 202 203 //there was no image, we will run it immediately 204 if (!curImg){ 205 return this.run(idx); 206 } 207 208 //if there was some image, preload it 209 vars.nextIdx = idx; 210 211 if(curImg.retrieve('loaded')){ //already loaded 212 return this.run(idx); 213 } else{ 214 vars.running = true; 215 vars.retain++; //increase reference count 216 vars.jslider.addClass('ja-ss-loading'); 217 218 this.img(curImg.src, this.load.bind(this, idx)); 219 } 220 }, 221 222 run: function(idx){ 223 var vars = this.vars, 224 options = this.options; 225 226 vars.retain = 0; //reset reference count, no matter how many item loading - just for animation look better 227 vars.jslider.removeClass('ja-ss-loading'); 228 229 if(vars.curIdx == idx){ 230 return false; 231 } 232 233 vars.running = true; 234 235 if (vars.jthumbitems) { 236 vars.jthumbitems.removeClass('active')[idx].addClass('active'); 237 238 if(vars.thumbscroll && vars.jthumbs){ 239 if (idx <= (vars.startidx + 1) || idx >= (vars.startidx + vars.visible - 1)) { 240 vars.startidx = Math.max(0, Math.min(idx - vars.visible + 2, vars.total - vars.visible)); 241 242 if(vars.vendor !== false){ 243 vars.jthumbs.setStyle(vars.vendor + 'transform', 244 'translate' + vars.thumborient + '(' + (-Math.min(vars.startidx, vars.maxpercent) * 100) + '%)'); 245 } else { 246 vars.thumbsFx.start(vars.thumborient, -Math.min(vars.startidx, vars.maxpercent) * 100); 247 } 248 } 249 } 250 } 251 252 this.slide(idx); 253 254 vars.jslider.removeClass('ja-ss-progress'); 255 }, 256 257 slide: function(idx){ 258 var options = this.options, 259 vars = this.vars; 260 261 vars.jitems.each(function(item, index){ 262 var cls = (idx == index) ? 'curr active' : 263 (index < idx && (index != 0 || idx != vars.jitems.length-1)) ? 'prev' : 264 (index > idx && (idx != 0 || index != vars.jitems.length-1)) ? 'next' : 265 (idx == 0) ? 'prev' : 'next'; 266 // check if element move out/in 267 if (item.hasClass ('curr') || cls.match(/curr/)) cls = 'animate ' + cls; 268 269 // remove old classes and add new classes 270 item.className = item._className + ' ' + cls; 271 }); 272 273 //Pause slide on hovering 274 vars.jslider.addEvent('mouseenter', function(){ 275 clearTimeout(vars.timer); 276 vars.timer = setTimeout(vars.animFinished, options.duration); 277 if(vars.stop == 0 && options.autoplay == '1'){ 278 vars.stop = 1; 279 } 280 }); 281 vars.jslider.addEvent('mouseleave', function(){ 282 clearTimeout(vars.timer); 283 vars.timer = setTimeout(vars.animFinished, options.duration); 284 if(vars.stop == 1 && options.autoplay == '1'){ 285 vars.stop = 0; 286 } 287 }); 288 289 clearTimeout(vars.timer); 290 vars.timer = setTimeout(vars.animFinished, this.options.duration); 291 vars.curIdx = idx; 292 }, 293 294 animFinished: function(){ 295 var options = this.options, 296 vars = this.vars; 297 298 vars.running = false; 299 300 if (!vars.stop && (options.autoplay && (vars.curIdx < vars.total -1 || options.repeat))) { 301 this.start(); 302 303 vars.jslider.addClass('ja-ss-progress'); 304 } 305 }, 306 307 initThumbAction: function () { 308 var options = this.options; 309 310 if (options.thumbnail) { 311 var vars = this.vars, 312 jslider = vars.jslider, 313 jthumbs = vars.jslider.getElement('.ja-ss-thumbs'), 314 jthumbwrap = vars.jslider.getElement('.ja-ss-thumbs-wrap'), 315 jthumbitems = vars.jslider.getElements('.ja-ss-thumb'); 316 317 if(jthumbitems.length){ 318 jthumbitems.removeClass('active'); 319 320 for (var i = 0, il = jthumbitems.length; i < il; i++) { 321 jthumbitems[i].addEvent('click', this.prepare.bind(this, i)); 322 } 323 324 jthumbs.addEvent('mousewheel', function (e) { 325 if (e.wheel < 0) { 326 e.stop(); 327 this.next(true); 328 } else { 329 e.stop(); 330 this.prev(true); 331 } 332 }.bind(this)); 333 334 var jthumbimg = jthumbitems[0].getElement('img'), 335 thumbready = function () { 336 //check if need for animation 337 var coord1 = jthumbitems[0].getCoordinates(), 338 coord2 = jthumbitems[1].getCoordinates(), 339 orient = 'width'; 340 341 if(Math.min(coord1.width, coord1.height) > 32){ 342 //has thumbnail 343 344 if(coord1.top < coord2.top && coord1.left == coord2.left){ 345 orient = 'height'; 346 } 347 348 var itemsize = coord1[orient], 349 padd = 0; 350 351 if(orient == 'width'){ 352 padd = jthumbitems[0].getStyle('margin-left').toInt() 353 + jthumbitems[0].getStyle('margin-right').toInt(); 354 } else { 355 padd = jthumbitems[0].getStyle('margin-top').toInt() 356 + jthumbitems[0].getStyle('margin-bottom').toInt(); 357 } 358 359 itemsize += padd; 360 361 jthumbwrap.addClass('ja-ss-thumb-' + orient); 362 jthumbs.setStyles({ 363 width: '', 364 height: '' 365 }).setStyle(orient, itemsize); 366 367 var visiblesize = jthumbwrap['get' + orient.capitalize()](), 368 visible = Math.floor(visiblesize / itemsize), 369 maxsize = (itemsize * jthumbitems.length - visiblesize - padd), 370 maxpercent = (maxsize <= 0 ? (maxsize / 2) : maxsize) / itemsize; 371 372 if(vars.vendor === false && !vars.thumbsFx){ 373 new Element('div', {'class': 'ja-ss-thumbie'}).wraps(jthumbs).setStyle('position', 'relative').setStyle(orient, itemsize); 374 375 vars.thumbsFx = new Fx.Tween(jthumbs, { 376 duration: 500, 377 link: 'cancel', 378 unit: '%' 379 });
380 } 381 382 Object.append(vars, { 383 thumbscroll: true, 384 thumborient: (vars.vendor !== false ? (orient == 'width' ? 'X' : 'Y') : (orient == 'width' ? 'left' : 'top')), 385 total: jthumbitems.length, 386 visible: visible, 387 maxpercent: maxpercent, 388 jthumbs: jthumbs, 389 startidx: vars.startidx || 0 390 }); 391 392 if(vars.vendor !== false){ 393 vars.jthumbs.setStyle(vars.vendor + 'transform', 394 'translate' + vars.thumborient + '(' + (-Math.min(vars.startidx, vars.maxpercent) * 100) + '%)'); 395 } else { 396 vars.thumbsFx.start(vars.thumborient, -Math.min(vars.startidx, vars.maxpercent) * 100); 397 } 398 } else { 399 400 Object.append(vars, { 401 thumbscroll: false, 402 jthumbitems: jthumbitems 403 }); 404 } 405 }; 406 407 window.addEvent('resize', function(){ 408 if(vars.thumborient){ 409 clearTimeout(vars.tsid); 410 vars.tsid = setTimeout(thumbready, 500); 411 } 412 }); 413 414 if(jthumbimg){ 415 this.img(jthumbimg.get('src'), thumbready); 416 } else { 417 thumbready.delay(10); 418 } 419 420 vars.jthumbitems = jthumbitems; 421 } 422 } 423 }, 424 425 initControlAction: function () { 426 var btnarr, 427 options = this.options; 428 429 if(options.navigation){ 430 var jslider = this.vars.jslider, 431 controls = ['prev', 'play', 'stop', 'playback', 'next']; 432 433 for (var j = 0, jl = controls.length; j < jl; j++) { 434 if(this[controls[j]]){ 435 btnarr = jslider.getElements('.ja-ss-' + controls[j]); 436 437 for (var i = 0, il = btnarr.length; i < il; i++) { 438 btnarr[i].addEvent('click', this[controls[j]].bind(this, true)); 439 } 440 } 441 } 442 } 443 }, 444 445 initItemAction: function(){ 446 var options = this.options; 447 448 if (options.urls) { 449 var vars = this.vars, 450 anchor = function(from, limit){ 451 if(!limit){ 452 limit = vars.jslider; 453 } 454 455 while(from && from != limit){ 456 if(from.get('tag').toLowerCase() == 'a'){ 457 return from; 458 } 459 460 from = from.getParent(); 461 } 462 463 return null; 464 }, 465 466 handle = function(e){ 467 var index = vars.jitems.indexOf(this); 468 469 if(index == -1){ 470 index = vars.curIdx; 471 } 472 473 var url = options.urls[index], 474 target = options.targets[index], 475 link = anchor(e.target); 476 477 if(link && link.href != '' && link.href != window.location.href){ 478 return true; 479 } 480 481 if (url) { 482 e.stop(); 483 484 if (target == '_blank'){ 485 window.open(url, 'JAWindow'); 486 } else { 487 window.location.href = url; 488 } 489 } 490 491 return false; 492 }; 493 494 vars.jmain.addEvent('click', handle); 495 vars.jitems.addEvent('click', handle); 496 } 497 }, 498 499 initTouchDevice: function(){ 500 var inst = this, 501 vars = this.vars, 502 ltouch = function(){ 503 vars.ltouch = true; 504 }, 505 start = function(e){ 506 507 clearTimeout(vars.ltid); 508 509 var point = e.touches[0]; 510 511 vars.moved = false; 512 vars.px = point.pageX; 513 vars.py = point.pageY; 514 vars.tm = e.timeStamp || new Date().getTime(); 515 vars.ltouch = false; 516 vars.ltid = setTimeout(ltouch, 150); 517 vars.tcancel = false; 518 519 document.addEvent('touchmove', move); 520 vars.jslider.addEvent('touchend', end); 521 }, 522 move = function(e){ 523 clearTimeout(vars.ltid); 524 525 var point = e.changedTouches[0]; 526 527 if(!vars.tcancel && !vars.ltouch && Math.abs(point.pageX - vars.px) > Math.abs(point.pageY - vars.py)){ 528 e.stop(); 529 530 var tm = e.timeStamp || new Date().getTime(); 531 if(tm - vars.tm > 300){ 532 vars.tm = tm; 533 vars.px = point.pageX; 534 } 535 536 vars.moved = true; 537 538 } else { 539 vars.tcancel = true; 540 return; 541 } 542 }, 543 end = function(e){ 544 545 document.removeEvent('touchmove', move); 546 vars.jslider.removeEvent('touchend', end); 547 548 if (e.touches.length != 0 || vars.tcancel){ 549 return; 550 } 551 552 var point = e.changedTouches[0]; 553 554 if(!vars.moved){ 555 var target = point.target; 556 while (target.nodeType != 1){ 557 target = target.parentNode; 558 } 559 560 if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA') { 561 var ev = document.createEvent('MouseEvents'); 562 ev.initMouseEvent('click', true, true, e.view, 1, 563 point.screenX, point.screenY, point.clientX, point.clientY, 564 e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, 565 0, null); 566 ev._fake = true; 567 target.dispatchEvent(ev); 568 } 569 570 } else if(((e.timeStamp || new Date().getTime()) - vars.tm) < 300) { 571 572 if(point.pageX - vars.px > 30){ 573 inst.prev(true); 574 } else if (point.pageX - vars.px < -30) { 575 inst.next(true); 576 } 577 } 578 }; 579 580 vars.jslider.addEvent('touchstart', start); 581 }, 582 583 initKbNav: function(){ 584 document.addEvent('keydown', function(e){
585 if (e.code == 39 || e.code == 40) { 586 this.next(); 587 } else if (e.code == 37 || e.code == 38) { 588 this.prev(); 589 } 590 }.bind(this)); 591 } 592});
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.