1/** 2 * ------------------------------------------------------------------------ 3 * JA Slideshow Lite Module for J25 & J3.3 4 * ------------------------------------------------------------------------ 5 * Copyright (C) 2004-2011 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 clearTimeout(vars.timer); 274 vars.timer = setTimeout(vars.animFinished, this.options.duration); 275 vars.curIdx = idx; 276 }, 277 278 animFinished: function(){ 279 var options = this.options, 280 vars = this.vars; 281 282 vars.running = false; 283 284 if (!vars.stop && (options.autoplay && (vars.curIdx < vars.total -1 || options.repeat))) { 285 this.start(); 286 287 vars.jslider.addClass('ja-ss-progress'); 288 } 289 }, 290 291 initThumbAction: function () { 292 var options = this.options; 293 294 if (options.thumbnail) { 295 var vars = this.vars, 296 jslider = vars.jslider, 297 jthumbs = vars.jslider.getElement('.ja-ss-thumbs'), 298 jthumbwrap = vars.jslider.getElement('.ja-ss-thumbs-wrap'), 299 jthumbitems = vars.jslider.getElements('.ja-ss-thumb'); 300 301 if(jthumbitems.length){ 302 jthumbitems.removeClass('active'); 303 304 for (var i = 0, il = jthumbitems.length; i < il; i++) { 305 jthumbitems[i].addEvent('click', this.prepare.bind(this, i)); 306 } 307 308 jthumbs.addEvent('mousewheel', function (e) { 309 if (e.wheel < 0) { 310 e.stop(); 311 this.next(true); 312 } else { 313 e.stop(); 314 this.prev(true); 315 } 316 }.bind(this)); 317 318 var jthumbimg = jthumbitems[0].getElement('img'), 319 thumbready = function () { 320 //check if need for animation 321 var coord1 = jthumbitems[0].getCoordinates(), 322 coord2 = jthumbitems[1].getCoordinates(), 323 orient = 'width'; 324 325 if(Math.min(coord1.width, coord1.height) > 32){ 326 //has thumbnail 327 328 if(coord1.top < coord2.top && coord1.left == coord2.left){ 329 orient = 'height'; 330 } 331 332 var itemsize = coord1[orient], 333 padd = 0; 334 335 if(orient == 'width'){ 336 padd = jthumbitems[0].getStyle('margin-left').toInt() 337 + jthumbitems[0].getStyle('margin-right').toInt(); 338 } else { 339 padd = jthumbitems[0].getStyle('margin-top').toInt() 340 + jthumbitems[0].getStyle('margin-bottom').toInt(); 341 } 342 343 itemsize += padd; 344 345 jthumbwrap.addClass('ja-ss-thumb-' + orient); 346 jthumbs.setStyles({ 347 width: '', 348 height: '' 349 }).setStyle(orient, itemsize); 350 351 var visiblesize = jthumbwrap['get' + orient.capitalize()](), 352 visible = Math.floor(visiblesize / itemsize), 353 maxsize = (itemsize * jthumbitems.length - visiblesize - padd), 354 maxpercent = (maxsize <= 0 ? (maxsize / 2) : maxsize) / itemsize; 355 356 if(vars.vendor === false && !vars.thumbsFx){ 357 new Element('div', {'class': 'ja-ss-thumbie'}).wraps(jthumbs).setStyle('position', 'relative').setStyle(orient, itemsize); 358 359 vars.thumbsFx = new Fx.Tween(jthumbs, { 360 duration: 500, 361 link: 'cancel', 362 unit: '%' 363 });
364 } 365 366 Object.append(vars, { 367 thumbscroll: true, 368 thumborient: (vars.vendor !== false ? (orient == 'width' ? 'X' : 'Y') : (orient == 'width' ? 'left' : 'top')), 369 total: jthumbitems.length, 370 visible: visible, 371 maxpercent: maxpercent, 372 jthumbs: jthumbs, 373 startidx: vars.startidx || 0 374 }); 375 376 if(vars.vendor !== false){ 377 vars.jthumbs.setStyle(vars.vendor + 'transform', 378 'translate' + vars.thumborient + '(' + (-Math.min(vars.startidx, vars.maxpercent) * 100) + '%)'); 379 } else { 380 vars.thumbsFx.start(vars.thumborient, -Math.min(vars.startidx, vars.maxpercent) * 100); 381 } 382 } else { 383 384 Object.append(vars, { 385 thumbscroll: false, 386 jthumbitems: jthumbitems 387 }); 388 } 389 }; 390 391 window.addEvent('resize', function(){ 392 if(vars.thumborient){ 393 clearTimeout(vars.tsid); 394 vars.tsid = setTimeout(thumbready, 500); 395 } 396 }); 397 398 if(jthumbimg){ 399 this.img(jthumbimg.get('src'), thumbready); 400 } else { 401 thumbready.delay(10); 402 } 403 404 vars.jthumbitems = jthumbitems; 405 } 406 } 407 }, 408 409 initControlAction: function () { 410 var btnarr, 411 options = this.options; 412 413 if(options.navigation){ 414 var jslider = this.vars.jslider, 415 controls = ['prev', 'play', 'stop', 'playback', 'next']; 416 417 for (var j = 0, jl = controls.length; j < jl; j++) { 418 if(this[controls[j]]){ 419 btnarr = jslider.getElements('.ja-ss-' + controls[j]); 420 421 for (var i = 0, il = btnarr.length; i < il; i++) { 422 btnarr[i].addEvent('click', this[controls[j]].bind(this, true)); 423 } 424 } 425 } 426 } 427 }, 428 429 initItemAction: function(){ 430 var options = this.options; 431 432 if (options.urls) { 433 var vars = this.vars, 434 anchor = function(from, limit){ 435 if(!limit){ 436 limit = vars.jslider; 437 } 438 439 while(from && from != limit){ 440 if(from.get('tag').toLowerCase() == 'a'){ 441 return from; 442 } 443 444 from = from.getParent(); 445 } 446 447 return null; 448 }, 449 450 handle = function(e){ 451 var index = vars.jitems.indexOf(this); 452 453 if(index == -1){ 454 index = vars.curIdx; 455 } 456 457 var url = options.urls[index], 458 target = options.targets[index], 459 link = anchor(e.target); 460 461 if(link && link.href != '' && link.href != window.location.href){ 462 return true; 463 } 464 465 if (url) { 466 e.stop(); 467 468 if (target == '_blank'){ 469 window.open(url, 'JAWindow'); 470 } else { 471 window.location.href = url; 472 } 473 } 474 475 return false; 476 }; 477 478 vars.jmain.addEvent('click', handle); 479 vars.jitems.addEvent('click', handle); 480 } 481 }, 482 483 initTouchDevice: function(){ 484 var inst = this, 485 vars = this.vars, 486 ltouch = function(){ 487 vars.ltouch = true; 488 }, 489 start = function(e){ 490 491 clearTimeout(vars.ltid); 492 493 var point = e.touches[0]; 494 495 vars.moved = false; 496 vars.px = point.pageX; 497 vars.py = point.pageY; 498 vars.tm = e.timeStamp || new Date().getTime(); 499 vars.ltouch = false; 500 vars.ltid = setTimeout(ltouch, 150); 501 vars.tcancel = false; 502 503 document.addEvent('touchmove', move); 504 vars.jslider.addEvent('touchend', end); 505 }, 506 move = function(e){ 507 clearTimeout(vars.ltid); 508 509 var point = e.changedTouches[0]; 510 511 if(!vars.tcancel && !vars.ltouch && Math.abs(point.pageX - vars.px) > Math.abs(point.pageY - vars.py)){ 512 e.stop(); 513 514 var tm = e.timeStamp || new Date().getTime(); 515 if(tm - vars.tm > 300){ 516 vars.tm = tm; 517 vars.px = point.pageX; 518 } 519 520 vars.moved = true; 521 522 } else { 523 vars.tcancel = true; 524 return; 525 } 526 }, 527 end = function(e){ 528 529 document.removeEvent('touchmove', move); 530 vars.jslider.removeEvent('touchend', end); 531 532 if (e.touches.length != 0 || vars.tcancel){ 533 return; 534 } 535 536 var point = e.changedTouches[0]; 537 538 if(!vars.moved){ 539 var target = point.target; 540 while (target.nodeType != 1){ 541 target = target.parentNode; 542 } 543 544 if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA') { 545 var ev = document.createEvent('MouseEvents'); 546 ev.initMouseEvent('click', true, true, e.view, 1, 547 point.screenX, point.screenY, point.clientX, point.clientY, 548 e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, 549 0, null); 550 ev._fake = true; 551 target.dispatchEvent(ev); 552 } 553 554 } else if(((e.timeStamp || new Date().getTime()) - vars.tm) < 300) { 555 556 if(point.pageX - vars.px > 30){ 557 inst.prev(true); 558 } else if (point.pageX - vars.px < -30) { 559 inst.next(true); 560 } 561 } 562 }; 563 564 vars.jslider.addEvent('touchstart', start); 565 }, 566 567 initKbNav: function(){ 568 document.addEvent('keydown', function(e){
569 if (e.code == 39 || e.code == 40) { 570 this.next(); 571 } else if (e.code == 37 || e.code == 38) { 572 this.prev(); 573 } 574 }.bind(this)); 575 } 576});
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.