(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o 0) { // select by data-attribute this.selectBySelector(selector); item.removeData('selected'); item.removeAttr('data-selected'); } }, enable: function () { this.$element.removeClass('disabled'); this.$input.removeAttr('disabled'); this.$button.removeClass('disabled'); }, disable: function () { this.$element.addClass('disabled'); this.$input.attr('disabled', true); this.$button.addClass('disabled'); }, itemclicked: function (e) { this.$selectedItem = $(e.target).parent(); // set input text and trigger input change event marked as synthetic this.$input.val(this.$selectedItem.text().trim()).trigger('change', { synthetic: true }); // pass object including text and any data-attributes // to onchange event var data = this.selectedItem(); // trigger changed event this.$element.trigger('changed.fu.combobox', data); e.preventDefault(); // return focus to control after selecting an option this.$element.find('.dropdown-toggle').focus(); }, inputchanged: function (e, extra) { // skip processing for internally-generated synthetic event // to avoid double processing if (extra && extra.synthetic) return; var val = $(e.target).val(); this.selectByText(val); // find match based on input // if no match, pass the input value var data = this.selectedItem(); if (data.text.length === 0) { data = { text: val }; } // trigger changed event this.$element.trigger('changed.fu.combobox', data); } }; Combobox.prototype.getValue = Combobox.prototype.selectedItem; // COMBOBOX PLUGIN DEFINITION $.fn.combobox = function (option) { var args = Array.prototype.slice.call(arguments, 1); var methodReturn; var $set = this.each(function () { var $this = $(this); var data = $this.data('fu.combobox'); var options = typeof option === 'object' && option; if (!data) { $this.data('fu.combobox', (data = new Combobox(this, options))); } if (typeof option === 'string') { methodReturn = data[option].apply(data, args); } }); return (methodReturn === undefined) ? $set : methodReturn; }; $.fn.combobox.defaults = { autoResizeMenu: true }; $.fn.combobox.Constructor = Combobox; $.fn.combobox.noConflict = function () { $.fn.combobox = old; return this; }; // DATA-API $(document).on('mousedown.fu.combobox.data-api', '[data-initialize=combobox]', function (e) { var $control = $(e.target).closest('.combobox'); if (!$control.data('fu.combobox')) { $control.combobox($control.data()); } }); // Must be domReady for AMD compatibility $(function () { $('[data-initialize=combobox]').each(function () { var $this = $(this); if (!$this.data('fu.combobox')) { $this.combobox($this.data()); } }); }); // -- BEGIN UMD WRAPPER AFTERWORD -- })); // -- END UMD WRAPPER AFTERWORD -- },{"jquery":34}],4:[function(require,module,exports){ /* * Fuel UX Datepicker * https://github.com/ExactTarget/fuelux * * Copyright (c) 2014 ExactTarget * Licensed under the BSD New license. */ // -- BEGIN UMD WRAPPER PREFACE -- // For more information on UMD visit: // https://github.com/umdjs/umd/blob/master/jqueryPlugin.js (function (factory) { if (typeof define === 'function' && define.amd) { // if AMD loader is available, register as an anonymous module. define(['jquery'], factory); } else if (typeof exports === 'object') { // Node/CommonJS module.exports = factory(require('jquery'), require('moment')); } else { // OR use browser globals if AMD is not present factory(jQuery); } }(function ($) { // -- END UMD WRAPPER PREFACE -- // -- BEGIN MODULE CODE HERE -- var INVALID_DATE = 'Invalid Date'; var MOMENT_NOT_AVAILABLE = 'moment.js is not available so you cannot use this function'; var datepickerStack = []; var moment = false; var old = $.fn.datepicker; var requestedMoment = false; var runStack = function () { var i, l; requestedMoment = true; for (i = 0, l = datepickerStack.length; i < l; i++) { datepickerStack[i].init.call(datepickerStack[i].scope); } datepickerStack = []; }; //only load moment if it's there. otherwise we'll look for it in window.moment if (typeof define === 'function' && define.amd) {//check if AMD is available require(['moment'], function (amdMoment) { moment = amdMoment; runStack(); }, function (err) { var failedId = err.requireModules && err.requireModules[0]; if (failedId === 'moment') { runStack(); } }); } else { runStack(); } // DATEPICKER CONSTRUCTOR AND PROTOTYPE var Datepicker = function (element, options) { this.$element = $(element); this.options = $.extend(true, {}, $.fn.datepicker.defaults, options); this.$calendar = this.$element.find('.datepicker-calendar'); this.$days = this.$calendar.find('.datepicker-calendar-days'); this.$header = this.$calendar.find('.datepicker-calendar-header'); this.$headerTitle = this.$header.find('.title'); this.$input = this.$element.find('input'); this.$wheels = this.$element.find('.datepicker-wheels'); this.$wheelsMonth = this.$element.find('.datepicker-wheels-month'); this.$wheelsYear = this.$element.find('.datepicker-wheels-year'); this.artificialScrolling = false; this.formatDate = this.options.formatDate || this.formatDate; this.inputValue = null; this.moment = false; this.momentFormat = null; this.parseDate = this.options.parseDate || this.parseDate; this.preventBlurHide = false; this.restricted = this.options.restricted || []; this.restrictedParsed = []; this.restrictedText = this.options.restrictedText; this.sameYearOnly = this.options.sameYearOnly; this.selectedDate = null; this.yearRestriction = null; this.$calendar.find('.datepicker-today').on('click.fu.datepicker', $.proxy(this.todayClicked, this)); this.$days.on('click.fu.datepicker', 'tr td button', $.proxy(this.dateClicked, this)); this.$header.find('.next').on('click.fu.datepicker', $.proxy(this.next, this)); this.$header.find('.prev').on('click.fu.datepicker', $.proxy(this.prev, this)); this.$headerTitle.on('click.fu.datepicker', $.proxy(this.titleClicked, this)); this.$input.on('change.fu.datepicker', $.proxy(this.inputChanged, this)); this.$input.on('mousedown.fu.datepicker', $.proxy(this.showDropdown, this)); this.$wheels.find('.datepicker-wheels-back').on('click.fu.datepicker', $.proxy(this.backClicked, this)); this.$wheels.find('.datepicker-wheels-select').on('click.fu.datepicker', $.proxy(this.selectClicked, this)); this.$wheelsMonth.on('click.fu.datepicker', 'ul button', $.proxy(this.monthClicked, this)); this.$wheelsYear.on('click.fu.datepicker', 'ul button', $.proxy(this.yearClicked, this)); this.$wheelsYear.find('ul').on('scroll.fu.datepicker', $.proxy(this.onYearScroll, this)); var init = function () { if (this.checkForMomentJS()) { moment = moment || window.moment;// need to pull in the global moment if they didn't do it via require this.moment = true; this.momentFormat = this.options.momentConfig.format; this.setCulture(this.options.momentConfig.culture); // support moment with lang (< v2.8) or locale moment.locale = moment.locale || moment.lang; } this.setRestrictedDates(this.restricted); if (!this.setDate(this.options.date)) { this.$input.val(''); this.inputValue = this.$input.val(); } if (this.sameYearOnly) { this.yearRestriction = (this.selectedDate) ? this.selectedDate.getFullYear() : new Date().getFullYear(); } }; if (requestedMoment) { init.call(this); } else { datepickerStack.push({ init: init, scope: this }); } }; Datepicker.prototype = { constructor: Datepicker, backClicked: function () { this.changeView('calendar'); }, changeView: function (view, date) { if (view === 'wheels') { this.$calendar.hide().attr('aria-hidden', 'true'); this.$wheels.show().removeAttr('aria-hidden', ''); if (date) { this.renderWheel(date); } } else { this.$wheels.hide().attr('aria-hidden', 'true'); this.$calendar.show().removeAttr('aria-hidden', ''); if (date) { this.renderMonth(date); } } }, checkForMomentJS: function () { if ( ($.isFunction(window.moment) || (typeof moment !== 'undefined' && $.isFunction(moment))) && $.isPlainObject(this.options.momentConfig) && (typeof this.options.momentConfig.culture === 'string' && typeof this.options.momentConfig.format === 'string') ) { return true; } else { return false; } }, dateClicked: function (e) { var $td = $(e.currentTarget).parents('td:first'); var date; if ($td.hasClass('restricted')) { return; } this.$days.find('td.selected').removeClass('selected'); $td.addClass('selected'); date = new Date($td.attr('data-year'), $td.attr('data-month'), $td.attr('data-date')); this.selectedDate = date; this.$input.val(this.formatDate(date)); this.inputValue = this.$input.val(); this.hideDropdown(); this.$input.focus(); this.$element.trigger('dateClicked.fu.datepicker', date); }, destroy: function () { this.$element.remove(); // any external bindings // [none] // empty elements to return to original markup this.$days.find('tbody').empty(); this.$wheelsYear.find('ul').empty(); return this.$element[0].outerHTML; }, disable: function () { this.$element.addClass('disabled'); this.$element.find('input, button').attr('disabled', 'disabled'); this.$element.find('.input-group-btn').removeClass('open'); }, enable: function () { this.$element.removeClass('disabled'); this.$element.find('input, button').removeAttr('disabled'); }, formatDate: function (date) { var padTwo = function (value) { var s = '0' + value; return s.substr(s.length - 2); }; if (this.moment) { return moment(date).format(this.momentFormat); } else { return padTwo(date.getMonth() + 1) + '/' + padTwo(date.getDate()) + '/' + date.getFullYear(); } }, getCulture: function () { if (this.moment) { return moment.locale(); } else { throw MOMENT_NOT_AVAILABLE; } }, getDate: function () { return (!this.selectedDate) ? new Date(NaN) : this.selectedDate; }, getFormat: function () { if (this.moment) { return this.momentFormat; } else { throw MOMENT_NOT_AVAILABLE; } }, getFormattedDate: function () { return (!this.selectedDate) ? INVALID_DATE : this.formatDate(this.selectedDate); }, getRestrictedDates: function () { return this.restricted; }, inputChanged: function () { var inputVal = this.$input.val(); var date; if (inputVal !== this.inputValue) { date = this.setDate(inputVal); if (date === null) { this.$element.trigger('inputParsingFailed.fu.datepicker', inputVal); } else if (date === false) { this.$element.trigger('inputRestrictedDate.fu.datepicker', date); } else { this.$element.trigger('changed.fu.datepicker', date); } } }, showDropdown: function (e) { if (!this.$input.is(':focus')){ this.$element.find('.input-group-btn').addClass('open'); } }, hideDropdown: function () { this.$element.find('.input-group-btn').removeClass('open'); }, isInvalidDate: function (date) { var dateString = date.toString(); if (dateString === INVALID_DATE || dateString === 'NaN') { return true; } return false; }, isRestricted: function (date, month, year) { var restricted = this.restrictedParsed; var i, from, l, to; if (this.sameYearOnly && this.yearRestriction !== null && year !== this.yearRestriction) { return true; } for (i = 0, l = restricted.length; i < l; i++) { from = restricted[i].from; to = restricted[i].to; if ( (year > from.year || (year === from.year && month > from.month) || (year === from.year && month === from.month && date >= from.date)) && (year < to.year || (year === to.year && month < to.month) || (year === to.year && month === to.month && date <= to.date)) ) { return true; } } return false; }, monthClicked: function (e) { this.$wheelsMonth.find('.selected').removeClass('selected'); $(e.currentTarget).parent().addClass('selected'); }, next: function () { var month = this.$headerTitle.attr('data-month'); var year = this.$headerTitle.attr('data-year'); month++; if (month > 11) { if (this.sameYearOnly) { return; } month = 0; year++; } this.renderMonth(new Date(year, month, 1)); }, onYearScroll: function (e) { if (this.artificialScrolling) { return; } var $yearUl = $(e.currentTarget); var height = ($yearUl.css('box-sizing') === 'border-box') ? $yearUl.outerHeight() : $yearUl.height(); var scrollHeight = $yearUl.get(0).scrollHeight; var scrollTop = $yearUl.scrollTop(); var bottomPercentage = (height / (scrollHeight - scrollTop)) * 100; var topPercentage = (scrollTop / scrollHeight) * 100; var i, start; if (topPercentage < 5) { start = parseInt($yearUl.find('li:first').attr('data-year'), 10); for (i = (start - 1); i > (start - 11); i--) { $yearUl.prepend('
  • '); } this.artificialScrolling = true; $yearUl.scrollTop(($yearUl.get(0).scrollHeight - scrollHeight) + scrollTop); this.artificialScrolling = false; } else if (bottomPercentage > 90) { start = parseInt($yearUl.find('li:last').attr('data-year'), 10); for (i = (start + 1); i < (start + 11); i++) { $yearUl.append('
  • '); } } }, //some code ripped from https://stackoverflow.com/questions/2182246/javascript-dates-in-ie-nan-firefox-chrome-ok parseDate: function (date) { var self = this; var BAD_DATE = new Date(NaN); var dt, isoExp, momentParse, momentParseWithFormat, tryMomentParseAll, month, parts, use; if (date) { if (this.moment) {//if we have moment, use that to parse the dates momentParseWithFormat = function (d) { var md = moment(d, self.momentFormat); return (true === md.isValid()) ? md.toDate() : BAD_DATE; }; momentParse = function (d) { var md = moment(new Date(d)); return (true === md.isValid()) ? md.toDate() : BAD_DATE; }; tryMomentParseAll = function (d, parseFunc1, parseFunc2) { var pd = parseFunc1(d); if (!self.isInvalidDate(pd)) { return pd; } pd = parseFunc2(pd); if (!self.isInvalidDate(pd)) { return pd; } return BAD_DATE; }; if ('string' === typeof (date)) { // Attempts to parse date strings using this.momentFormat, falling back on newing a date return tryMomentParseAll(date, momentParseWithFormat, momentParse); } else { // Attempts to parse date by newing a date object directly, falling back on parsing using this.momentFormat return tryMomentParseAll(date, momentParse, momentParseWithFormat); } } else {//if moment isn't present, use previous date parsing strategy if (typeof (date) === 'string') { dt = new Date(Date.parse(date)); if (!this.isInvalidDate(dt)) { return dt; } else { date = date.split('T')[0]; isoExp = /^\s*(\d{4})-(\d\d)-(\d\d)\s*$/; parts = isoExp.exec(date); if (parts) { month = parseInt(parts[2], 10); dt = new Date(parts[1], month - 1, parts[3]); if (month === (dt.getMonth() + 1)) { return dt; } } } } else { dt = new Date(date); if (!this.isInvalidDate(dt)) { return dt; } } } } return new Date(NaN); }, prev: function () { var month = this.$headerTitle.attr('data-month'); var year = this.$headerTitle.attr('data-year'); month--; if (month < 0) { if (this.sameYearOnly) { return; } month = 11; year--; } this.renderMonth(new Date(year, month, 1)); }, renderMonth: function (date) { date = date || new Date(); var firstDay = new Date(date.getFullYear(), date.getMonth(), 1).getDay(); var lastDate = new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate(); var lastMonthDate = new Date(date.getFullYear(), date.getMonth(), 0).getDate(); var $month = this.$headerTitle.find('.month'); var month = date.getMonth(); var now = new Date(); var nowDate = now.getDate(); var nowMonth = now.getMonth(); var nowYear = now.getFullYear(); var selected = this.selectedDate; var $tbody = this.$days.find('tbody'); var year = date.getFullYear(); var curDate, curMonth, curYear, i, j, rows, stage, previousStage, lastStage, $td, $tr; if (selected) { selected = { date: selected.getDate(), month: selected.getMonth(), year: selected.getFullYear() }; } $month.find('.current').removeClass('current'); $month.find('span[data-month="' + month + '"]').addClass('current'); this.$headerTitle.find('.year').text(year); this.$headerTitle.attr({ 'data-month': month, 'data-year': year }); $tbody.empty(); if (firstDay !== 0) { curDate = lastMonthDate - firstDay + 1; stage = -1; } else { curDate = 1; stage = 0; } rows = (lastDate <= (35 - firstDay)) ? 5 : 6; for (i = 0; i < rows; i++) { $tr = $(''); for (j = 0; j < 7; j++) { $td = $(''); if (stage === -1) { $td.addClass('last-month'); if (previousStage !== stage) { $td.addClass('first'); } } else if (stage === 1) { $td.addClass('next-month'); if (previousStage !== stage) { $td.addClass('first'); } } curMonth = month + stage; curYear = year; if (curMonth < 0) { curMonth = 11; curYear--; } else if (curMonth > 11) { curMonth = 0; curYear++; } $td.attr({ 'data-date': curDate, 'data-month': curMonth, 'data-year': curYear }); if (curYear === nowYear && curMonth === nowMonth && curDate === nowDate) { $td.addClass('current-day'); } else if (curYear < nowYear || (curYear === nowYear && curMonth < nowMonth) || (curYear === nowYear && curMonth === nowMonth && curDate < nowDate)) { $td.addClass('past'); if (!this.options.allowPastDates) { $td.addClass('restricted').attr('title', this.restrictedText); } } if (this.isRestricted(curDate, curMonth, curYear)) { $td.addClass('restricted').attr('title', this.restrictedText); } if (selected && curYear === selected.year && curMonth === selected.month && curDate === selected.date) { $td.addClass('selected'); } if ($td.hasClass('restricted')) { $td.html('' + curDate + ''); } else { $td.html(''); } curDate++; lastStage = previousStage; previousStage = stage; if (stage === -1 && curDate > lastMonthDate) { curDate = 1; stage = 0; if (lastStage !== stage) { $td.addClass('last'); } } else if (stage === 0 && curDate > lastDate) { curDate = 1; stage = 1; if (lastStage !== stage) { $td.addClass('last'); } } if (i === (rows - 1) && j === 6) { $td.addClass('last'); } $tr.append($td); } $tbody.append($tr); } }, renderWheel: function (date) { var month = date.getMonth(); var $monthUl = this.$wheelsMonth.find('ul'); var year = date.getFullYear(); var $yearUl = this.$wheelsYear.find('ul'); var i, $monthSelected, $yearSelected; if (this.sameYearOnly) { this.$wheelsMonth.addClass('full'); this.$wheelsYear.addClass('hidden'); } else { this.$wheelsMonth.removeClass('full'); this.$wheelsYear.removeClass('hide hidden'); // .hide is deprecated } $monthUl.find('.selected').removeClass('selected'); $monthSelected = $monthUl.find('li[data-month="' + month + '"]'); $monthSelected.addClass('selected'); $monthUl.scrollTop($monthUl.scrollTop() + ($monthSelected.position().top - $monthUl.outerHeight() / 2 - $monthSelected.outerHeight(true) / 2)); $yearUl.empty(); for (i = (year - 10); i < (year + 11); i++) { $yearUl.append('
  • '); } $yearSelected = $yearUl.find('li[data-year="' + year + '"]'); $yearSelected.addClass('selected'); this.artificialScrolling = true; $yearUl.scrollTop($yearUl.scrollTop() + ($yearSelected.position().top - $yearUl.outerHeight() / 2 - $yearSelected.outerHeight(true) / 2)); this.artificialScrolling = false; $monthSelected.find('button').focus(); }, selectClicked: function () { var month = this.$wheelsMonth.find('.selected').attr('data-month'); var year = this.$wheelsYear.find('.selected').attr('data-year'); this.changeView('calendar', new Date(year, month, 1)); }, setCulture: function (cultureCode) { if (!cultureCode) { return false; } if (this.moment) { moment.locale(cultureCode); } else { throw MOMENT_NOT_AVAILABLE; } }, setDate: function (date) { var parsed = this.parseDate(date); if (!this.isInvalidDate(parsed)) { if (!this.isRestricted(parsed.getDate(), parsed.getMonth(), parsed.getFullYear())) { this.selectedDate = parsed; this.renderMonth(parsed); this.$input.val(this.formatDate(parsed)); } else { this.selectedDate = false; this.renderMonth(); } } else { this.selectedDate = null; this.renderMonth(); } this.inputValue = this.$input.val(); return this.selectedDate; }, setFormat: function (format) { if (!format) { return false; } if (this.moment) { this.momentFormat = format; } else { throw MOMENT_NOT_AVAILABLE; } }, setRestrictedDates: function (restricted) { var parsed = []; var self = this; var i, l; var parseItem = function (val) { if (val === -Infinity) { return { date: -Infinity, month: -Infinity, year: -Infinity }; } else if (val === Infinity) { return { date: Infinity, month: Infinity, year: Infinity }; } else { val = self.parseDate(val); return { date: val.getDate(), month: val.getMonth(), year: val.getFullYear() }; } }; this.restricted = restricted; for (i = 0, l = restricted.length; i < l; i++) { parsed.push({ from: parseItem(restricted[i].from), to: parseItem(restricted[i].to) }); } this.restrictedParsed = parsed; }, titleClicked: function (e) { this.changeView('wheels', new Date(this.$headerTitle.attr('data-year'), this.$headerTitle.attr('data-month'), 1)); }, todayClicked: function (e) { var date = new Date(); if ((date.getMonth() + '') !== this.$headerTitle.attr('data-month') || (date.getFullYear() + '') !== this.$headerTitle.attr('data-year')) { this.renderMonth(date); } }, yearClicked: function (e) { this.$wheelsYear.find('.selected').removeClass('selected'); $(e.currentTarget).parent().addClass('selected'); } }; //for control library consistency Datepicker.prototype.getValue = Datepicker.prototype.getDate; // DATEPICKER PLUGIN DEFINITION $.fn.datepicker = function (option) { var args = Array.prototype.slice.call(arguments, 1); var methodReturn; var $set = this.each(function () { var $this = $(this); var data = $this.data('fu.datepicker'); var options = typeof option === 'object' && option; if (!data) { $this.data('fu.datepicker', (data = new Datepicker(this, options))); } if (typeof option === 'string') { methodReturn = data[option].apply(data, args); } }); return (methodReturn === undefined) ? $set : methodReturn; }; $.fn.datepicker.defaults = { allowPastDates: false, date: new Date(), formatDate: null, momentConfig: { culture: 'en', format: 'L'// more formats can be found here https://momentjs.com/docs/#/customization/long-date-formats/. }, parseDate: null, restricted: [],//accepts an array of objects formatted as so: { from: {{date}}, to: {{date}} } (ex: [ { from: new Date('12/11/2014'), to: new Date('03/31/2015') } ]) restrictedText: 'Restricted', sameYearOnly: false }; $.fn.datepicker.Constructor = Datepicker; $.fn.datepicker.noConflict = function () { $.fn.datepicker = old; return this; }; // DATA-API $(document).on('mousedown.fu.datepicker.data-api', '[data-initialize=datepicker]', function (e) { var $control = $(e.target).closest('.datepicker'); if (!$control.data('datepicker')) { $control.datepicker($control.data()); } }); //used to prevent the dropdown from closing when clicking within it's bounds $(document).on('click.fu.datepicker.data-api', '.datepicker .dropdown-menu', function (e) { var $target = $(e.target); if (!$target.is('.datepicker-date') || $target.closest('.restricted').length) { e.stopPropagation(); } }); //used to prevent the dropdown from closing when clicking on the input $(document).on('click.fu.datepicker.data-api', '.datepicker input', function (e) { e.stopPropagation(); }); $(function () { $('[data-initialize=datepicker]').each(function () { var $this = $(this); if ($this.data('datepicker')) { return; } $this.datepicker($this.data()); }); }); // -- BEGIN UMD WRAPPER AFTERWORD -- })); // -- END UMD WRAPPER AFTERWORD -- },{"jquery":34,"moment":35}],5:[function(require,module,exports){ /* * Fuel UX Dropdown Auto Flip * https://github.com/ExactTarget/fuelux * * Copyright (c) 2014 ExactTarget * Licensed under the BSD New license. */ // -- BEGIN UMD WRAPPER PREFACE -- // For more information on UMD visit: // https://github.com/umdjs/umd/blob/master/jqueryPlugin.js (function (factory) { if (typeof define === 'function' && define.amd) { // if AMD loader is available, register as an anonymous module. define(['jquery'], factory); } else if (typeof exports === 'object') { // Node/CommonJS module.exports = factory(require('jquery')); } else { // OR use browser globals if AMD is not present factory(jQuery); } }(function ($) { // -- END UMD WRAPPER PREFACE -- // -- BEGIN MODULE CODE HERE -- $(document.body).on('click.fu.dropdown-autoflip', '[data-toggle=dropdown][data-flip]', function (event) { if ($(this).data().flip === "auto") { // have the drop down decide where to place itself _autoFlip($(this).next('.dropdown-menu')); } }); // For pillbox suggestions dropdown $(document.body).on('suggested.fu.pillbox', function (event, element) { _autoFlip($(element)); $(element).parent().addClass('open'); }); function _autoFlip(menu) { // hide while the browser thinks $(menu).css({ visibility: "hidden" }); // decide where to put menu if (dropUpCheck(menu)) { menu.parent().addClass("dropup"); } else { menu.parent().removeClass("dropup"); } // show again $(menu).css({ visibility: "visible" }); } function dropUpCheck(element) { // caching container var $container = _getContainer(element); // building object with measurementsances for later use var measurements = {}; measurements.parentHeight = element.parent().outerHeight(); measurements.parentOffsetTop = element.parent().offset().top; measurements.dropdownHeight = element.outerHeight(); measurements.containerHeight = $container.overflowElement.outerHeight(); // this needs to be different if the window is the container or another element is measurements.containerOffsetTop = (!!$container.isWindow) ? $container.overflowElement.scrollTop() : $container.overflowElement.offset().top; // doing the calculations measurements.fromTop = measurements.parentOffsetTop - measurements.containerOffsetTop; measurements.fromBottom = measurements.containerHeight - measurements.parentHeight - (measurements.parentOffsetTop - measurements.containerOffsetTop); // actual determination of where to put menu // false = drop down // true = drop up if (measurements.dropdownHeight < measurements.fromBottom) { return false; } else if (measurements.dropdownHeight < measurements.fromTop) { return true; } else if (measurements.dropdownHeight >= measurements.fromTop && measurements.dropdownHeight >= measurements.fromBottom) { // decide which one is bigger and put it there if (measurements.fromTop >= measurements.fromBottom) { return true; } else { return false; } } } function _getContainer(element) { var containerElement, isWindow; if (element.attr('data-target')) { containerElement = element.attr('data-target'); isWindow = false; } else { containerElement = window; isWindow = true; } $.each(element.parents(), function (index, value) { if ($(value).css('overflow') !== 'visible') { containerElement = value; isWindow = false; return false; } }); return { overflowElement: $(containerElement), isWindow: isWindow }; } // register empty plugin $.fn.dropdownautoflip = function () { /* empty */ }; // -- BEGIN UMD WRAPPER AFTERWORD -- })); // -- END UMD WRAPPER AFTERWORD -- },{"jquery":34}],6:[function(require,module,exports){ /* * Fuel UX Infinite Scroll * https://github.com/ExactTarget/fuelux * * Copyright (c) 2014 ExactTarget * Licensed under the BSD New license. */ // -- BEGIN UMD WRAPPER PREFACE -- // For more information on UMD visit: // https://github.com/umdjs/umd/blob/master/jqueryPlugin.js (function (factory) { if (typeof define === 'function' && define.amd) { // if AMD loader is available, register as an anonymous module. define(['jquery', 'fuelux/loader'], factory); } else if (typeof exports === 'object') { // Node/CommonJS module.exports = factory(require('jquery')); } else { // OR use browser globals if AMD is not present factory(jQuery); } }(function ($) { // -- END UMD WRAPPER PREFACE -- // -- BEGIN MODULE CODE HERE -- var old = $.fn.infinitescroll; // INFINITE SCROLL CONSTRUCTOR AND PROTOTYPE var InfiniteScroll = function (element, options) { this.$element = $(element); this.$element.addClass('infinitescroll'); this.options = $.extend({}, $.fn.infinitescroll.defaults, options); this.curScrollTop = this.$element.scrollTop(); this.curPercentage = this.getPercentage(); this.fetchingData = false; this.$element.on('scroll.fu.infinitescroll', $.proxy(this.onScroll, this)); this.onScroll(); }; InfiniteScroll.prototype = { constructor: InfiniteScroll, destroy: function () { this.$element.remove(); // any external bindings // [none] // empty elements to return to original markup this.$element.empty(); return this.$element[0].outerHTML; }, disable: function () { this.$element.off('scroll.fu.infinitescroll'); }, enable: function () { this.$element.on('scroll.fu.infinitescroll', $.proxy(this.onScroll, this)); }, end: function (content) { var end = $('
    '); if (content) { end.append(content); } else { end.append('---------'); } this.$element.append(end); this.disable(); }, getPercentage: function () { var height = (this.$element.css('box-sizing') === 'border-box') ? this.$element.outerHeight() : this.$element.height(); var scrollHeight = this.$element.get(0).scrollHeight; return (scrollHeight > height) ? ((height / (scrollHeight - this.curScrollTop)) * 100) : 0; }, fetchData: function (force) { var load = $('
    '); var self = this; var moreBtn; var fetch = function () { var helpers = { percentage: self.curPercentage, scrollTop: self.curScrollTop }; var $loader = $('
    '); load.append($loader); $loader.loader(); if (self.options.dataSource) { self.options.dataSource(helpers, function (resp) { var end; load.remove(); if (resp.content) { self.$element.append(resp.content); } if (resp.end) { end = (resp.end !== true) ? resp.end : undefined; self.end(end); } self.fetchingData = false; }); } }; this.fetchingData = true; this.$element.append(load); if (this.options.hybrid && force !== true) { moreBtn = $(''); if (typeof this.options.hybrid === 'object') { moreBtn.append(this.options.hybrid.label); } else { moreBtn.append(''); } moreBtn.on('click.fu.infinitescroll', function () { moreBtn.remove(); fetch(); }); load.append(moreBtn); } else { fetch(); } }, onScroll: function (e) { this.curScrollTop = this.$element.scrollTop(); this.curPercentage = this.getPercentage(); if (!this.fetchingData && this.curPercentage >= this.options.percentage) { this.fetchData(); } } }; // INFINITE SCROLL PLUGIN DEFINITION $.fn.infinitescroll = function (option) { var args = Array.prototype.slice.call(arguments, 1); var methodReturn; var $set = this.each(function () { var $this = $(this); var data = $this.data('fu.infinitescroll'); var options = typeof option === 'object' && option; if (!data) { $this.data('fu.infinitescroll', (data = new InfiniteScroll(this, options))); } if (typeof option === 'string') { methodReturn = data[option].apply(data, args); } }); return (methodReturn === undefined) ? $set : methodReturn; }; $.fn.infinitescroll.defaults = { dataSource: null, hybrid: false,//can be true or an object with structure: { 'label': (markup or jQuery obj) } percentage: 95//percentage scrolled to the bottom before more is loaded }; $.fn.infinitescroll.Constructor = InfiniteScroll; $.fn.infinitescroll.noConflict = function () { $.fn.infinitescroll = old; return this; }; // NO DATA-API DUE TO NEED OF DATA-SOURCE // -- BEGIN UMD WRAPPER AFTERWORD -- })); // -- END UMD WRAPPER AFTERWORD -- },{"jquery":34}],7:[function(require,module,exports){ /* * Fuel UX Loader * https://github.com/ExactTarget/fuelux * * Copyright (c) 2014 ExactTarget * Licensed under the BSD New license. */ // -- BEGIN UMD WRAPPER PREFACE -- // For more information on UMD visit: // https://github.com/umdjs/umd/blob/master/jqueryPlugin.js (function (factory) { if (typeof define === 'function' && define.amd) { // if AMD loader is available, register as an anonymous module. define(['jquery'], factory); } else if (typeof exports === 'object') { // Node/CommonJS module.exports = factory(require('jquery')); } else { // OR use browser globals if AMD is not present factory(jQuery); } }(function ($) { // -- END UMD WRAPPER PREFACE -- // -- BEGIN MODULE CODE HERE -- var old = $.fn.loader; // LOADER CONSTRUCTOR AND PROTOTYPE var Loader = function (element, options) { this.$element = $(element); this.options = $.extend({}, $.fn.loader.defaults, options); this.begin = (this.$element.is('[data-begin]')) ? parseInt(this.$element.attr('data-begin'), 10) : 1; this.delay = (this.$element.is('[data-delay]')) ? parseFloat(this.$element.attr('data-delay')) : 150; this.end = (this.$element.is('[data-end]')) ? parseInt(this.$element.attr('data-end'), 10) : 8; this.frame = (this.$element.is('[data-frame]')) ? parseInt(this.$element.attr('data-frame'), 10) : this.begin; this.isIElt9 = false; this.timeout = {}; var ieVer = this.msieVersion(); if (ieVer !== false && ieVer < 9) { this.$element.addClass('iefix'); this.isIElt9 = true; } this.$element.attr('data-frame', this.frame + ''); this.play(); }; Loader.prototype = { constructor: Loader, destroy: function () { this.pause(); this.$element.remove(); // any external bindings // [none] // empty elements to return to original markup // [none] // returns string of markup return this.$element[0].outerHTML; }, ieRepaint: function () { if (this.isIElt9) { this.$element.addClass('iefix_repaint').removeClass('iefix_repaint'); } }, msieVersion: function () { var ua = window.navigator.userAgent; var msie = ua.indexOf('MSIE '); if (msie > 0) { return parseInt(ua.substring(msie + 5, ua.indexOf(".", msie)), 10); } else { return false; } }, next: function () { this.frame++; if (this.frame > this.end) { this.frame = this.begin; } this.$element.attr('data-frame', this.frame + ''); this.ieRepaint(); }, pause: function () { clearTimeout(this.timeout); }, play: function () { var self = this; clearTimeout(this.timeout); this.timeout = setTimeout(function () { self.next(); self.play(); }, this.delay); }, previous: function () { this.frame--; if (this.frame < this.begin) { this.frame = this.end; } this.$element.attr('data-frame', this.frame + ''); this.ieRepaint(); }, reset: function () { this.frame = this.begin; this.$element.attr('data-frame', this.frame + ''); this.ieRepaint(); } }; // LOADER PLUGIN DEFINITION $.fn.loader = function (option) { var args = Array.prototype.slice.call(arguments, 1); var methodReturn; var $set = this.each(function () { var $this = $(this); var data = $this.data('fu.loader'); var options = typeof option === 'object' && option; if (!data) { $this.data('fu.loader', (data = new Loader(this, options))); } if (typeof option === 'string') { methodReturn = data[option].apply(data, args); } }); return (methodReturn === undefined) ? $set : methodReturn; }; $.fn.loader.defaults = {}; $.fn.loader.Constructor = Loader; $.fn.loader.noConflict = function () { $.fn.loader = old; return this; }; // INIT LOADER ON DOMCONTENTLOADED $(function () { $('[data-initialize=loader]').each(function () { var $this = $(this); if (!$this.data('fu.loader')) { $this.loader($this.data()); } }); }); // -- BEGIN UMD WRAPPER AFTERWORD -- })); // -- END UMD WRAPPER AFTERWORD -- },{"jquery":34}],8:[function(require,module,exports){ /* * Fuel UX Picker * https://github.com/ExactTarget/fuelux * * Copyright (c) 2014 ExactTarget * Licensed under the BSD New license. */ // -- BEGIN UMD WRAPPER PREFACE -- // For more information on UMD visit: // https://github.com/umdjs/umd/blob/master/jqueryPlugin.js (function (factory) { if (typeof define === 'function' && define.amd) { // if AMD loader is available, register as an anonymous module. define(['jquery'], factory); } else if (typeof exports === 'object') { // Node/CommonJS module.exports = factory(require('jquery')); } else { // OR use browser globals if AMD is not present factory(jQuery); } }(function ($) { // -- END UMD WRAPPER PREFACE -- // -- BEGIN MODULE CODE HERE -- var old = $.fn.picker; // PLACARD CONSTRUCTOR AND PROTOTYPE var Picker = function Picker(element, options) { var self = this; this.$element = $(element); this.options = $.extend({}, $.fn.picker.defaults, options); this.$accept = this.$element.find('.picker-accept'); this.$cancel = this.$element.find('.picker-cancel'); this.$trigger = this.$element.find('.picker-trigger'); this.$footer = this.$element.find('.picker-footer'); this.$header = this.$element.find('.picker-header'); this.$popup = this.$element.find('.picker-popup'); this.$body = this.$element.find('.picker-body'); this.clickStamp = '_'; this.isInput = this.$trigger.is('input'); this.$trigger.on('keydown.fu.picker', $.proxy(this.keyComplete, this)); this.$trigger.on('focus.fu.picker', $.proxy(function inputFocus(e){ if(typeof e === "undefined" || $(e.target).is('input[type=text]')){ $.proxy(this.show(), this); } }, this)); this.$trigger.on('click.fu.picker', $.proxy(function triggerClick(e){ if(!$(e.target).is('input[type=text]')){ $.proxy(this.toggle(), this); }else{ $.proxy(this.show(), this); } }, this)); this.$accept.on('click.fu.picker', $.proxy(this.complete, this, 'accepted')); this.$cancel.on('click.fu.picker', function (e) { e.preventDefault(); self.complete('cancelled'); }); }; var _isOffscreen = function _isOffscreen(picker) { var windowHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); var scrollTop = $(document).scrollTop(); var popupTop = picker.$popup.offset(); var popupBottom = popupTop.top + picker.$popup.outerHeight(true); //if the bottom of the popup goes off the page, but the top does not, dropup. if (popupBottom > windowHeight + scrollTop || popupTop.top < scrollTop){ return true; }else{//otherwise, prefer showing the top of the popup only vs the bottom return false; } }; var _display = function _display(picker) { picker.$popup.css('visibility', 'hidden'); _showBelow(picker); //if part of the popup is offscreen try to show it above if(_isOffscreen(picker)){ _showAbove(picker); //if part of the popup is still offscreen, prefer cutting off the bottom if(_isOffscreen(picker)){ _showBelow(picker); } } picker.$popup.css('visibility', 'visible'); }; var _showAbove = function _showAbove(picker) { picker.$popup.css('top', - picker.$popup.outerHeight(true) + 'px'); }; var _showBelow = function _showBelow(picker) { picker.$popup.css('top', picker.$trigger.outerHeight(true) + 'px'); }; Picker.prototype = { constructor: Picker, complete: function complete(action) { var EVENT_CALLBACK_MAP = { 'accepted': 'onAccept', 'cancelled': 'onCancel', 'exited': 'onExit' }; var func = this.options[ EVENT_CALLBACK_MAP[action] ]; var obj = { contents: this.$body }; if (func) { func(obj); this.$element.trigger(action + '.fu.picker', obj); } else { this.$element.trigger(action + '.fu.picker', obj); this.hide(); } }, keyComplete: function keyComplete(e) { if (this.isInput && e.keyCode === 13) { this.complete('accepted'); this.$trigger.blur(); } else if (e.keyCode === 27) { this.complete('exited'); this.$trigger.blur(); } }, destroy: function destroy() { this.$element.remove(); // remove any external bindings $(document).off('click.fu.picker.externalClick.' + this.clickStamp); // empty elements to return to original markup // [none] // return string of markup return this.$element[0].outerHTML; }, disable: function disable() { this.$element.addClass('disabled'); this.$trigger.attr('disabled', 'disabled'); }, enable: function enable() { this.$element.removeClass('disabled'); this.$trigger.removeAttr('disabled'); }, toggle: function toggle() { if (this.$element.hasClass('showing')) { this.hide(); }else{ this.show(); } }, hide: function hide() { if (!this.$element.hasClass('showing')) { return; } this.$element.removeClass('showing'); $(document).off('click.fu.picker.externalClick.' + this.clickStamp); this.$element.trigger('hidden.fu.picker'); }, externalClickListener: function externalClickListener(e, force) { if (force === true || this.isExternalClick(e)) { this.complete('exited'); } }, isExternalClick: function isExternalClick(e) { var el = this.$element.get(0); var exceptions = this.options.externalClickExceptions || []; var $originEl = $(e.target); var i, l; if (e.target === el || $originEl.parents('.picker:first').get(0) === el) { return false; } else { for (i = 0, l = exceptions.length; i < l; i++) { if ($originEl.is(exceptions[i]) || $originEl.parents(exceptions[i]).length > 0) { return false; } } } return true; }, show: function show() { var other; other = $(document).find('.picker.showing'); if (other.length > 0) { if (other.data('fu.picker') && other.data('fu.picker').options.explicit) { return; } other.picker('externalClickListener', {}, true); } this.$element.addClass('showing'); _display(this); this.$element.trigger('shown.fu.picker'); this.clickStamp = new Date().getTime() + (Math.floor(Math.random() * 100) + 1); if (!this.options.explicit) { $(document).on('click.fu.picker.externalClick.' + this.clickStamp, $.proxy(this.externalClickListener, this)); } } }; // PLACARD PLUGIN DEFINITION $.fn.picker = function picker(option) { var args = Array.prototype.slice.call(arguments, 1); var methodReturn; var $set = this.each(function () { var $this = $(this); var data = $this.data('fu.picker'); var options = typeof option === 'object' && option; if (!data) { $this.data('fu.picker', (data = new Picker(this, options))); } if (typeof option === 'string') { methodReturn = data[option].apply(data, args); } }); return (methodReturn === undefined) ? $set : methodReturn; }; $.fn.picker.defaults = { onAccept: undefined, onCancel: undefined, onExit: undefined, externalClickExceptions: [], explicit: false }; $.fn.picker.Constructor = Picker; $.fn.picker.noConflict = function noConflict() { $.fn.picker = old; return this; }; // DATA-API $(document).on('focus.fu.picker.data-api', '[data-initialize=picker]', function (e) { var $control = $(e.target).closest('.picker'); if (!$control.data('fu.picker')) { $control.picker($control.data()); } }); // Must be domReady for AMD compatibility $(function () { $('[data-initialize=picker]').each(function () { var $this = $(this); if ($this.data('fu.picker')) return; $this.picker($this.data()); }); }); // -- BEGIN UMD WRAPPER AFTERWORD -- })); // -- END UMD WRAPPER AFTERWORD -- },{"jquery":34}],9:[function(require,module,exports){ /* * Fuel UX Pillbox * https://github.com/ExactTarget/fuelux * * Copyright (c) 2014 ExactTarget * Licensed under the BSD New license. */ // -- BEGIN UMD WRAPPER PREFACE -- // For more information on UMD visit: // https://github.com/umdjs/umd/blob/master/jqueryPlugin.js (function (factory) { if (typeof define === 'function' && define.amd) { // if AMD loader is available, register as an anonymous module. define(['jquery', 'fuelux/dropdown-autoflip'], factory); } else if (typeof exports === 'object') { // Node/CommonJS module.exports = factory(require('jquery')); } else { // OR use browser globals if AMD is not present factory(jQuery); } }(function ($) { if (!$.fn.dropdownautoflip) { throw new Error('Fuel UX pillbox control requires dropdown-autoflip.'); } // -- END UMD WRAPPER PREFACE -- // -- BEGIN MODULE CODE HERE -- var old = $.fn.pillbox; // PILLBOX CONSTRUCTOR AND PROTOTYPE var Pillbox = function (element, options) { this.$element = $(element); this.$moreCount = this.$element.find('.pillbox-more-count'); this.$pillGroup = this.$element.find('.pill-group'); this.$addItem = this.$element.find('.pillbox-add-item'); this.$addItemWrap = this.$addItem.parent(); this.$suggest = this.$element.find('.suggest'); this.$pillHTML = '
  • ' + ' ' + ' ' + ' Remove' + ' ' + '
  • '; this.options = $.extend({}, $.fn.pillbox.defaults, options); if (this.options.readonly === -1) { if (this.$element.attr('data-readonly') !== undefined) { this.readonly(true); } } else if (this.options.readonly) { this.readonly(true); } // EVENTS this.acceptKeyCodes = this._generateObject(this.options.acceptKeyCodes); // Creatie an object out of the key code array, so we dont have to loop through it on every key stroke this.$element.on('click.fu.pillbox', '.pill-group > .pill', $.proxy(this.itemClicked, this)); this.$element.on('click.fu.pillbox', $.proxy(this.inputFocus, this)); this.$element.on('keydown.fu.pillbox', '.pillbox-add-item', $.proxy(this.inputEvent, this)); if (this.options.onKeyDown) { this.$element.on('mousedown.fu.pillbox', '.suggest > li', $.proxy(this.suggestionClick, this)); } if (this.options.edit) { this.$element.addClass('pills-editable'); this.$element.on('blur.fu.pillbox', '.pillbox-add-item', $.proxy(this.cancelEdit, this)); } }; Pillbox.prototype = { constructor: Pillbox, destroy: function () { this.$element.remove(); // any external bindings // [none] // empty elements to return to original markup // [none] // returns string of markup return this.$element[0].outerHTML; }, items: function () { var self = this; return this.$pillGroup.children('.pill').map(function () { return self.getItemData($(this)); }).get(); }, itemClicked: function (e) { var self = this; var $target = $(e.target); var $item; e.preventDefault(); e.stopPropagation(); this._closeSuggestions(); if (!$target.hasClass('pill')) { $item = $target.parent(); if (this.$element.attr('data-readonly') === undefined) { if ($target.hasClass('glyphicon-close')) { if (this.options.onRemove) { this.options.onRemove(this.getItemData($item, { el: $item }), $.proxy(this._removeElement, this)); } else { this._removeElement(this.getItemData($item, { el: $item })); } return false; } else if (this.options.edit) { if ($item.find('.pillbox-list-edit').length) { return false; } this.openEdit($item); } } } else { $item = $target; } this.$element.trigger('clicked.fu.pillbox', this.getItemData($item)); }, readonly: function (enable) { if (enable) { this.$element.attr('data-readonly', 'readonly'); } else { this.$element.removeAttr('data-readonly'); } if (this.options.truncate) { this.truncate(enable); } }, suggestionClick: function (e) { var $item = $(e.currentTarget); var item = { text: $item.html(), value: $item.data('value') }; e.preventDefault(); this.$addItem.val(''); if ($item.data('attr')) { item.attr = JSON.parse($item.data('attr')); } item.data = $item.data('data'); this.addItems(item, true); // needs to be after addItems for IE this._closeSuggestions(); }, itemCount: function () { return this.$pillGroup.children('.pill').length; }, // First parameter is 1 based index (optional, if index is not passed all new items will be appended) // Second parameter can be array of objects [{ ... }, { ... }] or you can pass n additional objects as args // object structure is as follows (attr and value are optional): { text: '', value: '', attr: {}, data: {} } addItems: function () { var self = this; var items, index, isInternal; if (isFinite(String(arguments[0])) && !(arguments[0] instanceof Array)) { items = [].slice.call(arguments).slice(1); index = arguments[0]; } else { items = [].slice.call(arguments).slice(0); isInternal = items[1] && !items[1].text; } //If first argument is an array, use that, otherwise they probably passed each thing through as a separate arg, so use items as-is if (items[0] instanceof Array) { items = items[0]; } if (items.length) { $.each(items, function (i, value) { var data = { text: value.text, value: (value.value ? value.value : value.text), el: self.$pillHTML }; if (value.attr) { data.attr = value.attr; } if (value.data) { data.data = value.data; } items[i] = data; }); if (this.options.edit && this.currentEdit) { items[0].el = this.currentEdit.wrap('
    ').parent().html(); } if (isInternal) { items.pop(1); } if (self.options.onAdd && isInternal) { if (this.options.edit && this.currentEdit) { self.options.onAdd(items[0], $.proxy(self.saveEdit, this)); } else { self.options.onAdd(items[0], $.proxy(self.placeItems, this)); } } else { if (this.options.edit && this.currentEdit) { self.saveEdit(items); } else { if (index) { self.placeItems(index, items); } else { self.placeItems(items, isInternal); } } } } }, //First parameter is the index (1 based) to start removing items //Second parameter is the number of items to be removed removeItems: function (index, howMany) { var self = this; var count; var $currentItem; if (!index) { this.$pillGroup.find('.pill').remove(); this._removePillTrigger({ method: 'removeAll' }); } else { howMany = howMany ? howMany : 1; for (count = 0; count < howMany; count++) { $currentItem = self.$pillGroup.find('> .pill:nth-child(' + index + ')'); if ($currentItem) { $currentItem.remove(); } else { break; } } } }, //First parameter is index (optional) //Second parameter is new arguments placeItems: function () { var $newHtml = []; var items; var index; var $neighbor; var isInternal; if (isFinite(String(arguments[0])) && !(arguments[0] instanceof Array)) { items = [].slice.call(arguments).slice(1); index = arguments[0]; } else { items = [].slice.call(arguments).slice(0); isInternal = items[1] && !items[1].text; } if (items[0] instanceof Array) { items = items[0]; } if (items.length) { $.each(items, function (i, item) { var $item = $(item.el); var $neighbor; $item.attr('data-value', item.value); $item.find('span:first').html(item.text); // DOM attributes if (item.attr) { $.each(item.attr, function (key, value) { if (key === 'cssClass' || key === 'class') { $item.addClass(value); } else { $item.attr(key, value); } }); } if (item.data) { $item.data('data', item.data); } $newHtml.push($item); }); if (this.$pillGroup.children('.pill').length > 0) { if (index) { $neighbor = this.$pillGroup.find('.pill:nth-child(' + index + ')'); if ($neighbor.length) { $neighbor.before($newHtml); } else { this.$pillGroup.children('.pill:last').after($newHtml); } } else { this.$pillGroup.children('.pill:last').after($newHtml); } } else { this.$pillGroup.prepend($newHtml); } if (isInternal) { this.$element.trigger('added.fu.pillbox', { text: items[0].text, value: items[0].value }); } } }, inputEvent: function (e) { var self = this; var text = this.$addItem.val(); var value; var attr; var $lastItem; var $selection; if (this.acceptKeyCodes[e.keyCode]) { if (this.options.onKeyDown && this._isSuggestionsOpen()) { $selection = this.$suggest.find('.pillbox-suggest-sel'); if ($selection.length) { text = $selection.html(); value = $selection.data('value'); attr = $selection.data('attr'); } } //ignore comma and make sure text that has been entered (protects against " ,". https://github.com/ExactTarget/fuelux/issues/593), unless allowEmptyPills is true. if (text.replace(/[ ]*\,[ ]*/, '').match(/\S/) || (this.options.allowEmptyPills && text.length)) { this._closeSuggestions(); this.$addItem.hide(); if (attr) { this.addItems({ text: text, value: value, attr: JSON.parse(attr) }, true); } else { this.addItems({ text: text, value: value }, true); } setTimeout(function () { self.$addItem.show().val('').attr({ size: 10 }); }, 0); } e.preventDefault(); return true; } else if (e.keyCode === 8 || e.keyCode === 46) { // backspace: 8 // delete: 46 if (!text.length) { e.preventDefault(); if (this.options.edit && this.currentEdit) { this.cancelEdit(); return true; } this._closeSuggestions(); $lastItem = this.$pillGroup.children('.pill:last'); if ($lastItem.hasClass('pillbox-highlight')) { this._removeElement(this.getItemData($lastItem, { el: $lastItem })); } else { $lastItem.addClass('pillbox-highlight'); } return true; } } else if (text.length > 10) { if (this.$addItem.width() < (this.$pillGroup.width() - 6)) { this.$addItem.attr({ size: text.length + 3 }); } } this.$pillGroup.find('.pill').removeClass('pillbox-highlight'); if (this.options.onKeyDown) { if (e.keyCode === 9 || e.keyCode === 38 || e.keyCode === 40) { // tab: 9 // up arrow: 38 // down arrow: 40 if (this._isSuggestionsOpen()) { this._keySuggestions(e); } return true; } //only allowing most recent event callback to register this.callbackId = e.timeStamp; this.options.onKeyDown({ event: e, value: text }, function (data) { self._openSuggestions(e, data); }); } }, openEdit: function (el) { var index = el.index() + 1; var $addItemWrap = this.$addItemWrap.detach().hide(); this.$pillGroup.find('.pill:nth-child(' + index + ')').before($addItemWrap); this.currentEdit = el.detach(); $addItemWrap.addClass('editing'); this.$addItem.val(el.find('span:first').html()); $addItemWrap.show(); this.$addItem.focus().select(); }, cancelEdit: function (e) { var $addItemWrap; if (!this.currentEdit) { return false; } this._closeSuggestions(); if (e) { this.$addItemWrap.before(this.currentEdit); } this.currentEdit = false; $addItemWrap = this.$addItemWrap.detach(); $addItemWrap.removeClass('editing'); this.$addItem.val(''); this.$pillGroup.append($addItemWrap); }, //Must match syntax of placeItem so addItem callback is called when an item is edited //expecting to receive an array back from the callback containing edited items saveEdit: function () { var item = arguments[0][0] ? arguments[0][0] : arguments[0]; this.currentEdit = $(item.el); this.currentEdit.data('value', item.value); this.currentEdit.find('span:first').html(item.text); this.$addItemWrap.hide(); this.$addItemWrap.before(this.currentEdit); this.currentEdit = false; this.$addItem.val(''); this.$addItemWrap.removeClass('editing'); this.$pillGroup.append(this.$addItemWrap.detach().show()); this.$element.trigger('edited.fu.pillbox', { value: item.value, text: item.text }); }, removeBySelector: function () { var selectors = [].slice.call(arguments).slice(0); var self = this; $.each(selectors, function (i, sel) { self.$pillGroup.find(sel).remove(); }); this._removePillTrigger({ method: 'removeBySelector', removedSelectors: selectors }); }, removeByValue: function () { var values = [].slice.call(arguments).slice(0); var self = this; $.each(values, function (i, val) { self.$pillGroup.find('> .pill[data-value="' + val + '"]').remove(); }); this._removePillTrigger({ method: 'removeByValue', removedValues: values }); }, removeByText: function () { var text = [].slice.call(arguments).slice(0); var self = this; $.each(text, function (i, text) { self.$pillGroup.find('> .pill:contains("' + text + '")').remove(); }); this._removePillTrigger({ method: 'removeByText', removedText: text }); }, truncate: function (enable) { var self = this; var available, full, i, pills, used; this.$element.removeClass('truncate'); this.$addItemWrap.removeClass('truncated'); this.$pillGroup.find('.pill').removeClass('truncated'); if (enable) { this.$element.addClass('truncate'); available = this.$element.width(); full = false; i = 0; pills = this.$pillGroup.find('.pill').length; used = 0; this.$pillGroup.find('.pill').each(function () { var pill = $(this); if (!full) { i++; self.$moreCount.text(pills - i); if ((used + pill.outerWidth(true) + self.$addItemWrap.outerWidth(true)) <= available) { used += pill.outerWidth(true); } else { self.$moreCount.text((pills - i) + 1); pill.addClass('truncated'); full = true; } } else { pill.addClass('truncated'); } }); if (i === pills) { this.$addItemWrap.addClass('truncated'); } } }, inputFocus: function (e) { this.$element.find('.pillbox-add-item').focus(); }, getItemData: function (el, data) { return $.extend({ text: el.find('span:first').html() }, el.data(), data); }, _removeElement: function (data) { data.el.remove(); delete data.el; this.$element.trigger('removed.fu.pillbox', data); }, _removePillTrigger: function (removedBy) { this.$element.trigger('removed.fu.pillbox', removedBy); }, _generateObject: function (data) { var obj = {}; $.each(data, function (index, value) { obj[value] = true; }); return obj; }, _openSuggestions: function (e, data) { var markup = ''; var $suggestionList = $('