
if(typeof console != "undefined"){
  console.warn("veveoSearchBundled.min.js is deprecated. Use veveoSearchBundled.min.2.js instead.")
}

/*
 * 
 * Setup.js 
 * 
 */
 var $jq = jQuery;
 if(typeof Prototype !== "undefined"){
   jQuery.noConflict();   
 }
 
 
/*
 * 
 *  ProgramSearch.js
 * 
 */

PgmSrch = typeof PgmSrch !== "undefined"? PgmSrch:{}

PgmSrch.initializedCallbacks = [];

PgmSrch.resourcesToWaitFor = [];
/*
 * 
 * Util.js 
 * 
 */
 
 PgmSrch.util  = new (function(){
	
	var localUtil = this;
	
	this.namedLogger = function(name){
	    
	    this.debug = function(message){
	        PgmSrch.util.logger.debug("[" + name + "] " + message);
	    }
	    
	};
	
	
	this.logger = new (function(){
		
		var forceConsole = false; // create a console if the browser doesn't have one
		this.logToServer = false;
		var enabled = true;
		if(window.location.toString().indexOf("http://local.") == -1){
		    enabled = false;
		}
		var timers = [];
		var oThis = this;
		
		this.Timer = function(){
			this.elapsedTime = 0;
			this.startTime = null;
		};
		
		this.Timer.prototype = {
			start: function(){
				if(this.startTime !== null){
					throw new Error("Timer: \""+ this.name +"\" is already running");
				}
				this.startTime = new Date().getTime();
				return this;
			},
			stop : function(){
				if(this.startTime === null){
					throw new Error("Timer is already stopped");
				}
				this.elapsedTime += (new Date().getTime() - this.startTime);
				this.startTime = null;
				return this;
			}
		};
		
		this.enable = function(){
			enabled = true;
		};
		
		this.disable = function(){
			enabled = false;
		};
		
		this.startTimer = function(name){
			var timer = timers[name];
			if(typeof timer === "undefined"){
				timer = timers[name] = new this.Timer();
				timer.name = name;
			}
			timer.start();
		}
		
		this.stopTimer = function(name){
			var timer = timers[name];
			if(typeof timer === "undefined"){
				this.error("ERROR - there is no timer with the name: " + name); 
			}else{
				timer.stop();
			}
		}
		
		this.printTimes = function(){
			localUtil.array.forKeys(timers, function(name, timer){
				oThis.log("Timer: <b>" + name + "</b> total elapsed time is " + timer.elapsedTime + " ms.");
			});
			
			
		}
		this.clearTimers = function(){
			timers = [];
		}
		
		this.debug = function(arg){
			if(enabled){
				
				if(typeof console === "undefined" && forceConsole){
					$jq("<div id='consoleDiv' style='width: 400px; height: 200px; overflow:auto; background-color: #eeeeff; padding: 5px; position: absolute; z-index: 9999; top:0px; right:0px; color: #000000'>CONSOLE</div>").appendTo($jq("body"));
					window.console = {
						log: function(message){
                            // alert(message)
						    message = message.replace(/</g, "&lt;");
						    message = message.replace(/>/g, "&gt;");
                            // alert(message)
							$jq("#consoleDiv").append("<br><br>").append(message);
							var objDiv = 	document.getElementById("consoleDiv");
							objDiv.scrollTop = objDiv.scrollHeight
						}
					};	
				};
				
				var message;
				if(typeof arg === "function"){ // pass a function if we're the log message is expensive to calculate
					message = arg();
				}else{
					message = arg;
				}
				var date = new Date();
				var output = date.getMinutes() + ":" + date.getSeconds() + ":" + date.getMilliseconds()  + " " + message;
				if(this.logToServer){
			        $jq.get("logger.jsp",{logValue: output});
				}else if(typeof console !== "undefined"){ 
                    console.log(output);                   
				}					
			}
		};
		
		this.log = this.debug;
		this.error = this.log;
		this.warn = function(arg){
		    this.debug("WARNING: " + arg);
		}
		
	})();
	
	/*
	this.array = new (function(){

		// check if an array has an item
		this.has = function (a, obj) {
		  return $jq.inArray(obj,a) >= 0;
		}
		
		
		this.isArray = function(object){
			return typeof object.push !== "undefined";
		}
		
		// remove an item from an array
		this.remove = function(target, obj){ 
		  var i = target.length;
		  var ret = [];
		  while (i--) {
		    if (target[i] == obj) {
		    	target.splice(i, 1);
		    }
		  }
		  return target;
		}
		
		// remove all member of an array from a target array
		this.removeAll = function(target, items){
			for(item in items){
				 this.remove(target, items[item])
			}
			return target;
		}
		
		this.pushAll = function(target, items){
			for(i in items){
				target.push(items[i])
			}
			return target;
		}
		
		this.forKeys = function (obj, callback){
			var proto = obj.constructor.prototype,
  			h = obj.hasOwnProperty, key;
 			for(key in obj) {
  				if((h && h.call(obj,key)) || proto[key] !== obj[key])
   				callback(key, obj[key]);
 			}
		};

		
	})();
	
	*/
	
	this.addExternalJS = function(jsLocation){
	    var scriptNode =  document.createElement('script');
	    scriptNode.type = 'text/javascript';
	    scriptNode.href = jsLocation;
        document.getElementsByTagName("head")[0].appendChild(scriptNode);
	}
	
	this.addStyleSheet = function(cssLocation){
	    var cssNode = document.createElement('link');
        cssNode.type = 'text/css';
        cssNode.rel = 'stylesheet';
        cssNode.href = cssLocation;
        cssNode.media = 'screen';
        cssNode.title = 'dynamicLoadedSheet';
        document.getElementsByTagName("head")[0].appendChild(cssNode);
	}
	

	
	/*
	
	this.inspectOjb = function(obj){
	
            var props = ['defineProperty','getOwnPropertyDescriptor','documentElement','contentDocument','contentWindow','defaultView','width','updateInterval','pixelDepth','logicalYDPI','logicalXDPI','height','fontSmoothingEnabled','deviceYDPI','deviceXDPI','colorDepth','bufferDepth','availWidth','availHeight','forward','go','back','statusText','status','responseXML','responseText','readyState','onreadystatechange','setRequestHeader','send','getResponseHeader','getAllResponseHeaders','abort','GetObject','ScriptEngineMinorVersion','ScriptEngineMajorVersion','ScriptEngineBuildVersion','ScriptEngine','getPrototypeOf','stack','lineNumber','fileName','reduceRight','reduce','some','map','every','forEach','filter','trimRight','trimLeft','trim','toLocaleUpperCase','toLocaleLowerCase','quote','localeCompare','arity','callee','caller','length','constructor','prototype','valueOf','toString','toLocaleString','toSource','toJSON','arguments','call','propertyIsEnumerable','isPrototypeOf','hasOwnProperty','parent','__parent__','__proto__','__defineSetter','__defineGetter__','__count__','__iterator__','__noSuchMethod__','__lookupGetter__','__lookupSetter__','__caller__','watch','unwatch','onpropertychange','dimensions','getItem','lbound','toArray','ubound','global','ignoreCase','multiline','source','compile','exec','test','$1','$2','$3','$4','$5','$6','$7','$8','$9','index','input','lastIndex','lastMatch','lastParen','leftContext','rightContext','MAX_VALUE','MIN_VALUE','NaN','NEGATIVE_INFINITY','POSITIVE_INFINITY','toExponential','toFixed','toPrecision','abs','acos','asin','atan','atan2','ceil','cos','exp','floor','log','max','min','pow','random','round','sin','sqrt','tan','E','LN2','LN10','LOG2E','LOG10E','PI','SQRT1_2','SQRT2','stringify','parse','Infinity','undefined','decodeURI','decodeURIComponent','encodeURI','encodeURIComponent','escape','eval','isFinite','isNaN','parseFloat','parseInt','unescape','apply','description','message','name','number','atEnd','item','moveFirst','moveNext','write','writeln','getDate','getDay','getFullYear','getHours','getMilliseconds','getMinutes','getMonth','getSeconds','getTime','getTimezoneOffset','getUTCDate','getUTCDay','getUTCFullYear','getUTCHours','getUTCMilliseconds','getUTCMinutes','getUTCMonth','getUTCSeconds','getVarDate','getYear','setDate','setFullYear','setHours','setMilliseconds','setMinutes','setMonth','setSeconds','setTime','setUTCDate','setUTCFullYear','setUTCHours','setUTCMilliseconds','setUTCMinutes','setUTCMonth','setUTCSeconds','setYear','toDateString','toGMTString','toLocaleDateString','toLocaleTimeString','toTimeString','toUTCString','UTC','concat','join','pop','push','reverse','shift','slice','sort','splice','unshift','anchor','big','blink','bold','charAt','charCodeAt','fixed','fontcolor','fontsize','fromCharCode','indexOf','italics','lastIndexOf','link','match','replace','search','small','split','strike','sub','substr','substring','sup','toLowerCase','toUpperCase','all','anchors','applets','areas','attributes','behaviorUrns','blockFormats','boundElements','cells','childNodes','children','controlRange','elements','embeds','filters','fonts','forms','frames','images','imports','links','mimeTypes','namespaces','options','pages','plugins','rows','rules','scripts','styleSheets','tBodies','add','addBehavior','AddChannel','AddDesktopComponent','addElement','AddFavorite','addImport','addPageRule','addReadRequest','addRule','alert','appendChild','appendData','applyElement','assign','atan','attachEvent','AutoCompleteSaveForm','AutoScan','blur','charCodeAt','ChooseColorDlg','clear','clearAttributes','clearData','clearInterval','clearRequest','clearTimeout','click','cloneNode','close','collapse','compareEndPoints','componentFromPoint','confirm','contains','createAttribute','createCaption','createComment','createControlRange','createDocumentFragment','createElement','createEventObject','createPopup','createRange','createStyleSheet','createTextNode','createTextRange','createTFoot','createTHead','deleteCaption','deleteCell','deleteData','deleteRow','deleteTFoot','deleteTHead','detachEvent','doImport','doReadRequest','doScroll','dragDrop','duplicate','elementFromPoint','empty','escape','execCommand','execScript','findText','fireEvent','firstPage','focus','fontColor','fontSize','getAdjacentText','getAttribute','getAttributeNode','getBookmark','getCharset','getClientRects','getData','getElementById','getElementsByName','getElementsByTagName','getExpression','getNamedItem','getTimezoneOffset','getYear','hasChildNodes','hasFocus','hide','ImportExportFavorites','inRange','insertAdjacentElement','insertAdjacentText','insertBefore','insertCell','insertData','insertRow','isEqual','IsSubscribed','javaEnabled','lastPage','mergeAttributes','move','moveBy','moveEnd','moveRow','moveStart','moveTo','moveToBookmark','moveToElementText','moveToPoint','namedItem','namedRecordset','navigate','NavigateAndFind','nextPage','normalize','open','parentElement','pasteHTML','previousPage','print','prompt','queryCommandEnabled','queryCommandIndeterm','queryCommandState','queryCommandValue','recalc','refresh','plugin','releaseCapture','remove','removeAttribute','removeAttributeNode','removeBehavior','removeChild','removeExpression','removeNode','removeRule','location','String','replaceChild','replaceData','replaceNode','reset','resizeBy','scroll','scrollBy','scrollIntoView','scrollTo','select','form','control','setActive','setAttributeNode','setCapture','setExpression','setTimeout','setUTCMilliseconds','show','ShowBrowserUI','showHelp','showModalDialog','showModelessDialog','small','splitText','start','stop','submit','substringData','swapNode','tags','taintEnabled','urns','Array','attribute','Boolean','clientInformation','clipboardData','currentStyle','dataTransfer','Date','defaults','Dialog','Helper','document','event','external','history','implementation','Math','mimeType','namespace','navigator','Number','Object','page','popup','rule','runtimeStyle','screen','selection','style','styleSheet','TextNode','TextRange','TextRectangle','userProfile','window','abbr','align','allowTransparency','appMinorVersion','availLeft','BaseHref','borderColor','boundingLeft','cancelBubble','cellSpacing','clientY','code','cols','cookieEnabled','ctrlKey','dataFld','defaultCharset','dialogLeft','doctype','effectAllowed','fgColor','fileUpdatedDate','frameElement','headers','hostname','httpEquiv','isContentEditable','keyCode','lastModified','LOG10E','lowsrc','Methods','noHref','offsetHeight','offsetY','ownerDocument','profile','readOnly','rel','rowIndex','scheme','screenX','scrollHeight','selected','shiftKey','sourceIndex','srcElement','tabStop','text','body','title','trueSpeed','type','textarea','URLUnencoded','vAlign','table','value','viewMasterTab','XMLDocument'];

    for(var prop in obj){
        localUtil.logger.debug(
            "obj." + prop + " = " + obj[prop]
        );
    }

    for(var i = 0; i < props.length; i++){
        if (obj[props[i]]){
            localUtil.logger.debug("obj." + props[i] + " = " + obj[props[i]]);
        }
    }



}

*/
	
})();
/*
 * 
 * Util2.js 
 * 
 */
 
