
var Cookie = {
  create:function(name,value,days) {
    if(days){
      var date = new Date();
      date.setTime(date.getTime()+(days*24*60*60*1000));
      var expires = "; expires="+date.toGMTString();
    }
    else var expires = "";
    document.cookie = name+"="+value+expires+"; path=/";
  },
  read:function(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;
  },
  erase:function(name) {
    createCookie(name,"",-1);
  }
}



var BrowserDetect = {
  ie6:false,
  ie7:false,
  ie8:false,
	ie9:false,
  firefox:false,
  safari:false,
	chrome:false,
	webkit:false,
  
  windows:false,
  mac:false,
  linux:false,
  
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
		
		if(this.browser=="Explorer" && this.version==6) this.ie6 = true;
    if(this.browser=="Explorer" && this.version==7) this.ie7 = true;
    if(this.browser=="Explorer" && this.version==8) this.ie8 = true;
		if(this.browser=="Explorer" && this.version>=9) this.ie9 = true;
    
    if(this.browser=="Safari") this.safari = true;
    if(this.browser=="Firefox") this.firefox = true;
		if(this.browser=="Chrome") this.chrome = true;
		
		if(this.chrome || this.safari) this.webkit = true;
    
    if(this.OS=="Mac") this.mac = true;
    if(this.OS=="Windows") this.windows = true;
    if(this.OS=="Linux") this.linux = true;
    
	},
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.userAgent,
			subString: "Chrome",
			identity: "Chrome"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

};
BrowserDetect.init();


var Console = {
	display:function(msg){
		try{
			if(msg.indexOf("<body>")>-1){
				msg = msg.split('<body>')[1];
				msg = msg.split('</body>')[0];
			}
		}catch(ex){}
		
		$('_console').show();
		$('_console_msg').insert({top:'<div style="margin:5px;padding:5px;border:1px solid #999;">'+msg+"</div>"});
	},
	close:function(){
		$('_console_msg').update('');
		$('_console').hide();
	},
	template_html:['<div id="_console" style="display:none;">','	<div class="_console_ctrl">','		<a href="#" onclick="Console.close();return false;">Close</a>','	</div>','	<div id="_console_msg"></div>','	<div class="cd"></div>','</div>'],
	init:function(){
		$$('body')[0].insert({top:this.template_html.join('\n')});
	}
}

function fade_in(o,que,lam){
	if(lam==undefined){
		var lam = function(){};
	}
	new Effect.Appear($(o), {duration:Core.appear_duration, afterFinish:lam, queue: { position: 'end', scope: que } });
}
function fade_out(o,que,lam){
	if(lam==undefined){
		var lam = function(){};
	}
	new Effect.Fade($(o), {duration:Core.fade_duration, afterFinish:lam, queue: { position: 'end', scope: que } });
}

function slide_in(o,que,lam){
	if(lam==undefined){
		var lam = function(){};
	}
	new Effect.BlindDown($(o), {duration:Core.appear_duration, afterFinish:lam, queue: { position: 'end', scope: que } });
}
function slide_out(o,que,lam){
	if(lam==undefined){
		var lam = function(){};
	}
	new Effect.BlindUp($(o), {duration:Core.fade_duration, afterFinish:lam, queue: { position: 'end', scope: que } });
}
function switch_off(o,que,lam){
	if(lam==undefined){
		var lam = function(){};
	}
	new Effect.SwitchOff($(o), {duration:Core.fade_duration, afterFinish:lam, queue: { position: 'end', scope: que } });
}
function squish(o,que,lam){
	if(lam==undefined){
		var lam = function(){};
	}
	new Effect.Squish($(o), {duration:Core.fade_duration, afterFinish:lam, queue: { position: 'end', scope: que } });
}

function Debug(m){
	Console.display(m);
}


var Core = {
	fade_duration:0.3,
	appear_duration:0.4,
	custom:true,
	debug:false,
	enable_escape_key:false,
	last_key_pressed:-1,
	init:function(cbk){
		Server.use_disconnected_mode=false;//sets this up as faking a server back end
		Server.init();
		Event.observe(document, 'dom:loaded', function(){
			//setInterval(Card.maintain_size.bind(Card),Card.maintain_size_interval);
			Event.observe(window,'resize', Card.maintain_size.bind(Card));
			Event.observe(document, 'mousemove', Tooltip.mousemove);
			
			$$('body')[0].insert({top:'<div class="cd"></div>'});
			Page.init();
			Notice.init();
			Tooltip.init();
			Console.init();
			$$('body')[0].insert({top:'<div id="kernel-panic" style="display:none;">Something went wrong. Please try again.</div>'});
			$$('body')[0].insert({top:'<div id="site-offline" style="display:none;">The site is offline for maintenance; please try back soon.</div>'});
			
			if(cbk != undefined){
				cbk();
			}
		});
	},
	__post_load:null,
	preload_images:function(imgs){
		$A(imgs).each(function(img){
			preload_image = new Image(25,25); 
			preload_image.src=img;
		});
	},
	add_escape_callback:function(c){
		if(!Core.enable_escape_key) return;
		this.escape_key_callbacks.push(c);
	},
	escape_key_callbacks:$A([]),
	on_escape:function(){
		if(!Core.enable_escape_key) return;
		if(this.escape_key_callbacks.length > 0){
			var callback = this.escape_key_callbacks.pop();
			callback();
		}
	}
}


Event.observe(window, 'keydown', function(e){
	try{
		e = window.event ? event : e;
		lastKeyPressed = e.keyCode ? e.keyCode : e.charCode;
		Core.last_key_pressed = lastKeyPressed;
	}catch(ex){
		//for ie
	}
	if(Core.last_key_pressed==27){
		Window.on_escape();
		Window.clear_on_escape();
		Console.close();
	}
	if(Core.last_key_pressed==13 || Core.last_key_pressed==3){
		Window.on_enter();
		Window.clear_on_enter();
	}
});

function onenter(cbk){
	try{
		var e = window.event ? event : e;
		lastKeyPressed = e.keyCode ? e.keyCode : e.charCode;
		if(lastKeyPressed==13 || lastKeyPressed==3) cbk();
	}catch(ex){
		if(Core.last_key_pressed==13 || Core.last_key_pressed==3) cbk();
	}
}




















