/****

F a d e A r o u n d -

'Highlights' a hovered image or other element in a specified set, by fading the others to a
specified level.

Produces single-image rollover button groups.


Instructions
~~~~~~~~~~~~
Installation
------------
Save this text/file as: fadearound.js

Include the script in your document by placing the following tags in the <head> section:

 <script type='text/javascript' src='fadearound.js'></script>

(Add a path to the filename if necessary)

The involved elements in a fade group can be identified either by their individual ID attributes or
via a common class name. To fade only some elements that share a common CSS class, in your HTML add
a second name to the class of each element in the sub-group, and specify that second name when
initialising the script as shown in the examples below.

Configuration
-------------
The script is configured in a single line of code, using the syntax shown in the examples given
below.
The first parameter is a quoted string containing none or more of the following configuration
options:

 fade = n   | Where n is the final percentage opacity.

 preset = n | Where n is the 0-based index of the element to be preset.

 lock       | Enables highlight locking on click; automatically invoked when preset is used.


The configuration code must be inserted somewhere below all of the involved elements.

 This example highlights the hovered element in the group with IDs 'roll1' - 'roll5', by fading the
 rest to the default 50% opacity. No preset or locking is enabled:

 <script type='text/javascript'>

  new FadeAround("", "roll1", "roll2", "roll3", "roll4", "roll5"); // <- No comma after last parameter

 </script>

 This example configures the same set of elements to fade to 30% opacity and enables locking.

 <script type='text/javascript'>

  new FadeAround('lock fade=30', "roll1", "roll2", "roll3", "roll4", "roll5"); // <- No comma after last parameter

 </script>

 This example highlights any element with the CSS class 'rollElements' (or any class name that
 includes this individual word), by fading the rest to 50% opacity. The fifth element in the group
 (index 4) will be locked at startup; consequently locking on click is enabled for the group:

 <script type='text/javascript'>

  new FadeAround("fade=50, preset=4", "rollElements"); // <- No comma after last parameter

 </script>

Repeat for any other independent element groups.

** There's nothing else to do **

Pre-setting Via Querystring Parameter
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In addition to the pre-setting method described above, an element in a group can be pre-set by 
specifying its ID as a querystring parameter in the URL.

Example: A fade group on http://mysite.com includes an element with the ID "roll3", which is to be
pre-set.

 http://mysite.com?fadearoundpreset=roll3

To preset more than one group on the same page, just separate multiple IDs with the | character: 
 
 http://mysite.com?fadearoundpreset=roll3|link2

NOTE - When an element is enclosed within a link, the specified ID should apply to the element, 
rather than the link itself.

Fading Rollover Buttons
~~~~~~~~~~~~~~~~~~~~~~~
Single-image rollovers can be produced simply by enclosing each button image within an appropriate
link. Instead of swapping images, the hovered button remains at full opacity. This arrangement
allows the fade effect to be triggered by keyboard navigation (Usually the Tab key or Shift+Arrows).

Fading Links
~~~~~~~~~~~~
Please note that under strict <doctype>s, I.E. does not set opacity to text links, and links must be
styled with height and width.

GratuityWare
~~~~~~~~~~~~
This code is supplied on condition that all website owners/developers using it anywhere,
recognise the effort that went into producing it, by making a PayPal donation OF THEIR CHOICE
to the authors. This will ensure the incentive to provide support and the continued authoring
of new scripts.

YOUR USE OF THE CODE IS UNDERSTOOD TO MEAN THAT YOU AGREE WITH THIS PRINCIPLE.

You may donate at www.scripterlative.com, stating the URL to which the donation applies.

*** DO NOT CHANGE ANYTHING BELOW ****/

