String.prototype.trim = function(){    
    return this.replace(/^\s*(\S*(\s+\S+)*)\s*$/, "$1");
}  

Date.prototype.getDiff = function(dt) {

    var m1 = this.valueOf();
    var m2 = dt.valueOf();
    
    var diff = {};
    diff.milliseconds = (m2 > m1) ? m2 - m1 : m1 - m2;
    diff.seconds = diff.milliseconds / 1000;

    diff.minutes = diff.seconds / 60; 
    diff.hours =  diff.minutes / 60;
    diff.days =  diff.hours / 24;
    diff.weeks =  diff.days / 7;
    diff.months =  diff.weeks / 4;
    
    return diff;    

}

Date.prototype.getDiffFormat = function(dt) {
    var diff = this.getDiff(dt);
    if (diff.hours < 24) {
        if (diff.minutes < 60) {
            if (diff.minutes < 1) {
                if (diff.seconds < 1) {
                    return  "1 second ago";
                } else { 
                    return  Math.floor(diff.seconds) + " seconds ago";
                }
            } else {
                var s = (Math.floor(diff.minutes) == 1) ? " minute ago" : " minutes ago"
                return Math.floor(diff.minutes) + s;
            }        
        } else {
            var s = (Math.floor(diff.hours) == 1) ? " hour ago" : " hours ago"
            return Math.floor(diff.hours) + s;
        }
    } else if (diff.weeks > 0 && diff.weeks < 1) {
        var s = (Math.floor(diff.days) == 1) ? " day ago" : " days ago"
        return Math.floor(diff.days) + s;
    } else if (diff.weeks >= 1 && diff.weeks < 5) {
        var s = (Math.floor(diff.weeks) == 1) ? " week ago" : " weeks ago"
        return Math.floor(diff.weeks) + s;
    } else {
        var s = (Math.floor(diff.months) == 1) ? " month ago" : " months ago"
        return Math.floor(diff.months) + s;        
    }
}

String.prototype.replaceAll = function(target, substring){
	var strText = this;
	var intIndexOfMatch = strText.indexOf(target);
	while (intIndexOfMatch != -1){
		strText = strText.replace(target, substring)
		// Get the index of any next matching substring.
		intIndexOfMatch = strText.indexOf(target);
	}
	return(strText);
}