var PosterController = Class.create({
    name:'',
		disable_hash:true,
		name_singular:'',
    summary:'',
		summary_short:'',
		mode:'',
    controller_path:'',
    order_by:'id desc',
    search_text:'',
    id:-1,
    search_timer:null,
    $details_lock:false,
    tags:[],
    add_new_callback:null,
    add_new_callback_target:null,
		limit:50,
		offset:0,
		details_is_open:false,
		page_loaded:function(){
			this.refresh_list();
		},
		refresh_card:function(n){
			try{
				eval('this.refresh_'+n+"();");
			}catch(ex){
				Card.refresh(this,n);
			}
		},
		close_card:function(n){
			try{
				eval('this.close_'+n+"();");
			}catch(ex){
				Card.hide(this,n);
			}
		},
		sort_from_list:function(o){
			this.sort($F(o));
		},
		initialize:function(name, controller_path){
        this.name = name;
        this.controller_path = controller_path;
    },
		get_args_from_string:function(prefix,str,extra_cbk){
			var iargs = {};
			eval('var ag = this.'+str);
			prefix = prefix+'_';

			$w(ag).each(function(t){
				try{
					iargs[t.toString()] = $F(prefix+this.name+'_'+t);
				}catch(ex){
					try{
						iargs[t.toString()] = $F(prefix+this.name_singular+'_'+t);
					}catch(ex){
						Warn('Could not find ' + prefix+this.name_singular+'_'+t);
					}
				}
			}.bind(this));

			if(extra_cbk!=null){
				eval('var extras = this.'+extra_cbk+'();');
				if(extras!=null){
					Object.keys(extras).each(function(k){
						iargs[k] = extras[k];
					});
				}
			}

			return iargs;
		},
	
		fit_poster:function(){
			Warn('fit_poster2');
			return false;
			Poster.fit_poster_to_content('poster_'+this.name);
		},
		show_page:function(pg){
			this.offset = pg*this.limit;
			this.refresh_list();
		},
		toggle_show_deleted:function(){
			//clear the pagnation on changing the criteria
			this.offset = 0;
			this.refresh_list();
		},
    //before_search:function(){return true;}
    //after_search:function(){}
    search_keyup:function(o){
			
       if(this.search_timer != null) clearTimeout(this.search_timer);
       o=$(o);
       stx = $F(o).strip();
			
			if(this.search_text == stx){
				return;
			}else{
				this.search_text = stx;
			}
			
			if($(this.name+'_list_search') != null){
				$(this.name+'_list_search').value = stx;
			}
			
       if(this.before_search != null){
           if(!this.before_search()) return;
       }

			
			//clear the pagnation on searching
			this.offset = 0;
			
       this.search_timer = setTimeout(function(){
           this.refresh_list(function(){
               if(this.after_search != null){this.after_search();}
           }.bind(this));
       }.bind(this), 250);
    },
		
		search_blur:function(o){
			if($F(o)==''){
				$('recording_list_home_search').value = this.default_search_box_text;
			}
			
			if($F(o)==this.default_search_box_text){
				$('recording_list_home_search').addClassName('dim_search');
			}else{
				$('recording_list_home_search').removeClassName('dim_search');
			}
		},
		search_focus:function(o){
			if($F(o)==this.default_search_box_text){
				$('recording_list_home_search').value = '';
			}
			$('recording_list_home_search').removeClassName('dim_search');
		},
    
    //before_refresh_list:function(){return true;}
    //after_refresh_list:function(){}
		open:function(mode){
			this.mode=mode;
			this.refresh_list();
		},
		
		refresh_list_target:function(){
			return 'content_'+this.name;
		},
		refresh_list_search_box_src:function(){
			return this.name+'_list_search';
		},
		refresh_list_target_list:function(){
			return 'list_'+this.name;
		},
    refresh_list:function(callback){
        //if the child object has a before_refresh_list, and it returns false, we do not refresh the list
        if(this != null && this.before_refresh_list != null){
            if(!this.before_refresh_list()) return;
        }
        var tmd = '';
				try{
				tmd = $F(this.name+'_tag_mode').toString();
  			}catch(ex){}
				//conditions for the server
				var conditions = {order:this.order_by, text:this.search_text, limit:this.limit, offset:this.offset, tag_ids:this.tags, tag_mode:tmd, mode:this.mode};
				
				//add in optional criteria
				if($(this.name+'_list_show_deleted') != null){
					conditions['show_deleted'] = $(this.name+'_list_show_deleted').checked;
				}
				var srcsrc = this.refresh_list_search_box_src();
				if($(srcsrc) != null){
					conditions['search'] = $F(srcsrc);
					if(conditions['search']=='') conditions['search'] = null;
				}
				
				//pass along extra data if needed, and override any default items (like the two added above)
				var extra_data = $H(this.refresh_list_args());
				extra_data.each(function(pair){
					conditions[pair.key] = pair.value;
				});
				
				var tgt = this.refresh_list_target();
				Loading(tgt);
				
        //actually refresh the list
        Request(this.controller_path + '/list', conditions, function(r){
            Loaded(tgt);
						
						var tgt2 = this.refresh_list_target_list();
            $(tgt2).update(r.html);
						
            this.after_refresh_list(r);
            if(callback != null) callback();
        }.bind(this));
    },
		//extra data to send to server on list reload
		refresh_list_args:function(){
			return {};
		},
		//post list load actions
		after_refresh_list:function(r){
			
		},
    
    //before_sort:function(){return true;}
    //after_sort:function(){}
    sort:function(by){
			if(this.display != undefined && this.display=='grid'){
				this.order_by = by;
			}else{
				var now_desc = this.order_by.indexOf(' desc')>=0
				var now_asc = this.order_by.indexOf(' asc')>=0

				var want_desc = by.indexOf(' desc')>=0
				var want_asc =  by.indexOf(' asc')>=0

				var ob_strip = this.order_by.gsub(' asc', '').gsub(' desc', '').strip();
				var by_strip = by.gsub(' asc', '').gsub(' desc', '').strip();

				if(ob_strip==by_strip){
					if(now_desc){
						this.order_by = by_strip + ' asc';
					}else{
						this.order_by = by_strip + ' desc';
					}
				}else{
					this.order_by = by;
				}
			}
			
			
      if(this.before_sort != null){
          if(!this.before_sort()) return;
      }
      
      this.refresh_list(function(){
          if(self.after_sort != null){self.after_sort();}
      });
    },
		
		
		get_fields_as_args:function(){
			var a = {};
			Warn("not right");
			Object.keys(Map).each(function(t){
				eval('if(Object.isString(this.'+t+')){a.'+t+'=Map.'+t+'}');
				eval('if(Object.isNumber(this.'+t+')){a.'+t+'=Map.'+t+'}');
				eval('if(Object.isHash(this.'+t+')){a.'+t+'=Map.'+t+'}');
				eval('if(Object.isArray(this.'+t+')){a.'+t+'=Map.'+t+'}');
			}.bind(this));
			
			return a;
		},
		
		
		flash_details_ok:function(){
      Poster.flash_ok(this.name);
		},
		flash_details_error:function(){
      Poster.flash_error(this.name);
		},
		
		
		
		warn:function(msg, tgt){
			Warn(msg);
			if(tgt==undefined || tgt==null){
				tgt = this.$name;
			}
			Poster.flash_error(tgt);
		},
		
		
		
		
		
		is_editing:false,
		tgt_prefix:function(){
			if(this.is_editing){
				return 'edit';
			}else{
				return 'new';
			}
		},
		start_edit:function(){
			args = {id:this.id};
			var tgt = $('preview-pane-inner');
			this.is_editing = true;
			LoadingInline(tgt);
			Request(this.controller_path+'/edit', args, function(r){
				LoadedInline(tgt);
				this.details_is_open = true;
				tgt.update(r.html);
				// $('prev-pane-closer').onclick = function(){
				// 					this.close_edit();
				// 				}.bind(this);
			}.bind(this));
		},
		close_edit:function(){
			this.is_editing = false;
			this.load_details();
		},
		
		
		mark_poster_status:function(deleted){
			if(deleted){
				this.mark_poster_deleted();
			}else{
				this.unmark_poster_deleted();
			}
		},
		mark_poster_deleted:function(){
			try{
				$(this.name+'_delete_button').hide();
				$(this.name+'_restore_button').show();
			
				$('poster_'+this.name).select('.poster_content')[0].addClassName('red_poster_content');
				var pci = $('poster_'+this.name).select('.icon')[0];
				var src = pci.src;
				pci.src = src.replace('_deleted.png', '.png').replace('.png', '_deleted.png');
			}catch(ex){}
		},
		unmark_poster_deleted:function(){
			try{
				$(this.name+'_delete_button').show();
				$(this.name+'_restore_button').hide();
			
				$('poster_'+this.name).select('.poster_content')[0].removeClassName('red_poster_content');
				var pci = $('poster_'+this.name).select('.icon')[0];
				var src = pci.src;
				pci.src = src.replace('_deleted.png', '.png');
			}catch(ex){}
		},
		set_poster_icon:function(icon,deleted){
			try{
			  var icurl = '/images/icons/128/'+icon;
			  if(deleted){
			    icurl = icurl + '_deleted';
			  }
	      icurl = icurl + '.png';
				var pci = $('poster_'+this.name).select('.icon')[0].src = icurl;
			}catch(ex){}
		},
		
		
	
		
		
		


		
		
		
		
		
		
		refresh_after_save:true,
		before_save:function(args){return true;},
		after_save_ok:function(r){
			if(this.refresh_after_save){
				this.refresh_list();
			}
			//Poster.flash_ok(this.name);
		},
		after_save_fail:function(r){},
		get_save_args:function(){
			var args = this.get_args_from_string('edit','save_args_string','extra_save_args');
			args['id'] = this.id;
			return args;
		},
		extra_save_args:function(){return null;},
		save:function(){
			var args = this.get_save_args();
			var cont = this.before_save(args);
			
			if(!cont){
				this.on_save_error();
				return;
			}
			
			Request(this.controller_path+'/save', args, function(r){
				this.base_after_save(r);
			}.bind(this),{ error_callback: function(r){ this.on_save_error.apply(this,[r.msg]); }.bind(this)});
		},
		base_after_save:function(r){
			if(r.ok){
				this.after_save_ok(r);
			}else{
				this.after_save_fail(r);
			}
		},
		on_save_error:function(m){
			Poster.flash_error(this.name,m);
		},
		
		
		
		
		get_delete_description:function(){
			return ['Are you sure you want to delete ' + this.summary + '?'];
		},
		get_delete_label:function(){
			return 'Delete';
		},
		start_delete:function(){
			Dialogue.show({
				html:this.get_delete_description(),
				img:'/images/edit/remove_64.png',
				ok_label:this.get_delete_label(),
				on_ok:function(){
					this.do_delete();
				}.bind(this)
			});
		},
		do_delete:function(){
			Request(this.controller_path+'/delete', {id:this.id}, function(r){
				if(r.ok){
					this.after_delete(r);
				}
			}.bind(this));
		},
		after_delete:function(r){
			this.close_details();
			this.refresh_list();
		},
		
		get_restore_description:function(){
			return ['Are you sure you want to restore ' + this.summary + '?'];
		},
		get_restore_label:function(){
			return 'Restore';
		},
		start_restore:function(){
			Dialogue.show({
				html:this.get_restore_description(),
				img:'/images/edit/restore_64.png',
				ok_label:this.get_restore_label(),
				on_ok:function(){
					this.do_restore();
				}.bind(this)
			});
		},
		do_restore:function(){
			Request(this.controller_path+'/restore', {id:this.id}, function(r){
				this.after_restore(r);
			}.bind(this));
		},
		after_restore:function(r){
			this.close_details();
			this.refresh_list();
		},
    
		
		_after_start_new:function(details_r, complete_ui_callback){
			if(this.after_start_new != null) this.after_start_new(details_r);
			complete_ui_callback();
		},
		load_start_new:function(callback, target_area){
			
			var details_args = {};
			if(this.load_start_new_args != null){
				details_args = this.load_start_new_args();
			}

			Request(this.controller_path+'/new', details_args, function(r){
				Page.stop_spinning(target_area);
				if(r.ok){
					$(target_area).update(r.html);
					callback.apply(this, [true, r, this._after_start_new]);
				}else{
					$(target_area).update(r.msg);
					callback.apply(this, [false, r, this._after_start_new]);
				}
			}.bind(this));
		},
		
		allow_multi_tags:true,
		take_tag:function(o,tid){
			if(this.allow_multi_tags){
				if(o.hasClassName('selected')){
	        o.removeClassName('selected');
	        this.tags = this.tags.without(tid);
	      }else{
	        o.addClassName('selected');
	        this.tags.push(tid);
	      }
			}else{
				$$('.tag.selected').each(function(t){t.removeClassName('selected');});
				this.tags = [tid];
			}
      
      
      
      
      
      //this.tag_mode = $F($(o).up('.grid_tags').select('.tag_sel_type')[0]);
      this.offset = 0;
      this.refresh_list();
    },
    
    clear_all_tags:function(o){
    
    	$(o).up().select('.selected').each(function(t){t.removeClassName('selected');});
    	this.tags = [];
    	this.refresh_list();
    },
    
    
		after_take_tag_details:null,
    take_tag_details:function(o,tid){
      if(o.hasClassName('selected')){
        o.removeClassName('selected');
      }else{
        o.addClassName('selected');
      }
      
      Request(this.controller_path+'/change_tag', {id:this.id,tag_id:tid}, function(r){
				if(this.after_take_tag_details==null){
					this.refresh_list();
				}else{
					this.after_take_tag_details(r);
				}
        
      }.bind(this));
    },

		after_take_tag_details:null,
    take_tag_details:function(o,tid){
      if(o.hasClassName('selected')){
        o.removeClassName('selected');
      }else{
        o.addClassName('selected');
      }
      
      Request(this.controller_path+'/change_tag', {id:this.id,tag_id:tid}, function(r){
				if(this.after_take_tag_details==null){
					this.refresh_list();
				}else{
					this.after_take_tag_details(r);
				}
        
      }.bind(this));
    },
		
		
		
		
		
		
		
		
		
		//ok
		//ok
		//ok
		details:function(id,kill_animation){
			if(!this.before_details()){return;}
			this.id = id;
			this.details_is_open = true;
			var n = Card.show(this,'details',this.base_after_details.bind(this),kill_animation);
		},
		refresh_details:function(){
			var id = this.id;
			// this.close_details();
			this.details(id,true);
		},
		close_details:function(){
			this.id = -1;
			this.details_is_open = false;
			Card.hide(this,'details');
			this.after_close_details();
		},
		after_details_ok:function(){},
		after_details_always:function(){},
		after_details_fail:function(){},
		after_close_details:function(){},
		before_details:function(){return true;},
		extra_details_args:function(){return {};},
		get_details_args:function(){
			var args = this.extra_details_args();
			args['id'] = this.id;
			return args;
		},
		base_after_details:function(n,r){
			this.after_details_always(r);
			if(r.ok){
				this.deleted = r.deleted;
				this.summary = r.summary;
				this.after_details_ok(r);
			}else{
				this.after_details_fail(r);
			}
			if(this.deleted){
				Card.mark_focussed_deleted();
			}else{
				Card.unmark_focussed_deleted();
			}
		},
		
		start_create:function(){
			if(!this.before_start_create()){return;}
			this.start_create_is_open = true;
			var n = Card.show(this,'start_create',this.base_after_start_create.bind(this));
		},
		refresh_start_create:function(){
			// this.close_start_create();
			this.start_create();
		},
		close_start_create:function(){
			this.id = -1;
			this.start_create_is_open = false;
			Card.hide(this,'start_create');
			this.after_close_start_create();
		},
		after_start_create_ok:function(){},
		after_start_create_always:function(){},
		after_start_create_fail:function(){},
		after_close_start_create:function(){},
		before_start_create:function(){return true;},
		extra_start_create_args:function(){return {};},
		get_start_create_args:function(){
			var args = this.extra_start_create_args();
			return args;
		},
		base_after_start_create:function(n,r){
			this.after_start_create_always(r);
			if(r.ok){
				this.after_start_create_ok(r);
			}else{
				this.after_start_create_fail(r);
			}
		},
		
		after_create_ok:function(r){},
		after_create_fail:function(r){},
		before_create:function(args){
			return true;
		},
		get_create_args:function(){
			var args = this.get_args_from_string('new','create_args_string','extra_create_args');
			args['id'] = this.id;
			return args;
		},
		extra_create_args:function(){return null;},
		create:function(){
			var args = this.get_create_args();
			args['id'] = null;
			var cont = this.before_create(args);
			
			if(!cont){
				//this.on_create_error("Whoops");
				return;
			}
			
			Request(this.controller_path+'/create', args, function(r){
				this.base_after_create(r);
			}.bind(this));
		},
		after_create_always:function(r){
			
		},
		refresh_after_create:true,
		base_after_create:function(r){
			this.after_create_always(r);
			if(r.ok){
				if(this.refresh_after_create){
					this.refresh_list();
				}
				this.close_start_create();
				this.after_create_ok(r);
			}else{
				this.after_create_fail(r);
			}
		},
		
		
		switch_card_tab:function(o,n,act){
			var ct = $(o).up('.contents');
			ct.select('.tabs a.selected').each(function(t){t.removeClassName('selected');});
			$(o).addClassName('selected');
			ct.select('.tab_area').each(function(t){t.hide();});
			$('card_'+act+'_tab_'+n).show();
			this.refresh_card_tab(n,act);
		},
		refresh_card_tab:function(ta,act){
			var n = Card.name_from_pc(this,act);
			var tgt = $('card_'+act+'_tab_'+ta);
			eval('var args = this.get_'+act+'_args();');
			args.tab_name = ta;
			Request(this.controller_path+'/'+act+'_tab', args, function(r){
				var oo = "this.after_refresh_card_tab_"+act+"_"+ta;
				eval("if("+oo+"!=undefined){"+oo+"();setTimeout(function(){Card.content_changed();},400);}");
			}.bind(this),tgt);
		},
		
		
		hover_thumb:function(o){
			$(o).up().select('.thumb').each(function(t){$(t).addClassName('dimmed');$(t).removeClassName('litup');});
			$(o).removeClassName('dimmed');
			$(o).addClassName('litup');
		},
		blur_thumb:function(o){
			$(o).up().select('.thumb').each(function(t){$(t).removeClassName('dimmed');$(t).removeClassName('litup');});
		},
		
		
		
		//custom
		something:function(){
			
		}
		
    
});








