/**
 *
 *   Tea Party Patriots API client access library.
 *
 * Usage:
 * 		<script>
 * 			window.tppApiInit = function() {
 * 				TPPapi.init({
 * 					version: 'v1',
 * 					host   : '//host.name.com',    // optional, fallback to script source if on TPP
 * 					apikey : 'your API key here',  // optional, fallback to public
 * 					bearer : 'your bearer key'     // optional, fallback to public
 * 				});
 * 			}
 *
 * 			(function(d, s, id){
 *				if (!d.getElementById(id)) {
 *					var js  = d.createElement(s); js.id = id;
 *					js.src = "//api.teapartypatriots.org/api-clients/js/tpp_apibase.js";
 *					var tjs = d.getElementsByTagName(s)[0];
 *					tjs.parentNode.insertBefore(js, tjs);
 *				}}(document, 'script', 'tppapi-js'));
 *
 *    	</script>
 *
 * 		// TPPapi.groups.read(....)
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	root.console = root.console || {log: function(){}};

	root.TPPapi = root.TPPapi || {};
	var T = root.TPPapi = jQuery.extend(root.TPPapi, {
		config : {event:{}},
		init : function (config) {
			config = jQuery.extend({version: 'v1'}, this.config, config);
			config.host = config.host || TPPapi.config.host;
			// force always https
			config.host = config.host.replace('http:', 'https:');
			T.config = config;
			if (!T.config.host)
				console.log("ERROR: TPPapi has no host configured.");
		},
		getURL : function(url) {
			return T.config.host +'/'+ T.config.version +'/'+ url;
		},
		getApiKey : function(settings_) {
			var settings = jQuery.extend({	cache   :false,
											dataType:'json'},
										settings_);

			var dfd = jQuery.Deferred();

			if (T.config.apikey) {
				T.callback(settings.success, [T.config.apikey]);
				dfd.resolve([T.config.apikey]);
			} else {
				jQuery.ajax( T.getURL('auth/public_key') , {})
							.done(function(result, status, jqXHR){
								if (result.status) {
									T.config.apikey = result.data;
									if (settings_.success)
										T.callback(settings_.success, [result.data, status, jqXHR]);
									dfd.resolve([result.data, status, jqXHR]);
								}
								else if (settings_.error) {
									dfd.reject([jqXHR, "error"]);
									T.callback(settings_.error, [jqXHR, "error", result]);
								}
							}).fail(function(jqXHR, textStatus, errorThrown){
								if (settings_.error)
									T.callback(settings_.error, [jqXHR, "error"]);
								dfd.reject([jqXHR, "error"]);
							});

			}
			return dfd.promise();
		},

		get  : function (url, settings_) {
			var settings = jQuery.extend({	cache   :false,
											data    :{},
											dataType:'json',
											type    :'GET',
											crossDomain: true,
											headers :{}},
										settings_);
			var dfd = jQuery.Deferred()
			T.getApiKey({error: settings.error, success: function() {
				// if (!settings.headers['X-API-KEY'] && T.config.apikey)
				// 	settings.headers['X-API-KEY'] = T.config.apikey;
				// if (!settings.headers['Authorization'] && T.config.bearer)
				// 	settings.headers['Authorization'] = 'Bearer '+T.config.bearer;
				// if (!settings.data['_method']) {
				// 	settings.data['_method'] = settings.type;
				// }

				if( Object.prototype.toString.call( settings.data ) === '[object Array]' ) {
					throw new Error("Data being passed to T.get / T.post / etc must be a Javascript Object, not an Array!");
				}


				if (!settings.data['access_token'] && settings.headers['Authorization']) {
					if (settings.headers['Authorization'].substring(0,6).toLowerCase() == 'bearer' )
						settings.data['access_token'] = settings.headers['Authorization'].substring(7).trim();
				}

				if (!settings.data['access_token'] && T.config.bearer) {
					settings.data['access_token'] = T.config.bearer;
				}

				if (!settings.data['client_id'] && T.config.apikey) {
					settings.data['client_id'] = T.config.apikey;
				}

				if (!settings.data['_method'] && settings.headers['X-HTTP-METHOD-OVERRIDE']) {
					settings.data['_method'] = settings.type;
				}
				if (!settings.data['_method']) {
					settings.data['_method'] = settings.type;
				}

				var x_headers = ['X-HTTP-METHOD-OVERRIDE', 'Authorization', 'X-API-KEY'];
				for (i in x_headers)
					delete settings.headers[ x_headers[i] ];

				jQuery.ajax( T.getURL(url) , settings ).done(function(data, textStatus, jqXHR){
					dfd.resolve(data, textStatus, jqXHR);
				}).fail(function(jqXHR, textStatus, errorThrown){
					dfd.reject(jqXHR, textStatus, errorThrown);
				});
			}}).fail(function(jqXHR, textStatus, errorThrown){
				dfd.reject(jqXHR, textStatus, errorThrown);
			});
			return dfd.promise();
		},
		post : function (url, settings_) {
			var settings = jQuery.extend({data: {}}, settings_, {type:'POST'});
			return T.get(url, settings);
		},
		put  : function (url, settings_) {
			var settings = jQuery.extend({data:{}}, settings_, {type:'POST'});
			settings.data['_method'] = 'PUT';
			return T.post(url, settings);
		},
		delete: function (url, settings_) {
			var settings = jQuery.extend({data:{}}, settings_, {type:'POST'});
			settings.data['_method'] = 'DELETE';
			return T.post(url, settings);
		},
		callback : function (fn, args) {
			if (fn) {
				if (!T.isArrayLike(fn))
					fn = [fn];
				jQuery.each(fn, function(i,c) {
					c.apply(c,args);
				});
			}
		},

		/** Fire an event to listeners **/
		fire : function (eventname, args) {
			// var s = new Date();
			T.callback(T.config.event[eventname], args);
			// var e = new Date();
			// var d1 = s-this._.start;
			// var d2 = e-s;
			// console.log('Event '+eventname+' called '+d1+' after load and took '+d2);
		},
		/** register an event listener **/
		on : function (eventname, fn) {
			if (typeof T.config.event[eventname] == 'undefined')
				T.config.event[eventname] = [];
			T.config.event[eventname] = T.config.event[eventname].concat(fn);

			return fn;
		},
		/** remove an event listener **/
		off : function (eventname, fn) {
			if (typeof T.config.event[eventname] != 'undefined') {
				if (!T.isArrayLike(fn))
					fn = [fn];
				for (var i = T.config.event[eventname].length; i--;) {
					foreach (f in fn)
						if (T.config.event[eventname][i] === fn)
							T.config.event[eventname].splice(i,1);
				}
			}
			return fn;
		},

		// taken from jQuery
		isArrayLike : function ( obj ) {
			if (!obj)
				return false;

			var length = obj.length,
				type = jQuery.type( obj );

			if ( type === "function" || type==='string' || jQuery.isWindow( obj ) ) {
				return false;
			}

			if ( obj.nodeType === 1 && length ) {
				return true;
			}

			return type === "array" || length === 0 ||
				typeof length === "number" && length > 0 && ( length - 1 ) in obj;
		}

	});
	T.root = root;

})();

