/* handle the new item counter based on whether the page has focus or not */
var new_item_count = 0;
var enable_counter = false;
var original_title = document.title;
var original_search;
var loading_more = false;
var oldest_item = 0;
var since;
var wait_ms = 20000;
var event_id = '16';
var filter = '';	
var realtime = '';
var stream_paused = false;
var loading_top = false;
var pid;
var participant_ids = new Array();
var scroll_pause = false;
var flag = false;
var conditional_params;
var live_host = 'http://www.eventvue.com';
var widget = false;
var abbrev_times = false;

var parent_url = decodeURIComponent(document.location.hash.replace(/^#/, ''));

// read $_GET variables from current URL / passed in search string
function get_var(q,s) {
	s = (s) ? s : window.location.search;
	var re = new RegExp('&'+q+'=([^&]*)','i');
	return (s=s.replace(/^\?/,'&').match(re)) ?s=s[1] :s='';
}

function update_title_count() {
    document.title = (new_item_count > 0) ? "("+new_item_count+") " + original_title  : original_title;
}

$(window).bind('focus', function() { 
    new_item_count = 0;
    enable_counter = false;
    update_title_count();
});

$(window).bind('blur', function() { 
    enable_counter = true;
    update_title_count();
});

function make_links(status_update) {
    // http / https links 
    status_update = status_update.replace(/(^| )(https?:\/\/([.]?[a-zA-Z0-9_/?=&+-:@])*)/ig, "$1<a target=\"_blank\" href=\"$2\">$2</a>");
    // www links
    status_update = status_update.replace(/(^| )(www([.]?[a-zA-Z0-9_/?=&+-:@])*)/ig, "$1<a target=\"_blank\" href=\"http://$2\">$2</a>");
    // twitter usernames
    status_update = status_update.replace(/(^|[^a-z0-9_\/])@([a-z0-9_\/]+)/ig, "$1@<a target=\"_blank\" href=\"http://www.twitter.com/$2\">$2</a>");
    // hashtags
    status_update = status_update.replace(/(^|[^a-z0-9_\/])#([a-z0-9_\/]+)/ig, "$1#<a href=\"/stream/$2\">$2</a>");
    return status_update;
}

function add_new_item(item, append) {
	var content = entities(item.content);
     	content = make_links(content);
    var permalink = "/"+hashtag+"/"+item.guid;
    var author_link = "http://twitter.com/"+item.ext_username;
    if(item.source == 'twitter'){
        var source = "Twitter";
        var source_link = "http://twitter.com/"+item.ext_username+"/status/"+item.ext_item_id;
    } else if(item.source == "eventvue"){
        var source = "EventVue";
        var source_link = "http://eventvue.com";
    }
    
    new_item = $("#template_item").clone();
    if (single_item)
            new_item.addClass("single_item");        
    new_item.attr("id",item.guid);
    new_item.find(".item_left img").attr("src",item.avatar).attr("title", "@"+item.ext_username);
    new_item.find(".item_left a").attr("href",author_link);
    new_item.find(".item_author").text(item.ext_username).attr("href",author_link);
    new_item.find(".item_title").html(content);
	if (!search_api) {
		new_item.find(".item_permalink").attr("id",item.date_added).attr("href",permalink).addClass('pretty_time');
		new_item.find(".comment_link_wrap").removeClass('hidden');
	} else {
		new_item.find(".item_permalink").attr("id",item.date_added).attr("href",permalink).addClass('pretty_time');
	}
    new_item.find(".item_source").text(source).attr("href",source_link);
	new_item.find(".at_reply_comment_label").append(item.ext_username);
	if(item.ext_item_id != '0')
		new_item.find(".item_source").attr("id",item.ext_item_id);
    new_item.show("fast");
    // show more
    if (append) {
        $("#stream").append(new_item);
        $("#loading").hide();
    // add newest (default)
    } else {
        $("#stream").prepend(new_item);
        // tack an extra animation on the end in case the first one fails
        $(new_item).animate( { backgroundColor: "#ffffcc" }, 500 ).animate( { backgroundColor: "#ffffff" }, 3000 ).animate( { backgroundColor: "#ffffff" },1);
    }
}

function delete_item(item_id) {
    $("#"+item_id).hide("fast");
    // currently no way to delete from UI (here for admin deletes only)
}

function post_item(item) {
	//Setup the data to be posted to /ajax/add_item.php
	var data = {
				"event_id" : event_id,
				"oauth_key" : user.oauth_key,
				"oauth_secret" : user.oauth_secret,
				"ext_id" : user.ext_id,
				"username" : user.ext_username,
				"avatar" : user.avatar,
				"display_name" : user.display_name,
				"item_type" : item.item_type,
				"content" : item.content,
				"guid" : item.guid,
				"ext_post" : item.ext_pub,
				"published" : item.date_added,
				"hashtag" : hashtag
				};
	if(item.parent_guid != null) {
		data.parent_guid = item.parent_guid;
		data.in_reply_to = item.in_reply_to;
	}
	if(item.parent_author != null)
		data.parent_author = item.parent_author;

	 $.ajax({
		url: live_host+'/stream/ajax/add_item.php',
 		type: 'POST',
 		data: data,
		dataType: 'json',
		success: function(json){
		    // find the place to store the ext_item_id for an item
		    if(json.ext_item_id && !item.in_reply_to)
				$('#'+item.guid).find('.item_source').attr('id', json.ext_item_id);
			// find the place to store ext_item_id for an comment
			else if(json.ext_item_id && item.in_reply_to)
				$('#'+item.guid).find('.comment_body').attr('id', json.ext_item_id);
				
			// update the guid if it has changed
			if(json.guid != item.guid){
				$('#'+item.guid).find('.item_permalink').attr('href', '/stream/'+hashtag+'/'+json.guid);
				$('#'+item.guid).attr('id', json.guid);
			}
		},
		error: function(){
			var error_message = 'There was an error and your action could not be completed. Please try again.';
			//Pause the error actions to let the prepend effects finish
			setTimeout(function(){remove_item(item.guid,item.content,error_message,item.item_type,item.parent_guid)},2500);
		}
	});
}

//Removes an item from the stream
function remove_item(guid,content,alert_msg,type,parent_guid) {
	//Close the item from the stream
	$('#'+guid).slideUp();
	
	if(type == 'status_update' && content) {
		//repopulate the form
		$("#publisher").val(content).focus();
	} else if(type == 'comment' && content){
		$('#'+parent_guid).find('.comment_input').val(content).focus();
	}
	
	if(alert_msg)
		show_message(alert_msg);
		
	update_comment_count($('#'+guid),true);
}

function show_message(message) {
	alert(message);
}

function add_new_comment(item,parent_guid,open,init) {
	var content = entities(item.content);
	 	content = make_links(content);
    new_item = $("#comment_template").clone();       
    new_item.attr("id",item.guid);
    new_item.find("img").attr("src",item.avatar).attr("title", "@"+item.ext_username);
	new_item.find(".user_link").attr("href","http://twitter.com/"+item.ext_username);
    new_item.find(".item_left a").attr("href",item.author_link);
	new_item.find(".comment_body").prepend(content);
	if(item.ext_item_id != '0')
		new_item.find(".comment_body").attr('id', item.ext_item_id);
	new_item.find(".comment_footer").attr("id",item.date_added);
    new_item.show("fast");

	if(open)
		$("#"+parent_guid).find(".comments").removeClass('hidden');
	$("#"+parent_guid).find(".comment_publisher").before(new_item);
	parent_item = $('#'+parent_guid).find(".comment_link");
	update_comment_count(parent_item,false);
	pretty_time(abbrev_times);  // use abrev relative times on the widget 
	
    // window.alert(jQuery.param(item));
	
	// pop the whole item to the top of the stream (unless you're the person who posted it)
	// TODO: we really need to make variable names more consistent
	if(!init) {
		if (item.ext_username != user.ext_username && item.ext_username != user.ext_username) {
		    $("#stream").prepend($("#"+parent_guid));
		}
	}

}

function delete_comment(comment_id) {
    $("#"+comment_id).hide("fast");
    // currently no way to delete from UI (here for admin deletes only)
}

function pause_popup(message,display) {
    // $('#pause_popup #scroll_up').text(message);
	if(display)
		$('#pause_popup').fadeIn();
	else
		$('#pause_popup').fadeOut().fadeOut();  // chain them to get around jquery stickness
}

function pause_stream() {
	stream_paused = true;
	clearTimeout(pid);
}

function resume_stream() {
	stream_paused = false;
}

// dupe detection for statuses and comments
function is_dupe(guid) {
	if($("#"+guid).length == 0)
		return false;
	return true;
}

// used to load new items regardless of position
function update_feed(append, init) {
	// if there's no event_id, there's no need to get latest
	if(event_id == '') {
		$('#no_items').show();
		$('#loading').hide();
		return false;
	}
	
    var limiter = (append) ? "before="+oldest_item : "since="+since;

	if (search_api == '1') {
		var url = live_host+"/stream/ajax/latest.php?event_id="+event_id+"&search_api=1&search_hashtag="+hashtag+conditional_params;
	} else {
		var url = live_host+"/stream/ajax/latest.php?event_id="+event_id+"&"+limiter+conditional_params;
	}

    if (single_item)
        url += '&single_item='+single_item;
	if(append && stream_paused || !stream_paused && !loading_top) {
		loading_top = true;
		if(!init)
			$('.spinner').show();
		$.getJSON(url, function(json) {
			wait_ms = json.wait;
			// for new items added to top, store the server timestamp as the since value for our next call
		    if (!append || init) {
	    		since = json.timestamp;
	    	}
			$.each(json.items, function(i,item){
				// item doesn't exist in stream already
				if (!is_dupe(item.guid)) {
					// if the stream isn't paused, add the new items
	                add_new_item(item, append);
					// check for item comments
					if(item.comments) {
						for(i in item.comments){
							comment = item.comments[i];
							if ($("#"+comment.guid).length == 0) {
								add_new_comment(comment,comment.parent_guid,true,append);
							}
						}
					}
					flag = true;
	                if (append && search_api == 0) {
	                    oldest_item = item.date_added;
	                } else {
						//add the user to the sidebar
						add_participant(item.avatar,item.ext_username,item.ext_id);
	                    // increment title count if window focus is blurred
	            		if (enable_counter) {
	                        new_item_count++;
	                        update_title_count();
	                    }
	                }
					// load the initial participants
					if(init) {
						add_participant(item.avatar,item.ext_username,item.ext_id);
					}
				}
			});
			$.each(json.remove, function(i,item) {
				delete_item(item.guid);
			});
			$.each(json.comments, function(i,comment) {		
				if (!is_dupe(comment.guid)) {
					add_new_comment(comment,comment.parent_guid,true,init);
				}
			});
			
			//check to see if we need to switch from the search api to the stream
			if(json.switch_to_stream) {
				search_api = false;
				$('#search_message').fadeOut('slow');
			}
			
	    	if (append) {
	    	    loading_more = false;
				pretty_time(abbrev_times)
			}
			$('#loading').hide();
			$('.spinner').hide();
			loading_top = false;
			if(init || search_api == '1'){
				// if there are no items, show 0 results
				if(!flag)
					$('#no_items').show();
				pretty_time(abbrev_times)
			} else if(flag) {
					$('#no_items').hide();
			}
			// the AJAX server will tell you how long to wait -- allows for retime rate-limiting 
            if (!append || init)
               pid = setTimeout("update_feed()", wait_ms);
		});
	}
}

/* update the comment count */
function update_comment_count(obj,removed) {
    var parent = $(obj).closest(".item_right");
	cnt = parent.find(".comment_container").size();
	cnt -= (removed == true) ? 1 : 0;
	if (cnt == 0)
	    count = "comment";
	else if (cnt == 1)
	    count = "1 comment";
	else
	    count = cnt + " comments";
	parent.find(".comment_link").text(count);
}

function show_modal(html, size) {
    if (size == "small") {
        width = 430;
        height = 300; 
		top_offset = (($(window).height() - height)/2 - 80);
    } else {
        width = 724;
        height = 594;
		top_offset = (($(window).height() - height)/2 + 40);
    }
    // adjust for windows that aren't as tall as our modal window
    top_offset = (top_offset < 0) ? 12 : top_offset;
    $("#modal").css("marginTop",top_offset+'px').width(width+"px");
    $("#modal div").html(html);
    $("#overlay").show();
}

function hide_modal() {
	$('#create_event_content').html($('#create_modal'));
    $("#overlay").hide();
	if(!scroll_pause) {
		resume_stream();
		update_feed();
	}
}

function char_counter() {
    var remaining = 140 - $("#publisher").val().length;
        $('#character_count').text(remaining); 
   	if($("#publisher").val().length == 0) {
		$('#publish').removeClass("button").addClass("button_disabled").attr('disabled','disabled');
		$("#character_count").attr("style","");
		return false;
	} else if (remaining < 0) {
        $("#character_count").attr("style","color:red;");
		$('#publish').removeClass("button").addClass("button_disabled").attr('disabled','disabled');
		return false;
    } else {
        $("#character_count").attr("style","");
		$('#publish').removeClass("button_disabled").addClass("button").attr('disabled','');
		return true;
    }
}
 
function add_grid_images(contentElement, json) {
	var items = json.items;

	for (i in items) {
		var item = items[i];
		add_participant(item.avatar,item.ext_username,item.ext_id);
	}
}

function check_auth() {
	if(user.oauth_key == '' || user.oauth_secret == '' || user.ext_username == '')
		return false;
	return true;
}

// displays the modal telling the user to signin
function must_sign_in() {
	if(widget){
		XD.postMessage("show_modal", parent_url, parent);
	} else {
		show_modal("<div id='sign_in_content'></div>","small");
		//Load the modal layout from index.tpl
		var layout = $('#sign_in_modal_content').html();
		$('#sign_in_content').append(layout);
	}
}

// scroll up to pause the stream when you click on the comment input
function scroll_to_item($target) {
    // scroll to the top of the parent item unless the comment would be hidden due to # of comments
    comment_pos = $($target).offset().top;
    item_pos = $($target).closest(".chatter_item").offset().top;
    if (comment_pos - item_pos < $(window).height() - 50) {
        if(!widget) {
			$('html, body').animate({
	            scrollTop: item_pos+"px"
	        }, 150);
		} else {
			stream_offset = $('#stream').offset().top;
			offset = item_pos-stream_offset+6;
			$('#stream_wrap').animate({
	            scrollTop: offset+"px"
	        }, 150);
		}
    }
}

function entities(text) {
	text = text.replace(/</g,'&lt;');
	text = text.replace(/>/g,'&gt;');	
	return text;
}

replace = 0;
function add_participant(img,ext_username,ext_id) {
	//if the user is already in the list, do not add them again
	for(var i = 0; i < participant_ids.length; i++)
		if(participant_ids[i] == ext_id)
			return false;

	++replace;
	$item = $('#p'+replace);
	if($item.length == 0){
		$('#small_participants').append('<a target="_blank" href="" title=""><img id="p'+replace+'" src="" width="48" height="48" /></a>');
		$item = $('#p'+replace);
	}
	$('#p'+replace).hide();
	$item.closest('a').attr('title', "@"+ext_username).attr('href', 'http://twitter.com/'+ext_username);
	$('#p'+replace).attr('src', img);
	$('#p'+replace).fadeIn('slow');
	participant_ids[replace] = ext_id;
	if(replace == 15)
		replace = 0;
}

function clear_refill_form(element,input) {
	if(element.val() == input) {
		element.val('');
	} else if(element.val() == '') {
		element.val(input);
	}
}

$(document).ready(function() {	
	
    // only add the JSONP callback if we are not on eventvue.com (performance tweak)
    conditional_params = (window.location.host != "www.eventvue.com" || window.location.host != "eventvue.com") ? "&callback=?" : "";
    
	update_feed(true, true);
	if(!single_item)
		char_counter();
	
	//Check auth before a user trys and comment
	$('#publisher').focus(function (){
		if(!check_auth()) {
			if(!widget)
				must_sign_in();
			else
			   XD.postMessage("show_modal", parent_url, parent);
			return false;
		}
		// if there's nothing in the publisher box, add the hashtag
		else {
			if($(this).val().length == 0) {
				$(this).val(' #'+hashtag).selectRange(0,0);
			}
		}
	});
		
	// set the interval for pretty_time() to every 20 seconds
	setInterval("pretty_time(abbrev_times)", 20000);
    
    // check if we have a stream created for this hashtag otherwise display a diversion
    // if (!event_id) {
    //     show_modal("<div id='sign_in_content'></div>","small");
    //  //Load the modal layout from index.tpl
    //  var layout = $('#new_stream_modal_content').html();
    //  $('#sign_in_content').append(layout);
    // }
    
    /* use the scroll position to load more items & pause the stream when neccessary */
    $(window).scroll(function () { 
		// update the title count
		if (enable_counter) {
			new_item_count = 0;
			update_title_count();	
		}
        // disable scrolling feature on single item pages
        if (!single_item && !widget) {
            refresh_window = 300;
            scroll_bottom = $(window).scrollTop()+$(window).height();
            if (scroll_bottom+refresh_window >= $(document).height()) {
                if (!loading_more) {
                    loading_more = true;
                    // load_more();
                    update_feed(true);
                }
                $("#stream").append($("#loading").show());
            } else if ($(window).scrollTop() > $("#stream_header").offset().top) {
    			pause_popup('scroll up to resume live stream',true);
				scroll_pause = true;
    			pause_stream();
    		} else if ($(window).scrollTop() < $("#stream_header").offset().top && stream_paused) {
    			resume_stream();
				scroll_pause = false;
    			update_feed();
            } else {
    			pause_popup('scroll up to resume live stream',false);
				scroll_pause = false;
    			resume_stream();
            }
			// scroll popup will hide if the window scrolls to 0 really quicky
			if ($(window).scrollTop() == 0){
				pause_popup('scroll up to resume live stream',false);
            }
        }
    });

	// widget scrolling
	$('#stream_wrap').scroll(function () {
		if (!single_item && widget) {
            refresh_window = 300;
            scroll_bottom = $('#stream_wrap').scrollTop()+$('#stream_wrap').height();
            if (scroll_bottom+refresh_window >= $('#stream').height()) {
                if (!loading_more) {
                    loading_more = true;
                    // load_more();
                    update_feed(true);
                }
                $("#stream").append($("#loading").show());
            } else if ($('#stream_wrap').scrollTop() > 1) {
				$('#live_stream').addClass('hidden');	
				if(!stream_paused)
					$('#paused_stream').removeClass('hidden');
				scroll_pause = true;
    			pause_stream();
    		} else if ($('#stream').scrollTop() < 100 && stream_paused) {
				$('#live_stream').removeClass('hidden');	
				$('#paused_stream').addClass('hidden');
    			resume_stream();
				scroll_pause = false;
    			update_feed();
            } else {
				scroll_pause = false;
    			resume_stream();
            }
        }
	});

	//User submits a new status
	$('#publish').click(function () {
		// check char count
		if(!char_counter() && $("#publisher").val().length != 0) {
			show_message('Your status may not be longer than 140 characters');
			return false;
		}
		// check to make sure the user is signed in
		if(!check_auth()) {
			must_sign_in();
			return false;
		}
		var content = jQuery.trim($('#publisher').val());
		var timestamp = get_server_timestamp();
		//Validate the post
		if(content) {
			var permalink = ""; // Guid link e.g. http://www.eventvue.com/stream/defrag09/f4ffc1881...
			var guid = $.md5(user.ext_id+content+Math.floor(timestamp/100)+'00');

			var item = {
							"guid" : guid,
							"item_type" : "status_update",
							"content" : content,
							"ext_pub" : $('#ext_pub').is(":checked"),
							"date_added" : timestamp,
							"source" : "eventvue",
							"ext_username" : user.ext_username,
							"display_name" : user.display_name,
							"avatar" : user.avatar,
							"ext_id" : user.ext_id,
							"oauth_key" : user.oauth_key,
							"oauth_secret" : user.oauth_secret,
							"permalink" : permalink
						};
			//Add the item to the stream
			add_new_item(item,false);
			//Call the Ajax and post the item
			post_item(item);
			$('#publisher').val('');
			char_counter();
			//add the user to the recent participants
			add_participant(user.avatar,user.ext_username,user.ext_id);
		}					
	});
	
	$('#continue_twitter').live('click',function (){
		window.location = "/stream/auth_fwd.php?callback_url=http://"+window.location.host+window.location.pathname;
	});
	
	// scrolls to the top (widget)
	$('.unpause').click(function (){
		$('#stream_wrap').animate({
            scrollTop: "0px"
        }, 150);
		return false;
	});

	$('.avatar').error(function() {
		$(this).attr({
			src: 'http://www.eventvue.com/images/place_holder_74.gif'
		});
	});
    
    /* add the mousedown affect for all buttons */
    $(":button").bind("mousedown mouseup", function(e){
		if(!$(this).hasClass("button_disabled"))
        	$(this).toggleClass("button_down");
    });
    
    /* add the mousedown affect for all buttons */
    $("#sign_out").bind("click", function(e){
        // delete the auth cookies 
        document.cookie="twitter_secret=;expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain=.eventvue.com";
        document.cookie="twitter_key=;expires=Thu, 01-Jan-1970 00:00:01 GMT; path=/; domain=.eventvue.com";      
        // refresh the page
        window.location.reload();
    });
    
    /* add the mousedown affect for all buttons */
	$("#see_stream").bind("click", function(e){
	    window.location = "/stream/"+hashtag;
    });
    
    /* add the mousedown affect for all buttons */
	$("#see_all").bind("click", function(e){
		pause_stream();
        show_modal("<div id='participantscontent'></div>");
		//Load the modal layout from index.tpl
		var layout = $('#participant_modal_content').html();
		$('#participantscontent').append(layout);
		var url = live_host+"/stream/ajax/show_participants.php?event_id="+event_id+conditional_params;
		$.getJSON(url, function(json) {
			var items = json.items;
			for (i in items)
			{
				var item = items[i];
				var listItem = $('<li></li>');
				var image = $('<img class="rounded avatar" src="'+item.avatar+'" width="48" height="48" alt="'+item.ext_username+'" />');
				var author = '<a target="_blank" href="http://twitter.com/'+item.ext_username+'">'+item.ext_username+'</a>';
				image.error(function(){
					$(this).attr("src", "http://www.eventvue.com/images/place_holder_74.gif");
					$(this).css({visibility:"visible"});
				});
				listItem.append(image);
				listItem.append(author);
				$('#participant_list').append(listItem);
			}
			$('#participantscontent').css('background-image','none');
		});
    });
	
    /* 140 char counter */
    $("#publisher").bind("keyup", function(e){
        char_counter();
    });
    
    /* use event bubbling to avoid binding events to multiple items */
    $("#stream").click(function(e){
        
        var $target = $(e.target);
       
        /* toggle the display of comments */
        if ($target.hasClass("comment_link")) {
            comment_container = $target.closest(".item_right").find(".comments").toggleClass("hidden");
			if(check_auth())
            	comment = comment_container.find(".comment").focus();

			//If the comments are being closed (hidden), don't scroll to the item. Otherwise, scroll to the item to pause the stream.
			if(!comment_container.hasClass("hidden")) {
                scroll_to_item($target);
			}
		} else if($target.hasClass("comment_input")) {
			if(!check_auth())
				must_sign_in();
			else
                scroll_to_item($target);
        /* retweets */
        } else if ($target.hasClass("retweet_link")) {
            parent = $target.closest(".item_right");
            author = parent.find(".item_author").text();
            tweet = parent.find(".item_title").text();
            // existing_tweet = jQuery.trim($("#publisher").val().replace("@"+author,""));
            $("#publisher").val("RT @"+author+": "+tweet).focus();
            char_counter();
        /* toggle the comment checkbox via the "also @ reply" label */
        } else if ($target.hasClass("at_reply_comment_label")) {
            parent = $target.closest(".comment_publisher");
            checkbox = parent.find(".at_reply_comment");
            if (checkbox.attr("checked"))
                checkbox.removeAttr("checked")
            else
                checkbox.attr("checked","checked");
        /* publish a new comment */
        } else if ($target.hasClass("comment_button")) {
			//Check to make sure the user is signed in
			if(!check_auth()) {
				must_sign_in();
				return false;
			}
            comment_field = $target.prev();
            comment = jQuery.trim(comment_field.val());

            if (comment != "" && comment != "Add a comment...") {
                $parent = $target.parent();
				//See if the checkbox is checked
				var parent = $target.closest(".comment_publisher");
	            checkbox = parent.find(".at_reply_comment");
				parent = $target.closest(".chatter_item");
				parent_guid = parent.attr("id");
				var timestamp = get_server_timestamp();
				var guid = $.md5(user.ext_id+comment+Math.floor(timestamp/100)+'00');
				//Get the author of the original item
				parent_author = $target.closest(".item_right");
				in_reply_to = parent_author.find(".item_source").attr("id");
				parent_author = parent_author.find(".item_author").text();
				var item = {
								"item_type" : "comment",
								"content" : comment,
								"avatar" : user.avatar,
								"ext_username" : user.ext_username,
								"author_link" : "http://twitter.com/"+user.ext_username,
								"ext_pub" : checkbox.is(":checked"),
								"date_added" : timestamp,
								"source" : "EventVue",
								"ext_link" : "http://eventvue.com",
								"parent_author" : parent_author,
								"parent_guid" : parent_guid,
								"guid" : guid,
								"in_reply_to" : in_reply_to
							};	
				//Add the comment to the current comment list
				add_new_comment(item,parent_guid);			
				post_item(item);
				pretty_time(abbrev_times);
                update_comment_count($target);
                /* move new items to the top */
                var chatter_item = $target.closest(".chatter_item");
                //$("#stream").prepend($chatter_item);
                // put the focus back on the comment box and clear it
                chatter_item.find(".comment").focus().val("");
                just_inserted = $parent.parent().find(".comment_container:last");
                just_inserted.animate( { backgroundColor: "#ffffcc" }, 1 ).animate( { backgroundColor: "#eeeeee" }, 3000 );
				// uncheck checkbox
				parent.find(".at_reply_comment").attr('checked','');
                /* scroll up to the top */
                //$('html, body').animate({scrollTop:0}, 'fast'); 
            }
        } 
         /* delete a comment or chatter item */
        //  else if ($target.hasClass("delete_link")) {
        //     update_comment_count($target,true);
        //     $($target).closest(".comment_container, .chatter_item").hide("fast");
        // }
    });    
    // add scroll up link to pause growl
    $("#scroll_up").bind("click",function(e){
        $('html, body').animate({
            scrollTop: 0
        }, 500);
    });
    
    /* press enter to submit comment -- bind to parent for efficiency */
    $("#stream").bind("keypress",function(e){
        var $target = $(e.target);
        if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {  
            $target.next().click();
            return false;
        }
    });

    original_search = $("#search").val();

    /* REMEMBER TO COPY ANY CHANGES HERE TO JS ON INDEX.TPL */
    
    /* search box */
    $("#search").bind("focus blur",function(e){
        if ($("#search").val() == original_search)
            $("#search").val("");
        else
            $("#search").val(original_search);
    });

    // $("#search").bind("keypress",function(e){
    //         if ((e.which && e.which == 13) || (e.keyCode && e.keyCode == 13)) {
    // 	  		var term = $(this).val();
    // 			if(!term.match(/^[a-zA-Z0-9\-\_]*$/)) {
    // 				show_message('Please enter a valid hashtag.');
    // 				return false;
    // 			}
    // 			var term = term.replace('#', '');
    // 			term = term.toLowerCase();
    //             window.location = '/stream/'+term;
    //             return false;
    //         }
    //     });
	// $("#search").bind("keyup",function(e){
	// 		// remove any spaces
	// 		var term = $(this).val();
	// 		var term = term.replace(/\s/, '');
	// 		var term = term.replace(/,/, '');
	// 		$(this).val(term);
	// 	});

	$("#search").autocomplete('/stream/ajax/search_list.php',{width: 300,delay:0});
	$('#search').result(function(event, data, formatted) {
		window.location = '/'+data[1];
	});
	
	$('#search_form').submit(function (){ 
		var search_term = $('#search').val();
		var content = search_term.split(" ");
		$.each(content, function(){
			if(this.match(/^#[-\w]+$/)) {
				search_term = search_term.replace(this,"");
				$('#create_hashtag').val(this);
			}
		});
		if(!search_term.match(/^#[-\w]+$/) && search_term != '') {
			$('#create_name').val($.trim(search_term));
		}
		show_modal($('#create_modal'),'small');
		return false;
	});

	
	// put the create handling in a function until we can figure out the css button issue
	function create() {
		var event_name = $('#create_name').val();
		var event_hashtag = $('#create_hashtag').val();
		
		if(event_name == 'Name of Event') {
			$('.error_message').html('Please enter an event name.').fadeIn();
			return false;
		}
		if(!event_hashtag.match(/^#[-\w]+$/)) {
			$('.error_message').html('Please enter a Twitter hashtag.').fadeIn();
			return false;
		}
		// if there were no errors, create the event and forward the user to the stream
		var data = {
					"event_hashtag" : event_hashtag,
					"event_name" : event_name
					};

        $.ajax({
            url: '/stream/ajax/create_event.php',
        	type: 'POST',
        	data: data,
        	dataType: 'json',
            success: function(json){
                
                // trigger backfill for the specified event hashtag (don't wait for response)
                $.get("http://www.eventvue.com/stream/ajax/backfill.php", { hashtag: event_hashtag, event_id: json.event_id });
                
                if(!json.error) {
                    setTimeout(function() { 
						window.location = '/'+json.hashtag;
					}, 1000);
                } else {
                    $('.error_message').html('There was an error creating the event.').fadeIn();
                }
            }
        });
	}
	$('#create_form').submit(function (){
		create();
		return false;
	});
	$('#create_btn').click(function (){
        create();
	});
	
	$('#claim_event_btn').click(function (){ 
		show_modal($('#claim_modal'));
	});
});

// set the cursor position
$.fn.selectRange = function(start, end) {
        return this.each(function() {
                if(this.setSelectionRange) {
                        this.focus();
                        this.setSelectionRange(start, end);
                } else if(this.createTextRange) {
                        var range = this.createTextRange();
                        range.collapse(true);
                        range.moveEnd('character', end);
                        range.moveStart('character', start);
                        range.select();
                }
        });
};

// color plugin (used for color fade effect) 
// http://plugins.jquery.com/project/color
(function(jQuery){

	// We override the animation for all of these color styles
	jQuery.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'], function(i,attr){
		jQuery.fx.step[attr] = function(fx){
			if ( fx.state == 0 || fx.start.constructor != Array || fx.end.constructor != Array ) {
				fx.start = getColor( fx.elem, attr );
				fx.end = getRGB( fx.end );
			}

			fx.elem.style[attr] = "rgb(" + [
				Math.max(Math.min( parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0]), 255), 0),
				Math.max(Math.min( parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1]), 255), 0),
				Math.max(Math.min( parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2]), 255), 0)
			].join(",") + ")";
		}
	});

	// Color Conversion functions from highlightFade
	// By Blair Mitchelmore
	// http://jquery.offput.ca/highlightFade/

	// Parse strings looking for color tuples [255,255,255]
	function getRGB(color) {
		var result;

		// Check if we're already dealing with an array of colors
		if ( color && color.constructor == Array && color.length == 3 )
			return color;

		// Look for rgb(num,num,num)
		if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
			return [parseInt(result[1]), parseInt(result[2]), parseInt(result[3])];

		// Look for rgb(num%,num%,num%)
		if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
			return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];

		// Look for #a0b1c2
		if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
			return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];

		// Look for #fff
		if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
			return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];

		// Otherwise, we're most likely dealing with a named color
		return colors[jQuery.trim(color).toLowerCase()];
	}
	
	function getColor(elem, attr) {
		var color;

		do {
			color = jQuery.curCSS(elem, attr);

			// Keep going until we find an element that has color, or we hit the body
			if ( color != '' && color != 'transparent' || jQuery.nodeName(elem, "body") )
				break; 

			attr = "backgroundColor";
		} while ( elem = elem.parentNode );

		return getRGB(color);
	};
	
	// Some named colors to work with
	// From Interface by Stefan Petre
	// http://interface.eyecon.ro/

	var colors = {
		aqua:[0,255,255],
		azure:[240,255,255],
		beige:[245,245,220],
		black:[0,0,0],
		blue:[0,0,255],
		brown:[165,42,42],
		cyan:[0,255,255],
		darkblue:[0,0,139],
		darkcyan:[0,139,139],
		darkgrey:[169,169,169],
		darkgreen:[0,100,0],
		darkkhaki:[189,183,107],
		darkmagenta:[139,0,139],
		darkolivegreen:[85,107,47],
		darkorange:[255,140,0],
		darkorchid:[153,50,204],
		darkred:[139,0,0],
		darksalmon:[233,150,122],
		darkviolet:[148,0,211],
		fuchsia:[255,0,255],
		gold:[255,215,0],
		green:[0,128,0],
		indigo:[75,0,130],
		khaki:[240,230,140],
		lightblue:[173,216,230],
		lightcyan:[224,255,255],
		lightgreen:[144,238,144],
		lightgrey:[211,211,211],
		lightpink:[255,182,193],
		lightyellow:[255,255,224],
		lime:[0,255,0],
		magenta:[255,0,255],
		maroon:[128,0,0],
		navy:[0,0,128],
		olive:[128,128,0],
		orange:[255,165,0],
		pink:[255,192,203],
		purple:[128,0,128],
		violet:[128,0,128],
		red:[255,0,0],
		silver:[192,192,192],
		white:[255,255,255],
		yellow:[255,255,0]
	};
	
})(jQuery);