function getcords_insp(e){
	//get the position of the container, prototype functionality
	var containerLeft = $('details').cumulativeOffset()[0];
	var containerTop = $('details').cumulativeOffset()[1];

	//get the mouse coordinates
	mouseX = Event.pointerX(e);
	mouseY = Event.pointerY(e);

	//calculate the absolute mouse position in the div,
	//by mouseposition minus left position of the container
	horizontalPosition = mouseX - containerLeft;
	verticalPosition = mouseY - containerTop;

	//use prototypes function to get the dimension
	//this is a VERY usefull function because it also checks for borders
	containerDimensions = $('details').getDimensions();
	height   = containerDimensions.height;
	width = containerDimensions.width;

	//check if the mouse is out or inside the div
	//this if statement checks if the cursor is inside the div
	if(horizontalPosition < 0 || verticalPosition < 0 || mouseX > (width + containerLeft) || mouseY > (height + containerTop) ){
		Map.insp_blocker = false;
		Map.close_details();
	}else{
		Map.clear_insp_timer();
		Map.insp_blocker = true;
	}
}
















var Notice = {
	template_html:['<div id="notifications"><div></div></div>','<div id="throbber" style="display:none;"><img src="/images/ui/throbber.gif"></div>'],
	init:function(){
		$$('body')[0].insert({top:this.template_html.join('\n')});
	},
	throb_delay:200,
	flock:false,
	thtm:null,
	show_thobber:function(cbk){
		Effect.Queues.get('throbbersc').invoke('cancel');
		if(this.thtm!=null){
			clearTimeout(this.thtm);
		}
		this.thtm = setTimeout(function(){
			new Effect.Appear('throbber', {duration:0.25,queue: { position: 'end', scope: 'throbbersc' } });
			if(cbk != undefined){cbk();}
		},this.throb_delay);
	},
	hide_thobber:function(cbk){
		if(this.thtm!=null){
			clearTimeout(this.thtm);
		}
		Effect.Queues.get('throbbersc').invoke('cancel');
		new Effect.Fade('throbber', {duration:0.1, queue: { position: 'end', scope: 'throbbersc' } });
		if(cbk != undefined){cbk();}
	},
	
	//if you set this to true then infinite notices can pile up on the screen
	//if false, then only one notice will show up (the last one set)
	enable_multiple_notices:true,
	last_notice:null,
	pulsate:function(id){
		new Effect.Pulsate(id, {pulses:1, duration:0.25});
	},
	pulsate2x:function(id){
		new Effect.Pulsate(id, {duration:1.0, pulses:2});
	},
	pulsate3x:function(id){
		new Effect.Pulsate(id, {duration:0.6, pulses:3});
	},
	shake:function(id){
		new Effect.Shake(id, {duration:0.25});
	},
	flash_ok:function(id){
		new Effect.Highlight($(id), {startcolor:'#91e852', keepBackgroundImage:true, duration:0.5});
	},
	flash_text_ok:function(id){
		var end_color = $(id).style.color;
		
		//if the sender element does not have a specific color set we assume black othwise the second morph breaks
		if(end_color==null || end_color == undefined || end_color=='') end_color = '#000';
		
		new Effect.Morph(id, {style:{color:'#6bff00'}, duration:0.1});
		setTimeout(function(){
			new Effect.Morph(id, {style:{color:end_color}, duration:0.25});
		},200);
	},
	flash_error:function(id){
		new Effect.Highlight($(id), {startcolor:'#ec0000', keepBackgroundImage:true, duration:0.5});
	},
	flash_text_error:function(id){
		var end_color = $(id).style.color;
		
		//if the sender element does not have a specific color set we assume black othwise the second morph breaks
		if(end_color==null || end_color == undefined || end_color=='') end_color = '#000';
		
		new Effect.Morph(id, {style:{color:'#ff0000'}, duration:0.1});
		setTimeout(function(){
			new Effect.Morph(id, {style:{color:end_color}, duration:0.25});
		},200);
	},
	clear_all:function(){
		$$('a_bar_any').each(function(t){if(!t.hasClassName('a_bar_prototype')){t.remove()}});
	},
	/*responds to a server request's return object with a positive or negative UI feedback*/
	respond:function(r){
		if(r.success){
			Notice.success_text(r.msg);
		}else if(r.ok === false){
			Notice.warn_text(r.msg);
		}else{
			Notice.text(r.msg);
		}
	},
	//syntactic sugar is Warn(m)
	warn_text:function(m){
		if(m==undefined || m==null || m.length==0) return;
		Window.error();
		Notice.create({text:m, is_error:true});
	},
	success_text:function(m){
		if(m==undefined || m==null || m.length==0) return;
		Window.success();
		Notice.create({text:m, is_success:true});
	},
	//calling from outer wrapper so you don't have to click on the colored portion of the bar to kill
	//the notice
	dismiss_outer:function(o){
		try{
			Notice.dismiss($(o).childElements()[1]);
		}catch(ex){}
	},
	dismiss:function(o){
		//IE will not recognize when the user clicks on the info bar, and when it recognizes
		//a click on the close X it does things oddly. so we process IE separately.
		if(BrowserDetect.ie7 || BrowserDetect.ie8){
			//in case the element is deleted already
			try{
				if(o.nodeName.toLowerCase()=='a'){
					$(o).up().up().remove();
				}else{
					$(o).remove();
				}
			}catch(ex){}
		}else{
			try{
				o=$(o);
				try{
					if(!o.hasClassName('a_bar_any')){
						o = o.up('div')[0].up();
					}
				}catch(ex){}//who cares--thrown if they click the x, not the bar.
				new Effect.Puff(o, {duration:0.25});
				setTimeout(function(){o.remove();},255);
				//o.remove();
			}catch(ex){}//in case the element was deleted
		}
	},
	//syntactic sugar is Say(m)
	text:function(m){
		if(m==undefined || m==null || m.length==0) return;
		Window.neutral();
		Notice.create({text:m});
	},
	//does a text notify that does not auto-hide for 5 min
	warn_permanent:function(text){
		if(m==undefined || m==null || m.length==0) return;
		Notice.create({text:m,period:300000});
	},
	
	create:function(args){
		
		if(!this.enable_multiple_notices && this.last_notice != null){
			this.dismiss(this.last_notice);
			this.last_notice = null;
		}
		
		var style = 'a_bar_notification';
		var period=7*1000;
		
		if(args.is_error===true) style = 'a_bar_error';
		if(args.is_success===true) style = 'a_bar_success';
		if(args.period>0) period = args.period;
		
		var back_img_override = '';
		
		//allow the icon to the left of the message to be changed
		if(args.back_img_override != null){
			back_img_override = ' style="background-image:url(images/ui/' + args.back_img_override + '.png);" ';
		}
		
		
		
		var html = '<div class="not_content" ' + back_img_override + '>' + args.text + '</div>';
		
		
		var a = new Element('div', { 'class': 'a_bar_any', onclick: 'Notice.dismiss(this);' }).update(html);
		a.addClassName(style);
		
		this.last_notice = a;
		
		setTimeout(function(){
			Notice.dismiss(a);
			Notice.last_notice = null;
		}, period);
		
		
		$('notifications').childElements()[0].insert({before:a});
		// if(Notice.flock==false){
		//      Notice.false = true;
		//      new Effect.Pulsate('notifications',{duration:0.8,pulses:2})
		//      setTimeout(function(){Notice.flock=false;},810)
		//    }
	}
}

