').html(row.text).text().trim());\n } else {\n selected = values.includes(row._value || row.value);\n if (!selected && row.value === \"\".concat(+row.value)) {\n selected = values.includes(+row.value);\n }\n }\n if (row.selected !== selected) {\n hasChanged = true;\n }\n row.selected = selected;\n }\n } catch (err) {\n _iterator4.e(err);\n } finally {\n _iterator4.f();\n }\n };\n var _iterator5 = _createForOfIteratorHelper(this.data),\n _step5;\n try {\n for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {\n var row = _step5.value;\n if (row.type === 'optgroup') {\n _setSelects(row.children);\n } else {\n _setSelects([row]);\n }\n }\n } catch (err) {\n _iterator5.e(err);\n } finally {\n _iterator5.f();\n }\n if (hasChanged) {\n this.initSelected(ignoreTrigger);\n this.updateSelected();\n this.update(ignoreTrigger);\n }\n }\n }, {\n key: \"enable\",\n value: function enable() {\n this.$choice.removeClass('disabled');\n }\n }, {\n key: \"disable\",\n value: function disable() {\n this.$choice.addClass('disabled');\n }\n }, {\n key: \"check\",\n value: function check(value) {\n var option = findByParam(this.data, 'value', value);\n if (!option) {\n return;\n }\n this._check(option, true);\n }\n }, {\n key: \"uncheck\",\n value: function uncheck(value) {\n var option = findByParam(this.data, 'value', value);\n if (!option) {\n return;\n }\n this._check(option, false);\n }\n }, {\n key: \"_check\",\n value: function _check(option, checked) {\n if (this.options.single) {\n this._checkAll(false, true);\n }\n option.selected = checked;\n this.initSelected();\n this.updateSelected();\n this.update();\n }\n }, {\n key: \"checkAll\",\n value: function checkAll() {\n this._checkAll(true);\n }\n }, {\n key: \"uncheckAll\",\n value: function uncheckAll() {\n this._checkAll(false);\n }\n }, {\n key: \"_checkAll\",\n value: function _checkAll(checked, ignoreUpdate) {\n var _iterator6 = _createForOfIteratorHelper(this.data),\n _step6;\n try {\n for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {\n var row = _step6.value;\n if (row.type === 'optgroup') {\n this._checkGroup(row, checked, true);\n } else if (!row.disabled && !row.divider && (ignoreUpdate || row.visible)) {\n row.selected = checked;\n }\n }\n } catch (err) {\n _iterator6.e(err);\n } finally {\n _iterator6.f();\n }\n if (!ignoreUpdate) {\n this.initSelected();\n this.updateSelected();\n this.update();\n }\n }\n }, {\n key: \"_checkGroup\",\n value: function _checkGroup(group, checked, ignoreUpdate) {\n group.selected = checked;\n group.children.forEach(function (row) {\n if (!row.disabled && !row.divider && (ignoreUpdate || row.visible)) {\n row.selected = checked;\n }\n });\n if (!ignoreUpdate) {\n this.initSelected();\n this.updateSelected();\n this.update();\n }\n }\n }, {\n key: \"checkInvert\",\n value: function checkInvert() {\n if (this.options.single) {\n return;\n }\n var _iterator7 = _createForOfIteratorHelper(this.data),\n _step7;\n try {\n for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {\n var row = _step7.value;\n if (row.type === 'optgroup') {\n var _iterator8 = _createForOfIteratorHelper(row.children),\n _step8;\n try {\n for (_iterator8.s(); !(_step8 = _iterator8.n()).done;) {\n var child = _step8.value;\n if (!child.divider) {\n child.selected = !child.selected;\n }\n }\n } catch (err) {\n _iterator8.e(err);\n } finally {\n _iterator8.f();\n }\n } else if (!row.divider) {\n row.selected = !row.selected;\n }\n }\n } catch (err) {\n _iterator7.e(err);\n } finally {\n _iterator7.f();\n }\n this.initSelected();\n this.updateSelected();\n this.update();\n }\n }, {\n key: \"focus\",\n value: function focus() {\n this.$choice.focus();\n this.options.onFocus();\n }\n }, {\n key: \"blur\",\n value: function blur() {\n this.$choice.blur();\n this.options.onBlur();\n }\n }, {\n key: \"refresh\",\n value: function refresh() {\n this.destroy();\n this.init();\n }\n }, {\n key: \"filter\",\n value: function filter(ignoreTrigger) {\n var originalSearch = this.$searchInput.val().trim();\n var search = originalSearch.toLowerCase();\n if (this.filterText === search) {\n return;\n }\n this.filterText = search;\n var _iterator9 = _createForOfIteratorHelper(this.data),\n _step9;\n try {\n for (_iterator9.s(); !(_step9 = _iterator9.n()).done;) {\n var row = _step9.value;\n if (row.type === 'optgroup') {\n if (this.options.filterGroup) {\n var visible = this.options.customFilter({\n label: removeDiacritics(row.label.toString().toLowerCase()),\n search: removeDiacritics(search),\n originalLabel: row.label,\n originalSearch: originalSearch,\n row: row\n });\n row.visible = visible;\n var _iterator10 = _createForOfIteratorHelper(row.children),\n _step10;\n try {\n for (_iterator10.s(); !(_step10 = _iterator10.n()).done;) {\n var child = _step10.value;\n child.visible = visible;\n }\n } catch (err) {\n _iterator10.e(err);\n } finally {\n _iterator10.f();\n }\n } else {\n var _iterator11 = _createForOfIteratorHelper(row.children),\n _step11;\n try {\n for (_iterator11.s(); !(_step11 = _iterator11.n()).done;) {\n var _child = _step11.value;\n _child.visible = this.options.customFilter({\n text: removeDiacritics(_child.text.toString().toLowerCase()),\n search: removeDiacritics(search),\n originalText: _child.text,\n originalSearch: originalSearch,\n row: _child,\n parent: row\n });\n }\n } catch (err) {\n _iterator11.e(err);\n } finally {\n _iterator11.f();\n }\n row.visible = row.children.filter(function (child) {\n return child.visible;\n }).length > 0;\n }\n } else {\n row.visible = this.options.customFilter({\n text: removeDiacritics(row.text.toString().toLowerCase()),\n search: removeDiacritics(search),\n originalText: row.text,\n originalSearch: originalSearch,\n row: row\n });\n }\n }\n } catch (err) {\n _iterator9.e(err);\n } finally {\n _iterator9.f();\n }\n this.initListItems();\n this.initSelected(ignoreTrigger);\n this.updateSelected();\n if (!ignoreTrigger) {\n this.options.onFilter(originalSearch);\n }\n }\n }, {\n key: \"destroy\",\n value: function destroy() {\n if (!this.$parent) {\n return;\n }\n this.$el.before(this.$parent).removeClass('ms-offscreen');\n if (this.tabIndex !== null) {\n this.$el.attr('tabindex', this.tabIndex);\n }\n this.$parent.remove();\n if (this.fromHtml) {\n delete this.options.data;\n this.fromHtml = false;\n }\n }\n }]);\n return MultipleSelect;\n }();\n\n $$e.fn.multipleSelect = function (option) {\n for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {\n args[_key - 1] = arguments[_key];\n }\n var value;\n this.each(function (i, el) {\n var $this = $$e(el);\n var data = $this.data('multipleSelect');\n var options = $$e.extend({}, $this.data(), _typeof(option) === 'object' && option);\n if (!data) {\n data = new MultipleSelect($this, options);\n $this.data('multipleSelect', data);\n }\n if (typeof option === 'string') {\n var _data;\n if ($$e.inArray(option, Constants.METHODS) < 0) {\n throw new Error(\"Unknown method: \".concat(option));\n }\n value = (_data = data)[option].apply(_data, args);\n if (option === 'destroy') {\n $this.removeData('multipleSelect');\n }\n } else {\n data.init();\n }\n });\n return typeof value !== 'undefined' ? value : this;\n };\n $$e.fn.multipleSelect.Constructor = MultipleSelect;\n $$e.fn.multipleSelect.defaults = Constants.DEFAULTS;\n $$e.fn.multipleSelect.locales = Constants.LOCALES;\n $$e.fn.multipleSelect.methods = Constants.METHODS;\n\n}));","/*\r\n* Unobtrusive autocomplete\r\n*\r\n* To use it, you just have to include the HTML attribute autocomplete\r\n* with the autocomplete URL as the value\r\n*\r\n* Example:\r\n*
\r\n*\r\n* Optionally, you can use a jQuery selector to specify a field that can\r\n* be updated with the element id whenever you find a matching value\r\n*\r\n* Example:\r\n*
\r\n*/\r\n\r\n(function(jQuery)\r\n{\r\n var self = null;\r\n jQuery.fn.railsAutocomplete = function(selector) {\r\n var handler = function() {\r\n if (!this.railsAutoCompleter) {\r\n this.railsAutoCompleter = new jQuery.railsAutocomplete(this);\r\n }\r\n };\r\n if (jQuery.fn.on !== undefined) {\r\n if (!selector) {\r\n return;\r\n }\r\n return jQuery(document).on('focus',selector,handler);\r\n }\r\n else {\r\n return this.live('focus',handler);\r\n }\r\n };\r\n\r\n jQuery.railsAutocomplete = function (e) {\r\n var _e = e;\r\n this.init(_e);\r\n };\r\n jQuery.railsAutocomplete.options = {\r\n showNoMatches: true,\r\n noMatchesLabel: 'no existing match'\r\n }\r\n\r\n jQuery.railsAutocomplete.fn = jQuery.railsAutocomplete.prototype = {\r\n railsAutocomplete: '0.0.1'\r\n };\r\n\r\n jQuery.railsAutocomplete.fn.extend = jQuery.railsAutocomplete.extend = jQuery.extend;\r\n jQuery.railsAutocomplete.fn.extend({\r\n init: function(e) {\r\n e.delimiter = jQuery(e).attr('data-delimiter') || null;\r\n e.min_length = jQuery(e).attr('data-min-length') || jQuery(e).attr('min-length') || 2;\r\n e.append_to = jQuery(e).attr('data-append-to') || null;\r\n e.autoFocus = jQuery(e).attr('data-auto-focus') || false;\r\n function split( val ) {\r\n return val.split( e.delimiter );\r\n }\r\n function extractLast( term ) {\r\n return split( term ).pop().replace(/^\\s+/,\"\");\r\n }\r\n\r\n jQuery(e).autocomplete({\r\n appendTo: e.append_to,\r\n autoFocus: e.autoFocus,\r\n delay: jQuery(e).attr('delay') || 500,\r\n source: function( request, response ) {\r\n var firedFrom = this.element[0];\r\n var params = {term: extractLast( request.term )};\r\n if (jQuery(e).attr('data-autocomplete-fields')) {\r\n jQuery.each(jQuery.parseJSON(jQuery(e).attr('data-autocomplete-fields')), function(field, selector) {\r\n params[field] = jQuery(selector).val();\r\n });\r\n }\r\n jQuery.getJSON( jQuery(e).attr('data-autocomplete'), params, function() {\r\n var options = {};\r\n jQuery.extend(options, jQuery.railsAutocomplete.options);\r\n jQuery.each(options, function(key, value) {\r\n if(options.hasOwnProperty(key)) {\r\n var attrVal = jQuery(e).attr('data-' + key);\r\n options[key] = attrVal ? attrVal : value;\r\n }\r\n });\r\n if(arguments[0].length == 0 && jQuery.inArray(options.showNoMatches, [true, 'true']) >= 0) {\r\n arguments[0] = [];\r\n arguments[0][0] = { id: \"\", label: options.noMatchesLabel };\r\n }\r\n jQuery(arguments[0]).each(function(i, el) {\r\n var obj = {};\r\n obj[el.id] = el;\r\n jQuery(e).data(obj);\r\n });\r\n response.apply(null, arguments);\r\n jQuery(firedFrom).trigger('railsAutocomplete.source', arguments);\r\n });\r\n },\r\n change: function( event, ui ) {\r\n if(!jQuery(this).is('[data-id-element]') ||\r\n jQuery(jQuery(this).attr('data-id-element')).val() === \"\") {\r\n return;\r\n }\r\n jQuery(jQuery(this).attr('data-id-element')).val(ui.item ? ui.item.id : \"\").trigger('change');\r\n\r\n if (jQuery(this).attr('data-update-elements')) {\r\n var update_elements = jQuery.parseJSON(jQuery(this).attr(\"data-update-elements\"));\r\n var data = ui.item ? jQuery(this).data(ui.item.id.toString()) : {};\r\n if(update_elements && jQuery(update_elements['id']).val() === \"\") {\r\n return;\r\n }\r\n for (var key in update_elements) {\r\n var element = jQuery(update_elements[key]);\r\n if (element.is(':checkbox')) {\r\n if (data[key] != null) {\r\n element.prop('checked', data[key]);\r\n }\r\n } else {\r\n element.val(ui.item ? data[key] : \"\").trigger('change');\r\n }\r\n }\r\n }\r\n },\r\n search: function() {\r\n // custom minLength\r\n var term = extractLast( this.value );\r\n if ( term.length < e.min_length ) {\r\n return false;\r\n }\r\n },\r\n focus: function() {\r\n // prevent value inserted on focus\r\n return false;\r\n },\r\n select: function( event, ui ) {\r\n // first ensure value is a string\r\n ui.item.value = ui.item.value.toString();\r\n if(ui.item.value.toLowerCase().indexOf('no match') != -1 || ui.item.value.toLowerCase().indexOf('too many results') != -1){\r\n jQuery(this).trigger('railsAutocomplete.noMatch', ui);\r\n return false;\r\n }\r\n var terms = split( this.value );\r\n // remove the current input\r\n terms.pop();\r\n // add the selected item\r\n terms.push( ui.item.value );\r\n // add placeholder to get the comma-and-space at the end\r\n if (e.delimiter != null) {\r\n terms.push( \"\" );\r\n this.value = terms.join( e.delimiter );\r\n } else {\r\n this.value = terms.join(\"\");\r\n if (jQuery(this).attr('data-id-element')) {\r\n jQuery(jQuery(this).attr('data-id-element')).val(ui.item.id).trigger('change');\r\n }\r\n if (jQuery(this).attr('data-update-elements')) {\r\n var data = ui.item;\r\n var new_record = ui.item.value.indexOf('Create New') != -1 ? true : false;\r\n var update_elements = jQuery.parseJSON(jQuery(this).attr(\"data-update-elements\"));\r\n for (var key in update_elements) {\r\n if(jQuery(update_elements[key]).attr(\"type\") === \"checkbox\"){\r\n if(data[key] === true || data[key] === 1) {\r\n jQuery(update_elements[key]).attr(\"checked\",\"checked\");\r\n }\r\n else {\r\n jQuery(update_elements[key]).removeAttr(\"checked\");\r\n }\r\n }\r\n else{\r\n if((new_record && data[key] && data[key].indexOf('Create New') == -1) || !new_record){\r\n jQuery(update_elements[key]).val(data[key]).trigger('change');\r\n }else{\r\n jQuery(update_elements[key]).val('').trigger('change');\r\n }\r\n }\r\n }\r\n }\r\n }\r\n var remember_string = this.value;\r\n jQuery(this).bind('keyup.clearId', function(){\r\n if(jQuery.trim(jQuery(this).val()) != jQuery.trim(remember_string)){\r\n jQuery(jQuery(this).attr('data-id-element')).val(\"\").trigger('change');\r\n jQuery(this).unbind('keyup.clearId');\r\n }\r\n });\r\n jQuery(e).trigger('railsAutocomplete.select', ui);\r\n\r\n return false;\r\n }\r\n });\r\n jQuery(e).trigger('railsAutocomplete.init');\r\n }\r\n });\r\n\r\n jQuery(document).ready(function(){\r\n jQuery('input[data-autocomplete]').railsAutocomplete('input[data-autocomplete]');\r\n });\r\n})(jQuery);\r\n","/*\n * Bootstrap Duallistbox - v3.0.5\n * A responsive dual listbox widget optimized for Twitter Bootstrap. It works on all modern browsers and on touch devices.\n * http://www.virtuosoft.eu/code/bootstrap-duallistbox/\n *\n * Made by István Ujj-Mészáros\n * Under Apache License v2.0 License\n */\n;(function ($, window, document, undefined) {\n // Create the defaults once\n var pluginName = 'bootstrapduallistbox',\n defaults = {\n bootstrap2Compatible: false,\n moveOnSelect: true,\n nonSelectedListLabel: 'Available Columns', \n selectedListLabel: 'Displayed Columns', // true/false (forced true on androids, see the comment later)\n preserveSelectionOnMove: false, // 'all' / 'moved' / false\n helperSelectNamePostfix: '_helper', // 'string_of_postfix' / false\n selectorMinimalHeight: 100,\n showFilterInputs: false, // string, filter the selected options\n infoText: false, // text when all options are visible / false for no info text // when there are no options present in the list\n filterOnValues: false, // filter by selector's values, boolean\n sortByInputOrder: false\n },\n // Selections are invisible on android if the containing select is styled with CSS\n // http://code.google.com/p/android/issues/detail?id=16922\n isBuggyAndroid = /android/i.test(navigator.userAgent.toLowerCase());\n\n // The actual plugin constructor\n function bootstrapduallistbox(element, options) {\n this.element = $(element);\n // jQuery has an extend method which merges the contents of two or\n // more objects, storing the result in the first object. The first object\n // is generally empty as we don't want to alter the default options for\n // future instances of the plugin\n this.settings = $.extend({}, defaults, options);\n this._defaults = defaults;\n this._name = pluginName;\n this.init();\n }\n\n function triggerChangeEvent(dualListbox) {\n dualListbox.element.trigger('change');\n }\n\n function updateSelectionStates(dualListbox) {\n dualListbox.element.find('option').each(function(index, item) {\n var $item = $(item);\n if (typeof($item.data('original-index')) === 'undefined') {\n $item.data('original-index', dualListbox.elementCount++);\n }\n if (typeof($item.data('_selected')) === 'undefined') {\n $item.data('_selected', false);\n }\n });\n }\n\n function changeSelectionState(dualListbox, original_index, selected) {\n dualListbox.element.find('option').each(function(index, item) {\n var $item = $(item);\n if ($item.data('original-index') === original_index) {\n $item.prop('selected', selected);\n if(selected){\n $item.attr('data-sortindex', dualListbox.sortIndex);\n dualListbox.sortIndex++;\n } else {\n $item.removeAttr(\"data-sortindex\");\n }\n }\n });\n }\n\n function formatString(s, args) {\n return s.replace(/\\{(\\d+)\\}/g, function(match, number) {\n return typeof args[number] !== 'undefined' ? args[number] : match;\n });\n }\n\n function refreshInfo(dualListbox) {\n if (!dualListbox.settings.infoText) {\n return;\n }\n\n var visible1 = dualListbox.elements.select1.find('option').length,\n visible2 = dualListbox.elements.select2.find('option').length,\n all1 = dualListbox.element.find('option').length - dualListbox.selectedElements,\n all2 = dualListbox.selectedElements,\n content = '';\n\n if (all1 === 0) {\n content = dualListbox.settings.infoTextEmpty;\n } else if (visible1 === all1) {\n content = formatString(dualListbox.settings.infoText, [visible1, all1]);\n } else {\n content = formatString(dualListbox.settings.infoTextFiltered, [visible1, all1]);\n }\n\n dualListbox.elements.info1.html(content);\n dualListbox.elements.box1.toggleClass('filtered', !(visible1 === all1 || all1 === 0));\n\n if (all2 === 0) {\n content = dualListbox.settings.infoTextEmpty;\n } else if (visible2 === all2) {\n content = formatString(dualListbox.settings.infoText, [visible2, all2]);\n } else {\n content = formatString(dualListbox.settings.infoTextFiltered, [visible2, all2]);\n }\n\n dualListbox.elements.info2.html(content);\n dualListbox.elements.box2.toggleClass('filtered', !(visible2 === all2 || all2 === 0));\n }\n\n function refreshSelects(dualListbox) {\n dualListbox.selectedElements = 0;\n\n dualListbox.elements.select1.empty();\n dualListbox.elements.select2.empty();\n\n dualListbox.element.find('option').each(function(index, item) {\n var $item = $(item);\n if ($item.prop('selected')) {\n dualListbox.selectedElements++;\n dualListbox.elements.select2.append($item.clone(true).prop('selected', $item.data('_selected')));\n } else {\n dualListbox.elements.select1.append($item.clone(true).prop('selected', $item.data('_selected')));\n }\n });\n\n if (dualListbox.settings.showFilterInputs) {\n filter(dualListbox, 1);\n filter(dualListbox, 2);\n }\n refreshInfo(dualListbox);\n }\n\n function filter(dualListbox, selectIndex) {\n if (!dualListbox.settings.showFilterInputs) {\n return;\n }\n\n saveSelections(dualListbox, selectIndex);\n\n dualListbox.elements['select'+selectIndex].empty().scrollTop(0);\n var regex = new RegExp($.trim(dualListbox.elements['filterInput'+selectIndex].val()), 'gi'),\n allOptions = dualListbox.element.find('option'),\n options = dualListbox.element;\n\n if (selectIndex === 1) {\n options = allOptions.not(':selected');\n } else {\n options = options.find('option:selected');\n }\n\n options.each(function(index, item) {\n var $item = $(item),\n isFiltered = true;\n if (item.text.match(regex) || (dualListbox.settings.filterOnValues && $item.attr('value').match(regex) ) ) {\n isFiltered = false;\n dualListbox.elements['select'+selectIndex].append($item.clone(true).prop('selected', $item.data('_selected')));\n }\n allOptions.eq($item.data('original-index')).data('filtered'+selectIndex, isFiltered);\n });\n\n refreshInfo(dualListbox);\n }\n\n function saveSelections(dualListbox, selectIndex) {\n var options = dualListbox.element.find('option');\n dualListbox.elements['select'+selectIndex].find('option').each(function(index, item) {\n var $item = $(item);\n options.eq($item.data('original-index')).data('_selected', $item.prop('selected'));\n });\n }\n\n function sortOptionsByInputOrder(select){\n var selectopt = select.children('option');\n\n selectopt.sort(function(a,b){\n var an = parseInt(a.getAttribute('data-sortindex')),\n bn = parseInt(b.getAttribute('data-sortindex'));\n\n if(an > bn) {\n return 1;\n }\n if(an < bn) {\n return -1;\n }\n return 0;\n });\n\n selectopt.detach().appendTo(select);\n }\n\n function sortOptions(select) {\n select.find('option').sort(function(a, b) {\n return ($(a).data('original-index') > $(b).data('original-index')) ? 1 : -1;\n }).appendTo(select);\n }\n\n function clearSelections(dualListbox) {\n dualListbox.elements.select1.find('option').each(function() {\n dualListbox.element.find('option').data('_selected', false);\n });\n }\n\n function move(dualListbox) {\n if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {\n saveSelections(dualListbox, 1);\n saveSelections(dualListbox, 2);\n } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {\n saveSelections(dualListbox, 1);\n }\n\n dualListbox.elements.select1.find('option:selected').each(function(index, item) {\n var $item = $(item);\n if (!$item.data('filtered1')) {\n changeSelectionState(dualListbox, $item.data('original-index'), true);\n }\n });\n\n refreshSelects(dualListbox);\n triggerChangeEvent(dualListbox);\n if(dualListbox.settings.sortByInputOrder){\n sortOptionsByInputOrder(dualListbox.elements.select2);\n } else {\n sortOptions(dualListbox.elements.select2);\n }\n }\n\n function remove(dualListbox) {\n if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {\n saveSelections(dualListbox, 1);\n saveSelections(dualListbox, 2);\n } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {\n saveSelections(dualListbox, 2);\n }\n\n dualListbox.elements.select2.find('option:selected').each(function(index, item) {\n var $item = $(item);\n if (!$item.data('filtered2')) {\n changeSelectionState(dualListbox, $item.data('original-index'), false);\n }\n });\n\n refreshSelects(dualListbox);\n triggerChangeEvent(dualListbox);\n sortOptions(dualListbox.elements.select1);\n }\n\n function moveAll(dualListbox) {\n if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {\n saveSelections(dualListbox, 1);\n saveSelections(dualListbox, 2);\n } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {\n saveSelections(dualListbox, 1);\n }\n\n dualListbox.element.find('option').each(function(index, item) {\n var $item = $(item);\n if (!$item.data('filtered1')) {\n $item.prop('selected', true);\n $item.attr('data-sortindex', dualListbox.sortIndex);\n dualListbox.sortIndex++;\n }\n });\n\n refreshSelects(dualListbox);\n triggerChangeEvent(dualListbox);\n }\n\n function removeAll(dualListbox) {\n if (dualListbox.settings.preserveSelectionOnMove === 'all' && !dualListbox.settings.moveOnSelect) {\n saveSelections(dualListbox, 1);\n saveSelections(dualListbox, 2);\n } else if (dualListbox.settings.preserveSelectionOnMove === 'moved' && !dualListbox.settings.moveOnSelect) {\n saveSelections(dualListbox, 2);\n }\n\n dualListbox.element.find('option').each(function(index, item) {\n var $item = $(item);\n if (!$item.data('filtered2')) {\n $item.prop('selected', false);\n $item.removeAttr(\"data-sortindex\");\n }\n });\n\n refreshSelects(dualListbox);\n triggerChangeEvent(dualListbox);\n }\n\n function bindEvents(dualListbox) {\n dualListbox.elements.form.submit(function(e) {\n if (dualListbox.elements.filterInput1.is(':focus')) {\n e.preventDefault();\n dualListbox.elements.filterInput1.focusout();\n } else if (dualListbox.elements.filterInput2.is(':focus')) {\n e.preventDefault();\n dualListbox.elements.filterInput2.focusout();\n }\n });\n\n dualListbox.element.on('bootstrapduallistbox.refresh', function(e, mustClearSelections){\n dualListbox.refresh(mustClearSelections);\n });\n\n dualListbox.elements.filterClear1.on('click', function() {\n dualListbox.setNonSelectedFilter('', true);\n });\n\n dualListbox.elements.filterClear2.on('click', function() {\n dualListbox.setSelectedFilter('', true);\n });\n\n dualListbox.elements.moveButton.on('click', function() {\n move(dualListbox);\n });\n\n dualListbox.elements.moveAllButton.on('click', function() {\n moveAll(dualListbox);\n });\n\n dualListbox.elements.removeButton.on('click', function() {\n remove(dualListbox);\n });\n\n dualListbox.elements.removeAllButton.on('click', function() {\n removeAll(dualListbox);\n });\n\n dualListbox.elements.filterInput1.on('change keyup', function() {\n filter(dualListbox, 1);\n });\n\n dualListbox.elements.filterInput2.on('change keyup', function() {\n filter(dualListbox, 2);\n });\n }\n\n bootstrapduallistbox.prototype = {\n init: function () {\n // Add the custom HTML template\n this.container = $('' +\n '
' +\n '
' +\n '
' +\n '
' +\n '
' +\n ' ' +\n ' ' +\n '
' +\n '
' +\n '
' +\n '
' +\n '
' +\n '
' +\n '
' +\n ' ' +\n ' ' +\n '
' +\n '
' +\n '
' +\n '
')\n .insertBefore(this.element);\n\n // Cache the inner elements\n this.elements = {\n originalSelect: this.element,\n box1: $('.box1', this.container),\n box2: $('.box2', this.container),\n filterInput1: $('.box1 .filter', this.container),\n filterInput2: $('.box2 .filter', this.container),\n filterClear1: $('.box1 .clear1', this.container),\n filterClear2: $('.box2 .clear2', this.container),\n label1: $('.box1 > label', this.container),\n label2: $('.box2 > label', this.container),\n info1: $('.box1 .info', this.container),\n info2: $('.box2 .info', this.container),\n select1: $('.box1 select', this.container),\n select2: $('.box2 select', this.container),\n moveButton: $('.box1 .move', this.container),\n removeButton: $('.box2 .remove', this.container),\n moveAllButton: $('.box1 .moveall', this.container),\n removeAllButton: $('.box2 .removeall', this.container),\n form: $($('.box1 .filter', this.container)[0].form)\n };\n\n // Set select IDs\n this.originalSelectName = this.element.attr('name') || '';\n var select1Id = 'bootstrap-duallistbox-nonselected-list_' + this.originalSelectName,\n select2Id = 'bootstrap-duallistbox-selected-list_' + this.originalSelectName;\n this.elements.select1.attr('id', select1Id);\n this.elements.select2.attr('id', select2Id);\n this.elements.label1.attr('for', select1Id);\n this.elements.label2.attr('for', select2Id);\n\n // Apply all settings\n this.selectedElements = 0;\n this.sortIndex = 0;\n this.elementCount = 0;\n this.setBootstrap2Compatible(this.settings.bootstrap2Compatible);\n this.setFilterTextClear(this.settings.filterTextClear);\n this.setFilterPlaceHolder(this.settings.filterPlaceHolder);\n this.setMoveSelectedLabel(this.settings.moveSelectedLabel);\n this.setMoveAllLabel(this.settings.moveAllLabel);\n this.setRemoveSelectedLabel(this.settings.removeSelectedLabel);\n this.setRemoveAllLabel(this.settings.removeAllLabel);\n this.setMoveOnSelect(this.settings.moveOnSelect);\n this.setPreserveSelectionOnMove(this.settings.preserveSelectionOnMove);\n this.setSelectedListLabel(this.settings.selectedListLabel);\n this.setNonSelectedListLabel(this.settings.nonSelectedListLabel);\n this.setHelperSelectNamePostfix(this.settings.helperSelectNamePostfix);\n this.setSelectOrMinimalHeight(this.settings.selectorMinimalHeight);\n\n updateSelectionStates(this);\n\n this.setShowFilterInputs(this.settings.showFilterInputs);\n this.setNonSelectedFilter(this.settings.nonSelectedFilter);\n this.setSelectedFilter(this.settings.selectedFilter);\n this.setInfoText(this.settings.infoText);\n this.setInfoTextFiltered(this.settings.infoTextFiltered);\n this.setInfoTextEmpty(this.settings.infoTextEmpty);\n this.setFilterOnValues(this.settings.filterOnValues);\n this.setSortByInputOrder(this.settings.sortByInputOrder);\n\n // Hide the original select\n this.element.hide();\n\n bindEvents(this);\n refreshSelects(this);\n\n return this.element;\n },\n setBootstrap2Compatible: function(value, refresh) {\n this.settings.bootstrap2Compatible = value;\n if (value) {\n this.container.removeClass('row').addClass('row-fluid bs2compatible');\n this.container.find('.box1, .box2').removeClass('col-md-6').addClass('span6');\n this.container.find('.clear1, .clear2').removeClass('btn-default btn-xs').addClass('btn-mini');\n this.container.find('input, select').removeClass('form-control');\n this.container.find('.btn').removeClass('btn-default');\n this.container.find('.moveall > i, .move > i').removeClass('glyphicon glyphicon-arrow-right').addClass('icon-arrow-right');\n this.container.find('.removeall > i, .remove > i').removeClass('glyphicon glyphicon-arrow-left').addClass('icon-arrow-left');\n } else {\n this.container.removeClass('row-fluid bs2compatible').addClass('row');\n this.container.find('.box1, .box2').removeClass('span6').addClass('col-md-6');\n this.container.find('.clear1, .clear2').removeClass('btn-mini').addClass('btn-default btn-xs');\n this.container.find('input, select').addClass('form-control');\n this.container.find('.btn').addClass('btn-default');\n this.container.find('.moveall > i, .move > i').removeClass('icon-arrow-right').addClass('glyphicon glyphicon-arrow-right');\n this.container.find('.removeall > i, .remove > i').removeClass('icon-arrow-left').addClass('glyphicon glyphicon-arrow-left');\n }\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n setFilterTextClear: function(value, refresh) {\n this.settings.filterTextClear = value;\n this.elements.filterClear1.html(value);\n this.elements.filterClear2.html(value);\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n setFilterPlaceHolder: function(value, refresh) {\n this.settings.filterPlaceHolder = value;\n this.elements.filterInput1.attr('placeholder', value);\n this.elements.filterInput2.attr('placeholder', value);\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n setMoveSelectedLabel: function(value, refresh) {\n this.settings.moveSelectedLabel = value;\n this.elements.moveButton.attr('title', value);\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n setMoveAllLabel: function(value, refresh) {\n this.settings.moveAllLabel = value;\n this.elements.moveAllButton.attr('title', value);\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n setRemoveSelectedLabel: function(value, refresh) {\n this.settings.removeSelectedLabel = value;\n this.elements.removeButton.attr('title', value);\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n setRemoveAllLabel: function(value, refresh) {\n this.settings.removeAllLabel = value;\n this.elements.removeAllButton.attr('title', value);\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n setMoveOnSelect: function(value, refresh) {\n if (isBuggyAndroid) {\n value = true;\n }\n this.settings.moveOnSelect = value;\n if (this.settings.moveOnSelect) {\n this.container.addClass('moveonselect');\n var self = this;\n this.elements.select1.on('change', function() {\n move(self);\n });\n this.elements.select2.on('change', function() {\n remove(self);\n });\n } else {\n this.container.removeClass('moveonselect');\n this.elements.select1.off('change');\n this.elements.select2.off('change');\n }\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n setPreserveSelectionOnMove: function(value, refresh) {\n // We are forcing to move on select and disabling preserveSelectionOnMove on Android\n if (isBuggyAndroid) {\n value = false;\n }\n this.settings.preserveSelectionOnMove = value;\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n setSelectedListLabel: function(value, refresh) {\n this.settings.selectedListLabel = value;\n if (value) {\n this.elements.label2.show().html(value);\n } else {\n this.elements.label2.hide().html(value);\n }\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n setNonSelectedListLabel: function(value, refresh) {\n this.settings.nonSelectedListLabel = value;\n if (value) {\n this.elements.label1.show().html(value);\n } else {\n this.elements.label1.hide().html(value);\n }\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n setHelperSelectNamePostfix: function(value, refresh) {\n this.settings.helperSelectNamePostfix = value;\n if (value) {\n this.elements.select1.attr('name', this.originalSelectName + value + '1');\n this.elements.select2.attr('name', this.originalSelectName + value + '2');\n } else {\n this.elements.select1.removeAttr(\"name\");\n this.elements.select2.removeAttr(\"name\");\n }\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n setSelectOrMinimalHeight: function(value, refresh) {\n this.settings.selectorMinimalHeight = value;\n var height = this.element.height();\n if (this.element.height() < value) {\n height = value;\n }\n this.elements.select1.height(height);\n this.elements.select2.height(height);\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n setShowFilterInputs: function(value, refresh) {\n if (!value) {\n this.setNonSelectedFilter('');\n this.setSelectedFilter('');\n refreshSelects(this);\n this.elements.filterInput1.hide();\n this.elements.filterInput2.hide();\n } else {\n this.elements.filterInput1.show();\n this.elements.filterInput2.show();\n }\n this.settings.showFilterInputs = value;\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n setNonSelectedFilter: function(value, refresh) {\n if (this.settings.showFilterInputs) {\n this.settings.nonSelectedFilter = value;\n this.elements.filterInput1.val(value);\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n }\n },\n setSelectedFilter: function(value, refresh) {\n if (this.settings.showFilterInputs) {\n this.settings.selectedFilter = value;\n this.elements.filterInput2.val(value);\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n }\n },\n setInfoText: function(value, refresh) {\n this.settings.infoText = value;\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n setInfoTextFiltered: function(value, refresh) {\n this.settings.infoTextFiltered = value;\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n setInfoTextEmpty: function(value, refresh) {\n this.settings.infoTextEmpty = value;\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n setFilterOnValues: function(value, refresh) {\n this.settings.filterOnValues = value;\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n setSortByInputOrder: function(value, refresh){\n this.settings.sortByInputOrder = value;\n if (refresh) {\n refreshSelects(this);\n }\n return this.element;\n },\n getContainer: function() {\n return this.container;\n },\n refresh: function(mustClearSelections) {\n updateSelectionStates(this);\n\n if (!mustClearSelections) {\n saveSelections(this, 1);\n saveSelections(this, 2);\n } else {\n clearSelections(this);\n }\n\n refreshSelects(this);\n },\n destroy: function() {\n this.container.remove();\n this.element.show();\n $.data(this, 'plugin_' + pluginName, null);\n return this.element;\n }\n };\n\n // A really lightweight plugin wrapper around the constructor,\n // preventing against multiple instantiations\n $.fn[ pluginName ] = function (options) {\n var args = arguments;\n\n // Is the first parameter an object (options), or was omitted, instantiate a new instance of the plugin.\n if (options === undefined || typeof options === 'object') {\n return this.each(function () {\n // If this is not a select\n if (!$(this).is('select')) {\n $(this).find('select').each(function(index, item) {\n // For each nested select, instantiate the Dual List Box\n $(item).bootstrapduallistbox(options);\n });\n } else if (!$.data(this, 'plugin_' + pluginName)) {\n // Only allow the plugin to be instantiated once so we check that the element has no plugin instantiation yet\n\n // if it has no instance, create a new one, pass options to our plugin constructor,\n // and store the plugin instance in the elements jQuery data object.\n $.data(this, 'plugin_' + pluginName, new bootstrapduallistbox(this, options));\n }\n });\n // If the first parameter is a string and it doesn't start with an underscore or \"contains\" the `init`-function,\n // treat this as a call to a public method.\n } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {\n\n // Cache the method call to make it possible to return a value\n var returns;\n\n this.each(function () {\n var instance = $.data(this, 'plugin_' + pluginName);\n // Tests that there's already a plugin-instance and checks that the requested public method exists\n if (instance instanceof bootstrapduallistbox && typeof instance[options] === 'function') {\n // Call the method of our plugin instance, and pass it the supplied arguments.\n returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));\n }\n });\n\n // If the earlier cached method gives a value back return the value,\n // otherwise return this to preserve chainability.\n return returns !== undefined ? returns : this;\n }\n\n };\n\n})(jQuery, window, document);\n","/*\n* jQuery File Download Plugin v1.3.3\n*\n* http://www.johnculviner.com\n*\n* Copyright (c) 2012 - John Culviner\n*\n* Licensed under the MIT license:\n* http://www.opensource.org/licenses/mit-license.php\n*/\n\nvar $ = jQuery.noConflict();\n\n$.extend({\n //\n //$.fileDownload('/path/to/url/', options)\n // see directly below for possible 'options'\n fileDownload: function (fileUrl, options) {\n\n var defaultFailCallback = function (responseHtml, url) {\n alert(\"A file download error has occurred, please try again.\");\n };\n\n //provide some reasonable defaults to any unspecified options below\n var settings = $.extend({\n\n //\n //Requires jQuery UI: provide a message to display to the user when the file download is being prepared before the browser's dialog appears\n //\n preparingMessageHtml: null,\n\n //\n //Requires jQuery UI: provide a message to display to the user when a file download fails\n //\n failMessageHtml: null,\n\n //\n //the stock android browser straight up doesn't support file downloads initiated by a non GET: http://code.google.com/p/android/issues/detail?id=1780\n //specify a message here to display if a user tries with an android browser\n //if jQuery UI is installed this will be a dialog, otherwise it will be an alert\n //\n androidPostUnsupportedMessageHtml: \"Unfortunately your Android browser doesn't support this type of file download. Please try again with a different browser.\",\n\n //\n //Requires jQuery UI: options to pass into jQuery UI Dialog\n //\n dialogOptions: { modal: true },\n\n //\n //a function to call after a file download dialog/ribbon has appeared\n //Args:\n // url - the original url attempted\n //\n successCallback: function (url) { },\n\n //\n //a function to call after a file download dialog/ribbon has appeared\n //Args:\n // responseHtml - the html that came back in response to the file download. this won't necessarily come back depending on the browser.\n // in less than IE9 a cross domain error occurs because 500+ errors cause a cross domain issue due to IE subbing out the\n // server's error message with a \"helpful\" IE built in message\n // url - the original url attempted\n //\n failCallback: defaultFailCallback,\n\n //\n // the HTTP method to use. Defaults to \"GET\".\n //\n httpMethod: \"GET\",\n\n //\n // if specified will perform a \"httpMethod\" request to the specified 'fileUrl' using the specified data.\n // data must be an object (which will be $.param serialized) or already a key=value param string\n //\n data: null,\n\n //\n //a period in milliseconds to poll to determine if a successful file download has occured or not\n //\n checkInterval: 100,\n\n //\n //the cookie name to indicate if a file download has occured\n //\n cookieName: \"fileDownload\",\n\n //\n //the cookie value for the above name to indicate that a file download has occured\n //\n cookieValue: \"true\",\n\n //\n //the cookie path for above name value pair\n //\n cookiePath: \"/\",\n\n //\n //the title for the popup second window as a download is processing in the case of a mobile browser\n //\n popupWindowTitle: \"Initiating file download...\",\n\n //\n //Functionality to encode HTML entities for a POST, need this if data is an object with properties whose values contains strings with quotation marks.\n //HTML entity encoding is done by replacing all &,<,>,',\",\\r,\\n characters.\n //Note that some browsers will POST the string htmlentity-encoded whilst others will decode it before POSTing.\n //It is recommended that on the server, htmlentity decoding is done irrespective.\n //\n encodeHTMLEntities: true\n }, options);\n\n\n //Setup mobile browser detection: Partial credit: http://detectmobilebrowser.com/\n var userAgent = (navigator.userAgent || navigator.vendor || window.opera).toLowerCase();\n\n var isIos = false; //has full support of features in iOS 4.0+, uses a new window to accomplish this.\n var isAndroid = false; //has full support of GET features in 4.0+ by using a new window. POST will resort to a POST on the current window.\n var isOtherMobileBrowser = false; //there is no way to reliably guess here so all other mobile devices will GET and POST to the current window.\n\n if (/ip(ad|hone|od)/.test(userAgent)) {\n\n isIos = true;\n\n } else if (userAgent.indexOf('android') != -1) {\n\n isAndroid = true;\n\n } else {\n\n isOtherMobileBrowser = /avantgo|bada\\/|blackberry|blazer|compal|elaine|fennec|hiptop|playbook|silk|iemobile|iris|kindle|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\\/|plucker|pocket|psp|symbian|treo|up\\.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(userAgent) || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\\-(n|u)|c55\\/|capi|ccwa|cdm\\-|cell|chtm|cldc|cmd\\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\\-s|devi|dica|dmob|do(c|p)o|ds(12|\\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\\-|_)|g1 u|g560|gene|gf\\-5|g\\-mo|go(\\.w|od)|gr(ad|un)|haie|hcit|hd\\-(m|p|t)|hei\\-|hi(pt|ta)|hp( i|ip)|hs\\-c|ht(c(\\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\\-(20|go|ma)|i230|iac( |\\-|\\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\\/)|klon|kpt |kwc\\-|kyo(c|k)|le(no|xi)|lg( g|\\/(k|l|u)|50|54|e\\-|e\\/|\\-[a-w])|libw|lynx|m1\\-w|m3ga|m50\\/|ma(te|ui|xo)|mc(01|21|ca)|m\\-cr|me(di|rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\\-2|po(ck|rt|se)|prox|psio|pt\\-g|qa\\-a|qc(07|12|21|32|60|\\-[2-7]|i\\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\\-|oo|p\\-)|sdk\\/|se(c(\\-|0|1)|47|mc|nd|ri)|sgh\\-|shar|sie(\\-|m)|sk\\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\\-|v\\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\\-|tdg\\-|tel(i|m)|tim\\-|t\\-mo|to(pl|sh)|ts(70|m\\-|m3|m5)|tx\\-9|up(\\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|xda(\\-|2|g)|yas\\-|your|zeto|zte\\-/i.test(userAgent.substr(0, 4));\n\n }\n\n var httpMethodUpper = settings.httpMethod.toUpperCase();\n\n if (isAndroid && httpMethodUpper != \"GET\") {\n //the stock android browser straight up doesn't support file downloads initiated by non GET requests: http://code.google.com/p/android/issues/detail?id=1780\n\n if ($().dialog) {\n $(\"
\").html(settings.androidPostUnsupportedMessageHtml).dialog(settings.dialogOptions);\n } else {\n alert(settings.androidPostUnsupportedMessageHtml);\n }\n\n return;\n }\n\n //wire up a jquery dialog to display the preparing message if specified\n var $preparingDialog = null;\n if (settings.preparingMessageHtml) {\n\n $preparingDialog = $(\"
\").html(settings.preparingMessageHtml).dialog(settings.dialogOptions);\n\n }\n\n var internalCallbacks = {\n\n onSuccess: function (url) {\n\n //remove the perparing message if it was specified\n if ($preparingDialog) {\n $preparingDialog.dialog('close');\n };\n\n settings.successCallback(url);\n\n },\n\n onFail: function (responseHtml, url) {\n\n //remove the perparing message if it was specified\n if ($preparingDialog) {\n $preparingDialog.dialog('close');\n };\n\n //wire up a jquery dialog to display the fail message if specified\n if (settings.failMessageHtml) {\n\n $(\"
\").html(settings.failMessageHtml).dialog(settings.dialogOptions);\n\n //only run the fallcallback if the developer specified something different than default\n //otherwise we would see two messages about how the file download failed\n if (settings.failCallback != defaultFailCallback) {\n settings.failCallback(responseHtml, url);\n }\n\n } else {\n\n settings.failCallback(responseHtml, url);\n }\n }\n };\n\n\n //make settings.data a param string if it exists and isn't already\n if (settings.data !== null && typeof settings.data !== \"string\") {\n settings.data = $.param(settings.data);\n }\n\n\n var $iframe,\n downloadWindow,\n formDoc,\n $form;\n\n if (httpMethodUpper === \"GET\") {\n\n if (settings.data !== null) {\n //need to merge any fileUrl params with the data object\n\n var qsStart = fileUrl.indexOf('?');\n\n if (qsStart != -1) {\n //we have a querystring in the url\n\n if (fileUrl.substring(fileUrl.length - 1) !== \"&\") {\n fileUrl = fileUrl + \"&\";\n }\n } else {\n\n fileUrl = fileUrl + \"?\";\n }\n\n fileUrl = fileUrl + settings.data;\n }\n\n if (isIos || isAndroid) {\n\n downloadWindow = window.open(fileUrl);\n downloadWindow.document.title = settings.popupWindowTitle;\n window.trigger('focus');\n\n } else if (isOtherMobileBrowser) {\n\n window.location(fileUrl);\n\n } else {\n\n //create a temporary iframe that is used to request the fileUrl as a GET request\n $iframe = $(\"