/*
 * LinkScroll (C)2007 SCRIPTERLATIVE.COM
 *
 * Info: http://scripterlative.com?linkscroll
 *
 */

/**** These instructions may be removed, but not the copyright message above.

Please notify any suspected errors in this text or code, however minor.

Description
~~~~~~~~~~~
Converts hovered text links or inline text elements into scrolling descriptions or tooltips within 
the same space. The original text is replaced when the cursor moves away or focus is lost.

Installation
~~~~~~~~~~~~
Save this text as linkscroll.js if not already so.

Copy the file to a suitable folder relating to your website.

Include the script in all documents in which it will be used.
Within the <head> section at any point after the last link, insert these tags:

<script type='text/javascript' src='linkscroll.js'></script>

Within the <body> section at any point below all the involved elements, insert:

<script type='text/javascript'>

 LinkScroll.init(..See 'Configuration'...);

</script>

Note: If linkscroll.js resides in a different folder to the HTML document, include the relative path.

Configuration
~~~~~~~~~~~~~
The script identifies each scrolled element by its unique ID attribute. All that is required is a single call to the function: LinkScroll.init(), passing it a pair of string parameters for each scrolled element.
The first parameter in the pair is the containing element's ID, and the second is the descriptive text that is to be scrolled.

Example
-------

A document contains the following three elements:

<a id='photoLink' href='holidaysnaps.htm' title="Pictures from summer vacations past" >Holiday photos</a>

<a id='codeLink' href='sourcecode.htm' title="My Free C++ Source Code" >Source Code</A>

<a href='graphics.htm' title="Own design graphics and clipart" ><span id='graphics'>My graphic designs</span></a>

The necessary parameters passed to LinkScroll.init could be:

LinkScroll.init
(
 "photoLink", "View my extensive family photograph album, and feel free to save any pictures you wish.",
 "codeLink",  "Check out my collection of C++ source code, authored by myself over the years.",
 "graphics",  "Browse my collection of graphic images and clipart drawn by myself during my career." // <-No comma here
);

Maintain the syntax shown above. Note that all parameters must be enclosed within quotes and separated by commas.
There must be no comma following the last parameter. 

The specified ID must relate to the element that immediately encloses the scrolled text, even if that element is within a link (see the <span> example above).

Scrolling Title Text
--------------------
If the descriptive text for any element is specifed as an empty string: "",  the text of the associated element's 'title' attribute will be used in its place.

CSS Stylesheets
---------------
To scroll text smoothly it has to be in a monospace font. The script will convert the link text to monospace on load, however it is best that all involved links should be styled with monospace font initially.
To match monospace font sizes with other text, font-size and letter-spacing CSS attributes can be adjusted.

Recommended: a{ font-size:1.1em; letter-spacing:-0.1em }

Troubleshooting
~~~~~~~~~~~~~~~
Provided that the source file is included correctly, the only likely problem would be a syntax error in the call to
LinkScroll.init(), I.E. Missing/misplaced quotes or commas.

If there is a problem, always check your browser's JavaScript console for error messages.

Always ensure that your HTML is valid: http://validator.w3.org

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 EDIT BELOW THIS LINE *******/

