/**
 * sprintf and vsprintf for jQuery
 * somewhat based on http://jan.moesen.nu/code/javascript/sprintf-and-printf-in-javascript/
 * 
 * Copyright (c) 2008 Sabin Iacob (m0n5t3r) <iacobs@m0n5t3r.info>
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details. 
 *
 * @license http://www.gnu.org/licenses/gpl.html 
 * @project jquery.sprintf
 */
(function($){
	var formats = {
		'%': function(val) {return '%';},
		'b': function(val) {return  parseInt(val, 10).toString(2);},
		'c': function(val) {return  String.fromCharCode(parseInt(val, 10));},
		'd': function(val) {return  parseInt(val, 10) ? parseInt(val, 10) : 0;},
		'u': function(val) {return  Math.abs(val);},
		'f': function(val, p) {return  (p > -1) ? Math.round(parseFloat(val) * Math.pow(10, p)) / Math.pow(10, p): parseFloat(val);},
		'o': function(val) {return  parseInt(val, 10).toString(8);},
		's': function(val) {return  val;},
		'x': function(val) {return  ('' + parseInt(val, 10).toString(16)).toLowerCase();},
		'X': function(val) {return  ('' + parseInt(val, 10).toString(16)).toUpperCase();}
	};

	var re = /%(?:(\d+)?(?:\.(\d+))?|\(([^)]+)\))([%bcdufosxX])/g;

	var dispatch = function(data){
		if(data.length == 1 && typeof data[0] == 'object') { //python-style printf
			data = data[0];
			return function(match, w, p, lbl, fmt, off, str) {
				return formats[fmt](data[lbl]);
			};
		} else { // regular, somewhat incomplete, printf
			var idx = 0; // oh, the beauty of closures :D
			return function(match, w, p, lbl, fmt, off, str) {
				return formats[fmt](data[idx++], p);
			};
		}
	};

	$.extend({
		sprintf: function(format) {
			var argv = Array.apply(null, arguments).slice(1);
			return format.replace(re, dispatch(argv));
		},
		vsprintf: function(format, data) {
			return format.replace(re, dispatch(data));
		}
	});
})(jQuery);

/**
* jQuery jSelect plugin
* @requires	jQuery v1.2+
* @licenses	Creative Commons BY-SA [ http://creativecommons.org/licenses/by-sa/2.0/deed.fr ]
* @desc		Plugin jQuery that enable load and add Option in Select
* @author	Hervé GOUCHET [ contact(at)rvdevsign(dot)net ]
* @version	1.3.1
* @date		2009/03/17
* @doc		http://www.rvdevsign.net/ressources/javascript/jselect-plugin-jquery.html
*/

