/*! jQuery-Impromptu - v6.0.0 - 2014-12-27
* http://trentrichardson.com/Impromptu
* Copyright (c) 2014 Trent Richardson; Licensed MIT */
(function(root, factory) {
	if (typeof define === 'function' && define.amd) {
		define(['jquery'], factory);
	} else {
		factory(root.jQuery);
	}
}(this, function($) {
	'use strict';
	// ########################################################################
	// Base object
	// ########################################################################
	/**
	* Imp - Impromptu object - passing no params will not open, only return the instance
	* @param message String/Object - String of html or Object of states
	* @param options Object - Options to set the prompt
	* @return Imp - the instance of this Impromptu object
	*/
	var Imp = function(message, options){
		var t = this;
		t.id = Imp.count++;
		Imp.lifo.push(t);
		if(message){
			t.open(message, options);
		}
		return t;
	};
	// ########################################################################
	// static properties and methods
	// ########################################################################
	/**
	* defaults - the default options
	*/
	Imp.defaults = {
		prefix:'jqi',
		classes: {
			box: '',
			fade: '',
			prompt: '',
			form: '',
			close: '',
			title: '',
			message: '',
			buttons: '',
			button: '',
			defaultButton: ''
		},
		title: '',
		closeText: '×',
		buttons: {
			Ok: true
		},
		loaded: function(e){},
		submit: function(e,v,m,f){},
		close: function(e,v,m,f){},
		statechanging: function(e, from, to){},
		statechanged: function(e, to){},
		opacity: 0.6,
		zIndex: 999,
		overlayspeed: 'slow',
		promptspeed: 'fast',
		show: 'fadeIn',
		hide: 'fadeOut',
		focus: 0,
		defaultButton: 0,
		useiframe: false,
		top: '15%',
		position: {
			container: null,
			x: null,
			y: null,
			arrow: null,
			width: null
		},
		persistent: true,
		timeout: 0,
		states: {},
		state: {
			name: null,
			title: '',
			html: '',
			buttons: {
				Ok: true
			},
			focus: 0,
			defaultButton: 0,
			position: {
				container: null,
				x: null,
				y: null,
				arrow: null,
				width: null
			},
			submit: function(e,v,m,f){
				return true;
			}
		}
	};
	/**
	* setDefaults - Sets the default options
	* @param o Object - Options to set as defaults
	* @return void
	*/
	Imp.setDefaults = function(o) {
		Imp.defaults = $.extend({}, Imp.defaults, o);
	};
	/**
	* setStateDefaults - Sets the default options for a state
	* @param o Object - Options to set as defaults
	* @return void
	*/
	Imp.setStateDefaults = function(o) {
		Imp.defaults.state = $.extend({}, Imp.defaults.state, o);
	};
	/**
	* @var Int - A counter used to provide a unique ID for new prompts
	*/
	Imp.count = 0;
	/**
	* @var Array - An array of Impromptu intances in a LIFO queue (last in first out)
	*/
	Imp.lifo = [];
	/**
	* getLast - get the last element from the queue (doesn't pop, just returns)
	* @return Imp - the instance of this Impromptu object or false if queue is empty
	*/
	Imp.getLast = function(){
		var l = Imp.lifo.length;
		return (l > 0)? Imp.lifo[l-1] : false;
	};
	/**
	* removeFromStack - remove an element from the lifo stack by its id
	* @param id int - id of the instance to remove
	* @return api - The api of the element removed from the stack or void
	*/
	Imp.removeFromStack = function(id){
		for(var i=Imp.lifo.length-1; i>=0; i--){
			if(Imp.lifo[i].id === id){
				return Imp.lifo.splice(i,1)[0];
			}
		}
	};
	// ########################################################################
	// extend our object instance properties and methods
	// ########################################################################
	Imp.prototype = {
		/**
		* @var Int - A unique id, simply an autoincremented number
		*/
		id: null,
		/**
		* open - Opens the prompt
		* @param message String/Object - String of html or Object of states
		* @param options Object - Options to set the prompt
		* @return Imp - the instance of this Impromptu object
		*/
		open: function(message, options) {
			var t = this;
			t.options = $.extend({},Imp.defaults,options);
			// Be sure any previous timeouts are destroyed
			if(t.timeout){
				clearTimeout(t.timeout);
			}
			t.timeout = false;
			var opts = t.options,
				$body = $(document.body),
				$window = $(window);
			//build the box and fade
			var msgbox = '
';
			if(opts.useiframe && ($('object, applet').length > 0)) {
				msgbox += '
';
			} else {
				msgbox += '
';
			}
			msgbox += '
'+
				'
'+  stateobj.title +'
';
			}
			showHtml = stateobj.html;
			if (typeof stateobj.html === 'function') {
				showHtml = 'Error: html function must return text';
			}
			state += ''+
						arrow + title +
						'
' + showHtml +'
'+
						'
';
			// state buttons may be in object or array, lets convert objects to arrays
			if($.isArray(stateobj.buttons)){
				buttons = stateobj.buttons;
			}
			else if($.isPlainObject(stateobj.buttons)){
				for(k in stateobj.buttons){
					if(stateobj.buttons.hasOwnProperty(k)){
						buttons.push({ title: k, value: stateobj.buttons[k] });
					}
				}
			}
			// iterate over each button and create them
			for(i=0, l=buttons.length; i' + v.title + '';
			}
			
			state += '