PgmSrch.util.container = function(name){
    var container;
    var idsMapVal = PgmSrch.cnst.idsMap[name];
    if(idsMapVal instanceof Array){
        $jq(idsMapVal).each(function(i,item){
            if(i == 0){
                container = $jq("#" + item);
            }else{
                container = container.add($jq("#" + item));
            }
        })
    }else{
        container = $jq("#" + idsMapVal)
    }
	return container;
}

PgmSrch.util.getQueryParam = function(queryString, strParamName){
    var strReturn = ""
    var aQueryString = queryString.split("&");
    for ( var iParam = 0; iParam < aQueryString.length; iParam++ ){
      if ( aQueryString[iParam].indexOf(strParamName + "=") > -1 ){
        var aParam = aQueryString[iParam].split("=");
        strReturn = aParam[1];
        break;
      }
    }
    return strReturn;
}

PgmSrch.util.getURLParam = function(strParamName){
  var strReturn = "";
  var strHref = window.location.href;
  if ( strHref.indexOf("?") > -1 ){
    var strQueryString = strHref.substr(strHref.indexOf("?") + 1);
    strReturn = PgmSrch.util.getQueryParam(strQueryString, strParamName);
  }
  return unescape(strReturn);
}
/*
 * 
 *  Constants.js
 * 
 */
// PgmSrch.cnst may have already been defined. Don't destroy all of it if so.
PgmSrch.cnst = $jq.extend(PgmSrch.cnst || {}, function(){
	var self = {
	
		veveoXmlMap : {
		"Ver": "VerRENAME",
		"SVER": "server_version",
		"LRTM": "last_response_time",
		"n" : "number_of_results",
		"CF" : "cluster",
		"CI" : "terminal",
		"G": "asset_itentifier",
		"T": "title",
		"EPT": "episode_title",
		"RA" : "rating",
		"CBs": "fold_type",
		"YY" : "year",
		"SC" : "server_cookie",
		"D" : "description",
		"sr" : "star_rating",
		"C" : "cast",
		"H" : "host",
		"DI" : "director",
		"GN" : "genre",
		"L" : "language",
		"KW" : "keyword",
		"RE" : "reason_adult_only",
		"AI" : "action_item",
		"ty" : "item_type",
		"MI" : "more_info",
		"os" : "os",
		"CS" : "station_name",
		"VC" : "channel_number",
		"STID" : "station_id",
		"SHID" : "showid",
		"PPR" : "pay_per_view_price",
		"VOD" : "video_on_demand",
		"PVID" : "preview_id",
		"nr" : "num_results",
		"NR" : "num_results",
		"CST" : "asset_host_site",
		"TM" : "time",
		"un" : "submitted_by",
		"RF" : "url_to_watch",
		"SLK" : "clip_host",
		"CMI" : "thumb_url",
		"UT" : "tags",
		"RM" : "related_clips",
		"SBR" : "clips_from_same_site",
		"CNs" : "content",
		"RC" : "results",
		"TX" : "data",
		"xht" : "group_title",
		"SE" : "schedule_entry"
		
		
		},
		
		engToXML : function(english){
			for(key in self.veveoXmlMap){
				if(self.veveoXmlMap[key].toLowerCase() === english.toLowerCase()){
					return key;
				}
			}
			throw new Error("There's no tag corresponding to the word: " + english);
		},
		
		
		// PgmSrch.util.container(key) uses this. If the value is an array,
		// container(key) returns the first element found
		idsMap : {
			"DROPDOWN" : "dropdownContainer",
			// This is ugly, but it turns out that the id of the search box 
			// is a bit of a moving target, so exampine the query string and 
			// return to correct id based on that.
			"SEARCH_BOX" : (function(){
				var searchType = PgmSrch.util.getURLParam("type");
				ret = [];
				if(typeof searchType != "undefined"){
					ret = [{
						a:"epg",
						b:"epg2",
						c:"epg3",
						d:"epg4"
					}[searchType]];
				}

				return ret.concat(["epg","epgSrch", "epgSrch2", "epg2", "epg3", "epg4"]);
			})(),
			"GO_BUTTON" : "veveoSearchBtn",
			"RESULTS_ON_PAGE" : "resultsMain",
			"RELATED" : "related",
			"SEARCH_TITLE" : "searchTitle",
			"PREV_NEXT": "prevNext"
		},
			
		urls : {
			
			searchResults: "search.jsp"
		},
		
		months : [
		    "Jan",
		    "Feb",
		    "Mar",
		    "Apr",
		    "May",
		    "Jun",
		    "Jul",
		    "Aug",
		    "Sep",
		    "Oct",
		    "Nov",
		    "Dec"  
		],
		
		days: [
		    "Sun",
		    "Mon",
		    "Tue",
		    "Wed",
		    "Thu",
		    "Fri",
		    "Sat"
		],
		
		defaultRegionPK: 20054,
		
		defaultAjaxSettings : {
			XUA: "cvw",
			XUN: "",
			DS : "255",
			XPID: "pkg00@27.CABLEVISION",
			PN: 4
		},
		
		genreFilters: {
			ACTION: "G7",
			ACTION_ADVENTURE: "G1G7",
			ANIMATION: "G9",
			COMEDY: "G3"
		},
		
		messages: {
			NO_RESULTS : "No Results"
		},
		
            // searchUrl: "/proxy.jsp",
         searchUrl:"/search/veveo/proxy.jsp",
		
		//searchUrl : "test/data/VOD.xml",
		
		settings: {
		    resultsPerPage: 14
		},
		defaultSearchBoxText: "Search iO TV & On Demand" 
		
	};
	
	// set proxy url
	var url = window.location.toString();
	if(url.indexOf("http://localhost") > -1){
	  self.searchUrl = "/tvlistings/search/veveo/proxy.jsp";
	}else if(url.indexOf("tvlistings.optimum.net")){
	  self.searchUrl = "/search/veveo/proxy.jsp";
	}else{
  	  self.searchUrl = "/search/veveo/proxy";
	}

	return self;
}());
	
		
			
				
/*
* ESTDate.js
*/

/*
ESTDate is a class that is design to take a UTC moment and turn it in to a Date-like object which will ALWAYS translate into 
eastern standard time, regardless of how the users own system is set.

*/


PgmSrch.ESTDate = function(millis){
    
    var logger = new PgmSrch.util.namedLogger("PgmSrch.ESTDate");
    
    var HOURS_BEFORE_GMT = 5;
	
	millis = parseInt(millis);
	
	if(isNaN(millis)) {
	 	PgmSrch.util.logger.error("!!!!!!!!!!! Error in ESTDate: millis is NaN !!!!!!!!!!!!");
		throw new Error("ESTDate must be built using a number. The argument supplied to the constructor was: " + millis);
	}
	
	var MILLIS_PER_DAY = 1000 * 60 * 60 * 24;
	
	// this is a "real", anadultered Date. If we knew the users system was 
	// set correctly, we could just use this.
	var gmtDate = new Date(millis);
	
	// Loop through the time change dates that were set on the server side.
	var isDaylightSavings = function(date){
	    // loop through
	    for(var key in PgmSrch.cnst.dsts){
	        var timeChangeMoment = PgmSrch.cnst.dsts[key];
            // when we find a time change date that's later than the date 
            // in question, we know we're in daylight savings time if the later
            // switch date is an "end" date
	        if(date < timeChangeMoment.date){
	            return timeChangeMoment.type === "end"
	        }
	    }
	}
	
	// Now, we're going to create a new Date, and offset it from GMT by however much EST should be offset for 
	// a given moment. Then, when accessing the hours, minutes, etc of this date, we'll replace get[Hour|Minute|Day],
	// which varies depending on the user's system time zone, for getUTC[Hour|Minute|Day], which is always the same,
	// no matter what the user's system says.
	var date = new Date(millis);
    var estOffset = 60 * 60 * 1000 * HOURS_BEFORE_GMT;
    var dltOffset = isDaylightSavings(date) ? 60 * 60 * 1000 : 0;
    date.setTime(date.getTime() - (estOffset - dltOffset));
	var self = { 
	
		getDate: function(){
			return date.getUTCDate();
		},
		getDay:function(){
			return date.getUTCDay();
		},
		getFullYear:function(){
			return date.getUTCFullYear();
		},
		getHours:function(){
			return date.getUTCHours();
		},
		getMilliseconds:function(){
			return date.getUTCMilliseconds();
		},
		getMinutes:function(){
			return date.getUTCMinutes();
		},
		getMonth:function(){
			return date.getUTCMonth();
		},
		getSeconds:function(){
			return date.getUTCSeconds();
		},
		isGreaterThan: function(date /*Date*/){
		    return gmtDate > date;
		},
		isLessThan: function(date /*Date*/){
		    return gmtDate < date;
		}
	}
	return self;
}
PgmSrch.ForwardedSearchHandler = function(resultItemNavigator){
    
    var getParam = PgmSrch.util.getURLParam;
    var logger = PgmSrch.util.logger;
    var container = PgmSrch.util.container;
    
    return {
        run: function(){
            if(getParam("action") == "getDetails"){
                var parentItem = new PgmSrch.SerializedResultItem({
                    clusterOrTerminal: getParam("clusterOrTerminal"),
                             detailsQuery: getParam("detailsQuery"),
                             title: getParam("title"),
                             utcTime: getParam("utcTime"),
                             channelNumber: getParam("channelNumber"),
                             durationMinutes: getParam("durationMinutes"),
                             vodOrBroadcast: getParam("vodOrBroadcast"),
                             assetId: getParam("assetId")
                });
                resultItemNavigator.enterItem(parentItem);
            }
            
            if(getParam("query")){
                var searchBox = container("SEARCH_BOX")
                searchBox.get(0).value = getParam("query") || getParam("epg");
                searchBox.trigger(  { type : 'keyup', keyCode : 13, which: 13 } )  
            }
        }
    }
}

/*
 * 
 * Main.js 
 * 
 */

