/*
TAGALUS_LINK = '<a target="_blank" href="http://tagal.us/">Tagalus</a>';


function get_definition_form_code() {
  if ((TAGALUS_API_KEY == null) || (TAGALUS_API_KEY == '')) {
    return '<span class="small_label">You can add a definition to Tagalus if you <a href="http://blog.tagal.us/api-documentation/">enter a Tagalus API key</a></span>';
  }
  
  add_definition_form_code = '<div id="add_tagalus_definition">'
  add_definition_form_code += '<span class="small_label">Add your own definition to ' + TAGALUS_LINK + ': <br/></span>'
  add_definition_form_code += 'Tag:<br/><input type="text" id="add_tagalus_tag_name" /><br/>'
  add_definition_form_code += 'Definition: <br/>'
  add_definition_form_code += '<textarea id="add_tagalus_definition_the_definition"></textarea><br/>'
  add_definition_form_code += '<input type="submit" value="Submit" onclick="submit_tagalus_form(); return false;" />'
  add_definition_form_code += '</div>';

 return add_definition_form_code;
}


function submit_tagalus_form() {
  
  //alert("submitting");
  
  show_loader();
	
  
  if ((TAGALUS_API_KEY == null) || (TAGALUS_API_KEY == '')) {
    alert("You must enter a Tagalus API key to use that feature!");
    return;
  }
  
  TagalusAPI.api_key = TAGALUS_API_KEY;
  
  var user_tag = $('#add_tagalus_tag_name').val();
  var user_def = $('#add_tagalus_definition_the_definition').val();
  hide_notify_window();
  
  
  if ((user_tag == '') || (user_def == '')) {
    
    alert("You must enter both a tag and a definition");
    return;
    
  }
  
  
  
  //alert($('#add_tagalus_tag_name').val() + '' + $('#add_tagalus_definition_the_definition').val());
  //return;
  
  TagalusAPI.api_server = "http://api.localtag:3000/";
  TagalusAPI.api_call('definition/create.json', {
  				the_tag: user_tag,
  				the_definition: user_def,
  			} ,function(data) {
  				window.RETURNED_DATA = data;
  				if (data.error != null) {
  				  alert("There was an error: " + data.error);
  				  return;
  				}
  				alert("Your definition has been added to Tagalus!");
  				hide_loader();
  			});
  
}

function bind_hashtag_links() {

  $('.hashtag_link').unbind('click');

  $('.hashtag_link').bind('click',
  
    function(e) {
    
      var the_tag = e.target.text.substring(1);
      
      var tag_link = '<a target="_blank" href="http://tagal.us/tag/' + the_tag + '">#' + the_tag + '</a>';
    
      //alert("clicked");
    
      show_loader();
      show_notify_window("Loading definition for #" + the_tag + " from Tagalus...",e);
    
      TagalusAPI.api_server = "http://api.localtag:3000/";
      TagalusAPI.api_call('tag/' + the_tag + '/show.json', {} ,function(data) {
      				if (data == null) {
      				  $('#notify_content').html(TAGALUS_LINK + " doesn't have a definition for " + tag_link + "<br/>" + get_definition_form_code());
      				  $('#add_tagalus_tag_name').val(the_tag)
    				  } else {
    				    $('#notify_content').html('<span class="small_label">' + TAGALUS_LINK + " defines " + tag_link + " as:</span><br/>" + data.definition.the_definition + "<br/>" + get_definition_form_code());
    				    $('#add_tagalus_tag_name').val(the_tag)
      				  
    				  }
    				  hide_loader();
      			});
    			
    
      return false;
    
    }
  
  );


}
*/

function bind_hashtag_links() {
  
  //TagalusAPI.api_server = 'http://api.localtag:3000/';
  TagalusAPI.load_widget();
  TagalusAPI.add_buttons_to_elements('a.hashtag_link')
  //TagalusAPI.bind_to_clicks('a.hashtag_link')
  
}




//Functions for saving the state to OpenID

function auto_save() {
  if (AUTO_SAVE && (user_openid != '')) {
    save_to_openid(false);
  }
}

function save_to_openid(show_alert) {
  
  
  if (user_openid == '') {
    //ask the user for an openid, and check them in
    alert("You haven't entered an OpenID to save to!");
    return false;
  }
  
  
  //send a save request to the server
  if (PROXY) {
    proxy_save_state(user_openid,show_alert);
  }
  
  
}

function load_state() {
  
  entered_open_id = $('#openid_identifier').val();
  
  if ((user_openid == '') && (entered_open_id == '')) {
    
    alert("You must enter an OpenID!");
    return false;
    
  }
  
  if (user_openid != entered_open_id) {
    //we'll have to verify the id
    $("#save_state").submit();
    return false;
    
  }
  
  if (PROXY) {
    proxy_load_state(user_openid);
    
  }
  
  
}

function show_save_state_form() {
  
  $('#save_state_form').css('left',$(window).width() - 400);
	
	$('#save_state_form').toggle("slide", { direction: "up" });
  
}

function save_state_submit() {
  
  save_to_openid(true);
  
  hide_open_windows();
  
  return false;
}




if (window.RUNTIME_LOC == undefined) {
	
	var RUNTIME_LOC = 'local/web';
	
}

if (window.MOBILE == undefined) {
	
	var MOBILE = false;
	
}

if (window.user_openid == undefined) {
	
	//var user_openid = '';
	
}


/******************************** OPTIONS **********************************/

//Whether or not to destroy the oldest tweets when new ones are loaded
var DESTROY_TWEETS = true;
//Number of tweets to display on each panel at one time
var TWEET_DISPLAY_LIMIT = 20;
//Radius for location-based search
var LOCATION_SEARCH_DISTANCE = '5mi';
//Not currently used
var UPDATE_LOCATION = false;
//Frequency of auto-updates
var UPDATE_FREQ = 45000;
//auto save to openid?
var AUTO_SAVE = true;
//Frequency to auto save
var AUTO_SAVE_FREQ = 60000;
//Automatically refresh data?
var AUTO_UPDATE = true;
//URL Base of the client - should work with '' in most cases
var URL_BASE = '';
//Deprecated
var BIND_CLICKS = false;
//If cross-site AJAX is allowed
var XS = false;
//Running in Adobe AIR?
var AIR = false;
//Need a proxy to run?  In browsers, this will be 'true' until XS Ajax is allowed
var PROXY = true;
//Relative URL of the css file for the client
var CSS_FILE = 'dark.css';
//Font size in tweets
var FONT_SIZE = 100;
//Tabbed browsing
var TABBED_PANELS = false;
//Panel width
var PANEL_WIDTH = 500;
//Add a hashtag automatically
var ADD_HASHTAG = false;
//Display URL shortener
var SHOW_URL_SHORTNER = false;
//Display translate option
var TRANSLATE = false;

/******************************** END OPTIONS **********************************/

if (RUNTIME_LOC == 'air') {
	
	BIND_CLICKS = true;
	URL_BASE = 'http://combotweet.com/';
	XS = true;
	AIR = true;
	PROXY = false;
	
}

if (window.mt_options) {
	
	mt_options();
	
}

//CSS FILE STUFF

get_css()

function get_css() {
  var cookie_css = readCookie('combotweet_css')

  if (cookie_css != null) {
    CSS_FILE = cookie_css
  }
}

function readCookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}


function update_settings() {
	
	var need_refresh = false;
	
	if ( parseInt($('#refresh_freq').val()) != NaN) {
		UPDATE_FREQ = parseInt($('#refresh_freq').val()) * 1000;
	}
	
	SHOW_URL_SHORTENER = $('#show_url_shortener').attr('checked');
	
	if (SHOW_URL_SHORTENER == false) {
	  $('.url_shortener_container').hide();
	  //alert("nope")
	} else {
	  
	  $('.add_hashtag').css('display','normal')
	  $('.url_shortener_container').show();
	}
	
	DESTROY_TWEETS = $('#remove_old_tweets').attr('checked');
	
	ADD_HASHTAG = $('#add_hashtag').attr('checked');
	
	if (ADD_HASHTAG) {
	  
	  $('.add_hashtag').css('display','normal')
	  $('.add_hashtag').show()
	  
	} else {
	  
	  $('.add_hashtag').css('display','hidden')
	  $('.add_hashtag').hide()
	  
	}
	
	
	FONT_SIZE = parseInt($('#font_size').val());
	
	$('#panels').css('font-size',FONT_SIZE + '%');
	
	PANEL_WIDTH = parseInt($('#panel_width').val())
	
	if (PANEL_WIDTH < 400) {
		
		PANEL_WIDTH = 400;
		
	}
	
	update_widths();
	
	if (TABBED_PANELS != $('#tabbed_panels').attr('checked')) {
		TABBED_PANELS = $('#tabbed_panels').attr('checked');
		need_refresh = true
	}
	
	AUTO_SAVE = $('auto_save_checkbox').attr('checked');
	
	auto_save();
	
	if (CSS_FILE != $('#css_file_setting').val()) {
	  CSS_FILE = $('#css_file_setting').val()
	  need_refresh = true
	}
	
	save_settings_in_cookie();
	
	
	if (need_refresh) {
	  refresh_window();
	}
	
	show_settings_form();
	
}

function save_settings_in_cookie() {
	
	var settings = '';
	
	settings += "UPDATE_FREQ=" + UPDATE_FREQ;
	
	settings += '&'
	
	settings += "TABBED_PANELS=" + TABBED_PANELS;
	
	settings += '&'
	
	settings += "FONT_SIZE=" + FONT_SIZE;
	
	settings += '&'
	
	settings += "DESTROY_TWEETS=" + DESTROY_TWEETS;
	
	settings += '&'
	
	settings += "PANEL_WIDTH=" + PANEL_WIDTH;
	
	settings += '&'
	
	settings += "AUTO_SAVE=" + AUTO_SAVE;
	
	settings += '&'
	
	settings += "ADD_HASHTAG=" + ADD_HASHTAG;
	
	settings += '&'
	
		
	$.cookie('combotweet_settings',settings,{expires: 365})
	$.cookie('combotweet_css',CSS_FILE,{expires: 365})
	
}

function get_settings_in_cookie() {
	
	var settings = $.cookie('combotweet_settings');
	
	if (settings == null) {
		
		return;
		
	}
	
	var settings_array = settings.split('&');
	
	for (i in settings_array) {
		
		var vals = settings_array[i].split('=');
		
		if (vals[0] == 'UPDATE_FREQ') {
			UPDATE_FREQ = parseInt(vals[1]);
		} else if (vals[0] == 'FONT_SIZE') {
			FONT_SIZE = parseInt(vals[1]);
			$('#panels').css('font-size','' + FONT_SIZE + '%')
		} else if (vals[0] == 'PANEL_WIDTH') {
			PANEL_WIDTH = parseInt(vals[1])
			update_widths();
		} else if (vals[0] == 'DESTROY_TWEETS') {
			if (vals[1] == 'false') {
				DESTROY_TWEETS = false
			} else {
				DESTROY_TWEETS = true	
			}
		} else if (vals[0] == 'AUTO_SAVE') {
			if (vals[1] == 'false') {
				AUTO_SAVE = false
			} else {
				AUTO_SAVE = true	
			}
		} else if (vals[0] == 'ADD_HASHTAG') {
			if (vals[1] == 'false') {
				ADD_HASHTAG = false
			} else {
				ADD_HASHTAG = true	
			}
			$('.add_hashtag').css('display','normal')
		} else if (vals[0] == 'TABBED_PANELS') {	
			if (vals[1] == 'false') {
				TABBED_PANELS = false
			} else {
				TABBED_PANELS = true
				$('#header_nav_buttons').css('display','normal')
				$('#header_nav_buttons').show()	
			}
		}
		
	}
	
}




/********************************** GLOBALS *************************************/

var selected_tweet = -1;

var selected_tweet_panel = 0;

var tw_panels = new Array();

var front_panel = null;

var user_loc = "";

var plugin_hooks = new Array();




/********************************** OBJECTS **************************************/

//Object for each Panel
function Data_Panel(pan_id,type,t_user,t_pass,info) {
	
	this.panel_id = pan_id;	
	this.panel_type = type;
	this.user = t_user;
	this.pass = t_pass;
	this.gen_info = info;
	
	this.selected_tweet = null;
	
	this.auth = make_base_auth(t_user,t_pass);
	
	this.latest_tweet_id = '-1';
	
	this.tweet_type = null;
	this.panel_data = new Array();
	
	this.reply_id = -1;
	this.reply_to_name = null;
	
	this.tweet_display_limit = TWEET_DISPLAY_LIMIT;
	
	//derivative stuff
	this.derivative_panels = new Array();
	this.filter_rules = null;
	this.parent_panel = null;
	
	//friends and followers
	this.twitter_friends = null;
	this.twitter_followers = null;
	
}

//Object for plugin
//Non-functioning so far
function CT_Plugin(hook_handle,callback_fn) {
	
	this.hook = hook_handle;
	this.callback = callback_fn;
	
}




/********************************* STARTUP **************************************/

//jQuery hook for anything that must be run at startup
$(document).ready(function() {

	if (!AIR) {
		
		doc_ready_functions();
	
	}
	
});

function hide_flash_message() {
  
  $('#flash_message').fadeOut('slow')
  
}

//Startup functions
//Loads the session panels, and starts the auto_update routines to refresh tweets
//Adding search panels seems buggy
function doc_ready_functions() {
		
	//$('#nav_buttons').sortable();

	get_settings_in_cookie();

	get_session_panels();
	
	if (user_openid != '') {
	  
	  //$('#save_state_button').show();
	  //$('#load_state_button').hide();
	  $('#openid_identifier').attr('disabled','true');
	  
	}
	
	if ($('#flash_message').length != 0) {
	  setTimeout("hide_flash_message()",5000);
	}
	
	//init_facebook();
	
	
	if (window.request_panes != undefined) {
		
		
		//get the panels set in the request uri (search=1,2,3)
		for (i in request_panes) {
			
			add_search_panel(request_panes[i]);
			
		}
		
		request_panes = undefined;
		
	}

	if (AUTO_UPDATE) {
	
		auto_update_tweets();
	
	}
	
	setTimeout("auto_save_job()",AUTO_SAVE_FREQ);
	
	
	bind_shortcuts();
	
}

function auto_save_job() {
  auto_save()
  setTimeout("auto_save_job()",AUTO_SAVE_FREQ);
}

function bind_shortcuts() {
	
		shortcut.add("up",function() {
			
			goto_previous_tweet();
			//alert("up")
			
		});
		
		shortcut.add("down",function() {
			
			goto_next_tweet();
			//alert('down')
			
		});
		
		shortcut.add("left",function() {
			
			goto_previous_panel();
			//alert('down')
			return false;
			
		});
		
		shortcut.add("right",function() {
			
			goto_next_panel();
			//alert('down')
			return false;
			
		});
		
	
}




/************************ PARSE FUNCTIONS **********************************/

//Deprecated
function parse_last_update(panel_id,data) {
	
	$('#panel_' + panel_id).find('.last_update').html(data[0].text);
	
}