String.prototype.scrub = function() {
    // scrub some of the entity codes...
    var s = this.replaceAll('&', '[amp;]').toString();
    return s.replaceAll('[amp;]', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').toString();
}

function format_date(date, now){
    date.innerHTML = parse_date(date.innerHTML.trim()).getDiffFormat(now);
}

function parse_date(date){
    var parts, dt, tm;
    parts = date.split(' ')
    dt = parts[0].split('-')
    tm = parts[1].split(':')
    return new Date(dt[0], parseInt(dt[1], 10) - 1, dt[2], tm[0], tm[1], tm[2]);
}



/*toggle visibility of an element given ID
-- blog/archive

*/

function toggle(id) {
    var p = getElement(id);	
(computedStyle(p,'display')=='none')?showElement(p):hideElement(p);
    return true;
}
/* change status bar at the bottom
-- blog/archive
 */
function viewMsg(evt) {
    if (evt.eventType == 'onmouseover') {
        window.status = "Preview";
        return true;
    }
    else if (evt.eventType == 'onmouseout') {
        window.status = "";
        return true;
    }
    else
        return false;
}

/* does a dom update a soon as possible */
function schedule(objectID, functionCall)
{
	if (document.getElementById(objectID))
	{
		eval(functionCall);
	}
	else
	{
		setTimeout("schedule('" + objectID + "', '" + functionCall + "')", 1);
	}
	
	return true;
}

// Use this as the onclick handler of the master checkbox to control
// a group or list of checkboxes. 
// Arguments:
//	master -- the master controller checkbox
//	name   -- the name of every checkbox in the group or list
function checkControl(checkbox, name) {
	var elts = document.getElementsByName(name);
	if (!elts || elts == [])
		return;
	len = elts.length;
	for (var i = 0 ; i < len; i++) {
		elts[i].checked = checkbox.checked;
	}
}

// Uncheck the master when one of the list entry boxes is unchecked.
// Assumes the id of the master checkbox is 'master'
// picker.tmpl, groups.tmpl, list_all.tmpl
function uncheckMaster(checkbox) {
	var master = document.getElementById('master');
	if (!master) return;
	if (checkbox.checked == false) {
		master.checked = false;
	}
}

//Secondary master uncheck that takes ID as an argument.
//Use this for pages that have multiple master checkboxes.
//remember to put the form's ID into the argument of the repeated checkboxes
//see connections/index.tmpl for reference
function uncheckMasterId(checkbox,id) {
	var master = getElement(id);
	if (!master) return;
	if (checkbox.checked == false) {
		master.checked = false;
	}
}

function ghostText(id, text, normalColor, ghostColor) {
	if (normalColor == undefined)
		var normalColor = "#373737";

	if (ghostColor == undefined)
		var ghostColor = "#808080";

	var input = $(id);
	if (!input) return;
	connect(input, 'onblur', partial(ghostBlur,  ghostColor));
	connect(input, 'onfocus', partial(ghostFocus, normalColor));
	connect(input, 'onsubmit', ghostSubmit);
	input.ghostText = text;
    if(input.value == "" || input.value == text) {
        input.style.color = ghostColor;
        input.value = input.ghostText;
	} else {
        input.style.color = normalColor;
    }
}

function ghostBlur(c, e) {
	if(e.src().value == "") {
		e.src().style.color = c;
		e.src().value = e.src().ghostText;
	}
}

function ghostFocus(c, e) {
	if(e.src().value == e.src().ghostText) {
		e.src().value = "";
		e.src().style.color = c;
	}
}

function ghostSubmit(id) {
    if ( $(id) ) {
    	if($(id).value == $(id).ghostText) {
    		$(id).value = "";
    		$(id).style.color = c;
    	}
	}
}

/* open/close the RSS subscribe menu for directory/listing pages*/
setupRss=function() {
	MochiKit.Signal.connect("rssFeedIcon","onclick",toggleRss);
	MochiKit.Signal.connect("xIcon","onclick",toggleRss);
	MochiKit.Signal.connect("wrapper","onclick",hideRss);
	return false;
}

function toggleRss(e) {
	var rss = getElement( 'syndicationBox' );
	toggleElementClass( 'noDisplay', rss );	
	e.stop();
	return false;
}

function hideRss(e){
	var rss = getElement( 'syndicationBox' );
	setElementClass( rss , 'noDisplay');
}

function nearbyAjax (url) {
	var d = loadJSONDoc(url);
	d.addCallback(function (result) { 
			$('resultList').innerHTML = result["data"];
			//$('resultList').innerHTML += result["gmaplog"];
			markers = result["gmap"].concat(result["newMarkers"]).concat(result["newXMarkers"]);
			frames['gmframe'].ajaxUpdateNearBy(markers);
		});
}

/*
**  Toggle client-side notifiers and server-generated notification snippets
**
*/
function toggleNotify(on) {
    if (! $('js-notify')) return;
    if (on) {
        if ($('mcNotifier'))
            hideElement('mcNotifier');
        removeElementClass('js-notify', 'noDisplay');
        showElement('js-notify');
    } else {
        if ($('mcNotifier'))
            showElement('mcNotifier');
        hideElement('js-notify');
    }
}
/*
** Ajax calls to get reviews from external sites

** Calling template/script must set this to the URL for external reviews
** Parameters: cid company id
**						 site: scraper website name, set to dummy 'XYZ'

** This is all static because of the difficulties of dealing
** with setInterval, whose function argument's arguments are evaluated
** in global scope. I could get around this by using a singleton pattern,
** but WTF.
*/

MC_ExternalReviews =  {
	baseURL : '',
	wsn: '',
	tid : null,
	numdots : 0,
	dots : ['.', '. .', '. . .', '. . . .', '. . . . .'],
	displayName : '',
	reviewListID : 'review-list',
	selectID : 'reviewSite',
	current_site: ''
}

MochiKit.Base.update(MC_ExternalReviews, {

	setBaseURL: function(url) {MC_ExternalReviews.baseURL = url;},
	setWsn : function(wsn) {MC_ExternalReviews.wsn = wsn;},
	searching : function (){
		var s = '<span class="note">Searching for reviews on ' 
				+ MC_ExternalReviews.displayName + '</span>';
		var idx = MC_ExternalReviews.numdots % 5;
		$(MC_ExternalReviews.reviewListID).innerHTML = 
			s + MC_ExternalReviews.dots[idx];
		MC_ExternalReviews.numdots++;
	}, 

	getExternalReviews: function()
	{
		var select = $(MC_ExternalReviews.selectID);
		var site = select.options[select.options.selectedIndex].value;
		MC_ExternalReviews.displayName = 
				select.options[select.options.selectedIndex].text;
		if (MC_ExternalReviews.tid != null) {
			clearInterval(MC_ExternalReviews.tid);
			MC_ExternalReviews.tid = null;
			MC_ExternalReviews.numdots = 0;
		}
		if (site != 'merchantcircle') {
			MC_ExternalReviews.tid = setInterval('MC_ExternalReviews.searching()', 500);
			document.body.style.cursor = 'wait';
		}
		var url = "/ajax/xreviews/" + MC_ExternalReviews.wsn + "/" + site;
		var d = loadJSONDoc(url);
			d.addCallbacks(function (result) { 
				if (MC_ExternalReviews.tid != null) {
					clearInterval(MC_ExternalReviews.tid);
					MC_ExternalReviews.tid = null;
					MC_ExternalReviews.numdots = 0;
					document.body.style.cursor = 'default';
				}
				$(MC_ExternalReviews.reviewListID).innerHTML = result["data"];
			},
			function(result, site) {
				if (MC_ExternalReviews.tid != null) {
					clearInterval(MC_ExternalReviews.tid);
					MC_ExternalReviews.tid = null;
					MC_ExternalReviews.numdots = 0;
					document.body.style.cursor = 'default';
				}
	
				$(MC_ExternalReviews.reviewListID).innerHTML = 
						'<span class="note">There was an error searching ' + 
						MC_ExternalReviews.displayName +
						'. Try again later</span>';
			}
			);
		return false;
	},
	
	autoScrapeExternalReviews: function( site )
	{
		loadJSONDoc("/ajax/xreviews/" + MC_ExternalReviews.wsn + "/local.yahoo.com/1").addCallback(
			function (result) {
				if (result['count'] > 0) {
					$(MC_ExternalReviews.reviewListID).innerHTML = result["data"];
					$(MC_ExternalReviews.selectID).options.selectedIndex =  map(partial(itemgetter('value')),
					 	$(MC_ExternalReviews.selectID).options).indexOf('local.yahoo.com')
				}
			}
		);
	}
});


/*
** For character text limit in textarea fields.
*/

function textLimit(field, maxlen, options) {
if (field.value.length > maxlen) {
	field.value = field.value.substring(0, maxlen);
}
if (options) {
	try {
		var fostr = maxlen - field.value.length;
		if (options['format'])
            fostr = number_format(fostr);
		if (options['before']) 
			fostr = options['before'] + fostr;
		if (options['after']) 
			fostr = fostr + options['after'];
		getElement(options['counterID']).innerHTML = fostr;
	} catch (err){
		log(err);
	}
}
}

function number_format(num){
	num = num.toString();
	formatted = '';
	count = 0;
	
	for (var i = num.length - 1; i >= 0; i--){
		if (count > 0 && count % 3 == 0 && num[i] != '-'){
			formatted = num[i] + ',' + formatted;
		}
		else{
			formatted = num[i] + formatted;
		}
		
		count++;
	}
	
	return formatted;
}


/*
** JSON namespacing
*/
var app = {};
var mc = {};
mc.app = {};
mc.app.subscriber = function() {};
mc.app.subscriber.prototype = {
	fromSelect:null,
	toSelect:null,
	limit:null,
	limitAction:null,
	nonlimitAction:null,
	init:function (fromSelect,toSelect,limit,limitAction,nonlimitaction) {
		this.fromSelect = fromSelect;
		this.toSelect = toSelect;
		this.limit = limit;
		this.limitAction = limitAction;
		this.nonlimitAction = nonlimitaction;
		var checkCurrent = $(toSelect).options.length;
		if (checkCurrent >= this.limit) {
			this.disableOption(this.fromSelect);
		}
		return this;
	},
	makeOption:function(option) {
		return OPTION({"value": option.value}, option.text);
	},
	moveOption:function( fromSelect, toSelect, check )
	{
		if (check && $('subscribed').options.length >= mcApp.merchant.selector.limit) {
			if (mcApp.merchant.selector.limitAction)
				mcApp.merchant.selector.limitAction();	
			return;
		}
		// mov
		appendChildNodes(toSelect,
		    map( mcApp.merchant.selector.makeOption,
		    	 ifilter(itemgetter('selected'), $(fromSelect).options))
		);

		replaceChildNodes(fromSelect,
			list(ifilterfalse(itemgetter('selected'), $(fromSelect).options))
		);

		updateNodeAttributes($('ids'),
			{'value' : repr(map(itemgetter('value'), $('subscribed').options)) }
		);
		if ($('subscribed').options.length >= mcApp.merchant.selector.limit) {
			mcApp.merchant.selector.disableOption(mcApp.merchant.selector.fromSelect);
		} else {
			mcApp.merchant.selector.enableOption(mcApp.merchant.selector.fromSelect);
			if (mcApp.merchant.selector.nonlimitAction)
				mcApp.merchant.selector.nonlimitAction();
		}
	},
	disableOption: function(fromSelect)
	{
		$(fromSelect).disabled=true;
		$(fromSelect).backgroundColor='#ddd';
	},
	enableOption: function(fromSelect)
	{
		$(fromSelect).disabled=false;
		$(fromSelect).backgroundColor='#fff';		
	}
};


mc.app.ghostText = function() {};
mc.app.ghostText.prototype = {
	_normalColor:null,
	_ghostColor:null,
	_formId:null,
	_fieldId:null,
	_ghostMsg:null,
	_ghostErrMsg:null,
	init: function (formid,fieldid,normalColor,ghostColor,ghostMsg,ghostErrMsg) {
		this._formid = formid;
		this._fieldid = fieldid;
		this._normalColor = normalColor;
		this._ghostColor = ghostColor;
		this._ghostMsg = ghostMsg;
		this._ghostErrMsg = ghostErrMsg;
		return this;
	},
	ghostText: function (id, text, normalColor, ghostColor) {
		if (normalColor == undefined)
			normalColor = "#575757";

		if (ghostColor == undefined)
			ghostColor = "#ABABAB";

		var input = $(id);
		if (!input) return;
		connect(input, 'onblur', partial(mcApp.ghost.ghostBlur,  ghostColor));
		connect(input, 'onfocus', partial(mcApp.ghost.ghostFocus, normalColor));
		input.ghostText = text;
	    if(input.value == "" || input.value == text) {
		input.style.color = ghostColor;
		input.value = input.ghostText;
		} else {
		input.style.color = normalColor;
	    }
	},

	ghostBlur: function (c, e) {
		if(e.src().value == "") {
			e.src().style.color = c;
			e.src().value = e.src().ghostText;
		}
	},

	ghostFocus: function (c, e) {
		if(e.src().value == e.src().ghostText) {
			e.src().value = "";
			e.src().style.color = c;
		}
	},

	ghostSubmit: function (e) {
		if (mcApp.ghost) {
			var id =  mcApp.ghost._fieldid; 
			t = $(id).value;
			//prevent submit event from finishing  
			if (t.match(mcApp.ghost._ghostMsg)) { 
				alert(mcApp.ghost._ghostErrMsg);
				e.stop(); 
				return false;
			}
		}
	}
};


/* Top Nav Bar
**************/
function linkObject(title,href,divider,id) {
	this.title=title;
	//this.href=href;
	if (href.search(/http/) == 0) {
	    this.href = href;
	}  else {
	    this.href = 'http://' + document.location.host + href;
	}
	this.divider=divider;
	if (id) {
		this.id = id;
	}
}

//expects object(href) and object(menu)
function buildLinks(target,obj) {
	var a = A({'href':obj.href},obj.title);
	if (obj.id) {
		a.id = obj.id;
	}
	if (obj.title == 'Help') {
		a.target = 'help';
	}
	appendChildNodes(target,a);
	if (obj.divider) {
		appendChildNodes(target, ' | ');
	}
}

app.util = {
    // append a script tag to the head
	script:function(path) {
    	var head=document.getElementsByTagName("head")[0];
    	var script=document.createElement("script");
    	script.type = "text/javascript";
    	script.src = path
    	head.appendChild(script);
    }
}


app.nav = {
    container:null,
    items:{
        logout:new linkObject("Sign out","/auth/logout",false), //no divider
        signup:new linkObject("Sign up","/corporate/landing/signup.html",false),       //no divider
        login:new linkObject("Sign in","/auth/login",true),
        dash:new linkObject("Dashboard","/merchant",true),
        invite:new linkObject("Invite","/merchant/invite",true),
        dir:new linkObject("Directory","/directory",true),
        contentwriter:new linkObject("Content Writer","/contentwriter",true),
        help:new linkObject("Help","http://merchantcircle.helpserve.com/",true),
        website:new linkObject("View My Listing","/r?a=w",true),
        advertise:new linkObject("Advertise with Us", "/corporate/pricing.html",true),
        marketplacePublic:new linkObject("Marketplace", "/directory/marketplace",true,'marketNav'),
        marketplaceMerchant:new linkObject("Marketplace", "/merchant/marketplace",true,'marketNav'),
        cart:new linkObject("Shopping Cart",'https://' + document.location.host + '/secure/cart',true)
    },
    init:function(){
        // set the target container for the links...
        var containers = ['extraLinks', 'topMenu', 'miniNav']
        for (var i=0;i<containers.length;i++){
            var c = containers[i];
            if ($(c)){this.container=c;break;}
        }
        if (this.container) {
            $(this.container).innerHTML='';
            if (isLoggedIn()) {
                if (isConsumer()){
                    this.build_logged_in_consumer()
                } else {
                    this.build_logged_in_merchant()
                }
            } else {
                this.build_not_logged_in();
            }
        } else {
            log('no target exists for nav links')
        }

    },
    render:function(links){
        map(partial(buildLinks,this.container),links);
    },
    build_logged_in_merchant:function(){
        var href = window.location.href;
        var links = [this.items.marketplaceMerchant,
                     (href.indexOf('/merchant') == -1 || href.indexOf('/merchant/interstitial') > -1) ? this.items.dash : this.items.website,
                     this.items.cart,
                     this.items.help,
                     this.items.logout]
        this.render(links);

    },
    build_logged_in_consumer:function(){
        var links = [new linkObject(getProfileAlias(),'/profile',true),
                    this.items.contentwriter,
                    this.items.logout]
        this.render(links);        
    },
    build_not_logged_in:function(){
        var links = [this.items.login,
                    this.items.help,
                    this.items.signup]
        this.render(links);
    },
    
    end:function(){}
}


/* END Top Nav Bar
**************/

function resizer(img, w, h) {
		this._img = img;
		this.w = w;
		this.h = h;
		this.origW = img.width;
		this.origH = img.height;
		this.tempW = 0;
		this.tempH = 0;
		this.ratioH = function(){return this.origH/this.origW};
		this.ratioW = function(){return this.origW/this.origH};
		this.ratioTempH = function(){return this.tempH/this.tempW};
		this.ratioTempW = function(){return this.tempW/this.tempH};
		this.end = function(){};

		if (this.origW < this.w && this.origH < this.h) {
			this._img.style.visibility = 'visible';
			return;
		}
		if (this.ratioW() == 1) {
			// square image
			if (this.origW > this.w) {
				this.tempW = this.w;
				this.tempH = this.h;
			} else { // smaller size
				this.tempW = this.origW;
				this.tempH = this.origH;
			}
		} else if (this.ratioW() < 1) {
			// tall rectangle
			this.tempH = this.h;
			this.tempW = this.h * this.ratioW();
		} else if (this.ratioW() > 1) {
			// wide rectangle
			this.tempW = this.w;
			this.tempH = this.w * this.ratioH();
		}   
		if (this.tempW > this.w) {
			var diff = this.tempW - this.w
			this.tempW -= diff;
			this.tempH -= (diff * this.ratioW());
		}        
		if (this.tempH > this.h) {
			var diff = this.tempH - this.h
			this.tempW -= (diff * this.ratioW());
			this.tempH -= diff;
		}

		this._img.width = Math.ceil(this.tempW);
		this._img.height = Math.ceil(this.tempH);
		this._img.style.width = Math.ceil(this.tempW) + "px";
		this._img.style.height = Math.ceil(this.tempH) + "px";
		this._img.style.visibility = 'visible';
	return;
};

/* Picture Flipper
******************/

var flipperBaseUrl;
var displayedPicture = 0;
var displayedPictureIndex = 0;
var imageInfo = null;

function setFlipperBaseUrl(url) {flipperBaseUrl = url;}

function setImageInfo(s) {
	imageInfo = s; 
}

function setDisplayIndex(idx) {
	for (var i = 0; i < imageInfo.length; i++) {
		if (imageInfo[i].id == idx) {
			displayedPictureIndex = i;
			displayedPicture = idx;
			break;
		}	
	}
}

function getImageContent(kind, pindex, selected) {
	var url = flipperBaseUrl;
	var div_id = kind + '_flipper' ;
	url = url.replace(/XX/,div_id);
	if (kind != 'photo') {
		url = url.replace(/photo/, kind);
	}
	if (pindex) {
		url += '/' + pindex;
	}
	if (selected) {
		url += '?selected=' + selected;
		setDisplayIndex(selected);
	}
	var d = loadJSONDoc(url);
   d.addCallback(function (result) { 
			$(div_id).innerHTML = result["data"];
		});
	return false;
}

var has_videos = false;
var has_photos = false;

function setFlags(videos, photos) {
	log('setFlags: videos, photos', videos, photos);
	has_videos = videos > 0;
	has_photos = photos > 0;
}

function initTabs() {
	var photo_tab = $('photo_tab');
	var video_tab = $('video_tab');
	if (has_photos && has_videos) {
		switchTabs('photo');
	} else if (has_photos) {
		photo_tab.innerHTML = 'Photos';
		video_tab.innerHTML = '<span class="inactive">Videos</span>'
		getImageContent('photo', 0);
		$('photo_flipper').style.display = 'block';
		$('video_flipper').style.display = 'none';
	 	displayedPicture = imageInfo[0].id;
		displayedPictureIndex = 0;
		showElement('slideshow_link');
//		hideElement(video_tab);
	} else if (has_videos) {	
		video_tab.innerHTML = 'Videos';
		photo_tab.innerHTML = '<span class="inactive">Photos</span>'
		getImageContent('video', 0);
		$('photo_flipper').style.display = 'none';
		$('video_flipper').style.display = 'block';
		hideElement('slideshow_link');
//		hideElement(photo_tab); 
	} else {
		hideElement(photo_tab); 
		hideElement(video_tab); 
		hideElement(photo_flipper); 
		hideElement(video_flipper); 
		hideElement('slideshow_link');
	}
}

function switchTabs(which) {
	var photo_tab = $('photo_tab');
	var video_tab = $('video_tab');
	getImageContent(which, 0);
	if (which == 'photo') {
		photo_tab.innerHTML = 'Photos';
		var link = A(
			{'href':'javascript:void(0)','onclick':'switchTabs("video")'},
			'Videos');
		replaceChildNodes(video_tab, link);
		$('photo_flipper').style.display = 'block';
		$('video_flipper').style.display = 'none';
	 	displayedPicture = imageInfo[0].id;
		displayedPictureIndex = 0;
		showElement('slideshow_link');
	} else {
		stop();
		video_tab.innerHTML = 'Videos';
		var link = A(
			{'href':'javascript:void(0)','onclick':'switchTabs("photo")'},
			'Photos');
		replaceChildNodes(photo_tab, link);
		$('photo_flipper').style.display = 'none';
		$('video_flipper').style.display = 'block';
		hideElement('slideshow_link');
	}
}
function div_appear(i) {
	var image = imageInfo[i];
	var div = $('highlighted_image');
	var snippet = image.snippet;
	snippet = snippet.replace(/&lt;/g, '<');
	snippet = snippet.replace(/&gt;/g, '>');
	div.innerHTML = snippet;
	MochiKit.Visual.appear(div);		
}

function loadImage(i) {
	var image = imageInfo[i];
	var div = $('highlighted_image');
	if (!div) {
		log("Couldn't find highlighted image div");
		return;
	}
	var snippet = image.snippet;
	snippet = snippet.replace(/&lt;/g, '<');
	snippet = snippet.replace(/&gt;/g, '>');

	MochiKit.Visual.fade(div, {'to':0.1, 'from':1.0});
	
	displayedPictureIndex = i;
	displayedPicture = image.id;
	setTimeout("div_appear(" + i + ")", 1000);
/*
		// Nice, but doesn't work in IE
		function(div, snippet) {
			div.innerHTML = snippet;
			MochiKit.Visual.appear(div);
		}, 1000, div, snippet);
*/
}

function next() {
	var idx = displayedPictureIndex + 1 ;
	if (idx >= imageInfo.length)
			idx = 0;
	loadImage(idx);
}

var lock = new DeferredLock();
var tid;
var stopAnchor = A({'href':'javascript:void(0)','id':"slideshow_link",
									  'class':'extraTabLinkStop'}, "Stop Slideshow");
connect(stopAnchor, 'onclick', stop);
var playAnchor = A({'href':'javascript:void(0)', 'id':"slideshow_link",
									  'class':'extraTabLink'}, "View Slideshow");
connect(playAnchor, 'onclick', play_slideshow);

function play_slideshow() {
	var slink = $('slideshow_link');
	swapDOM(slink, stopAnchor);
	var d = lock.acquire();
	var fired = d.fired;
	if (fired != 0) return;
	next();
	tid = setInterval('next()', 5000);
}

function stop() {
	var slink = $('slideshow_link');
	swapDOM(slink, playAnchor);
	_stop();
}

function _stop() {
	try {
		clearInterval(tid);
	lock.release();
	} catch(e) {
	}
}

//createLoggingPane();

/* END Picture Flipper
******************/

/* Rank
******************/
// This file depends on functions defined in cookie.js

if ( typeof(readCookie) != undefined)
{
	function set_uid() {
		var gProfile = unencodeCookie("P");
		if (!gProfile || !gProfile["p"]) {
			return null;
		} else {
			return gProfile["p"];
		}
	}

	function rate_company_inline(id, rating) {
		var uid = set_uid();
		if (uid != null) {
			var d = loadJSONDoc('/ajax/rank?'+queryString({'uid':uid, 'id':id, 'rating':rating }));
			d.addCallback(function (result) {
				 $('rankContentLinks'+id).innerHTML = result["data"]; }
			);
			try {
			    //not always everywhere
			    trackEngagement('stars');
			} catch (err){ }
		}
	}

	function lightStars(id, star, path) {
		if (! path ) {
			path = '/static/imgs/icons/stars/';
		}
		for (var x=star; x > 0 ; x--) {
			element = 'c'+id + "-" + x;
			$(element).src = path + 'star_red.gif';
		}
	}

	function starMouseOut(id, star, color, path) {
		if (! path ) {
			path = '/static/imgs/icons/stars/';
		}
		for (var x=star; x > 0 ; x--) {
			element = 'c' + id + "-" + x;
			if ($(element).className == 'star-1') {
				$(element).src =  path + 'star_half.gif';
			}
			else if ($(element).className == 'star-2') {
				$(element).src =  path + 'star.gif';
			}
			else {
				$(element).src =  path + 'star_gray.gif';
			}
		}
	}

	function blankAllStars(id,total) {
		for (var x=1; x<=total; x++) {
			element='c'+id+'-'+x;
			$(element).src = '/static/imgs/icons/stars/star_gray.gif';
		}
	}
	
	function updateHiddenStars(id, stars, frm) {
	    $(id).value = stars;
	    frm.submit();
	}
}

/* END Rank
******************/

/* from mcGsearch.js
******************/

/* get all the dirt on an object. Probably not a good idea to have a recursive version :)
**
*/
function dirt(o) {
	result = '';
	if (o) {
		for (k in o) {
			result += k + ' = ' + o[k] + "\n";
		}
	}
	return result;
}
var _unescape;
if (typeof (decodeURIComponent)!="undefined") {
    _unescape = decodeURIComponent;
    _escape = encodeURIComponent;
}
else {
    _unescape = unescape;
    _escape = escape;
}

/* 
** Convenience function to get the url of a search item.
*/
function getResultUrl(result) {
	switch (result.GsearchResultClass) {
		case 'GlocalSearch': 
		{
			return _unescape(result.ddUrl);
			break;
		}
		case 'GblogSearch':
		{
			return _unescape(result.postUrl);
			break;
		}
		case 'GwebSearch':
		case 'GvideoSearch':
		case 'GnewsSearch':
		{
			return _unescape(result.url);
			break;
		}
		default: break;
	}
	return null;
}

/*
** Our little Google search item mapper class
*/
function MCSearchResultMap(result) {
	this.title = '';
	this.content = '';
	this.url = '';
	this.phones = '';
	if (result.phoneNumbers) {
		for (i = 0; i < result.phoneNumbers.length; i++) {
			n = result.phoneNumbers[i];
			this.phones += (i>0?'<br/>':'') + n.number + ' (' + n.type + ')';
		}
	}
	if (result.GsearchResultClass) {
		switch (result.GsearchResultClass) {
			case 'GlocalSearch': 
			{
				this.title = result.titleNoFormatting;
				this.content = result.streetAddress + '<br />' +
					result.city + ',' + result.region + '<br />' + this.phones;
				this.url = _unescape(result.ddUrl);
				break;
			}
			case 'GwebSearch':
			{
				this.title = result.titleNoFormatting;
				this.content = result.content;
				this.url = _unescape(result.url);
				break;
			}
			case 'GblogSearch':
			{
				this.title = result.titleNoFormatting;
				this.content = result.content;
				this.url = _unescape(result.postUrl);
				break;
			}
			case 'GnewsSearch':
			{
				this.title = result.titleNoFormatting;
				this.content = result.content;
				this.url = _unescape(result.url);
				break;
			}
			case 'GvideoSearch':
			{
				this.title = result.titleNoFormatting;
				this.content = result.content;
				this.url = _unescape(result.url);
				break;
			}
			default: break;
		}
		this.url_truncated = this.url;
		if (this.url_truncated.length > 50)
			this.url_truncated = this.url_truncated.substring(0,50) + '...';
	}
}
/*
** this is the method that inserts our formatted item. The variable "template" must
** be defined in the calling document, since it's a separate snippet that gets written in.
*/
MCSearchResultMap.prototype.insert = function() {
	var html = '';
	html = template.replace(/%%title%%/, this.title);
	html = html.replace(/%%content%%/, this.content);
	html = html.replace(/%%url%%/g, 'href="' + this.url + '"');
	html = html.replace(/%%url_truncated%%/, this.url_truncated);
	var div = DIV({'class':'infoData'});
	div.innerHTML = html;
	$('gResults').appendChild(div);
}

/*
** The Google AJAX Search API requires an object and a method for search callbacks.
** We also keep track of urls to avoid duplicates and try to avoid recursion.
*/
function Searcher() {
    this.urls = [];
}
// Not sure if this is really needed, since it's not really a lock...
var lock = new MochiKit.Async.DeferredLock();

/*
** The callback function for search completion
*/
Searcher.prototype.sc = function(t) {
	lock.acquire()
	if (t.results) {
	    var m, r, url, kind;
		for (var i = 0; i < t.results.length; i++) {
		    r = t.results[i]; // a GsearchResult object
	        url = getResultUrl(r);
	        if (MochiKit.Base.findValue(this.urls, url) > -1) {
                log('found duplicate', url);
                continue;
            }
	        this.urls.push(url);
			m = new MCSearchResultMap(r);
			kind = r.GsearchResultClass;
			m.insert();
			delete m;
		}
		t.clearResults();
		delete t;
		hideElement('webSearchText');
		hideElement('newsSearchText');
		hideElement('blogSearchText');
		hideElement('videoSearchText');
		hideElement('emptySearchText');
		if (kind) {
		    kind = kind.replace(/^G/, '').replace(/$/, 'Text');
		    showElement(kind);
		} else {
		    showElement('emptySearchText');
		}
	}
	lock.release();
}

function selectOnChange(select, n, c, s ){
    setSearchKind(select.options[select.options.selectedIndex].value, n, c, s);
}
function setSearchKind(kind, cname, city, state)
{
	var searcher;
	if (!$('gResults')) return;
	switch (kind) {
		case 'web': {
			searcher = new GwebSearch();
			break;
		}
		case 'news': {
			searcher = new GnewsSearch();
			break;
		}
		case 'blog': {
			searcher = new GblogSearch();
			break;
		}
		/*
		case 'local':{
			searcher = new GlocalSearch();
			break;
		}
		*/
		case 'video': {
			searcher = new GvideoSearch();
			break;
		}
		default: return;
	}
	replaceChildNodes('gResults', SPAN(' '));
	searcher.setResultSetSize(GSearch.SMALL_RESULTSET);
	searcher.setSearchCompleteCallback(new Searcher(), Searcher.prototype.sc, [searcher]);
	searcher.execute('"' + cname + '" ' + city);
}

/*
** Insert a script node on load which will force the initial gsearch to populate
** the search box. Takes the initial load out of the page onload sequence, makes it
** asynchronous.
**
** It appends a script node to the end of the child list of the <body> node.
** The script that it loads actually runs the search.
** Dependencies:
**      The calling document has a body tag with id = "consumer"
*/
function writeGsearchScriptNode() {
    var body = $('consumer');
    if (!body) return;
    var sn = createDOM("script", {'type':'text/javascript', 
                                  'src':'/static/js/mcGsearch_action.js'});
    appendChildNodes(body, sn);
}

/* END from mcGsearch.js
******************/


/*
** AJAX search for inviteCombo.tmpl actions
**
*/

if (!mc) { var mc = {}; log('mc created before mc.invite'); }
if (!mc.invite) { mc.invite = function () {}; }
mc.invite.prototype = {
        url:null,
    	init:function (url, forvar) {
    	    this.url = url;
    		return this;
    	},
        inlineSearch: function (inviteWhat,inviteWhere, claimed, inviteArea, url)
        {
           whatval =$(inviteWhat).value;
           whereval = $(inviteWhere).value;
           var err;
           if (!whatval) {
               err = '\n a search term ';
               $(inviteWhat).style.backgroundColor = "#ffdddd";
               }
           if (!whereval) {
               msg = '\n a location containing city, state and/or ZIP';
               (err)?err += 'and ' + msg : err=msg;
               $(inviteWhere).style.backgroundColor = "#ffdddd";
        	   }
        
            if (err) {
        	   $(inviteArea).innerHTML = '\nPlease enter' + err;
        	   return false;
        	   }
        	
            var args = {'search':true,'inviteWhat':whatval,'inviteWhere':whereval, 'claimed':claimed};
            $(inviteArea).innerHTML = 'Loading...'; 
            var d = loadJSONDoc(url, args);
            d.addCallback(function (result) { 
                log('invitearea value',inviteArea);
                $(inviteArea).innerHTML = result["data"]; 
                $(inviteWhat).style.backgroundColor = "#ffffff";
                $(inviteWhere).style.backgroundColor = "#ffffff";
        	   });
        	d.addErrback(function (result) { log ('XMLHttpRequest Failed', result); } );
        	return false;
        }        
    };

if ((mc)&&(!mc.form)) { mc.form = function () {}; } 
mc.form.gatherInvites = function () {
    /* 
    ** gather invites from AJAX invite search boxes
    ** refer to snippets/invite/ajaxMoreMerchants.tmpl 
    ** grab all radio boxes and copy them into the FORM for submission
    */
    var set1 = getElementsByTagAndClassName('input','mcR');
    var set2 = getElementsByTagAndClassName('input','allR');
    var checks = [];
    for (var i=0;i<set1.length;i++) {
        if(set1[i].checked == true) {
            checks.push(set1[i].id);
        }
        }

    for (var i=0;i<set2.length;i++) {
        if(set2[i].checked == true) {
            checks.push(set2[i].id);
        }
        }
    //now copy all checked items -- hidden field and email address -- to the form
    var theform = $('moreinvites');
    theform.innerHTML = '';
    for (var i=0;i<checks.length;i++) 
    {
        var hiddenemail = '<input type="hidden" name="__NAME__" value="__VALUE__" />';

        //copy the INPUT type="radio" field
        var cradio = $(checks[i]);
        var fradio = hiddenemail.replace('__NAME__','company-'+i+'.checked');
        fradio = fradio.replace('__VALUE__', cradio.checked + '" checked="checked"');

        //copy the INPUT type="text" field
        var cemail = $( checks[i].replace('checked','email') );
        var ftext = hiddenemail.replace('__NAME__','company-'+i+'.email');
        ftext = ftext.replace('__VALUE__',cemail.value);

        //copy the INPUT type="hidden" field
        var cid = $( checks[i].replace('checked','id') );
        var fid = hiddenemail.replace('__NAME__','company-'+i+'.id');
        fid = fid.replace('__VALUE__',cid.value);

        theform.innerHTML += fradio + fid + ftext;
    }
    log('form stuff', $('moreinvites').innerHTML);
    return true;
    }

/* END from inviteCombo search
******************/

/* BEGIN from merchant updateable maps
******************/
if (!mc) { var mc = {}; logDebug('mc created before mc.mapset'); }
if (!mc.mapset) {  mc.mapset = function () {}; }
mc.mapset.prototype = {
    url:null,
    lat:null,
    lon:null,
    origlat:null,
    origlon:null,
    init:function (url, lat , lon, origlat, origlon) {
        //receives IDs to values 
        this.url = url;
        this.lat = lat;
        this.lon = lon;
        this.origlat = origlat;
        this.origlon = origlon;
		logDebug('mc.mapset instance initialized');
        return this;
    },
    saveMapLocation: function( ) {
		obj = this;
        var qry= queryString({lat:$(obj.lat).value,lon:$(obj.lon).value, showMap:$('showMap').checked});
		$('origlat').value = $(obj.lat).value;
		$('origlon').value = $(obj.lon).value;
        var d = doXHR(obj.url, 
		{
            method:'POST',
			sendContent:qry,
            headers: {"Content-Type":"application/x-www-form-urlencoded"} 
        });
        d.addCallback(function (result) { 
				$('notify').innerHTML=unescape(result.responseText);
				appear('notify',{duration:0.3});
			});
        d.addErrback( function (result) { 
				$('notify').innerHTML=result.responseText; 
				logError('saveMapLocation callback failed'); 
			});
    },
    reset: function () {
        obj = this;
        orig = [$(obj.origlat).value,$(obj.origlon).value];
        log('reset clicked', orig);
    }
};
/* END merchant updateable maps
******************/



/*
**  Interactive Spell Checker code
*/

var gSpellCheckDone = false;
/*
**  show_hover_event 
**      populates the popup div with spelling correction suggestions,
**      and positions it "near" the preview field, which is an anchor somewhere.
**      The function depends on a div with id 'hover_div' defined in calling document
*/
function show_hover_event(e) {
    var a = e.target();
    popup_over(a);
}
function popup_over(a) {
    if (!a.id) return;
    var keys = a.id.split('-');
    // keys[1] is the preview field name
    // keys[2] is the index of the misspelling in the original string
    // keys[3] is the misspelled word
    var spanRE = new RegExp('span\\d+' + '-' + keys[1] + '-' + keys[2] + '-' + keys[3]);
    var hover_div = $('hover_div');
    hover_div.innerHTML = '';
    var repls = getElementsByTagAndClassName('span', 'replacementWord', a);
    var replacements = [];
    var text = a.childNodes[0].nodeValue;
    for (var j = 0; j < repls.length; j++) {
        var spanid = repls[j].id;
        if (spanid && spanid.match(spanRE)) {
            replacements.push(repls[j]);
        }
    }

    var len = replacements.length;
    var ul = UL();
    var anchor = null, li = null;
    for (var i = 0; i < len; i++) {
        var span = replacements[i];
        text = span.childNodes[0].nodeValue;
        anchor = A({'id':span.id.replace(/^span/,'a'), 'class':'wordReplaceAnchor', 'href':'javascript:void(0)'}, text);
        li = LI({'name':'foo'}, anchor);
        ul.appendChild(li);
    }
    hover_div.appendChild(ul);
    var pos = getElementPosition(a);
    var dims = getElementDimensions(a);
    pos.x += 3;
    pos.y += 5;
    // Connect up click handlers
    var anchors = getElementsByTagAndClassName('a', 'wordReplaceAnchor', hover_div);
    for (var i = 0; i < anchors.length; i++) {
        connect(anchors[i], 'onclick', highlightedWordClickHandler);
    }
    showElement('hover_div_container');
    // Wait a couple of seconds, then add a click handler to the document to close the hover div.
}

/*
**  Empty out and hide the popup
*/
function hide_hover_div() {
    $('hover_div').innerHTML = '';
    hideElement('hover_div_container')
}

/*
**  What to do when somebody clicks on a spelling suggestion
**
**  Each of the anchors has an id of the form:
**      aN-previewFieldId-index-replacementText
**      N is an integer, previewFieldId is the target anchor to replace,
**      index is the index of the misspelled word in the original input string,
**      replacementText shouldn't contain spaces...
*/

function highlightedWordClickHandler(evt) {
    var anchor = evt.target();
    var keys = anchor.id.split('-');
    var replacement = anchor.childNodes[0].nodeValue;
    replacement = replacement.replace(/^ */,'');
    replacement = replacement.replace(/ *$/,'');
    var previewField = keys[1];
    var field = fieldsFromPreview[previewField];
    var index = keys[2];
    var text = keys[3];
    var oldvalue = $(field).value;
    var pf = $(previewField);
    var targetAnchor = null;
    var spans = [];
    var found = false;
    var spid;
    
    // We've just got to find the anchor written in for this index by highlightWord,
    // replace it with a plain text node with the replacement text, and remove the
    // corresponding spans.
    var aid = 'anchor-' + previewField + '-' + index + '-' + text;
    targetAnchor = $(aid);
    if (!targetAnchor) return;
    swapDOM(targetAnchor, document.createTextNode(replacement));
    $(field).value = collapse_text(previewField);
    hide_hover_div();
}

function collapse_text(src) {
    var s = $(src);
    var nodes = s.childNodes;
    var child;
    var text = '';
    for (var i = 0; i < nodes.length; i++) {
        child = nodes[i];
        if (child.nodeName == "#text") {
            text += child.nodeValue;
        }
        if (child.nodeName == "A") {
            text += child.firstChild.nodeValue;
        }
    }
    return text;
}

/* map info windows
-- showMapInfoBlock called by marker (mcGmap.js)
-- result data populated by AJAX data returned (map.py)
*/

function DirectoryInfo(url,func) {
	this.url = url;
	this.targetId = 'mapInfoBlock';
	this.queryParams = undefined;
	this.afterCallback = undefined;
	if (!isUndefinedOrNull(func)) {
		this.func = func;
	}
}

DirectoryInfo.prototype.getInfo = function () {
	if (isUndefinedOrNull(this.queryParams)) {
		var d = loadJSONDoc(this.url);
	} else {
		var d = loadJSONDoc(this.url, this.queryParams);
	}
	//add the ajax object for access in AJAX callback
	d.dirInfo = this;
	$(this.targetId).innerHTML = '<div class="loading">Searching for businesses. Please wait.</div>';
    var cb = bind(function (result) { 
            if (isUndefinedOrNull(this.targetId)) 
            		this.targetId = 'mapInfoBlock';
            	$(this.targetId).innerHTML = result['data'];
            	try {
            		markers = result["gmap"];
            		if (!isUndefinedOrNull(d.dirInfo.func)) {
            			var evalStr='frames["gmframe"].' + d.dirInfo.func + '(markers);'
            			eval(evalStr);
            		} else {
            			frames['gmframe'].ajaxUpdateNearBy(markers);
            		}
            		if (!isUndefinedOrNull(d.dirInfo.afterCallback)) {
            		    d.dirInfo.afterCallback();
            		}
            	} catch (err) {
            		log('markers failed', err);
            	}
            }, this);
	d.addCallback(cb); //end d.callback
	return d;
}

DirectoryInfo.prototype.setFunc = function (funcName) {
    this.func = funcName;
}

/*select box navigator. 
* USAGE:
*  <select onchange="(this.id)">
*/
function selectGoTo(id) {
	window.location.href=$(id).value;
}

/* End map info windows
**************************/


/* Send to Friend
**************************/
function sendtofriend(actionUrl, formUrl, routeUrl, args) {
	this.actionUrl = actionUrl;
	this.formUrl = formUrl;
	this.routeUrl = routeUrl;
    this.replaceId = 'sendtofrienddiv';
    this.waitingId = 'sendToFriend';
	this.expertCount = 5;
	if (!isUndefinedOrNull(args)) {
	    this.replaceId = args['target'] || 'sendtofrienddiv';
	    this.waitingId = args['waiting'] || 'sendToFriend';
	    this.companyId = args['companyId'] || undefined;
        this.pageTitle = args['pageTitle'] || undefined;
        this.objectId = args['objectId'] || undefined;
        this.objectType = args['objectType'] || undefined;
	}
}

//AJAX retrieve the Send to friend form
sendtofriend.prototype.getForm = function () {
	var qry = queryString({url:this.routeUrl, companyId:this.companyId, pageTitle:this.pageTitle});
	var d = doXHR(this.formUrl, 
					{
			            method:'POST',
						sendContent:qry,
			            headers: {"Content-Type":"application/x-www-form-urlencoded"} 
			        });
	d.addCallback(this.handleResponse);
	d.addErrback(this.handleError);
}

//AJAX form submission
sendtofriend.prototype.sendForm = function () {
    var qryDict = {fromName: $('fromName').value,
							fromEmail: $('fromEmail').value,
							toEmail: $('toEmail').value,
							message: '',
							url: $('send_url').value,
							pageTitle:this.pageTitle,
							captchaGuess: $('stfCaptchaGuess').value,
							captchaHash: $('stfCaptchaHash').value,
							companyId:$('send_companyId').value};
    if ( !isUndefinedOrNull(this.objectType) && !isUndefinedOrNull(this.objectType) ) {
        qryDict['objectType'] = this.objectType;
        qryDict['objectId'] = this.objectId;
    }
	var qry = queryString( qryDict );
	var d = doXHR(this.actionUrl, {method:'POST',
						sendContent:qry,
						headers: {"Content-Type":"application/x-www-form-urlencoded"} 
					});
	$(this.waitingId).innerHTML = 'Please wait';
	d.addCallback(this.handleResponse);
	d.addErrback(this.handleError);
	return false;
}

sendtofriend.prototype.handleResponse = function (result) {
	log('handleResponse');
    if (isUndefinedOrNull(result.responseText)) {
        $('sendtofrienddiv').innerHTML = 'error ocurred';
    }
    //sendToFriend is display:none by default
	var stf = getElement('sendtofrienddiv');

	if (!stf) {
		//create new container
		stf = DIV({id:'sendtofrienddiv', style:'position:absolute;top:0'}, 'MerchantCircle is great.');
		appendChildNodes('footer', stf);
	}

	stf.innerHTML = result.responseText;
	try {
        //display the form
        var ndim = getViewportDimensions();
        var npos = getViewportPosition();
        npos.x = ndim.w / 4; //put corner off the side.
        npos.y -= 60;

		makePositioned(stf)
        setElementPosition(stf, npos);

        Draggable(stf, {handle:'movehandle'});
        showElement('sendToFriend');
    } catch (exc){
		log('sendtofriend positioning failed', exc);
        stf.innerHTML = result.responseText;
    }
	try {
		_gaq.push(['_trackEvent', "Send to Friend", "Share", window.location.pathname]);
	} catch (err) {
		log(err, 'sendtofriend');
	}
}

sendtofriend.prototype.handleError = function (result) {
	log('handleError');
	$('sendtofrienddiv').innerHTML = result['data'];
}

//suggest an expert to answer a question. A slight twist on the current sendtofriend.
sendtofriend.prototype.getSuggestExpertForm = function (qid) {
	var qry = queryString({url:this.routeUrl, companyId:this.companyId, questionID:qid, pageTitle:this.pageTitle, formVersion:'suggestExpert'});
	var d = doXHR(this.formUrl, 
					{
						method:'POST',
						sendContent:qry,
						headers: {"Content-Type":"application/x-www-form-urlencoded"} 
					});
	d.addCallback(this.handleResponse);
	d.addCallback( function () { ghostText('suggestQ', 'search connections'); });
	d.addErrback(this.handleError);
}

sendtofriend.prototype.getMore = function (url, listID, start, limit) {
	var qry = queryString({start:start, limit:limit});
	var d = doXHR(url, 
					{
						method:'POST',
						sendContent:qry,
						headers: {"Content-Type":"application/x-www-form-urlencoded"} 
					});
	removeElement(listID);
	d.addCallback(function (result) {
		addl = DIV();
		addl.innerHTML = result.responseText;
		appendChildNodes('suggestExpertList', addl);
	});
}

sendtofriend.prototype.searchConnections = function ( id ) {
	var qry = queryString({coname:$('suggestQ').value});
	var url = '/ajax/sendtofriend/searchConnections';
	var d = doXHR(url, 
					{
						method:'POST',
						sendContent:qry,
						headers: {"Content-Type":"application/x-www-form-urlencoded"} 
					});
	d.addCallback(function (result) {
		$('suggestExpertList').innerHTML = result.responseText;
	});
	return false;
}

sendtofriend.prototype.expertClick = function (obj, kind, id, text) {
	if (obj.checked == true) {
		if (this.expertCount == 0) {
			//max number of experts chosen. Do not allow to check.
			obj.checked = false;
			alert('Sorry! To prevent spam, you can only pick 5 people at a time.');
			return;
		} else {
			appendChildNodes('selectedExperts', 
				DIV({id:kind+'_'+id}, obj.title, 
					INPUT({type:'hidden', name:'expert-'+this.expertCount+'.id', value:id}),
					INPUT({type:'hidden', name:'expert-'+this.expertCount+'.obj', value:kind}),
					INPUT({type:'hidden', name:'expert-'+this.expertCount+'.text', value:text})
				));
			$('expertCount').innerHTML = --this.expertCount + ' left';
			return;
		}
	}  else {
		//remove the dom node
		removeElement(kind+'_'+obj.value);
		$('expertCount').innerHTML = ++this.expertCount;
		return;
	}
}

sendtofriend.prototype.sendExpert = function (obj) {
	qry1 = formContents(obj);
	qry2 = formContents('suggestEmailForm');
	names = concat(qry1[0], qry2[0]);
	values = concat(qry1[1], qry2[1]);
	qry = queryString(names, values)
	log(qry);
	var d = doXHR(obj.action, 
					{
						method:'POST',
						sendContent:qry,
						headers: {"Content-Type":"application/x-www-form-urlencoded"} 
					});
	this.expertCount = 5;
	d.addCallback(this.handleResponse);
	d.addCallback(function () {
		//if returns with an error, go back and check boxes for friends/companies
		map(function(obj) {
				try {
					//friends are user_XX and ck_user_XX
					//companies are company_XX and ck_company_XX
					getElement('ck_'+obj.id).checked = true;
				} catch (err) {}
			},
			getElementsByTagAndClassName('div','errExpert'));
	});
	d.addErrback(this.handleError);
	return false;
}

sendtofriend.prototype.swapView = function (obj, showMe) {
	// show/hide suggest experts tabs
	map(hideElement, ['suggestEmailList', 'suggestNeighborList', 'suggestExpertBox']);
	showElement(showMe);
	
	//highlight tab
	map(function (id) { 
			try {removeElementClass(id, 'expertHighlighted');} 
			catch(err){log(err);}
		}, ['expertCoTab','expertNbrTab','expertEmTab'] );
	addElementClass(obj, 'expertHighlighted');
}
/* End Send to Friend
**************************/

/* Newsletter subscribe
**************************/
function newsletterSubscribe () {
}

newsletterSubscribe.prototype.submitSubscription = function (form)
{
	var res = loadJSONDoc(form.action, { 'email':form['email'].value});
	res.addCallbacks(this.doReplaceForm,this.doReplaceErrorForm);
	return false;
}

newsletterSubscribe.prototype.doReplaceForm = function (result) {
    $('newsLetterSubscribe').innerHTML = result["data"];
}

newsletterSubscribe.prototype.doReplaceErrorForm = function () {
	window.location.reload();
}

/* End Newsletter subscribe
**************************/

/* use for onclick to mimic links. prevents robots from clicking to expensive pages
*****/
function jsHref (url) {
    window.location.href = url;
}


/* FORUM-
**************************/
var forum = {
    // thread
    initThread : function() {
    	if (isAdmin() || isModerator()) {
            this.showModerationControls('form','forumPostControl')				
    	} else {
    		// if customer toggle only the ones you've wrote...
    		var cid = getProfileCompany()
    		if (cid) {
    			this.showModerationControls('form', 'co-' + cid)
    		}	
    	}
    },
    // second-level topics...
    initTopic:function(klass) {
    	if (isAdmin() || isModerator()) {
            this.showModerationControls('*', 'forumModerator')
        }
    	if (isAdmin() ) {
            this.showModerationControls('*', 'forumAdmin')
        }
    },
    // main forum page listing all the forums (ie. top-level topics)...
    initTopics:function(klass) {
    	if (isAdmin() || isModerator()) {
            this.showModerationControls('*', 'forumModerator')
        }
    	if (isAdmin() ) {
            this.showModerationControls('*', 'forumAdmin')
        }
    },    
    showModerationControls:function(tagname, klass) {
    	var els = getElementsByTagAndClassName(tagname, klass);
    	var el;
    	for (var i=0; i < els.length; i++ )  {
            // showElement(els[i]);
            els[i].style.display = 'block';
    	}
    }
}
/* -FORUM
**************************/

/* LOCAL CONSUMER EMAIL
**************************/
/* usage: 
    newEmail = new localConsumerEmail({'city':'Pacifica', 'state':'CA'})
*/
function localConsumerEmail(args) {
    if (args != null) {
        if (args.action_get_form) {this._action_get_form=args.action_get_form;}
        if (args.action_post_form) {this._action_post_form=args.action_post_form;}        
        this.set_city_state(args.city, args.state, args.zip, args.neighborhood);
    }

    return this;
}


localConsumerEmail.prototype = {
    _email:null,
    _city:null,
    _state:null,
    _zip:null,
    _neighborhood:null,
    _action_get_form:null,
    _action_post_form:null,
    
    set_city_state:function(city,state,zip,neighborhood){
        this._city=city;
        this._state=state;
        this._zip=zip;
        this._neighborhood=neighborhood;
    },
    load_form:function(){
        var qs = queryString({city: this._city, state:this._state, zip:this._zip, neighborhood_id:this._neighborhood});
        
    	var d = doXHR(this._action_get_form, 
    	                {method:'POST',
    				     sendContent:qs,
    					 headers: {"Content-Type":"application/x-www-form-urlencoded"}
    					 });
    	d.addCallback(this.load_form_cb);
    	d.addErrback(this.load_form_error);        
    },
    load_form_cb:function(result){
        var el = $('local_consumer_email_signup');
        if (isUndefinedOrNull(result.responseText)) {
            el.innerHTML = "<p>We're sorry, an error ocurred trying to load the signup form.</p>";
        } else {  
            el.innerHTML = result.responseText
            localEmail.show_form();
        }
    },
    load_form_error:function(result){
        
    },
    
    show_form:function(){
        //display the form
        var ndim = getViewportDimensions();
        var npos = getViewportPosition();
        npos.x = (ndim.w / 2) - 300; //put corner off the side.
        npos.y += 50;
        var id = 'local_consumer_email_wrap'
        setElementPosition(id, npos);
        Draggable(id);
        showElement(id);
    },    
    
    
    signup:function(){
        var rec =  $('recipient').value;
        var zipcode_id = $('zipcode_id').value;
        var neighborhood_id =  $('neighborhood_id').value;
        var captchaHash = $('captchaHash').value;
        var captchaGuess = $('captchaGuess').value;
        
        var qs = queryString({recipient:rec, zipcode_id:zipcode_id, neighborhood_id:neighborhood_id, captchaHash:captchaHash, captchaGuess:captchaGuess});
    	var d = doXHR(this._action_post_form, 
    	                {method:'POST',
    				     sendContent:qs,
    					 headers: {"Content-Type":"application/x-www-form-urlencoded"}
    					 });
    	d.addCallback(this.signup_cb);
    	d.addErrback(this.signup_error);
    },
    signup_cb:function(result){
        var el = $('local_consumer_email_signup');
        if (isUndefinedOrNull(result.responseText)) {
            el.innerHTML = "<p>We're sorry, an error ocurred trying to save the signup form.</p>";
        } else {   
            el.innerHTML = result.responseText        
        }
    },
    signup_error:function(result){
        var el = $('local_consumer_email_signup');
        el.innerHTML="<p>We're sorry, there was an error processing your request.</p>"        
    },

    close:function(){
      hideElement('local_consumer_email_wrap');
      app.signup.consumer_nudge();
    },
    end:function(){}
}


/* -CONSUMER EMAIL
**************************/


/* Neighborhood navigator
**************************/
function mcNeighborSearch (url) {
    if (url)
	    this.url = url;
	insertSiblingNodesAfter('qsearch',SPAN({id:'neighborsearch', title:'narrow your search results'},IMG({src:'/static/imgs/buttons/arrowBox_neighborhoods.png', alt:'See neighborhoods in this city.'})));
	this.fired = false;
	this.ajax = null;
	return this;
}
mcNeighborSearch.prototype = {
	staticlist : function () {
	    //use this for static page DOM manip
	    //var mydiv = DIV({id:'neighborpopup'});
	    //mydiv.innerHTML = getElement('neighborlist').innerHTML;
	    //insertSiblingNodesAfter('neighborsearch',mydiv);
	    qpos = getElementPosition('neighborsearch');
        setElementPosition('neighborpopup',{x:qpos.x-100,y:qpos.y+30});
		appear('neighborpopup', {delay:0.1,duration:0.3});
		connect('nhoodclose','onclick', this.closelist);
	},
	getlist : function () {
	    //use this to get neighborhoods via ajax
		if (!this.fired) {
		this.ajax = loadJSONDoc(this.url);
		this.ajax.addCallback(bind(this.neighborhood_cb,this));
		this.fired = true;
		return;
		}
		appear('neighborpopup', {delay:0.3,duration:0.5});
	},
	neighborhood_cb : function (result) {
		var mydiv = DIV({id:'neighborpopup'});
		mydiv.innerHTML = result['data'];
		insertSiblingNodesAfter('neighborsearch', mydiv);
		appear(mydiv, {delay:0.2,duration:0.3});
		connect('nhoodclose','onclick', this.closelist);
	},
	closelist : function () {
	    fade('neighborpopup', {duration:0.3});
	}
}
/* end Neighborhood navigator
**************************/

/* Paid Info Popup
**************************/
function popHelp(utm) {
    var w = 520;
    var h = 400;
    var winopts = "toolbar=no,location=no,directories=no,status=yes,";
	var url = "/merchant/help/paidInfo";
    winopts = winopts + "menubar=no,scrollbars=no,resizable=yes,";
    winopts = winopts + "width=" + w + ",height=" + h;
    popupWin = window.open(url,"ContactSales",winopts);
	try{
		if (!isUndefinedOrNull(utm)) {
			_gaq = _gaq || [];
			_gaq.push(['_setCampMediumKey', utm['utm_medium']]);
			_gaq.push(['_setCampSourceKey', utm['utm_source']]);
			_gaq.push(['_trackPageview', url]);
		}
	} catch(err) { log(err); }
    popupWin.focus();
}
/* end Paid Info Popup
**************************/

/* Paid Info Popup
**************************/
function couponVote(coupon, replace, url) {
	getElement(replace).innerHTML = 'Saving...';
	var qry= queryString({id:coupon});
	var d = doXHR(url, 
		{
			method:'POST',
			sendContent:qry,
			headers: {"Content-Type":"application/x-www-form-urlencoded"} 
		});
	var voteResponse = function (resp) {
		var x = resp.responseText;
		var btn = A({ }, resp.responseText + ' Votes. Thanks!');
		
		
		swapDOM(replace, btn);
	};
	var voteErr = function (resp) {
		getElement(replace).innerHTML = 'error';
	};
	d.addCallback( voteResponse );
	d.addErrback( voteErr );
}
/* end Paid Info Popup
**************************/

/* Clipping offer (coupon, sale, promotion) into my offer book
**************************/
function needLoginOrNot(offer, replace, kind, url) {
    if (!isLoggedIn()) {
        // var redir = window.location.pathname+window.location.search;
        // redir = escape(redir);
        // var btn = A({'class':'clipMe','href':"/auth/login?redir="+redir}, 'Signup/Login to Clip');
        // swapDOM(replace, btn);
        app.signup.consumer_nudge();        
    } else {
        clipThisOffer(offer, replace, url);
    }
}

function clipThisOffer(offer, replace, url) {
	getElement(replace).innerHTML = 'Clipping to my CouponBook...';
	var qry= queryString({id:offer, check:1});
	var d = doXHR(url, 
		{
			method:'POST',
			sendContent:qry,
			headers: {"Content-Type":"application/x-www-form-urlencoded"} 
		});
	var clipResponse = function (resp) {
		var x = resp.responseText;
		if (x == -1){
            var redir = window.location.pathname+window.location.search;
            redir = escape(redir);
            window.location.href = "/auth/login?redir="+redir;
		} else if (x == -2) {
            var redir = window.location.pathname+window.location.search;
            redir = escape(redir);
            window.location.href = "/profile/get_started?redir="+redir;
		} else if (x == -3){
		    var btn = A({'class':'clipMe'}, 'Sorry! Cannot Clip This');
		} else {
		    var gotoMyOfferbookURL =  window.location.protocol + "//" + window.location.host + "/profile/showMyOfferbook";
		    var btn = A({'class':'clipMe','href':gotoMyOfferbookURL}, 'Clipped! View CouponBook.');
			try{
				_gaq.push(['_trackEvent', "Coupon", "Clip", window.location.pathname]);
			} catch(err) {
				log(err, 'clipResponse');
			}
			
		}
		swapDOM(replace, btn);
        try {app.fb.publish_feed_story()}catch(e){}; // trigger the action to submit the facebook feed story
	};
	var clipErr = function (resp) {
		getElement(replace).innerHTML = 'error';
	};
	d.addCallback( clipResponse );
	d.addErrback( clipErr );
}
/* end Clipping offer
**************************/

/* Add a favorite
**************************/
function addFavorite(cid, replace, url, profileUrl ) {
	getElement(replace).innerHTML = 'Following ... <img src="/static/imgs/loader_small.gif" alt="processing" />';
	var qry= queryString({cid:cid});
	var d = doXHR(url, 
		{
			method:'POST',
			sendContent:qry,
			headers: {"Content-Type":"application/x-www-form-urlencoded"} 
		});
	var addFavoriteResponse = function (resp) {
	    try {
	    	var data = evalJSONRequest( resp );
	    } catch (e) {
	    }
		redir = data.redir
		if (data.fromWhere == 'nbregflow') {
		    getElement( replace ).innerHTML = 'Success! Thanks for following ';
		} else if (redir != '') {
		    getElement( replace ).innerHTML = 'Success! View <a href="' + profileUrl + '">My Main Street</a>';
		    document.location = unescape(redir);
        } else {
		    getElement( replace ).innerHTML = 'Success! View <a href="' + profileUrl + '">My Main Street</a>';
        }
        try {app.fb.publish_feed_story()}catch(e){}; // trigger the action to submit the facebook feed story

	};
	var addFavoriteErr = function (resp) {
        // getElement(replace).innerHTML = resp.responseText;
		getElement( replace ).innerHTML = 'Success! View <a href="' + profileUrl + '">My Main Street</a>';
	};
	d.addCallback( addFavoriteResponse );
	d.addErrback( addFavoriteErr );
}
/* end add favorite
**************************/

function updateTbl( tbl, item, key ) {
    var elt = tbl[ key ];
    if (! elt ) {
        tbl[ key ] = [ item ]
    } else {
        tbl[ key ][tbl[key].length] = item;
    }
    return tbl;
}
/*
** showAddFavoriteLinks
** Crawl over the page looking for links with class showFavoriteLink
** Gather up the ids, which should all be of the form favorite-N, where
** N is the company id
**
** The callback turns on those links that are not already in the favorites set
** of the logged-in user (no user, all links)
*/
var addFavoriteLinksDone = false
function showAddFavoriteLinks( url )
{
    if ( addFavoriteLinksDone ) {
        return;
    }
    // No logged-in user, return
    if ( ! getSessionUserName() ) {
        return;
    }
    var links = getElementsByTagAndClassName( 'span', 'showFavoriteLink' );
    if ( links.length == 0 ) return;
    var ids = [];
    var tbl = {};
    for (var i = 0; i < links.length; i++ ) {
        var cid = getNodeAttribute( links[i], 'name' ) ? 
                        getNodeAttribute( links[i], 'name' ).replace( /^favorite-/, '') : 0;
        ids.push( cid );
        updateTbl( tbl, links[i], cid );
    }
    var qs = queryString( { fids: ids, backlink:document.location } );
	var d = doXHR(url, 
	{
		method:'POST',
		sendContent: qs, 
		headers: {"Content-Type":"application/x-www-form-urlencoded"} 
	});
    addFavoriteLinksDone = true;
    
    function callback( t, rp ) {
        // Incoming data is an array of dictionaries: { redir:X, fid:i }
        var data = evalJSONRequest( rp );
        var links = null;
        for ( var i = 0; i < data.length; i++ ) {
            datum = data[i]
            links = t[ datum.cid ];
            if ( links ) {
                for (var j = 0; j < links.length; j++ ) {
                    if ( datum.redir ) {
                        links[j].innerHTML = datum.redir;
                    } else {
                        links[j].innerHTML = '';
                    }
                }
            }
        }
    }
    d.addCallback( partial ( callback, tbl ) );
    d.addErrback( function( rp ) 
        {
            log('showAddFavoriteLinks: error', rp.responseText )
        });
}

/*
** showAddFriendsLinks
** Crawl over the page looking for links with class showFriendLink
** Gather up the ids, which should all be of the form friend-N, where
** N is the user id
**
** The callback turns on those links that are not already in the friends set
** of the logged-in user (no user, no links)
*/
var addFriendLinksDone = false; 
function showAddFriendLinks( url )
{
    log( 'Entering show add friends links');
    if ( addFriendLinksDone ) {
        return;
    }
    // No logged-in user, return
    if ( ! getSessionUserName() ) {
        return;
    }
    var links = getElementsByTagAndClassName( 'span', 'showFriendLink' );
    if ( links.length == 0 ) return;
    var ids = [];
    var tbl = {};
    for (var i = 0; i < links.length; i++ ) {
        var uid = getNodeAttribute( links[i], 'name' ) ? 
                        getNodeAttribute( links[i], 'name' ).replace( /^friend-/, '') : 0;
        if (uid != 0 ) {
            ids.push( uid );
            updateTbl( tbl, links[i], uid );
            log( 'adding ', uid, links[i])
        }
    }
    var qs = queryString( { uids: ids, backlink:document.location  } );
    log( 'showAddFriendLinks: qs', qs);
	var d = doXHR(url, 
	{
		method:'POST',
		sendContent: qs, 
		headers: {"Content-Type":"application/x-www-form-urlencoded"} 
	});
    addFriendLinksDone = true;
    
    function callback( t, rp ) {
        // Incoming data is an array of dictionaries: { redir:X, fid:i }
        var data = evalJSONRequest( rp );
        var links = null;
        for ( var i = 0; i < data.length; i++ ) {
            datum = data[i]
            links = t[ datum.uid ];
            if ( links ) {
                for (var j = 0; j < links.length; j++ ) {
                    if ( datum.redir ) {
                        links[j].innerHTML = datum.redir;
                    } else {
                        links[j].innerHTML = '';
                    }
                }
            }
        }
    }
    d.addCallback( partial ( callback, tbl ) );
    d.addErrback( function( rp ) 
        {
            log('showAddFriendLinks: error', rp.responseText )
        });
}
function showAddCommentLinks( url )
{
    var links = getElementsByTagAndClassName( 'a', 'leave_comment' );
    if ( links.length == 0 ) return;
    var ids = [];
    for (var i = 0; i < links.length; i++ ) {
        ids.push( links[i].id.replace( /^leave_comment_/, '') );
    }
    var qs = queryString( { sids: ids, backlink:document.location  } );
	var d = doXHR(url, 
	{
		method:'POST',
		sendContent: qs, 
		headers: {"Content-Type":"application/x-www-form-urlencoded"} 
	});

    d.addCallback( function (rp )
        {
            var data = evalJSONRequest( rp );
            var redir = data.redir;
            var showLinks = data.fids;
            for ( var i = 0; i < showLinks.length; i++ ) {
                if ( redir ) {
                    $( 'leave_comment_' + showLinks[ i ] ).href = redir;
                }
                showElement( 'leave_comment_' + showLinks[ i ] );
            }
        });
    d.addErrback( function( rp ) 
        {
            log('showAddCommentLinks: error', rp.responseText )
        });
}

function showConnectMerchantLink(targetId, recipientId, url) {
	/*
	Inject a "connect with this merchant" box onto the page
	recipientId = company.id
	*/
	// No logged-in user, return || on my own listing
	if ( !getSessionUserName() || (recipientId == getProfileCompany()) ) {
		return;
	}
	
	// check connection status
	var returnId = function (x) { 
		//blast in the DIV as sibling before the big info block.
		if (!x['connected']) {
			var infoBlock = getFirstElementByTagAndClassName('div','hreview-aggregate');
			var newDom = DIV({'id':'invitemeblock'});
			// see snippets/company/loggedInMerchantConnect.tmpl
			newDom.innerHTML = x['snippet'];
			var foo = insertSiblingNodesBefore(infoBlock, newDom);
			
			//ticket #7427
			//added this to not show the "send message" link when the logged in user is not already
			//connected to the page they're viewing. Also had to remove the merchantOnlyInline class
			//because it has a !import on it's display property which causes hideElement to not work
			var sendMessage = getElementsByTagAndClassName('li', 'sendMessageLink');
            for (var i in sendMessage){
                removeElementClass(sendMessage[i], 'merchantOnlyInline');
                hideElement(sendMessage[i]);
            }
			
			log('You are not connected with this company.');
		} else {
			log('You are connected with this company already.');
		}
	};
	var d = loadJSONDoc(url, {fromCo:getProfileCompany(), toCo:recipientId});
	d.addCallback( returnId );
}

/*
** Add a comment to a status update from a public page, feed list
*/

function publicAddComment( sid, isComment, comment, url, replace )
// Use for both status and comment elements in a feed
// Replace is the parent node that can be filled in with comment styling
// and data.
{
	var qry= queryString( { sid:sid, isComment: isComment, comment:comment } );
	var d = doXHR(url, 
		{
			method:'POST',
			sendContent:qry,
			headers: {"Content-Type":"application/x-www-form-urlencoded"} 
		});
	var publicAddCommentCallback = function (resp) {
        var data = evalJSONRequest( resp );
        var redir = data.redir;
		var html = data.html;
		if (redir) {
		    window.location = redir;
		}
		getElement( replace ).innerHTML = html;
	};
	var publicAddCommentErrback = function (resp) {
		getElement(replace).innerHTML = 'error';
	};
	d.addCallback( publicAddCommentCallback );
	d.addErrback( publicAddCommentErrback );
    
}
/* Add a friend
**************************/
function addFriend(uid, replace, url) {
    log( 'addFriend, uid, replace, url', uid, replace, url);
	getElement(replace).innerHTML = 'Adding a friend...';
	var qry= queryString( { uid:uid } );
	var d = doXHR(url, 
		{
			method:'POST',
			sendContent:qry,
			headers: {"Content-Type":"application/x-www-form-urlencoded"} 
		});
	var addFriendResponse = function (resp) {
	    try {
	    	var data = evalJSONRequest( resp );
	    } catch (e) {
	        log( 'Error converting JSONRequest');
	        return;
	    }
		redir = data.redir;
		text = data.text;
	    getElement( replace ).innerHTML = text;
		if (redir != '') {
		    document.location = unescape(redir);
        }
	};
	var addFriendErr = function (resp) {
		getElement(replace).innerHTML = 'error';
	};
	d.addCallback( addFriendResponse );
	d.addErrback( addFriendErr );
}
/* end add favorite
**************************/

/*
** merchantFollowRequest
** Let the logged-in merchant send a follow me request to a nabor
*/
function merchantFollowRequest( nid, replace, url ) {
    $( replace ).innerHTML = 'Sending request...';
	var d = doXHR(url, 
		{
			method:'POST',
			sendContent: queryString( { nid:nid }),
			headers: {"Content-Type":"application/x-www-form-urlencoded"} 
		});
    var merchantFollowRequestResponse = function ( resp ) {
        $( replace ).innerHTML = evalJSONRequest( resp );
    }
    var merchantFollowRequestErr = function ( resp ) {
        log( evalJSONRequest( resp ) );
    }
    d.addCallback( merchantFollowRequestResponse );
    d.addErrback( merchantFollowRequestErr );
}

/* COMPLIMENTS
**************************
flows: 
1. compliments -> confirmation/review -> confirmation
2. review -> confirmation/compliments -> confirmation

**************************/
var compliments = {
    loader:'<img src="/static/imgs/loader.gif" alt="" style="margin-left:5px;" />',
    start_html:null,
    compliments_overlay:null,
    load_url:'/ajax/compliments/load',
    save_url:'/ajax/compliments/save',
    save_review_url:'/ajax/compliments/save_review',
    save_review_with_captcha_url:'/ajax/compliments/save_review_with_captcha',    
    anon_review:null,
    company_id:null,
    
    init:function(){
        // initialize all links on the page to launch the overlay
        var link;
        var links = getElementsByTagAndClassName('a', 'compliment_load')
        for (var i=0; i < links.length; i++){
            link = links[i];
            connect(link, 'onclick', 
                function() {
                    var company_id = this.id.replace('compliment_company_','');
                    compliments.show(company_id, this.title);
                    if (trackEngagement) { trackEngagement('compliment'); }
                })
        }
        $('compliments_overlay').style.display='';
        var overlay_config = { width:"800px",
                               fixedcenter:true, 
                               close:false, 
                               draggable:false, 
                               zindex:100,
                               modal:true,
                               visible:false,
                               constraintoviewport:true}
        this.compliments_overlay = new YAHOO.widget.Panel("compliments_overlay",overlay_config);
        this.compliments_overlay.render();
        
        //this.show('50289', 'Big House of Fun')
    },
    
    resize:function(){
        window.setTimeout(function(){
            compliments.compliments_overlay.sizeMask();
        },1000)           
    },
    
    // update the compliments_to_save value...
    record:function() {
        var check; var a = [];
        var checks = getElementsByTagAndClassName('input', 'compliment_category', 'compliment_categories');
        for (var i=0; i < checks.length; i++){
            check = checks[i];
            if (check.checked) {
                a.push(check.value);
            }
        }        
        $('compliments_to_save').value = a.join(',')
    },
    
    show:function(company_id, company_name){
        if (this.start_html) {
            $('compliments_overlay').innerHTML = this.start_html
        } else {
            $('compliments_inner').innerHTML = this.loader;
            this.start_html = $('compliments_overlay').innerHTML
        }
        this.company_id = company_id; // store for the save call
        this.company_name = company_name;
        $('compliments_company_name').innerHTML = company_name;
        this.load_form()
    },
    
    close:function(company_id){
        this.compliments_overlay.hide();
        if (isLoggedIn()) {
            app.fb.publish_feed_story();
        } else {
            app.signup.consumer_nudge();
        }
    },  
    
    load_form:function(){
        var qs = queryString( {'bust':Math.random()});
    	var d = doXHR(this.load_url, {
    	         method:'POST',
			     sendContent:qs,
			     headers: {"Content-Type":"application/x-www-form-urlencoded"}
    	});
    	d.addCallback(this.load_form_cb);
    	d.addErrback(this.load_form_cb_error);
    	
    },
    load_form_cb:function(result){
        var parent = $('compliments_inner')
        parent.innerHTML = result.responseText
        
        connect($('compliments_save'), 'onclick', function(){compliments.save()})
        compliments.compliments_overlay.show();
        compliments.resize();
    },
    load_form_cb_error:function(result){
        alert('load_form_cb_error')
    },

    save:function(){
        var compliments = $('compliments_to_save').value;
        var qs = queryString( {'company_id': this.company_id, 'compliments':compliments, 'bust':Math.random()});
        $('compliments_save').disabled = true;

    	var d = doXHR(this.save_url, {
    	         method:'POST',
			     sendContent:qs,
			     headers: {"Content-Type":"application/x-www-form-urlencoded"}
    	});
    	d.addCallback(this.save_cb);
    	d.addErrback(this.save_cb_error); 
    },
    save_cb:function(result){
        var r = YAHOO.lang.JSON.parse(result.responseText)
        var parent = $('compliments_overlay')
        parent.innerHTML = r.data;
        if ($('compTable')) {
            $('compTable').innerHTML = r.compliments_data;
        } else {
            // bury since we might not have the compTable on directory pages alert('missing compTable')
        }
        
        $('compliments_company_name').innerHTML = compliments.company_name;
        review.prepare_form();
        compliments.resize();
        connect($('review_submit'), 'onclick', 
            function() {        
                compliments.save_review()
            })

    },
    save_cb_error:function(){
       // alert('save_cb_error')
        $('compliments_save').disabled = false;
    },
    
    save_review:function(){

        var params = review.get_review_form_params() // grab this from compliments object
        params.company_id = this.company_id;
        var url = (params.captchaHash) ? this.save_review_with_captcha_url : this.save_review_url // captcha is only present for not logged in users...
        var qs =  queryString(params)
        var d = doXHR(url, {
             method:'POST',
             sendContent:qs,
             headers: {"Content-Type":"application/x-www-form-urlencoded"}
        });
        d.addCallback(this.save_review_cb);
        d.addErrback(this.save_review_cb_error);
        // show loader
        $('review_container').innerHTML = this.loader;
    },
    save_review_cb:function(result){
        var r = YAHOO.lang.JSON.parse(result.responseText);
        if (r.cb=='save_cb'){
            compliments.save_cb(result);
            review.toggle_anon(); // open the anon rows
        } else {
            var parent = $('compliments_overlay')
            parent.innerHTML = r.data
            window.setTimeout(function(){
                compliments.close();
                app.fb.publish_feed_story();
            }, 3000)
        }
    },
    save_review_cb_error:function(result){
        alert('save_review_cb_error')
    },
    
    end:function(){}
}

var review = {
    initialized:false,
    loader:'<img src="/static/imgs/loader.gif" alt="" style="margin-left:5px;" />',
    start_html:null,
    review_overlay:null,
    load_url:'/ajax/compliments/load_review_form',
    save_review_url:'/ajax/compliments/save_review_form',
    save_review_with_captcha_url:'/ajax/compliments/save_review_form_with_captcha',
    
    save_compliments_url:'/ajax/compliments/save_compliments',

    anon_review:null,
    company_id:null,
    stars:null,
    
    init:function(){
        // loop all links and attach event handlers for writing a review
        var link;
        var links = getElementsByTagAndClassName('a', 'review_load');
        for (var i=0; i < links.length; i++){
            link = links[i];
            connect(link, 'onclick', function() {
                    this.href="javascript:void(0);"
                    var company_id = this.id.replace('review_company_','');
                    review.show(company_id, this.title);
                    return false
                })
        }
        
        var overlay_config = { width:"800px",
                               fixedcenter:true, 
                               close:false, 
                               draggable:false, 
                               zindex:100,
                               modal:true,
                               visible:false,
                               constraintoviewport:true}
        
        $('review_overlay').style.display='';
        this.review_overlay = new YAHOO.widget.Panel("review_overlay",overlay_config);                                                               
        this.review_overlay.render();
        this.initialized = true;
        //this.show('50289', 'Big House of Fun')
    },
    
    // this is triggered after someone rates a business... initialize the stars for the rating form to this value
    prepare_to_show:function(link) {
        if (this.initialized) {
            var stars = link.href.split('?stars=')
            if (stars.length) {
                this.stars = parseInt(stars[1])
            }
            link.href="javascript:void(0);"
            var company_id = link.id.replace('review_company_','');
            review.show(company_id, link.title);
            return false;
        } else {
            return true // shortcircuit so the link.href is used instead of loading the overlay
        }
    },

    get_review_form_params:function(){
        // the captcha form requires all these fields; the logged in user only has title, rating, body
        var fields = ['name', 'zipcode', 'email', 'captchaGuess', 'captchaHash', 'review_title', 'rating', 'body', 'anonymous'];
        var params = {}; 
        var params = {'anonymous':''}; 
        var field;
        for (var i=0; i < fields.length; i++){
            field = fields[i];
            if ($(field)) {
                if ( field == 'review_title' ) {
                    params['title'] = $(field).value;
                } else {
                    params[field] = $(field).value;
                }
            }
        }

		/*anonymity checking*/
		var author = 'none';
		if ($('authorAnonymous') && $('authorAnonymous').checked)
			author = 'anonymous';
		if ($('authorCompany') && $('authorCompany').checked)
			author = 'company';
		if ($('authorNeighbor') && $('authorNeighbor').checked)
			author = 'neighbor';
		params['anonymous'] = author;

        return params
    },

    show:function(company_id, company_name){
        if (this.start_html) {
            $('review_overlay').innerHTML = this.start_html
        } else {
            $('review_inner').innerHTML = this.loader;
            this.start_html = $('review_overlay').innerHTML
        }
        this.company_id = company_id; // store for the save call
        this.company_name = company_name;
        this.load_form()
    },
    
    close:function(){
        this.stars=null;
        this.review_overlay.hide();
        // only show the fb feed stuff for logged_in users
        if (isLoggedIn()) {
            app.fb.publish_feed_story();
        } else {
            app.signup.consumer_nudge();
        }
    },    
    
    resize:function(){
        window.setTimeout(function(){
           review.review_overlay.sizeMask();
        },1000)           
    },    

    load_form:function(){
        var qs = queryString( {'company_id': this.company_id, 'bust':Math.random()});
    	var d = doXHR(this.load_url, {
    	         method:'POST',
			     sendContent:qs,
			     headers: {"Content-Type":"application/x-www-form-urlencoded"}
    	});
    	d.addCallback(this.load_form_cb);
    	d.addErrback(this.load_form_cb_error);
    	
    },
    load_form_cb:function(result){
        var parent = $('review_inner')
        parent.innerHTML = result.responseText
        review.prepare_form();
        connect($('review_submit'), 'onclick', 
            function() {        
                review.save_review()
            })
        $('review_company_name').innerHTML = review.company_name;
		if ($('email')) {
		    $('email').value = ''; //prevent browser caching on email hidden field
        }
        review.review_overlay.show();
        review.resize();
    },
    
    load_form_cb_error:function(result){
        // alert('load_form_cb_error')
    },    
    
    save_review:function(){
        //review written first, compliments to follow
        var params = this.get_review_form_params()
	this.params = params;
        params.company_id = this.company_id;
        var url = (params.captchaHash) ? this.save_review_with_captcha_url : this.save_review_url // captcha is only present for not logged in users...
        var qs =  queryString(params) // queryString( {'company_id': this.company_id, 'name':name, 'zipcode':zipcode, 'email': email, 'title': title, 'rating':rating, 'body':body, 'anonymous':this.anon_review, 'captchaGuess':captchaGuess, 'captchaHash': captchaHash});
        var d = doXHR(url, {
             method:'POST',
             sendContent:qs,
             headers: {"Content-Type":"application/x-www-form-urlencoded"}
        });
	d.addCallback(this.save_review_cb);
        d.addErrback(this.save_review_cb_error);
        // show loader
        $('review_container').innerHTML = this.loader;
    },
    save_review_cb:function(result){
        var r = YAHOO.lang.JSON.parse(result.responseText);
        if (r.cb=='load_form_cb'){
            review.load_form_cb({'responseText':r.data});
            review.toggle_anon(); // open the anon rows
        } else {
	    //params = this.get_review_form_params()
	    if(review.params.rating > 2) {
		    var parent = $('review_overlay')
		    parent.innerHTML = r.data
		    $('review_company_name').innerHTML = review.company_name;
		    connect($('compliments_save'), 'onclick', function(){review.save_compliments()})		
	    }
	    else {
		    review.close();
	    }
        }
    },
    save_review_cb_error:function(result){
        // alert('save_review_cb_error')
    },


    save_compliments:function(){
        var compliments = $('compliments_to_save').value;
        var qs = queryString( {'company_id': this.company_id, 'compliments':compliments, 'bust':Math.random()});
        $('compliments_save').disabled = true;        
    	var d = doXHR(this.save_compliments_url, {
    	         method:'POST',
			     sendContent:qs,
			     headers: {"Content-Type":"application/x-www-form-urlencoded"}
    	});
    	d.addCallback(this.save_compliments_cb);
    	d.addErrback(this.save_compliments_cb_error);
    	$('compliments_inner').innerHTML = this.loader;
    	
    },
    save_compliments_cb:function(result){
        var r = YAHOO.lang.JSON.parse(result.responseText)
        var parent = $('review_overlay')
        parent.innerHTML = r.data;
        if ($('compTable')) {
            $('compTable').innerHTML = r.compliments_data;
        } else {
            // this might not be here. for example search...
            // alert('missing compTable')
        }
        window.setTimeout(function(){
            review.close()
            app.fb.publish_feed_story();
        }, 3000)
        
    },
    save_compliments_cb_error:function(){
        // alert('save_compliments_cb_error')
        $('compliments_save').disabled = false;
    },


	select_star:function(id) {
		setNodeAttribute('star-' + (id + 1) , "src", "/static/imgs/icons/stars/star.gif");
	},
	
	clear_star:function(id) {
		setNodeAttribute('star-' + (id + 1) , "src", "/static/imgs/icons/stars/star_gray.gif");
	},
	sync_stars:function() {
		if (arguments.length)
			$('rating').value = arguments[0];
		map(this.select_star, range(0, parseInt($('rating').value)));
		map(this.clear_star, range(parseInt($('rating').value), 5));
		return false;
	},
	toggle_anon:function(){
	    if ($('authorAnonymous')) {
    		fn = $('authorAnonymous').checked ? removeElementClass: addElementClass ;
    		forEach( ['anonymousRow'],
    					function(id) { fn( id, 'consumerOnly' ); }
    				);
		}
	},
		
    prepare_form:function(){
        //      if (getProfileEmail() && ! $('email').value) {
        //     updateNodeAttributes( "email", {'value':getProfileEmail()});
        // }
		if (this.stars) {
		    this.sync_stars(this.stars);
		} else {
            this.sync_stars();
		}

        
    },
    
    end:function(){}

}

//loadJSONDoc
var fb_wall_post = {
	initialized:false,
	loader:'<img src="/static/imgs/loader.gif" alt="" style="margin-left:5px;" />',
    start_html:null,
    overlay:null,
    load_url:'/ajax/facebook/load_wall_form',
    save_url:'/ajax/facebook/save_wall_form',
    
    init:function(){
        var overlay_config = { width:"800px",
                               fixedcenter:true, 
                               close:true, 
                               draggable:false, 
                               zindex:100,
                               modal:true,
                               visible:false,
                               constraintoviewport:true}
        
        $('fb_wall_overlay').style.display='';
        this.overlay = new YAHOO.widget.Panel("fb_wall_overlay",overlay_config);                                                               
        this.overlay.render();
        this.initialized = true;
    },
    

    show:function(module, module_id, text){
    	if (!this.initialized) {
    		this.init();
    	}
    	
        if (this.start_html) {
            $('fb_wall_overlay').innerHTML = this.start_html
        } else {
            $('fb_wall_inner').innerHTML = this.loader;
            this.start_html = $('fb_wall_overlay').innerHTML
        }
        
        this.load_form(module, module_id, text);
    },
    
    close:function(){
        this.overlay.hide();
    },    
    
    resize:function(){
        window.setTimeout(function(){
        	fb_wall_post.overlay.sizeMask();
        },1000)           
    },
    
    load_form:function(module, module_id, text){
        var qs = queryString( {'text': text, 'module':module, 'module_id':module_id});
        
        var d = doXHR(this.load_url, {
            method:'POST',
            sendContent:qs,
            headers: {"Content-Type":"application/x-www-form-urlencoded"}
       });
    	d.addCallback(this.load_form_cb);
    	d.addErrback(this.load_form_cb_error);
    	
    },
    load_form_cb:function(result){
    	var parent = $('fb_wall_inner');
        parent.innerHTML = result.responseText;
        
        fb_wall_post.overlay.show();
        fb_wall_post.resize();
        
        connect(('fb_wall_submit'), 'onclick', 
            function() {        
                fb_wall_post.save()
            })

    },
    
    load_form_cb_error:function(result){
        alert('load_form_cb_error')
        alert(result)
    },    
    
    save:function(){
        
        var text = $('fb_wall_text').value;
        var module = $('fb_wall_module').value;
        var module_id = $('fb_wall_module_id').value;

        var qs =  queryString({'text':text, 'module':module, 'module_id':module_id})
        var d = doXHR(this.save_url, {
             method:'POST',
             sendContent:qs,
             headers: {"Content-Type":"application/x-www-form-urlencoded"}
        });
        d.addCallback(this.save_cb);
        d.addErrback(this.save_cb_error);
        // show loader
        $('fb_wall_container').innerHTML = this.loader;
    },
    save_cb:function(result){
        var r = YAHOO.lang.JSON.parse(result.responseText);
        if (r.cb=='load_form_cb'){
            fb_wall_post.load_form_cb({'responseText':r.data});
        } else {
        	fb_wall_post.close();
        }
    },
    save_cb_error:function(result){
        alert('save_review_cb_error')
    },

    end:function(){}
}

// facebook api layer
app.fb = {
    session:null,
    uid:null,
    profile:null,
    key:null,
    redirect_to_profile_if_logged_in:null,
    redir:null,
	init:function(session){
		this.session = session;
		this.uid = session.uid
	},
	parse_dom:function(){
		FB.XFBML.Host.parseDomTree()
	},
	onlogin:function(){
	    // we need to pass the redirect to the fblogin
		if ($('redir')) { 
	        $("fb_signin_redir").value = $('redir').value;
	    } else if (this.redir) {
	        $("fb_signin_redir").value = this.redir;
	    }
		
		if (this.session.accessToken) {
		    $("fb_signin_token").value = this.session.accessToken;
		    $("fb_token_expires").value = this.session.expires;
	        $("fb_signin").submit();
		}
	},
    publish_feed_story:function() {
      // Load the feed form
          // FB.ensureInit(function() {
          //     var item = getSessionFbFeed()
          //     if (item) {
          //         item = MochiKit.Base.evalJSON(item)
          //         // var template_id = item[0];
          //         // var template_data = item[1];
          //         // if (template_data != ""){
          //         //     template_data = MochiKit.Base.evalJSON(template_data)
          //         // }
          //         // FB.Connect.showFeedDialog(template_id, template_data);
          //         FB.Connect.streamPublish('', item.attachment, item.action_links);
          //         clearSessionFbFeed()
          //     }
          //     // FB.Connect.showFeedDialog(form_bundle_id, template_data);
          //     // FB.Connect.showFeedDialog(form_bundle_id, template_data, null, null, FB.FeedStorySize.shortStory, FB.RequireConnect.promptConnect);
          //     // hide the "Loading feed story ..." div
          //     // ge('feed_loading').style.visibility = "hidden";
          // })
      },
      
      page_search:function(){
        var q = $('fb_page_query').value
        var qs = queryString( {'query':q, 'bust':Math.random()});
        var d = doXHR('/merchant/services/facebook_page_search', {
                 method:'POST',
                 sendContent:qs,
                 headers: {"Content-Type":"application/x-www-form-urlencoded"}
        });
        d.addCallback(this.page_search_cb);
        d.addErrback(this.page_search_error);
        $('pages').innerHTML = 'Searching, please be patient...'; // clear status field
      },
      page_search_cb:function(result){
          var r = YAHOO.lang.JSON.parse(result.responseText)
          $('pages').innerHTML = r.data
        // var pre = $('preinsert');
        // pre.innerHTML = r.data;
      },
      page_search_error:function(result){
          alert("Sorry we can't complete your search at this time.")
      },
      
      accounts:function(){
        var qs = queryString( {'bust':Math.random()});
        var d = doXHR('/merchant/services/facebook_accounts', {
                 method:'POST',
                 sendContent:qs,
                 headers: {"Content-Type":"application/x-www-form-urlencoded"}
        });
        d.addCallback(this.accounts_cb);
        d.addErrback(this.accounts_error);
        $('pages').innerHTML = 'Searching, please be patient...'; // clear status field
      },
      accounts_cb:function(result){
        alert('here')
          // var r = YAHOO.lang.JSON.parse(result.responseText)
          // $('pages').innerHTML = r.data
      },
      accounts_error:function(result){
          alert("Sorry we can't complete your search at this time.")
      },
      onlogout:function() {
    	  
      },
      
      
      end:function(){}
}


app.signup={
    
    consumer_nudge:function(options){
        // check for session/profile cookie to see if logged in
        if (!isLoggedIn()) {
            if (!$('consumer_nudge_c')){ 
                var redir = window.location;
                try{
                    $('login_redir').value = redir;
                } catch(e){}
                try{
                    $('signup_redir').value = redir;
                } catch(e){}
                        
                var overlay_config = { width:"800px",
                                       fixedcenter:true, 
                                       close:true, 
                                       draggable:false, 
                                       zindex:100,
                                       modal:true,
                                       visible:false,
                                       constraintoviewport:true}
                                       
                //retrieve context sensitive nudge
                if (options != undefined) {
                    //expected args: category, action
                    url = '/ajax/nudge/index';
                    log('attempt to run', url);
                    mymsg = loadJSONDoc(url, options).addCallbacks(
                        function (result) {
                            //success callback
                            replacementDiv = DIV();
                            replacementDiv.innerHTML = result['data'];
                            swapDOM('consumer_nudge', replacementDiv);
                            $('consumer_nudge').style.display='block';
                            app.signup.consumer_nudge_overlay = new YAHOO.widget.Panel("consumer_nudge",overlay_config);
                            app.signup.consumer_nudge_overlay.render();
                            app.signup.consumer_nudge_overlay.show();
                        },
                        function (result) {
                            //fail callback
                            app.signup.consumer_nudge_overlay.show();
                        }
                    ); //callbacks
                } else {
                    $('consumer_nudge').style.display='block';
                    this.consumer_nudge_overlay = new YAHOO.widget.Panel("consumer_nudge",overlay_config);
                    this.consumer_nudge_overlay.render();
                }
            }
            try {
                this.consumer_nudge_overlay.show();
            } catch(err) {
                //nothing
            }
        }

    },
	directory_nudge:function(version){
		if (!isLoggedIn() ) {
			version = version || 'unknown';
			if (!$('consumer_nudge_c') && !nudgeCount()){ 
				var redir = window.location;
				try{
					$('login_redir').value = redir;
				} catch(e){}
				try{
					$('signup_redir').value = redir;
				} catch(e){}
				
				var overlay_config = { width:"400px",
								context:['qn','tl','tr'],
								x:30,
								y:10,
								//fixedcenter:true, 
								close:true, 
								draggable:false, 
								zindex:100,
								modal:false,
								visible:false,
								constraintoviewport:true}
				$('directory_consumer_nudge').style.display='block';
				this.directory_consumer_nudge_overlay = new YAHOO.widget.Panel("directory_consumer_nudge",overlay_config);
				this.directory_consumer_nudge_overlay.render();
				try {
					_gaq.push(['_trackEvent', "Directory", "Consumer Nudge Popup", version]);
					log('show nudge version', version);
				} catch(err) {
					log('pageTracker inaccessible directory_nudge', err);
				}
			}
			this.directory_consumer_nudge_overlay.show();
			createNudgeCookie(1);
		}
	},
	unclaimed_nudge:function(version){
		if (!isLoggedIn() ) {
			version = version || 'unknown';
			if (!$('consumer_nudge_c') && !nudgeCount()){
				var redir = window.location;
				try{
					$('login_redir').value = redir;
				} catch(e){}
				try{
					$('signup_redir').value = redir;
				} catch(e){}
				
				var overlay_config = { width:"300px",
								context:['listingMenu','bl','tl'],
								x:30,
								y:10,
								//fixedcenter:true, 
								close:true, 
								draggable:false, 
								zindex:100,
								modal:false,
								visible:false,
								constraintoviewport:false}
				$('directory_consumer_nudge').style.display='block';
				this.directory_consumer_nudge_overlay = new YAHOO.widget.Panel("directory_consumer_nudge",overlay_config);
				this.directory_consumer_nudge_overlay.render();
				try {
					_gaq.push(['_trackEvent', "Unclaimed", "Answers Nudge - View", version]);
					log('show nudge version', version);
				} catch(err) {
					log('pageTracker inaccessible unclaimed_nudge', err);
				}
			}
			this.directory_consumer_nudge_overlay.show();
			createNudgeCookie(1);
		}
	},
	dashboard_nudge:function(data){
		timer_length = 30; 
		// createLoggingPane(true);
		startTime = nudgeCount();
		nowTime = new Date();
		lastLogin = data['lastLogin'];
		timer = 0;

		 if (startTime < 0) {
			log('nudge was previously fired or supressed', startTime);
			clearInterval(app.signup.dashboard_interval);
			return;
		} else if (isUndefinedOrNull(startTime) || ( lastLogin.valueOf() > startTime.valueOf() )) {
			startTime = nowTime;
			log('fresh nudge timer b/c no cookie or new login.', startTime);
		} else {
			startTime = new Date().setTime(startTime);
			timer = nowTime.getDiff(startTime).seconds;
		} 
		log('timer', timer);
		createDashboardNudgeCookie(startTime.valueOf());
		
		
		if ( isLoggedIn() && (timer > timer_length)) {
			if (!$('consumer_nudge_c')) {
				var overlay_config = { width:"300px",
								context:['qn','tl','tl'],
								x:30,
								y:10,
								fixedcenter:true, 
								close:true, 
								draggable:false, 
								zindex:100,
								modal:true,
								visible:false,
								constraintoviewport:true}
				$('consumer_nudge').style.display='block';
				this.dashboard_nudge_overlay = new YAHOO.widget.Panel("consumer_nudge", overlay_config);
				this.dashboard_nudge_overlay.render();
				try {
					_gaq.push(['_trackEvent', "Dashboard", "Dashboard Nudge - View"]);
					log('show nudge version', version);
				} catch(err) {
					log('dashboard_nudge pageTracker inaccessible', err);
				}
			}
			this.dashboard_nudge_overlay.show();
			log('stop interval!', app.signup.dashboard_interval);
			clearInterval(app.signup.dashboard_interval);
			createDashboardNudgeCookie(-1);
		} 
	},
	invoice_nudge:function(data){
		// createLoggingPane(true);
		if (!$('consumer_nudge_c')) {
			var overlay_config = { width:"400px",
							context:['receiptTable','tl','bl'],
							x:30, y:10,
							//fixedcenter:true, 
							close:true, 
							draggable:false, 
							zindex:100,
							modal:false,
							visible:false,
							constraintoviewport:true}
			$('consumer_nudge').style.display='block';
			this.invoice_nudge_overlay = new YAHOO.widget.Panel("consumer_nudge", overlay_config);
			this.invoice_nudge_overlay.render();
			try {
				_gaq.push(['_trackEvent', "Dashboard", "Invoice Nudge - View"]);
				log('show nudge version', version);
			} catch(err) {
				log('invoice_nudge pageTracker inaccessible', err);
			}
		}
		this.invoice_nudge_overlay.show();
	},
	click: function ( category, action, campaign ) {
		try {
			log('campaign', campaign);
			_gaq.push(['_trackEvent', category, action, campaign]);
		} catch(err) {
			log('pageTracker inaccessible', err);
		}
	},
	end:function(){}
}

app.list_suggest = {
    options_open:false,
    options_open_timeout_id:null,
    
    init:function(){
        connect($('list_title'), 'onclick', function(){
            app.list_suggest.show_options();
        })
        connect($('list_title'), 'onblur', function(){
            app.list_suggest.options_open_timeout_id=window.setTimeout('app.list_suggest.hide_options()', '300');
        })
        connect($('list_title'), 'onkeydown', function(e){
            app.list_suggest.hide_options();
        })

        var link; var links = getElementsByTagAndClassName('a', 'list_suggest_option');
        for(var i=0;i<links.length; i++){
            link = links[i];
            connect(link, 'onclick', function() {
                 var el = $('list_title');
                 el.value = this.innerHTML.replace('...','');
                 el.focus();
                 app.list_suggest.hide_options();
             })
        }
    },
    show_options:function(){
        this.options_open = true;
        $('list_suggestions').style.visibility='visible';
    },
    hide_options:function(){
        this.options_open = false;
        $('list_suggestions').style.visibility='hidden';
    },
    end:function(){}
}

/*
* Custom Google Ads
*/
function google_ad_request_done(google_ads) {
var s = '';
var i;
s += '<div class="adsBy"><a href=\"' + google_info.feedback_url + '\">Ads by Google</a></div>';

/*
* Verify that there are actually ads to display.
*/
if (google_ads.length == 0) {
log('google_ads 0 length');
return;
}
//log('line 2230: custom ad', google_ads[0].type);
if (google_ads[0].type == "flash") {
	//log('line 2232: attempt to render flash ad');
	s += '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' +
	' codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,0,0" WIDTH="' +
	google_ad.image_width + '" HEIGHT="' +
	google_ad.image_height + '"> <PARAM NAME="movie" VALUE="' +
	google_ad.image_url + '">' +
	'<PARAM NAME="quality" VALUE="high">' +
	'<PARAM NAME="AllowScriptAccess" VALUE="never">' +
	'<EMBED src="' +
	google_ad.image_url + '" WIDTH="' +
	google_ad.image_width + '" HEIGHT="' +
	google_ad.image_height +
	'" TYPE="application/x-shockwave-flash"' +
	' AllowScriptAccess="never" ' +
	' PLUGINSPAGE="http://www.macromedia.com/go/getflashplayer"></EMBED></OBJECT>';
} else if (google_ads[0].type == "image") {
	//log('line 2235: image google_ads');
	s+= renderImageAd(google_ads[0]);
} else if (google_ads[0].type == "html") {
	s += google_ads[0].snippet;
} else {
	if (google_ads.length == 1) {
		/*
		* Partners should adjust text sizes
		* so ads occupy the majority of ad space.
		*/
		s += '\n\n<div class="singleAd">\n\n'
		s += renderTextAd(google_ads[0]);
		s += "</div>\n\n"; //.singleAd
	} else if (google_ads.length > 1) {
		s += '\n\n<div class="multipleAds">\n\n'
		for(i = 0; i < google_ads.length; ++i) {
			s += renderTextAd(google_ads[i]);
		} //for
		s += "<div style=\"clear:both;\"></div></div>" + '\n\n\n\n'; //.multipleAds
	} //length > 1

	//google ad skipping
	if (google_ads[0].bidtype == 'CPC') {
		try {
            // log('Start', google_adnum, 'Rendering ads.');
            // google_adnum = google_adnum + google_ads.length;
            // log(google_ads.length, 'ads served. next', google_adnum);
		} catch (err) {
			log(err, 'make sure to set adnum somewhere');
		}
	}
} //adtypes
document.write(s);
return;
} //google_ad_request_done()

function renderImageAd(gad, options) {
	return '<a href="' +
	gad.url + '" target="_top" title="go to ' +
	gad.visible_url + '" onmouseout="window.status=\'\'" onmouseover="window.status=\'go to ' +
	gad.visible_url + '\';return true"><img border="0" src="' +
	gad.image_url + '"width="' +
	gad.image_width + '"height="' +
	gad.image_height + '" /></a>';
}

function renderTextAd(gad, options) {
	var foo = '';
	foo += '\n\n<div class="googleAd">\n';
	tmpl = '\t<div class="line1"><a href="__CLICK_URL__">__LINE1__</a></div> <div class="line2">__LINE2__</div> <div class="line3">__LINE3__</div> <div class="visibleUrl"><a href="__CLICK_URL__">__VISIBLE_URL__</a></div>';
	switch (googleAdCustomStyle) {
		case 'search':
			tmpl = '\t<div class="line1"><a href="__CLICK_URL__">__LINE1__</a></div><span class="line2">__LINE2__</span> <span class="line3">__LINE3__</span><div class="visibleUrl"><a href="__CLICK_URL__">__VISIBLE_URL__</a></div>';
			break;
		case 'horizontal':
			tmpl = '\t<div class="horizAdUnit"><div class="line1"><a href="__CLICK_URL__">__LINE1__</a></div><div class="line2">__LINE2__</div> <div class="line3">__LINE3__</div><div class="visibleUrl"><a href="__CLICK_URL__">__VISIBLE_URL__</a></div></div>';
			break;
		case 'compact':
			tmpl = '\t<div class="line1"><a href="__CLICK_URL__">__LINE1__</a></div><span class="line2">__LINE2__</span> <span class="line3">__LINE3__</span> <span class="visibleUrl"><a href="__CLICK_URL__">__VISIBLE_URL__</a></span>';
			break;
		default:
			tmpl = '\t<div class="line1"><a href="__CLICK_URL__">__LINE1__</a></div> <div class="line2">__LINE2__</div> <div class="line3">__LINE3__</div> <div class="visibleUrl"><a href="__CLICK_URL__">__VISIBLE_URL__</a></div><br />';
			break;
	}
	tmpl = tmpl.replace(new RegExp('__CLICK_URL__','g'), gad.url);
	tmpl = tmpl.replace('__LINE1__', gad.line1);
	tmpl = tmpl.replace('__LINE2__', gad.line2);
	tmpl = tmpl.replace('__LINE3__', gad.line3);
	tmpl = tmpl.replace(new RegExp('__VISIBLE_URL__','g'), gad.visible_url);
	foo += tmpl;
	foo += "</div>\n\n"; //.googleAd
	return foo;
}

/*
* END Custom Google Ads
*/


/*
** Key-up handler and associated utilities, to limit
** aliases to alphanumeric characters, not already taken
*/

mc.app.neighbor = function() {};
mc.app.neighbor = {
    nameExistsToId:null,
    init : function ( inputField, displayField, errField, postUrl ) {
        mc.app.neighbor.inputField = inputField;
        mc.app.neighbor.displayField = displayField;
        mc.app.neighbor.errField = errField;
        mc.app.neighbor.postUrl = postUrl;
    },
        
    name_handler : function( e ) {
        var evt = e || window.event;
        if (e.keyCode==13) {return false;} // exit if enter was pressed
    	    // only allow a-zA-Z0-9
        var el = $( mc.app.neighbor.inputField );
        var name = el.value
        //name = name.replace(/[^a-zA-Z0-9]/,"");
    	name = name.replace(/[^a-zA-Z0-9]/g,"");

        el.value = name;
        var name_msg = $( mc.app.neighbor.displayField );
        name_msg.className = "name_exists checking";
        if (mc.app.neighbor.nameExistsToId) {window.clearTimeout(mc.app.neighbor.nameExistsToId)}
        if (name) {
        	var length = name.length;
            if (length > 2 && length <= 50) {
                name_msg.innerHTML = "checking..."
                mc.app.neighbor.nameExistsToId = 
                    window.setTimeout("mc.app.neighbor.is_alias_available('"+name+"')",1000);
            } else {
                name_msg.innerHTML = "Your alias must be 3-50 characters.";
            }
        } else {
            name_msg.innerHTML = "";
        }
    },

    is_alias_available : function(name) {
	    this.errField.innerHTML = ''
	    var qs = queryString( {'name': name, 'bust':Math.random()});
	    var d = doXHR(mc.app.neighbor.postUrl, {
	   	         method:'POST',
			     sendContent:qs,
			     headers: {"Content-Type":"application/x-www-form-urlencoded"}
	   	});
	   	d.addCallback(mc.app.neighbor.is_alias_available_cb);
	   	d.addErrback(mc.app.neighbor.is_alias_available_cb_error);	

	},

	is_alias_available_cb : function (res) {
		var code = res.responseText
		var name_msg = $( mc.app.neighbor.displayField );

		if (code == '1') {
            //$('save_alias').disabled = false;
			name_msg.innerHTML = "That username is available!";
			name_msg.className = "name_exists available";
		} else {
            //$('save_alias').disabled = true;
			name_msg.innerHTML = "That username is taken. Please try again.";
			name_msg.className = "name_exists taken";
		}
	},
	is_alias_available_cb_error: function(res){}
	
}

mc.app.tracking = function() {};
mc.app.tracking = {
	outbound: function (cmd) {
		_gaq.push(cmd);
		log('mc.app.tracking.trackoutbound', cmd);
		return true;
	}
}

app.answers = {
    now:null,
    question_id:null,
    question_user_id:null,
    question_status:'open',
    user_votes:{},
    answer_el:null,
    answer_submit_url:null,
    answer_submit_btn:null,
    answer_error:false,
    answer_urls:[],
    
    init_public_question:function(){
        // display submit box if person is logged in
        if (this.question_status=='open'){
            // hook to prevent someone from answering thier own question...
            var uid = getProfileUserId()
            if (this.question_user_id != uid) {
                connect($('answer_form'), 'onclick', function(){app.answers.answer_form(this)})
                this.answer_form($('answer_form'))
            } else {
                connect($('answer_form'), 'onclick', function(){alert("We're sorry, but you're not allowed to answer your own question.")})
            }
        }
        if (isLoggedIn()) {
            // ownerOnly
            this.show_loggedin_controls();
            // grab all the votes this user has created for this question...
            this.get_user_votes()
        } else {
            // connect($('answer_form'), 'onclick', function(){
            //     app.signup.consumer_nudge();
            // })
            this.init_votes_with_nudge()
        }
        app.time_lapse.format_all_dates()
    },

    init_private_question:function(){
        this.get_user_votes();
        app.time_lapse.format_all_dates();
    },
    
    submit_question:function(suffix) {
    	try { ghostSubmit('ask_question');} catch (err) {}
    	
    	if (!isLoggedIn()) {
    	    // we need to take the form url and title and create a redir for the nudge
            app.signup.consumer_nudge();
    	    var title= $('title').value;
            var action = $('ask_question').action;
			if (suffix != undefined) {
				title = $('title' + suffix).value;
				action = $('ask_question' + suffix).action;
			} 
            var redir = action;
            if (redir.indexOf('?') == -1){redir += '?'} else {redir += '&'}
            var params = ['title=' + escape(title)]
            redir += params.join('&');
            try{
                $('signup_redir').value = redir;
            } catch(e){}
            try{
                $('login_redir').value = redir;
            } catch(e){}
            return false;
    	}
    	
    },
    
    submit_question_with_category:function() {
    	try { ghostSubmit('ask_question_with_category');} catch (err) {}
    	if (!isLoggedIn()) {
    	    // we need to take the form url and title and create a redir for the nudge
            app.signup.consumer_nudge();
    	    var title= $('title_first').value
    	    var cid= $('cid_first').value
            var action = $('ask_question_with_category').action
            var redir = action
            if (redir.indexOf('?') == -1){redir += '?'} else {redir += '&'}
            var params = ['title=' + escape(title), 'cid=' + cid]
            redir += params.join('&')
            try{
                $('signup_redir').value = redir;
            } catch(e){}
            try{
                $('login_redir').value = redir;
            } catch(e){}
            return false
    	}
    },
    
    show_loggedin_controls:function(){
        var uid = getProfileUserId()
        if (uid) {
            // display only for owner of this question
            var owner_id = 'owner_' + uid
            var el; var els = getElementsByTagAndClassName('span', owner_id).concat(getElementsByTagAndClassName('div', owner_id))
            for(var i=0;i<els.length; i++){
                el = els[i];
                el.style.display=''
             }
         }
    },

	showLinkAdder:function(id, type, value) {
		// log('add type to answer:', type);
		var instrNode;
		var inputNode = INPUT({'type':'text', 'class':'answer_urls mainInput askInput', 'title':type, 'value':value});
		switch(type) {
			case 'url':
				msg = 'Enter your link URL below. ';
				break;
			case 'youtube':
				msg = 'Enter your YouTube URL below. ';
				break;
			case 'pic':
				msg = 'Enter your picture URL below. (max dimensions 600w x 400h) '
				break;
		}
		rmBtn = A('remove');
		connect(rmBtn, 'onclick', function (evt) { removeElement(evt.src().parentNode); });
		instrNode = P({'class':"addImgVid"}, msg, rmBtn, BR(), inputNode);
		appendChildNodes(id, instrNode);
		//form post happens in answer_question function
	},

    init_form:function(){
        var form = $('answer_question_form')
        connect(form, 'onsubmit', function(){
            app.answers.answer_question();
            return false;
        })
        // connect($('answer_cancel'), 'onclick', function(){
        //     app.answers.answer_cancel();
        // })
        this.answer_submit_btn = $('save_btn')
        this.answer_el = $('answer_question')

        connect(this.answer_el, 'onkeyup', app.answers.answer_input_handler)
        connect(this.answer_el, 'onblur',  app.answers.answer_input_handler)
        connect(this.answer_el, 'onfocus', app.answers.answer_input_handler)
        
        if (this.answer_urls.length > 0){
            map(function (obj) { 
                app.answers.showLinkAdder('answerAddLink',obj.type, obj.value)
            }, this.answer_urls)
            this.answer_urls = []
        }
        app.tooltip.init('tt_answer', '<strong>Tip:</strong> Be specific &amp; detailed.<br /><br />Use any knowledge or expertise that you may have.')
        if (!isLoggedIn()){
            app.login.init('join');
            fb_connect_init() // show fb_login button
        }
    },
    init_votes:function(){
        var vote, answer; var answers = getElementsByTagAndClassName('div', 'answer');
        var questions = getElementsByTagAndClassName('div', 'questBox');
        if (questions.length) {
            answers.push(questions[0])
        }
        for(var i=0;i<answers.length; i++){
            answer = answers[i];
            this.init_vote(answer);
        }
    },
    init_votes_with_nudge:function(){
        var vote, answer, up, down; var answers = getElementsByTagAndClassName('div', 'answer');
        var questions = getElementsByTagAndClassName('div', 'questBox');
        if (questions.length) {
            answers.push(questions[0])
        }
        for(var i=0;i<answers.length; i++){
            a = answers[i];
            up = $(a.id + '_vote_up');
            down = $(a.id + '_vote_down');
            
            up.parentNode.className = 'thumbsUp';
            down.parentNode.className = 'thumbsDown';
            
            connect(up, 'onclick', function(){app.signup.consumer_nudge({'category':'answers', 'action':'thumbsup'})});
            connect(down, 'onclick', function(){app.signup.consumer_nudge({'category':'answers', 'action':'thumbsdown'})});
            
            $(a.id + '_vote').style.display='';
        }
    },    
    
    init_vote:function(el){
        // initialize the vote handlers and state
        var vote = this.user_votes[el.id]
        this.toggle_vote(el.id, vote)
    },
    toggle_vote:function(id, vote){
        var wrap = $(id + '_vote')
        var up = $(id + '_vote_up')
        var down = $(id + '_vote_down')
        if (vote == null){
            // empty
            connect(up, 'onclick', function(){app.answers.vote(this, 1)})
            connect(down, 'onclick', function(){app.answers.vote(this, -1)})
            up.parentNode.className = 'thumbsUp';
            down.parentNode.className = 'thumbsDown';
        } else if (vote==1) {
            // up
            connect(up, 'onclick', function(){return false;})
            connect(down, 'onclick', function(){app.answers.vote(this, -1)})
            up.parentNode.className = 'thumbsUpVote';
            down.parentNode.className = 'thumbsDown';
        } else if (vote==-1){
            // down
            connect(up, 'onclick', function(){app.answers.vote(this, 1)})
            connect(down, 'onclick', function(){return false;})
            up.parentNode.className = 'thumbsUp';
            down.parentNode.className = 'thumbsDownVote';
        }
        wrap.style.display='';
    },
    
    answer_input_reset:function(){
        this.answer_el.value='';
        // this.answer_submit_btn.disabled = true;
    },
    answer_input_handler:function(){
        if (this.value.length > 0) {
            // app.answers.answer_submit_btn.disabled = false;
			app.answers.answer_submit_btn.src = '/static/imgs/consumer/buttons/answerQuestion_green.png';
        } else {
            // app.answers.answer_submit_btn.disabled = true;
			app.answers.answer_submit_btn.src = '/static/imgs/consumer/buttons/answerQuestion_green.png';
        }
    },
    answer_cancel:function(){
        blindUp('answer_question_form_wrap',
                {duration:0.5, afterFinish:function(){$('answer_form').style.display=''}}
        )
        
    },
    update_answer_count:function(){
        if ($('answer_count')) {
            $('answer_count').innerHTML = this.question_answer_count
            if ($('be_the_first') && this.question_answer_count == 1) {
                $('be_the_first').style.display='none';
            }
        }
    },
    get_user_votes:function(){
    	var pars = queryString({'bust':Math.random()})
	    var d = doXHR(this.question_votes_for_user_url, 
			{
	            method:'POST',
				sendContent:pars,
				mimeType: 'application/x-www-form-urlencoded', 
				headers: {"Content-Type":"application/x-www-form-urlencoded"} 
	    });
	    d.addCallback(this.get_user_votes_cb);
	    d.addErrback(this.get_user_votes_error);
        return false;
        
    },
    get_user_votes_cb:function(result){
	    var r = YAHOO.lang.JSON.parse(result.responseText)
	    app.answers.user_votes = r;
	    app.answers.init_votes()
    },
    get_user_votes_error:function(){},
    
    answer_form:function(el){
//        el.style.display='none';
        if ($('answer_question_form_wrap').innerHTML==''){
            var pars = {'bust':Math.random(), 'question_id': this.question_id}
            loadJSONDoc(this.answer_form_url, pars).addCallback(this.answer_form_cb);
        } else {
            blindDown($('answer_question_form_wrap'),{duration:.5});
        }
    },
    answer_form_cb:function(result){
        var pre = $('preinsert')
        pre.innerHTML = result['data'];
        
        var parent = $('answer_question_form_wrap')
        var inner = $('answer_question_form_inner')
        pre.removeChild(inner)
        parent.appendChild(inner)
        if (!this.answer_error) {
           // blindDown(parent.id,{duration:0.5});
        }

        app.answers.init_form()
    },
    answer_question:function(){
        var qs = {}
        var answer = $('answer_question').value;
        var answer_urls = ''; var email = ''; var auth = ''; var captcha_hash=''; var captcha_guess='';
        if (!isLoggedIn()){
            email = $('email').value
            if ($('login_radio').checked) {
                auth = 'login' // this means the 'enter' button tripped the form submit
                return false;
            } else {
                auth = 'join'
            }
            captcha_hash = $('captchaHash').value
            captcha_guess = $('captchaGuess').value
        }
        $('answer_question_loader').style.display=''
        var urls = getElementsByTagAndClassName('input','answer_urls');
        map(function (x) {
             if (x.title == 'pic') {
                 answer_urls += ' \n\n [img]' + strip(x.value) + '[/img] \n\n ';
             } else {
                 answer_urls += ' \n\n ' + x.value + '\n\n ';
            }
            // cache the answer_urls in case we have an error
            app.answers.answer_urls.push({'type': x.title, 'value':x.value})
         }, urls );
        var subscribe = null;
        if ($('answer_subscribe')){subscribe = $('answer_subscribe').checked;}
        if (answer !='') {qs.answer = answer}
        if (email !='') {qs.email = email}
        if (answer_urls !=''){ qs.answer_urls = answer_urls}
        if (auth !='') { qs.auth = auth}
        if (captcha_hash !='') { qs.captchaHash = captcha_hash}
        if (captcha_guess !='') { qs.captchaGuess = captcha_guess}
        if (subscribe) { qs.answer_subscribe = 'true'}
        
        qs.bust = Math.random()
        var pars = queryString(qs);
        var d = doXHR(this.answer_submit_url, 
        {
            method:'POST',
            sendContent:pars,
            mimeType: 'application/x-www-form-urlencoded', 
            headers: {"Content-Type":"application/x-www-form-urlencoded"} 
        });
        d.addCallback(this.answer_question_cb);
        d.addErrback(this.answer_question_error);
        return false;
        
    },
    answer_question_cb:function(result){
        var r = YAHOO.lang.JSON.parse(result.responseText)
        if (r.signup){
            gProfile = unencodeCookie("P") || emptyProfile(); // unencode cookie again
            gClearSession = unencodeCookie("C") || emptySessionClear(); // unencode cookie again
            app.nav.init()
        }
        if (r.status > 0){
            if (r.next_url) {
                window.location = r.next_url // redirect the user to another question to answer
            } else {
                // authenicate cookies
                var pre = $('preinsert');
                pre.innerHTML = r.data;
                var parent = $('answers');
                var answer = $(r.dom_id)
                pre.removeChild(answer)
                answer.style.display='none'
                if (parent.childNodes.length) {
                    YAHOO.util.Dom.insertBefore(answer, parent.childNodes[0])
                } else {
                    parent.appendChild(answer)
                }
                // track answer and vote
                app.answers.user_votes[answer.id]=1
                app.answers.init_vote(answer)
                app.answers.answer_input_reset()
                app.answers.question_answer_count += 1
                app.answers.update_answer_count()
                app.time_lapse.format_all_dates()
    
                blindUp('answer_question_form_wrap',{duration:0.5,
                                                afterFinish:function(){
                                                    blindDown(answer.id,{duration:0.5, 
                                                                         afterFinish:function(){
                                                                            $('answer_saved_msg').style.display=''
                                                                            MochiKit.Visual.Highlight(answer.id, {startcolor:'#ffffcc', endcolor:'#ffffff'})
                                                                         }
                                                    })
                                            
                                                }
                                            })
            }

        } else {
            // we have an error
            var parent = $('answer_question_form_wrap')
            parent.innerHTML = ''; //remove old form
            var pre = $('preinsert')
            pre.innerHTML = r.data;
            var inner = $('answer_question_form_inner')
            pre.removeChild(inner)
            parent.appendChild(inner)
            app.answers.answer_error = true;
            app.answers.init_form()
        }
    },
    answer_question_error:function(error){
    	alert('Sorry, something went wrong. ' + error);
    },
    vote:function(el, value){
        var parts = el.id.split('_')
        var type = parts[0]
        var id = parts[1]
        var values = {'value': value, 'bust':Math.random()}
        var url;
        if (type == 'answer' ) {
            url = this.answer_vote_url
            values['answer_id'] = id
            this.user_votes['answer_' + id] = value;
        } else {
            url = this.question_vote_url
            values['question_id'] = id
            this.user_votes['question_' + id] = value;
        }
        var pars = queryString(values)
        // record vote so we can initialize properly on cb
        var d = doXHR(url, {
             method:'POST',
             sendContent:pars,
             mimeType: 'application/x-www-form-urlencoded', 
             headers: {"Content-Type":"application/x-www-form-urlencoded"} 
        });
        d.addCallback(this.vote_cb);
        d.addErrback(this.vote_error);
        return false;
    },
    vote_cb:function(result){
	    var r = YAHOO.lang.JSON.parse(result.responseText)
        // var pre = $('preinsert');
        // pre.innerHTML = r.data;
        var parent = $(r.dom_id + '_vote');
        parent.innerHTML = r.data
        app.answers.init_vote($(r.dom_id))
    },
    vote_error:function(){
        alert('Sorry, something went wrong.')
    },
    end:function(){}
}


app.time_lapse = {
    now:null,
    set_now:function(s){
        this.now=this.parse_date(s)
    },
    format_all_dates:function(){
        var date; var dates = getElementsByTagAndClassName('span', 'time_lapse');
        for(var i=0;i<dates.length; i++){
            date = dates[i];
            this.format_date(date);
         }
    },
	format_date:function(date){
        date.innerHTML = this.parse_date(date.title.trim()).getDiffFormat(this.now);
	},
	parse_date:function(date){
        var parts, dt, tm;
        parts = date.split(' ')
        dt = parts[0].split('-')
        tm = parts[1].split(':')
        return new Date(dt[0], parseInt(dt[1], 10) - 1, dt[2], tm[0], tm[1], tm[2]);
	},
	end:function(){}
}

// app.feed methods
app.feed = {
    hide_blanks:function(){
        var el; var els = getElementsByTagAndClassName('div', 'feedItem');
        for(var i=0;i<els.length; i++){
            el = els[i];
            if (el.innerHTML.trim() == '') {
                el.style.display = 'none';
            }
         }        
    }
}


app.login = {
    login_url:'/auth/ajax_login',
    fblogin_url:'/auth/ajax_fblogin',
    
    init:function(type){
        if(type=='login'){
            $('login_radio').checked=true;
        } else {
            $('join_radio').checked=true;
        }
        this.display(type);
    },
    
    display:function(type){
        if(type=='login'){
            $('login_wrap').style.display=''
            $('join_wrap').style.display='none'
            $('save_btn').style.display='none'
        } else {
            $('login_wrap').style.display='none'
            $('join_wrap').style.display=''
            $('save_btn').style.display=''
        }
    },
    
    authenticate:function(){
        $('login_error').innerHTML = '';
        var email = $('ajax_email').value;
        var password = $('ajax_password').value;
        
        var pars = queryString({'email':email, 'password':password, 'bust':Math.random()})
        var d = doXHR(this.login_url, {
            method:'POST',
            sendContent:pars,
            mimeType: 'application/x-www-form-urlencoded', 
            headers: {"Content-Type":"application/x-www-form-urlencoded"} 
        });
        d.addCallback(this.authenticate_cb);
        d.addErrback(this.authenticate_error);
        return false;
    },
    authenticate_cb:function(result){
        var r = YAHOO.lang.JSON.parse(result.responseText)
        if (r.status > 0){
            gProfile = unencodeCookie("P") || emptyProfile(); // unencode cookie again
            gClearSession = unencodeCookie("C") || emptySessionClear(); // unencode cookie again
            app.nav.init()
            $('auth_wrap').innerHTML="You're now logged in!";
            $('save_btn').style.display='';
            MochiKit.Visual.Highlight('auth_wrap', {startcolor:'#ffffcc', endcolor:'#ffffff'})
        } else {
            $('login_error').innerHTML = r.error;
        }
    },
    authenticate_error:function(result){ 
    	alert("Sorry, there was an error: " + result);
    },

    authenticate_facebook:function(){
        var pars = queryString({'bust':Math.random()})
        var d = doXHR(this.fblogin_url, {
            method:'POST',
            sendContent:pars,
            mimeType: 'application/x-www-form-urlencoded', 
            headers: {"Content-Type":"application/x-www-form-urlencoded"} 
        });
        d.addCallback(this.authenticate_cb);
        d.addErrback(this.authenticate_error);
        return false;
    },

    end:function(){}
}

app.tooltip = {
    manager:[],
    init:function(id, msg){
        if (id && msg){
            if ($(id)) {
                $(id).innerHTML = this.template(id, msg)
                this.manager.push(id)
            }
        }
    },
    template:function(id, msg){
		var a = []
		a.push('<div class="tooltipInfo">')
		a.push('<a href="javascript:app.tooltip.hide(\''+ id +'\')"><img src="/static/imgs/icons/x-small.gif" alt="close icon" title="Close Tooltip" class="close"></a>')
		a.push(msg)
		a.push('</div>') 
        return a.join('')
    },
    show:function(id){
        if ($(id)) {
            $(id).style.visibility='visible';
        }
    },
    hide:function(id){
        if ($(id)) {
            $(id).style.visibility='hidden';
        }
    },
    hide_all:function(){
        for (var i=0; i < this.manager.length; i++){
            this.hide(this.manager[i]);
        }
    },
    hook_hide_all_show_event:function(tip_id, handler_id, event_name){
        var func = eval("(function(){app.tooltip.hide_all(); app.tooltip.show('"+tip_id+"')})")
        connect($(handler_id), event_name, func)
    },
    end:function(){}
}

/*
** In cart offers
*/
function openDropDown( kind ) {
	var pane = $( kind + '_large' );
	var teasers = getElementsByTagAndClassName( 'div', 'teaser');
	for (var i = 0; i < teasers.length; i++ ) hideElement( teasers[i])
	if ( pane ) {
		showElement( pane );
	}
}

function getSuggestedDomains( url, callback, errback ) 
{
    /* returns a JS array of strings */
    var d = loadJSONDoc( url );
    d.addCallback( callback );
    d.addErrback( errback );
}

function handleCancel() {
	var teasers = getElementsByTagAndClassName( 'div', 'teaser');
	for (var i = 0; i < teasers.length; i++ ) showElement( teasers[i])
	var dropDowns = getElementsByTagAndClassName( 'div', 'expPack');
	for (var i = 0; i < teasers.length; i++ ) hideElement( dropDowns[i])
}

function getSuggestedContent( url, callback, errback ) 
{
    /* returns a JS array article objects */
    var d = loadJSONDoc( url );
    d.addCallback( callback );
    d.addErrback( errback );
}

function frame_external_links(base){
    // alert(base)
    var links = $$('a')
    var el, url;
    for (var i=0; i < links.length; i++){
        el = links[i]
        url = el.href
        if (url.indexOf('http://') == 0 && url.indexOf(base) < 0 && url.indexOf('google') < 0 && el.className.indexOf('noframe') < 0) {
            // log(el.href)
            el.href=base + '/f/' + escape(url)
        }
    }
}

app.local_merchants = {
    load_top_local_companies:function(data_URL){
        var d = doXHR(data_URL);
        d.addCallback(this.load_top_local_companies_cb);
        d.addErrback(this.load_top_local_companies_error);
        return false;
    },
    load_top_local_companies_cb:function(result){
        var r = YAHOO.lang.JSON.parse(result.responseText)
        $('topCompaniesContainer').innerHTML = r.data
    },
    load_top_local_companies_error:function(result){
        //alert('Sorry, there was an error loading the top companies widget.')
    }
}

app.local_ip_data = {
    loaded:false,
    ip_data:{},
    external_callback:"",
    load_local_ip_data:function(callback){
        var d = doXHR("/ajax/local-IPData");
        d.addCallback(this.load_local_ip_data_cb);
        d.addErrback(this.load_local_ip_data_error);
        this.external_callback = callback;
        return false;
    },
    load_local_ip_data_cb:function(result){
        var r = YAHOO.lang.JSON.parse(result.responseText)
        this.ip_data = r.data;
        this.loaded = true;
        if (this.external_callback != "") {
            eval(this.external_callback);
        }
    },
    load_local_ip_data_error:function(result){
        this.loaded = false;
        this.ip_data = {};
        //alert('Sorry, there was an error loading the local ip data.')
    }
}

app.request_deal = {
    company_id:null,
    form_url:'/ajax/deal/form',
    form_submit_url:'/ajax/deal/form_submit',
    container_id:'request_deal_overlay',
    activity:'request.quote',
    init:function(company_id){
        this.company_id = company_id;
        if (arguments[1] !== undefined){
            this.activity = arguments[1]
        }
        
        var randomnumber=Math.floor(Math.random()*2); //random 0 or 1
        var overlay_style = ['one_col', 'two_col'];
        var overlay_config = { width:"450px",
        				context:['largeCol','bl','tl'],
        				x:30,
        				y:10,
        				//fixedcenter:true, 
        				close:true, 
        				draggable:false, 
        				zindex:100,
        				modal:true,
        				visible:false,
        				constraintoviewport:false};
                        
        if (randomnumber > 0) {
            overlay_config = { width:"700px",
            				context:['leftCol','tl','tr', null, [-120,0] ],
            				close:true, 
            				draggable:false, 
            				zindex:100,
            				modal:true,
            				visible:false,
            				constraintoviewport:false}
        }
        // $(this.container_id).style.display='block';
        // $(this.container_id).style.visibility='visible';
        if (!$('request_deal_overlay_c')){
            this.request_deal_overlay = new YAHOO.widget.Panel(this.container_id, overlay_config);
            this.request_deal_overlay.render();
        } 
        $('request_deal_overlay_form').innerHTML = '<div class="loading">Loading request form...</div>';;
        this.request_deal_overlay.show();
        this.load_form(overlay_style[randomnumber]);
    },
    load_form:function(overlay_style){
        try {
            dcsMultiTrack('DCS.dcsuri', this.form_url + '/' + overlay_style, 'WT.ti', 'AJAX Request Deal', 'WT.si_n','reqdeal_ajax', 'WT.si_p',overlay_style, 'WT.si_x', '1');
            if (trackEngagement) {
                trackEngagement('bookappt');
            }
        }
        catch(err) {}
        var d = doXHR(this.form_url + '?' + queryString({'company_id':this.company_id, 'activity':this.activity, 'overlay_style':overlay_style, 'bust':Math.random()}), {});
        d.addCallback(this.load_form_cb);
        d.addErrback(this.load_form_error);
        return false;
    },
    load_form_cb:function(result){
        var r = YAHOO.lang.JSON.parse(result.responseText)
        $('request_deal_overlay_form').innerHTML = r.data
    },
    load_form_error:function(result){
        alert('Sorry, there was an error loading this form.')
    },
    toggle_submit:function(){
        try{
            var el = $('request_deal_submit')
            if(!el.disabled){
                el.disabled = true;
                el.value = 'Saving...'
            } else {
                el.disabled = false;
                el.value = 'Send Request'
            }
            
        }catch(e){}
    },
    save:function(){
        this.toggle_submit();
        pars2 = formContents('ajax_request_deal_form');
        pars2[0].push('bust');
        pars2[1].push(Math.random());
        pars2[0].push('company_id');
        pars2[1].push(this.company_id);
        pars2[0].push('activity');
        pars2[1].push(this.activity);

        var d = doXHR(this.form_submit_url, {
            method:'POST',
            sendContent:queryString(pars2),
            mimeType: 'application/x-www-form-urlencoded', 
            headers: {"Content-Type":"application/x-www-form-urlencoded"} 
        });
        d.addCallback(this.save_cb);
        d.addErrback(this.save_error);

    },
    save_cb:function(result){
        var r = YAHOO.lang.JSON.parse(result.responseText)
        $('request_deal_overlay_form').innerHTML = r.data
        // webtrends conversion.
        try {
            // if we have activity then something to screwed up
            // if we have sent_to then something got sent.
            log('form status', r.form_status);
            if (r.form_status == 'form_error') {
                // dcsMultiTrack('DCS.dcsuri', this.form_submit_url + '/error', 'WT.ti', 'AJAX Request Deal', 'WT.si_n','reqdeal_ajax', 'WT.si_p', r.form_status, 'WT.si_x', '2;2');
            } else {
                dcsMultiTrack('DCS.dcsuri', this.form_submit_url, 'WT.ti', 'AJAX Request Deal', 'WT.si_n','reqdeal_ajax', 'WT.si_p', 'reqdeal_ajax_complete', 'WT.si_x', '2', 'WT.si_cs','1');
            }
        } catch(err) {}
    },
    save_error:function(result){
        alert('Sorry, there was an error saving this form.')
    },
    close:function(){
        // $(this.container_id).style.display='none';
        // $(this.container_id).style.visibility='hidden';
        this.request_deal_overlay.hide();
    },
    end:function(){}
}

// Generate partner ad block
function formatPartnerAds_x( elem, sep, title, result ) {
	try {
		var innerHtml = '';
		var docs = result.response.docs;
		if (docs.length != 0) {
			innerHtml += '<h4>' + title + '</h4>';
		}
		for (var i = 0 ; i < docs.length; i++) {
			var doc = docs[i];
			var phone = doc.trackablePhone;
			var re10digit=/^\d{10}$/
			if (phone.match(re10digit)) {
				phone = '(' + phone.substring(0,3) + ')' + ' ' +
					phone.substring(3, 6) + '-' + phone.substring(6);
			}
			var companyLink = doc.internalLink;
			if (companyLink.length == 0) {
				companyLink = doc.trackableLink;
				innerHtml += '<tr><td><p><a rel="nofollow" href="' + companyLink + '">' + 
					doc.companyNameSort + '</a><br/>';
			} else {
				innerHtml += '<tr><td><p><a href="' + companyLink + '">' + 
					doc.companyNameSort + '</a><br/>';
			}
			if (phone.length == 0) {
				innerHtml += '' + doc.address;
			} else {
				innerHtml += '<b>' + phone + '</b>, ' + doc.address;
                var trackingPixel = doc.trackingPixel;
                if (trackingPixel && trackingPixel.length != 0) {
                    innerHtml += '<img src=' + trackingPixel + ' width="1" height="1" alt=""/>'
                }
			}
			innerHtml += '</p></td></tr>'
		}
		if (docs.length != 0) {
			$(elem).innerHTML = "<table cellspacing=\"0\">"+ innerHtml + "</table>" + sep;
		}
	} catch(err) {
		log('error formatting partner ad', err);
	}
}

// Generate partner ad block
function formatPartnerAds_a( elem, sep, result ) {
    formatPartnerAds_x(elem, sep, "Recommended Businesses", result);
}

function formatPartnerAds( result ) {
	try {
		var innerHtml = '';
		var docs = result.response.docs;
		if (docs.length != 0) {
			innerHtml += '<h3>Recommended Businesses</h3>';
		}
		for (var i = 0 ; i < docs.length; i++) {
			var doc = docs[i];
			var phone = doc.trackablePhone;
			var re10digit=/^\d{10}$/
			if (phone.match(re10digit)) {
				phone = '(' + phone.substring(0,3) + ')' + ' ' +
					phone.substring(3, 6) + '-' + phone.substring(6);
			}
			var companyLink = doc.internalLink;
			if (companyLink.length == 0) {
				companyLink = doc.trackableLink;
				innerHtml += '<tr><td><h4><a rel="nofollow" href="' + companyLink + '">' + 
					doc.companyNameSort + '</a></h4></td></tr>';
			} else {
				innerHtml += '<tr><td><h4><a href="' + companyLink + '">' + 
					doc.companyNameSort + '</a></h4></td></tr>';
			}
			if (phone.length == 0) {
				innerHtml += '<tr><td><h4 class="ppa">' + doc.address + '</h4></td></tr>';
			} else {
				innerHtml += '<tr><td><h4 class="ppa"><b>' + phone + '</b>, ' + doc.address + '';
                var trackingPixel = doc.trackingPixel;
                if (trackingPixel && trackingPixel.length != 0) {
                    innerHtml += '<img src=' + trackingPixel + ' width="1" height="1" alt=""/>'
                }
				innerHtml += '</h4></td></tr>';
			}
			var desc = ''; //doc.desc
			if (desc.length > 512) {
				var tail = desc.indexOf(' ', 512);
				if (tail != -1) {
					var more = '<a href="' + companyLink + '"> . . . </a>';
					desc = desc.substring(0, tail) + more;
				}
			}
			innerHtml += '<tr><td><p>' + desc + '</p></td></tr>';
		}
		$('partnerAds').innerHTML = "<table cellspacing=\"0\">"+ innerHtml + "</table>";
	} catch(err) {
		log('error formatting partner ad', err);
	}
}

/*!
 * Back Button Detection Object V 1.0.0
 * http://www.brookebryan.com/
 *
 * Copyright 2010, Brooke Bryan
 *
 * Date: Sat Feb 27 15:55:01 2010 GMT
 */
// put this on page to detect.
// bajb_backdetect.Initialise();
var bajb_backdetect = {
	Version: '1.0.0',
	Description: 'Back Button Detection',

	Browser: {
		IE:     !!(window.attachEvent && !window.opera),
		Safari:	navigator.userAgent.indexOf('Apple') > -1,
		Opera:	!!window.opera
	},

	FrameLoaded: 0,
	FrameTry:0,
	FrameTimeout: null,

	OnBack: function(){
        trackEngagement('back');
	},

	BAJBFrame: function(){
		var BAJBOnBack = document.getElementById('BAJBOnBack');
		if(bajb_backdetect.FrameLoaded > 1)
		{
			if(bajb_backdetect.FrameLoaded == 2)
			{
				bajb_backdetect.OnBack();
				history.back();
			}
		}
		bajb_backdetect.FrameLoaded++;
		if(bajb_backdetect.FrameLoaded == 1)
		{
			if(bajb_backdetect.Browser.IE)
			{
				bajb_backdetect.SetupFrames();
			}
			else
			{
				bajb_backdetect.FrameTimeout = setTimeout("bajb_backdetect.SetupFrames();",700);
			}
		}
	},

	SetupFrames: function()
	{
		clearTimeout(bajb_backdetect.FrameTimeout);
		var BBiFrame = document.getElementById('BAJBOnBack');
		var checkVar = BBiFrame.src.substr(-11,11);

		if(bajb_backdetect.FrameLoaded == 1 && checkVar != "HistoryLoad")
		{
			BBiFrame.src = "/static/blank.html?HistoryLoad";
		}
		else
		{
			if(bajb_backdetect.FrameTry < 2 && checkVar != "HistoryLoad")
			{
				bajb_backdetect.FrameTry++;
				bajb_backdetect.FrameTimeout = setTimeout("bajb_backdetect.SetupFrames();",700);
			}
		}
	},

	SafariHash: 'false',
	Safari: function()
	{
		if(bajb_backdetect.SafariHash == 'false')
		{
			if(window.location.hash == '#b')
			{
				bajb_backdetect.SafariHash = 'true';
			}
			else
			{
				window.location.hash = '#b';
			}
			setTimeout("bajb_backdetect.Safari();",100);
		}
		else if(bajb_backdetect.SafariHash == 'true')
		{
			if(window.location.hash == '')
			{
				bajb_backdetect.SafariHash = 'back';
				bajb_backdetect.OnBack();
				history.back();
			}
			else
			{
				setTimeout("bajb_backdetect.Safari();",100);
			}
		}
	},

	Initialise: function()
	{
		if(bajb_backdetect.Browser.Safari)
		{
			bajb_backdetect.Safari();
		}
		else
		{
			document.write('<iframe src="/static/blank.html" style="display:none;" id="BAJBOnBack" onunload="alert(\'de\')" onload="bajb_backdetect.BAJBFrame();"></iframe>');
		}
	}
};