(function(){
// Implement Array.indexOf for those stupid browsers that don't
//    (I am looking at you IE<9!)
// FROM https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf
// Production steps of ECMA-262, Edition 5, 15.4.4.14
// Reference: http://es5.github.io/#x15.4.4.14
if (!Array.prototype.indexOf) {
  Array.prototype.indexOf = function(searchElement, fromIndex) {

    var k;

    // 1. Let O be the result of calling ToObject passing
    //    the this value as the argument.
    if (this == null) {
      throw new TypeError('"this" is null or not defined');
    }

    var O = Object(this);

    // 2. Let lenValue be the result of calling the Get
    //    internal method of O with the argument "length".
    // 3. Let len be ToUint32(lenValue).
    var len = O.length >>> 0;

    // 4. If len is 0, return -1.
    if (len === 0) {
      return -1;
    }

    // 5. If argument fromIndex was passed let n be
    //    ToInteger(fromIndex); else let n be 0.
    var n = +fromIndex || 0;

    if (Math.abs(n) === Infinity) {
      n = 0;
    }

    // 6. If n >= len, return -1.
    if (n >= len) {
      return -1;
    }

    // 7. If n >= 0, then Let k be n.
    // 8. Else, n<0, Let k be len - abs(n).
    //    If k is less than 0, then let k be 0.
    k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);

    // 9. Repeat, while k < len
    while (k < len) {
      // a. Let Pk be ToString(k).
      //   This is implicit for LHS operands of the in operator
      // b. Let kPresent be the result of calling the
      //    HasProperty internal method of O with argument Pk.
      //   This step can be combined with c
      // c. If kPresent is true, then
      //    i.  Let elementK be the result of calling the Get
      //        internal method of O with the argument ToString(k).
      //   ii.  Let same be the result of applying the
      //        Strict Equality Comparison Algorithm to
      //        searchElement and elementK.
      //  iii.  If same is true, return k.
      if (k in O && O[k] === searchElement) {
        return k;
      }
      k++;
    }
    return -1;
  };
}
})();/**
 *
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var A = T.auth = T.auth || {
		loggedin : null,

		get_auth_levels: function() {
			return {
				'TPP_API_LEVEL_ADMIN':             90,
				'TPP_API_LEVEL_DEVELOPER':         70,
				'TPP_API_LEVEL_STAFF':             60,
				'TPP_API_LEVEL_INSIDE_TPP':        50,
				'TPP_API_LEVEL_VENDOR':            40,
				'TPP_API_LEVEL_GRASSROOT_SUPPORT': 30,
				'TPP_API_LEVEL_STATE_COORD':       20,
				'TPP_API_LEVEL_LOCAL_COORD':       10,
				'TPP_API_LEVEL_USER':               2,
				'TPP_API_LEVEL_GUEST':              1
			};
		},

		get_auth_level: function(name) {
			return A.get_auth_levels()[name];
		},

		get_user_id : function() {
			if (A.loggedin)
				return T.config.cid;
			return null;
		},
		get_user_level: function() {
			if (T.config.level)
				return T.config.level;
			return 1;
		},

		/**
		 * Is the bearer token a valid login.
		 * @param {object}  options Standard options.
		 * @param {string}  token   Optional. The token to check, otherwise uses options or config.
		 * @param {boolean} setback Optional. On success and true result, set token to config.
		 */
		isLoggedIn: function (options, token, setback) {
			var dfd = jQuery.Deferred();

			if ((!token || token == T.config.bearer) && A.loggedin !== null) {
				T.callback(options.success, [A.loggedin]);
				dfd.resolve([A.loggedin]);
			} else {
				var hdr = options.headers || {};
				if (token)
					hdr['Authorization'] = 'Bearer '+token;

				T.get('auth/valid_credentials',
					jQuery.extend(
						{},
						options,
						{headers: hdr,
						 success: function(result) {
								var loggedin = (result.data.type == 'bearer' && result.data.valid);
								T.config.level = result.level;

								if (!token || setback) {
									A.loggedin = loggedin;
									if (token && loggedin) {
										T.config.bearer = token;
										T.config.cid = result.data.cid;
									}
								}
								T.callback(options.success, [loggedin, result.request.expires]);
								dfd.resolve(loggedin, result.request.expires);
							},
						 error: function() {
						 		if (!token || setback) {
						 			A.loggedin = false;
						 			T.config.bearer = null;
						 			T.config.cid = null;
						 		}
						 		T.callback(options.success, [false]);
						 		dfd.resolve(false);
						 	}
						}));
			}
			return dfd.promise();
		},
		reset_password : function (email, options) {
			return T.post('auth/reset_password',
							jQuery.extend({},
									  options,
									  {data: jQuery.extend({},
								  						options&&options.data?options.data:{},
								  						{email:email})}));
		},
		/**
		 * User Login
		 * @param  {string} username User name, usually email.
		 * @param  {string} password User password
		 * @param  {object} options  Standard options.
		 */
		login: function (username, password, rememberme, options) {
			var dfd = jQuery.Deferred();
			var opts = jQuery.extend(
					{},
					options,
					{data: jQuery.extend(
							options.data,
							{username  : username,
							 password  : password,
							 rememberme: rememberme,
							 grant_type: 'password'
							}),
					// override the callbacks and handle below
					 success: function(result) {},
					 error: function(result) {}});

			T.post('auth/login/1', opts)
				.done(function(result, textStatus, jqXHR){
					if (result.data.access_token) {
						T.config.bearer = result.data.access_token;
						A.loggedin = true;
						T.config.cid = result.data.cid;
						T.config.level = result.level;
					} else {
						A.loggedin = false;
						T.config.cid = null;
					}
					T.callback(options.success, [result]);
					dfd.resolve(result, textStatus, jqXHR);
				}).fail(function(jqXHR, textStatus, errorThrown){
					dfd.reject(jqXHR, textStatus, errorThrown);
				});
			return dfd.promise();
		},
		/**
		 * Invalidate login session
		 * @param  {object} options Standard options
		 */
		logout: function (options) {
			var dfd = jQuery.Deferred();
			var opts = jQuery.extend(
					{},
					options,
					// override the callbacks and handle below
					{success: function(result) {
					}, error: function(result) {
					}});

			T.post('auth/logout', opts)
				.done(function(result, textStatus, jqXHR){
					A.loggedin = false;
					T.config.bearer = null;
					T.config.cid = null;
					T.callback(options.success, [result]);
					dfd.resolve(result, textStatus, jqXHR);
				}).fail(function(jqXHR, textStatus, errorThrown){
					A.loggedin = false;
					T.config.bearer = null;
					T.config.cid = null;
					T.callback(options.error, [result]);
					dfd.reject(jqXHR, textStatus, errorThrown);
				});
			return dfd.promise();
		},
		/** Facebook login via JS is limited **/
		facebook_login : function() {
			return T.get('auth/facebook');
		}
	};
})();/**
 *
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var C = T.contacts = T.contacts || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		create : function(options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.post('contacts/', settings);
		},
		register : function(options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.post('contacts/register', settings);
		},
		read : function(contactid, options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.get('contacts/' + (contactid || ''), settings);
		},
		update : function(contactid, options) {
			var settings = jQuery.extend({},
										C.defaults,
										options,
										{success:function(result){
											T.fire('model_afterupdate', ['contacts', result]);
											T.callback(options.success, [result]);
										}});
			T.fire('model_beforeupdate', ['contacts', contactid, settings]);
			return T.put('contacts/' + contactid, settings);
		},
		upload_avatar: function(contactid, file, options) {
			var fd = new FormData();
			fd.append('file', file);

			return T.post('contacts/'+contactid+'/avatar', jQuery.extend({},
				C.defaults,
				options,
				{ data:        fd,
				  processData: false,
				  contentType: false,
				  headers: {"X-HTTP-METHOD-OVERRIDE":"PUT"}
				}));
		},
		reset_password_request: function(email, options) {
			var data = {data: { email: email } };
			var settings = jQuery.extend(C.defaults, options, data);
			return T.post('contacts/resetpassword/', settings);
		},
		change_password: function(new_password, key, options) {
			var data = {data : {new_password: new_password, key: key}};
			var settings = jQuery.extend(C.defaults, options, data);
			return T.put('contacts/resetpassword/', settings);
		},
		search: function(options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.post('contacts/search/', settings);
		},
		groups: function (contactid, type, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.get('contacts/' + contactid + '/groups/' + type, settings);
		},
		optins: function (contactid, type, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.get('contacts/' + contactid + '/optins/' + type, settings);
		},
		add_optin: function(contactid, optin_id, options)  {
			var settings = jQuery.extend(C.defaults, options);
			return T.post('contacts/' + contactid + '/optins/' + optin_id, settings);
		},
		remove_optin: function(contactid, optin_id, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.delete('contacts/' + contactid + '/optins/' + optin_id, settings);
		},
		remove_email_optins: function(contactid, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.delete('contacts/' + contactid + '/optins/emails', settings);
		},
		remove_phone_optins: function(contactid, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.delete('contacts/' + contactid + '/optins/phones', settings);
		},
		remove_address_optins: function(contactid, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.delete('contacts/' + contactid + '/optins/addresses', settings);
		},
		join_group: function(contactid, groupid, options)  {
			var settings = jQuery.extend(C.defaults, options);
			return T.post('contacts/' + contactid + '/groups/' + groupid, settings);
		},
		leave_group: function(contactid, groupid, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.delete('contacts/' + contactid + '/groups/' + groupid, settings);
		},
		get_preferences: function(contactid, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.get('contacts/' + contactid + '/preferences', settings);
		},
		update_preferences: function(contactid, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.post('contacts/' + contactid + '/preferences', settings);
		},
		api_key: function(options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.get('contacts/apikey', settings);
		},
		optout_phone: function(number, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.post('contacts/optoutphone/'+number, settings);
		},
		quick_login: function(contactid, hashkey, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.post('contacts/quick_login/'+contactid+'/'+hashkey, settings);
		},
		complete_registration: function(contactid, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.put('contacts/complete_registration/'+contactid, settings);
		},
		engagement_first_100: function(options){
			var settings = jQuery.extend(C.defaults, options);
			return T.get('contacts/engagement_first_100', settings);
		},
		get_interests: function(contactid, options){
			var settings = jQuery.extend(C.defaults, options);
			return T.get('contacts/' + contactid + '/interests', settings);
		},
		set_interests: function(contactid, options){
			var settings = jQuery.extend(C.defaults, options);
			return T.post('contacts/' + contactid + '/interests', settings);
		},
		in_report: function(contact_id,report_id, options){
			var settings = jQuery.extend(C.defaults, options);
			return T.get('contacts/' + contact_id + '/in_report/'+report_id, settings);
		},
		signed_petitions: function(contact_id, options){
			var settings = jQuery.extend(C.defaults, options);
			return T.get('contacts/' + contact_id + '/petition_signatures/', settings);
		},
		activty: function(contact_id, options){
			var settings = jQuery.extend(C.defaults, options);
			return T.get('contacts/' + contact_id + '/activity', settings);
		},

	};
})();
(function(){
	var root = ( typeof window === 'object' && window ) || this;

	var T = root.TPPapi;
	var G = T.groups = {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		read : function(groupid, options) {
			var settings = jQuery.extend({}, G.defaults, options);
			return T.get('groups/search/' + groupid, settings);
		},
		update : function(groupid, options) {
			var settings = jQuery.extend({}, G.defaults, options);
			return T.put('groups/' + groupid, settings);
		},
		/**
		 * parameters that can be passed to the options data element for narrowing a search:
		 * 		- address
		 * 		- offset
		 * 		- limit
		 * 		- active
		 * 		- sort
		 * 		- distance
		 * 		- latlng
		 */
		search : function(options) {
			var settings = jQuery.extend({}, G.defaults, options);
			return T.get('groups/search/', settings);
		},
		members : function(groupid, options) {
			var settings = jQuery.extend({}, G.defaults, options);
			return T.get('groups/' + groupid + '/members/', settings);
		},
		member : function(groupid, contactid, options) {
			var settings = jQuery.extend({}, G.defaults, options);
			return T.get('groups/'+ groupid + '/members/' + settings.memberid, settings);
		},
		leadership : function(groupid, level, options) {
			var settings = jQuery.extend({}, G.defaults, options);
			T.get('groups/leadership/'+ groupid + '/' + level, settings);
		},
		contact : function(groupid, who, options) {
			var settings = jQuery.extend({}, G.defaults, options);
			return T.post('groups/' + groupid + '/contact/' + who, settings);
		},
		download : function(groupid, type, options) {
			var settings = jQuery.extend({}, G.defaults, options);
			return T.get('groups/' + groupid + '/download/' + type, settings);
		}
	};
})();/**
 *
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var C = T.congress = T.congress || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		/** Get a legislator's Bio */
		bio : function (id, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.get('congress/legislators/' + id + '/bio', settings);
		},
		/** Get Legislators.
		 * @param timeOrId the govtract ID or a timeframe (one of 'any', 'current', 'past10', 'past20')
		 *
		 * @example TPPapi.congress.legislators('current',
		 *          							{data:{fields:'last_name,term_total',
		 *          								   q:'{"term_state":"CO","term_total:{"$gt":8}}',
		 *          								   sort:'-term_total,last_name',
		 *          								   limit:1},
		 *          							success:function(result){
		 *          										 alert(result); }});
		 */
		legislators : function(timeOrId, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.get('congress/legislators/' + timeOrId, settings);
		},
		/** Get Senators.
		 * @param timeOrId the govtract ID or a timeframe (one of 'any', 'current', 'past10', 'past20')
		 */
		senators : function(timeOrId, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.get('congress/senators/' + timeOrId, settings);
		},
		/** Get Representatives.
		 * @param timeOrId the govtract ID or a timeframe (one of 'any', 'current', 'past10', 'past20')
		 */
		representatives : function(timeOrId, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.get('congress/representatives/' + timeOrId, settings);
		}
	}
})();/**
 * TPP Events JS API
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var C = T.events = T.events || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		create : function(options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.post('events/', settings);
		},
		read : function(tpp_id, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.get('events/'+tpp_id, settings);
		},
		update : function(tpp_id, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.put('events/'+tpp_id, settings);
		},
		remove : function(tpp_id, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.delete('events/'+tpp_id, settings);
		},
		duplicate : function(event_id, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.post('events/duplicate/'+event_id, settings);
		},
		search : function(options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.get('events/search/', settings);
		},
		rsvp: function(event_id, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.post('events/rsvp/'+event_id, settings);
		},
		types: function(options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.get('events/types', settings);
		},
		sendTownHallNotifications: function(event_id, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.post('events/sendTownHallNotifications/'+event_id, settings);
		},
		getICSFile: function(event_id, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.get('events/ics/'+event_id, settings);
		},
	}
})();/**
 * Access tpp_webcontent Database for dynamic content
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var C = T.webresources = T.webresources || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},

		/** Get Content by type_id */
		ContentByType : function (content_type, options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.get('webresources/' + content_type, settings);
		},
		/** Get Calls to Action */
		callstoaction: function (options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.get('webresources/callstoaction', settings);
		},
		/** Download an item */
		download: function (content_id, options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.get('webresources/'+content_id+'/download', settings);
		},
		update: function(content_id, options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.put('webresources/'+content_id, settings);
		},
		create: function(options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.post('webresources/', settings);
		}
	};
})();/**
 *  Get Involved Block Methods
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var C = T.getinvolved = T.getinvolved || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},

		lcModalSend: function(data, options){
			var settings = jQuery.extend(C.defaults, options);
			return T.post('getinvolved/sendEmailToGroup/', data, settings);
		},

		lcModalSendCheck: function(gid, pid, options){
			var settings = jQuery.extend(C.defaults, options);
			return T.get('getinvolved/hasEmailBeenSent?groupID=' + gid + 'postID=' + pid, settings);
		},

		join_us: function(options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.post('getinvolved/', settings);
		}

	}
})();(function(){
	var root = ( typeof window === 'object' && window ) || this;

	var T = root.TPPapi;
	var G = T.createGroup = {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},

		/**
		 * parameters from create group form:
		 * 		- group_name
		 * 		- group_description
		 * 		- address
		 * 		- city
		 * 		- state
		 * 		- zip_code
		 * 		- phone
		 *		- group_type (Pending Approval)
		 *		- primary_email (Profile Email)
		 *
		 */
		create : function(options) {
			var settings = jQuery.extend({}, G.defaults, options);
			return T.post('groups/', settings);
		},

	};
})();/**
 * Access volunteer items
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var C = T.volunteer = T.volunteer || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},

		/**
		 * Get Items for logged in user
		 *	Data attributes allowed are:
		 *		count	number of results to return (default: 15)
		 *		lat		latitude to pass instead of using user's location
		 *		long	longitude to pass instead of using user's location
		 */
		read : function (options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.get('volunteer/', settings);
		},
		/** Mark volunteer item as complete */
		update: function (volunteer_id, options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.post('volunteer/'+volunteer_id, settings);
		},
		interests_topics: function(options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.get('interests', settings);
		}

	};
})();
/**
 * Newsletter SignUp JS
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var C = T.newsletter = T.newsletter || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},

		/** Sign Up for Newsletter */
		signup : function (options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.post('newsletter/', settings);
		}

	};
})();/**
 *	conversions
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var C = T.conversions = T.conversions || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		conversion : function (options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.post('conversions/', settings);
		},
		roi : function (options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.post('conversions/roi', settings);
		}
	};
})();/**
 * Newsletter SignUp JS
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var C = T.eoe = T.eoe || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		get_list : function (options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.get('eoe/', settings);
		}

	};
})();/**
 * Rally RSVP JS
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var R = T.rally = T.rally || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		rsvp : function (rally_campaign_id, office_id, options) {
			var settings = jQuery.extend({}, R.defaults, options);
			return T.post('rallies/rsvp/'+rally_campaign_id+'/'+office_id, settings);
		}

	};
})();/**
 * Reports JS
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var R = T.reports = T.reports || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		execute: function (reportid, options) {
			var settings = jQuery.extend({}, R.defaults, options);
			return T.post('reports/' + reportid, settings);
		}
	};
})();/**
 * Segments JS
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var R = T.segments = T.segments || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		list : function (options) {
			var settings = jQuery.extend({}, R.defaults, options);
			T.get('segments/', settings);
		},
		execute: function (segment_id, options) {
			var settings = jQuery.extend({}, R.defaults, options);
			return T.get('segments/execute/' + segment_id, settings);
		}
	};
})();(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var apiRoot = 'future/';
	var T = root.TPPapi = root.TPPapi || {};
	var V = T.future = T.future || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		list : function (options) {
			var settings = jQuery.extend({}, V.defaults, options);
			T.get(apiRoot, settings);
		},
		read : function(id, options) {
			var settings = jQuery.extend({}, V.defaults, options);
			T.get(apiRoot + id, settings);
		},
		update : function(id, options) {
			var settings = jQuery.extend({}, V.defaults, options);
			T.put(apiRoot + id, settings);
		},
		delete: function(id, options) {
			var settings = jQuery.extend({}, V.defaults, options);
			T.delete(apiRoot + id, settings);
		},
		broadcast : function(id, options) {
			var settings = jQuery.extend({}, V.defaults, options);
			T.post(apiRoot + 'broadcast/' + id, settings);
		},
	};
})();(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var apiRoot = 'groundgame/campaigns/';
	var T = root.TPPapi = root.TPPapi || {};
	var V = T.gg_campaigns = T.gg_campaigns || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		list : function (options) {
			var settings = jQuery.extend({}, V.defaults, options);
			T.get(apiRoot, settings);
		},
		read : function(id, options) {
			var settings = jQuery.extend({}, G.defaults, options);
			T.get(apiRoot + id, settings);
		},
		update : function(id, options) {
			var settings = jQuery.extend({}, V.defaults, options);
			T.put(apiRoot + id, settings);
		},
	};
})();(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var apiRoot = 'groundgame/groups/';
	var T = root.TPPapi = root.TPPapi || {};
	var V = T.gg_groups = T.gg_groups || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		list : function (options) {
			var settings = jQuery.extend({}, V.defaults, options);
			T.get(apiRoot, settings);
		},
		read : function(id, options) {
			var settings = jQuery.extend({}, V.defaults, options);
			T.get(apiRoot + id, settings);
		},
		update : function(id, options) {
			var settings = jQuery.extend({}, V.defaults, options);
			T.put(apiRoot + id, settings);
		},
	};
})();(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var apiRoot = 'groundgame/surveys/';
	var T = root.TPPapi = root.TPPapi || {};
	var V = T.gg_surveys = T.gg_surveys || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		list : function (options) {
			var settings = jQuery.extend({}, V.defaults, options);
			T.get(apiRoot, settings);
		},
		read : function(id, options) {
			var settings = jQuery.extend({}, G.defaults, options);
			T.get(apiRoot + id, settings);
		},
		update : function(id, options) {
			var settings = jQuery.extend({}, V.defaults, options);
			T.put(apiRoot + id, settings);
		},
	};
})();(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var apiRoot = 'groundgame/volunteers/';
	var T = root.TPPapi = root.TPPapi || {};
	var V = T.gg_volunteers = T.gg_volunteers || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		list : function (options) {
			var settings = jQuery.extend({}, V.defaults, options);
			T.get(apiRoot, settings);
		},
		read : function(id, options) {
			var settings = jQuery.extend({}, V.defaults, options);
			T.get(apiRoot + id, settings);
		},
		update : function(id, options) {
			var settings = jQuery.extend({}, V.defaults, options);
			T.put(apiRoot + id, settings);
		},
		create: function(options) {
			var settings = jQuery.extend({}, V.defaults, options);
			T.post(apiRoot, settings);
		},
	};
})();/**
 * Donations API
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var D = T.donate = T.donate || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		donate : function(type, frequency, options) {
			var settings = jQuery.extend(D.defaults, options);
			return T.post('donate/charge/'+type+'/'+frequency, settings);
		},
		// create a manual donation (Cash, check, bank transfer record)
		create : function(options) {
			var settings = jQuery.extend({}, D.defaults, options);
			return T.post('donate', settings);
		},
		// update a manual donation
		update : function(donationid, options) {
			var settings = jQuery.extend({}, D.defaults, options);
			return T.put('donate/' + donationid, settings);
		},
		// get the donation campaigns
		campaigns : function(options) {
			var settings = jQuery.extend({}, D.defaults, options);
			return T.get('donate/campaigns', settings);
		},
		circles : function(options) {
			var settings = jQuery.extend({}, D.defaults, options);
			return T.get('donate/circles', settings);
		},
	};
})();
(function(){
	var root = ( typeof window === 'object' && window ) || this;

	var T = root.TPPapi;
	var M = T.memberships = {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		create: function(options) {
			var settings = jQuery.extend({}, M.defaults, options);
			T.post('memberships/', settings);
		},
		update : function(membership_id, options) {
			var settings = jQuery.extend({}, M.defaults, options);
			T.put('memberships/' + membership_id, settings);
		},
		delete: function(membership_id, options) {
			var settings = jQuery.extend({}, M.defaults, options);
			T.delete('memberships/'+ membership_id, settings);
		},
		/**
		 * Parameters accepted
		 * level - the level of role (member, local coordinator, state coordinator). Default: all
		 * group type - the type of group (local, inactive group, state group) Default: all
		 */
		by_contact: function(contact_id, options) {
			var settings = jQuery.extend({}, M.defaults, options);
			T.get('memberships/contact/'+ contact_id, settings);
		},
		/**
		 * Parameters accepted
		 * level - the level of role (member, local coordinator, state coordinator). Default: all
		 * group type - the type of group (local, inactive group, state group) Default: all
		 */
		by_group: function(group_id, options) {
			var settings = jQuery.extend({}, M.defaults, options);
			T.get('memberships/group/'+ group_id, settings);
		}
	};
})();/**
 * Petition JS
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var P = T.petition = T.petition || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		create: function(options) {
			var settings = jQuery.extend({}, P.defaults, options);
			return T.post('petitions/', settings);
		},
		update: function(petition_id, options) {
			var settings = jQuery.extend({}, P.defaults, options);
			return T.put('petitions/'+petition_id, settings);
		},
		list : function(options) {
			var settings = jQuery.extend({}, P.defaults, options);
			return T.get('petitions/', settings);
		},
		featured : function(options) {
			var settings = jQuery.extend({}, P.defaults, options);
			return T.get('petitions/featured', settings);
		},
		read : function(petition_id, options) {
			var settings = jQuery.extend({}, P.defaults, options);
			return T.get('petitions/'+petition_id, settings);
		},
		sign : function (petition_id, options) {
			var settings = jQuery.extend({}, P.defaults, options);
			return T.post('petitions/'+petition_id+'/sign', settings);
		},
		signatures : function(petition_id, options) {
			var settings = jQuery.extend({}, P.defaults, options);
			return T.get('petitions/'+petition_id+'/signatures', settings);
		},
		donations : function(petition_id, options) {
			var settings = jQuery.extend({}, P.defaults, options);
			return T.get('petitions/'+petition_id+'/donations', settings);
		},
		urls : function(petition_id, options) {
			var settings = jQuery.extend({}, P.defaults, options);
			return T.get('petitions/'+petition_id+'/urls', settings);
		},
		add_urls : function(petition_id, options) {
			var settings = jQuery.extend({}, P.defaults, options);
			return T.post('petitions/'+petition_id+'/urls', settings);
		},
		update_url : function(petition_id, url_id, options) {
			var settings = jQuery.extend({}, P.defaults, options);
			return T.put('petitions/'+petition_id+'/urls/'+url_id, settings);
		},
		delete_url : function(petition_id, url_id, options) {
			var settings = jQuery.extend({}, P.defaults, options);
			return T.delete('petitions/'+petition_id+'/urls/'+url_id, settings);
		}
	};
})();
/**
 * TPPCF API
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var R = T.tppcf = T.tppcf || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		vote : function (options) {
			var settings = jQuery.extend({}, R.defaults, options);
			return T.post('tppcf/votes/vote/', settings);
		}

	};
})();/**
 *	comm_addresses
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var C = T.comm_addresses = T.comm_addresses || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		update: function(tpp_id, options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.put('comms/addresses/'+tpp_id, settings);
		},
		create: function(options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.post('comms/addresses/', settings);
		}
	};
})();/**
 *	comm_phones
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var C = T.comm_phones = T.comm_phones || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		update: function(tpp_id, options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.put('comms/phones/'+tpp_id, settings);
		},
		create: function(options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.post('comms/phones/', settings);
		},
		delete: function(tpp_id, options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.delete('comms/phones/'+tpp_id, settings);
		}
	};
})();/**
 *	comm_emails
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var C = T.comm_emails = T.comm_emails || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		update: function(tpp_id, options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.put('comms/emails/'+tpp_id, settings);
		},
		create: function(options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.post('comms/emails/', settings);
		}
	};
})();/**
 *	comm_optins
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var C = T.comm_optins = T.comm_optins || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		read : function(tpp_id, options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.get('comms/optins/'+tpp_id, settings);
		},
		update: function(tpp_id, options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.put('comms/optins/'+tpp_id, settings);
		},
		create: function(options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.post('comms/optins/', settings);
		},
		delete: function(tpp_id, options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.delete('comms/optins/'+tpp_id, settings);
		}
	};
})();/**
 * Phone Banking JS
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var C = T.phone_banking = T.phone_banking || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		users_available_campaigns : function(options) {
			var settings = jQuery.extend({
				data: {
					active: true
				}
			}, C.defaults, options);

			return T.get('campaigns/search/phonebank', settings);
		},
		user_stats : function(campaign_id, user_id, options) {
			//get
			var settings = jQuery.extend({}, C.defaults, options);
			return T.get('campaigns/'+campaign_id+'/users/'+user_id, settings);
		},
		campaign_stats : function(campaign_id, options) {
			//get
			var settings = jQuery.extend({}, C.defaults, options);
			return T.get('campaigns/'+campaign_id+'/stats/', settings);
		},
		next_call : function(campaign_id, options) {
			//get
			var settings = jQuery.extend({}, C.defaults, options);
			return T.post('campaigns/'+campaign_id+'/nextcall', settings);
		},
		release_call : function(campaign_id, call_id, options) {
			//delete no complete flag
			var settings = jQuery.extend({data:{completed: 0}}, C.defaults, options);
			return T.delete('campaigns/'+campaign_id+'/calls/'+call_id, settings);
		},
		complete_call : function(campaign_id, call_id, options) {
			//delete release with complete flag
			var settings = jQuery.extend({data:{completed: 1}}, C.defaults, options);
			return T.delete('campaigns/'+campaign_id+'/calls/'+call_id, settings);
		},
		survey : function(campaign_id, call_id, options) {
			//put
			var settings = jQuery.extend({}, C.defaults, options);
			return T.put('campaigns/'+campaign_id+'/calls/'+call_id, settings);
		},
		make_call : function(campaign_id, call_id, options) {
			// psot with from number
			var settings = jQuery.extend({}, C.defaults, options);
			return T.post('campaigns/'+campaign_id+'/calls/'+call_id+'/call/', settings);
		}
	};
})();/**
 *	Contact Logs
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var C = T.contact_logs = T.contact_logs || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		create : function(tpp_id, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.post('logs/'+tpp_id, settings);
		},
		read : function(tpp_id, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.get('logs/'+tpp_id, settings);
		},
		update : function(tpp_id, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.put('logs/'+tpp_id, settings);
		},
		my_follow_ups : function(tpp_id, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.get('logs/my_follow_ups/'+tpp_id, settings);
		}
	};
})();/**
 * Campaign JS
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var C = T.campaigns = T.campaigns || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		read : function(campaign_id, options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.get('campaigns/'+campaign_id, settings);
		},
		create : function(options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.post('campaigns/', settings);
		},
		update : function(campaign_id, options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.put('campaigns/'+campaign_id, settings);
		},
		sign_legal : function(campaign_id, options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.post('campaigns/'+campaign_id+'/sign_legal', settings);
		},
		register_group: function(options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.post('campaigns/register_group', settings);
		},
		all_volunteer_types: function(options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.get('campaigns/volunteer_types', settings);
		}

	};
})();/**
 * Email StatsJS
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var C = T.email_stats = T.email_stats || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		read : function (job_id, options) {
			var settings = jQuery.extend({}, C.defaults, options);
			return T.get('emailstats/'+job_id, settings);
		}

	};
})();/**
 *	Volunteer Logs
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPapi = root.TPPapi || {};
	var C = T.volunteer_logs = T.volunteer_logs || {
		defaults : {
			success: function(data) {console.log("success", data);},
			error: function(data) {console.log("error", data);}
		},
		create : function(tpp_id, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.post('volunteer/logs/'+tpp_id, settings);
		},
		read : function(tpp_id, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.get('volunteer/logs/'+tpp_id, settings);
		},
		update : function(tpp_id, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.put('volunteer/logs/'+tpp_id, settings);
		},
		delete : function(tpp_id, options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.delete('volunteer/logs/'+tpp_id, settings);
		},
		search : function(options) {
			var settings = jQuery.extend(C.defaults, options);
			return T.get('volunteer/logs/search', settings);
		},
	};
})();

TPPapi.config.host = 'https://api.teapartypatriots.org';
TPPapi.root.tppApiInit();
/* Generated on 20210606194835 *//**
 *
 */
