/**

 * IMAGE REFLECTION
 *
 * Description: This script will allow images to have reflections if you specify it
 * to have them by saying class="reflect" along with some options
 *
 * Researched and Composed By Eric Fisher
 *
 * References: http://developer.apple.com/documentation/AppleApplications/Reference/SafariJSRef/Classes/Canvas.html
 */


/**
* HELPER METHOD
*
* DEFINE a function called getElementsByClassName
* This takes the className as a parameter and gets a list of all the tags in the HTML page.
* It then creates a new blank array and runs through all the tags and adds only those that are named className
* Then it returns the array
*/

document.getElementsByClassName = function(className) { //written in this style because it's a function of the document class
	var children = document.getElementsByTagName('*') || document.all; //children is a list of all the tags
	var elements = new Array();    //new blank array to be filled
	for (var i = 0; i < children.length; i++) {
		var child = children[i];
		var classNames = child.className.split(' ');  //split up the class name of this tag (in case there are multiple classes)
		for (var j = 0; j < classNames.length; j++) {
			if (classNames[j] == className) {    //if we've found the className we're looking for, add it to our blank array and break
				elements.push(child);
				break;
			}
		}
	}
	return elements;
}

/**
* DEFINE A CLASS CALLED REFLECTION
* with two variables: defaultHeight and defaultOpacitiy, initialized to a default value
*/

var Reflection = {
	defaultHeight : 0.5,   //default height
	defaultOpacity: 0.5,   //default opacity
	
	// DEFINE A FUNCTION CALLED "add" which takes two parameters: the image and some options
	
	add: function(image, options) {
	   // so as not to do two reflections, first remove the image
		Reflection.remove(image);
		//create a list of the default height and opacity
		doptions = { "height" : Reflection.defaultHeight, "opacity" : Reflection.defaultOpacity }
        //if options were specified, then replace any that weren't by the default ones
		if (options) {
			for (var i in doptions) {
				if (!options[i]) { options[i] = doptions[i]; }
			}
		}
		//otherwise just set options to the default ones 
		else { options = doptions; }
	   
        // TRY THIS

		try {
			// Create a new <div> tag
			var d = document.createElement('div');
			var p = image;
		
            //Now let's break down the class name to determine what we're doing			
			
			var classes = p.className.split(' ');    //split by white space
			var newClasses = '';
			for (j=0;j<classes.length;j++) {
				if (classes[j] != "reflect") {      //here we're talking about the other values like rh and ro
					if (newClasses) { newClasses += ' ' }  //if this is a second or greater class, make sure to add the space between them!
					newClasses += classes[j];      //add this class
				}
			}

			var reflectionHeight = Math.floor(p.height*options['height']);   //round down, multiply actual image height by our specified height
			var divHeight = Math.floor(p.height*(1+options['height']));      //make the division height double the height (to allow for both)
			var reflectionWidth = p.width;   //make the reflection span the width of the image
			
			// Set our division class name to all the newClasses
			d.className = newClasses;
			p.className = 'reflected';
			
			// Align any text on the bottom
			d.style.cssText = p.style.cssText;
			p.style.cssText = 'vertical-align: bottom';
			
			//Make sure the division we've created has the same width and height that we want and that it displays as pixels
			d.style.width = reflectionWidth+'px';
			d.style.height = divHeight+'px';
			
			//If there are elements and we're not using Opera

			if (document.all && !window.opera) {
	
			    //Step 1: Create a new image tag
				var reflection = document.createElement('img');
				//Step 2: Make this image tag's source our original image
				reflection.src = p.src;
				//Step 3: Ensure this new image's width is the same as the reflection width, adding 'px' for pixels
				reflection.style.width = reflectionWidth+'px';

				//Step 4: Set the bottom margin of the reflected image to the negative value of the total height - reflected height.
				//        The value is negative because we're bringing the next line CLOSER to the image as our reflection height gets smaller.
				reflection.style.marginBottom = "-"+(p.height-reflectionHeight)+'px';
				//Step 5: The piece that makes it FADE
				reflection.style.filter = 'flipv progid:DXImageTransform.Microsoft.Alpha(opacity='+(options['opacity']*100)+', style=1, finishOpacity=0, startx=0, starty=0, finishx=0, finishy='+(options['height']*100)+')';

				//CHECK IF THIS IS BEING DISPLAYED AS A LINK
                if(p.parentNode.nodeName=='A') {
                    reflection.style.border="0px";
                    var temp = p.parentNode;
                    var temp2 = temp.parentNode;
                    temp2.replaceChild(d,temp);
                    d.appendChild(temp);
                    temp.appendChild(reflection);
                    //temp.appendChild(p);
                    //alert(p.nodeName + " is a child of " + p.parentNode.nodeName + ", which is a child of " + p.parentNode.parentNode.nodeName + " which is a child of " + p.parentNode.parentNode.parentNode.nodeName);
                    //alert(temp.nodeName + " has " +                     //temp.parentNode.replaceChild(d,p);
                    //d.appendChild(temp);
                }
                else {
                    p.parentNode.replaceChild(d, p);
                    d.appendChild(p);
                    d.appendChild(reflection);
                }


			} 
			
			else {
			    //Create a new element <canvas> :: The canvas element is a third party extension to the HTML standard that allows for dynamic rendering of scriptable bitmap images.
				var canvas = document.createElement('canvas');
				//If there's a context (i.e. 2D ...)
				if (canvas.getContext) {
			        //Set our context to 2D (for 2D images)
					var context = canvas.getContext("2d");
				    //Set our height and width both as a CSS style, and as an HTML attribute (just in case!)
					canvas.style.height = reflectionHeight+'px';
					canvas.style.width = reflectionWidth+'px';
					canvas.height = reflectionHeight;
					canvas.width = reflectionWidth;
					
					//CHECK IF THIS IS BEING DISPLAYED AS A LINK
                if(p.parentNode.nodeName=='A') {
                    //reflection.style.border="0px";
                    var temp = p.parentNode;
                    var temp2 = temp.parentNode;
                    temp2.replaceChild(d,temp);
                    d.appendChild(temp);
					temp.appendChild(p);
                    temp.appendChild(canvas);
                    //temp.appendChild(p);
                    //alert(p.nodeName + " is a child of " + p.parentNode.nodeName + ", which is a child of " + p.parentNode.parentNode.nodeName + " which is a child of " + p.parentNode.parentNode.parentNode.nodeName);
                    //alert(temp.nodeName + " has " +                     //temp.parentNode.replaceChild(d,p);
                    //d.appendChild(temp);
                }
                else {
                    p.parentNode.replaceChild(d, p);
                    d.appendChild(p);
                    d.appendChild(canvas);
                }

                    //SAVE the context					
					context.save();
					
					//FLIP THE IMAGE

					// Translate the reflected image so that it's below the original image
					context.translate(0,image.height-1);
				    // Flip the image upside down
					context.scale(1,-1);
					// Now that we have the context down, DRAW THE REFLECTED IMAGE in our canvas!
					context.drawImage(image, 0, 0, reflectionWidth, image.height);

	                // Restore the canvas to BEFORE we translated and flipped the image
					context.restore();
					context.globalCompositeOperation = "destination-out";

					//Create a gradient on the reflected image now so that it fades out from total opacity to 0 by the time it reaches reflectionHeight
					var gradient = context.createLinearGradient(0, 0, 0, reflectionHeight); //the 4 parameters are X0,y0, x1, y1
					
					// THIS PART MAKES THE IMAGE FADE FROM THE DEFAULT OPACITY TO WHATEVER THE BACKGROUND (ALPHA) COLOR IS
					
					gradient.addColorStop(1, "rgba(255, 255, 255, 1.0)");  //because the offset is 1, we're talking about the END of the image. Make this the alpha channel (aka whatever the background color is)
					gradient.addColorStop(0, "rgba(255, 255, 255, "+(1-options['opacity'])+")");   //at the beginning, make this white plus whatever our opacity is set to

		
		            //now fill the canvas with a gradient
					context.fillStyle = gradient;
					//Version checking
					if (navigator.appVersion.indexOf('WebKit') != -1) { context.fill(); } //if not WebKit 
					else { context.fillRect(0, 0, reflectionWidth, reflectionHeight*2); } //fill the canvax with the specified dimensions
				}
			}
		} catch (e) {} //error checking if try doesn't work. But it will!
	},

    /**
    * DEFINE a function called remove which takes the image as a parameter and removes it from the HTML
    */

	remove : function(image) {
		if (image.className == "reflected") { //first make sure we're only removing an image who has a class="reflect"
			image.className = image.parentNode.className; //now set the class name of this image to whatever the parent's class name is
			image.parentNode.parentNode.replaceChild(image, image.parentNode); //now get the grandparent to replace the parent with the image.
		}
	}
}