//syntactic sugar
function Say(m){
	Notice.text(m);
}

//syntactic sugar
function Warn(m){
	Notice.warn_text(m);
}

//syntactic sugar
function Success(m){
	Notice.success_text(m);
}

function Fatal(m){
	Window.fatal(m);
}

function Panic(){
	Window.panic();
}

function Offline(){
	Window.offline();
}

function Throb(cbk){
	Notice.show_thobber(cbk);
}

function Unthrob(cbk){
	Notice.hide_thobber(cbk);
}

function Loading(divs){
	Throb(function(){
		var dvs = $w(divs);
		if(dvs.length>0){
			Effect.Queues.get('throbberdv').invoke('cancel');
			dvs.each(function(t){
				new Effect.Opacity(t, { from: 1.0, to: 0.3, duration: 0.3, queue: { position: 'end', scope: 'throbberdv' } });
			});
		}
	});
}

function Loaded(divs){
	Unthrob(function(){
		var dvs = $w(divs);
		if(dvs.length>0){
			Effect.Queues.get('throbberdv').invoke('cancel');
			dvs.each(function(t){
				//$(t).setOpacity(1.0);
				new Effect.Opacity(t, { from: $(t).getOpacity(), to: 1.0, duration: 0.3, queue: { position: 'end', scope: 'throbberdv' } });
			});
		}
	});
}

function LoadingInline(t){
	Effect.Queues.get('throbberinlinedv').invoke('cancel');
	t.update("");
	t.addClassName('loading-inline');
	new Effect.Opacity(t, { from: 1.0, to: 0.3, duration: 0.3, queue: { position: 'end', scope: 'throbberinlinedv' } });
}

function LoadedInline(t){
	Effect.Queues.get('throbberinlinedv').invoke('cancel');
	t.removeClassName('loading-inline');
	new Effect.Opacity(t, { from: $(t).getOpacity(), to: 1.0, duration: 0.3, queue: { position: 'end', scope: 'throbberinlinedv' } });
}




//only for ok/cancel dialogues
//hmm this looks like it only supports a single ok/cancel at a time. should be
//ok though since you cannot spawn an action from these. or you could, but you
//shouldn't, logically
//however these should actually be queued up, because when you chain them together it sort of breaks in that
//you need to use setTimeout to keep from hiding the second sheet you just asked for.
var Dialogue = {
	text:function(m){
		Dialogue.show({html:m});
	},
	//if an array turns into nice html, otherwise returns as-is
	turn_array_into_html:function(a){
		if(a.constructor.toString().indexOf("Array") == -1){
			return a;
		}else{
			var h = '';
			if(a.length>0){
				h = '<h1>' + a[0] + '</h1>';
				for(i=1;i<a.length;i++){
					h += '<p>' + a[i] + '</p>';
				}
			}
			return h;
		}
	},
	//show:function(img,html,on_ok,on_cancel,ok_label,cancel_label){
	show:function(args){
		//check for empty callbacks
		if(args.on_ok==null) args.on_ok = function(){};
		if(args.on_cancel==null) args.on_cancel = function(){};
		
		//check for no labels
		if(args.ok_label==null) args.ok_label = "Ok";
		if(args.cancel_label==null) args.cancel_label = "Cancel";
		
		//update html
		var the_html = Dialogue.turn_array_into_html(args.html);
		$('vh_dialogue_content_holder').update(the_html);
		
		//assign generic or custom icon
		if(args.img!=null){
			$('vh_dialogue_content_holder').style.backgroundImage = 'url('+args.img+')';
		}else{
			$('vh_dialogue_content_holder').style.backgroundImage = 'url(images/ui/info.png)';
		}
		
		//wire up cancel and ok buttons
		if(args.suppress_cancel_button){
		  $('dialogue_button_cancel').hide();
		}else{
		  $('dialogue_button_cancel').show();
		}
		
		if(BrowserDetect.ie6){
			$('dialogue_button_cancel').value = args.cancel_label;
		}else{
			$('dialogue_button_cancel').down().down().update(args.cancel_label);
		}
		
		var cancf = function(){
			try{
				args.on_cancel();
			}catch(ex){
				Notice.text(ex);
			}
			Dialogue.hide_dialogue();
		};
		Window.set_on_escape(cancf);
		$('dialogue_button_cancel').onclick = cancf;
		
		if(BrowserDetect.ie6){
			$('dialogue_button_ok').value = args.ok_label;
		}else{
			$('dialogue_button_ok').down().down().update(args.ok_label);
		}
		
		var okf = function(){
			try{
				args.on_ok();
			}catch(ex){
				Notice.text(ex);
			}
			Dialogue.hide_dialogue();
		};
		Window.set_on_enter(okf);
		$('dialogue_button_ok').onclick = okf;
		
		//show the completed UI
		Dialogue.show_diaglogue();
	},
	resize_dialogue:function(){
		var d = $('dialogues');
		var inner = d.select('.vh_dialogue_content')[0];
		var h = inner.getHeight();
		
		d.style.top = '50%';
		d.style.marginTop = '-' + (d.getHeight()/2).toString() + 'px';
	},
	hide:function(){
		Dialogue.hide_dialogue();
	},
	show_diaglogue:function(){
		Window.stack('dialogue_special____');
		
		if(BrowserDetect.ie6){
			$$('.content select').each(function(t){
				if($(t).visible()){
					t.addClassName('ie_only_hide');
				}
			});
		}
		
		$('dialogues').show();
		//resize to fit content
		Dialogue.resize_dialogue();
	},
	hide_dialogue:function(){
		Window.clear_on_enter();
		Window.clear_on_escape();
		$('dialogues').hide();
		Window.unstack('dialogue_special____');
		if(BrowserDetect.ie6){
			$$('.ie_only_hide').each(function(t){t.removeClassName('ie_only_hide');});
		}
	},
	make_red:function(name){
		$(name).removeClassName('green_528_box');
		$(name).addClassName('red_528_box');
	},
	make_green:function(name){
		$(name).removeClassName('red_528_box');
		$(name).addClassName('green_528_box');
	},
	make_normal:function(name){
		$(name).removeClassName('red_528_box');
		$(name).removeClassName('green_528_box');
	}
}