PgmSrch.Main =  function(){
	
	var self = {};
	var cnst = PgmSrch.cnst;
	var idsMap = PgmSrch.cnst.idsMap;
	var container = PgmSrch.util.container;
	var tmpl = PgmSrch.util.tmpl;	
	var lastXHR = false;
	var getURLParam = PgmSrch.util.getURLParam;
	var logger = new PgmSrch.util.namedLogger("Main.js");
	var mainSearchActionGroup = new PgmSrch.SearchActionGroup();
	    mainSearchActionGroup.name = "mainSearchActionGroup";
	    mainSearchActionGroup.setQueryFactory(PgmSrch.SearchQueryFactory());
	var dropdownSearchActionGroup =  new PgmSrch.SearchActionGroup();
	    dropdownSearchActionGroup.name = "dropdownSearchActionGroup";
	    dropdownSearchActionGroup.setQueryFactory(PgmSrch.NoFilterQueryFactory());
	var resultItemNavigator = container("RESULTS_ON_PAGE").length > 0 ?
	    new PgmSrch.SearchPageResultItemNavigator(self) :
	    new PgmSrch.ForwardingResultItemNavigator();
	    
    logger.debug("Running PgmSrch.Main");
	    
	var dropdownContainer;
	var currentPage = null;
	
	// put functions here that can't run until every external resource is loaded ()
	// the immediate reason I'm adding this is to give a way to wait until "popups.html" is loaded,
	// at the bottom of search.jsp
	var waitForResources = [];

	////////////////////////////////////////////
	// initialization
	////////////////////////////////////////////
	
	var positionDropdown = function(){
        var searchBoxPos = container("SEARCH_BOX").offset();
        dropdownContainer.css("top", (searchBoxPos.top + 30) + "px");
        dropdownContainer.css("left", searchBoxPos.left + "px");  
	};
	
	PgmSrch.TemplateRenderer.init();
    dropdownContainer = $jq(PgmSrch.TemplateRenderer.dropdownContainer.render()).appendTo($jq("body"));
    
	$jq(window).resize(function(){
	    positionDropdown();
	});
	
    var searchBoxInputHandler = new PgmSrch.SearchBoxInputHandler({
        searchBox: container("SEARCH_BOX"),
        searchButton:  container("GO_BUTTON"),
        main: self,
        searchActionGroup: dropdownSearchActionGroup,
        resultItemNavigator : resultItemNavigator
    });
    
    $jq("body").live("click", function(event){ 
        if(!event.isPropagationStopped()){
            dropdownContainer.hide();
            if(dropdownSearchActionGroup.getLastAction()){
                dropdownSearchActionGroup.getLastAction().selectNone();  
            };
        }
    });
	
	
    $jq(".pgmSrchResultsContainer .result").live("mouseover",function(){
        // bizzarre -- simply having this here seems to fix a bug where 
        // hover styles weren't being applied correctly in IE8
    })
	
	// event handler for clicking on results
	// should work for results in dropdown, in related box, and in main area
	$jq(".pgmSrchResultsContainer .result").live("click", function(event){
	    // set this data item to select
	    // populate related with searchgroup parent of data item	    
		var resultObject = $jq(this).data("data");
		resultObject.select();
		resultItemNavigator.enterItem(resultObject);
	});
	
	$jq(".prevNextContainer .prev").live("click", function(){
	    self.prevPage();
	});

  	$jq(".prevNextContainer .next").live("click", function(){
	     self.nextPage();
	});
	
	$jq("#dropdownContainer .viewAll").live("click", function(){
	    var action = dropdownSearchActionGroup.getLastAction();
	    self.initializeMainSearchActions(action);
	    self.scheduleRenderMain( action );
	})
	
	$jq(".prevNextContainer .pageNum").live("click", function(){
	    self.scheduleRenderMain(
	        mainSearchActionGroup.getPageAction(
	            $jq(this).text()
	        )
	    );
	})
	
	////////////////////////////////////////////
	// end event handlers
	////////////////////////////////////////////
	
	
	var renderResults = function(settings){
			
        try{

    		settings.resultsDiv.empty();	
    		settings.resultsDiv.show();
		
    		if(settings.resultItems.length == 0){
    		    $jq("<div class='noResults'>No results found.</div>").appendTo(settings.resultsDiv);
    		}else{
        		$jq(settings.resultItems).each(function(i, item){

                    try{
        		    
            			var resultHTML = settings.template.render(item);
            			var resultDom = $jq(resultHTML).appendTo(settings.resultsDiv);	
            			resultDom.data("data", item); // attach data to the dom object
            			if(i == 0){
            			    $jq(resultDom).addClass("first");
            			}
        			
        			}catch(e){
        			  $jq("<div style='border: solid 5px #333333; padding: 20px;'>Error processing: \"" + item.getTitle()  + "\":  " + e + "</div>").appendTo(settings.resultsDiv);
        			  logger.debug("ERROR: " + e);  
        			}
        		});
    		}
    	}catch(e){
    	    logger.debug("ERROR: " + e);
    	}
		
	}
	
	$jq.extend(self, { 
	    
	    init: function(){
	        var fn = function(){
	            new PgmSrch.ForwardedSearchHandler(resultItemNavigator).run(); // if landing on this page from another page, execute the search or handle the thingy
	        }
	        if(PgmSrch.resourcesToWaitFor.length == 0){
	            fn();
	        }else{
	            waitForResources.push(fn)
	        }
	    },
	    
	    resourceLoaded: function(name){
	        var newArray = [];
	        $jq(PgmSrch.resourcesToWaitFor).each(function(i, item){
	            if(item != name){
	                newArray.push(item)
	            }
	        });
	        PgmSrch.resourcesToWaitFor = newArray;
	        if(PgmSrch.resourcesToWaitFor.length == 0){
	            $jq(waitForResources).each(function(i,fn){
	                fn();
	            })
	        }
	    },
		
		scheduleRenderMain: function(searchAction){
			logger.debug("scheduleRenderMain called");
		    var searchResultsCallback = PgmSrch.searchResultsCallback;
		    if(typeof PgmSrch.searchResultsCallback !== "undefined"){
		        PgmSrch.searchResultsCallback()
		    }
	        self.setSearchTitle(searchAction.getTitle());
	        if(PgmSrch.doMRSSSearch && searchAction.getTitle()){
	            logger.debug("calling doMRSSSearch. Query is: " + searchAction.getTitle());
	            PgmSrch.doMRSSSearch(searchAction.getTitle());
	        }
		    currentPage = searchAction;
		    container("RESULTS_ON_PAGE").html("<H2 style='padding:40px'>LOADING...</H2>")
			searchAction.setCallback(function(){				
				renderResults({
						"resultItems":searchAction.getResultItems(), 
						"template":PgmSrch.TemplateRenderer.main, 
						"resultsDiv": container("RESULTS_ON_PAGE")
				});	
				
			    $jq( 
			        PgmSrch.TemplateRenderer.prevNext.render( 
			            new PgmSrch.PaginationContext(searchAction) 
			        )
			    ).appendTo( container("RESULTS_ON_PAGE") );
				
			});	
		},

		scheduleRenderDropdown: function(searchAction){
		    if(!searchAction){
		        return;
		    }
        	positionDropdown();
			searchAction.setCallback(function(){
    		    var resultsToRender = [];
    		    var resultItems = searchAction.getResultItems();
    		    
    		    for(var i = 0; i < 5; i++){
    		        if(resultItems[i]){
    		            resultsToRender.push(resultItems[i])
    		        }
    		    };
    		    
				renderResults({
						"resultItems":resultsToRender, 
						"template":PgmSrch.TemplateRenderer.dropdown, 
						"resultsDiv": dropdownContainer
				});
				searchBoxInputHandler.setResults(resultsToRender);
			});	
		},
		
		refreshDropdownSelection: function(){
		    $jq(".result", dropdownContainer).each(function(i, item){
		        var item = $jq(item);
		        var data = item.data("data");
		        if(data.isSelected()){
		            item.addClass("selected")
		        }else{
		            item.removeClass("selected");
		        }
		    })
		},
		
		
	    
	    drillDown: function(parentObject){
	        var query = parentObject.getDetailsQuery();
	        
	        logger.debug("Drilldown. query is: " + query);
	        
    		if(query){
	
		        logger.debug("about to call mainSearchActionGroup.newSearch");
    		    var newAction = 
    		        mainSearchActionGroup.newSearch({
    				    os:query
    			    });
    			newAction.setTitle( parentObject.getTitle() );

		        logger.debug("about to call scheduleRenderMain");
    			self.scheduleRenderMain(newAction);
    	    }
	    },
		
		setSearchBoxContents: function(val){
		    container("SEARCH_BOX").attr("value", val);
		},
		
		setSearchTitle: function(val){
    		container("SEARCH_TITLE").text(val);
		},
		
		getMainSearchActionGroup: function(){
		    return mainSearchActionGroup;
		},

		getDropdownSearchActionGroup: function(){
		    return dropdownSearchActionGroup;
		},
		getSearchBoxInputHandler: function(){
		    return searchBoxInputHandler;
		},
		getDropdownContainer: function(){
		    return dropdownContainer;
		},
		hideRelated: function(){
    	    container("RELATED").fadeOut("slow", function(){
    		    container("RELATED").hide();
    	    });
		},
		showRelated: function(){
		    container("RELATED").show();
		},
		initializeMainSearchActions: function(action){
		    mainSearchActionGroup.acceptFirstAction(action)
		},
		setMainSearchActionGroup: function(group){
		    mainSearchActionGroup = group;
		},
		nextPage: function(){
		    self.scheduleRenderMain(
	            currentPage.getNextPageAction()
	        );
		},
		prevPage: function(){
    	    self.scheduleRenderMain(
    	        currentPage.getPrevPageAction()
    	    );
		},
		goToPage: function(){
    	    self.scheduleRenderMain(
    	        mainSearchActionGroup
    	    );
		}
	});
	
	// run any functions that need to happen after everything is initialized
	$jq(PgmSrch.initializedCallbacks).each(function(i, fn){
	    fn();
	});
	
	return self;


};
	
PgmSrch.PaginationContext = function(searchAction) {
    
    var logger = new PgmSrch.util.namedLogger("PaginationContext");

    var visiblePageNums = 7;
    
    var distFromCenter = function(){
        return (visiblePageNums - 1) / 2;
    }
    
    var numPages = function(){
        return Math.ceil(
            searchAction.getNumResultsInGroup() /
            PgmSrch.cnst.settings.resultsPerPage
        );   
    }

    var self = {
        hasPrevPageAction: function() {
            return searchAction.hasPrevPageAction();
        },
        hasNextPageAction: function() {
            return searchAction.hasNextPageAction();
        },
        getPageNums: function() {
            var ret = [];
            
            var currentPageIndex = searchAction.getIndexInAllActions();
            
            var startIndex = Math.max(
                0,
                currentPageIndex - distFromCenter()
            );
            
            var endIndex = 
                Math.max(
                     Math.min(
                        numPages() - 1,
                        visiblePageNums - 1
                    ),
                    Math.min(
                        numPages() - 1,
                        currentPageIndex + distFromCenter()
                    )
                );
                
            for (var i = startIndex; i <= endIndex; i++) {
                ret.push(i + 1)
            };
            
            if ( ret[0] === 2 ) {
            	ret.splice(0, 0, "1");
            };
            
            return ret;
        },
        getIndexInAllActions: function() {
            return searchAction.getIndexInAllActions()
        },
        getVisiblePageNums: function(){
            return visiblePageNums;
        },
        setVisiblePageNums: function(num){
            if(num % 2 != 0 ){
                throw new Error("Please use odd numbers of pages.");
            };
            visiblePageNums = num;
        },
        lastPageLinkDisplayed: function(){
            var pageNums = self.getPageNums();
            return pageNums[pageNums.length - 1] == numPages()
        },
        forceDisplayFirstPageLink: function(){
            return self.getPageNums()[0] > 2 ;
        }
    };
    
    return self;


};
/*
*
* SearchAction.js
* A search action represents a call to the Veveo servers.
* Each search action is owned by a group. When a group has multiple search
* actions, these search actions represent pages.
*
*/