function FadeAround(/* (C)Scripterlative.com */)
{
 /* Free download and instructions: http://scripterlative.com?fadearound */

 this.data=[]; this.solidElem = null; this.timer = null; this.limit = 40; this.step = 10; this.canLock = false; this.lockUsed = false; this.period=40; this.constructor.auth = {logged:2};

 this.init=function()
 {
  var args=FadeAround.arguments, classExp, offset = 1, len, bon=0xF&0, eHandler = null, outDelay = null,
      setHovered = false, usingClass = false, classArray = [], eCollection, fadeArg, presetArg = null,
      presetData = decodeURIComponent(location.search).match( /[\?\&]fadearoundpreset=([^&]+)(&|$)/i );

  this.canLock = /\block\b/i.test(args[0]); this.cont();
  
  if( typeof args[0] !== 'string')
   alert('Error: The first parameter must be a quoted string - ['+args[1]+']');
  else
   if( !(fadeArg=args[0].match( /\bfade\s*=\s*(\S+)\%*\b/i )) )
    this.limit = 50;
   else
    if( isNaN( this.limit=Math.abs( Math.floor( Number( fadeArg[1] ) ) ) ) )
    {
     this.limit = 50;
     alert('Specified fade point "'+fadeArg[1]+'" did not evaluate to a number in the range 0-100');
    }

  this.step = Math.round( (100-this.limit)/5 );

  if(args.length==2)
  {
   classExp = new RegExp("\\b"+args[1]+"\\b");
   usingClass=true;
   offset=0;
   eCollection = document.getElementsByTagName('*');

   for(var i = 0, len = eCollection.length; i < len; i++)
    if( eCollection[i].className.match( classExp ) )
     classArray.push( eCollection[i] );

   if(classArray.length == 0)
    alert('Class name "' +args[1]+ '" not found.');
  }

  for(var i=0, idx=offset, len = usingClass ? classArray.length : args.length-offset, store; i < len && this.bon; i++, idx++)
  {
   store = this.data[ i ] = {};
   
   try
   {
    store.locked = false;
    store.holder = usingClass ? classArray[i] : (document.images[args[idx]] || document.getElementById(args[idx]) );
    store.hoverElem = store.holder.parentNode.nodeName=='A' ? store.holder.parentNode
                                                            : store.holder;
    store.opacLevel = 100;
   }
   catch(e){ alert('Image placeholder or element "'+args[idx]+'" not found.'); break;}

   this.addToHandler(store.hoverElem, 'onmouseover', eHandler=(function(obj, imgData)
   {
    return function()
    {
     clearTimeout( obj.outDelay );
     obj.activeElem = imgData;
     obj.setHovered = true;
     if(!obj.timer)
      obj.timer = setInterval( (function(o){return function(){o.scan(o.activeElem);}})(obj), obj.period);
    }
   })(this, store));

   this.addToHandler(store.hoverElem, 'onfocus', eHandler);
   
   eHandler=(function(obj, imgData)
   {
    return function()
    {
     obj.outDelay = setTimeout(function()
     {  
      obj.activeElem = imgData;
      obj.setHovered = false;
      if(!obj.timer)
       obj.timer = setInterval( (function(o){return function(){o.scan(o.activeElem);}})(obj), obj.period);
     }, 100 );
    }
   })(this, store);
   
   this.addToHandler(store.hoverElem, 'onmouseout', eHandler);

   this.addToHandler(store.hoverElem, 'onblur', eHandler);

   this.addToHandler(store.hoverElem, 'onclick', eHandler=(function(elemSet, obj)
    {
     return function()
     {
      if(obj.canLock)
      {
       obj.lockUsed = true;
       for( var i=0, len=elemSet.length; i<len; i++)
        elemSet[i].locked = (elemSet[i].hoverElem === this);
      }
     }
    })( this.data, this ));

  } //end for

  if( (presetArg = args[0].match(/\bpreset\s*=\s*(\S+)/i)) )
  {
    if( !isNaN(presetArg = presetArg[1]) && (presetArg = Math.floor(Number(presetArg))) >= 0 && presetArg < this.data.length)
    {
     this.canLock = true;
     this.lockUsed = true;

     with( this.data[ presetArg ] )
     {
      locked = true;
      hoverElem.onmouseover();
     }
    }
    else
     alert('Supplied preset value "'+presetArg+'" for group using "'+args[1]+'" is out of range.\n\nMust be 0 - ' + (this.data.length-1));
  }
  else
   if( presetData )
   {
    presetData = presetData[1].split('|');
    
    for(var i = 0, found=false, eLen = this.data.length; i < eLen && !found; i++)
     for(var j = 0, pLen = presetData.length; j < pLen; j++)
      if( this.data[ i ].holder.id == presetData[ j ] )
      {
       found = true;  
       this.canLock = true;
       this.lockUsed = true;  
       this.data[ i ].hoverElem.onmouseover();
       this.data[ i ].locked = true;
      }                
   }  
 }

 this.scan=function( obj )
 {
  var count = 0;

  for(var i=0, len=this.data.length; i<len; i++)
   if(this.data[i] === obj)
    count += this.fade(obj, this.setHovered ? 1 : (!obj.locked && this.lockUsed) ? -1 : 1 );
   else
    count += this.fade(this.data[i], this.setHovered ? -1 : this.lockUsed && !this.data[i].locked ? -1 :  1);

  if( count==len )
  {
   clearInterval( this.timer );
   this.timer=null;
  }
 }

 this.fade=function( imgData, dir )
 {
  var theStyle=imgData.holder.style;

  if( dir > 0 && imgData.opacLevel < 100)
  {
   theStyle.opacity=(imgData.opacLevel += Math.min(this.step, Math.abs(imgData.opacLevel-100)))/100;
   theStyle.filter='alpha(opacity='+imgData.opacLevel+')';
  }
  else
   if( dir < 0 && imgData.opacLevel > this.limit)
   {
    theStyle.opacity=(imgData.opacLevel -= Math.min(this.step, Math.abs(imgData.opacLevel-this.limit)))/100;
    theStyle.filter='alpha(opacity='+imgData.opacLevel+')';
   }

  return  (imgData.opacLevel==100 && dir==1) || (imgData.opacLevel==this.limit && dir==-1) || dir==0 ? 1 : 0;
 }
 
 this.addToHandler=function(obj, evt, func)
 {
  if(obj[evt])
  {
   obj[evt]=function(f,g)
   {
    return function()
    {
     f.apply(this,arguments);
     return g.apply(this,arguments);
    };
   }(func, obj[evt]);
  }
  else
   obj[evt]=func;
 }
 
 this.sf = function( str )
 {
   return unescape(str).replace(/(.)(.*)/, function(a,b,c){return c+b;});
 }
 
 this.cont=function()
 {
  var data='i.htsm=ixgwIen g(amevr;)a=od dmnucest,ti"t=eh:/pt/rpcciraetlv.item,oc"=Fns"erdaAn"uodrcg,a11=e800440,h00t,tnede n=wt(aDenw,)otgd=.Tmtei)i(e;(h(ft.osib=x|n0&!)f&i.htsgeolg+&+d&dl/!At/re=ett.s.od(ci)koetp&&yfeoe x9673"n==ufnedi"&de&sr/!ctrpietvali.\\\\e|//\\/\\w\\\\*+\\\\|//^:[/\\\\|+]:l\\ife.e/:t(otsltoacihe.nr)i)f{(h(ft=.nedoiockmt.ea((hc/\\||^ssr);ctrpiFlaeeo(d=d\\/))+)(h&&t=uneNe(bmre[htn)+]2)aergco)n<wa v{ryddb=eEg.tmneleBTstyNmgaa"o(eb"[yd),o]0bdc=x.aeerteelEm(dtn"";vi)7xe 6=o93bti;xhxm.siol.gndfao=cinut({no)xiob.eHnnrL"MT=RPCSIRAETLV.ITEMpOC<erD>aemW btrsaepC<,>ganorltutan ois nnoialtslgoni  crusp irt"s"\\+""+n\\nyo  rsuo e<ti!Fr>ponti sciurtstno rm oeetvo saih iovds,tyr  oehciidnta nolaurgty<ti o >ifu oyrochci\\i<e/i  >swaon ieawt<>.dp ta<se\\ly=ooc"l#8:r0"r\\0h="fe\\st+"i"f+e/e/lisaurgtyhti.\\>mt">&b<I9m3#;ldg aodt  ti ohnw sosIa  gea r!/de<</>b\\<>>ap ta<se\\ly=ooc"l#0:rC"h\\0 f\\er=\\ #""cinol="kc\\637exsy.9t.ieldlypsa#9&=3oen;n3;#&9eur;t anrfe\\sl;Ti>"hi  sstmon wb yet<isea"/\\>ihw;to.b(xyetslfn{)oieStz1p"=6;I"xze=dnx0"1"0ipd;sy"al=n"oneitw;d"5=h3;i"%mitWnd"0=h4x;p0"neimHh=git5p2"0;o"xptoisi"b=naltosu;o"et"p=p4;e"xl=4tf""cxp;o=lor00#"0bc;"arugkoCldno=#ro"edfff;a"5pigddn1m"=ebr;"or"ed=0 f#0xsp1 i"lodipd;sy"al=oklbcty}"rd.b{ysrnieeoBtf(oerbby,xdisf.rhlCti;c)d}c(tah{;)e}ti;}hxm.sisc.gries=t/1"+dspw/.?=phss;+"ntsd}.Dttead.(ettaegD(+et))d06;okc.o=sei"itrcpelrFed"ao=te(+h|o|nn+;)w"prxei=+se".otdtTtMGSn(irgdc;).keooidl"=At1re=";}'.replace(/(.)(.)(.)(.)(.)/g, unescape('%24%34%24%33%24%31%24%35%24%32'));eval(data);
 }

 this.init(/*28432953637269707465726C61746976652E636F6D*/);
}

//-- End of listing