//todo--track how many open items there are that require the page to be blurred, and only un-blur when that number is zero.
var Page = {
	template_html:[
	'<div id="dialogues" class="vh_dialogue_sheet" style="display:none;">                                                                                            ',
	'	<div class="vh_dialogue_content" id="vh_dialogue_content">                                                                                                   ',
	'		<div class="vh_dialogue_content_holder" id="vh_dialogue_content_holder">                                                                                 ',
	'			                                                                                                                                                     ',
	'		</div>                                                                                                                                                   ',
	'		<div class="vh_dialogue_buttons" id="d_buttons">                                                                                                         ',
	'			<button type="button" id="dialogue_button_cancel" class="custom_button" onclick="return false;"><span><span>Cancel</span></span></button>            ',
	'			<button type="button" id="dialogue_button_ok" class="custom_button primary" onclick="return false;"><span><span>Ok</span></span></button>     ',
	'		</div>                                                                                                                                                   ',
	'	</div>                                                                                                                                                       ',                                                                                                                                                   
	'</div>                                                                                                                                                          ',
	'<div id="page_dim" style="display:none;"></div>'
	],
	init:function(){
		$$('body')[0].insert({top:this.template_html.join('\n')});
	},
	
	
	
	
	
  spinny_timers:{},
  //under 200ms response time is instant
  start_spinning:function(o){
    Page.start_spinning_actual(o,Page.spinny_html);
  },
  start_spinning_small:function(o){
    Page.start_spinning_actual(o,Page.spinny_small_img);
  },
  //separated out because we have a few different spinners depending on where on the page the element is
  start_spinning_actual:function(o,spin_html){
    if(Page.spinny_timers[o] != null){
      clearTimeout(Page.spinny_timers[o]);
    }
    Page.spinny_timers[o] = setTimeout(function(){
      //not sure why but ff throws errors sometimes on this
			try{
				if($(o).innerHTML.strip()==''){
					$(o).update(spin_html);
				}else{
					$(o).setOpacity(0.2);
				}
			}catch(e){}
    }, 250);
  },
  stop_spinning:function(o){
    if(Page.spinny_timers[o] != null){
      clearTimeout(Page.spinny_timers[o]);
    }
		$(o).setOpacity(1);
  },
	spinny_html:'<div class="spinny_for_dialogues"></div>',
	black_spinny_html:'<div class="black_spinny_for_dialogues"></div>',
	spinny_small_img:'<img src="/images/ui/spinny_small.gif" />',
	blur:function(){
		Effect.Queues.get('pagedimq').invoke('cancel');
		new Effect.Appear($('page_dim'), {duration:0.05, queue: { position: 'end', scope: 'pagedimq' } });
	},
	focus:function(){
		Effect.Queues.get('pagedimq').invoke('cancel');
		new Effect.Fade($('page_dim'), {duration:Core.fade_duration, queue: { position: 'end', scope: 'pagedimq' } });
	}
}





var Tooltip = {
	template_html:['<div id="tooltip" style="display:none;"></div>'],
	init:function(){
		$$('body')[0].insert({top:this.template_html.join('\n')});
		
		$$('[tooltip]').reject(function(t){return t.readAttribute('tooltip')===true}).each(function(t){
			if(t.hasAttribute('onmouseover')){
				var mover = t.readAttribute('onmouseover');
			}else{
				var mover = '';
			}
			if(t.hasAttribute('onmouseout')){
				var mout = t.readAttribute('onmouseout');
			}else{
				var mout = '';
			}
			
			t.writeAttribute('onmouseover',mover+';'+"Tooltip.show('"+t.readAttribute('tooltip').gsub("'","\\'")+"');");
			t.writeAttribute('onmouseout',mout+';'+'Tooltip.hide();');
			
			t.writeAttribute('tooltip', true);
		});
		
	},
	change_color:function(color){
		$('tooltip').removeClassName('tooltip_blue');
		$('tooltip').removeClassName('tooltip_black');
		$('tooltip').addClassName('tooltip_'+color);
	},
	absolute_body_mode:false,
	x:0,
	y:0,
	x_incr:10,
	y_incr:10,
	visible:false,
	show:function(m,m2){
		Tooltip.y_incr = 10;
		Tooltip.visible=true;
		var n = "";
		n = "<h1>"+m+"</h1>";
		if(m2 != null && m2 != undefined){
			n = n + "<h2>"+m2+"</h2>";
		}
		$('tooltip').update(n);
		$('tooltip').show();
	},
	show_up:function(m){
		Tooltip.y_incr = -20;
		Tooltip.visible=true;
		$('tooltip').update(m);
		$('tooltip').show();
	},
	hide:function(){
		Tooltip.visible=false;
		$('tooltip').hide();
	},
	mousemove:function(evt){
		x=Event.pointerX(evt);
		y=Event.pointerY(evt);
		var a = $('body').cumulativeOffset();
		x = x + a[0];
		y = y + a[1];
		
		Tooltip.x = x;
		Tooltip.y = y;
		if(Tooltip.visible){
			$('tooltip').style.left = Tooltip.x+Tooltip.x_incr+'px';
			$('tooltip').style.top = Tooltip.y+Tooltip.y_incr+'px';
		}
	}
}











var Tab = {
	template_html:[
	'<div class="tab_top">#{tabs}<div class="cd"></div></div>',
	'#{content}'
	],
	create:function(id,tabs){
		var tmpl = new Template(this.template_html.join('\n'));
		
		var tab_top=[];
		var content=[];
		
		if(tabs.select(function(t){return t.selected==true}).length==0){
			tabs[0].selected = true;
		}
		
		tabs.each(function(t){
			var tooltip = '';
			if(t.tooltip != undefined && t.tooltip != null){
				tooltip = " tooltip=\"" + t.tooltip.gsub('"','\\"') + "\" ";
			}
			
			if(t.selected===true){
				var sel_cl = ' selected ';
				var ta_st = 'display:block;';
			}else{
				var sel_cl = '';
				var ta_st = 'display:none;';
			}
			
			tab_top.push('<div class="tab_tab'+sel_cl+'"><a href="#" onclick="Tab.show(this,\'#{container}\',\''+t.name+'\');return false"'+tooltip+'>'+t.title+'</a></div>');
			
			var html = t.html;
			
			if($(id+'_'+t.name) != null){
				var dh = $(id+'_'+t.name);
				dh.addClassName('tab_content');
				if(t.selected===true){
					dh.style.display = 'block';
				}else{
					dh.style.display = 'none';
				}
				dh.id = 'tab_'+dh.id;
			}else{
				content.push('<div class="tab_content" id="tab_#{container}_'+t.name+'" style="'+ta_st+'">'+html+'</div>');
			}
			
		});
		
		var tmpl_tabs = new Template(tab_top.join('\n'));
		var tmpl_content = new Template(content.join('\n'));
		
		args = {id:id,content:tmpl_content.evaluate({container:id}),tabs:tmpl_tabs.evaluate({container:id})};
		
		$(id).insert({top:tmpl.evaluate(args)});
		$(id).addClassName('tab_outer');
		
		Tooltip.init();
	},
	
	
	
	
	show:function(o, container, tab){
		if(o.nodeName.toLowerCase()=='a'){
			o=o.up();
		}
		$(container).select('.tab_content').each(function(t){t.hide();})
		$(container).select('.tab_tab').each(function(t){t.removeClassName('selected');});
		o.addClassName('selected');
		$('tab_'+container+'_'+tab).show();
	}
}