//Parse Shizzow data and display it
function parse_get_shouts_data(panel_id,page_num,data) {
	
	var shizzow_data = data;
	
	hide_loader();
	
	//$('#panel_' + panel_id).find('.tweets').html(data.results.shouts[0].places_name);
	
	var cur_date = new Date();
	
	data.results.shouts.reverse();
	
	var pan = get_panel_by_id(panel_id);
	
	for (i in data.results.shouts) {
		
		var to_add = "";
		
		
		var cur_shout = data.results.shouts[i];
		
		var s_id = cur_shout.shouts_history_id;
		
		if ($('#shout_' + s_id).length != 0) {
		  continue;
		}
		
		cur_shout['id'] = cur_shout.shouts_history_id;
		
		pan.panel_data.push(cur_shout);
		
		to_add += '<div class="tweet shout" id="shout_' + s_id + '">';
		
		to_add += '<div class="avatar_container"><img class="avatar" src="' + data.results.shouts[i].people_images.people_image_48 + '" alt="Avatar" /></div>';
		
		to_add += '<div class="the_tweet">';
		
		var shout_message = '';
		
		if (cur_shout.shouts_messages != null) {
			
			shout_message = cur_shout.shouts_messages[0].message;
			
		}
		
		to_add += '<a href="http://shizzow.com/people/' + cur_shout.people_name + '" target="_blank">' + cur_shout.people_name + '</a> shouted from <a href="" onclick="add_shizzow_place(' + "'" + panel_id + "'," + "'" + cur_shout.places_name + "'," + "'" + cur_shout.places_key + "'" + '); return false;">' + cur_shout.places_name + '</a>';
		
		if (shout_message != '') {
			
			to_add += '<span class="tweet_text">' + shout_message + '</span>';
			
		}
		
		to_add += '<span class="tweet_meta">';
	
		var created_date = new Date();
		
		created_date.setISO8601(cur_shout.arrived);
	
		//to_add += '<span id="tweet_time_' + s_id + '">' + get_time_text(cur_date,created_date) + "</span>";
		to_add += '<span id="tweet_time_' + panel_id + s_id + '">' + cur_shout.shout_time + "</span>";
		
		to_add += "</div>";
		
		//to_add += '<br class="clear_both"/>';
		
		to_add += "</div>";
		
		//alert(to_add);
		
		$('#panel_' + panel_id).find('.tweets').prepend(to_add);
		
		$('#panel_' + panel_id).find('#shout_' + s_id).show();
		
	}
	
	save_panel(panel_id,pan);
	
	
	//update_times(panel_id);
	
	//alert(data.results.shouts);
	
	
	
}

//Parse Twitter data and display it
function parse_get_tweets_data(panel_id,type,page_num,data) {
	
		//alert("displaying page " + page_num);
	
		//alert("parsing tweets for panel" + panel_id + "with data " + data);
	
		//alert("parsing tweet type:" + type);
		
		//alert("page: " + page_num)
	
		if (type == 'direct_sent') {
			type = 'direct';
		}
	
		var tweets = $('#panel_' + panel_id).find('.tweets');
		
		var pan = get_panel_by_id(panel_id);
				
		if (pan.panel_data == data) {
			
			//there's nothing new
			update_times(panel_id);
			
			return;
			
		}
		
		if (data.length == 0) {
		  update_times(panel_id);
		  //console.log("updating times bc length is 0")
		  return;
		} else {
		  //console.log('Data is not 0 ' + data.length)
		}
		
		if (pan.panel_type == 'shizzow_panel') {
			parse_get_shouts_data(panel_id,page_num,data);
			return;
		}
		
		var cur_date = new Date();
		
		var is_search = false;
		
		if (data.results != undefined) {
			
			is_search = true;
			
		}
		
		if (page_num == 1) {
			
			if (!is_search) {
				
				data.reverse();
				
			} else {
				
				data.results.reverse();
				
			}
			
		}
		
		var num_tweets = data.length;
		
		if (is_search) {
			
			num_tweets = data.results.length;
			
		}
		
		if (pan.panel_data == "") {
		  pan.panel_data = new Array();
		}
		
		//alert ("tweet type: " + pan.tweet_type);
		
		for (var i = 0; i < num_tweets; i++) {
			
			var tweet = null;
			
			if (!is_search) {
				tweet = data[i];
			} else {
				tweet = data.results[i];
			}
			

						
			var already_displayed = false;
		
		
			if (pan.tweet_type == 'replies') {
				//alert("is reply comparing" + tweet.from_user + " to " + pan.user);
				if (('' + tweet.from_user) == (pan.user + '')) {
					already_displayed = true;
				}
			}
		
			for (var j = 0; j < pan.panel_data.length; j++) {
			
				if (pan.panel_data[j].text == tweet.text) {  //wouldn't need if I used since in API call
				
					//$('#canvas').append("already here");
				
					already_displayed = true;
				
				}
				
				
			}
			
			if (already_displayed) {
				continue;
			}
			
			if (tweet.id > pan.latest_tweet_id) {
				
				pan.latest_tweet_id = tweet.id;
				
			}
			
			pan.panel_data.push(tweet);
			
			
			if (DESTROY_TWEETS) {
				
				if (pan.panel_data.length > pan.tweet_display_limit) {
					
					var old_tweet = pan.panel_data.shift();
					
					//remove the old tweet from the html as well
					
					$('#panel_' + panel_id + 'tweet_' + old_tweet.id).hide();
					
					$('#panel_' + panel_id + 'tweet_' + old_tweet.id).remove();
					
				}
				
			}
			
			var favorite_class_note = '';
			
			//alert(tweet.favorited);
			
			if (tweet.favorited) {
				
				favorite_class_note = 'favorite_tweet';
				
			}
			
			var tweet_div = '<div class="' + tweet.id + ' tweet ' + favorite_class_note + '" id="panel_' + panel_id + 'tweet_' + tweet.id + '">';
			
			tweet_div += '<div class="tweet_top"></div>';
			tweet_div += '<div class="tweet_left"></div>';		
		
			var profile_image_url = '';
			
			if (!is_search) {
				
				if (type != "direct") {
				
					profile_image_url = tweet.user.profile_image_url;
				
				} else {
					
					if (tweet.sender_screen_name != panel_id) {
					  profile_image_url = tweet.sender.profile_image_url;
					} else {
					  profile_image_url = tweet.recipient.profile_image_url;
					}
					
				}
				
			} else {
				
				profile_image_url = tweet.profile_image_url;
				
			}

			
		
			var from_sn = '';
		
			if (!is_search) {
				if (type == 'direct') {
					from_sn = tweet.sender_screen_name;
				} else {
					from_sn = tweet.user.screen_name;
				}
			} else {
				
				from_sn = tweet.from_user;
				
			}
			
			tweet_div += '<div class="avatar_container"><img class="avatar" src="' + profile_image_url + '" alt="Avatar" id="avatar_' + from_sn + '"/></div>';

		
			tweet_div += '<div class="the_tweet">';
		
			tweet_div += '<div class="the_tweet_top"></div>';
			tweet_div += '<div class="the_tweet_left"></div>';
		
			tweet_div += '<input type="hidden" class="tweet_user_name" value="' + from_sn + '"/>';
			tweet_div += '<input type="hidden" class="tweet_id" value="' + tweet.id + '"/>';
			
			
			tweet_div += '<a class="user_name" target="_blank" onclick="return display_twitter_user(\'' + from_sn + '\');" href="http://twitter.com/' + from_sn + '">' + from_sn + "</a>: ";
		
		
			var tweet_text = parse_tweet(tweet.text);
		
			tweet_div += '<span class="tweet_text">' + tweet_text + '</span>';
		
			tweet_div += '<span class="tweet_meta">';
		
			var created_date = new Date(tweet.created_at);
		
			tweet_div += '<span id="tweet_time_' + panel_id + tweet.id + '">' + '<a href="http://twitter.com/' + from_sn + '/status/' + tweet.id + '" target="_blank">' + get_time_text(cur_date,created_date) + "</a>";
		
		  tweet_div += "</span>";
			
		
			
		
			if (tweet.in_reply_to_screen_name != undefined) {
			
				tweet_div += 'In reply to <a href="http://twitter.com/' + tweet.in_reply_to_screen_name + '">' + tweet.in_reply_to_screen_name + '</a> ';
			
			}
		
			if (!is_search) {
				if (type != 'direct') {
					tweet_div += 'from ' + tweet.source;
				} else if (type == 'direct') {
				  tweet_div += 'to ' + tweet.recipient_screen_name;
				}
			}
		
		  if (TRANSLATE) {
		
		    tweet_div += ' / <a href="" onclick="translate_tweet(\'panel_' + panel_id + 'tweet_' + tweet.id + '\'); return false;">Translate</a>';
		  
	    }
		
			tweet_div += '</span>';
			
			var display_reply_icon = true;
			
			if (is_search) {
				
				display_reply_icon = false;
				
			}
			
			if (type == 'replies') {
				
				display_reply_icon = true;
				
			}
			
			if (from_sn == ('' + pan.user)) {
				
				display_reply_icon = false;
				
			}
			
			var display_favorite_icon = true;
			
			if (type == "direct") {
				
				display_favorite_icon = false;
				
			}
			
			if (is_search) {
				
				display_favorite_icon = false;
				
			}
			
			var panel_id_for_icons = panel_id;
			
			if (pan.parent_panel != null) {
			  panel_id_for_icons = pan.parent_panel
			}
			
			tweet_div += '<div class="tweet_buttons">';
			
				if (type != 'direct') {
					if (!is_search) {
						tweet_div += '<div id="retweet_' + tweet.id + '" class="retweet_icon" ';
						tweet_div +=  'onclick="retweet_button(\'' + panel_id_for_icons + '\',' + tweet.id + ",'" + from_sn + "')\">";
						tweet_div += '<img src="' + URL_BASE + 'images/Recycle.png" alt="Retweet" title="Retweet" /></div>';
					}
				}
			
				if (display_favorite_icon) {
					tweet_div += '<div id="favorite_' + tweet.id + '" class="favorite_icon" ';

					tweet_div +=  'onclick="toggle_favorite(\'' + panel_id_for_icons + '\',' + tweet.id + ')">';
					tweet_div += '<img src="' + URL_BASE + 'images/star.gif" alt="Favorite" title="Favorite this tweet" /></div>';
				}
				
				if (display_reply_icon) {
					//alert("is reply comparing" + tweet.from_user + " to " + pan.user);
					tweet_div += '<div id="reply_' + tweet.id + '" class="reply_icon" ';
	
					tweet_div +=  'onclick="reply_to_tweet(\'' + panel_id_for_icons +'\',' + tweet.id + ",'" + from_sn + "')\">";
					tweet_div += '<img src="' + URL_BASE + 'images/reply.gif" alt="Reply to this tweet" /></div>';
				}
				
			
			tweet_div += '</div>';
			
			
			
			tweet_div += '<div class="the_tweet_right"></div>';
			tweet_div += '<div class="the_tweet_bottom"></div>';
			
			tweet_div += '</div>';
			
			

			
			//tweet_div += '<br class="clear_both"/>';
			tweet_div += '<div class="tweet_right"></div>';
			tweet_div += '<div class="tweet_bottom"></div>';
			tweet_div += '</div>';
			
			if (page_num == 1) {
				tweets.prepend(tweet_div);
			} else {
				//alert("appending");
				tweets.append(tweet_div);
			}
			
			var reply_pan_id = '' + panel_id;
			var reply_tweet_id = '' + tweet.id;
			var reply_from_sn = '' + from_sn;
			

			
			$('#panel_' + panel_id + 'tweet_' + tweet.id).show();
			
		}
		
		
		hide_loader();
	
		save_panel(panel_id,pan);
		
		update_times(panel_id);
		
		$('.tweet').click(function() {
			
			$('.tweet:eq(' + selected_tweet + ')').removeClass('selected_tweet')
			
			selected_tweet_panel_id = $(this).parent().parent()[0].id
			
			
			//alert('clicked tweet!');
			selected_tweet = $('#' + selected_tweet_panel_id + ' div.tweet').index(this)
			
			
			for (i in tw_panels) {
				
				if (('panel_' + tw_panels[i].panel_id) == selected_tweet_panel_id) {
					
					selected_tweet_panel = i;
					
				}
				
			}
			
			$(this).addClass('selected_tweet')
		
		});
		
		bind_hashtag_links();
		
		update_widths();
		
		update_draggables();
		
		if (type == 'regular') {
		  parse_filtered_tweets(panel_id,page_num,data)
		}
		
	
}

function update_draggables() {
  
  $('img.avatar').draggable( 'destroy' )
  
  $('img.avatar').draggable({
    appendTo: 'body',
    helper: 'clone',
    zIndex: 300,
  })
  
  
}

function parse_filtered_tweets(panel_id,page_num,data) {
  
  var pan = get_panel_by_id(panel_id)
  
  
  
  for (i in pan.derivative_panels) {
    
    //filter the data
    //console.log("parsing")
    
    var d_panel = get_panel_by_id(pan.derivative_panels[i]);
    
    if (d_panel == null) {
      continue;
    }
    
    tweets_data = new Array();
    
    if (d_panel.filter_rules == null) {
      //console.log("no filter rules")
      continue;
    }
    
    if (d_panel.filter_rules['users'] != undefined) {
      
      if (d_panel.filter_rules['users']['all'] == undefined) {
        tweets_data = $.grep(data, function(d) {
          //console.log("comparing " + d.user.screen_name)
          return (d_panel.filter_rules.users[d.user.screen_name.toLowerCase()] == true)
        })
      } else {
        tweets_data = $.grep(data, function(d) {
          //console.log("comparing " + d.user.screen_name)
          return (d_panel.filter_rules.users[d.user.screen_name.toLowerCase()] != true)
        })
      }
      
      //console.log("tweets data is " + tweets_data.length)
      //window.FILTER_DATA = tweets_data
    } else {
      //console.log("no rules to parse")
    }
    
    if (d_panel.filter_rules['content'] != undefined) {
      for (r in d_panel.filter_rules['content']) {
        var rule = d_panel.filter_rules['content'][r]
        
        if (rule == null) {
          continue;
        }
        
        //console.log("Comparing " + JSON.stringify(rule))
        tweets_data = $.grep(tweets_data, function(d) {
          
          if (rule.rule_type == "CONTAINS") {
            return (d.text.toLowerCase().indexOf(rule.term.toLowerCase()) != -1)
          }
          
          if (rule.rule_type == "DOES_NOT_CONTAIN") {
            return (d.text.toLowerCase().indexOf(rule.term.toLowerCase()) == -1)
          }
        
        })
      }
    }
    
    parse_get_tweets_data(d_panel.panel_id,'regular',page_num,tweets_data.reverse())
  }
  
}