(function(){
	var root = ( typeof window === 'object' && window ) || this;
	root.console = root.console || {log: function(){}};

	var T = root.TPPweb = root.TPPweb || {};
	T.api = root.TPPapi;
	root.TPPweb = jQuery.extend(root.TPPweb, {
		config : {	on_init: [function(){T.releaseInit()}],
					on_ready: [],
					event: {}},
		_:{	state:	'loading',
			ninit:	0,
			authfn: [],
			start:  new Date()},
		/** Start the engines */
		init : function (config) {
			T.api = root.TPPapi;

			/* Make sure merge gets an on_init with both sets of functions */
			if (config && config.on_init)
				T.config.on_init  = T.config.on_init.concat(config.on_init);
			if (config && config.on_ready)
				T.config.on_ready = T.config.on_ready.concat(config.on_ready);

			var event = jQuery.extend({},
										T.config.event,
										{'init' : (T.config.event['init'] || []).concat(T.config.on_init),
										 'ready': (T.config.event['ready'] || []).concat(T.config.on_ready)});

			config = jQuery.extend( T.config,
									config,
									// {on_init: T.config.on_init,
									//  on_ready: T.config.on_ready},
									{event: event});

			T.api.on('init', config.event.init);
			T.api.on('ready',config.event.ready);

			config.host = config.host || TPPweb.config.host;
			T.config = config;
			if (!T.config.host)
				console.log("ERROR: TPPweb has no host configured.");

			T._.state = 'verifying';

			T._.hid = true;

			T._init();
		},
		/** Run registered initializations */
		_init : function() {
			// go see if we are logged in
			T.auth.isLoggedIn({
				success: function() {
					if (!T._.hid)
						return;  // assume we were called from onerror?

					if (T.verifyAuth(T._.authfn)) {
						jQuery(".tpp_requires_login").show();
						T._.hid = false;
					} else
						return;

					T._.state = 'initializing';

					// don't use fire() so we can increment ninit
					//
					// call an init first that will delay release so any fast releasing inits
					// will not cause premature ready status
					T.callInit( function(){setTimeout(T.releaseInit, 1);});
					for (var i in T.api.config.event['init']) {
						try {
							T.callInit( T.api.config.event['init'][i] );
						} catch (e) {
							console.log(e);
						}
					}
				}});
		},
		callInit : function (fn) {
			T._.ninit += 1;
			T.callback(fn);
		},

		/** Every function the is registered with on('init') MUST call releaseInit as it finishes. **/
		releaseInit : function () {
			T._.ninit -= 1;
			if (T._.ninit < 1) {
				setTimeout(function() {
					if (T._.state != 'ready') {
						jQuery(document).ready(function(){
							// only first to fire wins - first time I'm glad JS is single threaded
							if (T._.state != 'ready') {
								T._.state = 'ready';

								// on occasion we do not show the body until after the onReady is sent by jQuery
								// we need to setup vc pie chart since it wants things visible
								// jQuery('body').show();
								// if (window.vc_pieChart)
								// 	vc_pieChart();
								T.fire('ready');
							}
						});
					}
				},1);
			}
		},

		/** Stop the event. Really, please, for the love, stop. **/
		stopEvent: function(evt) {
			evt.preventDefault();
			evt.stopPropagation();
			evt.stopImmediatePropagation();
			// useful for calling at return of callee ... return TPPweb.stopEvent(evt);
			return false;
		},

		/**
		 * Called during startup to allow page to force redirect to login if user not logged in.
		 * @param {function} fn called during initialization. It takes no args and returns boolean if auth is required or string for required redirect url
		 */
		requiresAuth: function( level, fn ) {
			if (T._.state != 'verifying' && T._.state != 'initializing' && T._.state != 'loading') {
				T.verifyAuth({"level": level, "callback": fn});
			} else {
				T._.authfn = T._.authfn.concat({"level": level, "callback": fn});
			}
		},

		/** Called during initialization to force redirect if needed */
		verifyAuth: function(obj) {
			if ((!T.api.auth.loggedin || (T.api.auth.get_user_level() < obj.level)) && obj) {
				if (!T.isArrayLike(obj))
					obj = [obj];

				var verifying = true;
				jQuery.each(obj, function(i,c) {
					if (verifying) {
						var redir = c.callback.apply(c.callback);
						if (redir) {
							if(T.api.auth.loggedin && (T.api.auth.get_user_level() < obj.level)) {
								window.location = '/unauthorized';
								verifying = false;
							}else {
								window.location = '/login/' + ((redir!==true)?('?redirect_to='+redir):'/');
								verifying = false;
							}
						}
					}
				});
				return verifying;
			}
			return true;
		},

		/** Used to hide the body during startup until authentication status has been determined. */
		_hideBody: function(){
			// remove protocol, trim query params, remove hash, split into path pieces
			var path = document.documentURI.split('://').pop().split('?').shift().split('#').shift().split('/');

			if (path && (path.length > 2 || path[1] != '')) {
				try {
					T.util.addCSSRule( T.util.createStylesheet(), 'body', 'display:none', 0 );
				} catch (e) {
					console.log(e);
				}
			}
		},

		/** register an event listener **/
		on : function (eventname, fn) {
			if (eventname == 'init' && (T._.state == 'initializing' || T._.state == 'ready')) {
				T.callback(fn);
			} else if (eventname == 'ready' && T._.state == 'ready') {
				T.callback(fn);
			} else {
				T.api.on(eventname, fn);
			}
			return fn;
		},
		off: T.api.off,
		fire:T.api.fire,

		callback : T.api.callback,
		isArrayLike : T.api.isArrayLike
	});
	T.root = root;

	if (window) {
		var oldOnError = window.onerror;
		window.onerror = function(msg, url, linenumber, arg4){
			console.log('Error message: '+msg+'\nURL: '+url+'\nLine Number: '+linenumber, msg,url,linenumber,arg4);
			if (T._.hid) {
				try {
					T._init();
				} catch (e) {
					console.log(e);
				}
			}
			// alert('Error message: '+msg+'\nURL: '+url+'\nLine Number: '+linenumber);
			return true;
		}
	}

	T.on('ready', function(){

		// update the login link with a redirect so the user comes back to the page they started
		var login_link = jQuery('#menu-item-top-logn').find('a');
		if(login_link && login_link[0]) {
			login_link.prop('href', login_link.prop('href')+'?redirect_to='+window.location.pathname);
		}
	});
})();
/**
 * TPP website Authentication
 */
