var elements = lu.default_to( elements, {} );

////////////////////////////////////////
//
// main element definition

// elements.inviter is a constructor that creates a dom element, the appearence of which is determined b the 'type' argument
// the element has attached modules for model, view, and controller, defined below
elements.inviter = function( type, options ){
	if( !AppBase.user ){ return; }
	options = lu.defaults(options, {});
	var model = {}, view = {}, controller = {}, templates = {}, singleton = elements.inviter.singleton;




	////////////////////////////////////////
	//
	// controller

	controller.on_initialize = function(){
		view.on_create();
		if( model.type === 'inviter' ){
			view.show_in_banner('scraper');
		}
	};

	controller.report = function( news ){
		AppBase.post(
			'/contacts',
			{'xaction':'report','news':news}
		);
	};

	controller.on_successful_fetch_contacts = function( result, skip_scraper ){
		model.sender_email = result.sender_email;
		jQuery.each(result.address_book, function(which_contact, each_contact){
			each_contact.checked = true;
		});
		singleton.model.contacts = result.address_book;
		controller.sort_contacts();

		if( skip_scraper || singleton.model.contacts.length ){
			model.overlay_mode = 'selector';
			view.overlay('selector');
		}else{
			model.overlay_mode = 'scraper';
			view.overlay('scraper');
		}
	};

	controller.sort_contacts = function(){
		singleton.model.contacts.sort(
			function(apple,orange){
				var comparator = lu.trim(orange.name.toLowerCase()) < lu.trim(apple.name.toLowerCase());
				return comparator ? 1:-1;
			}
		);
	};

	controller.on_click_use_enumerator  = function(){
		controller.initiate_selector( true );
	};

	controller.on_click_use_scraper = function(){
		view.show_in_banner('scraper');
	};

	controller.on_before_submit_scraper_form = function( scraper_form ){
		if( !view.validate_scraper_form(scraper_form) ){
			view.flash_in_banner('incomplete_scraper_form_message');
			return false;
		}
		view.show_in_banner('loading_message');
	};

	controller.on_submit_scraper_form = function( response ){
		AppBase.handle_response(response, controller.on_successful_scrape, controller.on_failed_scrape);
	};

	controller.on_successful_scrape = function( result ){
		if( result.contacts.length === 0 ){
			view.flash_in_banner('no_contacts_message');
		}else{
			model.sender_email = result.sender_email;
			jQuery.each(result.contacts, function(which_contact, each_contact){
				each_contact.checked = true;
			});
			singleton.model.contacts = result.contacts;
			controller.sort_contacts();

			view.show_in_banner('scraper');
			view.overlay('selector');
			model.overlay_mode = 'selector';
		}
	};

	controller.on_failed_scrape = function( details ){
		bu.log(details);
		details = eval("(" + details + ")");
		if( lu.type_of(details) === 'string' ){ alert(details); }
		if( details.type === 'bad_password' ){
			view.flash_in_banner('bad_password_message');
		}
	};

	controller.on_click_close_overlay = function(){
		controller.report('cancel_'+model.type+'_'+model.overlay_mode);
		if(model.canceled_selection_callback){ model.canceled_selection_callback(); }
		view.remove_overlay();
	};

	controller.on_click_select_all = function( value ){
		view.select_all_contacts(value);
	};

	controller.on_click_contact = function( click_event, contact, change_state ){
		change_state = lu.default_to(change_state, true);
		var contact_checkbox = $(contact).find('.inviter_contact_checkbox')[0];
		var clicked_on_checkbox = $(click_event.target).hasClass('inviter_contact_checkbox');
		if( ! clicked_on_checkbox ){ contact_checkbox.checked = !contact_checkbox.checked; }
		controller.on_change_contact_checkbox(contact);
		if( ! clicked_on_checkbox ){ return false; }
	};

	controller.on_change_contact_checkbox = function( contact ){
		view.update_contact_highlighting( contact );
	};

	controller.on_click_rescrape = function(){
		controller.report('rescrape');
		view.overlay('scraper');
		model.overlay_mode = 'scraper';
	};

	controller.activate_selector_submit_button = function(){
		var setting = true;
		var submit_button_action = function(){return setting;};
		var event_is_bound = false;
		return function( new_setting ){
			setting = lu.default_to(new_setting, true);
			if( !event_is_bound ){
				$(inviter).find('.inviter_selector_form_submit_button').click(submit_button_action);
				event_is_bound = true;
			}
		};
	}();

	controller.on_before_submit_selector_form = function( fields, form ){
		controller.activate_selector_submit_button(false);
		var do_submit = false;
		jQuery.each( form.find('.inviter_contact_checkbox'), function(which_contact, each_contact){
			if( each_contact.checked === true ){ do_submit = true; }
		});
		if( do_submit ){
			view.turn_on_error('no_one_selected', false);
			return true;
		}
		view.turn_on_error('no_one_selected');
		controller.activate_selector_submit_button(true);
		return false;
	};

	controller.on_submit_selector_form = function( response ){
		AppBase.handle_response( response, controller.on_successful_communication, controller.on_failed_communication);
	};

	controller.on_failed_communication = function(message){
		controller.activate_selector_submit_button(true);
		alert(message);
	};

	controller.on_successful_communication = function(response){
        var timeout;
		if( model.type === 'sharer' ){
			timeout = 2000;
		}else if( model.type === 'inviter' ){
			timeout = 2000;
		}else if( model.type === 'group_inviter' ){
			timeout = 2000;
		}
		view.overlay('thanks_for_using');
		setTimeout(view.remove_overlay, timeout);
		controller.activate_selector_submit_button(true);
		if( model.successful_selection_callback ){ model.successful_selection_callback({'recipients':response.recipients}); }
	};

	controller.on_click_share = function( options ){
		controller.report('initiate_share');
		model.focal_channel = options.focal_channel;
		view.set_focal_channel_id();

		controller.initiate_selector();
	};

	controller.initiate_selector = function( skip_scraper ){
		api.User.fetch_contacts(function(result){controller.on_successful_fetch_contacts(result, skip_scraper);});
	};

	controller.on_before_submit_add_contact_form = function( fields, form ){
		var valid = view.validate_add_contact_manually_form();
		view.turn_on_error('manual_name_and_email', !valid);
		view.turn_on_error('invalid_manual_email', false);
		jQuery.each( $(inviter).find('.inviter_add_contact_manually_form').find('.bu_hinted'), function(which_field, each_field){
			each_field.scrutenize(false);
		});
		return valid;
	};

	controller.on_submit_add_contact_form = function( response ){
		view.turn_on_error('invalid_manual_email', false);
		AppBase.handle_response(response, controller.on_successful_add_contact);
	};

	controller.on_successful_add_contact = function( response ){
		if( response.error_type ){
			bu.log(response.error_type);
			view.turn_on_error('invalid_manual_email', (response.error_type == 'invalid_email'));
		}else{
			view.clear_manual_contact();
			controller.add_contact(response.contact, true);
			view.on_dim_for('selector');
		}
	};

	controller.add_contact = function( new_contact, show_newness ){
		new_contact.show_newness = show_newness;
		new_contact.checked = true;
		var new_contacts = [];
		jQuery.each(singleton.model.contacts, function(which_contact, each_contact){
			if( each_contact.puid != new_contact.puid ){
				new_contacts.push(each_contact);
			}
		});
		singleton.model.contacts = [new_contact].concat(new_contacts);
	};

	controller.on_click_invite_to_group = function(options){
		controller.report('initiate_group_invite');
		model.successful_selection_callback = options.on_invite;
		model.canceled_selection_callback = options.on_cancel;
		model.focal_group_puid = options.focal_group_puid;
		view.set_focal_group_puid();

		controller.initiate_selector();
	};








	////////////////////////////////////////
	//
	// view

	view.on_create = function(){
		// set up the scraper
		jQuery.each( $(inviter).find('.inviter_scraper_form'), function( which_scraper_form, each_scraper_form ){
			$(each_scraper_form).ajaxForm({
				beforeSubmit : function(        ){return controller.on_before_submit_scraper_form(each_scraper_form);},
				success      : function(response){return controller.on_submit_scraper_form(response);}
			});
		});

		$(inviter).find('.inviter_use_scraper_button'    ).click(function(){controller.on_click_use_scraper(   );});

		$(inviter).find('.inviter_use_enumerator_button' ).click(function(){controller.on_click_use_enumerator();});

		// set up scraper overlay
		$(inviter).find('.inviter_overlay_close_button').click(function(){return controller.on_click_close_overlay();});

		$(inviter).find('.inviter_add_contact_manually_form').submit(function(){
			jQuery.each( $(this).find('.bu_hinted'), function(){
				this.scrutenize(true);
			});
		});
		$(inviter).find('.inviter_add_contact_manually_form').ajaxForm({
			beforeSubmit : function( fields, form ){return controller.on_before_submit_add_contact_form( fields, form );},
			success      : function(response){controller.on_submit_add_contact_form(response);}
		});

		$(inviter).find('.inviter_select_all_button' ).click(function(){controller.on_click_select_all(true );});
		$(inviter).find('.inviter_select_none_button').click(function(){controller.on_click_select_all(false);});
		bu.limit_textarea($(inviter).find('.inviter_custom_message_field')[0], 200);//bu.limited(200, $(inviter).find('.inviter_custom_message_field')[0]);
		$(inviter).find('.inviter_rescrape_link').click(function(){controller.on_click_rescrape();});

		$(inviter).find('.inviter_selector_form').ajaxForm({
			beforeSubmit : function( fields, form ){return controller.on_before_submit_selector_form( fields, form );},
			success      : function(response){controller.on_submit_selector_form(response);}
		});
	};

	view.turn_on_error = function( which_error, setting ){
		if( typeof(setting) === 'undefined' ){ setting = true; }
		var action = setting ? 'show' : 'hide';
		$(inviter).find('.inviter_error_'+which_error)[action]();
	};

	view.flash_in_banner = function( focus ){
		view.show_in_banner(focus);
		setTimeout(function(){view.show_in_banner('scraper');}, 2000);
	};

	view.show_in_banner = function( focus ){
		$(inviter).find('.inviter_scraper, .inviter_loading_message, .inviter_no_contacts_message, .inviter_bad_password_message, .inviter_incomplete_scraper_form_message').css('display', 'none');
		if( focus !== 'nothing' ){ $(inviter).find('.inviter_'+focus).show(); }
	};

	view.select_all_contacts = function( value ){
		$(inviter).find('.inviter_contact').each(function(which_contact, each_contact){
			$(each_contact).find('.inviter_contact_checkbox')[0].checked = value;
		});
		view.update_contact_highlighting();
	};

	view.update_contact_highlighting = function(){
		jQuery.each($(inviter).find('.inviter_contact'), function( which_contact, each_contact ){
			var contact_is_checked = $(each_contact).find('.inviter_contact_checkbox')[0].checked;
			var action = contact_is_checked ? 'addClass' : 'removeClass';
			$(each_contact)[action]('inviter_contact_selected');
		});
		view.save_contact_highlighting_state();
	};

	view.save_contact_highlighting_state = function(){
		jQuery.each($(inviter).find('.inviter_contact'), function( which_contact, each_contact ){
			singleton.model.contacts[which_contact].checked = $(each_contact).find('.inviter_contact_checkbox')[0].checked;
		});
	};

	view.validate_scraper_form = function( scraper_form ){
		return (($(scraper_form).find('.inviter_email_field').val() !== '') && ($(scraper_form).find('.inviter_password_field').val() !== ''));
	};


	////////////////////////////////////////
	// code for overlaying messages

	view.overlay = function( focus ){
		view.adjust_overlay_size();
		$('#inviter_provider_main').hide();
		$(inviter).find('.inviter_overlay .inviter_scraper, .inviter_overlay .inviter_selector, .inviter_overlay .inviter_thanks_for_using').hide(); // hide all elements currently in the overlay, if present
		$('embed, object, select').css('visibility', 'hidden');
		$('.inviter embed, .inviter object, .inviter select').css('visibility', 'visible');
		$(inviter).find('.inviter_overlay, .inviter_overlay_loading_message').show();
		if( model.dim ){                                  view.on_dim_for(focus);    }
		else           { $.dimScreen(500, 0.7, function(){view.on_dim_for(focus);}); }
		model.dim = true;
	};

	view.on_dim_for = function( focus ){
		$(inviter).find('.inviter_overlay_loading_message').show();
		if( focus === 'thanks_for_using' ){
			// no logic necessary
		}else if( focus === 'scraper' ){
			// no logic necessary
		}else if( focus === 'selector' ){
			$(inviter).find('.inviter_contacts_list_holder').html( templates.contacts_list() );
			view.update_contact_highlighting();

			// configure the newly rendered template
			$(inviter).find('.inviter_sender_email').val(model.sender_email);
			$(inviter).find('.inviter_error_no_one_selected').hide();
			jQuery.each($(inviter).find('.inviter_contact'), function( which_contact, each_contact ){
				var update_highlighting = function(){ return controller.on_change_contact_checkbox( each_contact ); };
				$(this).change(update_highlighting).click(function(click_event){ return controller.on_click_contact(click_event, each_contact); });
			});
		}
		view.adjust_overlay_size();
		$(inviter).find('.inviter_overlay_loading_message').hide();
		$(inviter).find('.inviter_overlay .inviter_'+focus).show();
		model.scroll_position = bu.scroll_offset();
	};

	view.adjust_overlay_size = function(){
		$(inviter).find('.inviter_overlay').css({
			'top'    : (bu.scroll_offset().y     +  25) + 'px',
			'height' : (bu.window_dimensions().y -  75) + 'px'
		});
		$(inviter).find('.inviter_contacts_list').css({
			'height' : (bu.window_dimensions().y - 220) + 'px'
		});
	};

	view.remove_overlay = function(){
		model.dim = false;
		$('#inviter_provider_main').show();
		$(inviter).find('.inviter_overlay').hide();
		$('embed, object, select : not(.inviter embend, .inviter object, .inviter select)').css('visibility', 'visible');
		$.dimScreenStop();
	};

	view.set_focal_channel_id = function(){
		$(inviter).find('.inviter_focal_channel_id_field').val(model.focal_channel.channel_id);
	};

	view.set_focal_group_puid = function(){
		$(inviter).find('.inviter_focal_group_puid_field').val(model.focal_group_puid);
	};

	view.clear_manual_contact = function(){
		jQuery.each( $(inviter).find('.inviter_new_contact_name_field, .inviter_new_contact_email_field' ), function(which_field, each_field){
			$(each_field).val('');
			each_field.scrutenize();
		});
	};

	view.validate_add_contact_manually_form = function(){
		var name  = $(inviter).find('.inviter_new_contact_name_field' ).val();
		var email = $(inviter).find('.inviter_new_contact_email_field').val();
		return (name !== '' && email !== '');
	};




	////////////////////////////////////////
	//
	// templates

	templates.initial = function(){
		return DIV(
			{
				'class':'inviter inviter_'+model.type
			},
			function(){ if( model.type === 'inviter' ){
				return templates.inviter_banner();
			}else{return '';}}(),
			DIV({'class':'inviter_overlay'},
				IMG({'class':'inviter_overlay_close_button', 'src':Serdes.make_static_url('/images/close_sm.png'), 'alt':translate('inviter_close')}),
				P({'class':'inviter_title'}, "Share"),

				DIV({'class':'inviter_loading_message'                }, IMG({'src':Serdes.make_static_url('/images/fbjq_dialog_loading.gif')}) ),
				DIV({'class':'inviter_bad_password_message'           }, translate('inviter_incorrect_password'      ) ),
				DIV({'class':'inviter_incomplete_scraper_form_message'}, translate('inviter_enter_email_and_password') ),
				DIV({'class':'inviter_no_contacts_message'            }, translate('inviter_no_contacts_found'       ) ),

				DIV({'class':'inviter_overlay_loading_message'},
					IMG({'src':Serdes.make_static_url('/images/fbjq_dialog_loading.gif')})
				),

				templates.overlain_scraper_popup(),
				templates.selector(),
				DIV({'class':'inviter_thanks_for_using'},
					(
						model.type==='inviter' ? translate('inviter_friends_invited') :
						model.type==='sharer' ? translate('inviter_friends_shared_with') :
						model.type==='group_inviter' ? translate('inviter_thanks_for_inviting_to_group') :
						'bad_type'
					)
				)
			)
		);
	};

	templates.inviter_banner = function(){
		return DIV({'class':'inviter_banner'},
			DIV({'class':'inviter_loading_message'                }, IMG({'src':Serdes.make_static_url('/images/fbjq_dialog_loading.gif')}) ),
			DIV({'class':'inviter_bad_password_message'           }, translate('inviter_incorrect_password'      ) ),
			DIV({'class':'inviter_incomplete_scraper_form_message'}, translate('inviter_enter_email_and_password') ),
			DIV({'class':'inviter_no_contacts_message'            }, translate('inviter_no_contacts_found'       ) ),

			templates.scraper()
		);
	};

	templates.inviter_headline = function(){
		if( model.type === 'inviter' ){ return translate('inviter_invite_your_friends'); }
		else                    { return translate('inviter_share_with_your_friends'); }
	};

	templates.overlain_scraper_popup = function(){
		return DIV({'class':'inviter_scraper inviter_scraper_popup'},
			FORM(
				{
					'class':'inviter_scraper_form',
					'action':'/contacts',
					'method':'post'
				},
				P({'class':'inviter_container_popup'},
				$('<input type="hidden" name="xaction" value="scrape"/>')[0],

				P({'class':'inviter_headline_popup'},
					templates.inviter_headline() ),

				P({'class':'inviter_email inviter_email_popup'},
					LABEL({'for':'inviter_email_field', 'class':'inviter_email_label'}, translate('inviter_email')),
					$('<input type="text" class="inviter_email_field inviter_email_field_popup" name="inviter_email" maxlength="64">')[0],// note! these DO NOT work if written in the mochi compat syntax - the 'name' attribute is dropped by ie

					LABEL({'for':'inviter_provider'},'@'),
					$('<select class="inviter_provider" name="inviter_provider"></select>').append(
						$('<option value="yahoo.com"  >yahoo.com</option  >'),
						$('<option value="gmail.com"  >gmail.com</option  >'),
						$('<option value="aol.com"    >aol.com</option    >'),
						$('<option value="hotmail.com">hotmail.com</option>')
					)[0]
				),
				P({'class':'inviter_password inviter_password_popup'},
					LABEL({'for':'inviter_password_field','class':'inviter_password_label'}, translate('inviter_password')),
					$('<input type="password" class="inviter_password_field inviter_password_field_popup" name="inviter_password" maxlength="32">')[0] // note! these DO NOT work if written in the mochi compat syntax - the 'name' attribute is dropped by ie
				),
				P({'class':'inviter_submit'},
					$('<input type="submit" class="inviter_load_contacts_button inviter_load_contacts_button_popup" taborder="1" value="'+translate('inviter_view_my_contacts')+'" >')[0],// note! these DO NOT work if written in the mochi compat syntax - the 'name' attribute is dropped by ie
					(function(){
						if( model.allow_skip ){
							return A({'class':'inviter_skip_scraper_button', 'onclick':controller.on_click_close_overlay},
								translate('inviter_skip_button')
							);
						}else{
							return SPAN();
						}
                    }())
				)
				),
				DIV({'class':'inviter_use_enumerator_button_holder'},
					'(',
					A({'class':'inviter_use_enumerator_button'},
						translate('inviter_or_type_them_in')
					),
					')'
				)

			)
		);
	};

	templates.scraper = function(){
		return DIV({'class':'inviter_scraper'},
			FORM(
				{
					'class':'inviter_scraper_form',
					'action':'/contacts',
					'method':'post'
				},
				$('<input type="hidden" name="xaction" value="scrape">')[0],


				templates.inviter_headline(),

				SPAN({'class':'inviter_email'},
					$('<input type="text" maxlength="64" class="inviter_email_field" name="inviter_email" >')[0],// note! these DO NOT work if written in the mochi compat syntax - the 'name' attribute is dropped by ie

					LABEL({'for':'inviter_provider'}, '@' ),
					$('<select class="inviter_provider" id="inviter_provider_main" name="inviter_provider"></select>').append(
						$('<option value="yahoo.com"  >yahoo.com</option  >'),
						$('<option value="gmail.com"  >gmail.com</option  >'),
						$('<option value="aol.com"    >aol.com</option    >'),
						$('<option value="hotmail.com">hotmail.com</option>')
					)[0]
				),
				SPAN({'class':'inviter_password'},
					LABEL({'for':'inviter_password_field'},
						translate('inviter_password')
					),
					$('<input type="password" class="inviter_password_field" name="inviter_password" maxlength="32" >')[0],// note! these DO NOT work if written in the mochi compat syntax - the 'name' attribute is dropped by ie
					$('<input type="submit" class="inviter_load_contacts_button" taborder="1" value="'+translate('inviter_view_my_contacts')+'" >')[0]// note! these DO NOT work if written in the mochi compat syntax - the 'name' attribute is dropped by ie
				),
				DIV({'class':'inviter_use_enumerator_button_holder'},
					'(',
					A({'class':'inviter_use_enumerator_button'},
						translate('inviter_or_type_them_in')
					),
					')'
				),
				DIV({'class':'inviter_dont_worry_message'},
					translate('inviter_dont_worry')
				)
			)
		);
	};

	templates.selector = function(){
		return DIV({'class':'inviter_selector'},
			FORM(
				{
					'class':'inviter_selector_form',
					'action':'/contacts',
					'method':'post'
				},
				$('<input type="hidden" class="inviter_sender_email" name="sender_email">')[0],// note! these DO NOT work if written in the mochi compat syntax - the 'name' attribute is dropped by ie
				$('<input type="hidden" class="inviter_focal_channel_id_field" name="focal_channel_id">')[0],
				$('<input type="hidden" class="inviter_focal_group_puid_field" name="focal_group_puid">')[0],
				$('<input type="hidden" name="xaction" value="'+(
					model.type === 'inviter'       ? 'invite' :
					model.type === 'sharer'        ? 'share' :
					model.type === 'group_inviter' ? 'group_invite' :
					'big_error'
				)+'" >')[0],

				DIV({'class':'inviter_selector_left_column'},
					DIV({'class':'inviter_selector_top'},
						function(){
							if     ( model.type === 'inviter'       ){ return translate('inviter_select_friends_to_invite'      )+' '; }
							else if( model.type === 'sharer'        ){ return translate('inviter_select_friends_to_share_with'  )+' '; }
							else if( model.type === 'group_inviter' ){ return translate('inviter_select_friends_to_group_invite')+' '; }
						}(),
						'( ', A({'class':'inviter_select_all_button' },translate('inviter_all' )), ' / ', A({'class':'inviter_select_none_button'},translate('inviter_none')), ' )'),
					DIV({'class':'inviter_contacts_list_holder'})
				),
				DIV({'class':'inviter_selector_right'},
					P({'class':'inviter_subhead'},translate('inviter_add_custom_message')),
					DIV({ }, TEXTAREA({'class':'inviter_custom_message_field', 'name':'custom_message', 'rows':'6'},
						function(){
							if( model.type === 'sharer' ){
								return translate('default_share_text');
							}else if( model.type === 'inviter' ){
								return translate('default_invite_text');
							}else if( model.type === 'group_inviter' ){
								return translate('Default_group_inviter_text', Groups.profile_name);
							}
						}()
						)
					),
					DIV({ }, $('<button class="inviter_selector_form_submit_button save" type="submit">'+translate('inviter_send')+'</button>')[0]),
					(function(){
						if( model.allow_skip ){
							return DIV({'class':'inviter_skip_selector_button_holder'},
								A({'class':'inviter_skip_selector_button', 'onclick':controller.on_click_close_overlay},
									translate('inviter_skip_button')
								)
							);
						}else{
							return SPAN();
						}
                    }()),
					DIV({'class': 'inviter_error_no_one_selected'}, translate('inviter_no_contacts_selected'))
				)
			),
			FORM(
				{
					'class' : 'inviter_add_contact_manually_form',
					'action':'/contacts',
					'method':'post'
				},
				$('<input type="hidden" name="xaction" value="add_contact">')[0],

				translate('inviter_enter_contacts_manually'),
				DIV({},
					bu.hinted({hint:translate('inviter_manual_contact_name')},
                      $('<input type="text" class="inviter_new_contact_name_field" name="contact_name" maxlength="64"/>')[0]
                    ),
					bu.hinted({hint:translate('inviter_manual_contact_email')},
                      $('<input type="text" class="inviter_new_contact_email_field" name="contact_email" maxlength="64"/>')[0]
                    ),
					$('<button class="inviter_add_contact_manually_button save" type="submit">'+translate('inviter_add_contact')+'</button>')[0]
				),
				DIV({'class':'inviter_error_manual_name_and_email'},
					translate('inviter_error_manual_name_and_email')
				),
				DIV({'class':'inviter_error_invalid_manual_email'},
					translate('inviter_error_invalid_manual_email')
				)
			),
			P({'class':'inviter_rescrape_wrapper'}, A({'class':'inviter_rescrape_link'},translate('inviter_rescrape_prompt')))
		);
	};

	templates.contacts_list = function(){
		var contacts_string = new HTMLBlock();
		contacts_string.add('<input type="hidden" class="inviter_contact_count" name="contact_count" value="'+ singleton.model.contacts.length +'">');
		lu.each(singleton.model.contacts, function(which_contact, each_contact){
			contacts_string.add(bu.lines([
				'<li class="inviter_contact_'+which_contact+' inviter_contact inviter_contact_selected">',
					'<div class="inviter_contact_checkbox_holder">',
						'<input',
							'class="inviter_contact_checkbox_'+ which_contact +' inviter_contact_checkbox"',
							'type ="checkbox"',
							'name ="invite_'+ which_contact +'"',
							'value="'+ each_contact.puid +'"',
							''+(each_contact.checked ? 'checked=true' : '')+'',
						'/>',
						'<input',
							'class="inviter_contact_pemail_'+ which_contact +' inviter_contact_pemail"',
							'type ="hidden"',
							'name ="pemail_for_'+ which_contact +'"',
							'value="'+ each_contact.pemail +'"',
						'/>',
					'</div>',
					'<label class="inviter_contact_label_' +which_contact+ '" for="inviter_contact_checkbox_' +which_contact+ '">',
						''+function(){
							if( ! (each_contact.email || each_contact.pet_email) ){ return ''; }
							return '<div class="inviter_contact_email">'+( each_contact.pet_email ? each_contact.pet_email : each_contact.email ? each_contact.email : '' )+'</div>';
						}()+'',
						'<div class="inviter_contact_name">',
							''+( each_contact.pet_name ? each_contact.pet_name : each_contact.name )+' ',
						'</div>',
					'</label>',
				'</li>'
			]));
		});
		var contacts_ul = UL({'class':'inviter_contacts_list'});
		contacts_ul.innerHTML = contacts_string.dump();
		return contacts_ul;
	};




	////////////////////////////////////////
	//
	// model

	model.initialize = function(type, allow_skip){
		model.type = type;
        model.allow_skip = allow_skip;
	};




	////////////////////////////////////////
	//
	// applet setup and return

	model.initialize(type, options.allow_skip);
	var
		inviter = templates.initial(),
		jq_inviter = $(inviter),
		find = function(selector){return jq_inviter.find(selector);};
	controller.on_initialize();
	return $.extend(inviter, {'model':model, 'view':view, 'controller':controller, 'templates':templates, 'singleton':singleton});
};

elements.inviter.singleton = function(){
	var model = {}, view = {}, controller = {}, templates = {};

	return {model:model, view:view, controller:controller, templates:templates};
}();