(function(d){d.fn.jselect=function(b){var n=this;var b=d.extend({},d.fn.jselect.defaults,b);var j=[];if(b.loadUrl){d.ajax({type:b.loadType,url:b.loadUrl,data:b.loadData,dataType:b.loadDataType,success:function(c){var a=false;if(c){a=true}if(b.data.length>0){k(b.data,b.dataType,!a,false)}if(a==true){k(c,b.loadDataType,a,false)}},error:function(){b.loadUrl=null;if(d.isFunction(b.loadOnError)){b.loadOnError()}}})}else if(b.data.length>0){k(b.data,b.dataType,true,false)}else{p()}function p(){if(n.is("select")==true){s(d(n));if(d.isFunction(b.onComplete)){b.onComplete(d(n))}}}function k(a,e,i,h){var m={oValue:"",oText:"",oSelected:"",oClass:""};var l=[];if(e=='xml'||e=='html'){d('option',a).each(function(){oValue=d(this).attr('value');oText=(e=='xml'?d(this).attr('text'):d(this).text());oSelected=(d(this).attr('selected')=="true"||d(this).attr('selected')=="selected"?true:false);if(oValue!==""&&oText!==""){var c={oValue:oValue,oText:oText,oSelected:oSelected,oClass:d(this).attr('class')};c=d.extend({},m,c);if(h==false){j.push(c)}else{l.push(c)}}})}else if(e=='array'){var o=a.length;for(var f=0;f<o;f++){if(a[f].constructor.toString().indexOf("Array")==-1){if(a[f]!==""){var g={oValue:a[f],oText:a[f],oSelected:false,oClass:""};g=d.extend({},m,g);if(h==false){j.push(g)}else{l.push(g)}}}else if(a[f].length>1){if(a[f][0]!==""&&a[f][1]!==""){var g={oValue:a[f][0],oText:a[f][1],oSelected:(typeof a[f][2]!="undefined"?a[f][2]:false),oClass:(typeof a[f][3]!="undefined"?a[f][3]:"")};g=d.extend({},m,g);if(h==false){j.push(g)}else{l.push(g)}}}}}else if(e=='json'){var o=a.select.length;for(var f=0;f<o;f++){if(a.select[f].oValue!==""&&a.select[f].oText!==""){var g=d.extend({},m,a.select[f]);if(h==false){j.push(g)}else{l.push(g)}}}}if(i==true&&h==false){p()}if(h==true){return l}}function s(c){var a=j;if(b.replaceAll==false){var e=k(c,"html",false,true);a=e.concat(a)}c.empty();if(b.addOption==true){a.push({oValue:b.addOptionValue,oText:b.addOptionText,oSelected:false,oClass:b.addOptionClass})}q(c,a);c.change(function(){if(b.addOption==true){t(c)}if(d.isFunction(b.onChange)){b.onChange(d(this).val(),d(this).find("option[value='"+d(this).val()+"']").html(),d(this))}})}function q(c,a){var e=c.get(0);var i=a.length;e.options.length=i;for(var h=0;h<i;h++){u(e,h,a[h])}}function u(c,a,e){c.options[a]=new Option(e.oText,e.oValue);if(e.oSelected&&e.oSelected==true){c.options[a].selected=true}if(e.oClass){c.options[a].setAttribute("class",e.oClass)}}function t(c){if(c.val()==b.addOptionValue){var a=prompt(b.addOptionPrompt,"");if(a&&b.addOptionUrl){v(c,a)}}}function v(a,e){d.ajax({type:b.addOptionType,url:b.addOptionUrl,data:b.addOptionData+e,success:function(c){if(c&&c!=""){w(a,c,e)}else{r(a,e)}},error:function(){r(a,e)}})}function r(c,a){b.addOptionUrl=null;c.get(0)[0].selected=true;if(d.isFunction(b.addOptionOnError)){b.addOptionOnError(a,c)}}function w(c,a,e){var i=[];i=k(c,"html",false,true);if(b.addOption==true){i.pop()}i.push({oValue:a,oText:e,oSelected:b.addOptionSetSelected,oClass:b.addOptionSetClass});if(b.addOption==true){i.push({oValue:b.addOptionValue,oText:b.addOptionText,oSelected:false,oClass:b.addOptionClass})}q(c,i);if(d.isFunction(b.addOptionOnComplete)){b.addOptionOnComplete(a,e,c)}}};d.fn.jselect.defaults={data:[],dataType:"array",replaceAll:true,onChange:function(){},onComplete:function(){},loadUrl:null,loadData:null,loadType:"POST",loadOnError:function(){},loadDataType:"xml",addOption:false,addOptionUrl:null,addOptionData:"newOption=",addOptionType:"POST",addOptionValue:"-1",addOptionText:"Add an option",addOptionClass:null,addOptionPrompt:"Text of the new option:",addOptionSetSelected:true,addOptionSetClass:null,addOptionOnComplete:function(){},addOptionOnError:function(){}}})(jQuery);

var selectedIndex = function(eltID) {
  var optionName = $.sprintf("#%s option",eltID);
  var selectedOptionName = $.sprintf("#%s option:selected",eltID);
  return $(optionName).index($(selectedOptionName));
}

