﻿/*
 * SPServices - Work with SharePoint's Web Services using jQuery
 * Version 0.3.1
 * @requires jQuery v1.3.2 and jQuery.SPServices plug-in (tested with jQuery.SPServices-0.3.2.js) 
 * 
 * Copyright (c) 2009 Arnault Nouvel
 * Author : nouvel.arnault@hotmail.fr
 * 
 * Examples and docs at: 
 * http://spitemsrotator.codeplex.com
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/mit-license.php
 */

//Can be used with a standard announcements list
jQuery.fn.rotateAnnouncements = function(options){

	var opts = $.extend({
		displayDuration:10000,
		fadeDuration:1500,
		CAMLViewFields:"<ViewFields><FieldRef Name='Body' /></ViewFields>",
		CAMLQuery:"<Query><Where><Or><IsNull><FieldRef Name='Expires' /></IsNull><Geq><FieldRef Name='Expires' /><Value Type='DateTime'><Today /></Value></Geq></Or></Where></Query>",	
		itemHtml:"{ows_Body}"
	}, options);

	return this.rotateItems(opts);
	
}

jQuery.fn.getPages = function(options){

	var opts = $.extend({
		CAMLViewFields:"<ViewFields><FieldRef Name='Title' /></ViewFields>",
		CAMLQuery:"",	
		itemHtml:"{ows_Title}"
	}, options);

	return this.rotateItems(opts);
	
}


//Can be used with a standard picture library
jQuery.fn.rotatePictures = function (options) {

    var opts = $.extend({
        displayDuration: 5000,
        fadeDuration: 1500,
        CAMLViewFields: '<ViewFields><FieldRef Name="RequiredField" Explicit="TRUE" /><FieldRef Name="EncodedAbsUrl" /><FieldRef Name="NameOrTitle" /><FieldRef Name="ImageWidth" /><FieldRef Name="ImageHeight" /></ViewFields>',
        CAMLQueryOptions: "<QueryOptions><ViewAttributes Scope=\"Recursive\" /></QueryOptions>",
        getItemHtml: function (element, options) {

            try {
                var showTooltip = options.showToolTip;

                var elmt = $(element);

                //Get url of the image
                var imgUrl = elmt.attr("ows_EncodedAbsUrl");

                //Gets original size of the image
                var originalWidth = elmt.attr("ows_ImageWidth");
                var originalHeight = elmt.attr("ows_ImageHeight");

                //Compute size and position of the image so it fits in the container's center
                var sap = $.SPItemsRotator.getImageSizeAndPosition(originalWidth, originalHeight, options);

                var strTooltip = "alt='" + showTooltip ? elmt.attr("ows_NameOrTitle") : "" + "'";

                //returns corresponding HTML
                return "<img src='" + imgUrl + "' " + strTooltip + " style='position:relative;width:" + sap.width + "px;height:" + sap.height + "px;top:" + sap.top + ";left:" + sap.left + "'/>";
            } catch (e) {
                if (options.debug)
                    console.log("jQuery.fn.rotatePictures.getItemHtml : " + e);
            }
        }
    }, options);

    return this.rotateItems(opts);

}

//Main function
jQuery.fn.rotateItems = function(options){
	
	return this.each(function(){
		
		try{
		
			//SPItemsRotator options
			var displayOptions = $.extend({
				itemClass:"rotator-item",
				displayDuration:2000,
				fadeDuration:0,
				outerContainer:this,
				debug:false,
				randomStart:true,
				overflow:"hidden",
				itemHtml:"{ows_Title}",
				getItemHtml:jQuery.SPItemsRotator.getItemHtml,
				showTooltip:false
			}, options);
			
			//Forces reference to original object so it can be found by SPNewsRotator.Initialize
			displayOptions.container = this;
			
			//SPServices options
			var wsOptions = $.extend({
				operation:'GetListItems',
				CAMLViewName: "",			// View name in CAML format.
				CAMLQuery: "",				// Query in CAML format
				CAMLViewFields: "",			// View fields in CAML format
		     	CAMLRowLimit: "",			// Row limit in CAML format
				CAMLQueryOptions: "<QueryOptions></QueryOptions>",		// Query options in CAML format
				completefunc:function(xData, status){$.SPItemsRotator.initialize(xData, status, displayOptions, this);}
			}, options);
			
			//Calls the web service to retrieve data
			$().SPServices(wsOptions);
		
		}catch(e){
			if(options.debug)
				console.log("jQuery.fn.rotateItems: " + e);
		}
		
	});
	
}