// md5
(function($){
	var rotateLeft = function(lValue, iShiftBits) {
		return (lValue << iShiftBits) | (lValue >>> (32 - iShiftBits));
	}
	
	var addUnsigned = function(lX, lY) {
		var lX4, lY4, lX8, lY8, lResult;
		lX8 = (lX & 0x80000000);
		lY8 = (lY & 0x80000000);
		lX4 = (lX & 0x40000000);
		lY4 = (lY & 0x40000000);
		lResult = (lX & 0x3FFFFFFF) + (lY & 0x3FFFFFFF);
		if (lX4 & lY4) return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
		if (lX4 | lY4) {
			if (lResult & 0x40000000) return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
			else return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
		} else {
			return (lResult ^ lX8 ^ lY8);
		}
	}
	
	var F = function(x, y, z) {
		return (x & y) | ((~ x) & z);
	}
	
	var G = function(x, y, z) {
		return (x & z) | (y & (~ z));
	}
	
	var H = function(x, y, z) {
		return (x ^ y ^ z);
	}
	
	var I = function(x, y, z) {
		return (y ^ (x | (~ z)));
	}
	
	var FF = function(a, b, c, d, x, s, ac) {
		a = addUnsigned(a, addUnsigned(addUnsigned(F(b, c, d), x), ac));
		return addUnsigned(rotateLeft(a, s), b);
	};
	
	var GG = function(a, b, c, d, x, s, ac) {
		a = addUnsigned(a, addUnsigned(addUnsigned(G(b, c, d), x), ac));
		return addUnsigned(rotateLeft(a, s), b);
	};
	
	var HH = function(a, b, c, d, x, s, ac) {
		a = addUnsigned(a, addUnsigned(addUnsigned(H(b, c, d), x), ac));
		return addUnsigned(rotateLeft(a, s), b);
	};
	
	var II = function(a, b, c, d, x, s, ac) {
		a = addUnsigned(a, addUnsigned(addUnsigned(I(b, c, d), x), ac));
		return addUnsigned(rotateLeft(a, s), b);
	};
	
	var convertToWordArray = function(string) {
		var lWordCount;
		var lMessageLength = string.length;
		var lNumberOfWordsTempOne = lMessageLength + 8;
		var lNumberOfWordsTempTwo = (lNumberOfWordsTempOne - (lNumberOfWordsTempOne % 64)) / 64;
		var lNumberOfWords = (lNumberOfWordsTempTwo + 1) * 16;
		var lWordArray = Array(lNumberOfWords - 1);
		var lBytePosition = 0;
		var lByteCount = 0;
		while (lByteCount < lMessageLength) {
			lWordCount = (lByteCount - (lByteCount % 4)) / 4;
			lBytePosition = (lByteCount % 4) * 8;
			lWordArray[lWordCount] = (lWordArray[lWordCount] | (string.charCodeAt(lByteCount) << lBytePosition));
			lByteCount++;
		}
		lWordCount = (lByteCount - (lByteCount % 4)) / 4;
		lBytePosition = (lByteCount % 4) * 8;
		lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80 << lBytePosition);
		lWordArray[lNumberOfWords - 2] = lMessageLength << 3;
		lWordArray[lNumberOfWords - 1] = lMessageLength >>> 29;
		return lWordArray;
	};
	
	var wordToHex = function(lValue) {
		var WordToHexValue = "", WordToHexValueTemp = "", lByte, lCount;
		for (lCount = 0; lCount <= 3; lCount++) {
			lByte = (lValue >>> (lCount * 8)) & 255;
			WordToHexValueTemp = "0" + lByte.toString(16);
			WordToHexValue = WordToHexValue + WordToHexValueTemp.substr(WordToHexValueTemp.length - 2, 2);
		}
		return WordToHexValue;
	};
	
	var uTF8Encode = function(string) {
		string = string.replace(/\x0d\x0a/g, "\x0a");
		var output = "";
		for (var n = 0; n < string.length; n++) {
			var c = string.charCodeAt(n);
			if (c < 128) {
				output += String.fromCharCode(c);
			} else if ((c > 127) && (c < 2048)) {
				output += String.fromCharCode((c >> 6) | 192);
				output += String.fromCharCode((c & 63) | 128);
			} else {
				output += String.fromCharCode((c >> 12) | 224);
				output += String.fromCharCode(((c >> 6) & 63) | 128);
				output += String.fromCharCode((c & 63) | 128);
			}
		}
		return output;
	};
	
	$.extend({
		md5: function(string) {
			var x = Array();
			var k, AA, BB, CC, DD, a, b, c, d;
			var S11=7, S12=12, S13=17, S14=22;
			var S21=5, S22=9 , S23=14, S24=20;
			var S31=4, S32=11, S33=16, S34=23;
			var S41=6, S42=10, S43=15, S44=21;
			string = uTF8Encode(string);
			x = convertToWordArray(string);
			a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
			for (k = 0; k < x.length; k += 16) {
				AA = a; BB = b; CC = c; DD = d;
				a = FF(a, b, c, d, x[k+0],  S11, 0xD76AA478);
				d = FF(d, a, b, c, x[k+1],  S12, 0xE8C7B756);
				c = FF(c, d, a, b, x[k+2],  S13, 0x242070DB);
				b = FF(b, c, d, a, x[k+3],  S14, 0xC1BDCEEE);
				a = FF(a, b, c, d, x[k+4],  S11, 0xF57C0FAF);
				d = FF(d, a, b, c, x[k+5],  S12, 0x4787C62A);
				c = FF(c, d, a, b, x[k+6],  S13, 0xA8304613);
				b = FF(b, c, d, a, x[k+7],  S14, 0xFD469501);
				a = FF(a, b, c, d, x[k+8],  S11, 0x698098D8);
				d = FF(d, a, b, c, x[k+9],  S12, 0x8B44F7AF);
				c = FF(c, d, a, b, x[k+10], S13, 0xFFFF5BB1);
				b = FF(b, c, d, a, x[k+11], S14, 0x895CD7BE);
				a = FF(a, b, c, d, x[k+12], S11, 0x6B901122);
				d = FF(d, a, b, c, x[k+13], S12, 0xFD987193);
				c = FF(c, d, a, b, x[k+14], S13, 0xA679438E);
				b = FF(b, c, d, a, x[k+15], S14, 0x49B40821);
				a = GG(a, b, c, d, x[k+1],  S21, 0xF61E2562);
				d = GG(d, a, b, c, x[k+6],  S22, 0xC040B340);
				c = GG(c, d, a, b, x[k+11], S23, 0x265E5A51);
				b = GG(b, c, d, a, x[k+0],  S24, 0xE9B6C7AA);
				a = GG(a, b, c, d, x[k+5],  S21, 0xD62F105D);
				d = GG(d, a, b, c, x[k+10], S22, 0x2441453);
				c = GG(c, d, a, b, x[k+15], S23, 0xD8A1E681);
				b = GG(b, c, d, a, x[k+4],  S24, 0xE7D3FBC8);
				a = GG(a, b, c, d, x[k+9],  S21, 0x21E1CDE6);
				d = GG(d, a, b, c, x[k+14], S22, 0xC33707D6);
				c = GG(c, d, a, b, x[k+3],  S23, 0xF4D50D87);
				b = GG(b, c, d, a, x[k+8],  S24, 0x455A14ED);
				a = GG(a, b, c, d, x[k+13], S21, 0xA9E3E905);
				d = GG(d, a, b, c, x[k+2],  S22, 0xFCEFA3F8);
				c = GG(c, d, a, b, x[k+7],  S23, 0x676F02D9);
				b = GG(b, c, d, a, x[k+12], S24, 0x8D2A4C8A);
				a = HH(a, b, c, d, x[k+5],  S31, 0xFFFA3942);
				d = HH(d, a, b, c, x[k+8],  S32, 0x8771F681);
				c = HH(c, d, a, b, x[k+11], S33, 0x6D9D6122);
				b = HH(b, c, d, a, x[k+14], S34, 0xFDE5380C);
				a = HH(a, b, c, d, x[k+1],  S31, 0xA4BEEA44);
				d = HH(d, a, b, c, x[k+4],  S32, 0x4BDECFA9);
				c = HH(c, d, a, b, x[k+7],  S33, 0xF6BB4B60);
				b = HH(b, c, d, a, x[k+10], S34, 0xBEBFBC70);
				a = HH(a, b, c, d, x[k+13], S31, 0x289B7EC6);
				d = HH(d, a, b, c, x[k+0],  S32, 0xEAA127FA);
				c = HH(c, d, a, b, x[k+3],  S33, 0xD4EF3085);
				b = HH(b, c, d, a, x[k+6],  S34, 0x4881D05);
				a = HH(a, b, c, d, x[k+9],  S31, 0xD9D4D039);
				d = HH(d, a, b, c, x[k+12], S32, 0xE6DB99E5);
				c = HH(c, d, a, b, x[k+15], S33, 0x1FA27CF8);
				b = HH(b, c, d, a, x[k+2],  S34, 0xC4AC5665);
				a = II(a, b, c, d, x[k+0],  S41, 0xF4292244);
				d = II(d, a, b, c, x[k+7],  S42, 0x432AFF97);
				c = II(c, d, a, b, x[k+14], S43, 0xAB9423A7);
				b = II(b, c, d, a, x[k+5],  S44, 0xFC93A039);
				a = II(a, b, c, d, x[k+12], S41, 0x655B59C3);
				d = II(d, a, b, c, x[k+3],  S42, 0x8F0CCC92);
				c = II(c, d, a, b, x[k+10], S43, 0xFFEFF47D);
				b = II(b, c, d, a, x[k+1],  S44, 0x85845DD1);
				a = II(a, b, c, d, x[k+8],  S41, 0x6FA87E4F);
				d = II(d, a, b, c, x[k+15], S42, 0xFE2CE6E0);
				c = II(c, d, a, b, x[k+6],  S43, 0xA3014314);
				b = II(b, c, d, a, x[k+13], S44, 0x4E0811A1);
				a = II(a, b, c, d, x[k+4],  S41, 0xF7537E82);
				d = II(d, a, b, c, x[k+11], S42, 0xBD3AF235);
				c = II(c, d, a, b, x[k+2],  S43, 0x2AD7D2BB);
				b = II(b, c, d, a, x[k+9],  S44, 0xEB86D391);
				a = addUnsigned(a, AA);
				b = addUnsigned(b, BB);
				c = addUnsigned(c, CC);
				d = addUnsigned(d, DD);
			}
			var tempValue = wordToHex(a) + wordToHex(b) + wordToHex(c) + wordToHex(d);
			return tempValue.toLowerCase();
		}
	});
})(jQuery);

