: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
return escapeMarkup(template(data, container));
SingleSelection.prototype.selectionContainer = function () {
return $('<span></span>');
SingleSelection.prototype.update = function (data) {
var $rendered = this.$selection.find('.pumselect2-selection__rendered');
var formatted = this.display(selection, $rendered);
$rendered.empty().append(formatted);
$rendered.prop('title', selection.title || selection.text);
S2.define('pumselect2/selection/multiple',[
], function ($, BaseSelection, Utils) {
function MultipleSelection ($element, options) {
MultipleSelection.__super__.constructor.apply(this, arguments);
Utils.Extend(MultipleSelection, BaseSelection);
MultipleSelection.prototype.render = function () {
var $selection = MultipleSelection.__super__.render.call(this);
$selection.addClass('pumselect2-selection--multiple');
'<ul class="pumselect2-selection__rendered"></ul>'
MultipleSelection.prototype.bind = function (container, $container) {
MultipleSelection.__super__.bind.apply(this, arguments);
this.$selection.on('click', function (evt) {
'.pumselect2-selection__choice__remove',
// Ignore the event if it is disabled
if (self.options.get('disabled')) {
var $selection = $remove.parent();
var data = $selection.data('data');
self.trigger('unselect', {
MultipleSelection.prototype.clear = function () {
this.$selection.find('.pumselect2-selection__rendered').empty();
MultipleSelection.prototype.display = function (data, container) {
var template = this.options.get('templateSelection');
var escapeMarkup = this.options.get('escapeMarkup');
return escapeMarkup(template(data, container));
MultipleSelection.prototype.selectionContainer = function () {
'<li class="pumselect2-selection__choice">' +
'<span class="pumselect2-selection__choice__remove" role="presentation">' +
MultipleSelection.prototype.update = function (data) {
for (var d = 0; d < data.length; d++) {
var $selection = this.selectionContainer();
var formatted = this.display(selection, $selection);
$selection.append(formatted);
$selection.prop('title', selection.title || selection.text);
$selection.data('data', selection);
$selections.push($selection);
var $rendered = this.$selection.find('.pumselect2-selection__rendered');
Utils.appendMany($rendered, $selections);
return MultipleSelection;
S2.define('pumselect2/selection/placeholder',[
function Placeholder (decorated, $element, options) {
this.placeholder = this.normalizePlaceholder(options.get('placeholder'));
decorated.call(this, $element, options);
Placeholder.prototype.normalizePlaceholder = function (_, placeholder) {
if (typeof placeholder === 'string') {
Placeholder.prototype.createPlaceholder = function (decorated, placeholder) {
var $placeholder = this.selectionContainer();
$placeholder.html(this.display(placeholder));
$placeholder.addClass('pumselect2-selection__placeholder')
.removeClass('pumselect2-selection__choice');
Placeholder.prototype.update = function (decorated, data) {
var singlePlaceholder = (
data.length == 1 && data[0].id != this.placeholder.id
var multipleSelections = data.length > 1;
if (multipleSelections || singlePlaceholder) {
return decorated.call(this, data);
var $placeholder = this.createPlaceholder(this.placeholder);
this.$selection.find('.pumselect2-selection__rendered').append($placeholder);
S2.define('pumselect2/selection/allowClear',[
function AllowClear () { }
AllowClear.prototype.bind = function (decorated, container, $container) {
decorated.call(this, container, $container);
if (this.placeholder == null) {
if (this.options.get('debug') && window.console && console.error) {
'Select2: The `allowClear` option should be used in combination ' +
'with the `placeholder` option.'
this.$selection.on('mousedown', '.pumselect2-selection__clear',
container.on('keypress', function (evt) {
self._handleKeyboardClear(evt, container);
AllowClear.prototype._handleClear = function (_, evt) {
// Ignore the event if it is disabled
if (this.options.get('disabled')) {
var $clear = this.$selection.find('.pumselect2-selection__clear');
// Ignore the event if nothing has been selected
if ($clear.length === 0) {
var data = $clear.data('data');
for (var d = 0; d < data.length; d++) {
// Trigger the `unselect` event, so people can prevent it from being
this.trigger('unselect', unselectData);
// If the event was prevented, don't clear it out.
if (unselectData.prevented) {
this.$element.val(this.placeholder.id).trigger('change');
this.trigger('toggle', {});
AllowClear.prototype._handleKeyboardClear = function (_, evt, container) {
if (container.isOpen()) {
if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) {
AllowClear.prototype.update = function (decorated, data) {
decorated.call(this, data);
if (this.$selection.find('.pumselect2-selection__placeholder').length > 0 ||
'<span class="pumselect2-selection__clear">' +
$remove.data('data', data);
this.$selection.find('.pumselect2-selection__rendered').prepend($remove);
S2.define('pumselect2/selection/search',[
], function ($, Utils, KEYS) {
function Search (decorated, $element, options) {
decorated.call(this, $element, options);
Search.prototype.render = function (decorated) {
'<li class="pumselect2-search pumselect2-search--inline">' +
'<input class="pumselect2-search__field" type="search" tabindex="-1"' +
' autocomplete="off" autocorrect="off" autocapitalize="off"' +
' spellcheck="false" role="textbox" aria-autocomplete="list" />' +
this.$searchContainer = $search;
this.$search = $search.find('input');
var $rendered = decorated.call(this);
this._transferTabIndex();
Search.prototype.bind = function (decorated, container, $container) {
decorated.call(this, container, $container);
container.on('open', function () {
self.$search.trigger('focus');
container.on('close', function () {
self.$search.removeAttr('aria-activedescendant');
self.$search.trigger('focus');
container.on('enable', function () {
self.$search.prop('disabled', false);
self._transferTabIndex();
container.on('disable', function () {
self.$search.prop('disabled', true);
container.on('focus', function (evt) {
self.$search.trigger('focus');
container.on('results:focus', function (params) {
self.$search.attr('aria-activedescendant', params.id);
this.$selection.on('focusin', '.pumselect2-search--inline', function (evt) {
self.trigger('focus', evt);
this.$selection.on('focusout', '.pumselect2-search--inline', function (evt) {
this.$selection.on('keydown', '.pumselect2-search--inline', function (evt) {
self.trigger('keypress', evt);
self._keyUpPrevented = evt.isDefaultPrevented();
if (key === KEYS.BACKSPACE && self.$search.val() === '') {
var $previousChoice = self.$searchContainer
.prev('.pumselect2-selection__choice');
if ($previousChoice.length > 0) {
var item = $previousChoice.data('data');
self.searchRemoveChoice(item);
// Try to detect the IE version should the `documentMode` property that
// is stored on the document. This is only implemented in IE and is
// slightly cleaner than doing a user agent check.
// This property is not available in Edge, but Edge also doesn't have
var msie = document.documentMode;
var disableInputEvents = msie && msie <= 11;
// Workaround for browsers which do not support the `input` event
// This will prevent double-triggering of events for browsers which support
// both the `keyup` and `input` events.
'.pumselect2-search--inline',
// IE will trigger the `input` event when a placeholder is used on a
// search box. To get around this issue, we are forced to ignore all
// `input` events in IE and keep using `keyup`.
if (disableInputEvents) {
self.$selection.off('input.search input.searchcheck');
// Unbind the duplicated `keyup` event
self.$selection.off('keyup.search');
'keyup.search input.search',
'.pumselect2-search--inline',
// IE will trigger the `input` event when a placeholder is used on a
// search box. To get around this issue, we are forced to ignore all
// `input` events in IE and keep using `keyup`.
if (disableInputEvents && evt.type === 'input') {
self.$selection.off('input.search input.searchcheck');
// We can freely ignore events from modifier keys
if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) {
// Tabbing will be handled during the `keydown` phase
* This method will transfer the tabindex attribute from the rendered
* selection to the search box. This allows for the search box to be used as
* the primary focus instead of the selection container.
Search.prototype._transferTabIndex = function (decorated) {
this.$search.attr('tabindex', this.$selection.attr('tabindex'));
this.$selection.attr('tabindex', '-1');
Search.prototype.createPlaceholder = function (decorated, placeholder) {
this.$search.attr('placeholder', placeholder.text);
Search.prototype.update = function (decorated, data) {
var searchHadFocus = this.$search[0] == document.activeElement;
this.$search.attr('placeholder', '');
decorated.call(this, data);
this.$selection.find('.pumselect2-selection__rendered')
.append(this.$searchContainer);
Search.prototype.handleSearch = function () {
if (!this._keyUpPrevented) {
var input = this.$search.val();
this._keyUpPrevented = false;
Search.prototype.searchRemoveChoice = function (decorated, item) {
this.trigger('unselect', {
this.$search.val(item.text);
Search.prototype.resizeSearch = function () {
this.$search.css('width', '25px');
if (this.$search.attr('placeholder') !== '') {
width = this.$selection.find('.pumselect2-selection__rendered').innerWidth();
var minimumWidth = this.$search.val().length + 1;
width = (minimumWidth * 0.75) + 'em';