//Parses the text of an individual tweet
//Turns user names/urls/hashtags into hyperlinks
function parse_tweet(tweet) {
	
	if (tweet == null) {
	  return '';
	}
	
	var new_tweet = tweet;
	
	var url_RE = /(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|]/gi;
	new_tweet =  tweet.replace(url_RE,"<a target=\"_blank\" class=\"tweeted_link\" href=\"$&\" onclick=\"return follow_link('$&')\">$&</a>");
	
	var hashtag_RE = /[#]+[A-Za-z0-9-_]+/gi;
	new_tweet = new_tweet.replace(hashtag_RE,
		function(t) {
				var tag = t.replace("#","")
				return '<a class="hashtag_link" target="_blank" href="http://tagal.us/tag/' + tag + '" onclick="return follow_link(\'http://tagal.us/tag/' + tag + '\');">' + t + '</a>';
				//return t.link("http://tagal.us/tag/"+tag);
		}
		);
	
	var username_RE = /[@]+[A-Za-z0-9-_]+/gi;
	
	new_tweet = new_tweet.replace(username_RE, function(u) {
		
		var username = u.replace("@","");
		return '<a target="_blank" href="http://twitter.com/' + username + '" onclick="return display_twitter_user(\'' + username + '\');">' + u + '</a>';
		//return u.link("http://twitter.com/"+username);
		
	});
	
	
	return new_tweet;
}

//Parse the shizzow favorites data and display it in drop down menu
function parse_shizzow_favorites(panel_id,data) {
	
	//if ($('#panel_' + panel_id).find('.shizzow_favorites').length == 0) {
		
	//	$('#panel_' + panel_id).find('.twitter_inputs').append('<select class="shizzow_favorites"></select>');
		
	//}
	
	var shizzow_data = data;
	
	for (i in data.results.places) {
		
		var cur_place = data.results.places[i];
	
		$('#panel_' + panel_id).find('.shizzow_favorites').append('<option value="' + cur_place.places_key + '">' + cur_place.places_name + '</option>');
		
	}
	
}





//Looks through tw_panels to find panel with matching id
function get_panel_by_id(panel_id) {
	
	for (pan in tw_panels) {
		
		if (tw_panels[pan].panel_id == panel_id) {
			
			return tw_panels[pan];
			
		}
		
	}
	
	return null;
	
}

//Saves the state of a panel
function save_panel(panel_id,pan) {
	
	for (panel in tw_panels) {
		
		if (panel.panel_id == panel_id) {
			
			panel = pan;
			
		}
		
	}
	
	if (AIR) {
		
		air_save_panels();
		
	}
	
}

//Retrieves panels from previous session
function get_session_panels() {
	
	if (AIR) {
		
		air_get_session_panels();
		
		return;
	}
	
	if (PROXY) {
		
		proxy_get_session_panels();
		
		return;
		
	}
	
}

//NEWUI - Should add header to top instead of a tab
function add_new_nav_button(panel_id) {
	
	
	var panel_name = get_panel_user_name(panel_id);
	
	var close_button_code = '<img src="' + URL_BASE + 'images/Cancel.png" id="remove_panel_' + panel_id + '"  class="close_panel" onclick="remove_panel(\'' + panel_id + '\')" alt="Close Panel" title="Close this panel" />';
	
	var nav_button_code = '<div class="nav_button show_panel_' + panel_id + '" onclick="show_panel(\'' + panel_id + '\')">' + '<span class="panel_name">' + panel_name + '</span>' + close_button_code + '</div>';
	
	$('#header_nav_buttons').append(nav_button_code);
	
	
	$('#panel_' + panel_id).prepend(nav_button_code);
	
	
	if (!AIR) {
	  $('#panels').sortable('destroy')
		$('#panels').sortable(
			{
				handle: '.nav_button',
				start: function(ev,ui) {
				  $('.tweet').hide();
				},
				stop: function(ev,ui) {
				  $('.tweet').show();
				},
				update: function() {
					update_panel_order();
				},
			} 
			);
	}
	
}

function update_panel_order() {
  var displayed_order = $('#panels').sortable('toArray');
  var new_panel_array = new Array();
  for (i in displayed_order) {
    var cur_panel = get_panel_by_id(displayed_order[i].substring(6))
    new_panel_array.push(cur_panel)
  }
  tw_panels = new_panel_array;
  auto_save();
}

//Create a new panel
function make_new_panel() {
		
	var u = $('#tw_user').val();
	var p = $('#tw_pass').val();
	
	toggle_login_form();	
	
	$('#tw_user').val('');
	$('#tw_pass').val('');
	
	if ($('#account_type').val() == "shizzow") {
		make_new_shizzow_panel(u,p);
		return;
	}
	
	var new_id = u;
	
	if (get_panel_by_id(new_id) != null) {
		
		alert("You already have that panel open!");
		return;
		
	}	
	
	//check the login
	var good_login = true;
	
	if (PROXY) {
		
		good_login = proxy_check_login(u,p);
		
	}
	
	if (XS) {
		
		good_login = js_check_login(u,p);
		
	}
	
	if (!good_login) {
		
		alert("That login user/pass didn't work!");
		return;
		
	}
	
	
	//get the info
	
	var panel_info = null;
	
	if (XS) {
		
		panel_info = js_get_twitter_user_info(u);
		
	} else {
		
		panel_info = proxy_get_twitter_user_info(u);
		
	}
	
	
	var new_panel = new Data_Panel(new_id,'regular',u,p,panel_info);
	
	tw_panels.push(new_panel);
	
	if (AIR) {
		
		air_save_panels();
		
	}
	
	//register the panel
	
	if (!AIR) {
		var old_panel_code = proxy_get_panel(new_id,u,p,panel_info);
	}
	
	
	//get the html
	
	var panel_code = js_get_panel(new_id,u,p,panel_info);
		
		
		
	//set up panel
	set_up_panel(new_id,panel_code,u,p);
	
	auto_save();
	
}


//Remove a panel
function remove_panel(panel_id) {
	
	var pan = get_panel_by_id(panel_id)
	
	if (pan.parent_panel != null) {
	  var parent_pan = get_panel_by_id(pan.parent_panel)
	  
	  if (parent_pan != null) {
	  
  	  for (i in parent_pan.derivative_panels) {
  	    if (parent_pan.derivative_panels[i] == panel_id) {
	      
  	      parent_pan.derivative_panels.splice(i,1)
	      
  	    }
  	  }
	  
	    save_panel(parent_pan.panel_id,parent_pan)
  	  
	  }
	  
	}
	
	$('#panel_' + panel_id).remove();
	
	if (!TABBED_PANELS) {
		$('#panels').width($('#panels').width() - (PANEL_WIDTH - 20))
	} else {
		$('.show_panel_' + panel_id).remove();
	}
	
	$('#show_panel_' + panel_id).remove();
	
	//remove from tw_panels
	
	for (var i = 0; i < tw_panels.length; i++) {
		
		if (tw_panels[i].panel_id == panel_id) {
			
			tw_panels.splice(i,1);
			
		}
		
	}
	
	if (PROXY) {

		proxy_remove_panel(panel_id);

	}	
	
		
	if (AIR) {
		
		air_remove_panel(panel_id);	
	
	}

	//show the first available panel?
	
	front_panel = tw_panels[0].panel_id;
	
	show_panel(front_panel);
	
		
}


//Add a search panel
function add_search_panel(search_term) {

	if (search_term == null) {
		
		search_term = prompt_search_term();
		
	}
	
	if ((search_term == "") || (search_term == null)) {
		
		return;
		
	}
	
	//var panel_id = "Search " + search_term;
	
	//panel_id = panel_id.replace(/ /g,'_');
	var d = new Date();
	
	var panel_id = "Search_" + d.getTime();
	
	if (get_panel_by_id(panel_id) != null) {
		
		alert("You already have a panel open like that!");
		return;
		
	}
	
	/*
	if (search_term.indexOf("location") == 0) {
		
		if (search_term.indexOf(" ") != -1) {
			
			LOCATION_SEARCH_DISTANCE = (search_term.split(" "))[1];
			search_term = "location"
			
		}
		
		if (navigator.geolocation) {
			
			navigator.geolocation.getCurrentPosition(function(position) {  
			  		//alert("You seem to be at: " + position.latitude + ',' + position.longitude);  
					user_loc = position.latitude + '%2C' + position.longitude;
					refresh_tweets();
				}  
			);
			
		}
		
	}
	*/
	
	var new_panel = new Data_Panel(panel_id,'search_panel',search_term,'_search',null);
	
	tw_panels.push(new_panel);
	
	
	if (AIR) {
		
		air_save_panels();
		
	}
		
	var data = js_get_search_panel(panel_id,search_term,'_search'); //get the html
	
	
	
	if (PROXY) {
		var old_data = proxy_get_search_panel(panel_id,search_term,'_search');//register the panel
	}
	
	set_up_panel(panel_id, data, search_term,"_search");
	
	
	auto_save();
	
	return false;
	
}


//Displays a panel, gets the tweets, and adds a nav button
//Called when a panel is being made
function set_up_panel(id, data, t_user, t_pass) {
	
	$('.startup_box').hide();
	
	$('#panels').append(data);

	if (!TABBED_PANELS) {
		$('#panels').width($('#panels').width() + (PANEL_WIDTH + 20))
	}

	add_new_nav_button(id);
	show_panel(id);	
	js_get_friends_followers(id);
	
	get_tweets(id,'regular',1);
	
}

//Show a panel
function show_panel(panel_id) {
				
	if (panel_id == undefined) {
		
		return;
		
	}	

	
	var pan = get_panel_by_id(panel_id);
	
	
	
	if (pan == null) {
		
		return;
		
	}
	
	front_panel = panel_id;
	
	if (TABBED_PANELS) {
		$('.twitter_panel').hide();
		$('div#header_nav_buttons div.nav_button').removeClass('button_highlighted');
		$('div#header_nav_buttons div.show_panel_' + panel_id).addClass('button_highlighted');
	}
	
	$('#panel_' + panel_id).show();

	if (!TABBED_PANELS) {
    var tweet_input = $('#panel_' + panel_id).find('.nav_button');
  	tweet_input.focus();
	
  	$.scrollTo( tweet_input, 20, {
	
  		offset: { left: -20, top: -130 },
  		axis: 'xy',
	
  	} );
	}
	
	
	if (pan.tweet_type == null) { pan.tweet_type = 'regular'; save_panel(panel_id,pan); }
	
	$('#panel_' + panel_id + '_' + pan.tweet_type).show();
	
	//$('.tweet_type_button').css("background","#eee");
	//$('.tweet_type_button').css("border","1px solid #aaa");
	//$('.tweet_type_button').removeClass('button_highlighted');
	
	//$('#panel_' + panel_id + "_" + pan.tweet_type).css("background","white");
	//$('#panel_' + panel_id + "_" + pan.tweet_type).css("border-bottom","1px solid white");
	$('#panel_' + panel_id + "_" + pan.tweet_type).addClass('button_highlighted');
	
	
	$('#panel_' + panel_id).find('.tweet_input').keyup(function() {
		
		length_notify(panel_id);
		
	});
	
	if (TABBED_PANELS) {
		var bg_url = $('#panel_' + panel_id).find('.panel_background').val();
	
		if (!MOBILE) {
			//alert("setting background");
			//$('body').css('background',"url('" + bg_url + "') no-repeat fixed");
			//$('body').css('background-color',"#" + $('#panel_' + panel_id).find('.panel_background_color').val());
		}
	}
	
	
}

//Returns a string represting the panel for use in the tabs
//For Twitter panels, this is just the user name
//For search, it is "Search: TERM"
//For Shizzow, "Shizzow: USER"
function get_panel_user_name(panel_id) {
	

	
	if (panel_id.indexOf("Facebook_") != -1) {
	  
	  return "Facebook";
	  
	}
	
	if (panel_id.indexOf("Search_") != -1) {
	  
	  return "Search: " + get_panel_by_id(panel_id).user
	  
	}
	
	if (panel_id.indexOf("Shizzow") != -1) {
	  
	  return "Shizzow: " + get_panel_by_id(panel_id).user
	  
	}
	
	return "Twitter: " + get_panel_by_id(panel_id).user;
	

	
}

function make_droppables() {
  $('.twitter_panel').droppable( 'destroy' );
  for (i in tw_panels) {
    if (tw_panels[i].panel_type == 'filtered_panel') {
      panel_id = tw_panels[i].panel_id
    } else {
      continue
    }
    //console.log("Making " + panel_id + " droppable")
    $('#panel_' + panel_id ).droppable({
	  
  	   accept: ".avatar",
  	   drop: function(ev, ui) {


           //console.log(ev)
           var theId = ev.target.id.substring(7);
           
           //alert(JSON.stringify(ev.target))
           
           var drop_panel_id = this.id.substring(6);
           
           //alert(drop_panel_id)

           //console.log(theId + ' on panel ' + drop_panel_id);

           pan = get_panel_by_id(drop_panel_id)
         
           if (pan.filter_rules['users'] == undefined) {
             pan.filter_rules['users'] = new Object();
           }
         
           pan.filter_rules.users[theId.toLowerCase()] = true

          save_panel(pan.panel_id,pan)
         
          reload_filter_panel(panel_id)
      }
	  
  	  });
	}
}

function make_new_filtered_panel(panel_name,from_panel) {
  
  var from_panel = get_panel_by_id(from_panel);
  
  if (from_panel == null) {
    alert("Couldn't find panel");
    return;
  }
  
  var d = new Date();
	
	panel_id = "Filtered_" + d.getTime();
	
	panel_data = js_get_filtered_panel(panel_id)
	
	
	var new_panel = new Data_Panel(panel_id,'filtered_panel',panel_name + " > from panel " + from_panel.user,'_filtered',null);
	
	new_panel.parent_panel = from_panel.panel_id;
	
	//temp
	new_panel.filter_rules = new Object();
	new_panel.filter_rules['users'] = new Object();
	new_panel.filter_rules['content'] = new Array();
	
	tw_panels.push(new_panel);
	
	from_panel.derivative_panels.push(panel_id);
	
	set_up_panel(panel_id, panel_data, '',"_filtered");
	
	parse_filtered_tweets(from_panel.panel_id,2,from_panel.panel_data);
	
	make_droppables();
	
	return false;
	
}

function reload_filter_panel(panel_id) {
  
  var pan = get_panel_by_id(panel_id)
  
  pan.panel_data = new Array();
  
  save_panel(panel_id,pan)
  
  var from_panel = get_panel_by_id(pan.parent_panel)
  
  $('#panel_' + panel_id).find('.tweets').html('');
  
  parse_filtered_tweets(from_panel.panel_id,2,from_panel.panel_data);
  
  auto_save();
  
}




/******************************** CT PLUGINS CODE ********************************/

//Plugins are not yet functioning

function register_plugin(hook,callback_fn) {
	
	var plug = new CT_Plugin(hook,callback_fn);
	plugin_hooks.push(plug);
	
}

function get_plugins(hook) {
	
	
	
}

function run_plugins(hook,args) {
	
	for(var i = 0; i < plugin_hooks.length; i++) {
		
		if (plugin_hooks[i].hook == hook) {
			eval(plugin_hooks.callback_fn);
		}
		
	}
	
}

//translate

function translate_tweet(tweet_id) {
  var the_tweet = $('#' + tweet_id + " .tweet_text")
  var text = the_tweet.html();
  
  console.log('translating ' + text)
  
  google.language.translate(text, "", "en", function(result) {
    console.log('got result')
    if (!result.error) {
      the_tweet.html(result.translation);
    }
  });
  
}




function send_shout(panel_id) {
	
	var pan = get_panel_by_id(panel_id);
	var shout = $('#panel_' + panel_id).find('.tweet_input').val();
	var location = $('#panel_' + panel_id).find('.shizzow_favorites').val();
	
	$('#panel_' + panel_id).find('.tweet_input').val('');
	
	$('#panel_' + panel_id).find('.length_notify_box').html('');
	
	if (PROXY) {
		proxy_send_shout(panel_id,shout,location);
	}
	
}

function add_shizzow_place(panel_id,place_name,place_key) {
  
  $('#panel_' + panel_id).find('.shizzow_favorites').append('<option value="' + place_key + '">' + place_name + '</option>')
  $('#panel_' + panel_id).find('.shizzow_favorites').val(place_key)
  $('#panel_' + panel_id).find('.tweet_input').focus();
  
  $.scrollTo( $('#panel_' + panel_id + ''), 20, {
	
		offset: { left: 0, top: -110 }
	
	} );
  
}

//Make a new Shizzow panel
function make_new_shizzow_panel(u,p) {
	
	//alert("making shizzow panel");
	
	//u = u.substring(8);
	
	var d = new Date();
	
	var new_id = "Shizzow_" + d.getTime();
	
	if (get_panel_by_id(new_id) != null) {
		
		alert("You already have a panel open like that!");
		return;
		
	}
	
	if (PROXY) {
		var old_data = proxy_get_shizzow_panel(new_id,u,p);//register the panel
	}
	
	var panel_info = '';
	
	var new_panel = new Data_Panel(new_id,'shizzow_panel',u,p,panel_info);
	
	new_panel.tweet_type = "shouts";
	
	tw_panels.push(new_panel);
	
	var panel_code = js_get_shizzow_panel(new_id,u,p);
	
	set_up_panel(new_id,panel_code,u,p);
	
	if (PROXY) {
	
		proxy_get_shizzow_favorites(new_id);
	
	}
	
}




//Updates the timestamp on displayed tweets for a given panel
function update_times(panel_id) {
	
	var pan = get_panel_by_id(panel_id);
	
	var cur_date = new Date();
	
	if (pan.panel_data != undefined) {
		for (var t = 0; t < pan.panel_data.length; t++) {
	    //console.log("updating time on panel " + pan.panel_id)
			$('#tweet_time_' + panel_id + pan.panel_data[t].id + ' a').html(get_time_text(cur_date,new Date(pan.panel_data[t].created_at)));
	
		}
	}
	
	for (i in pan.derivative_panels) {
	  update_times(pan.derivative_panels[i])
	}
	
}

//Returns a string representing the age of the tweet. Eg "2 minutes ago", "4 hours ago"
function get_time_text(cur_date,created_date) {
		
	var time_diff = parseInt((cur_date.getTime() - created_date.getTime()) / 1000);
	
	
	if (time_diff <= (60 * 60 * 12))  {//12 hours ago
		
		if (time_diff <= 60) {
			return "Less than a minute ago ";
		} else if (time_diff < 3600) {
			var min_ago = parseInt(time_diff / 60);
			return min_ago + " minutes ago ";
		} else {
			var hrs_ago = parseInt(time_diff / 3600);
			return hrs_ago + " hours ago ";
		}
		
	} else {
		return created_date + " ";
	}
	
}




//Get the tweets/shouts/etc for a given panel
function get_tweets(panel_id,type,page_num) {

	//get the first tweet
	
	
	if (panel_id == null) {
		
		return;
		
	}

	
	var pan = get_panel_by_id(panel_id);

	if (pan.panel_type == 'filtered_panel') {
	  
	  return;
	  
	}

  if (pan.panel_type == 'facebook_panel') {
    fb_get_statuses(panel_id);
    return;
  }
  
  //if (pan.panel_type == 'search') {
  //  js_get_search_tweets_through_json(panel_id,page_num);
  //  return;
  //}

	show_loader();

	var tweets = $('#panel_' + panel_id).find('.tweets');

	if (type == undefined) {
		
		type = 'regular';
		
	}
	
	if (type != 'direct') {
		
		$('#panel_' + panel_id).find('.dm_notify_box').hide();
		
	} else {
		
		$('#panel_' + panel_id).find('.dm_notify_box').show();
		
	}	
	
	var init_load = false;
	
	if (pan.panel_data == null) {
		
		pan.panel_data = new Array();
		init_load = true;
		
	}
	
	if (pan.tweet_type == null) {
		
		pan.tweet_type = type;
		
	}
	
	if (pan.tweet_type != type) {
		
		
		
		tweets.html("");
		pan.tweet_type = type;
		pan.panel_data = new Array();
		pan.latest_tweet_id = -1;
		
		if ((pan.tweet_type == "direct") || (pan.tweet_type == "direct_sent")) {
			
			if ($('.direct_options').length == 0) {
				$('#panel_' + panel_id).find('.tweet_type_menu').append('<div class="direct_options"><a href="" onclick="get_tweets(\'' + panel_id + '\',\'direct\',1); return false;">Inbox</a><a href="" onclick="get_tweets(\'' + panel_id + '\',\'direct_sent\',1); return false;">Outbox</a><br class="clear_both"></div>');
			}
			
		} else {

			$('.direct_options').remove();
			
		}
		
	}

	save_panel(panel_id,pan);

	if (PROXY) {
		
		proxy_get_tweets(panel_id,type,page_num,pan.latest_tweet_id,user_loc,LOCATION_SEARCH_DISTANCE);
		
	}


	if (XS) {

		js_get_tweets(panel_id, type, page_num, pan.latest_tweet_id, user_loc, LOCATION_SEARCH_DISTANCE);

	}
	
	if (type == "direct_sent") {
		
		type = "direct";
		
	}
	
	$("#panel_" + panel_id).find('.tweet_type_button').removeClass('button_highlighted');
	$("#panel_" + panel_id).find('#panel_' + panel_id + '_' + type).addClass('button_highlighted');
	

	
	
}

//Same as get_tweets, but retrieves older data instead of newer
function get_more_tweets(panel_id) {
	
	var pan = get_panel_by_id(panel_id);
	
	//determine what page to get
	
	//up the limit
	if (DESTROY_TWEETS) {
		
		pan.tweet_display_limit += 20;
		save_panel(pan);
		
	}
	
	var num_tweets = pan.panel_data.length;
	
	
	if ((num_tweets % 20) != 0) {
		
		num_tweets++;
		
	}
	
	var page_num = Math.ceil(num_tweets / 20) + 1;
	
	var tweet_type = 'regular';
	
	if (pan.tweet_type != null) {
		
		tweet_type = pan.tweet_type;
		
	}
	
	get_tweets(panel_id,tweet_type,page_num);
	
}

//Send a tweet
function send_tweet(panel_id) {
	
	var tweet = $('#panel_' + panel_id).find('.tweet_input').val();
	
	if (ADD_HASHTAG) {
	  	  
	  var hashtag = $('#panel_' + panel_id).find('input.add_hashtag').val();
	  
	  if (hashtag != "") {
	  
      if (hashtag.charAt(0) != '#') {
    
        hashtag = '#' + hashtag;
    
      }
  
      tweet += " " + hashtag;
      
    }
	  
	}
	
	var pan = get_panel_by_id(panel_id);
	

	
	if (pan.reply_to_name != null) {
		
		if (tweet.indexOf('@' + pan.reply_to_name) == -1) {
			
			pan.reply_id = -1;
			
		}
		
	} else {
		
		pan.reply_to_name = null;
		
	}
	
	save_panel(pan);
		
	var reply_to_id = pan.reply_to_id;
	
	if (tweet.length > 140) {
		
		alert ("Too many characters: " + tweet.length);
		return;
		
	}
	
	$('#panel_' + panel_id).find('.tweet_input').val('');
	
	$('#panel_' + panel_id).find('.length_notify_box').html('');
	
	$('#panel_' + panel_id).find('.last_update').val(tweet);
	
	//alert(tweet);
	
	var dm = false;
	
	if (pan.tweet_type == 'direct') {
		
		dm = true;
		$('#panel_' + panel_id).find('.dm_notify_box').html('')
		
	}
	
	if (PROXY) {
		
		proxy_send_tweet(panel_id,tweet,reply_to_id,pan.reply_to_name,dm);
		
	}
	

	if (XS) {
		
		js_send_tweet(panel_id,tweet,reply_to_id,pan.reply_to_name,dm);
		
	}
	
	pan.reply_to_id = -1;
	pan.reply_to_name = null;
	
	save_panel(pan);
	
	
}

//Reply
function reply_to_tweet(panel_id,tweet_id,user_name) {
	
	//alert("Replying to tweet id" + tweet_id + ' from ' + user_name);
	
	var pan = get_panel_by_id(panel_id);
	
	pan.reply_id = tweet_id;
	pan.reply_to_name = user_name;
	
	save_panel(pan);
	
	var tweet_input = $('#panel_' + panel_id).find('.tweet_input');
	tweet_input.focus();
	
	$.scrollTo( tweet_input, 20, {
	
		offset: { left: -200, top: -130 },
		axis: 'xy',
	
	} );
	
	
	if (pan.tweet_type == 'direct') {
		
		$('#panel_' + panel_id).find('.dm_notify_box').html("Direct message to @" + user_name);
		
	} else {
	
		tweet_input.val("@" + user_name + " ");
	
	}
}

//Deprecated?
function reply_button(panel_id,obj) {
	
	var tweet_id = $(obj).parent('.the_tweet').find('.tweet_id').val();
	var user_name = $(obj).parent('.the_tweet').find('.tweet_user_name').val();
	
	reply_to_tweet(panel_id,tweet_id,user_name);
	
}

//Called when the retweet button is clicked
function retweet_button(panel_id,tweet_id,user_name) {
		

	var tweet_to_rt = $('#panel_' + panel_id + 'tweet_' + tweet_id).find('.tweet_text').text();
	
	var rt_text = "RT @" + user_name + ": " + tweet_to_rt;
	
	if (rt_text.length > 140) {
		
		rt_text = rt_text.substring(0,137) + "..";
		
	}
	
	$('#panel_' + panel_id).find('.tweet_input').val(rt_text);
	
}

//Turn on or off a favorite
function toggle_favorite(panel_id,tweet_id) {
	
	//alert('favoriting ' + tweet_id + 'on panel ' + panel_id);
	
	var is_fav = $('#panel_' + panel_id + 'tweet_' + tweet_id).hasClass('favorite_tweet');
	
	if (is_fav) {
		
		$('#panel_' + panel_id + 'tweet_' + tweet_id).removeClass('favorite_tweet');
		
	} else {
		
		$('#panel_' + panel_id + 'tweet_' + tweet_id).addClass('favorite_tweet');
		
	}
	
	if (PROXY) {
		
		proxy_toggle_favorite(panel_id,tweet_id,!is_fav);
		
	}
	
	if (XS) {
		
		js_toggle_favorite(panel_id,tweet_id,!is_fav);
		
	}
	
}

//Toggle button
function toggle_favorite_button(panel_id,obj) {
	
	var tweet_id = $(obj).parent('.the_tweet').find('.tweet_id').val();
	toggle_favorite(panel_id,tweet_id);
	
}


//Function to automatically refresh tweets
function auto_update_tweets() {
	
		//alert('auto');
	
		if (AIR) {
			
			setTimeout(function() { auto_update_tweets() },UPDATE_FREQ);
			
		} else {
	
			setTimeout("auto_update_tweets()",UPDATE_FREQ);

		}
		
		
		/*
		if (front_panel != null) {
			get_tweets(front_panel,get_panel_by_id(front_panel).tweet_type,1);
		}
		*/
		
		
		for(i in tw_panels) {
			
			//if (tw_panels[i].panel_type != "shizzow_panel") {
			
				get_tweets(tw_panels[i].panel_id,tw_panels[i].tweet_type,1);
			
			//}
			
		}
		
		
	
}

//Manually refresh tweets - Called by the refresh button
function refresh_tweets() {
	
	$('#panels').find('.panel_id').each(
		function(i) {
			
			
			get_tweets(this.value,'regular',1);
			
		}
		);
	
}


//Gets the tweets from a user
//Used when displaying user info
function get_user_tweets(notify_window_link,user) {
	
	$('.get_user_tweets').hide();
	//$(notify_window_link).parent().append('tweets');
	
	if (XS) {
		
		js_get_user_tweets(user,$(notify_window_link).parent());
		
	}
	
	if (PROXY) {
		
		proxy_get_user_tweets(user,$(notify_window_link).parent());
		
	}
	
}

//Follow a Twitter user
function follow_user(panel_id,user_name) {
	
	if (PROXY) {
		
		proxy_follow_user(panel_id,user_name);
		
	}
	
	if (XS) {
		
		js_follow_user(panel_id,user_name);
		
	}
	
}

function unfollow_user(panel_id,user_name) {
	
	if (PROXY) {
		
		proxy_unfollow_user(panel_id,user_name);
		
	}
	
	if (XS) {
		
		js_unfollow_user(panel_id,user_name);
		
	}
	
}






function goto_previous_tweet() {
	
		scroll_to_tweet(selected_tweet_panel,selected_tweet - 1);

}

function goto_next_tweet() {
		
	scroll_to_tweet(selected_tweet_panel,selected_tweet + 1);
	
	
}

function goto_previous_panel() {

	scroll_to_tweet(selected_tweet_panel - 1,selected_tweet)
	
}

function goto_next_panel() {
	
	scroll_to_tweet(selected_tweet_panel + 1,selected_tweet)
	
}

function scroll_to_tweet(panel_index, index) {

	//console.log("going to tweet " + index + " on panel " + panel_index)
	

	if (tw_panels.length == 0) {
		
		return;
		
	}

	var panel_name = tw_panels[selected_tweet_panel].panel_id;

	//console.log("removing selected_tweet from " + selected_tweet + " on panel " + panel_name)
	
	//$('#panel_' + panel_name + ' div.tweet:eq(' + selected_tweet + ')').removeClass('selected_tweet')
	
	$('.tweet').removeClass('selected_tweet')
	
	if (panel_index != selected_tweet_panel) {
		
		if ((panel_index > -1) && (panel_index < tw_panels.length)) {
			
			if (index >= tw_panels[panel_index].panel_data.length) {
				
				index = tw_panels[panel_index].panel_data.length - 1;
				
			}
			
			selected_tweet_panel = panel_index;
			
		}
		
	}
	
	if (index == -2) {
		
		if (selected_tweet_panel == 0) {
			//already on the first panel - can't go back any more
			index = -1;
		} else {
			
			selected_tweet_panel = selected_tweet_panel - 1;
			
			panel_name = tw_panels[selected_tweet_panel].panel_id;
			
			index = tw_panels[selected_tweet_panel].panel_data.length - 1;
			
		}
		
	}
	
	if (index >= tw_panels[selected_tweet_panel].panel_data.length) {
		
		if (selected_tweet_panel < (tw_panels.length -1)) {
			
			selected_tweet_panel++;
			
			panel_name = tw_panels[selected_tweet_panel].panel_id;
			
			index = -1;
			
		} else {
			
			index = tw_panels[selected_tweet_panel].panel_data.length - 1;
			
		}
		
	}
	
	if (index != -1) {

		$.scrollTo( $('#panel_' + panel_name + ' div.tweet:eq(' + index + ')'), 400, {
		
			offset: { left: 0, top: -90 }
		
		} );	
	
		$('#panel_' + panel_name + ' div.tweet:eq(' + index + ')').addClass('selected_tweet')
	} else {
		//scroll to the twitter inputs
		
		$.scrollTo( $('#panel_' + panel_name + ''), 400, {
		
			offset: { left: 0, top: -110 }
		
		} );
		
	}
	
	selected_tweet = index;
	
	//console.log("went to tweet " + selected_tweet + " on panel " + selected_tweet_panel)
	
}


//Displays or hides the user/pass form
//Should be "toggle_login_form" for consistency
function show_login_form() {
  $('#openid_identifier').val(user_openid);
  
  $('#old_login_form').hide();
  
  if ($('#login_form:visible').length == 0) {
	  show_overlay();
	} else {
	  hide_overlay();
	}
  
	$('#login_form').css('left',$(window).width() - 420)
	
	$('#login_form').toggle("slide", { direction: "up" }, 400,
	function() {
		
		$('#login_form:visible').find('#tw_user').focus();
		
		
	}
	);
}

function toggle_login_form() {
  
  show_login_form();
  hide_overlay();
  
}

function toggle_search_form() {
  show_overlay();
  $('#search_form').css('left',$(window).width() - 420)
	
  $('#search_form').toggle("slide", { direction: "up" }, 400,
	function() {
		
		if ($('#search_form:visible').length > 0) {
		  $('#search_term').focus();
		  $('#search_term').select();
		} else {
		  hide_overlay();
		}
		
	}
	);
}

function show_settings_form() {
	
	$('#settings_form').css('left',$(window).width() - 600)
	
	if ($('#settings_form:visible').length == 0) {
	  show_overlay();
	} else {
	  hide_overlay();
	}
	
	$('#settings_form').toggle("slide", { direction: "up" }, 400,
	function() {
		$('#tabbed_panels').attr('checked', TABBED_PANELS );
		$('#add_hashtag').attr('checked', ADD_HASHTAG );
		
		$('#refresh_freq').val('' + (UPDATE_FREQ / 1000));
		$('#remove_old_tweets').attr('checked', DESTROY_TWEETS );
		$('#font_size').val('' + FONT_SIZE);
		$('#panel_width').val('' + PANEL_WIDTH);
		$('#css_file_setting').val(CSS_FILE);
		$('#auto_save_checkbox').attr('checked',AUTO_SAVE);
	}
	);
	
	
	
}

//Asks the user to enter a search term
function prompt_search_term() {
	
	var search_prompt = "Enter a search term:";
	
	
	/*
	if (navigator.geolocation) {
		
		search_prompt += ' (use "location 5mi" syntax for location based search)';
		
	}
	*/
	
	var search_term = prompt(search_prompt);
	
	return search_term;
	
}




/******************************** WINDOW FUNCTIONS ******************************/

//Used to follow a link instead of <a href=""
//In web version, it just returns true so that the href="" is still followed
function follow_link(l) {
	
	if (AIR) {
		window.parentSandboxBridge.nav_in_browser(l);
		return false;
	}
	
	return true;
	
}

function show_overlay() {
  
  $('#notify_overlay').css('opacity','0.5');
	$('#notify_overlay').css('height',$(document).height());
	
	$('#notify_overlay').show();
  
}

function hide_overlay() {
  $('#notify_overlay').hide();
	
}

function hide_open_windows() {
  hide_overlay();
  hide_notify_window();
  hide_alert();
  $('#settings_form:visible').hide();
  $('#login_form:visible').hide();
  $('#search_form:visible').hide();
  
}

//Shows a notification window
//Right now, this is a lightbox style window w/dropshaddow
function show_notify_window(html, click_event) {
	
  show_overlay();
	
	var win_left = $(window).scrollLeft() + 100;
	var win_top = $(window).scrollTop() + 150;
	
	if (click_event != undefined) {
	  win_left = click_event.pageX;
	  win_top = click_event.pageY;
	}
	
	$('#notify_window').css('left',win_left);
	$('#notify_window').css('top',win_top);
	$('#notify_window').css('opacity','1');
	
	
	
	$('#notify_content').html(html);
	
	$('#notify_window').show();
	
}

//Hides the notification window
function hide_notify_window() {
	

	hide_overlay();
	
	$('#notify_content').html('');
	
	$('#notify_window').hide();
	
}

//Displays information about a user
function display_twitter_user(user) {
	
	var display_follow_link = true;
	
	var user_info = '';
	
	show_loader();
	
	if (PROXY) {
		user_info = proxy_get_twitter_user_info(user);
	}
	
	if (XS) {
		user_info = js_get_twitter_user_info(user);
	}
	
	hide_loader();
	
	var info_div = '';
	
	info_div += '<span class="user_name"><a target="_blank" href="http://twitter.com/' + user + '" onclick="return follow_link(\'http://twitter.com/' + user + '\')">@' + user + '</a>';
	
	if (display_follow_link) {
		
		info_div += ' - <a href="" onclick="follow_user_window(\'' + user + '\',' + user_info.id + '); return false;">Follow/Unfollow</a>';
		
	}
	
	info_div += '</span>';
	
	info_div += '<img class="avatar" src="' + user_info.profile_image_url + '" alt="Avatar" title="' + user + '"/>';
	info_div += '<p class="user_info">' + parse_tweet(user_info.description) + '</p>';
	
	if (user_info.url != null) {
		info_div += '<span class="user_url"><a target="_blank" href="' + user_info.url + '" onclick="return follow_link(\'' + user_info.url + '\')">' + user_info.url + '</a></span>';
	}
	
	info_div += '<div class="user_stats">';
	info_div += '<label>Followers:</label>' + user_info.followers_count + '<br/>';
	info_div += '<label>Following:</label>' + user_info.friends_count + '<br/>';
	info_div += "</div>";
	info_div += '<div class="user_tweets">';
	info_div += '<a href="" class="get_user_tweets" onclick="get_user_tweets(this,\'' + user + '\'); return false;">Get tweets</a>';
	info_div += '</div>';
	
	show_notify_window(info_div);
	
	return false;
	
}

//Displays a user's tweets
function display_user_tweets(data, container) {
	var tweets_html = '';

  $('#notify_window').width(PANEL_WIDTH);

  var cur_date = new Date();

	for (var i = 0; i < data.length; i ++) {
	
	  tweet = data[i];
	  
	  tweets_html += '<div class="tweet" style="display: block">'
	  
	  tweets_html += '<div class="avatar_container"><img class="avatar" src="' + tweet.user.profile_image_url + '" alt="Avatar"/></div>';
		
	  tweets_html += '<div class="the_tweet">'
		
		tweet_text = parse_tweet(tweet.text);
		
		tweets_html += '<span class="tweet_text">' + tweet_text + '</span>';
	
		tweets_html += '<span class="tweet_meta">';
	
		var created_date = new Date(tweet.created_at);
		
		from_sn = tweet.user.screen_name;
	
		tweets_html += '<span id="tweet_time_' + tweet.id + '">' + '<a href="http://twitter.com/' + from_sn + '/status/' + tweet.id + '" target="_blank">' + get_time_text(cur_date,created_date) + "</a></span>";
		
		tweets_html += '</span>'
		
		tweets_html += '</div>'
		tweets_html += '</div>'
		tweets_html += '<br class="clear_both"/>'
	
	}

	tweets_html += "";

	container.append(tweets_html);
	
}

//Displays a window asking which acct to use to follow a user
function follow_user_window(user_name,user_id) {
	
	
	var user_panels = new Array();
	
	for (i in tw_panels) {
		
		if (tw_panels[i].panel_type == "regular") {
			
			user_panels.push(tw_panels[i]);
			
		}
		
	}
	
	if (user_panels.length < 1) {
	
		alert("I'm sorry, but you aren't logged in to any Twitter accounts, so you can't follow that user");
		return;
		
	} 
	
	var notify_html = "";
	
	notify_html += '<h3>Follow @' + user_name + '</h3>';
	
	for (i in user_panels) {
	  
	  if (user_panels[i].twitter_friends == null) {
	    notify_html += '<a href="" onclick="follow_user(\'' + user_panels[i].panel_id + '\',\'' + user_name + '\'); return false;">Follow with ' + user_panels[i].panel_id + ' account</a>';
	  }
	  
	  if ($.inArray(user_id,user_panels[i].twitter_friends) == -1) {
		  notify_html += '<a href="" onclick="follow_user(\'' + user_panels[i].panel_id + '\',\'' + user_name + '\'); return false;">Follow with ' + user_panels[i].panel_id + ' account</a>';
		} else {
		  notify_html += '<a href="" onclick="unfollow_user(\'' + user_panels[i].panel_id + '\',\'' + user_name + '\'); return false;">Unfollow with ' + user_panels[i].panel_id + ' account</a>';
		  
		}
		
		notify_html += '<br/>';
	}
	
	show_notify_window(notify_html);
	
}


function update_widths() {
	
	$('div.panel').width(PANEL_WIDTH);
	
	$('div.the_tweet').width(PANEL_WIDTH - 110)
	
	if (!TABBED_PANELS) {
		$('#panels').width((PANEL_WIDTH + 20) * tw_panels.length)
	}
	
}

function refresh_window() {
	
	var href = window.location.href;
	window.location.href = href;
	
}

//Removes all panels and refreshes the page
function logout() {
	
	if (AIR) {
		
		air_destroy_db();
		refresh_window();
		
	}
	
	if (PROXY) {
		$.post(URL_BASE + 'bin/ajax.php', {
			func: "logout",
		}, function(data) {
			refresh_window();
		},"html");
	}
	
	
}

//Shows the spinning loader icon
function show_loader() {
	
	$('#loader').show();
	
}

//Hides the spinning loader icon
function hide_loader() {
	
	$('#loader').hide();
	
}

function shorten_url(panel_id) {
  
  url_to_shorten = $('#panel_' + panel_id).find('.url_shortener').val();
  
  $.getJSON("http://tr.im/api/trim_url.json?url=" + url_to_shorten + "&callback=?",
  
    function(data) {
      
      if (data.status.result == "ERROR") {
        
        alert("There was an error shortening your URL.  Please check that it is valid.");
        return;
        
      }
      
      shortened_url = data.url;
      
      $('#panel_' + panel_id).find('.url_shortener').val(shortened_url);
      
    }
    
    );
  
}

//Lets the user know how many more characters are available
function length_notify(panel_id) {
	
	var input_box = $('#panel_' + panel_id).find('.tweet_input');
	
	
	var chars_typed = input_box.val().length;
	
	if (ADD_HASHTAG) {
	  
	  chars_typed += $('#panel_' + panel_id).find('input.add_hashtag').val().length;
	  
	}
	
	if (chars_typed >= 140) {
		
		//input_box.val(input_box.val().substring(0,140));
		//chars_typed = max_length;
		
	}
	
	var char_span = '';
	
	if (chars_typed >= 120) {
		char_span = '<span style="color: red;">';
	} else {
		char_span = '<span>';
	}
	
	if (chars_typed == 0) {
	   $('#panel_' + panel_id).find('.length_notify_box').html('');
	} else {
		$('#panel_' + panel_id).find('.length_notify_box').html(char_span + (140 - chars_typed) + " characters left</span>");
  }
	
}

function open_filtered_panel_dialog() {
  
  hide_open_windows();
  
  
  var code = "";
  
  code += "Choose a name for the panel: <br/>"
  code += '<input type="text" id="filtered_panel_name" value="Filtered panel"/><br/>'
  code += "Choose a panel to filter tweets from:<br/>"
  code += '<select id="choose_filter">'
    for (i in tw_panels) {
      if (tw_panels[i].panel_type == "regular") {
        code += '<option value="' + tw_panels[i].panel_id + '">' + tw_panels[i].panel_id + '</option>'
      }
    }
  code += '</select><br/><br/>'
  code += '<input type="button" value="Make filter" onclick="make_new_filtered_panel($(\'#filtered_panel_name\').val(),$(\'#choose_filter\').val()); hide_open_windows()"/>'
  
  show_notify_window(code);
  
  //make_new_filtered_panel('jnpdx');
  

}

function edit_filter(panel_id) {
  
  var code = '<strong>Edit the filter</strong>';
  
  var pan = get_panel_by_id(panel_id);
  
  code += '<div id="filter_edit_form">'
  
  code += 'Panel name: <input type="text" id="filter_panel_name" value="' + pan.user + '"/><br/>'
  
  if (pan.filter_rules.users != undefined) {
    
    code += "Users to display tweets from (comma separated user names):<br/>";
    
    code += '<textarea id="users_filter">'
    
    for (u in pan.filter_rules.users) {
      
      if (pan.filter_rules.users[u] == true) {
        
        code += u + ','
        
      }
      
    }
    
    code += '</textarea>'
    
  }
  
  if (pan.filter_rules.content != undefined) {
    
    code += "Content filters (syntax CONTAINS ___ or DOES_NOT_CONTAIN ___ - comma separated):<br/>"
    
    code += '<textarea id="content_filter">'
    
    for (u in pan.filter_rules.content) {
      
        
        var rule = pan.filter_rules.content[u]
        
        code += rule.rule_type + ' ' + rule.term + ','
        
      
    }
    
    code += '</textarea>'
    
  }
  
  pan += '</div>'
  
  code += '<br/><input type="button" value="Save filter" onclick="save_filter(\'' + panel_id + '\')"/>'
  
  show_notify_window(code);
  
}

function save_filter(panel_id) {
  
  
  var pan = get_panel_by_id(panel_id);
  
  pan.user = $('#filter_panel_name').val();
  
  $('#panel_' + panel_id + ' .panel_name').text(pan.user)
  
  if ($('#users_filter').length > 0) {
    
    pan.filter_rules['users'] = new Object();
    
    var users_list = $('#users_filter').val();
    
    users_list = users_list.split(',');
    
    for (i in users_list) {
      
      //console.log("user " + users_list[i])
      
      if (i == '') { continue; }
      
      pan.filter_rules.users[users_list[i].replace(/^\s+|\s+$/g,"").replace('@','').toLowerCase()] = true
      
    }
    
  }
  
  if ($('#users_filter').length > 0) {
    
    pan.filter_rules['content'] = new Array();
    
    var rules_list = $('#content_filter').val();
    
    rules_list = rules_list.split(',');
    
    for (i in rules_list) {
      
      //console.log("user " + users_list[i])
      
      if (i == '') { continue; }
      
      var words = rules_list[i].split(' ');
      
      if (words.length >= 2) {
        pan.filter_rules.content.push( {
          rule_type: words[0],
          term: rules_list[i].substring(words[0].length + 1)
        } )
      }
      
    }
    
  }
  
  
  save_panel(panel_id,pan)
  
  reload_filter_panel(panel_id);
  
  hide_notify_window()
  
}

function combotweet_alert(msg) {
  show_overlay();
  $('#combotweet_alert_box p').text(msg);
  
  var win_left = $(window).scrollLeft() + 100;
	var win_top = $(window).scrollTop() + 150;
	
	$('#combotweet_alert_box').css('left',win_left);
	$('#combotweet_alert_box').css('top',win_top);
	$('#combotweet_alert_box').css('opacity','1');
  
  $('#combotweet_alert_box').show();
}

function hide_alert() {
  $('#combotweet_alert_box').hide();
  hide_overlay();
}




/***********************************  AIR FUNCTIONS *********************************/

function air_remove_panel(panel_id) {
	
	window.parentSandboxBridge.air_remove_panel();
	
}

function air_save_panels() {
	
	window.parentSandboxBridge.air_save_panels(tw_panels);
	
}

function air_get_session_panels() {
	
	
	var stored_v = window.parentSandboxBridge.air_get_session_panels();
	
	//air.trace(s); // "foo"
	
	//alert("Okay, back here got " + stored_v);
	
	var saved_panels = eval('(' + stored_v + ')');
	
	if (saved_panels == undefined) { return; }
	
	//for(i = 0; i < saved_panels.length; i++) {
	for (i = 0; i < 100; i++) {
		
		//alert(saved_panels['' + i]);
		
		if (saved_panels['' + i] == undefined) { return; }
				
		var pan = saved_panels['' + i];
		
		pan.latest_tweet_id = '-1';
		
		pan.panel_data = new Array();
		
		tw_panels.push(pan);
		
		var pan_html = js_get_panel(pan.panel_id,pan.user,pan.pass,pan.gen_info);
		
		set_up_panel(pan.panel_id, pan_html, pan.user, pan.pass);
		
				
	}
	
}

function air_destroy_db() {
	
			window.parentSandboxBridge.air_destroy_db();

	
}

function air_get_search_tweets(panel_id,search_term, tweet_type,page,since,location,location_search_dist) {
	
	//air_get_search_tweets(panel_id,search_term,page,since_req,location,location_search_dist);
	
	window.parentSandboxBridge.get_search_tweets(panel_id,search_term, tweet_type,page,since,location,location_search_dist,function(p,tweet_type,page,d) {
		parse_get_tweets_data(panel_id,tweet_type,page,d);
		
	});
	
}




/********************************* JS FUNCTIONS ***********************************/

//Used in XS and PROXY situations now
function js_get_panel(panel_id, t_user, t_pass, gen_info) {
	
	if (t_pass == "_search") {
		
		return js_get_search_panel(panel_id,t_user,t_pass);
		
	}
	
	var bg_img = '';
	var bg_col = '';
	
	if (gen_info != null) {
		
		if (gen_info.profile_background_image_url != undefined) {
			
			bg_img = gen_info.profile_background_image_url;
			
		}
		
		if (gen_info.profile_background_color != undefined) {
			
			bg_col = gen_info.profile_background_color;
			
		}
		
	}
	
	var panel_html = "";
	
	panel_html += '<div class="panel twitter_panel" id="panel_' + panel_id + '">';
	panel_html += '<input type="hidden" class="panel_id" value="' + panel_id + '"/><input type="hidden" class="panel_user_name" value="' + t_user + '"/>';
	panel_html += '<input type="hidden" class="panel_background" value="' + bg_img + '" /><input type="hidden" class="panel_background_color" value="' + bg_col + '" />';
	panel_html += '<input type="hidden" class="panel_type" value="regular_panel"/>';	

	panel_html += '<div class="twitter_inputs"><span class="dm_notify_box"></span><textarea class="tweet_input" name="tweet_input" rows="3" cols="30"></textarea><span class="add_hashtag">Add hashtag: </span><input type="text" class="add_hashtag" value=""/>'
	
	panel_html += '<input type="button" class="tweet_submit" onclick="send_tweet(\'' + panel_id + '\')" value="Update Status"/><span class="length_notify_box" id="chars_left_panel_' + panel_id + '"></span><br class="clear_both"/></div>';
	
	
	panel_html += '<div class="url_shortener_container"><input type="button" value="Shorten" class="url_shortener_submit" onclick="shorten_url(\'' + panel_id + '\')"/>URL Shortener: <input class="url_shortener" type="text" id="panel_' + panel_id + '_url_shortener"/><br class="clear_both" /></div>'
	
	
	panel_html += '<div class="last_update"></div>';
	panel_html += '<div class="tweet_type_menu"><br class="clear_both"/><div class="tweet_type_button" id="panel_' + panel_id + '_regular" onclick="get_tweets(\'' + panel_id + '\',\'regular\',1)">Timeline</div><div class="tweet_type_button" id="panel_' + panel_id + '_replies" onclick="get_tweets(\'' + panel_id + '\',\'replies\',1)">@' + t_user + '</div><div class="tweet_type_button" id="panel_' + panel_id + '_direct" onclick="get_tweets(\'' + panel_id + '\',\'direct\',1)">Direct messages</div><br class="clear_both" /></div>';

	panel_html += '<div class="tweets"></div>';
	panel_html += '<div class="more_tweets" onclick="get_more_tweets(\'' + panel_id + '\'); return false;">Load more tweets...</div>';

	panel_html += '</div>';
	
	
	panel_html += '';
	
	return panel_html;
		
}

function js_get_filtered_panel(panel_id) {
  var panel_html = "";
	
	panel_html += '<div class="panel twitter_panel" id="panel_' + panel_id + '">';
	panel_html += '<input type="hidden" class="panel_id" value="' + panel_id + '"/><input type="hidden" class="panel_user_name" value="' + '' + '"/>';
	//panel_html += '<input type="hidden" class="panel_background" value="' + bg_img + '" /><input type="hidden" class="panel_background_color" value="' + bg_col + '" />';
	panel_html += '<input type="hidden" class="panel_type" value="filtered_panel"/>';	

  panel_html += '<input type="button" class="edit_filter" value="Edit filter" onclick="edit_filter(\'' + panel_id + '\')"/>'

	//panel_html += '<div class="twitter_inputs"><span class="dm_notify_box"></span><textarea class="tweet_input" name="tweet_input" rows="3" cols="30"></textarea><span class="add_hashtag">Add hashtag: </span><input type="text" class="add_hashtag" value=""/>'
	
	//panel_html += '<input type="button" class="tweet_submit" onclick="send_tweet(\'' + panel_id + '\')" value="Update Status"/><span class="length_notify_box" id="chars_left_panel_' + panel_id + '"></span><br class="clear_both"/></div>';
	
	
	//panel_html += '<div class="url_shortener_container"><input type="button" value="Shorten" class="url_shortener_submit" onclick="shorten_url(\'' + panel_id + '\')"/>URL Shortener: <input class="url_shortener" type="text" id="panel_' + panel_id + '_url_shortener"/><br class="clear_both" /></div>'
	
	
	//panel_html += '<div class="last_update"></div>';
	//panel_html += '<div class="tweet_type_menu"><br class="clear_both"/><div class="tweet_type_button" id="panel_' + panel_id + '_regular" onclick="get_tweets(\'' + panel_id + '\',\'regular\',1)">Timeline</div><div class="tweet_type_button" id="panel_' + panel_id + '_replies" onclick="get_tweets(\'' + panel_id + '\',\'replies\',1)">Replies</div><div class="tweet_type_button" id="panel_' + panel_id + '_direct" onclick="get_tweets(\'' + panel_id + '\',\'direct\',1)">Direct messages</div><br class="clear_both" /></div>';

	panel_html += '<div class="tweets">'
	panel_html += '<br class="clear_both"/><span class="filter_message">You can click the \'Edit filter\' button to add items to this panel, or you can drag and drop avatars here.  Tweets from the users whose avatars you dropped will be displayed here</span>';
	panel_html += '</div>';
	//panel_html += '<div class="more_tweets" onclick="get_more_tweets(\'' + panel_id + '\'); return false;">Load more tweets...</div>';

	panel_html += '</div>';
	
	
	panel_html += '';
	
	return panel_html;
}

//Used in XS and PROXY situations now
function js_get_search_panel(panel_id,t_user,t_pass) {
	
	var panel_html = "";
	
	
	panel_html += '<div class="panel twitter_panel" id="panel_' + panel_id + '">';
	panel_html += '<input type="hidden" class="panel_id" value="' + panel_id + '"/><input type="hidden" class="panel_user_name" value="' + t_user + '"/><input type="hidden" class="panel_type" value="search_panel"/><input type="hidden" class="panel_background" value="" /><input type="hidden" class="panel_background_color" value="fff" />';
	panel_html += '<div class="twitter_inputs"></div>';
	panel_html += '<div class="tweet_type_menu"></div><div class="tweets"></div>';
	panel_html += '<div class="more_tweets" onclick="get_more_tweets(\'' + panel_id + '\'); return false;">Load more tweets...</div>';
	panel_html += '</div>';
	panel_html += '';
	
	return panel_html;
	
}

function js_get_friends_followers(panel_id) {
  
  var pan = get_panel_by_id(panel_id);
  
  //console.log("Getting friends and followers of" + panel_id + pan.panel_type)
  
  
  if (pan.panel_type != 'regular') {
    return;
  }
  
  
  $.getJSON("http://twitter.com/followers/ids.json?screen_name=" + pan.user + '&callback=?',
  function(data) {
    pan.twitter_followers = data
    save_panel(pan.panel_id,pan)
  });
  
  $.getJSON("http://twitter.com/friends/ids.json?screen_name=" + pan.user + '&callback=?',
  function(data) {
    pan.twitter_friends = data
    save_panel(pan.panel_id,pan)
  });
  
}

function js_get_search_tweets_through_json(panel_id,page) {
  
  show_loader();
  
  var pan = get_panel_by_id(panel_id);
  
  var search_term = escape(pan.user);
  
  var since = pan.latest_tweet_id
  
  var since_req = "&since_id=" + since;
	
	if (since == '-1') {
		
		since_req = '';
		
	}
	
	if (page != 1) {
		
		since_req = '';
		
	}
	
	$.getJSON("http://search.twitter.com/search.json?q=" + search_term + "&page=" + page + since_req + "&callback=?",
          function(data){
            parse_get_tweets_data(panel_id,'regular',page,data);
          });
  
  
}

function js_get_search_tweets(panel_id,tweet_type,page,since,location,location_search_dist) {
		
	var pan = get_panel_by_id(panel_id);
	
	var search_term = pan.user;
	
	var since_req = "&since_id=" + since;
	
	if (since == '-1') {
		
		since_req = '';
		
	}
	
	if (page != 1) {
		
		since_req = '';
		
	}
	
	if (AIR) {
		
		//we have to go through the interface because of XS restrictions
		
		air_get_search_tweets(panel_id,search_term,tweet_type,page,since_req,location,location_search_dist);
		
	} else {
	
		$.ajax( {
			url: 'http://search.twitter.com/search.json',
			dataType: 'json',
			cache: false,
			data: 'q=' + search_term + '&page=' + page + since_req,
			success: function(data) {
				parse_get_tweets_data(panel_id,tweet_type,page,data);
			}
	
		});
	
	}
	
}

function js_get_tweets(panel_id, tweet_type, page, since, location, location_search_dist) {

	//need search code

	var pan = get_panel_by_id(panel_id);
	
	if (tweet_type == 'replies') {
		
		return js_get_search_tweets(panel_id,tweet_type,page,since,location,location_search_dist);
		
	}
	
	if (pan.panel_type == 'search_panel') {
		
		return js_get_search_tweets(panel_id,tweet_type,page,since,location,location_search_dist);
		
	}

	since_req = "&since_id=" + since;
	
	if (since == '-1') {
		
		since_req = '';
		
	}
	
	if (page != 1) {
		
		since_req = '';
		
	}
	
	var auth = pan.auth;
	
	if (tweet_type == 'regular') {
	
		$.ajax( {
			url: 'http://twitter.com/statuses/friends_timeline.json',
			beforeSend: function(req) {
			        req.setRequestHeader('Authorization', auth);
			    }
			,
			dataType: 'json',
			cache: false,
			data: 'page=' + page + since_req,
			success: function(data) {
				parse_get_tweets_data(panel_id,tweet_type,page,data);
			}
		
		});
 	} else if (tweet_type == 'replies') {
	
		$.ajax( {
			url: 'http://twitter.com/statuses/replies.json',
			beforeSend: function(req) {
			        req.setRequestHeader('Authorization', auth);
			    }
			,
			dataType: 'json',
			cache: false,
			data: 'page=' + page + since_req,
			success: function(data) {
				parse_get_tweets_data(panel_id,tweet_type,page,data);
			}
		
		});
	
	} else if (tweet_type == 'direct') {
		
		
		$.ajax( {
			url: 'http://twitter.com/direct_messages.json',
			beforeSend: function(req) {
			        req.setRequestHeader('Authorization', auth);
			    }
			,
			dataType: 'json',
			cache: false,
			data: 'page=' + page + since_req,
			success: function(data) {
				parse_get_tweets_data(panel_id,tweet_type,page,data);
			}
		
		});
		
		
	} else if (tweet_type == 'direct_sent') {
		
		$.ajax( {
			url: 'http://twitter.com/direct_messages/sent.json',
			beforeSend: function(req) {
			        req.setRequestHeader('Authorization', auth);
			    }
			,
			dataType: 'json',
			cache: false,
			data: 'page=' + page + since_req,
			success: function(data) {
				parse_get_tweets_data(panel_id,tweet_type,page,data);
			}
		
		});
		
	}
	
	
}

function js_toggle_favorite(panel_id, tweet_id, new_val) {
	
	var pan = get_panel_by_id(panel_id);
	var auth = pan.auth;
	
	alert('http://twitter.com/favorites/create/' + tweet_id + '.json');
	
	if (new_val) {
		
		$.ajax( {
			url: 'http://twitter.com/favorites/create/' + tweet_id + '.json',
			beforeSend: function(req) {
			        req.setRequestHeader('Authorization', auth);
			    }
			,
			type: "POST",
			dataType: 'json',
			cache: false,
			success: function(data) {
				alert('toggled');
			},
			error: function(XMLHttpRequest, textStatus, errorThrown) {
				alert("Favorites don't work yet in the AIR version - sorry!");
				
			},

		});
		
	} else {
		
		$.ajax( {
			url: 'http://twitter.com/favorites/destroy/' + tweet_id + '.json',
			beforeSend: function(req) {
			        req.setRequestHeader('Authorization', auth);
			    }
			,
			type: "POST",
			dataType: 'json',
			cache: false,
			success: function(data) {

			}

		});
		
	}
	
}

function js_get_twitter_user_info(user) {
	
	var user_info = '';
	
	$.ajax({
		
		async: false,
		url: 'http://twitter.com/users/show/' + user + '.json',
		dataType: 'json',
		type: "GET",
		success: function(data) {
			
			user_info = data;
			
		},
		error: function(XMLHttpRequest, textStatus, errorThrown) {
			
			user_info = null;
			
		},
		});
	
	return user_info;
	
}

function js_get_user_tweets(user,container) {
	
	
	$.ajax({
		
		url: 'http://twitter.com/statuses/user_timeline/' + user + '.json',
		dataType: 'json',
		type: "GET",
		success: function(data) {
			
			display_user_tweets(data,container);
			
		},
		error: function(XMLHttpRequest, textStatus, errorThrown) {
			
			//user_info = null;
			
		},
		});
	
	
}

function js_check_login(user,pass) {
	
	//alert("checking " + user + ',' + pass);	
	
	var verified = false;
	
	var auth = make_base_auth(user,pass);
	
	$.ajax( {
		async: false,
		url: 'http://twitter.com/account/verify_credentials.json',
		beforeSend: function(req) {
		        req.setRequestHeader('Authorization', auth);
		    }
		,
		dataType: 'json',
		cache: false,
		type: "GET",
		success: function(data) {
			verified = true;
			//alert('verified as true');
		},
		error: function(req, textStatus, errorThrown) {
			verified = false;
			//alert('verified as false: ' + textStatus + JSON.stringify(req));
		}, 

	});
	
	return verified;
	
}

function js_send_tweet(panel_id,tweet,reply_to_id,reply_to_name,direct_message) {
		
	var pan = get_panel_by_id(panel_id);	
	
	var auth = pan.auth;
	
	tweet = escape(tweet);
	
	var reply_req = "&in_reply_to_status_id=" + reply_to_id;
	
	if (reply_to_id == 0) {
		
		reply_req = '';
		
	}
	
	if (!direct_message) {
	
		$.ajax( {
			url: 'http://twitter.com/statuses/update.json',
			beforeSend: function(req) {
			        req.setRequestHeader('Authorization', auth);
			    }
			,
			dataType: 'json',
			cache: false,
			data: 'status=' + tweet + reply_req,
			type: "POST",
			success: function(data) {
				get_tweets(panel_id,'regular',1);
			},
			error: function() {
				
				alert("There was an error sending that tweet!");
				
			},
	
		});
		
	} else {
	
		$.ajax( {
			url: 'http://twitter.com/direct_messages/new.json',
			beforeSend: function(req) {
			        req.setRequestHeader('Authorization', auth);
			    }
			,
			dataType: 'json',
			cache: false,
			data: 'user=' + reply_to_name + '&text=' + tweet,
			type: "POST",
			success: function(data) {
				get_tweets(panel_id,'regular',1);
			}
	
		});
		
	}
	
}

function js_get_user_tweets(user,container) {
	
	$.ajax({
		url: 'http://twitter.com/statuses/user_timeline/' + user + '.json?count=10',
		type: "GET",
		success: function(data) {
			
			display_user_tweets(data,container);
			
		},
		dataType: 'json',
		});
	
	
}

function js_follow_user(panel_id,user_name) {
	
	var pan = get_panel_by_id(panel_id);	
	
	var auth = pan.auth;
	
	$.ajax({
		url: 'http://twitter.com/friendships/create/' + user_name + '.json',
		type: "GET",
		success: function(data) {
			
			alert("You are now following @" + user_name);
			
		},
		error: function() {
			
			alert("There was an error while trying to follow @" + user_name);
			
		},
		dataType: 'json',
		});
	
}

function js_get_shizzow_panel(panel_id,s_user,s_pass) {
	
	var panel_html = "";
	
	
	panel_html += '<div class="panel twitter_panel" id="panel_' + panel_id + '">';
	panel_html += '<input type="hidden" class="panel_id" value="' + panel_id + '"/><input type="hidden" class="panel_user_name" value="' + s_user + '"/><input type="hidden" class="panel_type" value="shizzow_panel"/><input type="hidden" class="panel_background" value="" /><input type="hidden" class="panel_background_color" value="fff" />';
	panel_html += '<div class="twitter_inputs"><textarea class="tweet_input" name="tweet_input" rows="3" cols="30"></textarea><br/>Shout from: <select class="shizzow_favorites"></select><br/><input type="button" class="tweet_submit" onclick="send_shout(\'' + panel_id + '\')" value="Update"/><span class="length_notify_box" id="chars_left_panel_' + panel_id + '"></span><br class="clear_both"/></div>';
	panel_html += '<div class="tweet_type_menu"></div><div class="tweets"></div>';
	panel_html += '<div class="more_tweets" onclick="get_more_tweets(\'' + panel_id + '\'); return false;">Load more shouts...</div>';
	panel_html += '</div>';
	panel_html += '';
	
	return panel_html;
	
}

function js_get_facebook_panel(panel_id) {	
	
	var panel_html = "";
	
	
	panel_html += '<div class="panel facebook_panel" id="panel_' + panel_id + '">';
	panel_html += '<input type="hidden" class="panel_id" value="' + panel_id + '"/><input type="hidden" class="panel_type" value="facebook_panel"/><input type="hidden" class="panel_background" value="" /><input type="hidden" class="panel_background_color" value="fff" />';
	//panel_html += '<div class="twitter_inputs"><textarea class="tweet_input" name="tweet_input" rows="3" cols="30"></textarea><br/><input type="button" class="tweet_submit" onclick="update_facebook_status(\'' + panel_id + '\')" value="Update Status"/><span class="length_notify_box" id="chars_left_panel_' + panel_id + '"></span><br class="clear_both"/></div>';
	panel_html += '<div class="tweet_type_menu"></div><div class="tweets"></div>';
	//panel_html += '<div class="more_tweets" onclick="get_more_tweets(\'' + panel_id + '\'); return false;">Load more shouts...</div>';
	panel_html += '</div>';
	panel_html += '';
	
	return panel_html;
	
}




/******************************** PROXY FUNCTIONS ********************************/

function proxy_get_panel(id,t_user,t_pass,info) {
	
	var panel_code = '';
	
	$.post(URL_BASE + 'bin/ajax.php', {
		func: "get_panel",
		panel_id: id,
		user: t_user,
		pass: t_pass,
		async: false,
	}, function(data,textStatus) {

		panel_code = data;
		
	},
	"html");
	
	return panel_code;
	
}

function proxy_get_search_panel(id,t_user,t_pass,info) {
	
	$.post(URL_BASE + 'bin/ajax.php', {
		func: "get_search_panel",
		panel_id: id,
		search_term: t_user,
	}, function(data,textStatus) {
	
	},"html");
	
	return '';
	
}

function proxy_get_session_panels() {
	
	
	show_loader();
	
	$.post(URL_BASE + 'bin/ajax.php', {
		func: "get_session_panels",
	}, function(data) {
		
		//alert(JSON.stringify(data))
		
			
		//$('#panels').append(data);
		
		//$('.twitter_panel').hide();  //this hides all of them - should only hide front?	
		
		if (TABBED_PANELS) {
			$('#panels').width(PANEL_WIDTH + 20);
			$('#header_nav_buttons').show()	
		}
		
		if (data.panels_data == '') {
		  
		  //alert("panels_data is empty " + data.panels_data)
		  
		  //window.OLD_PANELS_DATA = JSON.parse(data.panels_data.replace('\"','"'));
		  //return;
		  
		}
		
		if (data.panels_data.length > 0) {
		  var old_panels_data = JSON.parse(data.panels_data.replace('\"','"'));
		
		  //alert(JSON.stringify(old_panels_data))
		
  		for (i in old_panels_data) {
		  
  		  var cur_panel = old_panels_data[i];
		  
  		  var pan_user = cur_panel.user;
  		  var gen_info = cur_panel.gen_info;
  		  var panel_id = cur_panel.panel_id;
  		  var pan_type = cur_panel.panel_type;
		  
  		  var new_panel = new Data_Panel(cur_panel.panel_id,cur_panel.panel_type,cur_panel.user,cur_panel.pass,cur_panel.gen_info)
  		  new_panel.derivative_panels = cur_panel.derivative_panels;
  		  new_panel.filter_rules = cur_panel.filter_rules;
  		  new_panel.parent_panel = cur_panel.parent_panel;
		  
  		  tw_panels[i] = new_panel;
		  
		    if (pan_type == 'search') { pan_type = "search_panel" }
		  
  		  if (pan_type == 'regular') {
  			  var pan_data = js_get_panel(panel_id, pan_user, '', gen_info);
  			} else if (pan_type == 'search_panel') {
  			  var pan_data = js_get_search_panel(panel_id,pan_user,"_search");
  			} else if (pan_type == 'shizzow_panel') {
  			  var pan_data = js_get_shizzow_panel(panel_id,pan_user,'')
  			  //alert("shizzow panel!");
  			} else if (pan_type == 'filtered_panel') {
  			  var pan_data = js_get_filtered_panel(panel_id)
  			}
			
  			set_up_panel(panel_id, pan_data, pan_user, '')
			
  			if (pan_type == "shizzow_panel") {
  			  if (PROXY) {

        		proxy_get_shizzow_favorites(panel_id);

        	}
  			}
		  
  		}
		
		
  		make_droppables();
		
  		hide_loader();

    	$.scrollTo( { top:0, left:0 });
		
  		if (old_panels_data.length != 0) {
  		  return;
  		}
		
	  }
				
		for (i in data.panels) {
		  
		  var cur_panel = data.panels[i];
		  var panel_id = cur_panel.panel_id;
		  var pan_type = cur_panel.panel_type;
		  var pan_user = cur_panel.panel_user;
		  var gen_info = cur_panel.gen_info;
		  tw_panels[tw_panels.length] = new Data_Panel(panel_id,pan_type,pan_user,'',null);
		  
		  if (pan_type == 'regular') {
			  var pan_data = js_get_panel(panel_id, pan_user, '', gen_info);
			} else if (pan_type == 'search') {
			  var pan_data = js_get_search_panel(panel_id,pan_user,"_search");
			} else if (pan_type == 'shizzow_panel') {
			  var pan_data = js_get_shizzow_panel(panel_id,pan_user,'')
			  //alert("shizzow panel!");
			}
			
			set_up_panel(panel_id, pan_data, pan_user, '')
			
			if (pan_type == "shizzow_panel") {
			  if (PROXY) {

      		proxy_get_shizzow_favorites(panel_id);

      	}
			}
			
		}
		
		
		hide_loader();
		
	},
	"json");
	
	
}

function proxy_get_tweets(panel_id,type,page_num,latest_tweet,user_loc,dist) {
	
	$.post(URL_BASE + 'bin/ajax.php', {
		func: "get_tweets",
		panel: panel_id,
		tweet_type: type,
		page: page_num,
		since: latest_tweet,
		location: user_loc,
		location_search_dist: dist,
	}, function(data) {
		parse_get_tweets_data(panel_id,type,page_num,data);
	},
	"json");
	
}

function proxy_remove_panel(panel_id) {
	
	$.post(URL_BASE + 'bin/ajax.php', {
		func: "remove_panel",
		panel: panel_id,
	}, function(data) {
	
	},
	'json');
	
}

function proxy_send_tweet(panel_id,tweet,reply_to_id,t_reply_to_name,dm) {
	
	var pan = get_panel_by_id(panel_id);
	
	var tweet_type_to_display = 'regular';
	
	if (pan.tweet_type == "direct") {
		
		tweet_type_to_display = "direct_sent";
		
	}
	
	$.post(URL_BASE + 'bin/ajax.php', {
		func: "send_tweet",
		panel: panel_id,
		tweet_data: tweet,
		reply_to: reply_to_id,
		reply_to_name: t_reply_to_name,
		direct_message: dm,
	}, function(data) {
		get_tweets(panel_id,tweet_type_to_display,1);
	},
	'json');
	
}

function proxy_toggle_favorite(panel_id,t_id,new_val) {
	
	$.post(URL_BASE + 'bin/ajax.php', {
		func: "toggle_favorite",
		panel: panel_id,
		tweet_id: t_id,
		favorite: new_val,
	}, function(data) {
		
	},
	'json');
	
}

function proxy_get_twitter_user_info(t_user) {
	
	var user_info = '';
	
	$.ajax({
		async: false,
		url: URL_BASE + 'bin/ajax.php',
		type: "POST",
		data: "func=get_twitter_user_info&user=" + t_user,
		success: function(data) {
			
			user_info = data;
			
		},
		dataType: 'json',
		
		});
	
	return user_info;
	
}

function proxy_check_login(t_user,t_pass) {
	
	var good_login = false;
	
	$.ajax({
		async: false,
		url: URL_BASE + 'bin/ajax.php',
		type: "POST",
		data: "func=check_login&user=" + t_user + '&pass=' + t_pass,
		success: function(data) {
			
			good_login = data;
			
		},
		dataType: 'json',
		
		});
	
	return good_login;
	
}

function proxy_get_user_tweets(user,container) {
	
	
	$.ajax({
		url: URL_BASE + 'bin/ajax.php',
		type: "POST",
		data: "func=get_user_tweets&user=" + user,
		success: function(data) {
			
			display_user_tweets(data,container);
			
		},
		dataType: 'json',
		});
	
	
}

function proxy_follow_user(panel_id,user_name) {
	
	$.post(URL_BASE + 'bin/ajax.php', {
		func: "follow_user",
		panel: panel_id,
		user: user_name,
	}, function(data) {
		alert("You are now following @" + user_name);
	},
	'json');
	
}

function proxy_unfollow_user(panel_id,user_name) {
	
	$.post(URL_BASE + 'bin/ajax.php', {
		func: "unfollow_user",
		panel: panel_id,
		user: user_name,
	}, function(data) {
		alert("You have unfollowed @" + user_name);
	},
	'json');
	
}


/** PROXY For Shizzow **/
function proxy_get_shizzow_panel(id,s_user,s_pass) {
	//alert('making the call');

	$.post(URL_BASE + 'bin/ajax.php', {
		func: "get_shizzow_panel",
		panel_id: id,
		user: s_user,
		pass: s_pass,
	}, function(data,textStatus) {
	
	},"html");
	
	return '';
	
}

function proxy_get_shizzow_favorites(panel_id) {
	
	$.post(URL_BASE + 'bin/ajax.php', {
		func: "get_shizzow_favorites",
		panel: panel_id,
	}, function(data,textStatus) {
		parse_shizzow_favorites(panel_id,data);
	},"json");
	
	return '';
	
}

function proxy_send_shout(panel_id,shout,location) {
	show_loader();
	
	$.post(URL_BASE + 'bin/ajax.php', {
		func: "proxy_send_shout",
		panel: panel_id,
		shout_text: shout,
		loc: location,
	}, function(data,textStatus) {
		alert(data.results.message);
		hide_loader();
	},"json");
	
	return '';
	
}

function proxy_save_state(openid,show_alert) {
  show_loader();
  
  //panels_data = eval(uneval(tw_panels));
  
  panels_data = JSON.parse(JSON.stringify(tw_panels))
  
  for (i in panels_data) {
    panels_data[i].panel_data = '';
    panels_data[i].twitter_friends = null;
    panels_data[i].twitter_followers = null;
    panels_data[i].auth = null;
  }
  
  $.post(URL_BASE + 'bin/ajax.php', {
      func: "save_state",
      panels_data: JSON.stringify(panels_data),
    }, function (data,textStatus) {
    hide_loader();
    if (show_alert) { alert("Your open panels have been saved."); }
  },'json');
  
  return '';
  
  
}


function proxy_load_state(openid) {
  show_loader();
  
  $.post(URL_BASE + 'bin/ajax.php', {
      func: "load_state",
    }, function (data,textStatus) {
      if (data == "NO_SAVED_STATE") {
        
        alert("There was no saved state to load!");
        
      } else {
        
        var href = window.location.href;
      	window.location.href = href;
        
      }
  },'json');
  
  return '';
  
}




/******* FROM http://delete.me.uk/2005/03/iso8601.html ******/

//Used to allow Date to parse ISO 8601
//Shizzow uses this format for their dates
//Doesn't work properly with Time zones, so isn't currently used
Date.prototype.setISO8601 = function (string) {
    var regexp = "([0-9]{4})(-([0-9]{2})(-([0-9]{2})" +
        "(T([0-9]{2}):([0-9]{2})(:([0-9]{2})(\.([0-9]+))?)?" +
        "(Z|(([-+])([0-9]{2}):([0-9]{2})))?)?)?)?";
    var d = string.match(new RegExp(regexp));

    var offset = 0;
    var date = new Date(d[1], 0, 1);

    if (d[3]) { date.setMonth(d[3] - 1); }
    if (d[5]) { date.setDate(d[5]); }
    if (d[7]) { date.setHours(d[7]); }
    if (d[8]) { date.setMinutes(d[8]); }
    if (d[10]) { date.setSeconds(d[10]); }
    if (d[12]) { date.setMilliseconds(Number("0." + d[12]) * 1000); }
    if (d[14]) {
        offset = (Number(d[16]) * 60) + Number(d[17]);
        offset *= ((d[15] == '-') ? 1 : -1);
    }

    offset -= date.getTimezoneOffset();
    time = (Number(date) + (offset * 60 * 1000));
    this.setTime(Number(time));
}




//LIBRARIES



/********************************** HTTP AUTH stuff **************************************************/

function make_base_auth(user, password) {
  var tok = user + ':' + password;
  var hash = Base64.encode(tok);
  return "Basic " + hash;
}

var Base64 = {

    // private property
    _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

    // public method for encoding
    encode : function (input) {
        var output = "";
        var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
        var i = 0;

        input = Base64._utf8_encode(input);

        while (i < input.length) {

            chr1 = input.charCodeAt(i++);
            chr2 = input.charCodeAt(i++);
            chr3 = input.charCodeAt(i++);

            enc1 = chr1 >> 2;
            enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
            enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
            enc4 = chr3 & 63;

            if (isNaN(chr2)) {
                enc3 = enc4 = 64;
            } else if (isNaN(chr3)) {
                enc4 = 64;
            }

            output = output +
            this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
            this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);

        }

        return output;
    },

    // public method for decoding
    decode : function (input) {
        var output = "";
        var chr1, chr2, chr3;
        var enc1, enc2, enc3, enc4;
        var i = 0;

        input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

        while (i < input.length) {

            enc1 = this._keyStr.indexOf(input.charAt(i++));
            enc2 = this._keyStr.indexOf(input.charAt(i++));
            enc3 = this._keyStr.indexOf(input.charAt(i++));
            enc4 = this._keyStr.indexOf(input.charAt(i++));

            chr1 = (enc1 << 2) | (enc2 >> 4);
            chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
            chr3 = ((enc3 & 3) << 6) | enc4;

            output = output + String.fromCharCode(chr1);

            if (enc3 != 64) {
                output = output + String.fromCharCode(chr2);
            }
            if (enc4 != 64) {
                output = output + String.fromCharCode(chr3);
            }

        }

        output = Base64._utf8_decode(output);

        return output;

    },

    // private method for UTF-8 encoding
    _utf8_encode : function (string) {
        string = string.replace(/\r\n/g,"\n");
        var utftext = "";

        for (var n = 0; n < string.length; n++) {

            var c = string.charCodeAt(n);

            if (c < 128) {
                utftext += String.fromCharCode(c);
            }
            else if((c > 127) && (c < 2048)) {
                utftext += String.fromCharCode((c >> 6) | 192);
                utftext += String.fromCharCode((c & 63) | 128);
            }
            else {
                utftext += String.fromCharCode((c >> 12) | 224);
                utftext += String.fromCharCode(((c >> 6) & 63) | 128);
                utftext += String.fromCharCode((c & 63) | 128);
            }

        }

        return utftext;
    },

    // private method for UTF-8 decoding
    _utf8_decode : function (utftext) {
        var string = "";
        var i = 0;
        var c = c1 = c2 = 0;

        while ( i < utftext.length ) {

            c = utftext.charCodeAt(i);

            if (c < 128) {
                string += String.fromCharCode(c);
                i++;
            }
            else if((c > 191) && (c < 224)) {
                c2 = utftext.charCodeAt(i+1);
                string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
                i += 2;
            }
            else {
                c2 = utftext.charCodeAt(i+1);
                c3 = utftext.charCodeAt(i+2);
                string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
                i += 3;
            }

        }

        return string;
    }

}