$(document).ready(function() {
  $.ajaxSetup({ 'beforeSend': function(xhr) {xhr.setRequestHeader("Accept", "text/javascript")} });
  
  $('.appointment_likes_comments span[title]').tipsy();
  $('#main_tabs li').tipsy();
  
  $(document).mouseup(function(e) {

     if ($(e.target).parent(".search_ui").length==0) {
          $('#autocomplete_popup').hide();
      }
  });
    
  $('#search_query').watermark("Search");
  $('#search_query').keyup(function() {
   var text = $('#search_query').val();
 
   if (text.length >= 3) {
     $(this).stopTime("search");
     $(this).oneTime(500, "search", function() {
       $('#autocomplete_search_button').attr('src','/images/search_spinner.gif');
       $.get('/search_autocomplete', {query: text}, function(json) {
         var off = $(".search_ui").offset();
         //$("fieldset#signin_menu").offset({left:off.left, top:off.top + 22});
         $('#autocomplete_popup').fadeIn();
         eval(json);
          $('#autocomplete_search_button').attr('src','/images/search_outline.png');
         if ($('.autocomplete_result').length > 0) {
           $('.autocomplete_result').click(function() {
              window.location = $(this).find("a").attr('href');
            });
         } else {
           //$('#autocomplete_popup') <-- Append a 'no results found' message
         }
       });
     });
   }
  });
});

/*
  1,
  2,
  5,
  10,
  20,
  50,
  100,
  Anywhere
*/

var offersBoard = {
  distanceLabel: null,
  hiddenField: null,
  initialValue: 4,
  valueMappings: [1, 2, 5, 10, 20, 50, 100, 125],
  friendlyNames: ["Within 1 Mile", "Within 2 Miles", "Within 5 Miles", "Within 10 Miles", "Within 20 Miles", "Within 50 Miles", "Within 100 Miles", "Anywhere"],
  
  initializeUI: function(initialValue, slider, hiddenField, label) {
    offersBoard.initialValue = initialValue;
    offersBoard.distanceLabel = label;
    offersBoard.hiddenField = hiddenField;
    slider.slider({
      value: offersBoard.indexForMiles(initialValue),
      min: 0,
      max: 7,
      step: 1,
      slide: function(event, ui) {
        offersBoard.adjustMiles(ui.value);
      }
    });
    offersBoard.adjustMiles(offersBoard.indexForMiles(initialValue));
  },
  indexForMiles: function(mi) {
    return jQuery.inArray(mi, offersBoard.valueMappings);
  },
  adjustMiles: function(v) {
    var friendly = offersBoard.friendlyNames[v];
    var mappedValue = offersBoard.valueMappings[v];
    
    offersBoard.distanceLabel.text(friendly);
    offersBoard.hiddenField.val(mappedValue);
  }
}

var fbPublish = function(msg, attachment, action_link, user_message_prompt) {
  FB.ensureInit(function () {
    FB.Connect.streamPublish(
      msg,
      attachment,
      action_link,
      null, /* == target_id */
      user_message_prompt,
      null /* == callback */
      );
  });
}

var fbCallback = function(post_id, exception, data) {
  if ($('facebook_alternate_publish')) {
    $('facebook_alternate_publish').toggle();
  }
}

var fbConnectLogin = function() {
  FB.Connect.requireSession();
}

var fbConnectLogout = function() {
  FB.Connect.logoutAndRedirect('/logout');
}

/* http://jqueryfordesigners.com/demo/infinite-carousel.html */