(function(){
	var root = ( typeof window === 'object' && window ) || this;
	root.console = root.console || {log: function(){}};

	var T = root.TPPweb = root.TPPweb || {};
	T.auth = T.auth || {};
	var A = T.auth = jQuery.extend(T.auth, {
		_profile : null,

		/**
		 * Is the current user logged in?
		 */
		isLoggedIn : function (options) {
			var cookie = false;
			var viaParam = false;
			if (!cookie) {
				// facebook login goes back and forth with API which redirects with param set.
				cookie = T.util.getQueryParam('access_token');
				viaParam = !!cookie;
			}
			if (!cookie)
				cookie = T.api.config.bearer;
			if (!cookie)
				cookie = T.util.readCookie('tpp');
			if (cookie) {
				if (viaParam) {
					var origSuccess = options.success;
					options = jQuery.extend({},options,{success:function(loggedin, expires) {
						if (loggedin) {
							T.api.config.bearer = cookie;
							var real_cookie = T.util.readCookie('tpp');
							if (expires && (!real_cookie || real_cookie != cookie)) {
								T.util.eraseCookie('tpp');
								T.util.createCookie('tpp', cookie, expires / (24 * 60 * 60));
							}
						}
						T.callback(origSuccess, [loggedin]);
						T.fire('login', [loggedin]);
					}})
				}
				T.api.auth.isLoggedIn( options, cookie, true );
			} else {
				T.callback(options.success, [false]);
			}
		},
		/**
		 * Get current user profile.
		 * @param  {object} options Options. force will force a reread from server, otherwise use a cached version if available
		 */
		userProfile : function (options) {
			var _options = jQuery.extend({
					force: false
				}, options);
			A.isLoggedIn(jQuery.extend(_options,
				{success: function(isLoggedIn){
						if (!isLoggedIn)
							A._profile = false;
						if (isLoggedIn && (_options.force || !A._profile)) {
							T.api.contacts.read( null, jQuery.extend({}, _options, {
								success: function(result) {
									if (result && result.status) {
										A._profile = result.data
									} else {
										A._profile = false;
									}
									T.callback(options.success, [A._profile]);
								}
							}));
						}
						else
							T.callback(options.success, [A._profile]);
					}
				}));
		},
		/**
		 * Mark profile invalid. Call when contact record is modified outside the normal API.
		 * @param {mixed} contact the contact modified. If it does not match then we won't invalidate. A false-like param will force invalidation. Param can also be profile object or string ID.
		 */
		invalidateProfile : function(contact) {
			if (contact && A._profile && A._profile.tpp_id != (contact.tpp_id || contact))
				return false;
			A._profile = false;
			return true;
		},
		/**
		 * Login user
		 * @param  {string}  username
		 * @param  {string}  password
		 * @param  {boolean} rememberme Increase cookie lifetime
		 */
		login : function(username, password, rememberme) {
			T.api.auth.login(username, password, rememberme, {
							data: {redirect_to: T.util.getQueryParam('redirect_to')},
							success: function(result) {
								var msg = "An error occurred. Please try again.";

								if (result && result.data.status == 'authenticated') {
									T.util.eraseCookie('tpp');
									T.util.createCookie('tpp', result.data.access_token, result.data.session_expires / (24 * 60 * 60));

									A._profile = result.data;
									T.fire('login', [true]);

									msg = '';

									if (result.data.redirect)
										document.location.href = result.data.redirect;
									else
										document.location.href = '/';
								}

								jQuery('.tppSpinner').hide();
								jQuery('#wp-submit').show();

								if (result && result.data.status == 'nologin') {
									swal({
										title: "Uh-Oh!",
										text: "Email or password is incorrect or not found.",
										type: "warning",
										showCancelButton: true,
										confirmButtonColor: "#DD6B55",
										confirmButtonText: "Let me try that again",
										cancelButtonText: "I've forgotten my password!",
										closeOnConfirm: true,
										closeOnCancel: false
									},
										function(isConfirm){
											if (isConfirm) {
												// do nothing but else only works this way
											} else {
												document.location.href = '/login/#fogot_password';
												location.reload();
											}
										}
									);
								}
								if (result && result.data.status == 'nologin-staff') {
									swal({title:"Oops!",
										text:   result.data.message,
										type:   'error',
									});
								}
								if (result && result.data.status == 'inactive') {
									//no password is associated to the account. The email for the user was stored but
									//the user has never registered with the site
									swal({
										title: "Complete Your Registration",
										text: "We need to you finish up your registration. Please fill out the form on the following page"
									},
										function() {
											document.location.href = "/register-now";
										}
									);
								}
							},
							error: function(jqXHR, textstatus, result) {

								jQuery('.tppSpinner').hide();
								jQuery('#wp-submit').show();

								var msg = "An error occurred. Please try again.";

								var alertbox = jQuery('#alert');
								alertbox.html(msg);
								alertbox.fadeIn();
							}
						});
		},
		/**
		 * Logout current user
		 */
		logout : function () {
			T.api.auth.logout({success: function(){
					A._profile = null;
					T.util.eraseCookie('tpp');
					T.fire('login', [false]);
					setTimeout(function(){window.location='/'},1);
				}, error: function(jqXHR, textStatus, errorThrown){
					console.log(jqXHR, textStatus, errorThrown);
					A._profile = null;
					T.util.eraseCookie('tpp');
					T.fire('login', [false]);
					setTimeout(function(){window.location='/'},1);
				}});
		},
		/**
		 * Reset a password for user with email.
		 */
		resetPassword : function (email) {
			T.api.auth.reset_password(email, {success:function(result){
				swal({
					title:"Thank You",
					text: result.message,
					html: true
				});
			}});
			return false;
		}
	});

	/*
	 * On contact record update let us invalidate the profile record
	 */
	T.on('model_beforeupdate', function(modelname, cid, options){
		if (modelname=='contacts') {
			A.invalidateProfile(cid);
		}
	});

	/*
	 * Member Login Page
	 */
	T.on('ready', function(){
		function showResetPasswordForm() {
			jQuery('#password-section').hide();
			jQuery('#rememberme-section').hide();
			jQuery('#forgot-password').hide();
			jQuery('#signin-section').hide();
			jQuery('#loginform-text').hide();
			jQuery('#reset-section').show();
			reset = true;
		}
		var memberlogin = jQuery('#member-login');
		if (memberlogin && memberlogin[0]) {

			// manage switching login <--> reset
			var reset = false;
			jQuery('#reset-section').hide();
			jQuery('#forgot-password').click(showResetPasswordForm);
			jQuery('#recover-password').click(function(){
				jQuery('#password-section').show();
				jQuery('#rememberme-section').show();
				jQuery('#forgot-password').show();
				jQuery('#signin-section').show();
				jQuery('#loginform-text').show();
				jQuery('#reset-section').hide();
				reset = false;
			});
			if(window.location.hash === '#forgot_password'){
				showResetPasswordForm();
			}

			jQuery('#facebookbutton').click(function(evt){
				document.location.href = TPPapi.config.host+'/v1/auth/facebook?client_id='+TPPapi.config.apikey;
				if(T.util.getQueryParam('redirect_to') !== null){
					document.location.href = TPPapi.config.host+'/v1/auth/facebook?client_id='+TPPapi.config.apikey+'&redirect_to='+T.util.getQueryParam('redirect_to');
				}
				evt.preventDefault();
				evt.stopPropagation();
				evt.stopImmediatePropagation();
				return false;
			});

			jQuery('#wp-submit').on('click', function(evt){
				console.log('login submit clicked');

				jQuery('#wp-submit').hide();
				jQuery('#signin-section').addClass('spinner');
				T.data.spinnerDom = jQuery('.spinner');
				T.data.createSpinner(T.data.spinnerDom[0]);

				T.auth.login(jQuery('#member-login #username').val(),
							jQuery('#member-login #password').val(),
							jQuery('#rememberme')[0].checked);
				evt.preventDefault();
				evt.stopPropagation();
				evt.stopImmediatePropagation();
				return false;
			});
			jQuery('#wp-recover').click(function(evt){
				evt.preventDefault();
				evt.stopPropagation();
				evt.stopImmediatePropagation();

				return A.resetPassword( jQuery('#member-login #username').val() );
			});

			// Keep the default submit from occurring
			jQuery('#loginform').submit(function(evt){
				evt.preventDefault();
				evt.stopPropagation();
				evt.stopImmediatePropagation();
				return false;
			});

			// if we are logged in and a redirect param is set, then go there
			T.auth.isLoggedIn({success:function(loggedin){
				if (loggedin) {
					var redir = T.util.getQueryParam('redirect_to');
					if (redir)
						document.location.href = redir;
				}
			}});
		}
	});

	/*
	 *  All pages' top user menu
	 */
	var setBodyLoginStyle = function(loggedin) {
		console.log('loggedin ',loggedin);
		if (loggedin) {
			jQuery('body').removeClass('tpp-logged-out').addClass('tpp-logged-in');
		} else {
			jQuery('body').removeClass('tpp-logged-in').addClass('tpp-logged-out');
		}
	};
	T.on('login', setBodyLoginStyle);

	/*
	 * We want to set this style VERY early.
	 * Using on('init'...) used to be late enough but not always.
	 */
	T.on('init', function(){
		A.isLoggedIn({success: function(loggedin){
			setBodyLoginStyle(loggedin);
		}});
		T.releaseInit();
	});
	T.on('ready', function(){

		// if on init is too early, then this should catch it
		setTimeout(function(){
			A.isLoggedIn({success: function(loggedin){
				setBodyLoginStyle(loggedin);
			}});
		},151);
		setTimeout(function(){
			A.isLoggedIn({success: function(loggedin){
				setBodyLoginStyle(loggedin);
			}});
		},771);

		// watch for logout
		jQuery('.menu-item-lout').click(function(evt){
			try {
				A.logout();
				evt.preventDefault();
				evt.stopPropagation();
				evt.stopImmediatePropagation();
			} catch (ex) {
				window.location.reload();
			}
			return false;
		});
	});

})();
/**
 *
 */