//This method will go through all of the images that have class="reflect" and check if they also specified rh and ro.
//If they did, then it will parse the string and get the numerical value of the reflection height and reflection opacity
//Otherwise, it passes null to Reflection's add function, which handles null input

function addReflection() {
	var reflectedImages = document.getElementsByClassName('reflect');  //get all the images that have class="reflect"
	for (i=0;i<reflectedImages.length;i++) {   //for each image...
		var rh = null;   //reset rh to null
		var ro = null;  //reset ro to null
		
		var classes = reflectedImages[i].className.split(' '); //get all the other classes that this image uses besides reflect
		for (j=0;j<classes.length;j++) {  //go through them all
			if (classes[j].indexOf("rh") == 0) { var rh = classes[j].substring(7)/100; }//if it's rh, then extract the amount and divide by 100 to get the percentage (so something like rh56 would give you .56
			else if (classes[j].indexOf("ro") == 0) { var ro = classes[j].substring(8)/100; } //else if it's ro, then extract the amount and divide by 100 to get the percentage
		}
		// Now use the reflection class to add a reflection to this image, which we've added classes to
		Reflection.add(reflectedImages[i], { height: rh, opacity : ro});
	}
}

//Do all of this when the page loads.

var previousOnload = window.onload;
window.onload = function () { 
	if(previousOnload) previousOnload(); 
	addReflection(); 
}

// END SCRIPT