/**
 * Cookie plugin
 *
 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 */

/**
 * Create a cookie with the given name and value and other optional parameters.
 *
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Set the value of a cookie.
 * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
 * @desc Create a cookie with all available options.
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Create a session cookie.
 * @example $.cookie('the_cookie', null);
 * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
 *       used when the cookie was set.
 *
 * @param String name The name of the cookie.
 * @param String value The value of the cookie.
 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
 *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
 *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
 *                             when the the browser exits.
 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
 *                        require a secure protocol (like HTTPS).
 * @type undefined
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */

/**
 * Get the value of a cookie with the given name.
 *
 * @example $.cookie('the_cookie');
 * @desc Get the value of a cookie.
 *
 * @param String name The name of the cookie.
 * @return The value of the cookie.
 * @type String
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */
jQuery.cookie = function(name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
        options = options || {};
        if (value === null) {
            value = '';
            options.expires = -1;
        }
        var expires = '';
        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
            var date;
            if (typeof options.expires == 'number') {
                date = new Date();
                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
            } else {
                date = options.expires;
            }
            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
        }
        // CAUTION: Needed to parenthesize options.path and options.domain
        // in the following expressions, otherwise they evaluate to undefined
        // in the packed version for some reason...
        var path = options.path ? '; path=' + (options.path) : '';
        var domain = options.domain ? '; domain=' + (options.domain) : '';
        var secure = options.secure ? '; secure' : '';
        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    } else { // only name given, get cookie
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
};