(function(){
    var root = ( typeof window === 'object' && window ) || this;
    var T = root.TPPweb = root.TPPweb || {};
    T.data = T.data || {};
    var D = T.data = jQuery.extend(T.data, {
        handlers : {},
        /**
         * Create a handler that manages a DOM element
         * @param  {string}  name    unique name - at least unique for lifespan of this page
         * @param  {mixed}   dom     jQuery object, DOM element, or string ID
         * @param  {object}  options overrides handler options
         */
        createHandler: function (name, dom, options) {
            if (D.handlers[name])
                throw ('Data handler exists for '+name);
            D.handlers[name] = jQuery.extend(new Object(), {
                dom     : null,
                fragment: null,
                template: null,
                name    : null,
                options : { bars_attr         : 'tpp-bars',		// <div tpp-bars="groups"><img tpp-model="groups.N.groupimg" /></div>
                    model             : null,			// simple model to use or handle onModelGet()
                    onGetFragment     : null,			// called to get HTML template fragment    function( handlername ) -> return text
                    onGetTemplate     : null,			// called to get compiled template         function( handlername, currentfragmant ) -> return handlebars compliant template
                    handlebarsOptions : {}              // allows passing handlebars options to the compile function
                },

                /** Initializes object. Called on createHandler() **/
                init : function (dom, options) {
                    if ((typeof dom) == 'string')
                        dom = jQuery('#'+dom);
                    else if (T.isArrayLike(dom) && dom.length)
                        dom = jQuery(dom[0]);
                    else
                        dom = jQuery(dom);
                    if (dom && dom[0])
                        this.dom = dom[0];
                    else
                        throw ('Trying to use something which is not a DOM element as a DataHandler: '+name);

                    if (this.dom._tpp_data)
                        throw ('Trying to reregister a DOM element under a different name: '+name);

                    this.dom._tpp_data = this.name = name;

                    if (options) {
                        this.options = jQuery.extend({}, this.options, options);
                    }

                    if (this.options.model)
                        this.process();

                    return this;
                },

                /** @return HTML fragment to process **/
                getFragment: function() {
                    if (this.options.onGetFragment)
                        return this.options.onGetFragment(this.name);
                    if(this.dom.id) {
                        var template = jQuery(this.dom).find('#' + this.dom.id + '-template');
                        if(template && template[0]) {
                            return template.html();
                        }
                    }
                    return jQuery(this.dom).html();
                },

                /** @return Handlebars template to process **/
                getTemplate: function() {
                    if (this.options.onGetTemplate)
                        return this.options.onGetTemplate(this.name, this.fragment);
                    return Handlebars.compile(this.fragment, this.options.handlebarsOptions);
                },

                /** Process the template, placing it in the document with a model
                 *  @param {object} template Optional: Handlebars template to process. Default is to obtain from current DOM element and replace.
                 **/
                process: function(template) {
                    if (!template) {
                        if (!this.fragment) {
                            this.fragment = this.getFragment();
                        }
                        if (!this.template) {
                            this.template = this.getTemplate();
                        }
                        template = this.template;
                    }
                    var jqo = jQuery(this.dom);
                    jqo.html('');
                    jqo.append( template(this.options.model) );
                    jqo.removeClass('tppTemplate');
                    jqo.find('.tppTemplate').removeClass('tppTemplate');
                },

                /** @return The handled DOM **/
                getDom : function () {
                    return this.dom;
                },

                getModel: function() {
                    return this.options.model;
                },
                setModel: function(model) {
                    this.options.model = model;
                }
            });
            return D.handlers[name].init(dom, options);
        },

        /** Manages a FORM element
         * @param  {string}  name    unique name - at least unique for lifespan of this page
         * @param  {mixed}   form    jQuery object, DOM element, or string ID
         * @param  {object}  options overrides handler options
         **/
        createFormHandler : function (name, form, options) {
            if (D.handlers[name])
                throw ('Form handler exists for '+name);

            D.handlers[name] = jQuery.extend(new Object(),{
                form : null,
                name : null,
                spin : null,
                tempdisabled : null,
                options : { model_attr : 'tpp-model',   // <input type='text' tpp-model="profile.fname" tpp-options="required:true"/>
                    option_attr: 'tpp-options',
                    root_dom   : null,
                    spin_root  : null,
                    field_defaults : {},
                    ignore_nodes   : ['CANVAS'],
                    edit_nodes : ['INPUT','SELECT','TEXTAREA'],
                    force_model_attr : false,   // any edit_nodes with no model_attr will be ignored if true, else use name attr as model_attr
                    fields     : [],			// elements that have a model attribute inside this form
                    model      : {},			// simple model to use or handle onModelGet()
                    onSubmit   : null,			// callback on submit               function( formname, event, options )
                    onValidate : null,			// callback on validate             function( formname, modelname, value ) -> return true or error string
                    onError    : null,			// callback on error                function( formname, type [validate|submit], message ) -> return true to continue processing
                    onModelGet : null,			// called to get data               function( formname, modelname, options ) -> return value
                    onModelSet : null,			// called to set data               function( formname, modelname, value, options ) -> return true on success, false to revert (must handle own user notification of error)
                    onChange   : null,			// called when form element changed function( formname, modelname, el, event, value ) -> return as for jQuery
                    spinner    : {} 			// override default spinner options
                },
                // inputMap : {},
                // outputMap : {},

                _param_to_dom : function(param) {
                    var jq = null;
                    if (!param)
                        return jq;
                    if ((typeof param) == 'string')
                        jq = jQuery('#'+param);
                    else if (T.isArrayLike(param) && param.length)
                        jq = jQuery(param[0]);
                    else
                        jq = jQuery(param);
                    return jq;
                },

                /** Initializes object. Called on createHandler() **/
                init : function (form, options) {
                    form = this._param_to_dom(form);
                    if (form && form[0] && form[0].nodeName=="FORM")
                        this.form = form[0];
                    else
                        throw ('Trying to use something which is not a form as a FormHandler: '+name);

                    if (this.form._tpp_data)
                        throw ('Trying to reregister a form under a different name: '+name);

                    this.form._tpp_data = this.name = name;

                    if (options) {
                        this.options = jQuery.extend({}, this.options, options);
                    }

                    if (this.options.root_dom) {
                        this.options.root_dom = this._param_to_dom(this.options.root_dom);
                    } else {
                        this.options.root_dom = jQuery(this.form);
                    }

                    if (this.options.spin_root) {
                        this.options.spin_root = this._param_to_dom(this.options.spin_root);
                    } else {
                        this.options.root_dom = jQuery(this.options.root_dom);
                    }

                    this.pause();

                    this.initFields();

                    var thatform = this;

                    jQuery(this.form).submit(this, function(evt){
                        T.stopEvent(evt);
                        return thatform.processFormAndSubmit(thatform);
                    });

                    return this;
                },
                processFormAndSubmit: function(form) {
                    var options = form.options;
                    var validate = function(m,v){return form.validate(m,v, true);};
                    for (var i in options.fields) {
                        for (var j in options.fields[i]) {
                            var fld = options.fields[i][j];
                            var jqo = jQuery(fld.dom);
                            var msg;

                            var fldOptions = fld.options;
                            if (!fldOptions || !fldOptions.readonly) {

                                msg = validate(fld.name, fld.get());
                                if (msg !== true)
                                    return false;

                                form.setValue(fld.getPostName(), fld.get(), false);
                            }
                        }
                    }
                    if (form.options.onSubmit)
                        return form.options.onSubmit( form.name, form.options );
                    return true;
                },

                /** @return This managed form DOM */
                getForm : function () {
                    return this.form;
                },

                /** Show a disabled form. **/
                pause: function() {
                    var that = this;
                    this.tempdisabled = this.tempdisabled || [];

                    var jform = this.options.root_dom;
                    this.form._tpp_opacity = this.form._tpp_opacity || jform.css('opacity');
                    jform.css('opacity', 0.8);

                    this.spin = T.data.createSpinner(this.options.spin_root, this.options.spinner);

                    jform.find(":input").each(function(n,el){
                        var jqo = jQuery(el);
                        if (!jqo.prop('disabled')) {
                            var elid = jqo[0].id;
                            if ((typeof elid == "undefined") || !elid) {
                                elid = "tpp-gen-"+(Date.now()%1000000);
                                jqo.attr("id",elid);
                            }
                            that.tempdisabled[that.tempdisabled.length] = jqo[0].nodeName+'#'+elid;
                            jqo.prop('disabled', true);
                        }
                    });
                },

                /** Reenable the form after pause **/
                resume: function() {
                    var jform = this.options.root_dom;
                    var opacity = this.form._tpp_opacity || 1.0;
                    jform.css('opacity', opacity);
                    this.form._tpp_opacity = null;

                    if (this.tempdisabled && this.tempdisabled.length) {
                        for (var i in this.tempdisabled) {
                            jQuery(this.tempdisabled[i]).prop('disabled', false);
                        }
                        this.tempdisabled = null;
                    }
                    if (this.spin) {
                        this.spin.stop();
                        this.spin = null;
                    }
                },

                getFields : function () {
                    return this.options.fields;
                },

                /** @return The contained fields */
                initFields : function () {
                    var that = this;
                    this.options.root_dom.find('*').each(function(n, obj){
                        var node= obj.nodeName;

                        if (jQuery.inArray(node, that.options.ignore_nodes) >= 0)
                            return;

                        var jqo = jQuery(obj);

                        var fldname = jqo.attr(that.options.model_attr);

                        if (jQuery.inArray(node, that.options.edit_nodes) >= 0) {
                            if (!fldname && !that.options.force_model_attr)
                                fldname = jqo.attr('name');
                        }

                        if (fldname) {
                            T.dataField.get(that, obj, fldname);
                        }
                    });
                },

                /** Set the form model.
                 *  This also sets all fields' values.
                 */
                setModel: function(modelobj) {
                    this.options.model = modelobj;
                    var that = this;
                    var findFld = function(obj, prefix) {
                        for (var i in obj) {
                            var name = prefix+i;
                            if (T.isArrayLike(obj[i])) {
                                findFld(obj[i], name+'.');
                            }
                            if (that.options.onModelSet) {
                                that.options.onModelSet(that.name, name, obj[i], that.options);
                            } else {
                                for (var j in that.options.fields[name]) {
                                    that.options.fields[name][j].set(obj[i]);
                                }
                            }

                            // that.setValue(prefix+i, obj[i], true);
                        }
                    }
                    findFld(modelobj, '');

                    this.resume();
                },

                /** @return The current Model **/
                getModel: function(modelname) {
                    if (!modelname)
                        return this.options.model;
                    if (this.options.onModelGet)
                        return this.options.onModelGet(this.name, modelname, this.options);

                    // model.name[foo] is really model.name.foo
                    if (modelname.indexOf('[') >0) {
                        modelname = modelname.replace('[','.').replace(']','');
                    }

                    // Set the model to the specified value. Recursively applies dotted notation
                    //    model = {name:{first:'Dave', last:'Smith'}}
                    //    myForm.setValue('name.last', 'Jones', x) will set the model[name][last] value
                    var names = modelname.split('.');

                    // force a container type .. looses old info
                    if (names.length > 1) {
                        var type = typeof this.options.model[names[0]];
                        if ( type=='undefined' || (type != 'object' && type != 'array'))
                            this.options.model[''+names[0]] = {};
                    }

                    var o = this.options.model;

                    for (var i=0; i<names.length-1; i++) {
                        o = o[''+names[i]];
                    }
                    return o[''+names[i]];
                },

                /** Set the value of a field.
                 * @param {string}  modelname  The model name, dotted notation for nested object.
                 * @param {mixed}   value      The new value
                 * @param {boolean} set_field  Default true, set false to disable setting fields with the new value
                 */
                setValue: function(modelname, value, set_field) {
                    if (this.options.onModelSet)
                        return this.options.onModelSet(this.name, modelname, value, this.options);

                    if (modelname.indexOf('[') >0) {
                        modelname = modelname.replace('[','.').replace(']','');
                    }

                    // Set the model to the specified value. Recursively applies dotted notation
                    //    model = {name:{first:'Dave', last:'Smith'}}
                    //    myForm.setValue('name.last', 'Jones', x) will set the model[name][last] value
                    var names = modelname.split('.');

                    // force a container type .. looses old info
                    if (names.length > 1) {
                        var type = typeof this.options.model[names[0]];
                        if ( type=='undefined' || (type != 'object' && type != 'array'))
                            this.options.model[''+names[0]] = {};
                    }

                    var o = this.options.model;

                    for (var i=0; i<names.length-1; i++) {
                        o = o[''+names[i]];
                    }
                    o[''+names[i]] = value;

                    // for (i in names) {
                    // 	o = o[names[i]];
                    // }
                    // o = value;

                    // set the value of a field to the model change
                    if (set_field !== false) {
                        for (i in this.options.fields[modelname]) {
                            this.options.fields[i].set(value);
                        }
                    }
                },

                /** Validate a field **/
                validate: function(modelname, value, report_error) {
                    var msg = true;
                    if (this.options.onValidate) {
                        msg = this.options.onValidate(this.name, modelname, value);
                    }
                    if (msg !== true && report_error) {
                        if (options.onError && options.onError(evt.data.name, 'validate', msg)) {
                            return true;
                        } else if (!options.onError) {
                            alert(msg);
                        }
                    }
                    return msg;
                },

                /** Force submit a form **/
                submit : function() {
                    this.processFormAndSubmit(this);
                }
                // setMapping : function (input, output) {
                // 	if (!output)
                // 		output = input;

                // 	this.inputMap = jQuery.extend
                // }
            });
            return D.handlers[name].init(form, options);
        },

        /** @return The named handler. */
        getHandler : function (name) {
            if (!D.handlers[name])
                return false;
            return D.handlers[name];
        },

        /** Remove the named handler. */
        removeHandler : function (name) {
            if (!D.handlers[name])
                return false;
            delete D.handlers[name];
            jQuery('#'+name)[0]._tpp_data = null;
            return true;
        },

        /** Create a spinner on an element
         *  @param {DOM}    el      Element to have spinner
         *  @param {object} options Optional option overrides
         */
        createSpinner: function(el, options) {
            var opts = jQuery.extend({},{
                lines: 11, // The number of lines to draw
                length: 8, // The length of each line
                width: 3, // The line thickness
                radius: 15, // The radius of the inner circle
                corners: 1, // Corner roundness (0..1)
                rotate: 0, // The rotation offset
                direction: 1, // 1: clockwise, -1: counterclockwise
                color: '#000', // #rgb or #rrggbb or array of colors
                speed: 0.6, // Rounds per second
                trail: 62, // Afterglow percentage
                shadow: false, // Whether to render a shadow
                hwaccel: false, // Whether to use hardware acceleration
                className: 'spinner', // The CSS class to assign to the spinner
                zIndex: 2e9, // The z-index (defaults to 2000000000)
                top: '50%', // Top position relative to parent
                left: '50%', // Left position relative to parent
                additional_style: ''
            }, options);
            // return new Spinner(opts).spin(el);
            return new (function(el, opts){
                this.el = el;
                this.spin = function() {
                    jQuery(this.el).prepend(
                        "<div class='tppSpinner' style='"+
                        (((opts || {}).additional_style !== "") ? opts.additional_style : '') +
                        //'position: absolute;'+
                        'background: rgba(255,255,255,0.8);'+
                        'width: 100%;'+
                        'height: 100%;'+
                        'left: 0;'+
                        'right: 0;'+
                        'top: 0;'+
                        'bottom: 0;'+
                        "z-index: 2000000;'>" +
                        ((typeof (opts || {}).text !== "undefined") ? '<h3 style="text-align:center;font-size:35px;">' + opts.text + '</h3>' : '') +
                        "<img src='//d3b5g5w8iutjdd.cloudfront.net/images/loadwait.gif' style='margin:20px 45%'/></div");
                    return this;
                };
                this.stop = function() {
                    jQuery(this.el).find('.tppSpinner').remove();
                    return this;
                };
            })(el, opts).spin();
        }

    });

})();
/**
 *
 */