$.fn.infiniteCarousel = function () {

    function repeat(str, num) {
        return new Array( num + 1 ).join( str );
    }
  
    return this.each(function () {
        var $wrapper = $('> div', this).css('overflow', 'hidden'),
            $slider = $wrapper.find('> ul'),
            $items = $slider.find('> li'),
            $single = $items.filter(':first'),
            
            singleWidth = $single.outerWidth(), 
            visible = Math.ceil($wrapper.innerWidth() / singleWidth), // note: doesn't include padding or border
            currentPage = 1,
            pages = Math.ceil($items.length / visible);            
        
        var $description = $('.bottom_overlay_text',this);

        // 1. Pad so that 'visible' number will always be seen, otherwise create empty items
        if (($items.length % visible) != 0) {
            $slider.append(repeat('<li class="empty" />', visible - ($items.length % visible)));
            $items = $slider.find('> li');
        }

        // 2. Top and tail the list with 'visible' number of items, top has the last section, and tail has the first
        $items.filter(':first').before($items.slice(- visible).clone().addClass('cloned'));
        $items.filter(':last').after($items.slice(0, visible).clone().addClass('cloned'));
        $items = $slider.find('> li'); // reselect
        
        // 3. Set the left position to the first 'real' item
        $wrapper.scrollLeft(singleWidth * visible);
        
        // 4. paging function
        function gotoPage(page) {
            var dir = page < currentPage ? -1 : 1,
                n = Math.abs(currentPage - page),
                left = singleWidth * dir * visible * n;
            
            $wrapper.filter(':not(:animated)').animate({
                scrollLeft : '+=' + left
            }, 500, function () {
                if (page == 0) {
                    $wrapper.scrollLeft(singleWidth * visible * pages);
                    page = pages;
                } else if (page > pages) {
                    $wrapper.scrollLeft(singleWidth * visible);
                    // reset back to start position
                    page = 1;
                } 

                currentPage = page;
                
                var child = currentPage + 1;
                var currentListItem = $wrapper.find('li:nth-child('+ child +') a');
                var title = $(currentListItem).attr('title');
                var link = $(currentListItem).attr('href');
                $description.html($.sprintf("<a href='%s'>%s</a>", link, title));
            });                
            
            return false;
        }
        
        // 5. Bind to the forward and back buttons
        $('a.back', this).click(function () {
            return gotoPage(currentPage - 1);                
        });
        
        $('a.forward', this).click(function () {
            return gotoPage(currentPage + 1);
        });
        
        // create a public interface to move to a specific page
        $(this).bind('goto', function (event, page) {
            gotoPage(page);
        });
    });  
};

(function($) {

  $.fn.wannabeTabs = function(settings) {
    var config = {'foo': 'bar'};
    if (settings) $.extend(config, settings);

    this.each(function() {
      $(this).hover(
        function() {
          $(this).addClass("ui-state-hover");
        },
        function() {
          $(this).removeClass("ui-state-hover");
        }
      );
    });

    return this;

  };

})(jQuery);

var showFullBusinessDescription = function() {
  $('.truncated_description').hide();
  $('.read_more_link').hide();
  $('.full_description').fadeIn();
}

var fbs_click = function() {
  u = location.href;
  t = document.title;
  window.open('http://www.facebook.com/sharer.php?u='+encodeURIComponent(u)+'&t='+encodeURIComponent(t),'sharer','toolbar=0,status=0,width=626,height=436');
  return false;
}

var digg_click = function() {
  u = location.href;
  t = document.title;
  window.open('http://digg.com/submit?url='+encodeURIComponent(u)+'&title='+encodeURIComponent(t)+'&media=news&topic=tech_news');
  return false;
}

var delicious_click = function() {
  u = location.href;
  t = document.title;
  window.open('http://delicious.com/post?url='+encodeURIComponent(u)+'&title='+encodeURIComponent(t));
  return false;
}

var reddit_click = function() {
  u = location.href;
  t = document.title;
  window.open('http://reddit.com/submit?url='+encodeURIComponent(u)+'&title='+encodeURIComponent(t));
  return false;
}

var su_click = function() {
  u = location.href;
  t = document.title;
  window.open('http://stumbleupon.com/submit?url='+encodeURIComponent(u)+'&title='+encodeURIComponent(t));
  return false;
}