/* Copyright (c) 2007 Paul Bakaus (paul.bakaus@googlemail.com) and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate: 2007-12-20 08:43:48 -0600 (Thu, 20 Dec 2007) $
 * $Rev: 4257 $
 *
 * Version: 1.2
 *
 * Requires: jQuery 1.2+
 */
eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(5($){$.19={P:\'1.2\'};$.u([\'j\',\'w\'],5(i,d){$.q[\'O\'+d]=5(){p(!3[0])6;g a=d==\'j\'?\'s\':\'m\',e=d==\'j\'?\'D\':\'C\';6 3.B(\':y\')?3[0][\'L\'+d]:4(3,d.x())+4(3,\'n\'+a)+4(3,\'n\'+e)};$.q[\'I\'+d]=5(b){p(!3[0])6;g c=d==\'j\'?\'s\':\'m\',e=d==\'j\'?\'D\':\'C\';b=$.F({t:Z},b||{});g a=3.B(\':y\')?3[0][\'8\'+d]:4(3,d.x())+4(3,\'E\'+c+\'w\')+4(3,\'E\'+e+\'w\')+4(3,\'n\'+c)+4(3,\'n\'+e);6 a+(b.t?(4(3,\'t\'+c)+4(3,\'t\'+e)):0)}});$.u([\'m\',\'s\'],5(i,b){$.q[\'l\'+b]=5(a){p(!3[0])6;6 a!=W?3.u(5(){3==h||3==r?h.V(b==\'m\'?a:$(h)[\'U\'](),b==\'s\'?a:$(h)[\'T\']()):3[\'l\'+b]=a}):3[0]==h||3[0]==r?S[(b==\'m\'?\'R\':\'Q\')]||$.N&&r.M[\'l\'+b]||r.A[\'l\'+b]:3[0][\'l\'+b]}});$.q.F({z:5(){g a=0,f=0,o=3[0],8,9,7,v;p(o){7=3.7();8=3.8();9=7.8();8.f-=4(o,\'K\');8.k-=4(o,\'J\');9.f+=4(7,\'H\');9.k+=4(7,\'Y\');v={f:8.f-9.f,k:8.k-9.k}}6 v},7:5(){g a=3[0].7;G(a&&(!/^A|10$/i.16(a.15)&&$.14(a,\'z\')==\'13\'))a=a.7;6 $(a)}});5 4(a,b){6 12($.11(a.17?a[0]:a,b,18))||0}})(X);',62,72,'|||this|num|function|return|offsetParent|offset|parentOffset|||||borr|top|var|window||Height|left|scroll|Left|padding|elem|if|fn|document|Top|margin|each|results|Width|toLowerCase|visible|position|body|is|Right|Bottom|border|extend|while|borderTopWidth|outer|marginLeft|marginTop|client|documentElement|boxModel|inner|version|pageYOffset|pageXOffset|self|scrollTop|scrollLeft|scrollTo|undefined|jQuery|borderLeftWidth|false|html|curCSS|parseInt|static|css|tagName|test|jquery|true|dimensions'.split('|'),0,{}))




/**
 * jQuery.ScrollTo - Easy element scrolling using jQuery.
 * Copyright (c) 2007-2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 9/11/2008
 * @author Ariel Flesler
 * @version 1.4
 *
 * http://flesler.blogspot.com/2007/10/jqueryscrollto.html
 */
;(function(h){var m=h.scrollTo=function(b,c,g){h(window).scrollTo(b,c,g)};m.defaults={axis:'y',duration:1};m.window=function(b){return h(window).scrollable()};h.fn.scrollable=function(){return this.map(function(){var b=this.parentWindow||this.defaultView,c=this.nodeName=='#document'?b.frameElement||b:this,g=c.contentDocument||(c.contentWindow||c).document,i=c.setInterval;return c.nodeName=='IFRAME'||i&&h.browser.safari?g.body:i?g.documentElement:this})};h.fn.scrollTo=function(r,j,a){if(typeof j=='object'){a=j;j=0}if(typeof a=='function')a={onAfter:a};a=h.extend({},m.defaults,a);j=j||a.speed||a.duration;a.queue=a.queue&&a.axis.length>1;if(a.queue)j/=2;a.offset=n(a.offset);a.over=n(a.over);return this.scrollable().each(function(){var k=this,o=h(k),d=r,l,e={},p=o.is('html,body');switch(typeof d){case'number':case'string':if(/^([+-]=)?\d+(px)?$/.test(d)){d=n(d);break}d=h(d,this);case'object':if(d.is||d.style)l=(d=h(d)).offset()}h.each(a.axis.split(''),function(b,c){var g=c=='x'?'Left':'Top',i=g.toLowerCase(),f='scroll'+g,s=k[f],t=c=='x'?'Width':'Height',v=t.toLowerCase();if(l){e[f]=l[i]+(p?0:s-o.offset()[i]);if(a.margin){e[f]-=parseInt(d.css('margin'+g))||0;e[f]-=parseInt(d.css('border'+g+'Width'))||0}e[f]+=a.offset[i]||0;if(a.over[i])e[f]+=d[v]()*a.over[i]}else e[f]=d[i];if(/^\d+$/.test(e[f]))e[f]=e[f]<=0?0:Math.min(e[f],u(t));if(!b&&a.queue){if(s!=e[f])q(a.onAfterFirst);delete e[f]}});q(a.onAfter);function q(b){o.animate(e,j,a.easing,b&&function(){b.call(this,r,a)})};function u(b){var c='scroll'+b,g=k.ownerDocument;return p?Math.max(g.documentElement[c],g.body[c]):k[c]}}).end()};function n(b){return typeof b=='object'?b:{top:b,left:b}}})(jQuery);




/**
 * http://www.openjs.com/scripts/events/keyboard_shortcuts/
 * Version : 2.01.B
 * By Binny V A
 * License : BSD
 */
shortcut = {
	'all_shortcuts':{},//All the shortcuts are stored in this array
	'add': function(shortcut_combination,callback,opt) {
		//Provide a set of default options
		var default_options = {
			'type':'keydown',
			'propagate':false,
			'disable_in_input':true,
			'target':document,
			'keycode':false
		}
		if(!opt) opt = default_options;
		else {
			for(var dfo in default_options) {
				if(typeof opt[dfo] == 'undefined') opt[dfo] = default_options[dfo];
			}
		}

		var ele = opt.target;
		if(typeof opt.target == 'string') ele = document.getElementById(opt.target);
		var ths = this;
		shortcut_combination = shortcut_combination.toLowerCase();

		//The function to be called at keypress
		var func = function(e) {
			e = e || window.event;
			
			if(opt['disable_in_input']) { //Don't enable shortcut keys in Input, Textarea fields
				var element;
				if(e.target) element=e.target;
				else if(e.srcElement) element=e.srcElement;
				if(element.nodeType==3) element=element.parentNode;

				if(element.tagName == 'INPUT' || element.tagName == 'TEXTAREA') return;
			}
	
			//Find Which key is pressed
			if (e.keyCode) code = e.keyCode;
			else if (e.which) code = e.which;
			var character = String.fromCharCode(code);
			
			if(code == 188) character=","; //If the user presses , when the type is onkeydown
			if(code == 190) character="."; //If the user presses , when the type is onkeydown

			var keys = shortcut_combination.split("+");
			//Key Pressed - counts the number of valid keypresses - if it is same as the number of keys, the shortcut function is invoked
			var kp = 0;
			
			//Work around for stupid Shift key bug created by using lowercase - as a result the shift+num combination was broken
			var shift_nums = {
				"`":"~",
				"1":"!",
				"2":"@",
				"3":"#",
				"4":"$",
				"5":"%",
				"6":"^",
				"7":"&",
				"8":"*",
				"9":"(",
				"0":")",
				"-":"_",
				"=":"+",
				";":":",
				"'":"\"",
				",":"<",
				".":">",
				"/":"?",
				"\\":"|"
			}
			//Special Keys - and their codes
			var special_keys = {
				'esc':27,
				'escape':27,
				'tab':9,
				'space':32,
				'return':13,
				'enter':13,
				'backspace':8,
	
				'scrolllock':145,
				'scroll_lock':145,
				'scroll':145,
				'capslock':20,
				'caps_lock':20,
				'caps':20,
				'numlock':144,
				'num_lock':144,
				'num':144,
				
				'pause':19,
				'break':19,
				
				'insert':45,
				'home':36,
				'delete':46,
				'end':35,
				
				'pageup':33,
				'page_up':33,
				'pu':33,
	
				'pagedown':34,
				'page_down':34,
				'pd':34,
	
				'left':37,
				'up':38,
				'right':39,
				'down':40,
	
				'f1':112,
				'f2':113,
				'f3':114,
				'f4':115,
				'f5':116,
				'f6':117,
				'f7':118,
				'f8':119,
				'f9':120,
				'f10':121,
				'f11':122,
				'f12':123
			}
	
			var modifiers = { 
				shift: { wanted:false, pressed:false},
				ctrl : { wanted:false, pressed:false},
				alt  : { wanted:false, pressed:false},
				meta : { wanted:false, pressed:false}	//Meta is Mac specific
			};
                        
			if(e.ctrlKey)	modifiers.ctrl.pressed = true;
			if(e.shiftKey)	modifiers.shift.pressed = true;
			if(e.altKey)	modifiers.alt.pressed = true;
			if(e.metaKey)   modifiers.meta.pressed = true;
                        
			for(var i=0; k=keys[i],i<keys.length; i++) {
				//Modifiers
				if(k == 'ctrl' || k == 'control') {
					kp++;
					modifiers.ctrl.wanted = true;

				} else if(k == 'shift') {
					kp++;
					modifiers.shift.wanted = true;

				} else if(k == 'alt') {
					kp++;
					modifiers.alt.wanted = true;
				} else if(k == 'meta') {
					kp++;
					modifiers.meta.wanted = true;
				} else if(k.length > 1) { //If it is a special key
					if(special_keys[k] == code) kp++;
					
				} else if(opt['keycode']) {
					if(opt['keycode'] == code) kp++;

				} else { //The special keys did not match
					if(character == k) kp++;
					else {
						if(shift_nums[character] && e.shiftKey) { //Stupid Shift key bug created by using lowercase
							character = shift_nums[character]; 
							if(character == k) kp++;
						}
					}
				}
			}
			
			if(kp == keys.length && 
						modifiers.ctrl.pressed == modifiers.ctrl.wanted &&
						modifiers.shift.pressed == modifiers.shift.wanted &&
						modifiers.alt.pressed == modifiers.alt.wanted &&
						modifiers.meta.pressed == modifiers.meta.wanted) {
				callback(e);
	
				if(!opt['propagate']) { //Stop the event
					//e.cancelBubble is supported by IE - this will kill the bubbling process.
					e.cancelBubble = true;
					e.returnValue = false;
	
					//e.stopPropagation works in Firefox.
					if (e.stopPropagation) {
						e.stopPropagation();
						e.preventDefault();
					}
					return false;
				}
			}
		}
		this.all_shortcuts[shortcut_combination] = {
			'callback':func, 
			'target':ele, 
			'event': opt['type']
		};
		//Attach the function with the event
		if(ele.addEventListener) ele.addEventListener(opt['type'], func, false);
		else if(ele.attachEvent) ele.attachEvent('on'+opt['type'], func);
		else ele['on'+opt['type']] = func;
	},

	//Remove the shortcut - just specify the shortcut and I will remove the binding
	'remove':function(shortcut_combination) {
		shortcut_combination = shortcut_combination.toLowerCase();
		var binding = this.all_shortcuts[shortcut_combination];
		delete(this.all_shortcuts[shortcut_combination])
		if(!binding) return;
		var type = binding['event'];
		var ele = binding['target'];
		var callback = binding['callback'];

		if(ele.detachEvent) ele.detachEvent('on'+type, callback);
		else if(ele.removeEventListener) ele.removeEventListener(type, callback, false);
		else ele['on'+type] = false;
	}
}