(function(){
    var root = ( typeof window === 'object' && window ) || this;
    var T = root.TPPweb = root.TPPweb || {};
    T.dataField = T.dataField || {};
    var D = T.dataField = jQuery.extend(T.dataField, {
        get: function(formHandler, el, fldname) {
            var commonName = fldname.replace('[]','');

            var fields = formHandler.getFields();

            fields[commonName] = fields[commonName] || [];
            var fldIndex = fields[commonName].length;

            // map jquery obj to DOM
            if (el && !el.nodeName && el.length)
                if (el.length)
                    el = el[0];
                else
                    return null;
            if (!el)
                return null;

            // see if this DOM is already in the form fields, use it
            for (i in fields[commonName]) {
                if (fields[commonName][i].dom === el)
                    return fields[commonName][i];
            }

            // new to me, create a handler
            var fld = fields[commonName][fldIndex] = new DataField(formHandler, el, fldname, commonName, fldIndex);

            fld.el.change(fld, function(evt){
                var form = evt.data.form;
                if (form.options.onChange) {
                    return form.options.onChange(form.name, evt.data.name, evt.data.dom, evt, evt.data.get());
                }
            });


        }
    });

    var DataField = function(formHandler, el, fldname, commonName, fldIndex) {
        this.dom        = el;
        this.name       = fldname,
            this.commonName = commonName,
            this.fldIndex   = fldIndex,

            this.el         = jQuery(el);
        this.form       = formHandler;

        this.nodeName   = this.dom.nodeName;

        // gather all the places that specify options for fields and this field
        this.options    = jQuery.extend(
            {},
            // defaults
            {	readonly:  true,
                arrayjoin: ';',
                flatarray: false,
                setters:   {'INPUT, SELECT, TEXTAREA': this._setInput,
                    'IMG':                     this._setImg,
                    'DIV.vc_pie_chart':        this._setPie }
            },

            // form specified (or from caller)
            this.form.options.field_defaults,

            // field specified
            {	isarray:  fldname.indexOf('[]') >0,
                truval:   this.el.attr('value') || 'on',
                flatarray:fldname.indexOf('[]') > 0,
            },
            this.el.attr(this.form.options.option_attr) );

        // edit nodes can determine for theirself if they are readonly
        if (jQuery.inArray(this.nodeName, this.form.options.edit_nodes) >= 0) {
            this.options.readonly = this.el.attr('readonly');
        }

        // not an edit field or other known type, set the DOM inner text to value
        this._setter = function(val) {
            this.el.html(val);
        }

        // find an appropriate better setter method
        for (i in this.options.setters) {
            if ( this.el.is( i ) ) {
                this._setter = this.options.setters[i];
                break;
            }
        }

    };

    DataField.prototype = {
        getRawName: function() {
            return this.name;
        },

        getCommonName: function() {
            return this.commonName;
        },

        getPostName: function() {
            return this.getCommonName() + (this.options.isarray && !this.options.flatarray
                ? ( '['+ this.fldIndex +']' )
                : '');
        },

        // get field value
        get:  function() {
            var val = null;

            if ((this.el.attr('type') != 'checkbox' && this.el.attr('type') != 'radio'))
                val = this.el.val();
            else
                val = this.dom.checked ? this.options.truval : false;

            // for flatarrays we consider the value to be all parts this field represents
            if (this.options.flatarray) {
                // get the current array
                var v = this.form.getModel(this.getCommonName());
                var on = val === this.options.truval;
                var pos = -1;

                // split it by the separator
                if (v) {
                    v = v.split(this.options.arrayjoin);
                    pos = v.indexOf(this.options.truval);
                }

                if (!on) {
                    // remove this truval since it is not checked
                    if (pos>=0)
                        v.splice(pos,1);
                } else {
                    v = v || []; // initialize empty array
                    if (pos<0)
                        v[v.length] = val;
                }

                if (v)
                    val = v.join(this.options.arrayjoin);
            }
            return val;
        },

        // set field value
        set:  function(val) {
            if(val === null) {
                this._setter(val, false);
                return;
            }
            var thatfld = this;
            var thatval = false;

            // if this is an array post field
            if (this.options.isarray) {
                if (this.options.flatarray) {

                    // split it by the separator
                    var v = val.split(this.options.arrayjoin);
                    var pos = v.indexOf(this.options.truval);

                    if (pos >= 0)
                        val = this.options.truval;
                    else
                        val = false;

                    thatval = val === this.options.truval;
                } else {
                    if (T.isArrayLike(val))
                        // array-like values should have one entry per selected that matches truval
                        jQuery(val).each(function(i,o){
                            if (o==thatfld.options.truval)
                                thatval = true;
                        });
                    else
                        thatval = val == this.options.truval;
                }
            }
            else
                thatval = val == this.options.truval;

            this._setter(val, thatval);
        },

        // setter for normal form inputs
        _setInput : function(val, checked) {

            if (this.el.attr('type') == 'checkbox' || this.el.attr('type') == 'radio') {
                // checkbox and radio are not consistent :(
                //
                this.dom.checked = checked;
            } else {
                this.el.val(val);
            }
        },

        // setter for Visual Composer Pie Chart
        _setPie : function(val, checked) {
            // Divide by 100 to turn a percentage into a proper fractional
            //
            // BUT do we need to specify this behavior to accomodate other charts?
            //
            this.el.data('vc_chart').value = val / 100;

            this.el.data('vc_chart').label_value = val;

            this.el.data('vc_chart').draw(true);
        },

        // setter for plain image
        _setImg: function(val) {
            this.el.attr('src', val);
        }
    };



})();
(function(){
	var root = ( typeof window === 'object' && window ) || this;
	root.console = root.console || {log: function(){}};

	var T = root.TPPweb = root.TPPweb || {};
	T.util = T.util || {};
	var U = T.util = jQuery.extend(T.util, {
		/** Read a cookie. Seems to only get the first occurance.  */
		readCookie : function(name) {
			return decodeURIComponent( (document.cookie.match('(^|; )'+name+'=([^;]*)')||0)[2] );
		},
		/** Create a cookie. Does not replace existing. */
		createCookie : function (name, value, days) {
		    var expires;

		    if (days) {
		        var date = new Date();
		        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
		        expires = "; expires=" + date.toGMTString();
		    } else {
		        expires = "";
		    }
		    var host = T.config.host.split('//', 2)[1];
		    var domain = host.split('/')[0];
		    var cookie = escape(name) + "=" + escape(value) + expires + "; path=/";

		    document.cookie = cookie + '; domain=.teapartypatriots.org';
		    if (value == '') {
			    document.cookie = cookie;
			    document.cookie = cookie + '; domain='+domain;
			}
		},
		/** Erase a cookie. Does not remove from the list but will superseded. */
		eraseCookie : function (name) {
		    U.createCookie(name, "", -1);
		},
		/** Get a query param value */
		getQueryParam: function (name) {
			var qry = document.location.search;
			if (qry && qry[0] == '?')
				qry = qry.substring(1);
			if (qry) {
				qry = qry.split('&');
				for (q in qry) {
					var param = qry[q].split('=');
					if (param[0] == name)
						return decodeURIComponent(param[1]);
				}
			}
			return null;
		},
		/** Get state's long name from 2-letter abbreviation */
		getStateName: function(stateCode) {
			states = {
				'AL': 'Alabama',
				'AK': 'Alaska',
				'AZ': 'Arizona',
				'AR': 'Arkansas',
				'CA': 'California',
				'CO': 'Colorado',
				'CT': 'Connecticut',
				'DE': 'Delaware',
				'DC': 'District of Columbia',
				'FL': 'Florida',
				'GA': 'Georgia',
				'HI': 'Hawaii',
				'ID': 'Idaho',
				'IL': 'Illinois',
				'IN': 'Indiana',
				'IA': 'Iowa',
				'KS': 'Kansas',
				'KY': 'Kentucky',
				'LA': 'Louisiana',
				'ME': 'Maine',
				'MD': 'Maryland',
				'MA': 'Massachusetts',
				'MI': 'Michigan',
				'MN': 'Minnesota',
				'MS': 'Mississippi',
				'MO': 'Missouri',
				'MT': 'Montana',
				'NE': 'Nebraska',
				'NV': 'Nevada',
				'NH': 'New Hampshire',
				'NJ': 'New Jersey',
				'NM': 'New Mexico',
				'NY': 'New York',
				'NC': 'North Carolina',
				'ND': 'North Dakota',
				'OH': 'Ohio',
				'OK': 'Oklahoma',
				'OR': 'Oregon',
				'PA': 'Pennsylvania',
				'RI': 'Rhode Island',
				'SC': 'South Carolina',
				'SD': 'South Dakota',
				'TN': 'Tennessee',
				'TX': 'Texas',
				'UT': 'Utah',
				'VT': 'Vermont',
				'VA': 'Virginia',
				'WA': 'Washington',
				'WV': 'West Virginia',
				'WI': 'Wisconsin',
				'WY': 'Wyoming'
			};
			return states[stateCode] || false;
		},

		createStylesheet : function() {
			// Create the <style> tag
			var style = document.createElement("style");

			// Add a media (and/or media query) here if you'd like!
			// style.setAttribute("media", "screen")
			// style.setAttribute("media", "only screen and (max-width : 1024px)")

			// WebKit hack :(
			style.appendChild(document.createTextNode(""));

			// Add the <style> element to the page
			document.head.appendChild(style);

			return style.sheet;
		},
		addCSSRule : function( sheet, selector, rules, index ) {
			if("insertRule" in sheet) {
				sheet.insertRule(selector + "{" + rules + "}", index);
			} else if("addRule" in sheet) {
				sheet.addRule(selector, rules, index);
			}
		},
		randomString: function(string_length) {
			var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz";
			var randomstring = '';
			for (var i=0; i<string_length; i++) {
				var rnum = Math.floor(Math.random() * chars.length);
				randomstring += chars.substring(rnum,rnum+1);
			}
			return randomstring;
		},
		getPrimary: function(object) {
			if(!object || object == undefined) return;
			for (var i = object.length - 1; i >= 0; i--) {
				if((object[i] || {}).is_primary) {
					return object[i];
				}
			};
		},
		/**
			lpad(10, 4);      // 0010
			lpad(9, 4);       // 0009
			lpad(123, 4);     // 0123
		 */
		lpad: function(n, width, z) {
			z = z || '0';
			n = n + '';
			return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
		},

		prettyPhone: function(phone) {
			// strip all non numerics and then format
			if (!phone) return '';

			return phone.replace( /[^\d]/g, '')
						.replace( /(\d{3})(\d{3})(\d{4})/, '($1) $2-$3');

		},
		prettyAddress: function(address_obj) {
			if(typeof address_obj !== 'object') return '';
			var addr_string =   (address_obj.street1 ? address_obj.street1 + ' '  : '') +
								(address_obj.street2 ? address_obj.street2 + ' '  : '') +
								(address_obj.street3 ? address_obj.street3 + ' '  : '') +
								(address_obj.city 	 ? address_obj.city    + ', ' : '') +
								(address_obj.state   ? address_obj.state   + ' '  : '') +
								(address_obj.zip 	 ? address_obj.zip 		      : '') +
								(address_obj.zip4 	 ? '-' + address_obj.zip4     : '');
			return addr_string;
		},
		/**
		 * Return a timestamp with the format "m/d/yy h:MM:ss TT"
		 * @type {Date}
		 */
		prettyTime: function(datetime) {
			console.warn('[TPP] **** You should switch to using Moment.js instead of this prettyTime utility ****');

			// Create a date object with the current time
			var now = new Date(datetime);

			// Create an array with the current month, day and time
			var date = [ now.getMonth() + 1, now.getDate(), now.getFullYear() ];

			// Create an array with the current hour, minute and second
			var time = [ now.getHours(), now.getMinutes() ];

			// Determine AM or PM suffix based on the hour
			var suffix = ( time[0] < 12 ) ? "AM" : "PM";

			// Convert hour from military time
			time[0] = ( time[0] < 12 ) ? time[0] : time[0] - 12;

			// If hour is 0, set it to 12
			time[0] = time[0] || 12;

			// If seconds and minutes are less than 10, add a zero
			for ( var i = 1; i < 3; i++ ) {
				if ( time[i] < 10 ) {
					time[i] = "0" + time[i];
				}
			}

			// Return the formatted string
			return date.join("/") + " " + time.join(":") + " " + suffix;

		}

	});
})();
/**
 * A collection of Handlebars JS helpers for use when templating
 */

(function(){
	var root = ( typeof window === 'object' && window ) || this;
	var T = root.TPPweb = root.TPPweb || {};

	T.on('init', function(){

		Handlebars.registerHelper({
			// {{#ifCond var1 '==' var2}}
			ifCond: function (v1, operator, v2, options) {
				switch (operator) {
					case '==':
						return (v1 == v2) ? options.fn(this) : options.inverse(this);
					case '===':
						return (v1 === v2) ? options.fn(this) : options.inverse(this);
					case '<':
						return (v1 < v2) ? options.fn(this) : options.inverse(this);
					case '<=':
						return (v1 <= v2) ? options.fn(this) : options.inverse(this);
					case '>':
						return (v1 > v2) ? options.fn(this) : options.inverse(this);
					case '>=':
						return (v1 >= v2) ? options.fn(this) : options.inverse(this);
					case '&&':
						return (v1 && v2) ? options.fn(this) : options.inverse(this);
					case '||':
						return (v1 || v2) ? options.fn(this) : options.inverse(this);
					case 'strcasecmp':
						if (v1 === undefined || v2 === undefined) return options.inverse(this);
						return (v1.toLowerCase() === v2.toLowerCase()) ? options.fn(this) : options.inverse(this);
					default:
						return options.inverse(this);
				}
			},

			// 2014-12-04 -> December 2014
			LongMonthAndYear: function(date) {
				var monthNames = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ];
				var properDate = new Date(date);
				return new Handlebars.SafeString(monthNames[properDate.getMonth()] + ' ' + properDate.getFullYear());
			},

			// John Doe -> John D
			FirstNameLastInitialFromFullName: function(name) {
				var name_parts = name
								? name.split(/[ ]/)
								: ['',''];
				var fname = name_parts[0] ||'';
				var lname = name_parts[1]?(name_parts[1][0]||''):'';
				return new Handlebars.SafeString(fname + ' ' + lname);
			},

			// John Doe -> John D
			FirstNameLastInitialFromNameParts: function(firstname, lastname) {
				var fname = firstname
							? firstname.charAt(0).toUpperCase() + firstname.slice(1)
							: '';
				var lname = lastname
							? lastname.charAt(0).toUpperCase()
							: '';
				return new Handlebars.SafeString(fname + ' ' + lname);
			},

			// given a users memberships array, determines if they are a member of the passed group
			IfMemberOfThisGroup: function(memberships, group_id, options) {
				var member = false;
				for (var i = memberships.length - 1; i >= 0; i--) {
					if(memberships[i].tpp_id === group_id) {
						member = true;
						break;
					}
				}

				if (member) {
					return options.fn(this);
				}
				else {
					return options.inverse(this);
				}
			},
			IfAdminOfThisGroup: function(memberships, group_id, options) {
				var admin = false;
				for (var i = memberships.length - 1; i >= 0; i--) {
					if(memberships[i].tpp_id === group_id && (memberships[i].role.indexOf('Coordinator') > -1)) {
						admin = true;
						break;
					}
				}

				if (admin) {
					return options.fn(this);
				}
				else {
					return options.inverse(this);
				}
			},
			// we require group information to be updated/validated every XX number of days.
			// this determines if we show the validation button
			ShowValidateInfoButton: function(days, last_modified, local_coordinators, cid, options) {
				if(local_coordinators === undefined || local_coordinators === null) {
					return options.inverse(this);
				}
				for (var i = local_coordinators.length - 1; i >= 0; i--) {
					if(local_coordinators[i].tpp_id !== undefined && cid !== undefined && local_coordinators[i].tpp_id === cid){
						// if we don't have last_modified date, always show it.
						if(last_modified === undefined)
						{
							return options.fn(this);
						}

						var now = new Date();
						var then = new Date(last_modified);

						if(then.setDate(then.getDate() + days) < now) {
							return options.fn(this);
						}
						else {
							return options.inverse(this);
						}
					}
				}
				return options.inverse(this);
			},

			IfLocalCoordiantorOrAbove: function(options) {
				// TPPweb.auth._profile.auth_role
				if((((TPPweb || {}).auth || {})._profile || {}).auth_role > 2) {
					return options.fn(this);
				}
				else {
					return options.inverse(this);
				}
			},
			// builds the search for google maps use
			GoogleMapSearch: function(group) {

				var map_search = 'usa';
				var map_zoom = "zoom=3";

				var primary_addresss = TPPweb.util.getPrimary(group.addresses);

				if(primary_addresss !== undefined && primary_addresss !== null) {
					if((primary_addresss.latitude !== undefined && primary_addresss.latitude !== '') && (primary_addresss.longitude !== undefined && primary_addresss.longitude !== '')){
						map_search = primary_addresss.latitude + ',' + primary_addresss.longitude;
						//alert(primary_addresss.street1);
						//alert(primary_addresss.city);
						//alert(jQuery('.vc_custom_heading').eq(2).text());
						if(primary_addresss.street1!='') map_search = primary_addresss.street1+', '+primary_addresss.city+', '+primary_addresss.state;
						//alert(primary_addresss.address);
						map_zoom = 'zoom=15';
					}
					else {
						var map_search_parts = [];
						if(primary_addresss.address !== undefined && primary_addresss.address !== ''){
							map_search_parts.push(encodeURIComponent(primary_addresss.address));
							map_zoom = 'zoom=15';
						}

						if(primary_addresss.city !== undefined && primary_addresss.city !== '') {
							map_search_parts.push(encodeURIComponent(primary_addresss.city));
							map_zoom = 'zoom=10';
						}

						if(primary_addresss.state !== undefined && primary_addresss.state !== '') {
							map_search_parts.push(encodeURIComponent(primary_addresss.state));
							map_zoom = 'zoom=6';
						}

						if(primary_addresss.zip_code !== undefined && primary_addresss.zip_code !== '') {
							map_search_parts.push(encodeURIComponent(primary_addresss.zip_code));
							map_zoom = 'zoom=10';
						}
						else {
							map_search_parts.push('USA');
							map_zoom = 'zoom=3';
						}
						map_search = map_search_parts.join(" ");
					}
				}

				return map_search + '&' + map_zoom;
			},
			// returns the url used as the source for an image
			// you'll need to append '&size=500x500' or your size to the returned URL
			GoogleStaticMapsUrl: function(group) {
				var GOOGLE_MAPS_API_KEY = 'AIzaSyBSaQXaAzUHNfGZa3oN-YSajl9QNeHsy8s';

				var searchAndZoom = Handlebars.helpers.GoogleMapSearch(group).split('&');

				return "//maps.googleapis.com/maps/api/staticmap?key=" + GOOGLE_MAPS_API_KEY + "&center=" + searchAndZoom[0] + "&markers=" + searchAndZoom[0] + "&" + searchAndZoom[1];
			},

			/**
			 * Output value if not empty, else default
			 */
			iff: function(value, defaultValue) {
				val = Handlebars.escapeExpression(value);
				def = Handlebars.escapeExpression(defaultValue);

				if (val && val.trim() !== '')
					return new Handlebars.SafeString(val);
				return new Handlebars.SafeString(def);
			},
			/**
			 * Return first day of the week
			 */
			forTheWeekOf: function(date, block) {
				var months = ["January","February","March","April","May","June","July","August","September","October","November","December"];
				var curr = (date !== undefined) ? new Date(date) : new Date(); // get current date
				var first = curr.getDate() - curr.getDay(); // First day is the day of the month - the day of the week
				var firstday = new Date(curr.setDate(first));

				return months[firstday.getMonth()] + ' ' + firstday.getDate() + ', ' + firstday.getFullYear();
			},
			/**
			 * This helps build grid tops and bottoms
			 * @param  {@first} arg1  @first handlebars helper
			 * @param  {@index} arg2  @index handlebars helper
			 * @param  {int} 	arg3  number of columns
			 * @param  {html} 	block HTML code to execute
			 * @return {void}
			 */
			gridTop: function(arg1, arg2, arg3, block){
				if(arg1 || arg2%arg3===0) {
					return block.fn(this);
				}
				return block.inverse(this);
			},
			/**
			 * This helps build grid tops and bottoms
			 * @param  {@last} 	arg1  @last handlebars helper
			 * @param  {@index} arg2  @index handlebars helper
			 * @param  {int} 	arg3  number of columns
			 * @param  {html} 	block HTML code to execute
			 * @return {void}
			 */
			gridBottom: function(arg1, arg2, arg3, block){
				if(arg1 || (arg2 !==0 && (arg2+1)%arg3===0)) {
					return block.fn(this);
				}
				return block.inverse(this);
			},
			nl2br: function(text) {
				if(text === undefined) return '';
				var nl2br = (text + '').replace(/([^>\r\n]?)(\r\n|\n\r|\r|\n)/g, '$1' + '<br>' + '$2');
				return new Handlebars.SafeString(nl2br);
			},
			eoeSupportInfo: function(support, cosign, govtrack_id) {
				var output = '';
				if(support === '' && cosign === '') {
					return '<a class="help_link" href="/end-obamacare-exemption-congressional-responses/?gtid=' + govtrack_id + '">Help get them on record</a>';
				}

				if(support){
					output += '<img class="support-image" src="https://d3b5g5w8iutjdd.cloudfront.net/wp-content/uploads/2015/06/Vote-YES1.png">';
				}
				else {
					output += '<img class="support-image" src="https://d3b5g5w8iutjdd.cloudfront.net/wp-content/uploads/2015/06/Vote-NO1.png">';
				}
				if(cosign){
					output += '<img class="cosign-image" src="https://d3b5g5w8iutjdd.cloudfront.net/wp-content/uploads/2015/06/Sponsor-YES1.png">';
				}
				else {
					output += '<img class="cosign-image" src="https://d3b5g5w8iutjdd.cloudfront.net/wp-content/uploads/2015/06/Sponsor-NO1.png">';
				}

				return output;
			},
			upperCaseFirst: function (string) {
				return string.charAt(0).toUpperCase() + string.slice(1)
			},

			// display name
			displayName: function(fname, lname, defaultName) {
				if(fname === undefined || lname === undefined) {
					return defaultName;
				}
				else if(fname === '' || lname === '') {
					return defaultName;
				}
				else {
					return fname + ' ' + lname;
				}
			},

			debug: function(optionalValue, optionalTitle) {
				console.log(optionalValue);
				if (optionalValue && optionalValue.name !== "debug") {
					if(optionalTitle) {
						console.log(optionalTitle);
					}
					else {
						console.log("Value");
					}
					console.log("====================");
					console.log(optionalValue);
				}
				else{
					console.log("Current Context");
					console.log("====================");
					console.log(this);
				}
			}
		});

		T.releaseInit();
	});
})();
/**
 * Javascript for TPP Events
 */