var initializeGallery = function() {
  $('ul.gallery_demo').galleria({
    clickNext: true,
    insert: '#main_image',
    history: false,
    onImage: function(image, caption, thumb) {
      // fade in the image & caption
			image.css('display','none').fadeIn(1000);
			caption.css('display','none').fadeIn(1000);
			
			// fetch the thumbnail container
			var _li = thumb.parents('li');
			
			// fade out inactive thumbnail
			_li.siblings().children('img.selected').fadeTo(500,0.3);
			
			// fade in active thumbnail
			thumb.fadeTo('fast',1).addClass('selected');
			
			// add a title for the clickable image
			image.attr('title','Next image >>');
    },
    onThumb : function(thumb) { // thumbnail effects goes here
			
			// fetch the thumbnail container
			var _li = thumb.parents('li');
			
			// if thumbnail is active, fade all the way.
			var _fadeTo = _li.is('.active') ? '1' : '0.3';
			
			// fade in the thumbnail when finnished loading
			thumb.css({display:'none',opacity:_fadeTo}).fadeIn(1500);
			
			// hover effects
			thumb.hover(
				function() { thumb.fadeTo('fast',1); },
				function() { _li.not('.active').children('img').fadeTo('fast',0.3); } // don't fade out if the parent is active
			)
		}
  });
}


var isFlashEnabled = function() {
  return (navigator.mimeTypes && navigator.mimeTypes["application/x-shockwave-flash"]);
}

/* ******************************************
 *	FileProgress Object
 *	Control object for displaying file info
 * ****************************************** */

function FileProgress(fileObj, target_id) {
	this.file_progress_id = "divFileProgress";

	this.fileProgressWrapper = $(this.file_progress_id);
	if (!this.fileProgressWrapper) {
		this.fileProgressWrapper = document.createElement("div");
		this.fileProgressWrapper.className = "progressWrapper";
		this.fileProgressWrapper.id = this.file_progress_id;

		this.fileProgressElement = document.createElement("div");
		this.fileProgressElement.className = "progressContainer";

		var progressCancel = document.createElement("a");
		progressCancel.className = "progressCancel";
		progressCancel.href = "#";
		progressCancel.style.visibility = "hidden";
		progressCancel.appendChild(document.createTextNode(" "));

		var progressText = document.createElement("div");
		progressText.className = "progressName";
		progressText.appendChild(document.createTextNode(fileObj.name));

		var progressBar = document.createElement("div");
		progressBar.className = "progressBarInProgress";

		var progressStatus = document.createElement("div");
		progressStatus.className = "progressBarStatus";
		progressStatus.innerHTML = "&nbsp;";

		this.fileProgressElement.appendChild(progressCancel);
		this.fileProgressElement.appendChild(progressText);
		this.fileProgressElement.appendChild(progressStatus);
		this.fileProgressElement.appendChild(progressBar);

		this.fileProgressWrapper.appendChild(this.fileProgressElement);

		$(target_id).appendChild(this.fileProgressWrapper);

	} else {
		this.fileProgressElement = this.fileProgressWrapper.firstChild;
		this.fileProgressElement.childNodes[1].firstChild.nodeValue = fileObj.name;
	}

	this.height = this.fileProgressWrapper.offsetHeight;

}
FileProgress.prototype.SetProgress = function(percentage) {
	this.fileProgressElement.className = "progressContainer green";
	this.fileProgressElement.childNodes[3].className = "progressBarInProgress";
	this.fileProgressElement.childNodes[3].style.width = percentage + "%";
}
FileProgress.prototype.SetComplete = function() {
	this.fileProgressElement.className = "progressContainer blue";
	this.fileProgressElement.childNodes[3].className = "progressBarComplete";
	this.fileProgressElement.childNodes[3].style.width = "";

}
FileProgress.prototype.SetError = function() {
	this.fileProgressElement.className = "progressContainer red";
	this.fileProgressElement.childNodes[3].className = "progressBarError";
	this.fileProgressElement.childNodes[3].style.width = "";

}
FileProgress.prototype.SetCancelled = function() {
	this.fileProgressElement.className = "progressContainer";
	this.fileProgressElement.childNodes[3].className = "progressBarError";
	this.fileProgressElement.childNodes[3].style.width = "";

}
FileProgress.prototype.SetStatus = function(status) {
	this.fileProgressElement.childNodes[2].innerHTML = status;
}