/* store the offset between the client and the server (allows for clocks to be off) */
function set_time_correction(ts_on_server) {
	var today = new Date();
	var ts_today = today.getTime();
	time_correction = Math.floor(ts_on_server - (ts_today/1000));
}

function get_server_timestamp() {
	var current = new Date().getTime();
	var server_timestamp = Math.floor(current/1000 + time_correction);
	return server_timestamp;
}

// display relative timestamps
function pretty_time(abrev) {
	jQuery.each($(".pretty_time"),function(obj) {

		ts = (time_correction == null) ? parseInt($(this).attr("id")) : (parseInt($(this).attr("id")) - parseInt(time_correction));

		var today = new Date();
		var date_today = today.getDate();
		var month_today = today.getMonth()+1;
		var year_today = today.getFullYear();
		var ts_today = today.getTime();

		new_time = new Date(ts*1000);
		mins = new_time.getMinutes();
		hours = new_time.getHours();
		date = new_time.getDate();
		month = new_time.getMonth()+1;
		year = new_time.getFullYear();
		ts = new_time.getTime();

		// how long ago was that date/time?
		seconds_ago = Math.abs(Math.round((ts_today - ts)/1000));
		minutes_ago = Math.round(seconds_ago/60);
		hours_ago = Math.round(minutes_ago/60);
		days_ago = Math.round(hours_ago/24);

		// change to 12 hour time
		if (hours > 12) {
			hours = hours - 12;
			am_pm = "pm";
		} else {
			hours = hours;
			am_pm = "am";
		}
		if (hours == 12)
			am_pm = "pm";
		if (hours == 0)
			hours = "12";

		// pad minutes (4:01pm instead of 4:1pm)
		if (mins < 10)
			mins = "0" + mins;

		// text to return
		var time_str = "";
		
        mins_form = (abrev) ? "mins" : "minutes";
        hr_form = (abrev) ? "hr" : "hour";
        hrs_form = (abrev) ? "hrs" : "hours";

   		if (seconds_ago < 30)
   			time_str = (abrev) ? "seconds ago" : "just seconds ago";
   		else if (seconds_ago < 60)
   			time_str = (abrev) ? "half a min ago" : "half a minute ago";
   		else if (minutes_ago == 1)
   			time_str = (abrev) ? "a min ago" : "a minute ago";
   		else if (hours_ago < 1)
   			time_str = minutes_ago + " " +mins_form+" ago";
   		else if (hours_ago == 1)
   			time_str = "1 "+hr_form+" ago";
   		else if (hours_ago <= 12)
   			time_str = hours_ago + " "+hrs_form+" ago";
   		else if (days_ago < 1) {
   			// just because it's within 24 hours, doesn't mean that it's really "today"
   			if (date == date_today)
      				time_str = (abrev) ? "today" : "at " + hours+":"+mins+am_pm+" today";
   			else
       			time_str = (abrev) ? "yesterday" : "at " + hours+":"+mins+am_pm+" yesterday";
   		} else if (days_ago == 1)
   			time_str = (abrev) ? "yesterday" : "at " + hours+":"+mins+am_pm+" yesterday";
   		else if (days_ago < 7)
   			time_str = days_ago+" days ago";
   		else if (days_ago == 7)
   			time_str = "1 week ago";
   		else
   			time_str = "on " + month+"/"+date+"/"+year;

		$(this).text(time_str);
	});
}