var Poster = {
	posters:$A([]),
	
	template_html:[
	'<div id="poster_#{name}" class="poster_sheet" style="display:none;">      ',
	'		<img src="images/paste_128.png" class="icon" />        ',
	'		<div class="poster_content">                                         ',
	'			<div class="closer" onclick="Poster.hide(this);"><img src="images/ui/blank.gif"></div>',
	'			<div class="inner chrome_body_offset"     ',
	'				style="">                                                    ',
	'				<h1 id="arrange_y_title">#{title}</h1>                          ',
	'			<div>                                                            ',
	'			<p>                                                              ',
	'				...                                                          ',
	'			</p>                                                             ',
	'			                                                                 ',
	'			                                                                 ',
	'		</div>                                                               ',
	'		                                                                     ',
	'	</div>                                                                   ',
	'		<div class="buttons" style="">                                ',
	'			<div class="buttons">                                            ',
	'				<button type="button" class="custom_button" onclick="Poster.hide(this);"><span><span>Cancel</span></span></button>',
	'				<button type="button" class="custom_button primary_button" onclick="Foo.bar();"><span><span>Save</span></span></button>',
	'			</div>                                                           ',
	'		</div>                                                               ',
	'		                                                                     ',
	'</div>                                                                      ',
	'<div class="poster_middle">                                                 ',
	'</div>                                                                      ',
	'</div>                                                                      '
	],
	
	
	create:function(args){
		if(this.posters.select(function(t){return t.name==args.name}).length==0){
			this.posters.push(args);
			
			var tmpl = new Template(this.template_html.join('\n'));
			var sargs = args;
			
			$('posters').insert({after:tmpl.evaluate(sargs)});
		}
	},
	destroy:function(){
		
	},
	switch_tab:function(o,nm){
	  Warn('switch_tab');
	return false;
		o=$(o);
	  var outer = o.up('.poster_sheet');
	  
    outer.select('.tabs a.selected').each(function(t){t.removeClassName('selected');});
    o.addClassName('selected');
		
    outer.select('.poster_tab_area').each(function(t){
      if(t.hasClassName('p_tab_area_'+nm)){
        t.show();
      }else{
        t.hide();
      }
    });
    
    Poster.fit_poster_to_content(outer.id.replace('poster_',''));
	},
	show:function(name){
		Warn('show');
		var pname = 'poster_'+name;
		var js_open = $(pname).select('.on_open');
		
		Sheet.show_this_one(pname);
		
		if(js_open.length>0){
			var target_area = Poster.find(name).select('.inner')[0];
			var outer_poster = Poster.find(name).select('.poster_content')[0];
			//$(outer_poster).setOpacity(0.2);
			Loading();
			Poster.fit_poster_to_content(pname);
			var buttons = Poster.find(name).select('.buttons')[0];
			// if(buttons != null){
			// 				buttons.hide();
			// 			}
			var load_and_show = function(callback, target_area){
				eval(js_open[0].innerHTML);
			};
			load_and_show.apply(this, [function(ok, details_r, final_callback){
				//if(buttons != null){
					buttons.show();
				//}
				Loaded();
				//$(outer_poster).setOpacity(1.0);
				if(final_callback != null){
					if(details_r.ok && (details_r.no_update==undefined || details_r.no_update == false)){
						$(target_area).update(details_r.html);
					}
					
					final_callback.apply(this, [details_r, function(){
						Poster.fit_poster_to_content(pname);
						if(!ok) Poster.flash_error(target_area);
					}]);
				}else{
					Poster.fit_poster_to_content(pname);
					if(!ok) Poster.flash_error(target_area);
				}
			}.bind(this), target_area]);
		}else{
			Poster.fit_poster_to_content(pname);
		}
	},
	hide:function(o){
		var pstr = this.find(o);
		
		//hide it
		Sheet.hide_this_one(pstr.id);
		
		//hide any open tooltips
		Tooltip.hide();
		
		if(BrowserDetect.ie6){
			$$('.ie_only_hide').each(function(t){t.removeClassName('ie_only_hide');});
		}
		
		this.dim_lower_posters();
	},
	flash_ok:function(o){
		var pstr = this.find(o);
		if(pstr!=null){
		  Notice.flash_ok(pstr.select('.inner')[0]);
		}
	},
	dim:function(o){
		var pstr = this.find(o);
		if(pstr!=null){
		  $(pstr).setOpacity(0.1);
		}
	},
	light:function(o){
		var pstr = this.find(o);
		if(pstr!=null){
		  $(pstr).setOpacity(1.0);
		}
	},
	vanish:function(o){
		var pstr = this.find(o);
		if(pstr!=null){
		  $(pstr).setOpacity(0.0);
		}
	},
	appear:function(o){
		var pstr = this.find(o);
		if(pstr!=null){
		  $(pstr).setOpacity(1.0);
		}
	},
	flash_error:function(o,m){
		var pstr = this.find(o);
		if(pstr!=null){
		  try{
				$(pstr).addClassName('error')
			}catch(ex){}
		}
			// if(m!=undefined && m!=null && m!=''){
			// 				var mlx = 100;
			// 				if(m.length>mlx){
			// 					m = truncate_middle(m,mlx);
			// 				}
			// 				try{
			// 					pstr.select('h1')[0].update(m);
			// 				}catch(ex){}
			// 				Poster.fit_poster_to_content(pstr);
			// 			}
			// 		}
	},
	clear_error:function(o){
		var pstr = this.find(o);
		$(pstr).removeClassName('error')
	},
	does_exist:function(s){
	  return $('poster_'+s) != null
	},
	find:function(o){
		if(typeof o == 'string'){
			//a string name passed in
			o = o.replace('poster_','')
			return $('poster_'+o);
		}else{
			//an object reference passed in
			o=$(o);
			return o.up('.poster_sheet');
		}
	},
	fit_poster_to_content:function(o){
		Warn('fit_poster_to_content');
		return false;
		if(typeof(o)=='string' && o.indexOf('poster_')==-1){
			o = 'poster_'+o;
		}
		$(o).select('.poster_content').each(function(t){t.show();});
		var d = $(o);
		var d2 = $(d.select('.poster_content')[0].select('.inner')[0]);
		
		
		d2.style.height = 'auto';
		d2.style.width = 'auto';
		
		
		var winwi = document.viewport.getWidth();
		if(d2.getWidth()>winwi-100){
			d2.style.width = (winwi-100)+'px';
			d2.style.overflowX = 'scroll';
		}else{
			d2.style.overflowX = '';
		}
		
		var winhi = document.viewport.getHeight();
		if(d2.getHeight()>winhi-200){
			d2.style.height = (winhi-200)+'px';
			d2.style.overflowY = 'scroll';
		}else{
			d2.style.overflowY = '';
		}
		
		
		var ht = d.getHeight();
		var vph = document.viewport.getHeight();
		
		var fcc = vph/2 - ht/2;
		var fcc2 = window.innerHeight/2 - ht/2;

		if(fcc<40){
      d.style.position = 'absolute';
		  fcc = 40;
		}else{
		  d.style.position = 'fixed';
		}

		d.style.top = Math.round(fcc2) + 'px';
		var ht = d.getWidth();
		d.style.marginLeft = '-'+Math.round(ht/2) + 'px';
		
		this.dim_lower_posters();
	},
	dim_lower_posters:function(){
		var posts = $$('.poster_sheet').collect(function(t){if($(t).visible()){return t}else{return null}}).compact();
		var zi = posts.collect(function(t){return parseInt(t.style.zIndex)}).sort().reverse()[0];
		posts.each(function(t){if(parseInt(t.style.zIndex)==zi){t.setOpacity(1.0);}else{t.setOpacity(0.4);}});
	}
}





/* START applesearch object */
		
if (!applesearch)	var applesearch = {};

applesearch.init = function ()
{
	// add applesearch css for non-safari, dom-capable browsers
	if ( navigator.userAgent.toLowerCase().indexOf('safari') < 0  && document.getElementById )
	{
		this.clearBtn = false;
		
		// add style sheet if not safari
		var dummy = document.getElementById("dummy_css");
		if (dummy)	dummy.href = "applesearch.css";
	}
}

// called when on user input - toggles clear fld btn
applesearch.onChange = function (fldID, btnID)
{
	// check whether to show delete button
	var fld = document.getElementById( fldID );
	var btn = document.getElementById( btnID );
	if (fld.value.length > 0 && !this.clearBtn)
	{
		btn.style.background = "white url('srch_r_f2.gif') no-repeat top left";
		btn.fldID = fldID; // btn remembers it's field
		btn.onclick = this.clearBtnClick;
		this.clearBtn = true;
	} else if (fld.value.length == 0 && this.clearBtn)
	{
		btn.style.background = "white url('srch_r.gif') no-repeat top left";
		btn.onclick = null;
		this.clearBtn = false;
	}
}