FileProgress.prototype.ToggleCancel = function(show, upload_obj, file_id) {
	this.fileProgressElement.childNodes[0].style.visibility = show ? "visible" : "hidden";
	if (upload_obj) {
		this.fileProgressElement.childNodes[0].onclick = function() { upload_obj.cancelUpload(); return false; };
	}
}

function AddImage(src) {
	var thumbnailID = 'thumb_' + S4();
	var newThumbnail = new Element("img", {id: thumbnailID, style:'margin:5px;', src:src});
	$("thumbnails").appendChild(newThumbnail);
}

////

var dsSWFUpload = {
  swfu: null,
  
  fileQueueError: function(fileObj, error_code, message) {
  	try {
  		var error_name = "";
  		switch(error_code) {
  			case SWFUpload.ERROR_CODE_QUEUE_LIMIT_EXCEEDED:
  				error_name = "You have attempted to queue too many files.";
  			break;
  		}

  		if (error_name !== "") {
  			alert(error_name);
  			return;
  		}

  		switch(error_code) {
  			case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:
  				image_name = "zerobyte.gif";
  			break;
  			case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:
  				image_name = "toobig.gif";
  			break;
  			case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:
  			case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE:
  			default:
  				alert(message);
  				image_name = "error.gif";
  			break;
  		}

  		AddImage("/images/" + image_name);

  	} catch (ex) { this.debug(ex); }
  },
  
  fileDialogComplete: function(num_files_queued) {
  	try {
  		if (num_files_queued > 0) {
  			this.startUpload();
  		}
  	} catch (ex) { this.debug(ex); }
  },
  uploadProgress: function(fileObj, bytesLoaded) {

  	try {
  		var percent = Math.ceil((bytesLoaded / fileObj.size) * 100)

  		var progress = new FileProgress(fileObj,  this.customSettings.upload_target);
  		progress.SetProgress(percent);
  		if (percent === 100) {
  			progress.SetStatus("Creating thumbnail...");
  			progress.ToggleCancel(false);
  			progress.ToggleCancel(true, this, fileObj.id);
  		} else {
  			progress.SetStatus("Uploading...");
  			progress.ToggleCancel(true, this, fileObj.id);
  		}
  	} catch (ex) { this.debug(ex); }
  },
  
  uploadSuccess: function(fileObj, server_data) {
  	try {
  		AddImage(server_data);

  		var progress = new FileProgress(fileObj,  this.customSettings.upload_target);

  		progress.SetStatus("Thumbnail Created.");
  		progress.ToggleCancel(false);

  	} catch (ex) { this.debug(ex); }
  },
  uploadComplete: function(fileObj) {
  	try {
  		/*  I want the next upload to continue automatically so I'll call startUpload here */
  		if (this.getStats().files_queued > 0) {
  			this.startUpload();
  		} else {
  			var progress = new FileProgress(fileObj,  this.customSettings.upload_target);
  			progress.SetComplete();
  			progress.SetStatus("All images received.");
  			progress.ToggleCancel(false);
  		}
  	} catch (ex) { this.debug(ex); }
  },
  uploadError: function(fileObj, error_code, message) {
  	var image_name =  "error.gif";
  	try {
  		switch(error_code) {
  			case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:
  				try {
  					var progress = new FileProgress(fileObj,  this.customSettings.upload_target);
  					progress.SetCancelled();
  					progress.SetStatus("Stopped");
  					progress.ToggleCancel(true, this, fileObj.id);
  				}
  				catch (ex) { this.debug(ex); }
  			case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED:
  				image_name = "uploadlimit.gif";
  			break;
  			default:
  				alert(message);
  			break;
  		}

  		AddImage("/images/" + image_name);

  	} catch (ex) { this.debug(ex); }

  },
  initializeSWFUpload: function(url, formAuthenticityToken) {
    swfu = new SWFUpload({
      upload_url: url,
      flash_url: '/flash/swfupload.swf',
    
      // Button settings
      button_image_url: "/images/choose_file_sprites.png",	// Relative to the Flash file
      button_width: "199",
      button_height: "30",
      button_placeholder_id: "upload_button_placeholder",
      file_size_limit : '2048',
      file_types : "*.png;*.jpg;*.jpeg;*.gif",
      file_types_description : 'Web Images',
      file_upload_limit : '0',
      prevent_swf_caching : true,
    
      custom_settings : {
        progressTarget : "fsUploadProgress"
      },
    
      file_queue_error_handler: this.fileQueueError,
      file_dialog_complete_handler: this.fileDialogComplete,
      upload_progress_handler: this.uploadProgress,
      upload_error_handler: this.uploadError,
      upload_success_handler: this.uploadSuccess,
      upload_complete_handler: this.uploadComplete,
    
      post_params: {
        authenticity_token: formAuthenticityToken
      },

      custom_settings: { 
        upload_target: 'divFileProgressContainer'
      },
      debug: false
    });
  }
};

