1/*! 2 * Galleria v 1.1.95 2010-08-06 3 * http://galleria.aino.se 4 * 5 * Copyright (c) 2010, Aino 6 * Licensed under the MIT license. 7 */ 8 9(function() { 10 11var initializing = false, 12 fnTest = /xyz/.test(function(){xyz;}) ? /\b__super\b/ : /.*/, 13 Class = function(){}, 14 window = this; 15 16Class.extend = function(prop) { 17 var __super = this.prototype; 18 initializing = true; 19 var proto = new this(); 20 initializing = false; 21 for (var name in prop) { 22 if (name) { 23 proto[name] = typeof prop[name] == "function" && 24 typeof __super[name] == "function" && fnTest.test(prop[name]) ? 25 (function(name, fn) { 26 return function() { 27 var tmp = this.__super; 28 this.__super = __super[name]; 29 var ret = fn.apply(this, arguments); 30 this.__super = tmp; 31 return ret; 32 }; 33 })(name, prop[name]) : prop[name]; 34 } 35 } 36 37 function Class() { 38 if ( !initializing && this.__constructor ) { 39 this.__constructor.apply(this, arguments); 40 } 41 } 42 Class.prototype = proto; 43 Class.constructor = Class; 44 Class.extend = arguments.callee; 45 return Class; 46}; 47 48var Base = Class.extend({ 49 loop : function( elem, fn) { 50 var scope = this; 51 if (typeof elem == 'number') { 52 elem = new Array(elem); 53 } 54 jQuery.each(elem, function() { 55 fn.call(scope, arguments[1], arguments[0]); 56 }); 57 return elem; 58 }, 59 create : function( elem, className ) { 60 elem = elem || 'div'; 61 var el = document.createElement(elem); 62 if (className) { 63 el.className = className; 64 } 65 return el; 66 }, 67 getElements : function( selector ) { 68 var elems = {}; 69 this.loop( jQuery(selector), this.proxy(function( elem ) { 70 this.push(elem, elems); 71 })); 72 return elems; 73 }, 74 setStyle : function( elem, css ) { 75 jQuery(elem).css(css); 76 return this; 77 }, 78 getStyle : function( elem, styleProp, parse ) { 79 var val = jQuery(elem).css(styleProp); 80 return parse ? this.parseValue( val ) : val; 81 }, 82 cssText : function( string ) { 83 var style = document.createElement('style'); 84 this.getElements('head')[0].appendChild(style); 85 if (style.styleSheet) { // IE 86 style.styleSheet.cssText = string; 87 } else { 88 var cssText = document.createTextNode(string); 89 style.appendChild(cssText); 90 } 91 return this; 92 }, 93 touch : function(el) { 94 var sibling = el.nextSibling; 95 var parent = el.parentNode; 96 parent.removeChild(el); 97 if ( sibling ) { 98 parent.insertBefore(el, sibling); 99 } else { 100 parent.appendChild(el); 101 } 102 if (el.styleSheet && el.styleSheet.imports.length) { 103 this.loop(el.styleSheet.imports, function(i) { 104 el.styleSheet.addImport(i.href); 105 }); 106 } 107 }, 108 loadCSS : function(href, callback) { 109 var exists = this.getElements('link[href="'+href+'"]').length; 110 if (exists) { 111 callback.call(null); 112 return exists[0]; 113 } 114 var link = this.create('link'); 115 link.rel = 'stylesheet'; 116 link.href = href; 117 118 if (typeof callback == 'function') { 119 // a new css check method, still experimental... 120 this.wait(function() { 121 return !!document.body; 122 }, function() { 123 var testElem = this.create('div', 'galleria-container galleria-stage'); 124 this.moveOut(testElem); 125 document.body.appendChild(testElem); 126 var getStyles = this.proxy(function() { 127 var str = ''; 128 var props; 129 if (document.defaultView && document.defaultView.getComputedStyle) { 130 props = document.defaultView.getComputedStyle(testElem, ""); 131 this.loop(props, function(prop) { 132 str += prop + props.getPropertyValue(prop); 133 }); 134 } else if (testElem.currentStyle) { // IE 135 props = testElem.currentStyle; 136 this.loop(props, function(val, prop) { 137 str += prop + val; 138 }); 139 } 140 return str; 141 }); 142 var current = getStyles(); 143 this.wait(function() { 144 return getStyles() !== current; 145 }, function() { 146 document.body.removeChild(testElem); 147 callback.call(link); 148 }, function() { 149 G.raise('Could not confirm theme CSS'); 150 }, 2000); 151 }); 152 } 153 window.setTimeout(this.proxy(function() { 154 var styles = this.getElements('link[rel="stylesheet"],style'); 155 if (styles.length) { 156 styles[0].parentNode.insertBefore(link, styles[0]); 157 } else { 158 this.getElements('head')[0].appendChild(link); 159 } 160 // IE needs a manual touch to re-order the cascade 161 if (G.IE) { 162 this.loop(styles, function(el) { 163 this.touch(el); 164 }) 165 } 166 }), 2); 167 return link; 168 }, 169 moveOut : function( elem ) { 170 return this.setStyle(elem, { 171 position: 'absolute', 172 left: '-10000px', 173 display: 'block' 174 }); 175 }, 176 moveIn : function( elem ) { 177 return this.setStyle(elem, { 178 left: '0' 179 }); 180 }, 181 reveal : function( elem ) { 182 return jQuery( elem ).show(); 183 }, 184 hide : function( elem ) { 185 return jQuery( elem ).hide(); 186 }, 187 mix : function() { 188 return jQuery.extend.apply(jQuery, arguments); 189 }, 190 proxy : function( fn, scope ) { 191 if ( typeof fn !== 'function' ) { 192 return function() {}; 193 } 194 scope = scope || this; 195 return function() { 196 return fn.apply( scope, Array.prototype.slice.call(arguments) ); 197 }; 198 }, 199 listen : function( elem, type, fn ) { 200 jQuery(elem).bind( type, fn ); 201 }, 202 forget : function( elem, type, fn ) {
203 jQuery(elem).unbind(type, fn); 204 }, 205 dispatch : function( elem, type ) { 206 jQuery(elem).trigger(type); 207 }, 208 clone : function( elem, keepEvents ) { 209 keepEvents = keepEvents || false; 210 return jQuery(elem).clone(keepEvents)[0]; 211 }, 212 removeAttr : function( elem, attributes ) { 213 this.loop( attributes.split(' '), function(attr) { 214 jQuery(elem).removeAttr(attr); 215 }); 216 }, 217 push : function( elem, obj ) { 218 if (typeof obj.length == 'undefined') { 219 obj.length = 0; 220 } 221 Array.prototype.push.call( obj, elem ); 222 return elem; 223 }, 224 width : function( elem, outer ) { 225 return this.meassure(elem, outer, 'Width'); 226 }, 227 height : function( elem, outer ) { 228 return this.meassure(elem, outer, 'Height'); 229 }, 230 meassure : function(el, outer, meassure) { 231 var elem = jQuery( el ); 232 var ret = outer ? elem['outer'+meassure](true) : elem[meassure.toLowerCase()](); 233 // fix quirks mode 234 if (G.QUIRK) { 235 var which = meassure == "Width" ? [ "left", "right" ] : [ "top", "bottom" ]; 236 this.loop(which, function(s) { 237 ret += elem.css('border-' + s + '-width').replace(/[^\d]/g,'') * 1; 238 ret += elem.css('padding-' + s).replace(/[^\d]/g,'') * 1; 239 }); 240 } 241 return ret; 242 }, 243 toggleClass : function( elem, className, arg ) { 244 if (typeof arg !== 'undefined') { 245 var fn = arg ? 'addClass' : 'removeClass'; 246 jQuery(elem)[fn](className); 247 return this; 248 } 249 jQuery(elem).toggleClass(className); 250 return this; 251 }, 252 hideAll : function( el ) { 253 jQuery(el).find('*').hide(); 254 }, 255 animate : function( el, options ) { 256 options.complete = this.proxy(options.complete); 257 var elem = jQuery(el); 258 if (!elem.length) { 259 return; 260 } 261 if (options.from) { 262 elem.css(from); 263 } 264 elem.animate(options.to, { 265 duration: options.duration || 400, 266 complete: options.complete, 267 easing: options.easing || 'swing' 268 }); 269 }, 270 wait : function(fn, callback, err, max) { 271 fn = this.proxy(fn); 272 callback = this.proxy(callback); 273 err = this.proxy(err); 274 var ts = new Date().getTime() + (max || 3000); 275 window.setTimeout(function() { 276 if (fn()) { 277 callback(); 278 return false; 279 } 280 if (new Date().getTime() >= ts) { 281 err(); 282 callback(); 283 return false; 284 } 285 window.setTimeout(arguments.callee, 2); 286 }, 2); 287 return this; 288 }, 289 loadScript: function(url, callback) { 290 var script = document.createElement('script'); 291 script.src = url; 292 script.async = true; // HTML5 293 294 var done = false; 295 var scope = this; 296 297 // Attach handlers for all browsers 298 script.onload = script.onreadystatechange = function() { 299 if ( !done && (!this.readyState || 300 this.readyState == "loaded" || this.readyState == "complete") ) { 301 done = true; 302 303 if (typeof callback == 'function') { 304 callback.call(scope, this); 305 } 306 307 // Handle memory leak in IE 308 script.onload = script.onreadystatechange = null; 309 } 310 }; 311 var s = document.getElementsByTagName('script')[0]; 312 s.parentNode.insertBefore(script, s); 313 314 return this; 315 }, 316 parseValue: function(val) { 317 if (typeof val == 'number') { 318 return val; 319 } else if (typeof val == 'string') { 320 var arr = val.match(/\-?\d/g); 321 return arr && arr.constructor == Array ? arr.join('')*1 : 0; 322 } else { 323 return 0; 324 } 325 } 326}); 327 328var Picture = Base.extend({ 329 __constructor : function(order) { 330 this.image = null; 331 this.elem = this.create('div', 'galleria-image'); 332 this.setStyle( this.elem, { 333 overflow: 'hidden', 334 position: 'relative' // for IE Standards mode 335 } ); 336 this.order = order; 337 this.orig = { w:0, h:0, r:1 }; 338 }, 339 340 cache: {}, 341 ready: false, 342 343 add: function(src) { 344 if (this.cache[src]) { 345 return this.cache[src]; 346 } 347 var image = new Image(); 348 image.src = src; 349 this.setStyle(image, {display: 'block'}); 350 if (image.complete && image.width) { 351 this.cache[src] = image; 352 return image; 353 } 354 image.onload = (function(scope) { 355 return function() { 356 scope.cache[src] = image; 357 }; 358 })(this); 359 return image; 360 }, 361 362 isCached: function(src) { 363 return this.cache[src] ? this.cache[src].complete : false;
364 }, 365 366 make: function(src) { 367 var i = this.cache[src] || this.add(src); 368 return this.clone(i); 369 }, 370 371 load: function(src, callback) { 372 callback = this.proxy( callback ); 373 this.elem.innerHTML = ''; 374 this.image = this.make( src ); 375 this.moveOut( this.image ); 376 this.elem.appendChild( this.image ); 377 this.wait(function() { 378 return (this.image.complete && this.image.width); 379 }, function() { 380 this.orig = { 381 h: this.h || this.image.height, 382 w: this.w || this.image.width 383 }; 384 callback( {target: this.image, scope: this} ); 385 }, function() { 386 G.raise('image not loaded in 20 seconds: '+ src); 387 }, 20000); 388 return this; 389 }, 390 391 scale: function(options) { 392 var o = this.mix({ 393 width: 0, 394 height: 0, 395 min: undefined, 396 max: undefined, 397 margin: 0, 398 complete: function(){}, 399 position: 'center', 400 crop: false 401 }, options); 402 if (!this.image) { 403 return this; 404 } 405 var width,height; 406 this.wait(function() { 407 width = o.width || this.width(this.elem); 408 height = o.height || this.height(this.elem); 409 return width && height; 410 }, function() { 411 var nw = (width - o.margin*2) / this.orig.w; 412 var nh = (height- o.margin*2) / this.orig.h; 413 var rmap = { 414 'true': Math.max(nw,nh), 415 'width': nw, 416 'height': nh, 417 'false': Math.min(nw,nh) 418 } 419 var ratio = rmap[o.crop.toString()]; 420 if (o.max) { 421 ratio = Math.min(o.max, ratio); 422 } 423 if (o.min) { 424 ratio = Math.max(o.min, ratio); 425 } 426 this.setStyle(this.elem, { 427 width: width, 428 height: height 429 }); 430 this.image.width = Math.ceil(this.orig.w * ratio); 431 this.image.height = Math.ceil(this.orig.h * ratio); 432 433 var getPosition = this.proxy(function(value, img, m) { 434 var result = 0; 435 if (/\%/.test(value)) { 436 var pos = parseInt(value) / 100; 437 result = Math.ceil(this.image[img] * -1 * pos + m * pos); 438 } else { 439 result = parseInt(value); 440 } 441 return result; 442 }); 443 444 var map = { 445 'top': { top: 0 }, 446 'left': { left: 0 }, 447 'right': { left: '100%' }, 448 'bottom': { top: '100%' } 449 } 450 451 var pos = {}; 452 var mix = {}; 453 454 this.loop(o.position.toLowerCase().split(' '), function(p, i) { 455 if (p == 'center') { 456 p = '50%'; 457 } 458 pos[i ? 'top' : 'left'] = p; 459 }); 460 461 this.loop(pos, function(val, key) { 462 if (map.hasOwnProperty(val)) { 463 mix = this.mix(mix, map[val]); 464 } 465 }); 466 467 pos = pos.top ? this.mix(pos, mix) : mix; 468 469 pos = this.mix({ 470 top: '50%', 471 left: '50%' 472 }, pos); 473 474 this.setStyle(this.image, { 475 position : 'relative', 476 top : getPosition(pos.top, 'height', height), 477 left : getPosition(pos.left, 'width', width) 478 }); 479 this.ready = true; 480 o.complete.call(this); 481 }); 482 return this; 483 } 484}); 485 486var G = window.Galleria = Base.extend({ 487 488 __constructor : function(options) { 489 this.theme = undefined; 490 this.options = options; 491 this.playing = false; 492 this.playtime = 5000; 493 this.active = null; 494 this.queue = {}; 495 this.data = {}; 496 this.dom = {}; 497 498 var kb = this.keyboard = { 499 keys : { 500 UP: 38, 501 DOWN: 40, 502 LEFT: 37, 503 RIGHT: 39, 504 RETURN: 13, 505 ESCAPE: 27, 506 BACKSPACE: 8 507 }, 508 map : {}, 509 bound: false, 510 press: this.proxy(function(e) { 511 var key = e.keyCode || e.which; 512 if (kb.map[key] && typeof kb.map[key] == 'function') { 513 kb.map[key].call(this, e); 514 } 515 }), 516 attach: this.proxy(function(map) { 517 for( var i in map ) { 518 var k = i.toUpperCase(); 519 if ( kb.keys[k] ) { 520 kb.map[kb.keys[k]] = map[i]; 521 } 522 } 523 if (!kb.bound) { 524 kb.bound = true; 525 this.listen(document, 'keydown', kb.press); 526 } 527 }), 528 detach: this.proxy(function() { 529 kb.bound = false;
530 this.forget(document, 'keydown', kb.press); 531 }) 532 }; 533 534 this.timeouts = { 535 trunk: {}, 536 add: function(id, fn, delay, loop) { 537 loop = loop || false; 538 this.clear(id); 539 if (loop) { 540 var self = this; 541 var old = fn; 542 fn = function() { 543 old(); 544 self.add(id,fn,delay); 545 } 546 } 547 this.trunk[id] = window.setTimeout(fn,delay); 548 }, 549 clear: function(id) { 550 if (id && this.trunk[id]) { 551 window.clearTimeout(this.trunk[id]); 552 delete this.trunk[id]; 553 } else if (typeof id == 'undefined') { 554 for (var i in this.trunk) { 555 window.clearTimeout(this.trunk[i]); 556 delete this.trunk[i]; 557 } 558 } 559 } 560 }; 561 562 this.controls = { 563 0 : null, 564 1 : null, 565 active : 0, 566 swap : function() { 567 this.active = this.active ? 0 : 1; 568 }, 569 getActive : function() { 570 return this[this.active]; 571 }, 572 getNext : function() { 573 return this[Math.abs(this.active - 1)]; 574 } 575 }; 576 577 var fs = this.fullscreen = { 578 scrolled: 0, 579 enter: this.proxy(function() { 580 this.toggleClass( this.get('container'), 'fullscreen'); 581 fs.scrolled = jQuery(window).scrollTop(); 582 this.loop(fs.getElements(), function(el, i) { 583 fs.styles[i] = el.getAttribute('style'); 584 el.removeAttribute('style'); 585 }); 586 this.setStyle(fs.getElements(0), { 587 position: 'fixed', 588 top: 0, 589 left: 0, 590 width: '100%', 591 height: '100%', 592 zIndex: 10000 593 }); 594 var bh = { 595 height: '100%', 596 overflow: 'hidden', 597 margin:0, 598 padding:0 599 }; 600 this.setStyle( fs.getElements(1), bh ); 601 this.setStyle( fs.getElements(2), bh ); 602 this.attachKeyboard({ 603 escape: this.exitFullscreen, 604 right: this.next, 605 left: this.prev 606 }); 607 this.rescale(this.proxy(function() { 608 this.trigger(G.FULLSCREEN_ENTER); 609 })); 610 this.listen(window, 'resize', fs.scale); 611 }), 612 scale: this.proxy(function() { 613 this.rescale(); 614 }), 615 exit: this.proxy(function() { 616 this.toggleClass( this.get('container'), 'fullscreen', false); 617 if (!fs.styles.length) { 618 return; 619 } 620 this.loop(fs.getElements(), function(el, i) { 621 el.removeAttribute('style'); 622 el.setAttribute('style', fs.styles[i]); 623 }); 624 window.scrollTo(0, fs.scrolled); 625 this.detachKeyboard(); 626 this.rescale(this.proxy(function() { 627 this.trigger(G.FULLSCREEN_EXIT); 628 })); 629 this.forget(window, 'resize', fs.scale); 630 }), 631 styles: [], 632 getElements: this.proxy(function(i) { 633 var elems = [ this.get('container'), document.body, this.getElements('html')[0] ]; 634 return i ? elems[i] : elems; 635 }) 636 }; 637 638 var idle = this.idle = { 639 trunk: [], 640 bound: false, 641 add: this.proxy(function(elem, styles, fn) { 642 if (!elem) { 643 return; 644 }
645 if (!idle.bound) { 646 idle.addEvent(); 647 } 648 elem = jQuery(elem); 649 var orig = {}; 650 for (var style in styles) { 651 orig[style] = elem.css(style); 652 } 653 elem.data('idle', { 654 from: orig, 655 to: styles, 656 complete: true, 657 busy: false, 658 fn: this.proxy(fn) 659 }); 660 idle.addTimer(); 661 idle.trunk.push(elem); 662 }), 663 remove: this.proxy(function(elem) { 664 elem = jQuery(elem); 665 this.loop(idle.trunk, function(el, i) { 666 if ( el && !el.not(elem).length ) { 667 idle.show(elem); 668 idle.trunk.splice(i,1); 669 } 670 }); 671 if (!idle.trunk.length) { 672 idle.removeEvent(); 673 this.clearTimer('idle'); 674 } 675 }), 676 addEvent: this.proxy(function() { 677 idle.bound = true; 678 this.listen( this.get('container'), 'mousemove click', idle.showAll ); 679 }), 680 removeEvent: this.proxy(function() { 681 idle.bound = false; 682 this.forget( this.get('container'), 'mousemove click', idle.showAll ); 683 }), 684 addTimer: this.proxy(function() { 685 this.addTimer('idle', this.proxy(function() { 686 idle.hide(); 687 }),this.options.idle_time); 688 }), 689 hide: this.proxy(function() { 690 this.trigger(G.IDLE_ENTER); 691 this.loop(idle.trunk, function(elem) { 692 var data = elem.data('idle'); 693 data.complete = false; 694 data.fn(); 695 elem.animate(data.to, { 696 duration: 600, 697 queue: false, 698 easing: 'swing' 699 }); 700 }); 701 }), 702 showAll: this.proxy(function() { 703 this.clearTimer('idle'); 704 this.loop(idle.trunk, function(elem) { 705 idle.show(elem); 706 }); 707 }), 708 show: this.proxy(function(elem) { 709 var data = elem.data('idle'); 710 if (!data.busy && !data.complete) { 711 data.busy = true; 712 this.trigger(G.IDLE_EXIT); 713 elem.animate(data.from, { 714 duration: 300, 715 queue: false, 716 easing: 'swing', 717 complete: function() { 718 $(this).data('idle').busy = false; 719 $(this).data('idle').complete = true; 720 } 721 }); 722 } 723 idle.addTimer(); 724 }) 725 }; 726 727 var lightbox = this.lightbox = { 728 w: 0, 729 h: 0, 730 initialized: false, 731 active: null, 732 init: this.proxy(function() { 733 if (lightbox.initialized) { 734 return; 735 } 736 lightbox.initialized = true; 737 var elems = 'lightbox-overlay lightbox-box lightbox-content lightbox-shadow lightbox-title ' + 738 'lightbox-info lightbox-close lightbox-prev lightbox-next lightbox-counter'; 739 this.loop(elems.split(' '), function(el) { 740 this.addElement(el); 741 lightbox[el.split('-')[1]] = this.get(el); 742 }); 743 744 lightbox.image = new Galleria.Picture(); 745 746 this.append({ 747 'lightbox-box': ['lightbox-shadow','lightbox-content', 'lightbox-close'], 748 'lightbox-info': ['lightbox-title','lightbox-counter','lightbox-next','lightbox-prev'], 749 'lightbox-content': ['lightbox-info'] 750 }); 751 document.body.appendChild( lightbox.overlay ); 752 document.body.appendChild( lightbox.box );
753 lightbox.content.appendChild( lightbox.image.elem ); 754 755 lightbox.close.innerHTML = '×'; 756 lightbox.prev.innerHTML = '◄'; 757 lightbox.next.innerHTML = '►'; 758 759 this.listen( lightbox.close, 'click', lightbox.hide ); 760 this.listen( lightbox.overlay, 'click', lightbox.hide ); 761 this.listen( lightbox.next, 'click', lightbox.showNext ); 762 this.listen( lightbox.prev, 'click', lightbox.showPrev ); 763 764 if (this.options.lightbox_clicknext) { 765 this.setStyle( lightbox.image.elem, {cursor:'pointer'} ); 766 this.listen( lightbox.image.elem, 'click', lightbox.showNext); 767 } 768 this.setStyle( lightbox.overlay, { 769 position: 'fixed', display: 'none', 770 opacity: this.options.overlay_opacity, 771 top: 0, left: 0, width: '100%', height: '100%', 772 background: this.options.overlay_background, zIndex: 99990 773 }); 774 this.setStyle( lightbox.box, { 775 position: 'fixed', display: 'none', 776 width: 400, height: 400, top: '50%', left: '50%', 777 marginTop: -200, marginLeft: -200, zIndex: 99991 778 }); 779 this.setStyle( lightbox.shadow, { 780 background:'#000', opacity:.4, width: '100%', height: '100%', position: 'absolute' 781 }); 782 this.setStyle( lightbox.content, { 783 backgroundColor:'#fff',position: 'absolute', 784 top: 10, left: 10, right: 10, bottom: 10, overflow: 'hidden' 785 }); 786 this.setStyle( lightbox.info, { 787 color: '#444', fontSize: '11px', fontFamily: 'arial,sans-serif', height: 13, lineHeight: '13px', 788 position: 'absolute', bottom: 10, left: 10, right: 10, opacity: 0 789 }); 790 this.setStyle( lightbox.close, { 791 background: '#fff', height: 20, width: 20, position: 'absolute', textAlign: 'center', cursor: 'pointer', 792 top: 10, right: 10, lineHeight: '22px', fontSize: '16px', fontFamily:'arial,sans-serif',color:'#444', zIndex: 99999 793 }); 794 this.setStyle( lightbox.image.elem, { 795 top: 10, left: 10, right: 10, bottom: 30, position: 'absolute' 796 }); 797 this.loop('title prev next counter'.split(' '), function(el) { 798 var css = { display: 'inline', 'float':'left' }; 799 if (el != 'title') { 800 this.mix(css, { 'float': 'right'}); 801 if (el != 'counter') { 802 this.mix(css, { cursor: 'pointer'}); 803 } else { 804 this.mix(css, { marginLeft: 8 }); 805 } 806 } 807 this.setStyle(lightbox[el], css); 808 }); 809 this.loop('prev next close'.split(' '), function(el) { 810 this.listen(lightbox[el], 'mouseover', this.proxy(function() { 811 this.setStyle(lightbox[el], { color:'#000' }); 812 })); 813 this.listen(lightbox[el], 'mouseout', this.proxy(function() { 814 this.setStyle(lightbox[el], { color:'#444' }); 815 })); 816 }); 817 this.trigger(G.LIGHTBOX_OPEN); 818 }), 819 rescale: this.proxy(function(e) { 820 var w = Math.min( this.width(window), lightbox.w ); 821 var h = Math.min( this.height(window), lightbox.h ); 822 var r = Math.min( (w-60) / lightbox.w, (h-80) / lightbox.h ); 823 var destW = (lightbox.w * r) + 40; 824 var destH = (lightbox.h * r) + 60; 825 var dest = { 826 width: destW, 827 height: destH, 828 marginTop: Math.ceil(destH/2)*-1, 829 marginLeft: Math.ceil(destW)/2*-1 830 } 831 if (!e) { 832 this.animate( lightbox.box, { 833 to: dest, 834 duration: this.options.lightbox_transition_speed, 835 easing: 'galleria', 836 complete: function() { 837 this.trigger({ 838 type: G.LIGHTBOX_IMAGE, 839 imageTarget: lightbox.image.image 840 }); 841 this.moveIn( lightbox.image.image ); 842 this.animate( lightbox.image.image, { to: { opacity:1 }, duration: this.options.lightbox_fade_speed } ); 843 this.animate( lightbox.info, { to: { opacity:1 }, duration: this.options.lightbox_fade_speed } ); 844 } 845 }); 846 } else { 847 this.setStyle( lightbox.box, dest ); 848 } 849 }), 850 hide: this.proxy(function() { 851 lightbox.image.image = null; 852 this.forget(window, 'resize', lightbox.rescale); 853 this.hide( lightbox.box ); 854 this.setStyle( lightbox.info, { opacity: 0 } ); 855 this.animate( lightbox.overlay, { 856 to: { opacity: 0 }, 857 duration: 200, 858 complete: function() { 859 this.hide( lightbox.overlay ); 860 this.setStyle( lightbox.overlay, { opacity: this.options.overlay_opacity}); 861 this.trigger(G.LIGHTBOX_CLOSE); 862 } 863 }); 864 }), 865 showNext: this.proxy(function() { 866 lightbox.show(this.getNext(lightbox.active)); 867 }), 868 showPrev: this.proxy(function() { 869 lightbox.show(this.getPrev(lightbox.active)); 870 }), 871 show: this.proxy(function(index) { 872 if (!lightbox.initialized) { 873 lightbox.init(); 874 } 875 this.forget( window, 'resize', lightbox.rescale ); 876 index = typeof index == 'number' ? index : this.getIndex(); 877 lightbox.active = index; 878 879 var data = this.getData(index); 880 var total = this.data.length; 881 this.setStyle( lightbox.info, {opacity:0}
881 ); 882 883 lightbox.image.load( data.image, function(o) { 884 lightbox.w = o.scope.orig.w; 885 lightbox.h = o.scope.orig.h; 886 this.setStyle(o.target, { 887 width: '100.5%', 888 height: '100.5%', 889 top:0, 890 zIndex: 99998, 891 opacity: 0 892 }); 893 lightbox.title.innerHTML = data.title; 894 lightbox.counter.innerHTML = (index+1) + ' / ' + total; 895 this.listen( window, 'resize', lightbox.rescale ); 896 lightbox.rescale(); 897 }); 898 this.reveal( lightbox.overlay ); 899 this.reveal( lightbox.box ); 900 }) 901 }; 902 903 this.thumbnails = { width: 0 }; 904 this.stageWidth = 0; 905 this.stageHeight = 0; 906 907 var elems = 'container stage images image-nav image-nav-left image-nav-right ' + 908 'info info-text info-title info-description info-author ' + 909 'thumbnails thumbnails-list thumbnails-container thumb-nav-left thumb-nav-right ' + 910 'loader counter'; 911 elems = elems.split(' '); 912 913 this.loop(elems, function(blueprint) { 914 this.dom[ blueprint ] = this.create('div', 'galleria-' + blueprint); 915 }); 916 917 this.target = this.dom.target = options.target.nodeName ? 918 options.target : this.getElements(options.target)[0]; 919 920 if (!this.target) { 921 G.raise('Target not found.'); 922 } 923 }, 924 925 init: function() { 926 927 this.options = this.mix(G.theme.defaults, this.options); 928 this.options = this.mix({ 929 autoplay: false, 930 carousel: true, 931 carousel_follow: true, 932 carousel_speed: 400, 933 carousel_steps: 'auto', 934 clicknext: false, 935 data_config : function( elem ) { return {}; }, 936 data_image_selector: 'img', 937 data_source: this.target, 938 data_type: 'auto', 939 debug: false, 940 extend: function(options) {}, 941 height: 'auto', 942 idle_time: 3000, 943 image_crop: false, 944 image_margin: 0, 945 image_pan: false, 946 image_pan_smoothness: 12, 947 image_position: '50%', 948 keep_source: false, 949 lightbox_clicknext: true, 950 lightbox_fade_speed: 200, 951 lightbox_transition_speed: 300, 952 link_source_images: true, 953 max_scale_ratio: undefined, 954 min_scale_ratio: undefined, 955 on_image: function(img,thumb) {}, 956 overlay_opacity: .85, 957 overlay_background: '#0b0b0b', 958 popup_links: false, 959 preload: 2, 960 queue: true, 961 show: 0, 962 show_info: true, 963 show_counter: true, 964 show_imagenav: true, 965 thumb_crop: true, 966 thumb_fit: true, 967 thumb_margin: 0, 968 thumb_quality: 'auto', 969 thumbnails: true, 970 transition: G.transitions.fade, 971 transition_speed: 400 972 }, this.options); 973 974 var o = this.options; 975 976 this.bind(G.DATA, function() { 977 this.run(); 978 }); 979 980 if (o.clicknext) { 981 this.loop(this.data, function(data) { 982 delete data.link; 983 }); 984 this.setStyle(this.get('stage'), { cursor: 'pointer'} ); 985 this.listen(this.get('stage'), 'click', this.proxy(function() { 986 this.next(); 987 })); 988 } 989 990 this.bind(G.IMAGE, function(e) { 991 o.on_image.call(this, e.imageTarget, e.thumbTarget); 992 }); 993 994 this.bind(G.READY, function() { 995 if (G.History) { 996 G.History.change(this.proxy(function(e) { 997 var val = parseInt(e.value.replace(/\//,'')); 998 if (isNaN(val)) { 999 window.history.go(-1); 1000 } else { 1001 this.show(val, undefined, true); 1002 } 1003 })); 1004 } 1005 1006 G.theme.init.call(this, o); 1007 o.extend.call(this, o); 1008 1009 if (/^[0-9]{1,4}$/.test(hash) && G.History) { 1010 this.show(hash, undefined, true); 1011 } else if (typeof o.show == 'number') { 1012 this.show(o.show); 1013 } 1014 1015 if (o.autoplay) { 1016 if (typeof o.autoplay == 'number') { 1017 this.playtime = o.autoplay; 1018 } 1019 this.trigger( G.PLAY ); 1020 this.playing = true; 1021 } 1022 }); 1023 this.load(); 1024 return this; 1025 }, 1026
1027 bind : function(type, fn) { 1028 this.listen( this.get('container'), type, this.proxy(fn) ); 1029 return this; 1030 }, 1031 1032 unbind : function(type) { 1033 this.forget( this.get('container'), type ); 1034 }, 1035 1036 trigger : function( type ) { 1037 type = typeof type == 'object' ? 1038 this.mix( type, { scope: this } ) : 1039 { type: type, scope: this }; 1040 this.dispatch( this.get('container'), type ); 1041 return this; 1042 }, 1043 1044 addIdleState: function() { 1045 this.idle.add.apply(this, arguments); 1046 return this; 1047 }, 1048 1049 removeIdleState: function() { 1050 this.idle.remove.apply(this, arguments); 1051 return this; 1052 }, 1053 1054 enterIdleMode: function() { 1055 this.idle.hide(); 1056 return this; 1057 }, 1058 1059 exitIdleMode: function() { 1060 this.idle.show(); 1061 return this; 1062 }, 1063 1064 addTimer: function() { 1065 this.timeouts.add.apply(this.timeouts, arguments); 1066 return this; 1067 }, 1068 1069 clearTimer: function() { 1070 this.timeouts.clear.apply(this.timeouts, arguments); 1071 return this; 1072 }, 1073 1074 enterFullscreen: function() { 1075 this.fullscreen.enter.apply(this, arguments); 1076 return this; 1077 }, 1078 1079 exitFullscreen: function() { 1080 this.fullscreen.exit.apply(this, arguments); 1081 return this; 1082 }, 1083 1084 openLightbox: function() { 1085 this.lightbox.show.apply(this, arguments); 1086 }, 1087 1088 closeLightbox: function() { 1089 this.lightbox.hide.apply(this, arguments); 1090 }, 1091 1092 getActive: function() { 1093 return this.controls.getActive(); 1094 }, 1095 1096 getActiveImage: function() { 1097 return this.getActive().image || null; 1098 }, 1099 1100 run : function() { 1101 var o = this.options; 1102 if (!this.data.length) { 1103 G.raise('Data is empty.'); 1104 } 1105 if (!o.keep_source && !Galleria.IE) { 1106 this.target.innerHTML = ''; 1107 } 1108 this.loop(2, function() { 1109 var image = new Picture(); 1110 this.setStyle( image.elem, { 1111 position: 'absolute', 1112 top: 0, 1113 left: 0 1114 }); 1115 this.setStyle(this.get( 'images' ), { 1116 position: 'relative', 1117 top: 0, 1118 left: 0, 1119 width: '100%', 1120 height: '100%' 1121 }); 1122 this.get( 'images' ).appendChild( image.elem ); 1123 this.push(image, this.controls); 1124 }, this); 1125 1126 if (o.carousel) { 1127 // try the carousel on each thumb load 1128 this.bind(G.THUMBNAIL, this.parseCarousel); 1129 } 1130 1131 this.build(); 1132 this.target.appendChild(this.get('container')); 1133 1134 this.loop(['info','counter','image-nav'], function(el) { 1135 if ( o[ 'show_'+el.replace(/-/,'') ] === false ) { 1136 this.moveOut( this.get(el) ); 1137 } 1138 }); 1139 1140 var w = 0; 1141 var h = 0; 1142 1143 for( var i=0; this.data[i]; i++ ) { 1144 var thumb; 1145 if (o.thumbnails === true) { 1146 thumb = new Picture(i); 1147 var src = this.data[i].thumb || this.data[i].image; 1148 1149 this.get( 'thumbnails' ).appendChild( thumb.elem ); 1150 1151 w = this.getStyle(thumb.elem, 'width', true); 1152 h = this.getStyle(thumb.elem, 'height', true); 1153 1154 // grab & reset size for smoother thumbnail loads 1155 if (o.thumb_fit && o.thum_crop !== true) { 1156 this.setStyle(thumb.elem, { width:0, height: 0}); 1157 } 1158 1159 thumb.load(src, this.proxy(function(e) { 1160 var orig = e.target.width; 1161 e.scope.scale({ 1162 width: w, 1163 height: h, 1164 crop: o.thumb_crop, 1165 margin: o.thumb_margin, 1166 complete: this.proxy(function() { 1167 // shrink thumbnails to fit 1168 var top = ['left', 'top'];
1169 var arr = ['Height', 'Width']; 1170 this.loop(arr, function(m,i) { 1171 if ((!o.thumb_crop || o.thumb_crop == m.toLowerCase()) && o.thumb_fit) { 1172 var css = {}; 1173 var opp = arr[Math.abs(i-1)].toLowerCase(); 1174 css[opp] = e.target[opp]; 1175 this.setStyle(e.target.parentNode, css); 1176 var css = {}; 1177 css[top[i]] = 0; 1178 this.setStyle(e.target, css); 1179 } 1180 e.scope['outer'+m] = this[m.toLowerCase()](e.target.parentNode, true); 1181 }); 1182 // set high quality if downscale is moderate 1183 this.toggleQuality(e.target, o.thumb_quality === true || ( o.thumb_quality == 'auto' && orig < e.target.width * 3 )); 1184 this.trigger({ 1185 type: G.THUMBNAIL, 1186 thumbTarget: e.target, 1187 thumbOrder: e.scope.order 1188 }); 1189 }) 1190 }); 1191 })); 1192 if (o.preload == 'all') { 1193 thumb.add(this.data[i].image); 1194 } 1195 } else if (o.thumbnails == 'empty') { 1196 thumb = { 1197 elem: this.create('div','galleria-image'), 1198 image: this.create('span','img') 1199 };
1200 thumb.elem.appendChild(thumb.image); 1201 this.get( 'thumbnails' ).appendChild( thumb.elem ); 1202 } else { 1203 thumb = { 1204 elem: false, 1205 image: false 1206 } 1207 } 1208 var activate = this.proxy(function(e) { 1209 this.pause(); 1210 e.preventDefault(); 1211 var ind = e.currentTarget.rel; 1212 if (this.active !== ind) { 1213 this.show( ind ); 1214 } 1215 }); 1216 if (o.thumbnails !== false) { 1217 thumb.elem.rel = i; 1218 this.listen(thumb.elem, 'click', activate); 1219 } 1220 if (o.link_source_images && o.keep_source && this.data[i].elem) { 1221 this.data[i].elem.rel = i; 1222 this.listen(this.data[i].elem, 'click', activate); 1223 } 1224 this.push(thumb, this.thumbnails ); 1225 } 1226 this.setStyle( this.get('thumbnails'), { opacity: 0 } ); 1227 1228 if (o.height && o.height != 'auto') { 1229 this.setStyle( this.get('container'), { height: o.height }) 1230 } 1231 1232 this.wait(function() { 1233 // the most sensitive piece of code in Galleria, we need to have all the meassurements right to continue 1234 var cssHeight = this.getStyle( this.get( 'container' ), 'height', true ); 1235 this.stageWidth = this.width(this.get( 'stage' )); 1236 this.stageHeight = this.height( this.get( 'stage' )); 1237 if (this.stageHeight < 50 && o.height == 'auto') { 1238 // no height detected for sure, set reasonable ratio (16/9) 1239 this.setStyle( this.get( 'container' ), { 1240 height: Math.round( this.stageWidth*9/16 ) 1241 } ); 1242 this.stageHeight = this.height( this.get( 'stage' )); 1243 } 1244 return this.stageHeight && this.stageWidth; 1245 }, function() { 1246 this.listen(this.get('image-nav-right'), 'click', this.proxy(function(e) { 1247 if (o.clicknext) { 1248 e.stopPropagation(); 1249 } 1250 this.pause(); 1251 this.next(); 1252 })); 1253 this.listen(this.get('image-nav-left'), 'click', this.proxy(function(e) { 1254 if (o.clicknext) { 1255 e.stopPropagation(); 1256 } 1257 this.pause(); 1258 this.prev(); 1259 })); 1260 this.setStyle( this.get('thumbnails'), { opacity: 1 } ); 1261 this.trigger( G.READY ); 1262 }, function() { 1263 G.raise('Galleria could not load properly. Make sure stage has a height and width.'); 1264 }, 5000); 1265 }, 1266 1267 mousePosition : function(e) { 1268 return { 1269 x: e.pageX - this.$('stage').offset().left + jQuery(document).scrollLeft(), 1270 y: e.pageY - this.$('stage').offset().top + jQuery(document).scrollTop() 1271 }; 1272 }, 1273 1274 addPan : function(img) { 1275 var c = this.options.image_crop; 1276 if ( c === false ) { 1277 return; 1278 } 1279 if (this.options.image_crop === false) { 1280 return; 1281 } 1282 img = img || this.controls.getActive().image; 1283 if (img.tagName.toUpperCase() != 'IMG') { 1284 G.raise('Could not add pan'); 1285 } 1286 1287 var x = img.width/2; 1288 var y = img.height/2; 1289 var curX = destX = this.getStyle(img, 'left', true) || 0; 1290 var curY = destY = this.getStyle(img, 'top', true) || 0; 1291 var distX = 0; 1292 var distY = 0; 1293 var active = false; 1294 var ts = new Date().getTime(); 1295 var calc = this.proxy(function(e) { 1296 if (new Date().getTime() - ts < 50) { 1297 return; 1298 } 1299 active = true; 1300 x = this.mousePosition(e).x; 1301 y = this.mousePosition(e).y; 1302 }); 1303 var loop = this.proxy(function(e) { 1304 if (!active) { 1305 return; 1306 } 1307 distX = img.width - this.stageWidth;
1308 distY = img.height - this.stageHeight; 1309 destX = x / this.stageWidth * distX * -1; 1310 destY = y / this.stageHeight * distY * -1; 1311 curX += (destX - curX) / this.options.image_pan_smoothness; 1312 curY += (destY - curY) / this.options.image_pan_smoothness; 1313 if (distY > 0) { 1314 this.setStyle(img, { top: Math.max(distY*-1, Math.min(0, curY)) }); 1315 } 1316 if (distX > 0) { 1317 this.setStyle(img, { left: Math.max(distX*-1, Math.min(0, curX)) }); 1318 } 1319 }); 1320 this.forget(this.get('stage'), 'mousemove'); 1321 this.listen(this.get('stage'), 'mousemove', calc); 1322 this.addTimer('pan', loop, 30, true); 1323 }, 1324 1325 removePan: function() { 1326 this.forget(this.get('stage'), 'mousemove'); 1327 this.clearTimer('pan'); 1328 }, 1329 1330 parseCarousel : function(e) { 1331 var w = 0; 1332 var h = 0; 1333 var hooks = [0]; 1334 this.loop(this.thumbnails, function(thumb,i) { 1335 if (thumb.ready) { 1336 w += thumb.outerWidth || this.width(thumb.elem, true); 1337 hooks[i+1] = w; 1338 h = Math.max(h, this.height(thumb.elem)); 1339 } 1340 }); 1341 this.toggleClass(this.get('thumbnails-container'), 'galleria-carousel', w > this.stageWidth); 1342 this.setStyle(this.get('thumbnails-list'), { 1343 overflow:'hidden', 1344 position: 'relative' // for IE Standards mode 1345 }); 1346 this.setStyle(this.get('thumbnails'), { 1347 width: w, 1348 height: h, 1349 position: 'relative', 1350 overflow: 'hidden' 1351 }); 1352 if (!this.carousel) { 1353 this.initCarousel(); 1354 } 1355 this.carousel.max = w; 1356 this.carousel.hooks = hooks; 1357 this.carousel.width = this.width(this.get('thumbnails-list')); 1358 this.carousel.setClasses(); 1359 }, 1360 1361 initCarousel : function() { 1362 var c = this.carousel = { 1363 right: this.get('thumb-nav-right'), 1364 left: this.get('thumb-nav-left'), 1365 update: this.proxy(function() { 1366 this.parseCarousel(); 1367 // todo: fix so the carousel moves to the left 1368 }), 1369 width: 0, 1370 current: 0, 1371 set: function(i) { 1372 i = Math.max(i,0); 1373 while (c.hooks[i-1] + c.width > c.max && i >= 0) { 1374 i--; 1375 } 1376 c.current = i; 1377 c.animate(); 1378 }, 1379 hooks: [], 1380 getLast: function(i) { 1381 i = i || c.current 1382 1383 return i-1; 1384 }, 1385 follow: function(i) { 1386 if (i == 0 || i == c.hooks.length-2) { 1387 c.set(i); 1388 return; 1389 } 1390 var last = c.current; 1391 while(c.hooks[last] - c.hooks[c.current] < c.width && last<= c.hooks.length) { 1392 last++; 1393 } 1394 if (i-1 < c.current) { 1395 c.set(i-1) 1396 } else if (i+2 > last) { 1397 c.set(i - last + c.current + 2) 1398 } 1399 }, 1400 max: 0, 1401 setClasses: this.proxy(function() { 1402 this.toggleClass( c.left, 'disabled', !c.current ); 1403 this.toggleClass( c.right, 'disabled', c.hooks[c.current] + c.width > c.max ); 1404 }), 1405 animate: this.proxy(function(to) { 1406 c.setClasses(); 1407 this.animate( this.get('thumbnails'), { 1408 to: { left: c.hooks[c.current] * -1 }, 1409 duration: this.options.carousel_speed, 1410 easing: 'galleria', 1411 queue: false 1412 }); 1413 }) 1414 }; 1415 this.listen(c.right, 'click', this.proxy(function(e) { 1416 if (this.options.carousel_steps == 'auto') { 1417 for (var i = c.current; i<c.hooks.length; i++) { 1418 if (c.hooks[i] - c.hooks[c.current] > c.width) { 1419 c.set(i-2); 1420 break; 1421 } 1422 } 1423 } else { 1424 c.set(c.current + this.options.carousel_steps); 1425 } 1426 })); 1427 this.listen(c.left, 'click', this.proxy(function(e) { 1428 if (this.options.carousel_steps == 'auto') { 1429 for (var i = c.current; i>=0; i--) { 1430 if (c.hooks[c.current] - c.hooks[i] > c.width) { 1431 c.set(i+2); 1432 break; 1433 } else if (i == 0) { 1434 c.set(0); 1435 break; 1436 } 1437 } 1438 } else { 1439 c.set(c.current - this.options.carousel_steps); 1440 } 1441 })); 1442 }, 1443 addElement : function() { 1444 this.loop(arguments, function(b) { 1445 this.dom[b] = this.create('div', 'galleria-' + b ); 1446 }); 1447 return this; 1448 }, 1449 getDimensions: function(i) { 1450 return { 1451 w: i.width, 1452 h: i.height, 1453 cw: this.stageWidth, 1454 ch: this.stageHeight, 1455 top: (this.stageHeight - i.height) / 2, 1456 left: (this.stageWidth - i.width) / 2 1457 }; 1458 }, 1459 attachKeyboard : function(map) { 1460 this.keyboard.attach(map); 1461 return this; 1462 }, 1463 detachKeyboard : function() { 1464 this.keyboard.detach(); 1465 return this; 1466 }, 1467 build : function() { 1468 this.append({ 1469 'info-text' : 1470 ['info-title', 'info-description', 'info-author'], 1471 'info' : 1472 ['info-text'], 1473 'image-nav' : 1474 ['image-nav-right', 'image-nav-left'], 1475 'stage' : 1476 ['images', 'loader', 'counter', 'image-nav'], 1477 'thumbnails-list' : 1478 ['thumbnails'], 1479 'thumbnails-container' :
1480 ['thumb-nav-left', 'thumbnails-list', 'thumb-nav-right'], 1481 'container' : 1482 ['stage', 'thumbnails-container', 'info'] 1483 }); 1484 1485 this.current = this.create('span', 'current'); 1486 this.current.innerHTML = '-'; 1487 this.get('counter').innerHTML = ' / <span class="total">' + this.data.length + '</span>'; 1488 this.prependChild('counter', this.current); 1489 }, 1490 1491 appendChild : function(parent, child) { 1492 try { 1493 this.get(parent).appendChild(this.get(child)); 1494 } catch(e) {} 1495 }, 1496 1497 prependChild : function(parent, child) { 1498 var child = this.get(child) || child; 1499 try { 1500 this.get(parent).insertBefore(child, this.get(parent).firstChild); 1501 } catch(e) {} 1502 }, 1503 1504 remove : function() { 1505 var a = Array.prototype.slice.call(arguments); 1506 this.jQuery(a.join(',')).remove(); 1507 }, 1508 1509 append : function(data) { 1510 for( var i in data) { 1511 if (data[i].constructor == Array) { 1512 for(var j=0; data[i][j]; j++) { 1513 this.appendChild(i, data[i][j]); 1514 } 1515 } else { 1516 this.appendChild(i, data[i]); 1517 } 1518 } 1519 return this; 1520 }, 1521 1522 rescale : function(width, height, callback) { 1523 1524 var o = this.options; 1525 callback = this.proxy(callback); 1526 1527 if (typeof width == 'function') { 1528 callback = this.proxy(width); 1529 width = undefined; 1530 } 1531 1532 var scale = this.proxy(function() { 1533 this.stageWidth = width || this.width(this.get('stage')); 1534 this.stageHeight = height || this.height(this.get('stage')); 1535 this.controls.getActive().scale({ 1536 width: this.stageWidth, 1537 height: this.stageHeight, 1538 crop: o.image_crop, 1539 max: o.max_scale_ratio, 1540 min: o.min_scale_ratio, 1541 margin: o.image_margin, 1542 position: o.image_position 1543 }); 1544 if (this.carousel) { 1545 this.carousel.update(); 1546 } 1547 this.trigger(G.RESCALE) 1548 callback(); 1549 }); 1550 if ( G.WEBKIT && !width && !height ) { 1551 this.addTimer('scale', scale, 5);// webkit is too fast 1552 } else { 1553 scale.call(this); 1554 } 1555 }, 1556 1557 show : function(index, rewind, history) { 1558 if (!this.options.queue && this.queue.stalled) { 1559 return; 1560 } 1561 rewind = typeof rewind != 'undefined' ? !!rewind : index < this.active; 1562 history = history || false; 1563 index = Math.max(0, Math.min(parseInt(index), this.data.length - 1)); 1564 if (!history && G.History) { 1565 G.History.value(index.toString()); 1566 return; 1567 } 1568 this.active = index; 1569 this.push([index,rewind], this.queue); 1570 if (!this.queue.stalled) { 1571 this.showImage(); 1572 } 1573 return this; 1574 }, 1575 1576 showImage : function() { 1577 var o = this.options; 1578 var args = this.queue[0]; 1579 var index = args[0]; 1580 var rewind = !!args[1]; 1581 if (o.carousel && this.carousel && o.carousel_follow) { 1582 this.carousel.follow(index); 1583 } 1584 1585 var src = this.getData(index).image; 1586 var active = this.controls.getActive(); 1587 var next = this.controls.getNext(); 1588 var cached = next.isCached(src); 1589 var complete = this.proxy(function() { 1590 this.queue.stalled = false; 1591 this.toggleQuality(next.image, o.image_quality); 1592 this.setStyle( active.elem, { zIndex : 0 } ); 1593 this.setStyle( next.elem, { zIndex : 1 } ); 1594 this.trigger({ 1595 type: G.IMAGE, 1596 index: index, 1597 imageTarget: next.image, 1598 thumbTarget: this.thumbnails[index].image 1599 }); 1600 if (o.image_pan) { 1601 this.addPan(next.image); 1602 } 1603 this.controls.swap(); 1604 this.moveOut( active.image ); 1605 if (this.getData( index ).link) { 1606 this.setStyle( next.image, { cursor: 'pointer' } ); 1607 this.listen( next.image, 'click', this.proxy(function() { 1608 if (o.popup_links) { 1609 var win = window.open(this.getData( index ).link, '_blank'); 1610 } else { 1611 window.location.href = this.getData( index ).link; 1612 } 1613 })); 1614 } 1615 Array.prototype.shift.call( this.queue ); 1616 if (this.queue.length) { 1617 this.showImage(); 1618 } 1619 this.playCheck(); 1620 }); 1621 if (typeof o.preload == 'number' && o.preload > 0) { 1622 var p,n = this.getNext(); 1623 try { 1624 for (var i = o.preload; i>0; i--) {
1625 p = new Picture(); 1626 p.add(this.getData(n).image); 1627 n = this.getNext(n); 1628 } 1629 } catch(e) {} 1630 } 1631 this.trigger( { 1632 type: G.LOADSTART, 1633 cached: cached, 1634 index: index, 1635 imageTarget: next.image, 1636 thumbTarget: this.thumbnails[index].image 1637 } ); 1638 1639 jQuery(this.thumbnails[index].elem).addClass('active').siblings('.active').removeClass('active'); 1640 1641 next.load( src, this.proxy(function(e) { 1642 next.scale({ 1643 width: this.stageWidth, 1644 height: this.stageHeight, 1645 crop: o.image_crop, 1646 max: o.max_scale_ratio, 1647 min: o.min_scale_ratio, 1648 margin: o.image_margin, 1649 position: o.image_position, 1650 complete: this.proxy(function() { 1651 if (active.image) { 1652 this.toggleQuality(active.image, false); 1653 } 1654 this.toggleQuality(next.image, false); 1655 this.trigger({ 1656 type: G.LOADFINISH, 1657 cached: cached, 1658 index: index, 1659 imageTarget: next.image, 1660 thumbTarget: this.thumbnails[index].image 1661 }); 1662 this.queue.stalled = true; 1663 var transition = G.transitions[o.transition] || o.transition; 1664 this.removePan(); 1665 this.setInfo(index); 1666 this.setCounter(index); 1667 if (typeof transition == 'function') { 1668 transition.call(this, { 1669 prev: active.image, 1670 next: next.image, 1671 rewind: rewind, 1672 speed: o.transition_speed || 400 1673 }, complete ); 1674 } else { 1675 complete(); 1676 } 1677 }) 1678 }); 1679 })); 1680 }, 1681 1682 getNext : function(base) { 1683 base = typeof base == 'number' ? base : this.active; 1684 return base == this.data.length - 1 ? 0 : base + 1; 1685 }, 1686 1687 getPrev : function(base) { 1688 base = typeof base == 'number' ? base : this.active; 1689 return base === 0 ? this.data.length - 1 : base - 1; 1690 }, 1691 1692 next : function() { 1693 if (this.data.length > 1) { 1694 this.show(this.getNext(), false); 1695 } 1696 return this; 1697 }, 1698 1699 prev : function() { 1700 if (this.data.length > 1) { 1701 this.show(this.getPrev(), true); 1702 } 1703 return this; 1704 }, 1705 1706 get : function( elem ) { 1707 return elem in this.dom ? this.dom[ elem ] : null; 1708 }, 1709 1710 getData : function( index ) { 1711 return this.data[index] || this.data[this.active]; 1712 }, 1713 1714 getIndex : function() { 1715 return typeof this.active === 'number' ? this.active : 0; 1716 }, 1717 1718 play : function(delay) { 1719 this.trigger( G.PLAY ); 1720 this.playing = true; 1721 this.playtime = delay || this.playtime; 1722 this.playCheck(); 1723 return this; 1724 }, 1725 1726 pause : function() { 1727 this.trigger( G.PAUSE ); 1728 this.playing = false; 1729 return this; 1730 }, 1731 1732 playCheck : function() { 1733 var p = 0; 1734 var i = 20; // the interval 1735 var ts = function() { 1736 return new Date().getTime(); 1737 } 1738 var now = ts(); 1739 if (this.playing) { 1740 this.clearTimer('play'); 1741 var fn = this.proxy(function() { 1742 p = ts() - now; 1743 if ( p >= this.playtime && this.playing ) { 1744 this.clearTimer('play'); 1745 this.next(); 1746 return; 1747 } 1748 if ( this.playing ) { 1749 this.trigger({ 1750 type: G.PROGRESS, 1751 percent: Math.ceil(p / this.playtime * 100), 1752 seconds: Math.floor(p/1000), 1753 milliseconds: p 1754 }); 1755 this.addTimer('play', fn, i); 1756 } 1757 }); 1758 this.addTimer('play', fn, i); 1759 } 1760 }, 1761 1762 setActive: function(val) { 1763 this.active = val; 1764 return this; 1765 }, 1766 1767 setCounter: function(index) { 1768 index = index || this.active; 1769 this.current.innerHTML = index+1; 1770 return this; 1771 }, 1772 1773 setInfo : function(index) { 1774 var data = this.getData(index || this.active); 1775 this.loop(['title','description','author'], function(type) { 1776 var elem = this.get('info-'+type); 1777 var fn = data[type] && data[type].length ? 'reveal' : 'hide'; 1778 this[fn](elem); 1779 if (data[type]) { 1780 elem.innerHTML = data[type]; 1781 } 1782 }); 1783 return this; 1784 }, 1785 1786 hasInfo : function(index) { 1787 var d = this.getData(index); 1788 var check = 'title description author'.split(' '); 1789 for ( var i=0; check[i]; i++ ) { 1790 if ( d[ check[i] ] && d[ check[i] ].length ) { 1791 return true; 1792 } 1793 } 1794 return false;
1795 }, 1796 1797 getDataObject : function(o) { 1798 var obj = { 1799 image: '', 1800 thumb: '', 1801 title: '', 1802 description: '', 1803 author: '', 1804 link: '' 1805 }; 1806 return o ? this.mix(obj,o) : obj; 1807 }, 1808 1809 jQuery : function( str ) { 1810 var ret = []; 1811 this.loop(str.split(','), this.proxy(function(elem) { 1812 elem = elem.replace(/^\s\s*/, "").replace(/\s\s*$/, ""); 1813 if (this.get(elem)) { 1814 ret.push(elem); 1815 } 1816 })); 1817 var jQ = jQuery(this.get(ret.shift())); 1818 this.loop(ret, this.proxy(function(elem) { 1819 jQ = jQ.add(this.get(elem)); 1820 })); 1821 return jQ; 1822 }, 1823 1824 $ : function( str ) { 1825 return this.jQuery( str ); 1826 }, 1827 1828 toggleQuality : function(img, force) { 1829 if (!G.IE7 || typeof img == 'undefined' || !img) { 1830 return this; 1831 } 1832 if (typeof force === 'undefined') { 1833 force = img.style.msInterpolationMode == 'nearest-neighbor'; 1834 } 1835 img.style.msInterpolationMode = force ? 'bicubic' : 'nearest-neighbor'; 1836 1837 return this; 1838 }, 1839 1840 unload : function() { 1841 //TODO 1842 }, 1843 1844 load : function() { 1845 var loaded = 0; 1846 var o = this.options; 1847 if ( 1848 (o.data_type == 'auto' && 1849 typeof o.data_source == 'object' && 1850 !(o.data_source instanceof jQuery) && 1851 !o.data_source.tagName 1852 ) || o.data_type == 'json' || o.data_source.constructor == Array ) { 1853 this.data = o.data_source; 1854 this.trigger( G.DATA ); 1855 1856 } else { // assume selector 1857 var images = jQuery(o.data_source).find(o.data_image_selector); 1858 var getData = this.proxy(function( elem ) { 1859 var i,j,anchor = elem.parentNode; 1860 if (anchor && anchor.nodeName == 'A') { 1861 if (anchor.href.match(/\.(png|gif|jpg|jpeg)/i)) { 1862 i = anchor.href; 1863 } else { 1864 j = anchor.href; 1865 } 1866 } 1867 var obj = this.getDataObject({ 1868 title: elem.title, 1869 thumb: elem.src, 1870 image: i || elem.src, 1871 description: elem.alt, 1872 link: j || elem.getAttribute('longdesc'), 1873 elem: elem 1874 }); 1875 return this.mix(obj, o.data_config( elem ) ); 1876 }); 1877 this.loop(images, function( elem ) { 1878 loaded++; 1879 this.push( getData( elem ), this.data ); 1880 if (!o.keep_source && !Galleria.IE) { 1881 elem.parentNode.removeChild(elem); 1882 } 1883 if ( loaded == images.length ) { 1884 this.trigger( G.DATA ); 1885 } 1886 }); 1887 } 1888 } 1889}); 1890 1891G.log = function() { 1892 try { 1893 console.log.apply( console, Array.prototype.slice.call(arguments) ); 1894 } catch(e) { 1895 try { 1896 opera.postError.apply( opera, arguments ); 1897 } catch(er) { 1898 alert( Array.prototype.join.call( arguments, " " ) ); 1899 } 1900 } 1901}; 1902 1903var nav = navigator.userAgent.toLowerCase(); 1904var hash = window.location.hash.replace(/#\//,''); 1905 1906G.DATA = 'data'; 1907G.READY = 'ready'; 1908G.THUMBNAIL = 'thumbnail'; 1909G.LOADSTART = 'loadstart'; 1910G.LOADFINISH = 'loadfinish'; 1911G.IMAGE = 'image'; 1912G.THEMELOAD = 'themeload'; 1913G.PLAY = 'play'; 1914G.PAUSE = 'pause'; 1915G.PROGRESS = 'progress'; 1916G.FULLSCREEN_ENTER = 'fullscreen_enter'; 1917G.FULLSCREEN_EXIT = 'fullscreen_exit'; 1918G.IDLE_ENTER = 'idle_enter'; 1919G.IDLE_EXIT = 'idle_exit'; 1920G.RESCALE = 'rescale'; 1921G.LIGHTBOX_OPEN = 'lightbox_open'; 1922G.LIGHTBOX_CLOSE = 'lightbox_cloe'; 1923G.LIGHTBOX_IMAGE = 'lightbox_image'; 1924 1925G.IE8 = (typeof(XDomainRequest) !== 'undefined') 1926G.IE7 = !!(window.XMLHttpRequest && document.expando); 1927G.IE6 = (!window.XMLHttpRequest); 1928G.IE = !!(G.IE6 || G.IE7); 1929G.WEBKIT = /webkit/.test( nav ); 1930G.SAFARI = /safari/.test( nav ); 1931G.CHROME = /chrome/.test( nav ); 1932G.QUIRK = (G.IE && document.compatMode && document.compatMode == "BackCompat"); 1933G.MAC = /mac/.test(navigator.platform.toLowerCase()); 1934G.OPERA = !!window.opera 1935 1936G.Picture = Picture; 1937 1938G.addTheme = function(obj) { 1939 var theme = {}; 1940 var orig = ['name','author','version','defaults','init']; 1941 var proto = G.prototype; 1942 proto.loop(orig, function(val) { 1943 if (!obj[ val ]) { 1944 G.raise(val+' not specified in theme.'); 1945 } 1946 if (val != 'name' && val != 'init') { 1947 theme[val] = obj[val]; 1948 } 1949 }); 1950 theme.init = obj.init; 1951 1952 if (obj.css) { 1953 var css; 1954 proto.loop(proto.getElements('script'), function(el) { 1955 var reg = new RegExp('galleria.' + obj.name.toLowerCase() + '.js'); 1956 if(reg.test(el.src)) { 1957 css = el.src.replace(/[^\/]*$/, "") + obj.css; 1958 proto.loadCSS(css, function() { 1959 G.theme = theme; 1960 jQuery(document).trigger( G.THEMELOAD ); 1961 }); 1962 } 1963 }); 1964 if (!css) { 1965 G.raise('No theme CSS loaded'); 1966 } 1967 } 1968 return theme; 1969}; 1970 1971G.raise = function(msg) { 1972 if ( G.debug ) { 1973 throw new Error( msg ); 1974 } 1975}; 1976 1977G.loadTheme = function(src) { 1978 G.prototype.loadScript(src); 1979}; 1980 1981G.galleries = []; 1982G.get = function(index) { 1983 if (G.galleries[index]) { 1984 return G.galleries[index]; 1985 } else if (typeof index !== 'number') { 1986 return G.galleries; 1987 } else {
1988 G.raise('Gallery index not found'); 1989 } 1990} 1991 1992jQuery.easing.galleria = function (x, t, b, c, d) { 1993 if ((t/=d/2) < 1) { 1994 return c/2*t*t*t*t + b; 1995 } 1996 return -c/2 * ((t-=2)*t*t*t - 2) + b; 1997}; 1998 1999G.transitions = { 2000 add: function(name, fn) { 2001 if (name != arguments.callee.name ) { 2002 this[name] = fn; 2003 } 2004 }, 2005 fade: function(params, complete) { 2006 jQuery(params.next).show().css('opacity',0).animate({ 2007 opacity: 1 2008 }, params.speed, complete); 2009 if (params.prev) { 2010 jQuery(params.prev).css('opacity',1).animate({ 2011 opacity: 0 2012 }, params.speed); 2013 } 2014 }, 2015 flash: function(params, complete) { 2016 jQuery(params.next).css('opacity',0); 2017 if (params.prev) { 2018 jQuery(params.prev).animate({ 2019 opacity: 0 2020 }, (params.speed/2), function() { 2021 jQuery(params.next).animate({ 2022 opacity: 1 2023 }, params.speed, complete); 2024 }); 2025 } else { 2026 jQuery(params.next).animate({ 2027 opacity: 1 2028 }, params.speed, complete); 2029 } 2030 }, 2031 pulse: function(params, complete) { 2032 if (params.prev) { 2033 jQuery(params.prev).css('opacity',0); 2034 } 2035 jQuery(params.next).css('opacity',0).animate({ 2036 opacity:1 2037 }, params.speed, complete); 2038 }, 2039 slide: function(params, complete) { 2040 var image = jQuery(params.next).parent(); 2041 var images = this.$('images'); 2042 var width = this.stageWidth; 2043 image.css({ 2044 left: width * ( params.rewind ? -1 : 1 ) 2045 }); 2046 images.animate({ 2047 left: width * ( params.rewind ? 1 : -1 ) 2048 }, { 2049 duration: params.speed, 2050 queue: false, 2051 easing: 'galleria', 2052 complete: function() { 2053 images.css('left',0); 2054 image.css('left',0); 2055 complete(); 2056 } 2057 }); 2058 }, 2059 fadeslide: function(params, complete) { 2060 if (params.prev) { 2061 jQuery(params.prev).css({ 2062 opacity: 1, 2063 left: 0 2064 }).animate({ 2065 opacity: 0, 2066 left: 50 * ( params.rewind ? 1 : -1 ) 2067 },{ 2068 duration: params.speed, 2069 queue: false, 2070 easing: 'swing' 2071 }); 2072 } 2073 jQuery(params.next).css({ 2074 left: 50 * ( params.rewind ? -1 : 1 ), 2075 opacity: 0 2076 }).animate({ 2077 opacity: 1, 2078 left:0 2079 }, { 2080 duration: params.speed, 2081 complete: complete, 2082 queue: false, 2083 easing: 'swing' 2084 }); 2085 } 2086}; 2087 2088G.addTransition = function() { 2089 G.transitions.add.apply(this, arguments); 2090} 2091 2092jQuery.fn.galleria = function(options) { 2093 2094 options = options || {}; 2095 var selector = this.selector; 2096 2097 return this.each(function() { 2098 if ( !options.keep_source ) { 2099 jQuery(this).children().hide(); 2100 } 2101 2102 options = G.prototype.mix(options, {target: this} ); 2103 var height = G.prototype.height(this) || G.prototype.getStyle(this, 'height', true); 2104 if (!options.height && height) { 2105 options = G.prototype.mix( { height: height }, options ); 2106 } 2107 2108 G.debug = !!options.debug; 2109 2110 var gallery = new G(options); 2111 2112 Galleria.galleries.push(gallery); 2113 2114 if (G.theme) { 2115 gallery.init(); 2116 } else { 2117 jQuery(document).bind(G.THEMELOAD, function() { 2118 gallery.init(); 2119 }); 2120 } 2121 }) 2122}; 2123 2124 2125})();
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.