// Custom selectbox using prototype & scriptaculous
// require prototype 1.6
SelectBox = Class.create();
SelectBox.prototype = {

	// selectbox id passed to replace by custom
    id: 0,
    
    // original selectbox element
    original_selectbox : false,
    
    // misc
    selectText: "please select",
    active_select: null,
    _active: false,
    all_selects: false,
    
    //positions
    options_top : 0,
    options_left : 0,
    select_width : 0,
    
    // animation
    animation_show : 'slide',
    animation_show_interval : 0.5,
    animation_hide : 'slide',
    animation_hide_interval : 0.5,
    
    // select area var
	select_button_id_text: '',
	select_button_class_text : '',
	select_area_id_text: '',
	select_area_class_text: '',
	select_area_active_class_text: '',
	select_text_id_text: '',


	// functions on events
		
	
	// options area var
    option_id_text: '',
    option_holder_id_text: '',
    option_holder_visible_class_text: '',
    option_holder_invisible_class_text: '',

	// construct
    initialize: function (params) {
    	
    	// require id of selectbox
    	if( typeof params.id == 'undefined' ){
    		alert('selectbox id in params required');
    		return false;
    	}
    	
    	//coord data...
    	this.options_top = params.options_top ? params.options_top : 0;
    	this.options_left = params.options_left ? params.options_left : 0;
    	this.select_width = params.select_width ? params.select_width : 0;
    	
    	//animation type ..
    	this.animation_show = params.animation_show ? params.animation_show : this.animation_show;
    	this.animation_hide = params.animation_hide ? params.animation_hide : this.animation_hide;

		//animation interval ..
    	this.animation_show_interval = params.animation_show_interval ? params.animation_show_interval : this.animation_show_interval;
    	this.animation_hide_interval = params.animation_hide_interval ? params.animation_hide_interval : this.animation_hide_interval;
    	
        var id = this.id = params.id;
        this.original_selectbox = $(id);
        
        // select area
        this.select_button_id_text = this.id + '-select-button';
        this.select_button_class_text = 'custom-select-button';
        this.select_area_id_text = this.id + '-select-area';
        this.select_area_class_text = 'select-area';
		this.select_area_active_class_text = 'select-area-active';
        this.select_text_id_text = this.id + '-select-text';
        
        // options area
        this.option_id_text = this.id + '-option-';
        this.option_holder_id_text = this.id + '-options-holder';
        this.option_holder_visible_class_text = 'options-visible';
        this.option_holder_invisible_class_text = 'options-invisible';
        
        // init
        this.createMarkup(id);
        this.initSelectEvent(this.select_button_id_text);
        this.initOptionsEvent($(id));
        this.all_selects = true;

    },

	// init select event
    initSelectEvent: function (button_id) {
        var self = this;
        $(button_id).observe('click', function (event) {
            self.showOptions(event, self);
            Event.stop(event);
        });
    },

	// init option click events
    initOptionsEvent: function (selectBox) {
        var self = this;
        var me = selectBox;
        for (var w = 0; w < me.options.length; w++) {
            if (me.options[w].title.indexOf("title") == -1) {
                $(self.option_id_text + w).observe('click', function (event) {
                    self.showOptions(event, self);
                    self.selectMe(selectBox, this.id.replace(self.option_id_text, ''));
                    Event.stop(event);
                });
            }
        }
    },


    // create dom element with for custom selectbox 
    createMarkup: function (id) {
        var selectBox = $(id);
        var q = id;
        //create and build div structure
        var selectArea = document.createElement("div");
        var left = document.createElement("span");
        left.className = "left";
        selectArea.appendChild(left);
        var disabled = document.createElement("span");
        disabled.className = "disabled";
        selectArea.appendChild(disabled);
        selectBox._disabled = disabled;
        var center = document.createElement("span");
        var button = document.createElement("a");
        var text = document.createTextNode(this.selectText);
        center.id = this.select_text_id_text;
        button.id = this.select_button_id_text;
        var stWidth = selectBox.offsetWidth;
        selectArea.style.width =  this.select_width ? this.select_width + "px" : stWidth + "px";
        button.href = "#";
        button.className = this.select_button_class_text;
        selectArea.className = this.select_area_class_text;
        selectArea.className += " " + selectBox.className;
        selectArea.id = this.select_area_id_text;
        center.className = "center";
        center.appendChild(text);
        selectArea.appendChild(center);
        selectArea.appendChild(button);
        selectBox.className += " outtaHere";
        selectBox.parentNode.insertBefore(selectArea, selectBox);
        var optionsDiv = document.createElement("div");
        var optionsListParent = document.createElement("div");
        optionsListParent.className = "select-center";
        var optionsList = document.createElement("ul");
        optionsDiv.innerHTML += "<div class='select-top'><div class='select-top-left'></div><div class='select-top-right'></div></div>";
        optionsListParent.appendChild(optionsList);
        optionsDiv.appendChild(optionsListParent);
        selectBox._options = optionsList;
        optionsDiv.style.width = this.select_width ? this.select_width + "px" : stWidth + "px";
        optionsDiv._parent = selectArea;
        optionsDiv.className = this.option_holder_invisible_class_text;
        optionsDiv.id = this.option_holder_id_text;
        this.populateSelectOptions(selectBox);
        optionsDiv.innerHTML += "<div class='select-bottom'><div class='select-bottom-left'></div><div class='select-bottom-right'></div></div>";
        document.getElementsByTagName("body")[0].appendChild(optionsDiv);
        selectBox.replaced = true;
        selectBox.up(0).appendChild(selectArea);
    },

    //collecting select options
    populateSelectOptions: function (selectBox) {
        var me = selectBox;
        me._options.innerHTML = "";
        for (var w = 0; w < me.options.length; w++) {
            if (me.options[w].title.indexOf("title") == -1) {
                var optionHolder = document.createElement('li');
                var optionLink = document.createElement('a');
                var optionTxt;
                if (me.options[w].title.indexOf('image') != -1) {
                    optionTxt = document.createElement('img');
                    optionSpan = document.createElement('span');
                    optionTxt.src = me.options[w].title;
                    optionSpan = document.createTextNode(me.options[w].text);
                } else {
                    optionTxt = document.createTextNode(me.options[w].text);
                }
                optionLink.href = "#";
                optionLink.id = this.option_id_text + w;
                if (me.options[w].title.indexOf('image') != -1) {
                    optionLink.appendChild(optionTxt);
                    optionLink.appendChild(optionSpan);
                } else {
                    optionLink.appendChild(optionTxt);
                }
                optionHolder.appendChild(optionLink);
                me._options.appendChild(optionHolder);
                if (me.options[w].selected) {
                    this.selectMe(selectBox, w);
                }
            }
            else if (me.options[w].selected) this.selectMe(me.id, w);
        }
        if (me.disabled) {
            me._disabled.style.display = "block";
        } else {
            me._disabled.style.display = "none";
        }
    },
		
		
		
	// show options area
    showOptions: function (event, selectbox) {
        var self = selectbox;
        var _selectHeight = self.options_top;
        var id = self.id;
        _elem = document.getElementById(self.option_holder_id_text);
        var divArea = document.getElementById(self.select_area_id_text);
        if (self.active_select && self.active_select != _elem) {
        	self.animateHide({
        		id : self.option_holder_id_text,
        		afterFinish: function () {
                    self.active_select.className = self.active_select.className.replace(self.option_holder_visible_class_text, self.option_holder_invisible_class_text);
                    self.active_select.style.height = "auto";
                    self._active.className = self._active.className.replace(self.select_area_active_class_text, '');
                }
        	});
        	
        }
        if (_elem.className.indexOf(self.option_holder_invisible_class_text) != -1) {
            _elem.style.left = "-9999px";
            _elem.style.top = self.findPosY(divArea) + _selectHeight + 'px';
            _elem.className = _elem.className.replace(self.option_holder_invisible_class_text, '');
            _elem.className += " "+self.option_holder_visible_class_text;
			$(_elem.id).setStyle({display:'none'});
            _elem.style.left = self.findPosX(divArea) + self.options_left + 'px';
            divArea.className += " "+self.select_area_active_class_text;
            self._active = divArea;
            self.active_select = _elem;
/*
            if (document.documentElement) {
                document.documentElement.onclick = function (e) {
                    self.hideSelectOptions(e, self)
                };
            } else {
                window.onclick = self.hideSelectOptions;
            }
*/
            self.animateShow({
            	id : self.option_holder_id_text,
            	afterFinish: function () {
					$(_elem.id).setStyle({display:'block'});
            	}
            });
        }
        else if (_elem.className.indexOf(self.option_holder_visible_class_text) != -1) {
            self.animateHide({
        		id : self.option_holder_id_text,
        		afterFinish: function () {
                    _elem.style.height = "auto";
                    _elem.className = _elem.className.replace(self.option_holder_visible_class_text, '');
                    _elem.className += " "+self.option_holder_invisible_class_text;
                    divArea.className = divArea.className.replace(self.select_area_active_class_text, '');
                }
            });
        }
    },
    
    animateHide: function (params) {
    	switch(this.animation_hide) {
    		case 'slide':
		    	Effect.SlideUp(params.id, {
		            duration: this.animation_hide_interval,
		            afterFinish: params.afterFinish
		        });
		        break;
   			case 'fade':
				Effect.Fade(params.id, {
		            duration: this.animation_hide_interval,
		            afterFinish:params.afterFinish
		        });
				break;
				
   			case 'blind':
				Effect.BlindUp(params.id, {
		            duration: this.animation_hide_interval,
		            afterFinish:params.afterFinish
		        });
				break;
				
   			case 'shrink':
				Effect.Shrink(params.id, {
		            duration: this.animation_hide_interval,
		            afterFinish:params.afterFinish
		        });
				break;
				
   			case 'squish':
				Effect.Squish(params.id, {
		            duration: this.animation_hide_interval,
		            afterFinish:params.afterFinish
		        });
				break;
												
        }

    },

    animateShow: function (params) {
		switch(this.animation_show) {
    		case 'slide':
		    	Effect.SlideDown(params.id, {
		            duration: this.animation_show_interval,
		            afterFinish:params.afterFinish
		        });
				break;
			case 'appear':
				Effect.Appear(params.id, {
		            duration: this.animation_show_interval,
		            afterFinish:params.afterFinish
		        });
				break;
			case 'blind':
				Effect.BlindDown(params.id, {
		            duration: this.animation_show_interval,
		            afterFinish:params.afterFinish
		        });
				break;				
				
		}
    },    

	// select option
    selectMe: function (selectField, linkNo) {
        selectNo = selectField.id;
        for (var k = 0; k < selectField.options.length; k++) {
            if (k == linkNo) {
                selectField.options[k].selected = true;
            }
            else {
                selectField.options[k].selected = false;
            }
        }
        textVar = document.getElementById(this.select_text_id_text);
        var newText;
        var optionSpan;
        if (selectField.options[linkNo].title.indexOf('image') != -1) {
            newText = document.createElement('img');
            newText.src = selectField.options[linkNo].title;
            optionSpan = document.createElement('span');
            optionSpan = document.createTextNode(selectField.options[linkNo].text);
        } else {
            newText = document.createTextNode(selectField.options[linkNo].text);
        }
        if (selectField.options[linkNo].title.indexOf('image') != -1) {
            if (textVar.childNodes.length > 1) textVar.removeChild(textVar.childNodes[0]);
            textVar.replaceChild(newText, textVar.childNodes[0]);
            textVar.appendChild(optionSpan);
        } else {
            if (textVar.childNodes.length > 1) textVar.removeChild(textVar.childNodes[0]);
            textVar.replaceChild(newText, textVar.childNodes[0]);
        }
        if (selectField.onchange && this.all_selects) {
            eval(selectField.onchange());
        }
    },

	// find y position
    findPosY: function (obj) {
        var posTop = 0;
        while (obj.offsetParent) {
            posTop += obj.offsetTop;
            obj = obj.offsetParent;
        }
        return posTop;
    },

	//find x position
    findPosX: function (obj) {
        var posLeft = 0;
        while (obj.offsetParent) {
            posLeft += obj.offsetLeft;
            obj = obj.offsetParent;
        }
        return posLeft;
    },

	// hide option area
    hideSelectOptions: function (e, self) {
        if (self.active_select) {
            if (!e) e = window.event;
            var _target = (e.target || e.srcElement);
            if (self.isElementBefore(_target, self.select_area_class_text) == 0 && self.isElementBefore(_target, self.option_holder_id_text) == 0) {
                self.active_select.className = self.active_select.className.replace(self.option_holder_visible_class_text, '');
                self.active_select.className = self.active_select.className.replace(self.option_holder_invisible_class_text, '');
                self.active_select.className += " "+self.option_holder_invisible_class_text;
                self._active.className = self._active.className.replace(self.select_area_active_class_text, '');
                self.active_select = false;

                if (document.documentElement) {
                    document.documentElement.onclick = function () {};
                }
                else {
                    window.onclick = null;
                }
            }
        }
    },

	// check if element
    isElementBefore: function (_el, _class) {
        var _parent = _el;
        do {
            _parent = _parent.parentNode;
        }
        while (_parent && _parent.className != null && _parent.className.indexOf(_class) == -1)
        if (_parent.className && _parent.className.indexOf(_class) != -1) {
            return 1;
        } else {
            return 0;
        }
    }
};














