PageSourceSearch

https://www.stadtwerk-am-see.de/de/static/js/HRSysLib/Transition/animator.js?nc=1790327236423

js stadtwerk-am-see.de collected 2026-09-25 20:48:22 UTC 33,595 bytes, 1,052 lines download raw bytes

1/*  
2	Animator.js 1.1.11
3	
4	This library is released under the BSD license:
5
6	Copyright (c) 2006, Bernard Sumption. All rights reserved.
7	
8	Redistribution and use in source and binary forms, with or without
9	modification, are permitted provided that the following conditions are met:
10	
11	Redistributions of source code must retain the above copyright notice, this
12	list of conditions and the following disclaimer. Redistributions in binary
13	form must reproduce the above copyright notice, this list of conditions and
14	the following disclaimer in the documentation and/or other materials
15	provided with the distribution. Neither the name BernieCode nor
16	the names of its contributors may be used to endorse or promote products
17	derived from this software without specific prior written permission. 
18	
19	THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20	AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21	IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22	ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
23	ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24	DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25	SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26	CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27	LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28	OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
29	DAMAGE.
30
31*/
32
33// Applies a sequence of numbers between 0 and 1 to a number of subjects
34// construct - see setOptions for parameters
35function Animator(options)
36{
37   try
38   {
39      this.setOptions(options);
40      var _this = this;
41      this.timerDelegate = function()
42      {
43         _this.onTimerEvent()
44      }
45      try
46      {
47         this.animFrameStart = null;
48         this.animFrameActive = false;
49         this.animFrameRequestID = null;
50         this.animFrameDelegate = function(timestamp)
51         {
52            var progress;
53            if (_this.animFrameStart === null) 
54               _this.animFrameStart = timestamp;
55            
56            progress = timestamp - _this.animFrameStart;
57//            if (progress >= _this.options.interval)
58            {
59               _this.animFrameStart = null;
60               _this.onTimerEvent();
61            }
62            if (_this.animFrameActive)
63            {
64               if (window.requestAnimationFrame != null)
65                  _this.animFrameRequestID = window.requestAnimationFrame(_this.animFrameDelegate);
66               else if (window.mozRequestAnimationFrame != null)
67                  _this.animFrameRequestID = window.mozRequestAnimationFrame(_this.animFrameDelegate);
68               else if (window.webkitRequestAnimationFrame != null)
69                  _this.animFrameRequestID = window.webkitRequestAnimationFrame(_this.animFrameDelegate);
70               else if (window.msRequestAnimationFrame != null)
71                  _this.animFrameRequestID = window.msRequestAnimationFrame(_this.animFrameDelegate);
72            }
73         }
74      }
75      catch (e) 
76      {
77         if (typeof(HRLogError) == 'function')
78            HRLogError(e);
79      }
80      this.subjects = [];
81      this.target = 0;
82      this.state = 0;
83      this.lastTime = null;
84   }
85   catch (e) 
86   {
87      if (typeof(HRLogError) == 'function')
88         HRLogError(e);
89   }
90};
91
92Animator.prototype = 
93{
94   // apply defaults
95   setOptions : function(options)
96   {
97      this.options = Animator.applyDefaults(
98      {
99         interval : 20, // time between animation frames
100         duration : 400, // length of animation
101         onComplete : function()
102         {
103         },
104         onStep : function()
105         {
106         },
107         transition : Animator.tx.easeInOut
108      }, options);
109   },
110   // animate from the current state to provided value
111   seekTo : function(to)
112   {
113      this.seekFromTo(this.state, to);
114   },
115	// animate from the current state to provided value
116   seekFromTo : function(from, to)
117   {
118      this.target = Math.max(0, Math.min(1, to));
119      this.state = Math.max(0, Math.min(1, from));
120      this.lastTime = new Date().getTime();
121      if (window.requestAnimationFrame == null && window.mozRequestAnimationFrame == null && window.webkitRequestAnimationFrame == null && window.msRequestAnimationFrame == null)
122      {
123         if (!this.intervalId)
124         {
125            this.intervalId = window.setInterval(this.timerDelegate, this.options.interval);
126         }
127      }
128      else
129      {
130         if (!this.animFrameActive)
131         {
132            this.animFrameActive = true;
133            if (window.requestAnimationFrame != null)
134               this.animFrameRequestID = window.requestAnimationFrame(this.animFrameDelegate);
135            else if (window.mozRequestAnimationFrame != null)
136               this.animFrameRequestID = window.mozRequestAnimationFrame(this.animFrameDelegate);
137            else if (window.webkitRequestAnimationFrame != null)
138               this.animFrameRequestID = window.webkitRequestAnimationFrame(this.animFrameDelegate);
139            else if (window.msRequestAnimationFrame != null)
140               this.animFrameRequestID = window.msRequestAnimationFrame(this.animFrameDelegate);
141         }
142      }
143   },
144   // animate from the current state to provided value
145   jumpTo : function(to)
146   {
147      this.target = this.state = Math.max(0, Math.min(1, to));
148      this.propagate();
149   },
150   // seek to the opposite of the current target
151   toggle : function()
152   {
153      this.seekTo(1 - this.target);
154   },
155   // add a function or an object with a method setState(state) that will be
156   // called with a number
157   // between 0 and 1 on each frame of the animation
158   addSubject : function(subject)
159   {
160      this.subjects[this.subjects.length] = subject;
161      return this;
162   },
163   // remove all subjects
164   clearSubjects : function()
165   {
166      this.subjects = [];
167   },
168   // forward the current state to the animation subjects
169   propagate : function()
170   {
171      var value = this.options.transition(this.state);
172      for ( var i = 0; i < this.subjects.length; i++)
173      {
174         if (this.subjects[i].setState)
175         {
176            this.subjects[i].setState(value);
177         }
178         else
179         {
180            this.subjects[i](value);
181         }
182      }
183   },
184   // called once per frame to update the current state
185   onTimerEvent : function()
186   {
187      var now = new Date().getTime();
188      var timePassed = now - this.lastTime;
189      this.lastTime = now;
190      var movement = (timePassed / this.options.duration) * (this.state < this.target ? 1 : -1);
191      if (Math.abs(movement) >= Math.abs(this.state - this.target))
192      {
193         this.state = this.target;
194      }
195      else
196      {
197         this.state += movement;
198      }
199
200      try
201      {
202         this.propagate();
203      }
204      finally
205      {
206         this.options.onStep.call(this);
207         if (this.target == this.state)
208         {
209            this.stop();
210         }
211      }
212   },
213   stop : function()
214   {
215      if (window.requestAnimationFrame == null && window.mozRequestAnimationFrame == null && window.webkitRequestAnimationFrame == null && window.msRequestAnimationFrame == null)
216      {
217         if (this.intervalId)
218         {
219            window.clearInterval(this.intervalId);
220            this.intervalId = null;
221            this.options.onComplete.call(this);
222         }
223      }
224      else
225      {
226         if (this.animFrameActive)
227         {
228            this.animFrameActive = false;
229            if (this.animFrameRequestID != null)
230            {
231               if (window.cancelAnimationFrame != null)
232                  window.cancelAnimationFrame(this.animFrameRequestID);
233               else if (window.mozCancelAnimationFrame != null)
234                  window.mozCancelAnimationFrame(this.animFrameRequestID);
235            }
236            this.animFrameRequestID = null;
237            this.options.onComplete.call(this);
238         }
239      }
240   },
241   // shortcuts
242   play : function()
243   {
244      this.seekFromTo(0, 1)
245   },
246   reverse : function()
247   {
248      this.seekFromTo(1, 0)
249   },
250   // return a string describing this Animator, for debugging
251   inspect : function()
252   {
253      var str = "#<Animator:\n";
254      for ( var i = 0; i < this.subjects.length; i++)
255      {
256         str += this.subjects[i].inspect();
257      }
258      str += ">";
259      return str;
260   }
261}
262// merge the properties of two objects
263Animator.applyDefaults = function(defaults, prefs)
264{
265   prefs = prefs || {};
266   var prop, result = {};
267   for (prop in defaults)
268      result[prop] = prefs[prop] !== undefined ? prefs[prop] : defaults[prop];
269      
270   return result;
271}
272// make an array from any object
273Animator.makeArrayOfElements = function(o)
274{
275   if (o == null)
276      return [];
277   if ("string" == typeof o)
278   {
279      return [ document.getElementById(o) ];
280   }
281   if (!o.length)
282      return [ o ];
283   var result = [];
284   for ( var i = 0; i < o.length; i++)
285   {
286      if ("string" == typeof o[i])
287      {
288         result[i] = document.getElementById(o[i]);
289      }
290      else
291      {
292         result[i] = o[i];
293      }
294   }
295   return result;
296}
297// convert a dash-delimited-property to a camelCaseProperty (c/o Prototype, thanks Sam!)
298Animator.camelize = function(string)
299{
300   var oStringList = string.split('-');
301   if (oStringList.length == 1)
302      return oStringList[0];
303
304   var camelizedString = string.indexOf('-') == 0 ? 
305                         oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) : 
306                         oStringList[0];
307
308   for ( var i = 1, len = oStringList.length; i < len; i++)
309   {
310      var s = oStringList[i];
311      camelizedString += s.charAt(0).toUpperCase() + s.substring(1);
312   }
313   return camelizedString;
314}
315// syntactic sugar for creating CSSStyleSubjects
316Animator.apply = function(el, style, options)
317{
318   if (style instanceof Array)
319   {
320      return new Animator(options).addSubject(new CSSStyleSubject(el, style[0], style[1]));
321   }
322   return new Animator(options).addSubject(new CSSStyleSubject(el, style));
323}
324// make a transition function that gradually accelerates. pass a=1 for smooth
325// gravitational acceleration, higher values for an exaggerated effect
326Animator.makeEaseIn = function(a)
327{
328   return function(state)
329   {
330      return Math.pow(state, a * 2);
331   }
332}
333// as makeEaseIn but for deceleration
334Animator.makeEaseOut = function(a)
335{
336   return function(state)
337   {
338      return 1 - Math.pow(1 - state, a * 2);
339   }
340}
341// make a transition function that, like an object with momentum being attracted
342// to a point,
343// goes past the target then returns
344Animator.makeElastic = function(bounces)
345{
346   return function(state)
347   {
348      state = Animator.tx.easeInOut(state);
349      return ((1 - Math.cos(state * Math.PI * bounces)) * (1 - state)) + state;
350   }
351}
352// make an Attack Decay Sustain Release envelope that starts and finishes on the same level
353// 
354Animator.makeADSR = function(attackEnd, decayEnd, sustainEnd, sustainLevel)
355{
356   if (sustainLevel == null)
357      sustainLevel = 0.5;
358   
359   return function(state)
360      {
361         if (state < attackEnd)
362         {
363            return state / attackEnd;
364         }
365         if (state < decayEnd)
366         {
367            return 1 - ((state - attackEnd) / (decayEnd - attackEnd) * (1 - sustainLevel));
368         }
369         if (state < sustainEnd)
370         {
371            return sustainLevel;
372         }
373         return sustainLevel * (1 - ((state - sustainEnd) / (1 - sustainEnd)));
374      }
375}
376// make a transition function that, like a ball falling to floor, reaches the target and/
377// bounces back again
378Animator.makeBounce = function(bounces)
379{
380   var fn = Animator.makeElastic(bounces);
381   return function(state)
382      {
383         state = fn(state);
384         return state <= 1 ? state : 2 - state;
385      }
386}
387 
388
389// pre-made transition functions to use with the 'transition' option
390Animator.tx =
391{
392   easeInOut : function(pos)
393      {
394         return ((-Math.cos(pos * Math.PI) / 2) + 0.5);
395      },
396   linear : function(x)
397      {
398         return x;
399      },
400   easeInOutQuad : function(pos)
401      {
402         if ((pos /= 0.5) < 1) 
403            return 0.5 * pos * pos + 0;
404         return -0.5 * ((--pos) * (pos - 2) - 1) + 0;
405      },
406   easeInOutCubic : function(pos)
407      {
408         if ((pos /= 0.5) < 1) 
409            return 0.5 * pos * pos * pos + 0;
410         return 0.5 * ((pos -= 2) * pos * pos + 2) + 0;
411      },
412   easeInOutQuart : function(pos)
413      {
414         if ((pos /= 0.5) < 1) 
415            return 0.5 * pos * pos * pos * pos + 0;
416         return -0.5 * ((pos -= 2) * pos * pos * pos - 2) + 0;
417      },
418   easeInOutQuint : function(pos)
419      {
420         if ((pos /= 0.5) < 1) 
421            return 0.5 * pos * pos * pos * pos * pos + 0;
422      return 0.5 * ((pos -= 2) * pos * pos * pos * pos + 2) + 0;
423      },
424   easeIn : Animator.makeEaseIn(1.5),
425   easeOut : Animator.makeEaseOut(1.5),
426   strongEaseIn : Animator.makeEaseIn(2.5),
427   strongEaseOut : Animator.makeEaseOut(2.5),
428   elastic : Animator.makeElastic(1),
429   veryElastic : Animator.makeElastic(3),
430   bouncy : Animator.makeBounce(1),
431   veryBouncy : Animator.makeBounce(3)
432}
433
434// animates a pixel-based style property between two integer values
435function NumericalStyleSubject(els, property, from, to, units)
436{
437   this.els = Animator.makeArrayOfElements(els);
438   var ieVersion = getIEVersionNr();
439   if (property == 'opacity' && window.ActiveXObject && ieVersion <= 9 && ieVersion > 0)
440   {
441      this.property = 'filter';
442   }
443   else
444   {
445      this.property = Animator.camelize(property);
446   }
447   this.from = parseFloat(from);
448   this.to = parseFloat(to);
449   this.units = units != null ? units : 'px';
450}
451NumericalStyleSubject.prototype =
452{
453   setState : function(state)
454   {
455      var style = this.getStyle(state);
456      var visibility = (this.property == 'opacity' && state == 0) ? 'hidden' : '';
457      var j = 0;
458      for ( var i = 0; i < this.els.length; i++)
459      {
460         try
461         {
462            this.els[i].style[this.property] = style;
463         }
464         catch (e)
465         {
466            // ignore fontWeight - intermediate numerical values cause exeptions
467            // in firefox
468            if (this.property != 'fontWeight')
469               throw e;
470         }
471         if (j++ > 20)
472            return;
473      }
474   },
475   getStyle : function(state)
476   {
477      state = this.from + ((this.to - this.from) * state);
478      if (this.property == 'filter')
479         return "alpha(opacity=" + Math.round(state * 100) + ")";
480      if (this.property == 'opacity')
481         return state;
482      return Math.round(state) + this.units;
483   },
484   inspect : function()
485   {
486      return "\t" + this.property + "(" + this.from + this.units + " to " + this.to + this.units
487             + ")\n";
488   }
489}
490
491// animates a colour based style property between two hex values
492function ColorStyleSubject(els, property, from, to)
493{
494   this.els = Animator.makeArrayOfElements(els);
495   this.property = Animator.camelize(property);
496   this.to = this.expandColor(to);
497   this.from = this.expandColor(from);
498   this.origFrom = from;
499   this.origTo = to;
500}
501
502ColorStyleSubject.prototype = {
503	// parse "#FFFF00" to [256, 256, 0]
504	expandColor: function(color) {
505		var hexColor, red, green, blue;
506		hexColor = ColorStyleSubject.parseColor(color);
507		if (hexColor) {
508			red = parseInt(hexColor.slice(1, 3), 16);
509			green = parseInt(hexColor.slice(3, 5), 16);
510			blue = parseInt(hexColor.slice(5, 7), 16);
511			return [red,green,blue]
512		}
513		if (window.ANIMATOR_DEBUG) {
514			alert("Invalid colour: '" + color + "'");
515		}
516	},
517	getValueForState: function(color, state) {
518		return Math.round(this.from[color] + ((this.to[color] - this.from[color]) * state));
519	},
520	setState: function(state) {
521		var color = '#'
522				+ ColorStyleSubject.toColorPart(this.getValueForState(0, state))
523				+ ColorStyleSubject.toColorPart(this.getValueForState(1, state))
524				+ ColorStyleSubject.toColorPart(this.getValueForState(2, state));
525		for (var i=0; i<this.els.length; i++) {
526			this.els[i].style[this.property] = color;
527		}
528	},
529	inspect: function() {
530		return "\t" + this.property + "(" + this.origFrom + " to " + this.origTo + ")\n";
531	}
532}
533
534// return a properly formatted 6-digit hex colour spec, or false
535ColorStyleSubject.parseColor = function(string)
536{
537   var color = '#', match;
538   if (match = ColorStyleSubject.parseColor.rgbRe.exec(string))
539   {
540      var part;
541      for ( var i = 1; i <= 3; i++)
542      {
543         part = Math.max(0, Math.min(255, parseInt(match[i])));
544         color += ColorStyleSubject.toColorPart(part);
545      }
546      return color;
547   }
548   if (match = ColorStyleSubject.parseColor.hexRe.exec(string))
549   {
550      if (match[1].length == 3)
551      {
552         for ( var i = 0; i < 3; i++)
553         {
554            color += match[1].charAt(i) + match[1].charAt(i);
555         }
556         return color;
557      }
558      return '#' + match[1];
559   }
560   return false;
561}
562// convert a number to a 2 digit hex string
563ColorStyleSubject.toColorPart = function(number)
564{
565   if (number > 255)
566      number = 255;
567   var digits = number.toString(16);
568   if (number < 16)
569      return '0' + digits;
570   return digits;
571}
572ColorStyleSubject.parseColor.rgbRe = /^rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i;
573ColorStyleSubject.parseColor.hexRe = /^\#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/;
574
575// Animates discrete styles, i.e. ones that do not scale but have discrete values
576// that can't be interpolated
577function DiscreteStyleSubject(els, property, from, to, threshold)
578{
579   this.els = Animator.makeArrayOfElements(els);
580   this.property = Animator.camelize(property);
581   this.from = from;
582   this.to = to;
583   this.threshold = threshold || 0.5;
584}
585
586DiscreteStyleSubject.prototype =
587{
588   setState : function(state)
589   {
590      var j = 0;
591      for ( var i = 0; i < this.els.length; i++)
592      {
593         this.els[i].style[this.property] = state <= this.threshold ? this.from : this.to;
594      }
595   },
596   inspect : function()
597   {
598      return "\t" + this.property + "(" + this.from + " to " + this.to + " @ " + this.threshold + ")\n";
599   }
600}
601
602//Animates numerical properties, i.e. scrollTop
603function NumericalPropertySubject(els, property, from, to)
604{
605    this.els = Animator.makeArrayOfElements(els);
606    this.property = Animator.camelize(property);
607    this.from = parseFloat(from);
608    this.to = parseFloat(to);
609}
610    
611NumericalPropertySubject.prototype =
612{
613    setState : function(state)
614    {
615       var j = 0;
616       state = this.from + ((this.to - this.from) * state);
617       for ( var i = 0; i < this.els.length; i++)
618       {
619          this.els[i][this.property] = Math.round(state);
620       }
621    },
622    inspect : function()
623    {
624       return "\t" + this.property + "(" + this.from + " to " + this.to + ")\n";
625    }
626}
627
628// animates between two styles defined using CSS.
629// if style1 and style2 are present, animate between them, if only style1
630// is present, animate between the element's current style and style1
631function CSSStyleSubject(els, style1, style2)
632{
633   els = Animator.makeArrayOfElements(els);
634   this.subjects = [];
635   if (els.length == 0)
636      return;
637   
638   var prop, toStyle, fromStyle;
639   if (style2)
640   {
641      fromStyle = this.parseStyle(style1, els[0]);
642      toStyle = this.parseStyle(style2, els[0]);
643   }
644   else
645   {
646      toStyle = this.parseStyle(style1, els[0]);
647      fromStyle =
648      {};
649      for (prop in toStyle)
650      {
651         fromStyle[prop] = CSSStyleSubject.getStyle(els[0], prop);
652      }
653   }
654   // remove unchanging properties
655   var prop;
656   for (prop in fromStyle)
657   {
658      if (fromStyle[prop] == toStyle[prop])
659      {
660         delete fromStyle[prop];
661         delete toStyle[prop];
662      }
663   }
664   // discover the type (numerical or colour) of each style
665   var prop, units, match, type, from, to;
666   for (prop in fromStyle)
667   {
668      var fromProp = String(fromStyle[prop]);
669      var toProp = String(toStyle[prop]);
670      if (toStyle[prop] == null)
671      {
672         if (window.ANIMATOR_DEBUG)
673            alert("No to style provided for '" + prop + '"');
674         continue;
675      }
676
677      if (from = ColorStyleSubject.parseColor(fromProp))
678      {
679         to = ColorStyleSubject.parseColor(toProp);
680         type = ColorStyleSubject;
681      }
682      else if (fromProp.match(CSSStyleSubject.numericalRe)
683               && toProp.match(CSSStyleSubject.numericalRe))
684      {
685         from = parseFloat(fromProp);
686         to = parseFloat(toProp);
687         type = NumericalStyleSubject;
688         match = CSSStyleSubject.numericalRe.exec(fromProp);
689         var reResult = CSSStyleSubject.numericalRe.exec(toProp);
690         if (match[1] != null)
691         {
692            units = match[1];
693         }
694         else if (reResult[1] != null)
695         {
696            units = reResult[1];
697         }
698         else
699         {
700            units = reResult;
701         }
702      }
703      else if (   fromProp.match(CSSStyleSubject.discreteRe)
704               && toProp.match(CSSStyleSubject.discreteRe))
705      {
706         from = fromProp;
707         to = toProp;
708         type = DiscreteStyleSubject;
709         units = 0; // hack - how to get an animator option down to here
710      }
711      else
712      {
713         if (window.ANIMATOR_DEBUG)
714         {
715            alert("Unrecognised format for value of " + prop + ": '" + fromStyle[prop] + "'");
716         }
717         continue;
718      }
719      this.subjects[this.subjects.length] = new type(els, prop, from, to, units);
720   }
721}
722
723CSSStyleSubject.prototype =
724{
725   // parses "width: 400px; color: #FFBB2E" to {width: "400px", color:
726   // "#FFBB2E"}
727   parseStyle : function(style, el)
728   {
729      var rtn =
730      {};
731      // if style is a rule set
732      if (style.indexOf(":") != -1)
733      {
734         var styles = style.split(";");
735         for ( var i = 0; i < styles.length; i++)
736         {
737            var parts = CSSStyleSubject.ruleRe.exec(styles[i]);
738            if (parts)
739            {
740               rtn[parts[1]] = parts[2];
741            }
742         }
743      }
744      // else assume style is a class name
745      else
746      {
747         var prop, value, oldClass;
748         oldClass = el.className;
749         el.className = style;
750         for ( var i = 0; i < CSSStyleSubject.cssProperties.length; i++)
751         {
752            prop = CSSStyleSubject.cssProperties[i];
753            value = CSSStyleSubject.getStyle(el, prop);
754            if (value != null)
755            {
756               rtn[prop] = value;
757            }
758         }
759         el.className = oldClass;
760      }
761      return rtn;
762
763   },
764   setState : function(state)
765   {
766      for ( var i = 0; i < this.subjects.length; i++)
767      {
768         this.subjects[i].setState(state);
769      }
770   },
771   inspect : function()
772   {
773      var str = "";
774      for ( var i = 0; i < this.subjects.length; i++)
775      {
776         str += this.subjects[i].inspect();
777      }
778      return str;
779   }
780}
781// get the current value of a css property,
782CSSStyleSubject.getStyle = function(el, property)
783{
784   var style;
785   if (document.defaultView && document.defaultView.getComputedStyle)
786   {
787      style = document.defaultView.getComputedStyle(el, "").getPropertyValue(property);
788      if (style)
789      {
790         return style;
791      }
792   }
793   property = Animator.camelize(property);
794   if (el.currentStyle)
795   {
796      style = el.currentStyle[property];
797   }
798   return style || el.style[property]
799}
800
801
802CSSStyleSubject.ruleRe = /^\s*([a-zA-Z\-]+)\s*:\s*(\S(.+\S)?)\s*$/;
803CSSStyleSubject.numericalRe = /^-?\d+(?:\.\d+)?(%|[a-zA-Z]{2})?$/;
804CSSStyleSubject.discreteRe = /^\w+$/;
805
806// required because the style object of elements isn't enumerable in Safari
807/*
808CSSStyleSubject.cssProperties = ['background-color','border','border-color','border-spacing',
809'border-style','border-top','border-right','border-bottom','border-left','border-top-color',
810'border-right-color','border-bottom-color','border-left-color','border-top-width','border-right-width',
811'border-bottom-width','border-left-width','border-width','bottom','color','font-size','font-size-adjust',
812'font-stretch','font-style','height','left','letter-spacing','line-height','margin','margin-top',
813'margin-right','margin-bottom','margin-left','marker-offset','max-height','max-width','min-height',
814'min-width','orphans','outline','outline-color','outline-style','outline-width','overflow','padding',
815'padding-top','padding-right','padding-bottom','padding-left','quotes','right','size','text-indent',
816'top','width','word-spacing','z-index','opacity','outline-offset'];*/
817
818
819CSSStyleSubject.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'];
820
821
822// chains several Animator objects together
823function AnimatorChain(animators, options)
824{
825   this.animators = animators;
826   this.setOptions(options);
827   for ( var i = 0; i < this.animators.length; i++)
828   {
829      this.listenTo(this.animators[i]);
830   }
831   this.forwards = false;
832   this.current = 0;
833}
834
835AnimatorChain.prototype =
836{
837   // apply defaults
838   setOptions : function(options)
839   {
840      this.options = Animator.applyDefaults(
841      {
842         // by default, each call to AnimatorChain.play() calls jumpTo(0) of
843         // each animator
844         // before playing, which can cause flickering if you have multiple
845         // animators all
846         // targeting the same element. Set this to false to avoid this.
847         resetOnPlay : true
848      }, options);
849   },
850   // play each animator in turn
851   play : function()
852   {
853      this.forwards = true;
854      this.current = -1;
855      if (this.options.resetOnPlay)
856      {
857         for ( var i = 0; i < this.animators.length; i++)
858         {
859            this.animators[i].jumpTo(0);
860         }
861      }
862      this.advance();
863   },
864   // play all animators backwards
865   reverse : function()
866   {
867      this.forwards = false;
868      this.current = this.animators.length;
869      if (this.options.resetOnPlay)
870      {
871         for ( var i = 0; i < this.animators.length; i++)
872         {
873            this.animators[i].jumpTo(1);
874         }
875      }
876      this.advance();
877   },
878   // if we have just play()'d, then call reverse(), and vice versa
879   toggle : function()
880   {
881      if (this.forwards)
882      {
883         this.seekTo(0);
884      }
885      else
886      {
887         this.seekTo(1);
888      }
889   },
890   // internal: install an event listener on an animator's onComplete option
891   // to trigger the next animator
892   listenTo : function(animator)
893   {
894      var oldOnComplete = animator.options.onComplete;
895      var _this = this;
896      animator.options.onComplete = function()
897      {
898         if (oldOnComplete)
899            oldOnComplete.call(animator);
900         _this.advance();
901      }
902   },
903   // play the next animator
904   advance : function()
905   {
906      if (this.forwards)
907      {
908         if (this.animators[this.current + 1] == null)
909            return;
910         this.current++;
911         this.animators[this.current].play();
912      }
913      else
914      {
915         if (this.animators[this.current - 1] == null)
916            return;
917         this.current--;
918         this.animators[this.current].reverse();
919      }
920   },
921   // this function is provided for drop-in compatibility with Animator objects,
922   // but only accepts 0 and 1 as target values
923   seekTo : function(target)
924   {
925      if (target <= 0)
926      {
927         this.forwards = false;
928         this.animators[this.current].seekTo(0);
929      }
930      else
931      {
932         this.forwards = true;
933         this.animators[this.current].seekTo(1);
934      }
935   }
936}
937
938// an Accordion is a class that creates and controls a number of Animators. An
939// array of elements is passed in,
940// and for each element an Animator and a activator button is created. When an
941// Animator's activator button is
942// clicked, the Animator and all before it seek to 0, and all Animators after it
943// seek to 1. This can be used to
944// create the classic Accordion effect, hence the name.
945// see setOptions for arguments
946function Accordion(options)
947{
948   this.setOptions(options);
949   var selected = this.options.initialSection, current;
950   if (this.options.rememberance)
951   {
952      current = document.location.hash.substring(1);
953   }
954   this.rememberanceTexts = [];
955   this.ans = [];
956   var _this = this;
957   for ( var i = 0; i < this.options.sections.length; i++)
958   {
959      var el = this.options.sections[i];
960      var an = new Animator(this.options.animatorOptions);
961      var from = this.options.from + (this.options.shift * i);
962      var to = this.options.to + (this.options.shift * i);
963      an.addSubject(new NumericalStyleSubject(el, this.options.property, from, to,
964                                              this.options.units));
965      an.jumpTo(0);
966      var activator = this.options.getActivator(el);
967      activator.index = i;
968      activator.onclick = function()
969      {
970         _this.show(this.index)
971      };
972      this.ans[this.ans.length] = an;
973      this.rememberanceTexts[i] = activator.innerHTML.replace(/\s/g, "");
974      if (this.rememberanceTexts[i] === current)
975      {
976         selected = i;
977      }
978   }
979   this.show(selected);
980}
981
982Accordion.prototype =
983{
984   // apply defaults
985   setOptions : function(options)
986   {
987      this.options = Object.extend(
988      {
989         // REQUIRED: an array of elements to use as the accordion sections
990         sections : null,
991         // a function that locates an activator button element given a section
992         // element.
993         // by default it takes a button id from the section's "activator"
994         // attibute
995         getActivator : function(el)
996         {
997            return document.getElementById(el.getAttribute("activator"))
998         },
999         // shifts each animator's range, for example with options
1000         // {from:0,to:100,shift:20}
1001         // the animators' ranges will be 0-100, 20-120, 40-140 etc.
1002         shift : 0,
1003         // the first page to show
1004         initialSection : 0,
1005         // if set to true, document.location.hash will be used to preserve the
1006         // open section across page reloads
1007         rememberance : true,
1008         // constructor arguments to the Animator objects
1009         animatorOptions :
1010         {}
1011      }, options ||
1012      {});
1013   },
1014   show : function(section)
1015   {
1016      for ( var i = 0; i < this.ans.length; i++)
1017      {
1018         this.ans[i].seekTo(i > section ? 1 : 0);
1019      }
1020      if (this.options.rememberance)
1021      {
1022         document.location.hash = this.rememberanceTexts[section];
1023      }
1024   }
1025}
1026
1027//
1028// Ein paar Hilfsfunktionen, bis wir uns sicher sein können, dass immer die HRSysLib zuvor geladen ist.
1029//
1030function getIEVersionNr()
1031{
1032   var ieVersion = -1;  // Default kein IE!
1033   try
1034   {  
1035      // Wenn wir unser Browser-Objekt am Start haben, fragen wir das.
1036      //
1037      if (typeof(HRBrowser) != 'undefined' && typeof(HRBrowser.getIEVersionsNr) == 'function')
1038         return HRBrowser.getIEVersionsNr();
1039      
1040      var agentStr = navigator.userAgent.toLowerCase();
1041      var ieKennung = 'msie';
1042      var indexOfIE = agentStr.indexOf(ieKennung);
1043      if (indexOfIE >= 0)
1044      {
1045         agentStr = agentStr.substring(indexOfIE + ieKennung.length);
1046         ieVersion = parseFloat(agentStr);
1047      }
1048   }
1049   catch (e) 
1050   {}
1051   return ieVersion;
1052}

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.