PgmSrch.SearchActionGroup =  function(){
	
 	var logger = new PgmSrch.util.namedLogger("SearchActionGroup");
 	var actions = [];
	var resultObjectFactory = function(){return PgmSrch.resultObjectFactory;};
	var queryFactory;
	var group = this;
	var defaultSettings = {
	    "searchURL":PgmSrch.cnst.searchUrl
	};
	
	
	var group = this;
	
	var settings = defaultSettings;
	
	this.reset = function(){
	    actions = [];
	};
	
	this.getActionLength = function(){
	    return actions.length
	}
	
	this.customSettings = function(customSettings){
	    settings = $jq.extend(settings, customSettings);
	}
	
	this.setQueryFactory = function(QueryFactory){
		queryFactory = QueryFactory;
	};
	
	this.getFirstAction = function(){
        return actions[0];
	}
	
	this.getLastAction = function(){
	    return actions[actions.length - 1];
	}
	
	this.getLastXHR = function(){
	    if(actions.length > 0){
	        return actions[actions.length - 1].getXHR();
	    }
	}

    this.newSearch = function(query){
    	/* kind of complicated -- new search needs to have the last search 
    	 * available, but then we need to clear the search
    	 */
        return this.acceptFirstAction( this.newSearchAction(query)); 
    };
 	
 	this.acceptFirstAction = function(action){ 
		logger.debug("acceptFirstAction called");
 	    actions = [action];
 	    action.setGroup(this);
 	    return action;
 	},
 	
 	this.getIndexInAllActions = function(action){
 	    
 	    for (var i=0; i < actions.length; i++) {
 	      if (actions[i] === action){
 	          return i;
 	      }
 	    };
 	}
 	
 	this.getNextPageAction = function(){
 	    return this.getPageAction(action.length - 1)
 	}
 	
 	this.newSearchAction =  function(baseQuery){
 	    var action =  new SearchAction( baseQuery );
        actions.push(action);
			logger.debug("adding new action. actions is: " + actions);
 		return action;
 	}
 	
 	this.getPageAction = function(page){
 	    
 	    
 	    var pageAction = function(){
 	        return actions[page - 1]    
 	    };
 	    
 	    var ret = pageAction();
 	    if(!ret){
 	        ret = new ProxySearchAction({
 	            onSetCallback: function(originalCallback){
                    var loadNext = function(){ // watch out! recursion! 
                        
                        var nextAction = group.getLastAction().getNextPageAction();
                        
                        nextAction.setCallback(function(){
                            if(pageAction()){                         
                                 // once we have the final searchAction, insert it into the proxy       
                                ret.setRealSearchAction(pageAction());
                                originalCallback(pageAction());
                            }else{
                                loadNext();
                            }
                        })
                    };
                    
                    loadNext();
 	            }
 	        });
 	    };
 	    return ret;
 	}
 	
 	// If the last item has no next page, we can calculate the number
 	// of results exactly. Otherwise, just use the "NR" tag, which isn't always
 	// accurate.
 	this.getNumResults = function(){
 	    var ret;
 	    if(actions.length === 0){
 	        ret = 0;
 	    }else if(this.getLastAction().hasNextPageAction()){
 	        ret = this.getLastAction().getReportedResultsInGroup();
 	    }else{
 	        ret = (actions.length - 1) * PgmSrch.cnst.settings.resultsPerPage;
 	        ret += this.getLastAction().getNumResults();
 	    }
        return ret;
 	}
 	
 	// used for paging, when initiating a random-access page load. This object acts as a stand-in for the real
 	// SearchAction, which doesn't exist yet
 	var ProxySearchAction = function(settings){
 	    var realSearchAction;
        return {
            setCallback: function(fn){
                settings.onSetCallback(fn)
            },
            setRealSearchAction: function(actionArg){ // eventually, there will be a real searchAction 
                realSearchAction = actionArg;
            },
            getTitle: function(){
                return group.getLastAction().getTitle();
            },
            getResultItems: function(){
                return realSearchAction.getResultItems();
            }, 
    		hasPrevPageAction: function(){
		        return realSearchAction.hasPrevPageAction();
		    },
		    hasNextPageAction: function(){
		        return realSearchAction.hasNextPageAction();
		    },     
			getNumResultsInGroup: function(){
		        return realSearchAction.getNumResultsInGroup();
			},
		    getPrevPageAction: function(){
		        return realSearchAction.getPrevPageAction();
		    },
		    getNextPageAction: function(){
		        return realSearchAction.getNextPageAction();
		    },
		    getIndexInAllActions: function(){
		        return realSearchAction.getIndexInAllActions()
		    },
		    toString: function(){
		        return "a ProxySearchAction";
		    }
        }
 	}
 	
	var SearchAction =  function(baseQuery){
 	
 	    var logger = new PgmSrch.util.namedLogger("SearchAction");
     	var title;
     	var parentGroup = group;
     	var parentQuery;
 	    if(group.getLastAction()){
 	        parentQuery = group.getLastAction().getQuery();
 	    };
 	    var query = queryFactory.buildQuery(baseQuery, parentQuery);
 	    
		var xmlResults, resultItems, callback, xhrComplete = false, callbackCalled = false, xhr;
		var nextAction = null; // next page of search results
		var prevAction = null; // prev page of search results
		var lastXHR = group.getLastXHR();
		var nextPageOs;
        if(lastXHR){
           if(lastXHR.readyState !== 4){
               lastXHR.abort();
            }
        }
		
		xhr = $jq.get(
			settings.searchURL,
			$jq.extend(
			    query, 
			    PgmSrch.cnst.defaultAjaxSettings,
			    {
					XPID: "pkg00@" + PgmSrch.region.getHubID() + ".CABLEVISION",
			        url:"http:\/\/" + PgmSrch.region.getVeveoIp() + "\/search"
			    }
			),
			function(xmlResultsArg){
				xmlResults = xmlResultsArg;
				resultItems = resultObjectFactory().wrapXML(xmlResults, self);
				doCallback();
				xhrComplete = true;
			},
			"xml"
		);
		
		var doCallback = function(){
			if(callback){
				callbackCalled = true;
				callback(self);
				callback = function(){};
			}
		};
		
		var failIfCallbackNotCalled = function(){
			if(!callbackCalled){
				throw new Error("Error in " + failIfCallbackNotCalled.caller + ". You can't call a getter before the callback has been called. Getter methods should always be called from inside a function which is set via setCallback.");
			}
		}
		
		var self = {
		    
		    toString: function(){
		        return "a SearchAction";
		    },
		    
			getXMLResults : function(){
				failIfCallbackNotCalled();
				return xmlResults;
			},
			getResultItems: function(){
				failIfCallbackNotCalled();
				return resultItems;
			},
			setCallback: function(fn){				
				callback = fn;	
				if(xhrComplete){
					doCallback();	
				}
			},
			getQuery: function(){
			    return query
			},
			
            getNextPageOs: function(){
				failIfCallbackNotCalled();
				if(!nextPageOs){
				    nextPageOs = $jq("od", self.getXMLResults()).text();
				}
                return nextPageOs;
            },
            getSC: function(){
				failIfCallbackNotCalled();
                return $jq("SC", self.getXMLResults()).text() 
            },
            setPrevPageAction: function(action){
                prevAction = action;
            },
		    getPrevPageAction: function(){
		        return prevAction;
		    },
    		hasPrevPageAction: function(){
		        return prevAction? true:false;
		    },
		    hasNextPageAction: function(){
				failIfCallbackNotCalled();
		        return self.getNextPageOs()? true:false;
		    },
		    getNextPageAction: function(){
    			failIfCallbackNotCalled();
		        if(!nextAction){
		            var query = {
            			os: escape(self.getNextPageOs())
            		};
            		if(self.getSC()){
            		    query.sc = escape(self.getSC());
            		}
        		    nextAction = parentGroup.newSearchAction(query)	  
		        };
		        nextAction.setPrevPageAction(self);
		        return nextAction; 
		    },
		    setGroup: function(group){
		        parentGroup = group;
		    },
		    getGroup: function(){
		        return parentGroup;
		    },
			getXHR: function(){
			    return xhr;
			},
			selectNone: function(){
			    self.selected = null;
			},
			getSelectedItem: function(){
			    return self.selected;
			},
			setSelectedItem: function(item){
			    self.selected = item;
			},
			setTitle: function(titleArg){
			    title = titleArg;
			},
			getTitle: function(){
			    var ret;
			    if(title){
			        return title
			    }else if(self.getPrevPageAction()){
			        ret = self.getPrevPageAction().getTitle()
			    }
    		    return ret;
			},
			getNumResultsInGroup: function(){
    			failIfCallbackNotCalled();
    			return group.getNumResults();
			},
			getNumResults: function(){
			    return resultItems.length;
			},
			getReportedResultsInGroup: function(){
			    return $jq("NR", self.getXMLResults()).text();
			},
			getIndexInAllActions: function(){
			    var ret = self.getGroup().getIndexInAllActions(self);
			    if(typeof ret === "undefined"){
			        throw new Error("Every action should always have an index.")
			    }
			    return ret;
			}
		};
		
		return self;
 	}				
 
 };
 
 
 
/*
*
* SearchBoxInputHandler.js
*
*/


PgmSrch.SearchBoxInputHandler = function(settings){
    
    var main = settings.main;
    var dropdownSearchActionGroup = settings.searchActionGroup;
    var searchBox = settings.searchBox;
    var logger = new PgmSrch.util.namedLogger("PgmSrch.SearchBoxInputHandler");
    var selectedIndex = -1;
    var results;
    var inputSearch= "";
    var resultItemNavigator = settings.resultItemNavigator;
    
    var lastAction = function(){
        return dropdownSearchActionGroup.getLastAction();
    };
    
    var newSearch = function(){
        var searchAction;
        selectedIndex = -1;
		// only look at the visible search box. More, invisible ones were added.
        inputSearch = searchBox.filter(":visible").attr("value");
        if(inputSearch){
            var searchAction = dropdownSearchActionGroup.newSearch({
                 w:escape(inputSearch)
             });
             searchAction.setTitle(inputSearch);
             main.scheduleRenderDropdown(searchAction);
             return searchAction;
        }
    };
    
    var keys = {
        37: "LEFT",
        39:"RIGHT",
        38: "UP",
        40: "DOWN",
        13: "RETURN"
    }; 
    
    
    var moveSelect = function(dir){
        if(results){
            selectedIndex = Math.max(
                -1,
                Math.min(
                    results.length - 1,
                    selectedIndex + dir
                )  
            );
            var toSelect = results[selectedIndex];
            if(toSelect){
                toSelect.select();
                // main.setSearchBoxContents( toSelect.getTitle() ); // don't update the search box
            }else{
                // searchBox.attr("value", inputSearch);
                lastAction().selectNone() 
            }
        };
        // this is really messed up, but it seems that adding this statement
        // fixes this bug: http://trac.emedia.cv.net/veveosearch/ticket/60
        logger.debug("selected item is now: " + lastAction().getSelectedItem() )
    }
    
    PgmSrch.initializedCallbacks.push(function(){
        // if the search box was focused on before all of 
        // the scripts loaded, run the search now
        if(PgmSrch.focusedInput === searchBox.get(0) ){
            newSearch()
        }
    })
    
    searchBox.click(function(){
        if(searchBox.attr("value") === PgmSrch.cnst.defaultSearchBoxText){
            searchBox.attr("value", "");
        }
        newSearch();
    });
    
    settings.searchButton.live("click", function(){
        PgmSrch.util.container("DROPDOWN").hide();
        if(!lastAction()){
            newSearch();
        };    
        resultItemNavigator.resultsToMainArea( lastAction() )
        
    });
    
    searchBox.keyup(function(e){   
        
        var utilKey = keys[ e.keyCode || e.which ]; 

        if(!utilKey){
             newSearch();
        }else{
            switch(utilKey){
                case "DOWN":
                    moveSelect(1);
                    break; 
                case "UP":
                    moveSelect(-1);   
                    break; 
                case "RETURN":
                
                    logger.debug("return was pressed");
                    PgmSrch.util.container("DROPDOWN").hide();
                    if(!lastAction()){
                        newSearch();
                    };
                    
                    if(lastAction().getSelectedItem()){ // if an item in the dropdown is selected
                         resultItemNavigator.enterItem(lastAction().getSelectedItem());
                    }else{ // otherwise, just use the current search and put it in the main area
                         resultItemNavigator.resultsToMainArea( lastAction() )
                    };                    
                    break;
            };
            
            main.refreshDropdownSelection();
        };
        
    });
    
    var self = {
        setResults: function(resultsArg){
            dropdownSearchActionGroup.getLastAction().selectNone();
            results = resultsArg;
        },
        getResults: function(){
            return results;
        }
    }
    return self;
}
PgmSrch.region = (function(){
   
    var get_cookie = function ( cookie_name ){
      var results = document.cookie.match ( '(^|;) ?' + cookie_name + '=([^;]*)(;|$)' );

      if ( results )
        return ( unescape ( results[2] ) );
      else
        return null;
    }

    
    // var defaultDevIP = "10.251.127.4";
    var defaultDevIP = "167.206.10.80";
    
    if(window.location.toString().indexOf("http://local.tvlistings") > -1){
        defaultDevIP = "10.251.218.19";
    }

    var sscToIpMapping = {
        
        
        // 1: defaultDevIP,
        // 2: defaultDevIP,
        // 3: defaultDevIP,
        // 4: defaultDevIP,
        // 5: defaultDevIP,
        // 6: defaultDevIP
        
       
        1: "167.206.10.75",
        2: "167.206.10.76",
        3: "167.206.10.77",
        4: "167.206.10.78",
        5: "167.206.10.79",
        6: "167.206.10.80"
    
    }

    var hubToSSCMapping = {
        1: [49,50,51,52,53,54, 44,45,46,47,48,70,71,72],
        2: [18,19,20,23,55,56,57,58,59,60,61,62,63,64,65,66,67,73],
        3: [2,3,4,5,15,26,8,9,10,11,12,13,17,68,69],
        4: [6,7,14,36,37,74],
        5: [28,29,30,38,40,41,43,42,31,16,24,25,32,33,34,35,39],
        6: [27, 92]
    }

    var regionToHubMapping = {
        20075: 39,
        20065: 37,
        20069: 28,
        20045: 66,
        20048: 8,
        20015: 49,
        20028: 44,
        20049: 6,
        20037: 58,
        20046: 73,
        20083: 10,
        20074: 38,
        20072: 34,
        20051: 7,
        20052: 75,
        20067: 24,
        20053: 9,
        20041: 61,
        20054: 5,
        20064: 36,
        20070: 32,
        20042: 62,
        20056: 14,
        20031: 19,
        20057: 76,
        20044: 65,
        20033: 23,
        20058: 11,
        20081: 79,
        20080: 41,
        20076: 40,
        20077: 29,
        20040: 60,
        20039: 59,
        20066: 74,
        20068: 25,
        20035: 56,
        20079: 77,
        20078: 78,
        20059: 10,
        20060: 15,
        20073: 35,
        20043: 64,
        20071: 33,
        20032: 20,
        20062: 12,
        20063: 17,
        20030: 18,
        20034: 55,
        20036: 57
    }
   
   var self = {
       
       getVeveoIp: function() {

           var ret = null;
           $jq.each(hubToSSCMapping, function(ssc, val){
               if($jq.inArray(self.getHubID(), val) >= 0 ){
                   ret = sscToIpMapping[ssc];
               }
           })
           if (ret!==null) {
        	   return ret;
           } else {
        	   return "167.206.10.80";
        	   
           }
       },
       
       getHubID: function(){
           var regionPK =  PgmSrch.cnst.defaultRegionPK; 

           if(get_cookie("oolpantry")){
               regionPK = get_cookie("oolpantry").split("|")[0].split("=")[1];
           }
           if (regionToHubMapping[regionPK]!==undefined) {
        	   return regionToHubMapping[regionPK]
           } else {
        	   return "27";
           }
       }
       
       
       
   }
   
   return self;
    
})()
PgmSrch.load = (function() {

    var DEV_TEST = "http://dev.east.";
    var STAGE_TEST = "http://stage.east.";
    var LOCAL_TEST = "http://local.";

    var DEV_BASE_PATH = "http://dev.east.tvlistings.optimum.net";
    var STAGE_BASE_PATH = "http://stage.east.tvlistings.optimum.net";
    
    // for deployment to prod, change this to "tvlistings.optimum.net"
    var PROD_BASE_PATH = "http://east.tvlistings.optimum.net";
    
    var LOCAL_BASE_PATH = "http://local.tvlistings.optimum.net"
    var basePath;
    var isProd = false;

    return {

        getBasePath: function() {
          
          //test
          
            if(window.location.toString().indexOf("localhost:8080/tvlistings") > -1){
              return "http://localhost:8080/tvlistings";
            }

            var testLoc = function(loc) {
                return window.location.toString().indexOf(loc) != -1
            }

            if (testLoc(DEV_TEST)) {
                basePath = DEV_BASE_PATH;
            } else if (testLoc(STAGE_TEST)) {
                basePath = STAGE_BASE_PATH;
            } else if (testLoc(LOCAL_TEST)) {
                basePath = LOCAL_BASE_PATH;
            } else {
                basePath = PROD_BASE_PATH;
            }

            return basePath;

        }

    }

})()
/*
 * 
 * NoFilterQueryFactory.js 
 * Subclass of SearchQueryFactory that returns an empty getFilterList
 */
 
 PgmSrch.NoFilterQueryFactory = function() {

	var that = new PgmSrch.SearchQueryFactory();

	that.getFiltersList = function() {
		var filtersList = [];
		return filtersList;
	};

	return that;

};