var Window = {
	hash:'',
	zindexbase:1001,
	count:0,
	blurred:false,
	development_mode:true,
	names:[],
	clear_on_enter:function(){
		this.on_enter = function(){};
	},
	clear_on_escape:function(){
		this.on_escape = function(){};
	},
	set_on_enter:function(lam){
		this.on_enter = lam;
	},
	set_on_escape:function(lam){
		this.on_escape = lam;
	},
	on_enter:function(){},
	on_escape:function(){},
	clear_hash:function(){
		Window.hash = '';
		window.location.hash = '';
	},
	fatal:function(m){
		if(this.development_mode){
			Console.display(m);
		}else{
			this.panic();
		}
	},
	panic:function(){
		this.blur();
		$('page_dim').style.zIndex = 89000;
		$('kernel-panic').show();
	},
	offline:function(){
		this.blur();
		$('page_dim').style.zIndex = 89000;
		$('site-offline').show();
	},
	stack:function(name){
		if(this.names.indexOf(name)==-1){
			this.zindexbase += 1;
			this.count += 1;
			this.blur();
			this.names.push(name);
		}
	},
	unstack:function(name){
		if(this.names.indexOf(name)!=-1){
			this.count -= 1;
			this.names = this.names.without(name);
			if(this.count==0) this.focus();
		}
	},
	blur:function(){
		if(this.blurred){return false;}
		this.blurred = true;
		Effect.Queues.get('pagedimq').invoke('cancel');
		new Effect.Appear($('page_dim'), {duration:0.1, queue: { position: 'end', scope: 'pagedimq' } });
	},
	focus:function(){
		if(!this.blurred){return false;}
		this.blurred = false;
		Effect.Queues.get('pagedimq').invoke('cancel');
		new Effect.Fade($('page_dim'), {duration:Core.fade_duration, queue: { position: 'end', scope: 'pagedimq' } });
	},
	error:function(){
		$('page_dim').removeClassName('green');
		$('page_dim').addClassName('red');
		setTimeout(function(){$('page_dim').removeClassName('red');},3000);
	},
	success:function(){
		$('page_dim').addClassName('green');
		$('page_dim').removeClassName('red');
		setTimeout(function(){$('page_dim').removeClassName('green');},3000);
	},
	neutral:function(){
		$('page_dim').removeClassName('red');
		$('page_dim').removeClassName('green');
	}
}


var Card = {
	maintain_size_interval:500,
	names:[],
	focussed:[],
	
	
	set_title:function(s){
		var fc = $(Card.focussed[0]);
		fc.select(".contents .leader .h1").each(function(t){
			t.update(s);
		})
	},
	set_sub_title:function(s){
		var fc = $(Card.focussed[0]);
		fc.select(".contents .leader .h2").each(function(t){
			t.update(s);
		})
	},
	
	content_changed:function(n){
		if(n==undefined){
			Card.fit_current.apply(Card);
		}else{
			Card.fit.apply(Card,[n]);
		}
	},
	refresh:function(obj,act,lam){
		this.show(obj,act,lam,true);
	},
	exists:function(obj,act){
		var n = this.name_from_pc(obj,act);
		return this.names.indexOf(n) != -1
	},
	show:function(obj,act,lam,kill_animation){
		var n = this.name_from_pc(obj,act);
		if(!this.exists(obj,act)){
			var str = "<div id='"+n+"' class='card' style='display:none;'></div>"
			$('body').insert({top:str});
		}
		try{
			eval("var args = obj.get_"+act+"_args();");
		}catch(ex){
			var args = {};
		}
		this.create(n,obj,act,args,lam,kill_animation);
		Window.stack(n);
		
		if(this.focussed.indexOf(n)==-1){
			this.focussed.push(n);
		}
		return n;
	},
	hide:function(obj,act){
		var n = this.name_from_pc(obj,act);
		if(this.exists(obj,act)){
			this.do_hide(n);
		}
	},
	hide_focussed:function(){
		if(this.focussed==[]){return false;}
		var cn = this.focussed[this.focussed.length-1];
		this.do_hide(cn);
	},
	do_hide:function(cn){
		Window.unstack(cn);
		this.focussed.pop();
		fade_out(cn,cn,this.blur_obscured_cards.bind(this));
	},
	
	
	mark_focussed_deleted:function(){
		if(this.focussed==[]){return false;}
		var cn = this.focussed[this.focussed.length-1];
		$(cn).addClassName('deleted');
	},
	unmark_focussed_deleted:function(){
		if(this.focussed==[]){return false;}
		var cn = this.focussed[this.focussed.length-1];
		$(cn).removeClassName('deleted');
	},
	name_from_pc:function(obj,act){
		return 'card_'+obj.name+"_"+act;
	},
	create:function(n,obj,act,args,lam,kill_animation){
		$(n).style.zIndex = Window.zindexbase;
		Window.zindexbase += 1;
		Request(obj.controller_path+'/'+act, args, function(r){
			if(lam != undefined){
				lam(n,r);
			}
			if(kill_animation===true){
			}else{
				fade_in(n,n,function(){this.fit(n);}.bind(this));
			}
			this.do_fit(n);
		}.bind(this),n);
		
		this.names.push(n);
	},
	fit_current:function(){
		this.maintain_size();
	},
	fit:function(n){
		this.do_fit(n);
		this.blur_obscured_cards();
	},
	do_fit:function(n){
		var lm = 10;
		var k = 0;
		var last = this.actually_do_fit(n);
		var ths = this.actually_do_fit(n);
		while(ths != last && k <= lm){
			last = ths;
			ths = this.actually_do_fit(n);
			k+=1;
		}
		if(k>8){
			Warn("yicj");
		}
	},
	actually_do_fit:function(n){
		var d = $(n);
		if(d==undefined){
			Warn('undef::'+n);
			return false;
		}
		
		var d2a = d.select('.scrollable');
		if(d2a.length==0){
			//Warn("No scrollable found");
		}
		var d3a = d.select('.scrollable_shell');
		if(d3a.length==0){
			//Warn("No scrollable_shell found");
		}
		
		var d2 = $(d2a[0]);
		var d3 = $(d3a[0]);
		d3.style.height = 'auto';
		d3.style.width = 'auto';
		
		
		var winwi = document.viewport.getWidth();
		if(d2.getWidth()>winwi-100){
			d3.style.width = (winwi-100)+'px';
			d3.style.overflowX = 'scroll';
		}else{
			d3.style.overflowX = '';
		}
		
		var winhi = document.viewport.getHeight();
		if(d2.getHeight()>winhi-200){
			d3.style.height = (winhi-200)+'px';
			d3.style.overflowY = 'scroll';
		}else{
			d3.style.overflowY = '';
		}
		
		
		var ht = d.getHeight();
		var vph = document.viewport.getHeight();
		
		var fcc = vph/2 - ht/2;
		var fcc2 = window.innerHeight/2 - ht/2;
		// 
		// if(fcc<40){
		//       d.style.position = 'absolute';
		//   fcc = 40;
		// }else{
		//   d.style.position = 'fixed';
		// }

		d.style.top = Math.round(fcc2) + 'px';
		var ht = d.getWidth();
		d.style.marginLeft = '-'+Math.round(ht/2) + 'px';
		return ht;
	},
	blur_obscured_cards:function(){
		var posts = $$('.card').collect(function(t){if($(t).visible()){return t}else{return null}}).compact();
		var zi = posts.collect(function(t){return parseInt(t.style.zIndex)}).sort().reverse()[0];
		posts.each(function(t){if(parseInt(t.style.zIndex)==zi){
			t.setOpacity(1.0);
			// this.focussed = t.id;
		}else{t.setOpacity(0.4);}});
	},
	maintain_size:function(){
		if(this.focussed.length==0){return false;}
		this.fit(this.focussed[this.focussed.length-1]);
	},
	refresh_focussed:function(){
		if(this.focussed==[]){return false;}
		var cn = this.focussed[this.focussed.length-1].gsub('card_','').split('_');
		var onm = cn[0];
		var actt = cn.join('_').gsub(onm+"_",'');
		onm = onm[0].toUpperCase() + onm.substring(1,onm.length);
		eval(onm+".refresh_"+actt+"();");
	},
	loading_focussed:function(){
		Loading();
		var fc = $(Card.focussed[0]);
		fc.setOpacity(0.5);
	},
	loaded_focussed:function(){
		Loaded();
		var fc = $(Card.focussed[0]);
		fc.setOpacity(1.0);
	}
}


























