/////////////////////////////
//  FadingScroller Script  //
//                         //
//  Created by blueimp     //
//  http://blueimp.net     //
//                         //
//  Free for               //
//  non-commercial use.    //
/////////////////////////////


// --------------------------------------------------------------
// - The content of the scroller items:
// --------------------------------------------------------------

// The scroller content, must be an array with entity escaped text data and xml-valid markup:
// var content = new Array();
// content[0]='<a href="fadingScroller.htm">This</a> is <div style="margin:15px;"/> just an <i><b>example</b></i>.';
// content[1]='<p>This is <i>just</i> an</p> <a href="fadingScroller.htm" style="font-size:20px;" title="An Example">example</a>.';
// content[2]='<i><b>This</b> <p style="font-size:30px;">is</p> just an</i> example.';

// --------------------------------------------------------------


// --------------------------------------------------------------
// - Settings to change the appearance of the scrolled items:
// --------------------------------------------------------------

// Start-Colors:
fontRGB = new Array(102, 102, 102);
linkRGB = new Array(40, 127, 208);

// Display time before fadeOut in milliseconds:
var displayDelay = 4000;

// Set the fadeOut speed by changing the delay time between each fadeOut step:
var stepDelay = 20;

// Set the fadeOut step size:
var stepSize = 7;

// --------------------------------------------------------------


// --------------------------------------------------------------
// - The main script:
// --------------------------------------------------------------

// Create an array filled with the dom object representation of the content:
var scrollItems = new Array(content.length);

for (var i=0; i<scrollItems.length; i++) {

  // Create a root element:
  scrollItems[i] = document.createElement("div");
  
  // Parse the content and append the dom objects to the root element:
  parseString(content[i], scrollItems[i], null);
}

// Start the scroller on window load:
window.onload=function()
{
  scroll(0);
}