( function () {
    var root = ( typeof window === 'object' && window ) || this;
    var T = root.TPPweb = root.TPPweb || {};
    T.events = T.events || {};
    var E = T.events = jQuery.extend( T.events, {
        create_event_form_id: '#create-event',
        event_map_id: 'tppw-event-map',
        chosen_address: {},

        start: function () {

            // look for the create event form
            E.create_event_dom = jQuery( E.create_event_form_id ).parents( 'form' );
            if ( E.create_event_dom && E.create_event_dom[0] ) {
                E.create_event_form_handler();
            }

            // look for the map
            E.event_map_dom = jQuery( '#' + E.event_map_id );
            if ( E.event_map_dom && E.event_map_dom[0] ) {
                E.start_map();
            }

            E.eventMapLegendToggle = jQuery( '.' + E.event_map_id + '__legend-toggle' );
            E.eventMapLegend = jQuery( '.' + E.event_map_id + '__legend' );
            if ( E.eventMapLegendToggle && E.eventMapLegendToggle[0] && E.eventMapLegend && E.eventMapLegend[0] ) {
                E.start_map_legend();
            }
        },
        create_event_form_handler: function () {
            // disable DHVC's stupid submit handler
            E.create_event_dom.find( '.sign-up-button button' ).prop( 'type', 'button' );

            // setup form handler
            E.create_form = T.data.createFormHandler( 'create_event', E.create_event_dom, {
                createEvent: { changed: false, submitCallback: null },
                root_dom: jQuery( E.create_event_form_id ),
                spin_root: E.create_event_dom,
                onChange: function ( formname, modelname, el, event, value ) {
                    E.create_form.options.createEvent.changed = true;
                },
                onSubmit: function ( formname, options ) {
                    var model = T.data.getHandler( formname ).getModel();

                    E.create_form.options.createEvent.changed = false;

                    if ( E.create_event_dom.valid() ) {
                        var data = {};

                        if ( E.chosen_address ) {
                            for ( var type in E.chosen_address ) {
                                var address_name = type.replace( '_address', '' );
                                if ( ( typeof E.chosen_address[type] != "string" ) && ( E.chosen_address[type] != null ) ) {
                                    data[address_name + '_address'] = E.chosen_address[type].delivery_line_1 || '';
                                    data[address_name + '_city'] = E.chosen_address[type].components.city_name || '';
                                    data[address_name + '_state'] = E.chosen_address[type].components.state_abbreviation || '';
                                    data[address_name + '_zip_code'] = E.chosen_address[type].components.zipcode || '';
                                    data[address_name + '_zip_4'] = E.chosen_address[type].components.plus4_code || '';
                                    data[address_name + '_geolatitude'] = E.chosen_address[type].metadata.latitude || '';
                                    data[address_name + '_geolongitude'] = E.chosen_address[type].metadata.longitude || '';
                                    data[address_name + '_county'] = E.chosen_address[type].metadata.county_name || '';
                                    data[address_name + '_district'] = E.chosen_address[type].metadata.congressional_district || '';
                                    data[address_name + '_time_zone'] = E.chosen_address[type].metadata.utc_offset || '';
                                } else {
                                    data[address_name + "_full_address"] = E.chosen_address[type];
                                }
                            }
                        }

                        // create the event via the api
                        T.api.events.create( {
                            data: jQuery.extend( {}, data, {
                                // organizer's info
                                fname: model.fname,
                                lname: model.lname,
                                email: model.email,
                                phone: model.phone,

                                mobile_phone: model.mobile_phone,
                                instagram: model.instagram,
                                facebook_page: model.facebook,
                                twitter_feed: model.twitter,
                                txt_optin: model.txt_optin,
                                // organizer's address
                                // setup above as organizer_address, organizer_city, etc..

                                // event address
                                // setup above as event_address, event_city, etc..

                                // Event details
                                event_type: model.type,
                                event_name: model.name,
                                event_description: model.description,
                                is_public: E.create_event_dom.find( 'input[name="is_public"]' ).val(),
                                event_start: model.event_date + ' ' + model.event_time,
                                is_recurring: model.is_recurring,


                                govtrack_id: model.legislators,
                                // townhall stuff
                                // TODO

                            } ),
                            success: function ( result ) {
                                E.create_event_dom.find( ':input' ).prop( 'disabled', 'disabled' )
                                E.spinner.stop();

                                if ( E.create_form.options.createEvent.submitCallback )
                                    E.create_form.options.createEvent.submitCallback();

                                swal( {
                                        type: 'success',
                                        title: "Thank You",
                                        text: 'Your event has been created and once approved will display on the events page',
                                    },
                                    function () {
                                        document.location.href = '/events/';
                                    } );
                            },
                            error: function ( a, b, c ) {
                                E.spinner.stop();
                                swal( {
                                    type: "error",
                                    title: "An Error has Occured",
                                    text: "An error has occured. Please try again or contact support"
                                } );
                                console.log( a, b, c );
                                //alert(b+": "+c);
                            }
                        } );
                    } else {
                        E.spinner.stop();
                    }

                    return false;
                }
            } );

            E.live_address = jQuery.LiveAddress( {
                key: '11222408539034340',
                addresses: [
                    { freeform: E.create_event_form_id + ' input[name="organizer_address"]' },
                    { freeform: E.create_event_form_id + ' input[name="event_address"]' }
                ]
            } );

            E.live_address.on( "AddressAccepted",
                function ( event, data, previousHandler ) {
                    var field_name = data.address.getDomFields().freeform.name;
                    E.chosen_address[field_name] = null;
                    if ( ( ( data || {} ).response || {} ).chosen ) {
                        E.chosen_address[field_name] = data.response.chosen;
                    } else if ( data.address.lastField.value ) {
                        // var matches = data.address.lastStreetInput.match(/([^,]+)[, ]+([a-z][a-z]+)?[, ]+(\d{5})(-\d{4})?$/i);
                        // if (matches !== null && matches[0] && matches[1] && matches[2] && matches[3] ) // let matches[4] slide since it is zip+4
                        E.chosen_address[field_name] = data.address.lastField.value;
                    }
                    previousHandler( event, data );
                }
            );

            E.create_event_dom.find( '.sign-up-button button' ).on( 'click', function ( event ) {
                T.stopEvent( event );
                event.preventDefault();

                E.spinner = T.data.createSpinner( E.create_event_dom[0] );
                jQuery( '.tppSpinner' ).css( 'position', 'absolute' );

                E.create_form.submit();
                return false;
            } );

            TPPapi.congress.legislators( 'current', {
                data: { sort: 'term_state, last_name' },
                success: function ( r ) {
                    var select = jQuery( 'select[name="legislators"]' );
                    for ( var idx in r.data ) {
                        var string = '';
                        var l = r.data[idx];

                        string += l.term_type.charAt( 0 ).toUpperCase() + l.term_type.slice( 1 ) + '. ';
                        string += ( l.nick_name !== null ) ? l.nick_name : l.first_name;
                        string += ' ' + l.last_name;

                        string += ' (' + l.term_party.charAt( 0 ).toUpperCase() + ')';
                        string += ' - ' + l.term_state;
                        string += ( l.term_district !== '0' ) ? '-' + T.util.lpad( l.term_district, 2 ) : '';

                        // add it to the select
                        select.append( '<option value="' + l.govtrack_id + '">' + string + '</option>' );

                    }
                    // look for logged in user
                    T.auth.userProfile( {
                        success: function ( result ) {
                            if ( result !== false ) {
                                // here we set model attributes for our OID and Campaign/Rally ID
                                // then we extend our model with anything returned from a logged in user.
                                var model = jQuery.extend( {
                                    phone: ( T.util.prettyPhone( ( T.util.getPrimary( ( result.phones || {} ) ) || false ).phone ) || '' ),
                                    email: ( T.util.getPrimary( ( result.emails || {} ) ) || {} ).email || '',
                                    organizer_address: T.util.prettyAddress( T.util.getPrimary( ( result.addresses || {} ) ) ) || '',
                                }, ( result || {} ) );

                                E.create_form.setModel( model );
                                jQuery( '.chosen select' ).trigger( "chosen:updated" );
                            } else {
                                E.create_form.setModel( {} );
                                jQuery( '.chosen select' ).trigger( "chosen:updated" );
                            }
                        }
                    } );

                    jQuery( '.chosen select' ).chosen();

                    // theme barfs when an anchor tag doesn't have an href property
                    jQuery( 'a.chosen-single' ).prop( 'href', '#' );
                }
            } );

            TPPapi.events.types( {
                success: function ( results ) {
                    var select = jQuery( 'select[name="type"]' );
                    select.find( 'option' ).remove();
                    for ( var idx in results.data ) {
                        var t = results.data[idx];
                        select.append( '<option value="' + t.id + '">' + t.name + '</option>' );
                    }
                }
            } );
        },
        start_map: function () {
            var data = {
                limit: 1000,
                exclude_type_id: 25
            };
            if ( E.event_map_dom.data( 'start-date' ) ) {
                data.eventFrom = E.event_map_dom.data( 'start-date' ) + " 00:00:00";
            }

            if ( E.event_map_dom.data( 'end-date' ) ) {
                data.eventTo = E.event_map_dom.data( 'end-date' );
            }

            if ( E.event_map_dom.data( 'event-type' ) ) {
                data.type_id = E.event_map_dom.data( 'event-type' );
            }

            T.api.events.search( {
                data: data,
                success: function ( results ) {
                    E.build_event_map( results.data );
                },
                error: function () {
                    console.log( 'error getting the events' );
                }
            } )
        },
        start_map_legend: function () {
            E.eventMapLegendToggle.on( 'click', function ( e ) {
                e.preventDefault();
                if ( e.target.innerText === 'Show Map Legend' ) {
                    e.target.innerText = 'Hide Map Legend';
                    E.eventMapLegend.slideDown();
                } else {
                    e.target.innerText = 'Show Map Legend';
                    E.eventMapLegend.slideUp();
                }
            } );
        },
        build_event_map: function ( events ) {

            //var bounds = new google.maps.LatLngBounds();
            var mapOptions = {
                zoom: 4,
                center: new google.maps.LatLng( 39.8281422, -98.5796298 )
            };

            var map = new google.maps.Map( document.getElementById( E.event_map_id ), mapOptions );

            E.infowindow = new google.maps.InfoWindow( {
                maxWidth: '300'
            } );

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

                var tppevent = events[i];

                var button_html = '<a class="vc_general vc_btn3 vc_btn3-size-md vc_btn3-shape-rounded vc_btn3-style-modern vc_btn3-color-blue" style="width:100%" href="/events/' + tppevent.tpp_id + '">More Info / RSVP</a>';

                var event_address = '';
                event_address += ( ( ( tppevent || {} ).event_address || {} ).street1 || '' ) + ' ';
                event_address += ( ( ( tppevent || {} ).event_address || {} ).city || '' ) + ', ';
                event_address += ( ( ( tppevent || {} ).event_address || {} ).state || '' ) + ' ';
                event_address += ( ( ( tppevent || {} ).event_address || {} ).zip || '' );

                var contentString = '<div id="infowindow">' +
                    '<h2 id="puHeading" class="puHeading">' +
                    '<a href="/events/' + tppevent.tpp_id + '">' +
                    tppevent.name +
                    '</a>' +
                    '</h2>' +
                    '<div id="puBody">' +
                    '<p><strong>' + ( ( ( tppevent || {} ).type || {} ).name || '' ) + '</strong><br/>' +
                    ///(((tppevent || {}).hide_location ) ? '' : '<em>'+event_address+'</em><br/>')+
                    ( ( ( tppevent || {} ).hide_location ) ? '' : '<em>' + ( ( ( tppevent || {} ).event_address || {} ).city || '' ) + '</em><br/>' ) +
                    ///'<em>'+moment.utc(tppevent.event_start).format('M/D/Y h:mm a')+'</em></p>'+
                    '<em>' + moment.utc( tppevent.event_start ).format( 'M/D/Y' ) + '</em></p>' +
                    '<p>' +
                    ( tppevent.description !== undefined ? tppevent.description : '' ) +
                    '</p>' +
                    '<p>' + button_html + '</p>' +
                    '</div>' +
                    '</div>';


                if ( ( ( tppevent || {} ).event_address || {} ).latitude === '' && ( ( tppevent || {} ).event_address || {} ).longitude === '' ) {
                    continue;
                }


                var latLng = new google.maps.LatLng( ( ( tppevent || {} ).event_address || {} ).latitude, ( ( tppevent || {} ).event_address || {} ).longitude );

                var image = ( ( tppevent || {} ).type || {} ).map_pin_image || 'http://cdn.teapartypatriots.org/images/gmaps-pins/Blank%20Pin.png';

                var marker = new google.maps.Marker( {
                    position: latLng,
                    map: map,
                    icon: {
                        url: image,
                        size: new google.maps.Size( 33, 30 ),
                    }
                } );

                E.map_info_window_listener( marker, map, contentString );
            }
        },
        map_info_window_listener: function ( marker, map, contentString ) {
            google.maps.event.addListener( marker, 'click', function () {
                E.infowindow.setContent( contentString );
                E.infowindow.open( map, marker );
            } );
        },

    } );

    jQuery( document ).on( 'ready', function () {
        T.on( 'ready', function () {
            E.start();
        } );
    } );
} )();

