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