/*
 * 
 * SearchQueryFactory.js 
 * Handles caching of queries, and gathering extra attributes such as filters to add in.
 * Rules are as follows:
 * - If no query is supplied, use the "w" and "os" values from the previous parameter.
 * - If no query is supplied, or query.sc is undefined, build sc value by examining 
 *   selected filters.
 */
 
 PgmSrch.SearchQueryFactory = function(){
     
     
    var logger = new PgmSrch.util.namedLogger("SearchQueryFactory");
 
 	var buildSCParam = function(){
 	    var filtersList = self.getFiltersList();
 		var sCParam;
 		var filLen = filtersList.length;
 		if(filLen > 0){
 			sCParam = filLen + "-";
 			for(var i = 0; i < filLen; i++){
 				sCParam += filtersList[i];
 				if(i < filLen - 1 ){
 					sCParam += ",";	
 				}
 			}
 		};
 		return sCParam;
 	}
 	
 	var lastBaseQuery = {};
 	
 	var self = {
 		
 		getFiltersList : function(){
 			var filtersList = [];
 	 		$jq("#filterBy .filterItems .selected, .filterTabs .selected").each(function(i, item){
 				var filterValue = $jq(item).data("filterValue");
	 			if (filterValue) {
    	 			filtersList.push(filterValue);  
	 			};
 			});
            return filtersList;
 		},
 		
 		buildQuery : function(baseQueryArg){
 		    
 			var baseQuery;
 			
 			// if a base query is passed in, use that for search,
 			if(baseQueryArg){
 				baseQuery = baseQueryArg
 				lastBaseQuery = $jq.extend({}, baseQuery); // copy the object
 			}else{  // otherwise, reuse the w and os values from the parent query
 				baseQuery = {} 
                $jq(["w", "os"]).each(function(i, paramKey){
 				    if(lastBaseQuery[paramKey]){
 				        baseQuery[paramKey] = lastBaseQuery[paramKey];
                    };
 				});
 			}
 			
 			var sCParam = buildSCParam();
 			
 			if((typeof sCParam !== "undefined") && (!baseQuery.sc)){
 				baseQuery.sc = sCParam;	
 			}
 			
 			var ret = $jq.extend({}, PgmSrch.cnst.defaultAjaxSettings, baseQuery);
 			
 			ret.XPID = PgmSrch.region.getHubID();
 			
			return ret;
			
 		}
 		
 		
 	};
 	
 	return self;
 
 };



/*
*
* ResultItem.js
*
*/

// See ResultObjectFactory for the construction of these objects
// Each of the functions listed below wraps an XML node in an object with getters.
// Each node we're working with gets wrapped first with ResultItem. After that,
// the resulting object can be passed to an additional function (i.e. TerminalResultItem) 
// to have more methods added. This can be looked at as a type of inheritance.