/**
 * Find My Legislators
 */
(function(){
    var root = ( typeof window === 'object' && window ) || this;
    var T = root.TPPweb = root.TPPweb || {};
    T.findmylegislators = T.findmylegislators || {};
    var D = T.findmylegislators = jQuery.extend(T.findmylegislators, {
        fmldom: null,
        fmltemplate: null,
        location_info: {},
        form: null,

        start: function() {
            //if we have an #fmlbox / Find My Legislators shortcode element
            var fml = jQuery('#fmlbox');
            if(fml && fml[0]){
                // get location info from profile or browser geolocation
                D.findLocation();
                // fill form with location info
                D.setupForm();
            }
        },

        findLocation: function() {
            T.auth.userProfile({
                success:function(profile){
                    if (profile && profile.apikey) {
                        D.location_info['email']     = T.util.getPrimary(profile.emails).email;

                        var primary_address          = T.util.getPrimary(profile.addresses);
                        D.location_info['address']   = primary_address.street1;
                        D.location_info['city']      = primary_address.city;
                        D.location_info['state']     = primary_address.state;
                        D.location_info['zip']       = primary_address.zip;
                        D.location_info['latitude']  = primary_address.latitude;
                        D.location_info['longitude'] = primary_address.longitude;

                        D.form.setModel(D.location_info);
                        D.getLegislators();
                    }
                    else {
                        //call to geoip2 to get geolocation data
                        var onSuccess = function(location){
                            D.location_info['address']   = null;
                            D.location_info['city']      = location.city.names.en;
                            D.location_info['state']     = location.subdivisions[0].iso_code;
                            D.location_info['zip']       = location.postal.code;
                            D.location_info['latitude']  = location.location.latitude;
                            D.location_info['longitude'] = location.location.longitude;

                            D.form.setModel(D.location_info);
                            D.getLegislators();
                        };

                        var onError = function(error){
                            D.form.setModel({});
                            console.log("Unable to find lat/long with geopip2");
                        };

                        geoip2.city(onSuccess, onError);
                    }
                }
            });
        },

        setupForm: function() {
            var formdom = jQuery('#fmlform');

            D.formname = 'fmlformhandler';

            D.form = T.data.createFormHandler(D.formname, formdom, {
                onChange: function(formname, modelname, el, event, value){
                    //on change behaviors
                },
                onSubmit: function(formname, options) {

                    jQuery('#fmlleg').addClass('tppTemplate');

                    D.getLegislators(D.formname, true);
                }
            });

            formdom.find('#fmlbutton').click(function(e){
                D.form.submit();
                return T.stopEvent(e);
            });
        },

        getLegislators: function (formname, ignoreLatLng) {
            var model = T.data.getHandler(D.formname).getModel();

            var query = null;
            if (!ignoreLatLng && model.latitude !== null && model.longitude !== null) {
                query = JSON.stringify({"district_location":{"$contains":{"lat": model.latitude ,"lon": model.longitude }}});
            }
            else {
                query = JSON.stringify({"district_location":{"$contains":{"addr":{"street":model.address,"city":model.city,"state":model.state,"zip":model.zip_code}}}});
            }

            var api_settings = {
                data: {
                    fields:'state_name,term_type,district_name,first_name,last_name,term_party,term_address,phone,twitter,twitter_off,fb_id,govtrack_id',
                    q: query
                },
                success: function(result) {
                    var legislator_result = result.data;

                    //changing values for display
                    for(i=0;i<legislator_result.length;i++){
                        legislator_result[i].term_type = legislator_result[i].term_type === 'rep'?'US Representative' : legislator_result[i].term_type === 'sen'? 'US Senator' : 'Unknown';
                        legislator_result[i].term_party = legislator_result[i].term_party === 'Republican'?'(R)' : legislator_result[i].term_party === 'Democrat'? '(D)' : '(I)';
                    }

                    D.buildelements(legislator_result);
                },
                error: function () {
                    console.log("Error Finding Legislators by Address");
                }
            };

            var type = jQuery('#legislator_type').val();
            switch(type) {
                case 'sen':
                    T.api.congress.senators('current', api_settings);
                    break;
                case 'rep':
                    T.api.congress.representatives('current', api_settings);
                    break;
                case 'both':
                default:
                    T.api.congress.legislators('current', api_settings);
                    break;
            }
        },

        buildelements : function(legislatorresult){
            if (!this.fmldom)
                this.fmldom = jQuery('#fmlleg');

            if (this.fmldom && this.fmldom[0]) {

                if (legislatorresult.length !== 1)
                    while(legislatorresult.length < 3) {
                        legislatorresult.push({
                            "district_name": null,
                            "state_name": "",
                            "term_type": "",
                            "term_party": "",
                            "term_address": "DC Office Address",
                            "govtrack_id": "blank",
                            "first_name": "Your",
                            "last_name": "Congressman",
                            "twitter_off": "",
                            "twitter": "",
                            "fb_id": "",
                            "phone": "XXX-XXX-XXXX"
                        });
                    }

                fmlmodel = {legislator : legislatorresult};

                if (!this.fmltemplate)
                    this.fmltemplate = T.data.createHandler('fml_handler', this.fmldom);

                this.fmltemplate.setModel(fmlmodel);
                this.fmltemplate.process();

                //fix for missing FML images
                jQuery('.legislator-image').error(function() {
                    this.onerror = "";
                    this.src = "https://s3.amazonaws.com/tpp-public/photos/legislators/blank-200px.jpeg";
                    return true;
                });
            }
        },
    });

    T.on('ready', function(){
        setTimeout(D.start, 100);
    });

})();
/**
 * Newsletter signup
 */
(function () {
    var root = (typeof window === 'object' && window) || this;
    var T = root.TPPweb = root.TPPweb || {};
    T.newsletter = T.newsletter || {};
    var D = T.newsletter = jQuery.extend(T.newsletter, {
        nsbdom: null,
        nsbtemplate: null,

        findlatlong: function (options) {
            var onSuccess = function (location) {
                var address = null;
                var city = location.city.names.en;
                var state = location.subdivisions[0].iso_code;
                var zip = location.postal.code;
                var geolat = location.location.latitude;
                var geolong = location.location.longitude;
                var model = {
                    address: address,
                    city: city,
                    state: state,
                    zip_code: zip,
                    geolat: geolat,
                    geolong: geolong
                }
                options.success(model);
            };

            var onError = function (error) {
                if (console && console.log) {
                    console.log(error);
                }
                var model = {};
                options.success(model);
            };

            geoip2.city(onSuccess, onError);
        },

    });


    T.on('ready', function () {
        var root = jQuery('.tpp-widget.tppw-newsletter-signup');
        if (root && root.length) {
            jQuery.each(root, function (i, el) {
                var $el = jQuery(el);
                var form_dom = $el.find('form');

                var form = T.data.createFormHandler('newsletter_signup', form_dom, {
                    newsletterSignup: {changed: false, submitCallback: null},
                    root_dom: $el,
                    onChange: function (formname, modelname, el, event, value) {
                        form.options.newsletterSignup.changed = true;
                    },
                    onSubmit: function (formname, options) {
                        var model = T.data.getHandler(formname).getModel();

                        form.options.newsletterSignup.changed = false;

                        T.api.newsletter.signup({
                            data: {
                                city: model.city,
                                state: model.state,
                                zip_code: model.zip_code,
                                email: model.email,
                                geolatitude: model.geolat,
                                geolongitude: model.geolong,
                                leadsource: model.leadsource
                            },
                            success: function (result) {
                                // hide email input
                                form_dom.hide();
                                // hide error may already be showing if error
                                $el.find('.tppw-newsletter-signup__error').hide();
                                //show thank you
                                $el.find('.tppw-newsletter-signup__thanks').show();

                                if ($el.data('redirect-url')) {
                                    var url = $el.data('redirect-url');
                                    url += url.indexOf("?") >= 0 ? "&" : "?";
                                    url += "id=" + result.data.tpp_id;
                                    url += "&newsletter_signup=success";
                                    window.location.href = url;
                                }
                            },
                            error: function (result) {
                                // show error
                                $el.find('.tppw-newsletter-signup__error').show();
                            }
                        });

                        return false;
                    }
                });

                form_dom.submit(function (event) {
                    T.stopEvent(event);

                    form.submit();
                    return false;
                });

                // Does this do anything?
                T.newsletter.findlatlong({
                    success: function (model) {
                        form.setModel(model);
                    },
                    error: function () {
                        var model = {};
                        form.setModel(model);
                    }
                });

                // Check to see if user logged in (profile true) and then check opt in status.  If both are true, hide form.  User already on newsletter list.
                T.auth.userProfile({
                    success: function (profile) {
                        if (profile) {
                            if (!profile.opt_in_email) {
                                //show the block
                                $el.show();
                            }
                        } else {
                            //show the block
                            $el.show();
                        }
                    }
                });
            });
        }
    });

})();

/**
 * Javascript for volunteer interests shortcode
 */
( function () {
    var root = ( typeof window === 'object' && window ) || this;
    var T = root.TPPweb = root.TPPweb || {};
    T.shortcodes = T.shortcodes || {};
    var VI = T.shortcodes.volunteer_interests = jQuery.extend( T.volunteer_interests, {
        root: 'volunteer-interests',
        checkbox_class: 'interests_checkbox',
        save_button_selector: '.volunteer_interests_save_button',
        tpp_id: null,
        page_built: false,
        start: function () {
            var root_dom = jQuery( '#' + VI.root );

            if ( root_dom && root_dom[0] ) {
                VI.root_dom = root_dom;
                T.data.spinnerDom = jQuery( '.spinner' );
                T.data.createSpinner( T.data.spinnerDom[0] );

                VI.get_interests_topics();

                if ( TPPweb.util.getQueryParam( 'id' ) !== null && TPPweb.util.getQueryParam( 'id' ) !== '' ) {
                    VI.tpp_id = TPPweb.util.getQueryParam( 'id' );
                    VI.get_user_interests();
                } else {
                    T.auth.userProfile( {
                        success: function ( profile ) {
                            if ( profile && profile.tpp_id ) {
                                VI.tpp_id = profile.tpp_id;
                                VI.get_user_interests();
                            } else {
                                VI.get_user_interests();
                            }
                        }
                    } );
                }
            }
        },
        get_interests_topics: function () {
            T.api.volunteer.interests_topics( {
                success: VI.render
            } );
        },
        get_user_interests: function () {
            if ( VI.tpp_id !== null ) {
                T.api.contacts.get_interests( VI.tpp_id, {
                    success: VI.load_user_interests
                } );
            }
        },
        load_user_interests: function ( results ) {
            VI.user_interests = results.data;
            VI.user_interests_interval = setInterval( function ( results ) {
                if ( VI.page_built && VI.user_interests ) {

                    VI.root_dom.find( 'input[name="email"]' ).hide();
                    VI.root_dom.find( 'label[for="dhvc_form_control_email"]' ).hide();

                    for ( var i = 0; i < VI.user_interests.length; i++ ) {
                        var interest = VI.user_interests[i];

                        VI.root_dom.find( 'input[value="' + interest.interest_id + '"]' ).trigger( 'click' );
                    }

                    clearInterval( VI.user_interests_interval );
                }
            }, 200 );
        },
        render: function ( results ) {
            if ( results.data.length ) {
                var templ = T.data.createHandler( VI.root, VI.root, {
                    handlebarsOptions: { noEscape: true }
                } );
                templ.setModel( results.data );
                templ.process();
                VI.initialize_listeners();

            }
            if ( TPPweb.util.getQueryParam( 'newsletter_signup' ) !== null && TPPweb.util.getQueryParam( 'newsletter_signup' ) !== '' ) {
                jQuery( "#newsletter_thanks" ).show();
            }
            T.data.spinnerDom.hide();
            VI.page_built = true;
        },
        initialize_listeners: function () {
            VI.root_dom.find( '.interests_checkbox' ).click( function ( event ) {
                event.stopPropagation();
            } );
            VI.root_dom.find( '.volunteer_interests_block' ).click( function ( e ) {
                var id = jQuery( this ).data( 'vi-id' );
                var input = VI.root_dom.find( 'input[value="' + id + '"]' );
                input.prop( 'checked', ! input.prop( 'checked' ) );
            } )

            // link the two email inputs
            VI.root_dom.find( 'input[name="email"]' ).keyup( function () {
                VI.root_dom.find( 'input[name="email"]' ).val( jQuery( this ).val() );
            } );

            VI.root_dom.find( VI.save_button_selector ).click( function ( event ) {
                T.stopEvent( event );

                // submit form
                if ( VI.tpp_id !== null || VI.root_dom.find( 'form' ).valid() ) {
                    var interests = [];
                    VI.root_dom.find( '.interests_checkbox:checked' ).each( function ( i ) {
                        interests[i] = jQuery( this ).val();
                    } );
                    T.api.contacts.set_interests( VI.tpp_id, {
                        data: {
                            'interests': interests,
                            'email': VI.root_dom.find( 'input[name="email"]' ).val(),
                        },
                        success: function ( results ) {
                            VI.root_dom.find( VI.save_button_selector ).prop( 'disabled', 'disabled' );
                            if ( VI.root_dom.data( 'redirect-url' ) ) {
                                window.location.href = VI.root_dom.data( 'redirect-url' );
                            } else {
                                swal( "Good Job!", "Your interests have been saved.", 'success' );
                            }
                        }
                    } );
                } else {
                    swal( 'Error', 'Please fill in your email address', 'error' );
                }

                return false;
            } );
        },

    } );

    T.on( 'ready', function () {
        VI.start();
    } );
} )();

TPPweb.config.host = 'https://www.teapartypatriots.org';TPPweb.root.tppWebInit();