text: /*
   * Fuel UX Picker
   * https://github.com/ExactTarget/fuelux
   *
   * Copyright (c) 2014 ExactTarget
   * Licensed under the BSD New license.
   */
  
  // -- BEGIN UMD WRAPPER PREFACE --
  
  // For more information on UMD visit:
  // https://github.com/umdjs/umd/blob/master/jqueryPlugin.js
  
  (function (factory) {
  	if (typeof define === 'function' && define.amd) {
  		// if AMD loader is available, register as an anonymous module.
  		define(['jquery'], factory);
  	} else if (typeof exports === 'object') {
  		// Node/CommonJS
  		module.exports = factory(require('jquery'));
  	} else {
  		// OR use browser globals if AMD is not present
  		factory(jQuery);
  	}
  }(function ($) {
  	// -- END UMD WRAPPER PREFACE --
  
  	// -- BEGIN MODULE CODE HERE --
  
  	var old = $.fn.picker;
  
  	// PLACARD CONSTRUCTOR AND PROTOTYPE
  
  	var Picker = function Picker(element, options) {
  		var self = this;
  		this.$element = $(element);
  		this.options = $.extend({}, $.fn.picker.defaults, options);
  
  		this.$accept = this.$element.find('.picker-accept');
  		this.$cancel = this.$element.find('.picker-cancel');
  		this.$trigger = this.$element.find('.picker-trigger');
  		this.$footer = this.$element.find('.picker-footer');
  		this.$header = this.$element.find('.picker-header');
  		this.$popup = this.$element.find('.picker-popup');
  		this.$body = this.$element.find('.picker-body');
  
  		this.clickStamp = '_';
  
  		this.isInput = this.$trigger.is('input');
  
  		this.$trigger.on('keydown.fu.picker', $.proxy(this.keyComplete, this));
  		this.$trigger.on('focus.fu.picker', $.proxy(function inputFocus(e){
  			if(typeof e === "undefined" || $(e.target).is('input[type=text]')){
  				$.proxy(this.show(), this);
  			}
  		}, this));
  		this.$trigger.on('click.fu.picker', $.proxy(function triggerClick(e){
  			if(!$(e.target).is('input[type=text]')){
  				$.proxy(this.toggle(), this);
  			}else{
  				$.proxy(this.show(), this);
  			}
  		}, this));
  		this.$accept.on('click.fu.picker', $.proxy(this.complete, this, 'accepted'));
  		this.$cancel.on('click.fu.picker', function (e) {
  			e.preventDefault(); self.complete('cancelled');
  		});
  
  
  	};
  
  	var _isOffscreen = function _isOffscreen(picker) {
  		var windowHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
  		var scrollTop = $(document).scrollTop();
  		var popupTop = picker.$popup.offset();
  		var popupBottom = popupTop.top + picker.$popup.outerHeight(true);
  
  		//if the bottom of the popup goes off the page, but the top does not, dropup.
  		if (popupBottom > windowHeight + scrollTop || popupTop.top < scrollTop){
  			return true;
  		}else{//otherwise, prefer showing the top of the popup only vs the bottom
  			return false;
  		}
  	};
  
  	var _display = function _display(picker) {
  		picker.$popup.css('visibility', 'hidden');
  
  		_showBelow(picker);
  
  		//if part of the popup is offscreen try to show it above
  		if(_isOffscreen(picker)){
  			_showAbove(picker);
  
  			//if part of the popup is still offscreen, prefer cutting off the bottom
  			if(_isOffscreen(picker)){
  				_showBelow(picker);
  			}
  		}
  
  		picker.$popup.css('visibility', 'visible');
  	};
  
  	var _showAbove = function _showAbove(picker) {
  		picker.$popup.css('top', - picker.$popup.outerHeight(true) + 'px');
  	};
  
  	var _showBelow = function _showBelow(picker) {
  		picker.$popup.css('top', picker.$trigger.outerHeight(true) + 'px');
  	};
  
  	Picker.prototype = {
  		constructor: Picker,
  
  		complete: function complete(action) {
  			var EVENT_CALLBACK_MAP = {
  				'accepted': 'onAccept',
  				'cancelled': 'onCancel',
  				'exited': 'onExit'
  			};
  			var func = this.options[ EVENT_CALLBACK_MAP[action] ];
  
  			var obj = {
  				contents: this.$body
  			};
  
  			if (func) {
  				func(obj);
  				this.$element.trigger(action + '.fu.picker', obj);
  			} else {
  				this.$element.trigger(action + '.fu.picker', obj);
  				this.hide();
  			}
  		},
  
  		keyComplete: function keyComplete(e) {
  			if (this.isInput && e.keyCode === 13) {
  				this.complete('accepted');
  				this.$trigger.blur();
  			} else if (e.keyCode === 27) {
  				this.complete('exited');
  				this.$trigger.blur();
  			}
  		},
  
  		destroy: function destroy() {
  			this.$element.remove();
  			// remove any external bindings
  			$(document).off('click.fu.picker.externalClick.' + this.clickStamp);
  			// empty elements to return to original markup
  			// [none]
  			// return string of markup
  			return this.$element[0].outerHTML;
  		},
  
  		disable: function disable() {
  			this.$element.addClass('disabled');
  			this.$trigger.attr('disabled', 'disabled');
  		},
  
  		enable: function enable() {
  			this.$element.removeClass('disabled');
  			this.$trigger.removeAttr('disabled');
  		},
  
  		toggle: function toggle() {
  			if (this.$element.hasClass('showing')) {
  				this.hide();
  			}else{
  				this.show();
  			}
  		},
  
  		hide: function hide() {
  			if (!this.$element.hasClass('showing')) {
  				return;
  			}
  
  			this.$element.removeClass('showing');
  			$(document).off('click.fu.picker.externalClick.' + this.clickStamp);
  			this.$element.trigger('hidden.fu.picker');
  		},
  
  		externalClickListener: function externalClickListener(e, force) {
  			if (force === true || this.isExternalClick(e)) {
  				this.complete('exited');
  			}
  		},
  
  		isExternalClick: function isExternalClick(e) {
  			var el = this.$element.get(0);
  			var exceptions = this.options.externalClickExceptions || [];
  			var $originEl = $(e.target);
  			var i, l;
  
  			if (e.target === el || $originEl.parents('.picker:first').get(0) === el) {
  				return false;
  			} else {
  				for (i = 0, l = exceptions.length; i < l; i++) {
  					if ($originEl.is(exceptions[i]) || $originEl.parents(exceptions[i]).length > 0) {
  						return false;
  					}
  
  				}
  			}
  
  			return true;
  		},
  
  		show: function show() {
  			var other;
  
  			other = $(document).find('.picker.showing');
  			if (other.length > 0) {
  				if (other.data('fu.picker') && other.data('fu.picker').options.explicit) {
  					return;
  				}
  
  				other.picker('externalClickListener', {}, true);
  			}
  
  			this.$element.addClass('showing');
  
  			_display(this);
  
  			this.$element.trigger('shown.fu.picker');
  
  			this.clickStamp = new Date().getTime() + (Math.floor(Math.random() * 100) + 1);
  			if (!this.options.explicit) {
  				$(document).on('click.fu.picker.externalClick.' + this.clickStamp, $.proxy(this.externalClickListener, this));
  			}
  		}
  	};
  
  	// PLACARD PLUGIN DEFINITION
  
  	$.fn.picker = function picker(option) {
  		var args = Array.prototype.slice.call(arguments, 1);
  		var methodReturn;
  
  		var $set = this.each(function () {
  			var $this = $(this);
  			var data = $this.data('fu.picker');
  			var options = typeof option === 'object' && option;
  
  			if (!data) {
  				$this.data('fu.picker', (data = new Picker(this, options)));
  			}
  
  			if (typeof option === 'string') {
  				methodReturn = data[option].apply(data, args);
  			}
  		});
  
  		return (methodReturn === undefined) ? $set : methodReturn;
  	};
  
  	$.fn.picker.defaults = {
  		onAccept: undefined,
  		onCancel: undefined,
  		onExit: undefined,
  		externalClickExceptions: [],
  		explicit: false
  	};
  
  	$.fn.picker.Constructor = Picker;
  
  	$.fn.picker.noConflict = function noConflict() {
  		$.fn.picker = old;
  		return this;
  	};
  
  	// DATA-API
  
  	$(document).on('focus.fu.picker.data-api', '[data-initialize=picker]', function (e) {
  		var $control = $(e.target).closest('.picker');
  		if (!$control.data('fu.picker')) {
  			$control.picker($control.data());
  		}
  	});
  
  	// Must be domReady for AMD compatibility
  	$(function () {
  		$('[data-initialize=picker]').each(function () {
  			var $this = $(this);
  			if ($this.data('fu.picker')) return;
  			$this.picker($this.data());
  		});
  	});
  
  	// -- BEGIN UMD WRAPPER AFTERWORD --
  }));
  // -- END UMD WRAPPER AFTERWORD --
  