$(document).ready( function() {
   PEPS.rollover.init();
});

PEPS = {};

PEPS.rollover = {
   init: function() {
      this.preload();
     
      $(".ro").hover(
         function () { $(this).attr( 'src', PEPS.rollover.newimage($(this).attr('src')) ); },
         function () { $(this).attr( 'src', PEPS.rollover.oldimage($(this).attr('src')) ); }
      );
   },

   preload: function() {
      $(window).bind('load', function() {
         $('.ro').each( function( key, elm ) { $('<img>').attr( 'src', PEPS.rollover.newimage( $(this).attr('src') ) ); });
      });
   },
   
   newimage: function( src ) {
      return src.substring( 0, src.search(/(\.[a-z]+)$/) ) + '_over' + src.match(/(\.[a-z]+)$/)[0];
   },

   oldimage: function( src ) {
      return src.replace(/_over\./, '.');
   }
};

// cross-domain plugin
var XD = function(){
  
    var interval_id,
    last_hash,
    cache_bust = 1,
    attached_callback,
    window = this;
    
    return {
        postMessage : function(message, target_url, target) {
            
            if (!target_url) { 
                return; 
            }
    
            target = target || parent;  // default to parent
    
            if (window['postMessage']) {
                // the browser supports window.postMessage, so call it with a targetOrigin
                // set appropriately, based on the target_url parameter.
                target['postMessage'](message, target_url.replace( /([^:]+:\/\/[^\/]+).*/, '$1'));

            } else if (target_url) {
                // the browser does not support window.postMessage, so set the location
                // of the target to target_url#message. A bit ugly, but it works! A cache
                // bust parameter is added to ensure that repeat messages trigger the callback.
                target.location = target_url.replace(/#.*$/, '') + '#' + (+new Date) + (cache_bust++) + '&' + message;
            }
        },
  
        receiveMessage : function(callback, source_origin) {
            
            // browser supports window.postMessage
            if (window['postMessage']) {
                // bind the callback to the actual event associated with window.postMessage
                if (callback) {
                    attached_callback = function(e) {
                        if ((typeof source_origin === 'string' && e.origin !== source_origin)
                        || (toString.call(source_origin) === "[object Function]" && source_origin(e.origin) === !1)) {
                            return !1;
                        }
                        callback(e);
                    };
                }
                if (window['addEventListener']) {
                    window[callback ? 'addEventListener' : 'removeEventListener']('message', attached_callback, !1);
                } else {
                    window[callback ? 'attachEvent' : 'detachEvent']('onmessage', attached_callback);
                }
            } else {
                // a polling loop is started & callback is called whenever the location.hash changes
                interval_id && clearInterval(interval_id);
                interval_id = null;

                if (callback) {
                    interval_id = setInterval(function(){
                        var hash = document.location.hash,
                        re = /^#?\d+&/;
                        if (hash !== last_hash && re.test(hash)) {
                            last_hash = hash;
                            callback({data: hash.replace(re, '')});
                        }
                    }, 100);
                }
            }   
        }
    };
}();