	
	
	/* MINDING YOUR MIND - AJAX JAVASCRIPT (ajax-calls.js) - 
	   this file contains JavaScript for calling and responding to CF-Ajax calls as well as CF-Ajax test scripts */
		
	
   function ajaxFileUpload() {
      // *** note this is handler for global ajax event, so will be triggered by ANY ajax call with global not set to false
      $().ajaxStart(function(){
	  	//debugger;
	  	aevShowWaiting();
      }); 
	  
      /* $().ajaxComplete(function(){
	  	//aevResponseSuccess();
      }); */
	  
	  $(document).ajaxError(function(){
		if (window.console && window.console.error) {
		        console.error(arguments);
		    }
	  });

      $.ajaxFileUpload
      (
         {
            url:'./editvideo_sv.cfm',
            secureuri:false,
            addAfterID:'vID',
            dataType: 'json',
			// *** for some reason we can trap complete event here but not beforeSend? why?
            success: function (data, status) { 
               if(typeof(data.error) != 'undefined') {
			   	  /* not sure when we will get here? if there is an error in the scripting or in ajax, it seems that it would be 
			   	   * tripped already before this. CF errors also are tripped before this. returned errors should get passed back
			   	   * with status=error and be handled below. but in case we get here, just handle whatever error we get.
			   	   */
                  if(data.error != '') {
                     aevResponseFail(data.error);
                  } else {
                     aevResponseFail(data.msg);
                  }
               } else {
			   	  /* here we can parse the string passed back from CF - success string with list of files posted (if any), or
			   	   * basic error string, or error because no files selected to post.
			   	   */
				   var errRE = /Error|error/;
				   var errpos = data.toString().search(errRE);
				   if (errpos > -1) {
				   		// update modal dialog with error message
				   		aevResponseFail(data.toString());
				   } else {
				   		// successful update and/or post - try to retrieve video id from data returned from CF
						// note: the goofiness below can be removed if we change the CF page to return a real json structure
						// instead of a string posing as json. 
						var vid = 0;
						var vidRE = /VID=\d+\;/;
						var vidpos = data.toString().search(vidRE);
						if (vidpos > -1) {
							// we do have string VID=n; in the returned data stream, now parse the actual id value out of that string
							var vidstr = data.toString().match(vidRE);
							vid = vidstr.toString().match(/\d+/g);
							vid = parseInt(vid);

							// we should now have a valid numeric id to process, make sure
							if (vid != NaN) {
								if (vid > 0) {
									// finally have valid video id, process that so we can update page underneath form
									updateOneVideo(vid);
								}
							}
						}

						//debugger;
						aevResponseSuccess();
				   }
			   }
			   
            },
            error: function (data, status, e) {
               /* NOTE: if this is tripped by CF outside of the processing page (where we catch any errors), CF will attempt to
                * return our global error page (with full graphic shell) back. Since these Ajax functions cannot handle that content, you 
                * will get a syntax error from jQuery/ajax rather than the real CF error. But at least it will look clean to the user.
                */
			   aevResponseFail(e);
            }
         }
      );
      
      return false;
   }	
   
   function updateOneVideo(vid) {
		// update content on page for this video after edit/add using modal dialog (data was updated via ajax w/o reloading page)
		
		$.ajax({
	      url: 'updatevideodata_sv.cfm',
	      data: 'vid=' + vid,
	      dataType: 'json',
		  
	      success: function (jjson) {
		  	// make sure we have container for this video, if not it is new and we need to add the containers as well as content
			var vidstr = vid.toString();
			var vcatstr = jjson.VCAT.toString();
			var thsrc = './videofiles/' + jjson.VIMG;
			var newdiv;
			var redodivs = false;
			
			// check if this category is new
			if ( $('#videoGroup_' + vcatstr).length <= 0 ) {
				// if category is new, create shell for this video category/group first
				newdiv = jQuery('<div></div>').addClass('videoGroup').attr('id', 'videoGroup_'+vcatstr).attr('recordid', vcatstr);
				// add it at top of video groups
				$('#videoShell').prepend(newdiv);
				// create div for category label and append it to the new category div
				newdiv = jQuery('<div></div>').addClass('videoCat').attr('id', 'videoCat_'+vcatstr);
				$('#videoGroup_' + vcatstr).append(newdiv);
				
				// finally, fill in content (name of this category)
				$('#videoCat_' + vcatstr).html(jjson.VCATNAME);
			}
			
			if ( $('#oneVideo_' + vidstr).attr('catid') != jjson.VCAT) {
				// moving to new category, will need to remove current containers and recreate. 	** no longer, this breaks IE and is
				// not necessary. just move the div and its kids to the new video category, and actions/styles will still work in IE! **
				
				//redodivs = true; -- now false since just moving, don't need to recreate containers.
				redodivs = false;
				//console.log("moving to new category, catid = %s, from db is %s", $('#oneVideo_' + vidstr).attr('catid'), jjson.VCAT);
				
				// get id of category we are currently under before moving old elements
				var oldcatid = $('#oneVideo_' + vidstr).parents('.videoGroup').attr('id');
				
				// instead of removing, just add it to beginning of new video group. 
				// (adding it means jQuery will move it if it already exists)
				$('#videoCat_' + vcatstr).after($('#oneVideo_' + vidstr));
				
				// check if old category is childless now - if so, remove it from page 	** reconsider this??
				// first child is category name div, so if child count is 1 or less it is really childless
				if ( $('#' + oldcatid + ' > *').length <= 1 ) {
					// empty and remove this entire category
					$('#' + oldcatid).empty();
					$('#' + oldcatid).remove();					
				}
			}
			
			if ( $('#oneVideo_' + vidstr).length > 0 ) {
			  	// video is not new, will just update content

				if ( thsrc != $('#vImgSrc_' + vidstr).attr('src') ) {
					// new image uploaded, need to update thumbnail on page
					loadVideoThumb(thsrc, 'vImg_'+vidstr, vidstr);
				}
			} else {
				// ** new video, will need to create containers
				redodivs = true;	
			}
					
			if (redodivs) {
				// new video (** no longer: OR move to new category **), need to create containers for content, fill, 
				// and append all to document. start with shell. ** these containers are not fully functional on IE until refresh!! 

				// if we are moving videos around, let's kill the manual row delimiters and hope for the best
				// with the floats. otherwise, it's even worse. ** for now, just removing from the start.
				//$('.clearVideos').remove();

				// create outer shell for this video item
				newdiv = jQuery('<div></div>')
					.addClass('oneVideoShell')
					.attr('id', 'oneVideo_'+vidstr)
					.attr('recordid', vidstr)
					.attr('catid', vcatstr);

				// add container to beginning of this category
				$('#videoCat_' + vcatstr).after(newdiv);
				
				// create div for thumb and append it to the newly created video shell div
				newdiv = jQuery('<div></div>').addClass('videoThumb').attr('id', 'vImg_'+vidstr);
				$('#oneVideo_' + vidstr).append(newdiv);
				
				// create new img holder for thumbnail, load and update div once loaded
				loadVideoThumb(thsrc, 'vImg_'+vidstr, vidstr);

				// create name and descrip divs and append them to newly created video shell div
				newdiv = jQuery('<div></div>').addClass('videoName').attr('id', 'vName_'+vidstr);
				$('#oneVideo_' + vidstr).append(newdiv);
				newdiv = jQuery('<div></div>').addClass('videoDescrip').attr('id', 'vDescrip_'+vidstr);
				$('#oneVideo_' + vidstr).append(newdiv);
			}

			// set basic content (same whether new video or not, now that any necessary divs have been created and appended to page)
			$('#vName_' + vidstr).html(jjson.VNAME);
			$('#vDescrip_' + vidstr).html(jjson.VDESCRIP);	
				
			// update sortable since have new item	
			$('#videoShell').sortable('refresh');
				
			//debugger;
	      },
		  
	      error: function (e) {
			alert('There was an error accessing the updated data. Please refresh the page to view your changes.');
	      }	
		  	
	    });
		
   }
   
	function loadVideoThumb(src, div, vidstr) {
	  // load given video thumb file into given container div for given video id
	  // remove current image if any, show loading animation, then fade on image once loaded
	  /* arguments as follows:
	   * 	src = url source of thumbnail loaded in 
	   * 	div = id of container, ie: vImg_9, into which img (vImgSrc_9) is placed
	   * 	vidstr = video database id (converted to string)
	   */

	  var img = new Image();
	  
	  // remove normal class from image container
	  $('#' + div).removeClass('videoThumb');
	  
	  // if we have valid corresponding image in this container, fade the image out and get rid of it
	  if ( $('#vImgSrc_' + vidstr).length > 0 ) {
	  	$('#vImgSrc_' + vidstr)
			.fadeOut()
			.remove();
	  }
	  // replace with waiting class so see animated gif while loading
	  $('#' + div).addClass('thumbLoading');
	
	  /* if (('#' + div).attr('ondblclick').length < 2) {
	  	 ('#' + div).attr( 'ondblclick', 'loadVideoForm('+vidstr+');' );
	  } */
	  //$('#' + div).ondblclick = function(){loadVideoForm(vidstr);};
	  
	  // ** this finally seems to get the dblclick event to work on newly created divs in IE
	  // ** however, once you drag it, it stops working again!! 
	  $('#' + div).bind("dblclick", function(){
	  	loadVideoForm(vidstr);
	  }); 
	  
	  // wrap our new image in jQuery, then:
	  $(img)
	    // once the image has loaded, execute this code
	    .load(function () {
	      // set the image hidden by default    
	      $(this).hide();

		  // *** why doesn't IE always get here once image is loaded??!!
		  // *** theory: if file is cached, doesn't trip loaded event; can't prove definitively
		  //alert('image loading done');
					
	      // with the holding div vImg_[n], apply:
	      $('#' + div)
	        // remove the loading class (so no background spinner), 
	        .removeClass('thumbLoading')
			// put the proper class back into place
			.addClass('videoThumb')
	        // then insert our image
	        .prepend(this)

			//.ondblclick = new Function("loadVideoForm("+vidstr+")");
			//.ondblclick=function(){loadVideoForm(vidstr);};
			//.attr( 'ondblclick', 'function(){loadVideoForm('+vidstr+');};' );
			
			// *** we should only do this if it's brand new div w/o already this attribute!
			// *** .attr( 'ondblclick', 'loadVideoForm('+vidstr+');' );
	    
	      // fade our image in to create a nice effect
	      $(this).fadeIn();
		  
		  //var test = document.getElementById('vImgSrc_'+vidstr);
		  //test.ondblclick = new Function("loadVideoForm("+vidstr+")"); 
		  //debugger;
	    })
	    
	    // if there was an error loading the image, react accordingly
	    .error(function () {
	      // notify the user that the image could not be loaded
		  alert('The new image could not be loaded. Please try refreshing this page.');
	    })
	    
	    // set other attributes needed
		.attr('id', 'vImgSrc_'+vidstr)
		.attr('border', '0')
		//.attr( "ondblclick", 'function(){loadVideoForm('+vidstr+');}' )
		
		// set the src attribute of the new image to our image; this should trigger the loading, which when done will trigger above code
		.attr('src', src);
	}

	function addVideoCat() {
		// add text entered by user to select list for categories without reloading page

	    /* $().ajaxStart(function(){
		  	//debugger;
		  	//aevShowWaiting();
	    }); */
			
		// get category text from field
		var newcat = $('#addNewCat').val();
		if (newcat.length > 0) {
			// category was entered, let's post it to the database - CF should return JSON of new option key/val pair to add
			$("#vCat").ajaxAddOption("addvideocat_sv.cfm", {"newcat" : newcat}, true, videoCatAdded, '', 'post');
		}
		
		//debugger;
		return false;
	}

	function videoCatAdded() {
		// clear out the new category text field
		$('#addNewCat').val('');
		// resort the options list
		//$("#vCat").sortOptions();		
	}
	
	
	function hideThisVideo(vid, showvid) {
		// update show/hide flag for this video and update current display correspondingly 
		
		aevShowUpdating();
		
		$.ajax({
	      url: 'archivevideo_sv.cfm',
	      data: 'vid=' + vid + '&showvid=' + showvid,
	      dataType: 'json',
		  global:false,
		  
	      success: function (data) {
			var errRE = /Error|error/;
			var errpos = data.toString().search(errRE);
			if (errpos > -1) {
				// update modal dialog with error message
			 	aevResponseFail(data.toString());
			} else {
				// remove video from current page display to reflect database update
				// if restore, remove from hidden list; if archive, remove from active list
					
				// get id of category we are currently under before moving old elements
				var oldcatid = $('#oneVideo_' + vid.toString()).parents('.videoGroup').attr('id');					
					
				$('#oneVideo_' + vid.toString()).empty();
				$('#oneVideo_' + vid.toString()).remove();		
					
				// check if old category is childless now - if so, remove it from page 	** reconsider this??
				// first child is category name div, so if child count is 1 or less it is really childless
				if ( $('#' + oldcatid + ' > *').length <= 1 ) {
					// empty and remove this entire category
					$('#' + oldcatid).empty();
					$('#' + oldcatid).remove();					
				}								
			
				removeModal();				   	
			 }		  	
		  },
		  
		  error: function (e) {
			alert('There was an error updating the database. Please refresh the page and try again later.');
			
			removeModal();
	      }	
		});
		
	}
	  

	function searchCollectionAdmin(op, obj) {
		// tell CF to create requested search collection and update page while working and once done
		
		var dispid = "";
		var deldispid = "";
		var createidxid = "";
		var delmsg = "You must use the controls above to create this collection before it can be indexed and enabled for searching.";
		var secmsg = "";
		
		if (op == 'createcoll') {
			dispid = '#createColl_' + obj.toString();
			createidxid = '#indexColl_' + obj.toString();
			setGlobalWaitCursor(1);
			$(dispid).html('Working, please wait....');
		} else if (op == 'indexcoll') {
			dispid = '#indexColl_' + obj.toString();
			setGlobalWaitCursor(1);
			$(dispid).html('Working, please wait....');			
		} else if (op == 'delcoll') {
			dispid = '#createColl_' + obj.toString();
			deldispid = '#indexColl_' + obj.toString();
			setGlobalWaitCursor(1);
			$(dispid).html('Working, please wait....');			
		}	
			
		$.ajax({
	      url: 'adminsearch_sv.cfm',
	      data: 'op=' + op + '&obj=' + obj,
	      dataType: 'json',
		  global:false,

	      success: function (data) {
			//var errRE = /Error|error/;
			//var errpos = data.toString().search(errRE);
	
			var msg = "";
			if (op == 'indexcoll') {
				try {
					msg = data.RETMSG;
					msg = msg + " " + data.INSERTED + " keys were inserted, ";
					msg = msg + data.UPDATED + " keys were updated, and ";
					msg = msg + data.DELETED + " keys were deleted. ";
					if (obj == 1)
						msg = msg + "These numbers may include admin or other pages which are not searchable and have been manually removed from the indices. ";
				} catch(e) {
					msg = "Unable to decode server response. Please refresh the page and try again later.";
				}				
			} else {
				try {
					msg = data.RETMSG;
					if (data.SECMSG.length > 1) {
						secmsg = data.SECMSG;
					}
					//msg = data.toString();
				} catch(e) {
					msg = "Unable to decode server response. Please refresh the page and try again later.";
				}				
			}
			//debugger;

	  		$(dispid).html(msg);
			if (op == 'delcoll') {
				$(deldispid).html(delmsg);
			} else if (op == 'createcoll' && secmsg.length > 1) {
				$(createidxid).html(secmsg);
			}
				
			setGlobalWaitCursor(0);
		  },	
		  	  
		  error: function (e) {
		  	//debugger;
			alert('There was an error processing your request. Please refresh the page and try again later.');
			setGlobalWaitCursor(0);
	      }	
		});		 
		  		
	}

	function setGlobalWaitCursor(waiting) {
		// update browser globally to use waiting cursor (no matter what element over) or reset to default
		
		if (waiting) 
			document.body.className = 'wait';
		else
			document.body.className = '';
	}



	// *** CFAjaxProxy Video Add/Edit/Post scripts ***
	function processAddEditVideo(vid) {
		// update modal dialog to show we are working...
		aevShowWaiting();
		
		// create instance of JS object to use communicating with CFC (this is set on calling page in CFAjaxProxy tag)
		var r = new addEditVideoRespond();
		// define the response function - will update modal dialog that operation is complete and then remove dialog
		r.setCallbackHandler(aevResponseSuccess);
		// define the error handler - for now, will just display generic error message in modal dialog
		r.setErrorHandler(aevResponseFail);
		
		// call the add/edit function from the CFC 
		r.addOrEditVideo(vid);
	}

	function aevShowWaiting() {
		// update modal dialog to use waiting/loading content
		aevUpdateModalDialog('w');
		//debugger;
	}
	
	function aevShowUpdating() {
		// update modal dialog to use updating/saving changes content
		aevUpdateModalDialog('u');
		//debugger;
	}	
	
	function aevResponseSuccess() {
		// update modal dialog with success message and call timeout to remove dialog after a few seconds
		aevUpdateModalDialog('s');
	}
	
	function aevResponseFail(errstr) {
		// update modal dialog with error message and call timeout to remove dialog after a few seconds
		aevUpdateModalDialog('f', errstr);
	}
	
	function aevUpdateModalDialog(mode, endstr) {
		// update div content with HTML string saved by CF into JS on calling page (which version based on mode)
		var closeNow = true;
	
		if (mode == 'w') {
			closeNow = false;
			document.getElementById("modalDialogInner").innerHTML = modalWaitStr;
		}
		else 
			if (mode == 's') 
				document.getElementById("modalDialogInner").innerHTML = modalDoneStr;
			else 
				if (mode == 'f') {
					closeNow = false;
					document.getElementById("modalDialogInner").innerHTML = modalErrStr + '\n<p class=\"err\">' + endstr + '</p>' + modalCloseStr;
				} else {
					if (mode =='u') {
						closeNow = false;
						document.getElementById("modalDialogInner").innerHTML = modalUpdateStr;
					}
				}
			
		if (closeNow) {
			// just close dialog now (after a short delay)
			window.setTimeout(function() {removeModal();},20);	//2000
			//removeModal();
		}
		
	}	
	
	// in admin mode, either load admin form (if ctrl pressed) or play video
	function playOrAdminVideo(shiftKey, vid, videoname) {
		if (shiftKey)
			loadVideoForm(vid);
		else	
			loadOneVideo(videoname);
	}
	

	// make Ajax call to load Flash movie player into modal dialog (modified from normal admin mode) and pass it name of video to play
	function loadOneVideo(videoname) {
		
		var flashvars = { FLVPath: 'videofiles/'+videoname };
		var params = { quality: 'high', wmode: 'transparent' };		//
		var attrs = "";
		var playernm = "mym_video_player.swf";
		//var playernm = "mym_test_121608_1.swf";
		
		$('#modalDialogShell').removeClass('modalShell');
		$('#modalDialogInner').removeClass('modalInner');
		$('#modalDialogShell').addClass('flashShell');
		$('#modalDialogInner').addClass('flashInner');	
		//setElementOpacity(document.getElementById('modalDialogInner'), 90);
			
		//setElementOpacity(document.getElementById('flashPlayerClose'), 0);
		beginModalFadeOn(90, 'modalDialogShell', '', 'flashPlayerClose');

		$.swfobject.embedSWF(playernm, "flashPlayerShell", "340", "300", "9.0.0", "", flashvars, params, attrs);
		
        /* var so = new SWFObject(videoname + '.swf', videoname, "320", "260", "9.0.0", "#FFFFFF");  // these are the original dimensions
        so.addParam("quality", "high");  
        so.addParam("wmode", "transparent");  
        so.addParam("salign", "c");  
        so.write("modalDialogInner"); */ 

	}	

	// make Ajax call to load video form for given video id into modal dialog
	function loadVideoForm(vid) {
		// create instance of JS object to use communicating with CFC (this is set on calling page in CFAjaxProxy tag)
		var r = new lvfRespond();
		// define the response function 
		r.setCallbackHandler(lvfDispResponse);
		// define the error handler 
		r.setErrorHandler(cfAPerrorHandler);
		// call the loadVideoForm function from the CFC 
		r.loadVideoForm(vid);
	}
		
	function removeFlashModal() {
		// fade out the shell with Flash content and, once faded, set everything back to normal dialog state
		$('#modalDialogInner').fadeOut(1000, function () {
			// note: this is necessary because normal dialog scripts don't hide inner div, so will be hidden otherwise still
			setElementDisplay('modalDialogInner', 'block');
			removeModal();
			$('#modalDialogShell').removeClass('flashShell');
			$('#modalDialogInner').removeClass('flashInner');	
			$('#modalDialogShell').addClass('modalShell');
			$('#modalDialogInner').addClass('modalInner');						
      	});		
		
	}
	
	function lvfDispResponse(resp) {
		// update div content with form returned from CFC after hitting database
		document.getElementById("modalDialogInner").innerHTML = resp;
		// show modal form and dialog content and focus on form field now that content has been loaded
		beginModalFadeOn(90, 'modalDialogShell', 'vName', '');
	}	
	
		
	
	// *** CFAjaxProxy TEST FUNCTIONS ***
	function cfAPgetResponse() {
		//grab the name from the field 
		var testname = document.getElementById('name').value;
		//initiate the proxy with a local var 
		var r = new cfAPrespond();
		//define the response function 
		r.setCallbackHandler(cfAPdispResponse);
		//define the error handler 
		r.setErrorHandler(cfAPerrorHandler);
		//call the cfAPtest function from the CFC 
		r.cfAPtest(testname);
	}

	function cfAPdispResponse(resp) {
		document.getElementById("responseArea").innerHTML = resp;
	}
	
	// Error handler for the asynchronous functions 
	function cfAPerrorHandler(statusCode,statusMsg) {
		setGlobalWaitCursor(0);
		alert('There was a communication error. Error ' + statusCode + ': '+statusMsg);
	}
	// *** END CFAjaxProxy TEST FUNCTIONS ***
	
	
	
		  