//plug-in code
jQuery.SPItemsRotator = {

	//Function used to setup the rotation cycle
	initialize:function(xData, status, options, query){
	
		try{
			var divItems = $(options.container);
			var divOuter = $(options.outerContainer);
			var itemClass = options.itemClass;
			var randomStart = options.randomStart;
			var debug = options.debug;
			var getItemHtml = options.getItemHtml;
			var overflow = options.overflow;
			
			if(debug){
				//debugger;
				console.log("REQUEST URL : " + query.url);
				console.log("REQUEST XML : " + query.data);
				console.log("RESPONSE STATUS : " + status);
				console.log("RESPONSE XML : " + xData.responseText);
			}
			
			//Creates a div with relative positioning, which is mandatory to have news items with absolute positioning
			divItems.append("<div class='newsrotator-inner' style='position:relative;width:100%;height:100%;overflow:" + overflow + ";'></div>");
			var divInner = divItems.find(".newsrotator-inner");
			
			//Creates and fills a div for each announcement in the list		
			var htmlItems = "";
			$(xData.responseXML).find("z\\:row").each(function(){
				var innerHtmlItem = getItemHtml(this, options);
				var htmlItem = "<div class='" + itemClass + "' style='display:none;position:absolute;top:0px;left:0px;'>" + innerHtmlItem + "</div>";
				htmlItems += htmlItem;
				if(debug)
					console.log("ITEM HTML : " + innerHtmlItem );
			});
			divInner.append(htmlItems);
		    
		    //Retrieves HTML objects that have been added
		    var items = divInner.find("." + itemClass);    
		    
		    //Adjust display
		    if(items.length > 0){
				
				//Shows the outer container and fix with
				divOuter.show();
				items.width(divInner.width());
				items.height(divInner.height());
				
				if(randomStart){
					//Display one of the items randomly
				    var randomNumber = Math.floor(Math.random() * items.length);
				    $(items[randomNumber]).show();
			    }
			    else{
			    	//Displays the first item
			    	$(items[0]).show();
			    }
			    
			    //Initiates the rotation cycle if there are more than 1 item to display
			    if(items.length > 1)
			    	window.setTimeout(function(){ $.SPItemsRotator.rotate(options); }, options.displayDuration);
		
		    }
		    else{
		    	//Hides the outer container
		    	divOuter.hide();
		    }
		}catch(e){
			if(options.debug)
				console.log("jQuery.SPItemsRotator.initialize : " + e);
		}
			
	},
	//Function that rotates items indefinitely
	rotate:function(options){
		
		try{
		
			var divContainer = $(options.container);
			var itemClass = options.itemClass;
			var fadeDuration = options.fadeDuration;
			var timeout = options.fadeDuration + options.displayDuration;
				
			//Retrieves visible item 
			var visibleItem = divContainer.find("." + itemClass + ":visible");
			//Selects next item to show
			var nextItem = visibleItem.next();
			if(nextItem.length == 0)
				nextItem = $(divContainer.find("." + itemClass)[0]);
		
			//Hides current item
			visibleItem.fadeOut(fadeDuration);
			//Shows next item
			nextItem.fadeIn(fadeDuration);
		
			//Initiates next rotation
			window.setTimeout(function(){ $.SPItemsRotator.rotate(options); }, timeout);
			
		}catch(e){
			if(options.debug)
				console.log("jQuery.SPItemsRotator.rotate : " + e);
		}
	},
	//Default rendering function
	getItemHtml:function(element, options){

		var itemHtml = options.itemHtml;	
		var elmt = $(element);

		//look for text inside brackets
		var exp = new RegExp("\{[^\}]*\}", "gi");
		var arMatch = itemHtml.match(exp);
		//replace each match by the corresponding field value
		for(var i=0;i<arMatch.length;i++){
			var match = arMatch[i];
			var expmatch = new RegExp(match, "gi");
			var value = elmt.attr(match.substring(1, match.length - 1)); 
			itemHtml = itemHtml.replace(expmatch, value?value:"");
		}
		
		return itemHtml;
			
	},
	//Utility function that computes the display size and position of an image
	getImageSizeAndPosition:function(originalWidth, originalHeight, options){
	
		var container = $(options.container);
		var maxWidth = container.width();
		var maxHeight = container.height();
		var overflow = options.overflow;	
		var sap = new Object();
		
		if(overflow == "visible"){
			sap.width = originalWidth;
			sap.height = originalHeight;
		}
		if(originalWidth <= maxWidth && originalHeight  <= maxHeight ){
			sap.width = originalWidth;
			sap.height = originalHeight;
		}
		else if( originalWidth/originalHeight > maxWidth/maxHeight ){
			sap.width = maxWidth;
			sap.height = maxWidth*originalHeight/originalWidth;
		}
	    else{
			sap.width = maxHeight*originalWidth/originalHeight;
			sap.height = maxHeight ;
		}
		
		sap.top = (maxHeight - sap.height)/2;
		sap.left = (maxWidth - sap.width)/2;
	
	    return sap;
	   
	}


}