(function(){
    
    var descendInToXml = function(node, path){ 
        var ret = node;
        for(var i = 0; i< path.length; i++){
            ret = path[i](ret);
            if(!ret){
                break
            }  
        };
        return ret;
    };
    
    var cnst = PgmSrch.cnst;

    PgmSrch.ResultItem = function(xmlDoc){
    	var engToXML = PgmSrch.cnst.engToXML;
	
    	var logger = PgmSrch.util.logger;
    	var searchAction = null;
	
    	var self = {
    		xmlDoc : xmlDoc,
    		logger : PgmSrch.util.logger,
    		engToXML : engToXML,
    		queryXML : function(nodePath){

            
    		    logger.startTimer("queryXML");

                var context = arguments[1] || xmlDoc;
   
    			for(var i = 0; i < nodePath.length; i++){
    				var veveoTagname = nodePath[i];
    				if(veveoTagname !== ">"){
    					veveoTagname = engToXML(veveoTagname);
    				};
    				if(veveoTagname){
    					nodePath[i] = veveoTagname;
    				};
    			};
    			nodePath = nodePath.join(" ");
			
    			var ret = $jq(nodePath, context).text();
    		    logger.stopTimer("queryXML");

    			return ret;

    		},
    		getTitle : function(){   

    			return descendInToXml(xmlDoc, [

    		        function(obj){
        		        return obj.getElementsByTagName('T')
        		    },
        		    function(obj){
        		        return obj[0]
        		    },   
        		    function(obj){
            		    return obj.getElementsByTagName('TX')
        		    },
        		    function(obj){
        		        return obj[0];
        		    },
        		    function(obj){
        		        return obj.childNodes;
        		    },
        		    function(obj){
        		        return obj[0];
        		    },
        		    function(obj){
        		        return obj.data
        		    }
    		    ]);
    		},
		
    		getEpisodeTitle: function(){},
		
    		getTerminalType : function(){
    			return self.queryXML([">", "item_type"]);
    		},
    		getFoldType : function(){
    			return self.queryXML(["fold_type"]);
    		},
    		getDescription : function(){
            
    			return descendInToXml(xmlDoc, [
		    
    		        function(obj){
        		        return obj.getElementsByTagName('D')
        		    },
        		    function(obj){
        		        return obj[0]
        		    },   
        		    function(obj){
            		    return obj.getElementsByTagName('TX')
        		    },
        		    function(obj){
        		        return obj[0];
        		    },
        		    function(obj){
        		        return obj.childNodes;
        		    },
        		    function(obj){
        		        return obj[0];
        		    },
        		    function(obj){
        		        return obj.data
        		    }
    		    ]);
    		},
    		getStationName : function(){},
    		getCast : function(){},
    		getDirector : function(){},
    		getDetailsQuery : function(){
			
    		},
    		//is it a fold or a terminal?
    		getItemType : function(){
    			var tagName = $jq(xmlDoc).get(0).tagName.toLowerCase();
    			var ret = "terminal";
    			if(tagName === engToXML("cluster").toLowerCase()){
    				ret = "cluster";		
    			}else if(tagName === "n"){
    				ret = null;	
    			};
    			return ret;
    		},
    		getDetailsActionOS : function(){},
    		getPrettyDate : function(){
    		    self.logger.warn("call to unimplemented getPrettyDate in " + self.getTitle());
    		    return null;
    		},
    		getDate : function(){	
    		    self.logger.warn("call to unimplemented getDate in " + self.getTitle()); 
    		    return null;
    		},
    		getSearchAction: function(){ // returns the searchAction that created this item
    		    return searchAction;
    		},
    		setSearchAction: function(obj){
    		    if(searchAction){throw new Error("searchAction should only be set once")}
    		    searchAction = obj;
    		},
    		select: function(){
    		    searchAction.setSelectedItem(self);
    		},
    		isSelected: function(){
    		    return self === searchAction.getSelectedItem();
    		}
    	};
    	return self;
    }


    PgmSrch.ClusterResultItem = function(prototype){
    	// ClusterResultItem is sort of a subclass of PgmSrch.ResultItem
    	var self = prototype;
    	$jq.extend(self,{
    		// these are the functions we're extending the prototype with
    		getMovieOrTV : function(){
    			return null;
    		},
		
    		getVodOrBroadcast: function(){
    		  return null;  
    		},
		
    		getDetailsQuery: function(){
    			return self.queryXML(["os"])
    		},
    		getClusterOrTerminal: function(){
    		    return "cluster";
    		},
    		asQueryString: function(){
    		    var ret =  
    		        "clusterOrTerminal=" + 
    		        escape( self.getClusterOrTerminal() ) +
    		        "&" +
    		        "detailsQuery=" +
    		        escape( self.getDetailsQuery() ) +
    		        "&" +
    		        "title="+
    		        escape( self.getTitle() );
    		    return ret;
    		}
    	});
    	return self;
    }

    PgmSrch.TerminalResultItem = function(prototype){
    	// TerminalResultItem is sort of a subclass of PgmSrch.ResultItem
    	var self = prototype;
    	var cnst = PgmSrch.cnst;
    	
    	var hasAiType = function(type){
    	    var ret = false;
    	    $jq("AI", self.xmlDoc).each(function(i, node){
        	        var itemType = self.queryXML(["ITEM_TYPE"], node);
        	        if(itemType == type){
        	            ret = true;
        	            return false;
        	        }
        	    });
        	return ret;
    	}
    	
    	$jq.extend(self,{
    		// these are the functions we're extending the prototype with
    		getMovieOrTV : function(){
    			var terminalType = self.getTerminalType();
    			if(terminalType === "4" || terminalType === "10"){
    				return "movie";
    			}else{
    				return "tv";
    			}
    		},
    		
    		hasVOD: function(){
    		   return hasAiType("VOD");
    		},
    		
    		hasBroadcast: function(){
    		   return hasAiType("SE");
    		},
    		
    		getVodOrBroadcast: function(){
    		    var returnVal = "broadcast";
        	    $jq("AI", self.xmlDoc).each(function(i, node){
        	        var itemType = self.queryXML(["ITEM_TYPE"], node);
        	        if(itemType == "VOD"){
        	            returnVal = "vod";
        	            return false;
        	        }
        	    });   
        	    return returnVal;
    		},
    		getDetailsQuery: function(){
    		    var returnVal;
    		    $jq("AI", self.xmlDoc).each(function(i, node){
    		        var itemType = self.queryXML(["ITEM_TYPE"], node);
    		        if(itemType == "MI"){
    		            returnVal = self.queryXML(["OS"], node)
    		            return false;
    		        }
    		    });
    			return returnVal;
    		},
		
    		getMainActionNode: function(){
    		    var ret;
        	    $jq("AI", self.xmlDoc).each(function(i,node){
        	        var jqNode = $jq(node);
        	        var item_type = jqNode.find(self.engToXML("ITEM_TYPE")).text();
        	        if(item_type === "SE" || item_type === "VOD"){
        	            ret = jqNode;
        	            return false;
                    }
        	    });
        	    return ret;
    		},
		
    		getAttr: function(){
    		    var node = self.getMainActionNode();
    		    return node.find("ATTR").text();
    		},
		
    		getStationName: function(){
    		    return self.getMainActionNode().find(self.engToXML("STATION_NAME")).find(self.engToXML("DATA")).text();
    		},
    		
    		getStationLogo : function(){
    		    return cnst.channelLogos[self.getStationName()];
    		},
		
    		getChannelNumber: function(){
    		    return self.getMainActionNode().find(self.engToXML("CHANNEL_NUMBER")).find(self.engToXML("DATA")).text();
    		},
      		getClusterOrTerminal: function(){
    		    return "terminal";
    		},
    		getAttr: function(){
    		    return self.getMainActionNode().find("ATTR").text().split(":")
    		},
    		isNew: function(){
    		    return $jq.inArray("NEW", self.getAttr()) > 0;
    		},
    		getRating: function(){
    		    throw new Error("getRating not yet implemented");
    		},
    		isNoResultsNode : function(){
    			return $jq( self.engToXML("title"), self.xmlDoc ).text() === "No Results";
    		},
    		getDurationMinutes : function(){
    		    throw new Error("getDurationMinutes must be implemented in a subclass.");
    		},
    		getPrettyDuration: function(){
    		    var totalMinutes = self.getDurationMinutes();
    		    var hours =  Math.floor( totalMinutes / 60 );
    		    var minutes = totalMinutes % 60;
    		    var ret = "";
    		    if(hours > 0){
    		        var hourText = hours == 1 ? "hour":"hours";
    		        ret += hours + "&nbsp;" + hourText;
    		        if(minutes > 0){
    		            ret += ", "
    		        }
    		    };
    		    if(minutes > 0){
    		        ret += minutes + "&nbsp;minutes"
    		    };
    		    return ret;
    		    
    		}
    	}); 
    	return self;
    }


    PgmSrch.VODResultItem = function(prototype){
        var logger = new PgmSrch.util.namedLogger("VODResultItem");
    	var self = prototype;
    	$jq.extend(self,{
    	    
    	    getVodOrBroadcast: function(){
    	      return "vod"  
    	    },
    	    
    	    getPrice: function(){
    	        var ret = null;
    	        var num = $jq("VPR", self.xmlDoc).text();
    	        if(num == 0){
    	            ret = "Free/Subscription"
    	        }else{
    	            ret = "$" + String(num)
    	        }
    	        return  ret;
    	    },
    	    
    	    getDurationMinutes: function(){
    	        var ret, os, MINUTES_PER_HOUR = 60;
    		    $jq("AI", self.xmlDoc).each(function(i,node){
    		        var 
    		            jqNode = $jq(node),
    		            item_type = jqNode.find(self.engToXML("ITEM_TYPE")).text();
    		        if(item_type === "VOD"){
    	                os = jqNode.find("os").text().split(",");
    	                var time = os[os.length-1].replace('"', '').split(":");
    	                ret = (parseInt(time[0]) * MINUTES_PER_HOUR) + parseInt(time[1])
    	                return false;
    	            }
 
    		    });

                logger.debug("getDurationMinutes for: " + self.getTitle() + " is: " + ret);

        		return ret
    	    }, 
    	    getAssetId: function(){
    	     //   return $jq("SHID", self.xmlDoc).text();
    	        return $jq("SHID:last", self.xmlDoc).text();
    	    },
    		asQueryString: function(){

    		    var ret =  
    		        "vodOrBroadcast=" +
    		        escape( self.getVodOrBroadcast() ) +
    		        "&" +
    		        "clusterOrTerminal=" + 
    		        escape( self.getClusterOrTerminal() ) +
    		        "&" +
    		        "title="+
    		        escape( self.getTitle() ) +
    		        "&" +
    		        "assetId=" +
    		        self.getAssetId();
    		    return ret;

    		}
    	});
    	return self;
    }

    var AbstractBroadcastResultItem = {
	
    	getDate: function(){
    	    var date;
    	    try{
    	        date = new PgmSrch.ESTDate(this.getUTCTime());
    	    }catch(e){
    	        logger.debug("Error creating date for item: " + this.getTitle())
    	    }
    	    return date;
    	},
	
    	getEndDate: function(){
    	    return new PgmSrch.ESTDate(this.getUTCTime() + this.getDurationMinutes() * 60 * 1000 );
    	}
    }

    PgmSrch.BroadcastResultItem = function(prototype){
    	// BroadcastResultItem is sort of a subclass of PgmSrch.TerminalResultItem
    	var logger = PgmSrch.util.logger;
    	var self = prototype;
    	var cnst = PgmSrch.cnst;
    	$jq.extend(self, AbstractBroadcastResultItem, {
    		// these are the functions we're extending the prototype with
    		
    		getVodOrBroadcast: function(){
    	      return "broadcast"  
    	    },
    		
    		asQueryString: function(){
		    
    		    var ret =  
    		        "vodOrBroadcast=" +
    		        escape( self.getVodOrBroadcast() ) +
    		        "&" +
    		        "clusterOrTerminal=" + 
    		        escape( self.getClusterOrTerminal() ) +
    		        "&" +
    		        "title="+
    		        escape( self.getTitle() ) +
    		        "&" +
    		        "utcTime=" +
    		        self.getUTCTime() + 
    		        "&" +
    		        "channelNumber=" +
    		        self.getChannelNumber() +
    		        "&" +
    		        "durationMinutes=" +
    		        self.getDurationMinutes()
    		        ;
		        
    		    return ret;
		    
    		},
    		
    		getDurationMinutes : function(){
    		    var ret, os;
    		    $jq("AI", self.xmlDoc).each(function(i,node){
    		        var 
    		            jqNode = $jq(node),
    		            item_type = jqNode.find(self.engToXML("ITEM_TYPE")).text();
    		            
    		        if(item_type === "SE"){
    		            os = jqNode.find("os").text().split(":");
    		            ret = os[7] / 60;
		                return false;
		            }

    		    });

        		return ret
    		},
    		
    		isWithinDVRRecordWindow: function(){
                var oneWeekOut = new Date();
                oneWeekOut.setDate(new Date().getDate() + 7);
    		    return self.getDate().isLessThan( oneWeekOut );
    		},
    		
    		getUTCTime: function(){
    		    
        		    var ut;
        		    $jq("AI", self.xmlDoc).each(function(i,node){
        		        var jqNode = $jq(node);
        		        var item_type = jqNode.find(self.engToXML("ITEM_TYPE")).text();
        		        if(item_type === "SE"){
        		            ut = parseFloat(jqNode.find("UT").text());
        		            return false;
        	            }
        		    });
        		    
        		    return ut * 1000;
        		    
    		},

    		getPrettyDate : function(){
    			var leadingZero = function(time){
    				if(time < 10){
                    	time = "0" + time;
                	};
                	return time;
    			}
			
                var date = self.getDate();
		    
                ret =  cnst.days[date.getDay()]
                    + ", "
                    + cnst.months[date.getMonth()]
                    + " "
                    + date.getDate();
            
                var amPm;
                var hours;
                if(date.getHours() > 12){
                    hours = date.getHours() - 12;
                    amPm = "PM";
                }else{
                    hours = (date.getHours() == 0) ? 12 : date.getHours();
                    amPm = "AM";
                };
            
                ret = ret  
                + " " 
                + hours
                +  ":"
                + leadingZero(date.getMinutes())
                + amPm;
            
                return ret;
    		},
		
    		getEpisodeTitle : function(){
                
                return descendInToXml(self.xmlDoc, [

    		        function(obj){
        		        return obj.getElementsByTagName('EPT')
        		    },
        		    function(obj){
        		        return obj[0]
        		    },   
        		    function(obj){
            		    return obj.getElementsByTagName('TX')
        		    },
        		    function(obj){
        		        return obj[0];
        		    },
        		    function(obj){
        		        return obj.childNodes;
        		    },
        		    function(obj){
        		        return obj[0];
        		    },
        		    function(obj){
        		        return obj.data
        		    }
    		    ]);
		    
    		}
    	});
    	return self;
    }

    PgmSrch.SerializedResultItem = function(data){
    
        return $jq.extend({}, AbstractBroadcastResultItem, {
    
            getClusterOrTerminal: function(){
                return data.clusterOrTerminal
            },
    
            getDetailsQuery: function(){
                return data.detailsQuery;
            },
    
            getTitle: function(){
                return data.title;
            },
            getUTCTime: function(){
                return parseInt(data.utcTime);
            },
            getDurationMinutes: function(){
                return parseInt(data.durationMinutes)
            },
            getVodOrBroadcast: function(){
                return data.vodOrBroadcast;
            },
            getAssetId: function(){
                return data.assetId
            },
            getChannelNumber: function(){
                return data.channelNumber
            }
        })
    }

})()
PgmSrch.ForwardingResultItemNavigator = function() {


    var logger = new PgmSrch.util.namedLogger("PgmSrch.ForwardingResultItemNavigator");
    logger.debug("creating ForwardingResultItemNavigator");

    var goToSearchPage = function(queryString) {
        window.location = PgmSrch.load.getBasePath() + 
            "/" + 
            PgmSrch.cnst.urls.searchResults + 
            queryString;
    };

    this.enterItem = function(resultItem) {
        var queryString = "?action=getDetails&" + resultItem.asQueryString();
        if(resultItem.getClusterOrTerminal() !== "cluster"){
            queryString = queryString +
                "&" +
                "query=" +
                PgmSrch.util.container("SEARCH_BOX").attr("value");
        }
        goToSearchPage(queryString);
    };

    this.resultsToMainArea = function(searchAction) {
        var queryString = "?query=" + searchAction.getQuery().w;
        goToSearchPage(queryString);
    };
};

PgmSrch.SearchPageResultItemNavigator = function(main) {

    var logger = new PgmSrch.util.namedLogger("SearchPageResultItemNavigator");

    this.enterItem = function(resultItem) {
        if (resultItem.getClusterOrTerminal() === "cluster") {
            logger.debug("about to call drillDown");
            main.drillDown(resultItem);
        } else {
            // if this is a dropdown item, refresh the main content area
            if (
                    typeof resultItem.getSearchAction !== "undefined" &&
                    resultItem.getSearchAction().getGroup() === PgmSrch.running.getDropdownSearchActionGroup()
                ) {
                this.resultsToMainArea(resultItem.getSearchAction());
            }
            
            if (resultItem.getVodOrBroadcast() === "broadcast") {
            
            
                var leadingZeroes = function(num){
                    var len = 2;
                    while(num.length < len){
                        num = "0" + num;
                    }
                    return num;
                }
            
                var formatDate = function(date) {
                    var dateStr =
                    String(date.getFullYear()) +
                    leadingZeroes(String(date.getMonth() + 1)) +
                    leadingZeroes(String(date.getDate())) +
                    leadingZeroes(String(date.getHours())) +
                    leadingZeroes(String(date.getMinutes())) +
                    leadingZeroes(String(date.getSeconds()));
                    return dateStr;
                };
            
                programDetails.show({
                    showId: jQuery('SHID', resultItem.xmlDoc).text(),
                    startTime: resultItem.getUTCTime(),
                    channelNumber: resultItem.getChannelNumber()
                });
                
            }else{
                showVODDetails(resultItem.getAssetId())
            }
        }
    };

    this.resultsToMainArea = function(searchAction) {

        main.initializeMainSearchActions(searchAction);
        main.scheduleRenderMain(searchAction);

    };

};

/*
 * 
 * ResultObjectFactory.js 
 * 
 */
 
 


 
 PgmSrch.resultObjectFactory = (function(){
 	
 	var logger = new PgmSrch.util.namedLogger("PgmSrch.resultObjectFactory");
 	
     var self = {

     	buildResultObj : function(node){

    var ret = []

    // First step in building wrapper object. It it turns out that
    // this node is a terminal, we'll throw this object out and build
    // either one or two new ones from scratch. This is getting a bit 
    // stupid and ugly, but unfortunately that's what happens at the end 
    // near the deadline sometimes.
    var obj = PgmSrch.ResultItem(node);


    // now continue building the object, depending on what flavor it is. This is
    // a sort of inheritance scheme, a way to branch the logic for terminals vs clusters
    // by wrapper them in different objects
    // A notable wrinkle is that a veveo result can be BOTH a vod and a broadcast item,
    // while according to our concept, a program must be either or. So, check here to see if
    // the veveo result is both. If so, return an array with two resultItems, rather
    // than just one.
    var type = obj.getItemType();
    if (type === "cluster") {
        ret.push(PgmSrch.ClusterResultItem(obj));
    } else if (type === "terminal") {
        obj = PgmSrch.TerminalResultItem(obj);
        if (obj.hasBroadcast()) {
            ret.push(
                PgmSrch.BroadcastResultItem(
                    PgmSrch.TerminalResultItem(
                        PgmSrch.ResultItem(node)
                    )
                )
            );
        }
        if (obj.hasVOD()) {
            ret.push(
                PgmSrch.VODResultItem(
                    PgmSrch.TerminalResultItem(
                        PgmSrch.ResultItem(node)
                    )
                )
            );
        }
    }

    return ret;
},
     	
     	wrapXML : function(data, searchAction){
     	    var resultItems = [];
     	    $jq("CNs", data).children().each(function(i, item){

     	        if(item.tagName == "CF" || item.tagName == "CI"){
         	        if( $jq("T",item).text() != "No Results"){
    				    var resultObjects = self.buildResultObj(item);
    				    if( resultObjects ){
    				        $jq(resultObjects).each(function(i, resultObject){
    				            resultObject.setSearchAction(searchAction);
        				        resultItems.push(resultObject)
    				        })
    				    };
    				};
				}
				
			});
			return resultItems;
     	}

     };
     
     return self;
     
 })();
 
 
 
 