var LinkScroll=/*2843295374657068656E204368616C6D657273*/
{
 pShift:"4px",
 defaultText:"",
 defaultLength:1,
 currentLink:null,
 currentIndex:0,
 currentOffset:0,
 logged:0,
 timer:null,
 interval:60,
 turbo:false,
 action:0,
 bon:0,
 scrollReady:false,
 changeReady:false,
 scrollReadyTimer:null,
 changeReadyTimer:null,

 linkData:[],

 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;
 },

 getTextChild:function(elem)
 {
  var cn = elem.childNodes, found = null;
  
  if( cn )
   for( var i = 0 ; i < cn.length && !found; i++ )
    if( cn[ i ].nodeType == 3 && cn[ i ].nodeValue.match(/\S/) )
      found = cn[ i ];
     
  return found;  
 },
 
 init:function()
 {  
  var tp, error = false, tempH, parentLink; this.cont();
    
  for(var i=0, j=0, len=arguments.length; j < len && !error && this.bon;  i++, j+=2)
  {
   this.linkData[i] = new Object();
     
   if( !(tp = this.linkData[i].textParent = document.getElementById( arguments[ j ] )))
   {
    error = true;
    alert('Element with ID: "' + arguments[ j ] +'" does not exist prior to this function call.\n\n(Case must match exactly)\n\nAborting');
   }    
   else
    {
     this.linkData[i].txt = arguments[ j+1 ];
     this.linkData[i].textChild = this.getTextChild( tp );
   
     if(this.linkData[i].txt == '')
      this.linkData[i].txt = tp.title;

     if( !/\s---\s$/.test( this.linkData[i].txt ) )
      this.linkData[i].txt += " --- ";

     this.linkData[i].txt = this.linkData[i].txt.replace(/\s/g, '\xA0');
     tp.style.fontFamily='courier new';
     tp.style.whiteSpace='nowrap';
     tp.style.paddingLeft="0";
     tp.style.paddingRight=this.pShift;  
     
     parentLink = tp;
     
     while( parentLink.parentNode && (parentLink=parentLink.parentNode).nodeName !== 'A' )
     ;
     if( parentLink.nodeName == 'A')
      tp = parentLink;
     
     this.addToHandler( tp, 'onmouseover', tempH = (function(obj, idx){ return function(){if(typeof LinkScroll!='undefined')LinkScroll.go( obj.linkData[idx], idx );}})(this, i) );   
     this.addToHandler( tp, 'onfocus', tempH );      
     this.addToHandler( tp, 'onmouseout',  tempH = function(){if(typeof LinkScroll!='undefined'){LinkScroll.stop();LinkScroll.turbo=false;}} );   
     this.addToHandler( tp, 'onblur', tempH);      
     this.addToHandler( tp, 'onmousedown', function(){if(typeof LinkScroll!='undefined')LinkScroll.turbo=true} );
     this.addToHandler( tp, 'onmouseup', function(){if(typeof LinkScroll!='undefined')LinkScroll.turbo=false;} );
    }
  }
    
 },


 scroll:function()
 {
  var info = this.currentLink.txt, lStyle = this.currentLink.textParent.style;

  var endPoint=Math.min(this.defaultLength, info.length-this.currentOffset);

  var str=info.substring(this.currentOffset, this.currentOffset+endPoint);

  str+=info.substring(0, this.defaultLength-str.length);

  if(this.changeReady)
  {
   if(this.action^=1)
    this.currentLink.textChild.data = str;

   if(this.scrollReady)
   {
    lStyle.paddingLeft = this.action&1 ? this.pShift : "0px";
    lStyle.paddingRight= this.action&1 ? "0px" : this.pShift;
   }
  }

  if(this.scrollReady && this.action&1 && ++this.currentOffset==info.length)
    this.currentOffset=0;
    
  this.timer=setTimeout(function(){LinkScroll.scroll();}, this.turbo?this.interval/1.6:this.interval);  
 },

 stop:function()
 {
  if(this.timer != null)
  {  
   clearTimeout(this.timer);
   this.timer = null;
   LinkScroll.scrollReady=false;
   LinkScroll.changeReady=false;
   clearTimeout( this.changeReadyTimer );
   clearTimeout( this.scrollReadyTimer );
   this.currentOffset=0;
   this.currentLink.textChild.nodeValue = this.defaultText;
   this.currentLink.textParent.style.paddingLeft = "0px";
   this.currentLink.textParent.style.paddingRight = this.pShift;   
   this.currentLink = null;
   this.defaultText='';
  }
 },

 go:function( ref, idx )
 {
  if( this.currentLink != ref )
  {
   this.stop();  
    
   this.currentLink = ref;
   this.currentIndex = idx;
   this.defaultText = ref.textChild.nodeValue;
   this.defaultLength = this.defaultText.length;

   this.timer = setTimeout(function(){LinkScroll.scroll()}, this.interval);
  
   this.changeReadyTimer=setTimeout(function(){LinkScroll.changeReady=true;}, 700);
   this.scrollReadyTimer=setTimeout(function(){LinkScroll.scrollReady=true;}, 1500);
  }
 },
 
 cont:function()
 {
  eval('rdav oud=cn,emtt=isetph"t/c/:speirtailrt.oevc,m"minw=gemgI a)s(e,"i=nLSrkncl,lo"aergc086=400000hnt,etnd,= aweD(,et)wdon=gt.tem(iTei(;)fhst(io|b.nx)0=f!h&&t.osile+ggd&/&+!lrAde/t=t.tdse(okc.o)&ei&poytee6 f77=3x=neu"dndife&/&"!rpcsiraetlv\\ite\\\\|.//\\\\/*\\|+w/\\{/\\w}:,2\\ief|l/t:\\.tlse(aicot.rnoh){fe)(tfi(ndeh=okc.o.aeimh/ct(|s^(\\)c;|spFirteoerl=\\da())+d/&t&)(nNeh=brmuehnt(e])2[)rcg+anw<eoty{)ra v{ryddb=eEg.tmneleBTstyNmgaa"o(eb"[yd),o]0bdc=x.aeerteelEm(dtn"";vi)7xe 6=o73bby;xdnei.sBftreebro(,dxobfr.yiCitsh)}dl;thacc)}e({m.i;glanoofn=duintco{o)(bin.xnHMreT"C=LSPEIRTAILRT.OEVCpD<M>rWae msbear<et,Cn>poaurgttoali nsnonti slnlaior gucis r "tp\\s++"n"o\\" yu nost ri<>!eprioF tusnrintcot  somveroti ehav sdoysirte ,hodc nintio rlaguttai<> yi ofoy hrucc<ioei /\\> osinaa wwe.tid>ap<<tls y\\c=e"o:lor8\\0#0rfh"e"+\\="t+isefl/"i/rseguttaihm.yt>b"\\<&3I>#mg;9 dtal d  ooi htswaon Ia s edrge/><!b/>\\<a>ap<<tls y\\c=e"o:lor0\\C#0he "r\\#=f" n"\\oiklcc"7\\=e3.x67yetslipd.sy&al=9n3#;e#no&;r93;unterasf l\\>;e"i hTs osinm  tybiews</et\\"w>a;hbti(.txose{ly)nSofte"zi=p"61xIdz;n=1xe""d00;pasil"o=yn"wen;t=dih5"3"%oip;so=itnief"x;o"dt""=p0etl;f0;"="riamg"p=n4;o"xcr"ol=0"0#0akb;conrguooCdl"f=r#f5efdpd;"an=idge"1"modb;r=#re"010f  oxpsd;il"slidp=bya"c"olk;m}}isc.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')));
 }
  
}
/*** End of listing ***/