
jQuery.colr = function() {

	this.n_images = 3;
	this.images = jQuery.colr.initial_images;
	this.hovered_image = null;

	this.init = function() {

		$j('#tabs').tabs( );
		$j('#tabs').bind( "tabsselect", {self:this}, this.tabs_select );
		this.init_images();

		$j('#get_scheme_from_image_button').bind( 'click', {'self':this}, this.get_scheme_from_image );
		$j('#load_random_flickr_image_button').bind( 'click', {'self':this}, this.load_random_flickr_image );
		$j('#image_url').bind( 'keypress', {'self':this}, this.load_image_from_url_keypress );
		$j('#load_your_own_button').bind( 'click', {'self':this}, this.load_your_own );


		var f = function(evt) {
			if (evt.keyCode != 13) return;
			evt.data.self.collage_search( evt );
		};

		$j('#collage_search_query').bind( 'keypress', {'self':this}, f );
		$j('#collage_search_button').bind( 'click', {'self':this}, this.collage_search );

	}

	this.init_images = function() {
		$j('.image_carousel').empty();
		for (var i=0;i<this.n_images;i++) {
			var image = this.images[i];
			image.index = i;
			image.carousel_index = i;
			this.display_image( this.images[i] );
		}

	}

	this.display_new_image = function() {
		var c = getCoords( $j('.image_carousel li:first img') );
		$j('.image_carousel li:first').css({'width':c.w + 'px'});
		$j('.image_carousel li:first').empty();

		var self = this;

		var f = function ( ) {
			self.init_images.apply( self, arguments );
		}

		$j('.image_carousel li:first').animate({'width':'0px'}, 'fast', 'linear', f);

	}


	this.display_image = function ( image ) {
		var image_html = tmpl( 'carousel_image_tmpl', image );
		$j('.image_carousel').append(image_html);
		
		$j('#carousel_image_' + image.carousel_index + ' img').bind( 'mouseover', {'image_index':image.index, 'self':this}, this.set_hover_image );
	}

	this.set_hover_image = function( evt ) {
		var image_index = evt.data.image_index;
		var self = evt.data.self;

		image = self.images[image_index];
		self.hovered_image = image;
		self.hovered_image_index = image_index;

		$j('.image_action_buttons').css( 'visibility', 'visible' );
		self.align_action_button( image );
		self.show_image_pixels( image );
	}

	this.align_action_button = function( image ) {

		var image_el = $j("#carousel_image_"+image.carousel_index + ' img');
		var c1= getCoords( image_el );
		var c2= getCoords( $j('.image_action_buttons') );
		var target_x = c1.x + (c1.w - c2.w) / 2;
		$j('.image_action_buttons').animate({'left': target_x+'px'},{'queue':false});

	}

	this.show_image_pixels = function( image ) {

		var image_el = $j("#carousel_image_"+image.carousel_index + ' img');

		var zoom_width = 10;
		var zoom_width2 = zoom_width * 2;

		p = getCoords(image_el);

		for (var i in image.image_pixels) {
			if (!image_pixel_els[i]) {
				image_pixel_els[i] = document.createElement('div');
				image_pixel_els[i].id = 'image_pixel_'+i;
				image_pixel_els[i].className = 'pixel_zoom';
				image_pixel_els[i].style.width = (zoom_width2)+'px';
				image_pixel_els[i].style.height = (zoom_width2)+'px';

				$j('#image_pixels_surround').append(image_pixel_els[i]);
			}

			$j(image_pixel_els[i]).unbind();

			var pixel = image.image_pixels[i];
			/*
			$j(pixel).css({
				'background-color': '#'+pixel.color,
				'top':(p.y + pixel.y - zoom_width) + 'px',
				'left':(p.x + pixel.x - zoom_width) + 'px'
				} );
			*/

			// direct calls for improved performance 
			image_pixel_els[i].style.backgroundColor = '#'+pixel.color;
			image_pixel_els[i].style.left = (p.x + pixel.x - (zoom_width))+'px';
			image_pixel_els[i].style.top = (p.y + pixel.y - (zoom_width))+'px';

			$j(image_pixel_els[i]).bind('mouseup', image_onclick);
		}

		$j('#image_pixels_surround').addClass('show_blocks');

	}

	this.tabs_select = function (evt) {
		var self = evt.data.self;

		self.hide_image_pixels();
        $j('#edit_color_dialog').dialog('destroy');
        $j('#edit_scheme_dialog').dialog('destroy');
	}

	this.hide_image_pixels = function (evt) {
		$j('#image_pixels_surround').removeClass('show_blocks');
	}



	this.get_scheme_from_image = function( evt ) {

		var z = $j.topZIndex('.ui-dialog');

		var num_colors = rand(4)+2;
		clear_edit_scheme();

		var self = evt.data.self;

		var image_pixels = self.hovered_image.image_pixels;

		if (!image_pixels || image_pixels.length == 0)
			return;

		var chosen_pixels = [];
		for (var i=0;i<num_colors;i++) {
			var pixel_index = rand(image_pixels.length-1)
			p = image_pixels[pixel_index];

			if (!array_contains(edit_scheme.colors, p.color)) {
				edit_scheme.colors.push(p.color);
				chosen_pixels.push(pixel_index);
			}
		}

		var c1 = getCoords( $j('#carousel_image_' + self.hovered_image_index + ' img') );
		var dialog_position = [c1.x, c1.y +c1.h];
		
		evt.data.props = { 'skip_animation':true, 'delay':300, 'dialog_position':dialog_position };

		do_edit_scheme( evt );

		for (var i=0;i<chosen_pixels.length;i++) {
			var pixel_index = chosen_pixels[i];
			var color = image_pixels[pixel_index]['color'];
			var el1 = $j('#image_pixel_'+pixel_index);
			var el2 = $j('#add_color_to_scheme');

			var ghost_el = $j('#ghost_'+i);
			var c1 = getCoords($j(el1));
			var c2 = getCoords($j(el2));

			$j(ghost_el).css({'zIndex':z+1,'left':c1.x+'px','top':c1.y+'px', 'width':c1.w+'px','height':c1.h+'px','background-color':'#'+color}).show();
		
			$j(ghost_el).animate( {'left':(c2.x + c1.w*i)+'px','top':c2.y+'px'}, 300, 'linear', partial(off_ghost,i) );

		}

		setTimeout(sync_edit_scheme,2000);
	  
		evt.preventDefault();
		evt.stopPropagation();
	}

	this.load_random_flickr_image = function( evt ) {

		var self = evt.data.self;

		colr_throbber.throb( $j('#load_random_flickr_image_button'), 'Fetching Image...');
		var url = base_url+'/random_flickr/?rand='+randomString(4);

		var successCallback = function(jsondata, statusText) {
			try {

				if (jsondata && jsondata.success == true) {
					colr_throbber.throb($j('#load_random_flickr_image_button'), 'Extracting Colors...');
					var image_url = jsondata.url;
					var image_title = jsondata.title;
					if (image_url.match(/\./))
						image_url = 'http://'+image_url.replace(/http:\/\//,'');
					self.load_image_from_url(image_url);

				} else {
					$j.colr.show_message('Error loading flickr image');
					colr_throbber.unthrob( $j('#load_random_flickr_image_button'));
				}

			} catch (e) {info( statusText); info(e);}

		};

	    $j.ajax( {'type':'GET', 'url':url, 'data':{}, 'dataType':'json', 'success':successCallback} );

	}

	this.load_image_from_file_button_click = function( evt ) {

		var self = evt.data.self;

		var f = function ( ) {
			self.file_upload_complete.apply( self, arguments );
		}

		$j('.aim_frame').remove();
		AIM.submit(document.getElementById('upload_file_form'),{'onStart' : self.file_upload_start, 'onComplete' : f });

	}


	this.file_upload_start = function() {
		$j.colr.show_message('<img src="'+base_url+'/throbber.gif"/>Uploading...');
	}

	this.file_upload_complete = function(response) {
		try {
			jsondata = eval('('+response+')');

			var self = this;
			var f = function() {
				self.file_extract_colors_complete.apply( self, arguments );
			}

			$j.colr.show_message('<img src="'+base_url+'/throbber.gif"/>Extracting Colors...');
			
			this.load_image_from_url(jsondata['temp_filename'], {'callback':f}, true );

		} catch (e) {$j.colr.show_message('Error uploading file: '+e);return;}
	}

	this.file_extract_colors_complete = function( response) {
		$j.colr.hide_messages();
		ScrollTo($('site_header'),{'duration':.5});
		blindDown($('site_image'), {'duration':.5});	

	}


	this.load_your_own = function( evt ) {
		var self = evt.data.self;

		var f = function(event, ui) {
			$j('#image_load_dialog').dialog('destroy');
			return false;
		}

		$j('#image_load_dialog').attr('title',"Load Image").dialog({'resizable':true, 'closeOnEscape':false, 'height':'auto', 'width':'500px', 'zIndex':10000, 'position':'center', 'beforeclose': f  }).show();

		$j('#load_image_from_url_button').bind( 'click', {'self':self}, self.load_image_from_url_button_click );
		$j('#load_image_from_file_button').bind( 'click', {'self':self}, self.load_image_from_file_button_click );

	}

	this.load_image_from_url_button_click = function( evt ) {
		var url = http_add( $j('#image_url').val() );
		var self = evt.data.self;
		self.load_image_from_url( url );
	}

	this.load_image_from_url_keypress = function( evt ) {
		if (evt.keyCode != 13) return;

		var self = evt.data.self;

		var url = http_add( $j('#image_url').val() );

		self.load_image_from_url( url );
	}

	this.load_image_from_url = function( image_url, opts, local_file ) {
		var callback = (opts && opts['callback']) ? opts['callback'] : null;

		this.hide_image_pixels();

		var url = base_url+'/image_pixels_url/?url='+image_url;

		if ( local_file == true )
			url = base_url + '/image_pixels_file/?file='+image_url;

		var self = this;

		var successCallback = function(jsondata, statusText) {
			if (jsondata && jsondata.success == true) {
				self.images.push( jsondata );
				self.images.shift();
				$j('.image_action_buttons').css( 'visibility', 'hidden' );
				self.display_new_image();
			} else {
				$j.colr.show_message('Error loading image color data');
			}
			setTimeout(function() {colr_throbber.unthrob( $j('#load_random_flickr_image_button'))}, 200);

		}

	    $j.ajax( {'type':'GET', 'url':url, 'data':{}, 'dataType':'json', 'success':successCallback} );
	}


	this.collage_search = function( evt ) {

		var self = evt.data.self;

		var query =  $j('#collage_search_query').val();

		$j.colr.show_message('Searching...');

		var url = base_url+'/json/search/'+query;

		var successCallback = function(jsondata, statusText) {
			$j.colr.hide_messages();

			if (jsondata.success == true) {
				$j.colr.show_message('Building Collage...');
				collage_data = self.combine( jsondata.colors, jsondata.schemes);
				self.display_collage( collage_data );

			} else {
				$j.colr.show_message('Error.  No results found..');
			}

		};

		$j.ajax( {'type':'GET', 'url':url, 'data':{}, 'dataType':'json', 'success':successCallback} );
	}


	this.combine = function( colors, schemes ) {

		if ( ! colors ) colors = [];
		if ( ! schemes ) schemes = [];

		var r_colors = {};
		var r_tags = {};

		var n_total_colors = 0;
		var n_tags = 0;

		n_colors = ( colors.length > 150 ) ? 150 : colors.length;

		for ( i=0;i<n_colors;i++) {

			if ( ! colors[i] ) continue;

			var hex = colors[i]['hex'];

			if ( isNaN( r_colors[ hex ] ) ) {
				r_colors[ hex ]  = 0;
				n_total_colors ++;
			}

			r_colors[ hex ] ++;

			for ( j=0;j<colors[i]['tags'].length;j++) {

				var tag = colors[i]['tags'][j]['name'];

				if ( isNaN( r_tags[ tag ] ) ) {
					r_tags[ tag ] = 0;
					n_tags ++;
				}

				r_tags[ tag ]++

			}

		}


		for ( i=0;i<schemes.length;i++) {

			if ( ! schemes[i] ) continue;

			/*
			// Add colors from schemes
			for ( j=0;j<schemes[i]['colors'].length;j++) {

				var hex = schemes[i]['colors'][j];

				if ( isNaN( r_colors[ hex ] ) ) {
					r_colors[ hex ] = 0;
					n_total_colors ++;
				}

				r_colors[ hex ]++
			}
			*/

			for ( j=0;j<schemes[i]['tags'].length;j++) {

				var tag = schemes[i]['tags'][j]['name'];

				if ( isNaN( r_tags[ tag ] ) ) {
					r_tags[ tag ]  = 0;
					n_tags ++;
				}

				r_tags[ tag ]++

			}

		}

		return { 'colors' : r_colors, 'tags' : r_tags, 'n_colors' : n_total_colors, 'n_tags' : n_tags };
	}


	this.display_collage = function( collage_data ) {

		var colors = collage_data.colors;
		var tags = collage_data.tags;

		var n_colors = collage_data.n_colors;
		var n_tags = collage_data.n_tags;

		var results = '';

		var tags_string = '';
	

		// lut lookup by colors
		colors_lut = [];
		for ( var color in colors ) {
			colors_lut.push( color );
		}

		cloud_data = [];
		wordle_data = '';

		var i = 0;
		var color_index = 0;

		for ( var tag in tags ) {

			if ( n_colors > 0 ) {
				color_index++;
			}

			if ( color_index > n_colors ) {
				color_index = 0;
			}

			cloud_data.push( {'text':tag, 'weight': tags[tag], 'color':'#'+colors_lut[color_index] } );
			wordle_data += tag + ':' + tags[tag] + ':' + colors_lut[color_index] + "\n";

		}
		
		var c = { 'w':550, 'h':350};
		var c = getCoords( $j('#tabs-3') );
		setCoords( $j('#collage_display'), {'w':c.w, 'h':400} );
		$j('#collage_display').empty().jQCloud( cloud_data );
		$j('#collage_display').topZIndex();;

		$j('#wordle_link input[name=colorwordcounts]').val( wordle_data );
		$j('#wordle_link').show();

		return;

		results = tags_string.replace( /\n/g, "<br/>" );
		
		$j('#collage_display').html( results ); 

	}

};


jQuery.colr.show_message = function( text, opts ) {

	if ( ! text ) return;
	if ( typeof(text) == typeof([]) &&  text.length == 0 ) return;

	if ( !opts ) opts = {};

	var jgrowl_opts = {
						theme: 'redmond',
						position:'center',
						sticky: false,
						life: 1500,
						speed: 'slow',
						easing: 'swing',
						animateOpen: {
							height: "show",
							width: "show"
						}
	};


    jQuery.extend( jgrowl_opts, opts );

	if ( jgrowl_opts.position ) {
		$j.jGrowl.defaults.position = jgrowl_opts.position;
	}

    $j.jGrowl(text, jgrowl_opts);

};

jQuery.colr.hide_messages = function( ) {
	
	$j('#jGrowl').find('div.jGrowl-notification.redmond').animate($j.jGrowl.defaults.animateClose, $j.jGrowl.defaults.speed, 
		$j.jGrowl.defaults.easing, function() {
		$j(this).remove();
	 });

};




// Simple JavaScript Templating
// John Resig - http://ejohn.org/ - MIT Licensed
(function(){
  var cache = {};
 
  this.tmpl = function tmpl(str, data){
    // Figure out if we are getting a template, or if we need to
    // load the template - and be sure to cache the result.
    var fn = !/\W/.test(str) ?
      cache[str] = cache[str] ||
        tmpl(document.getElementById(str).innerHTML) :
     
      // Generate a reusable function that will serve as a template
      // generator (and which will be cached).
      new Function("obj",
        "var p=[],print=function(){p.push.apply(p,arguments);};" +
     
        // Introduce the data as local variables using with(){}
        "with(obj){p.push('" +

        // Convert the template into pure JavaScript
        str
          .replace(/[\r\t\n]/g, " ")
          .split("<%").join("\t")
          .replace(/((^|%>)[^\t]*)'/g, "$1\r")
          .replace(/\t=(.*?)%>/g, "',$1,'")
          .split("\t").join("');")
          .split("%>").join("p.push('")
          .split("\r").join("\\'")
      + "');}return p.join('');");

    // Provide some basic currying to the user
    return data ? fn( data ) : fn;
  };
})();

jQuery(window).bind('load', function() {colr_onload(); window.c = new jQuery.colr(); c.init(); });
//jQuery(document).ready( function() {colr_onload(); window.c = new jQuery.colr(); c.init(); });


var initial_image_index = '0';
var image_pixels = [];
var image_pixel_els = [];
var title_image_src;
var pixel_highlight_inprogress = false;
var liquidity = null;

var colors = {};
var colors_history = {};
var schemes_history = {};
var current_color;
var current_matching_color_index = null;
var current_matching_scheme_index = null;
var edit_scheme_el;
var matching_colors = [];
var matching_schemes = [];
var starred_colors = {};
var starred_schemes = {};
var list_entries = [];
var previous_list_entries = [];
var max_list_entries = 20;
var image_colors_active = false;
var default_max_timestamp = 9999999999;
var search_max_timestamp = default_max_timestamp;

var schemes = {};
//var base_url = document.location.href;
//var base_url = 'http://www.colr.org';

var edit_scheme_id;
var edit_scheme = {'id':-1,'colors':[],'tags':[],'timestamp':0};

var counts = {};
var color_offset = 0;
var scheme_offset = 0;
//var timestamp_offset = 0;
var older_than = '';
var newer_than = '';

var cookie_expire1 = new Date();
cookie_expire1.setDate(cookie_expire1.getDate()+365)

var colr_contextmenu = null;
var colr_moremenu = null;
var colr_swatchmenu = null;
var colr_hoverpane = null;
var colr_messages = null;


var chunksize = 10;

function colr_onload() {
	colr_contextmenu = new dropdownMenu({'id':'colr_menu0','title':'','image_url':base_url});
	colr_swatchmenu = new dropdownMenu({'id':'colr_swatchmenu','image_url':base_url});
	colr_hoverpane = new hoverPane({'id':'colr_hoverpane0','image_url':base_url});
	colr_throbber = new Throbber({'image':base_url+'/throbber.gif'});

	$j(document).bind( 'onkeypress', {'self': colr_hoverpane}, colr_hoverpane.keypress );


	//preload_images(['dropdown_menu_arrow.gif','greystar.gif','star.gif','arrow_up.gif','paint_can_icon1.gif','brush_icon1.gif','brush_icon1_grey.gif','color_details.png','expand_scheme.png'], base_url);

	var starred_colors_text = getcookie('starred_colors');
	if (starred_colors_text != null)
		var starred_colors_array = starred_colors_text.split(escape('|'));
	if (starred_colors_array)
		for (var i=0;i<starred_colors_array.length;i++)
			starred_colors[starred_colors_array[i]] = 1;

	var starred_schemes_text = getcookie('starred_schemes');
	if (starred_schemes_text != null)
		var starred_schemes_array = starred_schemes_text.split(escape('|'));
	if (starred_schemes_array)
		for (var i=0;i<starred_schemes_array.length;i++)
			starred_schemes[starred_schemes_array[i]] = 1;

	update_list_entries();
	jQuery.colr.display_list_entries();
	display_list_nav();

	// color picker
	$j('#colorpicker_icon').ColorPicker( {
		'onChange' : colorpicker_onchange,
		'onSubmit' : colorpicker_onsubmit,
		'onHide'   : colorpicker_onhide,
		'onShow'   : function (colpkr) {
						$j(colpkr).fadeIn(500).topZIndex();
							return false;
							}
	} );


	$j('#color_input').val('');
	$j('#tag_input').val('');

	//load_image_from_url(initial_image_index);

	$j('.color_list .list_title').html ('Latest Colors');
	$j('.scheme_list .list_title').html ('Latest Schemes');


	//connect($('site_image_surround'), 'onmouseout', function(evt) {if(evt.target().target && evt.event().target.className == 'pixel_zoom') return;image_colors_active=false;setTimeout(function(){if (!image_colors_active) hide_image_colors()}),500;});
	//connect($('site_image_area'), 'onmouseover', hide_image_colors);


	liquidity = getcookie('liquidity');
	if (liquidity == null)
		liquidity = 1;

	set_liquidity( liquidity );
	$j('#liquidity_slider').slider({'min':0, 'max':5, 'step':1, 'change':liquidity_slider_onchange, 'value':liquidity});

	// if some color or scheme is already supplied at load time
	/*
	if ( matching_colors.length ==1 )
		set_edit_color(matching_colors[0]);

	if ( matching_schemes.length ==1 )
		set_edit_scheme(schemes[matching_schemes[0]]);
	*/

	// insert liquidity css
	// commented out after the generated css was placed in the stylesheet
	/*
	var csstext = '';
	for (var liquidity_level=0;liquidity_level<6;liquidity_level++) {	
	if (liquidity_level > 0) {
	var	color_liquidity_offset = 'background-position:-'+(60*(liquidity_level-1))+'px 0px;';
	var	scheme_liquidity_offset = 'background-position:-'+(25*(liquidity_level-1))+'px 0px;';
	}else {
	var	color_liquidity_offset = 'display:none;';
	var	scheme_liquidity_offset = 'display:none;';
	}

	for (var i=0;i<11;i++) {
	csstext += 'body.liquidity_'+liquidity_level+' .color_swatch_splat_'+i+' {'+color_liquidity_offset+'}\n';
	csstext += 'body.liquidity_'+liquidity_level+' .scheme_swatch_splat_'+i+' {'+scheme_liquidity_offset+'}\n';
	}
	}
	insert_inline_css(csstext,'liquidity_css');
	*/
}

function liquidity_slider_onchange(evt, slider) {
	set_liquidity(slider.value);
}

function set_liquidity( liquidity ) {

	$j('#current_liquidity').html( liquidity );

	$j('body').removeClass().addClass( 'liquidity_'+liquidity );

	setcookie('liquidity',liquidity,cookie_expire1,'/',null,null);
}

function reset_search() {
	older_than='';
	newer_than='';
	search_max_timestamp = default_max_timestamp;
	$j('.list_title').empty();
}

function reset_edit_scheme() {
  current_matching_scheme_index = null;
  edit_scheme = {};
  edit_scheme_id = null;
  edit_scheme.id = -1;
  edit_scheme.colors = new Array();
  edit_scheme.tags = new Array();
}

function clear_messages() {
  $j.colr.show_message();
}

function search_by_tag(tag_names, random_tag, evt) {

	if (!tag_names && !random_tag) tag_names = $j('#tag_input').val();
	counts['matching_colors'] = 0;
	counts['matching_schemes'] = 0;

	$j('#tag_input').val( tag_names );

	color_offset = (color_offset <0)? 0 : color_offset;
	scheme_offset = (scheme_offset <0)? 0 : scheme_offset;

	$j.colr.show_message('Searching...');

	var data = { 'color_offset' : color_offset,
				'scheme_offset' : scheme_offset,
				'older_than' : older_than,
				'newer_than' : newer_than };

	if (random_tag)
		var url = base_url+'/json/search/random';
	else
		var url = base_url+'/json/search/'+tag_names+'?'+data;

	var self = this;

	var successCallback = function(jsondata, statusText) {
    	$j.colr.hide_messages();

		if (jsondata.success == true) {
			if (jsondata.new_tag_name != null && jsondata.new_tag_name != '')
				$j('#tag_input').val( jsondata.new_tag_name );

			if ($j('#tag_input').val() == '')  {

				$j('.color_list .list_title').html ('Latest Colors');
				$j('.scheme_list .list_title').html ('Latest Schemes');
			} else {

				$j('.color_list .list_title').html( '"'+$j('#tag_input').val() + '" matches ' + jsondata.counts['matching_colors'] + ' colors'  );
				$j('.scheme_list .list_title').html( '"'+$j('#tag_input').val() + '" matches ' + jsondata.counts['matching_schemes'] + ' schemes' );
			} 

			matching_colors = [];
			matching_schemes = [];
			update_matching_colors(jsondata.colors);
			update_matching_schemes(jsondata.schemes);
			update_stuff(jsondata);
			current_matching_color_index = null; // no current color
			update_list_entries();
			jQuery.colr.display_list_entries();
			display_list_nav();
		} else {
			$j.colr.show_message('Unable to load colors.');
		}

	};

	$j.ajax( {'type':'GET', 'url':url, 'data':{}, 'dataType':'json', 'success':successCallback} );
}


function get_random_tag() {
  search_by_tag('',true);
}

function load_colors_from_site(site_url) {

	$j.colr.show_message('Fetching...');

	var url = base_url+'/json/from_web?url='+site_url;

	var successCallback = function(jsondata, statusText) {

		$j.colr.hide_messages();

		if (jsondata.success == true) {

			results = draw_site_color_results(jsondata.urls);

			$j('#site_color_results').html( results );

			var url_color_index = 0;

			for (url in jsondata.urls) {
				for (var i=0;i<jsondata.urls[url].length;i++) {
					connect($('url_color_'+url_color_index), 'onclick', site_color_onclick)
					url_color_index++;
				}
			}

		} else {
			$j.colr.show_message('Unable to load colors from URL!');
		}

	};

	$j.ajax( {'type':'GET', 'url':url, 'data':{}, 'dataType':'json', 'success':successCallback} );
}

function site_color_onclick(evt) {
	var color = Color.fromBackground(evt.src()).toHexString().replace(/#/,'');
	var el1 = evt.src();
	var el2 = getFirstElementByTagAndClassName('div', 'swatch', $('edit_color'));
	if (!el2)
		el2 = $('edit_color');


	var ghost_el = $('ghost_0');
	var c1 = getCoords($j(el1));
	var c2 = getCoords($j(el2));

	var percent_x = Math.floor(c2.w / c1.w * 100) - 25;
	var percent_y = Math.floor(c2.h / c1.h * 100) - 25;
	setElementPosition(ghost_el,{'x':c1.x,'y':c1.y});
	setElementDimensions(ghost_el,{'w':c1.w,'h':c1.h});
	ghost_el.style.backgroundColor = '#'+color;
	showElement(ghost_el);
	Move(ghost_el,{'x':c2.x,'y':c2.y,'mode':'absolute', 'duration':.5, 'afterFinish':partial(off_ghost,0)});
	Scale(ghost_el,percent_x,{'scaleY':false, 'duration':.5});
	Scale(ghost_el,percent_y,{'scaleX':false, 'duration':.5});
	setTimeout(function() {ScrollTo($('site_header'),{'duration':.5})},200);

	setTimeout(partial(set_edit_color,color),500);
}



function draw_site_color_results(urls) {
  var results = '';
  var url_color_index = 0;
  for (url in urls) {
    results += '<div class="site_url_link"><a target="_new" href="'+url+'">'+url+'</a></div>';
    results += '<div class="site_url_colors">';
    if (urls[url].length == 0)
      results += '<span class="subdued">None!</span>';
    else {
      urls[url].sort(hsvsort);
      for (var l1=0;l1<urls[url].length;l1++) {
        var color = urls[url][l1];
        results += '<div id="url_color_'+url_color_index+'" class="site_color" style="background-color:#'+color+';">&nbsp;&nbsp;&nbsp;';
        results += '</div>';
        url_color_index++;
      }
    }
    results += '</div>';
  }
  return results;
}


function http_add(url) {
	return 'http://'+url.replace(/http:\/\//,'');
}



function get_colors_from_image() {
  colr_throbber.throb( $j('#get_colors_from_image_button'),'Getting...');
  var num_colors = rand(4)+2;
  
  if (!image_pixels || image_pixels.length == 0)
    return;
  
  got_colors = new Array();
  for (var i=0;i<num_colors;i++) {
    var pixel_index = rand(image_pixels.length-1)
    p = image_pixels[pixel_index];
    got_colors.push(p.color);
  }
  load_colors({colors_array:got_colors});
}

function similar_schemes(scheme, props) {
	$j.colr.show_message('Fetching Similar Schemes...');

	var colors_string = scheme.colors.join(',');
	colors_string = colors_string.replace(/#/g,'');

	var url = base_url+'/json/search_by_colors';

	var data = { 'colors' : colors_string };

	var successCallback = function(jsondata, statusText) {
		$j.colr.hide_messages();

		if (jsondata.success == true) {

			$j('.scheme_list .list_title').html( jsondata.counts['matching_schemes'] + ' Similar Schemes' );

          	update_stuff(jsondata);

			matching_schemes = [];

			previous_list_entries = list_entries;

			list_entries = [];
			for (var i=0;i<jsondata.schemes.length;i++) {
				var scheme = jsondata.schemes[i];
				list_entries.push({'type':'scheme','id':scheme.id,'timestamp':1000-i});
			}

			clear_list_nav();
			jQuery.colr.display_list_entries();
			$j('#undo_similar_schemes').click( restore_list_entries );

		} else {
			$j.colr.show_message('Unable to load colors from URL!');
		}
	};

	$j.ajax( {'type':'GET', 'url':url, 'data':data,  'dataType':'json', 'success':successCallback} );

}


function expand_scheme(scheme, props) {
	var result_index = props['result_index'];

	var scheme_el = null;

	if (result_index == 'edit_scheme') {
		scheme_el = $j('#edit_scheme');
	}
	else {
		scheme_el = $j('.scheme_list .scheme_match')[result_index];
	}

	var swatch_els = $j(scheme_el).find( 'div.scheme_swatch' );
	var color_match_els = $j('.color_list .color_match');

	previous_list_entries = list_entries;
	list_entries = [];

	for (var i=0;i<swatch_els.length;i++) {
		var ghost_el = $j('#ghost_'+i);

		if ( ghost_el.length == 0 ) continue;

		var swatch_el = swatch_els[i];

		var color = scheme.colors[i];
	
		var el1 = swatch_el;
		var el2 = color_match_els[i]; 

		var c1 = getCoords($j(el1));
		var c2 = getCoords($j(el2));

		setCoords( ghost_el, c1 );

		ghost_el.css( 'backgroundColor', '#'+color ).show().topZIndex();
	
		$j(ghost_el).animate( {'left' : c2.x + 'px',
							   'top'  : c2.y + 'px', 
							   'width': c2.w + 'px', 
							   'height' : c2.h + 'px'} , 500, 'swing', partial(off_ghost,i) );


		list_entries.push({'type':'color','id':color,'timestamp':1000-i});
	}


	setTimeout(function(){
		jQuery.colr.display_list_entries();
		load_colors({colors_array:scheme.colors});
		$j.scrollTo( '.list_scaffold', {'duration':500, 'offset':{'top':-50} } );
		//$j('.color_list .list_title').html( 'Expanded scheme colors <span class="button ui-state-default ui-corner-all" id="undo_expand_colors">undo</span>' );
		$j('.color_list .list_title').html( 'Expanded scheme colors' );
		//$j('#undo_expand_colors').click( restore_list_entries );
	},500);

}

function restore_list_entries() {
	list_entries = previous_list_entries;
	jQuery.colr.display_list_entries();
}

 // this looks like crap. Need a better highlight
function highlight_image(tf) {
  var im_el = $("site_image_surround");
  if (tf)
    im_el.style.borderColor = '#ff0000';
  else
    im_el.style.borderColor = '#999999';
}


function update_scheme(scheme_id, properties) {
  var el_id = get_property(properties,'el_id',null);
  if (!el_id) return;
  $(el_id).innerHTML = draw_scheme(scheme_id, properties);
}



function sync_edit_scheme() {
	var scheme_colors = '';

	for (i=0;i<edit_scheme.colors.length;i++) {

		scheme_colors += edit_scheme.colors[i];

		if (i<edit_scheme.colors.length-1)
			scheme_colors += ',';

	}


	var url = base_url+'/json/scheme/?colors='+scheme_colors;

	var successCallback = function(jsondata, statusText) {
    	$j.colr.hide_messages();

		if (jsondata.success == true) {
	
			// if scheme already present, replace current scheme with this one
			if (jsondata.new_scheme_id == -1) {
				edit_scheme_id = -1;
				edit_scheme.id = -1;
				edit_scheme.tags = []
			} else {
				update_stuff(jsondata);
				edit_scheme_id = jsondata.new_scheme_id;
				edit_scheme = schemes[edit_scheme_id];
			}

			display_edit_scheme(edit_scheme, {'allow_interaction':true,'el_id':'edit_scheme'});

		} else {
			$j.colr.show_message('Error syncing scheme');
		}

	}
 
	$j.ajax( {'type':'GET', 'url':url, 'data':{}, 'dataType':'json', 'success':successCallback} );
}


function display_color_list_entries() {

	var match_results = '';

	var list_entries = $j.colr.list_colors;

	for ( var i=0; i<list_entries.length; i++ ) {
		var entry = list_entries[i];

		var el_id = 'match_'+entry.id;

		match_results += '<div class="color_match" id="'+el_id+'"></div>';
	}


	$j(".color_list .list_entries").html(match_results);

	if (list_entries.length > 0)
		rnd.seed = list_entries[0]['id'].charCodeAt(0);

	for ( var i=0; i<list_entries.length; i++ ) {
		var entry = list_entries[i];

		var el_id = 'match_'+entry.id;
		display_color(i,{'allow_interaction':true,'result_id':i});
	}
}


function display_scheme_list_entries() {

	var match_results = '';

	var list_entries = $j.colr.list_schemes;

	for ( var i=0; i<list_entries.length; i++ ) {
		var entry = list_entries[i];

		var el_id = 'match_'+entry.id;

		match_results += '<div class="scheme_match" id="'+el_id+'"></div>';
	}


	$j(".scheme_list .list_entries").html(match_results);

	if (list_entries.length > 0)
		rnd.seed = list_entries[0]['id'].charCodeAt(0);

	for ( var i=0; i<list_entries.length; i++ ) {
		var entry = list_entries[i];

		var el_id = 'match_'+entry.id;
		display_scheme_list_entry(i,{'allow_interaction':true,'result_id':i});
	}
}


jQuery.colr.display_list_entries = function() {
	display_color_list_entries();
	display_scheme_list_entries();
}

function clear_list_nav() {
	$j('#topnav1').empty();
	$j('#topnav2').empty();
}

function display_list_nav() {
	var prev_results = '';
	var next_results = '';

	if (list_entries.length > 0 && 
			( counts['matching_schemes']+ counts['matching_colors'] > list_entries.length ||
			  counts['matching_schemes'] == 0 && counts['matching_colors'] == 0 && list_entries.length > 0 )) {
		next_results = 'older >';
	}

	if (list_entries.length > 0 && list_entries[0]['timestamp'] < search_max_timestamp && search_max_timestamp != default_max_timestamp) {
		prev_results = '< newer';
	}

	if (counts['matching_schemes'] == 0 && counts['matching_colors'] == 0 && list_entries.length > 0 && search_max_timestamp != default_max_timestamp) {
		prev_results = '< newer';
	}
	
	if (counts['matching_schemes'] + counts['matching_colors'] > 0 && list_entries.length == 0) {
		prev_results = '< newer';
	}

	$j('#topnav1').html( prev_results );
	$j('#topnav2').html( next_results );

	if (next_results != '') {
    	$j('#topnav2').unbind();
		$j('#topnav2').bind( 'click', {}, function(evt){newer_than='';older_than=list_entries.slice(-1)[0]['timestamp'];continue_search()});
	}

	if (prev_results != '') {
    	$j('#topnav1').unbind();
		if ( list_entries.length > 0 )
			$j('#topnav1').bind( 'click', {}, function(evt){older_than='';newer_than=list_entries[0]['timestamp'];continue_search()});
		else
			$j('#topnav1').bind( 'click', {}, function(evt){older_than='';newer_than=older_than;continue_search()});
	}
}

function continue_search() {
  matching_colors = [];
  matching_schemes = [];
  search_by_tag($('tag_input').value);
}


function display_colors() {
  var color_results = '';
  
  for (var color_index=0;color_index<matching_colors.length;color_index++) {
    var el_id = 'color_match_'+color_index;
    color_results += '<div class="color_match" id="'+el_id+'"></div>';
  }

  $("color_matches").innerHTML = color_results;
  
  for (var color_index=0;color_index<matching_colors.length;color_index++) {
    var el = $('color_match_'+color_index);

    var color_contents = '';
    if (matching_colors.length == 1 || current_matching_color_index == color_index) {
      display_color(color_index,{'allow_interaction':true});
      current_color_el = el_id;
    } else
      display_color(color_index,{'allow_interaction':false});
  }
}


function display_color(match_index, props) {

	var color =$j.colr.list_colors[match_index]['id'];

	var el = $j('#match_'+color);

	el.html( draw_color(color, props) );

	hookup_color_events(el, color, props);
}


function view_color(color, props, evt) {

	if (!props['skip_animation']) {  // Animated transition
		var ghost_el = $j('#ghost_0');

		var target_el = $j('#edit_color').find('div.swatch');

		if (!target_el)
			target_el = $j('#edit_color');

		var duration = ( props['duration'] ) ? props['duration'] : .5;

		var c1 = getCoords($j(props['source_el']));
		var c2 = getCoords($j(target_el));

		var percent_x = Math.floor(c2.w / c1.w * 100);

		setCoords( ghost_el, {'x':c1.x,'y':c1.y, 'w':c1.w,'h':c1.h} );

		ghost_el.css( 'backgroundColor', '#'+color).show();
	
		$j(ghost_el).animate( {'left' : c2.x + 'px',
							   'top'  : c2.y + 'px'
							   } , 500, 'swing', partial(poof_ghost, 0) );

		//Move(ghost_el,{'x':c2.x,'y':c2.y,'mode':'absolute', 'duration':(duration*2), 'afterFinish':partial(poof_ghost,0)});
		//Scale(ghost_el,percent,{'scaleY':false, 'duration':(duration*2)});

		//setTimeout(function() {ScrollTo($('site_header'),{'duration':duration})},500);
		setTimeout(partial(display_edit_color,color), duration*1000);
	} else {
		display_edit_color(color);
	}
}


function edit_color( evt ) {

	var color = evt.data.color;
	var props = evt.data.props;

	var f = function(event, ui) {
        $j('#edit_color_dialog').dialog('destroy');
        return false;
    }

    $j('#edit_color_dialog').attr('title',"Edit Color").dialog({'resizable':true, 'closeOnEscape':false, 'height':'auto', 'zIndex':10000, 'position':'center', 'beforeclose': f  }).show();


	if (!props['skip_animation']) {  // Animated transition
		var ghost_el = $j('#ghost_0');
		ghost_el.css( 'backgroundColor', '#'+color );

		var target_el = $j('#edit_color');

		var c2 = getCoords($j(target_el));

		ghost_el.show().topZIndex();
	
		$j(ghost_el).animate( {'left' : c2.x + 'px',
							   'top'  : c2.y + 'px',
							   'width': c2.w + 'px' 
							   } , 300, 'linear', partial(poof_ghost, 0) );

	//ghost_el.animate( {'left':c2.x + 'px' , 'top':c2.y + 'px' ,}, 300, 'linear', partial(poof_ghost,0) );
		//$j.scrollTo( '#site_header', {'duration':500, 'offset':{'top':-50} } );
	}
	display_edit_color(color);
}


function do_edit_scheme( evt ) {

	var scheme = evt.data.scheme;
	var props = evt.data.props;

	if (scheme) {
		edit_scheme = scheme;
	}

	var f = function(event, ui) {
        $j('#edit_scheme_dialog').dialog('destroy');
        return false;
    }

	var dialog_position = props.dialog_position || 'center';

    $j('#edit_scheme_dialog').attr('title',"Edit Scheme").dialog({'resizable':true, 'closeOnEscape':false, 'height':'auto', 'zIndex':10000, 'position':dialog_position, 'beforeclose': f  }).show();


	if (!props['skip_animation']) {  // Animated transition

		var ghost_el = $j('#ghost_0');
		var c1 = getCoords($j('#match_'+props['result_id']));
		var c2 = getCoords($j('#edit_scheme'));
		var percent = Math.floor(c2.w / c1.w * 100);
		ghost_el.show();
	
		$j(ghost_el).animate( {'left' : c2.x + 'px',
							   'top'  : c2.y + 'px',
							   'width': c2.w + 'px' 
							   } , 500, 'swing', partial(poof_ghost, 0) );

		$j.scrollTo( '#site_header', {'duration':500, 'offset':{'top':-50} } );
	}

	if ( props['delay'] ) {
		setTimeout( display_edit_scheme, props['delay']);
	}
	else {
		display_edit_scheme();
	}
}

function move_ghost(start_el, end_el, opts) {
	var ghost_el = $('ghost_0');
	var c1 = getCoords($j(start_el));
	var c2 = getCoords($j(end_el));
	var percent = Math.floor(c2.w / c1.w * 100);
	setElementPosition(ghost_el,{'x':c1.x,'y':c1.y});
	setElementDimensions(ghost_el,{'w':c1.w,'h':c1.h});
	showElement(ghost_el);
	Move(ghost_el,{'x':c2.x,'y':c2.y,'mode':'absolute', 'duration':1, 'afterFinish':poof_ghost});
	Scale(ghost_el,percent,{'scaleY':false, 'duration':1});
	setTimeout(function() {ScrollTo($('site_header'),{'duration':.5})},500);
}


function poof_ghost(ghost_index) {
	if (!ghost_index) ghost_index = '0';
	$j('#ghost_'+ghost_index).fadeOut( 400 );
}

function off_ghost(ghost_index) {
	$j('#ghost_'+ghost_index).hide();
}

function display_edit_color(color) {

	var testcolor = $j.xcolor.test( color );
	if ( ! testcolor ) return;

	var props = {'edit':true};
	$j('#edit_color').html( draw_color(color, props) );
 
	hookup_color_events( $j('#edit_color'), color, props);

	$j('#color_input').val( '#'+color.toUpperCase() );
}



function hookup_color_events(el, color, props) {

	var result_id = props['result_id'];
	if (props['edit'])
		result_id = 'edit_color';

	// hook up tags 
  	var tags_el = el.find('div.tags');
	var tag_els = tags_el.find('span.tag');

	for (var l1=0;l1<tag_els.length;l1++) {
		var tag_el = $j(tag_els[l1]);
		var tag_contents = tag_el.html();
		tag_el.bind( 'click', {}, partial( search_by_tag, tag_contents, false ) );
		//connect(tag_els[l1],'oncontextmenu',partial(color_current_tag_contextmenu, color, tag_contents));
	}

	// Add tags button 
	var add_tags_el = tags_el.find('span.button');
	add_tags_el.bind( 'click', {}, partial(show_add_tags_to_color_dialog, color ) );

	var more_button_el = $j(el).find('.more_button');
	var more_stuff_el = $j(el).find('.more_stuff');
	more_button_el.bind( 'click', {'self':this, 'type':'color', 'id':color, 'more_button_el':more_button_el, 'more_stuff_el':more_stuff_el, 'props':props}, toggle_more );

	// Edit button
	if (!props['edit']) {
		var edit_button_el = $j(el).find('.edit_button');
		edit_button_el.bind( 'click', {'self':this, 'color':color, 'props':{'edit':true, 'result_id':props['result_id'] }}, edit_color );
	}

	// hook up star icon
	var favorite_el = $j(el).find( 'span.favorite' );
	favorite_el.bind( 'click', {}, partial(toggle_star_color, color) );

}


function toggle_more( evt ) {

	var type = evt.data.type;
	var id = evt.data.id;
	var props = evt.data.props;
	var more_button_el = evt.data.more_button_el;
	var more_stuff_el = evt.data.more_stuff_el;

	var result_id = props['result_id'];

	if (props['edit'])
		result_id = 'edit_'+type; 

 
	if (more_stuff_el.css('display') == 'none') {
		results = '';
		if (type == 'color') {
			var color = id;
			results += '<div style="float:right;text-align:right;">';
			results += '<span id="matching_paints_button_'+result_id+'" class="button small ui-state-default ui-corner-all"><img src="'+base_url+'/brush_icon1.gif"/> Matching Paints</span>';
			results += '<br/>';
			results += '<span id="matching_idee_images_button_'+result_id+'" class="button small ui-state-default ui-corner-all"><img src="'+base_url+'/idee.gif"/> Matching Id&#233;e images</span>';
			results += '<br/>';
			results += '<span id="matching_istockphotos_button_'+result_id+'" class="button small ui-state-default ui-corner-all"><span class="more_swatch" style="background-color:#'+color+';"><img src="'+base_url+'/istockphoto_logo_trans.png"/></span>Matching IstockPhotos</span>';
			results += '</div>';


			//results += '<div class="color_hex">'+$j.fmtColor( '#'+color, 'hex' )+'</div>';
			results += '<br style="clear:both;"/>';
			results += '<div id="tag_history_'+result_id+'" class="tag_history">';
			results += '<span style="color:#000000;">Tag history: </span>';

			var color_history = colors_history[color];
			for (var history_index in color_history) {
				var historytag = color_history[history_index];

				var tag_id_results = (historytag.d_count >= historytag.a_count) ? '<span class="deleted">'+historytag.name+'</span>' : '<span class="current">'+historytag.name+'</span>';

				tag_id_results +=" (+"+historytag.a_count;
				if (historytag.d_count)
					tag_id_results += ' -' + historytag.d_count + ')&nbsp;&nbsp;&nbsp;';
				else
					tag_id_results += ')&nbsp;&nbsp;&nbsp;';
				  
				results += '<span id="history_tag_'+history_index+'" class="tag">'+tag_id_results+'</span>';
			}
			results += '</div>'; // history
			
			results += '<br style="clear:both;"/>';

			more_stuff_el.html( results ) ;

    		$j('#matching_idee_images_button_'+result_id).bind( 'click', {'color':color}, idee_search_color );
    		$j('#matching_paints_button_'+result_id).bind( 'click', {'color' : color}, get_paint_colors );
    		$j('#matching_istockphotos_button_'+result_id).bind( 'click', {'color':color}, istockphoto );

		  	// history contextmenu stuff
			var tag_els = $j('#tag_history_'+result_id+' .tag');
			tag_els.each( function() { 
				var tag_el = $j(this);
				var current_tag = tag_el.find('.current');
				if ( current_tag.length > 0 ) {
					tag_el.bind( 'mouseover', { 'self':this, 'color':color, 'tag_el': tag_el, 'tag':current_tag.html()},  color_current_tag_hover );
					//$j(this).bind( 'contextmenu', {}, partial( color_current_tag_contextmenu, color, current_tag.html() ) );
				}

				var deleted_tag = tag_el.find('.deleted');
				if ( deleted_tag.length > 0 ) {
					tag_el.bind( 'mouseover', { 'self':this, 'color':color, 'tag_el': tag_el, 'tag':deleted_tag.html()},  color_removed_tag_hover );
					//$j(this).bind( 'contextmenu', {}, partial( color_removed_tag_contextmenu, color, deleted_tag.html() ) );
				}
		  	});


		} else if (type == 'scheme') {
			var scheme = id;
			var scheme_id = scheme['id'];

			results += '<div style="float:right;text-align:right;">';
			results += '<span id="expand_scheme_colors_button_'+result_id+'" class="button small ui-state-default ui-corner-all"><img src="'+base_url+'/expand_scheme.png"/> Expand scheme colors</span>';
			results += '<br/>'
			results += '<span id="similar_schemes_button_'+result_id+'" class="button small ui-state-default ui-corner-all"><img src="'+base_url+'/expand_scheme.png"/> Similar Schemes</span>';
			results += '<br/>';
			results += '<span id="matching_idee_images_button_'+result_id+'" class="button small ui-state-default ui-corner-all"><img src="'+base_url+'/idee.gif"/> Matching Id&#233;e images</span>';
			results += '<br/>';
			results += '<span id="download_aco_button_'+result_id+'" class="button small ui-state-default ui-corner-all">Download scheme as <span class="scheme2aco">.aco</span></span>';
			results += '</div>';

			results += '<div id="tag_history_'+result_id+'" class="tag_history">';
			results += '<span style="color:#000000;">Tag history: </span>';

			var scheme_history = schemes_history[scheme_id];
			for (var history_index in scheme_history) {
				var historytag = scheme_history[history_index];

				var tag_id_results = (historytag.d_count >= historytag.a_count) ? '<span class="deleted">'+historytag.name+'</span>' : '<span class="current">'+historytag.name+'</span>';

				tag_id_results +=" (+"+historytag.a_count;
				if (historytag.d_count)
					tag_id_results += ' -' + historytag.d_count + ')&nbsp;&nbsp;&nbsp;';
				else
					tag_id_results += ')&nbsp;&nbsp;&nbsp;';
				  
				results += '<span id="history_tag_'+history_index+'" class="tag">'+tag_id_results+'</span>';
			}
			results += '</div>'; // scheme_history
	
			results += '<br style="clear:both;"/>';
			more_stuff_el.html( results );


		  	// history contextmenu stuff
			var tag_els = $j('#tag_history_'+result_id+' .tag');

			tag_els.each( function() { 
				var tag_el = $j(this);
				var current_tag = tag_el.find('.current');
				if ( current_tag.length > 0 ) {
					tag_el.bind( 'mouseover', { 'self':this, 'scheme':scheme, 'tag_el': tag_el, 'tag':current_tag.html()},  scheme_current_tag_hover );
				}

				var deleted_tag = tag_el.find('.deleted');
				if ( deleted_tag.length > 0 ) {
					tag_el.bind( 'mouseover', { 'self':this, 'scheme':scheme, 'tag_el': tag_el, 'tag':deleted_tag.html()},  scheme_removed_tag_hover );
				}
		  	});

    		$j('#matching_idee_images_button_'+result_id).bind( 'click', {}, partial( idee_search_scheme, scheme ) );
    		$j('#expand_scheme_colors_button_'+result_id).bind( 'click', {}, partial( expand_scheme, scheme, {'result_index':result_id} ) );
    		$j('#similar_schemes_button_'+result_id).bind( 'click', {}, partial( similar_schemes, scheme, {'result_id':result_id} ) );
    		$j('#download_aco_button_'+result_id).bind( 'click', {}, partial( scheme2aco, scheme ) );
		}

		more_button_el.html( 'Less &#9652;' );

		$j(more_stuff_el).slideDown();

  	} else {

		var f = function() {
			more_button_el.html( 'More &#9662;' );
		};

		$j(more_stuff_el).slideUp( 'fast', f );
	}
}


function display_schemes() {
	return;
  var scheme_results = '';
  
  for (var scheme_index=0;scheme_index<matching_schemes.length;scheme_index++) {
    var el_id = 'scheme_match_'+scheme_index;
    scheme_results += '<div class="scheme_match" id="'+el_id+'"></div>';
  }

  $("scheme_matches").innerHTML = scheme_results;
  
  for (var scheme_index=0;scheme_index<matching_schemes.length;scheme_index++) {
    var el = $('scheme_match_'+scheme_index);

    var scheme_contents = '';
    if (matching_schemes.length == 1 || current_matching_scheme_index == scheme_index) {
      display_scheme(scheme_index,{'allow_interaction':true});
      edit_scheme_el = el_id;
    } else
      display_scheme(scheme_index,{'allow_interaction':false});
  }
}


function display_scheme_list_entry(match_index, props) {
	var scheme_id = $j.colr.list_schemes[match_index]['id'];
	var el = $j('#match_'+scheme_id);
	var scheme = schemes[scheme_id];
	el.html( draw_scheme(scheme_id, props) );

  // hook up star icon
  //var tags_el = getFirstElementByTagAndClassName('div', 'tags', el);
  //var icon_els = getElementsByTagAndClassName('img', 'tag_icon', tags_el);
  //if (icon_els[0])
  //connect(icon_els[0],'onclick',partial(toggle_star_scheme, scheme_id, props));

	hookup_scheme_events(el, scheme, props);
}

function display_edit_scheme() {
	var props = {'edit':true};
	$j('#edit_scheme').html( draw_scheme(-1, props) );
	hookup_scheme_events( $j('#edit_scheme'), edit_scheme, props );
}



function set_active_matching_scheme(scheme_index, evt) {
  if (colr_hoverpane.active == true) return;

  if (edit_scheme == matching_schemes[scheme_index] && current_matching_scheme_index != null) return;  // already done!
  
  // remove interaction from previous scheme
  if (current_matching_scheme_index != null)
    display_scheme_list_entry(current_matching_scheme_index, {'allow_interaction':false});

  // draw active matching scheme "active"
  current_matching_scheme_index = scheme_index;
  edit_scheme = matching_schemes[scheme_index];
  display_scheme_list_entry(scheme_index, {'allow_interaction':true});

  // display active matching scheme in edit_scheme area
  display_edit_scheme(edit_scheme, {'allow_interaction':false});
}



function hookup_scheme_events(el, scheme, props) {
	// hook up history stuff
	//var history_toggle = getFirstElementByTagAndClassName('span', 'history_toggle', el);
	var history_toggle = el.find('span.history_toggle');

	var history_box = el.find('div.scheme_history');
	var result_id = (props['edit']) ? 'edit_scheme' : props['result_id']; 


	// history contextmenu stuff
	var tag_els = history_box.find('span.deleted');
	for (var l1=0;l1<tag_els.length;l1++) {
		var tag_el = ( $j(tag_els[l1]) );
		var tag_contents = tag_el.html();;
		tags_el.bind( 'contextmenu', {}, partial(scheme_removed_tag_contextmenu, scheme, tag_contents) ); 
		connect(tag_els[l1],'oncontextmenu',partial(scheme_removed_tag_contextmenu, scheme, tag_contents));
	}

	colr_swatchmenu.hide();

	// hook up tags 
	var tags_el = el.find('div.tags');
	var tag_els = tags_el.find('span.tag');
	for (var l1=0;l1<tag_els.length;l1++) {
		var tag_el = ( $j(tag_els[l1]) );
		var tag_contents = tag_el.html();;
		tag_el.bind( 'click', {}, partial( search_by_tag, tag_contents, false ) ); 
		tag_el.bind( 'contextmenu', {}, partial(scheme_current_tag_contextmenu, scheme, tag_contents) ); 
	}

	// Add tags button 
	var add_tags_el = tags_el.find('span.button');

	add_tags_el.bind( 'click', {}, partial(show_add_tags_to_scheme_dialog, scheme) );

	var more_button_el = $j(el).find('.more_button');
	var more_stuff_el = $j(el).find('.more_stuff');
	more_button_el.bind( 'click', {'self':this, 'type':'scheme', 'id':scheme, 'more_button_el':more_button_el, 'more_stuff_el':more_stuff_el, 'props':props}, toggle_more );

	// hook up star icon
	var favorite_el = $j(el).find( 'span.favorite' );
	favorite_el.bind( 'click', {}, partial(toggle_star_scheme, scheme['id']) );

  
    // hook up swatches
	var swatch_els = $j(el).find( 'div.scheme_swatch' );

	for (var l1=0;l1<swatch_els.length;l1++) {
		var swatch_el = $j(swatch_els[l1]);
		//var color = Color.fromBackground(swatch_el).toHexString().toLowerCase().substring(1,7);
		var color = $j.xcolor.test( swatch_el.css('background-color') ).getHex().substring(1,7);

		swatch_el.bind( 'mouseover', { 'self': this, 'color': color, 'swatch_el' : swatch_el, 'props' : props}, swatch_click );
		swatch_el.bind( 'click', { 'self': this, 'color': color, 'swatch_el' : swatch_el, 'props' : props}, swatch_click );
		//swatch_el.bind( 'mouseover', {}, partial(swatch_click, color, swatch_el, props) );
		//swatch_el.bind( 'click', {}, partial(swatch_click, color, swatch_el, props) );

		if (props['el_id'] == 'edit_scheme') {
			var remove_swatch_el = swatch_el.next();
			remove_swatch_el.bind( 'click', {}, partial( remove_color_from_edit_scheme, color ) );
		}
	}
  

	if (props['edit']) {

		var add_color_el = $j('#add_color_to_scheme');

		if ( add_color_el.length > 0 )

			add_color_el.bind( 'click', {}, partial( add_color_to_scheme_start, scheme ) );
	}

	// Edit button
	if (!props['edit']) {
		var edit_button_el = $j(el).find('.edit_button');
		edit_button_el.bind( 'click', {'self':this, 'scheme':scheme, 'props':props}, do_edit_scheme );
	}
}

function swatch_click(evt) {

	var color = evt.data.color;
	var swatch_el = evt.data.swatch_el;
	var props = evt.data.props;

	var duration = (props['edit']) ? .25 : .5;

	colr_swatchmenu.base_el = swatch_el;
	colr_swatchmenu.clearitems();


	var f = function() {
		var ghost_el = $j('#ghost_0');
		cloneCoords( $j(swatch_el), ghost_el );
		edit_color({ 'data': {'color':color, 'props': {} } }  );
	}

	colr_swatchmenu.additem({'id':'view_color','text':'Edit this color','action':f});

	if (props['edit'])
		colr_swatchmenu.additem({'id':'remove_color','text':'Remove','action':partial(remove_color_from_edit_scheme, color)});

	colr_swatchmenu.show(evt);
  
}

function set_edit_scheme(scheme, evt) {
  if (colr_hoverpane.active == true) return;

  edit_scheme = scheme;
  for (var i=0;i<matching_schemes.length;i++)
    if (matching_schemes[i] == scheme.id) {
      current_matching_scheme_index = i;
      break;
    }

  display_edit_scheme(edit_scheme, {'allow_interaction':false});
}


function image_onclick(evt) {
	if (colr_hoverpane.active == true) return;

	var pixel_el = evt.currentTarget;

	var color = $j.xcolor.test( $j(pixel_el).css( 'background-color' ) ).getHex( ).substring(1,7);

	var swatch_el = $j('#edit_color').find('div.swatch');

	var ghost_el = $j('#ghost_0');

	cloneCoords( $j(pixel_el), ghost_el );

/*
	var c1 = getCoords($j(pixel_el));
	var c2 = getCoords($j(swatch_el));
	var percent = Math.floor(c2.w / c1.w * 100) - 25;
	setCoords( ghost_el, {'x':c1.x,'y':c1.y, 'w':c1.w,'h':c1.h} );
	ghost_el.css( 'backgroundColor', '#'+color );
	ghost_el.show();
*/
	//ghost_el.animate( {'left':c2.x + 'px' , 'top':c2.y + 'px' ,}, 300, 'linear', partial(poof_ghost,0) );
	//setTimeout(partial(edit_color,color),100);
	edit_color( { 'data': { 'color':color, 'props':{} } } );

}

function toggle_star_color(color, evt) {
	if (starred_colors[color] && starred_colors[color] == 1) // already starred
		starred_colors[color] = null;
	else
		starred_colors[color] = 1;

	var starred_colors_array = new Array();
	for (var starred_color in starred_colors)
		if (starred_colors[starred_color] == 1)
			starred_colors_array.push(starred_color);

	var starred_colors_text = starred_colors_array.join("|");
	setcookie('starred_colors',starred_colors_text,cookie_expire1,'/',null,null);

	jQuery.colr.display_list_entries();
	display_edit_color(color);
	evt.stop();
}

function toggle_star_scheme(scheme_id, properties, evt) {

	var el_id = get_property(properties,'el_id','');

	if (starred_schemes[scheme_id] && starred_schemes[scheme_id] == 1) // already starred
		starred_schemes[scheme_id] = null;
	else
		starred_schemes[scheme_id] = 1;

	var starred_schemes_array = new Array();
	for (var starred_scheme_id in starred_schemes)
		if (starred_schemes[starred_scheme_id] == 1 && !starred_scheme_id.match(/\D/))  // id must be numeric
			starred_schemes_array.push(starred_scheme_id);

	var starred_schemes_text = starred_schemes_array.join("|");
	setcookie('starred_schemes',starred_schemes_text,cookie_expire1,'/',null,null);

	jQuery.colr.display_list_entries();
	display_edit_scheme();
}

function draw_color(color, props) {  // color is a hex string
	var allow_interaction = get_property(props,'allow_interaction',false);
	var show_history = get_property(props,'show_history',false);
	var result_id = get_property(props,'result_id',false);
	if (props['edit'])
		result_id = 'edit_color';

	var results = "";
	if (!color) return;

	if (!colors[color]) { // color not present (not in db?)
		colors[color] = {};
	}
	//var active_text = (allow_interaction) ? ' class="selected"' : '';
	results += '<div class="color">';


	results += '<div class="buttons">';

	if (!props['edit']) {
		results += '<span class="edit_button button small ui-state-default ui-corner-all"> Edit</span>';
	}
	var imgsrc = (starred_colors[color] && starred_colors[color] == 1) ? 'star.gif' : 'greystar.gif';
	results += '<br/><span class="more_button button small ui-state-default ui-corner-all"> More &#9662;</span>';
	results += '</div>';


	var which_splat = Math.floor(rand(10));
	results += '<div class="swatch" style="background-color:#'+color+';float:left;width:60px;">';
	results += '<div class="splat color_swatch_splat_'+which_splat+'" style="background-image:url(\''+base_url+'/splats/splat'+which_splat+'_60x25.png\');background-repeat:no-repeat;width:60px;">&nbsp;';
	results += '</div>'; // splat
	results += '</div>'; // swatch
	results += "<br style=\"clear:left;\"/>";


	var wrap_text = (colors[color].tags && colors[color].tags.length > 4) ? 'style="white-space:normal;"' : '';
	//results += '<br/>'+list_entries[result_id].timestamp+'<br/>';

	results += '<div class="stuff">';
	results += '<div class="tags"'+wrap_text+'>';

	if (colors[color].tags && colors[color].tags.length > 0) {
		for (var tag_index in colors[color].tags) {
			var tag = colors[color].tags[tag_index]
			results += '<span class="tag">'+tag.name+'</span> ';
		}
	} else {
		results += "<i>no tags</i>&nbsp;&nbsp;";
	}

	if ( props['edit'] ) {
		results += '<span class="button small ui-state-default ui-corner-all"> + Add tags</span>';
	}

	results += '</div>';  // tags

	if (!props['edit'])
		results += '<div class="color_hex">#'+color+'</div>';


//	results += '<div style="float:right;text-align:right;padding-top:2px;">';
//	results += '</div>';
	results += '</div>';  // stuff
	
	results += '<div class="more_stuff">';
	results += '</div>';  // more_stuff
	results += '<br style="clear:both;"/>';



	results += '</div>';  // color


	//results += '<div class="more">';


	return results;
}

function rnd() {
        rnd.seed = (rnd.seed*9301+49297) % 233280;
        return rnd.seed/(233280.0);
};

function rand(number) {
        return Math.ceil(rnd()*number);
};

function draw_scheme(scheme_id, props) {
	var allow_interaction = get_property(props,'allow_interaction',false);
	var show_history = get_property(props,'show_history',false);
	var el_id = get_property(props,'el_id','');
	var result_id = get_property(props,'result_id','');
	if (props['edit'])
		result_id = 'edit_scheme';

	scheme = schemes[scheme_id];
	if (!scheme)
	scheme = edit_scheme;

	var history_style = (show_history) ? 'block': 'none';
	var active_text = (allow_interaction) ? ' selected' : '';

	var results = '';
	results += '<div class="scheme'+active_text+'">';

	results += '<div class="buttons">';
	results += '<span class="edit_button button small ui-state-default ui-corner-all"> Edit</span>';

	var imgsrc = (starred_schemes[scheme_id] && starred_schemes[scheme_id] == 1) ? 'star.gif' : 'greystar.gif';
	results += '<br/><span class="more_button button small ui-state-default ui-corner-all"> More &#9662;</span>';
	results += '</div>';


	results += '<div class="colors">';
  
  	var color_results = '';
  	for (i=0;i<scheme.colors.length;i++) {
		var which_splat = Math.floor(rand(10));
		results += '<div class="scheme_swatch" style="background-color:#'+scheme.colors[i]+';float:left;">';
		results += '<div class="splat scheme_swatch_splat_'+which_splat+'" style="background-image:url(\''+base_url+'/splats/splat'+which_splat+'_25x25.png\');background-repeat:no-repeat;width:25px;">&nbsp;';
		results += '</div>'; // splat
		results += '</div>'; // swatch
	}

    if (el_id == 'edit_scheme' && allow_interaction)
		results += '<div class="remove_swatch">x</div>';
    
    color_results += " '"+scheme.colors[i]+"' ";

	if ( props['edit'] ) {
		var no_colors = '';
		var no_colors_style = '';
		if (!scheme.colors.length || scheme.colors.length == 0) {
			no_colors = '(no colors)&nbsp;&nbsp;';
			no_colors_style = ' style="width:auto;padding:2px;" ';
		}
		results += '<div id="add_color_to_scheme" class="ui-state-default ui-corner-all" '+no_colors_style+'>'+no_colors+'<span class="ui-icon ui-icon-plusthick">&nbsp;</span></div>';
	}

	results += '<br style="clear:left;"/>';
	results += '</div>';  // colors div


	results += '<div class="stuff">';

	var wrap_text = (scheme.tags && scheme.tags.length > 4) ? 'style="white-space:normal;"' : '';
	results += '<div class="tags"'+wrap_text+'>';

	//results += '<br/>'+list_entries[result_id].timestamp+'<br/>';
	//results += '<br/>'+list_entries[result_id].id+'<br/>';

	if (scheme.tags && scheme.tags.length > 0)
		for (var tag_index in scheme.tags) {
			var tag = scheme.tags[tag_index]
			results += '<span class="tag">'+tag.name+'</span> ';
		}
		else
    		results += "<i>no tags</i>&nbsp;&nbsp;";
  
	if ( props['edit'] ) {
		results += '<span class="button small ui-state-default ui-corner-all"> + Add tags</span>';
	}

	results += '</div>';  // tags
	
	results += '<div id="more_stuff_'+result_id+'" class="more_stuff">';
	results += '</div>';  // more_stuff
	results += '<br style="clear:both;"/>';
	results += '</div>';  // stuff
 
	results += '</div>';  // scheme div
	return results;
}




function show_favorites() {
	return;
	colr_throbber.throb( $j('#favorites_button'),'Getting...');
	var starred_colors_array = new Array();
	var starred_schemes_array = new Array();

	for (var color in starred_colors)
		if (starred_colors[color] == 1 && color != '')
			starred_colors_array.push(color);

	for (var scheme in starred_schemes)
		if (starred_schemes[scheme] == 1)
			starred_schemes_array.push(scheme);
	
	if ( starred_colors_array.length > 0 ) 
		load_colors({colors_array:starred_colors_array});

	if ( starred_schemes_array.length > 0 ) {
		matching_schemes = [];
		var f = function(jsondata) {
			update_matching_colors(jsondata.colors);
			update_matching_schemes(jsondata.schemes);
			update_stuff(jsondata);
			current_matching_color_index = null; // no current color
			update_list_entries({ignore_max:true});
			jQuery.colr.display_list_entries();
			clear_list_nav();
		}

		load_schemes(starred_schemes_array, f);
	}

	$j('.list_title').html( 'Favorites' );
	colr_throbber.unthrob( $j('#favorites_button'));
}

function get_starred_colors() {
  colr_throbber.throb( $j('#favorites_button'),'Getting...');
  var starred_colors_array = new Array();
  for (var color in starred_colors)
    if (starred_colors[color] == 1)
      starred_colors_array.push(color);
      
  load_colors({colors_array:starred_colors_array});

  $j('.list_title').html( 'Starred colors' );
  colr_throbber.unthrob( $j('#get_starred_colors_button'));
}

function get_starred_schemes() {
  colr_throbber.throb( $j('#get_starred_schemes_button'),'Getting...');
  var starred_schemes_array = new Array();
  for (var scheme in starred_schemes)
    if (starred_schemes[scheme] == 1)
      starred_schemes_array.push(scheme);
  load_schemes(starred_schemes_array);
  $('scheme_match_title').innerHTML = 'Starred schemes';
  colr_throbber.unthrob( $j('#get_starred_schemes_button'));
}


function remove_color_from_edit_scheme(color, evt) {
	if (array_contains(edit_scheme.colors,color)) {
		var temp_colors = new Array;

		for (var i=0;i<edit_scheme.colors.length;i++)
			if (edit_scheme.colors[i] != color)
				temp_colors.push(edit_scheme.colors[i]);

		edit_scheme.colors = temp_colors;

		if (edit_scheme.colors.length > 0){
			display_edit_scheme();
			sync_edit_scheme();
		} else
			clear_edit_scheme();
	}
}

function clear_edit_scheme() {
  reset_edit_scheme();
  display_edit_scheme(edit_scheme, {'allow_interaction':true,'el_id':'edit_scheme'});
  //$('edit_scheme').innerHTML = draw_scheme(edit_scheme_id, {'allow_interaction':true,'el_id':'edit_scheme'});
}


function add_color_to_scheme_start(scheme, evt) {
	colr_hoverpane.show(evt);
}

function show_add_tags_to_color_dialog(color, evt) {

	var f = function(event, ui) {
        $j('#add_tags_dialog').dialog('destroy');
        return false;
    }

	var f2 = function( event, ui ) {
		$j('#add_tags_input').focus();
	}


    $j('#add_tags_dialog').attr('title',"Add Tags").dialog({'resizable':true , 'zIndex':10000, 'position':'center', 'beforeclose': f, 'open': f2  }).show();

	$j('#add_tags_input').val('');
	$j('#add_tags_input').val('');


	$j('#add_tags_submit_button').unbind('click');

	var f = function() {
		add_tags_to_color( color, evt );
	}

	$j('#add_tags_input').keypress( function( evt ) { if ( evt.keyCode == 13 ) { f() } } );

	$j('#add_tags_submit_button').bind('click', f);
    

}

function add_tags_to_color( color ) {

	var tags = $j('#add_tags_input').val();

	if (!tags || tags == undefined || tags == 'undefined') {
		$j.colr.show_message("no tags added!");
		return;
	}

	$j('#add_tags_dialog').dialog('destroy');

	$j.colr.show_message('<img class="minithrobber" style="vertical-align:middle;" src="'+base_url+'/throbber.gif"> Adding...');

	var url = base_url+'/json/color/'+color+'/addtag/';

	var data = { 'tags': tags };

	var successCallback = function(jsondata, statusText) {

		if (jsondata.success == true) {
			$j.colr.show_message(jsondata.messages);
			update_stuff(jsondata);

			if ( $j('#tag_input').val() == '' && !array_contains( matching_colors, color ) )
				matching_colors = array_unshift( matching_colors, color );
			
			jQuery.colr.display_list_entries( );
			display_edit_color( color );
		} else {
			$j.colr.show_message(jsondata.messages);
		}

  	}
  
	$j.ajax( {'type':'POST', 'url':url, 'data':data,  'dataType':'json', 'success':successCallback} );
}

function show_add_tags_to_scheme_dialog(scheme, evt) {

	var f = function(event, ui) {
        $j('#add_tags_dialog').dialog('destroy');
        return false;
    }

	var f2 = function( event, ui ) {
		$j('#add_tags_input').focus();
	}

    $j('#add_tags_dialog').attr('title',"Add Tags").dialog({'resizable':true , 'zIndex':10000, 'position':'center', 'beforeclose': f, 'open' : f2  }).show();

	$j('#add_tags_input').val('');

	$j('#add_tags_submit_button').unbind('click');

	var f = function() {
		add_tags_to_scheme( scheme, evt );
	}

	$j('#add_tags_input').keypress( function( evt ) { if ( evt.keyCode == 13 ) { f() } } );

	$j('#add_tags_submit_button').bind('click', f);

}


function add_tags_to_scheme(scheme) {

	var tags = $j('#add_tags_input').val();
	if (!tags || tags == undefined || tags == 'undefined') {
		$j.colr.show_message("no tags added!");
		return;
	}
		
	$j('#add_tags_dialog').dialog('destroy');

	var scheme_colors = '';
	for (i=0;i<scheme.colors.length;i++) {
		scheme_colors += scheme.colors[i];
		if (i<scheme.colors.length-1)
			scheme_colors += ',';
	}
	
	var url = base_url+'/json/scheme/'+scheme.id+'/addtag/';
	
	var data = { 'tags' : tags, 'colors' : scheme_colors };
	
	var successCallback = function(jsondata, statusText) {

		if (jsondata.success == true) {
			$j.colr.show_message(jsondata.messages);
			update_stuff(jsondata);
			scheme = jsondata.schemes[0];
			edit_scheme = scheme;

			list_entries = array_unshift(list_entries,{'type':'scheme','id':scheme['id'],'timestamp':scheme['timestamp']} );
			jQuery.colr.display_list_entries();
			display_edit_scheme();
						
		} else {
			$j.colr.show_message(jsondata.messages);
		}
	};
	
	$j.ajax( {'type':'POST', 'url':url, 'data':data,  'dataType':'json', 'success':successCallback} );

}



function get_paint_colors(evt) {

	var color = evt.data.color;


	if (!color.match(/#?([0-9]|[A-F]){6}/i))  // valid hex #color?
		return;

	color = color.replace(/#/g,'');

	var url = base_url+'/json/get_paint/'+color;

	var successCallback = function(jsondata, statusText) {

		if (jsondata.success == true) {

			$j.colr.show_message(jsondata.messages);
			var paint_results = draw_paint_results(color, jsondata.paint_colors);

			var f = function(event, ui) {
				$j('#paint_colors_dialog').dialog('destroy');
				return false;
			}

			$j('#paint_colors_dialog').html( paint_results ).dialog({'resizable':true , 'zIndex':10000, 'position':'center', 'beforeclose': f  }).show();

		} else {
			$j.colr.show_message('Error loading image color data');
		}
	 }
  
  $j.ajax( { 'type':'GET', 'url':url,  'dataType':'json', 'success':successCallback} );
}

function info(txt) {
	try{console.info(txt)}catch(e){};
}

function log_paint_request(paint_url) {
	var url = base_url+'/paint_request/?url='+escape(paint_url);
	$j.ajax( {'type':'GET', 'url':url, 'data':{}, 'dataType':'json'} );
}


function draw_paint_results(color, paint_colors) {
  var results = '';
  var duron_paint_results = '';
  var behr_paint_results = '';
  var glidden_paint_results = '';
  var l1 = 0;
  var hsv = $j.xcolor.test(color).getHSV();
  var extra_style = (hsv.v < .5) ? 'color:#fff;' : '';

  results += '<div style="padding-top:20px;width:90%;text-align:left;white-space:nowrap;clear:left;">';
  results += '<a id="paint_tab0" href="javascript:tab_show(0,\'paint\');" class="tab active"><img src="duron_logo.gif"/></a>';
  results += '<a id="paint_tab1" href="javascript:tab_show(1,\'paint\');" class="tab"><img src="behr_logo.gif"/></a>';
  results += '<a id="paint_tab2" href="javascript:tab_show(2,\'paint\');" class="tab"><img src="glidden_logo.gif"/></a>';
  results += '</div>';
  
  for (paint_company in paint_colors) {
    paint_company_colors = paint_colors[paint_company];
    for (l1=0;l1<paint_company_colors.length;l1++) {
      var link_text = ''
      if (paint_company == 'duron') {
        var code = unescape(paint_company_colors[l1][1][0]);
        var rc = code.split(',');
        var url = 'http://www.duron.com/services/architects_designers/color_spaces/duronCOLOR/search.asp?group_id='+rc[0]+'&row_id='+rc[1];
        var paint_color_hex = paint_company_colors[l1][0];
        var paint_color_name = unescape(paint_company_colors[l1][1][1]);
        duron_paint_results += '<div class="paint_result" style="background-color:#'+paint_color_hex+';'+extra_style+'"'+link_text+'>'+paint_color_name+'</div>';
      } else if (paint_company == 'behr') {
        var code = paint_company_colors[l1][1][0]
        var url = 'http://www.behr.com/behrx/colorsmart/colorByName.jsp?colorName='+code;
        var paint_color_hex = paint_company_colors[l1][0];
        var paint_color_name = unescape(paint_company_colors[l1][1][1]);
        behr_paint_results += '<div class="paint_result" style="background-color:#'+paint_color_hex+';'+extra_style+'"'+link_text+'>'+paint_color_name+'</div>';
      } else if (paint_company == 'glidden') {
        var code = paint_company_colors[l1][1][0]
        var url = 'http://www.glidden.com/colors/getStripeCard.do?stripecardid='+code;
        var paint_color_hex = paint_company_colors[l1][0];
        var paint_color_name = unescape(paint_company_colors[l1][1][1]);
        glidden_paint_results += '<div class="paint_result" style="background-color:#'+paint_color_hex+';'+extra_style+'"'+link_text+'>'+paint_color_name+'</div>';
      }
    }
  }
  
  results += '<div id="paint_tab_area0" class="tab_area">';
  results += duron_paint_results;
  results += '</div>';
  
  results += '<div id="paint_tab_area1" class="tab_area" style="display:none;">';
  results += behr_paint_results;
  results += '</div>';
    
  results += '<div id="paint_tab_area2" class="tab_area" style="display:none;">';
  results += glidden_paint_results;
  results += '</div>';
  
  results = '<div class="paint_results" style="height:'+(l1*2+1)+'em;">'+results+'</div><br style="clear:both;"/>';
  
  return results;
}



function tab_show(tab_num,tab_group_id) {
  var elList, i;
  i=0;
  // update all tabs.
  while ($j(tab_group_id+'_tab'+i) && i < 100) {
    if (i == tab_num) {
    // If the tab is the new active tab, activate it. 
	  $j('#'+tab_group_id+'_tab'+i).addClass('active');
      $j('#'+tab_group_id+'_tab_area'+i).show();
      //$(tab_group_id+'_tab'+i).blur();
    } else {
      // Otherwise, make sure the tab is deactivated.
	  $j('#'+tab_group_id+'_tab'+i).removeClass('active');
      $j('#'+tab_group_id+'_tab_area'+i).hide();
    }
    i++;
  }
}

function update_stuff(jsondata) {
	if (jsondata.counts) counts = jsondata.counts;


	if ( jsondata.max_timestamp && search_max_timestamp == default_max_timestamp &&
          ( older_than != '' || newer_than != '') ) {
		search_max_timestamp = jsondata.max_timestamp;
	}

	if (jsondata.max_timestamp && older_than == '') {
		older_than = jsondata.max_timestamp;
	}

	update_colors(jsondata.colors);
	update_colors_history(jsondata.colors_history);
	update_schemes(jsondata.schemes);
	update_schemes_history(jsondata.schemes_history);
	update_list_entries();
}

function update_colors(c) {
	if (!c || !c.length) return;
	for (var l1=0;l1<c.length;l1++) {
		if ( c[l1] == '' ) continue;
		colors[c[l1]['hex']] = c[l1];
	}
}

function update_colors_history(ch) {
  for (color_hex in ch)
    colors_history[color_hex] = ch[color_hex];
}

function update_matching_colors(c) {
  if (!c || !c.length) return;
  
  matching_colors = [];
  for (var l1=0;l1<c.length;l1++) {
    if ( c[l1]['hex'] == '' ) continue;
    matching_colors.push(c[l1]['hex']);
  }
}

function update_schemes(s) {
  if (!s || !s.length) return;
  for (var l1=0;l1<s.length;l1++)
    schemes[s[l1]['id']] = s[l1];
}

function update_schemes_history(sh) {
  for (scheme_id in sh)
    schemes_history[scheme_id] = sh[scheme_id];
}


function update_matching_schemes(s) {
  if (!s || !s.length) return;
  
  matching_schemes = [];
  for (var l1=0;l1<s.length;l1++)
    matching_schemes.push(s[l1]['id']);
}

function update_list_entries(args) {

	if ( !args ) args={};
	window.list_entries = [];

	$j.colr.list_colors = [];
	$j.colr.list_schemes = [];

	for (i=0;i<matching_colors.length;i++) {
		var c = colors[matching_colors[i]];
		if (newer_than != '' && c['timestamp'] > newer_than) next;
		list_entries.push({'type':'color','id':c['hex'],'timestamp':c['timestamp']});
		$j.colr.list_colors.push({'type':'color','id':c['hex'],'timestamp':c['timestamp']});
	}

	for (i=0;i<matching_schemes.length;i++) {
		var s = schemes[matching_schemes[i]];
		//log('matching scheme: '+s['id'] + ' '+s['timestamp']);
		//if (s['timestamp'] > timestamp_offset) next;
		if (newer_than != '' && s['timestamp'] < newer_than) next;
		list_entries.push({'type':'scheme','id':s['id'],'timestamp':s['timestamp']});
		$j.colr.list_schemes.push({'type':'scheme','id':s['id'],'timestamp':s['timestamp']});
	}

	list_entries.sort(listsort);

	if (newer_than != '')
		list_entries.reverse();

	if ( !args.ignore_max )
		list_entries = list_entries.slice(0,max_list_entries);

	if (newer_than != '')
		list_entries.reverse();
	
}


function update_edit_color(color) {
	if (!color.match(/#?([0-9]|[A-F]){6}/i))  // valid hex #color?
		return;

	color = color.replace(/#/g,'');
	current_color = color;

	var url = base_url+'/json/color/'+color;

	var successCallback = function(jsondata, statusText) {
    	$j.colr.hide_messages();

		if (jsondata.success == true) {
	    	update_stuff(jsondata);
        
			display_edit_color(color);

		} else {
        	$j.colr.show_message('Error loading image color data');
		}
	}
 
	$j.ajax( {'type':'GET', 'url':url, 'data':{}, 'dataType':'json', 'success':successCallback} );
}

function load_colors(args) {
	colors_array = args.colors_array;

	colors_string = colors_array.join(',');
	colors_string = colors_string.replace(/#/g,'');

	var url = base_url+'/json/colors/'+colors_string;

	var successCallback = function(jsondata, statusText) {

		if (jsondata.success == true) {
			$j.colr.show_message(jsondata.messages);

			matching_colors = [];
			update_matching_colors(jsondata.colors);
			update_matching_schemes(jsondata.schemes);
			update_stuff(jsondata);
			current_matching_color_index = null; // no current color

			update_list_entries();
			jQuery.colr.display_list_entries();
		} else {
			$j.colr.show_message('Error loading  color data');
		}
	};

	$j.ajax( {'type':'GET', 'url':url, 'data':{}, 'dataType':'json', 'success':successCallback} );
}



function load_schemes(scheme_ids_array, callback) {
  scheme_ids_string = scheme_ids_array.join(',');
  scheme_ids_string = scheme_ids_string.replace(/#/g,'');

  var url = base_url+'/json/schemes/'+scheme_ids_string;
  var req = getXMLHttpRequest();
  req.open("GET", url, true);
  var d = sendXMLHttpRequest(req);
  d.addCallback(partial(function(callback, rsp) {
    try {
      jsondata = eval('(' + rsp.responseText + ')');
      if (jsondata.success == true) {
	  	callback(jsondata);
   	  } else {
        $j.colr.show_message('Error loading scheme data');
      }
    } catch (e) {log(e);}
  }, callback));
  
  d.addErrback(function(err) {
    new_window_show(err.req.responseText);
  });
}

function color_current_tag_hover( evt) {
	var color = evt.data.color;
	var tag = evt.data.tag;
	var tag_el = evt.data.tag_el;

	colr_contextmenu.base_el = tag_el;
	colr_contextmenu.clearitems();
	colr_contextmenu.additem({'id':'remove_tag_title','text':'Tag "'+tag+'"','disabled':true});
	colr_contextmenu.additem({'id':'remove_tag','text':'Remove this tag','confirm':true,'action':partial(remove_tag_from_color, color, tag)});
	colr_contextmenu.show(evt);
}

function color_removed_tag_hover(evt) {
	var color = evt.data.color;
	var tag = evt.data.tag;
	var tag_el = evt.data.tag_el;

	colr_contextmenu.base_el = tag_el;

	colr_contextmenu.clearitems();
	colr_contextmenu.additem({'id':'restore_tag_title','text':'Tag "'+tag+'"','disabled':true});
	colr_contextmenu.additem({'id':'restore_tag','text':'Restore this tag','confirm':true,'action':partial(restore_tag_to_color, color, tag)});
	colr_contextmenu.show(evt);
}

function color_current_tag_contextmenu(color, tag, evt) {
  if (evt.modifier().shift) return true;

  colr_contextmenu.clearitems();
  colr_contextmenu.additem({'id':'remove_tag_title','text':'Tag "'+tag+'"','disabled':true});
  colr_contextmenu.additem({'id':'remove_tag','text':'Remove this tag','confirm':true,'action':partial(remove_tag_from_color, color, tag)});
  colr_contextmenu.show(evt);
}


function color_removed_tag_contextmenu(color, tag, evt) {
  if (evt.modifier().shift) return true;
  colr_contextmenu.clearitems();
  colr_contextmenu.additem({'id':'restore_tag_title','text':'Tag "'+tag+'"','disabled':true});
  colr_contextmenu.additem({'id':'restore_tag','text':'Restore this tag','confirm':true,'action':partial(restore_tag_to_color, color, tag)});
  colr_contextmenu.show(evt);
}


function toggle_history(history_toggle_el,history_el, evt) {
  if (MochiKit.Style.computedStyle(history_el, 'display') == 'none') {
    showElement(history_el);
    history_toggle_el.innerHTML = 'History:';
  } else {
    hideElement(history_el);
    history_toggle_el.innerHTML = 'H';
  }
  evt.stop();
}

function toggleElement(el) {
  if (!el) return;
  
  if (el.style.display == 'none')
    showElement(el)
  else
    hideElement(el);
}

function show_color_details(color, evt) {

	colr_dialog_box.reset();
	colr_dialog_box.setTitle('Color Details ');

	var contents = '';
	contents += '<div class="color_details_swatch" style="background-color:#'+color+';">&nbsp;</div>';
	contents += '<br/>#'+color
	contents += '&nbsp;&nbsp;&nbsp;'+Color.fromHexString(color).toRGBString();
	contents += '<br/>Tag history';
	contents += '<div class="tag_history">';

	var color_history = colors_history[color];
	for (var history_index in color_history) {
		var historytag = color_history[history_index];

		var tag_id_contents = (historytag.d_count >= historytag.a_count) ? '<span class="deleted">'+historytag.name+'</span>' : historytag.name;

		tag_id_contents +=" (+"+historytag.a_count;
		if (historytag.d_count)
			tag_id_contents += ' -' + historytag.d_count + ')&nbsp;&nbsp;&nbsp;';
		else
			tag_id_contents += ')&nbsp;&nbsp;&nbsp;';
		  
		contents += '<span id="history_tag_'+history_index+'" class="tag">'+tag_id_contents+'</span>';
	}
	contents += '</div>'; // color_history


    colr_dialog_box.setContents(contents);
    colr_dialog_box.show();
    colr_dialog_box.anchor(null,[0,0],evt);
    $(colr_dialog_box.id+'_header').style.backgroundcolor = '#'+color;

	var history_box = getFirstElementByTagAndClassName('div', 'tag_history', colr_dialog_box.element);

	// history contextmenu stuff

	for (var history_index in color_history) {
		var history_tag = $('history_tag_'+history_index);
		var tag_contents = history_tag.innerHTML;

		var history = color_history[history_index];
		connect(history_tag,'oncontextmenu',partial(color_removed_tag_contextmenu, color, tag_contents));
	}  


}

function istockphoto(color) {
  var r = h2d(color.substr(0,2));
  var g = h2d(color.substr(2,2));
  var b = h2d(color.substr(4,2));
  
  var url = 'http://www.istockphoto.com/file_search.php?action=file&color='+r+','+g+','+b;
  new_window_show(url);
}

function idee_search_scheme(scheme) {
  var url = 'http://labs.ideeinc.com/multicolour/#colors=' + scheme.colors.join(",");
  new_window_show(url);
}

function idee_search_color(color) {
  var url = 'http://labs.ideeinc.com/multicolour/#colors=' + color;
  new_window_show(url);
}

function h2d(h) {return parseInt(h,16);}


function scheme2aco(scheme) {
  //var scheme = (scheme_id) ? schemes[scheme_id] :edit_scheme;

  var url = base_url + "/scheme2aco.php?scheme_id="+scheme['id'];
  
  for (i=0;i<scheme.colors.length;i++) {
    url += "&color[]=" + scheme.colors[i];
  }
  
  aco_window = window.open(url, "aco_window", "resizable=yes,status=yes,toolbar=yes,menubar=yes,location=yes,scrollbars=yes width=400,height=200");
}


function scheme_current_tag_hover( evt) {
	var scheme = evt.data.scheme;
	var tag = evt.data.tag;
	var tag_el = evt.data.tag_el;

	colr_contextmenu.base_el = tag_el;
	colr_contextmenu.clearitems();
	colr_contextmenu.additem({'id':'remove_tag_title','text':'Tag "'+tag+'"','disabled':true});
	colr_contextmenu.additem({'id':'remove_tag','text':'Remove this tag','confirm':true,'action':partial(remove_tag_from_scheme, scheme, tag)});
	colr_contextmenu.show(evt);
}

function scheme_removed_tag_hover(evt) {
	var scheme = evt.data.scheme;
	var tag = evt.data.tag;
	var tag_el = evt.data.tag_el;

	colr_contextmenu.base_el = tag_el;

	colr_contextmenu.clearitems();
	colr_contextmenu.additem({'id':'restore_tag_title','text':'Tag "'+tag+'"','disabled':true});
	colr_contextmenu.additem({'id':'restore_tag','text':'Restore this tag','confirm':true,'action':partial(restore_tag_to_scheme, scheme, tag)});
	colr_contextmenu.show(evt);
}

function scheme_current_tag_contextmenu(scheme, tag, evt) {
  if ( evt.shiftKey ) return true;
  colr_contextmenu.clearitems();
  colr_contextmenu.additem({'id':'remove_tag_title','text':'Tag "'+tag+'"','disabled':true});
  colr_contextmenu.additem({'id':'remove_tag','text':'Remove this tag','confirm':true,'action':partial(remove_tag_from_scheme, scheme, tag)});
  colr_contextmenu.show(evt);
}



function scheme_removed_tag_contextmenu(scheme, tag, evt) {
  if ( evt.shiftKey ) return true;
  colr_contextmenu.clearitems();
  colr_contextmenu.additem({'id':'restore_tag_title','text':'Tag "'+tag+'"','disabled':true});
  colr_contextmenu.additem({'id':'restore_tag','text':'Restore this tag','confirm':true,'action':partial(restore_tag_to_scheme, scheme, tag)});
  colr_contextmenu.show(evt);
}


function remove_tag_from_scheme(scheme, tag, evt) {

	$j.colr.show_message('Removing...');

	var url = base_url+'/json/scheme/'+scheme.id+'/removetag/';

	var data = { 'tag' :tag };
  
	var successCallback = function(jsondata, statusText) {

		if (jsondata.success == true) {
			$j.colr.show_message(jsondata.messages);
			update_stuff(jsondata);

			jQuery.colr.display_list_entries();
			display_edit_scheme(scheme);

		} else {
			$j.colr.show_message(jsondata.messages);
		}
	}
  
	$j.ajax( {'type':'POST', 'url':url, 'data':data,  'dataType':'json', 'success':successCallback} );
}


function restore_tag_to_scheme(scheme, tag, evt) {
	$j.colr.show_message('Adding...');

	var url = base_url+'/json/scheme/'+scheme.id+'/addtag/';
  
	var data = { 'tags' :tag };
  
	var successCallback = function(jsondata, statusText) {
		if (jsondata.success == true) {
			$j.colr.show_message(jsondata.messages);
			update_stuff(jsondata);

			if ($j('#tag_input').value == '' && !array_contains(matching_schemes,scheme.id))
				matching_schemes = array_unshift(matching_schemes,scheme.id);

			display_edit_scheme(scheme);
			jQuery.colr.display_list_entries();
			$j.colr.hide_messages();

		} else {
			$j.colr.show_message(jsondata.messages);
		}

	}

	$j.ajax( {'type':'POST', 'url':url, 'data':data,  'dataType':'json', 'success':successCallback} );
}


function remove_tag_from_color(color, tag, evt) {

	$j.colr.show_message('Removing...');

	var url = base_url+'/json/color/'+color+'/removetag/';

	var data = { 'tag': tag };

	var successCallback = function(jsondata, statusText) {
		if (jsondata.success == true) {
		$j.colr.show_message(jsondata.messages);
		update_stuff(jsondata);

		if ($j('#tag_input').val( ) == '' && !array_contains(matching_colors,color))
			matching_colors = array_unshift(matching_colors,color);

			update_matching_colors(jsondata.colors);
			update_list_entries();
			jQuery.colr.display_list_entries();
			//display_current_color(color);

		} else {
			$j.colr.show_message(jsondata.messages);
		}
	}
  
	$j.ajax( {'type':'POST', 'url':url, 'data':data,  'dataType':'json', 'success':successCallback} );
}


function restore_tag_to_color(color, tag, evt) {
	$j.colr.show_message('Adding...');

	var url = base_url+'/json/color/'+color+'/addtag/';

	var data = {'tags' : tag};
  
	var successCallback = function(jsondata, statusText) {

		if (jsondata.success == true) {
			$j.colr.show_message(jsondata.messages);
			update_stuff(jsondata);

			if ($j('#tag_input').val() == '' && !array_contains(matching_colors,color))
			matching_colors = array_unshift(matching_colors,color);
			update_list_entries();
			jQuery.colr.display_list_entries();
		} else {
			$j.colr.show_message(jsondata.messages);
		}

	}
	$j.ajax( {'type':'POST', 'url':url, 'data':data,  'dataType':'json', 'success':successCallback} );
  
}





function colorpicker_onhide( picker ) {
	var newcolor = $j.xcolor.test( $j('#color_input').val() );
	if ( ! newcolor ) return;
	var hex = newcolor.getHex().substring(1,7);
	update_edit_color(hex);
}


function colorpicker_onsubmit(hsb, hex, rgb) {
	$j('#color_input').val( '#' + hex );
	update_edit_color(hex);
}


function colorpicker_onchange(hsb, hex, rgb) {
	$j('#color_input').val( '#' + hex );
}



rnd.today=new Date();
rnd.seed=rnd.today.getTime();
function rnd() {
        rnd.seed = (rnd.seed*9301+49297) % 233280;
        return rnd.seed/(233280.0);
}

function rand(number) {
  return Math.ceil(rnd()*number);
}

function randomString(string_length) {
  var chars = "0123456789abcdefghiklmnopqrstuvwxyz";
  var randomstring = '';
  for (var i=0; i<string_length; i++) {
    var rnum = Math.floor(Math.random() * 36);  // 36 = chars.length
    randomstring += chars.substring(rnum,rnum+1);
  }
  return randomstring;
}



function new_window_show(text) {
  info_window = this.open('', 'info_window', 'resizable=yes,status=yes,scrollbars=yes,locationbar=yes,location=yes,menubar=yes,toolbar=yes,width=1000,height=1000');
  
  if (text.match(/^http/)) {
    info_window.location = text;
  } else {
    doc = info_window.document;
    doc.open('text/html');
    doc.write(text);
    doc.close();
  }
  info_window.focus();
}

function preload_images(images, base_url) {
  var txt = '';
  for (var i=0;i<images.length;i++) {
    txt += '<img src="'+base_url+'/'+images[i]+'"/>'
  }
  
  var imgdiv = createDOM('div', {'id':'preload_images','style':{'display':'none'}});

  document.getElementsByTagName('body').item(0).insertBefore(imgdiv, document.getElementsByTagName('body').item(0).firstChild);
  imgdiv.innerHTML = txt;
}

function listsort(a,b) {
	//return a['timestamp'] - b['timestamp'];
	var d1 = b['timestamp'] - a['timestamp'];
	if (d1 != 0) return d1;

	if (b['id'] > a['id']) return 1
	if (b['id'] < a['id']) return -1
	return 0; 
}

function schemesort(a_id,b_id) {
	var a = schemes[a_id];
	var b = schemes[b_id];

	var d1 = b['timestamp'] - a['timestamp'];
	if (d1 != 0) return d1;

	if (b['id'] > a['id']) return 1
	if (b['id'] < a['id']) return -1
	return 0; 
}

function colorsort(a_id,b_id) {
	var a = colors[a_id];
	var b = colors[b_id];

	var d1 = b['timestamp'] - a['timestamp'];
	if (d1 != 0) return d1;

	if (b_id > a_id) return 1
	if (b_id < a_id) return -1
	return 0; 
}


function hsvsort(a, b) {
  if (a == '000000') return 1;
  if (a == 'ffffff') return -1;
  
  var a1 = $j.xcolor.test(a).getHSV();
  var b1 = $j.xcolor.test(b).getHSV();
  
  var hyst =.055;

  if (a1.h < b1.h-hyst) return -1;
  if (a1.h > b1.h+hyst) return 1;
  
  if (a1.s < b1.s) return -1;
  if (a1.s > b1.s) return 1;
  
  if (a1.s < b1.s) return -1;
  if (a1.s > b1.s) return 1;
  
  return 0;
}


/**
 * Sets a Cookie with the given name and value.
 *
 * name       Name of the cookie
 * value      Value of the cookie
 * [expires]  Expiration date of the cookie (default: end of current session)
 * [path]     Path where the cookie is valid (default: path of calling document)
 * [domain]   Domain where the cookie is valid
 *              (default: domain of calling document)
 * [secure]   Boolean value indicating if the cookie transmission requires a
 *              secure transmission
 */
function setcookie(name, value, expires, path, domain, secure) {
    document.cookie = name + "=" + escape(value) +
        ((expires) ? "; expires=" + expires.toGMTString() : "") +
        ((path) ? "; path=" + path : "") +
        ((domain) ? "; domain=" + domain : "") +
        ((secure) ? "; secure" : "");
}

function getcookie(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 array_contains(ar, el) {
  if (!ar || !el) return;
  for(var i=0;i<ar.length;i++)
    if(el == ar[i]) return true;
  return false;
}

function array_unshift(ar, el) {
  var copy = [];
  copy.push(el);
  for (var i = 0; i < ar.length; i++)
     copy.push(ar[i]);
  return copy;
}

function get_property(p, k, d) {
 try {
    if (p === null) return d;
 
    if (typeof(p[k]) == 'boolean' || typeof(p[k]) == 'number')
      return p[k];
 
    return (p[k]) ? p[k] : d;
  } catch (e) {
    //alert(p);
    //alert(e);
    return d;
  }
}




function hoverPane(properties) {
	this.id = (properties['id']) ? properties['id'] : null;
	$j('body').append('<div id="' + this.id+'_el" class="hoverpane">');
	this.el = $j('#'+this.id+'_el');
	this.target_id = null;
	this.color = '';
	this.active = false;

	this.hover_pane_text = '<div>Click a color </div>(esc or right-click to cancel)';
	this.hover_pane_invalid_text = '<div style="background-color:#f6cccc">Sorry, it doesn\'t work here</div>';

	this.show = function(evt) {
		this.active = true;
		$j(document).bind( 'mouseup.hoverpane', { 'self':this }, this.add_color_to_scheme );
		$j(document).bind( 'mousemove.hoverpane', { 'self':this }, this.update );
		$j(document).bind( 'contextmenu.hoverpane', { 'self':this }, this.hide );
		$j(document).bind( 'keypress.hoverpane', { 'self':this }, this.keypress );

		evt.data.self = this;
		this.update(evt);
		this.el.topZIndex();
	}
  
	this.update = function(evt) {

		var self = evt.data.self;
		if ( $j(evt.target).hasClass( 'carousel_image' ) ) {
			self.el.html( self.hover_pane_invalid_text );
		} else {
			self.target_id = evt.target.id;
			//self.color = Color.fromBackground(evt.target());

			self.color = $j.xcolor.test( $j(evt.target).css( 'backgroundColor') );
			self.el.html( self.hover_pane_text +'<div id="'+self.id+'_swatch" style="background-color:'+self.color.getHex()+';">&nbsp;</div>' );
		}
	   
		setCoords( self.el,{'x':evt.pageX+5,'y':evt.pageY-5} );
		self.el.show();
	}

	this.add_color_to_scheme = function(evt) {

		var self = evt.data.self;

		var color = self.color.getHex().toLowerCase().substring(1,7);
		if (array_contains(edit_scheme.colors,color)) {
			var temp = self.el.innerHTML;
			self.el.innerHTML = "<div>Already in scheme!</div>";

			//setTimeout(bind(function(txt) {self.el.innerHTML=txt}, self, temp),1000);
			setTimeout(function() {self.el.innerHTML=temp},1000);
		} else {
			edit_scheme.colors.push(color);

			var el1 = $j('#'+self.id+'_swatch');
			var el2 = $j('#add_color_to_scheme');

			var ghost_el = $j('#ghost_'+i);
			var c1 = getCoords($j(el1));
			var c2 = getCoords($j(el2));

			ghost_el.css({'left':c1.x+'px','top':c1.y+'px', 'width':c1.w+'px','height':c1.h+'px','background-color':'#'+color}).show();
		
			ghost_el.topZIndex();
			ghost_el.animate( {'left':c2.x+'px','top':c2.y+'px', 'width':c2.w+'px'}, 300, 'linear', partial(off_ghost,i) );

			setTimeout(display_edit_scheme,500);
			setTimeout(sync_edit_scheme,2000);

			self.hide(evt);
		}
	}
  
  this.keypress = function(evt) {
	var self = evt.data.self;
    if (evt.keyCode == 27)
    self.hide(evt);
	evt.stopPropagation();
  }
  
  this.hide = function(evt) {
	var self = evt.data.self;
    self.active = false;
    $j(self.el).hide();

   	$j(document).unbind( 'mouseup.hoverpane' );
	$j(document).unbind( 'mousemove.hoverpane' );
	$j(document).unbind( 'contextmenu.hoverpane' );
	$j(document).unbind( 'keypress.hoverpane' );


    try {
      evt.stop();
    } catch (e) {}  // do nothing

  }
}

function insert_inline_css(csstext, id) {
	csstext = '<!--\n'+csstext+'-->';
	if ($(id)) {
      removeElement($(id));
	}	
	var s = document.createElement('style');
	s.setAttribute("type", "text/css");
	s.setAttribute("id", id);
	if ( s.styleSheet ) {
	  s.styleSheet.cssText = csstext;
	} else {
	  var cssText = document.createTextNode(csstext);
	  s.appendChild(cssText);
	}
	document.getElementsByTagName('head').item(0).appendChild(s);
}


function getCoords(el) {
	if ( el.length == 0 ) return {'x':0,'y':0,'w':0,'h':0};
    var o = el.offset();
    var h = el.outerHeight();
    var w = el.outerWidth();
    var c = {'x':Math.floor(o.left),'y':Math.floor(o.top),'w':w,'h':h};
    return c;
}

function setCoords(el, c) {
    el.css({'top':c.y+'px','left':c.x+'px'});
    if (c.w) { 
        el.css({'width':c.w+'px'})
        el.css({'height':c.h+'px'})
    }
}

function cloneCoords(e1, e2) {
	setCoords( e2, getCoords( e1 ) );
}




function Throbber(properties) {
	this.image = (properties['image']) ? properties['image'] : null; // throbber image

	this.throb_elements = {};  // currently active throbber elements
	this.throb_contents = {};  // pre-throb contents of the active throbber elements

	this.throb = function(el,text) {
		if (!el) return;

		if (!this.throb_elements[el.id]) {
			this.throb_elements[el.id] = el;
			this.throb_contents[el.id] = el.html();
		}
		el.html( '<img class="minithrobber" style="vertical-align:top;" src="' + this.image + '">' + text );
	}

	this.unthrob = function(el) {
		if (this.throb_elements[el.id])
			this.throb_elements[el.id].html( this.throb_contents[el.id] );

		this.throb_elements[el.id] = null;
		this.throb_contents[el.id] = null;
	}
}






function dropdownMenu(properties) {
	this.id = (properties['id']) ? properties['id'] : null;
	this.title = (properties['title']) ? properties['title'] : null;
	this.image_url = (properties['image_url']) ? properties['image_url'] : '';
	this.base_el = (properties['base_element']) ? properties['base_element'] : null;

	this.el = $j('<div class="dropdownmenu"></div>').appendTo( $j(document.body) );
 
	this.menuitems = [];

	if (this.base_el) {
		if (this.title != null)
			this.base_el.html( this.title );
		this.base_el.addClass( 'dropdownmenu_base' );
	}

	this.toggle = function(evt) {
		var self = evt.data.self;

		if (self.el.style.display == 'block')
			self.hide(evt);
		else
			self.show(evt);
	}
  
	this.show = function(evt) {
		this.hide_others();
		this.render();

		if (this.base_el) {
			this.base_el.addClass('active');
			var c =	getCoords( this.base_el );
			setCoords(this.el,{'x':c.x,'y':c.y+c.h});
		} else {
			setCoords(this.el,{'x':evt.pageX-2,'y':evt.pageY-5});
		}

		this.el.show( );

		for (var l1=0;l1<this.menuitems.length;l1++) {
			this.menuitems[l1]['awaiting_confirm'] = false;
			var item = this.menuitems[l1];
			var el = $j('#'+this.id+'_'+item.id);

			el.bind( 'mouseover', {'self':this, 'el' : el }, this.menuitem_highlight );
			el.bind( 'mouseout', {'self':this, 'el' : el }, this.menuitem_unhighlight );
			//connect($(el_id), 'onmouseover', bind(this.menuitem_highlight, this, $(el_id)));
			//connect($(el_id), 'onmouseout', bind(this.menuitem_unhighlight, this, $(el_id)));
			if (item['action']) {
				if (item['confirm'] == true) {
					el.bind( 'click', {'self':this, 'el' : el, 'action' : item['action'] }, this.menuitem_confirm );
					//connect($(el_id), 'onclick', bind(this.menuitem_confirm, this, $(el_id), item['action']));
				} else {
					el.bind( 'mousedown', {'self':this }, item['action'] );
					//connect($(el_id), 'onmousedown', item['action']);
				}
			}
		}

		this.toFront();
		evt.preventDefault();
		evt.stopPropagation();
		evt.stopImmediatePropagation();
	}
  
	this.hide = function( evt ) {
		var self = (evt) ? evt.data.self : this;

		self.el.hide();

		if (self.base_el)
			self.base_el.removeClass('active');

		for (var l1=0;l1<self.menuitems.length;l1++) {
			var item = self.menuitems[l1];
			$j('#'+item.id).unbind();
		}
	}
  
  // to be overridden
  this.hide_others = function() {
  }
  
  
  // hook it up!
  if (this.base_el != null) {
	this.base_el.unbind(); // disconnect any previous signals connected to base_element (possibly from prior menu instantiations)
	this.base_el.bind( 'click', {'self':this}, this.toggle );
  }

  $j(document).bind( 'click', {'self':this}, this.hide );
  
  
	this.menuitem_confirm = function( evt ) {

		var el = evt.data.el;
		var action = evt.data.action;
		var self = evt.data.self;

		el.unbind();
		el.bind( 'mouseover', {'self':this, 'el': el}, self.menuitem_highlight );
		el.bind( 'mouseout', {'self':this, 'el': el}, self.menuitem_unhighlight );

		el.append('<span id="'+self.id+'_confirm" class="menuitem_confirm">  Are you sure?</span>');

		el.find('.menuitem_confirm').bind( 'mousedown', evt.data, action );

		self.blink_el( self, $j('#'+self.id+'_confirm'), 2, false );

		evt.stopPropagation();
		evt.stopImmediatePropagation();
		evt.preventDefault();
	}
  
	this.menuitem_highlight = function(evt) {
		var el = evt.data.el;
		$j(el).addClass( 'highlight');
	}
  
  this.menuitem_unhighlight = function(evt) {
	var el = evt.data.el;
    $j(el).removeClass( 'highlight');
  }
  
  this.additem = function(item) {
    //item['id'] = this.id+'_menuitem_'+this.menuitems.length;
    this.menuitems.push(item);
  }
  
  this.setitem = function(item) {
    var el_id = this.id+'_'+item.id;
    if ($(el_id))
      removeElement($(el_id)); // remove previous menuitem
      
    for (var l1=0;l1<this.menuitems.length;l1++) {
      if (this.menuitems[l1].id != item.id) continue;
      this.menuitems[l1] = item;
      break;
    }
  }
  
  this.render = function() {
    var menu_contents = '';
    for (var l1=0;l1<this.menuitems.length;l1++) {
      var menuitem = this.menuitems[l1];
      var el_id = this.id+'_'+menuitem.id;
      var disabled = (menuitem.disabled == true) ? ' disabled':'';
      var invisible = (menuitem.visible == false) ? ' style="display:none;"':'';
      menu_contents += '<div id="'+el_id+'" class="menuitem'+disabled+'"'+invisible+'>';
      menu_contents += menuitem.text;
      menu_contents += '</div>';
    }
    
    this.el.html( menu_contents );
  }
  
  this.clearitems = function() {
    this.el.html('');
    this.menuitems = [];
  }
  
	this.blink_el = function( self, el, times, onoff, evt) {

		if (!el) return;

		if (times == 0) {

			if (!onoff)
				el.removeClass('blink');

			if (onoff)
				el.addClass('blink');
			return;
		}

		el.toggleClass('blink');

		setTimeout( function(){  self.blink_el( self, el, times-1, onoff) }, 100);
	}

	this.toFront = function() {
		$j(this.el).topZIndex();
	}
 
  
}


/*
AJAX IFRAME METHOD (AIM)
* http://www.webtoolkit.info/
*
**/

var AIM = {

    frame : function(c) {

        var n = 'f' + Math.floor(Math.random() * 99999);
        var d = document.createElement('DIV');
        d.innerHTML = '<iframe class="aim_frame" style="display:none" src="about:blank" id="'+n+'" name="'+n+'" onload="AIM.loaded(\''+n+'\')"></iframe>';
        document.body.appendChild(d);

        var i = document.getElementById(n);
        if (c && typeof(c.onComplete) == 'function') {
            i.onComplete = c.onComplete;
        }

        return n;
    },

    form : function(f, name) {
        f.setAttribute('target', name);
    },

    submit : function(f, c) {
        AIM.form(f, AIM.frame(c));
		$j('#file_ext').val( $j('#image_file').val().replace(/.+\./g,''));
		f.submit();
        if (c && typeof(c.onStart) == 'function') {
            return c.onStart();
        } else {
            return true;
        }
    },

    loaded : function(id) {
        var i = document.getElementById(id);
		var d = null;

        if (i.contentDocument) {
            var d = i.contentDocument;
        } else if (i.contentWindow) {
            var d = i.contentWindow.document;
        } else {
            var d = window.frames[id].document;
        }
        if ( !d || d.location.href == "about:blank") {
            return;
        }

        if (typeof(i.onComplete) == 'function') {
            i.onComplete(d.body.firstChild.innerHTML);
        }
    }

}

window.partial = function (func) {
    /***

        Return a partially applied function, e.g.:

            addNumbers = function (a, b) {
                return a + b;
            }

            addOne = partial(addNumbers, 1);

            assert(addOne(2) == 3);

        NOTE: This could be used to implement, but is NOT currying.

    ***/
    var preargs = extend([], arguments, 1);
    return function () {
        return func.apply(this, extend(preargs.slice(), arguments));
    }
}

window.extend = function (self, obj, /* optional */skip) {
    /***

        Mutate an array by extending it with an array-like obj,
        starting with the "skip" index of obj.  If null is given
        as the initial list, a new one will be created.

        This mutates *and returns* the given list, be warned.

    ***/
   
    // Extend an array with an array-like object starting
    // from the skip index
    if (!self) {
        self = [];
    }
    if (!skip) {
        skip = 0;
    }
    if (obj) {
        for (var i = skip; i < obj.length; i++) {
            self.push(obj[i]);
        }
    }
    // This mutates, but it's convenient to return because
    // it's often used like a constructor when turning some
    // ghetto array-like to a real array
    return self;
}