var addEmailToList = function() {
  var email = $.trim($('#add_email').val());
  if (email.length > 0) {
    var labelString = "<li><label><input type='checkbox' name='email_addresses[]' value='"+ email +"' checked='1' /> " + email + "</label></li>";
    $('#email_box_list').append(labelString);
    $('#add_email').val("").select();
    $('#email_box_list li:first-child').effect('highlight',{}, 2000);
  }
}

var loadContacts = function(contacts) {
  console.log(contacts);
  $('#email_box_list').append(contacts);
}

var dismissReferralBoxyDialog = function() {
  Boxy.get("#gmail_invite").hide();
}

var S4 = function() {
   return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
}

var validateCardType = function(cardNumber) {
  cardNumber = cardNumber.replace(/ /g,"");
  cardNumber = cardNumber.replace(/-/g,"");
  var cardNumberLength = cardNumber.length;
  
  var cardType = identifyCardType(cardNumber);
  
  if (null == cardType) {
    return null;
  } else {
    var numberProduct;
    var numberProductDigitIndex;
    var checkSumTotal = 0;

    for (digitCounter = cardNumberLength - 1; digitCounter >= 0; digitCounter--) {
      checkSumTotal += parseInt(cardNumber.charAt(digitCounter));
      digitCounter--;
      numberProduct = String((cardNumber.charAt(digitCounter) * 2));
      
      for (var productDigitCounter = 0;productDigitCounter < numberProduct.length; productDigitCounter++) {
        checkSumTotal += parseInt(numberProduct.charAt(productDigitCounter));
      }
    }

    if (0 == checkSumTotal % 10) {
      return cardType;
    } else {
      return null;
    }
  }
}

var identifyCardType = function(cardNumber) {
  var cardType = null;
  
  var issuers = [
    //Prefix 4, Length 16
    ["visa", /^4\d{15}$/],
    
    //Prefix 51..55, Length 16
    ["mastercard", /^5[1-5]\d{14}$/],
    
    //Prefix 6011, Length 16
    ["discover", /^6011\d{12}$/],
    
    //Prefix 34 or 37, Length 15 
    ["amex", /^3[4,7]\d{13}$/]
  ];
  
  $(issuers).each(function(idx,val) {
    var potentialCardType = val[0];
    var regex = val[1];
    
    if (regex.test(cardNumber)) {
      cardType = potentialCardType;
    }
  });
  
  return cardType;
}