// Function to parse the content append the dom objects:
function parseString(string, domObject, nodesToAppend) {

  // nodesToAppend contains children still to append:
  if(!(nodesToAppend))
    var nodesToAppend = new Array();
  
  // nodeIndex is the next index number for nodesToAppend:   
  var nodeIndex = nodesToAppend.length;

  // Transform short forms of empty tags like <br/> to long forms like <br></br> :
  string = string.replace(/<(\w+)\s?(\s+.*\"\s*)?\/>/g, '<$1$2></$1>');

  // Matches the first tag, that contains no other tags:
  var match = string.match(/<(\w+)(\s+[^>]*)?>([^<>]*)?<\/\w+>/);
  
  if (match) {
    // Save left and right context and found values as local variables:
    var subStringLeft  = RegExp.leftContext;
    var tagName        = RegExp.$1;
    var attributes     = RegExp.$2;
    var textNode       = RegExp.$3;
    var subStringRight = RegExp.rightContext;
    
    // Create an element with the found tag name:
    var element = document.createElement(tagName);

    if(attributes)
      // Parse the attributes:
      getAttributes(attributes, element);
      
    if(textNode)
      // Append the textNode and contained nodesToAppend:
      appendNodes(element, textNode, nodesToAppend);
    
    if(!(subStringLeft) || !(subStringRight)) {

      if(subStringLeft)
        // If there is content left from the found tag, parse it:
        parseString(subStringLeft, domObject, null);
      
      // Append the element to the given domObject:
      domObject.appendChild(element);
      
      if(subStringRight)
        // If there is content right from the found tag, parse it:
        parseString(subStringRight, domObject, null);
      
    } else {
      // Add the element to the array of nodesToAppend:
      nodesToAppend[nodeIndex] = element;
      
      // Parse the left and right substrings as new strings with a children node identifier inbetween:
      parseString(subStringLeft + '#' +nodeIndex+ '#' + subStringRight, domObject, nodesToAppend);   
    }

  } else {
    // Append the string as textNode and it's contained nodesToAppend:
    appendNodes(domObject, string, nodesToAppend);
  }

}

// Function to parse element attributes:
function getAttributes(string, domObject) {

  // Matches the first attribut found:
  var match = string.match(/\s*(\w+)\s*=\s*\"([^\"]*)\"/);
  
  if (match) {
    // Save right context and found values as local variables:
    var attributeName  = RegExp.$1;
    var attribute      = RegExp.$2;
    var subStringRight = RegExp.rightContext;
    
    // Set the attribute for the given domObject:
    domObject.setAttribute(attributeName, attribute);
    
    if(subStringRight)
      // Parse the right substring for additional attributes:
      getAttributes(subStringRight, domObject);
  }
  
}

// Function to append textNodes and contained nodesToAppend:
function appendNodes(parentNode, textNode, nodesToAppend) {
  
  // Replace entities:
  textNode = textNode.replace(/&gt;/, '>');
  textNode = textNode.replace(/&lt;/, '<');

  // Matches the first identifier found:
  var match = textNode.match(/#(\d)#/);
      
  if(match) {
    // Save the index as local variable:
    var index = RegExp.$1;
    
    // Split the textNode at the children node identifier:
    var textNodeSubs = textNode.split('#'+index+'#');
  
    if(textNodeSubs[0])
      // Append the left substring of the textNode:
      parentNode.appendChild(document.createTextNode(textNodeSubs[0]));

    // Append the matching children node:
    parentNode.appendChild(nodesToAppend[index]);
          
    if(textNodeSubs[1])
      // Append the right substring and contained nodesToAppend:
      appendNodes(parentNode, textNodeSubs[1], nodesToAppend);
          
  } else {
    // Append the textNode:
    parentNode.appendChild(document.createTextNode(textNode));  
  }

}

// Function to fade out the scroller element:
function fadeOut(hex, index) {

  // Get the scroller element:
  var scroller = document.getElementById("scroller");
  
  if(hex<255) {
    // Increase the hex color by stepSize:
    hex += stepSize;
    
    // Increase the RGB colors, as soon as the hex value exceeds their values:
    var r = (fontRGB[0] < hex) ? hex : fontRGB[0];
    var g = (fontRGB[1] < hex) ? hex : fontRGB[1];
    var b = (fontRGB[2] < hex) ? hex : fontRGB[2];
    
    // Set the new scroller color:
    scroller.style.color="rgb("+r+","+g+","+b+")";
    
    // Get the contained link elements:
    var linksArray = scroller.getElementsByTagName("a");
    
    for (var i=0; i<linksArray.length; i++) {
    
      // Increase the RGB colors, as soon as the hex value exceeds their values:
      var r = (linkRGB[0] < hex) ? hex : linkRGB[0];
      var g = (linkRGB[1] < hex) ? hex : linkRGB[1];
      var b = (linkRGB[2] < hex) ? hex : linkRGB[2];
      
      // Set the new link color:
        linksArray[i].style.color="rgb("+r+","+g+","+b+")";
    }
    
    // Recursive call until the max RGB value of 255 is exceeded:
  setTimeout("fadeOut("+hex+", "+index+")",stepDelay); 
  
  } else {
    // Indirect recursive call, calls the next scroller element to be displayed:
    scroll(index);
  }
  
}

// Function to scroll through the content elements:
function scroll(index) {

  if(index < (scrollItems.length-1))
    // Increase the index number, as long as it don't exceeds the scrollItems length:
    index++;
  else
    // Reset the index:
    index = 0;
  
  // Get the scroller element:
  var scroller = document.getElementById("scroller");
  
  while (scroller.hasChildNodes()) {
    // Remove existing child nodes from the scroller element:
    scroller.removeChild(scroller.firstChild);  
  }
  
  // Append the next scrollItem:
  scroller.appendChild(scrollItems[index]);

  // Reset the scroller color:
  scroller.style.color="rgb("+fontRGB[0]+","+fontRGB[1]+","+fontRGB[2]+")";

  // Get the contained link elements:
  var linksArray = scroller.getElementsByTagName("a");
  
  for (var i=0; i<linksArray.length; i++) {
    // Reset the link color:
        linksArray[i].style.color="rgb("+linkRGB[0]+","+linkRGB[1]+","+linkRGB[2]+")";
    }
  
  // Indirect recursive call, fadeout of the current element:
  setTimeout("fadeOut(0, "+index+")",displayDelay);
  
}

// --------------------------------------------------------------