if(!PgmSrch.Templates){
    PgmSrch.Templates = {}
}
PgmSrch.TemplateRenderer =  (function(){
	
	var logger = PgmSrch.util.logger;
	
	var process = function(tmpName, data){
	    var ret;
	        ret =  self[tmpName].tmpl.process(data, {throwExceptions:true});
	    return ret
	}
	
	var self =  {
	    init: function(){
	    	self.main = {
	    		tmpl: TrimPath.parseTemplate(PgmSrch.Templates.main),
	    		render: function(data){
	    			return process("main", data);
	    		}
	    	};
	    	self.dropdown = {
	    		tmpl: TrimPath.parseTemplate(PgmSrch.Templates.dropDownItems),
	    		render: function(data){
	    			return process("dropdown", data);
	    		}
	    	};
	    	
	    	self.dropdownContainer = {
	    		render: function(data){
	    		  return PgmSrch.Templates.dropdownContainer 
	    		}
	    	}

    	    self.prevNext = {
	    		tmpl: TrimPath.parseTemplate(PgmSrch.Templates.pagination),
	    		render: function(data){
	    			return process("prevNext", data);
	    		}
	    	}
	    	
	    	
	    }
	    
	};
	return self;

})();
PgmSrch.Templates =  (function(){
	
	var logger = PgmSrch.util.logger;
	
	var process = function(tmpName, data){
	    return self[tmpName].tmpl.process(data, {throwExceptions:true});
	}
	
	var self =  {
	    init: function(){
	    	self.main = {
	    		tmpl: TrimPath.parseTemplate($jq("#main_template").text()),
	    		render: function(data){
	    			return process("main", data);
	    		}
	    	};
	    	self.dropdown = {
	    		tmpl: TrimPath.parseTemplate(""
+ "<div class=\"result{if isSelected()} selected{/if}{if getItemType() == \"cluster\"} cluster{/if}\">"
+ "<div class=\"inner\">"
+ "<div class=\"title\">\${ getTitle() }</div>"
+ "<div class=\"description\">\${getDescription()}</em></div>"
+ "</div>"
+ "</div>"
+ ""
),
	    		render: function(data){
	    			return process("dropdown", data);
	    		}
	    	};
	    	
	    	self.dropdownContainer = {
	    		render: function(data){
	    		  return  ' <div id="dropdownContainer" class="pgmSrchResultsContainer " ></div>'
	    		}
	    	}

    	    self.prevNext = {
	    		tmpl: TrimPath.parseTemplate($jq("#prev_next_template").text()),
	    		render: function(data){
	    			return process("prevNext", data);
	    		}
	    	}
	    	
	    	
	    }
	    
	};
	return self;

})();
/**
 * TrimPath Template. Release 1.0.38.
 * Copyright (C) 2004, 2005 Metaha.
 * 
 * TrimPath Template is licensed under the GNU General Public License
 * and the Apache License, Version 2.0, as follows:
 *
 * This program is free software; you can redistribute it and/or 
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed WITHOUT ANY WARRANTY; without even the 
 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var TrimPath;

// TODO: Debugging mode vs stop-on-error mode - runtime flag.
// TODO: Handle || (or) characters and backslashes.
// TODO: Add more modifiers.

(function() {               // Using a closure to keep global namespace clean.
    if (TrimPath == null)
        TrimPath = new Object();
    if (TrimPath.evalEx == null)
        TrimPath.evalEx = function(src) { return eval(src); };

    var UNDEFINED;
    if (Array.prototype.pop == null)  // IE 5.x fix from Igor Poteryaev.
        Array.prototype.pop = function() {
            if (this.length === 0) {return UNDEFINED;}
            return this[--this.length];
        };
    if (Array.prototype.push == null) // IE 5.x fix from Igor Poteryaev.
        Array.prototype.push = function() {
            for (var i = 0; i < arguments.length; ++i) {this[this.length] = arguments[i];}
            return this.length;
        };

    TrimPath.parseTemplate = function(tmplContent, optTmplName, optEtc) {
        if (optEtc == null)
            optEtc = TrimPath.parseTemplate_etc;
        var funcSrc = parse(tmplContent, optTmplName, optEtc);
        var func = TrimPath.evalEx(funcSrc, optTmplName, 1);
        if (func != null)
            return new optEtc.Template(optTmplName, tmplContent, funcSrc, func, optEtc);
        return null;
    }
    
/*    
    // commenting this out because it scares me
    try {
        String.prototype.process = function(context, optFlags) {
            var template = TrimPath.parseTemplate(this, null);
            if (template != null)
                return template.process(context, optFlags);
            return this;
        }
    } catch (e) { // Swallow exception, such as when String.prototype is sealed.
    }
*/
    
    TrimPath.parseTemplate_etc = {};            // Exposed for extensibility.
    TrimPath.parseTemplate_etc.statementTag = "forelse|for|if|elseif|else|var|macro";
    TrimPath.parseTemplate_etc.statementDef = { // Lookup table for statement tags.
        "if"     : { delta:  1, prefix: "if (", suffix: ") {", paramMin: 1 },
        "else"   : { delta:  0, prefix: "} else {" },
        "elseif" : { delta:  0, prefix: "} else if (", suffix: ") {", paramDefault: "true" },
        "/if"    : { delta: -1, prefix: "}" },
        "for"    : { delta:  1, paramMin: 3, 
                     prefixFunc : function(stmtParts, state, tmplName, etc) {
                        if (stmtParts[2] != "in")
                            throw new etc.ParseError(tmplName, state.line, "bad for loop statement: " + stmtParts.join(' '));
                        var iterVar = stmtParts[1];
                        var listVar = "__LIST__" + iterVar;
                        return [ "var ", listVar, " = ", stmtParts[3], ";",
                             // Fix from Ross Shaull for hash looping, make sure that we have an array of loop lengths to treat like a stack.
                             "var __LENGTH_STACK__;",
                             "if (typeof(__LENGTH_STACK__) == 'undefined' || !__LENGTH_STACK__.length) __LENGTH_STACK__ = new Array();", 
                             "__LENGTH_STACK__[__LENGTH_STACK__.length] = 0;", // Push a new for-loop onto the stack of loop lengths.
                             "if ((", listVar, ") != null) { ",
                             "var ", iterVar, "_ct = 0;",       // iterVar_ct variable, added by B. Bittman     
                             "for (var ", iterVar, "_index in ", listVar, ") { ",
                             iterVar, "_ct++;",
                             "if (typeof(", listVar, "[", iterVar, "_index]) == 'function') {continue;}", // IE 5.x fix from Igor Poteryaev.
                             "__LENGTH_STACK__[__LENGTH_STACK__.length - 1]++;",
                             "var ", iterVar, " = ", listVar, "[", iterVar, "_index];" ].join("");
                     } },
        "forelse" : { delta:  0, prefix: "} } if (__LENGTH_STACK__[__LENGTH_STACK__.length - 1] == 0) { if (", suffix: ") {", paramDefault: "true" },
        "/for"    : { delta: -1, prefix: "} }; delete __LENGTH_STACK__[__LENGTH_STACK__.length - 1];" }, // Remove the just-finished for-loop from the stack of loop lengths.
        "var"     : { delta:  0, prefix: "var ", suffix: ";" },
        "macro"   : { delta:  1, 
                      prefixFunc : function(stmtParts, state, tmplName, etc) {
                          var macroName = stmtParts[1].split('(')[0];
                          return [ "var ", macroName, " = function", 
                                   stmtParts.slice(1).join(' ').substring(macroName.length),
                                   "{ var _OUT_arr = []; var _OUT = { write: function(m) { if (m) _OUT_arr.push(m); } }; " ].join('');
                     } }, 
        "/macro"  : { delta: -1, prefix: " return _OUT_arr.join(''); };" }
    }
    TrimPath.parseTemplate_etc.modifierDef = {
        "eat"        : function(v)    { return ""; },
        "escape"     : function(s)    { return String(s).replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"); },
        "capitalize" : function(s)    { return String(s).toUpperCase(); },
        "default"    : function(s, d) { return s != null ? s : d; }
    }
    TrimPath.parseTemplate_etc.modifierDef.h = TrimPath.parseTemplate_etc.modifierDef.escape;

    TrimPath.parseTemplate_etc.Template = function(tmplName, tmplContent, funcSrc, func, etc) {
        this.process = function(context, flags) {
            if (context == null)
                context = {};
            if (context._MODIFIERS == null)
                context._MODIFIERS = {};
            if (context.defined == null)
                context.defined = function(str) { return (context[str] != undefined); };
            for (var k in etc.modifierDef) {
                if (context._MODIFIERS[k] == null)
                    context._MODIFIERS[k] = etc.modifierDef[k];
            }
            if (flags == null)
                flags = {};
            var resultArr = [];
            var resultOut = { write: function(m) { resultArr.push(m); } };
            try {
                func(resultOut, context, flags);
            } catch (e) {
                if (flags.throwExceptions == true)
                    throw e;
                var result = new String(resultArr.join("") + "[ERROR: " + e.toString() + (e.message ? '; ' + e.message : '') + "]");
                result["exception"] = e;
                return result;
            }
            return resultArr.join("");
        }
        this.name       = tmplName;
        this.source     = tmplContent; 
        this.sourceFunc = funcSrc;
        this.toString   = function() { return "TrimPath.Template [" + tmplName + "]"; }
    }
    TrimPath.parseTemplate_etc.ParseError = function(name, line, message) {
        this.name    = name;
        this.line    = line;
        this.message = message;
    }
    TrimPath.parseTemplate_etc.ParseError.prototype.toString = function() { 
        return ("TrimPath template ParseError in " + this.name + ": line " + this.line + ", " + this.message);
    }
    
    var parse = function(body, tmplName, etc) {
        body = cleanWhiteSpace(body);
        var funcText = [ "var TrimPath_Template_TEMP = function(_OUT, _CONTEXT, _FLAGS) { with (_CONTEXT) {" ];
        var state    = { stack: [], line: 1 };                              // TODO: Fix line number counting.
        var endStmtPrev = -1;
        while (endStmtPrev + 1 < body.length) {
            var begStmt = endStmtPrev;
            // Scan until we find some statement markup.
            begStmt = body.indexOf("{", begStmt + 1);
            while (begStmt >= 0) {
                var endStmt = body.indexOf('}', begStmt + 1);
                var stmt = body.substring(begStmt, endStmt);
                var blockrx = stmt.match(/^\{(cdata|minify|eval)/); // From B. Bittman, minify/eval/cdata implementation.
                if (blockrx) {
                    var blockType = blockrx[1]; 
                    var blockMarkerBeg = begStmt + blockType.length + 1;
                    var blockMarkerEnd = body.indexOf('}', blockMarkerBeg);
                    if (blockMarkerEnd >= 0) {
                        var blockMarker;
                        if( blockMarkerEnd - blockMarkerBeg <= 0 ) {
                            blockMarker = "{/" + blockType + "}";
                        } else {
                            blockMarker = body.substring(blockMarkerBeg + 1, blockMarkerEnd);
                        }                        
                        
                        var blockEnd = body.indexOf(blockMarker, blockMarkerEnd + 1);
                        if (blockEnd >= 0) {                            
                            emitSectionText(body.substring(endStmtPrev + 1, begStmt), funcText);
                            
                            var blockText = body.substring(blockMarkerEnd + 1, blockEnd);
                            if (blockType == 'cdata') {
                                emitText(blockText, funcText);
                            } else if (blockType == 'minify') {
                                emitText(scrubWhiteSpace(blockText), funcText);
                            } else if (blockType == 'eval') {
                                if (blockText != null && blockText.length > 0) // From B. Bittman, eval should not execute until process().
                                    funcText.push('_OUT.write( (function() { ' + blockText + ' })() );');
                            }
                            begStmt = endStmtPrev = blockEnd + blockMarker.length - 1;
                        }
                    }                        
                } else if (body.charAt(begStmt - 1) != '$' &&               // Not an expression or backslashed,
                           body.charAt(begStmt - 1) != '\\') {              // so check if it is a statement tag.
                    var offset = (body.charAt(begStmt + 1) == '/' ? 2 : 1); // Close tags offset of 2 skips '/'.
                                                                            // 10 is larger than maximum statement tag length.
                    if (body.substring(begStmt + offset, begStmt + 10 + offset).search(TrimPath.parseTemplate_etc.statementTag) == 0) 
                        break;                                              // Found a match.
                }
                begStmt = body.indexOf("{", begStmt + 1);
            }
            if (begStmt < 0)                              // In "a{for}c", begStmt will be 1.
                break;
            var endStmt = body.indexOf("}", begStmt + 1); // In "a{for}c", endStmt will be 5.
            if (endStmt < 0)
                break;
            emitSectionText(body.substring(endStmtPrev + 1, begStmt), funcText);
            emitStatement(body.substring(begStmt, endStmt + 1), state, funcText, tmplName, etc);
            endStmtPrev = endStmt;
        }
        emitSectionText(body.substring(endStmtPrev + 1), funcText);
        if (state.stack.length != 0)
            throw new etc.ParseError(tmplName, state.line, "unclosed, unmatched statement(s): " + state.stack.join(","));
        funcText.push("}}; TrimPath_Template_TEMP");
        return funcText.join("");
    }
    
    var emitStatement = function(stmtStr, state, funcText, tmplName, etc) {
        var parts = stmtStr.slice(1, -1).split(' ');
        var stmt = etc.statementDef[parts[0]]; // Here, parts[0] == for/if/else/...
        if (stmt == null) {                    // Not a real statement.
            emitSectionText(stmtStr, funcText);
            return;
        }
        if (stmt.delta < 0) {
            if (state.stack.length <= 0)
                throw new etc.ParseError(tmplName, state.line, "close tag does not match any previous statement: " + stmtStr);
            state.stack.pop();
        } 
        if (stmt.delta > 0)
            state.stack.push(stmtStr);

        if (stmt.paramMin != null &&
            stmt.paramMin >= parts.length)
            throw new etc.ParseError(tmplName, state.line, "statement needs more parameters: " + stmtStr);
        if (stmt.prefixFunc != null)
            funcText.push(stmt.prefixFunc(parts, state, tmplName, etc));
        else 
            funcText.push(stmt.prefix);
        if (stmt.suffix != null) {
            if (parts.length <= 1) {
                if (stmt.paramDefault != null)
                    funcText.push(stmt.paramDefault);
            } else {
                for (var i = 1; i < parts.length; i++) {
                    if (i > 1)
                        funcText.push(' ');
                    funcText.push(parts[i]);
                }
            }
            funcText.push(stmt.suffix);
        }
    }

    var emitSectionText = function(text, funcText) {
        if (text.length <= 0)
            return;
        var nlPrefix = 0;               // Index to first non-newline in prefix.
        var nlSuffix = text.length - 1; // Index to first non-space/tab in suffix.
        while (nlPrefix < text.length && (text.charAt(nlPrefix) == '\n'))
            nlPrefix++;
        while (nlSuffix >= 0 && (text.charAt(nlSuffix) == ' ' || text.charAt(nlSuffix) == '\t'))
            nlSuffix--;
        if (nlSuffix < nlPrefix)
            nlSuffix = nlPrefix;
        if (nlPrefix > 0) {
            funcText.push('if (_FLAGS.keepWhitespace == true) _OUT.write("');
            var s = text.substring(0, nlPrefix).replace('\n', '\\n'); // A macro IE fix from BJessen.
            if (s.charAt(s.length - 1) == '\n')
            	s = s.substring(0, s.length - 1);
            funcText.push(s);
            funcText.push('");');
        }
        var lines = text.substring(nlPrefix, nlSuffix + 1).split('\n');
        for (var i = 0; i < lines.length; i++) {
            emitSectionTextLine(lines[i], funcText);
            if (i < lines.length - 1)
                funcText.push('_OUT.write("\\n");\n');
        }
        if (nlSuffix + 1 < text.length) {
            funcText.push('if (_FLAGS.keepWhitespace == true) _OUT.write("');
            var s = text.substring(nlSuffix + 1).replace('\n', '\\n');
            if (s.charAt(s.length - 1) == '\n')
            	s = s.substring(0, s.length - 1);
            funcText.push(s);
            funcText.push('");');
        }
    }
    
    var emitSectionTextLine = function(line, funcText) {
        var endMarkPrev = '}';
        var endExprPrev = -1;
        while (endExprPrev + endMarkPrev.length < line.length) {
            var begMark = "${", endMark = "}";
            var begExpr = line.indexOf(begMark, endExprPrev + endMarkPrev.length); // In "a${b}c", begExpr == 1
            if (begExpr < 0)
                break;
            if (line.charAt(begExpr + 2) == '%') {
                begMark = "${%";
                endMark = "%}";
            }
            var endExpr = line.indexOf(endMark, begExpr + begMark.length);         // In "a${b}c", endExpr == 4;
            if (endExpr < 0)
                break;
            emitText(line.substring(endExprPrev + endMarkPrev.length, begExpr), funcText);                
            // Example: exprs == 'firstName|default:"John Doe"|capitalize'.split('|')
            var exprArr = line.substring(begExpr + begMark.length, endExpr).replace(/\|\|/g, "#@@#").split('|');
            for (var k in exprArr) {
                if (exprArr[k].replace) // IE 5.x fix from Igor Poteryaev.
                    exprArr[k] = exprArr[k].replace(/#@@#/g, '||');
            }
            funcText.push('_OUT.write(');
            emitExpression(exprArr, exprArr.length - 1, funcText); 
            funcText.push(');');
            endExprPrev = endExpr;
            endMarkPrev = endMark;
        }
        emitText(line.substring(endExprPrev + endMarkPrev.length), funcText); 
    }
    
    var emitText = function(text, funcText) {
        if (text == null ||
            text.length <= 0)
            return;
        text = text.replace(/\\/g, '\\\\');
        text = text.replace(/\n/g, '\\n');
        text = text.replace(/"/g,  '\\"');
        funcText.push('_OUT.write("');
        funcText.push(text);
        funcText.push('");');
    }
    
    var emitExpression = function(exprArr, index, funcText) {
        // Ex: foo|a:x|b:y1,y2|c:z1,z2 is emitted as c(b(a(foo,x),y1,y2),z1,z2)
        var expr = exprArr[index]; // Ex: exprArr == [firstName,capitalize,default:"John Doe"]
        if (index <= 0) {          // Ex: expr    == 'default:"John Doe"'
            funcText.push(expr);
            return;
        }
        var parts = expr.split(':');
        funcText.push('_MODIFIERS["');
        funcText.push(parts[0]); // The parts[0] is a modifier function name, like capitalize.
        funcText.push('"](');
        emitExpression(exprArr, index - 1, funcText);
        if (parts.length > 1) {
            funcText.push(',');
            funcText.push(parts[1]);
        }
        funcText.push(')');
    }

    var cleanWhiteSpace = function(result) {
        result = result.replace(/\t/g,   "    ");
        result = result.replace(/\r\n/g, "\n");
        result = result.replace(/\r/g,   "\n");
        result = result.replace(/^(\s*\S*(\s+\S+)*)\s*$/, '$1'); // Right trim by Igor Poteryaev.
        return result;
    }

    var scrubWhiteSpace = function(result) {
        result = result.replace(/^\s+/g,   "");
        result = result.replace(/\s+$/g,   "");
        result = result.replace(/\s+/g,   " ");
        result = result.replace(/^(\s*\S*(\s+\S+)*)\s*$/, '$1'); // Right trim by Igor Poteryaev.
        return result;
    }

    // The DOM helper functions depend on DOM/DHTML, so they only work in a browser.
    // However, these are not considered core to the engine.
    //
    TrimPath.parseDOMTemplate = function(elementId, optDocument, optEtc) {
        if (optDocument == null)
            optDocument = document;
        var element = optDocument.getElementById(elementId);
        var content = element.value;     // Like textarea.value.
        if (content == null)
            content = element.innerHTML; // Like textarea.innerHTML.
        content = content.replace(/&lt;/g, "<").replace(/&gt;/g, ">");
        return TrimPath.parseTemplate(content, elementId, optEtc);
    }

    TrimPath.processDOMTemplate = function(elementId, context, optFlags, optDocument, optEtc) {
        return TrimPath.parseDOMTemplate(elementId, optDocument, optEtc).process(context, optFlags);
    }
}) ();
 PgmSrch.Templates.dropDownItems = ""
+ "<div class=\"result{if isSelected()} selected{/if}{if getItemType() == \"cluster\"} cluster{/if}\">"
+ "<div class=\"inner\">"
+ "<div class=\"title\">\${ getTitle() }</div>"
+ "<div class=\"description\">\${getDescription()}</em></div>"
+ "</div>"
+ "</div>"
+ ""

PgmSrch.Templates.dropdownContainer = ' <div id="dropdownContainer" class="pgmSrchResultsContainer clickable" ></div>';
PgmSrch.Templates.main = ""
+ ""
+ ""
+ "{if getItemType() == \"cluster\"}"
+ ""
+ "<div class=\"result cluster\">"
+ ""
+ ""
+ "<div class=\"left column\"></div>"
+ ""
+ "<div class=\"middle column\">"
+ "<div class=\"title\">${ getTitle() }</div>"
+ "<div class=\"description\">${getDescription()}</div>"
+ "</div>"
+ "<div style=\"clear:both\"></div>"
+ ""
+ "</div>"
+ ""
+ "{elseif getVodOrBroadcast() == \"broadcast\"}"
+ "<div class=\"result broadcast\">"
+ ""
+ "<div class=\"left column\"></div>"
+ ""
+ "<div class=\"middle column\">"
+ "<div class=\"title\">"
+ "${ getTitle() }"
+ "{if getEpisodeTitle() && getEpisodeTitle() != \"\"}"
+ "<span class=\'episodeTitle\'>&ndash; ${getEpisodeTitle()}</span>"
+ "{/if}"
+ "{if isNew()}"
+ "&nbsp;&nbsp;<img src=\"/images/epg/new_icon.png\" alt=\"NEW\">"
+ "{/if}"
+ "</div>"
+ "<div class=\"description\">${getDescription()}</em></div>"
+ ""
+ "{if  isWithinDVRRecordWindow()}"
+ "<div class=\"recordLink\" >Record to DVR</div>"
+ "{/if}"
+ "</div>"
+ ""
+ "<div class=\"right column\">"
+ "<div class=\"date\">${getPrettyDate()}</div>"
+ "{if getStationLogo()}"
+ "<div class=\"channelLogo\">"
+ "<a href=\"search.jsp?query=${getStationName()}\"><img src=\"/images/epg/logos/grid/${getStationLogo()}\"></a>"
+ "</div>"
+ "{/if}"
+ "<div class=\"length\">${getPrettyDuration()}</div>"
+ "<div class=\"channel\">"
+ "${getChannelNumber()} ${getStationName()}"
+ "</div>"
+ "</div>"
+ "<div style=\"clear:both\"></div></div>"
+ ""
+ "{else}"
+ "<!--  //////////// VOD template //////////// -->"
+ "<div class=\"result vod\">"
+ ""
+ "<div class=\"left column\"></div>"
+ ""
+ "<div class=\"middle column\">"
+ "<div class=\"title\">"
+ "${ getTitle() }"
+ "{if getEpisodeTitle() && getEpisodeTitle() != \"\"}"
+ "<span class=\'episodeTitle\'>&ndash; ${getEpisodeTitle()}</span>"
+ "{/if}"
+ "</div>"
+ "<div class=\"description\">${getDescription()}</em></div>"
+ "</div>"
+ ""
+ "<div class=\"right column\">"
+ "<div class=\"length\">${getPrettyDuration()}</div>"
+ "<div class=\"price\">${getPrice()}</div>"
+ "</div>"
+ ""
+ "<div style=\"clear:both\"></div>"
+ ""
+ "</div>"
+ ""
+ "{/if}"
+ ""
+ ""
+ ""
+ ""

PgmSrch.Templates.pagination = ""
+ "<div class=\"prevNextContainer\">"
+ "{if getPageNums().length > 1}"
+ "{if hasNextPageAction() }"
+ "<div class=\"next button\" style=\"float:right\"><span class=\"text\">Next Page</span> <img src=\"/images/veveo_search/arrow_right.gif\" alt=\"right arrow\"></div>"
+ "{/if}"
+ "{if hasPrevPageAction() }"
+ "<div class=\"prev button\" style=\"float:left\"><img src=\"/images/veveo_search/arrow_left.gif\" alt=\"left arrow\"> <span class=\"text\">Previous Page</span></div>"
+ "{/if}"
+ "<div class=\"pageNumbers\">"
+ "{if forceDisplayFirstPageLink()}"
+ "<span class=\'pageNum\'>1</span>"
+ "<span>&hellip;</span>"
+ "{/if}"
+ "{for num in getPageNums()}"
+ "<span class=\'pageNum{if num === getIndexInAllActions() + 1} selected{/if}\'>${num}</span>"
+ "{/for}"
+ "{if !lastPageLinkDisplayed()}"
+ "<span>&hellip;</span>"
+ "{/if}"
+ "</div>"
+ "{/if}"
+ "</div>"
+ "<div style=\"clear:both\"></div>"
+ ""
+ ""

/*
 * 
 *  OnLoad.js
 * 
 */
 
$jq("input").live("click",function(){
    PgmSrch.focusedInput = this;
});

$jq(document).ready(function(){
    PgmSrch.util.addStyleSheet(
        PgmSrch.load.getBasePath() + "/css/veveosearch/search.css"
    );
    PgmSrch.running = PgmSrch.Main();
    PgmSrch.running.init();	
	
});


