Function.prototype.method = function( name, func ){
	if(!this.prototype[name]){
		this.prototype[name] = func;
	}
};
String.prototype.trim = function( ){ var trimmed = this.replace(/^\s+/, "" ); return trimmed.replace(/\s+$/, "" ); };
//namespace
var Interact = {
	indx : 0,
	increment : function(){
		z = ++this.indx;
		return function(){
			return z;
		};
		
	},
	decrement : function(){
		z = --this.indx;
		return function(){
			return z;
		};
	},
	hash : {},
	db : function(msg){
		if(!this.debug){
			return;
		}
		if( typeof( console ) === "object" && typeof( console.log ) === "function" ){
			con = console;
		} else if( typeof( window.console ) === "object" && typeof( window.console.log ) === "function"  ){
			con = window.console;
		} else {
			return;
		}
		if( con ){
			con.log( msg );
		}
	},

	starclasses : {
		0 : 'zero',
		1 : 'one',
		2 : 'two',
		3 : 'three',
		4 : 'four',
		5 : 'five'
	},
	
	lpad : function( val ){
		if( val < 10 ){
			val = '0' + val;
		}
		return val;
	},
	
	fd : function(  format, oDate ){

		/**
			Day		: Day Name ("Monday")   
			DD		: Date, leading	(08)
			D		: Date	(8)
			Month	: Month Name ("January")
			MM		: Month Number, leading (01)
			M		: Month Number (1)
			YYYY	: Year (2008)
			YY		: Year (08)
			HH		: Hour, 24 Hour format
			H		: Hour, 12 Hour format
			mm		: Minute (01)
			( '-', ':', '/', ' ', etc, everything not above, reproduced literally )
			
			I always wondered how these things worked.
		
		*/
		
		if( typeof( oDate ) !== "object" ){
			oDate = new Date();
		}
		var months = [ 'January','February','March','April','May','June','July','August','September','October','November','December' ];
		var days = [ 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
		if( !format ){
			format = "MM-DD-YYYY HH:mm";
		}


		//switch 'Day' and 'Month' to friendly formats
		format = format.replace( /Day/, "NN" );
		format = format.replace( /Month/, "MMMM" );
		var cur, scratch, out = "", token, i = 0, j;

		while(  format.length ){
			token = "";
			cur = format.charAt(i);

			//create token by munching all the chars that match format[0]
			while(  format.charAt(i) === cur ){
				token += format.charAt(i++);
			}
			//chop the token off the format string
			format = format.slice(  token.length, format.length );
			i = 0;
			//switch that mother
			switch( token ){
				case 'NN' :
					out += days[oDate.getDay()];
					break;
				case 'D' :
					out += oDate.getDate();
					break;
				case 'DD' :
					out += this.lpad(oDate.getDate());
					break;
				case 'MMMM':
					out += months[ oDate.getMonth() ];
					break;
				case 'M':
					out += oDate.getMonth();
					break;
				case 'MM':
					out += this.lpad(oDate.getMonth());
					break;
				case 'YYYY':
					out += oDate.getFullYear();
					break;
				case 'YY':
					out += oDate.getFullYear().substring(2,4);
					break;
				case 'HH':
					out += oDate.getHours();
					break;
				case 'H':
				scratch = oDate.getHours();
					if( scratch > 12 ){
						scratch = scratch - 12;
					}
					out += scratch;
					break;
				case 'mm':
					out += this.lpad(oDate.getMinutes());
					break;
				default:
					out += token;
					break;
			}
		}
		return out;
	},
	
	
	//get the largest from an array of numbers
	biggest : function( arr ){
		return Math.max.apply( Math, arr );
	},
	
	smallest : function( arr ){
		return Math.min.apply( Math, arr );
	},
	
	//image preloading
	preload : function( source ){
		
		var i = new Image();
	
		$(i).attr( { src : source } );
		return i;
	},
	prepStars : function(){
		
		//dont need this with the consolidated star images
		return;
		this.stars = {};
		for( var i = 0; i < 6; i++ ){
			this.stars[i] = this.preload( document.location.protocol + '//' + document.location.hostname +  '/gfx/elements/icon/stars/stars-bl-' + i + '.gif' );
		}
		
	},
	prepTabs : function(){
		var i, tabs = ['featured', 'trailers', 'whatsnew', 'bymovie' ];
		this.tabs = {};
		this.tabson = {};
		for(i=0; i<tabs.length; i++ ){
			this.tabs[i] = this.preload( this.baseurl + '/gfx/elements/icon/mediaroom/' + tabs[i] + '.png' );
			this.tabson[i] = this.preload( this.baseurl + '/gfx/elements/icon/mediaroom/' + tabs[i] + '-on.png' );
		}
	},
	
	
	//unlink event handlers and elegantly dispose lightbox
	fader : function( h ){
		$("#slideshell").remove();
		$("#login-submit").unbind('click');
		$("#register-submit").unbind('click');
		$("#username").unbind( 'keydown' );
		h.o.remove();
		h.w.fadeOut( 440 );
	},


	wireLogin : function( h ){
		h.w.show();
		if( $("#register-submit").get().length){
			$("#register").jqmHide();
		}

	},
	
	showLB : function( h ){
		h.w.show();
	},
	
	wireRegister : function( h ){
//	debugger;
		$("#lbshell").jqmHide();
		h.w.show();

		
	},
	wireSubmit : function(){
		$('.register-submit').click( function(){
			$(this).parent().submit();
		});
	},
	
	
	//this just switches img source to highlight mouseover
	wireLinkMouseover : function( selector, png ) {
		
		if( png ){
			$( selector ).bind( 'mouseenter', function(){
				$(this).attr( { src : $(this).attr( 'src' ).replace( /\.png/, "-on.png" ) } );
			}).bind( 'mouseleave', function(){
				$(this).attr( { src : $(this).attr( 'src' ).replace( /-on\.png/, ".png" ) } );
			});
		} else {
			$( selector ).bind( 'mouseenter', function(){
				$(this).attr( { src : $(this).attr( 'src' ).replace( /\.gif/, "-on.gif" ) } );
			}).bind( 'mouseleave', function(){
				$(this).attr( { src : $(this).attr( 'src' ).replace( /-on\.gif/, ".gif" ) } );
			});
		}
		
		
		
	},
	setProp : function( prop, val ){
		//i know, i know. bad bad bad.
		eval('this.' + prop + '= "' + val + '"' );
	},
	
	scrollToTop : function( el /** string id* -- OR SELECTOR? */ ){
		
		if(!el){
			el = "#content-body";
		} else if( el.charAt(0) != '#' && el.charAt(0) != '.'){
			el = "#" + el;
		}
		this.db( "scrolling: " + el);

		//scroll to top of article (or whatever)
		var article = $(el).offset().top;
		if( document.documentElement && document.documentElement.scrollTop ){
			$(document.documentElement).animate( { scrollTop : article }, "slow" );
			return;
		} else 	if( document.body && document.body.scrollTop){
			$(document.body).animate( { scrollTop : article }, "slow" );
			return;
		} else 	if( window.pageYOffset ){
			$(window).animate( { pageYOffset : article }, "slow" );
		}
	}

};

Axlotl.prototype = Interact;

Axlotl.method( 'doLogin', function( refresh ){

//	$("#register").jqmAddTrigger( "a#forgotlink" );
	
		var forgotdiv = '<div class="modal jqmWindow" id="forgotshell" style="display:none;"><img src="/gfx/icons/ajax1.gif" class="load-indicator" alt="loading"/></div>';

		$("body").append(forgotdiv );
		$("#forgotshell").jqm( {  trigger : 'a#forgotlink', modal : false, onshow : axlotl.wireRegister,   onHide : axlotl.fader, ajax : '@href' });
		

	
	//allow keypress cancel and submit
	$("body").keydown( function ( e ){
		if( e.which	 === 27 ){ //escape key
			$("#lbshell").jqmHide();
		} else if( e.which === 13 ){  //return key
			e.preventDefault();
			subDoLogin(); 
		}
	});
	
	//submit button
	$( '#login-submit' ).bind( 'mousedown', function(){ subDoLogin(); });
	
	var subDoLogin = function(){	
		var reqStr = $("#loginform").serialize() + '&output_format=json&nocache=1';
		

//			$.getJSON( axlotl.url + '?' + reqStr);
		$.getJSON( axlotl.url + '?' + reqStr, function( data ){
			
			if( data.MESSAGE === "LOGIN_SUCCESSFUL" || data.MSG === "LOGIN_SUCCESSFUL"){
				
				
				//after all my work we change to a universal reload on login
				var refresh = true;
				if($(".milk-contest").get().length){
					refresh = true;
				}
				
				if(document.location.pathname.indexOf('mosaic_register') > 0 ){
					refresh = 1;
				}
				//if its an administrator, just reload. too much crap to load piece by piece.
				if( (data.data.children && data.data.children.public && 
					data.data.children.public.administrator && data.data.children.public.administrator.module && 
					typeof(data.data.children.public.administrator.module.length) !== "number" )
				|| refresh ){
					document.location.href = document.location.protocol + '//' + document.location.host + document.location.pathname + document.location.search;
				}
				var url = data.data.url;
				var title = data.data.title;
				//close the dialog
				$("#lbshell").jqmHide();
				
				//replace the usernave with appropriate links
				var htmlStr = '<div id="usernav">' +
							'<a href="/account/' + url.toLowerCase() + '">Hi ' + title + '</a>' +
							'<a href="/account/' + url.toLowerCase() + '/edit/">Edit Your Profile</a>' +
							'<a href="/logout">Logout</a>' +
							'</div>';
//				$("#usernav").replaceWith( htmlStr );
		
				//set some vals
				//axlotl.siteuser.guid = data.data.guid;
				//axlotl.siteuser.title = data.data.title;
				
				axlotl.setProp( 'siteuser.guid', data.data.guid );
				axlotl.setProp( 'siteuser.title', data.data.title );
				
				//turn on some of the stuff that you can do now
				$("#commentopen").attr( { href : '/lightbox/comment.php?parenttype=account&parent=' + axlotl.siteuser.guid } );
				$("#saveopen").attr( { href : '/lightbox/confirmsave.php' } );
				$("#emailopen").attr( { href : '/lightbox/email.php' } );
				
				if($("#messagelogin").get().length){
					document.getElementById('div_updatecomment').style.display = 'block';
					$("#poster").val( data.data.guid );
				}
				
				
				//profile wall
				if($("#poster").get().length){
					$("#poster").val(data.data.guid);
				}
				if($("#owner").get().length){
					$("#owner").val(data.data.guid);
				}
				
				//wire up one or more ratings widgets based on classname of anchor wrapper
				if( $(".starlogin").get().length){
					$.each( $(".starlogin") , function(){
						$(this).replaceWith( $(this).html() );
					});
					$(".starwidget" ).mousedown( axlotl.updateRating ).bind('mousemove', axlotl.updateRating );
					
				}
				
				//mini-interact links
				if($(".mini-buttons").get().length){
					$.each( $(".mini-buttons li a.glogin"), function( ){
						var origHref = $(this).attr( 'href' );
						
						origHref = origHref.replace(/\/lightbox\/login\.php\?refresh=1&/, "");
						axlotl.db( origHref );
						var type = origHref.match(/type=([a-z]+)&/)[1],
						url = origHref.match(/url=([a-z|_|0-9|A-Z]+)&/)[1],
						mod = origHref.match(/mod=([a-z]+)$/)[1];
						
						var newHref = '/' + type + '/' + url + '?mod=' + mod,
						inner = $(this).html();

						$(this).replaceWith( '<a href="' + newHref + '">' + inner + '</a>' );

					});
				}
				

				//wire up forum links
				if( $(".forum-comment-login").get().length){
					var newHref = $(".forum-comment-login").attr('href').replace(/login/, "discussion" );
					var newParam = 'poster=' + axlotl.siteuser.guid;
					newHref = newHref.replace(/poster=/, newParam );
					var htmlStr = 'POST A RESPONSE<img src="/gfx/elements/gray-post-button.gif" alt="submit"/>';
					$(".forum-comment-login").attr( { href : newHref } ).html( htmlStr );
					
				}
				if($(".forum-response-login").get().length ){
					var newHref = $(".forum-response-login").attr('href').replace(/login/, "discussion" );
					var newParam = 'poster=' + axlotl.siteuser.guid;
					newHref = newHref.replace(/poster=/, newParam );
					var htmlStr = 'COMMENT ON THIS RESPONSE<img src="/gfx/elements/gray-post-button.gif" alt="submit">';
					$(".forum-response-login").attr( { href : newHref } ).html( htmlStr );
				}
				
				if($(".forum-topic-login").get().length ){
					var newHref = $(".forum-topic-login").attr('href').replace(/login/, "discussion" );

					var htmlStr = 'RECOMMEND A TOPIC<img src="/gfx/elements/gray-post-button.gif" alt="submit">';
					$(".forum-topic-login").attr( { href : newHref } ).html( htmlStr );
				}
				

				//video emailer
				if($("#videoemail").get().length){
					var oldHref = $("#videoemail").attr( 'href' );
					var newHref = oldHref.replace(/login/, "email");
					$("#videoemail").attr( { href : newHref } );
				}

				
				//unhook handlers
				$("body").unbind( 'keydown' );
				$('.register-submit').unbind( 'click' );
			} else {
				$("small.redmessage").fadeIn( 200 );
			}
		});
		
	};
	
});


Axlotl.method( 'refreshUserNav', function( username ){

	axlotl.setProp( 'siteuser.title', username );
	var markup = '<p class="loner">WELCOME BACK <strong>' + username + '</strong></p><ul><li><a href="/account' + username + '">View Your Profile</a>|</li><li><a href="/account/' + username + '/edit">Account settings</a>|</li><li><a href="/logout">Log Out</a></li></ul>';
	$("#usernav").html(markup);
});

//this is the pagination for comments.
Axlotl.method('repaginate', function( e ){ 
	e.preventDefault();
	e.stopPropagation();
	var qstr = '/ajaxcomments/', self = axlotl;

	//startrow regex
	var re = /startrow=([0-9]+)/;

	//our destination comment page
	var loc = e.target.href;

	//get the new page number
	var locstart = loc.match(re);
	var newPage = parseInt(locstart[1], 10);

	//set the style class of the new link (to nonlink)
	$(".comments .pagination li a.nonlink").removeClass( "nonlink");
	$(this).addClass( "nonlink" );

	//grap the query string and append it to the template url
	qstr += loc.slice( loc.indexOf('?'), loc.length );

	//get the new comments and insert them
	$(".commentlist").load( self.url + qstr, null, function(){
		self.scrollToTop("interact");
	});

	//comments pagination data
	var pObj = self.pagination;

	//rewire 'older' and 'newer' links
	var newstart = 'startrow=';
	//'newer'
	if( newPage   > 0 ){
		newstart  +=  newPage  - pObj.numrows;
		$("#newer").attr( 'href', loc.replace(re, newstart )).removeClass( 'nonlink' );
	} else {
		newstart  += 0;
		$("#newer").attr( 'href', loc.replace(re, newstart )).addClass( 'nonlink' );
	}

	//'older'
	newstart = 'startrow=';
	if( (newPage + pObj.numrows)  < pObj.total ){
		newstart += newPage + pObj.numrows;
		$("#older").attr( 'href', loc.replace(re, newstart )).removeClass( 'nonlink' );
	} else {
		newstart += pObj.total - ( pObj.total % pObj.numrows );
		$("#older").attr( 'href', loc.replace(re, newstart )).addClass( 'nonlink' );
	}


	//if we got here through newer or older links, we need to 'nonlink' the matching page number.
	$.each($(".comments .pagination li a"), function(){
		var elem = $(this);
		if( elem.attr('href').match( re )[1] == newPage ){
			if( !elem.hasClass( 'nonlink' ) ){
				elem.addClass( 'nonlink' );
			}
		}
	});	
});

//this is the pagination for articles
Axlotl.method( 'paginate', function(){	
	var self = axlotl;

	//wire up the page number "links"
	$(".pagination li").click(function( e ){
		
		//numerical id shared by page and page number
		var target = $(this).attr('id').match(/\d+/);

		//the page
		targetDiv = "#paginate_" + target;
		
		//the page number link
		targetRef = "#pagenav" + target;
		
		//move current page out of the window, move selecte4d page in.
		$(".pageshell").css( { position: 'absolute', left : "-199em", height : '0px' } );
		$( targetDiv ).css( { left: 0, position: 'static', height : 'auto'} );
		$(".filmworld-article-nav .pagination .nonlink").removeClass("nonlink");
		$(targetRef).addClass( "nonlink" );
		
		
		self.scrollToTop( '.article-body' );
		if(typeof(setBG) == "function" ){
			setBG();
		}
		

	});	
});

Axlotl.method('selectorize', function( els ){
	var  ids, s="";
	
	//single string id
	if( typeof( els ) === "string") {
		return "#" + els;
	 
	//array of id strings
	} else if( typeof( els ) === "object" && els.length ) {
		

		//make a jquery selector from the array
		$.each( els, function(){
			s += "#" + this + ",";
		});
		//remove trailing comma
		return s.substring( 0, (s.length - 1 ));
	} else {
		axlotl.db("selectorize:: invalid arg: " + typeof(els));
		return false;
	}
	
});

Axlotl.method( 'checkUnique', function( els /** string id or array of ids */){

	var ids = this.selectorize( els );

	//on keyUP so we see the last entered character
	$(ids).bind( 'blur', function(){

		//inp is the actual input el, proposed is its current value
		var inp = $(this);
		var proposed = escape($(this).val());
		
		//don't bother with empty strings
		if(!proposed.length){
			return;
		}
		
		var id = $(this).attr("id");
		var tit =  $(this).attr("name");
		axlotl.db(proposed);
		var data = {
			publickey : axlotl.pk,
			output_format : "json",
			field : tit,
			type : 'account',
			value : proposed
		};
		
		//check for uniqueness
		$.getJSON( axlotl.baseurl + '/services/isunique/', data, function( response ){
			axlotl.db(response);
			if(!!response){
				if( ! response.success ){

					//failure. set classes
					if( $(inp).hasClass( "valpass" ) ){
						$(inp).removeClass( "valpass" ).addClass( "valfail" );
					}

					$(inp).addClass( "valfail" );
					$('#errorDiv').html('<small class="redmessage">That ' +id + ' is already taken.</small>' );
				} else {

					//ok now! set classes
					if( $(inp).hasClass( "valfail" ) ){
						$(inp).removeClass( "valfail" ).addClass( "valpass" );
						$('#errorDiv').html('<small class="bluemessage">That one\'s OK!</small>');
					}
				}
			}
			
		});
		
	});
});

Axlotl.method( 'regform', function( button, form, xtra ){ //string ids
	var self = axlotl;
	
	//set these as members so are available
	//in previously anonymous form (now axltol.submitRegistration())
	self.xtra = xtra;
	self.form = form;
	
	
	axlotl.db('button: ' + button );
	axlotl.db( 'test: ' + $("#" + button).get().length );
	if(!$("#" + button).get().length ){
		return;
	}
	
	

//	debugger;
	axlotl.checkUnique( ['username', 'email' ] );

	//set the action to current page
	$("#" + form ).attr( { 'action' : document.location.pathname + document.location.search } );
	$("#registertarget").val(document.location.pathname + document.location.search );
	


	//month length calculator and inserter
	
	$("#birthday_month, #birthday_year").bind( "change", function(){
		
		//we don't have a month yet
		if($("#birthday_month").val() === "MONTH" ){
			return;
		}
		var ml = [ 31, , 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
		var y = parseInt(document.getElementById("birthday_year").value, 10) || new Date().getFullYear();
		var monthVal = parseInt(document.getElementById("birthday_month").value, 10) - 1;
		var l = ml[monthVal] || 28 + !( y % 3 );

		var htmlStr = '<select id="birthday_day" name="birthday_day">';
		htmlStr += '<option selected="selected" value="">DAY</option>';
		for( i = 1; i <= l; i++){
			htmlStr += '<option value="' + i + '">' + i + '</option>';
		}
		htmlStr += '</select>';
		$("#birthday_day").replaceWith( htmlStr );
	});
	
	
	$("#" + button).click( self.submitRegistration );

});

Axlotl.method( 'submitRegistration', function( e ){ 
	e.preventDefault();
	var self = axlotl;
	axlotl.db('regform internal anon func called. target: ' + e.target );
	
	//this whole conditional can be removed when the 
	//whoinspiresyou contest is over
	if(self.xtra){
		
		
		var popError = function( msgs ){
			var err = '<ul>';
			$.each(msgs, function(i, val){
				var sel = "#" + i;
				axlotl.db( i + "::" + val );
				err += '<li>' + val + '</li>';
				$(sel).css( { border : '1px solid red', background : '#ffffee' } ).bind( 'focus', function(){
					$(this).css( { border : '1px solid #6290B7', background: '#ffffff' });
				});
			});
			err += '</ul>';
			$("#otherErrDiv").html( err ).show();

		};
		
		var err = false;
		var msgs = {};
		if(!$("#college").val().length ){
			err = true;
			msgs['college'] = "College is required";

		}
		
		 if(!$("#org").val().length){
			msgs['org'] = "Organization is required";
			
			err = true;
		} 
		//
		var xxxx = 10;
		
		//age check
		if($("#bd-input").get().length){
			if($("#birthday_year").val() == ''
			|| $("#birthday_month").val() == ''
			|| $("#birthday_day").val() == ''){
				msgs ['bd'] = "Birthday is required.";
				err = true;
			} else {
				var y, b, nd, f, d = new Date(), a = 16; /**a = age requirement in years*/
				y = 31556926; /** one year in seconds */
				b = d.getTime() - (y * a * 1000); //"a" years ago
				nd = new Date(b);
				f = self.fd( "YYYY MM DD", nd ).split(" ");
				var niced = self.fd("DD, Month YYYY", nd );
				self.db( a + " if born by " + niced);
				var bd = new Date($("#birthday_year").val() + ' ' + $("#birthday_month").val() + ' ' +  $("#birthday_day").val()).getTime();
				
				self.db("bd: " + bd + " ::cutoff: " + nd.getTime());
				if( bd > nd.getTime() ){
					self.db("too young");
					msgs['tooyoung'] = "You must be 16 to enter this contest";
					err = true;
				}
			}
			
			
		}
		
		if( err ){
			popError(msgs);
			return;
		}
	}
	if( $("textarea.milk-loggedin").get().length){
		if($("#mystory").val().length == 0 ){
			alert("you cannot submit an empty story" );
			return false;
		}
	}
	$("#errDiv").html("<small></small>");
	
	axlotl.db( 'here we go: ' + self.form );
	//axlotl.db( 'SubmitForm(document.getElementById( "'+ self.form + '" ), false);');
	//SubmitForm(document.getElementById( self.form ), false);
	
	mrkp = $('#' + self.form).html();
	
	$('#' + self.form).css('display', 'none');
	$('#' + self.form).before('<div id="ajaxstatus" style="clear:both;width:340px;text-align:center;font-size:20px;font-weight:900;padding:20px 5px"><img src="/gfx/elements/loadercircles.gif" /><br />Please wait while we submit your form.</div>')
	$('#register_submit').css('display','none');

	//return true;
	
	if(Validate(document.getElementById( self.form ), false)) {
	
		var formdata = formToArray(self.form);
		if (formdata) { 
			trace("got form data");
		} else {
			trace("no form data!");
			return;
		}
	
		formdata.output_format = 'json';
		url = baseurl + '/services/' + formdata.service;
	
		resp = srcGet(url, formdata, null);
		trace('RESPONSE::' + resp);
		resp = JSON.parse(resp);
		if(resp.register == 1) {
			window.document.location = window.document.location;
		} else {
			$('#' + self.form).css('display','block');
			$('#ajaxstatus').remove();
			$('#register_submit').css('display','inline')
		}
	
	} else {
		$('#' + self.form).css('display','block');
		$('#ajaxstatus').remove();
		$('#register_submit').css('display','inline');
		return false;
	}
	
});



Axlotl.method( 'pngfix', function(){
	if($.browser.msie && /MSIE\s(5\.5|6\.)/.test(navigator.userAgent)){
			$("img[src$='.png']").ifixpng();
	
	
			$("#greenisu").ifixpng();

			$(".img-replace").ifixpng();
			$("#subfoot").ifixpng();
			$(".title h1").ifixpng();
	
	}
	
	
});

Axlotl.method( 'saveFave', function(){
	var self = axlotl;
	axlotl.wireLinkMouseover( '#closebutton' );
	axlotl.wireLinkMouseover( '.register-submit' );

	$('.register-submit').bind( 'click', function(e){ doFavorite(e); });
	
	//allow keypress cancel and submit
	$("body").keydown( function ( e ){
		if( e.which	 === 27 ){ //escape key
			$("#lbshell").jqmHide();
		} else if( e.which === 13 ){  //return key
			e.preventDefault();
			doFavorite( e );
		}
	});

	var doFavorite = function(e){
		e.preventDefault();
		e.stopPropagation();
		var data = {
			child : axlotl.media.guid,
			childtype : axlotl.media.type,
			publickey : axlotl.pk,
			parent : axlotl.siteuser.guid,
			parenttype : "account",
			relation : "favorite",
			output_format : "json",
			service : "addrelationship"
		};
		
		$.getJSON( axlotl.url, data, function( response ){
			if( response.addrelationship ){
				$("#lbshell").jqmHide();
			} else {
				$("#message").text( "Sorry, there was a problem saving this favorite.");
			}
		});
		
		//unhook handlers
		$("body").unbind( 'keydown' );
		$('.register-submit').unbind( 'click' );
		return false;
	};

});


Axlotl.method( 'sendComment', function( params ){
	
	
	var reqData, self = axlotl,
	nickname = params.nickname,
	fullname = params.fullname,
	userUrl = params.userUrl,
	timestamp = params.timestamp,
	commentbody = params.commentbody;

	reqData = {
		item : self.media.guid,
		publickey : self.pk,
		itemtype : self.media.type,
		type : 'comment',
		output_format : 'json',
		poster : $("#poster").val(),
		owner : $("#owner").val(),
		service : 'updateasset',
		comment : commentbody,
		nocache : 1
	};
	//var x = reqData;
     
	$.getJSON( axlotl.baseurl, reqData, function(req){
		this.data = req;
		$("#lbshell").jqmHide();
		$("#inserted").removeAttr('id');
		var commentHTML = '<li style="display:none;" id="inserted"><small>On ' + timestamp +
		 			' <a href="' + userUrl + '">' + nickname + '</a>' +
					' said:</small><p>' + req.comment + '</p></li>';
		$(".commentlist li:first").before( commentHTML );
    
		$("#inserted").effect( "highlight", {  }, 1000);
		if($("#nocomments").get().length){
			$("#nocomments").replaceWith("<li></li>");
		}
	});
	
	//unhook handlers
	$("body").unbind( 'keydown' );
	$('.register-submit').unbind( 'click' );
});



Axlotl.method('displayWindow', function(url, w,h,features) { 
	axlotl.db("hi");
	var window_width = w ? w : 800;
	var window_height = h ? h : 600;
	var winName = "Popup";
	/**
	if (document.all || document.layers) {
	window_width = screen.availWidth;
	window_height = screen.availHeight;
	}else{
	window_width = screen.width;
	window_height = screen.height;
	}
	*/
	var newfeatures = features;
	var window_top = Math.floor((screen.height-window_height)/2);
	var window_left = Math.floor((screen.width-window_width)/4);
	axlotl.db('width=' + window_width + ',height=' + window_height + ',top=' + window_top + ',left=' + window_left + ','+ newfeatures + '');
	var newWindow=window.open(url,'' + winName + '','width=' + window_width + ',height=' + window_height + ',top=' + window_top + ',left=' + window_left + ','+ newfeatures + '');
	newWindow.focus();
});


Axlotl.method('loadVid', function(e){
	
	e.preventDefault();
	e.stopPropagation();
	var self = axlotl;
	self.db('loadVid');
	var guid = $(this).attr('className').replace(/moused/, "").replace(/title/, "").trim();
	self.db(guid);
	
	var r = Math.floor( Math.random() * 1000000);
	var flashvars = {};
	var params = {};
	var attributes = {};
	params.menu = "false";
	flashvars.showPlacard = '0';

	params.allowScriptAccess = "sameDomain";
	params.allowFullScreen = "true";
	params.quality = "high";
//	flashvars.videoUrl = "<= $feature->data['title']; ?>";
	flashvars.anurl = "http://fif.s3.amazonaws.com/" + guid + ".480x270_hi.mp4";
	axlotl.db(flashvars.anurl);
	params.wmode = "transparent";
	swfobject.embedSWF( "/swf/video_player_480x270.swf?rand=" + r, "videoplayer", "478", "299", "9.0.0", false, flashvars, params, attributes);
});

Axlotl.method('loadSlide', function( e ){
	e.preventDefault();
	e.stopPropagation();

	var self = axlotl, source, guid, qstr;
	self.db('loadSlide');
	//photo guid from the src
//	guid = $(this).attr( "src" ).match( /\/([0-9a-z\-]+)\/\d+x\d+\.jpg/)[1];
	
	//oh wait. the service uses the title ($data->['url'])
//	var title = $(this).attr( 'title' );
	var title = $(this).attr('className').replace(/moused/, "").replace(/title/, "").trim();
	axlotl.db("getting: " + self.baseurl + '/account/ajaxphoto?nocache=1&photo=' + title);
	$.getJSON( self.baseurl + '/account/ajaxphoto?nocache=1&photo=' + title, function( response ){
		
		
		
		//replace the photo's src
		$("#profile-photo-main-view img#slideshow-feature").attr( { src : self.baseurl + '/uploads/image/mediafile/' + response.guid + '/535x.jpg'} );
		
		self.db( response);
		//set the text parts
		$(".profile-photo-heading").html( response.title );
		$("#photodesc").html( response.description );
		$("#photocredit").html(response.credit );
		
		//reset object properties so we can interact on the new image
		self.setProp( 'media.guid', response.guid);
		self.setProp( 'media.title', response.title);
		
	
		//comments
		qstr = '/asset/ajaxcomments/?nocache=1&startrow=0&numrows=20&parenttype=photo&parent=' + response.guid;

		//get the new comments and insert them
		$(".commentlist").load( self.baseurl + qstr );

		//and ratings. sheesh.
		//exists but can be "0"
		if(response.average > -1 ){
			$("#av").text(response.average);
		}
		
		
		//remove ratings of previous slide
		$.each( self.starclasses, function( prop, val ){
			$("#starbox").removeClass(val);
		});
		
		//set guid class of ratings stars to the current slide:
		var newClass;
		if( newRatings[response.guid] && newRatings[response.guid].rating){
			newClass = 'starwidget guid ' + response.guid + ' ' +  self.starclasses[newRatings[response.guid].rating];
		} else {
			newClass = 'starwidget guid ' + response.guid;
		}
		self.db( "setting rating stars to className " + newClass );
		$("#starbox").attr( { className : newClass } );
		
		//if( response.userrating > -1 ){
		//can stop calculating ratings in ajaxphoto.inc and use the json instead.
		if( newRatings[response.guid] && newRatings[response.guid].rating ){
			
			//remove current rating class
			self.db( 'adding rating class  ' + self.starclasses[newRatings[response.guid].rating]);
			

			//add rating from response
			$("#starbox").addClass( self.starclasses[newRatings[response.guid].rating] );
		}

		if(response.notthere < -1){
			alert("oops");
		}
		
		$(".pagination").remove();
	}, function(){
		
		//callback: if we have a js-set bg position (e.g. coraline) reset that
		if(typeof(setBG) == "function" ){

			setBG();
		}
	});
	
});

Axlotl.method( 'setCarousel', function(){
	
	var slideBrowserWidth = 0, unit = 0;
	
	$("#profile-photo-nav ul li").map( function(){
		unit = $(this).width();
		slideBrowserWidth += unit;
		
	});
	$("#profile-photo-nav ul").css( { width : slideBrowserWidth });
	return slideBrowserWidth;
});

Axlotl.method('browseSlides', function( e ){
	var self = axlotl;
//	debugger;
	var  slides = 4;
	var unit = $("#profile-photo-nav ul li:first").width();
	var slideBrowserWidth = self.setCarousel();
//axlotl.db('unit: ' + unit + '  width: ' + slideBrowserWidth + '  unit*slides: ' + (unit*slides) );
	//too few photos to browse
	if( slideBrowserWidth <= unit * slides ){
		$("#profile-photo-nav span.leftnav").addClass( "unset" );
		return;
	}

	//fudge a little wiggle room
	slideBrowserWidth += 10;
	
	
	//which way are we going
	var direction = $(this).attr('class').replace(/nav/, "");
	var delta = unit * slides;
	
	//which way we goin?
	if( direction.indexOf( "right" ) !== -1 ){
		delta *= -1;
	}
	
	//our destination 'left' setting
	var dest = parseInt($("#profile-photo-nav ul").css( "left" ), 10) + delta;
	
	
	//turn the buttons on or off as needed (visual cue)
	if( (dest + slideBrowserWidth ) < unit * slides ){
		$("#profile-photo-nav span.rightnav").addClass( "unset" );
	} else {
		$("#profile-photo-nav span.rightnav").removeClass( "unset" );
	}
	
	if( dest >= self.browserOrigLeft ) {
		$("#profile-photo-nav span.leftnav").addClass( "unset" );
	} else {
		$("#profile-photo-nav span.leftnav").removeClass( "unset" );
	}
	
	//don't let it dest beyond either edge (actually enforce it)
	if( (dest + slideBrowserWidth) < 0 || dest > self.browserOrigLeft ){
		return;
	}
	
	//set the width of the thumbnail list and then move it
	//(now we set the width in a separate function, setCorousel)
	$("#profile-photo-nav ul").animate(
		{ left : dest }, "slow"
		);

	
});


Axlotl.method('updateRating', function( e ){

	
	var wLoc = $('.starwidget').offset(),
	self = axlotl, 
	update, 
	av, 
	itemGuid, 
	data, 
	source;
	
	var baseWidth = $(".starwidget").width();
	var starunit = baseWidth / 5;

	//our rating, based on mouse position over the widget
	update = Math.ceil(( e.clientX - wLoc.left ) / starunit );
//	self.db( "( e.clientX - wLoc.left ) :" + e.clientX +" :: " + wLoc.left  + " ::total:: " + ( e.clientX - wLoc.left )  );
//	self.db(update + " :: " + starunit);

	//make sure we've computed a valid rating
	if( update > 0 && update < 6 ){
		
		//we're handling animation and the actual rating in the same handler,
		//switching on whether the mouse is moving (animate the stars)
		//or clicking (send the rating and set the average)
		if( e.type == "mousedown" || e.type == "mouseleave"){		

			//turn off the mousemove handler AND the reattachment handler so we can see the rating returned from the server
			//(and remove the moseover class)
			$(this).unbind( 'mousemove' ).unbind( 'mouseenter' ).unbind('mousedown').unbind("mouseleave").removeClass("mo");

			itemGuid = self.media.guid;
			if($(this).hasClass( "guid" ) ){
				itemGuid = $(this).attr('class').replace( /starwidget/, "" );
				itemGuid = itemGuid.replace(/guid/, "" );
				itemGuid = itemGuid.replace(/zero|one|two|three|four|five/, "" );

				itemGuid = itemGuid.trim();
				
				self.db("setting itemGuid to " + itemGuid );
			}
			if( e.type == "mouseleave"){
				
				//return to the last rating from user
				/**
				*	TODO: multivote needs to handle this differently!
				*	if(we've voted since pageload){ use that } else { same as below }
				*/
				if(newRatings[itemGuid] && newRatings[itemGuid].rating){
/**
					self.db( "itemGuid: " + itemGuid + " :: starclasses[userRatings[itemGuid]]: " + self.starclasses[newRatings[itemGuid].rating] );
					self.db( "newRatings[itemGuid].rating: " + newRatings[itemGuid].rating );
					self.db( "newRatings[itemGuid].guid: " + newRatings[itemGuid].guid );
					self.db( "newRatings[itemGuid].rateditem: " + newRatings[itemGuid].rateditem );
*/
					//set the stars to the users previous rating of this item
					var clname =  'starwidget guid ' + itemGuid + ' ' +  self.starclasses[newRatings[itemGuid].rating];
					$(this).attr( { className : clname } );
				}
				
			} else {
				//send the rating to the server
				var ratingGuid = 0;
				if(newRatings[itemGuid]){
					if(newRatings[itemGuid].guid){
						var ratingGuid = newRatings[itemGuid].guid;
					}
				} 
					

				data = {
					rateditem : itemGuid,
					ratedtype : self.media.type,
					rater : self.siteuser.guid,
					type : 'rating',
					publickey : self.pk,
					rating : update,
					service : 'updateasset',
					output_format : 'json',
					nocache : 1,
					guid : ratingGuid
				};


				$.getJSON( self.baseurl, data, function( req ){

					//successful call to webservice?
					if( req.updateasset ){
						if( req.rating.totals.average === null ){
							if(typeof(req.rating) == "number"){
								av = req.rating;
							} else {
								av = 0;
							}

						} else {
							av = req.rating.totals.average.substring( 0, req.rating.totals.average.lastIndexOf( '.' ) + 2 );
						}


						self.db( "setting newRatings key " + itemGuid + " to rating " + update );
						//set the new rating in the userRatings hash (if it exists)
						if(req.siteuserrating) {
							newRatings[itemGuid] = {
								'rating' : update,
								'guid' : req.siteuserrating,
								'rateditem' : itemGuid
							};
						}
						
			
						
						//display the recalculated average
						$("#av").text( av );
					}
				});
			}
			

			//turn the mousemove handler back on next time we REenter the element if we can vote again
			if( self.multivote ){
				$(this).bind( 'mouseenter', function( ev ){
					$(this).bind( 'mousemove', self.updateRating ).bind('mousedown', self.updateRating ).bind("mouseleave", self.updateRating );
				});
			}
		} else {
			//mousemove: just update the image
			
//			source = '/gfx/elements/icon/stars/stars-bl-' + update + '.gif';
			self.db( "update: " + update + " :: starclasses[update]: " + self.starclasses[update] );
			$(this).addClass("mo")
			.removeClass('zero')
			.removeClass('one')
			.removeClass('two')
			.removeClass('three')
			.removeClass('four')
			.removeClass('five')
			.addClass(self.starclasses[update]);
			
			//$(this).attr( { src :  source } );

		}
		$("#starbox").ifixpng();
	} 
});

/**
*	a fix for loging out by sending ?service=logout, which leaves that in the url after
*	(this causes a variety of problems)
*
*	Now we logout via ajax, then refresh page.
*/
Axlotl.method( 'logout', function( e ){
	e.preventDefault();
	e.stopPropagation();
	var self = axlotl;
	var reqData = {
		'service' : 'logout'
		, 'output_format' : 'json'
		, 'nocache' : 'true'
	};
	$.getJSON( self.fullurl, reqData, function( response ){
		self.db(response);
		
		if( axlotl.fullurl.indexOf('?') !== false ){
			var xtra = '&nocache=1';
		} else {
			var xtra = '?nocache=1';
		}
		self.db( 'document.location.href = ' + self.fullurl + xtra );
		document.location.href =  self.fullurl;
	});

});





//instantiate the class containing the php data
var axlotl =  new Axlotl();



//domready
$(function(){
	//png fix
		axlotl.pngfix();
		
		
		
		$("#global_logout").click( axlotl.logout );
		
		
		//wire up the login link lightbox
		$("#globallogin").attr( { href : '/lightbox/login.php' } );
		
		//autoselect embed source onfocus
		$("#embed").bind( 'click', function(e){
			$(this).focus();
			$(this).select();
		});
		
		
		//fully qualified hrefs == offsite link == new window
		$("a").each(function(){
			var hrf = $(this).attr( 'href' );
			if(!!hrf){
				if( hrf.match(/^http:\/\//)){
					$(this).attr( { target : "_blank" } );
				}
			} 
		});
		
		
		if( $(".pageshell").get().length ){
			axlotl.paginate();
		}
		
		//annoying: remove the border from the last div in  the about me sections
		$(".aboutme-section div:last-child").css({ borderBottom : "none" });

		//comments pagination ajax
		$("ul.pagination li a ").click( axlotl.repaginate );


		//lightbox links 
		if( axlotl.siteuser.guid  ){
			var interactdiv = '<div class="marquee jqmWindow" id="lbshell" style="display:none;"><img src="/gfx/icons/ajax1.gif" class="load-indicator" alt="loading"/></div>';
			$("body").append(interactdiv);
			$("#lbshell").jqm( {  trigger : ".interactButton", modal : true,  onShow : axlotl.showLB, onHide : axlotl.fader, ajax : '@href' });

			//ratings widget handler
			axlotl.prepStars();
			$(".starwidget" ).mousedown( axlotl.updateRating ).bind('mousemove', axlotl.updateRating ).bind('mouseleave', axlotl.updateRating );
		} else {
			//global login
			var logindiv = '<div class="modal jqmWindow" id="lbshell" style="display:none;"><img src="/gfx/icons/ajax1.gif" class="load-indicator" alt="loading"/></div>';
			var registerdiv = '<div class="modal jqmWindow" id="regshell" style="display:none;"><img src="/gfx/icons/ajax1.gif" class="load-indicator" alt="loading"/></div>';

			$(".gregister").each(function() {
				theurl = $(this).attr('href');
				qs = theurl.substring(theurl.indexOf('?'));
				trace(theurl + '::' + qs);
				$(this).attr( { 'href' : '/lightbox/register.php' + qs } );
			});

			//$(".gregister").attr( { 'href' : '/lightbox/register.php' } );
			$(".glogin").attr( { 'href' : '/lightbox/login.php' } );
			$("body").append(logindiv).append(registerdiv );
			$("#lbshell").jqm( {  trigger : ".glogin",   onShow : axlotl.wireLogin, onHide : axlotl.fader, ajax : '@href' });
			$("#regshell").jqm( {  trigger : '.gregister',   onShow : axlotl.wireRegister, onHide : axlotl.fader, ajax : '@href' });



			//ratings widget handler
			axlotl.prepStars();
			$(".starwidget" ).bind('mousemove', axlotl.updateRating );
		}
		
		

		
		//popup print window
		$("li.printopen a").click( function( e ){

			e.preventDefault();
			e.stopPropagation();
			
			var tit = $(this).attr( "title" );
			var hrf = axlotl.baseurl + $(this).attr( "href" );
		//	alert( 'href: ' + hrf + ' title: ' + tit );
		if($.browser.msie ){
			tit = "";
		}
			window.open( hrf, tit, "scrollbars=1,resizable=1,width=682,height=780" );
		});
		
		
		//redirects from mini-interact
		if( axlotl.autolaunch.mod ){

			var loc = '/lightbox/' + axlotl.autolaunch.mod + '.php';
			if( axlotl.autolaunch.mod === "comment" ){
				loc += '?parenttype=' + axlotl.media.type;
				loc += '&parent=' + axlotl.media.guid;
			} 
			$("#lbshell").jqm( {ajax : loc} );
			$("#lbshell" ).jqmShow();
			
			//now hook up regular behavior under the covers
			$("#lbshell").jqm( {  trigger : ".interactButton", modal : true,  onShow : axlotl.showLB, onHide : axlotl.fader, ajax : '@href' });
		}
		
		//wire up the photo browser thumbnails
		$("#profile-photo-nav ul li a").bind( 'click', 

			 axlotl.loadSlide 
		).bind( 'mouseenter', function(){
			$(this).addClass( "moused" );
		}).bind( 'mouseleave', function(){
			$(this).removeClass( "moused" );
		});
		

		$("div#profile-photo-nav.video ul li a").unbind('click'
		).bind( 'click', axlotl.loadVid ).bind( 'mouseenter', function(){
			$(this).addClass( "moused" );
		}).bind( 'mouseleave', function(){
			$(this).removeClass( "moused" );
		});

		
		//remember the original starting point for the slide browser
		axlotl.browserOrigLeft = parseInt($("#profile-photo-nav ul").css( "left" ), 10);
		$("#profile-photo-nav span").bind( 'mousedown', axlotl.browseSlides );
		
		//set the carousel width
		axlotl.setCarousel();

		
		//subscribe-unsubscribe links
		if($(".comm-links").get().length){
			$(".comm-links").click( function( e ){
	//			debugger;
				var z = $(this).attr('class');
				var y = z.match(/unsub/);
				if($(this).attr('class').match(/unsub/) ){
					$.getJSON( axlotl.baseurl + '?service=deleterelationship&' + $("#unsub").serialize(), function( resp ){
						if(resp.deleterelationship ){
							$("#unsublink").html("Subscribe via email").attr( { id : 'sublink' } );

							$("#unsub").attr( { id : 'sub' } );
							$(".unsub").removeClass("unsub").addClass("sub");
						}
					});
				} else {
					$.getJSON( axlotl.baseurl + '?service=addrelationship&' + $("#sub").serialize(), function( resp ){
						if(resp.addrelationship ){
							$("#sublink").html("Unsubscribe from Email Updates").attr( { id : 'unsublink' } );
							

							$("#sub").attr( { id : "unsub" } );
							$(".sub").removeClass("sub").addClass("unsub");
						}
					});
				}
			});
		}
		
		//media room tabs
		if($("#videoplayer").get().length ){
			axlotl.prepTabs();
		}
		
	
		if(!!newRatings){
			
			//the user's ratings are in a json string in the header called newRatings
			//index is item guid, val is a hash of rating, guid(of the rating), and the guid of the item
			$.each( newRatings, function( item, arr ){
				var rating = arr.rating;

				var selector = "#starbox." + item;
				
				
				//see if there's a star rating module for this media item
				if($(selector).get().length){
					if($(selector).hasClass("guid")){
						axlotl.db('setting rating ' + rating + ' for item ' + arr.rateditem );
						
						var score = newRatings[item].rating;
						// we set the star to zero on pageload as a rule so remove that and
						// set the class from the rating instead
						$(selector).removeClass('zero').addClass( axlotl.starclasses[score] );
					
					}
				}
			});
		}
		
		
		//mainnav controls
		$("#mainnav > li").bind('mouseenter', function(){
			axlotl.db("curlist: " + $(".curlist").attr('className' ) );
			
			
			$(".curlist").hide().removeClass('curlist');
			var secid = $(this).attr('id');
			$("." + secid).show().addClass('curlist');
			
			//dont affect a mousreover on the current tab
			if(!$(this).hasClass('current') || $("#home").get().length > 0){
				$(this).addClass('moused');
			}
			
		}).bind('mouseleave', function(){
			$(this).removeClass('moused');
			$(".curlist").hide();
			$(".curlist").removeClass( 'curlist' );
			if($(".current").get().length){
				
				$(".current > ul").show().addClass('curlist');
			}
		});
	
	
		//global searchform
	$("#searchterms").bind( 'focus', function(){
		$(this).val("");
	});
	$("#sfsubmit").bind( 'mouseenter mouseleave', function(){
		$(this).toggleClass("moused");
	}).bind( 'click', function( e ){
		
		e.preventDefault();
		e.stopPropagation();
		
		
		if(!!e.cancelBubble && typeof(e.cancelBubble) == 'function' ){
			e.cancelBubble();
		}
		$("#global-searchform>form").submit();
		

	});
});
