
/* Omni Image View, Fade, and/or Slide Script ©2008 John Davenport Scheuer
   as first seen in http://www.dynamicdrive.com/forums/
   username: jscheuer1 - This Notice Must Remain for Legal Use
   */

var viewfadeslide = { //place comma after each entry

//Use true or false or object containing boolean values for separate primary load areas

 enableCaption : false, //Should "title" attribute of link and any paired image's 3rd parameter to be used as caption?
 makeTitle : false, //Make title attribute for enlarged image from name attribute of trigger link?
 hideImgMouseOut : false, //Hide enlarged image when mouse moves out of anchor link? (if enlarged image is hyperlinked, always set to false!)
 disableOnClick : true, //Disable default onclick for mouseover triggers?
 populateWithFirst : true, //Fire first link in load area group(s) onload?
 enableCount : false,

//Use true or false

 enableTransition : true, //Enable fade transition in browsers capable of it?

//Use true or false or object containing boolean values or tag name for separate primary load areas

 writeNumberButtons : true, //Also requires element with id of load_area_idNum ex: <div id="loadareaNum"></div>
 writeControlButtons : true, //Also requires element with id of load_area_idControl ex: <span id="loadareaControl"></span>
 
 useButtons : true, //Allows choosing individual Control buttons by numbers, ex:  useButtons : {loadarea: {4 : true, 5 : true}},
 //Works off array: 0 = 'Next', 1 = 'Previous', 2 = 'First', 3 = 'Last', 4 = 'Run', 5 = 'Stop' - otherwise just set to true

 enableSlideShow : false, //Enable slide show(s) use - true/false or {load_area : delay}
 startSlideShow : false,
 swapControlVals : true, //true false or object with boolean values - should running/paused state affect buttons?
//Below three (only valid if slide show running) may use pause or stop, if a load area is not mentioned, nothing will happen for these cases
 slideHoverBehavior : 'stop', //What happens onmouseover of larger images if slide show is running
 slideTriggerBehavior : 'pause', //What happens when triggers are activated if slide show is running
 slideNumberButtonsBehavior : 'stop', //What happens when numbered buttons are clicked if slide show is running

//Set to true only if using lightbox 2.04a add on and lightbox groups
 enableLightBoxGroups : false, //Enable writing out all lightbox group links (lightbox[groupname]) links to a display none div? (true/false only)

       ///////////// Edit Only If You Know What You Are Doing /////////////

 makeAlt : true,
 navSlideTitles : ['Next', 'Previous', 'First', 'Last', 'Run', 'Stop'], //array of allowed titles for navigating and/or slide show control elements
 numDes : 'Image ', //allowed prefix for titles for navigating via enumerating triggers (Image #);
 numPre : '', //prefix for __(Image number )__# of #
 numQnt : ' / ', //bridge for Image number # __(of)__ #
 pauseValue : 'Paused', //value/text for 'Run' control element when slide is paused
 runningValue : 'Running', //value/text for 'Run' control element when slide is running
 stoppedValue : 'Stopped', //value/text for 'Stop' control element when slide is stopped
 enableNavSlide : true, //Allow for "Image #", "Next", "Previous", "First", "Last", "Run" and/or "Stop" elements for primary load area id(s)?

       ///////////// Stop Editing /////////////

 fadecapable : false, //property to hold result of test for generic style opacity (fade) support
 iefadecapable : false, //property to hold result of test for ie style filter opacity support
 preloadedimages : [], //array to hold preloaded enlarged images
 register : {}, //object to hold nav/slide class/id names
 paired : {}, //object to hold paired class/id trigger pairings
 slidestarted : {},
 populated : {},
 boolObj : function (v, p){v = this[v]; return p == 'not_what_you_are_looking_for'? false : (v === true || (typeof v == 'object' &&
 typeof v[p] != 'undefined' && v[p]));}, //returns true if fed a precise boolean true or an object with a 'truthy' property p
 parentAtt : function(el, at, t, re){ //determines if el or a parent has an attribute that satisfies a test
  re = re? new RegExp(re) : new RegExp();
  if(t[el[at].replace(re, '')]) return el; //returns the element with that attribute, 
  while (el.parentNode){
   if (el.parentNode[at] && t[el.parentNode[at].replace(re, '')])
    return el.parentNode; //it's parent that has it, or
   el = el.parentNode;
  }
  el = {}; el[at] = 'not_what_you_are_looking_for';
  return el; //an object with that attribute as a property with the value out of range
 },

 testforfilters : function(){
  /*@cc_on @*/
  /*@if(@_jscript_version >= 5)
  this.ie = navigator.appVersion.replace(/^.*MSIE (\d+\.\d+).*$/, '$1');
  if(this.enableTransition && this.ie >= 5.5)
   try {
    this.iefadecapable = document.documentElement.filters;
    this.iefadestring = 'progid:DXImageTransform.Microsoft.Alpha(opacity='; //IE 5.5+ specific opacity filter string
   } catch(e){this.iefadecapable = null}
  else this.iefadecapable = null;
  @end @*/
  if(this.enableTransition && this.iefadecapable === false){
   var ft = function(o){return typeof document.documentElement.style[o] == 'string'? o : false;};
   for (var f = ['-Ktml-Opacity', '-Moz-Opacity', 'opacity'], i = f.length - 1; i > -1; --i){
    this.ft = ft(f[i]);
    if(this.ft){
     this.fadecapable = true;
     break;
     }
   }
  }
 },

 byClass : function(n, el){
  el = el || document;
  if(el.getElementsByClassName && document.getElementsByClassName('a').constructor == Object)
   return el.getElementsByClassName(n);
  var t = el.all || el.getElementsByTagName('*');
  for (var r = new RegExp('\\b' + n + '\\b'), a = [], i = t.length - 1; i > -1; --i)
   if(r.test(t[i].className)) a[a.length] = t[i];
  return a;
 },

 populate : function(t, ext){ //parse the attribute values of a trigger for populating its load area(s)
  var s = t.rel.split('::'), p = t.rev.split('::')[0], vfs = viewfadeslide, tx = null, lt = null, l = null,
  a = null, n = ext? 3 : 1, f, tran = vfs.boolObj('enableTransition', p), hide = vfs.boolObj('hideImgMouseOut', p),
  trancapable = vfs.fadecapable || vfs.iefadecapable, im = document.createElement('img');
  if(!ext){
   for(var ccc = 0, re = new RegExp(' *' + p + 'Active'), cc = 1, at = document.getElementsByTagName('a'), i = 0; i < at.length; ++i){
    if(at[i] == t) ccc = cc;
    if(at[i].rev.split('::')[0] == p)
     at[i].className = at[i].className.replace(re, ''), ++cc;
   }
   t.className += ' ' + p + 'Active';
   for (var cre = new RegExp('^' + vfs.numDes + '\\d+'), ct = vfs.byClass(p), i = ct.length - 1; i > -1; --i){
    if(cre.test(ct[i].title)) ct[i].className = ct[i].className.replace(re, '');
    if(ct[i].title == vfs.numDes + ccc) ct[i].className += ' ' + p + 'Active';
   }
  }
  s = ext? s.slice(2) : t.rev.split('::');
  var lp = document.getElementById(s[0]);
  if(!lp.getElementsByTagName('td')[0]){
   lt = document.createElement('table');
   l = document.createElement('td');
   lt.style.borderCollapse = 'collapse';
   lt.style.width = lt.style.height = l.style.width = l.style.height = '100%';
   l.style.padding = l.style.margin = 0;
   l.style.textAlign = 'center';
   l.style.verticalAlign = 'middle';
   lt.appendChild(document.createElement('tbody'));
   lt.firstChild.appendChild(document.createElement('tr'));
   lt.firstChild.firstChild.appendChild(l);
   lp.appendChild(lt);
   if(tran && trancapable) {
    lp.style.position = 'relative';
    lt.style.position = 'absolute';
    lp.appendChild(lt.cloneNode(true));
   }
  }

  if(vfs.ie && vfs.ie == 6)
   for(var i = 0; i < lp.getElementsByTagName('table').length; ++i)
    lp.getElementsByTagName('table')[i].style.height = lp.currentStyle.height;

  lt = lp.getElementsByTagName('table')[lp.getElementsByTagName('table').length - 1];
  l = lp.getElementsByTagName('td')[lp.getElementsByTagName('td').length - 1];

  var lb = lp.getElementsByTagName('table')[1]? lp.getElementsByTagName('table')[0] : null;
  if(lb) {
   var lc = lp.getElementsByTagName('td')[0];
   lt.style.zIndex = 1;
  }

  if (!ext && vfs.boolObj('enableCount', p)){
   var cnt = [], ctxt = [' ' + (vfs.numPre[p] || vfs.numPre), ccc, ( vfs.numQnt[p] || vfs.numQnt), cc - 1];
   if(lp.lastChild.className != p + 'Count'){
    for(var j = 0; j < 4; ++j){
     cnt[j] = document.createElement('span');
     cnt[j].className = j? p + 'Count_' + j : p + 'Count';
     cnt[j].appendChild(document.createTextNode(ctxt[j]));
     if(j) cnt[0].appendChild(cnt[j]);
    }
    cnt = cnt[0];
   } else {
    cnt = lp.lastChild;
    cnt.childNodes[1].firstChild.nodeValue = ctxt[1];
    cnt.childNodes[3].firstChild.nodeValue = ctxt[3];
   }
  }

  var emptyLoadArea = function(){
   while (l.lastChild) l.removeChild(l.lastChild);
   while (lt.nextSibling && (cnt && !hide? lt.nextSibling.className != p + 'Count' : 1)) lp.removeChild(lt.nextSibling);
   if(lb && hide && lc.getElementsByTagName('img')[0])
    lc.removeChild(lc.getElementsByTagName('img')[0]);
  };

  im.alt = vfs.boolObj('makeAlt', p)? (t.name.split('::')[ext? 1 : 0] || t.name || '') : '';
  if(vfs.boolObj('makeTitle', p))
  im.title = t.name.split('::')[ext? 1 : 0] || t.name || '';
  im.style.border = 'none';
  im.style.visibility = 'hidden';

  if (!ext && /mouseover/.test(t.rel) && vfs.boolObj('disableOnClick', p)) //kill onclick event for mouseover triggers if so confgured
   if (!t.onclick || !t.onclick.killed_for_viewfadeslide) {
    t.onclick = function(){return false;};
    t.onclick.killed_for_viewfadeslide = true;
  }

  vfs.boolAdd(hide, t, 'mouseout', emptyLoadArea, ext);

  if (vfs.boolObj('enableCaption', p)){
   tx = document.createElement('span');
   tx.className = p + 'Caption';
   if ((ext && s[2] && s[2] != '') || (!ext && t.title && t.title != '')) //if there actually is a caption (title attribute, or as paired value)
    tx.appendChild(document.createTextNode(ext? s[2] : t.title));
   else
    tx.appendChild(document.createTextNode('\xa0'));
  }
  
  if (lb){ //Is this an IE browser that supports filters or a browser that fades & is this feature enabled?
   if (l.getElementsByTagName('img')[0]){
    if(!lc.getElementsByTagName('img')[0]){lc.appendChild(document.createElement('img'))}
    lc.getElementsByTagName('img')[0].src = l.getElementsByTagName('img')[0].src;
   }
   vfs.iefadecapable? lt.style.filter = vfs.iefadestring + 0 +')' : lt.style[vfs.ft] = 0;
  }
  
  vfs.boolAdd(true , im, 'load', function(){ //When enlarged image has completely loaded
   im.style.visibility = '';
   if (lb) vfs.fadein(lt);
   if (tx) cnt && cnt == lp.lastChild? lp.insertBefore(tx, lp.lastChild) : lp.appendChild(tx);
   if (cnt && cnt != lp.lastChild) lp.appendChild(cnt);
  }, false, true);

  vfs.boolAdd(true , im, 'error', function(){ //If an error has occurred while loading the image to show
   im.style.visibility = '';
   if(lb) vfs.iefadecapable? im.style.filter = vfs.iefadestring + 100 + ')' : im.style[vfs.ft] = 1;
  }, false, true);

  emptyLoadArea();

  if (s[n]){ //if there is a link for the larger image
   a = document.createElement('a');
   a.href = s[n];
   if(s[n + 1] && typeof Lightbox != 'undefined' && Lightbox.version == '2.04a' && /^lightbox/.test(s[n + 1])){ //Lightbox v2.04a tie-in
    a.rel = s[n + 1];
    if(s[n + 2]) a.title = s[n + 2];
    if(s[n + 3]) a.rev = s.slice(n + 3).join('::');
   }
   else if (s[n + 1] && /^lightbox/.test(s[n + 1])) alert('A \'target\' of ' + s[n + 1] + ' requires Lightbox v2.04a properly installed');
   else if (s[n + 1] || s[n + 2]){ //if link is targeted and/or perhaps has other specifications
    f = function(e){
     var win = window.open(s[n], s[n + 1], s[n + 2] || '');
     if(s[n + 3])
      win.focus();
     if(e && e.preventDefault)
      e.preventDefault();
     return false;
    };
    vfs.boolAdd(true, a, 'click', f, false, true);
   }
   l.appendChild(a);
  }

  (a || l).appendChild(im);
  im.src = ext? s[1] : t.href;

  if(!ext && t.rel.split('::').length > 3) //if this is a trigger with paired load areas & larger images,
   vfs.populate(t, 1) //and it's second one hasn't been processed yet, go again with the second one
 },

 fadein : function(i){ //generic opacity fade in
  var vfs = viewfadeslide;
  if(vfs.fadecapable)
   if(i.style[vfs.ft] < 0.99){
    i.style[vfs.ft] = parseFloat(i.style[vfs.ft]) + 0.03;
    setTimeout(function(){vfs.fadein(i);}, 30);
   } else i.style[vfs.ft] = 0.9999;
  else if(vfs.iefadecapable)
   if(i.style.filter.replace(/\D/g, '') < 100){
    i.style.filter = vfs.iefadestring + (parseInt(i.style.filter.replace(/\D/g, '')) + 3) + ')';
    setTimeout(function(){vfs.fadein(i);}, 30);
   } else i.style.filter = vfs.iefadestring + '100)';
 },

 clickOver : function(e){ //front end to determine what to do with onmouseover & onclick events
  e = e || window.event; viewfadeslide.preload(e); //run preload function to take care of any updating to the page/script that may be needed
  var t = e.target || e.srcElement || null, re = null, k = e.type || null, vfs = viewfadeslide, u;

  if(t && k){ //if we have an event target and an event type
   if(k == 'click' && //if this is a click on an allowed nav/slide element
   vfs.boolObj('enableNavSlide', vfs.parentAtt(t, 'className', vfs.register, ' .*').className.replace(/ .*/, '')))
    return vfs.slide(e, vfs.parentAtt(t, 'className', vfs.register, ' .*'));
   else if(k == 'mouseover' && vfs.boolObj('enableSlideShow', (u = vfs.parentAtt(t, 'id', vfs.register)).id) &&
   vfs.csb('slideHoverBehavior', u.id))
     if(vfs.csb('slideHoverBehavior', u.id) == 1) //pause sliding if mouseover slideshow primary load area
      vfs.slidePause(u.id, u);
     else vfs.stopSlide(u.id); //stop sliding if mouseover slideshow primary load area
   else if(k == 'mouseover' && vfs.boolObj('enableSlideShow', vfs.paired[(u=vfs.parentAtt(t, 'id', vfs.paired)).id]) &&
   vfs.csb('slideHoverBehavior', vfs.paired[u.id]))
     if(vfs.csb('slideHoverBehavior', vfs.paired[u.id]) == 1) //pause sliding if mouseover slideshow paired load area
      vfs.slidePause(vfs.paired[u.id], u);
     else vfs.stopSlide(vfs.paired[u.id]); //stop sliding if mouseover slideshow paired load area
   re = new RegExp('^vfsimage::' + k); //set regExp to help further evaluate trigger
   t = t.rel && re.test(t.rel)? t : t.parentNode? t.parentNode : null;
  }
  if(!t || !k || !t.rel || !re || !re.test(t.rel)) //if true, we have no trigger or a trigger unrelated to this script
   return undefined;

  if(vfs.boolObj('enableSlideShow', (u = t.rev.split('::')[0]))) //if we were sliding & activated a trigger of that slide
   if(vfs.csb('slideTriggerBehavior', u))
    if(vfs.csb('slideTriggerBehavior', u) == 1)
     vfs.slidePause(u, t); //pause or
    else vfs.stopSlide(u); //stop sliding

  vfs.populate(t); //if we've gotten this far, get to work displaying the larger image

  if(k == 'click'){ //if a valid click trigger was clicked, don't execute the href of the trigger
   if(e.preventDefault)
    e.preventDefault();
   return false;
  } return undefined; //otherwise let other code or default behavior decide what to do about a click
 },

 slide : function(e, t, ttl){ //parse nav/slide ("Next", "Previous", "First", "Last", "Start", "Stop", or "Image #") elements
  var im, ta = [t.className.replace(/ .*/, ''), t.title], //break element into its relevant attributes as an array
  vfs = this, re = new RegExp(' *' + ta[0] + 'Active'), cre = vfs.numDes + '\\d+', nst = vfs.navSlideTitles, co = false;
  if(!new RegExp('^(' + cre + ')|(' + nst.join(')|(') + ')$').test(ta[1])){ //error alert for erroneously classed elements conflicting with nav/slide
   alert('"' + ta[0] + '" classed elements are reserved for Thumbnail II Viewer nav/slide\n' +
   'control and require a title attribute of "' + vfs.numDes + '#", "' + nst.join('", "').replace(/,([^,]+)$/, ' or$1') + '".');
   return undefined;
  } cre = new RegExp('^' + cre);
  if(ta[1] == nst[4]) vfs.startSlide(ta[0]);
  else if(ta[1] == nst[5]) vfs.stopSlide(ta[0]);
  else {
   if(e && e.type == 'click')
    if(new RegExp('^(' + nst.slice(0, 4).concat(nst.slice(5)).join(')|(') + ')$').test(ta[1])) vfs.stopSlide(ta[0]);
    else if(cre.test(ta[1]) && vfs.csb('slideNumberButtonsBehavior', ta[0]))
     if(vfs.csb('slideNumberButtonsBehavior', ta[0]))
      if(vfs.csb('slideNumberButtonsBehavior', ta[0]) == 1)
       vfs.slidePause(ta[0], t); //pause sliding if number button/element clicked and so configured
      else vfs.stopSlide(ta[0]); //stop sliding if number button/element clicked and so configured
   if(cre.test(ta[1])) co = ta[1].replace(new RegExp(vfs.numDes), '') - 1;
   for(var c = 0, el = document.getElementById(ta[0]), a = document.getElementsByTagName('a'), imt = [], i = 0; i < a.length; ++i)
    if(a[i].rev.split('::')[0] == ta[0]){ //if element is classed as nav/slide for a load area
     if (!el) return undefined; im = el.getElementsByTagName('img')[el.getElementsByTagName('img').length -1];
     if(co===false && im && im.src == a[i].href)
      c = imt.length; //with above line gets current image trigger number from this group or remains 0 if none
     imt[imt.length] = a[i]; //collecting an array of triggers for this load area
    } if (!el) return undefined;
   c = ta[1] == nst[3]? imt.length - 1 : !im? 0 : ta[1] == nst[0]? c + 1 : ta[1] == nst[1]? c - 1 : 0;
   c = c < 0? c + imt.length : c >= imt.length? c - imt.length : c; //with above line determine which trigger for this load area is wanted
   vfs.populate(imt[(co!==false? co : c)]); //and fire it
  }
   if(co===false)
    for (var ct = vfs.byClass(ta[0]), i = ct.length - 1; i > -1; --i){
     if(!cre.test(ct[i].title)) ct[i].className = ct[i].className.replace(re, '');
     if(ct[i].title == (ttl? ttl : ta[1])) ct[i].className += ' ' + ta[0] + 'Active';
   }
  if(e && e.preventDefault) //with below two lines, since all nav/slide is done onclick, stop the default click behavior (if any) of the element
   e.preventDefault();
  return false;
 },

 ieAttach : function (el, k, f){ //for attachEvents in IE which require 'this' keyword to refer to attached element
  var t = function(){return f.apply(el)};
  el.attachEvent(k, t);
 },

 boolAdd : function (b, el, k, f, ext, i){ //viewfadeslide's addEventListener/attachEvent engine
  if(b){
   ext = typeof ext == 'string'? ext : ext? 'ext' : '';
   if(!i && !el['on' + k]) el['on' + k] = function(){return;};
   if(i || !el['on' + k]['altered_for_viewfadeslide' + ext]){
    if(el.addEventListener)
     el.addEventListener(k, f, false);
    else if(el.attachEvent)
     this.ieAttach(el, 'on' + k, f);
    if(!i) el['on' + k]['altered_for_viewfadeslide' + ext] = true;
   }
  }
 },

 truegroups : function(ar){
  if(typeof Lightbox == 'undefined' || Lightbox.version != '2.04a') return;
  var tg = 'truegroups_for_vfslight';
  if(!ar){
   var re = new RegExp('^lightbox\\[[^\\]]+\\]$');
   for(var l = {}, a = document.getElementsByTagName('a'), i = 0; i < a.length; ++i)
    if(/^vfsimage::/.test(a[i].rel)){ //a thumbnail link
     if(re.test(a[i].rev.split('::')[2])){ //with regular lightbox group activation
      ar = a[i].rev.split('::').slice(1);
      l[ar[1]]? l[ar[1]].push(ar) : l[ar[1]] = [ar];
     }
     if(re.test(a[i].rel.split('::')[6])){ //with paired lightbox group activation
      ar = a[i].rel.split('::').slice(5);
      l[ar[1]]? l[ar[1]].push(ar) : l[ar[1]] = [ar];
     }
    }
   if(!$(tg)){
    var d = document.createElement('div'); d.style.display = 'none';
    d.id = tg; document.body.insertBefore(d, document.body.firstChild);
   }
   for (var p in l) this.truegroups(l[p]);
  } else {
   for(var a, i = 0; i < ar.length; ++i){
    a = document.createElement('a');
    a.href = ar[i][0];
    ar[i][0] = a.href;
    for (var addit = true, ea = $(tg).getElementsByTagName('a'), j = ea.length - 1; j > -1; --j){
     if(ea[j].href == a.href && ea[j].rel == ar[i][1]){
      addit = false; break;
     }
    }
    if(addit){
     a.rel = ar[i][1];
     a.title = ar[i][2] || '';
     if(ar[i][3]) a.rev = ar[i].slice(3).join('::');
     $(tg).appendChild(a);
    } else a = null;
   }
   for (var j = ea.length - 1; j > -1; --j){
    ea[j].className = ea[j].rel == ar[0][1]? 'ffd' : '';
    for (var i = ar.length - 1; i > -1; --i)
     if(ea[j].href == ar[i][0]) ea[j].className = '';
    }
   for (var ffd = viewfadeslide.byClass('ffd', $(tg)), i = ffd.length - 1; i > -1; --i)
    $(tg).removeChild(ffd[i]);
  }
 },

 startSlide : function(p, e){
  var vfs = viewfadeslide, slideIt = function(p){
   if(vfs[p + 'paused']){
    vfs[p + 'timer'] = setTimeout(function(){slideIt(p);}, 300);
    return;
   }
   vfs.slide(null, vfs[p + 'slider'], vfs.navSlideTitles[4]);
   vfs[p + 'timer'] = setTimeout(function(){slideIt(p);}, typeof vfs.enableSlideShow[p] == 'number'? vfs.enableSlideShow[p] : 3000);
  }, c = vfs.byClass(p);
  if(!vfs[p + 'slider']){
   vfs[p + 'slider'] = document.createElement('span');
   vfs[p + 'slider'].className = p;
   vfs[p + 'slider'].title = vfs.navSlideTitles[0];
  }
  if(!vfs[p + 'timer']){
   if(vfs.boolObj('swapControlVals', p)){
    vfs.swapValTex(c, vfs.navSlideTitles[4], vfs.runningValue);
    vfs.swapValTex(c, vfs.navSlideTitles[5]);
   }
   if(e && e.type == 'load' || e === true){
    vfs[p + 'timer'] = setTimeout(function(){slideIt(p);}, typeof vfs.enableSlideShow[p] == 'number'? vfs.enableSlideShow[p] : 3000);
    if(vfs.boolObj('enableSlideShow', p))
     for (var b = vfs.boolObj('startSlideShow', p), re = new RegExp(' *' + p + 'Active'), c = vfs.byClass(p), i = c.length - 1; i > -1; --i)
      if(c[i].title == vfs.navSlideTitles[(b? 4 : 5)] && !re.test(c[i].className)) c[i].className += ' ' + p + 'Active';
   } else slideIt(p);
  }
 },

 stopSlide : function(p){
  var vfs = viewfadeslide, c = vfs.byClass(p);
  if(!vfs[p + 'timer']) return;
  clearTimeout(vfs[p + 'timer']);
  vfs[p + 'timer'] = false;
  for (var re = new RegExp('^' + vfs.numDes + '\\d+$'), cre = new RegExp(' *' + p + 'Active'), i = c.length - 1; i > -1; --i){
   if(!re.test(c[i].title)) c[i].className = c[i].className.replace(cre, '');
   if(c[i].title == vfs.navSlideTitles[5]) c[i].className += ' ' + p + 'Active';
  }
  if(vfs.boolObj('swapControlVals', p)){
   vfs.swapValTex(c, vfs.navSlideTitles[4]);
   vfs.swapValTex(c, vfs.navSlideTitles[5], vfs.stoppedValue);
  }
 },

 csb : function(prop, key){
  var vfs = viewfadeslide;
  return vfs[prop] == 'pause' || vfs[prop][key] && vfs[prop][key] == 'pause'? 1 :
  vfs[prop] == 'stop' || vfs[prop][key] && vfs[prop][key] == 'stop'? 2 : 0;
 },

 swapValTex : function(els, o, n){
  n = n || o;
  for (var i = els.length - 1; i > -1; --i)
   if(els[i].nodeName == 'INPUT' && els[i].title == o) els[i].value = n;
   else if(els[i].firstChild && els[i].title == o) els[i].firstChild.nodeValue = n;
 },

 slidePause : function(p, el){
  var vfs = viewfadeslide;
  if(el)
   vfs.boolAdd(true, el, 'mouseout', function(){vfs.slideResume(p);}, 'pause');
  if(vfs[p + 'timer'] && vfs.boolObj('swapControlVals', p))
   vfs.swapValTex(vfs.byClass(p), vfs.navSlideTitles[4], vfs.pauseValue);
  if(vfs.slideResume[p]) clearTimeout(vfs.slideResume[p]);
  vfs[p + 'paused'] = true;
 },

 slideResume : function(p){
  var vfs = viewfadeslide;
  if (vfs.boolObj('swapControlVals', p) && vfs[p + 'timer']) vfs.swapValTex(vfs.byClass(p), vfs.navSlideTitles[4], vfs.runningValue);
  vfs.slideResume[p] = setTimeout(function(){vfs[p + 'paused'] = false;}, 500);
 },

 makeNum : function(p){
  if(document.getElementById(p + 'Num')){
   var e = document.getElementById(p + 'Num'), vfs = viewfadeslide, tn = vfs.writeNumberButtons;
   tn = tn[p] && tn[p] !== true? tn[p] : 'input';
   for(var ip, r = new RegExp('^' + p + ':'), c = 1, a = document.getElementsByTagName('a'), i = 0; i < a.length; ++i)
    if(r.test(a[i].rev) || a[i].rev == p)
     if(!vfs.byClass(p, e)[c - 1]){
      ip = document.createElement(tn);
      if(tn.toLowerCase() == 'input') ip.type = 'button';
      ip.className = p + (c == 1? ' ' + p + 'Active' : '');
      if(tn.toLowerCase() == 'a') ip.href = 'javascript: ' + vfs.numDes.replace(/ /g, '_') + c + '()';
      tn.toLowerCase() == 'input'? ip.value = c : ip.appendChild(document.createTextNode(c));
      ip.title = vfs.numDes + c++;
      e.appendChild(ip);
      e.appendChild(document.createTextNode(' '));
    } else c++;
   var ips = e.getElementsByTagName(tn);
   while(ips.length > c - 1)
    e.removeChild(ips[ips.length - 1]);
  }
 },

 makeControl : function(p){
  if(document.getElementById(p + 'Control')){
   var vfs = viewfadeslide, e = document.getElementById(p + 'Control'), tn = vfs.writeControlButtons,
   n = vfs.navSlideTitles, g = vfs.boolObj('enableSlideShow', p) && vfs.boolObj('startSlideShow', p) || vfs[p + 'timer'], s = vfs.boolObj('swapControlVals', p);
   tn = tn[p] && tn[p] !== true && tn[p].toLowerCase() != 'button'? tn[p] : 'input';
   for(var ip, v, i = 0; i < n.length - (vfs.boolObj('enableSlideShow', p)? 0 : 2); ++i)
    if(!vfs.byClass(p, e)[i]){
     ip = document.createElement(tn);
     ip.style.display = !vfs.useButtons[p] || vfs.useButtons[p] && vfs.useButtons[p][i]? '' : 'none';
     if(tn.toLowerCase() == 'input') ip.type = 'button';
     ip.className = g && i == 4 || !g && i == 5? p + ' ' + p + 'Active' : p;
     if(tn.toLowerCase() == 'a') ip.href = 'javascript: ' + n[i] + '()';
     v = g && s && i == 4? vfs.runningValue : !g && s && i == 5? vfs.stoppedValue : n[i];
     tn.toLowerCase() == 'input'? ip.value = v : ip.appendChild(document.createTextNode(v));
     ip.title = n[i];
     e.appendChild(ip);
     e.appendChild(document.createTextNode(' '));
   }
  }
 },

 resetDefaults : function(p){
  var vfs = viewfadeslide;
  vfs.populated[p] = false;
  vfs.slidestarted[p] = false;
  if(vfs.slideResume[p]){
   clearTimeout(vfs.slideResume[p]);
   vfs.slideResume[p] = false;
  }
  vfs[p + 'paused'] = false;
  if(vfs[p + 'timer']){
   clearTimeout(vfs[p + 'timer']);
   vfs[p + 'timer'] = false;
  }
 },

 preload : function(e){ //runs onload and on all other significant events for this script to set/upgrade preloads and element event observation
  e = e || window.event; var k = e.type;
  if(k == 'keydown' && (window.opera? !/^9|(16)$/.test(e.keyCode) : e.keyCode != 9)) return; //if keydown & not a relevant key
  var a = document.getElementsByTagName('a'), vfs = viewfadeslide, load = k == 'load';
  if(load){ //set initial values that either need not change, or that need not change unless event is not onload
   if(vfs.config) //if separate config present, import it
    for(var p in vfs.config)
     vfs[p] = vfs.config[p];
   vfs.testforfilters();
   var loadit = true, eloadit = true; //set values to preload all images first run (onload)
  }
  for (var rel, rev, ext, f, c = vfs.preloadedimages.length, i = a.length - 1; i > -1; --i)
   if(/^vfsimage::/.test(a[i].rel)){ //is this a link configured for this script?
    rev = a[i].rev.split('::')[0];
    vfs.register[rev] = true; //register loadarea as one to be used for this script
    if(a[i].rel.split('::').length > 3) //if this is a paired trigger
     vfs.paired[ext = a[i].rel.split('::')[2]] = rev; //store a reference to its primary trigger's load area
    if(!window.opera){
     f = function(){ //add onfocus to mouseover triggers
      var l = this.rev.split('::')[0];
      if(vfs.csb('slideTriggerBehavior', l))
       if(vfs.csb('slideTriggerBehavior', l) == 1){
        vfs.slidePause(l);
        vfs.boolAdd(true, this, 'blur', function(){vfs.slideResume(l);});
       } else vfs.stopSlide(l);
      vfs.populate(this);
      };
     vfs.boolAdd(/^vfsimage::mouseover/.test(a[i].rel), a[i], 'focus', f);
    }
    if(!load) //if not onload, before adding a preload, make sure it hasn't already been preloaded
     for(var loadit = true, eloadit = true, j = 0; j < c; ++j){
      if(a[i].href == vfs.preloadedimages[j].src)
       loadit = false;
      if(a[i].rel.split('::').length > 3 && a[i].rel.split('::')[3] == vfs.preloadedimages[j].src)
       eloadit = false;
     }
    if(loadit){ //if onload, or this image hasn't been preloaded
     vfs.preloadedimages[c] = new Image();
     vfs.preloadedimages[c++].src = a[i].href;
    }
    if(a[i].rel.split('::').length > 3 && eloadit){ //if there is a paired image & the event is onload, or it hasn't been preloaded
     rel = a[i].rel.split('::');
     vfs.preloadedimages[c] = new Image();
     vfs.preloadedimages[c].src = rel[3];
     rel[3] = vfs.preloadedimages[c++].src;
     a[i].rel = rel.join('::'); //with above line, set actual image URI back to the rel attribute for possible future testing
    }
   } // end "is this a link configured for this script?"
   for(var p in vfs.register){
    if(document.getElementById(p) && !document.getElementById(p).getElementsByTagName('td')[0])
     vfs.resetDefaults(p); //if imported content has been re-imported, reset all its flags
    if(vfs.boolObj('populateWithFirst', p)  && !vfs.populated[p])
     for(var i = 0; i < a.length; ++i) //find its first trigger & execute it
      if(p == a[i].rev.split('::')[0]){
       vfs.populate(a[i]);
       vfs.populated[p] = true;
       break; //and stop looking
      }
    if(vfs.boolObj('writeNumberButtons', p)) vfs.makeNum(p);
    if(vfs.boolObj('writeControlButtons', p)) vfs.makeControl(p);
    if(vfs.boolObj('enableSlideShow', p) && !vfs.slidestarted[p])
     if (vfs.boolObj('startSlideShow', p)) vfs.startSlide(p, true);
     else if (!vfs.boolObj('startSlideShow', p) && vfs.boolObj('swapControlVals', p))
      vfs.swapValTex(vfs.byClass(p), vfs.navSlideTitles[5], vfs.stoppedValue);
    vfs.slidestarted[p] = true;
   }
  if(vfs.enableLightBoxGroups) vfs.truegroups();
 },
 
 init : function(){ //attach/add all relevant event observations only if they haven't already been attached/added
  var e = [['load', 'preload'], ['keydown', 'preload'], ['mouseover', 'clickOver'], ['click', 'clickOver']];
  for (var i = e.length - 1; i > -1; --i)
   this.boolAdd(!this.init.run, (i? document : window), e[i][0], this[e[i][1]], false, true);
  this.init.run = true;
 }
};

viewfadeslide.init();