1/* ####### Animator.js code starts here ########## */ 2 /* 3 Animator.js 1.1.9 4 5 This library is released under the BSD license: 6 7 Copyright (c) 2006, Bernard Sumption. All rights reserved. 8 9 Redistribution and use in source and binary forms, with or without 10 modification, are permitted provided that the following conditions are met: 11 12 Redistributions of source code must retain the above copyright notice, this 13 list of conditions and the following disclaimer. Redistributions in binary 14 form must reproduce the above copyright notice, this list of conditions and 15 the following disclaimer in the documentation and/or other materials 16 provided with the distribution. Neither the name BernieCode nor 17 the names of its contributors may be used to endorse or promote products 18 derived from this software without specific prior written permission. 19 20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR 24 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 30 DAMAGE. 31 32 */ 33 34 35 // Applies a sequence of numbers between 0 and 1 to a number of subjects 36 // construct - see setOptions for parameters 37 function Animator(options) { 38 this.setOptions(options); 39 var _this = this; 40 this.timerDelegate = function(){_this.onTimerEvent()}; 41 this.subjects = []; 42 this.target = 0; 43 this.state = 0; 44 this.lastTime = null; 45 }; 46 Animator.prototype = { 47 // apply defaults 48 setOptions: function(options) { 49 this.options = Animator.applyDefaults({ 50 interval: 20, // time between animation frames 51 duration: 400, // length of animation 52 onComplete: function(){}, 53 onStep: function(){}, 54 transition: Animator.tx.easeInOut 55 }, options); 56 }, 57 // animate from the current state to provided value 58 seekTo: function(to) { 59 this.seekFromTo(this.state, to); 60 }, 61 // animate from the current state to provided value 62 seekFromTo: function(from, to) { 63 this.target = Math.max(0, Math.min(1, to)); 64 this.state = Math.max(0, Math.min(1, from)); 65 this.lastTime = new Date().getTime(); 66 if (!this.intervalId) { 67 this.intervalId = window.setInterval(this.timerDelegate, this.options.interval); 68 } 69 }, 70 // animate from the current state to provided value 71 jumpTo: function(to) { 72 this.target = this.state = Math.max(0, Math.min(1, to));
73 this.propagate(); 74 }, 75 // seek to the opposite of the current target 76 toggle: function() { 77 this.seekTo(1 - this.target); 78 }, 79 // add a function or an object with a method setState(state) that will be called with a number 80 // between 0 and 1 on each frame of the animation 81 addSubject: function(subject) { 82 this.subjects[this.subjects.length] = subject; 83 return this; 84 }, 85 // remove all subjects 86 clearSubjects: function() { 87 this.subjects = []; 88 }, 89 // forward the current state to the animation subjects 90 propagate: function() { 91 var value = this.options.transition(this.state); 92 for (var i=0; i<this.subjects.length; i++) { 93 if (this.subjects[i].setState) { 94 this.subjects[i].setState(value); 95 } else { 96 this.subjects[i](value); 97 } 98 } 99 }, 100 // called once per frame to update the current state 101 onTimerEvent: function() { 102 var now = new Date().getTime(); 103 var timePassed = now - this.lastTime; 104 this.lastTime = now; 105 var movement = (timePassed / this.options.duration) * (this.state < this.target ? 1 : -1); 106 if (Math.abs(movement) >= Math.abs(this.state - this.target)) { 107 this.state = this.target; 108 } else { 109 this.state += movement; 110 } 111 112 try { 113 this.propagate(); 114 } finally { 115 this.options.onStep.call(this); 116 if (this.target == this.state) { 117 window.clearInterval(this.intervalId); 118 this.intervalId = null; 119 this.options.onComplete.call(this); 120 } 121 } 122 }, 123 // shortcuts 124 play: function() {this.seekFromTo(0, 1)}, 125 reverse: function() {this.seekFromTo(1, 0)}, 126 // return a string describing this Animator, for debugging 127 inspect: function() { 128 var str = "#<Animator:\n"; 129 for (var i=0; i<this.subjects.length; i++) { 130 str += this.subjects[i].inspect(); 131 } 132 str += ">"; 133 return str; 134 } 135 } 136 // merge the properties of two objects 137 Animator.applyDefaults = function(defaults, prefs) { 138 prefs = prefs || {}; 139 var prop, result = {}; 140 for (prop in defaults) result[prop] = prefs[prop] !== undefined ? prefs[prop] : defaults[prop]; 141 return result; 142 } 143 // make an array from any object 144 Animator.makeArray = function(o) { 145 if (o == null) return []; 146 if (!o.length) return [o]; 147 var result = []; 148 for (var i=0; i<o.length; i++) result[i] = o[i]; 149 return result; 150 } 151 // convert a dash-delimited-property to a camelCaseProperty (c/o Prototype, thanks Sam!) 152 Animator.camelize = function(string) { 153 var oStringList = string.split('-'); 154 if (oStringList.length == 1) return oStringList[0]; 155 156 var camelizedString = string.indexOf('-') == 0 157 ? oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) 158 : oStringList[0]; 159 160 for (var i = 1, len = oStringList.length; i < len; i++) { 161 var s = oStringList[i]; 162 camelizedString += s.charAt(0).toUpperCase() + s.substring(1); 163 } 164 return camelizedString; 165 } 166 // syntactic sugar for creating CSSStyleSubjects 167 Animator.apply = function(el, style, options) { 168 if (style instanceof Array) { 169 return new Animator(options).addSubject(new CSSStyleSubject(el, style[0], style[1])); 170 } 171 return new Animator(options).addSubject(new CSSStyleSubject(el, style)); 172 } 173 // make a transition function that gradually accelerates. pass a=1 for smooth 174 // gravitational acceleration, higher values for an exaggerated effect 175 Animator.makeEaseIn = function(a) { 176 return function(state) { 177 return Math.pow(state, a*2); 178 } 179 } 180 // as makeEaseIn but for deceleration 181 Animator.makeEaseOut = function(a) { 182 return function(state) { 183 return 1 - Math.pow(1 - state, a*2); 184 } 185 } 186 // make a transition function that, like an object with momentum being attracted to a point, 187 // goes past the target then returns 188 Animator.makeElastic = function(bounces) { 189 return function(state) { 190 state = Animator.tx.easeInOut(state); 191 return ((1-Math.cos(state * Math.PI * bounces)) * (1 - state)) + state; 192 } 193 } 194 // make an Attack Decay Sustain Release envelope that starts and finishes on the same level 195 // 196 Animator.makeADSR = function(attackEnd, decayEnd, sustainEnd, sustainLevel) { 197 if (sustainLevel == null) sustainLevel = 0.5; 198 return function(state) { 199 if (state < attackEnd) { 200 return state / attackEnd; 201 } 202 if (state < decayEnd) { 203 return 1 - ((state - attackEnd) / (decayEnd - attackEnd) * (1 - sustainLevel)); 204 } 205 if (state < sustainEnd) { 206 return sustainLevel; 207 } 208 return sustainLevel * (1 - ((state - sustainEnd) / (1 - sustainEnd))); 209 } 210 } 211 // make a transition function that, like a ball falling to floor, reaches the target and/ 212 // bounces back again
213 Animator.makeBounce = function(bounces) { 214 var fn = Animator.makeElastic(bounces); 215 return function(state) { 216 state = fn(state); 217 return state <= 1 ? state : 2-state; 218 } 219 } 220 221 // pre-made transition functions to use with the 'transition' option 222 Animator.tx = { 223 easeInOut: function(pos){ 224 return ((-Math.cos(pos*Math.PI)/2) + 0.5); 225 }, 226 linear: function(x) { 227 return x; 228 }, 229 easeIn: Animator.makeEaseIn(1.5), 230 easeOut: Animator.makeEaseOut(1.5), 231 strongEaseIn: Animator.makeEaseIn(2.5), 232 strongEaseOut: Animator.makeEaseOut(2.5), 233 elastic: Animator.makeElastic(1), 234 veryElastic: Animator.makeElastic(3), 235 bouncy: Animator.makeBounce(1), 236 veryBouncy: Animator.makeBounce(3) 237 } 238 239 // animates a pixel-based style property between two integer values 240 function NumericalStyleSubject(els, property, from, to, units) { 241 this.els = Animator.makeArray(els); 242 if (property == 'opacity' && window.ActiveXObject) { 243 this.property = 'filter'; 244 } else { 245 this.property = Animator.camelize(property); 246 } 247 try{ 248 var isIE9 = (navigator.userAgent.match(/\bMSIE\b/) && (document.documentMode ==9)); 249 250 if(isIE9){ 251 this.property = Animator.camelize(property); 252 } 253 }catch(e){} 254 this.from = parseFloat(from); 255 this.to = parseFloat(to); 256 this.units = units != null ? units : 'px'; 257 } 258 NumericalStyleSubject.prototype = { 259 setState: function(state) { 260 var style = this.getStyle(state); 261 var visibility = (this.property == 'opacity' && state == 0) ? 'hidden' : ''; 262 var j=0; 263 for (var i=0; i<this.els.length; i++) { 264 try { 265 this.els[i].style[this.property] = style; 266 } catch (e) { 267 // ignore fontWeight - intermediate numerical values cause exeptions in firefox 268 if (this.property != 'fontWeight') throw e; 269 } 270 if (j++ > 20) return; 271 } 272 }, 273 getStyle: function(state) { 274 state = this.from + ((this.to - this.from) * state); 275 if (this.property == 'filter') return "alpha(opacity=" + Math.round(state*100) + ")"; 276 if (this.property == 'opacity') return state; 277 return Math.round(state) + this.units; 278 }, 279 inspect: function() { 280 return "\t" + this.property + "(" + this.from + this.units + " to " + this.to + this.units + ")\n"; 281 } 282 } 283 284 // animates a colour based style property between two hex values 285 function ColorStyleSubject(els, property, from, to) { 286 this.els = Animator.makeArray(els); 287 this.property = Animator.camelize(property); 288 this.to = this.expandColor(to); 289 this.from = this.expandColor(from); 290 this.origFrom = from; 291 this.origTo = to; 292 } 293 294 ColorStyleSubject.prototype = { 295 // parse "#FFFF00" to [256, 256, 0] 296 expandColor: function(color) { 297 var hexColor, red, green, blue; 298 hexColor = ColorStyleSubject.parseColor(color); 299 if (hexColor) { 300 red = parseInt(hexColor.slice(1, 3), 16); 301 green = parseInt(hexColor.slice(3, 5), 16); 302 blue = parseInt(hexColor.slice(5, 7), 16); 303 return [red,green,blue] 304 } 305 if (window.DEBUG) { 306 //alert("Invalid colour: '" + color + "'"); 307 alert(ICaltgopub.pa_txt1 + color + "' "); 308 } 309 }, 310 getValueForState: function(color, state) { 311 return Math.round(this.from[color] + ((this.to[color] - this.from[color]) * state)); 312 }, 313 setState: function(state) { 314 var color = '#' 315 + ColorStyleSubject.toColorPart(this.getValueForState(0, state)) 316 + ColorStyleSubject.toColorPart(this.getValueForState(1, state)) 317 + ColorStyleSubject.toColorPart(this.getValueForState(2, state)); 318 for (var i=0; i<this.els.length; i++) { 319 this.els[i].style[this.property] = color; 320 } 321 }, 322 inspect: function() { 323 return "\t" + this.property + "(" + this.origFrom + " to " + this.origTo + ")\n"; 324 } 325 } 326 327 // return a properly formatted 6-digit hex colour spec, or false 328 ColorStyleSubject.parseColor = function(string) { 329 var color = '#', match; 330 if(match = ColorStyleSubject.parseColor.rgbRe.exec(string)) { 331 var part; 332 for (var i=1; i<=3; i++) { 333 part = Math.max(0, Math.min(255, parseInt(match[i]))); 334 color += ColorStyleSubject.toColorPart(part); 335 } 336 return color; 337 } 338 if (match = ColorStyleSubject.parseColor.hexRe.exec(string)) { 339 if(match[1].length == 3) { 340 for (var i=0; i<3; i++) { 341 color += match[1].charAt(i) + match[1].charAt(i); 342 } 343 return color; 344 } 345 return '#' + match[1]; 346 } 347 return false;
348 } 349 // convert a number to a 2 digit hex string 350 ColorStyleSubject.toColorPart = function(number) { 351 if (number > 255) number = 255; 352 var digits = number.toString(16); 353 if (number < 16) return '0' + digits; 354 return digits; 355 } 356 ColorStyleSubject.parseColor.rgbRe = /^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i; 357 ColorStyleSubject.parseColor.hexRe = /^\#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/; 358 359 // Animates discrete styles, i.e. ones that do not scale but have discrete values 360 // that can't be interpolated 361 function DiscreteStyleSubject(els, property, from, to, threshold) { 362 this.els = Animator.makeArray(els); 363 this.property = Animator.camelize(property); 364 this.from = from; 365 this.to = to; 366 this.threshold = threshold || 0.5; 367 } 368 369 DiscreteStyleSubject.prototype = { 370 setState: function(state) { 371 var j=0; 372 for (var i=0; i<this.els.length; i++) { 373 this.els[i].style[this.property] = state <= this.threshold ? this.from : this.to; 374 } 375 }, 376 inspect: function() { 377 return "\t" + this.property + "(" + this.from + " to " + this.to + " @ " + this.threshold + ")\n"; 378 } 379 } 380 381 // animates between two styles defined using CSS. 382 // if style1 and style2 are present, animate between them, if only style1 383 // is present, animate between the element's current style and style1 384 function CSSStyleSubject(els, style1, style2) { 385 els = Animator.makeArray(els); 386 this.subjects = []; 387 if (els.length == 0) return; 388 var prop, toStyle, fromStyle; 389 if (style2) { 390 fromStyle = this.parseStyle(style1, els[0]); 391 toStyle = this.parseStyle(style2, els[0]); 392 } else { 393 toStyle = this.parseStyle(style1, els[0]); 394 fromStyle = {}; 395 for (prop in toStyle) { 396 fromStyle[prop] = CSSStyleSubject.getStyle(els[0], prop); 397 } 398 } 399 // remove unchanging properties 400 var prop; 401 for (prop in fromStyle) { 402 if (fromStyle[prop] == toStyle[prop]) { 403 delete fromStyle[prop]; 404 delete toStyle[prop]; 405 } 406 } 407 // discover the type (numerical or colour) of each style 408 var prop, units, match, type, from, to; 409 for (prop in fromStyle) { 410 var fromProp = String(fromStyle[prop]); 411 var toProp = String(toStyle[prop]); 412 if (toStyle[prop] == null) { 413 if (window.DEBUG) alert(ICaltgopub.pa_txt2 + prop + '"'); 414 continue; 415 } 416 417 if (from = ColorStyleSubject.parseColor(fromProp)) { 418 to = ColorStyleSubject.parseColor(toProp); 419 type = ColorStyleSubject; 420 } else if (fromProp.match(CSSStyleSubject.numericalRe) 421 && toProp.match(CSSStyleSubject.numericalRe)) { 422 from = parseFloat(fromProp); 423 to = parseFloat(toProp); 424 type = NumericalStyleSubject; 425 match = CSSStyleSubject.numericalRe.exec(fromProp); 426 var reResult = CSSStyleSubject.numericalRe.exec(toProp); 427 if (match[1] != null) { 428 units = match[1]; 429 } else if (reResult[1] != null) { 430 units = reResult[1]; 431 } else { 432 units = reResult; 433 } 434 } else if (fromProp.match(CSSStyleSubject.discreteRe) 435 && toProp.match(CSSStyleSubject.discreteRe)) { 436 from = fromProp; 437 to = toProp; 438 type = DiscreteStyleSubject; 439 units = 0; // hack - how to get an animator option down to here 440 } else { 441 if (window.DEBUG) { 442 alert(ICaltgopub.pa_txt3 + prop + ": '" + fromStyle[prop] + "'"); 443 } 444 continue; 445 } 446 this.subjects[this.subjects.length] = new type(els, prop, from, to, units); 447 } 448 } 449 450 CSSStyleSubject.prototype = { 451 // parses "width: 400px; color: #FFBB2E" to {width: "400px", color: "#FFBB2E"} 452 parseStyle: function(style, el) { 453 var rtn = {}; 454 // if style is a rule set 455 if (style.indexOf(":") != -1) { 456 var styles = style.split(";"); 457 for (var i=0; i<styles.length; i++) { 458 var parts = CSSStyleSubject.ruleRe.exec(styles[i]); 459 if (parts) { 460 rtn[parts[1]] = parts[2]; 461 } 462 } 463 } 464 // else assume style is a class name 465 else { 466 var prop, value, oldClass; 467 oldClass = el.className; 468 el.className = style; 469 for (var i=0; i<CSSStyleSubject.cssProperties.length; i++) { 470 prop = CSSStyleSubject.cssProperties[i]; 471 value = CSSStyleSubject.getStyle(el, prop); 472 if (value != null) { 473 rtn[prop] = value; 474 } 475 } 476 el.className = oldClass; 477 } 478 return rtn; 479 480 }, 481 setState: function(state) { 482 for (var i=0; i<this.subjects.length; i++) { 483 this.subjects[i].setState(state); 484 } 485 }, 486 inspect: function() { 487 var str = ""; 488 for (var i=0; i<this.subjects.length; i++) { 489 str += this.subjects[i].inspect(); 490 } 491 return str; 492 } 493 } 494 // get the current value of a css property, 495 /* 496 CSSStyleSubject.getStyle = function(el, property){ 497 var style; 498 if(document.defaultView && document.defaultView.getComputedStyle){ 499 style = document.defaultView.getComputedStyle(el, "").getPropertyValue(property); 500 if (style) { 501 return style; 502 } else { 503 return('none'); 504 } 505 } 506 507 508 property = Animator.camelize(property); 509 if(el.currentStyle){ 510 style = el.currentStyle[property]; 511 } 512 return style || el.style[property] 513 } 514 */ 515 CSSStyleSubject.getStyle = function(el, property){ 516 if (document.defaultView) { 517 var computedStyle = document.defaultView.getComputedStyle(el, null); 518 // Safari returns null from computed style if the display of the element is none 519 // if this is the case, then we just return 'none' if the user is asking for the 520 // 'display' property, or we temporarily set the display to 'block' and re-fetch 521 // the computed style 522 if (computedStyle) { 523 style = document.defaultView.getComputedStyle(el, "").getPropertyValue(property); 524 } else if (property == 'display') { 525 style = 'none'; 526 } else { 527 property = Animator.camelize(property); 528 if(el.currentStyle){ 529 style = el.currentStyle[property]; 530 } 531 } 532 return style || el.style[property]; 533 } 534 } 535 536 CSSStyleSubject.ruleRe = /^\s*([a-zA-Z\-]+)\s*:\s*(\S(.+\S)?)\s*$/; 537 CSSStyleSubject.numericalRe = /^-?\d+(?:\.\d+)?(%|[a-zA-Z]{2})?$/; 538 CSSStyleSubject.discreteRe = /^\w+$/; 539 540 // required because the style object of elements isn't enumerable in Safari 541 /* 542 CSSStyleSubject.cssProperties = ['background-color','border','border-color','border-spacing', 543 'border-style','border-top','border-right','border-bottom','border-left','border-top-color', 544 'border-right-color','border-bottom-color','border-left-color','border-top-width','border-right-width', 545 'border-bottom-width','border-left-width','border-width','bottom','color','font-size','font-size-adjust', 546 'font-stretch','font-style','height','left','letter-spacing','line-height','margin','margin-top', 547 'margin-right','margin-bottom','margin-left','marker-offset','max-height','max-width','min-height', 548 'min-width','orphans','outline','outline-color','outline-style','outline-width','overflow','padding', 549 'padding-top','padding-right','padding-bottom','padding-left','quotes','right','size','text-indent',
550 'top','width','word-spacing','z-index','opacity','outline-offset'];*/ 551 552 553 CSSStyleSubject.cssProperties = ['azimuth','background','background-attachment','background-color','background-image','background-position','background-repeat','border-collapse','border-color','border-spacing','border-style','border-top','border-top-color','border-right-color','border-bottom-color','border-left-color','border-top-style','border-right-style','border-bottom-style','border-left-style','border-top-width','border-right-width','border-bottom-width','border-left-width','border-width','bottom','clear','clip','color','content','cursor','direction','display','elevation','empty-cells','css-float','font','font-family','font-size','font-size-adjust','font-stretch','font-style','font-variant','font-weight','height','left','letter-spacing','line-height','list-style','list-style-image','list-style-position','list-style-type','margin','margin-top','margin-right','margin-bottom','margin-left','max-height','max-width','min-height','min-width','orphans','outline','outline-color','outline-style','outline-width','overflow','padding','padding-top','padding-right','padding-bottom','padding-left','pause','position','right','size','table-layout','text-align','text-decoration','text-indent','text-shadow','text-transform','top','vertical-align','visibility','white-space','width','word-spacing','z-index','opacity','outline-offset','overflow-x','overflow-y']; 554 555 556 // chains several Animator objects together 557 function AnimatorChain(animators, options) { 558 this.animators = animators; 559 this.setOptions(options); 560 for (var i=0; i<this.animators.length; i++) { 561 this.listenTo(this.animators[i]); 562 } 563 this.forwards = false; 564 this.current = 0; 565 } 566 567 AnimatorChain.prototype = { 568 // apply defaults 569 setOptions: function(options) { 570 this.options = Animator.applyDefaults({ 571 // by default, each call to AnimatorChain.play() calls jumpTo(0) of each animator 572 // before playing, which can cause flickering if you have multiple animators all 573 // targeting the same element. Set this to false to avoid this. 574 resetOnPlay: true 575 }, options); 576 }, 577 // play each animator in turn 578 play: function() { 579 this.forwards = true; 580 this.current = -1; 581 if (this.options.resetOnPlay) { 582 for (var i=0; i<this.animators.length; i++) { 583 this.animators[i].jumpTo(0); 584 } 585 } 586 this.advance(); 587 }, 588 // play all animators backwards 589 reverse: function() { 590 this.forwards = false; 591 this.current = this.animators.length; 592 if (this.options.resetOnPlay) { 593 for (var i=0; i<this.animators.length; i++) { 594 this.animators[i].jumpTo(1); 595 } 596 } 597 this.advance(); 598 }, 599 // if we have just play()'d, then call reverse(), and vice versa 600 toggle: function() { 601 if (this.forwards) { 602 this.seekTo(0); 603 } else { 604 this.seekTo(1); 605 } 606 }, 607 // internal: install an event listener on an animator's onComplete option 608 // to trigger the next animator 609 listenTo: function(animator) { 610 var oldOnComplete = animator.options.onComplete; 611 var _this = this; 612 animator.options.onComplete = function() { 613 if (oldOnComplete) oldOnComplete.call(animator); 614 _this.advance(); 615 } 616 }, 617 // play the next animator 618 advance: function() { 619 if (this.forwards) { 620 if (this.animators[this.current + 1] == null) return; 621 this.current++; 622 this.animators[this.current].play(); 623 } else { 624 if (this.animators[this.current - 1] == null) return; 625 this.current--; 626 this.animators[this.current].reverse(); 627 } 628 }, 629 // this function is provided for drop-in compatibility with Animator objects, 630 // but only accepts 0 and 1 as target values 631 seekTo: function(target) { 632 if (target <= 0) { 633 this.forwards = false; 634 this.animators[this.current].seekTo(0); 635 } else { 636 this.forwards = true; 637 this.animators[this.current].seekTo(1); 638 } 639 } 640 } 641 642 // an Accordion is a class that creates and controls a number of Animators. An array of elements is passed in, 643 // and for each element an Animator and a activator button is created. When an Animator's activator button is 644 // clicked, the Animator and all before it seek to 0, and all Animators after it seek to 1. This can be used to 645 // create the classic Accordion effect, hence the name. 646 // see setOptions for arguments 647 function Accordion(options) { 648 this.setOptions(options); 649 var selected = this.options.initialSection, current; 650 if (this.options.rememberance) { 651 current = document.location.hash.substring(1); 652 } 653 this.rememberanceTexts = []; 654 this.ans = []; 655 var _this = this; 656 for (var i=0; i<this.options.sections.length; i++) { 657 var el = this.options.sections[i]; 658 var an = new Animator(this.options.animatorOptions); 659 var from = this.options.from + (this.options.shift * i); 660 var to = this.options.to + (this.options.shift * i);
661 an.addSubject(new NumericalStyleSubject(el, this.options.property, from, to, this.options.units)); 662 an.jumpTo(0); 663 var activator = this.options.getActivator(el); 664 activator.index = i; 665 activator.onclick = function(){_this.show(this.index)}; 666 this.ans[this.ans.length] = an; 667 this.rememberanceTexts[i] = activator.innerHTML.replace(/\s/g, ""); 668 if (this.rememberanceTexts[i] === current) { 669 selected = i; 670 } 671 } 672 this.show(selected); 673 } 674 675 Accordion.prototype = { 676 // apply defaults 677 setOptions: function(options) { 678 this.options = Object.extend({ 679 // REQUIRED: an array of elements to use as the accordion sections 680 sections: null, 681 // a function that locates an activator button element given a section element. 682 // by default it takes a button id from the section's "activator" attibute 683 getActivator: function(el) {return document.getElementById(el.getAttribute("activator"))}, 684 // shifts each animator's range, for example with options {from:0,to:100,shift:20} 685 // the animators' ranges will be 0-100, 20-120, 40-140 etc. 686 shift: 0, 687 // the first page to show 688 initialSection: 0, 689 // if set to true, document.location.hash will be used to preserve the open section across page reloads 690 rememberance: true, 691 // constructor arguments to the Animator objects 692 animatorOptions: {} 693 }, options || {}); 694 }, 695 show: function(section) { 696 for (var i=0; i<this.ans.length; i++) { 697 this.ans[i].seekTo(i > section ? 1 : 0); 698 } 699 if (this.options.rememberance) { 700 document.location.hash = this.rememberanceTexts[section]; 701 } 702 } 703 } 704 705 /* ####### Animator.js code ends here ########## */ 706 707 /* ####### Photoalbum.js code starts here ########## */ 708 709 710 /***** GLOBALS *****/ 711 712 var slowest = 5000; 713 var slow = 4000; 714 var med = 3000; 715 var fast = 2000; 716 var fastest = 1000; 717 var slideTime; 718 var randTime; 719 720 /*****These are our events****/ 721 722 //parent.content.onscroll = adjustoverlay; 723 window.onscroll = adjustOverlay; 724 //window.onresize = adjustOverlay; 725 726 /***** Event Functions*****/ 727 728 function checkMouseover(evt) { 729 730 //alert(evt); 731 732 if (!evt) var evt = window.event; 733 734 if(document.all) 735 evtObj = evt.srcElement; 736 else 737 evtObj = evt.target; 738 739 if (evtObj.id.substring(0,5) == 'thumb' && evtObj.parentNode.offsetWidth < 75) 740 { 741 var positionX = getCoords(evtObj).x; 742 var positionY = getCoords(evtObj).y; 743 enlargedImage = $('enlargedImage'+this.photoNum); 744 745 enlargedImage.style.width = Math.floor(evtObj.width * 2.25) + 'px'; 746 enlargedImage.style.height = Math.floor(evtObj.height * 2.25) + 'px'; 747 enlargedImage.style.position = "absolute"; 748 enlargedImage.style.top = positionY - Math.floor(evtObj.height * 0.75) + 'px'; 749 enlargedImage.style.left = positionX - Math.floor(evtObj.width * 0.75)+ 'px'; 750 enlargedImage.src = this.imageAttributes[this.currentImage].olpath; // so we size down rather than up 751 //alert(enlargedImage.style.width); 752 enlargedImage.style.display = 'block'; 753 } 754 } 755 756 function checkDoubleClicks(evt) { 757 758 if (!evt) var evt = window.event; 759 760 if(document.all) 761 evtObj = evt.srcElement; 762 else 763 evtObj = evt.target; 764 765 if (((evtObj.id.substring(0, 5) == "thumb") || (evtObj.id.substring(0, 8) == 'enlarged')) && this.mainViewer == 1) 766 { 767 //setting height & width of background gray area. 768 PA_ID = this.photoNum; 769 770 window.document.body.appendChild($('detailScreen')); 771 window.document.body.appendChild($('detailsContainer' + PA_ID)); 772 $('detailScreen').style.height = getWinHeight(); 773 $('detailScreen').style.width = getWinWidth();
774 this.showDetails(evtObj); 775 if ($('pausebutton'+this.photoNum).style.display == 'block') 776 { 777 //this.stop(); 778 this.midPlay = 1; 779 } 780 } 781 else return; 782 } 783 784 function checkClickables(evt) { 785 //alert(evt.target.id); 786 //alert(this.currentImage); 787 788 if (!evt) var evt = window.event; 789 790 if(document.all) 791 evtObj = evt.srcElement; 792 else 793 evtObj = evt.target; 794 795 if (((evtObj.id.substring(0, 5) == 'thumb') || (evtObj.id.substring(0, 8) == 'enlarged')) && (evtObj.id.substring(5, 8) != "Con")) 796 { 797 thumbID = evtObj.id.split("_"); 798 799 this.lastImage=this.currentImage; 800 this.currentImage = parseInt(thumbID[2]); //image container 801 this.currentImage = parseInt(thumbID[2]); //image 802 803 this.findCurrent(); 804 this.showCurrent(evtObj); 805 } 806 /*if ((evtObj.id.substring(0, 8) == "enlarged")) { 807 this.lastImage = this.currentImage; 808 this.currentImage = parseInt($('enlargedImage'+this.photoNum).name); 809 this.findCurrent(); 810 this.showCurrent(); 811 }*/ 812 if((evtObj.id == ("mainImage"+this.photoNum) || evtObj.id == ("imageContainer"+this.photoNum)) || (evtObj.id.substring(0, 5) == "thumb" && this.mainViewer == 0) || ((evtObj.id.substring(0, 8) == "enlarged") && (this.mainViewer == 0))) 813 { 814 //setting height & width of background gray area. 815 PA_ID = this.photoNum; 816 //detailsScreen = $('detailscreen'); 817 818 window.document.body.appendChild($('detailScreen')); 819 window.document.body.appendChild($('detailsContainer' + PA_ID)); 820 $('detailScreen').style.height = getWinHeight(); 821 $('detailScreen').style.width = getWinWidth();
822 this.showDetails(evtObj); 823 //this.stop(); 824 this.midPlay = 1; 825 } 826 } 827 //document.onmouseout = checkMouseout 828 829 PhotoAlbum.prototype.calcRatio = calcRatio; 830 PhotoAlbum.prototype.buildThumbs = buildThumbs; 831 PhotoAlbum.prototype.updateCounter = updateCounter; 832 PhotoAlbum.prototype.buildMainViewer = buildMainViewer; 833 PhotoAlbum.prototype.showDetails = showDetails; 834 PhotoAlbum.prototype.showNextDetail = showNextDetail; 835 PhotoAlbum.prototype.showPrevDetail = showPrevDetail; 836 PhotoAlbum.prototype.closeDetails = closeDetails; 837 PhotoAlbum.prototype.next = next; 838 PhotoAlbum.prototype.previous = previous; 839 PhotoAlbum.prototype.findCurrent = findCurrent; 840 PhotoAlbum.prototype.showCurrent = showCurrent; 841 PhotoAlbum.prototype.initPlay = initPlay; 842 PhotoAlbum.prototype.linearPlay = linearPlay; 843 PhotoAlbum.prototype.randPlay = randPlay; 844 PhotoAlbum.prototype.stop = stop; 845 PhotoAlbum.prototype.f_Slide = f_Slide; 846 PhotoAlbum.prototype.l_Slide = l_Slide; 847 PhotoAlbum.prototype.changeSpeed = changeSpeed; 848 PhotoAlbum.prototype.adjustOverlay = adjustOverlay; 849 PhotoAlbum.prototype.hideDetails = hideDetails; 850 PhotoAlbum.prototype.checkClickables = checkClickables; 851 PhotoAlbum.prototype.checkDoubleClicks = checkDoubleClicks; 852 PhotoAlbum.prototype.checkMouseover = checkMouseover; 853 854 /*****The PhotoAlbum object ****/ 855 856 function PhotoAlbum(photoNum, mainWidth,photoAlbumType,imageBackColor,titleColor, thumbWidth,numOfThumbs,aspectRatio,titles, imageAttributes,textFont,specifyBoxWidth, newIC) { 857 858 this.photoNum=photoNum; //The photo number 859 860 this.mainWidth = mainWidth; //colum width of the web page - should determine the size of the entire photo album 861 this.photoAlbumType = photoAlbumType; //PhotoAlbum Type 1-5 862 this.imageBackColor = imageBackColor; //color of overlay matte and thumbnail BG: defualt is WHITE 863 this.titleColor = titleColor; //title/desc text color 864 this.textFont = textFont; 865 this.specifyBoxWidth = specifyBoxWidth; 866 867 if(this.specifyBoxWidth == "true"){ 868 this.numOfThumbs = 0; 869 if (thumbWidth.length == 0) { 870 this.thumbWidth = 0; 871 } else { 872 this.thumbWidth = parseInt(thumbWidth); //advance option 873 } 874 } 875 else{ 876 this.thumbWidth = 0; 877 if (numOfThumbs.length == 0) { 878 this.numOfThumbs = 0; 879 } else { 880 this.numOfThumbs = parseInt(numOfThumbs); //calculated based on mainWidth, 0 means nothing specified and use 'thumbWidth' advance option 881 } 882 } 883 884 this.aspectRatio = aspectRatio; //could be "square", "portrait", "landscape": default should be SQUARE per the specs, landscape might be better :-P 885 886 if (titles.length == 0 || titles == "false") { 887 this.titles = 0; 888 } else { 889 this.titles = 1; 890 } 891 892 this.slideSpeed = med; //default is medium, 2 seconds 893 this.imageAttributes = imageAttributes; //should be an array 894 895 this.imageTotal = imageAttributes.length; 896 897 for(i=0; i<this.imageTotal; i++) { 898 imgObject = new Image(); 899 imgObject.src=imageAttributes[i].sspath; 900 imgObject.src=imageAttributes[i].tnpath; 901 imgObject.src=imageAttributes[i].olpath; 902 //alert(imgObject.height); 903 } 904 905 this.newIC = newIC; 906 907 this.mainHeight; //calculated in calcRatio() 908 this.thumbHeight; //calculated in calcRatio() 909 910 911 /*** Init Variables ****/ 912 913 this.imageTotal = imageAttributes.length; 914 915 this.controls = 0; //show controls? 916 this.thumbnails = 0; //show thmbnails? 917 this.mainViewer = 0; //show main viewer? 918 this.randomSlideShow = 0; //random? 919 this.defaultPlay = 0; //make automatic if thumbs and controls are off 920 this.currentImage = 0; 921 //this.currentDetail = 0; 922 this.lastImage = 0; 923 this.stopSlide = 0; 924 this.firstPlay = 1; 925 this.midPlay = 0; 926 this.Xcoord = 0; 927 this.Ycoord = 0; 928 this.playInterval = 0; 929 this.randInterval = 0; 930 this.mainDiv; 931 this.mainIMG; 932 this.thumbDiv; 933 this.thumbIMG; 934 this.thumbTitle; 935 this.largestDiv = []; 936 this.enlargedImage; 937 this.mainContainer = $('mainContainer' + this.photoNum); 938 939 this.anContainer = new Animator({transition: Animator.makeEaseOut(4), duration: 1000}); 940 this.anImage = new Animator({transition: Animator.makeEaseOut(3), duration: 600}); 941 this.anTitle = new Animator({transition: Animator.makeEaseOut(3), duration: 600}); 942 this.anScreen = new Animator({duration: 500}); 943 944 //anDesc = new Animator({transition: Animator.makeEaseOut(3), duration: 600}); 945 //anClose = new Animator({transition: Animator.makeEaseOut(3), duration: 600}); 946 947 // document.ondblclick = this.checkDoubleClicks; 948 //document.onmouseover = this.checkMouseover; 949 950 this.calcRatio(); 951 952 //if(this.thumbnails ==1 ){this.buildThumbs();} 953 this.buildThumbs(); 954 this.findCurrent(); 955 //if(this.mainViewer == 1){this.buildMainViewer();} 956 this.buildMainViewer(); 957 this.showCurrent(); 958 959 var PA_ID = this.photoNum; 960 var oldhandler = window.onload; 961 if(this.newIC=="true") 962 window.onload = function() {oldhandler(); buildOverlay(PA_ID);} 963 964 //this.buildOverlay(this.photoNum); 965 966 this.anContainer.addSubject(new CSSStyleSubject($('details'+this.photoNum), "position: relative; top: 30px; left: 500px; opacity: 0.0; filter: alpha(opacity = 0); width: 400px; height: 400px; border: 1px solid #cccccc; margin: auto; overflow: hidden;", "opacity: 1; filter: alpha(opacity = 100); width: 500px; height: 690px; border: 2px solid #56A7EF; margin: auto;")); 967 968 //anContainer.addSubject(new CSSStyleSubject($('details'), "detailsPre", "detailsPost")); 969 970 this.anImage.addSubject(new CSSStyleSubject($('popImage'+this.photoNum), "opacity: 0;filter: alpha(opacity = 0);", "opacity: 1; filter: alpha(opacity = 100);")); 971 this.anTitle.addSubject(new CSSStyleSubject($('popTitle'+this.photoNum), "opacity: 0;filter: alpha(opacity = 0);", "opacity: 1; filter: alpha(opacity = 100);")); 972 this.anScreen.addSubject(new CSSStyleSubject($('detailScreen'), "opacity: 0;filter: alpha(opacity = 0);", "opacity: 0.5; filter: alpha(opacity = 50);"));
973 //anDesc.addSubject(new CSSStyleSubject($('popDesc'+photoNum), "opacity: 0;filter: alpha(opacity = 0);", "opacity: 1; filter: alpha(opacity = 100);")); 974 975 976 switch(this.photoAlbumType) 977 { 978 case (this.photoAlbumType=1): 979 this.mainViewer=1; 980 this.controls=1; 981 this.thumbnails=1; 982 this.defaultPlay=0; 983 break; 984 case (this.photoAlbumType=2): 985 this.mainViewer=1; 986 this.controls=0; 987 this.thumbnails=1; 988 this.defaultPlay=1; 989 break; 990 case (this.photoAlbumType=3): 991 this.mainViewer=1; 992 this.controls=1; 993 this.thumbnails=0; 994 this.defaultPlay=0; 995 break; 996 case (this.photoAlbumType=4): 997 this.mainViewer=1; 998 this.controls=0; 999 this.thumbnails=0; 1000 this.defaultPlay=1; 1001 break; 1002 default: 1003 this.mainViewer=0; 1004 this.controls=0; 1005 this.thumbnails=1; 1006 this.defaultPlay=0; 1007 $('photoFoot' + this.photoNum).style.display = 'none'; 1008 } 1009 1010 $("imageContainer"+this.photoNum).style.backgroundColor = this.imageBackColor; 1011 $("imageContainer"+this.photoNum).style.borderColor = this.imageBackColor; 1012 1013 if (this.defaultPlay ==1) { 1014 swap('detailplaybtn'+this.photoNum,'detailpausebtn'+this.photoNum); 1015 swap('playbutton'+this.photoNum,'pausebutton'+this.photoNum); 1016 this.initPlay(); 1017 } 1018 if (this.controls == 0) { 1019 $("controls"+this.photoNum).style.display = "none"; 1020 } 1021 1022 if (this.thumbnails == 0) { 1023 $('thumbContainer'+this.photoNum).style.display = 'none'; 1024 //initPlay(); 1025 } 1026 1027 if(this.mainViewer == 0) { 1028 $("controls"+this.photoNum).style.display = "none"; 1029 $("imageContainer"+this.photoNum).style.display = "none"; 1030 this.defaultPlay = 0; 1031 } 1032 1033 //alert($('thumbContainer'+this.photoNum)); 1034 1035 $("photoFoot"+this.photoNum).style.width = mainWidth + "px"; 1036 $("controls"+this.photoNum).style.width = (mainWidth-6) + "px"; 1037 $("details"+this.photoNum).style.backgroundColor = imageBackColor; 1038 $("details"+this.photoNum).style.borderColor = "#CCCCCC"; 1039 $("popTitle"+this.photoNum).style.color = titleColor; 1040 $("popTitle"+this.photoNum).style.backgroundColor = imageBackColor; //fix IE Bold glitch 1041 if(this.textFont != ""){ 1042 $("popTitle"+this.photoNum).style.fontFamily = this.textFont; 1043 } 1044 $("popDesc"+this.photoNum).style.color = titleColor; 1045 $("popDesc"+this.photoNum).style.backgroundColor = imageBackColor; //fix IE Bold glitch 1046 if(this.textFont != ""){ 1047 $("popDesc"+this.photoNum).style.fontFamily = this.textFont; 1048 } 1049 this.updateCounter(this.photoNum); 1050 1051 //var pa_self = this; 1052 //normAddEvent(this.mainDiv, "click", function(e){ 1053 // pa_self.checkClick(pa_self.mainDiv); 1054 // }); 1055 1056 1057 if (this.mainContainer.addEventListener){ 1058 this.mainContainer.addEventListener('click', createObjectCallback(this, this.checkClickables), false); 1059 this.mainContainer.addEventListener('dblclick', createObjectCallback(this, this.checkDoubleClicks), false); 1060 //this.mainContainer.addEventListener('mouseover', createObjectCallback(this, this.checkMouseover), false); 1061 } else if (this.mainContainer.attachEvent){ 1062 this.mainContainer.attachEvent('onclick', createObjectCallback(this, this.checkClickables)); 1063 this.mainContainer.attachEvent('ondblclick', createObjectCallback(this, this.checkDoubleClicks)); 1064 //this.mainContainer.attachEvent('onmouseover', createObjectCallback(this, this.checkMouseover)); 1065 } 1066 1067 1068 if(this.largestDiv.length > 0) { 1069 for(var i=0; i<this.largestDiv.length; i++) { 1070 //alert(getStyle(this.largestDiv[i], 'height')); 1071 } 1072 } 1073 1074 //alert('returned zero-length array'); 1075 1076 } 1077 1078 function buildOverlay(PA_ID) { 1079 1080 window.document.body.appendChild($('detailScreen')); 1081 window.document.body.appendChild($('detailsContainer' + PA_ID)); 1082 1083 } 1084 1085 function calcRatio() { 1086 1087 if (this.aspectRatio == "landscape") {
1088 this.thumbHeight = Math.floor(this.thumbWidth*0.75); 1089 this.mainHeight = Math.floor(this.mainWidth*0.75); 1090 } 1091 else if (this.aspectRatio == "portrait") { 1092 this.thumbHeight =Math.floor(this.thumbWidth*1.33); 1093 this.mainHeight = Math.floor(this.mainWidth*1.33); 1094 } 1095 else //if "square" 1096 { 1097 this.thumbHeight = this.thumbWidth; 1098 this.mainHeight = this.mainWidth; 1099 } 1100 1101 //alert("mainHeight: "+this.mainHeight); 1102 1103 } 1104 1105 function updateCounter() { 1106 this.currentNum = this.currentImage + 1; 1107 if ($("SlideNum"+this.photoNum)) { 1108 $("SlideNum"+this.photoNum).innerHTML = this.currentNum + "/" + this.imageTotal; 1109 } 1110 } 1111 1112 function buildThumbs() { 1113 1114 //var largestTitle = 0; //height added by thumbnail titles 1115 1116 var j=0; 1117 var largestTitle = [j]; //height added by thumbnail titles 1118 1119 if (this.numOfThumbs > 0 ) { 1120 if (document.all) 1121 this.thumbWidth = Math.floor(this.mainWidth/this.numOfThumbs) - 13; //18 is padding+ border + left/right extremes 1122 else 1123 this.thumbWidth = Math.floor(this.mainWidth/this.numOfThumbs) - 12; 1124 } 1125 1126 this.calcRatio(); 1127 1128 $('thumbContainer'+this.photoNum).style.width = this.mainWidth + "px"; 1129 1130 1131 this.thumbDiv = new Array; 1132 this.thumbIMG = new Array; 1133 this.thumbTitle = new Array; 1134 this.thumbTable = new Array; 1135 this.thumbTBody = new Array; 1136 this.thumbTR = new Array; 1137 this.thumbTD = new Array; 1138 1139 for(i=0; i<this.imageTotal; i++) { 1140 this.thumbDiv[i] = document.createElement("div"); 1141 this.thumbTitle[i] = document.createElement("div"); 1142 this.thumbIMG[i] = document.createElement("IMG"); 1143 this.thumbTable[i] = document.createElement("table"); 1144 this.thumbTBody[i] = document.createElement("tbody"); 1145 this.thumbTR[i] = document.createElement("tr"); 1146 this.thumbTD[i] = document.createElement("td"); 1147 1148 1149 this.thumbTable[i].cellPadding = 0; 1150 this.thumbTable[i].cellSpacing = 0; 1151 this.thumbTable[i].height = this.thumbHeight+"px"; 1152 this.thumbTable[i].width = this.thumbWidth+"px"; 1153 this.thumbTD[i].height = this.thumbHeight+"px"; 1154 this.thumbTD[i].width = this.thumbWidth+"px"; 1155 this.thumbTD[i].vAlign = "middle"; 1156 1157 this.thumbDiv[i].className="imageThumb"; 1158 this.thumbDiv[i].id="thumbDiv_"+this.photoNum + "_" + i; 1159 this.thumbDiv[i].style.width = this.thumbWidth + "px"; 1160 this.thumbDiv[i].style.height = this.thumbHeight + "px"; 1161 this.thumbDiv[i].style.backgroundColor = this.imageBackColor; 1162 this.thumbDiv[i].style.borderColor = this.imageBackColor; 1163 this.thumbDiv[i].style.lineHeight = this.thumbHeight + "px"; 1164 1165 this.thumbIMG[i].src = this.imageAttributes[i].tnpath; 1166 this.thumbIMG[i].alt = this.imageAttributes[i].alt; 1167 this.thumbIMG[i].id = "thumb_"+this.photoNum + "_" + i; 1168 this.thumbIMG[i].style.margin = "auto"; 1169 this.thumbIMG[i].style.display = "block"; //IE fix 1170 this.thumbIMG[i].style.textAlign = "center"; //IE fix 1171 1172 this.thumbTitle[i].className = 'thumbTitle'; 1173 this.thumbTitle[i].innerHTML = this.imageAttributes[i].title; 1174 this.thumbTitle[i].style.color = this.titleColor; 1175 this.thumbTitle[i].style.fontFamily = this.textFont; 1176 this.thumbTitle[i].style.textAlign = "center"; 1177 this.thumbTitle[i].style.cursor = "default"; 1178 1179 if(this.imageAttributes[i].title.length > largestTitle[j]) { 1180 largestTitle[j] = this.imageAttributes[i].title.length; 1181 this.largestDiv[j] = this.thumbTitle[i]; 1182 //alert(this.largestDiv[j].offsetHeight); 1183 } 1184 1185 if(((i+1)%this.numOfThumbs) == 0) { 1186 j++; 1187 largestTitle[j] = 0; 1188 this.largestDiv[j] = this.thumbTitle[i]; 1189 } 1190 1191 1192 /* 1193 if(this.imageAttributes[i].title.length > largestTitle) 1194 largestTitle = this.imageAttributes[i].title.length; 1195 */ 1196 1197 /**Attach**/ 1198 $("thumbContainer"+this.photoNum).appendChild(this.thumbDiv[i]); 1199 this.thumbDiv[i].appendChild(this.thumbTable[i]); 1200 this.thumbTable[i].appendChild(this.thumbTBody[i]); 1201 this.thumbTBody[i].appendChild(this.thumbTR[i]); 1202 this.thumbTR[i].appendChild(this.thumbTD[i]); 1203 this.thumbTD[i].appendChild(this.thumbIMG[i]); 1204 this.thumbDiv[i].appendChild(this.thumbTitle[i]); 1205 } 1206 1207 //Calculate height with titles PER ROW 1208 1209 var newHeight = []; 1210 1211 if (this.titles == 1) { 1212 1213 //get specific height per row 1214 for(i=0; i<=j; i++) { 1215 approxWidth = Math.ceil(largestTitle[i]*11); //font size is 11px 1216 1217 if(approxWidth > this.thumbWidth)
1218 rowUnit = Math.ceil(approxWidth/this.thumbWidth); 1219 else if(largestTitle[i] == 0) 1220 rowUnit = 0; 1221 else 1222 rowUnit = 1; 1223 1224 newHeight[i] = rowUnit * 16; //line-height is set to 16px 1225 } 1226 1227 j=0; //reset row counter 1228 1229 for(i=0; i<this.imageTotal; i++) { 1230 1231 1232 //alert(parseInt(getStyle(this.thumbDiv[i], 'height')) + ' + ' + parseInt(getStyle(this.largestDiv[j], 'height'))); 1233 1234 1235 //if(document.all) 1236 this.thumbDiv[i].style.height = parseInt(this.thumbDiv[i].style.height) + newHeight[j] + "px"; 1237 //else 1238 // this.thumbDiv[i].style.height = parseInt(getStyle(this.thumbDiv[i], 'height')) + parseInt(getStyle(this.largestDiv[j], 'height')) + "px"; 1239 1240 //alert('should equal this: ' + this.thumbDiv[i].style.height); 1241 if(((i+1)%this.numOfThumbs) == 0) { 1242 //alert(this.largestDiv[j].offsetHeight); 1243 j++; 1244 } 1245 } 1246 } 1247 } 1248 1249 1250 function getStyle(node, sStyle) { 1251 var style; 1252 if (document.all) { 1253 nodeStyle = node.offsetHeight; 1254 } else { 1255 try { 1256 nodeStyle = document.defaultView.getComputedStyle(node,null).getPropertyValue(sStyle); 1257 } catch(e) { } 1258 } 1259 return nodeStyle; 1260 } 1261 1262 1263 1264 1265 1266 1267 function buildMainViewer() { 1268 //this.mainDiv = document.createElement("div"); 1269 this.mainIMG = document.createElement("IMG"); 1270 1271 $("imageContainer"+this.photoNum).width = this.mainWidth; 1272 $("imageContainer"+this.photoNum).height = this.mainHeight; 1273 //this.mainDiv.className = "mainImageDiv"; 1274 //this.mainDiv.id = "imageContainer"+this.photoNum; 1275 $("imageContainer"+this.photoNum).appendChild(this.mainIMG); 1276 $('detailScreen').style.height = getWinHeight(); 1277 $('detailScreen').style.width = getWinWidth(); 1278 1279 if(this.newIC == 'false' && document.all) { 1280 $('details'+this.photoNum).style.position = 'absolute'; 1281 } 1282 1283 } 1284 1285 /*****Behavioral Functions****/ 1286 1287 function getWinWidth(){ 1288 var w; 1289 if(document.innerWidth) { 1290 w=document.innerWidth; 1291 } else if(document.documentElement.clientWidth) { 1292 w=document.documentElement.clientWidth; 1293 } else if(document.body) { 1294 w=document.body.clientWidth; 1295 } 1296 return w; 1297 } 1298 function getWinHeight(){ 1299 var h; 1300 if(document.innerHeight){ 1301 h=document.innerHeight; 1302 } else if(document.documentElement.clientHeight) { 1303 h=document.documentElement.clientHeight; 1304 } else if(document.body) { 1305 h=document.body.clientHeight; 1306 } 1307 return h; 1308 } 1309 1310 function showDetails(evtObj) { 1311 1312 // this.mainIMG.style.display = 'none'; 1313 1314 //Hide all dropdowns in page id IE 1315 if(document.all) { 1316 var dropdowns = document.getElementsByTagName('select'); 1317 for (var j = 0; j < dropdowns.length; j++) { 1318 dropdowns[j].style.visibility = 'hidden'; 1319 } 1320 } 1321 1322 if (document.all) { 1323 1324 if(this.newIC == 'false') { 1325 if (((evtObj.id.substring(0, 5) == 'thumb') || (evtObj.id.substring(0, 8) == 'enlarged')) && (evtObj.id.substring(5, 8) != "Con")) { 1326 $('detailsContainer'+this.photoNum).style.marginTop = getCoords(evtObj).y - 20 + "px"; 1327 $('detailsContainer'+this.photoNum).style.marginLeft = getCoords($('mainContainer'+this.photoNum)).x + "px"; 1328 } 1329 else { 1330 $("detailsContainer"+this.photoNum).style.marginTop = getCoords($('mainContainer'+this.photoNum)).y + "px"; 1331 $("detailsContainer"+this.photoNum).style.marginLeft = getCoords($('mainContainer'+this.photoNum)).x + "px"; 1332 } 1333 } 1334 else { 1335 $("detailsContainer"+this.photoNum).style.top = document.documentElement.scrollTop + 10 + "px"; 1336 $("detailScreen").style.top = document.documentElement.scrollTop + "px"; 1337 } 1338 1339 if(navigator.appVersion.indexOf("MSIE 7.")!=-1) { 1340 $("detailScreen").style.top = "0px"; 1341 } 1342 } 1343 else { //anything other than IE 1344 $("detailsContainer"+this.photoNum).style.top = window.pageYOffset + 10 + "px"; 1345 $("detailScreen").style.top = "0px"; 1346 } 1347 1348 $("detailsContainer"+this.photoNum).style.display = "block"; 1349 $("detailScreen").style.display = "block"; 1350 $("popImage"+this.photoNum).src = this.imageAttributes[this.currentImage].olpath; 1351 //$("popImage"+this.photoNum).style.marginTop = Math.floor((500 - $("popImage"+this.photoNum).height)/2) + "px"; 1352 //alert(this.imageAttributes[this.currentImage].title.length); 1353 $("popTitle"+this.photoNum).innerHTML = this.imageAttributes[this.currentImage].title; 1354 $("popDesc"+this.photoNum).innerHTML = this.imageAttributes[this.currentImage].desc; 1355
1356 this.anContainer.toggle(); 1357 if(this.newIC == 'true') 1358 this.anScreen.toggle(); 1359 this.anImage.toggle(); 1360 this.anTitle.toggle(); 1361 1362 /* window.setTimeout('anScreen.toggle()', 600); 1363 window.setTimeout('anImage.toggle()', 400); 1364 window.setTimeout('anTitle.toggle()', 400); */ 1365 } 1366 1367 function closeDetails() { 1368 1369 1370 if ($('playbutton'+this.photoNum).style.display == 'none' || (this.defaultPlay == 1 && this.controls == 0)) { 1371 window.setTimeout(createObjectCallback(this, this.initPlay), 500); 1372 } 1373 1374 this.anImage.toggle(); 1375 this.anTitle.toggle(); 1376 this.anContainer.toggle(); 1377 if(this.newIC == 'true') 1378 this.anScreen.toggle(); 1379 window.setTimeout(createObjectCallback(this, this.hideDetails), 1000); 1380 } 1381 1382 function hideDetails() { 1383 $("detailsContainer"+this.photoNum).style.display = "none"; 1384 $("detailScreen").style.display = "none"; 1385 this.mainIMG.style.display = 'block'; 1386 1387 //Show all dropdowns in page if IE 1388 if(document.all) { 1389 var dropdowns = document.getElementsByTagName('select'); 1390 for (var i = 0; i < dropdowns.length; i++) { 1391 dropdowns[i].style.visibility = 'visible'; 1392 } 1393 } 1394 } 1395 1396 function stop() { 1397 if (this.randomSlideShow == 1) { 1398 clearInterval(this.randInterval); 1399 } 1400 else { 1401 /**if (playInterval != "")**/ 1402 clearInterval(this.playInterval); 1403 } 1404 this.midPlay = 0; 1405 } 1406 1407 function f_Slide() { 1408 this.lastImage = this.currentImage; 1409 this.currentImage = 0; 1410 1411 this.findCurrent(); 1412 this.showCurrent(); 1413 } 1414 1415 function l_Slide() { 1416 this.lastImage = this.currentImage; 1417 this.currentImage = this.imageTotal -1; 1418 1419 this.findCurrent(); 1420 this.showCurrent(); 1421 } 1422 1423 function findCurrent() { 1424 //alert("thumb"+this.photoNum + this.lastImage); 1425 //$("thumb_"+this.photoNum + "_" + this.lastImage).parentNode.className = "imageThumb"; 1426 //$("thumb_"+this.photoNum + "_" + i).parentNode.className = "imageThumbSelected"; 1427 this.updateCounter(this.currentImage); 1428 } 1429 1430 function showCurrent() { 1431 1432 this.mainIMG.src = this.imageAttributes[this.currentImage].sspath; 1433 this.mainIMG.alt = this.imageAttributes[this.currentImage].alt; 1434 1435 this.mainIMG.id = "mainImage"+this.photoNum; 1436 1437 $("popImage"+this.photoNum).src = this.imageAttributes[this.currentImage].olpath; 1438 if ($("popTitle"+this.photoNum)) 1439 $("popTitle"+this.photoNum).innerHTML = this.imageAttributes[this.currentImage].title; 1440 if ($("popDesc"+this.photoNum)) 1441 $("popDesc"+this.photoNum).innerHTML = this.imageAttributes[this.currentImage].desc; 1442 1443 } 1444 1445 function initPlay() { 1446 //alert(this); 1447 1448 var speed = this.slideSpeed; 1449 1450 if (this.randomSlideShow == 1) { 1451 if(this.firstPlay == 0) clearInterval(this.randInterval); 1452 this.randInterval = window.setInterval(createObjectCallback(this, this.linearPlay), speed); 1453 } 1454 else { 1455 if(this.firstPlay == 0) clearInterval(this.playInterval); 1456 1457 //alert(this.id); 1458 1459 this.playInterval = window.setInterval(createObjectCallback(this, this.linearPlay), speed); 1460 } 1461 1462 //alert(this.linearPlay); 1463 1464 this.firstPlay = 0; 1465 } 1466 1467 function linearPlay() { 1468 //alert("linear play: " + this); 1469 //if (this.stopSlide != 1) { 1470 // if ($('detailScreen').style.display == 'block') { 1471 // if (this.currentDetail != this.imageTotal -1) 1472 // this.currentDetail++; 1473 // else 1474 // this.currentDetail = 0; 1475 1476 // $("popImage"+this.photoNum).src = this.imageAttributes[currentDetail].olpath; 1477 // $("popTitle"+this.photoNum).innerHTML = this.imageAttributes[currentDetail].title; 1478 // $("popDesc"+this.photoNum).innerHTML = this.imageAttributes[currentDetail].desc; 1479 // } 1480 1481 this.showNextDetail(); 1482 //} 1483 //else return; 1484 } 1485 1486 function next() { 1487 //alert("Next this: "+ this); 1488 if (this.currentImage < this.imageTotal-1) { 1489 this.lastImage=this.currentImage; 1490 this.currentImage++; 1491 } 1492 else { 1493 this.currentImage=0; 1494 this.lastImage = this.imageTotal - 1; 1495 } 1496 this.findCurrent(); 1497 this.showCurrent(); 1498 } 1499 1500 function showNextDetail() { 1501 1502 /* 1503 if (this.currentImage != this.imageTotal -1) 1504 this.currentImage++; 1505 else 1506 this.currentImage = 0; 1507 */ 1508 1509 this.next(); 1510 1511 $("popImage"+this.photoNum).src = this.imageAttributes[this.currentImage].olpath; 1512 $("popTitle"+this.photoNum).innerHTML = this.imageAttributes[this.currentImage].title; 1513 $("popDesc"+this.photoNum).innerHTML = this.imageAttributes[this.currentImage].desc; 1514 } 1515 1516 function previous() { 1517 if (this.currentImage > 0) { 1518 this.lastImage=this.currentImage; 1519 this.currentImage--; 1520 } 1521 else { 1522 this.currentImage=this.imageTotal-1; 1523 this.lastImage = 0; 1524 } 1525 this.findCurrent(); 1526 this.showCurrent(); 1527 } 1528 1529 function showPrevDetail() { 1530 /* 1531 if (this.currentImage != 0) 1532 this.currentImage--; 1533 else 1534 this.currentImage = this.imageTotal-1; 1535 */ 1536 1537 this.previous(); 1538 1539 $("popImage"+this.photoNum).src = this.imageAttributes[this.currentImage].olpath; 1540 $("popTitle"+this.photoNum).innerHTML = this.imageAttributes[this.currentImage].title; 1541 $("popDesc"+this.photoNum).innerHTML = this.imageAttributes[this.currentImage].desc; 1542 1543 } 1544 1545 function randPlay() { 1546 1547 if (stopSlide != 1) { 1548 if (this.currentImage <= this.imageTotal) 1549 { 1550 1551 this.lastImage = this.currentImage; 1552 1553 while (this.lastImage == this.currentImage) { 1554 this.currentImage = randNum(0, (this.imageTotal-1)); 1555 } 1556 1557 this.findCurrent(); 1558 this.showCurrent(); 1559 1560 } 1561 } 1562 else return; 1563 } 1564 1565 function changeSpeed(speed, num, relative_path) 1566 { 1567 this.slideSpeed = speed; 1568 //speed = this.slideSpeed; //just trust me 1569 1570 for (i=num; i<6; i++) 1571 { 1572 $('speed'+i+this.photoNum).src = relative_path+'images/photoalbum/button_photoSpeed'+i+'.jpg'; 1573 //$('detailspeed'+i).src = 'images/photoalbum/button_photoSpeed'+i+'.jpg'; 1574 } 1575 for (i=1; i<=num; i++) 1576 { 1577 $('speed'+i+this.photoNum).src = relative_path+'images/photoalbum/button_photoSpeed'+i+'_ON.jpg'; 1578 //$('detailspeed'+i).src = 'images/button_photoSpeed'+i+'_ON.jpg'; 1579 } 1580 1581 if (this.randomSlideShow == 1) { 1582 clearInterval(this.randInterval); 1583 this.randInterval = window.setInterval(createObjectCallback(this, this.randPlay), this.slideSpeed); 1584 } 1585 else if($('playbutton'+this.photoNum).style.display == 'none') 1586 { 1587 clearInterval(this.playInterval); 1588 this.playInterval = window.setInterval(createObjectCallback(this, this.linearPlay), this.slideSpeed); 1589 } 1590 } 1591 1592 1593 function swap(a, b) { 1594 $(a).style.display = 'none'; 1595 $(b).style.display = 'inline'; 1596 } 1597 1598 function $(id) { 1599 return document.getElementById(id); 1600 } 1601 1602 function randNum(x, y) { 1603 var range = y - x + 1; 1604 return Math.floor(Math.random() * range) + x; 1605 } 1606 1607 function getCoords(element) 1608 { 1609 var valueT = 0, valueL = 0; 1610 1611 do 1612 { 1613 valueT += element.offsetTop || 0; 1614 valueL += element.offsetLeft || 0; 1615 element = element.offsetParent; 1616 } 1617 while (element); 1618 1619 return {x: valueL, y: valueT}; 1620 } 1621 1622 function adjustOverlay() { //onscroll 1623 try{ 1624 if (document.all &&(navigator.appVersion.indexOf("MSIE 7.")==-1)) { 1625 $('detailScreen').style.height = getWinHeight(); //adjust for resize 1626 $('detailScreen').style.width = getWinWidth(); //adjust for resize 1627 //$("detailsContainer"+this.photoNum).style.top = document.documentElement.scrollTop + 10 + "px"; 1628 if(this.newIC == 'false') { //legacy frames 1629 //$("detailScreen").style.top = parent.content.document.body.scrollTop + "px"; 1630 } 1631 else { 1632 $("detailScreen").style.top = document.documentElement.scrollTop + "px"; 1633 } 1634 } 1635 } 1636 catch(e){return false;} 1637 //else { 1638 // $("detailsContainer").style.top = window.pageYOffset + 10 + "px"; 1639 // $("detailScreen").style.top = window.pageYOffset + "px"; 1640 // } 1641 1642 } 1643 1644 function createObjectCallback(obj, fn) 1645 { 1646 return function() 1647 { 1648 fn.apply(obj, arguments); 1649 }; 1650 } 1651 1652 /* ####### Photoalbum.js code ends here ########## */
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.