github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/public/libs/flat-ui/js/flat-ui.js (about)

     1  /*!
     2   * Flat UI Free v2.2.2 (http://designmodo.github.io/Flat-UI/)
     3   * Copyright 2013-2014 Designmodo, Inc.
     4   */
     5  /*!
     6   * jQuery UI Core 1.10.4
     7   * http://jqueryui.com
     8   *
     9   * Copyright 2014 jQuery Foundation and other contributors
    10   * Released under the MIT license.
    11   * http://jquery.org/license
    12   *
    13   * http://api.jqueryui.com/category/ui-core/
    14   */
    15  (function( $, undefined ) {
    16  
    17  var uuid = 0,
    18  	runiqueId = /^ui-id-\d+$/;
    19  
    20  // $.ui might exist from components with no dependencies, e.g., $.ui.position
    21  $.ui = $.ui || {};
    22  
    23  $.extend( $.ui, {
    24  	version: "1.10.4",
    25  
    26  	keyCode: {
    27  		BACKSPACE: 8,
    28  		COMMA: 188,
    29  		DELETE: 46,
    30  		DOWN: 40,
    31  		END: 35,
    32  		ENTER: 13,
    33  		ESCAPE: 27,
    34  		HOME: 36,
    35  		LEFT: 37,
    36  		NUMPAD_ADD: 107,
    37  		NUMPAD_DECIMAL: 110,
    38  		NUMPAD_DIVIDE: 111,
    39  		NUMPAD_ENTER: 108,
    40  		NUMPAD_MULTIPLY: 106,
    41  		NUMPAD_SUBTRACT: 109,
    42  		PAGE_DOWN: 34,
    43  		PAGE_UP: 33,
    44  		PERIOD: 190,
    45  		RIGHT: 39,
    46  		SPACE: 32,
    47  		TAB: 9,
    48  		UP: 38
    49  	}
    50  });
    51  
    52  // plugins
    53  $.fn.extend({
    54  	focus: (function( orig ) {
    55  		return function( delay, fn ) {
    56  			return typeof delay === "number" ?
    57  				this.each(function() {
    58  					var elem = this;
    59  					setTimeout(function() {
    60  						$( elem ).focus();
    61  						if ( fn ) {
    62  							fn.call( elem );
    63  						}
    64  					}, delay );
    65  				}) :
    66  				orig.apply( this, arguments );
    67  		};
    68  	})( $.fn.focus ),
    69  
    70  	scrollParent: function() {
    71  		var scrollParent;
    72  		if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) {
    73  			scrollParent = this.parents().filter(function() {
    74  				return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
    75  			}).eq(0);
    76  		} else {
    77  			scrollParent = this.parents().filter(function() {
    78  				return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
    79  			}).eq(0);
    80  		}
    81  
    82  		return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent;
    83  	},
    84  
    85  	zIndex: function( zIndex ) {
    86  		if ( zIndex !== undefined ) {
    87  			return this.css( "zIndex", zIndex );
    88  		}
    89  
    90  		if ( this.length ) {
    91  			var elem = $( this[ 0 ] ), position, value;
    92  			while ( elem.length && elem[ 0 ] !== document ) {
    93  				// Ignore z-index if position is set to a value where z-index is ignored by the browser
    94  				// This makes behavior of this function consistent across browsers
    95  				// WebKit always returns auto if the element is positioned
    96  				position = elem.css( "position" );
    97  				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
    98  					// IE returns 0 when zIndex is not specified
    99  					// other browsers return a string
   100  					// we ignore the case of nested elements with an explicit value of 0
   101  					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
   102  					value = parseInt( elem.css( "zIndex" ), 10 );
   103  					if ( !isNaN( value ) && value !== 0 ) {
   104  						return value;
   105  					}
   106  				}
   107  				elem = elem.parent();
   108  			}
   109  		}
   110  
   111  		return 0;
   112  	},
   113  
   114  	uniqueId: function() {
   115  		return this.each(function() {
   116  			if ( !this.id ) {
   117  				this.id = "ui-id-" + (++uuid);
   118  			}
   119  		});
   120  	},
   121  
   122  	removeUniqueId: function() {
   123  		return this.each(function() {
   124  			if ( runiqueId.test( this.id ) ) {
   125  				$( this ).removeAttr( "id" );
   126  			}
   127  		});
   128  	}
   129  });
   130  
   131  // selectors
   132  function focusable( element, isTabIndexNotNaN ) {
   133  	var map, mapName, img,
   134  		nodeName = element.nodeName.toLowerCase();
   135  	if ( "area" === nodeName ) {
   136  		map = element.parentNode;
   137  		mapName = map.name;
   138  		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
   139  			return false;
   140  		}
   141  		img = $( "img[usemap=#" + mapName + "]" )[0];
   142  		return !!img && visible( img );
   143  	}
   144  	return ( /input|select|textarea|button|object/.test( nodeName ) ?
   145  		!element.disabled :
   146  		"a" === nodeName ?
   147  			element.href || isTabIndexNotNaN :
   148  			isTabIndexNotNaN) &&
   149  		// the element and all of its ancestors must be visible
   150  		visible( element );
   151  }
   152  
   153  function visible( element ) {
   154  	return $.expr.filters.visible( element ) &&
   155  		!$( element ).parents().addBack().filter(function() {
   156  			return $.css( this, "visibility" ) === "hidden";
   157  		}).length;
   158  }
   159  
   160  $.extend( $.expr[ ":" ], {
   161  	data: $.expr.createPseudo ?
   162  		$.expr.createPseudo(function( dataName ) {
   163  			return function( elem ) {
   164  				return !!$.data( elem, dataName );
   165  			};
   166  		}) :
   167  		// support: jQuery <1.8
   168  		function( elem, i, match ) {
   169  			return !!$.data( elem, match[ 3 ] );
   170  		},
   171  
   172  	focusable: function( element ) {
   173  		return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
   174  	},
   175  
   176  	tabbable: function( element ) {
   177  		var tabIndex = $.attr( element, "tabindex" ),
   178  			isTabIndexNaN = isNaN( tabIndex );
   179  		return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
   180  	}
   181  });
   182  
   183  // support: jQuery <1.8
   184  if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
   185  	$.each( [ "Width", "Height" ], function( i, name ) {
   186  		var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
   187  			type = name.toLowerCase(),
   188  			orig = {
   189  				innerWidth: $.fn.innerWidth,
   190  				innerHeight: $.fn.innerHeight,
   191  				outerWidth: $.fn.outerWidth,
   192  				outerHeight: $.fn.outerHeight
   193  			};
   194  
   195  		function reduce( elem, size, border, margin ) {
   196  			$.each( side, function() {
   197  				size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
   198  				if ( border ) {
   199  					size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
   200  				}
   201  				if ( margin ) {
   202  					size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
   203  				}
   204  			});
   205  			return size;
   206  		}
   207  
   208  		$.fn[ "inner" + name ] = function( size ) {
   209  			if ( size === undefined ) {
   210  				return orig[ "inner" + name ].call( this );
   211  			}
   212  
   213  			return this.each(function() {
   214  				$( this ).css( type, reduce( this, size ) + "px" );
   215  			});
   216  		};
   217  
   218  		$.fn[ "outer" + name] = function( size, margin ) {
   219  			if ( typeof size !== "number" ) {
   220  				return orig[ "outer" + name ].call( this, size );
   221  			}
   222  
   223  			return this.each(function() {
   224  				$( this).css( type, reduce( this, size, true, margin ) + "px" );
   225  			});
   226  		};
   227  	});
   228  }
   229  
   230  // support: jQuery <1.8
   231  if ( !$.fn.addBack ) {
   232  	$.fn.addBack = function( selector ) {
   233  		return this.add( selector == null ?
   234  			this.prevObject : this.prevObject.filter( selector )
   235  		);
   236  	};
   237  }
   238  
   239  // support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
   240  if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
   241  	$.fn.removeData = (function( removeData ) {
   242  		return function( key ) {
   243  			if ( arguments.length ) {
   244  				return removeData.call( this, $.camelCase( key ) );
   245  			} else {
   246  				return removeData.call( this );
   247  			}
   248  		};
   249  	})( $.fn.removeData );
   250  }
   251  
   252  
   253  
   254  
   255  
   256  // deprecated
   257  $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
   258  
   259  $.support.selectstart = "onselectstart" in document.createElement( "div" );
   260  $.fn.extend({
   261  	disableSelection: function() {
   262  		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
   263  			".ui-disableSelection", function( event ) {
   264  				event.preventDefault();
   265  			});
   266  	},
   267  
   268  	enableSelection: function() {
   269  		return this.unbind( ".ui-disableSelection" );
   270  	}
   271  });
   272  
   273  $.extend( $.ui, {
   274  	// $.ui.plugin is deprecated. Use $.widget() extensions instead.
   275  	plugin: {
   276  		add: function( module, option, set ) {
   277  			var i,
   278  				proto = $.ui[ module ].prototype;
   279  			for ( i in set ) {
   280  				proto.plugins[ i ] = proto.plugins[ i ] || [];
   281  				proto.plugins[ i ].push( [ option, set[ i ] ] );
   282  			}
   283  		},
   284  		call: function( instance, name, args ) {
   285  			var i,
   286  				set = instance.plugins[ name ];
   287  			if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
   288  				return;
   289  			}
   290  
   291  			for ( i = 0; i < set.length; i++ ) {
   292  				if ( instance.options[ set[ i ][ 0 ] ] ) {
   293  					set[ i ][ 1 ].apply( instance.element, args );
   294  				}
   295  			}
   296  		}
   297  	},
   298  
   299  	// only used by resizable
   300  	hasScroll: function( el, a ) {
   301  
   302  		//If overflow is hidden, the element might have extra content, but the user wants to hide it
   303  		if ( $( el ).css( "overflow" ) === "hidden") {
   304  			return false;
   305  		}
   306  
   307  		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
   308  			has = false;
   309  
   310  		if ( el[ scroll ] > 0 ) {
   311  			return true;
   312  		}
   313  
   314  		// TODO: determine which cases actually cause this to happen
   315  		// if the element doesn't have the scroll set, see if it's possible to
   316  		// set the scroll
   317  		el[ scroll ] = 1;
   318  		has = ( el[ scroll ] > 0 );
   319  		el[ scroll ] = 0;
   320  		return has;
   321  	}
   322  });
   323  
   324  })( jQuery );
   325  
   326  /*!
   327   * jQuery UI Widget 1.10.4
   328   * http://jqueryui.com
   329   *
   330   * Copyright 2014 jQuery Foundation and other contributors
   331   * Released under the MIT license.
   332   * http://jquery.org/license
   333   *
   334   * http://api.jqueryui.com/jQuery.widget/
   335   */
   336  (function( $, undefined ) {
   337  
   338  var uuid = 0,
   339  	slice = Array.prototype.slice,
   340  	_cleanData = $.cleanData;
   341  $.cleanData = function( elems ) {
   342  	for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
   343  		try {
   344  			$( elem ).triggerHandler( "remove" );
   345  		// http://bugs.jquery.com/ticket/8235
   346  		} catch( e ) {}
   347  	}
   348  	_cleanData( elems );
   349  };
   350  
   351  $.widget = function( name, base, prototype ) {
   352  	var fullName, existingConstructor, constructor, basePrototype,
   353  		// proxiedPrototype allows the provided prototype to remain unmodified
   354  		// so that it can be used as a mixin for multiple widgets (#8876)
   355  		proxiedPrototype = {},
   356  		namespace = name.split( "." )[ 0 ];
   357  
   358  	name = name.split( "." )[ 1 ];
   359  	fullName = namespace + "-" + name;
   360  
   361  	if ( !prototype ) {
   362  		prototype = base;
   363  		base = $.Widget;
   364  	}
   365  
   366  	// create selector for plugin
   367  	$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
   368  		return !!$.data( elem, fullName );
   369  	};
   370  
   371  	$[ namespace ] = $[ namespace ] || {};
   372  	existingConstructor = $[ namespace ][ name ];
   373  	constructor = $[ namespace ][ name ] = function( options, element ) {
   374  		// allow instantiation without "new" keyword
   375  		if ( !this._createWidget ) {
   376  			return new constructor( options, element );
   377  		}
   378  
   379  		// allow instantiation without initializing for simple inheritance
   380  		// must use "new" keyword (the code above always passes args)
   381  		if ( arguments.length ) {
   382  			this._createWidget( options, element );
   383  		}
   384  	};
   385  	// extend with the existing constructor to carry over any static properties
   386  	$.extend( constructor, existingConstructor, {
   387  		version: prototype.version,
   388  		// copy the object used to create the prototype in case we need to
   389  		// redefine the widget later
   390  		_proto: $.extend( {}, prototype ),
   391  		// track widgets that inherit from this widget in case this widget is
   392  		// redefined after a widget inherits from it
   393  		_childConstructors: []
   394  	});
   395  
   396  	basePrototype = new base();
   397  	// we need to make the options hash a property directly on the new instance
   398  	// otherwise we'll modify the options hash on the prototype that we're
   399  	// inheriting from
   400  	basePrototype.options = $.widget.extend( {}, basePrototype.options );
   401  	$.each( prototype, function( prop, value ) {
   402  		if ( !$.isFunction( value ) ) {
   403  			proxiedPrototype[ prop ] = value;
   404  			return;
   405  		}
   406  		proxiedPrototype[ prop ] = (function() {
   407  			var _super = function() {
   408  					return base.prototype[ prop ].apply( this, arguments );
   409  				},
   410  				_superApply = function( args ) {
   411  					return base.prototype[ prop ].apply( this, args );
   412  				};
   413  			return function() {
   414  				var __super = this._super,
   415  					__superApply = this._superApply,
   416  					returnValue;
   417  
   418  				this._super = _super;
   419  				this._superApply = _superApply;
   420  
   421  				returnValue = value.apply( this, arguments );
   422  
   423  				this._super = __super;
   424  				this._superApply = __superApply;
   425  
   426  				return returnValue;
   427  			};
   428  		})();
   429  	});
   430  	constructor.prototype = $.widget.extend( basePrototype, {
   431  		// TODO: remove support for widgetEventPrefix
   432  		// always use the name + a colon as the prefix, e.g., draggable:start
   433  		// don't prefix for widgets that aren't DOM-based
   434  		widgetEventPrefix: existingConstructor ? (basePrototype.widgetEventPrefix || name) : name
   435  	}, proxiedPrototype, {
   436  		constructor: constructor,
   437  		namespace: namespace,
   438  		widgetName: name,
   439  		widgetFullName: fullName
   440  	});
   441  
   442  	// If this widget is being redefined then we need to find all widgets that
   443  	// are inheriting from it and redefine all of them so that they inherit from
   444  	// the new version of this widget. We're essentially trying to replace one
   445  	// level in the prototype chain.
   446  	if ( existingConstructor ) {
   447  		$.each( existingConstructor._childConstructors, function( i, child ) {
   448  			var childPrototype = child.prototype;
   449  
   450  			// redefine the child widget using the same prototype that was
   451  			// originally used, but inherit from the new version of the base
   452  			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
   453  		});
   454  		// remove the list of existing child constructors from the old constructor
   455  		// so the old child constructors can be garbage collected
   456  		delete existingConstructor._childConstructors;
   457  	} else {
   458  		base._childConstructors.push( constructor );
   459  	}
   460  
   461  	$.widget.bridge( name, constructor );
   462  };
   463  
   464  $.widget.extend = function( target ) {
   465  	var input = slice.call( arguments, 1 ),
   466  		inputIndex = 0,
   467  		inputLength = input.length,
   468  		key,
   469  		value;
   470  	for ( ; inputIndex < inputLength; inputIndex++ ) {
   471  		for ( key in input[ inputIndex ] ) {
   472  			value = input[ inputIndex ][ key ];
   473  			if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
   474  				// Clone objects
   475  				if ( $.isPlainObject( value ) ) {
   476  					target[ key ] = $.isPlainObject( target[ key ] ) ?
   477  						$.widget.extend( {}, target[ key ], value ) :
   478  						// Don't extend strings, arrays, etc. with objects
   479  						$.widget.extend( {}, value );
   480  				// Copy everything else by reference
   481  				} else {
   482  					target[ key ] = value;
   483  				}
   484  			}
   485  		}
   486  	}
   487  	return target;
   488  };
   489  
   490  $.widget.bridge = function( name, object ) {
   491  	var fullName = object.prototype.widgetFullName || name;
   492  	$.fn[ name ] = function( options ) {
   493  		var isMethodCall = typeof options === "string",
   494  			args = slice.call( arguments, 1 ),
   495  			returnValue = this;
   496  
   497  		// allow multiple hashes to be passed on init
   498  		options = !isMethodCall && args.length ?
   499  			$.widget.extend.apply( null, [ options ].concat(args) ) :
   500  			options;
   501  
   502  		if ( isMethodCall ) {
   503  			this.each(function() {
   504  				var methodValue,
   505  					instance = $.data( this, fullName );
   506  				if ( !instance ) {
   507  					return $.error( "cannot call methods on " + name + " prior to initialization; " +
   508  						"attempted to call method '" + options + "'" );
   509  				}
   510  				if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
   511  					return $.error( "no such method '" + options + "' for " + name + " widget instance" );
   512  				}
   513  				methodValue = instance[ options ].apply( instance, args );
   514  				if ( methodValue !== instance && methodValue !== undefined ) {
   515  					returnValue = methodValue && methodValue.jquery ?
   516  						returnValue.pushStack( methodValue.get() ) :
   517  						methodValue;
   518  					return false;
   519  				}
   520  			});
   521  		} else {
   522  			this.each(function() {
   523  				var instance = $.data( this, fullName );
   524  				if ( instance ) {
   525  					instance.option( options || {} )._init();
   526  				} else {
   527  					$.data( this, fullName, new object( options, this ) );
   528  				}
   529  			});
   530  		}
   531  
   532  		return returnValue;
   533  	};
   534  };
   535  
   536  $.Widget = function( /* options, element */ ) {};
   537  $.Widget._childConstructors = [];
   538  
   539  $.Widget.prototype = {
   540  	widgetName: "widget",
   541  	widgetEventPrefix: "",
   542  	defaultElement: "<div>",
   543  	options: {
   544  		disabled: false,
   545  
   546  		// callbacks
   547  		create: null
   548  	},
   549  	_createWidget: function( options, element ) {
   550  		element = $( element || this.defaultElement || this )[ 0 ];
   551  		this.element = $( element );
   552  		this.uuid = uuid++;
   553  		this.eventNamespace = "." + this.widgetName + this.uuid;
   554  		this.options = $.widget.extend( {},
   555  			this.options,
   556  			this._getCreateOptions(),
   557  			options );
   558  
   559  		this.bindings = $();
   560  		this.hoverable = $();
   561  		this.focusable = $();
   562  
   563  		if ( element !== this ) {
   564  			$.data( element, this.widgetFullName, this );
   565  			this._on( true, this.element, {
   566  				remove: function( event ) {
   567  					if ( event.target === element ) {
   568  						this.destroy();
   569  					}
   570  				}
   571  			});
   572  			this.document = $( element.style ?
   573  				// element within the document
   574  				element.ownerDocument :
   575  				// element is window or document
   576  				element.document || element );
   577  			this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
   578  		}
   579  
   580  		this._create();
   581  		this._trigger( "create", null, this._getCreateEventData() );
   582  		this._init();
   583  	},
   584  	_getCreateOptions: $.noop,
   585  	_getCreateEventData: $.noop,
   586  	_create: $.noop,
   587  	_init: $.noop,
   588  
   589  	destroy: function() {
   590  		this._destroy();
   591  		// we can probably remove the unbind calls in 2.0
   592  		// all event bindings should go through this._on()
   593  		this.element
   594  			.unbind( this.eventNamespace )
   595  			// 1.9 BC for #7810
   596  			// TODO remove dual storage
   597  			.removeData( this.widgetName )
   598  			.removeData( this.widgetFullName )
   599  			// support: jquery <1.6.3
   600  			// http://bugs.jquery.com/ticket/9413
   601  			.removeData( $.camelCase( this.widgetFullName ) );
   602  		this.widget()
   603  			.unbind( this.eventNamespace )
   604  			.removeAttr( "aria-disabled" )
   605  			.removeClass(
   606  				this.widgetFullName + "-disabled " +
   607  				"ui-state-disabled" );
   608  
   609  		// clean up events and states
   610  		this.bindings.unbind( this.eventNamespace );
   611  		this.hoverable.removeClass( "ui-state-hover" );
   612  		this.focusable.removeClass( "ui-state-focus" );
   613  	},
   614  	_destroy: $.noop,
   615  
   616  	widget: function() {
   617  		return this.element;
   618  	},
   619  
   620  	option: function( key, value ) {
   621  		var options = key,
   622  			parts,
   623  			curOption,
   624  			i;
   625  
   626  		if ( arguments.length === 0 ) {
   627  			// don't return a reference to the internal hash
   628  			return $.widget.extend( {}, this.options );
   629  		}
   630  
   631  		if ( typeof key === "string" ) {
   632  			// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
   633  			options = {};
   634  			parts = key.split( "." );
   635  			key = parts.shift();
   636  			if ( parts.length ) {
   637  				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
   638  				for ( i = 0; i < parts.length - 1; i++ ) {
   639  					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
   640  					curOption = curOption[ parts[ i ] ];
   641  				}
   642  				key = parts.pop();
   643  				if ( arguments.length === 1 ) {
   644  					return curOption[ key ] === undefined ? null : curOption[ key ];
   645  				}
   646  				curOption[ key ] = value;
   647  			} else {
   648  				if ( arguments.length === 1 ) {
   649  					return this.options[ key ] === undefined ? null : this.options[ key ];
   650  				}
   651  				options[ key ] = value;
   652  			}
   653  		}
   654  
   655  		this._setOptions( options );
   656  
   657  		return this;
   658  	},
   659  	_setOptions: function( options ) {
   660  		var key;
   661  
   662  		for ( key in options ) {
   663  			this._setOption( key, options[ key ] );
   664  		}
   665  
   666  		return this;
   667  	},
   668  	_setOption: function( key, value ) {
   669  		this.options[ key ] = value;
   670  
   671  		if ( key === "disabled" ) {
   672  			this.widget()
   673  				.toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
   674  				.attr( "aria-disabled", value );
   675  			this.hoverable.removeClass( "ui-state-hover" );
   676  			this.focusable.removeClass( "ui-state-focus" );
   677  		}
   678  
   679  		return this;
   680  	},
   681  
   682  	enable: function() {
   683  		return this._setOption( "disabled", false );
   684  	},
   685  	disable: function() {
   686  		return this._setOption( "disabled", true );
   687  	},
   688  
   689  	_on: function( suppressDisabledCheck, element, handlers ) {
   690  		var delegateElement,
   691  			instance = this;
   692  
   693  		// no suppressDisabledCheck flag, shuffle arguments
   694  		if ( typeof suppressDisabledCheck !== "boolean" ) {
   695  			handlers = element;
   696  			element = suppressDisabledCheck;
   697  			suppressDisabledCheck = false;
   698  		}
   699  
   700  		// no element argument, shuffle and use this.element
   701  		if ( !handlers ) {
   702  			handlers = element;
   703  			element = this.element;
   704  			delegateElement = this.widget();
   705  		} else {
   706  			// accept selectors, DOM elements
   707  			element = delegateElement = $( element );
   708  			this.bindings = this.bindings.add( element );
   709  		}
   710  
   711  		$.each( handlers, function( event, handler ) {
   712  			function handlerProxy() {
   713  				// allow widgets to customize the disabled handling
   714  				// - disabled as an array instead of boolean
   715  				// - disabled class as method for disabling individual parts
   716  				if ( !suppressDisabledCheck &&
   717  						( instance.options.disabled === true ||
   718  							$( this ).hasClass( "ui-state-disabled" ) ) ) {
   719  					return;
   720  				}
   721  				return ( typeof handler === "string" ? instance[ handler ] : handler )
   722  					.apply( instance, arguments );
   723  			}
   724  
   725  			// copy the guid so direct unbinding works
   726  			if ( typeof handler !== "string" ) {
   727  				handlerProxy.guid = handler.guid =
   728  					handler.guid || handlerProxy.guid || $.guid++;
   729  			}
   730  
   731  			var match = event.match( /^(\w+)\s*(.*)$/ ),
   732  				eventName = match[1] + instance.eventNamespace,
   733  				selector = match[2];
   734  			if ( selector ) {
   735  				delegateElement.delegate( selector, eventName, handlerProxy );
   736  			} else {
   737  				element.bind( eventName, handlerProxy );
   738  			}
   739  		});
   740  	},
   741  
   742  	_off: function( element, eventName ) {
   743  		eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
   744  		element.unbind( eventName ).undelegate( eventName );
   745  	},
   746  
   747  	_delay: function( handler, delay ) {
   748  		function handlerProxy() {
   749  			return ( typeof handler === "string" ? instance[ handler ] : handler )
   750  				.apply( instance, arguments );
   751  		}
   752  		var instance = this;
   753  		return setTimeout( handlerProxy, delay || 0 );
   754  	},
   755  
   756  	_hoverable: function( element ) {
   757  		this.hoverable = this.hoverable.add( element );
   758  		this._on( element, {
   759  			mouseenter: function( event ) {
   760  				$( event.currentTarget ).addClass( "ui-state-hover" );
   761  			},
   762  			mouseleave: function( event ) {
   763  				$( event.currentTarget ).removeClass( "ui-state-hover" );
   764  			}
   765  		});
   766  	},
   767  
   768  	_focusable: function( element ) {
   769  		this.focusable = this.focusable.add( element );
   770  		this._on( element, {
   771  			focusin: function( event ) {
   772  				$( event.currentTarget ).addClass( "ui-state-focus" );
   773  			},
   774  			focusout: function( event ) {
   775  				$( event.currentTarget ).removeClass( "ui-state-focus" );
   776  			}
   777  		});
   778  	},
   779  
   780  	_trigger: function( type, event, data ) {
   781  		var prop, orig,
   782  			callback = this.options[ type ];
   783  
   784  		data = data || {};
   785  		event = $.Event( event );
   786  		event.type = ( type === this.widgetEventPrefix ?
   787  			type :
   788  			this.widgetEventPrefix + type ).toLowerCase();
   789  		// the original event may come from any element
   790  		// so we need to reset the target on the new event
   791  		event.target = this.element[ 0 ];
   792  
   793  		// copy original event properties over to the new event
   794  		orig = event.originalEvent;
   795  		if ( orig ) {
   796  			for ( prop in orig ) {
   797  				if ( !( prop in event ) ) {
   798  					event[ prop ] = orig[ prop ];
   799  				}
   800  			}
   801  		}
   802  
   803  		this.element.trigger( event, data );
   804  		return !( $.isFunction( callback ) &&
   805  			callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
   806  			event.isDefaultPrevented() );
   807  	}
   808  };
   809  
   810  $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
   811  	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
   812  		if ( typeof options === "string" ) {
   813  			options = { effect: options };
   814  		}
   815  		var hasOptions,
   816  			effectName = !options ?
   817  				method :
   818  				options === true || typeof options === "number" ?
   819  					defaultEffect :
   820  					options.effect || defaultEffect;
   821  		options = options || {};
   822  		if ( typeof options === "number" ) {
   823  			options = { duration: options };
   824  		}
   825  		hasOptions = !$.isEmptyObject( options );
   826  		options.complete = callback;
   827  		if ( options.delay ) {
   828  			element.delay( options.delay );
   829  		}
   830  		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
   831  			element[ method ]( options );
   832  		} else if ( effectName !== method && element[ effectName ] ) {
   833  			element[ effectName ]( options.duration, options.easing, callback );
   834  		} else {
   835  			element.queue(function( next ) {
   836  				$( this )[ method ]();
   837  				if ( callback ) {
   838  					callback.call( element[ 0 ] );
   839  				}
   840  				next();
   841  			});
   842  		}
   843  	};
   844  });
   845  
   846  })( jQuery );
   847  
   848  /*!
   849   * jQuery UI Mouse 1.10.4
   850   * http://jqueryui.com
   851   *
   852   * Copyright 2014 jQuery Foundation and other contributors
   853   * Released under the MIT license.
   854   * http://jquery.org/license
   855   *
   856   * http://api.jqueryui.com/mouse/
   857   *
   858   * Depends:
   859   *	jquery.ui.widget.js
   860   */
   861  (function( $, undefined ) {
   862  
   863  var mouseHandled = false;
   864  $( document ).mouseup( function() {
   865  	mouseHandled = false;
   866  });
   867  
   868  $.widget("ui.mouse", {
   869  	version: "1.10.4",
   870  	options: {
   871  		cancel: "input,textarea,button,select,option",
   872  		distance: 1,
   873  		delay: 0
   874  	},
   875  	_mouseInit: function() {
   876  		var that = this;
   877  
   878  		this.element
   879  			.bind("mousedown."+this.widgetName, function(event) {
   880  				return that._mouseDown(event);
   881  			})
   882  			.bind("click."+this.widgetName, function(event) {
   883  				if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
   884  					$.removeData(event.target, that.widgetName + ".preventClickEvent");
   885  					event.stopImmediatePropagation();
   886  					return false;
   887  				}
   888  			});
   889  
   890  		this.started = false;
   891  	},
   892  
   893  	// TODO: make sure destroying one instance of mouse doesn't mess with
   894  	// other instances of mouse
   895  	_mouseDestroy: function() {
   896  		this.element.unbind("."+this.widgetName);
   897  		if ( this._mouseMoveDelegate ) {
   898  			$(document)
   899  				.unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
   900  				.unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
   901  		}
   902  	},
   903  
   904  	_mouseDown: function(event) {
   905  		// don't let more than one widget handle mouseStart
   906  		if( mouseHandled ) { return; }
   907  
   908  		// we may have missed mouseup (out of window)
   909  		(this._mouseStarted && this._mouseUp(event));
   910  
   911  		this._mouseDownEvent = event;
   912  
   913  		var that = this,
   914  			btnIsLeft = (event.which === 1),
   915  			// event.target.nodeName works around a bug in IE 8 with
   916  			// disabled inputs (#7620)
   917  			elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
   918  		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
   919  			return true;
   920  		}
   921  
   922  		this.mouseDelayMet = !this.options.delay;
   923  		if (!this.mouseDelayMet) {
   924  			this._mouseDelayTimer = setTimeout(function() {
   925  				that.mouseDelayMet = true;
   926  			}, this.options.delay);
   927  		}
   928  
   929  		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
   930  			this._mouseStarted = (this._mouseStart(event) !== false);
   931  			if (!this._mouseStarted) {
   932  				event.preventDefault();
   933  				return true;
   934  			}
   935  		}
   936  
   937  		// Click event may never have fired (Gecko & Opera)
   938  		if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
   939  			$.removeData(event.target, this.widgetName + ".preventClickEvent");
   940  		}
   941  
   942  		// these delegates are required to keep context
   943  		this._mouseMoveDelegate = function(event) {
   944  			return that._mouseMove(event);
   945  		};
   946  		this._mouseUpDelegate = function(event) {
   947  			return that._mouseUp(event);
   948  		};
   949  		$(document)
   950  			.bind("mousemove."+this.widgetName, this._mouseMoveDelegate)
   951  			.bind("mouseup."+this.widgetName, this._mouseUpDelegate);
   952  
   953  		event.preventDefault();
   954  
   955  		mouseHandled = true;
   956  		return true;
   957  	},
   958  
   959  	_mouseMove: function(event) {
   960  		// IE mouseup check - mouseup happened when mouse was out of window
   961  		if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
   962  			return this._mouseUp(event);
   963  		}
   964  
   965  		if (this._mouseStarted) {
   966  			this._mouseDrag(event);
   967  			return event.preventDefault();
   968  		}
   969  
   970  		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
   971  			this._mouseStarted =
   972  				(this._mouseStart(this._mouseDownEvent, event) !== false);
   973  			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
   974  		}
   975  
   976  		return !this._mouseStarted;
   977  	},
   978  
   979  	_mouseUp: function(event) {
   980  		$(document)
   981  			.unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
   982  			.unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
   983  
   984  		if (this._mouseStarted) {
   985  			this._mouseStarted = false;
   986  
   987  			if (event.target === this._mouseDownEvent.target) {
   988  				$.data(event.target, this.widgetName + ".preventClickEvent", true);
   989  			}
   990  
   991  			this._mouseStop(event);
   992  		}
   993  
   994  		return false;
   995  	},
   996  
   997  	_mouseDistanceMet: function(event) {
   998  		return (Math.max(
   999  				Math.abs(this._mouseDownEvent.pageX - event.pageX),
  1000  				Math.abs(this._mouseDownEvent.pageY - event.pageY)
  1001  			) >= this.options.distance
  1002  		);
  1003  	},
  1004  
  1005  	_mouseDelayMet: function(/* event */) {
  1006  		return this.mouseDelayMet;
  1007  	},
  1008  
  1009  	// These are placeholder methods, to be overriden by extending plugin
  1010  	_mouseStart: function(/* event */) {},
  1011  	_mouseDrag: function(/* event */) {},
  1012  	_mouseStop: function(/* event */) {},
  1013  	_mouseCapture: function(/* event */) { return true; }
  1014  });
  1015  
  1016  })(jQuery);
  1017  
  1018  /*!
  1019   * jQuery UI Position 1.10.4
  1020   * http://jqueryui.com
  1021   *
  1022   * Copyright 2014 jQuery Foundation and other contributors
  1023   * Released under the MIT license.
  1024   * http://jquery.org/license
  1025   *
  1026   * http://api.jqueryui.com/position/
  1027   */
  1028  (function( $, undefined ) {
  1029  
  1030  $.ui = $.ui || {};
  1031  
  1032  var cachedScrollbarWidth,
  1033  	max = Math.max,
  1034  	abs = Math.abs,
  1035  	round = Math.round,
  1036  	rhorizontal = /left|center|right/,
  1037  	rvertical = /top|center|bottom/,
  1038  	roffset = /[\+\-]\d+(\.[\d]+)?%?/,
  1039  	rposition = /^\w+/,
  1040  	rpercent = /%$/,
  1041  	_position = $.fn.position;
  1042  
  1043  function getOffsets( offsets, width, height ) {
  1044  	return [
  1045  		parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
  1046  		parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
  1047  	];
  1048  }
  1049  
  1050  function parseCss( element, property ) {
  1051  	return parseInt( $.css( element, property ), 10 ) || 0;
  1052  }
  1053  
  1054  function getDimensions( elem ) {
  1055  	var raw = elem[0];
  1056  	if ( raw.nodeType === 9 ) {
  1057  		return {
  1058  			width: elem.width(),
  1059  			height: elem.height(),
  1060  			offset: { top: 0, left: 0 }
  1061  		};
  1062  	}
  1063  	if ( $.isWindow( raw ) ) {
  1064  		return {
  1065  			width: elem.width(),
  1066  			height: elem.height(),
  1067  			offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
  1068  		};
  1069  	}
  1070  	if ( raw.preventDefault ) {
  1071  		return {
  1072  			width: 0,
  1073  			height: 0,
  1074  			offset: { top: raw.pageY, left: raw.pageX }
  1075  		};
  1076  	}
  1077  	return {
  1078  		width: elem.outerWidth(),
  1079  		height: elem.outerHeight(),
  1080  		offset: elem.offset()
  1081  	};
  1082  }
  1083  
  1084  $.position = {
  1085  	scrollbarWidth: function() {
  1086  		if ( cachedScrollbarWidth !== undefined ) {
  1087  			return cachedScrollbarWidth;
  1088  		}
  1089  		var w1, w2,
  1090  			div = $( "<div style='display:block;position:absolute;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
  1091  			innerDiv = div.children()[0];
  1092  
  1093  		$( "body" ).append( div );
  1094  		w1 = innerDiv.offsetWidth;
  1095  		div.css( "overflow", "scroll" );
  1096  
  1097  		w2 = innerDiv.offsetWidth;
  1098  
  1099  		if ( w1 === w2 ) {
  1100  			w2 = div[0].clientWidth;
  1101  		}
  1102  
  1103  		div.remove();
  1104  
  1105  		return (cachedScrollbarWidth = w1 - w2);
  1106  	},
  1107  	getScrollInfo: function( within ) {
  1108  		var overflowX = within.isWindow || within.isDocument ? "" :
  1109  				within.element.css( "overflow-x" ),
  1110  			overflowY = within.isWindow || within.isDocument ? "" :
  1111  				within.element.css( "overflow-y" ),
  1112  			hasOverflowX = overflowX === "scroll" ||
  1113  				( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
  1114  			hasOverflowY = overflowY === "scroll" ||
  1115  				( overflowY === "auto" && within.height < within.element[0].scrollHeight );
  1116  		return {
  1117  			width: hasOverflowY ? $.position.scrollbarWidth() : 0,
  1118  			height: hasOverflowX ? $.position.scrollbarWidth() : 0
  1119  		};
  1120  	},
  1121  	getWithinInfo: function( element ) {
  1122  		var withinElement = $( element || window ),
  1123  			isWindow = $.isWindow( withinElement[0] ),
  1124  			isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9;
  1125  		return {
  1126  			element: withinElement,
  1127  			isWindow: isWindow,
  1128  			isDocument: isDocument,
  1129  			offset: withinElement.offset() || { left: 0, top: 0 },
  1130  			scrollLeft: withinElement.scrollLeft(),
  1131  			scrollTop: withinElement.scrollTop(),
  1132  			width: isWindow ? withinElement.width() : withinElement.outerWidth(),
  1133  			height: isWindow ? withinElement.height() : withinElement.outerHeight()
  1134  		};
  1135  	}
  1136  };
  1137  
  1138  $.fn.position = function( options ) {
  1139  	if ( !options || !options.of ) {
  1140  		return _position.apply( this, arguments );
  1141  	}
  1142  
  1143  	// make a copy, we don't want to modify arguments
  1144  	options = $.extend( {}, options );
  1145  
  1146  	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
  1147  		target = $( options.of ),
  1148  		within = $.position.getWithinInfo( options.within ),
  1149  		scrollInfo = $.position.getScrollInfo( within ),
  1150  		collision = ( options.collision || "flip" ).split( " " ),
  1151  		offsets = {};
  1152  
  1153  	dimensions = getDimensions( target );
  1154  	if ( target[0].preventDefault ) {
  1155  		// force left top to allow flipping
  1156  		options.at = "left top";
  1157  	}
  1158  	targetWidth = dimensions.width;
  1159  	targetHeight = dimensions.height;
  1160  	targetOffset = dimensions.offset;
  1161  	// clone to reuse original targetOffset later
  1162  	basePosition = $.extend( {}, targetOffset );
  1163  
  1164  	// force my and at to have valid horizontal and vertical positions
  1165  	// if a value is missing or invalid, it will be converted to center
  1166  	$.each( [ "my", "at" ], function() {
  1167  		var pos = ( options[ this ] || "" ).split( " " ),
  1168  			horizontalOffset,
  1169  			verticalOffset;
  1170  
  1171  		if ( pos.length === 1) {
  1172  			pos = rhorizontal.test( pos[ 0 ] ) ?
  1173  				pos.concat( [ "center" ] ) :
  1174  				rvertical.test( pos[ 0 ] ) ?
  1175  					[ "center" ].concat( pos ) :
  1176  					[ "center", "center" ];
  1177  		}
  1178  		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
  1179  		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
  1180  
  1181  		// calculate offsets
  1182  		horizontalOffset = roffset.exec( pos[ 0 ] );
  1183  		verticalOffset = roffset.exec( pos[ 1 ] );
  1184  		offsets[ this ] = [
  1185  			horizontalOffset ? horizontalOffset[ 0 ] : 0,
  1186  			verticalOffset ? verticalOffset[ 0 ] : 0
  1187  		];
  1188  
  1189  		// reduce to just the positions without the offsets
  1190  		options[ this ] = [
  1191  			rposition.exec( pos[ 0 ] )[ 0 ],
  1192  			rposition.exec( pos[ 1 ] )[ 0 ]
  1193  		];
  1194  	});
  1195  
  1196  	// normalize collision option
  1197  	if ( collision.length === 1 ) {
  1198  		collision[ 1 ] = collision[ 0 ];
  1199  	}
  1200  
  1201  	if ( options.at[ 0 ] === "right" ) {
  1202  		basePosition.left += targetWidth;
  1203  	} else if ( options.at[ 0 ] === "center" ) {
  1204  		basePosition.left += targetWidth / 2;
  1205  	}
  1206  
  1207  	if ( options.at[ 1 ] === "bottom" ) {
  1208  		basePosition.top += targetHeight;
  1209  	} else if ( options.at[ 1 ] === "center" ) {
  1210  		basePosition.top += targetHeight / 2;
  1211  	}
  1212  
  1213  	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
  1214  	basePosition.left += atOffset[ 0 ];
  1215  	basePosition.top += atOffset[ 1 ];
  1216  
  1217  	return this.each(function() {
  1218  		var collisionPosition, using,
  1219  			elem = $( this ),
  1220  			elemWidth = elem.outerWidth(),
  1221  			elemHeight = elem.outerHeight(),
  1222  			marginLeft = parseCss( this, "marginLeft" ),
  1223  			marginTop = parseCss( this, "marginTop" ),
  1224  			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
  1225  			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
  1226  			position = $.extend( {}, basePosition ),
  1227  			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
  1228  
  1229  		if ( options.my[ 0 ] === "right" ) {
  1230  			position.left -= elemWidth;
  1231  		} else if ( options.my[ 0 ] === "center" ) {
  1232  			position.left -= elemWidth / 2;
  1233  		}
  1234  
  1235  		if ( options.my[ 1 ] === "bottom" ) {
  1236  			position.top -= elemHeight;
  1237  		} else if ( options.my[ 1 ] === "center" ) {
  1238  			position.top -= elemHeight / 2;
  1239  		}
  1240  
  1241  		position.left += myOffset[ 0 ];
  1242  		position.top += myOffset[ 1 ];
  1243  
  1244  		// if the browser doesn't support fractions, then round for consistent results
  1245  		if ( !$.support.offsetFractions ) {
  1246  			position.left = round( position.left );
  1247  			position.top = round( position.top );
  1248  		}
  1249  
  1250  		collisionPosition = {
  1251  			marginLeft: marginLeft,
  1252  			marginTop: marginTop
  1253  		};
  1254  
  1255  		$.each( [ "left", "top" ], function( i, dir ) {
  1256  			if ( $.ui.position[ collision[ i ] ] ) {
  1257  				$.ui.position[ collision[ i ] ][ dir ]( position, {
  1258  					targetWidth: targetWidth,
  1259  					targetHeight: targetHeight,
  1260  					elemWidth: elemWidth,
  1261  					elemHeight: elemHeight,
  1262  					collisionPosition: collisionPosition,
  1263  					collisionWidth: collisionWidth,
  1264  					collisionHeight: collisionHeight,
  1265  					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
  1266  					my: options.my,
  1267  					at: options.at,
  1268  					within: within,
  1269  					elem : elem
  1270  				});
  1271  			}
  1272  		});
  1273  
  1274  		if ( options.using ) {
  1275  			// adds feedback as second argument to using callback, if present
  1276  			using = function( props ) {
  1277  				var left = targetOffset.left - position.left,
  1278  					right = left + targetWidth - elemWidth,
  1279  					top = targetOffset.top - position.top,
  1280  					bottom = top + targetHeight - elemHeight,
  1281  					feedback = {
  1282  						target: {
  1283  							element: target,
  1284  							left: targetOffset.left,
  1285  							top: targetOffset.top,
  1286  							width: targetWidth,
  1287  							height: targetHeight
  1288  						},
  1289  						element: {
  1290  							element: elem,
  1291  							left: position.left,
  1292  							top: position.top,
  1293  							width: elemWidth,
  1294  							height: elemHeight
  1295  						},
  1296  						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
  1297  						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
  1298  					};
  1299  				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
  1300  					feedback.horizontal = "center";
  1301  				}
  1302  				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
  1303  					feedback.vertical = "middle";
  1304  				}
  1305  				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
  1306  					feedback.important = "horizontal";
  1307  				} else {
  1308  					feedback.important = "vertical";
  1309  				}
  1310  				options.using.call( this, props, feedback );
  1311  			};
  1312  		}
  1313  
  1314  		elem.offset( $.extend( position, { using: using } ) );
  1315  	});
  1316  };
  1317  
  1318  $.ui.position = {
  1319  	fit: {
  1320  		left: function( position, data ) {
  1321  			var within = data.within,
  1322  				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
  1323  				outerWidth = within.width,
  1324  				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
  1325  				overLeft = withinOffset - collisionPosLeft,
  1326  				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
  1327  				newOverRight;
  1328  
  1329  			// element is wider than within
  1330  			if ( data.collisionWidth > outerWidth ) {
  1331  				// element is initially over the left side of within
  1332  				if ( overLeft > 0 && overRight <= 0 ) {
  1333  					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
  1334  					position.left += overLeft - newOverRight;
  1335  				// element is initially over right side of within
  1336  				} else if ( overRight > 0 && overLeft <= 0 ) {
  1337  					position.left = withinOffset;
  1338  				// element is initially over both left and right sides of within
  1339  				} else {
  1340  					if ( overLeft > overRight ) {
  1341  						position.left = withinOffset + outerWidth - data.collisionWidth;
  1342  					} else {
  1343  						position.left = withinOffset;
  1344  					}
  1345  				}
  1346  			// too far left -> align with left edge
  1347  			} else if ( overLeft > 0 ) {
  1348  				position.left += overLeft;
  1349  			// too far right -> align with right edge
  1350  			} else if ( overRight > 0 ) {
  1351  				position.left -= overRight;
  1352  			// adjust based on position and margin
  1353  			} else {
  1354  				position.left = max( position.left - collisionPosLeft, position.left );
  1355  			}
  1356  		},
  1357  		top: function( position, data ) {
  1358  			var within = data.within,
  1359  				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
  1360  				outerHeight = data.within.height,
  1361  				collisionPosTop = position.top - data.collisionPosition.marginTop,
  1362  				overTop = withinOffset - collisionPosTop,
  1363  				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
  1364  				newOverBottom;
  1365  
  1366  			// element is taller than within
  1367  			if ( data.collisionHeight > outerHeight ) {
  1368  				// element is initially over the top of within
  1369  				if ( overTop > 0 && overBottom <= 0 ) {
  1370  					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
  1371  					position.top += overTop - newOverBottom;
  1372  				// element is initially over bottom of within
  1373  				} else if ( overBottom > 0 && overTop <= 0 ) {
  1374  					position.top = withinOffset;
  1375  				// element is initially over both top and bottom of within
  1376  				} else {
  1377  					if ( overTop > overBottom ) {
  1378  						position.top = withinOffset + outerHeight - data.collisionHeight;
  1379  					} else {
  1380  						position.top = withinOffset;
  1381  					}
  1382  				}
  1383  			// too far up -> align with top
  1384  			} else if ( overTop > 0 ) {
  1385  				position.top += overTop;
  1386  			// too far down -> align with bottom edge
  1387  			} else if ( overBottom > 0 ) {
  1388  				position.top -= overBottom;
  1389  			// adjust based on position and margin
  1390  			} else {
  1391  				position.top = max( position.top - collisionPosTop, position.top );
  1392  			}
  1393  		}
  1394  	},
  1395  	flip: {
  1396  		left: function( position, data ) {
  1397  			var within = data.within,
  1398  				withinOffset = within.offset.left + within.scrollLeft,
  1399  				outerWidth = within.width,
  1400  				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
  1401  				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
  1402  				overLeft = collisionPosLeft - offsetLeft,
  1403  				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
  1404  				myOffset = data.my[ 0 ] === "left" ?
  1405  					-data.elemWidth :
  1406  					data.my[ 0 ] === "right" ?
  1407  						data.elemWidth :
  1408  						0,
  1409  				atOffset = data.at[ 0 ] === "left" ?
  1410  					data.targetWidth :
  1411  					data.at[ 0 ] === "right" ?
  1412  						-data.targetWidth :
  1413  						0,
  1414  				offset = -2 * data.offset[ 0 ],
  1415  				newOverRight,
  1416  				newOverLeft;
  1417  
  1418  			if ( overLeft < 0 ) {
  1419  				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
  1420  				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
  1421  					position.left += myOffset + atOffset + offset;
  1422  				}
  1423  			}
  1424  			else if ( overRight > 0 ) {
  1425  				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
  1426  				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
  1427  					position.left += myOffset + atOffset + offset;
  1428  				}
  1429  			}
  1430  		},
  1431  		top: function( position, data ) {
  1432  			var within = data.within,
  1433  				withinOffset = within.offset.top + within.scrollTop,
  1434  				outerHeight = within.height,
  1435  				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
  1436  				collisionPosTop = position.top - data.collisionPosition.marginTop,
  1437  				overTop = collisionPosTop - offsetTop,
  1438  				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
  1439  				top = data.my[ 1 ] === "top",
  1440  				myOffset = top ?
  1441  					-data.elemHeight :
  1442  					data.my[ 1 ] === "bottom" ?
  1443  						data.elemHeight :
  1444  						0,
  1445  				atOffset = data.at[ 1 ] === "top" ?
  1446  					data.targetHeight :
  1447  					data.at[ 1 ] === "bottom" ?
  1448  						-data.targetHeight :
  1449  						0,
  1450  				offset = -2 * data.offset[ 1 ],
  1451  				newOverTop,
  1452  				newOverBottom;
  1453  			if ( overTop < 0 ) {
  1454  				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
  1455  				if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
  1456  					position.top += myOffset + atOffset + offset;
  1457  				}
  1458  			}
  1459  			else if ( overBottom > 0 ) {
  1460  				newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
  1461  				if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
  1462  					position.top += myOffset + atOffset + offset;
  1463  				}
  1464  			}
  1465  		}
  1466  	},
  1467  	flipfit: {
  1468  		left: function() {
  1469  			$.ui.position.flip.left.apply( this, arguments );
  1470  			$.ui.position.fit.left.apply( this, arguments );
  1471  		},
  1472  		top: function() {
  1473  			$.ui.position.flip.top.apply( this, arguments );
  1474  			$.ui.position.fit.top.apply( this, arguments );
  1475  		}
  1476  	}
  1477  };
  1478  
  1479  // fraction support test
  1480  (function () {
  1481  	var testElement, testElementParent, testElementStyle, offsetLeft, i,
  1482  		body = document.getElementsByTagName( "body" )[ 0 ],
  1483  		div = document.createElement( "div" );
  1484  
  1485  	//Create a "fake body" for testing based on method used in jQuery.support
  1486  	testElement = document.createElement( body ? "div" : "body" );
  1487  	testElementStyle = {
  1488  		visibility: "hidden",
  1489  		width: 0,
  1490  		height: 0,
  1491  		border: 0,
  1492  		margin: 0,
  1493  		background: "none"
  1494  	};
  1495  	if ( body ) {
  1496  		$.extend( testElementStyle, {
  1497  			position: "absolute",
  1498  			left: "-1000px",
  1499  			top: "-1000px"
  1500  		});
  1501  	}
  1502  	for ( i in testElementStyle ) {
  1503  		testElement.style[ i ] = testElementStyle[ i ];
  1504  	}
  1505  	testElement.appendChild( div );
  1506  	testElementParent = body || document.documentElement;
  1507  	testElementParent.insertBefore( testElement, testElementParent.firstChild );
  1508  
  1509  	div.style.cssText = "position: absolute; left: 10.7432222px;";
  1510  
  1511  	offsetLeft = $( div ).offset().left;
  1512  	$.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;
  1513  
  1514  	testElement.innerHTML = "";
  1515  	testElementParent.removeChild( testElement );
  1516  })();
  1517  
  1518  }( jQuery ) );
  1519  
  1520  /*!
  1521   * jQuery UI Button 1.10.4
  1522   * http://jqueryui.com
  1523   *
  1524   * Copyright 2014 jQuery Foundation and other contributors
  1525   * Released under the MIT license.
  1526   * http://jquery.org/license
  1527   *
  1528   * http://api.jqueryui.com/button/
  1529   *
  1530   * Depends:
  1531   *	jquery.ui.core.js
  1532   *	jquery.ui.widget.js
  1533   */
  1534  (function( $, undefined ) {
  1535  
  1536  var lastActive,
  1537  	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
  1538  	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
  1539  	formResetHandler = function() {
  1540  		var form = $( this );
  1541  		setTimeout(function() {
  1542  			form.find( ":ui-button" ).button( "refresh" );
  1543  		}, 1 );
  1544  	},
  1545  	radioGroup = function( radio ) {
  1546  		var name = radio.name,
  1547  			form = radio.form,
  1548  			radios = $( [] );
  1549  		if ( name ) {
  1550  			name = name.replace( /'/g, "\\'" );
  1551  			if ( form ) {
  1552  				radios = $( form ).find( "[name='" + name + "']" );
  1553  			} else {
  1554  				radios = $( "[name='" + name + "']", radio.ownerDocument )
  1555  					.filter(function() {
  1556  						return !this.form;
  1557  					});
  1558  			}
  1559  		}
  1560  		return radios;
  1561  	};
  1562  
  1563  $.widget( "ui.button", {
  1564  	version: "1.10.4",
  1565  	defaultElement: "<button>",
  1566  	options: {
  1567  		disabled: null,
  1568  		text: true,
  1569  		label: null,
  1570  		icons: {
  1571  			primary: null,
  1572  			secondary: null
  1573  		}
  1574  	},
  1575  	_create: function() {
  1576  		this.element.closest( "form" )
  1577  			.unbind( "reset" + this.eventNamespace )
  1578  			.bind( "reset" + this.eventNamespace, formResetHandler );
  1579  
  1580  		if ( typeof this.options.disabled !== "boolean" ) {
  1581  			this.options.disabled = !!this.element.prop( "disabled" );
  1582  		} else {
  1583  			this.element.prop( "disabled", this.options.disabled );
  1584  		}
  1585  
  1586  		this._determineButtonType();
  1587  		this.hasTitle = !!this.buttonElement.attr( "title" );
  1588  
  1589  		var that = this,
  1590  			options = this.options,
  1591  			toggleButton = this.type === "checkbox" || this.type === "radio",
  1592  			activeClass = !toggleButton ? "ui-state-active" : "";
  1593  
  1594  		if ( options.label === null ) {
  1595  			options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
  1596  		}
  1597  
  1598  		this._hoverable( this.buttonElement );
  1599  
  1600  		this.buttonElement
  1601  			.addClass( baseClasses )
  1602  			.attr( "role", "button" )
  1603  			.bind( "mouseenter" + this.eventNamespace, function() {
  1604  				if ( options.disabled ) {
  1605  					return;
  1606  				}
  1607  				if ( this === lastActive ) {
  1608  					$( this ).addClass( "ui-state-active" );
  1609  				}
  1610  			})
  1611  			.bind( "mouseleave" + this.eventNamespace, function() {
  1612  				if ( options.disabled ) {
  1613  					return;
  1614  				}
  1615  				$( this ).removeClass( activeClass );
  1616  			})
  1617  			.bind( "click" + this.eventNamespace, function( event ) {
  1618  				if ( options.disabled ) {
  1619  					event.preventDefault();
  1620  					event.stopImmediatePropagation();
  1621  				}
  1622  			});
  1623  
  1624  		// Can't use _focusable() because the element that receives focus
  1625  		// and the element that gets the ui-state-focus class are different
  1626  		this._on({
  1627  			focus: function() {
  1628  				this.buttonElement.addClass( "ui-state-focus" );
  1629  			},
  1630  			blur: function() {
  1631  				this.buttonElement.removeClass( "ui-state-focus" );
  1632  			}
  1633  		});
  1634  
  1635  		if ( toggleButton ) {
  1636  			this.element.bind( "change" + this.eventNamespace, function() {
  1637  				that.refresh();
  1638  			});
  1639  		}
  1640  
  1641  		if ( this.type === "checkbox" ) {
  1642  			this.buttonElement.bind( "click" + this.eventNamespace, function() {
  1643  				if ( options.disabled ) {
  1644  					return false;
  1645  				}
  1646  			});
  1647  		} else if ( this.type === "radio" ) {
  1648  			this.buttonElement.bind( "click" + this.eventNamespace, function() {
  1649  				if ( options.disabled ) {
  1650  					return false;
  1651  				}
  1652  				$( this ).addClass( "ui-state-active" );
  1653  				that.buttonElement.attr( "aria-pressed", "true" );
  1654  
  1655  				var radio = that.element[ 0 ];
  1656  				radioGroup( radio )
  1657  					.not( radio )
  1658  					.map(function() {
  1659  						return $( this ).button( "widget" )[ 0 ];
  1660  					})
  1661  					.removeClass( "ui-state-active" )
  1662  					.attr( "aria-pressed", "false" );
  1663  			});
  1664  		} else {
  1665  			this.buttonElement
  1666  				.bind( "mousedown" + this.eventNamespace, function() {
  1667  					if ( options.disabled ) {
  1668  						return false;
  1669  					}
  1670  					$( this ).addClass( "ui-state-active" );
  1671  					lastActive = this;
  1672  					that.document.one( "mouseup", function() {
  1673  						lastActive = null;
  1674  					});
  1675  				})
  1676  				.bind( "mouseup" + this.eventNamespace, function() {
  1677  					if ( options.disabled ) {
  1678  						return false;
  1679  					}
  1680  					$( this ).removeClass( "ui-state-active" );
  1681  				})
  1682  				.bind( "keydown" + this.eventNamespace, function(event) {
  1683  					if ( options.disabled ) {
  1684  						return false;
  1685  					}
  1686  					if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
  1687  						$( this ).addClass( "ui-state-active" );
  1688  					}
  1689  				})
  1690  				// see #8559, we bind to blur here in case the button element loses
  1691  				// focus between keydown and keyup, it would be left in an "active" state
  1692  				.bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
  1693  					$( this ).removeClass( "ui-state-active" );
  1694  				});
  1695  
  1696  			if ( this.buttonElement.is("a") ) {
  1697  				this.buttonElement.keyup(function(event) {
  1698  					if ( event.keyCode === $.ui.keyCode.SPACE ) {
  1699  						// TODO pass through original event correctly (just as 2nd argument doesn't work)
  1700  						$( this ).click();
  1701  					}
  1702  				});
  1703  			}
  1704  		}
  1705  
  1706  		// TODO: pull out $.Widget's handling for the disabled option into
  1707  		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
  1708  		// be overridden by individual plugins
  1709  		this._setOption( "disabled", options.disabled );
  1710  		this._resetButton();
  1711  	},
  1712  
  1713  	_determineButtonType: function() {
  1714  		var ancestor, labelSelector, checked;
  1715  
  1716  		if ( this.element.is("[type=checkbox]") ) {
  1717  			this.type = "checkbox";
  1718  		} else if ( this.element.is("[type=radio]") ) {
  1719  			this.type = "radio";
  1720  		} else if ( this.element.is("input") ) {
  1721  			this.type = "input";
  1722  		} else {
  1723  			this.type = "button";
  1724  		}
  1725  
  1726  		if ( this.type === "checkbox" || this.type === "radio" ) {
  1727  			// we don't search against the document in case the element
  1728  			// is disconnected from the DOM
  1729  			ancestor = this.element.parents().last();
  1730  			labelSelector = "label[for='" + this.element.attr("id") + "']";
  1731  			this.buttonElement = ancestor.find( labelSelector );
  1732  			if ( !this.buttonElement.length ) {
  1733  				ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
  1734  				this.buttonElement = ancestor.filter( labelSelector );
  1735  				if ( !this.buttonElement.length ) {
  1736  					this.buttonElement = ancestor.find( labelSelector );
  1737  				}
  1738  			}
  1739  			this.element.addClass( "ui-helper-hidden-accessible" );
  1740  
  1741  			checked = this.element.is( ":checked" );
  1742  			if ( checked ) {
  1743  				this.buttonElement.addClass( "ui-state-active" );
  1744  			}
  1745  			this.buttonElement.prop( "aria-pressed", checked );
  1746  		} else {
  1747  			this.buttonElement = this.element;
  1748  		}
  1749  	},
  1750  
  1751  	widget: function() {
  1752  		return this.buttonElement;
  1753  	},
  1754  
  1755  	_destroy: function() {
  1756  		this.element
  1757  			.removeClass( "ui-helper-hidden-accessible" );
  1758  		this.buttonElement
  1759  			.removeClass( baseClasses + " ui-state-active " + typeClasses )
  1760  			.removeAttr( "role" )
  1761  			.removeAttr( "aria-pressed" )
  1762  			.html( this.buttonElement.find(".ui-button-text").html() );
  1763  
  1764  		if ( !this.hasTitle ) {
  1765  			this.buttonElement.removeAttr( "title" );
  1766  		}
  1767  	},
  1768  
  1769  	_setOption: function( key, value ) {
  1770  		this._super( key, value );
  1771  		if ( key === "disabled" ) {
  1772  			this.element.prop( "disabled", !!value );
  1773  			if ( value ) {
  1774  				this.buttonElement.removeClass( "ui-state-focus" );
  1775  			}
  1776  			return;
  1777  		}
  1778  		this._resetButton();
  1779  	},
  1780  
  1781  	refresh: function() {
  1782  		//See #8237 & #8828
  1783  		var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
  1784  
  1785  		if ( isDisabled !== this.options.disabled ) {
  1786  			this._setOption( "disabled", isDisabled );
  1787  		}
  1788  		if ( this.type === "radio" ) {
  1789  			radioGroup( this.element[0] ).each(function() {
  1790  				if ( $( this ).is( ":checked" ) ) {
  1791  					$( this ).button( "widget" )
  1792  						.addClass( "ui-state-active" )
  1793  						.attr( "aria-pressed", "true" );
  1794  				} else {
  1795  					$( this ).button( "widget" )
  1796  						.removeClass( "ui-state-active" )
  1797  						.attr( "aria-pressed", "false" );
  1798  				}
  1799  			});
  1800  		} else if ( this.type === "checkbox" ) {
  1801  			if ( this.element.is( ":checked" ) ) {
  1802  				this.buttonElement
  1803  					.addClass( "ui-state-active" )
  1804  					.attr( "aria-pressed", "true" );
  1805  			} else {
  1806  				this.buttonElement
  1807  					.removeClass( "ui-state-active" )
  1808  					.attr( "aria-pressed", "false" );
  1809  			}
  1810  		}
  1811  	},
  1812  
  1813  	_resetButton: function() {
  1814  		if ( this.type === "input" ) {
  1815  			if ( this.options.label ) {
  1816  				this.element.val( this.options.label );
  1817  			}
  1818  			return;
  1819  		}
  1820  		var buttonElement = this.buttonElement.removeClass( typeClasses ),
  1821  			buttonText = $( "<span></span>", this.document[0] )
  1822  				.addClass( "ui-button-text" )
  1823  				.html( this.options.label )
  1824  				.appendTo( buttonElement.empty() )
  1825  				.text(),
  1826  			icons = this.options.icons,
  1827  			multipleIcons = icons.primary && icons.secondary,
  1828  			buttonClasses = [];
  1829  
  1830  		if ( icons.primary || icons.secondary ) {
  1831  			if ( this.options.text ) {
  1832  				buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
  1833  			}
  1834  
  1835  			if ( icons.primary ) {
  1836  				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
  1837  			}
  1838  
  1839  			if ( icons.secondary ) {
  1840  				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
  1841  			}
  1842  
  1843  			if ( !this.options.text ) {
  1844  				buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
  1845  
  1846  				if ( !this.hasTitle ) {
  1847  					buttonElement.attr( "title", $.trim( buttonText ) );
  1848  				}
  1849  			}
  1850  		} else {
  1851  			buttonClasses.push( "ui-button-text-only" );
  1852  		}
  1853  		buttonElement.addClass( buttonClasses.join( " " ) );
  1854  	}
  1855  });
  1856  
  1857  $.widget( "ui.buttonset", {
  1858  	version: "1.10.4",
  1859  	options: {
  1860  		items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
  1861  	},
  1862  
  1863  	_create: function() {
  1864  		this.element.addClass( "ui-buttonset" );
  1865  	},
  1866  
  1867  	_init: function() {
  1868  		this.refresh();
  1869  	},
  1870  
  1871  	_setOption: function( key, value ) {
  1872  		if ( key === "disabled" ) {
  1873  			this.buttons.button( "option", key, value );
  1874  		}
  1875  
  1876  		this._super( key, value );
  1877  	},
  1878  
  1879  	refresh: function() {
  1880  		var rtl = this.element.css( "direction" ) === "rtl";
  1881  
  1882  		this.buttons = this.element.find( this.options.items )
  1883  			.filter( ":ui-button" )
  1884  				.button( "refresh" )
  1885  			.end()
  1886  			.not( ":ui-button" )
  1887  				.button()
  1888  			.end()
  1889  			.map(function() {
  1890  				return $( this ).button( "widget" )[ 0 ];
  1891  			})
  1892  				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
  1893  				.filter( ":first" )
  1894  					.addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
  1895  				.end()
  1896  				.filter( ":last" )
  1897  					.addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
  1898  				.end()
  1899  			.end();
  1900  	},
  1901  
  1902  	_destroy: function() {
  1903  		this.element.removeClass( "ui-buttonset" );
  1904  		this.buttons
  1905  			.map(function() {
  1906  				return $( this ).button( "widget" )[ 0 ];
  1907  			})
  1908  				.removeClass( "ui-corner-left ui-corner-right" )
  1909  			.end()
  1910  			.button( "destroy" );
  1911  	}
  1912  });
  1913  
  1914  }( jQuery ) );
  1915  
  1916  /*!
  1917   * jQuery UI Slider 1.10.4
  1918   * http://jqueryui.com
  1919   *
  1920   * Copyright 2014 jQuery Foundation and other contributors
  1921   * Released under the MIT license.
  1922   * http://jquery.org/license
  1923   *
  1924   * http://api.jqueryui.com/slider/
  1925   *
  1926   * Depends:
  1927   *	jquery.ui.core.js
  1928   *	jquery.ui.mouse.js
  1929   *	jquery.ui.widget.js
  1930   */
  1931  (function( $, undefined ) {
  1932  
  1933  // number of pages in a slider
  1934  // (how many times can you page up/down to go through the whole range)
  1935  var numPages = 5;
  1936  
  1937  $.widget( "ui.slider", $.ui.mouse, {
  1938  	version: "1.10.4",
  1939  	widgetEventPrefix: "slide",
  1940  
  1941  	options: {
  1942  		animate: false,
  1943  		distance: 0,
  1944  		max: 100,
  1945  		min: 0,
  1946  		orientation: "horizontal",
  1947  		range: false,
  1948  		step: 1,
  1949  		value: 0,
  1950  		values: null,
  1951  
  1952  		// callbacks
  1953  		change: null,
  1954  		slide: null,
  1955  		start: null,
  1956  		stop: null
  1957  	},
  1958  
  1959  	_create: function() {
  1960  		this._keySliding = false;
  1961  		this._mouseSliding = false;
  1962  		this._animateOff = true;
  1963  		this._handleIndex = null;
  1964  		this._detectOrientation();
  1965  		this._mouseInit();
  1966  
  1967  		this.element
  1968  			.addClass( "ui-slider" +
  1969  				" ui-slider-" + this.orientation +
  1970  				" ui-widget" +
  1971  				" ui-widget-content" +
  1972  				" ui-corner-all");
  1973  
  1974  		this._refresh();
  1975  		this._setOption( "disabled", this.options.disabled );
  1976  
  1977  		this._animateOff = false;
  1978  	},
  1979  
  1980  	_refresh: function() {
  1981  		this._createRange();
  1982  		this._createHandles();
  1983  		this._setupEvents();
  1984  		this._refreshValue();
  1985  	},
  1986  
  1987  	_createHandles: function() {
  1988  		var i, handleCount,
  1989  			options = this.options,
  1990  			existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
  1991  			handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
  1992  			handles = [];
  1993  
  1994  		handleCount = ( options.values && options.values.length ) || 1;
  1995  
  1996  		if ( existingHandles.length > handleCount ) {
  1997  			existingHandles.slice( handleCount ).remove();
  1998  			existingHandles = existingHandles.slice( 0, handleCount );
  1999  		}
  2000  
  2001  		for ( i = existingHandles.length; i < handleCount; i++ ) {
  2002  			handles.push( handle );
  2003  		}
  2004  
  2005  		this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
  2006  
  2007  		this.handle = this.handles.eq( 0 );
  2008  
  2009  		this.handles.each(function( i ) {
  2010  			$( this ).data( "ui-slider-handle-index", i );
  2011  		});
  2012  	},
  2013  
  2014  	_createRange: function() {
  2015  		var options = this.options,
  2016  			classes = "";
  2017  
  2018  		if ( options.range ) {
  2019  			if ( options.range === true ) {
  2020  				if ( !options.values ) {
  2021  					options.values = [ this._valueMin(), this._valueMin() ];
  2022  				} else if ( options.values.length && options.values.length !== 2 ) {
  2023  					options.values = [ options.values[0], options.values[0] ];
  2024  				} else if ( $.isArray( options.values ) ) {
  2025  					options.values = options.values.slice(0);
  2026  				}
  2027  			}
  2028  
  2029  			if ( !this.range || !this.range.length ) {
  2030  				this.range = $( "<div></div>" )
  2031  					.appendTo( this.element );
  2032  
  2033  				classes = "ui-slider-range" +
  2034  				// note: this isn't the most fittingly semantic framework class for this element,
  2035  				// but worked best visually with a variety of themes
  2036  				" ui-widget-header ui-corner-all";
  2037  			} else {
  2038  				this.range.removeClass( "ui-slider-range-min ui-slider-range-max" )
  2039  					// Handle range switching from true to min/max
  2040  					.css({
  2041  						"left": "",
  2042  						"bottom": ""
  2043  					});
  2044  			}
  2045  
  2046  			this.range.addClass( classes +
  2047  				( ( options.range === "min" || options.range === "max" ) ? " ui-slider-range-" + options.range : "" ) );
  2048  		} else {
  2049  			if ( this.range ) {
  2050  				this.range.remove();
  2051  			}
  2052  			this.range = null;
  2053  		}
  2054  	},
  2055  
  2056  	_setupEvents: function() {
  2057  		var elements = this.handles.add( this.range ).filter( "a" );
  2058  		this._off( elements );
  2059  		this._on( elements, this._handleEvents );
  2060  		this._hoverable( elements );
  2061  		this._focusable( elements );
  2062  	},
  2063  
  2064  	_destroy: function() {
  2065  		this.handles.remove();
  2066  		if ( this.range ) {
  2067  			this.range.remove();
  2068  		}
  2069  
  2070  		this.element
  2071  			.removeClass( "ui-slider" +
  2072  				" ui-slider-horizontal" +
  2073  				" ui-slider-vertical" +
  2074  				" ui-widget" +
  2075  				" ui-widget-content" +
  2076  				" ui-corner-all" );
  2077  
  2078  		this._mouseDestroy();
  2079  	},
  2080  
  2081  	_mouseCapture: function( event ) {
  2082  		var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
  2083  			that = this,
  2084  			o = this.options;
  2085  
  2086  		if ( o.disabled ) {
  2087  			return false;
  2088  		}
  2089  
  2090  		this.elementSize = {
  2091  			width: this.element.outerWidth(),
  2092  			height: this.element.outerHeight()
  2093  		};
  2094  		this.elementOffset = this.element.offset();
  2095  
  2096  		position = { x: event.pageX, y: event.pageY };
  2097  		normValue = this._normValueFromMouse( position );
  2098  		distance = this._valueMax() - this._valueMin() + 1;
  2099  		this.handles.each(function( i ) {
  2100  			var thisDistance = Math.abs( normValue - that.values(i) );
  2101  			if (( distance > thisDistance ) ||
  2102  				( distance === thisDistance &&
  2103  					(i === that._lastChangedValue || that.values(i) === o.min ))) {
  2104  				distance = thisDistance;
  2105  				closestHandle = $( this );
  2106  				index = i;
  2107  			}
  2108  		});
  2109  
  2110  		allowed = this._start( event, index );
  2111  		if ( allowed === false ) {
  2112  			return false;
  2113  		}
  2114  		this._mouseSliding = true;
  2115  
  2116  		this._handleIndex = index;
  2117  
  2118  		closestHandle
  2119  			.addClass( "ui-state-active" )
  2120  			.focus();
  2121  
  2122  		offset = closestHandle.offset();
  2123  		mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
  2124  		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
  2125  			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
  2126  			top: event.pageY - offset.top -
  2127  				( closestHandle.height() / 2 ) -
  2128  				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
  2129  				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
  2130  				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
  2131  		};
  2132  
  2133  		if ( !this.handles.hasClass( "ui-state-hover" ) ) {
  2134  			this._slide( event, index, normValue );
  2135  		}
  2136  		this._animateOff = true;
  2137  		return true;
  2138  	},
  2139  
  2140  	_mouseStart: function() {
  2141  		return true;
  2142  	},
  2143  
  2144  	_mouseDrag: function( event ) {
  2145  		var position = { x: event.pageX, y: event.pageY },
  2146  			normValue = this._normValueFromMouse( position );
  2147  
  2148  		this._slide( event, this._handleIndex, normValue );
  2149  
  2150  		return false;
  2151  	},
  2152  
  2153  	_mouseStop: function( event ) {
  2154  		this.handles.removeClass( "ui-state-active" );
  2155  		this._mouseSliding = false;
  2156  
  2157  		this._stop( event, this._handleIndex );
  2158  		this._change( event, this._handleIndex );
  2159  
  2160  		this._handleIndex = null;
  2161  		this._clickOffset = null;
  2162  		this._animateOff = false;
  2163  
  2164  		return false;
  2165  	},
  2166  
  2167  	_detectOrientation: function() {
  2168  		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
  2169  	},
  2170  
  2171  	_normValueFromMouse: function( position ) {
  2172  		var pixelTotal,
  2173  			pixelMouse,
  2174  			percentMouse,
  2175  			valueTotal,
  2176  			valueMouse;
  2177  
  2178  		if ( this.orientation === "horizontal" ) {
  2179  			pixelTotal = this.elementSize.width;
  2180  			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
  2181  		} else {
  2182  			pixelTotal = this.elementSize.height;
  2183  			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
  2184  		}
  2185  
  2186  		percentMouse = ( pixelMouse / pixelTotal );
  2187  		if ( percentMouse > 1 ) {
  2188  			percentMouse = 1;
  2189  		}
  2190  		if ( percentMouse < 0 ) {
  2191  			percentMouse = 0;
  2192  		}
  2193  		if ( this.orientation === "vertical" ) {
  2194  			percentMouse = 1 - percentMouse;
  2195  		}
  2196  
  2197  		valueTotal = this._valueMax() - this._valueMin();
  2198  		valueMouse = this._valueMin() + percentMouse * valueTotal;
  2199  
  2200  		return this._trimAlignValue( valueMouse );
  2201  	},
  2202  
  2203  	_start: function( event, index ) {
  2204  		var uiHash = {
  2205  			handle: this.handles[ index ],
  2206  			value: this.value()
  2207  		};
  2208  		if ( this.options.values && this.options.values.length ) {
  2209  			uiHash.value = this.values( index );
  2210  			uiHash.values = this.values();
  2211  		}
  2212  		return this._trigger( "start", event, uiHash );
  2213  	},
  2214  
  2215  	_slide: function( event, index, newVal ) {
  2216  		var otherVal,
  2217  			newValues,
  2218  			allowed;
  2219  
  2220  		if ( this.options.values && this.options.values.length ) {
  2221  			otherVal = this.values( index ? 0 : 1 );
  2222  
  2223  			if ( ( this.options.values.length === 2 && this.options.range === true ) &&
  2224  					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
  2225  				) {
  2226  				newVal = otherVal;
  2227  			}
  2228  
  2229  			if ( newVal !== this.values( index ) ) {
  2230  				newValues = this.values();
  2231  				newValues[ index ] = newVal;
  2232  				// A slide can be canceled by returning false from the slide callback
  2233  				allowed = this._trigger( "slide", event, {
  2234  					handle: this.handles[ index ],
  2235  					value: newVal,
  2236  					values: newValues
  2237  				} );
  2238  				otherVal = this.values( index ? 0 : 1 );
  2239  				if ( allowed !== false ) {
  2240  					this.values( index, newVal );
  2241  				}
  2242  			}
  2243  		} else {
  2244  			if ( newVal !== this.value() ) {
  2245  				// A slide can be canceled by returning false from the slide callback
  2246  				allowed = this._trigger( "slide", event, {
  2247  					handle: this.handles[ index ],
  2248  					value: newVal
  2249  				} );
  2250  				if ( allowed !== false ) {
  2251  					this.value( newVal );
  2252  				}
  2253  			}
  2254  		}
  2255  	},
  2256  
  2257  	_stop: function( event, index ) {
  2258  		var uiHash = {
  2259  			handle: this.handles[ index ],
  2260  			value: this.value()
  2261  		};
  2262  		if ( this.options.values && this.options.values.length ) {
  2263  			uiHash.value = this.values( index );
  2264  			uiHash.values = this.values();
  2265  		}
  2266  
  2267  		this._trigger( "stop", event, uiHash );
  2268  	},
  2269  
  2270  	_change: function( event, index ) {
  2271  		if ( !this._keySliding && !this._mouseSliding ) {
  2272  			var uiHash = {
  2273  				handle: this.handles[ index ],
  2274  				value: this.value()
  2275  			};
  2276  			if ( this.options.values && this.options.values.length ) {
  2277  				uiHash.value = this.values( index );
  2278  				uiHash.values = this.values();
  2279  			}
  2280  
  2281  			//store the last changed value index for reference when handles overlap
  2282  			this._lastChangedValue = index;
  2283  
  2284  			this._trigger( "change", event, uiHash );
  2285  		}
  2286  	},
  2287  
  2288  	value: function( newValue ) {
  2289  		if ( arguments.length ) {
  2290  			this.options.value = this._trimAlignValue( newValue );
  2291  			this._refreshValue();
  2292  			this._change( null, 0 );
  2293  			return;
  2294  		}
  2295  
  2296  		return this._value();
  2297  	},
  2298  
  2299  	values: function( index, newValue ) {
  2300  		var vals,
  2301  			newValues,
  2302  			i;
  2303  
  2304  		if ( arguments.length > 1 ) {
  2305  			this.options.values[ index ] = this._trimAlignValue( newValue );
  2306  			this._refreshValue();
  2307  			this._change( null, index );
  2308  			return;
  2309  		}
  2310  
  2311  		if ( arguments.length ) {
  2312  			if ( $.isArray( arguments[ 0 ] ) ) {
  2313  				vals = this.options.values;
  2314  				newValues = arguments[ 0 ];
  2315  				for ( i = 0; i < vals.length; i += 1 ) {
  2316  					vals[ i ] = this._trimAlignValue( newValues[ i ] );
  2317  					this._change( null, i );
  2318  				}
  2319  				this._refreshValue();
  2320  			} else {
  2321  				if ( this.options.values && this.options.values.length ) {
  2322  					return this._values( index );
  2323  				} else {
  2324  					return this.value();
  2325  				}
  2326  			}
  2327  		} else {
  2328  			return this._values();
  2329  		}
  2330  	},
  2331  
  2332  	_setOption: function( key, value ) {
  2333  		var i,
  2334  			valsLength = 0;
  2335  
  2336  		if ( key === "range" && this.options.range === true ) {
  2337  			if ( value === "min" ) {
  2338  				this.options.value = this._values( 0 );
  2339  				this.options.values = null;
  2340  			} else if ( value === "max" ) {
  2341  				this.options.value = this._values( this.options.values.length-1 );
  2342  				this.options.values = null;
  2343  			}
  2344  		}
  2345  
  2346  		if ( $.isArray( this.options.values ) ) {
  2347  			valsLength = this.options.values.length;
  2348  		}
  2349  
  2350  		$.Widget.prototype._setOption.apply( this, arguments );
  2351  
  2352  		switch ( key ) {
  2353  			case "orientation":
  2354  				this._detectOrientation();
  2355  				this.element
  2356  					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
  2357  					.addClass( "ui-slider-" + this.orientation );
  2358  				this._refreshValue();
  2359  				break;
  2360  			case "value":
  2361  				this._animateOff = true;
  2362  				this._refreshValue();
  2363  				this._change( null, 0 );
  2364  				this._animateOff = false;
  2365  				break;
  2366  			case "values":
  2367  				this._animateOff = true;
  2368  				this._refreshValue();
  2369  				for ( i = 0; i < valsLength; i += 1 ) {
  2370  					this._change( null, i );
  2371  				}
  2372  				this._animateOff = false;
  2373  				break;
  2374  			case "min":
  2375  			case "max":
  2376  				this._animateOff = true;
  2377  				this._refreshValue();
  2378  				this._animateOff = false;
  2379  				break;
  2380  			case "range":
  2381  				this._animateOff = true;
  2382  				this._refresh();
  2383  				this._animateOff = false;
  2384  				break;
  2385  		}
  2386  	},
  2387  
  2388  	//internal value getter
  2389  	// _value() returns value trimmed by min and max, aligned by step
  2390  	_value: function() {
  2391  		var val = this.options.value;
  2392  		val = this._trimAlignValue( val );
  2393  
  2394  		return val;
  2395  	},
  2396  
  2397  	//internal values getter
  2398  	// _values() returns array of values trimmed by min and max, aligned by step
  2399  	// _values( index ) returns single value trimmed by min and max, aligned by step
  2400  	_values: function( index ) {
  2401  		var val,
  2402  			vals,
  2403  			i;
  2404  
  2405  		if ( arguments.length ) {
  2406  			val = this.options.values[ index ];
  2407  			val = this._trimAlignValue( val );
  2408  
  2409  			return val;
  2410  		} else if ( this.options.values && this.options.values.length ) {
  2411  			// .slice() creates a copy of the array
  2412  			// this copy gets trimmed by min and max and then returned
  2413  			vals = this.options.values.slice();
  2414  			for ( i = 0; i < vals.length; i+= 1) {
  2415  				vals[ i ] = this._trimAlignValue( vals[ i ] );
  2416  			}
  2417  
  2418  			return vals;
  2419  		} else {
  2420  			return [];
  2421  		}
  2422  	},
  2423  
  2424  	// returns the step-aligned value that val is closest to, between (inclusive) min and max
  2425  	_trimAlignValue: function( val ) {
  2426  		if ( val <= this._valueMin() ) {
  2427  			return this._valueMin();
  2428  		}
  2429  		if ( val >= this._valueMax() ) {
  2430  			return this._valueMax();
  2431  		}
  2432  		var step = ( this.options.step > 0 ) ? this.options.step : 1,
  2433  			valModStep = (val - this._valueMin()) % step,
  2434  			alignValue = val - valModStep;
  2435  
  2436  		if ( Math.abs(valModStep) * 2 >= step ) {
  2437  			alignValue += ( valModStep > 0 ) ? step : ( -step );
  2438  		}
  2439  
  2440  		// Since JavaScript has problems with large floats, round
  2441  		// the final value to 5 digits after the decimal point (see #4124)
  2442  		return parseFloat( alignValue.toFixed(5) );
  2443  	},
  2444  
  2445  	_valueMin: function() {
  2446  		return this.options.min;
  2447  	},
  2448  
  2449  	_valueMax: function() {
  2450  		return this.options.max;
  2451  	},
  2452  
  2453  	_refreshValue: function() {
  2454  		var lastValPercent, valPercent, value, valueMin, valueMax,
  2455  			oRange = this.options.range,
  2456  			o = this.options,
  2457  			that = this,
  2458  			animate = ( !this._animateOff ) ? o.animate : false,
  2459  			_set = {};
  2460  
  2461  		if ( this.options.values && this.options.values.length ) {
  2462  			this.handles.each(function( i ) {
  2463  				valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
  2464  				_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
  2465  				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
  2466  				if ( that.options.range === true ) {
  2467  					if ( that.orientation === "horizontal" ) {
  2468  						if ( i === 0 ) {
  2469  							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
  2470  						}
  2471  						if ( i === 1 ) {
  2472  							that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
  2473  						}
  2474  					} else {
  2475  						if ( i === 0 ) {
  2476  							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
  2477  						}
  2478  						if ( i === 1 ) {
  2479  							that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
  2480  						}
  2481  					}
  2482  				}
  2483  				lastValPercent = valPercent;
  2484  			});
  2485  		} else {
  2486  			value = this.value();
  2487  			valueMin = this._valueMin();
  2488  			valueMax = this._valueMax();
  2489  			valPercent = ( valueMax !== valueMin ) ?
  2490  					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
  2491  					0;
  2492  			_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
  2493  			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
  2494  
  2495  			if ( oRange === "min" && this.orientation === "horizontal" ) {
  2496  				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
  2497  			}
  2498  			if ( oRange === "max" && this.orientation === "horizontal" ) {
  2499  				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
  2500  			}
  2501  			if ( oRange === "min" && this.orientation === "vertical" ) {
  2502  				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
  2503  			}
  2504  			if ( oRange === "max" && this.orientation === "vertical" ) {
  2505  				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
  2506  			}
  2507  		}
  2508  	},
  2509  
  2510  	_handleEvents: {
  2511  		keydown: function( event ) {
  2512  			var allowed, curVal, newVal, step,
  2513  				index = $( event.target ).data( "ui-slider-handle-index" );
  2514  
  2515  			switch ( event.keyCode ) {
  2516  				case $.ui.keyCode.HOME:
  2517  				case $.ui.keyCode.END:
  2518  				case $.ui.keyCode.PAGE_UP:
  2519  				case $.ui.keyCode.PAGE_DOWN:
  2520  				case $.ui.keyCode.UP:
  2521  				case $.ui.keyCode.RIGHT:
  2522  				case $.ui.keyCode.DOWN:
  2523  				case $.ui.keyCode.LEFT:
  2524  					event.preventDefault();
  2525  					if ( !this._keySliding ) {
  2526  						this._keySliding = true;
  2527  						$( event.target ).addClass( "ui-state-active" );
  2528  						allowed = this._start( event, index );
  2529  						if ( allowed === false ) {
  2530  							return;
  2531  						}
  2532  					}
  2533  					break;
  2534  			}
  2535  
  2536  			step = this.options.step;
  2537  			if ( this.options.values && this.options.values.length ) {
  2538  				curVal = newVal = this.values( index );
  2539  			} else {
  2540  				curVal = newVal = this.value();
  2541  			}
  2542  
  2543  			switch ( event.keyCode ) {
  2544  				case $.ui.keyCode.HOME:
  2545  					newVal = this._valueMin();
  2546  					break;
  2547  				case $.ui.keyCode.END:
  2548  					newVal = this._valueMax();
  2549  					break;
  2550  				case $.ui.keyCode.PAGE_UP:
  2551  					newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) );
  2552  					break;
  2553  				case $.ui.keyCode.PAGE_DOWN:
  2554  					newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) );
  2555  					break;
  2556  				case $.ui.keyCode.UP:
  2557  				case $.ui.keyCode.RIGHT:
  2558  					if ( curVal === this._valueMax() ) {
  2559  						return;
  2560  					}
  2561  					newVal = this._trimAlignValue( curVal + step );
  2562  					break;
  2563  				case $.ui.keyCode.DOWN:
  2564  				case $.ui.keyCode.LEFT:
  2565  					if ( curVal === this._valueMin() ) {
  2566  						return;
  2567  					}
  2568  					newVal = this._trimAlignValue( curVal - step );
  2569  					break;
  2570  			}
  2571  
  2572  			this._slide( event, index, newVal );
  2573  		},
  2574  		click: function( event ) {
  2575  			event.preventDefault();
  2576  		},
  2577  		keyup: function( event ) {
  2578  			var index = $( event.target ).data( "ui-slider-handle-index" );
  2579  
  2580  			if ( this._keySliding ) {
  2581  				this._keySliding = false;
  2582  				this._stop( event, index );
  2583  				this._change( event, index );
  2584  				$( event.target ).removeClass( "ui-state-active" );
  2585  			}
  2586  		}
  2587  	}
  2588  
  2589  });
  2590  
  2591  }(jQuery));
  2592  
  2593  /*!
  2594   * jQuery UI Effects 1.10.4
  2595   * http://jqueryui.com
  2596   *
  2597   * Copyright 2014 jQuery Foundation and other contributors
  2598   * Released under the MIT license.
  2599   * http://jquery.org/license
  2600   *
  2601   * http://api.jqueryui.com/category/effects-core/
  2602   */
  2603  (function($, undefined) {
  2604  
  2605  var dataSpace = "ui-effects-";
  2606  
  2607  $.effects = {
  2608  	effect: {}
  2609  };
  2610  
  2611  /*!
  2612   * jQuery Color Animations v2.1.2
  2613   * https://github.com/jquery/jquery-color
  2614   *
  2615   * Copyright 2013 jQuery Foundation and other contributors
  2616   * Released under the MIT license.
  2617   * http://jquery.org/license
  2618   *
  2619   * Date: Wed Jan 16 08:47:09 2013 -0600
  2620   */
  2621  (function( jQuery, undefined ) {
  2622  
  2623  	var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
  2624  
  2625  	// plusequals test for += 100 -= 100
  2626  	rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
  2627  	// a set of RE's that can match strings and generate color tuples.
  2628  	stringParsers = [{
  2629  			re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
  2630  			parse: function( execResult ) {
  2631  				return [
  2632  					execResult[ 1 ],
  2633  					execResult[ 2 ],
  2634  					execResult[ 3 ],
  2635  					execResult[ 4 ]
  2636  				];
  2637  			}
  2638  		}, {
  2639  			re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
  2640  			parse: function( execResult ) {
  2641  				return [
  2642  					execResult[ 1 ] * 2.55,
  2643  					execResult[ 2 ] * 2.55,
  2644  					execResult[ 3 ] * 2.55,
  2645  					execResult[ 4 ]
  2646  				];
  2647  			}
  2648  		}, {
  2649  			// this regex ignores A-F because it's compared against an already lowercased string
  2650  			re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
  2651  			parse: function( execResult ) {
  2652  				return [
  2653  					parseInt( execResult[ 1 ], 16 ),
  2654  					parseInt( execResult[ 2 ], 16 ),
  2655  					parseInt( execResult[ 3 ], 16 )
  2656  				];
  2657  			}
  2658  		}, {
  2659  			// this regex ignores A-F because it's compared against an already lowercased string
  2660  			re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
  2661  			parse: function( execResult ) {
  2662  				return [
  2663  					parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
  2664  					parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
  2665  					parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
  2666  				];
  2667  			}
  2668  		}, {
  2669  			re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
  2670  			space: "hsla",
  2671  			parse: function( execResult ) {
  2672  				return [
  2673  					execResult[ 1 ],
  2674  					execResult[ 2 ] / 100,
  2675  					execResult[ 3 ] / 100,
  2676  					execResult[ 4 ]
  2677  				];
  2678  			}
  2679  		}],
  2680  
  2681  	// jQuery.Color( )
  2682  	color = jQuery.Color = function( color, green, blue, alpha ) {
  2683  		return new jQuery.Color.fn.parse( color, green, blue, alpha );
  2684  	},
  2685  	spaces = {
  2686  		rgba: {
  2687  			props: {
  2688  				red: {
  2689  					idx: 0,
  2690  					type: "byte"
  2691  				},
  2692  				green: {
  2693  					idx: 1,
  2694  					type: "byte"
  2695  				},
  2696  				blue: {
  2697  					idx: 2,
  2698  					type: "byte"
  2699  				}
  2700  			}
  2701  		},
  2702  
  2703  		hsla: {
  2704  			props: {
  2705  				hue: {
  2706  					idx: 0,
  2707  					type: "degrees"
  2708  				},
  2709  				saturation: {
  2710  					idx: 1,
  2711  					type: "percent"
  2712  				},
  2713  				lightness: {
  2714  					idx: 2,
  2715  					type: "percent"
  2716  				}
  2717  			}
  2718  		}
  2719  	},
  2720  	propTypes = {
  2721  		"byte": {
  2722  			floor: true,
  2723  			max: 255
  2724  		},
  2725  		"percent": {
  2726  			max: 1
  2727  		},
  2728  		"degrees": {
  2729  			mod: 360,
  2730  			floor: true
  2731  		}
  2732  	},
  2733  	support = color.support = {},
  2734  
  2735  	// element for support tests
  2736  	supportElem = jQuery( "<p>" )[ 0 ],
  2737  
  2738  	// colors = jQuery.Color.names
  2739  	colors,
  2740  
  2741  	// local aliases of functions called often
  2742  	each = jQuery.each;
  2743  
  2744  // determine rgba support immediately
  2745  supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
  2746  support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
  2747  
  2748  // define cache name and alpha properties
  2749  // for rgba and hsla spaces
  2750  each( spaces, function( spaceName, space ) {
  2751  	space.cache = "_" + spaceName;
  2752  	space.props.alpha = {
  2753  		idx: 3,
  2754  		type: "percent",
  2755  		def: 1
  2756  	};
  2757  });
  2758  
  2759  function clamp( value, prop, allowEmpty ) {
  2760  	var type = propTypes[ prop.type ] || {};
  2761  
  2762  	if ( value == null ) {
  2763  		return (allowEmpty || !prop.def) ? null : prop.def;
  2764  	}
  2765  
  2766  	// ~~ is an short way of doing floor for positive numbers
  2767  	value = type.floor ? ~~value : parseFloat( value );
  2768  
  2769  	// IE will pass in empty strings as value for alpha,
  2770  	// which will hit this case
  2771  	if ( isNaN( value ) ) {
  2772  		return prop.def;
  2773  	}
  2774  
  2775  	if ( type.mod ) {
  2776  		// we add mod before modding to make sure that negatives values
  2777  		// get converted properly: -10 -> 350
  2778  		return (value + type.mod) % type.mod;
  2779  	}
  2780  
  2781  	// for now all property types without mod have min and max
  2782  	return 0 > value ? 0 : type.max < value ? type.max : value;
  2783  }
  2784  
  2785  function stringParse( string ) {
  2786  	var inst = color(),
  2787  		rgba = inst._rgba = [];
  2788  
  2789  	string = string.toLowerCase();
  2790  
  2791  	each( stringParsers, function( i, parser ) {
  2792  		var parsed,
  2793  			match = parser.re.exec( string ),
  2794  			values = match && parser.parse( match ),
  2795  			spaceName = parser.space || "rgba";
  2796  
  2797  		if ( values ) {
  2798  			parsed = inst[ spaceName ]( values );
  2799  
  2800  			// if this was an rgba parse the assignment might happen twice
  2801  			// oh well....
  2802  			inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
  2803  			rgba = inst._rgba = parsed._rgba;
  2804  
  2805  			// exit each( stringParsers ) here because we matched
  2806  			return false;
  2807  		}
  2808  	});
  2809  
  2810  	// Found a stringParser that handled it
  2811  	if ( rgba.length ) {
  2812  
  2813  		// if this came from a parsed string, force "transparent" when alpha is 0
  2814  		// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
  2815  		if ( rgba.join() === "0,0,0,0" ) {
  2816  			jQuery.extend( rgba, colors.transparent );
  2817  		}
  2818  		return inst;
  2819  	}
  2820  
  2821  	// named colors
  2822  	return colors[ string ];
  2823  }
  2824  
  2825  color.fn = jQuery.extend( color.prototype, {
  2826  	parse: function( red, green, blue, alpha ) {
  2827  		if ( red === undefined ) {
  2828  			this._rgba = [ null, null, null, null ];
  2829  			return this;
  2830  		}
  2831  		if ( red.jquery || red.nodeType ) {
  2832  			red = jQuery( red ).css( green );
  2833  			green = undefined;
  2834  		}
  2835  
  2836  		var inst = this,
  2837  			type = jQuery.type( red ),
  2838  			rgba = this._rgba = [];
  2839  
  2840  		// more than 1 argument specified - assume ( red, green, blue, alpha )
  2841  		if ( green !== undefined ) {
  2842  			red = [ red, green, blue, alpha ];
  2843  			type = "array";
  2844  		}
  2845  
  2846  		if ( type === "string" ) {
  2847  			return this.parse( stringParse( red ) || colors._default );
  2848  		}
  2849  
  2850  		if ( type === "array" ) {
  2851  			each( spaces.rgba.props, function( key, prop ) {
  2852  				rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
  2853  			});
  2854  			return this;
  2855  		}
  2856  
  2857  		if ( type === "object" ) {
  2858  			if ( red instanceof color ) {
  2859  				each( spaces, function( spaceName, space ) {
  2860  					if ( red[ space.cache ] ) {
  2861  						inst[ space.cache ] = red[ space.cache ].slice();
  2862  					}
  2863  				});
  2864  			} else {
  2865  				each( spaces, function( spaceName, space ) {
  2866  					var cache = space.cache;
  2867  					each( space.props, function( key, prop ) {
  2868  
  2869  						// if the cache doesn't exist, and we know how to convert
  2870  						if ( !inst[ cache ] && space.to ) {
  2871  
  2872  							// if the value was null, we don't need to copy it
  2873  							// if the key was alpha, we don't need to copy it either
  2874  							if ( key === "alpha" || red[ key ] == null ) {
  2875  								return;
  2876  							}
  2877  							inst[ cache ] = space.to( inst._rgba );
  2878  						}
  2879  
  2880  						// this is the only case where we allow nulls for ALL properties.
  2881  						// call clamp with alwaysAllowEmpty
  2882  						inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
  2883  					});
  2884  
  2885  					// everything defined but alpha?
  2886  					if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
  2887  						// use the default of 1
  2888  						inst[ cache ][ 3 ] = 1;
  2889  						if ( space.from ) {
  2890  							inst._rgba = space.from( inst[ cache ] );
  2891  						}
  2892  					}
  2893  				});
  2894  			}
  2895  			return this;
  2896  		}
  2897  	},
  2898  	is: function( compare ) {
  2899  		var is = color( compare ),
  2900  			same = true,
  2901  			inst = this;
  2902  
  2903  		each( spaces, function( _, space ) {
  2904  			var localCache,
  2905  				isCache = is[ space.cache ];
  2906  			if (isCache) {
  2907  				localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
  2908  				each( space.props, function( _, prop ) {
  2909  					if ( isCache[ prop.idx ] != null ) {
  2910  						same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
  2911  						return same;
  2912  					}
  2913  				});
  2914  			}
  2915  			return same;
  2916  		});
  2917  		return same;
  2918  	},
  2919  	_space: function() {
  2920  		var used = [],
  2921  			inst = this;
  2922  		each( spaces, function( spaceName, space ) {
  2923  			if ( inst[ space.cache ] ) {
  2924  				used.push( spaceName );
  2925  			}
  2926  		});
  2927  		return used.pop();
  2928  	},
  2929  	transition: function( other, distance ) {
  2930  		var end = color( other ),
  2931  			spaceName = end._space(),
  2932  			space = spaces[ spaceName ],
  2933  			startColor = this.alpha() === 0 ? color( "transparent" ) : this,
  2934  			start = startColor[ space.cache ] || space.to( startColor._rgba ),
  2935  			result = start.slice();
  2936  
  2937  		end = end[ space.cache ];
  2938  		each( space.props, function( key, prop ) {
  2939  			var index = prop.idx,
  2940  				startValue = start[ index ],
  2941  				endValue = end[ index ],
  2942  				type = propTypes[ prop.type ] || {};
  2943  
  2944  			// if null, don't override start value
  2945  			if ( endValue === null ) {
  2946  				return;
  2947  			}
  2948  			// if null - use end
  2949  			if ( startValue === null ) {
  2950  				result[ index ] = endValue;
  2951  			} else {
  2952  				if ( type.mod ) {
  2953  					if ( endValue - startValue > type.mod / 2 ) {
  2954  						startValue += type.mod;
  2955  					} else if ( startValue - endValue > type.mod / 2 ) {
  2956  						startValue -= type.mod;
  2957  					}
  2958  				}
  2959  				result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
  2960  			}
  2961  		});
  2962  		return this[ spaceName ]( result );
  2963  	},
  2964  	blend: function( opaque ) {
  2965  		// if we are already opaque - return ourself
  2966  		if ( this._rgba[ 3 ] === 1 ) {
  2967  			return this;
  2968  		}
  2969  
  2970  		var rgb = this._rgba.slice(),
  2971  			a = rgb.pop(),
  2972  			blend = color( opaque )._rgba;
  2973  
  2974  		return color( jQuery.map( rgb, function( v, i ) {
  2975  			return ( 1 - a ) * blend[ i ] + a * v;
  2976  		}));
  2977  	},
  2978  	toRgbaString: function() {
  2979  		var prefix = "rgba(",
  2980  			rgba = jQuery.map( this._rgba, function( v, i ) {
  2981  				return v == null ? ( i > 2 ? 1 : 0 ) : v;
  2982  			});
  2983  
  2984  		if ( rgba[ 3 ] === 1 ) {
  2985  			rgba.pop();
  2986  			prefix = "rgb(";
  2987  		}
  2988  
  2989  		return prefix + rgba.join() + ")";
  2990  	},
  2991  	toHslaString: function() {
  2992  		var prefix = "hsla(",
  2993  			hsla = jQuery.map( this.hsla(), function( v, i ) {
  2994  				if ( v == null ) {
  2995  					v = i > 2 ? 1 : 0;
  2996  				}
  2997  
  2998  				// catch 1 and 2
  2999  				if ( i && i < 3 ) {
  3000  					v = Math.round( v * 100 ) + "%";
  3001  				}
  3002  				return v;
  3003  			});
  3004  
  3005  		if ( hsla[ 3 ] === 1 ) {
  3006  			hsla.pop();
  3007  			prefix = "hsl(";
  3008  		}
  3009  		return prefix + hsla.join() + ")";
  3010  	},
  3011  	toHexString: function( includeAlpha ) {
  3012  		var rgba = this._rgba.slice(),
  3013  			alpha = rgba.pop();
  3014  
  3015  		if ( includeAlpha ) {
  3016  			rgba.push( ~~( alpha * 255 ) );
  3017  		}
  3018  
  3019  		return "#" + jQuery.map( rgba, function( v ) {
  3020  
  3021  			// default to 0 when nulls exist
  3022  			v = ( v || 0 ).toString( 16 );
  3023  			return v.length === 1 ? "0" + v : v;
  3024  		}).join("");
  3025  	},
  3026  	toString: function() {
  3027  		return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
  3028  	}
  3029  });
  3030  color.fn.parse.prototype = color.fn;
  3031  
  3032  // hsla conversions adapted from:
  3033  // https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
  3034  
  3035  function hue2rgb( p, q, h ) {
  3036  	h = ( h + 1 ) % 1;
  3037  	if ( h * 6 < 1 ) {
  3038  		return p + (q - p) * h * 6;
  3039  	}
  3040  	if ( h * 2 < 1) {
  3041  		return q;
  3042  	}
  3043  	if ( h * 3 < 2 ) {
  3044  		return p + (q - p) * ((2/3) - h) * 6;
  3045  	}
  3046  	return p;
  3047  }
  3048  
  3049  spaces.hsla.to = function ( rgba ) {
  3050  	if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
  3051  		return [ null, null, null, rgba[ 3 ] ];
  3052  	}
  3053  	var r = rgba[ 0 ] / 255,
  3054  		g = rgba[ 1 ] / 255,
  3055  		b = rgba[ 2 ] / 255,
  3056  		a = rgba[ 3 ],
  3057  		max = Math.max( r, g, b ),
  3058  		min = Math.min( r, g, b ),
  3059  		diff = max - min,
  3060  		add = max + min,
  3061  		l = add * 0.5,
  3062  		h, s;
  3063  
  3064  	if ( min === max ) {
  3065  		h = 0;
  3066  	} else if ( r === max ) {
  3067  		h = ( 60 * ( g - b ) / diff ) + 360;
  3068  	} else if ( g === max ) {
  3069  		h = ( 60 * ( b - r ) / diff ) + 120;
  3070  	} else {
  3071  		h = ( 60 * ( r - g ) / diff ) + 240;
  3072  	}
  3073  
  3074  	// chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
  3075  	// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
  3076  	if ( diff === 0 ) {
  3077  		s = 0;
  3078  	} else if ( l <= 0.5 ) {
  3079  		s = diff / add;
  3080  	} else {
  3081  		s = diff / ( 2 - add );
  3082  	}
  3083  	return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
  3084  };
  3085  
  3086  spaces.hsla.from = function ( hsla ) {
  3087  	if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
  3088  		return [ null, null, null, hsla[ 3 ] ];
  3089  	}
  3090  	var h = hsla[ 0 ] / 360,
  3091  		s = hsla[ 1 ],
  3092  		l = hsla[ 2 ],
  3093  		a = hsla[ 3 ],
  3094  		q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
  3095  		p = 2 * l - q;
  3096  
  3097  	return [
  3098  		Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
  3099  		Math.round( hue2rgb( p, q, h ) * 255 ),
  3100  		Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
  3101  		a
  3102  	];
  3103  };
  3104  
  3105  
  3106  each( spaces, function( spaceName, space ) {
  3107  	var props = space.props,
  3108  		cache = space.cache,
  3109  		to = space.to,
  3110  		from = space.from;
  3111  
  3112  	// makes rgba() and hsla()
  3113  	color.fn[ spaceName ] = function( value ) {
  3114  
  3115  		// generate a cache for this space if it doesn't exist
  3116  		if ( to && !this[ cache ] ) {
  3117  			this[ cache ] = to( this._rgba );
  3118  		}
  3119  		if ( value === undefined ) {
  3120  			return this[ cache ].slice();
  3121  		}
  3122  
  3123  		var ret,
  3124  			type = jQuery.type( value ),
  3125  			arr = ( type === "array" || type === "object" ) ? value : arguments,
  3126  			local = this[ cache ].slice();
  3127  
  3128  		each( props, function( key, prop ) {
  3129  			var val = arr[ type === "object" ? key : prop.idx ];
  3130  			if ( val == null ) {
  3131  				val = local[ prop.idx ];
  3132  			}
  3133  			local[ prop.idx ] = clamp( val, prop );
  3134  		});
  3135  
  3136  		if ( from ) {
  3137  			ret = color( from( local ) );
  3138  			ret[ cache ] = local;
  3139  			return ret;
  3140  		} else {
  3141  			return color( local );
  3142  		}
  3143  	};
  3144  
  3145  	// makes red() green() blue() alpha() hue() saturation() lightness()
  3146  	each( props, function( key, prop ) {
  3147  		// alpha is included in more than one space
  3148  		if ( color.fn[ key ] ) {
  3149  			return;
  3150  		}
  3151  		color.fn[ key ] = function( value ) {
  3152  			var vtype = jQuery.type( value ),
  3153  				fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
  3154  				local = this[ fn ](),
  3155  				cur = local[ prop.idx ],
  3156  				match;
  3157  
  3158  			if ( vtype === "undefined" ) {
  3159  				return cur;
  3160  			}
  3161  
  3162  			if ( vtype === "function" ) {
  3163  				value = value.call( this, cur );
  3164  				vtype = jQuery.type( value );
  3165  			}
  3166  			if ( value == null && prop.empty ) {
  3167  				return this;
  3168  			}
  3169  			if ( vtype === "string" ) {
  3170  				match = rplusequals.exec( value );
  3171  				if ( match ) {
  3172  					value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
  3173  				}
  3174  			}
  3175  			local[ prop.idx ] = value;
  3176  			return this[ fn ]( local );
  3177  		};
  3178  	});
  3179  });
  3180  
  3181  // add cssHook and .fx.step function for each named hook.
  3182  // accept a space separated string of properties
  3183  color.hook = function( hook ) {
  3184  	var hooks = hook.split( " " );
  3185  	each( hooks, function( i, hook ) {
  3186  		jQuery.cssHooks[ hook ] = {
  3187  			set: function( elem, value ) {
  3188  				var parsed, curElem,
  3189  					backgroundColor = "";
  3190  
  3191  				if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
  3192  					value = color( parsed || value );
  3193  					if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
  3194  						curElem = hook === "backgroundColor" ? elem.parentNode : elem;
  3195  						while (
  3196  							(backgroundColor === "" || backgroundColor === "transparent") &&
  3197  							curElem && curElem.style
  3198  						) {
  3199  							try {
  3200  								backgroundColor = jQuery.css( curElem, "backgroundColor" );
  3201  								curElem = curElem.parentNode;
  3202  							} catch ( e ) {
  3203  							}
  3204  						}
  3205  
  3206  						value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
  3207  							backgroundColor :
  3208  							"_default" );
  3209  					}
  3210  
  3211  					value = value.toRgbaString();
  3212  				}
  3213  				try {
  3214  					elem.style[ hook ] = value;
  3215  				} catch( e ) {
  3216  					// wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
  3217  				}
  3218  			}
  3219  		};
  3220  		jQuery.fx.step[ hook ] = function( fx ) {
  3221  			if ( !fx.colorInit ) {
  3222  				fx.start = color( fx.elem, hook );
  3223  				fx.end = color( fx.end );
  3224  				fx.colorInit = true;
  3225  			}
  3226  			jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
  3227  		};
  3228  	});
  3229  
  3230  };
  3231  
  3232  color.hook( stepHooks );
  3233  
  3234  jQuery.cssHooks.borderColor = {
  3235  	expand: function( value ) {
  3236  		var expanded = {};
  3237  
  3238  		each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
  3239  			expanded[ "border" + part + "Color" ] = value;
  3240  		});
  3241  		return expanded;
  3242  	}
  3243  };
  3244  
  3245  // Basic color names only.
  3246  // Usage of any of the other color names requires adding yourself or including
  3247  // jquery.color.svg-names.js.
  3248  colors = jQuery.Color.names = {
  3249  	// 4.1. Basic color keywords
  3250  	aqua: "#00ffff",
  3251  	black: "#000000",
  3252  	blue: "#0000ff",
  3253  	fuchsia: "#ff00ff",
  3254  	gray: "#808080",
  3255  	green: "#008000",
  3256  	lime: "#00ff00",
  3257  	maroon: "#800000",
  3258  	navy: "#000080",
  3259  	olive: "#808000",
  3260  	purple: "#800080",
  3261  	red: "#ff0000",
  3262  	silver: "#c0c0c0",
  3263  	teal: "#008080",
  3264  	white: "#ffffff",
  3265  	yellow: "#ffff00",
  3266  
  3267  	// 4.2.3. "transparent" color keyword
  3268  	transparent: [ null, null, null, 0 ],
  3269  
  3270  	_default: "#ffffff"
  3271  };
  3272  
  3273  })( jQuery );
  3274  
  3275  
  3276  /******************************************************************************/
  3277  /****************************** CLASS ANIMATIONS ******************************/
  3278  /******************************************************************************/
  3279  (function() {
  3280  
  3281  var classAnimationActions = [ "add", "remove", "toggle" ],
  3282  	shorthandStyles = {
  3283  		border: 1,
  3284  		borderBottom: 1,
  3285  		borderColor: 1,
  3286  		borderLeft: 1,
  3287  		borderRight: 1,
  3288  		borderTop: 1,
  3289  		borderWidth: 1,
  3290  		margin: 1,
  3291  		padding: 1
  3292  	};
  3293  
  3294  $.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
  3295  	$.fx.step[ prop ] = function( fx ) {
  3296  		if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
  3297  			jQuery.style( fx.elem, prop, fx.end );
  3298  			fx.setAttr = true;
  3299  		}
  3300  	};
  3301  });
  3302  
  3303  function getElementStyles( elem ) {
  3304  	var key, len,
  3305  		style = elem.ownerDocument.defaultView ?
  3306  			elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
  3307  			elem.currentStyle,
  3308  		styles = {};
  3309  
  3310  	if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
  3311  		len = style.length;
  3312  		while ( len-- ) {
  3313  			key = style[ len ];
  3314  			if ( typeof style[ key ] === "string" ) {
  3315  				styles[ $.camelCase( key ) ] = style[ key ];
  3316  			}
  3317  		}
  3318  	// support: Opera, IE <9
  3319  	} else {
  3320  		for ( key in style ) {
  3321  			if ( typeof style[ key ] === "string" ) {
  3322  				styles[ key ] = style[ key ];
  3323  			}
  3324  		}
  3325  	}
  3326  
  3327  	return styles;
  3328  }
  3329  
  3330  
  3331  function styleDifference( oldStyle, newStyle ) {
  3332  	var diff = {},
  3333  		name, value;
  3334  
  3335  	for ( name in newStyle ) {
  3336  		value = newStyle[ name ];
  3337  		if ( oldStyle[ name ] !== value ) {
  3338  			if ( !shorthandStyles[ name ] ) {
  3339  				if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
  3340  					diff[ name ] = value;
  3341  				}
  3342  			}
  3343  		}
  3344  	}
  3345  
  3346  	return diff;
  3347  }
  3348  
  3349  // support: jQuery <1.8
  3350  if ( !$.fn.addBack ) {
  3351  	$.fn.addBack = function( selector ) {
  3352  		return this.add( selector == null ?
  3353  			this.prevObject : this.prevObject.filter( selector )
  3354  		);
  3355  	};
  3356  }
  3357  
  3358  $.effects.animateClass = function( value, duration, easing, callback ) {
  3359  	var o = $.speed( duration, easing, callback );
  3360  
  3361  	return this.queue( function() {
  3362  		var animated = $( this ),
  3363  			baseClass = animated.attr( "class" ) || "",
  3364  			applyClassChange,
  3365  			allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
  3366  
  3367  		// map the animated objects to store the original styles.
  3368  		allAnimations = allAnimations.map(function() {
  3369  			var el = $( this );
  3370  			return {
  3371  				el: el,
  3372  				start: getElementStyles( this )
  3373  			};
  3374  		});
  3375  
  3376  		// apply class change
  3377  		applyClassChange = function() {
  3378  			$.each( classAnimationActions, function(i, action) {
  3379  				if ( value[ action ] ) {
  3380  					animated[ action + "Class" ]( value[ action ] );
  3381  				}
  3382  			});
  3383  		};
  3384  		applyClassChange();
  3385  
  3386  		// map all animated objects again - calculate new styles and diff
  3387  		allAnimations = allAnimations.map(function() {
  3388  			this.end = getElementStyles( this.el[ 0 ] );
  3389  			this.diff = styleDifference( this.start, this.end );
  3390  			return this;
  3391  		});
  3392  
  3393  		// apply original class
  3394  		animated.attr( "class", baseClass );
  3395  
  3396  		// map all animated objects again - this time collecting a promise
  3397  		allAnimations = allAnimations.map(function() {
  3398  			var styleInfo = this,
  3399  				dfd = $.Deferred(),
  3400  				opts = $.extend({}, o, {
  3401  					queue: false,
  3402  					complete: function() {
  3403  						dfd.resolve( styleInfo );
  3404  					}
  3405  				});
  3406  
  3407  			this.el.animate( this.diff, opts );
  3408  			return dfd.promise();
  3409  		});
  3410  
  3411  		// once all animations have completed:
  3412  		$.when.apply( $, allAnimations.get() ).done(function() {
  3413  
  3414  			// set the final class
  3415  			applyClassChange();
  3416  
  3417  			// for each animated element,
  3418  			// clear all css properties that were animated
  3419  			$.each( arguments, function() {
  3420  				var el = this.el;
  3421  				$.each( this.diff, function(key) {
  3422  					el.css( key, "" );
  3423  				});
  3424  			});
  3425  
  3426  			// this is guarnteed to be there if you use jQuery.speed()
  3427  			// it also handles dequeuing the next anim...
  3428  			o.complete.call( animated[ 0 ] );
  3429  		});
  3430  	});
  3431  };
  3432  
  3433  $.fn.extend({
  3434  	addClass: (function( orig ) {
  3435  		return function( classNames, speed, easing, callback ) {
  3436  			return speed ?
  3437  				$.effects.animateClass.call( this,
  3438  					{ add: classNames }, speed, easing, callback ) :
  3439  				orig.apply( this, arguments );
  3440  		};
  3441  	})( $.fn.addClass ),
  3442  
  3443  	removeClass: (function( orig ) {
  3444  		return function( classNames, speed, easing, callback ) {
  3445  			return arguments.length > 1 ?
  3446  				$.effects.animateClass.call( this,
  3447  					{ remove: classNames }, speed, easing, callback ) :
  3448  				orig.apply( this, arguments );
  3449  		};
  3450  	})( $.fn.removeClass ),
  3451  
  3452  	toggleClass: (function( orig ) {
  3453  		return function( classNames, force, speed, easing, callback ) {
  3454  			if ( typeof force === "boolean" || force === undefined ) {
  3455  				if ( !speed ) {
  3456  					// without speed parameter
  3457  					return orig.apply( this, arguments );
  3458  				} else {
  3459  					return $.effects.animateClass.call( this,
  3460  						(force ? { add: classNames } : { remove: classNames }),
  3461  						speed, easing, callback );
  3462  				}
  3463  			} else {
  3464  				// without force parameter
  3465  				return $.effects.animateClass.call( this,
  3466  					{ toggle: classNames }, force, speed, easing );
  3467  			}
  3468  		};
  3469  	})( $.fn.toggleClass ),
  3470  
  3471  	switchClass: function( remove, add, speed, easing, callback) {
  3472  		return $.effects.animateClass.call( this, {
  3473  			add: add,
  3474  			remove: remove
  3475  		}, speed, easing, callback );
  3476  	}
  3477  });
  3478  
  3479  })();
  3480  
  3481  /******************************************************************************/
  3482  /*********************************** EFFECTS **********************************/
  3483  /******************************************************************************/
  3484  
  3485  (function() {
  3486  
  3487  $.extend( $.effects, {
  3488  	version: "1.10.4",
  3489  
  3490  	// Saves a set of properties in a data storage
  3491  	save: function( element, set ) {
  3492  		for( var i=0; i < set.length; i++ ) {
  3493  			if ( set[ i ] !== null ) {
  3494  				element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
  3495  			}
  3496  		}
  3497  	},
  3498  
  3499  	// Restores a set of previously saved properties from a data storage
  3500  	restore: function( element, set ) {
  3501  		var val, i;
  3502  		for( i=0; i < set.length; i++ ) {
  3503  			if ( set[ i ] !== null ) {
  3504  				val = element.data( dataSpace + set[ i ] );
  3505  				// support: jQuery 1.6.2
  3506  				// http://bugs.jquery.com/ticket/9917
  3507  				// jQuery 1.6.2 incorrectly returns undefined for any falsy value.
  3508  				// We can't differentiate between "" and 0 here, so we just assume
  3509  				// empty string since it's likely to be a more common value...
  3510  				if ( val === undefined ) {
  3511  					val = "";
  3512  				}
  3513  				element.css( set[ i ], val );
  3514  			}
  3515  		}
  3516  	},
  3517  
  3518  	setMode: function( el, mode ) {
  3519  		if (mode === "toggle") {
  3520  			mode = el.is( ":hidden" ) ? "show" : "hide";
  3521  		}
  3522  		return mode;
  3523  	},
  3524  
  3525  	// Translates a [top,left] array into a baseline value
  3526  	// this should be a little more flexible in the future to handle a string & hash
  3527  	getBaseline: function( origin, original ) {
  3528  		var y, x;
  3529  		switch ( origin[ 0 ] ) {
  3530  			case "top": y = 0; break;
  3531  			case "middle": y = 0.5; break;
  3532  			case "bottom": y = 1; break;
  3533  			default: y = origin[ 0 ] / original.height;
  3534  		}
  3535  		switch ( origin[ 1 ] ) {
  3536  			case "left": x = 0; break;
  3537  			case "center": x = 0.5; break;
  3538  			case "right": x = 1; break;
  3539  			default: x = origin[ 1 ] / original.width;
  3540  		}
  3541  		return {
  3542  			x: x,
  3543  			y: y
  3544  		};
  3545  	},
  3546  
  3547  	// Wraps the element around a wrapper that copies position properties
  3548  	createWrapper: function( element ) {
  3549  
  3550  		// if the element is already wrapped, return it
  3551  		if ( element.parent().is( ".ui-effects-wrapper" )) {
  3552  			return element.parent();
  3553  		}
  3554  
  3555  		// wrap the element
  3556  		var props = {
  3557  				width: element.outerWidth(true),
  3558  				height: element.outerHeight(true),
  3559  				"float": element.css( "float" )
  3560  			},
  3561  			wrapper = $( "<div></div>" )
  3562  				.addClass( "ui-effects-wrapper" )
  3563  				.css({
  3564  					fontSize: "100%",
  3565  					background: "transparent",
  3566  					border: "none",
  3567  					margin: 0,
  3568  					padding: 0
  3569  				}),
  3570  			// Store the size in case width/height are defined in % - Fixes #5245
  3571  			size = {
  3572  				width: element.width(),
  3573  				height: element.height()
  3574  			},
  3575  			active = document.activeElement;
  3576  
  3577  		// support: Firefox
  3578  		// Firefox incorrectly exposes anonymous content
  3579  		// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
  3580  		try {
  3581  			active.id;
  3582  		} catch( e ) {
  3583  			active = document.body;
  3584  		}
  3585  
  3586  		element.wrap( wrapper );
  3587  
  3588  		// Fixes #7595 - Elements lose focus when wrapped.
  3589  		if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
  3590  			$( active ).focus();
  3591  		}
  3592  
  3593  		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
  3594  
  3595  		// transfer positioning properties to the wrapper
  3596  		if ( element.css( "position" ) === "static" ) {
  3597  			wrapper.css({ position: "relative" });
  3598  			element.css({ position: "relative" });
  3599  		} else {
  3600  			$.extend( props, {
  3601  				position: element.css( "position" ),
  3602  				zIndex: element.css( "z-index" )
  3603  			});
  3604  			$.each([ "top", "left", "bottom", "right" ], function(i, pos) {
  3605  				props[ pos ] = element.css( pos );
  3606  				if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
  3607  					props[ pos ] = "auto";
  3608  				}
  3609  			});
  3610  			element.css({
  3611  				position: "relative",
  3612  				top: 0,
  3613  				left: 0,
  3614  				right: "auto",
  3615  				bottom: "auto"
  3616  			});
  3617  		}
  3618  		element.css(size);
  3619  
  3620  		return wrapper.css( props ).show();
  3621  	},
  3622  
  3623  	removeWrapper: function( element ) {
  3624  		var active = document.activeElement;
  3625  
  3626  		if ( element.parent().is( ".ui-effects-wrapper" ) ) {
  3627  			element.parent().replaceWith( element );
  3628  
  3629  			// Fixes #7595 - Elements lose focus when wrapped.
  3630  			if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
  3631  				$( active ).focus();
  3632  			}
  3633  		}
  3634  
  3635  
  3636  		return element;
  3637  	},
  3638  
  3639  	setTransition: function( element, list, factor, value ) {
  3640  		value = value || {};
  3641  		$.each( list, function( i, x ) {
  3642  			var unit = element.cssUnit( x );
  3643  			if ( unit[ 0 ] > 0 ) {
  3644  				value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
  3645  			}
  3646  		});
  3647  		return value;
  3648  	}
  3649  });
  3650  
  3651  // return an effect options object for the given parameters:
  3652  function _normalizeArguments( effect, options, speed, callback ) {
  3653  
  3654  	// allow passing all options as the first parameter
  3655  	if ( $.isPlainObject( effect ) ) {
  3656  		options = effect;
  3657  		effect = effect.effect;
  3658  	}
  3659  
  3660  	// convert to an object
  3661  	effect = { effect: effect };
  3662  
  3663  	// catch (effect, null, ...)
  3664  	if ( options == null ) {
  3665  		options = {};
  3666  	}
  3667  
  3668  	// catch (effect, callback)
  3669  	if ( $.isFunction( options ) ) {
  3670  		callback = options;
  3671  		speed = null;
  3672  		options = {};
  3673  	}
  3674  
  3675  	// catch (effect, speed, ?)
  3676  	if ( typeof options === "number" || $.fx.speeds[ options ] ) {
  3677  		callback = speed;
  3678  		speed = options;
  3679  		options = {};
  3680  	}
  3681  
  3682  	// catch (effect, options, callback)
  3683  	if ( $.isFunction( speed ) ) {
  3684  		callback = speed;
  3685  		speed = null;
  3686  	}
  3687  
  3688  	// add options to effect
  3689  	if ( options ) {
  3690  		$.extend( effect, options );
  3691  	}
  3692  
  3693  	speed = speed || options.duration;
  3694  	effect.duration = $.fx.off ? 0 :
  3695  		typeof speed === "number" ? speed :
  3696  		speed in $.fx.speeds ? $.fx.speeds[ speed ] :
  3697  		$.fx.speeds._default;
  3698  
  3699  	effect.complete = callback || options.complete;
  3700  
  3701  	return effect;
  3702  }
  3703  
  3704  function standardAnimationOption( option ) {
  3705  	// Valid standard speeds (nothing, number, named speed)
  3706  	if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
  3707  		return true;
  3708  	}
  3709  
  3710  	// Invalid strings - treat as "normal" speed
  3711  	if ( typeof option === "string" && !$.effects.effect[ option ] ) {
  3712  		return true;
  3713  	}
  3714  
  3715  	// Complete callback
  3716  	if ( $.isFunction( option ) ) {
  3717  		return true;
  3718  	}
  3719  
  3720  	// Options hash (but not naming an effect)
  3721  	if ( typeof option === "object" && !option.effect ) {
  3722  		return true;
  3723  	}
  3724  
  3725  	// Didn't match any standard API
  3726  	return false;
  3727  }
  3728  
  3729  $.fn.extend({
  3730  	effect: function( /* effect, options, speed, callback */ ) {
  3731  		var args = _normalizeArguments.apply( this, arguments ),
  3732  			mode = args.mode,
  3733  			queue = args.queue,
  3734  			effectMethod = $.effects.effect[ args.effect ];
  3735  
  3736  		if ( $.fx.off || !effectMethod ) {
  3737  			// delegate to the original method (e.g., .show()) if possible
  3738  			if ( mode ) {
  3739  				return this[ mode ]( args.duration, args.complete );
  3740  			} else {
  3741  				return this.each( function() {
  3742  					if ( args.complete ) {
  3743  						args.complete.call( this );
  3744  					}
  3745  				});
  3746  			}
  3747  		}
  3748  
  3749  		function run( next ) {
  3750  			var elem = $( this ),
  3751  				complete = args.complete,
  3752  				mode = args.mode;
  3753  
  3754  			function done() {
  3755  				if ( $.isFunction( complete ) ) {
  3756  					complete.call( elem[0] );
  3757  				}
  3758  				if ( $.isFunction( next ) ) {
  3759  					next();
  3760  				}
  3761  			}
  3762  
  3763  			// If the element already has the correct final state, delegate to
  3764  			// the core methods so the internal tracking of "olddisplay" works.
  3765  			if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
  3766  				elem[ mode ]();
  3767  				done();
  3768  			} else {
  3769  				effectMethod.call( elem[0], args, done );
  3770  			}
  3771  		}
  3772  
  3773  		return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
  3774  	},
  3775  
  3776  	show: (function( orig ) {
  3777  		return function( option ) {
  3778  			if ( standardAnimationOption( option ) ) {
  3779  				return orig.apply( this, arguments );
  3780  			} else {
  3781  				var args = _normalizeArguments.apply( this, arguments );
  3782  				args.mode = "show";
  3783  				return this.effect.call( this, args );
  3784  			}
  3785  		};
  3786  	})( $.fn.show ),
  3787  
  3788  	hide: (function( orig ) {
  3789  		return function( option ) {
  3790  			if ( standardAnimationOption( option ) ) {
  3791  				return orig.apply( this, arguments );
  3792  			} else {
  3793  				var args = _normalizeArguments.apply( this, arguments );
  3794  				args.mode = "hide";
  3795  				return this.effect.call( this, args );
  3796  			}
  3797  		};
  3798  	})( $.fn.hide ),
  3799  
  3800  	toggle: (function( orig ) {
  3801  		return function( option ) {
  3802  			if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
  3803  				return orig.apply( this, arguments );
  3804  			} else {
  3805  				var args = _normalizeArguments.apply( this, arguments );
  3806  				args.mode = "toggle";
  3807  				return this.effect.call( this, args );
  3808  			}
  3809  		};
  3810  	})( $.fn.toggle ),
  3811  
  3812  	// helper functions
  3813  	cssUnit: function(key) {
  3814  		var style = this.css( key ),
  3815  			val = [];
  3816  
  3817  		$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
  3818  			if ( style.indexOf( unit ) > 0 ) {
  3819  				val = [ parseFloat( style ), unit ];
  3820  			}
  3821  		});
  3822  		return val;
  3823  	}
  3824  });
  3825  
  3826  })();
  3827  
  3828  /******************************************************************************/
  3829  /*********************************** EASING ***********************************/
  3830  /******************************************************************************/
  3831  
  3832  (function() {
  3833  
  3834  // based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
  3835  
  3836  var baseEasings = {};
  3837  
  3838  $.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
  3839  	baseEasings[ name ] = function( p ) {
  3840  		return Math.pow( p, i + 2 );
  3841  	};
  3842  });
  3843  
  3844  $.extend( baseEasings, {
  3845  	Sine: function ( p ) {
  3846  		return 1 - Math.cos( p * Math.PI / 2 );
  3847  	},
  3848  	Circ: function ( p ) {
  3849  		return 1 - Math.sqrt( 1 - p * p );
  3850  	},
  3851  	Elastic: function( p ) {
  3852  		return p === 0 || p === 1 ? p :
  3853  			-Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
  3854  	},
  3855  	Back: function( p ) {
  3856  		return p * p * ( 3 * p - 2 );
  3857  	},
  3858  	Bounce: function ( p ) {
  3859  		var pow2,
  3860  			bounce = 4;
  3861  
  3862  		while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
  3863  		return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
  3864  	}
  3865  });
  3866  
  3867  $.each( baseEasings, function( name, easeIn ) {
  3868  	$.easing[ "easeIn" + name ] = easeIn;
  3869  	$.easing[ "easeOut" + name ] = function( p ) {
  3870  		return 1 - easeIn( 1 - p );
  3871  	};
  3872  	$.easing[ "easeInOut" + name ] = function( p ) {
  3873  		return p < 0.5 ?
  3874  			easeIn( p * 2 ) / 2 :
  3875  			1 - easeIn( p * -2 + 2 ) / 2;
  3876  	};
  3877  });
  3878  
  3879  })();
  3880  
  3881  })(jQuery);
  3882  
  3883  /*!
  3884   * jQuery UI Touch Punch 0.2.2
  3885   *
  3886   * Copyright 2011, Dave Furfero
  3887   * Dual licensed under the MIT or GPL Version 2 licenses.
  3888   *
  3889   * Depends:
  3890   *  jquery.ui.widget.js
  3891   *  jquery.ui.mouse.js
  3892   */
  3893  (function ($) {
  3894  
  3895    // Detect touch support
  3896    $.support.touch = 'ontouchend' in document;
  3897  
  3898    // Ignore browsers without touch support
  3899    if (!$.support.touch) {
  3900      return;
  3901    }
  3902  
  3903    var mouseProto = $.ui.mouse.prototype,
  3904        _mouseInit = mouseProto._mouseInit,
  3905        touchHandled;
  3906  
  3907    /**
  3908     * Simulate a mouse event based on a corresponding touch event
  3909     * @param {Object} event A touch event
  3910     * @param {String} simulatedType The corresponding mouse event
  3911     */
  3912    function simulateMouseEvent (event, simulatedType) {
  3913  
  3914      // Ignore multi-touch events
  3915      if (event.originalEvent.touches.length > 1) {
  3916        return;
  3917      }
  3918  
  3919      event.preventDefault();
  3920  
  3921      var touch = event.originalEvent.changedTouches[0],
  3922          simulatedEvent = document.createEvent('MouseEvents');
  3923      
  3924      // Initialize the simulated mouse event using the touch event's coordinates
  3925      simulatedEvent.initMouseEvent(
  3926        simulatedType,    // type
  3927        true,             // bubbles                    
  3928        true,             // cancelable                 
  3929        window,           // view                       
  3930        1,                // detail                     
  3931        touch.screenX,    // screenX                    
  3932        touch.screenY,    // screenY                    
  3933        touch.clientX,    // clientX                    
  3934        touch.clientY,    // clientY                    
  3935        false,            // ctrlKey                    
  3936        false,            // altKey                     
  3937        false,            // shiftKey                   
  3938        false,            // metaKey                    
  3939        0,                // button                     
  3940        null              // relatedTarget              
  3941      );
  3942  
  3943      // Dispatch the simulated event to the target element
  3944      event.target.dispatchEvent(simulatedEvent);
  3945    }
  3946  
  3947    /**
  3948     * Handle the jQuery UI widget's touchstart events
  3949     * @param {Object} event The widget element's touchstart event
  3950     */
  3951    mouseProto._touchStart = function (event) {
  3952  
  3953      var self = this;
  3954  
  3955      // Ignore the event if another widget is already being handled
  3956      if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0])) {
  3957        return;
  3958      }
  3959  
  3960      // Set the flag to prevent other widgets from inheriting the touch event
  3961      touchHandled = true;
  3962  
  3963      // Track movement to determine if interaction was a click
  3964      self._touchMoved = false;
  3965  
  3966      // Simulate the mouseover event
  3967      simulateMouseEvent(event, 'mouseover');
  3968  
  3969      // Simulate the mousemove event
  3970      simulateMouseEvent(event, 'mousemove');
  3971  
  3972      // Simulate the mousedown event
  3973      simulateMouseEvent(event, 'mousedown');
  3974    };
  3975  
  3976    /**
  3977     * Handle the jQuery UI widget's touchmove events
  3978     * @param {Object} event The document's touchmove event
  3979     */
  3980    mouseProto._touchMove = function (event) {
  3981  
  3982      // Ignore event if not handled
  3983      if (!touchHandled) {
  3984        return;
  3985      }
  3986  
  3987      // Interaction was not a click
  3988      this._touchMoved = true;
  3989  
  3990      // Simulate the mousemove event
  3991      simulateMouseEvent(event, 'mousemove');
  3992    };
  3993  
  3994    /**
  3995     * Handle the jQuery UI widget's touchend events
  3996     * @param {Object} event The document's touchend event
  3997     */
  3998    mouseProto._touchEnd = function (event) {
  3999  
  4000      // Ignore event if not handled
  4001      if (!touchHandled) {
  4002        return;
  4003      }
  4004  
  4005      // Simulate the mouseup event
  4006      simulateMouseEvent(event, 'mouseup');
  4007  
  4008      // Simulate the mouseout event
  4009      simulateMouseEvent(event, 'mouseout');
  4010  
  4011      // If the touch interaction did not move, it should trigger a click
  4012      if (!this._touchMoved) {
  4013  
  4014        // Simulate the click event
  4015        simulateMouseEvent(event, 'click');
  4016      }
  4017  
  4018      // Unset the flag to allow other widgets to inherit the touch event
  4019      touchHandled = false;
  4020    };
  4021  
  4022    /**
  4023     * A duck punch of the $.ui.mouse _mouseInit method to support touch events.
  4024     * This method extends the widget with bound touch event handlers that
  4025     * translate touch events to mouse events and pass them to the widget's
  4026     * original mouse event handling methods.
  4027     */
  4028    mouseProto._mouseInit = function () {
  4029      
  4030      var self = this;
  4031  
  4032      // Delegate the touch handlers to the widget's element
  4033      self.element
  4034        .bind('touchstart', $.proxy(self, '_touchStart'))
  4035        .bind('touchmove', $.proxy(self, '_touchMove'))
  4036        .bind('touchend', $.proxy(self, '_touchEnd'));
  4037  
  4038      // Call the original $.ui.mouse init method
  4039      _mouseInit.call(self);
  4040    };
  4041  
  4042  })(jQuery);
  4043  /*!
  4044   * Bootstrap v3.2.0 (http://getbootstrap.com)
  4045   * Copyright 2011-2014 Twitter, Inc.
  4046   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  4047   */
  4048  
  4049  if (typeof jQuery === 'undefined') { throw new Error('Bootstrap\'s JavaScript requires jQuery') }
  4050  
  4051  /* ========================================================================
  4052   * Bootstrap: transition.js v3.2.0
  4053   * http://getbootstrap.com/javascript/#transitions
  4054   * ========================================================================
  4055   * Copyright 2011-2014 Twitter, Inc.
  4056   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  4057   * ======================================================================== */
  4058  
  4059  
  4060  +function ($) {
  4061    'use strict';
  4062  
  4063    // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
  4064    // ============================================================
  4065  
  4066    function transitionEnd() {
  4067      var el = document.createElement('bootstrap')
  4068  
  4069      var transEndEventNames = {
  4070        WebkitTransition : 'webkitTransitionEnd',
  4071        MozTransition    : 'transitionend',
  4072        OTransition      : 'oTransitionEnd otransitionend',
  4073        transition       : 'transitionend'
  4074      }
  4075  
  4076      for (var name in transEndEventNames) {
  4077        if (el.style[name] !== undefined) {
  4078          return { end: transEndEventNames[name] }
  4079        }
  4080      }
  4081  
  4082      return false // explicit for ie8 (  ._.)
  4083    }
  4084  
  4085    // http://blog.alexmaccaw.com/css-transitions
  4086    $.fn.emulateTransitionEnd = function (duration) {
  4087      var called = false
  4088      var $el = this
  4089      $(this).one('bsTransitionEnd', function () { called = true })
  4090      var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
  4091      setTimeout(callback, duration)
  4092      return this
  4093    }
  4094  
  4095    $(function () {
  4096      $.support.transition = transitionEnd()
  4097  
  4098      if (!$.support.transition) return
  4099  
  4100      $.event.special.bsTransitionEnd = {
  4101        bindType: $.support.transition.end,
  4102        delegateType: $.support.transition.end,
  4103        handle: function (e) {
  4104          if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
  4105        }
  4106      }
  4107    })
  4108  
  4109  }(jQuery);
  4110  
  4111  /* ========================================================================
  4112   * Bootstrap: alert.js v3.2.0
  4113   * http://getbootstrap.com/javascript/#alerts
  4114   * ========================================================================
  4115   * Copyright 2011-2014 Twitter, Inc.
  4116   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  4117   * ======================================================================== */
  4118  
  4119  
  4120  +function ($) {
  4121    'use strict';
  4122  
  4123    // ALERT CLASS DEFINITION
  4124    // ======================
  4125  
  4126    var dismiss = '[data-dismiss="alert"]'
  4127    var Alert   = function (el) {
  4128      $(el).on('click', dismiss, this.close)
  4129    }
  4130  
  4131    Alert.VERSION = '3.2.0'
  4132  
  4133    Alert.prototype.close = function (e) {
  4134      var $this    = $(this)
  4135      var selector = $this.attr('data-target')
  4136  
  4137      if (!selector) {
  4138        selector = $this.attr('href')
  4139        selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
  4140      }
  4141  
  4142      var $parent = $(selector)
  4143  
  4144      if (e) e.preventDefault()
  4145  
  4146      if (!$parent.length) {
  4147        $parent = $this.hasClass('alert') ? $this : $this.parent()
  4148      }
  4149  
  4150      $parent.trigger(e = $.Event('close.bs.alert'))
  4151  
  4152      if (e.isDefaultPrevented()) return
  4153  
  4154      $parent.removeClass('in')
  4155  
  4156      function removeElement() {
  4157        // detach from parent, fire event then clean up data
  4158        $parent.detach().trigger('closed.bs.alert').remove()
  4159      }
  4160  
  4161      $.support.transition && $parent.hasClass('fade') ?
  4162        $parent
  4163          .one('bsTransitionEnd', removeElement)
  4164          .emulateTransitionEnd(150) :
  4165        removeElement()
  4166    }
  4167  
  4168  
  4169    // ALERT PLUGIN DEFINITION
  4170    // =======================
  4171  
  4172    function Plugin(option) {
  4173      return this.each(function () {
  4174        var $this = $(this)
  4175        var data  = $this.data('bs.alert')
  4176  
  4177        if (!data) $this.data('bs.alert', (data = new Alert(this)))
  4178        if (typeof option == 'string') data[option].call($this)
  4179      })
  4180    }
  4181  
  4182    var old = $.fn.alert
  4183  
  4184    $.fn.alert             = Plugin
  4185    $.fn.alert.Constructor = Alert
  4186  
  4187  
  4188    // ALERT NO CONFLICT
  4189    // =================
  4190  
  4191    $.fn.alert.noConflict = function () {
  4192      $.fn.alert = old
  4193      return this
  4194    }
  4195  
  4196  
  4197    // ALERT DATA-API
  4198    // ==============
  4199  
  4200    $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)
  4201  
  4202  }(jQuery);
  4203  
  4204  /* ========================================================================
  4205   * Bootstrap: button.js v3.2.0
  4206   * http://getbootstrap.com/javascript/#buttons
  4207   * ========================================================================
  4208   * Copyright 2011-2014 Twitter, Inc.
  4209   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  4210   * ======================================================================== */
  4211  
  4212  
  4213  +function ($) {
  4214    'use strict';
  4215  
  4216    // BUTTON PUBLIC CLASS DEFINITION
  4217    // ==============================
  4218  
  4219    var Button = function (element, options) {
  4220      this.$element  = $(element)
  4221      this.options   = $.extend({}, Button.DEFAULTS, options)
  4222      this.isLoading = false
  4223    }
  4224  
  4225    Button.VERSION  = '3.2.0'
  4226  
  4227    Button.DEFAULTS = {
  4228      loadingText: 'loading...'
  4229    }
  4230  
  4231    Button.prototype.setState = function (state) {
  4232      var d    = 'disabled'
  4233      var $el  = this.$element
  4234      var val  = $el.is('input') ? 'val' : 'html'
  4235      var data = $el.data()
  4236  
  4237      state = state + 'Text'
  4238  
  4239      if (data.resetText == null) $el.data('resetText', $el[val]())
  4240  
  4241      $el[val](data[state] == null ? this.options[state] : data[state])
  4242  
  4243      // push to event loop to allow forms to submit
  4244      setTimeout($.proxy(function () {
  4245        if (state == 'loadingText') {
  4246          this.isLoading = true
  4247          $el.addClass(d).attr(d, d)
  4248        } else if (this.isLoading) {
  4249          this.isLoading = false
  4250          $el.removeClass(d).removeAttr(d)
  4251        }
  4252      }, this), 0)
  4253    }
  4254  
  4255    Button.prototype.toggle = function () {
  4256      var changed = true
  4257      var $parent = this.$element.closest('[data-toggle="buttons"]')
  4258  
  4259      if ($parent.length) {
  4260        var $input = this.$element.find('input')
  4261        if ($input.prop('type') == 'radio') {
  4262          if ($input.prop('checked') && this.$element.hasClass('active')) changed = false
  4263          else $parent.find('.active').removeClass('active')
  4264        }
  4265        if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
  4266      }
  4267  
  4268      if (changed) this.$element.toggleClass('active')
  4269    }
  4270  
  4271  
  4272    // BUTTON PLUGIN DEFINITION
  4273    // ========================
  4274  
  4275    function Plugin(option) {
  4276      return this.each(function () {
  4277        var $this   = $(this)
  4278        var data    = $this.data('bs.button')
  4279        var options = typeof option == 'object' && option
  4280  
  4281        if (!data) $this.data('bs.button', (data = new Button(this, options)))
  4282  
  4283        if (option == 'toggle') data.toggle()
  4284        else if (option) data.setState(option)
  4285      })
  4286    }
  4287  
  4288    var old = $.fn.button
  4289  
  4290    $.fn.button             = Plugin
  4291    $.fn.button.Constructor = Button
  4292  
  4293  
  4294    // BUTTON NO CONFLICT
  4295    // ==================
  4296  
  4297    $.fn.button.noConflict = function () {
  4298      $.fn.button = old
  4299      return this
  4300    }
  4301  
  4302  
  4303    // BUTTON DATA-API
  4304    // ===============
  4305  
  4306    $(document).on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
  4307      var $btn = $(e.target)
  4308      if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
  4309      Plugin.call($btn, 'toggle')
  4310      e.preventDefault()
  4311    })
  4312  
  4313  }(jQuery);
  4314  
  4315  /* ========================================================================
  4316   * Bootstrap: carousel.js v3.2.0
  4317   * http://getbootstrap.com/javascript/#carousel
  4318   * ========================================================================
  4319   * Copyright 2011-2014 Twitter, Inc.
  4320   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  4321   * ======================================================================== */
  4322  
  4323  
  4324  +function ($) {
  4325    'use strict';
  4326  
  4327    // CAROUSEL CLASS DEFINITION
  4328    // =========================
  4329  
  4330    var Carousel = function (element, options) {
  4331      this.$element    = $(element).on('keydown.bs.carousel', $.proxy(this.keydown, this))
  4332      this.$indicators = this.$element.find('.carousel-indicators')
  4333      this.options     = options
  4334      this.paused      =
  4335      this.sliding     =
  4336      this.interval    =
  4337      this.$active     =
  4338      this.$items      = null
  4339  
  4340      this.options.pause == 'hover' && this.$element
  4341        .on('mouseenter.bs.carousel', $.proxy(this.pause, this))
  4342        .on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
  4343    }
  4344  
  4345    Carousel.VERSION  = '3.2.0'
  4346  
  4347    Carousel.DEFAULTS = {
  4348      interval: 5000,
  4349      pause: 'hover',
  4350      wrap: true
  4351    }
  4352  
  4353    Carousel.prototype.keydown = function (e) {
  4354      switch (e.which) {
  4355        case 37: this.prev(); break
  4356        case 39: this.next(); break
  4357        default: return
  4358      }
  4359  
  4360      e.preventDefault()
  4361    }
  4362  
  4363    Carousel.prototype.cycle = function (e) {
  4364      e || (this.paused = false)
  4365  
  4366      this.interval && clearInterval(this.interval)
  4367  
  4368      this.options.interval
  4369        && !this.paused
  4370        && (this.interval = setInterval($.proxy(this.next, this), this.options.interval))
  4371  
  4372      return this
  4373    }
  4374  
  4375    Carousel.prototype.getItemIndex = function (item) {
  4376      this.$items = item.parent().children('.item')
  4377      return this.$items.index(item || this.$active)
  4378    }
  4379  
  4380    Carousel.prototype.to = function (pos) {
  4381      var that        = this
  4382      var activeIndex = this.getItemIndex(this.$active = this.$element.find('.item.active'))
  4383  
  4384      if (pos > (this.$items.length - 1) || pos < 0) return
  4385  
  4386      if (this.sliding)       return this.$element.one('slid.bs.carousel', function () { that.to(pos) }) // yes, "slid"
  4387      if (activeIndex == pos) return this.pause().cycle()
  4388  
  4389      return this.slide(pos > activeIndex ? 'next' : 'prev', $(this.$items[pos]))
  4390    }
  4391  
  4392    Carousel.prototype.pause = function (e) {
  4393      e || (this.paused = true)
  4394  
  4395      if (this.$element.find('.next, .prev').length && $.support.transition) {
  4396        this.$element.trigger($.support.transition.end)
  4397        this.cycle(true)
  4398      }
  4399  
  4400      this.interval = clearInterval(this.interval)
  4401  
  4402      return this
  4403    }
  4404  
  4405    Carousel.prototype.next = function () {
  4406      if (this.sliding) return
  4407      return this.slide('next')
  4408    }
  4409  
  4410    Carousel.prototype.prev = function () {
  4411      if (this.sliding) return
  4412      return this.slide('prev')
  4413    }
  4414  
  4415    Carousel.prototype.slide = function (type, next) {
  4416      var $active   = this.$element.find('.item.active')
  4417      var $next     = next || $active[type]()
  4418      var isCycling = this.interval
  4419      var direction = type == 'next' ? 'left' : 'right'
  4420      var fallback  = type == 'next' ? 'first' : 'last'
  4421      var that      = this
  4422  
  4423      if (!$next.length) {
  4424        if (!this.options.wrap) return
  4425        $next = this.$element.find('.item')[fallback]()
  4426      }
  4427  
  4428      if ($next.hasClass('active')) return (this.sliding = false)
  4429  
  4430      var relatedTarget = $next[0]
  4431      var slideEvent = $.Event('slide.bs.carousel', {
  4432        relatedTarget: relatedTarget,
  4433        direction: direction
  4434      })
  4435      this.$element.trigger(slideEvent)
  4436      if (slideEvent.isDefaultPrevented()) return
  4437  
  4438      this.sliding = true
  4439  
  4440      isCycling && this.pause()
  4441  
  4442      if (this.$indicators.length) {
  4443        this.$indicators.find('.active').removeClass('active')
  4444        var $nextIndicator = $(this.$indicators.children()[this.getItemIndex($next)])
  4445        $nextIndicator && $nextIndicator.addClass('active')
  4446      }
  4447  
  4448      var slidEvent = $.Event('slid.bs.carousel', { relatedTarget: relatedTarget, direction: direction }) // yes, "slid"
  4449      if ($.support.transition && this.$element.hasClass('slide')) {
  4450        $next.addClass(type)
  4451        $next[0].offsetWidth // force reflow
  4452        $active.addClass(direction)
  4453        $next.addClass(direction)
  4454        $active
  4455          .one('bsTransitionEnd', function () {
  4456            $next.removeClass([type, direction].join(' ')).addClass('active')
  4457            $active.removeClass(['active', direction].join(' '))
  4458            that.sliding = false
  4459            setTimeout(function () {
  4460              that.$element.trigger(slidEvent)
  4461            }, 0)
  4462          })
  4463          .emulateTransitionEnd($active.css('transition-duration').slice(0, -1) * 1000)
  4464      } else {
  4465        $active.removeClass('active')
  4466        $next.addClass('active')
  4467        this.sliding = false
  4468        this.$element.trigger(slidEvent)
  4469      }
  4470  
  4471      isCycling && this.cycle()
  4472  
  4473      return this
  4474    }
  4475  
  4476  
  4477    // CAROUSEL PLUGIN DEFINITION
  4478    // ==========================
  4479  
  4480    function Plugin(option) {
  4481      return this.each(function () {
  4482        var $this   = $(this)
  4483        var data    = $this.data('bs.carousel')
  4484        var options = $.extend({}, Carousel.DEFAULTS, $this.data(), typeof option == 'object' && option)
  4485        var action  = typeof option == 'string' ? option : options.slide
  4486  
  4487        if (!data) $this.data('bs.carousel', (data = new Carousel(this, options)))
  4488        if (typeof option == 'number') data.to(option)
  4489        else if (action) data[action]()
  4490        else if (options.interval) data.pause().cycle()
  4491      })
  4492    }
  4493  
  4494    var old = $.fn.carousel
  4495  
  4496    $.fn.carousel             = Plugin
  4497    $.fn.carousel.Constructor = Carousel
  4498  
  4499  
  4500    // CAROUSEL NO CONFLICT
  4501    // ====================
  4502  
  4503    $.fn.carousel.noConflict = function () {
  4504      $.fn.carousel = old
  4505      return this
  4506    }
  4507  
  4508  
  4509    // CAROUSEL DATA-API
  4510    // =================
  4511  
  4512    $(document).on('click.bs.carousel.data-api', '[data-slide], [data-slide-to]', function (e) {
  4513      var href
  4514      var $this   = $(this)
  4515      var $target = $($this.attr('data-target') || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '')) // strip for ie7
  4516      if (!$target.hasClass('carousel')) return
  4517      var options = $.extend({}, $target.data(), $this.data())
  4518      var slideIndex = $this.attr('data-slide-to')
  4519      if (slideIndex) options.interval = false
  4520  
  4521      Plugin.call($target, options)
  4522  
  4523      if (slideIndex) {
  4524        $target.data('bs.carousel').to(slideIndex)
  4525      }
  4526  
  4527      e.preventDefault()
  4528    })
  4529  
  4530    $(window).on('load', function () {
  4531      $('[data-ride="carousel"]').each(function () {
  4532        var $carousel = $(this)
  4533        Plugin.call($carousel, $carousel.data())
  4534      })
  4535    })
  4536  
  4537  }(jQuery);
  4538  
  4539  /* ========================================================================
  4540   * Bootstrap: collapse.js v3.2.0
  4541   * http://getbootstrap.com/javascript/#collapse
  4542   * ========================================================================
  4543   * Copyright 2011-2014 Twitter, Inc.
  4544   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  4545   * ======================================================================== */
  4546  
  4547  
  4548  +function ($) {
  4549    'use strict';
  4550  
  4551    // COLLAPSE PUBLIC CLASS DEFINITION
  4552    // ================================
  4553  
  4554    var Collapse = function (element, options) {
  4555      this.$element      = $(element)
  4556      this.options       = $.extend({}, Collapse.DEFAULTS, options)
  4557      this.transitioning = null
  4558  
  4559      if (this.options.parent) this.$parent = $(this.options.parent)
  4560      if (this.options.toggle) this.toggle()
  4561    }
  4562  
  4563    Collapse.VERSION  = '3.2.0'
  4564  
  4565    Collapse.DEFAULTS = {
  4566      toggle: true
  4567    }
  4568  
  4569    Collapse.prototype.dimension = function () {
  4570      var hasWidth = this.$element.hasClass('width')
  4571      return hasWidth ? 'width' : 'height'
  4572    }
  4573  
  4574    Collapse.prototype.show = function () {
  4575      if (this.transitioning || this.$element.hasClass('in')) return
  4576  
  4577      var startEvent = $.Event('show.bs.collapse')
  4578      this.$element.trigger(startEvent)
  4579      if (startEvent.isDefaultPrevented()) return
  4580  
  4581      var actives = this.$parent && this.$parent.find('> .panel > .in')
  4582  
  4583      if (actives && actives.length) {
  4584        var hasData = actives.data('bs.collapse')
  4585        if (hasData && hasData.transitioning) return
  4586        Plugin.call(actives, 'hide')
  4587        hasData || actives.data('bs.collapse', null)
  4588      }
  4589  
  4590      var dimension = this.dimension()
  4591  
  4592      this.$element
  4593        .removeClass('collapse')
  4594        .addClass('collapsing')[dimension](0)
  4595  
  4596      this.transitioning = 1
  4597  
  4598      var complete = function () {
  4599        this.$element
  4600          .removeClass('collapsing')
  4601          .addClass('collapse in')[dimension]('')
  4602        this.transitioning = 0
  4603        this.$element
  4604          .trigger('shown.bs.collapse')
  4605      }
  4606  
  4607      if (!$.support.transition) return complete.call(this)
  4608  
  4609      var scrollSize = $.camelCase(['scroll', dimension].join('-'))
  4610  
  4611      this.$element
  4612        .one('bsTransitionEnd', $.proxy(complete, this))
  4613        .emulateTransitionEnd(350)[dimension](this.$element[0][scrollSize])
  4614    }
  4615  
  4616    Collapse.prototype.hide = function () {
  4617      if (this.transitioning || !this.$element.hasClass('in')) return
  4618  
  4619      var startEvent = $.Event('hide.bs.collapse')
  4620      this.$element.trigger(startEvent)
  4621      if (startEvent.isDefaultPrevented()) return
  4622  
  4623      var dimension = this.dimension()
  4624  
  4625      this.$element[dimension](this.$element[dimension]())[0].offsetHeight
  4626  
  4627      this.$element
  4628        .addClass('collapsing')
  4629        .removeClass('collapse')
  4630        .removeClass('in')
  4631  
  4632      this.transitioning = 1
  4633  
  4634      var complete = function () {
  4635        this.transitioning = 0
  4636        this.$element
  4637          .trigger('hidden.bs.collapse')
  4638          .removeClass('collapsing')
  4639          .addClass('collapse')
  4640      }
  4641  
  4642      if (!$.support.transition) return complete.call(this)
  4643  
  4644      this.$element
  4645        [dimension](0)
  4646        .one('bsTransitionEnd', $.proxy(complete, this))
  4647        .emulateTransitionEnd(350)
  4648    }
  4649  
  4650    Collapse.prototype.toggle = function () {
  4651      this[this.$element.hasClass('in') ? 'hide' : 'show']()
  4652    }
  4653  
  4654  
  4655    // COLLAPSE PLUGIN DEFINITION
  4656    // ==========================
  4657  
  4658    function Plugin(option) {
  4659      return this.each(function () {
  4660        var $this   = $(this)
  4661        var data    = $this.data('bs.collapse')
  4662        var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
  4663  
  4664        if (!data && options.toggle && option == 'show') option = !option
  4665        if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
  4666        if (typeof option == 'string') data[option]()
  4667      })
  4668    }
  4669  
  4670    var old = $.fn.collapse
  4671  
  4672    $.fn.collapse             = Plugin
  4673    $.fn.collapse.Constructor = Collapse
  4674  
  4675  
  4676    // COLLAPSE NO CONFLICT
  4677    // ====================
  4678  
  4679    $.fn.collapse.noConflict = function () {
  4680      $.fn.collapse = old
  4681      return this
  4682    }
  4683  
  4684  
  4685    // COLLAPSE DATA-API
  4686    // =================
  4687  
  4688    $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
  4689      var href
  4690      var $this   = $(this)
  4691      var target  = $this.attr('data-target')
  4692          || e.preventDefault()
  4693          || (href = $this.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7
  4694      var $target = $(target)
  4695      var data    = $target.data('bs.collapse')
  4696      var option  = data ? 'toggle' : $this.data()
  4697      var parent  = $this.attr('data-parent')
  4698      var $parent = parent && $(parent)
  4699  
  4700      if (!data || !data.transitioning) {
  4701        if ($parent) $parent.find('[data-toggle="collapse"][data-parent="' + parent + '"]').not($this).addClass('collapsed')
  4702        $this[$target.hasClass('in') ? 'addClass' : 'removeClass']('collapsed')
  4703      }
  4704  
  4705      Plugin.call($target, option)
  4706    })
  4707  
  4708  }(jQuery);
  4709  
  4710  /* ========================================================================
  4711   * Bootstrap: dropdown.js v3.2.0
  4712   * http://getbootstrap.com/javascript/#dropdowns
  4713   * ========================================================================
  4714   * Copyright 2011-2014 Twitter, Inc.
  4715   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  4716   * ======================================================================== */
  4717  
  4718  
  4719  +function ($) {
  4720    'use strict';
  4721  
  4722    // DROPDOWN CLASS DEFINITION
  4723    // =========================
  4724  
  4725    var backdrop = '.dropdown-backdrop'
  4726    var toggle   = '[data-toggle="dropdown"]'
  4727    var Dropdown = function (element) {
  4728      $(element).on('click.bs.dropdown', this.toggle)
  4729    }
  4730  
  4731    Dropdown.VERSION = '3.2.0'
  4732  
  4733    Dropdown.prototype.toggle = function (e) {
  4734      var $this = $(this)
  4735  
  4736      if ($this.is('.disabled, :disabled')) return
  4737  
  4738      var $parent  = getParent($this)
  4739      var isActive = $parent.hasClass('open')
  4740  
  4741      clearMenus()
  4742  
  4743      if (!isActive) {
  4744        if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
  4745          // if mobile we use a backdrop because click events don't delegate
  4746          $('<div class="dropdown-backdrop"/>').insertAfter($(this)).on('click', clearMenus)
  4747        }
  4748  
  4749        var relatedTarget = { relatedTarget: this }
  4750        $parent.trigger(e = $.Event('show.bs.dropdown', relatedTarget))
  4751  
  4752        if (e.isDefaultPrevented()) return
  4753  
  4754        $this.trigger('focus')
  4755  
  4756        $parent
  4757          .toggleClass('open')
  4758          .trigger('shown.bs.dropdown', relatedTarget)
  4759      }
  4760  
  4761      return false
  4762    }
  4763  
  4764    Dropdown.prototype.keydown = function (e) {
  4765      if (!/(38|40|27)/.test(e.keyCode)) return
  4766  
  4767      var $this = $(this)
  4768  
  4769      e.preventDefault()
  4770      e.stopPropagation()
  4771  
  4772      if ($this.is('.disabled, :disabled')) return
  4773  
  4774      var $parent  = getParent($this)
  4775      var isActive = $parent.hasClass('open')
  4776  
  4777      if (!isActive || (isActive && e.keyCode == 27)) {
  4778        if (e.which == 27) $parent.find(toggle).trigger('focus')
  4779        return $this.trigger('click')
  4780      }
  4781  
  4782      var desc = ' li:not(.divider):visible a'
  4783      var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
  4784  
  4785      if (!$items.length) return
  4786  
  4787      var index = $items.index($items.filter(':focus'))
  4788  
  4789      if (e.keyCode == 38 && index > 0)                 index--                        // up
  4790      if (e.keyCode == 40 && index < $items.length - 1) index++                        // down
  4791      if (!~index)                                      index = 0
  4792  
  4793      $items.eq(index).trigger('focus')
  4794    }
  4795  
  4796    function clearMenus(e) {
  4797      if (e && e.which === 3) return
  4798      $(backdrop).remove()
  4799      $(toggle).each(function () {
  4800        var $parent = getParent($(this))
  4801        var relatedTarget = { relatedTarget: this }
  4802        if (!$parent.hasClass('open')) return
  4803        $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
  4804        if (e.isDefaultPrevented()) return
  4805        $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
  4806      })
  4807    }
  4808  
  4809    function getParent($this) {
  4810      var selector = $this.attr('data-target')
  4811  
  4812      if (!selector) {
  4813        selector = $this.attr('href')
  4814        selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
  4815      }
  4816  
  4817      var $parent = selector && $(selector)
  4818  
  4819      return $parent && $parent.length ? $parent : $this.parent()
  4820    }
  4821  
  4822  
  4823    // DROPDOWN PLUGIN DEFINITION
  4824    // ==========================
  4825  
  4826    function Plugin(option) {
  4827      return this.each(function () {
  4828        var $this = $(this)
  4829        var data  = $this.data('bs.dropdown')
  4830  
  4831        if (!data) $this.data('bs.dropdown', (data = new Dropdown(this)))
  4832        if (typeof option == 'string') data[option].call($this)
  4833      })
  4834    }
  4835  
  4836    var old = $.fn.dropdown
  4837  
  4838    $.fn.dropdown             = Plugin
  4839    $.fn.dropdown.Constructor = Dropdown
  4840  
  4841  
  4842    // DROPDOWN NO CONFLICT
  4843    // ====================
  4844  
  4845    $.fn.dropdown.noConflict = function () {
  4846      $.fn.dropdown = old
  4847      return this
  4848    }
  4849  
  4850  
  4851    // APPLY TO STANDARD DROPDOWN ELEMENTS
  4852    // ===================================
  4853  
  4854    $(document)
  4855      .on('click.bs.dropdown.data-api', clearMenus)
  4856      .on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
  4857      .on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
  4858      .on('keydown.bs.dropdown.data-api', toggle + ', [role="menu"], [role="listbox"]', Dropdown.prototype.keydown)
  4859  
  4860  }(jQuery);
  4861  
  4862  /* ========================================================================
  4863   * Bootstrap: modal.js v3.2.0
  4864   * http://getbootstrap.com/javascript/#modals
  4865   * ========================================================================
  4866   * Copyright 2011-2014 Twitter, Inc.
  4867   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  4868   * ======================================================================== */
  4869  
  4870  
  4871  +function ($) {
  4872    'use strict';
  4873  
  4874    // MODAL CLASS DEFINITION
  4875    // ======================
  4876  
  4877    var Modal = function (element, options) {
  4878      this.options        = options
  4879      this.$body          = $(document.body)
  4880      this.$element       = $(element)
  4881      this.$backdrop      =
  4882      this.isShown        = null
  4883      this.scrollbarWidth = 0
  4884  
  4885      if (this.options.remote) {
  4886        this.$element
  4887          .find('.modal-content')
  4888          .load(this.options.remote, $.proxy(function () {
  4889            this.$element.trigger('loaded.bs.modal')
  4890          }, this))
  4891      }
  4892    }
  4893  
  4894    Modal.VERSION  = '3.2.0'
  4895  
  4896    Modal.DEFAULTS = {
  4897      backdrop: true,
  4898      keyboard: true,
  4899      show: true
  4900    }
  4901  
  4902    Modal.prototype.toggle = function (_relatedTarget) {
  4903      return this.isShown ? this.hide() : this.show(_relatedTarget)
  4904    }
  4905  
  4906    Modal.prototype.show = function (_relatedTarget) {
  4907      var that = this
  4908      var e    = $.Event('show.bs.modal', { relatedTarget: _relatedTarget })
  4909  
  4910      this.$element.trigger(e)
  4911  
  4912      if (this.isShown || e.isDefaultPrevented()) return
  4913  
  4914      this.isShown = true
  4915  
  4916      this.checkScrollbar()
  4917      this.$body.addClass('modal-open')
  4918  
  4919      this.setScrollbar()
  4920      this.escape()
  4921  
  4922      this.$element.on('click.dismiss.bs.modal', '[data-dismiss="modal"]', $.proxy(this.hide, this))
  4923  
  4924      this.backdrop(function () {
  4925        var transition = $.support.transition && that.$element.hasClass('fade')
  4926  
  4927        if (!that.$element.parent().length) {
  4928          that.$element.appendTo(that.$body) // don't move modals dom position
  4929        }
  4930  
  4931        that.$element
  4932          .show()
  4933          .scrollTop(0)
  4934  
  4935        if (transition) {
  4936          that.$element[0].offsetWidth // force reflow
  4937        }
  4938  
  4939        that.$element
  4940          .addClass('in')
  4941          .attr('aria-hidden', false)
  4942  
  4943        that.enforceFocus()
  4944  
  4945        var e = $.Event('shown.bs.modal', { relatedTarget: _relatedTarget })
  4946  
  4947        transition ?
  4948          that.$element.find('.modal-dialog') // wait for modal to slide in
  4949            .one('bsTransitionEnd', function () {
  4950              that.$element.trigger('focus').trigger(e)
  4951            })
  4952            .emulateTransitionEnd(300) :
  4953          that.$element.trigger('focus').trigger(e)
  4954      })
  4955    }
  4956  
  4957    Modal.prototype.hide = function (e) {
  4958      if (e) e.preventDefault()
  4959  
  4960      e = $.Event('hide.bs.modal')
  4961  
  4962      this.$element.trigger(e)
  4963  
  4964      if (!this.isShown || e.isDefaultPrevented()) return
  4965  
  4966      this.isShown = false
  4967  
  4968      this.$body.removeClass('modal-open')
  4969  
  4970      this.resetScrollbar()
  4971      this.escape()
  4972  
  4973      $(document).off('focusin.bs.modal')
  4974  
  4975      this.$element
  4976        .removeClass('in')
  4977        .attr('aria-hidden', true)
  4978        .off('click.dismiss.bs.modal')
  4979  
  4980      $.support.transition && this.$element.hasClass('fade') ?
  4981        this.$element
  4982          .one('bsTransitionEnd', $.proxy(this.hideModal, this))
  4983          .emulateTransitionEnd(300) :
  4984        this.hideModal()
  4985    }
  4986  
  4987    Modal.prototype.enforceFocus = function () {
  4988      $(document)
  4989        .off('focusin.bs.modal') // guard against infinite focus loop
  4990        .on('focusin.bs.modal', $.proxy(function (e) {
  4991          if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
  4992            this.$element.trigger('focus')
  4993          }
  4994        }, this))
  4995    }
  4996  
  4997    Modal.prototype.escape = function () {
  4998      if (this.isShown && this.options.keyboard) {
  4999        this.$element.on('keyup.dismiss.bs.modal', $.proxy(function (e) {
  5000          e.which == 27 && this.hide()
  5001        }, this))
  5002      } else if (!this.isShown) {
  5003        this.$element.off('keyup.dismiss.bs.modal')
  5004      }
  5005    }
  5006  
  5007    Modal.prototype.hideModal = function () {
  5008      var that = this
  5009      this.$element.hide()
  5010      this.backdrop(function () {
  5011        that.$element.trigger('hidden.bs.modal')
  5012      })
  5013    }
  5014  
  5015    Modal.prototype.removeBackdrop = function () {
  5016      this.$backdrop && this.$backdrop.remove()
  5017      this.$backdrop = null
  5018    }
  5019  
  5020    Modal.prototype.backdrop = function (callback) {
  5021      var that = this
  5022      var animate = this.$element.hasClass('fade') ? 'fade' : ''
  5023  
  5024      if (this.isShown && this.options.backdrop) {
  5025        var doAnimate = $.support.transition && animate
  5026  
  5027        this.$backdrop = $('<div class="modal-backdrop ' + animate + '" />')
  5028          .appendTo(this.$body)
  5029  
  5030        this.$element.on('click.dismiss.bs.modal', $.proxy(function (e) {
  5031          if (e.target !== e.currentTarget) return
  5032          this.options.backdrop == 'static'
  5033            ? this.$element[0].focus.call(this.$element[0])
  5034            : this.hide.call(this)
  5035        }, this))
  5036  
  5037        if (doAnimate) this.$backdrop[0].offsetWidth // force reflow
  5038  
  5039        this.$backdrop.addClass('in')
  5040  
  5041        if (!callback) return
  5042  
  5043        doAnimate ?
  5044          this.$backdrop
  5045            .one('bsTransitionEnd', callback)
  5046            .emulateTransitionEnd(150) :
  5047          callback()
  5048  
  5049      } else if (!this.isShown && this.$backdrop) {
  5050        this.$backdrop.removeClass('in')
  5051  
  5052        var callbackRemove = function () {
  5053          that.removeBackdrop()
  5054          callback && callback()
  5055        }
  5056        $.support.transition && this.$element.hasClass('fade') ?
  5057          this.$backdrop
  5058            .one('bsTransitionEnd', callbackRemove)
  5059            .emulateTransitionEnd(150) :
  5060          callbackRemove()
  5061  
  5062      } else if (callback) {
  5063        callback()
  5064      }
  5065    }
  5066  
  5067    Modal.prototype.checkScrollbar = function () {
  5068      if (document.body.clientWidth >= window.innerWidth) return
  5069      this.scrollbarWidth = this.scrollbarWidth || this.measureScrollbar()
  5070    }
  5071  
  5072    Modal.prototype.setScrollbar = function () {
  5073      var bodyPad = parseInt((this.$body.css('padding-right') || 0), 10)
  5074      if (this.scrollbarWidth) this.$body.css('padding-right', bodyPad + this.scrollbarWidth)
  5075    }
  5076  
  5077    Modal.prototype.resetScrollbar = function () {
  5078      this.$body.css('padding-right', '')
  5079    }
  5080  
  5081    Modal.prototype.measureScrollbar = function () { // thx walsh
  5082      var scrollDiv = document.createElement('div')
  5083      scrollDiv.className = 'modal-scrollbar-measure'
  5084      this.$body.append(scrollDiv)
  5085      var scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth
  5086      this.$body[0].removeChild(scrollDiv)
  5087      return scrollbarWidth
  5088    }
  5089  
  5090  
  5091    // MODAL PLUGIN DEFINITION
  5092    // =======================
  5093  
  5094    function Plugin(option, _relatedTarget) {
  5095      return this.each(function () {
  5096        var $this   = $(this)
  5097        var data    = $this.data('bs.modal')
  5098        var options = $.extend({}, Modal.DEFAULTS, $this.data(), typeof option == 'object' && option)
  5099  
  5100        if (!data) $this.data('bs.modal', (data = new Modal(this, options)))
  5101        if (typeof option == 'string') data[option](_relatedTarget)
  5102        else if (options.show) data.show(_relatedTarget)
  5103      })
  5104    }
  5105  
  5106    var old = $.fn.modal
  5107  
  5108    $.fn.modal             = Plugin
  5109    $.fn.modal.Constructor = Modal
  5110  
  5111  
  5112    // MODAL NO CONFLICT
  5113    // =================
  5114  
  5115    $.fn.modal.noConflict = function () {
  5116      $.fn.modal = old
  5117      return this
  5118    }
  5119  
  5120  
  5121    // MODAL DATA-API
  5122    // ==============
  5123  
  5124    $(document).on('click.bs.modal.data-api', '[data-toggle="modal"]', function (e) {
  5125      var $this   = $(this)
  5126      var href    = $this.attr('href')
  5127      var $target = $($this.attr('data-target') || (href && href.replace(/.*(?=#[^\s]+$)/, ''))) // strip for ie7
  5128      var option  = $target.data('bs.modal') ? 'toggle' : $.extend({ remote: !/#/.test(href) && href }, $target.data(), $this.data())
  5129  
  5130      if ($this.is('a')) e.preventDefault()
  5131  
  5132      $target.one('show.bs.modal', function (showEvent) {
  5133        if (showEvent.isDefaultPrevented()) return // only register focus restorer if modal will actually get shown
  5134        $target.one('hidden.bs.modal', function () {
  5135          $this.is(':visible') && $this.trigger('focus')
  5136        })
  5137      })
  5138      Plugin.call($target, option, this)
  5139    })
  5140  
  5141  }(jQuery);
  5142  
  5143  /* ========================================================================
  5144   * Bootstrap: tooltip.js v3.2.0
  5145   * http://getbootstrap.com/javascript/#tooltip
  5146   * Inspired by the original jQuery.tipsy by Jason Frame
  5147   * ========================================================================
  5148   * Copyright 2011-2014 Twitter, Inc.
  5149   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  5150   * ======================================================================== */
  5151  
  5152  
  5153  +function ($) {
  5154    'use strict';
  5155  
  5156    // TOOLTIP PUBLIC CLASS DEFINITION
  5157    // ===============================
  5158  
  5159    var Tooltip = function (element, options) {
  5160      this.type       =
  5161      this.options    =
  5162      this.enabled    =
  5163      this.timeout    =
  5164      this.hoverState =
  5165      this.$element   = null
  5166  
  5167      this.init('tooltip', element, options)
  5168    }
  5169  
  5170    Tooltip.VERSION  = '3.2.0'
  5171  
  5172    Tooltip.DEFAULTS = {
  5173      animation: true,
  5174      placement: 'top',
  5175      selector: false,
  5176      template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
  5177      trigger: 'hover focus',
  5178      title: '',
  5179      delay: 0,
  5180      html: false,
  5181      container: false,
  5182      viewport: {
  5183        selector: 'body',
  5184        padding: 0
  5185      }
  5186    }
  5187  
  5188    Tooltip.prototype.init = function (type, element, options) {
  5189      this.enabled   = true
  5190      this.type      = type
  5191      this.$element  = $(element)
  5192      this.options   = this.getOptions(options)
  5193      this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
  5194  
  5195      var triggers = this.options.trigger.split(' ')
  5196  
  5197      for (var i = triggers.length; i--;) {
  5198        var trigger = triggers[i]
  5199  
  5200        if (trigger == 'click') {
  5201          this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
  5202        } else if (trigger != 'manual') {
  5203          var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
  5204          var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'
  5205  
  5206          this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
  5207          this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
  5208        }
  5209      }
  5210  
  5211      this.options.selector ?
  5212        (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
  5213        this.fixTitle()
  5214    }
  5215  
  5216    Tooltip.prototype.getDefaults = function () {
  5217      return Tooltip.DEFAULTS
  5218    }
  5219  
  5220    Tooltip.prototype.getOptions = function (options) {
  5221      options = $.extend({}, this.getDefaults(), this.$element.data(), options)
  5222  
  5223      if (options.delay && typeof options.delay == 'number') {
  5224        options.delay = {
  5225          show: options.delay,
  5226          hide: options.delay
  5227        }
  5228      }
  5229  
  5230      return options
  5231    }
  5232  
  5233    Tooltip.prototype.getDelegateOptions = function () {
  5234      var options  = {}
  5235      var defaults = this.getDefaults()
  5236  
  5237      this._options && $.each(this._options, function (key, value) {
  5238        if (defaults[key] != value) options[key] = value
  5239      })
  5240  
  5241      return options
  5242    }
  5243  
  5244    Tooltip.prototype.enter = function (obj) {
  5245      var self = obj instanceof this.constructor ?
  5246        obj : $(obj.currentTarget).data('bs.' + this.type)
  5247  
  5248      if (!self) {
  5249        self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
  5250        $(obj.currentTarget).data('bs.' + this.type, self)
  5251      }
  5252  
  5253      clearTimeout(self.timeout)
  5254  
  5255      self.hoverState = 'in'
  5256  
  5257      if (!self.options.delay || !self.options.delay.show) return self.show()
  5258  
  5259      self.timeout = setTimeout(function () {
  5260        if (self.hoverState == 'in') self.show()
  5261      }, self.options.delay.show)
  5262    }
  5263  
  5264    Tooltip.prototype.leave = function (obj) {
  5265      var self = obj instanceof this.constructor ?
  5266        obj : $(obj.currentTarget).data('bs.' + this.type)
  5267  
  5268      if (!self) {
  5269        self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
  5270        $(obj.currentTarget).data('bs.' + this.type, self)
  5271      }
  5272  
  5273      clearTimeout(self.timeout)
  5274  
  5275      self.hoverState = 'out'
  5276  
  5277      if (!self.options.delay || !self.options.delay.hide) return self.hide()
  5278  
  5279      self.timeout = setTimeout(function () {
  5280        if (self.hoverState == 'out') self.hide()
  5281      }, self.options.delay.hide)
  5282    }
  5283  
  5284    Tooltip.prototype.show = function () {
  5285      var e = $.Event('show.bs.' + this.type)
  5286  
  5287      if (this.hasContent() && this.enabled) {
  5288        this.$element.trigger(e)
  5289  
  5290        var inDom = $.contains(document.documentElement, this.$element[0])
  5291        if (e.isDefaultPrevented() || !inDom) return
  5292        var that = this
  5293  
  5294        var $tip = this.tip()
  5295  
  5296        var tipId = this.getUID(this.type)
  5297  
  5298        this.setContent()
  5299        $tip.attr('id', tipId)
  5300        this.$element.attr('aria-describedby', tipId)
  5301  
  5302        if (this.options.animation) $tip.addClass('fade')
  5303  
  5304        var placement = typeof this.options.placement == 'function' ?
  5305          this.options.placement.call(this, $tip[0], this.$element[0]) :
  5306          this.options.placement
  5307  
  5308        var autoToken = /\s?auto?\s?/i
  5309        var autoPlace = autoToken.test(placement)
  5310        if (autoPlace) placement = placement.replace(autoToken, '') || 'top'
  5311  
  5312        $tip
  5313          .detach()
  5314          .css({ top: 0, left: 0, display: 'block' })
  5315          .addClass(placement)
  5316          .data('bs.' + this.type, this)
  5317  
  5318        this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
  5319  
  5320        var pos          = this.getPosition()
  5321        var actualWidth  = $tip[0].offsetWidth
  5322        var actualHeight = $tip[0].offsetHeight
  5323  
  5324        if (autoPlace) {
  5325          var orgPlacement = placement
  5326          var $parent      = this.$element.parent()
  5327          var parentDim    = this.getPosition($parent)
  5328  
  5329          placement = placement == 'bottom' && pos.top   + pos.height       + actualHeight - parentDim.scroll > parentDim.height ? 'top'    :
  5330                      placement == 'top'    && pos.top   - parentDim.scroll - actualHeight < 0                                   ? 'bottom' :
  5331                      placement == 'right'  && pos.right + actualWidth      > parentDim.width                                    ? 'left'   :
  5332                      placement == 'left'   && pos.left  - actualWidth      < parentDim.left                                     ? 'right'  :
  5333                      placement
  5334  
  5335          $tip
  5336            .removeClass(orgPlacement)
  5337            .addClass(placement)
  5338        }
  5339  
  5340        var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
  5341  
  5342        this.applyPlacement(calculatedOffset, placement)
  5343  
  5344        var complete = function () {
  5345          that.$element.trigger('shown.bs.' + that.type)
  5346          that.hoverState = null
  5347        }
  5348  
  5349        $.support.transition && this.$tip.hasClass('fade') ?
  5350          $tip
  5351            .one('bsTransitionEnd', complete)
  5352            .emulateTransitionEnd(150) :
  5353          complete()
  5354      }
  5355    }
  5356  
  5357    Tooltip.prototype.applyPlacement = function (offset, placement) {
  5358      var $tip   = this.tip()
  5359      var width  = $tip[0].offsetWidth
  5360      var height = $tip[0].offsetHeight
  5361  
  5362      // manually read margins because getBoundingClientRect includes difference
  5363      var marginTop = parseInt($tip.css('margin-top'), 10)
  5364      var marginLeft = parseInt($tip.css('margin-left'), 10)
  5365  
  5366      // we must check for NaN for ie 8/9
  5367      if (isNaN(marginTop))  marginTop  = 0
  5368      if (isNaN(marginLeft)) marginLeft = 0
  5369  
  5370      offset.top  = offset.top  + marginTop
  5371      offset.left = offset.left + marginLeft
  5372  
  5373      // $.fn.offset doesn't round pixel values
  5374      // so we use setOffset directly with our own function B-0
  5375      $.offset.setOffset($tip[0], $.extend({
  5376        using: function (props) {
  5377          $tip.css({
  5378            top: Math.round(props.top),
  5379            left: Math.round(props.left)
  5380          })
  5381        }
  5382      }, offset), 0)
  5383  
  5384      $tip.addClass('in')
  5385  
  5386      // check to see if placing tip in new offset caused the tip to resize itself
  5387      var actualWidth  = $tip[0].offsetWidth
  5388      var actualHeight = $tip[0].offsetHeight
  5389  
  5390      if (placement == 'top' && actualHeight != height) {
  5391        offset.top = offset.top + height - actualHeight
  5392      }
  5393  
  5394      var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)
  5395  
  5396      if (delta.left) offset.left += delta.left
  5397      else offset.top += delta.top
  5398  
  5399      var arrowDelta          = delta.left ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
  5400      var arrowPosition       = delta.left ? 'left'        : 'top'
  5401      var arrowOffsetPosition = delta.left ? 'offsetWidth' : 'offsetHeight'
  5402  
  5403      $tip.offset(offset)
  5404      this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], arrowPosition)
  5405    }
  5406  
  5407    Tooltip.prototype.replaceArrow = function (delta, dimension, position) {
  5408      this.arrow().css(position, delta ? (50 * (1 - delta / dimension) + '%') : '')
  5409    }
  5410  
  5411    Tooltip.prototype.setContent = function () {
  5412      var $tip  = this.tip()
  5413      var title = this.getTitle()
  5414  
  5415      $tip.find('.tooltip-inner')[this.options.html ? 'html' : 'text'](title)
  5416      $tip.removeClass('fade in top bottom left right')
  5417    }
  5418  
  5419    Tooltip.prototype.hide = function () {
  5420      var that = this
  5421      var $tip = this.tip()
  5422      var e    = $.Event('hide.bs.' + this.type)
  5423  
  5424      this.$element.removeAttr('aria-describedby')
  5425  
  5426      function complete() {
  5427        if (that.hoverState != 'in') $tip.detach()
  5428        that.$element.trigger('hidden.bs.' + that.type)
  5429      }
  5430  
  5431      this.$element.trigger(e)
  5432  
  5433      if (e.isDefaultPrevented()) return
  5434  
  5435      $tip.removeClass('in')
  5436  
  5437      $.support.transition && this.$tip.hasClass('fade') ?
  5438        $tip
  5439          .one('bsTransitionEnd', complete)
  5440          .emulateTransitionEnd(150) :
  5441        complete()
  5442  
  5443      this.hoverState = null
  5444  
  5445      return this
  5446    }
  5447  
  5448    Tooltip.prototype.fixTitle = function () {
  5449      var $e = this.$element
  5450      if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
  5451        $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
  5452      }
  5453    }
  5454  
  5455    Tooltip.prototype.hasContent = function () {
  5456      return this.getTitle()
  5457    }
  5458  
  5459    Tooltip.prototype.getPosition = function ($element) {
  5460      $element   = $element || this.$element
  5461      var el     = $element[0]
  5462      var isBody = el.tagName == 'BODY'
  5463      return $.extend({}, (typeof el.getBoundingClientRect == 'function') ? el.getBoundingClientRect() : null, {
  5464        scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop(),
  5465        width:  isBody ? $(window).width()  : $element.outerWidth(),
  5466        height: isBody ? $(window).height() : $element.outerHeight()
  5467      }, isBody ? { top: 0, left: 0 } : $element.offset())
  5468    }
  5469  
  5470    Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
  5471      return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2  } :
  5472             placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2  } :
  5473             placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
  5474          /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width   }
  5475  
  5476    }
  5477  
  5478    Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
  5479      var delta = { top: 0, left: 0 }
  5480      if (!this.$viewport) return delta
  5481  
  5482      var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
  5483      var viewportDimensions = this.getPosition(this.$viewport)
  5484  
  5485      if (/right|left/.test(placement)) {
  5486        var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
  5487        var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
  5488        if (topEdgeOffset < viewportDimensions.top) { // top overflow
  5489          delta.top = viewportDimensions.top - topEdgeOffset
  5490        } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
  5491          delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
  5492        }
  5493      } else {
  5494        var leftEdgeOffset  = pos.left - viewportPadding
  5495        var rightEdgeOffset = pos.left + viewportPadding + actualWidth
  5496        if (leftEdgeOffset < viewportDimensions.left) { // left overflow
  5497          delta.left = viewportDimensions.left - leftEdgeOffset
  5498        } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
  5499          delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
  5500        }
  5501      }
  5502  
  5503      return delta
  5504    }
  5505  
  5506    Tooltip.prototype.getTitle = function () {
  5507      var title
  5508      var $e = this.$element
  5509      var o  = this.options
  5510  
  5511      title = $e.attr('data-original-title')
  5512        || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)
  5513  
  5514      return title
  5515    }
  5516  
  5517    Tooltip.prototype.getUID = function (prefix) {
  5518      do prefix += ~~(Math.random() * 1000000)
  5519      while (document.getElementById(prefix))
  5520      return prefix
  5521    }
  5522  
  5523    Tooltip.prototype.tip = function () {
  5524      return (this.$tip = this.$tip || $(this.options.template))
  5525    }
  5526  
  5527    Tooltip.prototype.arrow = function () {
  5528      return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
  5529    }
  5530  
  5531    Tooltip.prototype.validate = function () {
  5532      if (!this.$element[0].parentNode) {
  5533        this.hide()
  5534        this.$element = null
  5535        this.options  = null
  5536      }
  5537    }
  5538  
  5539    Tooltip.prototype.enable = function () {
  5540      this.enabled = true
  5541    }
  5542  
  5543    Tooltip.prototype.disable = function () {
  5544      this.enabled = false
  5545    }
  5546  
  5547    Tooltip.prototype.toggleEnabled = function () {
  5548      this.enabled = !this.enabled
  5549    }
  5550  
  5551    Tooltip.prototype.toggle = function (e) {
  5552      var self = this
  5553      if (e) {
  5554        self = $(e.currentTarget).data('bs.' + this.type)
  5555        if (!self) {
  5556          self = new this.constructor(e.currentTarget, this.getDelegateOptions())
  5557          $(e.currentTarget).data('bs.' + this.type, self)
  5558        }
  5559      }
  5560  
  5561      self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
  5562    }
  5563  
  5564    Tooltip.prototype.destroy = function () {
  5565      clearTimeout(this.timeout)
  5566      this.hide().$element.off('.' + this.type).removeData('bs.' + this.type)
  5567    }
  5568  
  5569  
  5570    // TOOLTIP PLUGIN DEFINITION
  5571    // =========================
  5572  
  5573    function Plugin(option) {
  5574      return this.each(function () {
  5575        var $this   = $(this)
  5576        var data    = $this.data('bs.tooltip')
  5577        var options = typeof option == 'object' && option
  5578  
  5579        if (!data && option == 'destroy') return
  5580        if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
  5581        if (typeof option == 'string') data[option]()
  5582      })
  5583    }
  5584  
  5585    var old = $.fn.tooltip
  5586  
  5587    $.fn.tooltip             = Plugin
  5588    $.fn.tooltip.Constructor = Tooltip
  5589  
  5590  
  5591    // TOOLTIP NO CONFLICT
  5592    // ===================
  5593  
  5594    $.fn.tooltip.noConflict = function () {
  5595      $.fn.tooltip = old
  5596      return this
  5597    }
  5598  
  5599  }(jQuery);
  5600  
  5601  /* ========================================================================
  5602   * Bootstrap: popover.js v3.2.0
  5603   * http://getbootstrap.com/javascript/#popovers
  5604   * ========================================================================
  5605   * Copyright 2011-2014 Twitter, Inc.
  5606   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  5607   * ======================================================================== */
  5608  
  5609  
  5610  +function ($) {
  5611    'use strict';
  5612  
  5613    // POPOVER PUBLIC CLASS DEFINITION
  5614    // ===============================
  5615  
  5616    var Popover = function (element, options) {
  5617      this.init('popover', element, options)
  5618    }
  5619  
  5620    if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
  5621  
  5622    Popover.VERSION  = '3.2.0'
  5623  
  5624    Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
  5625      placement: 'right',
  5626      trigger: 'click',
  5627      content: '',
  5628      template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
  5629    })
  5630  
  5631  
  5632    // NOTE: POPOVER EXTENDS tooltip.js
  5633    // ================================
  5634  
  5635    Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)
  5636  
  5637    Popover.prototype.constructor = Popover
  5638  
  5639    Popover.prototype.getDefaults = function () {
  5640      return Popover.DEFAULTS
  5641    }
  5642  
  5643    Popover.prototype.setContent = function () {
  5644      var $tip    = this.tip()
  5645      var title   = this.getTitle()
  5646      var content = this.getContent()
  5647  
  5648      $tip.find('.popover-title')[this.options.html ? 'html' : 'text'](title)
  5649      $tip.find('.popover-content').empty()[ // we use append for html objects to maintain js events
  5650        this.options.html ? (typeof content == 'string' ? 'html' : 'append') : 'text'
  5651      ](content)
  5652  
  5653      $tip.removeClass('fade top bottom left right in')
  5654  
  5655      // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
  5656      // this manually by checking the contents.
  5657      if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
  5658    }
  5659  
  5660    Popover.prototype.hasContent = function () {
  5661      return this.getTitle() || this.getContent()
  5662    }
  5663  
  5664    Popover.prototype.getContent = function () {
  5665      var $e = this.$element
  5666      var o  = this.options
  5667  
  5668      return $e.attr('data-content')
  5669        || (typeof o.content == 'function' ?
  5670              o.content.call($e[0]) :
  5671              o.content)
  5672    }
  5673  
  5674    Popover.prototype.arrow = function () {
  5675      return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
  5676    }
  5677  
  5678    Popover.prototype.tip = function () {
  5679      if (!this.$tip) this.$tip = $(this.options.template)
  5680      return this.$tip
  5681    }
  5682  
  5683  
  5684    // POPOVER PLUGIN DEFINITION
  5685    // =========================
  5686  
  5687    function Plugin(option) {
  5688      return this.each(function () {
  5689        var $this   = $(this)
  5690        var data    = $this.data('bs.popover')
  5691        var options = typeof option == 'object' && option
  5692  
  5693        if (!data && option == 'destroy') return
  5694        if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
  5695        if (typeof option == 'string') data[option]()
  5696      })
  5697    }
  5698  
  5699    var old = $.fn.popover
  5700  
  5701    $.fn.popover             = Plugin
  5702    $.fn.popover.Constructor = Popover
  5703  
  5704  
  5705    // POPOVER NO CONFLICT
  5706    // ===================
  5707  
  5708    $.fn.popover.noConflict = function () {
  5709      $.fn.popover = old
  5710      return this
  5711    }
  5712  
  5713  }(jQuery);
  5714  
  5715  /* ========================================================================
  5716   * Bootstrap: scrollspy.js v3.2.0
  5717   * http://getbootstrap.com/javascript/#scrollspy
  5718   * ========================================================================
  5719   * Copyright 2011-2014 Twitter, Inc.
  5720   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  5721   * ======================================================================== */
  5722  
  5723  
  5724  +function ($) {
  5725    'use strict';
  5726  
  5727    // SCROLLSPY CLASS DEFINITION
  5728    // ==========================
  5729  
  5730    function ScrollSpy(element, options) {
  5731      var process  = $.proxy(this.process, this)
  5732  
  5733      this.$body          = $('body')
  5734      this.$scrollElement = $(element).is('body') ? $(window) : $(element)
  5735      this.options        = $.extend({}, ScrollSpy.DEFAULTS, options)
  5736      this.selector       = (this.options.target || '') + ' .nav li > a'
  5737      this.offsets        = []
  5738      this.targets        = []
  5739      this.activeTarget   = null
  5740      this.scrollHeight   = 0
  5741  
  5742      this.$scrollElement.on('scroll.bs.scrollspy', process)
  5743      this.refresh()
  5744      this.process()
  5745    }
  5746  
  5747    ScrollSpy.VERSION  = '3.2.0'
  5748  
  5749    ScrollSpy.DEFAULTS = {
  5750      offset: 10
  5751    }
  5752  
  5753    ScrollSpy.prototype.getScrollHeight = function () {
  5754      return this.$scrollElement[0].scrollHeight || Math.max(this.$body[0].scrollHeight, document.documentElement.scrollHeight)
  5755    }
  5756  
  5757    ScrollSpy.prototype.refresh = function () {
  5758      var offsetMethod = 'offset'
  5759      var offsetBase   = 0
  5760  
  5761      if (!$.isWindow(this.$scrollElement[0])) {
  5762        offsetMethod = 'position'
  5763        offsetBase   = this.$scrollElement.scrollTop()
  5764      }
  5765  
  5766      this.offsets = []
  5767      this.targets = []
  5768      this.scrollHeight = this.getScrollHeight()
  5769  
  5770      var self     = this
  5771  
  5772      this.$body
  5773        .find(this.selector)
  5774        .map(function () {
  5775          var $el   = $(this)
  5776          var href  = $el.data('target') || $el.attr('href')
  5777          var $href = /^#./.test(href) && $(href)
  5778  
  5779          return ($href
  5780            && $href.length
  5781            && $href.is(':visible')
  5782            && [[$href[offsetMethod]().top + offsetBase, href]]) || null
  5783        })
  5784        .sort(function (a, b) { return a[0] - b[0] })
  5785        .each(function () {
  5786          self.offsets.push(this[0])
  5787          self.targets.push(this[1])
  5788        })
  5789    }
  5790  
  5791    ScrollSpy.prototype.process = function () {
  5792      var scrollTop    = this.$scrollElement.scrollTop() + this.options.offset
  5793      var scrollHeight = this.getScrollHeight()
  5794      var maxScroll    = this.options.offset + scrollHeight - this.$scrollElement.height()
  5795      var offsets      = this.offsets
  5796      var targets      = this.targets
  5797      var activeTarget = this.activeTarget
  5798      var i
  5799  
  5800      if (this.scrollHeight != scrollHeight) {
  5801        this.refresh()
  5802      }
  5803  
  5804      if (scrollTop >= maxScroll) {
  5805        return activeTarget != (i = targets[targets.length - 1]) && this.activate(i)
  5806      }
  5807  
  5808      if (activeTarget && scrollTop <= offsets[0]) {
  5809        return activeTarget != (i = targets[0]) && this.activate(i)
  5810      }
  5811  
  5812      for (i = offsets.length; i--;) {
  5813        activeTarget != targets[i]
  5814          && scrollTop >= offsets[i]
  5815          && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
  5816          && this.activate(targets[i])
  5817      }
  5818    }
  5819  
  5820    ScrollSpy.prototype.activate = function (target) {
  5821      this.activeTarget = target
  5822  
  5823      $(this.selector)
  5824        .parentsUntil(this.options.target, '.active')
  5825        .removeClass('active')
  5826  
  5827      var selector = this.selector +
  5828          '[data-target="' + target + '"],' +
  5829          this.selector + '[href="' + target + '"]'
  5830  
  5831      var active = $(selector)
  5832        .parents('li')
  5833        .addClass('active')
  5834  
  5835      if (active.parent('.dropdown-menu').length) {
  5836        active = active
  5837          .closest('li.dropdown')
  5838          .addClass('active')
  5839      }
  5840  
  5841      active.trigger('activate.bs.scrollspy')
  5842    }
  5843  
  5844  
  5845    // SCROLLSPY PLUGIN DEFINITION
  5846    // ===========================
  5847  
  5848    function Plugin(option) {
  5849      return this.each(function () {
  5850        var $this   = $(this)
  5851        var data    = $this.data('bs.scrollspy')
  5852        var options = typeof option == 'object' && option
  5853  
  5854        if (!data) $this.data('bs.scrollspy', (data = new ScrollSpy(this, options)))
  5855        if (typeof option == 'string') data[option]()
  5856      })
  5857    }
  5858  
  5859    var old = $.fn.scrollspy
  5860  
  5861    $.fn.scrollspy             = Plugin
  5862    $.fn.scrollspy.Constructor = ScrollSpy
  5863  
  5864  
  5865    // SCROLLSPY NO CONFLICT
  5866    // =====================
  5867  
  5868    $.fn.scrollspy.noConflict = function () {
  5869      $.fn.scrollspy = old
  5870      return this
  5871    }
  5872  
  5873  
  5874    // SCROLLSPY DATA-API
  5875    // ==================
  5876  
  5877    $(window).on('load.bs.scrollspy.data-api', function () {
  5878      $('[data-spy="scroll"]').each(function () {
  5879        var $spy = $(this)
  5880        Plugin.call($spy, $spy.data())
  5881      })
  5882    })
  5883  
  5884  }(jQuery);
  5885  
  5886  /* ========================================================================
  5887   * Bootstrap: tab.js v3.2.0
  5888   * http://getbootstrap.com/javascript/#tabs
  5889   * ========================================================================
  5890   * Copyright 2011-2014 Twitter, Inc.
  5891   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  5892   * ======================================================================== */
  5893  
  5894  
  5895  +function ($) {
  5896    'use strict';
  5897  
  5898    // TAB CLASS DEFINITION
  5899    // ====================
  5900  
  5901    var Tab = function (element) {
  5902      this.element = $(element)
  5903    }
  5904  
  5905    Tab.VERSION = '3.2.0'
  5906  
  5907    Tab.prototype.show = function () {
  5908      var $this    = this.element
  5909      var $ul      = $this.closest('ul:not(.dropdown-menu)')
  5910      var selector = $this.data('target')
  5911  
  5912      if (!selector) {
  5913        selector = $this.attr('href')
  5914        selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
  5915      }
  5916  
  5917      if ($this.parent('li').hasClass('active')) return
  5918  
  5919      var previous = $ul.find('.active:last a')[0]
  5920      var e        = $.Event('show.bs.tab', {
  5921        relatedTarget: previous
  5922      })
  5923  
  5924      $this.trigger(e)
  5925  
  5926      if (e.isDefaultPrevented()) return
  5927  
  5928      var $target = $(selector)
  5929  
  5930      this.activate($this.closest('li'), $ul)
  5931      this.activate($target, $target.parent(), function () {
  5932        $this.trigger({
  5933          type: 'shown.bs.tab',
  5934          relatedTarget: previous
  5935        })
  5936      })
  5937    }
  5938  
  5939    Tab.prototype.activate = function (element, container, callback) {
  5940      var $active    = container.find('> .active')
  5941      var transition = callback
  5942        && $.support.transition
  5943        && $active.hasClass('fade')
  5944  
  5945      function next() {
  5946        $active
  5947          .removeClass('active')
  5948          .find('> .dropdown-menu > .active')
  5949          .removeClass('active')
  5950  
  5951        element.addClass('active')
  5952  
  5953        if (transition) {
  5954          element[0].offsetWidth // reflow for transition
  5955          element.addClass('in')
  5956        } else {
  5957          element.removeClass('fade')
  5958        }
  5959  
  5960        if (element.parent('.dropdown-menu')) {
  5961          element.closest('li.dropdown').addClass('active')
  5962        }
  5963  
  5964        callback && callback()
  5965      }
  5966  
  5967      transition ?
  5968        $active
  5969          .one('bsTransitionEnd', next)
  5970          .emulateTransitionEnd(150) :
  5971        next()
  5972  
  5973      $active.removeClass('in')
  5974    }
  5975  
  5976  
  5977    // TAB PLUGIN DEFINITION
  5978    // =====================
  5979  
  5980    function Plugin(option) {
  5981      return this.each(function () {
  5982        var $this = $(this)
  5983        var data  = $this.data('bs.tab')
  5984  
  5985        if (!data) $this.data('bs.tab', (data = new Tab(this)))
  5986        if (typeof option == 'string') data[option]()
  5987      })
  5988    }
  5989  
  5990    var old = $.fn.tab
  5991  
  5992    $.fn.tab             = Plugin
  5993    $.fn.tab.Constructor = Tab
  5994  
  5995  
  5996    // TAB NO CONFLICT
  5997    // ===============
  5998  
  5999    $.fn.tab.noConflict = function () {
  6000      $.fn.tab = old
  6001      return this
  6002    }
  6003  
  6004  
  6005    // TAB DATA-API
  6006    // ============
  6007  
  6008    $(document).on('click.bs.tab.data-api', '[data-toggle="tab"], [data-toggle="pill"]', function (e) {
  6009      e.preventDefault()
  6010      Plugin.call($(this), 'show')
  6011    })
  6012  
  6013  }(jQuery);
  6014  
  6015  /* ========================================================================
  6016   * Bootstrap: affix.js v3.2.0
  6017   * http://getbootstrap.com/javascript/#affix
  6018   * ========================================================================
  6019   * Copyright 2011-2014 Twitter, Inc.
  6020   * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
  6021   * ======================================================================== */
  6022  
  6023  
  6024  +function ($) {
  6025    'use strict';
  6026  
  6027    // AFFIX CLASS DEFINITION
  6028    // ======================
  6029  
  6030    var Affix = function (element, options) {
  6031      this.options = $.extend({}, Affix.DEFAULTS, options)
  6032  
  6033      this.$target = $(this.options.target)
  6034        .on('scroll.bs.affix.data-api', $.proxy(this.checkPosition, this))
  6035        .on('click.bs.affix.data-api',  $.proxy(this.checkPositionWithEventLoop, this))
  6036  
  6037      this.$element     = $(element)
  6038      this.affixed      =
  6039      this.unpin        =
  6040      this.pinnedOffset = null
  6041  
  6042      this.checkPosition()
  6043    }
  6044  
  6045    Affix.VERSION  = '3.2.0'
  6046  
  6047    Affix.RESET    = 'affix affix-top affix-bottom'
  6048  
  6049    Affix.DEFAULTS = {
  6050      offset: 0,
  6051      target: window
  6052    }
  6053  
  6054    Affix.prototype.getPinnedOffset = function () {
  6055      if (this.pinnedOffset) return this.pinnedOffset
  6056      this.$element.removeClass(Affix.RESET).addClass('affix')
  6057      var scrollTop = this.$target.scrollTop()
  6058      var position  = this.$element.offset()
  6059      return (this.pinnedOffset = position.top - scrollTop)
  6060    }
  6061  
  6062    Affix.prototype.checkPositionWithEventLoop = function () {
  6063      setTimeout($.proxy(this.checkPosition, this), 1)
  6064    }
  6065  
  6066    Affix.prototype.checkPosition = function () {
  6067      if (!this.$element.is(':visible')) return
  6068  
  6069      var scrollHeight = $(document).height()
  6070      var scrollTop    = this.$target.scrollTop()
  6071      var position     = this.$element.offset()
  6072      var offset       = this.options.offset
  6073      var offsetTop    = offset.top
  6074      var offsetBottom = offset.bottom
  6075  
  6076      if (typeof offset != 'object')         offsetBottom = offsetTop = offset
  6077      if (typeof offsetTop == 'function')    offsetTop    = offset.top(this.$element)
  6078      if (typeof offsetBottom == 'function') offsetBottom = offset.bottom(this.$element)
  6079  
  6080      var affix = this.unpin   != null && (scrollTop + this.unpin <= position.top) ? false :
  6081                  offsetBottom != null && (position.top + this.$element.height() >= scrollHeight - offsetBottom) ? 'bottom' :
  6082                  offsetTop    != null && (scrollTop <= offsetTop) ? 'top' : false
  6083  
  6084      if (this.affixed === affix) return
  6085      if (this.unpin != null) this.$element.css('top', '')
  6086  
  6087      var affixType = 'affix' + (affix ? '-' + affix : '')
  6088      var e         = $.Event(affixType + '.bs.affix')
  6089  
  6090      this.$element.trigger(e)
  6091  
  6092      if (e.isDefaultPrevented()) return
  6093  
  6094      this.affixed = affix
  6095      this.unpin = affix == 'bottom' ? this.getPinnedOffset() : null
  6096  
  6097      this.$element
  6098        .removeClass(Affix.RESET)
  6099        .addClass(affixType)
  6100        .trigger($.Event(affixType.replace('affix', 'affixed')))
  6101  
  6102      if (affix == 'bottom') {
  6103        this.$element.offset({
  6104          top: scrollHeight - this.$element.height() - offsetBottom
  6105        })
  6106      }
  6107    }
  6108  
  6109  
  6110    // AFFIX PLUGIN DEFINITION
  6111    // =======================
  6112  
  6113    function Plugin(option) {
  6114      return this.each(function () {
  6115        var $this   = $(this)
  6116        var data    = $this.data('bs.affix')
  6117        var options = typeof option == 'object' && option
  6118  
  6119        if (!data) $this.data('bs.affix', (data = new Affix(this, options)))
  6120        if (typeof option == 'string') data[option]()
  6121      })
  6122    }
  6123  
  6124    var old = $.fn.affix
  6125  
  6126    $.fn.affix             = Plugin
  6127    $.fn.affix.Constructor = Affix
  6128  
  6129  
  6130    // AFFIX NO CONFLICT
  6131    // =================
  6132  
  6133    $.fn.affix.noConflict = function () {
  6134      $.fn.affix = old
  6135      return this
  6136    }
  6137  
  6138  
  6139    // AFFIX DATA-API
  6140    // ==============
  6141  
  6142    $(window).on('load', function () {
  6143      $('[data-spy="affix"]').each(function () {
  6144        var $spy = $(this)
  6145        var data = $spy.data()
  6146  
  6147        data.offset = data.offset || {}
  6148  
  6149        if (data.offsetBottom) data.offset.bottom = data.offsetBottom
  6150        if (data.offsetTop)    data.offset.top    = data.offsetTop
  6151  
  6152        Plugin.call($spy, data)
  6153      })
  6154    })
  6155  
  6156  }(jQuery);
  6157  
  6158  /* ========================================================================
  6159   * bootstrap-switch - v3.0.2
  6160   * http://www.bootstrap-switch.org
  6161   * ========================================================================
  6162   * Copyright 2012-2013 Mattia Larentis
  6163   *
  6164   * ========================================================================
  6165   * Licensed under the Apache License, Version 2.0 (the "License");
  6166   * you may not use this file except in compliance with the License.
  6167   * You may obtain a copy of the License at
  6168   *
  6169   *     http://www.apache.org/licenses/LICENSE-2.0
  6170   *
  6171   * Unless required by applicable law or agreed to in writing, software
  6172   * distributed under the License is distributed on an "AS IS" BASIS,
  6173   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  6174   * See the License for the specific language governing permissions and
  6175   * limitations under the License.
  6176   * ========================================================================
  6177   */
  6178  
  6179  (function() {
  6180    var __slice = [].slice;
  6181  
  6182    (function($, window) {
  6183      "use strict";
  6184      var BootstrapSwitch;
  6185      BootstrapSwitch = (function() {
  6186        function BootstrapSwitch(element, options) {
  6187          if (options == null) {
  6188            options = {};
  6189          }
  6190          this.$element = $(element);
  6191          this.options = $.extend({}, $.fn.bootstrapSwitch.defaults, {
  6192            state: this.$element.is(":checked"),
  6193            size: this.$element.data("size"),
  6194            animate: this.$element.data("animate"),
  6195            disabled: this.$element.is(":disabled"),
  6196            readonly: this.$element.is("[readonly]"),
  6197            indeterminate: this.$element.data("indeterminate"),
  6198            onColor: this.$element.data("on-color"),
  6199            offColor: this.$element.data("off-color"),
  6200            onText: this.$element.data("on-text"),
  6201            offText: this.$element.data("off-text"),
  6202            labelText: this.$element.data("label-text"),
  6203            baseClass: this.$element.data("base-class"),
  6204            wrapperClass: this.$element.data("wrapper-class"),
  6205            radioAllOff: this.$element.data("radio-all-off")
  6206          }, options);
  6207          this.$wrapper = $("<div>", {
  6208            "class": (function(_this) {
  6209              return function() {
  6210                var classes;
  6211                classes = ["" + _this.options.baseClass].concat(_this._getClasses(_this.options.wrapperClass));
  6212                classes.push(_this.options.state ? "" + _this.options.baseClass + "-on" : "" + _this.options.baseClass + "-off");
  6213                if (_this.options.size != null) {
  6214                  classes.push("" + _this.options.baseClass + "-" + _this.options.size);
  6215                }
  6216                if (_this.options.animate) {
  6217                  classes.push("" + _this.options.baseClass + "-animate");
  6218                }
  6219                if (_this.options.disabled) {
  6220                  classes.push("" + _this.options.baseClass + "-disabled");
  6221                }
  6222                if (_this.options.readonly) {
  6223                  classes.push("" + _this.options.baseClass + "-readonly");
  6224                }
  6225                if (_this.options.indeterminate) {
  6226                  classes.push("" + _this.options.baseClass + "-indeterminate");
  6227                }
  6228                if (_this.$element.attr("id")) {
  6229                  classes.push("" + _this.options.baseClass + "-id-" + (_this.$element.attr("id")));
  6230                }
  6231                return classes.join(" ");
  6232              };
  6233            })(this)()
  6234          });
  6235          this.$container = $("<div>", {
  6236            "class": "" + this.options.baseClass + "-container"
  6237          });
  6238          this.$on = $("<span>", {
  6239            html: this.options.onText,
  6240            "class": "" + this.options.baseClass + "-handle-on " + this.options.baseClass + "-" + this.options.onColor
  6241          });
  6242          this.$off = $("<span>", {
  6243            html: this.options.offText,
  6244            "class": "" + this.options.baseClass + "-handle-off " + this.options.baseClass + "-" + this.options.offColor
  6245          });
  6246          this.$label = $("<label>", {
  6247            html: this.options.labelText,
  6248            "class": "" + this.options.baseClass + "-label"
  6249          });
  6250          if (this.options.indeterminate) {
  6251            this.$element.prop("indeterminate", true);
  6252          }
  6253          this.$element.on("init.bootstrapSwitch", (function(_this) {
  6254            return function() {
  6255              return _this.options.onInit.apply(element, arguments);
  6256            };
  6257          })(this));
  6258          this.$element.on("switchChange.bootstrapSwitch", (function(_this) {
  6259            return function() {
  6260              return _this.options.onSwitchChange.apply(element, arguments);
  6261            };
  6262          })(this));
  6263          this.$container = this.$element.wrap(this.$container).parent();
  6264          this.$wrapper = this.$container.wrap(this.$wrapper).parent();
  6265          this.$element.before(this.$on).before(this.$label).before(this.$off).trigger("init.bootstrapSwitch");
  6266          this._elementHandlers();
  6267          this._handleHandlers();
  6268          this._labelHandlers();
  6269          this._formHandler();
  6270        }
  6271  
  6272        BootstrapSwitch.prototype._constructor = BootstrapSwitch;
  6273  
  6274        BootstrapSwitch.prototype.state = function(value, skip) {
  6275          if (typeof value === "undefined") {
  6276            return this.options.state;
  6277          }
  6278          if (this.options.disabled || this.options.readonly || this.options.indeterminate) {
  6279            return this.$element;
  6280          }
  6281          if (this.options.state && !this.options.radioAllOff && this.$element.is(':radio')) {
  6282            return this.$element;
  6283          }
  6284          value = !!value;
  6285          this.$element.prop("checked", value).trigger("change.bootstrapSwitch", skip);
  6286          return this.$element;
  6287        };
  6288  
  6289        BootstrapSwitch.prototype.toggleState = function(skip) {
  6290          if (this.options.disabled || this.options.readonly || this.options.indeterminate) {
  6291            return this.$element;
  6292          }
  6293          return this.$element.prop("checked", !this.options.state).trigger("change.bootstrapSwitch", skip);
  6294        };
  6295  
  6296        BootstrapSwitch.prototype.size = function(value) {
  6297          if (typeof value === "undefined") {
  6298            return this.options.size;
  6299          }
  6300          if (this.options.size != null) {
  6301            this.$wrapper.removeClass("" + this.options.baseClass + "-" + this.options.size);
  6302          }
  6303          if (value) {
  6304            this.$wrapper.addClass("" + this.options.baseClass + "-" + value);
  6305          }
  6306          this.options.size = value;
  6307          return this.$element;
  6308        };
  6309  
  6310        BootstrapSwitch.prototype.animate = function(value) {
  6311          if (typeof value === "undefined") {
  6312            return this.options.animate;
  6313          }
  6314          value = !!value;
  6315          this.$wrapper[value ? "addClass" : "removeClass"]("" + this.options.baseClass + "-animate");
  6316          this.options.animate = value;
  6317          return this.$element;
  6318        };
  6319  
  6320        BootstrapSwitch.prototype.disabled = function(value) {
  6321          if (typeof value === "undefined") {
  6322            return this.options.disabled;
  6323          }
  6324          value = !!value;
  6325          this.$wrapper[value ? "addClass" : "removeClass"]("" + this.options.baseClass + "-disabled");
  6326          this.$element.prop("disabled", value);
  6327          this.options.disabled = value;
  6328          return this.$element;
  6329        };
  6330  
  6331        BootstrapSwitch.prototype.toggleDisabled = function() {
  6332          this.$element.prop("disabled", !this.options.disabled);
  6333          this.$wrapper.toggleClass("" + this.options.baseClass + "-disabled");
  6334          this.options.disabled = !this.options.disabled;
  6335          return this.$element;
  6336        };
  6337  
  6338        BootstrapSwitch.prototype.readonly = function(value) {
  6339          if (typeof value === "undefined") {
  6340            return this.options.readonly;
  6341          }
  6342          value = !!value;
  6343          this.$wrapper[value ? "addClass" : "removeClass"]("" + this.options.baseClass + "-readonly");
  6344          this.$element.prop("readonly", value);
  6345          this.options.readonly = value;
  6346          return this.$element;
  6347        };
  6348  
  6349        BootstrapSwitch.prototype.toggleReadonly = function() {
  6350          this.$element.prop("readonly", !this.options.readonly);
  6351          this.$wrapper.toggleClass("" + this.options.baseClass + "-readonly");
  6352          this.options.readonly = !this.options.readonly;
  6353          return this.$element;
  6354        };
  6355  
  6356        BootstrapSwitch.prototype.indeterminate = function(value) {
  6357          if (typeof value === "undefined") {
  6358            return this.options.indeterminate;
  6359          }
  6360          value = !!value;
  6361          this.$wrapper[value ? "addClass" : "removeClass"]("" + this.options.baseClass + "-indeterminate");
  6362          this.$element.prop("indeterminate", value);
  6363          this.options.indeterminate = value;
  6364          return this.$element;
  6365        };
  6366  
  6367        BootstrapSwitch.prototype.toggleIndeterminate = function() {
  6368          this.$element.prop("indeterminate", !this.options.indeterminate);
  6369          this.$wrapper.toggleClass("" + this.options.baseClass + "-indeterminate");
  6370          this.options.indeterminate = !this.options.indeterminate;
  6371          return this.$element;
  6372        };
  6373  
  6374        BootstrapSwitch.prototype.onColor = function(value) {
  6375          var color;
  6376          color = this.options.onColor;
  6377          if (typeof value === "undefined") {
  6378            return color;
  6379          }
  6380          if (color != null) {
  6381            this.$on.removeClass("" + this.options.baseClass + "-" + color);
  6382          }
  6383          this.$on.addClass("" + this.options.baseClass + "-" + value);
  6384          this.options.onColor = value;
  6385          return this.$element;
  6386        };
  6387  
  6388        BootstrapSwitch.prototype.offColor = function(value) {
  6389          var color;
  6390          color = this.options.offColor;
  6391          if (typeof value === "undefined") {
  6392            return color;
  6393          }
  6394          if (color != null) {
  6395            this.$off.removeClass("" + this.options.baseClass + "-" + color);
  6396          }
  6397          this.$off.addClass("" + this.options.baseClass + "-" + value);
  6398          this.options.offColor = value;
  6399          return this.$element;
  6400        };
  6401  
  6402        BootstrapSwitch.prototype.onText = function(value) {
  6403          if (typeof value === "undefined") {
  6404            return this.options.onText;
  6405          }
  6406          this.$on.html(value);
  6407          this.options.onText = value;
  6408          return this.$element;
  6409        };
  6410  
  6411        BootstrapSwitch.prototype.offText = function(value) {
  6412          if (typeof value === "undefined") {
  6413            return this.options.offText;
  6414          }
  6415          this.$off.html(value);
  6416          this.options.offText = value;
  6417          return this.$element;
  6418        };
  6419  
  6420        BootstrapSwitch.prototype.labelText = function(value) {
  6421          if (typeof value === "undefined") {
  6422            return this.options.labelText;
  6423          }
  6424          this.$label.html(value);
  6425          this.options.labelText = value;
  6426          return this.$element;
  6427        };
  6428  
  6429        BootstrapSwitch.prototype.baseClass = function(value) {
  6430          return this.options.baseClass;
  6431        };
  6432  
  6433        BootstrapSwitch.prototype.wrapperClass = function(value) {
  6434          if (typeof value === "undefined") {
  6435            return this.options.wrapperClass;
  6436          }
  6437          if (!value) {
  6438            value = $.fn.bootstrapSwitch.defaults.wrapperClass;
  6439          }
  6440          this.$wrapper.removeClass(this._getClasses(this.options.wrapperClass).join(" "));
  6441          this.$wrapper.addClass(this._getClasses(value).join(" "));
  6442          this.options.wrapperClass = value;
  6443          return this.$element;
  6444        };
  6445  
  6446        BootstrapSwitch.prototype.radioAllOff = function(value) {
  6447          if (typeof value === "undefined") {
  6448            return this.options.radioAllOff;
  6449          }
  6450          this.options.radioAllOff = value;
  6451          return this.$element;
  6452        };
  6453  
  6454        BootstrapSwitch.prototype.onInit = function(value) {
  6455          if (typeof value === "undefined") {
  6456            return this.options.onInit;
  6457          }
  6458          if (!value) {
  6459            value = $.fn.bootstrapSwitch.defaults.onInit;
  6460          }
  6461          this.options.onInit = value;
  6462          return this.$element;
  6463        };
  6464  
  6465        BootstrapSwitch.prototype.onSwitchChange = function(value) {
  6466          if (typeof value === "undefined") {
  6467            return this.options.onSwitchChange;
  6468          }
  6469          if (!value) {
  6470            value = $.fn.bootstrapSwitch.defaults.onSwitchChange;
  6471          }
  6472          this.options.onSwitchChange = value;
  6473          return this.$element;
  6474        };
  6475  
  6476        BootstrapSwitch.prototype.destroy = function() {
  6477          var $form;
  6478          $form = this.$element.closest("form");
  6479          if ($form.length) {
  6480            $form.off("reset.bootstrapSwitch").removeData("bootstrap-switch");
  6481          }
  6482          this.$container.children().not(this.$element).remove();
  6483          this.$element.unwrap().unwrap().off(".bootstrapSwitch").removeData("bootstrap-switch");
  6484          return this.$element;
  6485        };
  6486  
  6487        BootstrapSwitch.prototype._elementHandlers = function() {
  6488          return this.$element.on({
  6489            "change.bootstrapSwitch": (function(_this) {
  6490              return function(e, skip) {
  6491                var checked;
  6492                e.preventDefault();
  6493                e.stopImmediatePropagation();
  6494                checked = _this.$element.is(":checked");
  6495                if (checked === _this.options.state) {
  6496                  return;
  6497                }
  6498                _this.options.state = checked;
  6499                _this.$wrapper.removeClass(checked ? "" + _this.options.baseClass + "-off" : "" + _this.options.baseClass + "-on").addClass(checked ? "" + _this.options.baseClass + "-on" : "" + _this.options.baseClass + "-off");
  6500                if (!skip) {
  6501                  if (_this.$element.is(":radio")) {
  6502                    $("[name='" + (_this.$element.attr('name')) + "']").not(_this.$element).prop("checked", false).trigger("change.bootstrapSwitch", true);
  6503                  }
  6504                  return _this.$element.trigger("switchChange.bootstrapSwitch", [checked]);
  6505                }
  6506              };
  6507            })(this),
  6508            "focus.bootstrapSwitch": (function(_this) {
  6509              return function(e) {
  6510                e.preventDefault();
  6511                return _this.$wrapper.addClass("" + _this.options.baseClass + "-focused");
  6512              };
  6513            })(this),
  6514            "blur.bootstrapSwitch": (function(_this) {
  6515              return function(e) {
  6516                e.preventDefault();
  6517                return _this.$wrapper.removeClass("" + _this.options.baseClass + "-focused");
  6518              };
  6519            })(this),
  6520            "keydown.bootstrapSwitch": (function(_this) {
  6521              return function(e) {
  6522                if (!e.which || _this.options.disabled || _this.options.readonly || _this.options.indeterminate) {
  6523                  return;
  6524                }
  6525                switch (e.which) {
  6526                  case 37:
  6527                    e.preventDefault();
  6528                    e.stopImmediatePropagation();
  6529                    return _this.state(false);
  6530                  case 39:
  6531                    e.preventDefault();
  6532                    e.stopImmediatePropagation();
  6533                    return _this.state(true);
  6534                }
  6535              };
  6536            })(this)
  6537          });
  6538        };
  6539  
  6540        BootstrapSwitch.prototype._handleHandlers = function() {
  6541          this.$on.on("click.bootstrapSwitch", (function(_this) {
  6542            return function(e) {
  6543              _this.state(false);
  6544              return _this.$element.trigger("focus.bootstrapSwitch");
  6545            };
  6546          })(this));
  6547          return this.$off.on("click.bootstrapSwitch", (function(_this) {
  6548            return function(e) {
  6549              _this.state(true);
  6550              return _this.$element.trigger("focus.bootstrapSwitch");
  6551            };
  6552          })(this));
  6553        };
  6554  
  6555        BootstrapSwitch.prototype._labelHandlers = function() {
  6556          return this.$label.on({
  6557            "mousemove.bootstrapSwitch touchmove.bootstrapSwitch": (function(_this) {
  6558              return function(e) {
  6559                var left, pageX, percent, right;
  6560                if (!_this.isLabelDragging) {
  6561                  return;
  6562                }
  6563                e.preventDefault();
  6564                _this.isLabelDragged = true;
  6565                pageX = e.pageX || e.originalEvent.touches[0].pageX;
  6566                percent = ((pageX - _this.$wrapper.offset().left) / _this.$wrapper.width()) * 100;
  6567                left = 25;
  6568                right = 75;
  6569                if (_this.options.animate) {
  6570                  _this.$wrapper.removeClass("" + _this.options.baseClass + "-animate");
  6571                }
  6572                if (percent < left) {
  6573                  percent = left;
  6574                } else if (percent > right) {
  6575                  percent = right;
  6576                }
  6577                _this.$container.css("margin-left", "" + (percent - right) + "%");
  6578                return _this.$element.trigger("focus.bootstrapSwitch");
  6579              };
  6580            })(this),
  6581            "mousedown.bootstrapSwitch touchstart.bootstrapSwitch": (function(_this) {
  6582              return function(e) {
  6583                if (_this.isLabelDragging || _this.options.disabled || _this.options.readonly || _this.options.indeterminate) {
  6584                  return;
  6585                }
  6586                e.preventDefault();
  6587                _this.isLabelDragging = true;
  6588                return _this.$element.trigger("focus.bootstrapSwitch");
  6589              };
  6590            })(this),
  6591            "mouseup.bootstrapSwitch touchend.bootstrapSwitch": (function(_this) {
  6592              return function(e) {
  6593                if (!_this.isLabelDragging) {
  6594                  return;
  6595                }
  6596                e.preventDefault();
  6597                if (_this.isLabelDragged) {
  6598                  _this.isLabelDragged = false;
  6599                  _this.state(parseInt(_this.$container.css("margin-left"), 10) > -(_this.$container.width() / 6));
  6600                  if (_this.options.animate) {
  6601                    _this.$wrapper.addClass("" + _this.options.baseClass + "-animate");
  6602                  }
  6603                  _this.$container.css("margin-left", "");
  6604                } else {
  6605                  _this.state(!_this.options.state);
  6606                }
  6607                return _this.isLabelDragging = false;
  6608              };
  6609            })(this),
  6610            "mouseleave.bootstrapSwitch": (function(_this) {
  6611              return function(e) {
  6612                return _this.$label.trigger("mouseup.bootstrapSwitch");
  6613              };
  6614            })(this)
  6615          });
  6616        };
  6617  
  6618        BootstrapSwitch.prototype._formHandler = function() {
  6619          var $form;
  6620          $form = this.$element.closest("form");
  6621          if ($form.data("bootstrap-switch")) {
  6622            return;
  6623          }
  6624          return $form.on("reset.bootstrapSwitch", function() {
  6625            return window.setTimeout(function() {
  6626              return $form.find("input").filter(function() {
  6627                return $(this).data("bootstrap-switch");
  6628              }).each(function() {
  6629                return $(this).bootstrapSwitch("state", this.checked);
  6630              });
  6631            }, 1);
  6632          }).data("bootstrap-switch", true);
  6633        };
  6634  
  6635        BootstrapSwitch.prototype._getClasses = function(classes) {
  6636          var c, cls, _i, _len;
  6637          if (!$.isArray(classes)) {
  6638            return ["" + this.options.baseClass + "-" + classes];
  6639          }
  6640          cls = [];
  6641          for (_i = 0, _len = classes.length; _i < _len; _i++) {
  6642            c = classes[_i];
  6643            cls.push("" + this.options.baseClass + "-" + c);
  6644          }
  6645          return cls;
  6646        };
  6647  
  6648        return BootstrapSwitch;
  6649  
  6650      })();
  6651      $.fn.bootstrapSwitch = function() {
  6652        var args, option, ret;
  6653        option = arguments[0], args = 2 <= arguments.length ? __slice.call(arguments, 1) : [];
  6654        ret = this;
  6655        this.each(function() {
  6656          var $this, data;
  6657          $this = $(this);
  6658          data = $this.data("bootstrap-switch");
  6659          if (!data) {
  6660            $this.data("bootstrap-switch", data = new BootstrapSwitch(this, option));
  6661          }
  6662          if (typeof option === "string") {
  6663            return ret = data[option].apply(data, args);
  6664          }
  6665        });
  6666        return ret;
  6667      };
  6668      $.fn.bootstrapSwitch.Constructor = BootstrapSwitch;
  6669      return $.fn.bootstrapSwitch.defaults = {
  6670        state: true,
  6671        size: null,
  6672        animate: true,
  6673        disabled: false,
  6674        readonly: false,
  6675        indeterminate: false,
  6676        onColor: "primary",
  6677        offColor: "default",
  6678        onText: "ON",
  6679        offText: "OFF",
  6680        labelText: "&nbsp;",
  6681        baseClass: "bootstrap-switch",
  6682        wrapperClass: "wrapper",
  6683        radioAllOff: false,
  6684        onInit: function() {},
  6685        onSwitchChange: function() {}
  6686      };
  6687    })(window.jQuery, window);
  6688  
  6689  }).call(this);
  6690  
  6691  (function ($) {
  6692    "use strict";
  6693  
  6694    var defaultOptions = {
  6695      tagClass: function(item) {
  6696        return 'label label-info';
  6697      },
  6698      itemValue: function(item) {
  6699        return item ? item.toString() : item;
  6700      },
  6701      itemText: function(item) {
  6702        return this.itemValue(item);
  6703      },
  6704      freeInput: true,
  6705      addOnBlur: true,
  6706      maxTags: undefined,
  6707      maxChars: undefined,
  6708      confirmKeys: [13, 44],
  6709      onTagExists: function(item, $tag) {
  6710        $tag.hide().fadeIn();
  6711      },
  6712      trimValue: false,
  6713      allowDuplicates: false
  6714    };
  6715  
  6716    /**
  6717     * Constructor function
  6718     */
  6719    function TagsInput(element, options) {
  6720      this.itemsArray = [];
  6721  
  6722      this.$element = $(element);
  6723      this.$element.hide();
  6724  
  6725      this.isSelect = (element.tagName === 'SELECT');
  6726      this.multiple = (this.isSelect && element.hasAttribute('multiple'));
  6727      this.objectItems = options && options.itemValue;
  6728      this.placeholderText = element.hasAttribute('placeholder') ? this.$element.attr('placeholder') : '';
  6729      this.inputSize = Math.max(1, this.placeholderText.length);
  6730  
  6731      this.$container = $('<div class="bootstrap-tagsinput"></div>');
  6732      this.$input = $('<input type="text" placeholder="' + this.placeholderText + '"/>').appendTo(this.$container);
  6733  
  6734      this.$element.after(this.$container);
  6735  
  6736      var inputWidth = (this.inputSize < 3 ? 3 : this.inputSize) + "em";
  6737      this.$input.get(0).style.cssText = "width: " + inputWidth + " !important;";
  6738      this.build(options);
  6739    }
  6740  
  6741    TagsInput.prototype = {
  6742      constructor: TagsInput,
  6743  
  6744      /**
  6745       * Adds the given item as a new tag. Pass true to dontPushVal to prevent
  6746       * updating the elements val()
  6747       */
  6748      add: function(item, dontPushVal) {
  6749        var self = this;
  6750  
  6751        if (self.options.maxTags && self.itemsArray.length >= self.options.maxTags)
  6752          return;
  6753  
  6754        // Ignore falsey values, except false
  6755        if (item !== false && !item)
  6756          return;
  6757  
  6758        // Trim value
  6759        if (typeof item === "string" && self.options.trimValue) {
  6760          item = $.trim(item);
  6761        }
  6762  
  6763        // Throw an error when trying to add an object while the itemValue option was not set
  6764        if (typeof item === "object" && !self.objectItems)
  6765          throw("Can't add objects when itemValue option is not set");
  6766  
  6767        // Ignore strings only containg whitespace
  6768        if (item.toString().match(/^\s*$/))
  6769          return;
  6770  
  6771        // If SELECT but not multiple, remove current tag
  6772        if (self.isSelect && !self.multiple && self.itemsArray.length > 0)
  6773          self.remove(self.itemsArray[0]);
  6774  
  6775        if (typeof item === "string" && this.$element[0].tagName === 'INPUT') {
  6776          var items = item.split(',');
  6777          if (items.length > 1) {
  6778            for (var i = 0; i < items.length; i++) {
  6779              this.add(items[i], true);
  6780            }
  6781  
  6782            if (!dontPushVal)
  6783              self.pushVal();
  6784            return;
  6785          }
  6786        }
  6787  
  6788        var itemValue = self.options.itemValue(item),
  6789            itemText = self.options.itemText(item),
  6790            tagClass = self.options.tagClass(item);
  6791  
  6792        // Ignore items allready added
  6793        var existing = $.grep(self.itemsArray, function(item) { return self.options.itemValue(item) === itemValue; } )[0];
  6794        if (existing && !self.options.allowDuplicates) {
  6795          // Invoke onTagExists
  6796          if (self.options.onTagExists) {
  6797            var $existingTag = $(".tag", self.$container).filter(function() { return $(this).data("item") === existing; });
  6798            self.options.onTagExists(item, $existingTag);
  6799          }
  6800          return;
  6801        }
  6802  
  6803        // if length greater than limit
  6804        if (self.items().toString().length + item.length + 1 > self.options.maxInputLength)
  6805          return;
  6806  
  6807        // raise beforeItemAdd arg
  6808        var beforeItemAddEvent = $.Event('beforeItemAdd', { item: item, cancel: false });
  6809        self.$element.trigger(beforeItemAddEvent);
  6810        if (beforeItemAddEvent.cancel)
  6811          return;
  6812  
  6813        // register item in internal array and map
  6814        self.itemsArray.push(item);
  6815  
  6816        // add a tag element
  6817        var $tag = $('<span class="tag ' + htmlEncode(tagClass) + '">' + htmlEncode(itemText) + '<span data-role="remove"></span></span>');
  6818        $tag.data('item', item);
  6819        self.findInputWrapper().before($tag);
  6820        $tag.after(' ');
  6821  
  6822        // add <option /> if item represents a value not present in one of the <select />'s options
  6823        if (self.isSelect && !$('option[value="' + encodeURIComponent(itemValue) + '"]',self.$element)[0]) {
  6824          var $option = $('<option selected>' + htmlEncode(itemText) + '</option>');
  6825          $option.data('item', item);
  6826          $option.attr('value', itemValue);
  6827          self.$element.append($option);
  6828        }
  6829  
  6830        if (!dontPushVal)
  6831          self.pushVal();
  6832  
  6833        // Add class when reached maxTags
  6834        if (self.options.maxTags === self.itemsArray.length || self.items().toString().length === self.options.maxInputLength)
  6835          self.$container.addClass('bootstrap-tagsinput-max');
  6836  
  6837        self.$element.trigger($.Event('itemAdded', { item: item }));
  6838      },
  6839  
  6840      /**
  6841       * Removes the given item. Pass true to dontPushVal to prevent updating the
  6842       * elements val()
  6843       */
  6844      remove: function(item, dontPushVal) {
  6845        var self = this;
  6846  
  6847        if (self.objectItems) {
  6848          if (typeof item === "object")
  6849            item = $.grep(self.itemsArray, function(other) { return self.options.itemValue(other) ==  self.options.itemValue(item); } );
  6850          else
  6851            item = $.grep(self.itemsArray, function(other) { return self.options.itemValue(other) ==  item; } );
  6852  
  6853          item = item[item.length-1];
  6854        }
  6855  
  6856        if (item) {
  6857          var beforeItemRemoveEvent = $.Event('beforeItemRemove', { item: item, cancel: false });
  6858          self.$element.trigger(beforeItemRemoveEvent);
  6859          if (beforeItemRemoveEvent.cancel)
  6860            return;
  6861  
  6862          $('.tag', self.$container).filter(function() { return $(this).data('item') === item; }).remove();
  6863          $('option', self.$element).filter(function() { return $(this).data('item') === item; }).remove();
  6864          if($.inArray(item, self.itemsArray) !== -1)
  6865            self.itemsArray.splice($.inArray(item, self.itemsArray), 1);
  6866        }
  6867  
  6868        if (!dontPushVal)
  6869          self.pushVal();
  6870  
  6871        // Remove class when reached maxTags
  6872        if (self.options.maxTags > self.itemsArray.length)
  6873          self.$container.removeClass('bootstrap-tagsinput-max');
  6874  
  6875        self.$element.trigger($.Event('itemRemoved',  { item: item }));
  6876      },
  6877  
  6878      /**
  6879       * Removes all items
  6880       */
  6881      removeAll: function() {
  6882        var self = this;
  6883  
  6884        $('.tag', self.$container).remove();
  6885        $('option', self.$element).remove();
  6886  
  6887        while(self.itemsArray.length > 0)
  6888          self.itemsArray.pop();
  6889  
  6890        self.pushVal();
  6891      },
  6892  
  6893      /**
  6894       * Refreshes the tags so they match the text/value of their corresponding
  6895       * item.
  6896       */
  6897      refresh: function() {
  6898        var self = this;
  6899        $('.tag', self.$container).each(function() {
  6900          var $tag = $(this),
  6901              item = $tag.data('item'),
  6902              itemValue = self.options.itemValue(item),
  6903              itemText = self.options.itemText(item),
  6904              tagClass = self.options.tagClass(item);
  6905  
  6906            // Update tag's class and inner text
  6907            $tag.attr('class', null);
  6908            $tag.addClass('tag ' + htmlEncode(tagClass));
  6909            $tag.contents().filter(function() {
  6910              return this.nodeType == 3;
  6911            })[0].nodeValue = htmlEncode(itemText);
  6912  
  6913            if (self.isSelect) {
  6914              var option = $('option', self.$element).filter(function() { return $(this).data('item') === item; });
  6915              option.attr('value', itemValue);
  6916            }
  6917        });
  6918      },
  6919  
  6920      /**
  6921       * Returns the items added as tags
  6922       */
  6923      items: function() {
  6924        return this.itemsArray;
  6925      },
  6926  
  6927      /**
  6928       * Assembly value by retrieving the value of each item, and set it on the
  6929       * element.
  6930       */
  6931      pushVal: function() {
  6932        var self = this,
  6933            val = $.map(self.items(), function(item) {
  6934              return self.options.itemValue(item).toString();
  6935            });
  6936  
  6937        self.$element.val(val, true).trigger('change');
  6938      },
  6939  
  6940      /**
  6941       * Initializes the tags input behaviour on the element
  6942       */
  6943      build: function(options) {
  6944        var self = this;
  6945  
  6946        self.options = $.extend({}, defaultOptions, options);
  6947        // When itemValue is set, freeInput should always be false
  6948        if (self.objectItems)
  6949          self.options.freeInput = false;
  6950  
  6951        makeOptionItemFunction(self.options, 'itemValue');
  6952        makeOptionItemFunction(self.options, 'itemText');
  6953        makeOptionFunction(self.options, 'tagClass');
  6954        
  6955        // Typeahead Bootstrap version 2.3.2
  6956        if (self.options.typeahead) {
  6957          var typeahead = self.options.typeahead || {};
  6958  
  6959          makeOptionFunction(typeahead, 'source');
  6960  
  6961          self.$input.typeahead($.extend({}, typeahead, {
  6962            source: function (query, process) {
  6963              function processItems(items) {
  6964                var texts = [];
  6965  
  6966                for (var i = 0; i < items.length; i++) {
  6967                  var text = self.options.itemText(items[i]);
  6968                  map[text] = items[i];
  6969                  texts.push(text);
  6970                }
  6971                process(texts);
  6972              }
  6973  
  6974              this.map = {};
  6975              var map = this.map,
  6976                  data = typeahead.source(query);
  6977  
  6978              if ($.isFunction(data.success)) {
  6979                // support for Angular callbacks
  6980                data.success(processItems);
  6981              } else if ($.isFunction(data.then)) {
  6982                // support for Angular promises
  6983                data.then(processItems);
  6984              } else {
  6985                // support for functions and jquery promises
  6986                $.when(data)
  6987                 .then(processItems);
  6988              }
  6989            },
  6990            updater: function (text) {
  6991              self.add(this.map[text]);
  6992            },
  6993            matcher: function (text) {
  6994              return (text.toLowerCase().indexOf(this.query.trim().toLowerCase()) !== -1);
  6995            },
  6996            sorter: function (texts) {
  6997              return texts.sort();
  6998            },
  6999            highlighter: function (text) {
  7000              var regex = new RegExp( '(' + this.query + ')', 'gi' );
  7001              return text.replace( regex, "<strong>$1</strong>" );
  7002            }
  7003          }));
  7004        }
  7005  
  7006        // typeahead.js
  7007        if (self.options.typeaheadjs) {
  7008            var typeaheadjs = self.options.typeaheadjs || {};
  7009            
  7010            self.$input.typeahead(null, typeaheadjs).on('typeahead:selected', $.proxy(function (obj, datum) {
  7011              if (typeaheadjs.valueKey)
  7012                self.add(datum[typeaheadjs.valueKey]);
  7013              else
  7014                self.add(datum);
  7015              self.$input.typeahead('val', '');
  7016            }, self));
  7017        }
  7018  
  7019        self.$container.on('click', $.proxy(function(event) {
  7020          if (! self.$element.attr('disabled')) {
  7021            self.$input.removeAttr('disabled');
  7022          }
  7023          self.$input.focus();
  7024        }, self));
  7025  
  7026          if (self.options.addOnBlur && self.options.freeInput) {
  7027            self.$input.on('focusout', $.proxy(function(event) {
  7028                // HACK: only process on focusout when no typeahead opened, to
  7029                //       avoid adding the typeahead text as tag
  7030                if ($('.typeahead, .twitter-typeahead', self.$container).length === 0) {
  7031                  self.add(self.$input.val());
  7032                  self.$input.val('');
  7033                }
  7034            }, self));
  7035          }
  7036          
  7037  
  7038        self.$container.on('keydown', 'input', $.proxy(function(event) {
  7039          var $input = $(event.target),
  7040              $inputWrapper = self.findInputWrapper();
  7041  
  7042          if (self.$element.attr('disabled')) {
  7043            self.$input.attr('disabled', 'disabled');
  7044            return;
  7045          }
  7046  
  7047          switch (event.which) {
  7048            // BACKSPACE
  7049            case 8:
  7050              if (doGetCaretPosition($input[0]) === 0) {
  7051                var prev = $inputWrapper.prev();
  7052                if (prev) {
  7053                  self.remove(prev.data('item'));
  7054                }
  7055              }
  7056              break;
  7057  
  7058            // DELETE
  7059            case 46:
  7060              if (doGetCaretPosition($input[0]) === 0) {
  7061                var next = $inputWrapper.next();
  7062                if (next) {
  7063                  self.remove(next.data('item'));
  7064                }
  7065              }
  7066              break;
  7067  
  7068            // LEFT ARROW
  7069            case 37:
  7070              // Try to move the input before the previous tag
  7071              var $prevTag = $inputWrapper.prev();
  7072              if ($input.val().length === 0 && $prevTag[0]) {
  7073                $prevTag.before($inputWrapper);
  7074                $input.focus();
  7075              }
  7076              break;
  7077            // RIGHT ARROW
  7078            case 39:
  7079              // Try to move the input after the next tag
  7080              var $nextTag = $inputWrapper.next();
  7081              if ($input.val().length === 0 && $nextTag[0]) {
  7082                $nextTag.after($inputWrapper);
  7083                $input.focus();
  7084              }
  7085              break;
  7086           default:
  7087               // ignore
  7088           }
  7089  
  7090          // Reset internal input's size
  7091          var textLength = $input.val().length,
  7092              wordSpace = Math.ceil(textLength / 5),
  7093              size = textLength + wordSpace + 1;
  7094          $input.attr('size', Math.max(this.inputSize, $input.val().length));
  7095        }, self));
  7096  
  7097        self.$container.on('keypress', 'input', $.proxy(function(event) {
  7098           var $input = $(event.target);
  7099  
  7100           if (self.$element.attr('disabled')) {
  7101              self.$input.attr('disabled', 'disabled');
  7102              return;
  7103           }
  7104  
  7105           var text = $input.val(),
  7106           maxLengthReached = self.options.maxChars && text.length >= self.options.maxChars;
  7107           if (self.options.freeInput && (keyCombinationInList(event, self.options.confirmKeys) || maxLengthReached)) {
  7108              self.add(maxLengthReached ? text.substr(0, self.options.maxChars) : text);
  7109              $input.val('');
  7110              event.preventDefault();
  7111           }
  7112  
  7113           // Reset internal input's size
  7114           var textLength = $input.val().length,
  7115              wordSpace = Math.ceil(textLength / 5),
  7116              size = textLength + wordSpace + 1;
  7117           $input.attr('size', Math.max(this.inputSize, $input.val().length));
  7118        }, self));
  7119  
  7120        // Remove icon clicked
  7121        self.$container.on('click', '[data-role=remove]', $.proxy(function(event) {
  7122          if (self.$element.attr('disabled')) {
  7123            return;
  7124          }
  7125          self.remove($(event.target).closest('.tag').data('item'));
  7126        }, self));
  7127  
  7128        // Only add existing value as tags when using strings as tags
  7129        if (self.options.itemValue === defaultOptions.itemValue) {
  7130          if (self.$element[0].tagName === 'INPUT') {
  7131              self.add(self.$element.val());
  7132          } else {
  7133            $('option', self.$element).each(function() {
  7134              self.add($(this).attr('value'), true);
  7135            });
  7136          }
  7137        }
  7138      },
  7139  
  7140      /**
  7141       * Removes all tagsinput behaviour and unregsiter all event handlers
  7142       */
  7143      destroy: function() {
  7144        var self = this;
  7145  
  7146        // Unbind events
  7147        self.$container.off('keypress', 'input');
  7148        self.$container.off('click', '[role=remove]');
  7149  
  7150        self.$container.remove();
  7151        self.$element.removeData('tagsinput');
  7152        self.$element.show();
  7153      },
  7154  
  7155      /**
  7156       * Sets focus on the tagsinput
  7157       */
  7158      focus: function() {
  7159        this.$input.focus();
  7160      },
  7161  
  7162      /**
  7163       * Returns the internal input element
  7164       */
  7165      input: function() {
  7166        return this.$input;
  7167      },
  7168  
  7169      /**
  7170       * Returns the element which is wrapped around the internal input. This
  7171       * is normally the $container, but typeahead.js moves the $input element.
  7172       */
  7173      findInputWrapper: function() {
  7174        var elt = this.$input[0],
  7175            container = this.$container[0];
  7176        while(elt && elt.parentNode !== container)
  7177          elt = elt.parentNode;
  7178  
  7179        return $(elt);
  7180      }
  7181    };
  7182  
  7183    /**
  7184     * Register JQuery plugin
  7185     */
  7186    $.fn.tagsinput = function(arg1, arg2) {
  7187      var results = [];
  7188  
  7189      this.each(function() {
  7190        var tagsinput = $(this).data('tagsinput');
  7191        // Initialize a new tags input
  7192        if (!tagsinput) {
  7193            tagsinput = new TagsInput(this, arg1);
  7194            $(this).data('tagsinput', tagsinput);
  7195            results.push(tagsinput);
  7196  
  7197            if (this.tagName === 'SELECT') {
  7198                $('option', $(this)).attr('selected', 'selected');
  7199            }
  7200  
  7201            // Init tags from $(this).val()
  7202            $(this).val($(this).val());
  7203        } else if (!arg1 && !arg2) {
  7204            // tagsinput already exists
  7205            // no function, trying to init
  7206            results.push(tagsinput);
  7207        } else if(tagsinput[arg1] !== undefined) {
  7208            // Invoke function on existing tags input
  7209            var retVal = tagsinput[arg1](arg2);
  7210            if (retVal !== undefined)
  7211                results.push(retVal);
  7212        }
  7213      });
  7214  
  7215      if ( typeof arg1 == 'string') {
  7216        // Return the results from the invoked function calls
  7217        return results.length > 1 ? results : results[0];
  7218      } else {
  7219        return results;
  7220      }
  7221    };
  7222  
  7223    $.fn.tagsinput.Constructor = TagsInput;
  7224  
  7225    /**
  7226     * Most options support both a string or number as well as a function as
  7227     * option value. This function makes sure that the option with the given
  7228     * key in the given options is wrapped in a function
  7229     */
  7230    function makeOptionItemFunction(options, key) {
  7231      if (typeof options[key] !== 'function') {
  7232        var propertyName = options[key];
  7233        options[key] = function(item) { return item[propertyName]; };
  7234      }
  7235    }
  7236    function makeOptionFunction(options, key) {
  7237      if (typeof options[key] !== 'function') {
  7238        var value = options[key];
  7239        options[key] = function() { return value; };
  7240      }
  7241    }
  7242    /**
  7243     * HtmlEncodes the given value
  7244     */
  7245    var htmlEncodeContainer = $('<div />');
  7246    function htmlEncode(value) {
  7247      if (value) {
  7248        return htmlEncodeContainer.text(value).html();
  7249      } else {
  7250        return '';
  7251      }
  7252    }
  7253  
  7254    /**
  7255     * Returns the position of the caret in the given input field
  7256     * http://flightschool.acylt.com/devnotes/caret-position-woes/
  7257     */
  7258    function doGetCaretPosition(oField) {
  7259      var iCaretPos = 0;
  7260      if (document.selection) {
  7261        oField.focus ();
  7262        var oSel = document.selection.createRange();
  7263        oSel.moveStart ('character', -oField.value.length);
  7264        iCaretPos = oSel.text.length;
  7265      } else if (oField.selectionStart || oField.selectionStart == '0') {
  7266        iCaretPos = oField.selectionStart;
  7267      }
  7268      return (iCaretPos);
  7269    }
  7270  
  7271    /**
  7272      * Returns boolean indicates whether user has pressed an expected key combination. 
  7273      * @param object keyPressEvent: JavaScript event object, refer
  7274      *     http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
  7275      * @param object lookupList: expected key combinations, as in:
  7276      *     [13, {which: 188, shiftKey: true}]
  7277      */
  7278    function keyCombinationInList(keyPressEvent, lookupList) {
  7279        var found = false;
  7280        $.each(lookupList, function (index, keyCombination) {
  7281            if (typeof (keyCombination) === 'number' && keyPressEvent.which === keyCombination) {
  7282                found = true;
  7283                return false;
  7284            }
  7285  
  7286            if (keyPressEvent.which === keyCombination.which) {
  7287                var alt = !keyCombination.hasOwnProperty('altKey') || keyPressEvent.altKey === keyCombination.altKey,
  7288                    shift = !keyCombination.hasOwnProperty('shiftKey') || keyPressEvent.shiftKey === keyCombination.shiftKey,
  7289                    ctrl = !keyCombination.hasOwnProperty('ctrlKey') || keyPressEvent.ctrlKey === keyCombination.ctrlKey;
  7290                if (alt && shift && ctrl) {
  7291                    found = true;
  7292                    return false;
  7293                }
  7294            }
  7295        });
  7296  
  7297        return found;
  7298    }
  7299  
  7300    /**
  7301     * Initialize tagsinput behaviour on inputs and selects which have
  7302     * data-role=tagsinput
  7303     */
  7304    $(function() {
  7305      $("input[data-role=tagsinput], select[multiple][data-role=tagsinput]").tagsinput();
  7306    });
  7307  })(window.jQuery);
  7308  
  7309  /*!
  7310  
  7311  Holder - client side image placeholders
  7312  Version 2.4.0+bxlim
  7313  © 2014 Ivan Malopinsky - http://imsky.co
  7314  
  7315  Site:     http://imsky.github.io/holder
  7316  Issues:   https://github.com/imsky/holder/issues
  7317  License:  http://opensource.org/licenses/MIT
  7318  
  7319  */
  7320  !function(e,t,r){t[e]=r}("onDomReady",this,function(e){"use strict";function t(e){if(!b){if(!a.body)return i(t);for(b=!0;e=S.shift();)i(e)}}function r(e){(y||e.type===s||a[c]===u)&&(n(),t())}function n(){y?(a[x](m,r,d),e[x](s,r,d)):(a[g](v,r),e[g](h,r))}function i(e,t){setTimeout(e,+t>=0?t:1)}function o(e){b?i(e):S.push(e)}null==document.readyState&&document.addEventListener&&(document.addEventListener("DOMContentLoaded",function E(){document.removeEventListener("DOMContentLoaded",E,!1),document.readyState="complete"},!1),document.readyState="loading");var a=e.document,l=a.documentElement,s="load",d=!1,h="on"+s,u="complete",c="readyState",f="attachEvent",g="detachEvent",p="addEventListener",m="DOMContentLoaded",v="onreadystatechange",x="removeEventListener",y=p in a,w=d,b=d,S=[];if(a[c]===u)i(t);else if(y)a[p](m,r,d),e[p](s,r,d);else{a[f](v,r),e[f](h,r);try{w=null==e.frameElement&&l}catch(C){}w&&w.doScroll&&!function k(){if(!b){try{w.doScroll("left")}catch(e){return i(k,50)}n(),t()}}()}return o.version="1.4.0",o.isReady=function(){return b},o}(this)),document.querySelectorAll||(document.querySelectorAll=function(e){var t,r=document.createElement("style"),n=[];for(document.documentElement.firstChild.appendChild(r),document._qsa=[],r.styleSheet.cssText=e+"{x-qsa:expression(document._qsa && document._qsa.push(this))}",window.scrollBy(0,0),r.parentNode.removeChild(r);document._qsa.length;)t=document._qsa.shift(),t.style.removeAttribute("x-qsa"),n.push(t);return document._qsa=null,n}),document.querySelector||(document.querySelector=function(e){var t=document.querySelectorAll(e);return t.length?t[0]:null}),document.getElementsByClassName||(document.getElementsByClassName=function(e){return e=String(e).replace(/^|\s+/g,"."),document.querySelectorAll(e)}),Object.keys||(Object.keys=function(e){if(e!==Object(e))throw TypeError("Object.keys called on non-object");var t,r=[];for(t in e)Object.prototype.hasOwnProperty.call(e,t)&&r.push(t);return r}),function(e){var t="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";e.atob=e.atob||function(e){e=String(e);var r,n=0,i=[],o=0,a=0;if(e=e.replace(/\s/g,""),e.length%4===0&&(e=e.replace(/=+$/,"")),e.length%4===1)throw Error("InvalidCharacterError");if(/[^+/0-9A-Za-z]/.test(e))throw Error("InvalidCharacterError");for(;n<e.length;)r=t.indexOf(e.charAt(n)),o=o<<6|r,a+=6,24===a&&(i.push(String.fromCharCode(o>>16&255)),i.push(String.fromCharCode(o>>8&255)),i.push(String.fromCharCode(255&o)),a=0,o=0),n+=1;return 12===a?(o>>=4,i.push(String.fromCharCode(255&o))):18===a&&(o>>=2,i.push(String.fromCharCode(o>>8&255)),i.push(String.fromCharCode(255&o))),i.join("")},e.btoa=e.btoa||function(e){e=String(e);var r,n,i,o,a,l,s,d=0,h=[];if(/[^\x00-\xFF]/.test(e))throw Error("InvalidCharacterError");for(;d<e.length;)r=e.charCodeAt(d++),n=e.charCodeAt(d++),i=e.charCodeAt(d++),o=r>>2,a=(3&r)<<4|n>>4,l=(15&n)<<2|i>>6,s=63&i,d===e.length+2?(l=64,s=64):d===e.length+1&&(s=64),h.push(t.charAt(o),t.charAt(a),t.charAt(l),t.charAt(s));return h.join("")}}(this),function(){function e(t,r,n){t.document;var i,o=t.currentStyle[r].match(/([\d\.]+)(%|cm|em|in|mm|pc|pt|)/)||[0,0,""],a=o[1],l=o[2];return n=n?/%|em/.test(l)&&t.parentElement?e(t.parentElement,"fontSize",null):16:n,i="fontSize"==r?n:/width/i.test(r)?t.clientWidth:t.clientHeight,"%"==l?a/100*i:"cm"==l?.3937*a*96:"em"==l?a*n:"in"==l?96*a:"mm"==l?.3937*a*96/10:"pc"==l?12*a*96/72:"pt"==l?96*a/72:a}function t(e,t){var r="border"==t?"Width":"",n=t+"Top"+r,i=t+"Right"+r,o=t+"Bottom"+r,a=t+"Left"+r;e[t]=(e[n]==e[i]&&e[n]==e[o]&&e[n]==e[a]?[e[n]]:e[n]==e[o]&&e[a]==e[i]?[e[n],e[i]]:e[a]==e[i]?[e[n],e[i],e[o]]:[e[n],e[i],e[o],e[a]]).join(" ")}function r(r){var n,i=this,o=r.currentStyle,a=e(r,"fontSize"),l=function(e){return"-"+e.toLowerCase()};for(n in o)if(Array.prototype.push.call(i,"styleFloat"==n?"float":n.replace(/[A-Z]/,l)),"width"==n)i[n]=r.offsetWidth+"px";else if("height"==n)i[n]=r.offsetHeight+"px";else if("styleFloat"==n)i.float=o[n];else if(/margin.|padding.|border.+W/.test(n)&&"auto"!=i[n])i[n]=Math.round(e(r,n,a))+"px";else if(/^outline/.test(n))try{i[n]=o[n]}catch(s){i.outlineColor=o.color,i.outlineStyle=i.outlineStyle||"none",i.outlineWidth=i.outlineWidth||"0px",i.outline=[i.outlineColor,i.outlineWidth,i.outlineStyle].join(" ")}else i[n]=o[n];t(i,"margin"),t(i,"padding"),t(i,"border"),i.fontSize=Math.round(a)+"px"}window.getComputedStyle||(r.prototype={constructor:r,getPropertyPriority:function(){throw new Error("NotSupportedError: DOM Exception 9")},getPropertyValue:function(e){return this[e.replace(/-\w/g,function(e){return e[1].toUpperCase()})]},item:function(e){return this[e]},removeProperty:function(){throw new Error("NoModificationAllowedError: DOM Exception 7")},setProperty:function(){throw new Error("NoModificationAllowedError: DOM Exception 7")},getPropertyCSSValue:function(){throw new Error("NotSupportedError: DOM Exception 9")}},window.getComputedStyle=Window.prototype.getComputedStyle=function(e){return new r(e)})}(),Object.prototype.hasOwnProperty||(Object.prototype.hasOwnProperty=function(e){var t=this.__proto__||this.constructor.prototype;return e in this&&(!(e in t)||t[e]!==this[e])}),function(e,t){e.augment=t()}(this,function(){"use strict";var e=function(){},t=Array.prototype.slice,r=function(r,n){var i=e.prototype="function"==typeof r?r.prototype:r,o=new e,a=n.apply(o,t.call(arguments,2).concat(i));if("object"==typeof a)for(var l in a)o[l]=a[l];if(!o.hasOwnProperty("constructor"))return o;var s=o.constructor;return s.prototype=o,s};return r.defclass=function(e){var t=e.constructor;return t.prototype=e,t},r.extend=function(e,t){return r(e,function(e){return this.uber=e,t})},r}),function(e,t){function r(e,t,r,o){var a=n(r.substr(r.lastIndexOf(e.domain)),e);a&&i(null,o,a,t)}function n(e,t){for(var r={theme:p(A.settings.themes.gray,null),stylesheets:t.stylesheets,holderURL:[]},n=!1,i=String.fromCharCode(11),o=e.replace(/([^\\])\//g,"$1"+i).split(i),a=/%[0-9a-f]{2}/gi,l=o.length,s=0;l>s;s++){var d=o[s];if(d.match(a))try{d=decodeURIComponent(d)}catch(h){d=o[s]}var u=!1;if(A.flags.dimensions.match(d))n=!0,r.dimensions=A.flags.dimensions.output(d),u=!0;else if(A.flags.fluid.match(d))n=!0,r.dimensions=A.flags.fluid.output(d),r.fluid=!0,u=!0;else if(A.flags.textmode.match(d))r.textmode=A.flags.textmode.output(d),u=!0;else if(A.flags.colors.match(d)){var c=A.flags.colors.output(d);r.theme=p(r.theme,c),u=!0}else if(t.themes[d])t.themes.hasOwnProperty(d)&&(r.theme=p(t.themes[d],null)),u=!0;else if(A.flags.font.match(d))r.font=A.flags.font.output(d),u=!0;else if(A.flags.auto.match(d))r.auto=!0,u=!0;else if(A.flags.text.match(d))r.text=A.flags.text.output(d),u=!0;else if(A.flags.random.match(d)){null==A.vars.cache.themeKeys&&(A.vars.cache.themeKeys=Object.keys(t.themes));var f=A.vars.cache.themeKeys[0|Math.random()*A.vars.cache.themeKeys.length];r.theme=p(t.themes[f],null),u=!0}u&&r.holderURL.push(d)}return r.holderURL.unshift(t.domain),r.holderURL=r.holderURL.join("/"),n?r:!1}function i(e,t,r,n){var i=r.dimensions,a=r.theme,l=i.width+"x"+i.height;if(e=null==e?r.fluid?"fluid":"image":e,null!=r.text&&(a.text=r.text,"object"===t.nodeName.toLowerCase())){for(var d=a.text.split("\\n"),u=0;u<d.length;u++)d[u]=b(d[u]);a.text=d.join("\\n")}var f=r.holderURL,g=p(n,null);r.font&&(a.font=r.font,!g.noFontFallback&&"img"===t.nodeName.toLowerCase()&&A.setup.supportsCanvas&&"svg"===g.renderer&&(g=p(g,{renderer:"canvas"}))),r.font&&"canvas"==g.renderer&&(g.reRender=!0),"background"==e?null==t.getAttribute("data-background-src")&&c(t,{"data-background-src":f}):c(t,{"data-src":f}),r.theme=a,t.holderData={flags:r,renderSettings:g},("image"==e||"fluid"==e)&&c(t,{alt:a.text?(a.text.length>16?a.text.substring(0,16)+"…":a.text)+" ["+l+"]":l}),"image"==e?("html"!=g.renderer&&r.auto||(t.style.width=i.width+"px",t.style.height=i.height+"px"),"html"==g.renderer?t.style.backgroundColor=a.background:(o(e,{dimensions:i,theme:a,flags:r},t,g),r.textmode&&"exact"==r.textmode&&(A.vars.resizableImages.push(t),s(t)))):"background"==e&&"html"!=g.renderer?o(e,{dimensions:i,theme:a,flags:r},t,g):"fluid"==e&&("%"==i.height.slice(-1)?t.style.height=i.height:null!=r.auto&&r.auto||(t.style.height=i.height+"px"),"%"==i.width.slice(-1)?t.style.width=i.width:null!=r.auto&&r.auto||(t.style.width=i.width+"px"),("inline"==t.style.display||""===t.style.display||"none"==t.style.display)&&(t.style.display="block"),h(t),"html"==g.renderer?t.style.backgroundColor=a.background:(A.vars.resizableImages.push(t),s(t)))}function o(e,t,r,n){function i(){var e=null;switch(n.renderer){case"canvas":e=L(s);break;case"svg":e=O(s,n);break;default:throw"Holder: invalid renderer: "+n.renderer}return e}var o=null;switch(n.renderer){case"svg":if(!A.setup.supportsSVG)return;break;case"canvas":if(!A.setup.supportsCanvas)return;break;default:return}{var l={width:t.dimensions.width,height:t.dimensions.height,theme:t.theme,flags:t.flags},s=a(l);({text:l.text,width:l.width,height:l.height,textHeight:l.font.size,font:l.font.family,fontWeight:l.font.weight,template:l.theme})}if(o=i(),null==o)throw"Holder: couldn't render placeholder";"background"==e?(r.style.backgroundImage="url("+o+")",r.style.backgroundSize=l.width+"px "+l.height+"px"):("img"===r.nodeName.toLowerCase()?c(r,{src:o}):"object"===r.nodeName.toLowerCase()&&(c(r,{data:o}),c(r,{type:"image/svg+xml"})),n.reRender&&setTimeout(function(){var e=i();if(null==e)throw"Holder: couldn't render placeholder";"img"===r.nodeName.toLowerCase()?c(r,{src:e}):"object"===r.nodeName.toLowerCase()&&(c(r,{data:e}),c(r,{type:"image/svg+xml"}))},100)),c(r,{"data-holder-rendered":!0})}function a(e){function t(e,t,r,n){t.width=r,t.height=n,e.width=Math.max(e.width,t.width),e.height+=t.height,e.add(t)}switch(e.font={family:e.theme.font?e.theme.font:"Arial, Helvetica, Open Sans, sans-serif",size:l(e.width,e.height,e.theme.size?e.theme.size:12),weight:e.theme.fontweight?e.theme.fontweight:"bold"},e.text=e.theme.text?e.theme.text:Math.floor(e.width)+"x"+Math.floor(e.height),e.flags.textmode){case"literal":e.text=e.flags.dimensions.width+"x"+e.flags.dimensions.height;break;case"exact":if(!e.flags.exactDimensions)break;e.text=Math.floor(e.flags.exactDimensions.width)+"x"+Math.floor(e.flags.exactDimensions.height)}var r=new F({width:e.width,height:e.height}),n=r.Shape,i=new n.Rect("holderBg",{fill:e.theme.background});i.resize(e.width,e.height),r.root.add(i);var o=new n.Group("holderTextGroup",{text:e.text,align:"center",font:e.font,fill:e.theme.foreground});o.moveTo(null,null,1),r.root.add(o);var a=o.textPositionData=T(r);if(!a)throw"Holder: staging fallback not supported yet.";o.properties.leading=a.boundingBox.height;var s=null,d=null;if(a.lineCount>1){var h=0,u=0,c=e.width*A.setup.lineWrapRatio,f=0;d=new n.Group("line"+f);for(var g=0;g<a.words.length;g++){var p=a.words[g];s=new n.Text(p.text);var m="\\n"==p.text;(h+p.width>=c||m===!0)&&(t(o,d,h,o.properties.leading),h=0,u+=o.properties.leading,f+=1,d=new n.Group("line"+f),d.y=u),m!==!0&&(s.moveTo(h,0),h+=a.spaceWidth+p.width,d.add(s))}t(o,d,h,o.properties.leading);for(var v in o.children)d=o.children[v],d.moveTo((o.width-d.width)/2,null,null);o.moveTo((e.width-o.width)/2,(e.height-o.height)/2,null),(e.height-o.height)/2<0&&o.moveTo(null,0,null)}else s=new n.Text(e.text),d=new n.Group("line0"),d.add(s),o.add(d),o.moveTo((e.width-a.boundingBox.width)/2,(e.height-a.boundingBox.height)/2,null);return r}function l(e,t,r){t=parseInt(t,10),e=parseInt(e,10);var n=Math.max(t,e),i=Math.min(t,e),o=1/12,a=Math.min(.75*i,.75*n*o);return Math.round(Math.max(r,a))}function s(e){var t;t=null==e||null==e.nodeType?A.vars.resizableImages:[e];for(var r in t)if(t.hasOwnProperty(r)){var n=t[r];if(n.holderData){var i=n.holderData.flags,a=d(n,k.invisibleErrorFn(s));if(a){if(i.fluid&&i.auto){var l=n.holderData.fluidConfig;switch(l.mode){case"width":a.height=a.width/l.ratio;break;case"height":a.width=a.height*l.ratio}}var h={dimensions:a,theme:i.theme,flags:i};i.textmode&&"exact"==i.textmode&&(i.exactDimensions=a,h.dimensions=i.dimensions),o("image",h,n,n.holderData.renderSettings)}}}}function d(e,t){var r={height:e.clientHeight,width:e.clientWidth};return r.height||r.width?(e.removeAttribute("data-holder-invisible"),r):(c(e,{"data-holder-invisible":!0}),void t.call(this,e))}function h(e){if(e.holderData){var t=d(e,k.invisibleErrorFn(h));if(t){var r=e.holderData.flags,n={fluidHeight:"%"==r.dimensions.height.slice(-1),fluidWidth:"%"==r.dimensions.width.slice(-1),mode:null,initialDimensions:t};n.fluidWidth&&!n.fluidHeight?(n.mode="width",n.ratio=n.initialDimensions.width/parseFloat(r.dimensions.height)):!n.fluidWidth&&n.fluidHeight&&(n.mode="height",n.ratio=parseFloat(r.dimensions.width)/n.initialDimensions.height),e.holderData.fluidConfig=n}}}function u(e,t){return null==t?E.createElement(e):E.createElementNS(t,e)}function c(e,t){for(var r in t)e.setAttribute(r,t[r])}function f(e,t,r){if(null==e){e=u("svg",C);var n=u("defs",C);e.appendChild(n)}return e.webkitMatchesSelector&&e.setAttribute("xmlns",C),c(e,{width:t,height:r,viewBox:"0 0 "+t+" "+r,preserveAspectRatio:"none"}),e}function g(e,r){if(t.XMLSerializer){{var n=new XMLSerializer,i="",o=r.stylesheets;e.querySelector("defs")}if(r.svgXMLStylesheet){for(var a=(new DOMParser).parseFromString("<xml />","application/xml"),l=o.length-1;l>=0;l--){var s=a.createProcessingInstruction("xml-stylesheet",'href="'+o[l]+'" rel="stylesheet"');a.insertBefore(s,a.firstChild)}var d=a.createProcessingInstruction("xml",'version="1.0" encoding="UTF-8" standalone="yes"');a.insertBefore(d,a.firstChild),a.removeChild(a.documentElement),i=n.serializeToString(a)}var h=n.serializeToString(e);return h=h.replace(/\&amp;(\#[0-9]{2,}\;)/g,"&$1"),i+h}}function p(e,t){var r={};for(var n in e)e.hasOwnProperty(n)&&(r[n]=e[n]);if(null!=t)for(var i in t)t.hasOwnProperty(i)&&(r[i]=t[i]);return r}function m(e){var t=[];for(var r in e)e.hasOwnProperty(r)&&t.push(r+":"+e[r]);return t.join(";")}function v(e){A.vars.debounceTimer||e.call(this),A.vars.debounceTimer&&clearTimeout(A.vars.debounceTimer),A.vars.debounceTimer=setTimeout(function(){A.vars.debounceTimer=null,e.call(this)},A.setup.debounce)}function x(){v(function(){s(null)})}function y(e){var r=null;return"string"==typeof e?r=E.querySelectorAll(e):t.NodeList&&e instanceof t.NodeList?r=e:t.Node&&e instanceof t.Node?r=[e]:t.HTMLCollection&&e instanceof t.HTMLCollection?r=e:null===e&&(r=[]),r}function w(e,t){var r=new Image;r.onerror=function(){t.call(this,!1,e)},r.onload=function(){t.call(this,!0,e)},r.src=e.src}function b(e){for(var t=[],r=0,n=e.length-1;n>=0;n--)r=e[n].charCodeAt(),t.unshift(r>128?["&#",r,";"].join(""):e[n]);return t.join("")}function S(e){return e.replace(/&#(\d+);/g,function(e,t){return String.fromCharCode(t)})}var C="http://www.w3.org/2000/svg",E=t.document,k={addTheme:function(e,t){return null!=e&&null!=t&&(A.settings.themes[e]=t),delete A.vars.cache.themeKeys,this},addImage:function(e,t){var r=E.querySelectorAll(t);if(r.length)for(var n=0,i=r.length;i>n;n++){var o=u("img");c(o,{"data-src":e}),r[n].appendChild(o)}return this},run:function(e){e=e||{};var o={};A.vars.preempted=!0;var a=p(A.settings,e);o.renderer=a.renderer?a.renderer:A.setup.renderer,-1===A.setup.renderers.join(",").indexOf(o.renderer)&&(o.renderer=A.setup.supportsSVG?"svg":A.setup.supportsCanvas?"canvas":"html"),a.use_canvas?o.renderer="canvas":a.use_svg&&(o.renderer="svg");var l=y(a.images),s=y(a.bgnodes),d=y(a.stylenodes),h=y(a.objects);o.stylesheets=[],o.svgXMLStylesheet=!0,o.noFontFallback=a.noFontFallback?a.noFontFallback:!1;for(var c=0;c<d.length;c++){var f=d[c];if(f.attributes.rel&&f.attributes.href&&"stylesheet"==f.attributes.rel.value){var g=f.attributes.href.value,m=u("a");m.href=g;var v=m.protocol+"//"+m.host+m.pathname+m.search;o.stylesheets.push(v)}}for(c=0;c<s.length;c++){var x=t.getComputedStyle(s[c],null).getPropertyValue("background-image"),b=s[c].getAttribute("data-background-src"),S=null;S=null==b?x:b;var C=null,E="?"+a.domain+"/";if(0===S.indexOf(E))C=S.slice(1);else if(-1!=S.indexOf(E)){var k=S.substr(S.indexOf(E)).slice(1),T=k.match(/([^\"]*)"?\)/);null!=T&&(C=T[1])}if(null!=C){var L=n(C,a);L&&i("background",s[c],L,o)}}for(c=0;c<h.length;c++){var O=h[c],F={};try{F.data=O.getAttribute("data"),F.dataSrc=O.getAttribute("data-src")}catch(z){}var M=null!=F.data&&0===F.data.indexOf(a.domain),D=null!=F.dataSrc&&0===F.dataSrc.indexOf(a.domain);M?r(a,o,F.data,O):D&&r(a,o,F.dataSrc,O)}for(c=0;c<l.length;c++){var R=l[c],j={};try{j.src=R.getAttribute("src"),j.dataSrc=R.getAttribute("data-src"),j.rendered=R.getAttribute("data-holder-rendered")}catch(z){}var B=null!=j.src,P=null!=j.dataSrc&&0===j.dataSrc.indexOf(a.domain),N=null!=j.rendered&&"true"==j.rendered;B?0===j.src.indexOf(a.domain)?r(a,o,j.src,R):P&&(N?r(a,o,j.dataSrc,R):w({src:j.src,options:a,renderSettings:o,dataSrc:j.dataSrc,image:R},function(e,t){e||r(t.options,t.renderSettings,t.dataSrc,t.image)})):P&&r(a,o,j.dataSrc,R)}return this},invisibleErrorFn:function(){return function(e){if(e.hasAttribute("data-holder-invisible"))throw"Holder: invisible placeholder"}}};k.add_theme=k.addTheme,k.add_image=k.addImage,k.invisible_error_fn=k.invisibleErrorFn;var A={settings:{domain:"holder.js",images:"img",objects:"object",bgnodes:"body .holderjs",stylenodes:"head link.holderjs",stylesheets:[],themes:{gray:{background:"#EEEEEE",foreground:"#AAAAAA"},social:{background:"#3a5a97",foreground:"#FFFFFF"},industrial:{background:"#434A52",foreground:"#C2F200"},sky:{background:"#0D8FDB",foreground:"#FFFFFF"},vine:{background:"#39DBAC",foreground:"#1E292C"},lava:{background:"#F8591A",foreground:"#1C2846",size:12}}},flags:{dimensions:{regex:/^(\d+)x(\d+)$/,output:function(e){var t=this.regex.exec(e);return{width:+t[1],height:+t[2]}}},fluid:{regex:/^([0-9]+%?)x([0-9]+%?)$/,output:function(e){var t=this.regex.exec(e);return{width:t[1],height:t[2]}}},colors:{regex:/(?:#|\^)([0-9a-f]{3,})\:(?:#|\^)([0-9a-f]{3,})/i,output:function(e){var t=this.regex.exec(e);return{foreground:"#"+t[2],background:"#"+t[1]}}},text:{regex:/text\:(.*)/,output:function(e){return this.regex.exec(e)[1].replace("\\/","/")}},font:{regex:/font\:(.*)/,output:function(e){return this.regex.exec(e)[1]}},auto:{regex:/^auto$/},textmode:{regex:/textmode\:(.*)/,output:function(e){return this.regex.exec(e)[1]}},random:{regex:/^random$/}}},T=function(){var e=null,t=null,r=null;return function(n){var i=n.root;if(A.setup.supportsSVG){var o=!1,a=function(e){return E.createTextNode(e)};null==e&&(o=!0),e=f(e,i.properties.width,i.properties.height),o&&(t=u("text",C),r=a(null),c(t,{x:0}),t.appendChild(r),e.appendChild(t),E.body.appendChild(e),e.style.visibility="hidden",e.style.position="absolute",e.style.top="-100%",e.style.left="-100%");var l=i.children.holderTextGroup,s=l.properties;c(t,{y:s.font.size,style:m({"font-weight":s.font.weight,"font-size":s.font.size+"px","font-family":s.font.family,"dominant-baseline":"middle"})}),r.nodeValue=s.text;var d=t.getBBox(),h=Math.ceil(d.width/(i.properties.width*A.setup.lineWrapRatio)),g=s.text.split(" "),p=s.text.match(/\\n/g);h+=null==p?0:p.length,r.nodeValue=s.text.replace(/[ ]+/g,"");var v=t.getComputedTextLength(),x=d.width-v,y=Math.round(x/Math.max(1,g.length-1)),w=[];if(h>1){r.nodeValue="";for(var b=0;b<g.length;b++)if(0!==g[b].length){r.nodeValue=S(g[b]);var k=t.getBBox();w.push({text:g[b],width:k.width})}}return{spaceWidth:y,lineCount:h,boundingBox:d,words:w}}return!1}}(),L=function(){var e=u("canvas"),t=null;return function(r){null==t&&(t=e.getContext("2d"));var n=r.root;e.width=A.dpr(n.properties.width),e.height=A.dpr(n.properties.height),t.textBaseline="middle",t.fillStyle=n.children.holderBg.properties.fill,t.fillRect(0,0,A.dpr(n.children.holderBg.width),A.dpr(n.children.holderBg.height));{var i=n.children.holderTextGroup;i.properties}t.font=i.properties.font.weight+" "+A.dpr(i.properties.font.size)+"px "+i.properties.font.family+", monospace",t.fillStyle=i.properties.fill;for(var o in i.children){var a=i.children[o];for(var l in a.children){var s=a.children[l],d=A.dpr(i.x+a.x+s.x),h=A.dpr(i.y+a.y+s.y+i.properties.leading/2);t.fillText(s.properties.text,d,h)}}return e.toDataURL("image/png")}}(),O=function(){if(t.XMLSerializer){var e=f(null,0,0),r=u("rect",C);return e.appendChild(r),function(t,n){var i=t.root;f(e,i.properties.width,i.properties.height);for(var o=e.querySelectorAll("g"),a=0;a<o.length;a++)o[a].parentNode.removeChild(o[a]);c(r,{width:i.children.holderBg.width,height:i.children.holderBg.height,fill:i.children.holderBg.properties.fill});var l=i.children.holderTextGroup,s=l.properties,d=u("g",C);e.appendChild(d);for(var h in l.children){var p=l.children[h];for(var v in p.children){var x=p.children[v],y=l.x+p.x+x.x,w=l.y+p.y+x.y+l.properties.leading/2,b=u("text",C),S=E.createTextNode(null);c(b,{x:y,y:w,style:m({fill:s.fill,"font-weight":s.font.weight,"font-family":s.font.family+", monospace","font-size":s.font.size+"px","dominant-baseline":"central"})}),S.nodeValue=x.properties.text,b.appendChild(S),d.appendChild(b)}}var k="data:image/svg+xml;base64,"+btoa(unescape(encodeURIComponent(g(e,n))));return k}}}(),F=function(e){function t(e,t){for(var r in t)e[r]=t[r];return e}var r=1,n=augment.defclass({constructor:function(e){r++,this.parent=null,this.children={},this.id=r,this.name="n"+r,null!=e&&(this.name=e),this.x=0,this.y=0,this.z=0,this.width=0,this.height=0},resize:function(e,t){null!=e&&(this.width=e),null!=t&&(this.height=t)},moveTo:function(e,t,r){this.x=null!=e?e:this.x,this.y=null!=t?t:this.y,this.z=null!=r?r:this.z},add:function(e){var t=e.name;if(null!=this.children[t])throw"SceneGraph: child with that name already exists: "+t;this.children[t]=e,e.parent=this}}),i=augment(n,function(t){this.constructor=function(){t.constructor.call(this,"root"),this.properties=e}}),o=augment(n,function(e){function r(r,n){if(e.constructor.call(this,r),this.properties={fill:"#000"},null!=n)t(this.properties,n);else if(null!=r&&"string"!=typeof r)throw"SceneGraph: invalid node name"}this.Group=augment.extend(this,{constructor:r,type:"group"}),this.Rect=augment.extend(this,{constructor:r,type:"rect"}),this.Text=augment.extend(this,{constructor:function(e){r.call(this),this.properties.text=e},type:"text"})}),a=new i;return this.Shape=o,this.root=a,this};for(var z in A.flags)A.flags.hasOwnProperty(z)&&(A.flags[z].match=function(e){return e.match(this.regex)});A.setup={renderer:"html",debounce:100,ratio:1,supportsCanvas:!1,supportsSVG:!1,lineWrapRatio:.9,renderers:["html","canvas","svg"]},A.dpr=function(e){return e*A.setup.ratio},A.vars={preempted:!1,resizableImages:[],debounceTimer:null,cache:{}},function(){var e=1,r=1,n=u("canvas"),i=null;n.getContext&&-1!=n.toDataURL("image/png").indexOf("data:image/png")&&(A.setup.renderer="canvas",i=n.getContext("2d"),A.setup.supportsCanvas=!0),A.setup.supportsCanvas&&(e=t.devicePixelRatio||1,r=i.webkitBackingStorePixelRatio||i.mozBackingStorePixelRatio||i.msBackingStorePixelRatio||i.oBackingStorePixelRatio||i.backingStorePixelRatio||1),A.setup.ratio=e/r,E.createElementNS&&E.createElementNS(C,"svg").createSVGRect&&(A.setup.renderer="svg",A.setup.supportsSVG=!0)}(),e(k,"Holder",t),t.onDomReady&&t.onDomReady(function(){A.vars.preempted||k.run(),t.addEventListener?(t.addEventListener("resize",x,!1),t.addEventListener("orientationchange",x,!1)):t.attachEvent("onresize",x),"object"==typeof t.Turbolinks&&t.document.addEventListener("page:change",function(){k.run()})})}(function(e,t,r){var n="function"==typeof define&&define.amd;n?define(e):r[t]=e},this);
  7321  /*!
  7322   * typeahead.js 0.10.5
  7323   * https://github.com/twitter/typeahead.js
  7324   * Copyright 2013-2014 Twitter, Inc. and other contributors; Licensed MIT
  7325   */
  7326  
  7327  (function($) {
  7328      var _ = function() {
  7329          "use strict";
  7330          return {
  7331              isMsie: function() {
  7332                  return /(msie|trident)/i.test(navigator.userAgent) ? navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2] : false;
  7333              },
  7334              isBlankString: function(str) {
  7335                  return !str || /^\s*$/.test(str);
  7336              },
  7337              escapeRegExChars: function(str) {
  7338                  return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
  7339              },
  7340              isString: function(obj) {
  7341                  return typeof obj === "string";
  7342              },
  7343              isNumber: function(obj) {
  7344                  return typeof obj === "number";
  7345              },
  7346              isArray: $.isArray,
  7347              isFunction: $.isFunction,
  7348              isObject: $.isPlainObject,
  7349              isUndefined: function(obj) {
  7350                  return typeof obj === "undefined";
  7351              },
  7352              toStr: function toStr(s) {
  7353                  return _.isUndefined(s) || s === null ? "" : s + "";
  7354              },
  7355              bind: $.proxy,
  7356              each: function(collection, cb) {
  7357                  $.each(collection, reverseArgs);
  7358                  function reverseArgs(index, value) {
  7359                      return cb(value, index);
  7360                  }
  7361              },
  7362              map: $.map,
  7363              filter: $.grep,
  7364              every: function(obj, test) {
  7365                  var result = true;
  7366                  if (!obj) {
  7367                      return result;
  7368                  }
  7369                  $.each(obj, function(key, val) {
  7370                      if (!(result = test.call(null, val, key, obj))) {
  7371                          return false;
  7372                      }
  7373                  });
  7374                  return !!result;
  7375              },
  7376              some: function(obj, test) {
  7377                  var result = false;
  7378                  if (!obj) {
  7379                      return result;
  7380                  }
  7381                  $.each(obj, function(key, val) {
  7382                      if (result = test.call(null, val, key, obj)) {
  7383                          return false;
  7384                      }
  7385                  });
  7386                  return !!result;
  7387              },
  7388              mixin: $.extend,
  7389              getUniqueId: function() {
  7390                  var counter = 0;
  7391                  return function() {
  7392                      return counter++;
  7393                  };
  7394              }(),
  7395              templatify: function templatify(obj) {
  7396                  return $.isFunction(obj) ? obj : template;
  7397                  function template() {
  7398                      return String(obj);
  7399                  }
  7400              },
  7401              defer: function(fn) {
  7402                  setTimeout(fn, 0);
  7403              },
  7404              debounce: function(func, wait, immediate) {
  7405                  var timeout, result;
  7406                  return function() {
  7407                      var context = this, args = arguments, later, callNow;
  7408                      later = function() {
  7409                          timeout = null;
  7410                          if (!immediate) {
  7411                              result = func.apply(context, args);
  7412                          }
  7413                      };
  7414                      callNow = immediate && !timeout;
  7415                      clearTimeout(timeout);
  7416                      timeout = setTimeout(later, wait);
  7417                      if (callNow) {
  7418                          result = func.apply(context, args);
  7419                      }
  7420                      return result;
  7421                  };
  7422              },
  7423              throttle: function(func, wait) {
  7424                  var context, args, timeout, result, previous, later;
  7425                  previous = 0;
  7426                  later = function() {
  7427                      previous = new Date();
  7428                      timeout = null;
  7429                      result = func.apply(context, args);
  7430                  };
  7431                  return function() {
  7432                      var now = new Date(), remaining = wait - (now - previous);
  7433                      context = this;
  7434                      args = arguments;
  7435                      if (remaining <= 0) {
  7436                          clearTimeout(timeout);
  7437                          timeout = null;
  7438                          previous = now;
  7439                          result = func.apply(context, args);
  7440                      } else if (!timeout) {
  7441                          timeout = setTimeout(later, remaining);
  7442                      }
  7443                      return result;
  7444                  };
  7445              },
  7446              noop: function() {}
  7447          };
  7448      }();
  7449      var VERSION = "0.10.5";
  7450      var tokenizers = function() {
  7451          "use strict";
  7452          return {
  7453              nonword: nonword,
  7454              whitespace: whitespace,
  7455              obj: {
  7456                  nonword: getObjTokenizer(nonword),
  7457                  whitespace: getObjTokenizer(whitespace)
  7458              }
  7459          };
  7460          function whitespace(str) {
  7461              str = _.toStr(str);
  7462              return str ? str.split(/\s+/) : [];
  7463          }
  7464          function nonword(str) {
  7465              str = _.toStr(str);
  7466              return str ? str.split(/\W+/) : [];
  7467          }
  7468          function getObjTokenizer(tokenizer) {
  7469              return function setKey() {
  7470                  var args = [].slice.call(arguments, 0);
  7471                  return function tokenize(o) {
  7472                      var tokens = [];
  7473                      _.each(args, function(k) {
  7474                          tokens = tokens.concat(tokenizer(_.toStr(o[k])));
  7475                      });
  7476                      return tokens;
  7477                  };
  7478              };
  7479          }
  7480      }();
  7481      var LruCache = function() {
  7482          "use strict";
  7483          function LruCache(maxSize) {
  7484              this.maxSize = _.isNumber(maxSize) ? maxSize : 100;
  7485              this.reset();
  7486              if (this.maxSize <= 0) {
  7487                  this.set = this.get = $.noop;
  7488              }
  7489          }
  7490          _.mixin(LruCache.prototype, {
  7491              set: function set(key, val) {
  7492                  var tailItem = this.list.tail, node;
  7493                  if (this.size >= this.maxSize) {
  7494                      this.list.remove(tailItem);
  7495                      delete this.hash[tailItem.key];
  7496                  }
  7497                  if (node = this.hash[key]) {
  7498                      node.val = val;
  7499                      this.list.moveToFront(node);
  7500                  } else {
  7501                      node = new Node(key, val);
  7502                      this.list.add(node);
  7503                      this.hash[key] = node;
  7504                      this.size++;
  7505                  }
  7506              },
  7507              get: function get(key) {
  7508                  var node = this.hash[key];
  7509                  if (node) {
  7510                      this.list.moveToFront(node);
  7511                      return node.val;
  7512                  }
  7513              },
  7514              reset: function reset() {
  7515                  this.size = 0;
  7516                  this.hash = {};
  7517                  this.list = new List();
  7518              }
  7519          });
  7520          function List() {
  7521              this.head = this.tail = null;
  7522          }
  7523          _.mixin(List.prototype, {
  7524              add: function add(node) {
  7525                  if (this.head) {
  7526                      node.next = this.head;
  7527                      this.head.prev = node;
  7528                  }
  7529                  this.head = node;
  7530                  this.tail = this.tail || node;
  7531              },
  7532              remove: function remove(node) {
  7533                  node.prev ? node.prev.next = node.next : this.head = node.next;
  7534                  node.next ? node.next.prev = node.prev : this.tail = node.prev;
  7535              },
  7536              moveToFront: function(node) {
  7537                  this.remove(node);
  7538                  this.add(node);
  7539              }
  7540          });
  7541          function Node(key, val) {
  7542              this.key = key;
  7543              this.val = val;
  7544              this.prev = this.next = null;
  7545          }
  7546          return LruCache;
  7547      }();
  7548      var PersistentStorage = function() {
  7549          "use strict";
  7550          var ls, methods;
  7551          try {
  7552              ls = window.localStorage;
  7553              ls.setItem("~~~", "!");
  7554              ls.removeItem("~~~");
  7555          } catch (err) {
  7556              ls = null;
  7557          }
  7558          function PersistentStorage(namespace) {
  7559              this.prefix = [ "__", namespace, "__" ].join("");
  7560              this.ttlKey = "__ttl__";
  7561              this.keyMatcher = new RegExp("^" + _.escapeRegExChars(this.prefix));
  7562          }
  7563          if (ls && window.JSON) {
  7564              methods = {
  7565                  _prefix: function(key) {
  7566                      return this.prefix + key;
  7567                  },
  7568                  _ttlKey: function(key) {
  7569                      return this._prefix(key) + this.ttlKey;
  7570                  },
  7571                  get: function(key) {
  7572                      if (this.isExpired(key)) {
  7573                          this.remove(key);
  7574                      }
  7575                      return decode(ls.getItem(this._prefix(key)));
  7576                  },
  7577                  set: function(key, val, ttl) {
  7578                      if (_.isNumber(ttl)) {
  7579                          ls.setItem(this._ttlKey(key), encode(now() + ttl));
  7580                      } else {
  7581                          ls.removeItem(this._ttlKey(key));
  7582                      }
  7583                      return ls.setItem(this._prefix(key), encode(val));
  7584                  },
  7585                  remove: function(key) {
  7586                      ls.removeItem(this._ttlKey(key));
  7587                      ls.removeItem(this._prefix(key));
  7588                      return this;
  7589                  },
  7590                  clear: function() {
  7591                      var i, key, keys = [], len = ls.length;
  7592                      for (i = 0; i < len; i++) {
  7593                          if ((key = ls.key(i)).match(this.keyMatcher)) {
  7594                              keys.push(key.replace(this.keyMatcher, ""));
  7595                          }
  7596                      }
  7597                      for (i = keys.length; i--; ) {
  7598                          this.remove(keys[i]);
  7599                      }
  7600                      return this;
  7601                  },
  7602                  isExpired: function(key) {
  7603                      var ttl = decode(ls.getItem(this._ttlKey(key)));
  7604                      return _.isNumber(ttl) && now() > ttl ? true : false;
  7605                  }
  7606              };
  7607          } else {
  7608              methods = {
  7609                  get: _.noop,
  7610                  set: _.noop,
  7611                  remove: _.noop,
  7612                  clear: _.noop,
  7613                  isExpired: _.noop
  7614              };
  7615          }
  7616          _.mixin(PersistentStorage.prototype, methods);
  7617          return PersistentStorage;
  7618          function now() {
  7619              return new Date().getTime();
  7620          }
  7621          function encode(val) {
  7622              return JSON.stringify(_.isUndefined(val) ? null : val);
  7623          }
  7624          function decode(val) {
  7625              return JSON.parse(val);
  7626          }
  7627      }();
  7628      var Transport = function() {
  7629          "use strict";
  7630          var pendingRequestsCount = 0, pendingRequests = {}, maxPendingRequests = 6, sharedCache = new LruCache(10);
  7631          function Transport(o) {
  7632              o = o || {};
  7633              this.cancelled = false;
  7634              this.lastUrl = null;
  7635              this._send = o.transport ? callbackToDeferred(o.transport) : $.ajax;
  7636              this._get = o.rateLimiter ? o.rateLimiter(this._get) : this._get;
  7637              this._cache = o.cache === false ? new LruCache(0) : sharedCache;
  7638          }
  7639          Transport.setMaxPendingRequests = function setMaxPendingRequests(num) {
  7640              maxPendingRequests = num;
  7641          };
  7642          Transport.resetCache = function resetCache() {
  7643              sharedCache.reset();
  7644          };
  7645          _.mixin(Transport.prototype, {
  7646              _get: function(url, o, cb) {
  7647                  var that = this, jqXhr;
  7648                  if (this.cancelled || url !== this.lastUrl) {
  7649                      return;
  7650                  }
  7651                  if (jqXhr = pendingRequests[url]) {
  7652                      jqXhr.done(done).fail(fail);
  7653                  } else if (pendingRequestsCount < maxPendingRequests) {
  7654                      pendingRequestsCount++;
  7655                      pendingRequests[url] = this._send(url, o).done(done).fail(fail).always(always);
  7656                  } else {
  7657                      this.onDeckRequestArgs = [].slice.call(arguments, 0);
  7658                  }
  7659                  function done(resp) {
  7660                      cb && cb(null, resp);
  7661                      that._cache.set(url, resp);
  7662                  }
  7663                  function fail() {
  7664                      cb && cb(true);
  7665                  }
  7666                  function always() {
  7667                      pendingRequestsCount--;
  7668                      delete pendingRequests[url];
  7669                      if (that.onDeckRequestArgs) {
  7670                          that._get.apply(that, that.onDeckRequestArgs);
  7671                          that.onDeckRequestArgs = null;
  7672                      }
  7673                  }
  7674              },
  7675              get: function(url, o, cb) {
  7676                  var resp;
  7677                  if (_.isFunction(o)) {
  7678                      cb = o;
  7679                      o = {};
  7680                  }
  7681                  this.cancelled = false;
  7682                  this.lastUrl = url;
  7683                  if (resp = this._cache.get(url)) {
  7684                      _.defer(function() {
  7685                          cb && cb(null, resp);
  7686                      });
  7687                  } else {
  7688                      this._get(url, o, cb);
  7689                  }
  7690                  return !!resp;
  7691              },
  7692              cancel: function() {
  7693                  this.cancelled = true;
  7694              }
  7695          });
  7696          return Transport;
  7697          function callbackToDeferred(fn) {
  7698              return function customSendWrapper(url, o) {
  7699                  var deferred = $.Deferred();
  7700                  fn(url, o, onSuccess, onError);
  7701                  return deferred;
  7702                  function onSuccess(resp) {
  7703                      _.defer(function() {
  7704                          deferred.resolve(resp);
  7705                      });
  7706                  }
  7707                  function onError(err) {
  7708                      _.defer(function() {
  7709                          deferred.reject(err);
  7710                      });
  7711                  }
  7712              };
  7713          }
  7714      }();
  7715      var SearchIndex = function() {
  7716          "use strict";
  7717          function SearchIndex(o) {
  7718              o = o || {};
  7719              if (!o.datumTokenizer || !o.queryTokenizer) {
  7720                  $.error("datumTokenizer and queryTokenizer are both required");
  7721              }
  7722              this.datumTokenizer = o.datumTokenizer;
  7723              this.queryTokenizer = o.queryTokenizer;
  7724              this.reset();
  7725          }
  7726          _.mixin(SearchIndex.prototype, {
  7727              bootstrap: function bootstrap(o) {
  7728                  this.datums = o.datums;
  7729                  this.trie = o.trie;
  7730              },
  7731              add: function(data) {
  7732                  var that = this;
  7733                  data = _.isArray(data) ? data : [ data ];
  7734                  _.each(data, function(datum) {
  7735                      var id, tokens;
  7736                      id = that.datums.push(datum) - 1;
  7737                      tokens = normalizeTokens(that.datumTokenizer(datum));
  7738                      _.each(tokens, function(token) {
  7739                          var node, chars, ch;
  7740                          node = that.trie;
  7741                          chars = token.split("");
  7742                          while (ch = chars.shift()) {
  7743                              node = node.children[ch] || (node.children[ch] = newNode());
  7744                              node.ids.push(id);
  7745                          }
  7746                      });
  7747                  });
  7748              },
  7749              get: function get(query) {
  7750                  var that = this, tokens, matches;
  7751                  tokens = normalizeTokens(this.queryTokenizer(query));
  7752                  _.each(tokens, function(token) {
  7753                      var node, chars, ch, ids;
  7754                      if (matches && matches.length === 0) {
  7755                          return false;
  7756                      }
  7757                      node = that.trie;
  7758                      chars = token.split("");
  7759                      while (node && (ch = chars.shift())) {
  7760                          node = node.children[ch];
  7761                      }
  7762                      if (node && chars.length === 0) {
  7763                          ids = node.ids.slice(0);
  7764                          matches = matches ? getIntersection(matches, ids) : ids;
  7765                      } else {
  7766                          matches = [];
  7767                          return false;
  7768                      }
  7769                  });
  7770                  return matches ? _.map(unique(matches), function(id) {
  7771                      return that.datums[id];
  7772                  }) : [];
  7773              },
  7774              reset: function reset() {
  7775                  this.datums = [];
  7776                  this.trie = newNode();
  7777              },
  7778              serialize: function serialize() {
  7779                  return {
  7780                      datums: this.datums,
  7781                      trie: this.trie
  7782                  };
  7783              }
  7784          });
  7785          return SearchIndex;
  7786          function normalizeTokens(tokens) {
  7787              tokens = _.filter(tokens, function(token) {
  7788                  return !!token;
  7789              });
  7790              tokens = _.map(tokens, function(token) {
  7791                  return token.toLowerCase();
  7792              });
  7793              return tokens;
  7794          }
  7795          function newNode() {
  7796              return {
  7797                  ids: [],
  7798                  children: {}
  7799              };
  7800          }
  7801          function unique(array) {
  7802              var seen = {}, uniques = [];
  7803              for (var i = 0, len = array.length; i < len; i++) {
  7804                  if (!seen[array[i]]) {
  7805                      seen[array[i]] = true;
  7806                      uniques.push(array[i]);
  7807                  }
  7808              }
  7809              return uniques;
  7810          }
  7811          function getIntersection(arrayA, arrayB) {
  7812              var ai = 0, bi = 0, intersection = [];
  7813              arrayA = arrayA.sort(compare);
  7814              arrayB = arrayB.sort(compare);
  7815              var lenArrayA = arrayA.length, lenArrayB = arrayB.length;
  7816              while (ai < lenArrayA && bi < lenArrayB) {
  7817                  if (arrayA[ai] < arrayB[bi]) {
  7818                      ai++;
  7819                  } else if (arrayA[ai] > arrayB[bi]) {
  7820                      bi++;
  7821                  } else {
  7822                      intersection.push(arrayA[ai]);
  7823                      ai++;
  7824                      bi++;
  7825                  }
  7826              }
  7827              return intersection;
  7828              function compare(a, b) {
  7829                  return a - b;
  7830              }
  7831          }
  7832      }();
  7833      var oParser = function() {
  7834          "use strict";
  7835          return {
  7836              local: getLocal,
  7837              prefetch: getPrefetch,
  7838              remote: getRemote
  7839          };
  7840          function getLocal(o) {
  7841              return o.local || null;
  7842          }
  7843          function getPrefetch(o) {
  7844              var prefetch, defaults;
  7845              defaults = {
  7846                  url: null,
  7847                  thumbprint: "",
  7848                  ttl: 24 * 60 * 60 * 1e3,
  7849                  filter: null,
  7850                  ajax: {}
  7851              };
  7852              if (prefetch = o.prefetch || null) {
  7853                  prefetch = _.isString(prefetch) ? {
  7854                      url: prefetch
  7855                  } : prefetch;
  7856                  prefetch = _.mixin(defaults, prefetch);
  7857                  prefetch.thumbprint = VERSION + prefetch.thumbprint;
  7858                  prefetch.ajax.type = prefetch.ajax.type || "GET";
  7859                  prefetch.ajax.dataType = prefetch.ajax.dataType || "json";
  7860                  !prefetch.url && $.error("prefetch requires url to be set");
  7861              }
  7862              return prefetch;
  7863          }
  7864          function getRemote(o) {
  7865              var remote, defaults;
  7866              defaults = {
  7867                  url: null,
  7868                  cache: true,
  7869                  wildcard: "%QUERY",
  7870                  replace: null,
  7871                  rateLimitBy: "debounce",
  7872                  rateLimitWait: 300,
  7873                  send: null,
  7874                  filter: null,
  7875                  ajax: {}
  7876              };
  7877              if (remote = o.remote || null) {
  7878                  remote = _.isString(remote) ? {
  7879                      url: remote
  7880                  } : remote;
  7881                  remote = _.mixin(defaults, remote);
  7882                  remote.rateLimiter = /^throttle$/i.test(remote.rateLimitBy) ? byThrottle(remote.rateLimitWait) : byDebounce(remote.rateLimitWait);
  7883                  remote.ajax.type = remote.ajax.type || "GET";
  7884                  remote.ajax.dataType = remote.ajax.dataType || "json";
  7885                  delete remote.rateLimitBy;
  7886                  delete remote.rateLimitWait;
  7887                  !remote.url && $.error("remote requires url to be set");
  7888              }
  7889              return remote;
  7890              function byDebounce(wait) {
  7891                  return function(fn) {
  7892                      return _.debounce(fn, wait);
  7893                  };
  7894              }
  7895              function byThrottle(wait) {
  7896                  return function(fn) {
  7897                      return _.throttle(fn, wait);
  7898                  };
  7899              }
  7900          }
  7901      }();
  7902      (function(root) {
  7903          "use strict";
  7904          var old, keys;
  7905          old = root.Bloodhound;
  7906          keys = {
  7907              data: "data",
  7908              protocol: "protocol",
  7909              thumbprint: "thumbprint"
  7910          };
  7911          root.Bloodhound = Bloodhound;
  7912          function Bloodhound(o) {
  7913              if (!o || !o.local && !o.prefetch && !o.remote) {
  7914                  $.error("one of local, prefetch, or remote is required");
  7915              }
  7916              this.limit = o.limit || 5;
  7917              this.sorter = getSorter(o.sorter);
  7918              this.dupDetector = o.dupDetector || ignoreDuplicates;
  7919              this.local = oParser.local(o);
  7920              this.prefetch = oParser.prefetch(o);
  7921              this.remote = oParser.remote(o);
  7922              this.cacheKey = this.prefetch ? this.prefetch.cacheKey || this.prefetch.url : null;
  7923              this.index = new SearchIndex({
  7924                  datumTokenizer: o.datumTokenizer,
  7925                  queryTokenizer: o.queryTokenizer
  7926              });
  7927              this.storage = this.cacheKey ? new PersistentStorage(this.cacheKey) : null;
  7928          }
  7929          Bloodhound.noConflict = function noConflict() {
  7930              root.Bloodhound = old;
  7931              return Bloodhound;
  7932          };
  7933          Bloodhound.tokenizers = tokenizers;
  7934          _.mixin(Bloodhound.prototype, {
  7935              _loadPrefetch: function loadPrefetch(o) {
  7936                  var that = this, serialized, deferred;
  7937                  if (serialized = this._readFromStorage(o.thumbprint)) {
  7938                      this.index.bootstrap(serialized);
  7939                      deferred = $.Deferred().resolve();
  7940                  } else {
  7941                      deferred = $.ajax(o.url, o.ajax).done(handlePrefetchResponse);
  7942                  }
  7943                  return deferred;
  7944                  function handlePrefetchResponse(resp) {
  7945                      that.clear();
  7946                      that.add(o.filter ? o.filter(resp) : resp);
  7947                      that._saveToStorage(that.index.serialize(), o.thumbprint, o.ttl);
  7948                  }
  7949              },
  7950              _getFromRemote: function getFromRemote(query, cb) {
  7951                  var that = this, url, uriEncodedQuery;
  7952                  if (!this.transport) {
  7953                      return;
  7954                  }
  7955                  query = query || "";
  7956                  uriEncodedQuery = encodeURIComponent(query);
  7957                  url = this.remote.replace ? this.remote.replace(this.remote.url, query) : this.remote.url.replace(this.remote.wildcard, uriEncodedQuery);
  7958                  return this.transport.get(url, this.remote.ajax, handleRemoteResponse);
  7959                  function handleRemoteResponse(err, resp) {
  7960                      err ? cb([]) : cb(that.remote.filter ? that.remote.filter(resp) : resp);
  7961                  }
  7962              },
  7963              _cancelLastRemoteRequest: function cancelLastRemoteRequest() {
  7964                  this.transport && this.transport.cancel();
  7965              },
  7966              _saveToStorage: function saveToStorage(data, thumbprint, ttl) {
  7967                  if (this.storage) {
  7968                      this.storage.set(keys.data, data, ttl);
  7969                      this.storage.set(keys.protocol, location.protocol, ttl);
  7970                      this.storage.set(keys.thumbprint, thumbprint, ttl);
  7971                  }
  7972              },
  7973              _readFromStorage: function readFromStorage(thumbprint) {
  7974                  var stored = {}, isExpired;
  7975                  if (this.storage) {
  7976                      stored.data = this.storage.get(keys.data);
  7977                      stored.protocol = this.storage.get(keys.protocol);
  7978                      stored.thumbprint = this.storage.get(keys.thumbprint);
  7979                  }
  7980                  isExpired = stored.thumbprint !== thumbprint || stored.protocol !== location.protocol;
  7981                  return stored.data && !isExpired ? stored.data : null;
  7982              },
  7983              _initialize: function initialize() {
  7984                  var that = this, local = this.local, deferred;
  7985                  deferred = this.prefetch ? this._loadPrefetch(this.prefetch) : $.Deferred().resolve();
  7986                  local && deferred.done(addLocalToIndex);
  7987                  this.transport = this.remote ? new Transport(this.remote) : null;
  7988                  return this.initPromise = deferred.promise();
  7989                  function addLocalToIndex() {
  7990                      that.add(_.isFunction(local) ? local() : local);
  7991                  }
  7992              },
  7993              initialize: function initialize(force) {
  7994                  return !this.initPromise || force ? this._initialize() : this.initPromise;
  7995              },
  7996              add: function add(data) {
  7997                  this.index.add(data);
  7998              },
  7999              get: function get(query, cb) {
  8000                  var that = this, matches = [], cacheHit = false;
  8001                  matches = this.index.get(query);
  8002                  matches = this.sorter(matches).slice(0, this.limit);
  8003                  matches.length < this.limit ? cacheHit = this._getFromRemote(query, returnRemoteMatches) : this._cancelLastRemoteRequest();
  8004                  if (!cacheHit) {
  8005                      (matches.length > 0 || !this.transport) && cb && cb(matches);
  8006                  }
  8007                  function returnRemoteMatches(remoteMatches) {
  8008                      var matchesWithBackfill = matches.slice(0);
  8009                      _.each(remoteMatches, function(remoteMatch) {
  8010                          var isDuplicate;
  8011                          isDuplicate = _.some(matchesWithBackfill, function(match) {
  8012                              return that.dupDetector(remoteMatch, match);
  8013                          });
  8014                          !isDuplicate && matchesWithBackfill.push(remoteMatch);
  8015                          return matchesWithBackfill.length < that.limit;
  8016                      });
  8017                      cb && cb(that.sorter(matchesWithBackfill));
  8018                  }
  8019              },
  8020              clear: function clear() {
  8021                  this.index.reset();
  8022              },
  8023              clearPrefetchCache: function clearPrefetchCache() {
  8024                  this.storage && this.storage.clear();
  8025              },
  8026              clearRemoteCache: function clearRemoteCache() {
  8027                  this.transport && Transport.resetCache();
  8028              },
  8029              ttAdapter: function ttAdapter() {
  8030                  return _.bind(this.get, this);
  8031              }
  8032          });
  8033          return Bloodhound;
  8034          function getSorter(sortFn) {
  8035              return _.isFunction(sortFn) ? sort : noSort;
  8036              function sort(array) {
  8037                  return array.sort(sortFn);
  8038              }
  8039              function noSort(array) {
  8040                  return array;
  8041              }
  8042          }
  8043          function ignoreDuplicates() {
  8044              return false;
  8045          }
  8046      })(this);
  8047      var html = function() {
  8048          return {
  8049              wrapper: '<span class="twitter-typeahead"></span>',
  8050              dropdown: '<span class="tt-dropdown-menu"></span>',
  8051              dataset: '<div class="tt-dataset-%CLASS%"></div>',
  8052              suggestions: '<span class="tt-suggestions"></span>',
  8053              suggestion: '<div class="tt-suggestion"></div>'
  8054          };
  8055      }();
  8056      var css = function() {
  8057          "use strict";
  8058          var css = {
  8059              wrapper: {
  8060                  position: "relative",
  8061                  display: "inline-block"
  8062              },
  8063              hint: {
  8064                  position: "absolute",
  8065                  top: "0",
  8066                  left: "0",
  8067                  borderColor: "transparent",
  8068                  boxShadow: "none",
  8069                  opacity: "1"
  8070              },
  8071              input: {
  8072                  position: "relative",
  8073                  verticalAlign: "top",
  8074                  backgroundColor: "transparent"
  8075              },
  8076              inputWithNoHint: {
  8077                  position: "relative",
  8078                  verticalAlign: "top"
  8079              },
  8080              dropdown: {
  8081                  position: "absolute",
  8082                  top: "100%",
  8083                  left: "0",
  8084                  zIndex: "100",
  8085                  display: "none"
  8086              },
  8087              suggestions: {
  8088                  display: "block"
  8089              },
  8090              suggestion: {
  8091                  whiteSpace: "nowrap",
  8092                  cursor: "pointer"
  8093              },
  8094              suggestionChild: {
  8095                  whiteSpace: "normal"
  8096              },
  8097              ltr: {
  8098                  left: "0",
  8099                  right: "auto"
  8100              },
  8101              rtl: {
  8102                  left: "auto",
  8103                  right: " 0"
  8104              }
  8105          };
  8106          if (_.isMsie()) {
  8107              _.mixin(css.input, {
  8108                  backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"
  8109              });
  8110          }
  8111          if (_.isMsie() && _.isMsie() <= 7) {
  8112              _.mixin(css.input, {
  8113                  marginTop: "-1px"
  8114              });
  8115          }
  8116          return css;
  8117      }();
  8118      var EventBus = function() {
  8119          "use strict";
  8120          var namespace = "typeahead:";
  8121          function EventBus(o) {
  8122              if (!o || !o.el) {
  8123                  $.error("EventBus initialized without el");
  8124              }
  8125              this.$el = $(o.el);
  8126          }
  8127          _.mixin(EventBus.prototype, {
  8128              trigger: function(type) {
  8129                  var args = [].slice.call(arguments, 1);
  8130                  this.$el.trigger(namespace + type, args);
  8131              }
  8132          });
  8133          return EventBus;
  8134      }();
  8135      var EventEmitter = function() {
  8136          "use strict";
  8137          var splitter = /\s+/, nextTick = getNextTick();
  8138          return {
  8139              onSync: onSync,
  8140              onAsync: onAsync,
  8141              off: off,
  8142              trigger: trigger
  8143          };
  8144          function on(method, types, cb, context) {
  8145              var type;
  8146              if (!cb) {
  8147                  return this;
  8148              }
  8149              types = types.split(splitter);
  8150              cb = context ? bindContext(cb, context) : cb;
  8151              this._callbacks = this._callbacks || {};
  8152              while (type = types.shift()) {
  8153                  this._callbacks[type] = this._callbacks[type] || {
  8154                      sync: [],
  8155                      async: []
  8156                  };
  8157                  this._callbacks[type][method].push(cb);
  8158              }
  8159              return this;
  8160          }
  8161          function onAsync(types, cb, context) {
  8162              return on.call(this, "async", types, cb, context);
  8163          }
  8164          function onSync(types, cb, context) {
  8165              return on.call(this, "sync", types, cb, context);
  8166          }
  8167          function off(types) {
  8168              var type;
  8169              if (!this._callbacks) {
  8170                  return this;
  8171              }
  8172              types = types.split(splitter);
  8173              while (type = types.shift()) {
  8174                  delete this._callbacks[type];
  8175              }
  8176              return this;
  8177          }
  8178          function trigger(types) {
  8179              var type, callbacks, args, syncFlush, asyncFlush;
  8180              if (!this._callbacks) {
  8181                  return this;
  8182              }
  8183              types = types.split(splitter);
  8184              args = [].slice.call(arguments, 1);
  8185              while ((type = types.shift()) && (callbacks = this._callbacks[type])) {
  8186                  syncFlush = getFlush(callbacks.sync, this, [ type ].concat(args));
  8187                  asyncFlush = getFlush(callbacks.async, this, [ type ].concat(args));
  8188                  syncFlush() && nextTick(asyncFlush);
  8189              }
  8190              return this;
  8191          }
  8192          function getFlush(callbacks, context, args) {
  8193              return flush;
  8194              function flush() {
  8195                  var cancelled;
  8196                  for (var i = 0, len = callbacks.length; !cancelled && i < len; i += 1) {
  8197                      cancelled = callbacks[i].apply(context, args) === false;
  8198                  }
  8199                  return !cancelled;
  8200              }
  8201          }
  8202          function getNextTick() {
  8203              var nextTickFn;
  8204              if (window.setImmediate) {
  8205                  nextTickFn = function nextTickSetImmediate(fn) {
  8206                      setImmediate(function() {
  8207                          fn();
  8208                      });
  8209                  };
  8210              } else {
  8211                  nextTickFn = function nextTickSetTimeout(fn) {
  8212                      setTimeout(function() {
  8213                          fn();
  8214                      }, 0);
  8215                  };
  8216              }
  8217              return nextTickFn;
  8218          }
  8219          function bindContext(fn, context) {
  8220              return fn.bind ? fn.bind(context) : function() {
  8221                  fn.apply(context, [].slice.call(arguments, 0));
  8222              };
  8223          }
  8224      }();
  8225      var highlight = function(doc) {
  8226          "use strict";
  8227          var defaults = {
  8228              node: null,
  8229              pattern: null,
  8230              tagName: "strong",
  8231              className: null,
  8232              wordsOnly: false,
  8233              caseSensitive: false
  8234          };
  8235          return function hightlight(o) {
  8236              var regex;
  8237              o = _.mixin({}, defaults, o);
  8238              if (!o.node || !o.pattern) {
  8239                  return;
  8240              }
  8241              o.pattern = _.isArray(o.pattern) ? o.pattern : [ o.pattern ];
  8242              regex = getRegex(o.pattern, o.caseSensitive, o.wordsOnly);
  8243              traverse(o.node, hightlightTextNode);
  8244              function hightlightTextNode(textNode) {
  8245                  var match, patternNode, wrapperNode;
  8246                  if (match = regex.exec(textNode.data)) {
  8247                      wrapperNode = doc.createElement(o.tagName);
  8248                      o.className && (wrapperNode.className = o.className);
  8249                      patternNode = textNode.splitText(match.index);
  8250                      patternNode.splitText(match[0].length);
  8251                      wrapperNode.appendChild(patternNode.cloneNode(true));
  8252                      textNode.parentNode.replaceChild(wrapperNode, patternNode);
  8253                  }
  8254                  return !!match;
  8255              }
  8256              function traverse(el, hightlightTextNode) {
  8257                  var childNode, TEXT_NODE_TYPE = 3;
  8258                  for (var i = 0; i < el.childNodes.length; i++) {
  8259                      childNode = el.childNodes[i];
  8260                      if (childNode.nodeType === TEXT_NODE_TYPE) {
  8261                          i += hightlightTextNode(childNode) ? 1 : 0;
  8262                      } else {
  8263                          traverse(childNode, hightlightTextNode);
  8264                      }
  8265                  }
  8266              }
  8267          };
  8268          function getRegex(patterns, caseSensitive, wordsOnly) {
  8269              var escapedPatterns = [], regexStr;
  8270              for (var i = 0, len = patterns.length; i < len; i++) {
  8271                  escapedPatterns.push(_.escapeRegExChars(patterns[i]));
  8272              }
  8273              regexStr = wordsOnly ? "\\b(" + escapedPatterns.join("|") + ")\\b" : "(" + escapedPatterns.join("|") + ")";
  8274              return caseSensitive ? new RegExp(regexStr) : new RegExp(regexStr, "i");
  8275          }
  8276      }(window.document);
  8277      var Input = function() {
  8278          "use strict";
  8279          var specialKeyCodeMap;
  8280          specialKeyCodeMap = {
  8281              9: "tab",
  8282              27: "esc",
  8283              37: "left",
  8284              39: "right",
  8285              13: "enter",
  8286              38: "up",
  8287              40: "down"
  8288          };
  8289          function Input(o) {
  8290              var that = this, onBlur, onFocus, onKeydown, onInput;
  8291              o = o || {};
  8292              if (!o.input) {
  8293                  $.error("input is missing");
  8294              }
  8295              onBlur = _.bind(this._onBlur, this);
  8296              onFocus = _.bind(this._onFocus, this);
  8297              onKeydown = _.bind(this._onKeydown, this);
  8298              onInput = _.bind(this._onInput, this);
  8299              this.$hint = $(o.hint);
  8300              this.$input = $(o.input).on("blur.tt", onBlur).on("focus.tt", onFocus).on("keydown.tt", onKeydown);
  8301              if (this.$hint.length === 0) {
  8302                  this.setHint = this.getHint = this.clearHint = this.clearHintIfInvalid = _.noop;
  8303              }
  8304              if (!_.isMsie()) {
  8305                  this.$input.on("input.tt", onInput);
  8306              } else {
  8307                  this.$input.on("keydown.tt keypress.tt cut.tt paste.tt", function($e) {
  8308                      if (specialKeyCodeMap[$e.which || $e.keyCode]) {
  8309                          return;
  8310                      }
  8311                      _.defer(_.bind(that._onInput, that, $e));
  8312                  });
  8313              }
  8314              this.query = this.$input.val();
  8315              this.$overflowHelper = buildOverflowHelper(this.$input);
  8316          }
  8317          Input.normalizeQuery = function(str) {
  8318              return (str || "").replace(/^\s*/g, "").replace(/\s{2,}/g, " ");
  8319          };
  8320          _.mixin(Input.prototype, EventEmitter, {
  8321              _onBlur: function onBlur() {
  8322                  this.resetInputValue();
  8323                  this.trigger("blurred");
  8324              },
  8325              _onFocus: function onFocus() {
  8326                  this.trigger("focused");
  8327              },
  8328              _onKeydown: function onKeydown($e) {
  8329                  var keyName = specialKeyCodeMap[$e.which || $e.keyCode];
  8330                  this._managePreventDefault(keyName, $e);
  8331                  if (keyName && this._shouldTrigger(keyName, $e)) {
  8332                      this.trigger(keyName + "Keyed", $e);
  8333                  }
  8334              },
  8335              _onInput: function onInput() {
  8336                  this._checkInputValue();
  8337              },
  8338              _managePreventDefault: function managePreventDefault(keyName, $e) {
  8339                  var preventDefault, hintValue, inputValue;
  8340                  switch (keyName) {
  8341                    case "tab":
  8342                      hintValue = this.getHint();
  8343                      inputValue = this.getInputValue();
  8344                      preventDefault = hintValue && hintValue !== inputValue && !withModifier($e);
  8345                      break;
  8346  
  8347                    case "up":
  8348                    case "down":
  8349                      preventDefault = !withModifier($e);
  8350                      break;
  8351  
  8352                    default:
  8353                      preventDefault = false;
  8354                  }
  8355                  preventDefault && $e.preventDefault();
  8356              },
  8357              _shouldTrigger: function shouldTrigger(keyName, $e) {
  8358                  var trigger;
  8359                  switch (keyName) {
  8360                    case "tab":
  8361                      trigger = !withModifier($e);
  8362                      break;
  8363  
  8364                    default:
  8365                      trigger = true;
  8366                  }
  8367                  return trigger;
  8368              },
  8369              _checkInputValue: function checkInputValue() {
  8370                  var inputValue, areEquivalent, hasDifferentWhitespace;
  8371                  inputValue = this.getInputValue();
  8372                  areEquivalent = areQueriesEquivalent(inputValue, this.query);
  8373                  hasDifferentWhitespace = areEquivalent ? this.query.length !== inputValue.length : false;
  8374                  this.query = inputValue;
  8375                  if (!areEquivalent) {
  8376                      this.trigger("queryChanged", this.query);
  8377                  } else if (hasDifferentWhitespace) {
  8378                      this.trigger("whitespaceChanged", this.query);
  8379                  }
  8380              },
  8381              focus: function focus() {
  8382                  this.$input.focus();
  8383              },
  8384              blur: function blur() {
  8385                  this.$input.blur();
  8386              },
  8387              getQuery: function getQuery() {
  8388                  return this.query;
  8389              },
  8390              setQuery: function setQuery(query) {
  8391                  this.query = query;
  8392              },
  8393              getInputValue: function getInputValue() {
  8394                  return this.$input.val();
  8395              },
  8396              setInputValue: function setInputValue(value, silent) {
  8397                  this.$input.val(value);
  8398                  silent ? this.clearHint() : this._checkInputValue();
  8399              },
  8400              resetInputValue: function resetInputValue() {
  8401                  this.setInputValue(this.query, true);
  8402              },
  8403              getHint: function getHint() {
  8404                  return this.$hint.val();
  8405              },
  8406              setHint: function setHint(value) {
  8407                  this.$hint.val(value);
  8408              },
  8409              clearHint: function clearHint() {
  8410                  this.setHint("");
  8411              },
  8412              clearHintIfInvalid: function clearHintIfInvalid() {
  8413                  var val, hint, valIsPrefixOfHint, isValid;
  8414                  val = this.getInputValue();
  8415                  hint = this.getHint();
  8416                  valIsPrefixOfHint = val !== hint && hint.indexOf(val) === 0;
  8417                  isValid = val !== "" && valIsPrefixOfHint && !this.hasOverflow();
  8418                  !isValid && this.clearHint();
  8419              },
  8420              getLanguageDirection: function getLanguageDirection() {
  8421                  return (this.$input.css("direction") || "ltr").toLowerCase();
  8422              },
  8423              hasOverflow: function hasOverflow() {
  8424                  var constraint = this.$input.width() - 2;
  8425                  this.$overflowHelper.text(this.getInputValue());
  8426                  return this.$overflowHelper.width() >= constraint;
  8427              },
  8428              isCursorAtEnd: function() {
  8429                  var valueLength, selectionStart, range;
  8430                  valueLength = this.$input.val().length;
  8431                  selectionStart = this.$input[0].selectionStart;
  8432                  if (_.isNumber(selectionStart)) {
  8433                      return selectionStart === valueLength;
  8434                  } else if (document.selection) {
  8435                      range = document.selection.createRange();
  8436                      range.moveStart("character", -valueLength);
  8437                      return valueLength === range.text.length;
  8438                  }
  8439                  return true;
  8440              },
  8441              destroy: function destroy() {
  8442                  this.$hint.off(".tt");
  8443                  this.$input.off(".tt");
  8444                  this.$hint = this.$input = this.$overflowHelper = null;
  8445              }
  8446          });
  8447          return Input;
  8448          function buildOverflowHelper($input) {
  8449              return $('<pre aria-hidden="true"></pre>').css({
  8450                  position: "absolute",
  8451                  visibility: "hidden",
  8452                  whiteSpace: "pre",
  8453                  fontFamily: $input.css("font-family"),
  8454                  fontSize: $input.css("font-size"),
  8455                  fontStyle: $input.css("font-style"),
  8456                  fontVariant: $input.css("font-variant"),
  8457                  fontWeight: $input.css("font-weight"),
  8458                  wordSpacing: $input.css("word-spacing"),
  8459                  letterSpacing: $input.css("letter-spacing"),
  8460                  textIndent: $input.css("text-indent"),
  8461                  textRendering: $input.css("text-rendering"),
  8462                  textTransform: $input.css("text-transform")
  8463              }).insertAfter($input);
  8464          }
  8465          function areQueriesEquivalent(a, b) {
  8466              return Input.normalizeQuery(a) === Input.normalizeQuery(b);
  8467          }
  8468          function withModifier($e) {
  8469              return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;
  8470          }
  8471      }();
  8472      var Dataset = function() {
  8473          "use strict";
  8474          var datasetKey = "ttDataset", valueKey = "ttValue", datumKey = "ttDatum";
  8475          function Dataset(o) {
  8476              o = o || {};
  8477              o.templates = o.templates || {};
  8478              if (!o.source) {
  8479                  $.error("missing source");
  8480              }
  8481              if (o.name && !isValidName(o.name)) {
  8482                  $.error("invalid dataset name: " + o.name);
  8483              }
  8484              this.query = null;
  8485              this.highlight = !!o.highlight;
  8486              this.name = o.name || _.getUniqueId();
  8487              this.source = o.source;
  8488              this.displayFn = getDisplayFn(o.display || o.displayKey);
  8489              this.templates = getTemplates(o.templates, this.displayFn);
  8490              this.$el = $(html.dataset.replace("%CLASS%", this.name));
  8491          }
  8492          Dataset.extractDatasetName = function extractDatasetName(el) {
  8493              return $(el).data(datasetKey);
  8494          };
  8495          Dataset.extractValue = function extractDatum(el) {
  8496              return $(el).data(valueKey);
  8497          };
  8498          Dataset.extractDatum = function extractDatum(el) {
  8499              return $(el).data(datumKey);
  8500          };
  8501          _.mixin(Dataset.prototype, EventEmitter, {
  8502              _render: function render(query, suggestions) {
  8503                  if (!this.$el) {
  8504                      return;
  8505                  }
  8506                  var that = this, hasSuggestions;
  8507                  this.$el.empty();
  8508                  hasSuggestions = suggestions && suggestions.length;
  8509                  if (!hasSuggestions && this.templates.empty) {
  8510                      this.$el.html(getEmptyHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);
  8511                  } else if (hasSuggestions) {
  8512                      this.$el.html(getSuggestionsHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);
  8513                  }
  8514                  this.trigger("rendered");
  8515                  function getEmptyHtml() {
  8516                      return that.templates.empty({
  8517                          query: query,
  8518                          isEmpty: true
  8519                      });
  8520                  }
  8521                  function getSuggestionsHtml() {
  8522                      var $suggestions, nodes;
  8523                      $suggestions = $(html.suggestions).css(css.suggestions);
  8524                      nodes = _.map(suggestions, getSuggestionNode);
  8525                      $suggestions.append.apply($suggestions, nodes);
  8526                      that.highlight && highlight({
  8527                          className: "tt-highlight",
  8528                          node: $suggestions[0],
  8529                          pattern: query
  8530                      });
  8531                      return $suggestions;
  8532                      function getSuggestionNode(suggestion) {
  8533                          var $el;
  8534                          $el = $(html.suggestion).append(that.templates.suggestion(suggestion)).data(datasetKey, that.name).data(valueKey, that.displayFn(suggestion)).data(datumKey, suggestion);
  8535                          $el.children().each(function() {
  8536                              $(this).css(css.suggestionChild);
  8537                          });
  8538                          return $el;
  8539                      }
  8540                  }
  8541                  function getHeaderHtml() {
  8542                      return that.templates.header({
  8543                          query: query,
  8544                          isEmpty: !hasSuggestions
  8545                      });
  8546                  }
  8547                  function getFooterHtml() {
  8548                      return that.templates.footer({
  8549                          query: query,
  8550                          isEmpty: !hasSuggestions
  8551                      });
  8552                  }
  8553              },
  8554              getRoot: function getRoot() {
  8555                  return this.$el;
  8556              },
  8557              update: function update(query) {
  8558                  var that = this;
  8559                  this.query = query;
  8560                  this.canceled = false;
  8561                  this.source(query, render);
  8562                  function render(suggestions) {
  8563                      if (!that.canceled && query === that.query) {
  8564                          that._render(query, suggestions);
  8565                      }
  8566                  }
  8567              },
  8568              cancel: function cancel() {
  8569                  this.canceled = true;
  8570              },
  8571              clear: function clear() {
  8572                  this.cancel();
  8573                  this.$el.empty();
  8574                  this.trigger("rendered");
  8575              },
  8576              isEmpty: function isEmpty() {
  8577                  return this.$el.is(":empty");
  8578              },
  8579              destroy: function destroy() {
  8580                  this.$el = null;
  8581              }
  8582          });
  8583          return Dataset;
  8584          function getDisplayFn(display) {
  8585              display = display || "value";
  8586              return _.isFunction(display) ? display : displayFn;
  8587              function displayFn(obj) {
  8588                  return obj[display];
  8589              }
  8590          }
  8591          function getTemplates(templates, displayFn) {
  8592              return {
  8593                  empty: templates.empty && _.templatify(templates.empty),
  8594                  header: templates.header && _.templatify(templates.header),
  8595                  footer: templates.footer && _.templatify(templates.footer),
  8596                  suggestion: templates.suggestion || suggestionTemplate
  8597              };
  8598              function suggestionTemplate(context) {
  8599                  return "<p>" + displayFn(context) + "</p>";
  8600              }
  8601          }
  8602          function isValidName(str) {
  8603              return /^[_a-zA-Z0-9-]+$/.test(str);
  8604          }
  8605      }();
  8606      var Dropdown = function() {
  8607          "use strict";
  8608          function Dropdown(o) {
  8609              var that = this, onSuggestionClick, onSuggestionMouseEnter, onSuggestionMouseLeave;
  8610              o = o || {};
  8611              if (!o.menu) {
  8612                  $.error("menu is required");
  8613              }
  8614              this.isOpen = false;
  8615              this.isEmpty = true;
  8616              this.datasets = _.map(o.datasets, initializeDataset);
  8617              onSuggestionClick = _.bind(this._onSuggestionClick, this);
  8618              onSuggestionMouseEnter = _.bind(this._onSuggestionMouseEnter, this);
  8619              onSuggestionMouseLeave = _.bind(this._onSuggestionMouseLeave, this);
  8620              this.$menu = $(o.menu).on("click.tt", ".tt-suggestion", onSuggestionClick).on("mouseenter.tt", ".tt-suggestion", onSuggestionMouseEnter).on("mouseleave.tt", ".tt-suggestion", onSuggestionMouseLeave);
  8621              _.each(this.datasets, function(dataset) {
  8622                  that.$menu.append(dataset.getRoot());
  8623                  dataset.onSync("rendered", that._onRendered, that);
  8624              });
  8625          }
  8626          _.mixin(Dropdown.prototype, EventEmitter, {
  8627              _onSuggestionClick: function onSuggestionClick($e) {
  8628                  this.trigger("suggestionClicked", $($e.currentTarget));
  8629              },
  8630              _onSuggestionMouseEnter: function onSuggestionMouseEnter($e) {
  8631                  this._removeCursor();
  8632                  this._setCursor($($e.currentTarget), true);
  8633              },
  8634              _onSuggestionMouseLeave: function onSuggestionMouseLeave() {
  8635                  this._removeCursor();
  8636              },
  8637              _onRendered: function onRendered() {
  8638                  this.isEmpty = _.every(this.datasets, isDatasetEmpty);
  8639                  this.isEmpty ? this._hide() : this.isOpen && this._show();
  8640                  this.trigger("datasetRendered");
  8641                  function isDatasetEmpty(dataset) {
  8642                      return dataset.isEmpty();
  8643                  }
  8644              },
  8645              _hide: function() {
  8646                  this.$menu.hide();
  8647              },
  8648              _show: function() {
  8649                  this.$menu.css("display", "block");
  8650              },
  8651              _getSuggestions: function getSuggestions() {
  8652                  return this.$menu.find(".tt-suggestion");
  8653              },
  8654              _getCursor: function getCursor() {
  8655                  return this.$menu.find(".tt-cursor").first();
  8656              },
  8657              _setCursor: function setCursor($el, silent) {
  8658                  $el.first().addClass("tt-cursor");
  8659                  !silent && this.trigger("cursorMoved");
  8660              },
  8661              _removeCursor: function removeCursor() {
  8662                  this._getCursor().removeClass("tt-cursor");
  8663              },
  8664              _moveCursor: function moveCursor(increment) {
  8665                  var $suggestions, $oldCursor, newCursorIndex, $newCursor;
  8666                  if (!this.isOpen) {
  8667                      return;
  8668                  }
  8669                  $oldCursor = this._getCursor();
  8670                  $suggestions = this._getSuggestions();
  8671                  this._removeCursor();
  8672                  newCursorIndex = $suggestions.index($oldCursor) + increment;
  8673                  newCursorIndex = (newCursorIndex + 1) % ($suggestions.length + 1) - 1;
  8674                  if (newCursorIndex === -1) {
  8675                      this.trigger("cursorRemoved");
  8676                      return;
  8677                  } else if (newCursorIndex < -1) {
  8678                      newCursorIndex = $suggestions.length - 1;
  8679                  }
  8680                  this._setCursor($newCursor = $suggestions.eq(newCursorIndex));
  8681                  this._ensureVisible($newCursor);
  8682              },
  8683              _ensureVisible: function ensureVisible($el) {
  8684                  var elTop, elBottom, menuScrollTop, menuHeight;
  8685                  elTop = $el.position().top;
  8686                  elBottom = elTop + $el.outerHeight(true);
  8687                  menuScrollTop = this.$menu.scrollTop();
  8688                  menuHeight = this.$menu.height() + parseInt(this.$menu.css("paddingTop"), 10) + parseInt(this.$menu.css("paddingBottom"), 10);
  8689                  if (elTop < 0) {
  8690                      this.$menu.scrollTop(menuScrollTop + elTop);
  8691                  } else if (menuHeight < elBottom) {
  8692                      this.$menu.scrollTop(menuScrollTop + (elBottom - menuHeight));
  8693                  }
  8694              },
  8695              close: function close() {
  8696                  if (this.isOpen) {
  8697                      this.isOpen = false;
  8698                      this._removeCursor();
  8699                      this._hide();
  8700                      this.trigger("closed");
  8701                  }
  8702              },
  8703              open: function open() {
  8704                  if (!this.isOpen) {
  8705                      this.isOpen = true;
  8706                      !this.isEmpty && this._show();
  8707                      this.trigger("opened");
  8708                  }
  8709              },
  8710              setLanguageDirection: function setLanguageDirection(dir) {
  8711                  this.$menu.css(dir === "ltr" ? css.ltr : css.rtl);
  8712              },
  8713              moveCursorUp: function moveCursorUp() {
  8714                  this._moveCursor(-1);
  8715              },
  8716              moveCursorDown: function moveCursorDown() {
  8717                  this._moveCursor(+1);
  8718              },
  8719              getDatumForSuggestion: function getDatumForSuggestion($el) {
  8720                  var datum = null;
  8721                  if ($el.length) {
  8722                      datum = {
  8723                          raw: Dataset.extractDatum($el),
  8724                          value: Dataset.extractValue($el),
  8725                          datasetName: Dataset.extractDatasetName($el)
  8726                      };
  8727                  }
  8728                  return datum;
  8729              },
  8730              getDatumForCursor: function getDatumForCursor() {
  8731                  return this.getDatumForSuggestion(this._getCursor().first());
  8732              },
  8733              getDatumForTopSuggestion: function getDatumForTopSuggestion() {
  8734                  return this.getDatumForSuggestion(this._getSuggestions().first());
  8735              },
  8736              update: function update(query) {
  8737                  _.each(this.datasets, updateDataset);
  8738                  function updateDataset(dataset) {
  8739                      dataset.update(query);
  8740                  }
  8741              },
  8742              empty: function empty() {
  8743                  _.each(this.datasets, clearDataset);
  8744                  this.isEmpty = true;
  8745                  function clearDataset(dataset) {
  8746                      dataset.clear();
  8747                  }
  8748              },
  8749              isVisible: function isVisible() {
  8750                  return this.isOpen && !this.isEmpty;
  8751              },
  8752              destroy: function destroy() {
  8753                  this.$menu.off(".tt");
  8754                  this.$menu = null;
  8755                  _.each(this.datasets, destroyDataset);
  8756                  function destroyDataset(dataset) {
  8757                      dataset.destroy();
  8758                  }
  8759              }
  8760          });
  8761          return Dropdown;
  8762          function initializeDataset(oDataset) {
  8763              return new Dataset(oDataset);
  8764          }
  8765      }();
  8766      var Typeahead = function() {
  8767          "use strict";
  8768          var attrsKey = "ttAttrs";
  8769          function Typeahead(o) {
  8770              var $menu, $input, $hint;
  8771              o = o || {};
  8772              if (!o.input) {
  8773                  $.error("missing input");
  8774              }
  8775              this.isActivated = false;
  8776              this.autoselect = !!o.autoselect;
  8777              this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;
  8778              this.$node = buildDom(o.input, o.withHint);
  8779              $menu = this.$node.find(".tt-dropdown-menu");
  8780              $input = this.$node.find(".tt-input");
  8781              $hint = this.$node.find(".tt-hint");
  8782              $input.on("blur.tt", function($e) {
  8783                  var active, isActive, hasActive;
  8784                  active = document.activeElement;
  8785                  isActive = $menu.is(active);
  8786                  hasActive = $menu.has(active).length > 0;
  8787                  if (_.isMsie() && (isActive || hasActive)) {
  8788                      $e.preventDefault();
  8789                      $e.stopImmediatePropagation();
  8790                      _.defer(function() {
  8791                          $input.focus();
  8792                      });
  8793                  }
  8794              });
  8795              $menu.on("mousedown.tt", function($e) {
  8796                  $e.preventDefault();
  8797              });
  8798              this.eventBus = o.eventBus || new EventBus({
  8799                  el: $input
  8800              });
  8801              this.dropdown = new Dropdown({
  8802                  menu: $menu,
  8803                  datasets: o.datasets
  8804              }).onSync("suggestionClicked", this._onSuggestionClicked, this).onSync("cursorMoved", this._onCursorMoved, this).onSync("cursorRemoved", this._onCursorRemoved, this).onSync("opened", this._onOpened, this).onSync("closed", this._onClosed, this).onAsync("datasetRendered", this._onDatasetRendered, this);
  8805              this.input = new Input({
  8806                  input: $input,
  8807                  hint: $hint
  8808              }).onSync("focused", this._onFocused, this).onSync("blurred", this._onBlurred, this).onSync("enterKeyed", this._onEnterKeyed, this).onSync("tabKeyed", this._onTabKeyed, this).onSync("escKeyed", this._onEscKeyed, this).onSync("upKeyed", this._onUpKeyed, this).onSync("downKeyed", this._onDownKeyed, this).onSync("leftKeyed", this._onLeftKeyed, this).onSync("rightKeyed", this._onRightKeyed, this).onSync("queryChanged", this._onQueryChanged, this).onSync("whitespaceChanged", this._onWhitespaceChanged, this);
  8809              this._setLanguageDirection();
  8810          }
  8811          _.mixin(Typeahead.prototype, {
  8812              _onSuggestionClicked: function onSuggestionClicked(type, $el) {
  8813                  var datum;
  8814                  if (datum = this.dropdown.getDatumForSuggestion($el)) {
  8815                      this._select(datum);
  8816                  }
  8817              },
  8818              _onCursorMoved: function onCursorMoved() {
  8819                  var datum = this.dropdown.getDatumForCursor();
  8820                  this.input.setInputValue(datum.value, true);
  8821                  this.eventBus.trigger("cursorchanged", datum.raw, datum.datasetName);
  8822              },
  8823              _onCursorRemoved: function onCursorRemoved() {
  8824                  this.input.resetInputValue();
  8825                  this._updateHint();
  8826              },
  8827              _onDatasetRendered: function onDatasetRendered() {
  8828                  this._updateHint();
  8829              },
  8830              _onOpened: function onOpened() {
  8831                  this._updateHint();
  8832                  this.eventBus.trigger("opened");
  8833              },
  8834              _onClosed: function onClosed() {
  8835                  this.input.clearHint();
  8836                  this.eventBus.trigger("closed");
  8837              },
  8838              _onFocused: function onFocused() {
  8839                  this.isActivated = true;
  8840                  this.dropdown.open();
  8841              },
  8842              _onBlurred: function onBlurred() {
  8843                  this.isActivated = false;
  8844                  this.dropdown.empty();
  8845                  this.dropdown.close();
  8846              },
  8847              _onEnterKeyed: function onEnterKeyed(type, $e) {
  8848                  var cursorDatum, topSuggestionDatum;
  8849                  cursorDatum = this.dropdown.getDatumForCursor();
  8850                  topSuggestionDatum = this.dropdown.getDatumForTopSuggestion();
  8851                  if (cursorDatum) {
  8852                      this._select(cursorDatum);
  8853                      $e.preventDefault();
  8854                  } else if (this.autoselect && topSuggestionDatum) {
  8855                      this._select(topSuggestionDatum);
  8856                      $e.preventDefault();
  8857                  }
  8858              },
  8859              _onTabKeyed: function onTabKeyed(type, $e) {
  8860                  var datum;
  8861                  if (datum = this.dropdown.getDatumForCursor()) {
  8862                      this._select(datum);
  8863                      $e.preventDefault();
  8864                  } else {
  8865                      this._autocomplete(true);
  8866                  }
  8867              },
  8868              _onEscKeyed: function onEscKeyed() {
  8869                  this.dropdown.close();
  8870                  this.input.resetInputValue();
  8871              },
  8872              _onUpKeyed: function onUpKeyed() {
  8873                  var query = this.input.getQuery();
  8874                  this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorUp();
  8875                  this.dropdown.open();
  8876              },
  8877              _onDownKeyed: function onDownKeyed() {
  8878                  var query = this.input.getQuery();
  8879                  this.dropdown.isEmpty && query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.moveCursorDown();
  8880                  this.dropdown.open();
  8881              },
  8882              _onLeftKeyed: function onLeftKeyed() {
  8883                  this.dir === "rtl" && this._autocomplete();
  8884              },
  8885              _onRightKeyed: function onRightKeyed() {
  8886                  this.dir === "ltr" && this._autocomplete();
  8887              },
  8888              _onQueryChanged: function onQueryChanged(e, query) {
  8889                  this.input.clearHintIfInvalid();
  8890                  query.length >= this.minLength ? this.dropdown.update(query) : this.dropdown.empty();
  8891                  this.dropdown.open();
  8892                  this._setLanguageDirection();
  8893              },
  8894              _onWhitespaceChanged: function onWhitespaceChanged() {
  8895                  this._updateHint();
  8896                  this.dropdown.open();
  8897              },
  8898              _setLanguageDirection: function setLanguageDirection() {
  8899                  var dir;
  8900                  if (this.dir !== (dir = this.input.getLanguageDirection())) {
  8901                      this.dir = dir;
  8902                      this.$node.css("direction", dir);
  8903                      this.dropdown.setLanguageDirection(dir);
  8904                  }
  8905              },
  8906              _updateHint: function updateHint() {
  8907                  var datum, val, query, escapedQuery, frontMatchRegEx, match;
  8908                  datum = this.dropdown.getDatumForTopSuggestion();
  8909                  if (datum && this.dropdown.isVisible() && !this.input.hasOverflow()) {
  8910                      val = this.input.getInputValue();
  8911                      query = Input.normalizeQuery(val);
  8912                      escapedQuery = _.escapeRegExChars(query);
  8913                      frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.+$)", "i");
  8914                      match = frontMatchRegEx.exec(datum.value);
  8915                      match ? this.input.setHint(val + match[1]) : this.input.clearHint();
  8916                  } else {
  8917                      this.input.clearHint();
  8918                  }
  8919              },
  8920              _autocomplete: function autocomplete(laxCursor) {
  8921                  var hint, query, isCursorAtEnd, datum;
  8922                  hint = this.input.getHint();
  8923                  query = this.input.getQuery();
  8924                  isCursorAtEnd = laxCursor || this.input.isCursorAtEnd();
  8925                  if (hint && query !== hint && isCursorAtEnd) {
  8926                      datum = this.dropdown.getDatumForTopSuggestion();
  8927                      datum && this.input.setInputValue(datum.value);
  8928                      this.eventBus.trigger("autocompleted", datum.raw, datum.datasetName);
  8929                  }
  8930              },
  8931              _select: function select(datum) {
  8932                  this.input.setQuery(datum.value);
  8933                  this.input.setInputValue(datum.value, true);
  8934                  this._setLanguageDirection();
  8935                  this.eventBus.trigger("selected", datum.raw, datum.datasetName);
  8936                  this.dropdown.close();
  8937                  _.defer(_.bind(this.dropdown.empty, this.dropdown));
  8938              },
  8939              open: function open() {
  8940                  this.dropdown.open();
  8941              },
  8942              close: function close() {
  8943                  this.dropdown.close();
  8944              },
  8945              setVal: function setVal(val) {
  8946                  val = _.toStr(val);
  8947                  if (this.isActivated) {
  8948                      this.input.setInputValue(val);
  8949                  } else {
  8950                      this.input.setQuery(val);
  8951                      this.input.setInputValue(val, true);
  8952                  }
  8953                  this._setLanguageDirection();
  8954              },
  8955              getVal: function getVal() {
  8956                  return this.input.getQuery();
  8957              },
  8958              destroy: function destroy() {
  8959                  this.input.destroy();
  8960                  this.dropdown.destroy();
  8961                  destroyDomStructure(this.$node);
  8962                  this.$node = null;
  8963              }
  8964          });
  8965          return Typeahead;
  8966          function buildDom(input, withHint) {
  8967              var $input, $wrapper, $dropdown, $hint;
  8968              $input = $(input);
  8969              $wrapper = $(html.wrapper).css(css.wrapper);
  8970              $dropdown = $(html.dropdown).css(css.dropdown);
  8971              $hint = $input.clone().css(css.hint).css(getBackgroundStyles($input));
  8972              $hint.val("").removeData().addClass("tt-hint").removeAttr("id name placeholder required").prop("readonly", true).attr({
  8973                  autocomplete: "off",
  8974                  spellcheck: "false",
  8975                  tabindex: -1
  8976              });
  8977              $input.data(attrsKey, {
  8978                  dir: $input.attr("dir"),
  8979                  autocomplete: $input.attr("autocomplete"),
  8980                  spellcheck: $input.attr("spellcheck"),
  8981                  style: $input.attr("style")
  8982              });
  8983              $input.addClass("tt-input").attr({
  8984                  autocomplete: "off",
  8985                  spellcheck: false
  8986              }).css(withHint ? css.input : css.inputWithNoHint);
  8987              try {
  8988                  !$input.attr("dir") && $input.attr("dir", "auto");
  8989              } catch (e) {}
  8990              return $input.wrap($wrapper).parent().prepend(withHint ? $hint : null).append($dropdown);
  8991          }
  8992          function getBackgroundStyles($el) {
  8993              return {
  8994                  backgroundAttachment: $el.css("background-attachment"),
  8995                  backgroundClip: $el.css("background-clip"),
  8996                  backgroundColor: $el.css("background-color"),
  8997                  backgroundImage: $el.css("background-image"),
  8998                  backgroundOrigin: $el.css("background-origin"),
  8999                  backgroundPosition: $el.css("background-position"),
  9000                  backgroundRepeat: $el.css("background-repeat"),
  9001                  backgroundSize: $el.css("background-size")
  9002              };
  9003          }
  9004          function destroyDomStructure($node) {
  9005              var $input = $node.find(".tt-input");
  9006              _.each($input.data(attrsKey), function(val, key) {
  9007                  _.isUndefined(val) ? $input.removeAttr(key) : $input.attr(key, val);
  9008              });
  9009              $input.detach().removeData(attrsKey).removeClass("tt-input").insertAfter($node);
  9010              $node.remove();
  9011          }
  9012      }();
  9013      (function() {
  9014          "use strict";
  9015          var old, typeaheadKey, methods;
  9016          old = $.fn.typeahead;
  9017          typeaheadKey = "ttTypeahead";
  9018          methods = {
  9019              initialize: function initialize(o, datasets) {
  9020                  datasets = _.isArray(datasets) ? datasets : [].slice.call(arguments, 1);
  9021                  o = o || {};
  9022                  return this.each(attach);
  9023                  function attach() {
  9024                      var $input = $(this), eventBus, typeahead;
  9025                      _.each(datasets, function(d) {
  9026                          d.highlight = !!o.highlight;
  9027                      });
  9028                      typeahead = new Typeahead({
  9029                          input: $input,
  9030                          eventBus: eventBus = new EventBus({
  9031                              el: $input
  9032                          }),
  9033                          withHint: _.isUndefined(o.hint) ? true : !!o.hint,
  9034                          minLength: o.minLength,
  9035                          autoselect: o.autoselect,
  9036                          datasets: datasets
  9037                      });
  9038                      $input.data(typeaheadKey, typeahead);
  9039                  }
  9040              },
  9041              open: function open() {
  9042                  return this.each(openTypeahead);
  9043                  function openTypeahead() {
  9044                      var $input = $(this), typeahead;
  9045                      if (typeahead = $input.data(typeaheadKey)) {
  9046                          typeahead.open();
  9047                      }
  9048                  }
  9049              },
  9050              close: function close() {
  9051                  return this.each(closeTypeahead);
  9052                  function closeTypeahead() {
  9053                      var $input = $(this), typeahead;
  9054                      if (typeahead = $input.data(typeaheadKey)) {
  9055                          typeahead.close();
  9056                      }
  9057                  }
  9058              },
  9059              val: function val(newVal) {
  9060                  return !arguments.length ? getVal(this.first()) : this.each(setVal);
  9061                  function setVal() {
  9062                      var $input = $(this), typeahead;
  9063                      if (typeahead = $input.data(typeaheadKey)) {
  9064                          typeahead.setVal(newVal);
  9065                      }
  9066                  }
  9067                  function getVal($input) {
  9068                      var typeahead, query;
  9069                      if (typeahead = $input.data(typeaheadKey)) {
  9070                          query = typeahead.getVal();
  9071                      }
  9072                      return query;
  9073                  }
  9074              },
  9075              destroy: function destroy() {
  9076                  return this.each(unattach);
  9077                  function unattach() {
  9078                      var $input = $(this), typeahead;
  9079                      if (typeahead = $input.data(typeaheadKey)) {
  9080                          typeahead.destroy();
  9081                          $input.removeData(typeaheadKey);
  9082                      }
  9083                  }
  9084              }
  9085          };
  9086          $.fn.typeahead = function(method) {
  9087              var tts;
  9088              if (methods[method] && method !== "initialize") {
  9089                  tts = this.filter(function() {
  9090                      return !!$(this).data(typeaheadKey);
  9091                  });
  9092                  return methods[method].apply(tts, [].slice.call(arguments, 1));
  9093              } else {
  9094                  return methods.initialize.apply(this, arguments);
  9095              }
  9096          };
  9097          $.fn.typeahead.noConflict = function noConflict() {
  9098              $.fn.typeahead = old;
  9099              return this;
  9100          };
  9101      })();
  9102  })(window.jQuery);
  9103  /*
  9104  Copyright 2012 Igor Vaynberg
  9105  
  9106  Version: 3.5.1 Timestamp: Tue Jul 22 18:58:56 EDT 2014
  9107  
  9108  This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU
  9109  General Public License version 2 (the "GPL License"). You may choose either license to govern your
  9110  use of this software only upon the condition that you accept all of the terms of either the Apache
  9111  License or the GPL License.
  9112  
  9113  You may obtain a copy of the Apache License and the GPL License at:
  9114  
  9115      http://www.apache.org/licenses/LICENSE-2.0
  9116      http://www.gnu.org/licenses/gpl-2.0.html
  9117  
  9118  Unless required by applicable law or agreed to in writing, software distributed under the
  9119  Apache License or the GPL License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
  9120  CONDITIONS OF ANY KIND, either express or implied. See the Apache License and the GPL License for
  9121  the specific language governing permissions and limitations under the Apache License and the GPL License.
  9122  */
  9123  (function ($) {
  9124      if(typeof $.fn.each2 == "undefined") {
  9125          $.extend($.fn, {
  9126              /*
  9127              * 4-10 times faster .each replacement
  9128              * use it carefully, as it overrides jQuery context of element on each iteration
  9129              */
  9130              each2 : function (c) {
  9131                  var j = $([0]), i = -1, l = this.length;
  9132                  while (
  9133                      ++i < l
  9134                      && (j.context = j[0] = this[i])
  9135                      && c.call(j[0], i, j) !== false //"this"=DOM, i=index, j=jQuery object
  9136                  );
  9137                  return this;
  9138              }
  9139          });
  9140      }
  9141  })(jQuery);
  9142  
  9143  (function ($, undefined) {
  9144      "use strict";
  9145      /*global document, window, jQuery, console */
  9146  
  9147      if (window.Select2 !== undefined) {
  9148          return;
  9149      }
  9150  
  9151      var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, nextUid, sizer,
  9152          lastMousePosition={x:0,y:0}, $document, scrollBarDimensions,
  9153  
  9154      KEY = {
  9155          TAB: 9,
  9156          ENTER: 13,
  9157          ESC: 27,
  9158          SPACE: 32,
  9159          LEFT: 37,
  9160          UP: 38,
  9161          RIGHT: 39,
  9162          DOWN: 40,
  9163          SHIFT: 16,
  9164          CTRL: 17,
  9165          ALT: 18,
  9166          PAGE_UP: 33,
  9167          PAGE_DOWN: 34,
  9168          HOME: 36,
  9169          END: 35,
  9170          BACKSPACE: 8,
  9171          DELETE: 46,
  9172          isArrow: function (k) {
  9173              k = k.which ? k.which : k;
  9174              switch (k) {
  9175              case KEY.LEFT:
  9176              case KEY.RIGHT:
  9177              case KEY.UP:
  9178              case KEY.DOWN:
  9179                  return true;
  9180              }
  9181              return false;
  9182          },
  9183          isControl: function (e) {
  9184              var k = e.which;
  9185              switch (k) {
  9186              case KEY.SHIFT:
  9187              case KEY.CTRL:
  9188              case KEY.ALT:
  9189                  return true;
  9190              }
  9191  
  9192              if (e.metaKey) return true;
  9193  
  9194              return false;
  9195          },
  9196          isFunctionKey: function (k) {
  9197              k = k.which ? k.which : k;
  9198              return k >= 112 && k <= 123;
  9199          }
  9200      },
  9201      MEASURE_SCROLLBAR_TEMPLATE = "<div class='select2-measure-scrollbar'></div>",
  9202  
  9203      DIACRITICS = {"\u24B6":"A","\uFF21":"A","\u00C0":"A","\u00C1":"A","\u00C2":"A","\u1EA6":"A","\u1EA4":"A","\u1EAA":"A","\u1EA8":"A","\u00C3":"A","\u0100":"A","\u0102":"A","\u1EB0":"A","\u1EAE":"A","\u1EB4":"A","\u1EB2":"A","\u0226":"A","\u01E0":"A","\u00C4":"A","\u01DE":"A","\u1EA2":"A","\u00C5":"A","\u01FA":"A","\u01CD":"A","\u0200":"A","\u0202":"A","\u1EA0":"A","\u1EAC":"A","\u1EB6":"A","\u1E00":"A","\u0104":"A","\u023A":"A","\u2C6F":"A","\uA732":"AA","\u00C6":"AE","\u01FC":"AE","\u01E2":"AE","\uA734":"AO","\uA736":"AU","\uA738":"AV","\uA73A":"AV","\uA73C":"AY","\u24B7":"B","\uFF22":"B","\u1E02":"B","\u1E04":"B","\u1E06":"B","\u0243":"B","\u0182":"B","\u0181":"B","\u24B8":"C","\uFF23":"C","\u0106":"C","\u0108":"C","\u010A":"C","\u010C":"C","\u00C7":"C","\u1E08":"C","\u0187":"C","\u023B":"C","\uA73E":"C","\u24B9":"D","\uFF24":"D","\u1E0A":"D","\u010E":"D","\u1E0C":"D","\u1E10":"D","\u1E12":"D","\u1E0E":"D","\u0110":"D","\u018B":"D","\u018A":"D","\u0189":"D","\uA779":"D","\u01F1":"DZ","\u01C4":"DZ","\u01F2":"Dz","\u01C5":"Dz","\u24BA":"E","\uFF25":"E","\u00C8":"E","\u00C9":"E","\u00CA":"E","\u1EC0":"E","\u1EBE":"E","\u1EC4":"E","\u1EC2":"E","\u1EBC":"E","\u0112":"E","\u1E14":"E","\u1E16":"E","\u0114":"E","\u0116":"E","\u00CB":"E","\u1EBA":"E","\u011A":"E","\u0204":"E","\u0206":"E","\u1EB8":"E","\u1EC6":"E","\u0228":"E","\u1E1C":"E","\u0118":"E","\u1E18":"E","\u1E1A":"E","\u0190":"E","\u018E":"E","\u24BB":"F","\uFF26":"F","\u1E1E":"F","\u0191":"F","\uA77B":"F","\u24BC":"G","\uFF27":"G","\u01F4":"G","\u011C":"G","\u1E20":"G","\u011E":"G","\u0120":"G","\u01E6":"G","\u0122":"G","\u01E4":"G","\u0193":"G","\uA7A0":"G","\uA77D":"G","\uA77E":"G","\u24BD":"H","\uFF28":"H","\u0124":"H","\u1E22":"H","\u1E26":"H","\u021E":"H","\u1E24":"H","\u1E28":"H","\u1E2A":"H","\u0126":"H","\u2C67":"H","\u2C75":"H","\uA78D":"H","\u24BE":"I","\uFF29":"I","\u00CC":"I","\u00CD":"I","\u00CE":"I","\u0128":"I","\u012A":"I","\u012C":"I","\u0130":"I","\u00CF":"I","\u1E2E":"I","\u1EC8":"I","\u01CF":"I","\u0208":"I","\u020A":"I","\u1ECA":"I","\u012E":"I","\u1E2C":"I","\u0197":"I","\u24BF":"J","\uFF2A":"J","\u0134":"J","\u0248":"J","\u24C0":"K","\uFF2B":"K","\u1E30":"K","\u01E8":"K","\u1E32":"K","\u0136":"K","\u1E34":"K","\u0198":"K","\u2C69":"K","\uA740":"K","\uA742":"K","\uA744":"K","\uA7A2":"K","\u24C1":"L","\uFF2C":"L","\u013F":"L","\u0139":"L","\u013D":"L","\u1E36":"L","\u1E38":"L","\u013B":"L","\u1E3C":"L","\u1E3A":"L","\u0141":"L","\u023D":"L","\u2C62":"L","\u2C60":"L","\uA748":"L","\uA746":"L","\uA780":"L","\u01C7":"LJ","\u01C8":"Lj","\u24C2":"M","\uFF2D":"M","\u1E3E":"M","\u1E40":"M","\u1E42":"M","\u2C6E":"M","\u019C":"M","\u24C3":"N","\uFF2E":"N","\u01F8":"N","\u0143":"N","\u00D1":"N","\u1E44":"N","\u0147":"N","\u1E46":"N","\u0145":"N","\u1E4A":"N","\u1E48":"N","\u0220":"N","\u019D":"N","\uA790":"N","\uA7A4":"N","\u01CA":"NJ","\u01CB":"Nj","\u24C4":"O","\uFF2F":"O","\u00D2":"O","\u00D3":"O","\u00D4":"O","\u1ED2":"O","\u1ED0":"O","\u1ED6":"O","\u1ED4":"O","\u00D5":"O","\u1E4C":"O","\u022C":"O","\u1E4E":"O","\u014C":"O","\u1E50":"O","\u1E52":"O","\u014E":"O","\u022E":"O","\u0230":"O","\u00D6":"O","\u022A":"O","\u1ECE":"O","\u0150":"O","\u01D1":"O","\u020C":"O","\u020E":"O","\u01A0":"O","\u1EDC":"O","\u1EDA":"O","\u1EE0":"O","\u1EDE":"O","\u1EE2":"O","\u1ECC":"O","\u1ED8":"O","\u01EA":"O","\u01EC":"O","\u00D8":"O","\u01FE":"O","\u0186":"O","\u019F":"O","\uA74A":"O","\uA74C":"O","\u01A2":"OI","\uA74E":"OO","\u0222":"OU","\u24C5":"P","\uFF30":"P","\u1E54":"P","\u1E56":"P","\u01A4":"P","\u2C63":"P","\uA750":"P","\uA752":"P","\uA754":"P","\u24C6":"Q","\uFF31":"Q","\uA756":"Q","\uA758":"Q","\u024A":"Q","\u24C7":"R","\uFF32":"R","\u0154":"R","\u1E58":"R","\u0158":"R","\u0210":"R","\u0212":"R","\u1E5A":"R","\u1E5C":"R","\u0156":"R","\u1E5E":"R","\u024C":"R","\u2C64":"R","\uA75A":"R","\uA7A6":"R","\uA782":"R","\u24C8":"S","\uFF33":"S","\u1E9E":"S","\u015A":"S","\u1E64":"S","\u015C":"S","\u1E60":"S","\u0160":"S","\u1E66":"S","\u1E62":"S","\u1E68":"S","\u0218":"S","\u015E":"S","\u2C7E":"S","\uA7A8":"S","\uA784":"S","\u24C9":"T","\uFF34":"T","\u1E6A":"T","\u0164":"T","\u1E6C":"T","\u021A":"T","\u0162":"T","\u1E70":"T","\u1E6E":"T","\u0166":"T","\u01AC":"T","\u01AE":"T","\u023E":"T","\uA786":"T","\uA728":"TZ","\u24CA":"U","\uFF35":"U","\u00D9":"U","\u00DA":"U","\u00DB":"U","\u0168":"U","\u1E78":"U","\u016A":"U","\u1E7A":"U","\u016C":"U","\u00DC":"U","\u01DB":"U","\u01D7":"U","\u01D5":"U","\u01D9":"U","\u1EE6":"U","\u016E":"U","\u0170":"U","\u01D3":"U","\u0214":"U","\u0216":"U","\u01AF":"U","\u1EEA":"U","\u1EE8":"U","\u1EEE":"U","\u1EEC":"U","\u1EF0":"U","\u1EE4":"U","\u1E72":"U","\u0172":"U","\u1E76":"U","\u1E74":"U","\u0244":"U","\u24CB":"V","\uFF36":"V","\u1E7C":"V","\u1E7E":"V","\u01B2":"V","\uA75E":"V","\u0245":"V","\uA760":"VY","\u24CC":"W","\uFF37":"W","\u1E80":"W","\u1E82":"W","\u0174":"W","\u1E86":"W","\u1E84":"W","\u1E88":"W","\u2C72":"W","\u24CD":"X","\uFF38":"X","\u1E8A":"X","\u1E8C":"X","\u24CE":"Y","\uFF39":"Y","\u1EF2":"Y","\u00DD":"Y","\u0176":"Y","\u1EF8":"Y","\u0232":"Y","\u1E8E":"Y","\u0178":"Y","\u1EF6":"Y","\u1EF4":"Y","\u01B3":"Y","\u024E":"Y","\u1EFE":"Y","\u24CF":"Z","\uFF3A":"Z","\u0179":"Z","\u1E90":"Z","\u017B":"Z","\u017D":"Z","\u1E92":"Z","\u1E94":"Z","\u01B5":"Z","\u0224":"Z","\u2C7F":"Z","\u2C6B":"Z","\uA762":"Z","\u24D0":"a","\uFF41":"a","\u1E9A":"a","\u00E0":"a","\u00E1":"a","\u00E2":"a","\u1EA7":"a","\u1EA5":"a","\u1EAB":"a","\u1EA9":"a","\u00E3":"a","\u0101":"a","\u0103":"a","\u1EB1":"a","\u1EAF":"a","\u1EB5":"a","\u1EB3":"a","\u0227":"a","\u01E1":"a","\u00E4":"a","\u01DF":"a","\u1EA3":"a","\u00E5":"a","\u01FB":"a","\u01CE":"a","\u0201":"a","\u0203":"a","\u1EA1":"a","\u1EAD":"a","\u1EB7":"a","\u1E01":"a","\u0105":"a","\u2C65":"a","\u0250":"a","\uA733":"aa","\u00E6":"ae","\u01FD":"ae","\u01E3":"ae","\uA735":"ao","\uA737":"au","\uA739":"av","\uA73B":"av","\uA73D":"ay","\u24D1":"b","\uFF42":"b","\u1E03":"b","\u1E05":"b","\u1E07":"b","\u0180":"b","\u0183":"b","\u0253":"b","\u24D2":"c","\uFF43":"c","\u0107":"c","\u0109":"c","\u010B":"c","\u010D":"c","\u00E7":"c","\u1E09":"c","\u0188":"c","\u023C":"c","\uA73F":"c","\u2184":"c","\u24D3":"d","\uFF44":"d","\u1E0B":"d","\u010F":"d","\u1E0D":"d","\u1E11":"d","\u1E13":"d","\u1E0F":"d","\u0111":"d","\u018C":"d","\u0256":"d","\u0257":"d","\uA77A":"d","\u01F3":"dz","\u01C6":"dz","\u24D4":"e","\uFF45":"e","\u00E8":"e","\u00E9":"e","\u00EA":"e","\u1EC1":"e","\u1EBF":"e","\u1EC5":"e","\u1EC3":"e","\u1EBD":"e","\u0113":"e","\u1E15":"e","\u1E17":"e","\u0115":"e","\u0117":"e","\u00EB":"e","\u1EBB":"e","\u011B":"e","\u0205":"e","\u0207":"e","\u1EB9":"e","\u1EC7":"e","\u0229":"e","\u1E1D":"e","\u0119":"e","\u1E19":"e","\u1E1B":"e","\u0247":"e","\u025B":"e","\u01DD":"e","\u24D5":"f","\uFF46":"f","\u1E1F":"f","\u0192":"f","\uA77C":"f","\u24D6":"g","\uFF47":"g","\u01F5":"g","\u011D":"g","\u1E21":"g","\u011F":"g","\u0121":"g","\u01E7":"g","\u0123":"g","\u01E5":"g","\u0260":"g","\uA7A1":"g","\u1D79":"g","\uA77F":"g","\u24D7":"h","\uFF48":"h","\u0125":"h","\u1E23":"h","\u1E27":"h","\u021F":"h","\u1E25":"h","\u1E29":"h","\u1E2B":"h","\u1E96":"h","\u0127":"h","\u2C68":"h","\u2C76":"h","\u0265":"h","\u0195":"hv","\u24D8":"i","\uFF49":"i","\u00EC":"i","\u00ED":"i","\u00EE":"i","\u0129":"i","\u012B":"i","\u012D":"i","\u00EF":"i","\u1E2F":"i","\u1EC9":"i","\u01D0":"i","\u0209":"i","\u020B":"i","\u1ECB":"i","\u012F":"i","\u1E2D":"i","\u0268":"i","\u0131":"i","\u24D9":"j","\uFF4A":"j","\u0135":"j","\u01F0":"j","\u0249":"j","\u24DA":"k","\uFF4B":"k","\u1E31":"k","\u01E9":"k","\u1E33":"k","\u0137":"k","\u1E35":"k","\u0199":"k","\u2C6A":"k","\uA741":"k","\uA743":"k","\uA745":"k","\uA7A3":"k","\u24DB":"l","\uFF4C":"l","\u0140":"l","\u013A":"l","\u013E":"l","\u1E37":"l","\u1E39":"l","\u013C":"l","\u1E3D":"l","\u1E3B":"l","\u017F":"l","\u0142":"l","\u019A":"l","\u026B":"l","\u2C61":"l","\uA749":"l","\uA781":"l","\uA747":"l","\u01C9":"lj","\u24DC":"m","\uFF4D":"m","\u1E3F":"m","\u1E41":"m","\u1E43":"m","\u0271":"m","\u026F":"m","\u24DD":"n","\uFF4E":"n","\u01F9":"n","\u0144":"n","\u00F1":"n","\u1E45":"n","\u0148":"n","\u1E47":"n","\u0146":"n","\u1E4B":"n","\u1E49":"n","\u019E":"n","\u0272":"n","\u0149":"n","\uA791":"n","\uA7A5":"n","\u01CC":"nj","\u24DE":"o","\uFF4F":"o","\u00F2":"o","\u00F3":"o","\u00F4":"o","\u1ED3":"o","\u1ED1":"o","\u1ED7":"o","\u1ED5":"o","\u00F5":"o","\u1E4D":"o","\u022D":"o","\u1E4F":"o","\u014D":"o","\u1E51":"o","\u1E53":"o","\u014F":"o","\u022F":"o","\u0231":"o","\u00F6":"o","\u022B":"o","\u1ECF":"o","\u0151":"o","\u01D2":"o","\u020D":"o","\u020F":"o","\u01A1":"o","\u1EDD":"o","\u1EDB":"o","\u1EE1":"o","\u1EDF":"o","\u1EE3":"o","\u1ECD":"o","\u1ED9":"o","\u01EB":"o","\u01ED":"o","\u00F8":"o","\u01FF":"o","\u0254":"o","\uA74B":"o","\uA74D":"o","\u0275":"o","\u01A3":"oi","\u0223":"ou","\uA74F":"oo","\u24DF":"p","\uFF50":"p","\u1E55":"p","\u1E57":"p","\u01A5":"p","\u1D7D":"p","\uA751":"p","\uA753":"p","\uA755":"p","\u24E0":"q","\uFF51":"q","\u024B":"q","\uA757":"q","\uA759":"q","\u24E1":"r","\uFF52":"r","\u0155":"r","\u1E59":"r","\u0159":"r","\u0211":"r","\u0213":"r","\u1E5B":"r","\u1E5D":"r","\u0157":"r","\u1E5F":"r","\u024D":"r","\u027D":"r","\uA75B":"r","\uA7A7":"r","\uA783":"r","\u24E2":"s","\uFF53":"s","\u00DF":"s","\u015B":"s","\u1E65":"s","\u015D":"s","\u1E61":"s","\u0161":"s","\u1E67":"s","\u1E63":"s","\u1E69":"s","\u0219":"s","\u015F":"s","\u023F":"s","\uA7A9":"s","\uA785":"s","\u1E9B":"s","\u24E3":"t","\uFF54":"t","\u1E6B":"t","\u1E97":"t","\u0165":"t","\u1E6D":"t","\u021B":"t","\u0163":"t","\u1E71":"t","\u1E6F":"t","\u0167":"t","\u01AD":"t","\u0288":"t","\u2C66":"t","\uA787":"t","\uA729":"tz","\u24E4":"u","\uFF55":"u","\u00F9":"u","\u00FA":"u","\u00FB":"u","\u0169":"u","\u1E79":"u","\u016B":"u","\u1E7B":"u","\u016D":"u","\u00FC":"u","\u01DC":"u","\u01D8":"u","\u01D6":"u","\u01DA":"u","\u1EE7":"u","\u016F":"u","\u0171":"u","\u01D4":"u","\u0215":"u","\u0217":"u","\u01B0":"u","\u1EEB":"u","\u1EE9":"u","\u1EEF":"u","\u1EED":"u","\u1EF1":"u","\u1EE5":"u","\u1E73":"u","\u0173":"u","\u1E77":"u","\u1E75":"u","\u0289":"u","\u24E5":"v","\uFF56":"v","\u1E7D":"v","\u1E7F":"v","\u028B":"v","\uA75F":"v","\u028C":"v","\uA761":"vy","\u24E6":"w","\uFF57":"w","\u1E81":"w","\u1E83":"w","\u0175":"w","\u1E87":"w","\u1E85":"w","\u1E98":"w","\u1E89":"w","\u2C73":"w","\u24E7":"x","\uFF58":"x","\u1E8B":"x","\u1E8D":"x","\u24E8":"y","\uFF59":"y","\u1EF3":"y","\u00FD":"y","\u0177":"y","\u1EF9":"y","\u0233":"y","\u1E8F":"y","\u00FF":"y","\u1EF7":"y","\u1E99":"y","\u1EF5":"y","\u01B4":"y","\u024F":"y","\u1EFF":"y","\u24E9":"z","\uFF5A":"z","\u017A":"z","\u1E91":"z","\u017C":"z","\u017E":"z","\u1E93":"z","\u1E95":"z","\u01B6":"z","\u0225":"z","\u0240":"z","\u2C6C":"z","\uA763":"z","\u0386":"\u0391","\u0388":"\u0395","\u0389":"\u0397","\u038A":"\u0399","\u03AA":"\u0399","\u038C":"\u039F","\u038E":"\u03A5","\u03AB":"\u03A5","\u038F":"\u03A9","\u03AC":"\u03B1","\u03AD":"\u03B5","\u03AE":"\u03B7","\u03AF":"\u03B9","\u03CA":"\u03B9","\u0390":"\u03B9","\u03CC":"\u03BF","\u03CD":"\u03C5","\u03CB":"\u03C5","\u03B0":"\u03C5","\u03C9":"\u03C9","\u03C2":"\u03C3"};
  9204  
  9205      $document = $(document);
  9206  
  9207      nextUid=(function() { var counter=1; return function() { return counter++; }; }());
  9208  
  9209  
  9210      function reinsertElement(element) {
  9211          var placeholder = $(document.createTextNode(''));
  9212  
  9213          element.before(placeholder);
  9214          placeholder.before(element);
  9215          placeholder.remove();
  9216      }
  9217  
  9218      function stripDiacritics(str) {
  9219          // Used 'uni range + named function' from http://jsperf.com/diacritics/18
  9220          function match(a) {
  9221              return DIACRITICS[a] || a;
  9222          }
  9223  
  9224          return str.replace(/[^\u0000-\u007E]/g, match);
  9225      }
  9226  
  9227      function indexOf(value, array) {
  9228          var i = 0, l = array.length;
  9229          for (; i < l; i = i + 1) {
  9230              if (equal(value, array[i])) return i;
  9231          }
  9232          return -1;
  9233      }
  9234  
  9235      function measureScrollbar () {
  9236          var $template = $( MEASURE_SCROLLBAR_TEMPLATE );
  9237          $template.appendTo('body');
  9238  
  9239          var dim = {
  9240              width: $template.width() - $template[0].clientWidth,
  9241              height: $template.height() - $template[0].clientHeight
  9242          };
  9243          $template.remove();
  9244  
  9245          return dim;
  9246      }
  9247  
  9248      /**
  9249       * Compares equality of a and b
  9250       * @param a
  9251       * @param b
  9252       */
  9253      function equal(a, b) {
  9254          if (a === b) return true;
  9255          if (a === undefined || b === undefined) return false;
  9256          if (a === null || b === null) return false;
  9257          // Check whether 'a' or 'b' is a string (primitive or object).
  9258          // The concatenation of an empty string (+'') converts its argument to a string's primitive.
  9259          if (a.constructor === String) return a+'' === b+''; // a+'' - in case 'a' is a String object
  9260          if (b.constructor === String) return b+'' === a+''; // b+'' - in case 'b' is a String object
  9261          return false;
  9262      }
  9263  
  9264      /**
  9265       * Splits the string into an array of values, trimming each value. An empty array is returned for nulls or empty
  9266       * strings
  9267       * @param string
  9268       * @param separator
  9269       */
  9270      function splitVal(string, separator) {
  9271          var val, i, l;
  9272          if (string === null || string.length < 1) return [];
  9273          val = string.split(separator);
  9274          for (i = 0, l = val.length; i < l; i = i + 1) val[i] = $.trim(val[i]);
  9275          return val;
  9276      }
  9277  
  9278      function getSideBorderPadding(element) {
  9279          return element.outerWidth(false) - element.width();
  9280      }
  9281  
  9282      function installKeyUpChangeEvent(element) {
  9283          var key="keyup-change-value";
  9284          element.on("keydown", function () {
  9285              if ($.data(element, key) === undefined) {
  9286                  $.data(element, key, element.val());
  9287              }
  9288          });
  9289          element.on("keyup", function () {
  9290              var val= $.data(element, key);
  9291              if (val !== undefined && element.val() !== val) {
  9292                  $.removeData(element, key);
  9293                  element.trigger("keyup-change");
  9294              }
  9295          });
  9296      }
  9297  
  9298  
  9299      /**
  9300       * filters mouse events so an event is fired only if the mouse moved.
  9301       *
  9302       * filters out mouse events that occur when mouse is stationary but
  9303       * the elements under the pointer are scrolled.
  9304       */
  9305      function installFilteredMouseMove(element) {
  9306          element.on("mousemove", function (e) {
  9307              var lastpos = lastMousePosition;
  9308              if (lastpos === undefined || lastpos.x !== e.pageX || lastpos.y !== e.pageY) {
  9309                  $(e.target).trigger("mousemove-filtered", e);
  9310              }
  9311          });
  9312      }
  9313  
  9314      /**
  9315       * Debounces a function. Returns a function that calls the original fn function only if no invocations have been made
  9316       * within the last quietMillis milliseconds.
  9317       *
  9318       * @param quietMillis number of milliseconds to wait before invoking fn
  9319       * @param fn function to be debounced
  9320       * @param ctx object to be used as this reference within fn
  9321       * @return debounced version of fn
  9322       */
  9323      function debounce(quietMillis, fn, ctx) {
  9324          ctx = ctx || undefined;
  9325          var timeout;
  9326          return function () {
  9327              var args = arguments;
  9328              window.clearTimeout(timeout);
  9329              timeout = window.setTimeout(function() {
  9330                  fn.apply(ctx, args);
  9331              }, quietMillis);
  9332          };
  9333      }
  9334  
  9335      function installDebouncedScroll(threshold, element) {
  9336          var notify = debounce(threshold, function (e) { element.trigger("scroll-debounced", e);});
  9337          element.on("scroll", function (e) {
  9338              if (indexOf(e.target, element.get()) >= 0) notify(e);
  9339          });
  9340      }
  9341  
  9342      function focus($el) {
  9343          if ($el[0] === document.activeElement) return;
  9344  
  9345          /* set the focus in a 0 timeout - that way the focus is set after the processing
  9346              of the current event has finished - which seems like the only reliable way
  9347              to set focus */
  9348          window.setTimeout(function() {
  9349              var el=$el[0], pos=$el.val().length, range;
  9350  
  9351              $el.focus();
  9352  
  9353              /* make sure el received focus so we do not error out when trying to manipulate the caret.
  9354                  sometimes modals or others listeners may steal it after its set */
  9355              var isVisible = (el.offsetWidth > 0 || el.offsetHeight > 0);
  9356              if (isVisible && el === document.activeElement) {
  9357  
  9358                  /* after the focus is set move the caret to the end, necessary when we val()
  9359                      just before setting focus */
  9360                  if(el.setSelectionRange)
  9361                  {
  9362                      el.setSelectionRange(pos, pos);
  9363                  }
  9364                  else if (el.createTextRange) {
  9365                      range = el.createTextRange();
  9366                      range.collapse(false);
  9367                      range.select();
  9368                  }
  9369              }
  9370          }, 0);
  9371      }
  9372  
  9373      function getCursorInfo(el) {
  9374          el = $(el)[0];
  9375          var offset = 0;
  9376          var length = 0;
  9377          if ('selectionStart' in el) {
  9378              offset = el.selectionStart;
  9379              length = el.selectionEnd - offset;
  9380          } else if ('selection' in document) {
  9381              el.focus();
  9382              var sel = document.selection.createRange();
  9383              length = document.selection.createRange().text.length;
  9384              sel.moveStart('character', -el.value.length);
  9385              offset = sel.text.length - length;
  9386          }
  9387          return { offset: offset, length: length };
  9388      }
  9389  
  9390      function killEvent(event) {
  9391          event.preventDefault();
  9392          event.stopPropagation();
  9393      }
  9394      function killEventImmediately(event) {
  9395          event.preventDefault();
  9396          event.stopImmediatePropagation();
  9397      }
  9398  
  9399      function measureTextWidth(e) {
  9400          if (!sizer){
  9401              var style = e[0].currentStyle || window.getComputedStyle(e[0], null);
  9402              sizer = $(document.createElement("div")).css({
  9403                  position: "absolute",
  9404                  left: "-10000px",
  9405                  top: "-10000px",
  9406                  display: "none",
  9407                  fontSize: style.fontSize,
  9408                  fontFamily: style.fontFamily,
  9409                  fontStyle: style.fontStyle,
  9410                  fontWeight: style.fontWeight,
  9411                  letterSpacing: style.letterSpacing,
  9412                  textTransform: style.textTransform,
  9413                  whiteSpace: "nowrap"
  9414              });
  9415              sizer.attr("class","select2-sizer");
  9416              $("body").append(sizer);
  9417          }
  9418          sizer.text(e.val());
  9419          return sizer.width();
  9420      }
  9421  
  9422      function syncCssClasses(dest, src, adapter) {
  9423          var classes, replacements = [], adapted;
  9424  
  9425          classes = $.trim(dest.attr("class"));
  9426  
  9427          if (classes) {
  9428              classes = '' + classes; // for IE which returns object
  9429  
  9430              $(classes.split(/\s+/)).each2(function() {
  9431                  if (this.indexOf("select2-") === 0) {
  9432                      replacements.push(this);
  9433                  }
  9434              });
  9435          }
  9436  
  9437          classes = $.trim(src.attr("class"));
  9438  
  9439          if (classes) {
  9440              classes = '' + classes; // for IE which returns object
  9441  
  9442              $(classes.split(/\s+/)).each2(function() {
  9443                  if (this.indexOf("select2-") !== 0) {
  9444                      adapted = adapter(this);
  9445  
  9446                      if (adapted) {
  9447                          replacements.push(adapted);
  9448                      }
  9449                  }
  9450              });
  9451          }
  9452  
  9453          dest.attr("class", replacements.join(" "));
  9454      }
  9455  
  9456  
  9457      function markMatch(text, term, markup, escapeMarkup) {
  9458          var match=stripDiacritics(text.toUpperCase()).indexOf(stripDiacritics(term.toUpperCase())),
  9459              tl=term.length;
  9460  
  9461          if (match<0) {
  9462              markup.push(escapeMarkup(text));
  9463              return;
  9464          }
  9465  
  9466          markup.push(escapeMarkup(text.substring(0, match)));
  9467          markup.push("<span class='select2-match'>");
  9468          markup.push(escapeMarkup(text.substring(match, match + tl)));
  9469          markup.push("</span>");
  9470          markup.push(escapeMarkup(text.substring(match + tl, text.length)));
  9471      }
  9472  
  9473      function defaultEscapeMarkup(markup) {
  9474          var replace_map = {
  9475              '\\': '&#92;',
  9476              '&': '&amp;',
  9477              '<': '&lt;',
  9478              '>': '&gt;',
  9479              '"': '&quot;',
  9480              "'": '&#39;',
  9481              "/": '&#47;'
  9482          };
  9483  
  9484          return String(markup).replace(/[&<>"'\/\\]/g, function (match) {
  9485              return replace_map[match];
  9486          });
  9487      }
  9488  
  9489      /**
  9490       * Produces an ajax-based query function
  9491       *
  9492       * @param options object containing configuration parameters
  9493       * @param options.params parameter map for the transport ajax call, can contain such options as cache, jsonpCallback, etc. see $.ajax
  9494       * @param options.transport function that will be used to execute the ajax request. must be compatible with parameters supported by $.ajax
  9495       * @param options.url url for the data
  9496       * @param options.data a function(searchTerm, pageNumber, context) that should return an object containing query string parameters for the above url.
  9497       * @param options.dataType request data type: ajax, jsonp, other datatypes supported by jQuery's $.ajax function or the transport function if specified
  9498       * @param options.quietMillis (optional) milliseconds to wait before making the ajaxRequest, helps debounce the ajax function if invoked too often
  9499       * @param options.results a function(remoteData, pageNumber, query) that converts data returned form the remote request to the format expected by Select2.
  9500       *      The expected format is an object containing the following keys:
  9501       *      results array of objects that will be used as choices
  9502       *      more (optional) boolean indicating whether there are more results available
  9503       *      Example: {results:[{id:1, text:'Red'},{id:2, text:'Blue'}], more:true}
  9504       */
  9505      function ajax(options) {
  9506          var timeout, // current scheduled but not yet executed request
  9507              handler = null,
  9508              quietMillis = options.quietMillis || 100,
  9509              ajaxUrl = options.url,
  9510              self = this;
  9511  
  9512          return function (query) {
  9513              window.clearTimeout(timeout);
  9514              timeout = window.setTimeout(function () {
  9515                  var data = options.data, // ajax data function
  9516                      url = ajaxUrl, // ajax url string or function
  9517                      transport = options.transport || $.fn.select2.ajaxDefaults.transport,
  9518                      // deprecated - to be removed in 4.0  - use params instead
  9519                      deprecated = {
  9520                          type: options.type || 'GET', // set type of request (GET or POST)
  9521                          cache: options.cache || false,
  9522                          jsonpCallback: options.jsonpCallback||undefined,
  9523                          dataType: options.dataType||"json"
  9524                      },
  9525                      params = $.extend({}, $.fn.select2.ajaxDefaults.params, deprecated);
  9526  
  9527                  data = data ? data.call(self, query.term, query.page, query.context) : null;
  9528                  url = (typeof url === 'function') ? url.call(self, query.term, query.page, query.context) : url;
  9529  
  9530                  if (handler && typeof handler.abort === "function") { handler.abort(); }
  9531  
  9532                  if (options.params) {
  9533                      if ($.isFunction(options.params)) {
  9534                          $.extend(params, options.params.call(self));
  9535                      } else {
  9536                          $.extend(params, options.params);
  9537                      }
  9538                  }
  9539  
  9540                  $.extend(params, {
  9541                      url: url,
  9542                      dataType: options.dataType,
  9543                      data: data,
  9544                      success: function (data) {
  9545                          // TODO - replace query.page with query so users have access to term, page, etc.
  9546                          // added query as third paramter to keep backwards compatibility
  9547                          var results = options.results(data, query.page, query);
  9548                          query.callback(results);
  9549                      },
  9550                      error: function(jqXHR, textStatus, errorThrown){
  9551                          var results = {
  9552                              hasError: true,
  9553                              jqXHR: jqXHR,
  9554                              textStatus: textStatus,
  9555                              errorThrown: errorThrown,
  9556                          };
  9557  
  9558                          query.callback(results);
  9559                      }
  9560                  });
  9561                  handler = transport.call(self, params);
  9562              }, quietMillis);
  9563          };
  9564      }
  9565  
  9566      /**
  9567       * Produces a query function that works with a local array
  9568       *
  9569       * @param options object containing configuration parameters. The options parameter can either be an array or an
  9570       * object.
  9571       *
  9572       * If the array form is used it is assumed that it contains objects with 'id' and 'text' keys.
  9573       *
  9574       * If the object form is used it is assumed that it contains 'data' and 'text' keys. The 'data' key should contain
  9575       * an array of objects that will be used as choices. These objects must contain at least an 'id' key. The 'text'
  9576       * key can either be a String in which case it is expected that each element in the 'data' array has a key with the
  9577       * value of 'text' which will be used to match choices. Alternatively, text can be a function(item) that can extract
  9578       * the text.
  9579       */
  9580      function local(options) {
  9581          var data = options, // data elements
  9582              dataText,
  9583              tmp,
  9584              text = function (item) { return ""+item.text; }; // function used to retrieve the text portion of a data item that is matched against the search
  9585  
  9586           if ($.isArray(data)) {
  9587              tmp = data;
  9588              data = { results: tmp };
  9589          }
  9590  
  9591           if ($.isFunction(data) === false) {
  9592              tmp = data;
  9593              data = function() { return tmp; };
  9594          }
  9595  
  9596          var dataItem = data();
  9597          if (dataItem.text) {
  9598              text = dataItem.text;
  9599              // if text is not a function we assume it to be a key name
  9600              if (!$.isFunction(text)) {
  9601                  dataText = dataItem.text; // we need to store this in a separate variable because in the next step data gets reset and data.text is no longer available
  9602                  text = function (item) { return item[dataText]; };
  9603              }
  9604          }
  9605  
  9606          return function (query) {
  9607              var t = query.term, filtered = { results: [] }, process;
  9608              if (t === "") {
  9609                  query.callback(data());
  9610                  return;
  9611              }
  9612  
  9613              process = function(datum, collection) {
  9614                  var group, attr;
  9615                  datum = datum[0];
  9616                  if (datum.children) {
  9617                      group = {};
  9618                      for (attr in datum) {
  9619                          if (datum.hasOwnProperty(attr)) group[attr]=datum[attr];
  9620                      }
  9621                      group.children=[];
  9622                      $(datum.children).each2(function(i, childDatum) { process(childDatum, group.children); });
  9623                      if (group.children.length || query.matcher(t, text(group), datum)) {
  9624                          collection.push(group);
  9625                      }
  9626                  } else {
  9627                      if (query.matcher(t, text(datum), datum)) {
  9628                          collection.push(datum);
  9629                      }
  9630                  }
  9631              };
  9632  
  9633              $(data().results).each2(function(i, datum) { process(datum, filtered.results); });
  9634              query.callback(filtered);
  9635          };
  9636      }
  9637  
  9638      // TODO javadoc
  9639      function tags(data) {
  9640          var isFunc = $.isFunction(data);
  9641          return function (query) {
  9642              var t = query.term, filtered = {results: []};
  9643              var result = isFunc ? data(query) : data;
  9644              if ($.isArray(result)) {
  9645                  $(result).each(function () {
  9646                      var isObject = this.text !== undefined,
  9647                          text = isObject ? this.text : this;
  9648                      if (t === "" || query.matcher(t, text)) {
  9649                          filtered.results.push(isObject ? this : {id: this, text: this});
  9650                      }
  9651                  });
  9652                  query.callback(filtered);
  9653              }
  9654          };
  9655      }
  9656  
  9657      /**
  9658       * Checks if the formatter function should be used.
  9659       *
  9660       * Throws an error if it is not a function. Returns true if it should be used,
  9661       * false if no formatting should be performed.
  9662       *
  9663       * @param formatter
  9664       */
  9665      function checkFormatter(formatter, formatterName) {
  9666          if ($.isFunction(formatter)) return true;
  9667          if (!formatter) return false;
  9668          if (typeof(formatter) === 'string') return true;
  9669          throw new Error(formatterName +" must be a string, function, or falsy value");
  9670      }
  9671  
  9672    /**
  9673     * Returns a given value
  9674     * If given a function, returns its output
  9675     *
  9676     * @param val string|function
  9677     * @param context value of "this" to be passed to function
  9678     * @returns {*}
  9679     */
  9680      function evaluate(val, context) {
  9681          if ($.isFunction(val)) {
  9682              var args = Array.prototype.slice.call(arguments, 2);
  9683              return val.apply(context, args);
  9684          }
  9685          return val;
  9686      }
  9687  
  9688      function countResults(results) {
  9689          var count = 0;
  9690          $.each(results, function(i, item) {
  9691              if (item.children) {
  9692                  count += countResults(item.children);
  9693              } else {
  9694                  count++;
  9695              }
  9696          });
  9697          return count;
  9698      }
  9699  
  9700      /**
  9701       * Default tokenizer. This function uses breaks the input on substring match of any string from the
  9702       * opts.tokenSeparators array and uses opts.createSearchChoice to create the choice object. Both of those
  9703       * two options have to be defined in order for the tokenizer to work.
  9704       *
  9705       * @param input text user has typed so far or pasted into the search field
  9706       * @param selection currently selected choices
  9707       * @param selectCallback function(choice) callback tho add the choice to selection
  9708       * @param opts select2's opts
  9709       * @return undefined/null to leave the current input unchanged, or a string to change the input to the returned value
  9710       */
  9711      function defaultTokenizer(input, selection, selectCallback, opts) {
  9712          var original = input, // store the original so we can compare and know if we need to tell the search to update its text
  9713              dupe = false, // check for whether a token we extracted represents a duplicate selected choice
  9714              token, // token
  9715              index, // position at which the separator was found
  9716              i, l, // looping variables
  9717              separator; // the matched separator
  9718  
  9719          if (!opts.createSearchChoice || !opts.tokenSeparators || opts.tokenSeparators.length < 1) return undefined;
  9720  
  9721          while (true) {
  9722              index = -1;
  9723  
  9724              for (i = 0, l = opts.tokenSeparators.length; i < l; i++) {
  9725                  separator = opts.tokenSeparators[i];
  9726                  index = input.indexOf(separator);
  9727                  if (index >= 0) break;
  9728              }
  9729  
  9730              if (index < 0) break; // did not find any token separator in the input string, bail
  9731  
  9732              token = input.substring(0, index);
  9733              input = input.substring(index + separator.length);
  9734  
  9735              if (token.length > 0) {
  9736                  token = opts.createSearchChoice.call(this, token, selection);
  9737                  if (token !== undefined && token !== null && opts.id(token) !== undefined && opts.id(token) !== null) {
  9738                      dupe = false;
  9739                      for (i = 0, l = selection.length; i < l; i++) {
  9740                          if (equal(opts.id(token), opts.id(selection[i]))) {
  9741                              dupe = true; break;
  9742                          }
  9743                      }
  9744  
  9745                      if (!dupe) selectCallback(token);
  9746                  }
  9747              }
  9748          }
  9749  
  9750          if (original!==input) return input;
  9751      }
  9752  
  9753      function cleanupJQueryElements() {
  9754          var self = this;
  9755  
  9756          $.each(arguments, function (i, element) {
  9757              self[element].remove();
  9758              self[element] = null;
  9759          });
  9760      }
  9761  
  9762      /**
  9763       * Creates a new class
  9764       *
  9765       * @param superClass
  9766       * @param methods
  9767       */
  9768      function clazz(SuperClass, methods) {
  9769          var constructor = function () {};
  9770          constructor.prototype = new SuperClass;
  9771          constructor.prototype.constructor = constructor;
  9772          constructor.prototype.parent = SuperClass.prototype;
  9773          constructor.prototype = $.extend(constructor.prototype, methods);
  9774          return constructor;
  9775      }
  9776  
  9777      AbstractSelect2 = clazz(Object, {
  9778  
  9779          // abstract
  9780          bind: function (func) {
  9781              var self = this;
  9782              return function () {
  9783                  func.apply(self, arguments);
  9784              };
  9785          },
  9786  
  9787          // abstract
  9788          init: function (opts) {
  9789              var results, search, resultsSelector = ".select2-results";
  9790  
  9791              // prepare options
  9792              this.opts = opts = this.prepareOpts(opts);
  9793  
  9794              this.id=opts.id;
  9795  
  9796              // destroy if called on an existing component
  9797              if (opts.element.data("select2") !== undefined &&
  9798                  opts.element.data("select2") !== null) {
  9799                  opts.element.data("select2").destroy();
  9800              }
  9801  
  9802              this.container = this.createContainer();
  9803  
  9804              this.liveRegion = $("<span>", {
  9805                      role: "status",
  9806                      "aria-live": "polite"
  9807                  })
  9808                  .addClass("select2-hidden-accessible")
  9809                  .appendTo(document.body);
  9810  
  9811              this.containerId="s2id_"+(opts.element.attr("id") || "autogen"+nextUid());
  9812              this.containerEventName= this.containerId
  9813                  .replace(/([.])/g, '_')
  9814                  .replace(/([;&,\-\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1');
  9815              this.container.attr("id", this.containerId);
  9816  
  9817              this.container.attr("title", opts.element.attr("title"));
  9818  
  9819              this.body = $("body");
  9820  
  9821              syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);
  9822  
  9823              this.container.attr("style", opts.element.attr("style"));
  9824              this.container.css(evaluate(opts.containerCss, this.opts.element));
  9825              this.container.addClass(evaluate(opts.containerCssClass, this.opts.element));
  9826  
  9827              this.elementTabIndex = this.opts.element.attr("tabindex");
  9828  
  9829              // swap container for the element
  9830              this.opts.element
  9831                  .data("select2", this)
  9832                  .attr("tabindex", "-1")
  9833                  .before(this.container)
  9834                  .on("click.select2", killEvent); // do not leak click events
  9835  
  9836              this.container.data("select2", this);
  9837  
  9838              this.dropdown = this.container.find(".select2-drop");
  9839  
  9840              syncCssClasses(this.dropdown, this.opts.element, this.opts.adaptDropdownCssClass);
  9841  
  9842              this.dropdown.addClass(evaluate(opts.dropdownCssClass, this.opts.element));
  9843              this.dropdown.data("select2", this);
  9844              this.dropdown.on("click", killEvent);
  9845  
  9846              this.results = results = this.container.find(resultsSelector);
  9847              this.search = search = this.container.find("input.select2-input");
  9848  
  9849              this.queryCount = 0;
  9850              this.resultsPage = 0;
  9851              this.context = null;
  9852  
  9853              // initialize the container
  9854              this.initContainer();
  9855  
  9856              this.container.on("click", killEvent);
  9857  
  9858              installFilteredMouseMove(this.results);
  9859  
  9860              this.dropdown.on("mousemove-filtered", resultsSelector, this.bind(this.highlightUnderEvent));
  9861              this.dropdown.on("touchstart touchmove touchend", resultsSelector, this.bind(function (event) {
  9862                  this._touchEvent = true;
  9863                  this.highlightUnderEvent(event);
  9864              }));
  9865              this.dropdown.on("touchmove", resultsSelector, this.bind(this.touchMoved));
  9866              this.dropdown.on("touchstart touchend", resultsSelector, this.bind(this.clearTouchMoved));
  9867  
  9868              // Waiting for a click event on touch devices to select option and hide dropdown
  9869              // otherwise click will be triggered on an underlying element
  9870              this.dropdown.on('click', this.bind(function (event) {
  9871                  if (this._touchEvent) {
  9872                      this._touchEvent = false;
  9873                      this.selectHighlighted();
  9874                  }
  9875              }));
  9876  
  9877              installDebouncedScroll(80, this.results);
  9878              this.dropdown.on("scroll-debounced", resultsSelector, this.bind(this.loadMoreIfNeeded));
  9879  
  9880              // do not propagate change event from the search field out of the component
  9881              $(this.container).on("change", ".select2-input", function(e) {e.stopPropagation();});
  9882              $(this.dropdown).on("change", ".select2-input", function(e) {e.stopPropagation();});
  9883  
  9884              // if jquery.mousewheel plugin is installed we can prevent out-of-bounds scrolling of results via mousewheel
  9885              if ($.fn.mousewheel) {
  9886                  results.mousewheel(function (e, delta, deltaX, deltaY) {
  9887                      var top = results.scrollTop();
  9888                      if (deltaY > 0 && top - deltaY <= 0) {
  9889                          results.scrollTop(0);
  9890                          killEvent(e);
  9891                      } else if (deltaY < 0 && results.get(0).scrollHeight - results.scrollTop() + deltaY <= results.height()) {
  9892                          results.scrollTop(results.get(0).scrollHeight - results.height());
  9893                          killEvent(e);
  9894                      }
  9895                  });
  9896              }
  9897  
  9898              installKeyUpChangeEvent(search);
  9899              search.on("keyup-change input paste", this.bind(this.updateResults));
  9900              search.on("focus", function () { search.addClass("select2-focused"); });
  9901              search.on("blur", function () { search.removeClass("select2-focused");});
  9902  
  9903              this.dropdown.on("mouseup", resultsSelector, this.bind(function (e) {
  9904                  if ($(e.target).closest(".select2-result-selectable").length > 0) {
  9905                      this.highlightUnderEvent(e);
  9906                      this.selectHighlighted(e);
  9907                  }
  9908              }));
  9909  
  9910              // trap all mouse events from leaving the dropdown. sometimes there may be a modal that is listening
  9911              // for mouse events outside of itself so it can close itself. since the dropdown is now outside the select2's
  9912              // dom it will trigger the popup close, which is not what we want
  9913              // focusin can cause focus wars between modals and select2 since the dropdown is outside the modal.
  9914              this.dropdown.on("click mouseup mousedown touchstart touchend focusin", function (e) { e.stopPropagation(); });
  9915  
  9916              this.nextSearchTerm = undefined;
  9917  
  9918              if ($.isFunction(this.opts.initSelection)) {
  9919                  // initialize selection based on the current value of the source element
  9920                  this.initSelection();
  9921  
  9922                  // if the user has provided a function that can set selection based on the value of the source element
  9923                  // we monitor the change event on the element and trigger it, allowing for two way synchronization
  9924                  this.monitorSource();
  9925              }
  9926  
  9927              if (opts.maximumInputLength !== null) {
  9928                  this.search.attr("maxlength", opts.maximumInputLength);
  9929              }
  9930  
  9931              var disabled = opts.element.prop("disabled");
  9932              if (disabled === undefined) disabled = false;
  9933              this.enable(!disabled);
  9934  
  9935              var readonly = opts.element.prop("readonly");
  9936              if (readonly === undefined) readonly = false;
  9937              this.readonly(readonly);
  9938  
  9939              // Calculate size of scrollbar
  9940              scrollBarDimensions = scrollBarDimensions || measureScrollbar();
  9941  
  9942              this.autofocus = opts.element.prop("autofocus");
  9943              opts.element.prop("autofocus", false);
  9944              if (this.autofocus) this.focus();
  9945  
  9946              this.search.attr("placeholder", opts.searchInputPlaceholder);
  9947          },
  9948  
  9949          // abstract
  9950          destroy: function () {
  9951              var element=this.opts.element, select2 = element.data("select2"), self = this;
  9952  
  9953              this.close();
  9954  
  9955              if (element.length && element[0].detachEvent) {
  9956                  element.each(function () {
  9957                      this.detachEvent("onpropertychange", self._sync);
  9958                  });
  9959              }
  9960              if (this.propertyObserver) {
  9961                  this.propertyObserver.disconnect();
  9962                  this.propertyObserver = null;
  9963              }
  9964              this._sync = null;
  9965  
  9966              if (select2 !== undefined) {
  9967                  select2.container.remove();
  9968                  select2.liveRegion.remove();
  9969                  select2.dropdown.remove();
  9970                  element
  9971                      .removeClass("select2-offscreen")
  9972                      .removeData("select2")
  9973                      .off(".select2")
  9974                      .prop("autofocus", this.autofocus || false);
  9975                  if (this.elementTabIndex) {
  9976                      element.attr({tabindex: this.elementTabIndex});
  9977                  } else {
  9978                      element.removeAttr("tabindex");
  9979                  }
  9980                  element.show();
  9981              }
  9982  
  9983              cleanupJQueryElements.call(this,
  9984                  "container",
  9985                  "liveRegion",
  9986                  "dropdown",
  9987                  "results",
  9988                  "search"
  9989              );
  9990          },
  9991  
  9992          // abstract
  9993          optionToData: function(element) {
  9994              if (element.is("option")) {
  9995                  return {
  9996                      id:element.prop("value"),
  9997                      text:element.text(),
  9998                      element: element.get(),
  9999                      css: element.attr("class"),
 10000                      disabled: element.prop("disabled"),
 10001                      locked: equal(element.attr("locked"), "locked") || equal(element.data("locked"), true)
 10002                  };
 10003              } else if (element.is("optgroup")) {
 10004                  return {
 10005                      text:element.attr("label"),
 10006                      children:[],
 10007                      element: element.get(),
 10008                      css: element.attr("class")
 10009                  };
 10010              }
 10011          },
 10012  
 10013          // abstract
 10014          prepareOpts: function (opts) {
 10015              var element, select, idKey, ajaxUrl, self = this;
 10016  
 10017              element = opts.element;
 10018  
 10019              if (element.get(0).tagName.toLowerCase() === "select") {
 10020                  this.select = select = opts.element;
 10021              }
 10022  
 10023              if (select) {
 10024                  // these options are not allowed when attached to a select because they are picked up off the element itself
 10025                  $.each(["id", "multiple", "ajax", "query", "createSearchChoice", "initSelection", "data", "tags"], function () {
 10026                      if (this in opts) {
 10027                          throw new Error("Option '" + this + "' is not allowed for Select2 when attached to a <select> element.");
 10028                      }
 10029                  });
 10030              }
 10031  
 10032              opts = $.extend({}, {
 10033                  populateResults: function(container, results, query) {
 10034                      var populate, id=this.opts.id, liveRegion=this.liveRegion;
 10035  
 10036                      populate=function(results, container, depth) {
 10037  
 10038                          var i, l, result, selectable, disabled, compound, node, label, innerContainer, formatted;
 10039  
 10040                          results = opts.sortResults(results, container, query);
 10041  
 10042                          // collect the created nodes for bulk append
 10043                          var nodes = [];
 10044                          for (i = 0, l = results.length; i < l; i = i + 1) {
 10045  
 10046                              result=results[i];
 10047  
 10048                              disabled = (result.disabled === true);
 10049                              selectable = (!disabled) && (id(result) !== undefined);
 10050  
 10051                              compound=result.children && result.children.length > 0;
 10052  
 10053                              node=$("<li></li>");
 10054                              node.addClass("select2-results-dept-"+depth);
 10055                              node.addClass("select2-result");
 10056                              node.addClass(selectable ? "select2-result-selectable" : "select2-result-unselectable");
 10057                              if (disabled) { node.addClass("select2-disabled"); }
 10058                              if (compound) { node.addClass("select2-result-with-children"); }
 10059                              node.addClass(self.opts.formatResultCssClass(result));
 10060                              node.attr("role", "presentation");
 10061  
 10062                              label=$(document.createElement("div"));
 10063                              label.addClass("select2-result-label");
 10064                              label.attr("id", "select2-result-label-" + nextUid());
 10065                              label.attr("role", "option");
 10066  
 10067                              formatted=opts.formatResult(result, label, query, self.opts.escapeMarkup);
 10068                              if (formatted!==undefined) {
 10069                                  label.html(formatted);
 10070                                  node.append(label);
 10071                              }
 10072  
 10073  
 10074                              if (compound) {
 10075  
 10076                                  innerContainer=$("<ul></ul>");
 10077                                  innerContainer.addClass("select2-result-sub");
 10078                                  populate(result.children, innerContainer, depth+1);
 10079                                  node.append(innerContainer);
 10080                              }
 10081  
 10082                              node.data("select2-data", result);
 10083                              nodes.push(node[0]);
 10084                          }
 10085  
 10086                          // bulk append the created nodes
 10087                          container.append(nodes);
 10088                          liveRegion.text(opts.formatMatches(results.length));
 10089                      };
 10090  
 10091                      populate(results, container, 0);
 10092                  }
 10093              }, $.fn.select2.defaults, opts);
 10094  
 10095              if (typeof(opts.id) !== "function") {
 10096                  idKey = opts.id;
 10097                  opts.id = function (e) { return e[idKey]; };
 10098              }
 10099  
 10100              if ($.isArray(opts.element.data("select2Tags"))) {
 10101                  if ("tags" in opts) {
 10102                      throw "tags specified as both an attribute 'data-select2-tags' and in options of Select2 " + opts.element.attr("id");
 10103                  }
 10104                  opts.tags=opts.element.data("select2Tags");
 10105              }
 10106  
 10107              if (select) {
 10108                  opts.query = this.bind(function (query) {
 10109                      var data = { results: [], more: false },
 10110                          term = query.term,
 10111                          children, placeholderOption, process;
 10112  
 10113                      process=function(element, collection) {
 10114                          var group;
 10115                          if (element.is("option")) {
 10116                              if (query.matcher(term, element.text(), element)) {
 10117                                  collection.push(self.optionToData(element));
 10118                              }
 10119                          } else if (element.is("optgroup")) {
 10120                              group=self.optionToData(element);
 10121                              element.children().each2(function(i, elm) { process(elm, group.children); });
 10122                              if (group.children.length>0) {
 10123                                  collection.push(group);
 10124                              }
 10125                          }
 10126                      };
 10127  
 10128                      children=element.children();
 10129  
 10130                      // ignore the placeholder option if there is one
 10131                      if (this.getPlaceholder() !== undefined && children.length > 0) {
 10132                          placeholderOption = this.getPlaceholderOption();
 10133                          if (placeholderOption) {
 10134                              children=children.not(placeholderOption);
 10135                          }
 10136                      }
 10137  
 10138                      children.each2(function(i, elm) { process(elm, data.results); });
 10139  
 10140                      query.callback(data);
 10141                  });
 10142                  // this is needed because inside val() we construct choices from options and their id is hardcoded
 10143                  opts.id=function(e) { return e.id; };
 10144              } else {
 10145                  if (!("query" in opts)) {
 10146  
 10147                      if ("ajax" in opts) {
 10148                          ajaxUrl = opts.element.data("ajax-url");
 10149                          if (ajaxUrl && ajaxUrl.length > 0) {
 10150                              opts.ajax.url = ajaxUrl;
 10151                          }
 10152                          opts.query = ajax.call(opts.element, opts.ajax);
 10153                      } else if ("data" in opts) {
 10154                          opts.query = local(opts.data);
 10155                      } else if ("tags" in opts) {
 10156                          opts.query = tags(opts.tags);
 10157                          if (opts.createSearchChoice === undefined) {
 10158                              opts.createSearchChoice = function (term) { return {id: $.trim(term), text: $.trim(term)}; };
 10159                          }
 10160                          if (opts.initSelection === undefined) {
 10161                              opts.initSelection = function (element, callback) {
 10162                                  var data = [];
 10163                                  $(splitVal(element.val(), opts.separator)).each(function () {
 10164                                      var obj = { id: this, text: this },
 10165                                          tags = opts.tags;
 10166                                      if ($.isFunction(tags)) tags=tags();
 10167                                      $(tags).each(function() { if (equal(this.id, obj.id)) { obj = this; return false; } });
 10168                                      data.push(obj);
 10169                                  });
 10170  
 10171                                  callback(data);
 10172                              };
 10173                          }
 10174                      }
 10175                  }
 10176              }
 10177              if (typeof(opts.query) !== "function") {
 10178                  throw "query function not defined for Select2 " + opts.element.attr("id");
 10179              }
 10180  
 10181              if (opts.createSearchChoicePosition === 'top') {
 10182                  opts.createSearchChoicePosition = function(list, item) { list.unshift(item); };
 10183              }
 10184              else if (opts.createSearchChoicePosition === 'bottom') {
 10185                  opts.createSearchChoicePosition = function(list, item) { list.push(item); };
 10186              }
 10187              else if (typeof(opts.createSearchChoicePosition) !== "function")  {
 10188                  throw "invalid createSearchChoicePosition option must be 'top', 'bottom' or a custom function";
 10189              }
 10190  
 10191              return opts;
 10192          },
 10193  
 10194          /**
 10195           * Monitor the original element for changes and update select2 accordingly
 10196           */
 10197          // abstract
 10198          monitorSource: function () {
 10199              var el = this.opts.element, observer, self = this;
 10200  
 10201              el.on("change.select2", this.bind(function (e) {
 10202                  if (this.opts.element.data("select2-change-triggered") !== true) {
 10203                      this.initSelection();
 10204                  }
 10205              }));
 10206  
 10207              this._sync = this.bind(function () {
 10208  
 10209                  // sync enabled state
 10210                  var disabled = el.prop("disabled");
 10211                  if (disabled === undefined) disabled = false;
 10212                  this.enable(!disabled);
 10213  
 10214                  var readonly = el.prop("readonly");
 10215                  if (readonly === undefined) readonly = false;
 10216                  this.readonly(readonly);
 10217  
 10218                  syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);
 10219                  this.container.addClass(evaluate(this.opts.containerCssClass, this.opts.element));
 10220  
 10221                  syncCssClasses(this.dropdown, this.opts.element, this.opts.adaptDropdownCssClass);
 10222                  this.dropdown.addClass(evaluate(this.opts.dropdownCssClass, this.opts.element));
 10223  
 10224              });
 10225  
 10226              // IE8-10 (IE9/10 won't fire propertyChange via attachEventListener)
 10227              if (el.length && el[0].attachEvent) {
 10228                  el.each(function() {
 10229                      this.attachEvent("onpropertychange", self._sync);
 10230                  });
 10231              }
 10232  
 10233              // safari, chrome, firefox, IE11
 10234              observer = window.MutationObserver || window.WebKitMutationObserver|| window.MozMutationObserver;
 10235              if (observer !== undefined) {
 10236                  if (this.propertyObserver) { delete this.propertyObserver; this.propertyObserver = null; }
 10237                  this.propertyObserver = new observer(function (mutations) {
 10238                      $.each(mutations, self._sync);
 10239                  });
 10240                  this.propertyObserver.observe(el.get(0), { attributes:true, subtree:false });
 10241              }
 10242          },
 10243  
 10244          // abstract
 10245          triggerSelect: function(data) {
 10246              var evt = $.Event("select2-selecting", { val: this.id(data), object: data, choice: data });
 10247              this.opts.element.trigger(evt);
 10248              return !evt.isDefaultPrevented();
 10249          },
 10250  
 10251          /**
 10252           * Triggers the change event on the source element
 10253           */
 10254          // abstract
 10255          triggerChange: function (details) {
 10256  
 10257              details = details || {};
 10258              details= $.extend({}, details, { type: "change", val: this.val() });
 10259              // prevents recursive triggering
 10260              this.opts.element.data("select2-change-triggered", true);
 10261              this.opts.element.trigger(details);
 10262              this.opts.element.data("select2-change-triggered", false);
 10263  
 10264              // some validation frameworks ignore the change event and listen instead to keyup, click for selects
 10265              // so here we trigger the click event manually
 10266              this.opts.element.click();
 10267  
 10268              // ValidationEngine ignores the change event and listens instead to blur
 10269              // so here we trigger the blur event manually if so desired
 10270              if (this.opts.blurOnChange)
 10271                  this.opts.element.blur();
 10272          },
 10273  
 10274          //abstract
 10275          isInterfaceEnabled: function()
 10276          {
 10277              return this.enabledInterface === true;
 10278          },
 10279  
 10280          // abstract
 10281          enableInterface: function() {
 10282              var enabled = this._enabled && !this._readonly,
 10283                  disabled = !enabled;
 10284  
 10285              if (enabled === this.enabledInterface) return false;
 10286  
 10287              this.container.toggleClass("select2-container-disabled", disabled);
 10288              this.close();
 10289              this.enabledInterface = enabled;
 10290  
 10291              return true;
 10292          },
 10293  
 10294          // abstract
 10295          enable: function(enabled) {
 10296              if (enabled === undefined) enabled = true;
 10297              if (this._enabled === enabled) return;
 10298              this._enabled = enabled;
 10299  
 10300              this.opts.element.prop("disabled", !enabled);
 10301              this.enableInterface();
 10302          },
 10303  
 10304          // abstract
 10305          disable: function() {
 10306              this.enable(false);
 10307          },
 10308  
 10309          // abstract
 10310          readonly: function(enabled) {
 10311              if (enabled === undefined) enabled = false;
 10312              if (this._readonly === enabled) return;
 10313              this._readonly = enabled;
 10314  
 10315              this.opts.element.prop("readonly", enabled);
 10316              this.enableInterface();
 10317          },
 10318  
 10319          // abstract
 10320          opened: function () {
 10321              return (this.container) ? this.container.hasClass("select2-dropdown-open") : false;
 10322          },
 10323  
 10324          // abstract
 10325          positionDropdown: function() {
 10326              var $dropdown = this.dropdown,
 10327                  offset = this.container.offset(),
 10328                  height = this.container.outerHeight(false),
 10329                  width = this.container.outerWidth(false),
 10330                  dropHeight = $dropdown.outerHeight(false),
 10331                  $window = $(window),
 10332                  windowWidth = $window.width(),
 10333                  windowHeight = $window.height(),
 10334                  viewPortRight = $window.scrollLeft() + windowWidth,
 10335                  viewportBottom = $window.scrollTop() + windowHeight,
 10336                  dropTop = offset.top + height,
 10337                  dropLeft = offset.left,
 10338                  enoughRoomBelow = dropTop + dropHeight <= viewportBottom,
 10339                  enoughRoomAbove = (offset.top - dropHeight) >= $window.scrollTop(),
 10340                  dropWidth = $dropdown.outerWidth(false),
 10341                  enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight,
 10342                  aboveNow = $dropdown.hasClass("select2-drop-above"),
 10343                  bodyOffset,
 10344                  above,
 10345                  changeDirection,
 10346                  css,
 10347                  resultsListNode;
 10348  
 10349              // always prefer the current above/below alignment, unless there is not enough room
 10350              if (aboveNow) {
 10351                  above = true;
 10352                  if (!enoughRoomAbove && enoughRoomBelow) {
 10353                      changeDirection = true;
 10354                      above = false;
 10355                  }
 10356              } else {
 10357                  above = false;
 10358                  if (!enoughRoomBelow && enoughRoomAbove) {
 10359                      changeDirection = true;
 10360                      above = true;
 10361                  }
 10362              }
 10363  
 10364              //if we are changing direction we need to get positions when dropdown is hidden;
 10365              if (changeDirection) {
 10366                  $dropdown.hide();
 10367                  offset = this.container.offset();
 10368                  height = this.container.outerHeight(false);
 10369                  width = this.container.outerWidth(false);
 10370                  dropHeight = $dropdown.outerHeight(false);
 10371                  viewPortRight = $window.scrollLeft() + windowWidth;
 10372                  viewportBottom = $window.scrollTop() + windowHeight;
 10373                  dropTop = offset.top + height;
 10374                  dropLeft = offset.left;
 10375                  dropWidth = $dropdown.outerWidth(false);
 10376                  enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight;
 10377                  $dropdown.show();
 10378  
 10379                  // fix so the cursor does not move to the left within the search-textbox in IE
 10380                  this.focusSearch();
 10381              }
 10382  
 10383              if (this.opts.dropdownAutoWidth) {
 10384                  resultsListNode = $('.select2-results', $dropdown)[0];
 10385                  $dropdown.addClass('select2-drop-auto-width');
 10386                  $dropdown.css('width', '');
 10387                  // Add scrollbar width to dropdown if vertical scrollbar is present
 10388                  dropWidth = $dropdown.outerWidth(false) + (resultsListNode.scrollHeight === resultsListNode.clientHeight ? 0 : scrollBarDimensions.width);
 10389                  dropWidth > width ? width = dropWidth : dropWidth = width;
 10390                  dropHeight = $dropdown.outerHeight(false);
 10391                  enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight;
 10392              }
 10393              else {
 10394                  this.container.removeClass('select2-drop-auto-width');
 10395              }
 10396  
 10397              //console.log("below/ droptop:", dropTop, "dropHeight", dropHeight, "sum", (dropTop+dropHeight)+" viewport bottom", viewportBottom, "enough?", enoughRoomBelow);
 10398              //console.log("above/ offset.top", offset.top, "dropHeight", dropHeight, "top", (offset.top-dropHeight), "scrollTop", this.body.scrollTop(), "enough?", enoughRoomAbove);
 10399  
 10400              // fix positioning when body has an offset and is not position: static
 10401              if (this.body.css('position') !== 'static') {
 10402                  bodyOffset = this.body.offset();
 10403                  dropTop -= bodyOffset.top;
 10404                  dropLeft -= bodyOffset.left;
 10405              }
 10406  
 10407              if (!enoughRoomOnRight) {
 10408                  dropLeft = offset.left + this.container.outerWidth(false) - dropWidth;
 10409              }
 10410  
 10411              css =  {
 10412                  left: dropLeft,
 10413                  width: width
 10414              };
 10415  
 10416              if (above) {
 10417                  css.top = offset.top - dropHeight;
 10418                  css.bottom = 'auto';
 10419                  this.container.addClass("select2-drop-above");
 10420                  $dropdown.addClass("select2-drop-above");
 10421              }
 10422              else {
 10423                  css.top = dropTop;
 10424                  css.bottom = 'auto';
 10425                  this.container.removeClass("select2-drop-above");
 10426                  $dropdown.removeClass("select2-drop-above");
 10427              }
 10428              css = $.extend(css, evaluate(this.opts.dropdownCss, this.opts.element));
 10429  
 10430              $dropdown.css(css);
 10431          },
 10432  
 10433          // abstract
 10434          shouldOpen: function() {
 10435              var event;
 10436  
 10437              if (this.opened()) return false;
 10438  
 10439              if (this._enabled === false || this._readonly === true) return false;
 10440  
 10441              event = $.Event("select2-opening");
 10442              this.opts.element.trigger(event);
 10443              return !event.isDefaultPrevented();
 10444          },
 10445  
 10446          // abstract
 10447          clearDropdownAlignmentPreference: function() {
 10448              // clear the classes used to figure out the preference of where the dropdown should be opened
 10449              this.container.removeClass("select2-drop-above");
 10450              this.dropdown.removeClass("select2-drop-above");
 10451          },
 10452  
 10453          /**
 10454           * Opens the dropdown
 10455           *
 10456           * @return {Boolean} whether or not dropdown was opened. This method will return false if, for example,
 10457           * the dropdown is already open, or if the 'open' event listener on the element called preventDefault().
 10458           */
 10459          // abstract
 10460          open: function () {
 10461  
 10462              if (!this.shouldOpen()) return false;
 10463  
 10464              this.opening();
 10465  
 10466              // Only bind the document mousemove when the dropdown is visible
 10467              $document.on("mousemove.select2Event", function (e) {
 10468                  lastMousePosition.x = e.pageX;
 10469                  lastMousePosition.y = e.pageY;
 10470              });
 10471  
 10472              return true;
 10473          },
 10474  
 10475          /**
 10476           * Performs the opening of the dropdown
 10477           */
 10478          // abstract
 10479          opening: function() {
 10480              var cid = this.containerEventName,
 10481                  scroll = "scroll." + cid,
 10482                  resize = "resize."+cid,
 10483                  orient = "orientationchange."+cid,
 10484                  mask;
 10485  
 10486              this.container.addClass("select2-dropdown-open").addClass("select2-container-active");
 10487  
 10488              this.clearDropdownAlignmentPreference();
 10489  
 10490              if(this.dropdown[0] !== this.body.children().last()[0]) {
 10491                  this.dropdown.detach().appendTo(this.body);
 10492              }
 10493  
 10494              // create the dropdown mask if doesn't already exist
 10495              mask = $("#select2-drop-mask");
 10496              if (mask.length == 0) {
 10497                  mask = $(document.createElement("div"));
 10498                  mask.attr("id","select2-drop-mask").attr("class","select2-drop-mask");
 10499                  mask.hide();
 10500                  mask.appendTo(this.body);
 10501                  mask.on("mousedown touchstart click", function (e) {
 10502                      // Prevent IE from generating a click event on the body
 10503                      reinsertElement(mask);
 10504  
 10505                      var dropdown = $("#select2-drop"), self;
 10506                      if (dropdown.length > 0) {
 10507                          self=dropdown.data("select2");
 10508                          if (self.opts.selectOnBlur) {
 10509                              self.selectHighlighted({noFocus: true});
 10510                          }
 10511                          self.close();
 10512                          e.preventDefault();
 10513                          e.stopPropagation();
 10514                      }
 10515                  });
 10516              }
 10517  
 10518              // ensure the mask is always right before the dropdown
 10519              if (this.dropdown.prev()[0] !== mask[0]) {
 10520                  this.dropdown.before(mask);
 10521              }
 10522  
 10523              // move the global id to the correct dropdown
 10524              $("#select2-drop").removeAttr("id");
 10525              this.dropdown.attr("id", "select2-drop");
 10526  
 10527              // show the elements
 10528              mask.show();
 10529  
 10530              this.positionDropdown();
 10531              this.dropdown.show();
 10532              this.positionDropdown();
 10533  
 10534              this.dropdown.addClass("select2-drop-active");
 10535  
 10536              // attach listeners to events that can change the position of the container and thus require
 10537              // the position of the dropdown to be updated as well so it does not come unglued from the container
 10538              var that = this;
 10539              this.container.parents().add(window).each(function () {
 10540                  $(this).on(resize+" "+scroll+" "+orient, function (e) {
 10541                      if (that.opened()) that.positionDropdown();
 10542                  });
 10543              });
 10544  
 10545  
 10546          },
 10547  
 10548          // abstract
 10549          close: function () {
 10550              if (!this.opened()) return;
 10551  
 10552              var cid = this.containerEventName,
 10553                  scroll = "scroll." + cid,
 10554                  resize = "resize."+cid,
 10555                  orient = "orientationchange."+cid;
 10556  
 10557              // unbind event listeners
 10558              this.container.parents().add(window).each(function () { $(this).off(scroll).off(resize).off(orient); });
 10559  
 10560              this.clearDropdownAlignmentPreference();
 10561  
 10562              $("#select2-drop-mask").hide();
 10563              this.dropdown.removeAttr("id"); // only the active dropdown has the select2-drop id
 10564              this.dropdown.hide();
 10565              this.container.removeClass("select2-dropdown-open").removeClass("select2-container-active");
 10566              this.results.empty();
 10567  
 10568              // Now that the dropdown is closed, unbind the global document mousemove event
 10569              $document.off("mousemove.select2Event");
 10570  
 10571              this.clearSearch();
 10572              this.search.removeClass("select2-active");
 10573              this.opts.element.trigger($.Event("select2-close"));
 10574          },
 10575  
 10576          /**
 10577           * Opens control, sets input value, and updates results.
 10578           */
 10579          // abstract
 10580          externalSearch: function (term) {
 10581              this.open();
 10582              this.search.val(term);
 10583              this.updateResults(false);
 10584          },
 10585  
 10586          // abstract
 10587          clearSearch: function () {
 10588  
 10589          },
 10590  
 10591          //abstract
 10592          getMaximumSelectionSize: function() {
 10593              return evaluate(this.opts.maximumSelectionSize, this.opts.element);
 10594          },
 10595  
 10596          // abstract
 10597          ensureHighlightVisible: function () {
 10598              var results = this.results, children, index, child, hb, rb, y, more, topOffset;
 10599  
 10600              index = this.highlight();
 10601  
 10602              if (index < 0) return;
 10603  
 10604              if (index == 0) {
 10605  
 10606                  // if the first element is highlighted scroll all the way to the top,
 10607                  // that way any unselectable headers above it will also be scrolled
 10608                  // into view
 10609  
 10610                  results.scrollTop(0);
 10611                  return;
 10612              }
 10613  
 10614              children = this.findHighlightableChoices().find('.select2-result-label');
 10615  
 10616              child = $(children[index]);
 10617  
 10618              topOffset = (child.offset() || {}).top || 0;
 10619  
 10620              hb = topOffset + child.outerHeight(true);
 10621  
 10622              // if this is the last child lets also make sure select2-more-results is visible
 10623              if (index === children.length - 1) {
 10624                  more = results.find("li.select2-more-results");
 10625                  if (more.length > 0) {
 10626                      hb = more.offset().top + more.outerHeight(true);
 10627                  }
 10628              }
 10629  
 10630              rb = results.offset().top + results.outerHeight(true);
 10631              if (hb > rb) {
 10632                  results.scrollTop(results.scrollTop() + (hb - rb));
 10633              }
 10634              y = topOffset - results.offset().top;
 10635  
 10636              // make sure the top of the element is visible
 10637              if (y < 0 && child.css('display') != 'none' ) {
 10638                  results.scrollTop(results.scrollTop() + y); // y is negative
 10639              }
 10640          },
 10641  
 10642          // abstract
 10643          findHighlightableChoices: function() {
 10644              return this.results.find(".select2-result-selectable:not(.select2-disabled):not(.select2-selected)");
 10645          },
 10646  
 10647          // abstract
 10648          moveHighlight: function (delta) {
 10649              var choices = this.findHighlightableChoices(),
 10650                  index = this.highlight();
 10651  
 10652              while (index > -1 && index < choices.length) {
 10653                  index += delta;
 10654                  var choice = $(choices[index]);
 10655                  if (choice.hasClass("select2-result-selectable") && !choice.hasClass("select2-disabled") && !choice.hasClass("select2-selected")) {
 10656                      this.highlight(index);
 10657                      break;
 10658                  }
 10659              }
 10660          },
 10661  
 10662          // abstract
 10663          highlight: function (index) {
 10664              var choices = this.findHighlightableChoices(),
 10665                  choice,
 10666                  data;
 10667  
 10668              if (arguments.length === 0) {
 10669                  return indexOf(choices.filter(".select2-highlighted")[0], choices.get());
 10670              }
 10671  
 10672              if (index >= choices.length) index = choices.length - 1;
 10673              if (index < 0) index = 0;
 10674  
 10675              this.removeHighlight();
 10676  
 10677              choice = $(choices[index]);
 10678              choice.addClass("select2-highlighted");
 10679  
 10680              // ensure assistive technology can determine the active choice
 10681              this.search.attr("aria-activedescendant", choice.find(".select2-result-label").attr("id"));
 10682  
 10683              this.ensureHighlightVisible();
 10684  
 10685              this.liveRegion.text(choice.text());
 10686  
 10687              data = choice.data("select2-data");
 10688              if (data) {
 10689                  this.opts.element.trigger({ type: "select2-highlight", val: this.id(data), choice: data });
 10690              }
 10691          },
 10692  
 10693          removeHighlight: function() {
 10694              this.results.find(".select2-highlighted").removeClass("select2-highlighted");
 10695          },
 10696  
 10697          touchMoved: function() {
 10698              this._touchMoved = true;
 10699          },
 10700  
 10701          clearTouchMoved: function() {
 10702            this._touchMoved = false;
 10703          },
 10704  
 10705          // abstract
 10706          countSelectableResults: function() {
 10707              return this.findHighlightableChoices().length;
 10708          },
 10709  
 10710          // abstract
 10711          highlightUnderEvent: function (event) {
 10712              var el = $(event.target).closest(".select2-result-selectable");
 10713              if (el.length > 0 && !el.is(".select2-highlighted")) {
 10714                  var choices = this.findHighlightableChoices();
 10715                  this.highlight(choices.index(el));
 10716              } else if (el.length == 0) {
 10717                  // if we are over an unselectable item remove all highlights
 10718                  this.removeHighlight();
 10719              }
 10720          },
 10721  
 10722          // abstract
 10723          loadMoreIfNeeded: function () {
 10724              var results = this.results,
 10725                  more = results.find("li.select2-more-results"),
 10726                  below, // pixels the element is below the scroll fold, below==0 is when the element is starting to be visible
 10727                  page = this.resultsPage + 1,
 10728                  self=this,
 10729                  term=this.search.val(),
 10730                  context=this.context;
 10731  
 10732              if (more.length === 0) return;
 10733              below = more.offset().top - results.offset().top - results.height();
 10734  
 10735              if (below <= this.opts.loadMorePadding) {
 10736                  more.addClass("select2-active");
 10737                  this.opts.query({
 10738                          element: this.opts.element,
 10739                          term: term,
 10740                          page: page,
 10741                          context: context,
 10742                          matcher: this.opts.matcher,
 10743                          callback: this.bind(function (data) {
 10744  
 10745                      // ignore a response if the select2 has been closed before it was received
 10746                      if (!self.opened()) return;
 10747  
 10748  
 10749                      self.opts.populateResults.call(this, results, data.results, {term: term, page: page, context:context});
 10750                      self.postprocessResults(data, false, false);
 10751  
 10752                      if (data.more===true) {
 10753                          more.detach().appendTo(results).text(evaluate(self.opts.formatLoadMore, self.opts.element, page+1));
 10754                          window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10);
 10755                      } else {
 10756                          more.remove();
 10757                      }
 10758                      self.positionDropdown();
 10759                      self.resultsPage = page;
 10760                      self.context = data.context;
 10761                      this.opts.element.trigger({ type: "select2-loaded", items: data });
 10762                  })});
 10763              }
 10764          },
 10765  
 10766          /**
 10767           * Default tokenizer function which does nothing
 10768           */
 10769          tokenize: function() {
 10770  
 10771          },
 10772  
 10773          /**
 10774           * @param initial whether or not this is the call to this method right after the dropdown has been opened
 10775           */
 10776          // abstract
 10777          updateResults: function (initial) {
 10778              var search = this.search,
 10779                  results = this.results,
 10780                  opts = this.opts,
 10781                  data,
 10782                  self = this,
 10783                  input,
 10784                  term = search.val(),
 10785                  lastTerm = $.data(this.container, "select2-last-term"),
 10786                  // sequence number used to drop out-of-order responses
 10787                  queryNumber;
 10788  
 10789              // prevent duplicate queries against the same term
 10790              if (initial !== true && lastTerm && equal(term, lastTerm)) return;
 10791  
 10792              $.data(this.container, "select2-last-term", term);
 10793  
 10794              // if the search is currently hidden we do not alter the results
 10795              if (initial !== true && (this.showSearchInput === false || !this.opened())) {
 10796                  return;
 10797              }
 10798  
 10799              function postRender() {
 10800                  search.removeClass("select2-active");
 10801                  self.positionDropdown();
 10802                  if (results.find('.select2-no-results,.select2-selection-limit,.select2-searching').length) {
 10803                      self.liveRegion.text(results.text());
 10804                  }
 10805                  else {
 10806                      self.liveRegion.text(self.opts.formatMatches(results.find('.select2-result-selectable').length));
 10807                  }
 10808              }
 10809  
 10810              function render(html) {
 10811                  results.html(html);
 10812                  postRender();
 10813              }
 10814  
 10815              queryNumber = ++this.queryCount;
 10816  
 10817              var maxSelSize = this.getMaximumSelectionSize();
 10818              if (maxSelSize >=1) {
 10819                  data = this.data();
 10820                  if ($.isArray(data) && data.length >= maxSelSize && checkFormatter(opts.formatSelectionTooBig, "formatSelectionTooBig")) {
 10821                      render("<li class='select2-selection-limit'>" + evaluate(opts.formatSelectionTooBig, opts.element, maxSelSize) + "</li>");
 10822                      return;
 10823                  }
 10824              }
 10825  
 10826              if (search.val().length < opts.minimumInputLength) {
 10827                  if (checkFormatter(opts.formatInputTooShort, "formatInputTooShort")) {
 10828                      render("<li class='select2-no-results'>" + evaluate(opts.formatInputTooShort, opts.element, search.val(), opts.minimumInputLength) + "</li>");
 10829                  } else {
 10830                      render("");
 10831                  }
 10832                  if (initial && this.showSearch) this.showSearch(true);
 10833                  return;
 10834              }
 10835  
 10836              if (opts.maximumInputLength && search.val().length > opts.maximumInputLength) {
 10837                  if (checkFormatter(opts.formatInputTooLong, "formatInputTooLong")) {
 10838                      render("<li class='select2-no-results'>" + evaluate(opts.formatInputTooLong, opts.element, search.val(), opts.maximumInputLength) + "</li>");
 10839                  } else {
 10840                      render("");
 10841                  }
 10842                  return;
 10843              }
 10844  
 10845              if (opts.formatSearching && this.findHighlightableChoices().length === 0) {
 10846                  render("<li class='select2-searching'>" + evaluate(opts.formatSearching, opts.element) + "</li>");
 10847              }
 10848  
 10849              search.addClass("select2-active");
 10850  
 10851              this.removeHighlight();
 10852  
 10853              // give the tokenizer a chance to pre-process the input
 10854              input = this.tokenize();
 10855              if (input != undefined && input != null) {
 10856                  search.val(input);
 10857              }
 10858  
 10859              this.resultsPage = 1;
 10860  
 10861              opts.query({
 10862                  element: opts.element,
 10863                      term: search.val(),
 10864                      page: this.resultsPage,
 10865                      context: null,
 10866                      matcher: opts.matcher,
 10867                      callback: this.bind(function (data) {
 10868                  var def; // default choice
 10869  
 10870                  // ignore old responses
 10871                  if (queryNumber != this.queryCount) {
 10872                    return;
 10873                  }
 10874  
 10875                  // ignore a response if the select2 has been closed before it was received
 10876                  if (!this.opened()) {
 10877                      this.search.removeClass("select2-active");
 10878                      return;
 10879                  }
 10880  
 10881                  // handle ajax error
 10882                  if(data.hasError !== undefined && checkFormatter(opts.formatAjaxError, "formatAjaxError")) {
 10883                      render("<li class='select2-ajax-error'>" + evaluate(opts.formatAjaxError, opts.element, data.jqXHR, data.textStatus, data.errorThrown) + "</li>");
 10884                      return;
 10885                  }
 10886  
 10887                  // save context, if any
 10888                  this.context = (data.context===undefined) ? null : data.context;
 10889                  // create a default choice and prepend it to the list
 10890                  if (this.opts.createSearchChoice && search.val() !== "") {
 10891                      def = this.opts.createSearchChoice.call(self, search.val(), data.results);
 10892                      if (def !== undefined && def !== null && self.id(def) !== undefined && self.id(def) !== null) {
 10893                          if ($(data.results).filter(
 10894                              function () {
 10895                                  return equal(self.id(this), self.id(def));
 10896                              }).length === 0) {
 10897                              this.opts.createSearchChoicePosition(data.results, def);
 10898                          }
 10899                      }
 10900                  }
 10901  
 10902                  if (data.results.length === 0 && checkFormatter(opts.formatNoMatches, "formatNoMatches")) {
 10903                      render("<li class='select2-no-results'>" + evaluate(opts.formatNoMatches, opts.element, search.val()) + "</li>");
 10904                      return;
 10905                  }
 10906  
 10907                  results.empty();
 10908                  self.opts.populateResults.call(this, results, data.results, {term: search.val(), page: this.resultsPage, context:null});
 10909  
 10910                  if (data.more === true && checkFormatter(opts.formatLoadMore, "formatLoadMore")) {
 10911                      results.append("<li class='select2-more-results'>" + opts.escapeMarkup(evaluate(opts.formatLoadMore, opts.element, this.resultsPage)) + "</li>");
 10912                      window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10);
 10913                  }
 10914  
 10915                  this.postprocessResults(data, initial);
 10916  
 10917                  postRender();
 10918  
 10919                  this.opts.element.trigger({ type: "select2-loaded", items: data });
 10920              })});
 10921          },
 10922  
 10923          // abstract
 10924          cancel: function () {
 10925              this.close();
 10926          },
 10927  
 10928          // abstract
 10929          blur: function () {
 10930              // if selectOnBlur == true, select the currently highlighted option
 10931              if (this.opts.selectOnBlur)
 10932                  this.selectHighlighted({noFocus: true});
 10933  
 10934              this.close();
 10935              this.container.removeClass("select2-container-active");
 10936              // synonymous to .is(':focus'), which is available in jquery >= 1.6
 10937              if (this.search[0] === document.activeElement) { this.search.blur(); }
 10938              this.clearSearch();
 10939              this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");
 10940          },
 10941  
 10942          // abstract
 10943          focusSearch: function () {
 10944              focus(this.search);
 10945          },
 10946  
 10947          // abstract
 10948          selectHighlighted: function (options) {
 10949              if (this._touchMoved) {
 10950                this.clearTouchMoved();
 10951                return;
 10952              }
 10953              var index=this.highlight(),
 10954                  highlighted=this.results.find(".select2-highlighted"),
 10955                  data = highlighted.closest('.select2-result').data("select2-data");
 10956  
 10957              if (data) {
 10958                  this.highlight(index);
 10959                  this.onSelect(data, options);
 10960              } else if (options && options.noFocus) {
 10961                  this.close();
 10962              }
 10963          },
 10964  
 10965          // abstract
 10966          getPlaceholder: function () {
 10967              var placeholderOption;
 10968              return this.opts.element.attr("placeholder") ||
 10969                  this.opts.element.attr("data-placeholder") || // jquery 1.4 compat
 10970                  this.opts.element.data("placeholder") ||
 10971                  this.opts.placeholder ||
 10972                  ((placeholderOption = this.getPlaceholderOption()) !== undefined ? placeholderOption.text() : undefined);
 10973          },
 10974  
 10975          // abstract
 10976          getPlaceholderOption: function() {
 10977              if (this.select) {
 10978                  var firstOption = this.select.children('option').first();
 10979                  if (this.opts.placeholderOption !== undefined ) {
 10980                      //Determine the placeholder option based on the specified placeholderOption setting
 10981                      return (this.opts.placeholderOption === "first" && firstOption) ||
 10982                             (typeof this.opts.placeholderOption === "function" && this.opts.placeholderOption(this.select));
 10983                  } else if ($.trim(firstOption.text()) === "" && firstOption.val() === "") {
 10984                      //No explicit placeholder option specified, use the first if it's blank
 10985                      return firstOption;
 10986                  }
 10987              }
 10988          },
 10989  
 10990          /**
 10991           * Get the desired width for the container element.  This is
 10992           * derived first from option `width` passed to select2, then
 10993           * the inline 'style' on the original element, and finally
 10994           * falls back to the jQuery calculated element width.
 10995           */
 10996          // abstract
 10997          initContainerWidth: function () {
 10998              function resolveContainerWidth() {
 10999                  var style, attrs, matches, i, l, attr;
 11000  
 11001                  if (this.opts.width === "off") {
 11002                      return null;
 11003                  } else if (this.opts.width === "element"){
 11004                      return this.opts.element.outerWidth(false) === 0 ? 'auto' : this.opts.element.outerWidth(false) + 'px';
 11005                  } else if (this.opts.width === "copy" || this.opts.width === "resolve") {
 11006                      // check if there is inline style on the element that contains width
 11007                      style = this.opts.element.attr('style');
 11008                      if (style !== undefined) {
 11009                          attrs = style.split(';');
 11010                          for (i = 0, l = attrs.length; i < l; i = i + 1) {
 11011                              attr = attrs[i].replace(/\s/g, '');
 11012                              matches = attr.match(/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i);
 11013                              if (matches !== null && matches.length >= 1)
 11014                                  return matches[1];
 11015                          }
 11016                      }
 11017  
 11018                      if (this.opts.width === "resolve") {
 11019                          // next check if css('width') can resolve a width that is percent based, this is sometimes possible
 11020                          // when attached to input type=hidden or elements hidden via css
 11021                          style = this.opts.element.css('width');
 11022                          if (style.indexOf("%") > 0) return style;
 11023  
 11024                          // finally, fallback on the calculated width of the element
 11025                          return (this.opts.element.outerWidth(false) === 0 ? 'auto' : this.opts.element.outerWidth(false) + 'px');
 11026                      }
 11027  
 11028                      return null;
 11029                  } else if ($.isFunction(this.opts.width)) {
 11030                      return this.opts.width();
 11031                  } else {
 11032                      return this.opts.width;
 11033                 }
 11034              };
 11035  
 11036              var width = resolveContainerWidth.call(this);
 11037              if (width !== null) {
 11038                  this.container.css("width", width);
 11039              }
 11040          }
 11041      });
 11042  
 11043      SingleSelect2 = clazz(AbstractSelect2, {
 11044  
 11045          // single
 11046  
 11047          createContainer: function () {
 11048              var container = $(document.createElement("div")).attr({
 11049                  "class": "select2-container"
 11050              }).html([
 11051                  "<a href='javascript:void(0)' class='select2-choice' tabindex='-1'>",
 11052                  "   <span class='select2-chosen'>&#160;</span><abbr class='select2-search-choice-close'></abbr>",
 11053                  "   <span class='select2-arrow' role='presentation'><b role='presentation'></b></span>",
 11054                  "</a>",
 11055                  "<label for='' class='select2-offscreen'></label>",
 11056                  "<input class='select2-focusser select2-offscreen' type='text' aria-haspopup='true' role='button' />",
 11057                  "<div class='select2-drop select2-display-none'>",
 11058                  "   <div class='select2-search'>",
 11059                  "       <label for='' class='select2-offscreen'></label>",
 11060                  "       <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input' role='combobox' aria-expanded='true'",
 11061                  "       aria-autocomplete='list' />",
 11062                  "   </div>",
 11063                  "   <ul class='select2-results' role='listbox'>",
 11064                  "   </ul>",
 11065                  "</div>"].join(""));
 11066              return container;
 11067          },
 11068  
 11069          // single
 11070          enableInterface: function() {
 11071              if (this.parent.enableInterface.apply(this, arguments)) {
 11072                  this.focusser.prop("disabled", !this.isInterfaceEnabled());
 11073              }
 11074          },
 11075  
 11076          // single
 11077          opening: function () {
 11078              var el, range, len;
 11079  
 11080              if (this.opts.minimumResultsForSearch >= 0) {
 11081                  this.showSearch(true);
 11082              }
 11083  
 11084              this.parent.opening.apply(this, arguments);
 11085  
 11086              if (this.showSearchInput !== false) {
 11087                  // IE appends focusser.val() at the end of field :/ so we manually insert it at the beginning using a range
 11088                  // all other browsers handle this just fine
 11089  
 11090                  this.search.val(this.focusser.val());
 11091              }
 11092              if (this.opts.shouldFocusInput(this)) {
 11093                  this.search.focus();
 11094                  // move the cursor to the end after focussing, otherwise it will be at the beginning and
 11095                  // new text will appear *before* focusser.val()
 11096                  el = this.search.get(0);
 11097                  if (el.createTextRange) {
 11098                      range = el.createTextRange();
 11099                      range.collapse(false);
 11100                      range.select();
 11101                  } else if (el.setSelectionRange) {
 11102                      len = this.search.val().length;
 11103                      el.setSelectionRange(len, len);
 11104                  }
 11105              }
 11106  
 11107              // initializes search's value with nextSearchTerm (if defined by user)
 11108              // ignore nextSearchTerm if the dropdown is opened by the user pressing a letter
 11109              if(this.search.val() === "") {
 11110                  if(this.nextSearchTerm != undefined){
 11111                      this.search.val(this.nextSearchTerm);
 11112                      this.search.select();
 11113                  }
 11114              }
 11115  
 11116              this.focusser.prop("disabled", true).val("");
 11117              this.updateResults(true);
 11118              this.opts.element.trigger($.Event("select2-open"));
 11119          },
 11120  
 11121          // single
 11122          close: function () {
 11123              if (!this.opened()) return;
 11124              this.parent.close.apply(this, arguments);
 11125  
 11126              this.focusser.prop("disabled", false);
 11127  
 11128              if (this.opts.shouldFocusInput(this)) {
 11129                  this.focusser.focus();
 11130              }
 11131          },
 11132  
 11133          // single
 11134          focus: function () {
 11135              if (this.opened()) {
 11136                  this.close();
 11137              } else {
 11138                  this.focusser.prop("disabled", false);
 11139                  if (this.opts.shouldFocusInput(this)) {
 11140                      this.focusser.focus();
 11141                  }
 11142              }
 11143          },
 11144  
 11145          // single
 11146          isFocused: function () {
 11147              return this.container.hasClass("select2-container-active");
 11148          },
 11149  
 11150          // single
 11151          cancel: function () {
 11152              this.parent.cancel.apply(this, arguments);
 11153              this.focusser.prop("disabled", false);
 11154  
 11155              if (this.opts.shouldFocusInput(this)) {
 11156                  this.focusser.focus();
 11157              }
 11158          },
 11159  
 11160          // single
 11161          destroy: function() {
 11162              $("label[for='" + this.focusser.attr('id') + "']")
 11163                  .attr('for', this.opts.element.attr("id"));
 11164              this.parent.destroy.apply(this, arguments);
 11165  
 11166              cleanupJQueryElements.call(this,
 11167                  "selection",
 11168                  "focusser"
 11169              );
 11170          },
 11171  
 11172          // single
 11173          initContainer: function () {
 11174  
 11175              var selection,
 11176                  container = this.container,
 11177                  dropdown = this.dropdown,
 11178                  idSuffix = nextUid(),
 11179                  elementLabel;
 11180  
 11181              if (this.opts.minimumResultsForSearch < 0) {
 11182                  this.showSearch(false);
 11183              } else {
 11184                  this.showSearch(true);
 11185              }
 11186  
 11187              this.selection = selection = container.find(".select2-choice");
 11188  
 11189              this.focusser = container.find(".select2-focusser");
 11190  
 11191              // add aria associations
 11192              selection.find(".select2-chosen").attr("id", "select2-chosen-"+idSuffix);
 11193              this.focusser.attr("aria-labelledby", "select2-chosen-"+idSuffix);
 11194              this.results.attr("id", "select2-results-"+idSuffix);
 11195              this.search.attr("aria-owns", "select2-results-"+idSuffix);
 11196  
 11197              // rewrite labels from original element to focusser
 11198              this.focusser.attr("id", "s2id_autogen"+idSuffix);
 11199  
 11200              elementLabel = $("label[for='" + this.opts.element.attr("id") + "']");
 11201  
 11202              this.focusser.prev()
 11203                  .text(elementLabel.text())
 11204                  .attr('for', this.focusser.attr('id'));
 11205  
 11206              // Ensure the original element retains an accessible name
 11207              var originalTitle = this.opts.element.attr("title");
 11208              this.opts.element.attr("title", (originalTitle || elementLabel.text()));
 11209  
 11210              this.focusser.attr("tabindex", this.elementTabIndex);
 11211  
 11212              // write label for search field using the label from the focusser element
 11213              this.search.attr("id", this.focusser.attr('id') + '_search');
 11214  
 11215              this.search.prev()
 11216                  .text($("label[for='" + this.focusser.attr('id') + "']").text())
 11217                  .attr('for', this.search.attr('id'));
 11218  
 11219              this.search.on("keydown", this.bind(function (e) {
 11220                  if (!this.isInterfaceEnabled()) return;
 11221  
 11222                  // filter 229 keyCodes (input method editor is processing key input)
 11223                  if (229 == e.keyCode) return;
 11224  
 11225                  if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) {
 11226                      // prevent the page from scrolling
 11227                      killEvent(e);
 11228                      return;
 11229                  }
 11230  
 11231                  switch (e.which) {
 11232                      case KEY.UP:
 11233                      case KEY.DOWN:
 11234                          this.moveHighlight((e.which === KEY.UP) ? -1 : 1);
 11235                          killEvent(e);
 11236                          return;
 11237                      case KEY.ENTER:
 11238                          this.selectHighlighted();
 11239                          killEvent(e);
 11240                          return;
 11241                      case KEY.TAB:
 11242                          this.selectHighlighted({noFocus: true});
 11243                          return;
 11244                      case KEY.ESC:
 11245                          this.cancel(e);
 11246                          killEvent(e);
 11247                          return;
 11248                  }
 11249              }));
 11250  
 11251              this.search.on("blur", this.bind(function(e) {
 11252                  // a workaround for chrome to keep the search field focussed when the scroll bar is used to scroll the dropdown.
 11253                  // without this the search field loses focus which is annoying
 11254                  if (document.activeElement === this.body.get(0)) {
 11255                      window.setTimeout(this.bind(function() {
 11256                          if (this.opened()) {
 11257                              this.search.focus();
 11258                          }
 11259                      }), 0);
 11260                  }
 11261              }));
 11262  
 11263              this.focusser.on("keydown", this.bind(function (e) {
 11264                  if (!this.isInterfaceEnabled()) return;
 11265  
 11266                  if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) {
 11267                      return;
 11268                  }
 11269  
 11270                  if (this.opts.openOnEnter === false && e.which === KEY.ENTER) {
 11271                      killEvent(e);
 11272                      return;
 11273                  }
 11274  
 11275                  if (e.which == KEY.DOWN || e.which == KEY.UP
 11276                      || (e.which == KEY.ENTER && this.opts.openOnEnter)) {
 11277  
 11278                      if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) return;
 11279  
 11280                      this.open();
 11281                      killEvent(e);
 11282                      return;
 11283                  }
 11284  
 11285                  if (e.which == KEY.DELETE || e.which == KEY.BACKSPACE) {
 11286                      if (this.opts.allowClear) {
 11287                          this.clear();
 11288                      }
 11289                      killEvent(e);
 11290                      return;
 11291                  }
 11292              }));
 11293  
 11294  
 11295              installKeyUpChangeEvent(this.focusser);
 11296              this.focusser.on("keyup-change input", this.bind(function(e) {
 11297                  if (this.opts.minimumResultsForSearch >= 0) {
 11298                      e.stopPropagation();
 11299                      if (this.opened()) return;
 11300                      this.open();
 11301                  }
 11302              }));
 11303  
 11304              selection.on("mousedown touchstart", "abbr", this.bind(function (e) {
 11305                  if (!this.isInterfaceEnabled()) return;
 11306                  this.clear();
 11307                  killEventImmediately(e);
 11308                  this.close();
 11309                  this.selection.focus();
 11310              }));
 11311  
 11312              selection.on("mousedown touchstart", this.bind(function (e) {
 11313                  // Prevent IE from generating a click event on the body
 11314                  reinsertElement(selection);
 11315  
 11316                  if (!this.container.hasClass("select2-container-active")) {
 11317                      this.opts.element.trigger($.Event("select2-focus"));
 11318                  }
 11319  
 11320                  if (this.opened()) {
 11321                      this.close();
 11322                  } else if (this.isInterfaceEnabled()) {
 11323                      this.open();
 11324                  }
 11325  
 11326                  killEvent(e);
 11327              }));
 11328  
 11329              dropdown.on("mousedown touchstart", this.bind(function() {
 11330                  if (this.opts.shouldFocusInput(this)) {
 11331                      this.search.focus();
 11332                  }
 11333              }));
 11334  
 11335              selection.on("focus", this.bind(function(e) {
 11336                  killEvent(e);
 11337              }));
 11338  
 11339              this.focusser.on("focus", this.bind(function(){
 11340                  if (!this.container.hasClass("select2-container-active")) {
 11341                      this.opts.element.trigger($.Event("select2-focus"));
 11342                  }
 11343                  this.container.addClass("select2-container-active");
 11344              })).on("blur", this.bind(function() {
 11345                  if (!this.opened()) {
 11346                      this.container.removeClass("select2-container-active");
 11347                      this.opts.element.trigger($.Event("select2-blur"));
 11348                  }
 11349              }));
 11350              this.search.on("focus", this.bind(function(){
 11351                  if (!this.container.hasClass("select2-container-active")) {
 11352                      this.opts.element.trigger($.Event("select2-focus"));
 11353                  }
 11354                  this.container.addClass("select2-container-active");
 11355              }));
 11356  
 11357              this.initContainerWidth();
 11358              this.opts.element.addClass("select2-offscreen");
 11359              this.setPlaceholder();
 11360  
 11361          },
 11362  
 11363          // single
 11364          clear: function(triggerChange) {
 11365              var data=this.selection.data("select2-data");
 11366              if (data) { // guard against queued quick consecutive clicks
 11367                  var evt = $.Event("select2-clearing");
 11368                  this.opts.element.trigger(evt);
 11369                  if (evt.isDefaultPrevented()) {
 11370                      return;
 11371                  }
 11372                  var placeholderOption = this.getPlaceholderOption();
 11373                  this.opts.element.val(placeholderOption ? placeholderOption.val() : "");
 11374                  this.selection.find(".select2-chosen").empty();
 11375                  this.selection.removeData("select2-data");
 11376                  this.setPlaceholder();
 11377  
 11378                  if (triggerChange !== false){
 11379                      this.opts.element.trigger({ type: "select2-removed", val: this.id(data), choice: data });
 11380                      this.triggerChange({removed:data});
 11381                  }
 11382              }
 11383          },
 11384  
 11385          /**
 11386           * Sets selection based on source element's value
 11387           */
 11388          // single
 11389          initSelection: function () {
 11390              var selected;
 11391              if (this.isPlaceholderOptionSelected()) {
 11392                  this.updateSelection(null);
 11393                  this.close();
 11394                  this.setPlaceholder();
 11395              } else {
 11396                  var self = this;
 11397                  this.opts.initSelection.call(null, this.opts.element, function(selected){
 11398                      if (selected !== undefined && selected !== null) {
 11399                          self.updateSelection(selected);
 11400                          self.close();
 11401                          self.setPlaceholder();
 11402                          self.nextSearchTerm = self.opts.nextSearchTerm(selected, self.search.val());
 11403                      }
 11404                  });
 11405              }
 11406          },
 11407  
 11408          isPlaceholderOptionSelected: function() {
 11409              var placeholderOption;
 11410              if (this.getPlaceholder() === undefined) return false; // no placeholder specified so no option should be considered
 11411              return ((placeholderOption = this.getPlaceholderOption()) !== undefined && placeholderOption.prop("selected"))
 11412                  || (this.opts.element.val() === "")
 11413                  || (this.opts.element.val() === undefined)
 11414                  || (this.opts.element.val() === null);
 11415          },
 11416  
 11417          // single
 11418          prepareOpts: function () {
 11419              var opts = this.parent.prepareOpts.apply(this, arguments),
 11420                  self=this;
 11421  
 11422              if (opts.element.get(0).tagName.toLowerCase() === "select") {
 11423                  // install the selection initializer
 11424                  opts.initSelection = function (element, callback) {
 11425                      var selected = element.find("option").filter(function() { return this.selected && !this.disabled });
 11426                      // a single select box always has a value, no need to null check 'selected'
 11427                      callback(self.optionToData(selected));
 11428                  };
 11429              } else if ("data" in opts) {
 11430                  // install default initSelection when applied to hidden input and data is local
 11431                  opts.initSelection = opts.initSelection || function (element, callback) {
 11432                      var id = element.val();
 11433                      //search in data by id, storing the actual matching item
 11434                      var match = null;
 11435                      opts.query({
 11436                          matcher: function(term, text, el){
 11437                              var is_match = equal(id, opts.id(el));
 11438                              if (is_match) {
 11439                                  match = el;
 11440                              }
 11441                              return is_match;
 11442                          },
 11443                          callback: !$.isFunction(callback) ? $.noop : function() {
 11444                              callback(match);
 11445                          }
 11446                      });
 11447                  };
 11448              }
 11449  
 11450              return opts;
 11451          },
 11452  
 11453          // single
 11454          getPlaceholder: function() {
 11455              // if a placeholder is specified on a single select without a valid placeholder option ignore it
 11456              if (this.select) {
 11457                  if (this.getPlaceholderOption() === undefined) {
 11458                      return undefined;
 11459                  }
 11460              }
 11461  
 11462              return this.parent.getPlaceholder.apply(this, arguments);
 11463          },
 11464  
 11465          // single
 11466          setPlaceholder: function () {
 11467              var placeholder = this.getPlaceholder();
 11468  
 11469              if (this.isPlaceholderOptionSelected() && placeholder !== undefined) {
 11470  
 11471                  // check for a placeholder option if attached to a select
 11472                  if (this.select && this.getPlaceholderOption() === undefined) return;
 11473  
 11474                  this.selection.find(".select2-chosen").html(this.opts.escapeMarkup(placeholder));
 11475  
 11476                  this.selection.addClass("select2-default");
 11477  
 11478                  this.container.removeClass("select2-allowclear");
 11479              }
 11480          },
 11481  
 11482          // single
 11483          postprocessResults: function (data, initial, noHighlightUpdate) {
 11484              var selected = 0, self = this, showSearchInput = true;
 11485  
 11486              // find the selected element in the result list
 11487  
 11488              this.findHighlightableChoices().each2(function (i, elm) {
 11489                  if (equal(self.id(elm.data("select2-data")), self.opts.element.val())) {
 11490                      selected = i;
 11491                      return false;
 11492                  }
 11493              });
 11494  
 11495              // and highlight it
 11496              if (noHighlightUpdate !== false) {
 11497                  if (initial === true && selected >= 0) {
 11498                      this.highlight(selected);
 11499                  } else {
 11500                      this.highlight(0);
 11501                  }
 11502              }
 11503  
 11504              // hide the search box if this is the first we got the results and there are enough of them for search
 11505  
 11506              if (initial === true) {
 11507                  var min = this.opts.minimumResultsForSearch;
 11508                  if (min >= 0) {
 11509                      this.showSearch(countResults(data.results) >= min);
 11510                  }
 11511              }
 11512          },
 11513  
 11514          // single
 11515          showSearch: function(showSearchInput) {
 11516              if (this.showSearchInput === showSearchInput) return;
 11517  
 11518              this.showSearchInput = showSearchInput;
 11519  
 11520              this.dropdown.find(".select2-search").toggleClass("select2-search-hidden", !showSearchInput);
 11521              this.dropdown.find(".select2-search").toggleClass("select2-offscreen", !showSearchInput);
 11522              //add "select2-with-searchbox" to the container if search box is shown
 11523              $(this.dropdown, this.container).toggleClass("select2-with-searchbox", showSearchInput);
 11524          },
 11525  
 11526          // single
 11527          onSelect: function (data, options) {
 11528  
 11529              if (!this.triggerSelect(data)) { return; }
 11530  
 11531              var old = this.opts.element.val(),
 11532                  oldData = this.data();
 11533  
 11534              this.opts.element.val(this.id(data));
 11535              this.updateSelection(data);
 11536  
 11537              this.opts.element.trigger({ type: "select2-selected", val: this.id(data), choice: data });
 11538  
 11539              this.nextSearchTerm = this.opts.nextSearchTerm(data, this.search.val());
 11540              this.close();
 11541  
 11542              if ((!options || !options.noFocus) && this.opts.shouldFocusInput(this)) {
 11543                  this.focusser.focus();
 11544              }
 11545  
 11546              if (!equal(old, this.id(data))) {
 11547                  this.triggerChange({ added: data, removed: oldData });
 11548              }
 11549          },
 11550  
 11551          // single
 11552          updateSelection: function (data) {
 11553  
 11554              var container=this.selection.find(".select2-chosen"), formatted, cssClass;
 11555  
 11556              this.selection.data("select2-data", data);
 11557  
 11558              container.empty();
 11559              if (data !== null) {
 11560                  formatted=this.opts.formatSelection(data, container, this.opts.escapeMarkup);
 11561              }
 11562              if (formatted !== undefined) {
 11563                  container.append(formatted);
 11564              }
 11565              cssClass=this.opts.formatSelectionCssClass(data, container);
 11566              if (cssClass !== undefined) {
 11567                  container.addClass(cssClass);
 11568              }
 11569  
 11570              this.selection.removeClass("select2-default");
 11571  
 11572              if (this.opts.allowClear && this.getPlaceholder() !== undefined) {
 11573                  this.container.addClass("select2-allowclear");
 11574              }
 11575          },
 11576  
 11577          // single
 11578          val: function () {
 11579              var val,
 11580                  triggerChange = false,
 11581                  data = null,
 11582                  self = this,
 11583                  oldData = this.data();
 11584  
 11585              if (arguments.length === 0) {
 11586                  return this.opts.element.val();
 11587              }
 11588  
 11589              val = arguments[0];
 11590  
 11591              if (arguments.length > 1) {
 11592                  triggerChange = arguments[1];
 11593              }
 11594  
 11595              if (this.select) {
 11596                  this.select
 11597                      .val(val)
 11598                      .find("option").filter(function() { return this.selected }).each2(function (i, elm) {
 11599                          data = self.optionToData(elm);
 11600                          return false;
 11601                      });
 11602                  this.updateSelection(data);
 11603                  this.setPlaceholder();
 11604                  if (triggerChange) {
 11605                      this.triggerChange({added: data, removed:oldData});
 11606                  }
 11607              } else {
 11608                  // val is an id. !val is true for [undefined,null,'',0] - 0 is legal
 11609                  if (!val && val !== 0) {
 11610                      this.clear(triggerChange);
 11611                      return;
 11612                  }
 11613                  if (this.opts.initSelection === undefined) {
 11614                      throw new Error("cannot call val() if initSelection() is not defined");
 11615                  }
 11616                  this.opts.element.val(val);
 11617                  this.opts.initSelection(this.opts.element, function(data){
 11618                      self.opts.element.val(!data ? "" : self.id(data));
 11619                      self.updateSelection(data);
 11620                      self.setPlaceholder();
 11621                      if (triggerChange) {
 11622                          self.triggerChange({added: data, removed:oldData});
 11623                      }
 11624                  });
 11625              }
 11626          },
 11627  
 11628          // single
 11629          clearSearch: function () {
 11630              this.search.val("");
 11631              this.focusser.val("");
 11632          },
 11633  
 11634          // single
 11635          data: function(value) {
 11636              var data,
 11637                  triggerChange = false;
 11638  
 11639              if (arguments.length === 0) {
 11640                  data = this.selection.data("select2-data");
 11641                  if (data == undefined) data = null;
 11642                  return data;
 11643              } else {
 11644                  if (arguments.length > 1) {
 11645                      triggerChange = arguments[1];
 11646                  }
 11647                  if (!value) {
 11648                      this.clear(triggerChange);
 11649                  } else {
 11650                      data = this.data();
 11651                      this.opts.element.val(!value ? "" : this.id(value));
 11652                      this.updateSelection(value);
 11653                      if (triggerChange) {
 11654                          this.triggerChange({added: value, removed:data});
 11655                      }
 11656                  }
 11657              }
 11658          }
 11659      });
 11660  
 11661      MultiSelect2 = clazz(AbstractSelect2, {
 11662  
 11663          // multi
 11664          createContainer: function () {
 11665              var container = $(document.createElement("div")).attr({
 11666                  "class": "select2-container select2-container-multi"
 11667              }).html([
 11668                  "<ul class='select2-choices'>",
 11669                  "  <li class='select2-search-field'>",
 11670                  "    <label for='' class='select2-offscreen'></label>",
 11671                  "    <input type='text' autocomplete='off' autocorrect='off' autocapitalize='off' spellcheck='false' class='select2-input'>",
 11672                  "  </li>",
 11673                  "</ul>",
 11674                  "<div class='select2-drop select2-drop-multi select2-display-none'>",
 11675                  "   <ul class='select2-results'>",
 11676                  "   </ul>",
 11677                  "</div>"].join(""));
 11678              return container;
 11679          },
 11680  
 11681          // multi
 11682          prepareOpts: function () {
 11683              var opts = this.parent.prepareOpts.apply(this, arguments),
 11684                  self=this;
 11685  
 11686              // TODO validate placeholder is a string if specified
 11687  
 11688              if (opts.element.get(0).tagName.toLowerCase() === "select") {
 11689                  // install the selection initializer
 11690                  opts.initSelection = function (element, callback) {
 11691  
 11692                      var data = [];
 11693  
 11694                      element.find("option").filter(function() { return this.selected && !this.disabled }).each2(function (i, elm) {
 11695                          data.push(self.optionToData(elm));
 11696                      });
 11697                      callback(data);
 11698                  };
 11699              } else if ("data" in opts) {
 11700                  // install default initSelection when applied to hidden input and data is local
 11701                  opts.initSelection = opts.initSelection || function (element, callback) {
 11702                      var ids = splitVal(element.val(), opts.separator);
 11703                      //search in data by array of ids, storing matching items in a list
 11704                      var matches = [];
 11705                      opts.query({
 11706                          matcher: function(term, text, el){
 11707                              var is_match = $.grep(ids, function(id) {
 11708                                  return equal(id, opts.id(el));
 11709                              }).length;
 11710                              if (is_match) {
 11711                                  matches.push(el);
 11712                              }
 11713                              return is_match;
 11714                          },
 11715                          callback: !$.isFunction(callback) ? $.noop : function() {
 11716                              // reorder matches based on the order they appear in the ids array because right now
 11717                              // they are in the order in which they appear in data array
 11718                              var ordered = [];
 11719                              for (var i = 0; i < ids.length; i++) {
 11720                                  var id = ids[i];
 11721                                  for (var j = 0; j < matches.length; j++) {
 11722                                      var match = matches[j];
 11723                                      if (equal(id, opts.id(match))) {
 11724                                          ordered.push(match);
 11725                                          matches.splice(j, 1);
 11726                                          break;
 11727                                      }
 11728                                  }
 11729                              }
 11730                              callback(ordered);
 11731                          }
 11732                      });
 11733                  };
 11734              }
 11735  
 11736              return opts;
 11737          },
 11738  
 11739          // multi
 11740          selectChoice: function (choice) {
 11741  
 11742              var selected = this.container.find(".select2-search-choice-focus");
 11743              if (selected.length && choice && choice[0] == selected[0]) {
 11744  
 11745              } else {
 11746                  if (selected.length) {
 11747                      this.opts.element.trigger("choice-deselected", selected);
 11748                  }
 11749                  selected.removeClass("select2-search-choice-focus");
 11750                  if (choice && choice.length) {
 11751                      this.close();
 11752                      choice.addClass("select2-search-choice-focus");
 11753                      this.opts.element.trigger("choice-selected", choice);
 11754                  }
 11755              }
 11756          },
 11757  
 11758          // multi
 11759          destroy: function() {
 11760              $("label[for='" + this.search.attr('id') + "']")
 11761                  .attr('for', this.opts.element.attr("id"));
 11762              this.parent.destroy.apply(this, arguments);
 11763  
 11764              cleanupJQueryElements.call(this,
 11765                  "searchContainer",
 11766                  "selection"
 11767              );
 11768          },
 11769  
 11770          // multi
 11771          initContainer: function () {
 11772  
 11773              var selector = ".select2-choices", selection;
 11774  
 11775              this.searchContainer = this.container.find(".select2-search-field");
 11776              this.selection = selection = this.container.find(selector);
 11777  
 11778              var _this = this;
 11779              this.selection.on("click", ".select2-search-choice:not(.select2-locked)", function (e) {
 11780                  //killEvent(e);
 11781                  _this.search[0].focus();
 11782                  _this.selectChoice($(this));
 11783              });
 11784  
 11785              // rewrite labels from original element to focusser
 11786              this.search.attr("id", "s2id_autogen"+nextUid());
 11787  
 11788              this.search.prev()
 11789                  .text($("label[for='" + this.opts.element.attr("id") + "']").text())
 11790                  .attr('for', this.search.attr('id'));
 11791  
 11792              this.search.on("input paste", this.bind(function() {
 11793                  if (this.search.attr('placeholder') && this.search.val().length == 0) return;
 11794                  if (!this.isInterfaceEnabled()) return;
 11795                  if (!this.opened()) {
 11796                      this.open();
 11797                  }
 11798              }));
 11799  
 11800              this.search.attr("tabindex", this.elementTabIndex);
 11801  
 11802              this.keydowns = 0;
 11803              this.search.on("keydown", this.bind(function (e) {
 11804                  if (!this.isInterfaceEnabled()) return;
 11805  
 11806                  ++this.keydowns;
 11807                  var selected = selection.find(".select2-search-choice-focus");
 11808                  var prev = selected.prev(".select2-search-choice:not(.select2-locked)");
 11809                  var next = selected.next(".select2-search-choice:not(.select2-locked)");
 11810                  var pos = getCursorInfo(this.search);
 11811  
 11812                  if (selected.length &&
 11813                      (e.which == KEY.LEFT || e.which == KEY.RIGHT || e.which == KEY.BACKSPACE || e.which == KEY.DELETE || e.which == KEY.ENTER)) {
 11814                      var selectedChoice = selected;
 11815                      if (e.which == KEY.LEFT && prev.length) {
 11816                          selectedChoice = prev;
 11817                      }
 11818                      else if (e.which == KEY.RIGHT) {
 11819                          selectedChoice = next.length ? next : null;
 11820                      }
 11821                      else if (e.which === KEY.BACKSPACE) {
 11822                          if (this.unselect(selected.first())) {
 11823                              this.search.width(10);
 11824                              selectedChoice = prev.length ? prev : next;
 11825                          }
 11826                      } else if (e.which == KEY.DELETE) {
 11827                          if (this.unselect(selected.first())) {
 11828                              this.search.width(10);
 11829                              selectedChoice = next.length ? next : null;
 11830                          }
 11831                      } else if (e.which == KEY.ENTER) {
 11832                          selectedChoice = null;
 11833                      }
 11834  
 11835                      this.selectChoice(selectedChoice);
 11836                      killEvent(e);
 11837                      if (!selectedChoice || !selectedChoice.length) {
 11838                          this.open();
 11839                      }
 11840                      return;
 11841                  } else if (((e.which === KEY.BACKSPACE && this.keydowns == 1)
 11842                      || e.which == KEY.LEFT) && (pos.offset == 0 && !pos.length)) {
 11843  
 11844                      this.selectChoice(selection.find(".select2-search-choice:not(.select2-locked)").last());
 11845                      killEvent(e);
 11846                      return;
 11847                  } else {
 11848                      this.selectChoice(null);
 11849                  }
 11850  
 11851                  if (this.opened()) {
 11852                      switch (e.which) {
 11853                      case KEY.UP:
 11854                      case KEY.DOWN:
 11855                          this.moveHighlight((e.which === KEY.UP) ? -1 : 1);
 11856                          killEvent(e);
 11857                          return;
 11858                      case KEY.ENTER:
 11859                          this.selectHighlighted();
 11860                          killEvent(e);
 11861                          return;
 11862                      case KEY.TAB:
 11863                          this.selectHighlighted({noFocus:true});
 11864                          this.close();
 11865                          return;
 11866                      case KEY.ESC:
 11867                          this.cancel(e);
 11868                          killEvent(e);
 11869                          return;
 11870                      }
 11871                  }
 11872  
 11873                  if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e)
 11874                   || e.which === KEY.BACKSPACE || e.which === KEY.ESC) {
 11875                      return;
 11876                  }
 11877  
 11878                  if (e.which === KEY.ENTER) {
 11879                      if (this.opts.openOnEnter === false) {
 11880                          return;
 11881                      } else if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
 11882                          return;
 11883                      }
 11884                  }
 11885  
 11886                  this.open();
 11887  
 11888                  if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) {
 11889                      // prevent the page from scrolling
 11890                      killEvent(e);
 11891                  }
 11892  
 11893                  if (e.which === KEY.ENTER) {
 11894                      // prevent form from being submitted
 11895                      killEvent(e);
 11896                  }
 11897  
 11898              }));
 11899  
 11900              this.search.on("keyup", this.bind(function (e) {
 11901                  this.keydowns = 0;
 11902                  this.resizeSearch();
 11903              })
 11904              );
 11905  
 11906              this.search.on("blur", this.bind(function(e) {
 11907                  this.container.removeClass("select2-container-active");
 11908                  this.search.removeClass("select2-focused");
 11909                  this.selectChoice(null);
 11910                  if (!this.opened()) this.clearSearch();
 11911                  e.stopImmediatePropagation();
 11912                  this.opts.element.trigger($.Event("select2-blur"));
 11913              }));
 11914  
 11915              this.container.on("click", selector, this.bind(function (e) {
 11916                  if (!this.isInterfaceEnabled()) return;
 11917                  if ($(e.target).closest(".select2-search-choice").length > 0) {
 11918                      // clicked inside a select2 search choice, do not open
 11919                      return;
 11920                  }
 11921                  this.selectChoice(null);
 11922                  this.clearPlaceholder();
 11923                  if (!this.container.hasClass("select2-container-active")) {
 11924                      this.opts.element.trigger($.Event("select2-focus"));
 11925                  }
 11926                  this.open();
 11927                  this.focusSearch();
 11928                  e.preventDefault();
 11929              }));
 11930  
 11931              this.container.on("focus", selector, this.bind(function () {
 11932                  if (!this.isInterfaceEnabled()) return;
 11933                  if (!this.container.hasClass("select2-container-active")) {
 11934                      this.opts.element.trigger($.Event("select2-focus"));
 11935                  }
 11936                  this.container.addClass("select2-container-active");
 11937                  this.dropdown.addClass("select2-drop-active");
 11938                  this.clearPlaceholder();
 11939              }));
 11940  
 11941              this.initContainerWidth();
 11942              this.opts.element.addClass("select2-offscreen");
 11943  
 11944              // set the placeholder if necessary
 11945              this.clearSearch();
 11946          },
 11947  
 11948          // multi
 11949          enableInterface: function() {
 11950              if (this.parent.enableInterface.apply(this, arguments)) {
 11951                  this.search.prop("disabled", !this.isInterfaceEnabled());
 11952              }
 11953          },
 11954  
 11955          // multi
 11956          initSelection: function () {
 11957              var data;
 11958              if (this.opts.element.val() === "" && this.opts.element.text() === "") {
 11959                  this.updateSelection([]);
 11960                  this.close();
 11961                  // set the placeholder if necessary
 11962                  this.clearSearch();
 11963              }
 11964              if (this.select || this.opts.element.val() !== "") {
 11965                  var self = this;
 11966                  this.opts.initSelection.call(null, this.opts.element, function(data){
 11967                      if (data !== undefined && data !== null) {
 11968                          self.updateSelection(data);
 11969                          self.close();
 11970                          // set the placeholder if necessary
 11971                          self.clearSearch();
 11972                      }
 11973                  });
 11974              }
 11975          },
 11976  
 11977          // multi
 11978          clearSearch: function () {
 11979              var placeholder = this.getPlaceholder(),
 11980                  maxWidth = this.getMaxSearchWidth();
 11981  
 11982              if (placeholder !== undefined  && this.getVal().length === 0 && this.search.hasClass("select2-focused") === false) {
 11983                  this.search.val(placeholder).addClass("select2-default");
 11984                  // stretch the search box to full width of the container so as much of the placeholder is visible as possible
 11985                  // we could call this.resizeSearch(), but we do not because that requires a sizer and we do not want to create one so early because of a firefox bug, see #944
 11986                  this.search.width(maxWidth > 0 ? maxWidth : this.container.css("width"));
 11987              } else {
 11988                  this.search.val("").width(10);
 11989              }
 11990          },
 11991  
 11992          // multi
 11993          clearPlaceholder: function () {
 11994              if (this.search.hasClass("select2-default")) {
 11995                  this.search.val("").removeClass("select2-default");
 11996              }
 11997          },
 11998  
 11999          // multi
 12000          opening: function () {
 12001              this.clearPlaceholder(); // should be done before super so placeholder is not used to search
 12002              this.resizeSearch();
 12003  
 12004              this.parent.opening.apply(this, arguments);
 12005  
 12006              this.focusSearch();
 12007  
 12008              // initializes search's value with nextSearchTerm (if defined by user)
 12009              // ignore nextSearchTerm if the dropdown is opened by the user pressing a letter
 12010              if(this.search.val() === "") {
 12011                  if(this.nextSearchTerm != undefined){
 12012                      this.search.val(this.nextSearchTerm);
 12013                      this.search.select();
 12014                  }
 12015              }
 12016  
 12017              this.updateResults(true);
 12018              if (this.opts.shouldFocusInput(this)) {
 12019                  this.search.focus();
 12020              }
 12021              this.opts.element.trigger($.Event("select2-open"));
 12022          },
 12023  
 12024          // multi
 12025          close: function () {
 12026              if (!this.opened()) return;
 12027              this.parent.close.apply(this, arguments);
 12028          },
 12029  
 12030          // multi
 12031          focus: function () {
 12032              this.close();
 12033              this.search.focus();
 12034          },
 12035  
 12036          // multi
 12037          isFocused: function () {
 12038              return this.search.hasClass("select2-focused");
 12039          },
 12040  
 12041          // multi
 12042          updateSelection: function (data) {
 12043              var ids = [], filtered = [], self = this;
 12044  
 12045              // filter out duplicates
 12046              $(data).each(function () {
 12047                  if (indexOf(self.id(this), ids) < 0) {
 12048                      ids.push(self.id(this));
 12049                      filtered.push(this);
 12050                  }
 12051              });
 12052              data = filtered;
 12053  
 12054              this.selection.find(".select2-search-choice").remove();
 12055              $(data).each(function () {
 12056                  self.addSelectedChoice(this);
 12057              });
 12058              self.postprocessResults();
 12059          },
 12060  
 12061          // multi
 12062          tokenize: function() {
 12063              var input = this.search.val();
 12064              input = this.opts.tokenizer.call(this, input, this.data(), this.bind(this.onSelect), this.opts);
 12065              if (input != null && input != undefined) {
 12066                  this.search.val(input);
 12067                  if (input.length > 0) {
 12068                      this.open();
 12069                  }
 12070              }
 12071  
 12072          },
 12073  
 12074          // multi
 12075          onSelect: function (data, options) {
 12076  
 12077              if (!this.triggerSelect(data) || data.text === "") { return; }
 12078  
 12079              this.addSelectedChoice(data);
 12080  
 12081              this.opts.element.trigger({ type: "selected", val: this.id(data), choice: data });
 12082  
 12083              // keep track of the search's value before it gets cleared
 12084              this.nextSearchTerm = this.opts.nextSearchTerm(data, this.search.val());
 12085  
 12086              this.clearSearch();
 12087              this.updateResults();
 12088  
 12089              if (this.select || !this.opts.closeOnSelect) this.postprocessResults(data, false, this.opts.closeOnSelect===true);
 12090  
 12091              if (this.opts.closeOnSelect) {
 12092                  this.close();
 12093                  this.search.width(10);
 12094              } else {
 12095                  if (this.countSelectableResults()>0) {
 12096                      this.search.width(10);
 12097                      this.resizeSearch();
 12098                      if (this.getMaximumSelectionSize() > 0 && this.val().length >= this.getMaximumSelectionSize()) {
 12099                          // if we reached max selection size repaint the results so choices
 12100                          // are replaced with the max selection reached message
 12101                          this.updateResults(true);
 12102                      } else {
 12103                          // initializes search's value with nextSearchTerm and update search result
 12104                          if(this.nextSearchTerm != undefined){
 12105                              this.search.val(this.nextSearchTerm);
 12106                              this.updateResults();
 12107                              this.search.select();
 12108                          }
 12109                      }
 12110                      this.positionDropdown();
 12111                  } else {
 12112                      // if nothing left to select close
 12113                      this.close();
 12114                      this.search.width(10);
 12115                  }
 12116              }
 12117  
 12118              // since its not possible to select an element that has already been
 12119              // added we do not need to check if this is a new element before firing change
 12120              this.triggerChange({ added: data });
 12121  
 12122              if (!options || !options.noFocus)
 12123                  this.focusSearch();
 12124          },
 12125  
 12126          // multi
 12127          cancel: function () {
 12128              this.close();
 12129              this.focusSearch();
 12130          },
 12131  
 12132          addSelectedChoice: function (data) {
 12133              var enableChoice = !data.locked,
 12134                  enabledItem = $(
 12135                      "<li class='select2-search-choice'>" +
 12136                      "    <div></div>" +
 12137                      "    <a href='#' class='select2-search-choice-close' tabindex='-1'></a>" +
 12138                      "</li>"),
 12139                  disabledItem = $(
 12140                      "<li class='select2-search-choice select2-locked'>" +
 12141                      "<div></div>" +
 12142                      "</li>");
 12143              var choice = enableChoice ? enabledItem : disabledItem,
 12144                  id = this.id(data),
 12145                  val = this.getVal(),
 12146                  formatted,
 12147                  cssClass;
 12148  
 12149              formatted=this.opts.formatSelection(data, choice.find("div"), this.opts.escapeMarkup);
 12150              if (formatted != undefined) {
 12151                  choice.find("div").replaceWith("<div>"+formatted+"</div>");
 12152              }
 12153              cssClass=this.opts.formatSelectionCssClass(data, choice.find("div"));
 12154              if (cssClass != undefined) {
 12155                  choice.addClass(cssClass);
 12156              }
 12157  
 12158              if(enableChoice){
 12159                choice.find(".select2-search-choice-close")
 12160                    .on("mousedown", killEvent)
 12161                    .on("click dblclick", this.bind(function (e) {
 12162                    if (!this.isInterfaceEnabled()) return;
 12163  
 12164                    this.unselect($(e.target));
 12165                    this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");
 12166                    killEvent(e);
 12167                    this.close();
 12168                    this.focusSearch();
 12169                })).on("focus", this.bind(function () {
 12170                    if (!this.isInterfaceEnabled()) return;
 12171                    this.container.addClass("select2-container-active");
 12172                    this.dropdown.addClass("select2-drop-active");
 12173                }));
 12174              }
 12175  
 12176              choice.data("select2-data", data);
 12177              choice.insertBefore(this.searchContainer);
 12178  
 12179              val.push(id);
 12180              this.setVal(val);
 12181          },
 12182  
 12183          // multi
 12184          unselect: function (selected) {
 12185              var val = this.getVal(),
 12186                  data,
 12187                  index;
 12188              selected = selected.closest(".select2-search-choice");
 12189  
 12190              if (selected.length === 0) {
 12191                  throw "Invalid argument: " + selected + ". Must be .select2-search-choice";
 12192              }
 12193  
 12194              data = selected.data("select2-data");
 12195  
 12196              if (!data) {
 12197                  // prevent a race condition when the 'x' is clicked really fast repeatedly the event can be queued
 12198                  // and invoked on an element already removed
 12199                  return;
 12200              }
 12201  
 12202              var evt = $.Event("select2-removing");
 12203              evt.val = this.id(data);
 12204              evt.choice = data;
 12205              this.opts.element.trigger(evt);
 12206  
 12207              if (evt.isDefaultPrevented()) {
 12208                  return false;
 12209              }
 12210  
 12211              while((index = indexOf(this.id(data), val)) >= 0) {
 12212                  val.splice(index, 1);
 12213                  this.setVal(val);
 12214                  if (this.select) this.postprocessResults();
 12215              }
 12216  
 12217              selected.remove();
 12218  
 12219              this.opts.element.trigger({ type: "select2-removed", val: this.id(data), choice: data });
 12220              this.triggerChange({ removed: data });
 12221  
 12222              return true;
 12223          },
 12224  
 12225          // multi
 12226          postprocessResults: function (data, initial, noHighlightUpdate) {
 12227              var val = this.getVal(),
 12228                  choices = this.results.find(".select2-result"),
 12229                  compound = this.results.find(".select2-result-with-children"),
 12230                  self = this;
 12231  
 12232              choices.each2(function (i, choice) {
 12233                  var id = self.id(choice.data("select2-data"));
 12234                  if (indexOf(id, val) >= 0) {
 12235                      choice.addClass("select2-selected");
 12236                      // mark all children of the selected parent as selected
 12237                      choice.find(".select2-result-selectable").addClass("select2-selected");
 12238                  }
 12239              });
 12240  
 12241              compound.each2(function(i, choice) {
 12242                  // hide an optgroup if it doesn't have any selectable children
 12243                  if (!choice.is('.select2-result-selectable')
 12244                      && choice.find(".select2-result-selectable:not(.select2-selected)").length === 0) {
 12245                      choice.addClass("select2-selected");
 12246                  }
 12247              });
 12248  
 12249              if (this.highlight() == -1 && noHighlightUpdate !== false){
 12250                  self.highlight(0);
 12251              }
 12252  
 12253              //If all results are chosen render formatNoMatches
 12254              if(!this.opts.createSearchChoice && !choices.filter('.select2-result:not(.select2-selected)').length > 0){
 12255                  if(!data || data && !data.more && this.results.find(".select2-no-results").length === 0) {
 12256                      if (checkFormatter(self.opts.formatNoMatches, "formatNoMatches")) {
 12257                          this.results.append("<li class='select2-no-results'>" + evaluate(self.opts.formatNoMatches, self.opts.element, self.search.val()) + "</li>");
 12258                      }
 12259                  }
 12260              }
 12261  
 12262          },
 12263  
 12264          // multi
 12265          getMaxSearchWidth: function() {
 12266              return this.selection.width() - getSideBorderPadding(this.search);
 12267          },
 12268  
 12269          // multi
 12270          resizeSearch: function () {
 12271              var minimumWidth, left, maxWidth, containerLeft, searchWidth,
 12272                  sideBorderPadding = getSideBorderPadding(this.search);
 12273  
 12274              minimumWidth = measureTextWidth(this.search) + 10;
 12275  
 12276              left = this.search.offset().left;
 12277  
 12278              maxWidth = this.selection.width();
 12279              containerLeft = this.selection.offset().left;
 12280  
 12281              searchWidth = maxWidth - (left - containerLeft) - sideBorderPadding;
 12282  
 12283              if (searchWidth < minimumWidth) {
 12284                  searchWidth = maxWidth - sideBorderPadding;
 12285              }
 12286  
 12287              if (searchWidth < 40) {
 12288                  searchWidth = maxWidth - sideBorderPadding;
 12289              }
 12290  
 12291              if (searchWidth <= 0) {
 12292                searchWidth = minimumWidth;
 12293              }
 12294  
 12295              this.search.width(Math.floor(searchWidth));
 12296          },
 12297  
 12298          // multi
 12299          getVal: function () {
 12300              var val;
 12301              if (this.select) {
 12302                  val = this.select.val();
 12303                  return val === null ? [] : val;
 12304              } else {
 12305                  val = this.opts.element.val();
 12306                  return splitVal(val, this.opts.separator);
 12307              }
 12308          },
 12309  
 12310          // multi
 12311          setVal: function (val) {
 12312              var unique;
 12313              if (this.select) {
 12314                  this.select.val(val);
 12315              } else {
 12316                  unique = [];
 12317                  // filter out duplicates
 12318                  $(val).each(function () {
 12319                      if (indexOf(this, unique) < 0) unique.push(this);
 12320                  });
 12321                  this.opts.element.val(unique.length === 0 ? "" : unique.join(this.opts.separator));
 12322              }
 12323          },
 12324  
 12325          // multi
 12326          buildChangeDetails: function (old, current) {
 12327              var current = current.slice(0),
 12328                  old = old.slice(0);
 12329  
 12330              // remove intersection from each array
 12331              for (var i = 0; i < current.length; i++) {
 12332                  for (var j = 0; j < old.length; j++) {
 12333                      if (equal(this.opts.id(current[i]), this.opts.id(old[j]))) {
 12334                          current.splice(i, 1);
 12335                          if(i>0){
 12336                          	i--;
 12337                          }
 12338                          old.splice(j, 1);
 12339                          j--;
 12340                      }
 12341                  }
 12342              }
 12343  
 12344              return {added: current, removed: old};
 12345          },
 12346  
 12347  
 12348          // multi
 12349          val: function (val, triggerChange) {
 12350              var oldData, self=this;
 12351  
 12352              if (arguments.length === 0) {
 12353                  return this.getVal();
 12354              }
 12355  
 12356              oldData=this.data();
 12357              if (!oldData.length) oldData=[];
 12358  
 12359              // val is an id. !val is true for [undefined,null,'',0] - 0 is legal
 12360              if (!val && val !== 0) {
 12361                  this.opts.element.val("");
 12362                  this.updateSelection([]);
 12363                  this.clearSearch();
 12364                  if (triggerChange) {
 12365                      this.triggerChange({added: this.data(), removed: oldData});
 12366                  }
 12367                  return;
 12368              }
 12369  
 12370              // val is a list of ids
 12371              this.setVal(val);
 12372  
 12373              if (this.select) {
 12374                  this.opts.initSelection(this.select, this.bind(this.updateSelection));
 12375                  if (triggerChange) {
 12376                      this.triggerChange(this.buildChangeDetails(oldData, this.data()));
 12377                  }
 12378              } else {
 12379                  if (this.opts.initSelection === undefined) {
 12380                      throw new Error("val() cannot be called if initSelection() is not defined");
 12381                  }
 12382  
 12383                  this.opts.initSelection(this.opts.element, function(data){
 12384                      var ids=$.map(data, self.id);
 12385                      self.setVal(ids);
 12386                      self.updateSelection(data);
 12387                      self.clearSearch();
 12388                      if (triggerChange) {
 12389                          self.triggerChange(self.buildChangeDetails(oldData, self.data()));
 12390                      }
 12391                  });
 12392              }
 12393              this.clearSearch();
 12394          },
 12395  
 12396          // multi
 12397          onSortStart: function() {
 12398              if (this.select) {
 12399                  throw new Error("Sorting of elements is not supported when attached to <select>. Attach to <input type='hidden'/> instead.");
 12400              }
 12401  
 12402              // collapse search field into 0 width so its container can be collapsed as well
 12403              this.search.width(0);
 12404              // hide the container
 12405              this.searchContainer.hide();
 12406          },
 12407  
 12408          // multi
 12409          onSortEnd:function() {
 12410  
 12411              var val=[], self=this;
 12412  
 12413              // show search and move it to the end of the list
 12414              this.searchContainer.show();
 12415              // make sure the search container is the last item in the list
 12416              this.searchContainer.appendTo(this.searchContainer.parent());
 12417              // since we collapsed the width in dragStarted, we resize it here
 12418              this.resizeSearch();
 12419  
 12420              // update selection
 12421              this.selection.find(".select2-search-choice").each(function() {
 12422                  val.push(self.opts.id($(this).data("select2-data")));
 12423              });
 12424              this.setVal(val);
 12425              this.triggerChange();
 12426          },
 12427  
 12428          // multi
 12429          data: function(values, triggerChange) {
 12430              var self=this, ids, old;
 12431              if (arguments.length === 0) {
 12432                   return this.selection
 12433                       .children(".select2-search-choice")
 12434                       .map(function() { return $(this).data("select2-data"); })
 12435                       .get();
 12436              } else {
 12437                  old = this.data();
 12438                  if (!values) { values = []; }
 12439                  ids = $.map(values, function(e) { return self.opts.id(e); });
 12440                  this.setVal(ids);
 12441                  this.updateSelection(values);
 12442                  this.clearSearch();
 12443                  if (triggerChange) {
 12444                      this.triggerChange(this.buildChangeDetails(old, this.data()));
 12445                  }
 12446              }
 12447          }
 12448      });
 12449  
 12450      $.fn.select2 = function () {
 12451  
 12452          var args = Array.prototype.slice.call(arguments, 0),
 12453              opts,
 12454              select2,
 12455              method, value, multiple,
 12456              allowedMethods = ["val", "destroy", "opened", "open", "close", "focus", "isFocused", "container", "dropdown", "onSortStart", "onSortEnd", "enable", "disable", "readonly", "positionDropdown", "data", "search"],
 12457              valueMethods = ["opened", "isFocused", "container", "dropdown"],
 12458              propertyMethods = ["val", "data"],
 12459              methodsMap = { search: "externalSearch" };
 12460  
 12461          this.each(function () {
 12462              if (args.length === 0 || typeof(args[0]) === "object") {
 12463                  opts = args.length === 0 ? {} : $.extend({}, args[0]);
 12464                  opts.element = $(this);
 12465  
 12466                  if (opts.element.get(0).tagName.toLowerCase() === "select") {
 12467                      multiple = opts.element.prop("multiple");
 12468                  } else {
 12469                      multiple = opts.multiple || false;
 12470                      if ("tags" in opts) {opts.multiple = multiple = true;}
 12471                  }
 12472  
 12473                  select2 = multiple ? new window.Select2["class"].multi() : new window.Select2["class"].single();
 12474                  select2.init(opts);
 12475              } else if (typeof(args[0]) === "string") {
 12476  
 12477                  if (indexOf(args[0], allowedMethods) < 0) {
 12478                      throw "Unknown method: " + args[0];
 12479                  }
 12480  
 12481                  value = undefined;
 12482                  select2 = $(this).data("select2");
 12483                  if (select2 === undefined) return;
 12484  
 12485                  method=args[0];
 12486  
 12487                  if (method === "container") {
 12488                      value = select2.container;
 12489                  } else if (method === "dropdown") {
 12490                      value = select2.dropdown;
 12491                  } else {
 12492                      if (methodsMap[method]) method = methodsMap[method];
 12493  
 12494                      value = select2[method].apply(select2, args.slice(1));
 12495                  }
 12496                  if (indexOf(args[0], valueMethods) >= 0
 12497                      || (indexOf(args[0], propertyMethods) >= 0 && args.length == 1)) {
 12498                      return false; // abort the iteration, ready to return first matched value
 12499                  }
 12500              } else {
 12501                  throw "Invalid arguments to select2 plugin: " + args;
 12502              }
 12503          });
 12504          return (value === undefined) ? this : value;
 12505      };
 12506  
 12507      // plugin defaults, accessible to users
 12508      $.fn.select2.defaults = {
 12509          width: "copy",
 12510          loadMorePadding: 0,
 12511          closeOnSelect: true,
 12512          openOnEnter: true,
 12513          containerCss: {},
 12514          dropdownCss: {},
 12515          containerCssClass: "",
 12516          dropdownCssClass: "",
 12517          formatResult: function(result, container, query, escapeMarkup) {
 12518              var markup=[];
 12519              markMatch(result.text, query.term, markup, escapeMarkup);
 12520              return markup.join("");
 12521          },
 12522          formatSelection: function (data, container, escapeMarkup) {
 12523              return data ? escapeMarkup(data.text) : undefined;
 12524          },
 12525          sortResults: function (results, container, query) {
 12526              return results;
 12527          },
 12528          formatResultCssClass: function(data) {return data.css;},
 12529          formatSelectionCssClass: function(data, container) {return undefined;},
 12530          minimumResultsForSearch: 0,
 12531          minimumInputLength: 0,
 12532          maximumInputLength: null,
 12533          maximumSelectionSize: 0,
 12534          id: function (e) { return e == undefined ? null : e.id; },
 12535          matcher: function(term, text) {
 12536              return stripDiacritics(''+text).toUpperCase().indexOf(stripDiacritics(''+term).toUpperCase()) >= 0;
 12537          },
 12538          separator: ",",
 12539          tokenSeparators: [],
 12540          tokenizer: defaultTokenizer,
 12541          escapeMarkup: defaultEscapeMarkup,
 12542          blurOnChange: false,
 12543          selectOnBlur: false,
 12544          adaptContainerCssClass: function(c) { return c; },
 12545          adaptDropdownCssClass: function(c) { return null; },
 12546          nextSearchTerm: function(selectedObject, currentSearchTerm) { return undefined; },
 12547          searchInputPlaceholder: '',
 12548          createSearchChoicePosition: 'top',
 12549          shouldFocusInput: function (instance) {
 12550              // Attempt to detect touch devices
 12551              var supportsTouchEvents = (('ontouchstart' in window) ||
 12552                                         (navigator.msMaxTouchPoints > 0));
 12553  
 12554              // Only devices which support touch events should be special cased
 12555              if (!supportsTouchEvents) {
 12556                  return true;
 12557              }
 12558  
 12559              // Never focus the input if search is disabled
 12560              if (instance.opts.minimumResultsForSearch < 0) {
 12561                  return false;
 12562              }
 12563  
 12564              return true;
 12565          }
 12566      };
 12567  
 12568      $.fn.select2.locales = [];
 12569  
 12570      $.fn.select2.locales['en'] = {
 12571           formatMatches: function (matches) { if (matches === 1) { return "One result is available, press enter to select it."; } return matches + " results are available, use up and down arrow keys to navigate."; },
 12572           formatNoMatches: function () { return "No matches found"; },
 12573           formatAjaxError: function (jqXHR, textStatus, errorThrown) { return "Loading failed"; },
 12574           formatInputTooShort: function (input, min) { var n = min - input.length; return "Please enter " + n + " or more character" + (n == 1 ? "" : "s"); },
 12575           formatInputTooLong: function (input, max) { var n = input.length - max; return "Please delete " + n + " character" + (n == 1 ? "" : "s"); },
 12576           formatSelectionTooBig: function (limit) { return "You can only select " + limit + " item" + (limit == 1 ? "" : "s"); },
 12577           formatLoadMore: function (pageNumber) { return "Loading more results…"; },
 12578           formatSearching: function () { return "Searching…"; },
 12579      };
 12580  
 12581      $.extend($.fn.select2.defaults, $.fn.select2.locales['en']);
 12582  
 12583      $.fn.select2.ajaxDefaults = {
 12584          transport: $.ajax,
 12585          params: {
 12586              type: "GET",
 12587              cache: false,
 12588              dataType: "json"
 12589          }
 12590      };
 12591  
 12592      // exports
 12593      window.Select2 = {
 12594          query: {
 12595              ajax: ajax,
 12596              local: local,
 12597              tags: tags
 12598          }, util: {
 12599              debounce: debounce,
 12600              markMatch: markMatch,
 12601              escapeMarkup: defaultEscapeMarkup,
 12602              stripDiacritics: stripDiacritics
 12603          }, "class": {
 12604              "abstract": AbstractSelect2,
 12605              "single": SingleSelect2,
 12606              "multi": MultiSelect2
 12607          }
 12608      };
 12609  
 12610  }(jQuery));
 12611  
 12612  /* ============================================================
 12613   * flatui-radiocheck v0.1.0
 12614   * ============================================================ */
 12615  
 12616  +function (global, $) {
 12617    'use strict';
 12618  
 12619    var Radiocheck = function (element, options) {
 12620      this.init('radiocheck', element, options);
 12621    };
 12622  
 12623    Radiocheck.DEFAULTS = {
 12624      checkboxClass: 'custom-checkbox',
 12625      radioClass: 'custom-radio',
 12626      checkboxTemplate: '<span class="icons"><span class="icon-unchecked"></span><span class="icon-checked"></span></span>',
 12627      radioTemplate: '<span class="icons"><span class="icon-unchecked"></span><span class="icon-checked"></span></span>'
 12628    };
 12629  
 12630    Radiocheck.prototype.init = function (type, element, options) {
 12631      this.$element = $(element);
 12632      this.options = $.extend({}, Radiocheck.DEFAULTS, this.$element.data(), options);
 12633      if (this.$element.attr('type') == 'checkbox') {
 12634        this.$element.addClass(this.options.checkboxClass);
 12635        this.$element.after(this.options.checkboxTemplate);
 12636      } else if (this.$element.attr('type') == 'radio') {
 12637        this.$element.addClass(this.options.radioClass);
 12638        this.$element.after(this.options.radioTemplate);
 12639      }
 12640    };
 12641  
 12642    Radiocheck.prototype.check = function () {
 12643      this.$element.prop('checked', true);
 12644      this.$element.trigger('change.radiocheck').trigger('checked.radiocheck');
 12645    },
 12646  
 12647    Radiocheck.prototype.uncheck = function () {
 12648      this.$element.prop('checked', false);
 12649      this.$element.trigger('change.radiocheck').trigger('unchecked.radiocheck');
 12650    },
 12651  
 12652    Radiocheck.prototype.toggle = function () {
 12653      this.$element.prop('checked', function (i, value) {
 12654        return !value;
 12655      });
 12656      this.$element.trigger('change.radiocheck').trigger('toggled.radiocheck');
 12657    },
 12658  
 12659    Radiocheck.prototype.indeterminate = function () {
 12660      this.$element.prop('indeterminate', true);
 12661      this.$element.trigger('change.radiocheck').trigger('indeterminated.radiocheck');
 12662    },
 12663  
 12664    Radiocheck.prototype.determinate = function () {
 12665      this.$element.prop('indeterminate', false);
 12666      this.$element.trigger('change.radiocheck').trigger('determinated.radiocheck');
 12667    },
 12668  
 12669    Radiocheck.prototype.disable = function () {
 12670      this.$element.prop('disabled', true);
 12671      this.$element.trigger('change.radiocheck').trigger('disabled.radiocheck');
 12672    },
 12673  
 12674    Radiocheck.prototype.enable = function () {
 12675      this.$element.prop('disabled', false);
 12676      this.$element.trigger('change.radiocheck').trigger('enabled.radiocheck');
 12677    },
 12678  
 12679    Radiocheck.prototype.destroy = function () {
 12680      this.$element.removeData().removeClass(this.options.checkboxClass + ' ' + this.options.radioClass).next('.icons').remove();
 12681      this.$element.trigger('destroyed.radiocheck');
 12682    };
 12683  
 12684    // RADIOCHECK PLUGIN DEFINITION
 12685    // ============================
 12686  
 12687    function Plugin(option) {
 12688      return this.each(function () {
 12689        var $this   = $(this);
 12690        var data    = $this.data('radiocheck');
 12691        var options = typeof option == 'object' && option;
 12692  
 12693        if (!data && option == 'destroy') { return; }
 12694        if (!data) {
 12695          $this.data('radiocheck', (data = new Radiocheck(this, options)));
 12696        }
 12697        if (typeof option == 'string') {
 12698          data[option]();
 12699        }
 12700  
 12701        // Adding 'nohover' class for mobile devices
 12702  
 12703        var mobile = /mobile|tablet|phone|ip(ad|od)|android|silk|webos/i.test(global.navigator.userAgent);
 12704  
 12705        if (mobile === true) {
 12706          $this.parent().hover(function () {
 12707            $this.addClass('nohover');
 12708          }, function () {
 12709            $this.removeClass('nohover');
 12710          });
 12711        }
 12712      });
 12713    }
 12714  
 12715    var old = $.fn.radiocheck;
 12716  
 12717    $.fn.radiocheck             = Plugin;
 12718    $.fn.radiocheck.Constructor = Radiocheck;
 12719  
 12720    // RADIOCHECK NO CONFLICT
 12721    // ======================
 12722  
 12723    $.fn.radiocheck.noConflict = function () {
 12724      $.fn.radiocheck = old;
 12725      return this;
 12726    };
 12727  
 12728  }(this, jQuery);