' +
+ '
' +
- '';
@@ -226,111 +519,198 @@
},
createView: function () {
- var $drop = this.createDropdown();
- var $li = this.createLi();
- $drop.find('ul').append($li);
+ var $drop = this.createDropdown(),
+ li = this.createLi();
+
+ $drop.find('ul')[0].innerHTML = li;
return $drop;
},
reloadLi: function () {
- //Remove all children.
- this.destroyLi();
- //Re build
- var $li = this.createLi();
- this.$menu.find('ul').append($li);
- },
-
- destroyLi: function () {
- this.$menu.find('li').remove();
+ // rebuild
+ var li = this.createLi();
+ this.$menuInner[0].innerHTML = li;
},
createLi: function () {
var that = this,
_li = [],
- optID = 0;
+ optID = 0,
+ titleOption = document.createElement('option'),
+ liIndex = -1; // increment liIndex whenever a new
element is created to ensure liObj is correct
// Helper functions
/**
* @param content
* @param [index]
* @param [classes]
+ * @param [optgroup]
* @returns {string}
*/
- var generateLI = function (content, index, classes) {
+ var generateLI = function (content, index, classes, optgroup) {
return '' + content + '';
+ ((typeof classes !== 'undefined' && '' !== classes) ? ' class="' + classes + '"' : '') +
+ ((typeof index !== 'undefined' && null !== index) ? ' data-original-index="' + index + '"' : '') +
+ ((typeof optgroup !== 'undefined' && null !== optgroup) ? 'data-optgroup="' + optgroup + '"' : '') +
+ '>' + content + '';
};
/**
* @param text
* @param [classes]
* @param [inline]
- * @param [optgroup]
+ * @param [tokens]
* @returns {string}
*/
- var generateA = function (text, classes, inline, optgroup) {
- var normText = normalizeToBase(htmlEscape(text));
+ var generateA = function (text, classes, inline, tokens) {
return '
' + text +
- '' +
- '';
+ (typeof classes !== 'undefined' ? ' class="' + classes + '"' : '') +
+ (inline ? ' style="' + inline + '"' : '') +
+ (that.options.liveSearchNormalize ? ' data-normalized-text="' + normalizeToBase(htmlEscape($(text).html())) + '"' : '') +
+ (typeof tokens !== 'undefined' || tokens !== null ? ' data-tokens="' + tokens + '"' : '') +
+ ' role="option">' + text +
+ '
' +
+ '';
};
- this.$element.find('option').each(function () {
+ if (this.options.title && !this.multiple) {
+ // this option doesn't create a new
element, but does add a new option, so liIndex is decreased
+ // since liObj is recalculated on every refresh, liIndex needs to be decreased even if the titleOption is already appended
+ liIndex--;
+
+ if (!this.$element.find('.bs-title-option').length) {
+ // Use native JS to prepend option (faster)
+ var element = this.$element[0];
+ titleOption.className = 'bs-title-option';
+ titleOption.innerHTML = this.options.title;
+ titleOption.value = '';
+ element.insertBefore(titleOption, element.firstChild);
+ // Check if selected or data-selected attribute is already set on an option. If not, select the titleOption option.
+ // the selected item may have been changed by user or programmatically before the bootstrap select plugin runs,
+ // if so, the select will have the data-selected attribute
+ var $opt = $(element.options[element.selectedIndex]);
+ if ($opt.attr('selected') === undefined && this.$element.data('selected') === undefined) {
+ titleOption.selected = true;
+ }
+ }
+ }
+
+ var $selectOptions = this.$element.find('option');
+
+ $selectOptions.each(function (index) {
var $this = $(this);
+ liIndex++;
+
+ if ($this.hasClass('bs-title-option')) return;
+
// Get the class and text for the option
- var optionClass = $this.attr('class') || '',
- inline = $this.attr('style'),
+ var optionClass = this.className || '',
+ inline = htmlEscape(this.style.cssText),
text = $this.data('content') ? $this.data('content') : $this.html(),
- subtext = typeof $this.data('subtext') !== 'undefined' ? '' + $this.data('subtext') + '' : '',
+ tokens = $this.data('tokens') ? $this.data('tokens') : null,
+ subtext = typeof $this.data('subtext') !== 'undefined' ? '' + $this.data('subtext') + '' : '',
icon = typeof $this.data('icon') !== 'undefined' ? ' ' : '',
- isDisabled = $this.is(':disabled') || $this.parent().is(':disabled'),
- index = $this[0].index;
+ $parent = $this.parent(),
+ isOptgroup = $parent[0].tagName === 'OPTGROUP',
+ isOptgroupDisabled = isOptgroup && $parent[0].disabled,
+ isDisabled = this.disabled || isOptgroupDisabled,
+ prevHiddenIndex;
+
if (icon !== '' && isDisabled) {
icon = '' + icon + '';
}
+ if (that.options.hideDisabled && (isDisabled && !isOptgroup || isOptgroupDisabled)) {
+ // set prevHiddenIndex - the index of the first hidden option in a group of hidden options
+ // used to determine whether or not a divider should be placed after an optgroup if there are
+ // hidden options between the optgroup and the first visible option
+ prevHiddenIndex = $this.data('prevHiddenIndex');
+ $this.next().data('prevHiddenIndex', (prevHiddenIndex !== undefined ? prevHiddenIndex : index));
+
+ liIndex--;
+ return;
+ }
+
if (!$this.data('content')) {
// Prepend any icon and append any subtext to the main text.
text = icon + '' + text + subtext + '';
}
- if (that.options.hideDisabled && isDisabled) {
- return;
- }
+ if (isOptgroup && $this.data('divider') !== true) {
+ if (that.options.hideDisabled && isDisabled) {
+ if ($parent.data('allOptionsDisabled') === undefined) {
+ var $options = $parent.children();
+ $parent.data('allOptionsDisabled', $options.filter(':disabled').length === $options.length);
+ }
+
+ if ($parent.data('allOptionsDisabled')) {
+ liIndex--;
+ return;
+ }
+ }
+
+ var optGroupClass = ' ' + $parent[0].className || '';
- if ($this.parent().is('optgroup') && $this.data('divider') !== true) {
if ($this.index() === 0) { // Is it the first option of the optgroup?
optID += 1;
// Get the opt group label
- var label = $this.parent().attr('label');
- var labelSubtext = typeof $this.parent().data('subtext') !== 'undefined' ? '' + $this.parent().data('subtext') + '' : '';
- var labelIcon = $this.parent().data('icon') ? ' ' : '';
- label = labelIcon + '' + label + labelSubtext + '';
+ var label = $parent[0].label,
+ labelSubtext = typeof $parent.data('subtext') !== 'undefined' ? '' + $parent.data('subtext') + '' : '',
+ labelIcon = $parent.data('icon') ? ' ' : '';
+
+ label = labelIcon + '' + htmlEscape(label) + labelSubtext + '';
if (index !== 0 && _li.length > 0) { // Is it NOT the first option of the select && are there elements in the dropdown?
- _li.push(generateLI('', null, 'divider'));
+ liIndex++;
+ _li.push(generateLI('', null, 'divider', optID + 'div'));
}
-
- _li.push(generateLI(label, null, 'dropdown-header'));
+ liIndex++;
+ _li.push(generateLI(label, null, 'dropdown-header' + optGroupClass, optID));
}
- _li.push(generateLI(generateA(text, 'opt ' + optionClass, inline, optID), index));
+ if (that.options.hideDisabled && isDisabled) {
+ liIndex--;
+ return;
+ }
+
+ _li.push(generateLI(generateA(text, 'opt ' + optionClass + optGroupClass, inline, tokens), index, '', optID));
} else if ($this.data('divider') === true) {
_li.push(generateLI('', index, 'divider'));
} else if ($this.data('hidden') === true) {
- _li.push(generateLI(generateA(text, optionClass, inline), index, 'hide is-hidden'));
+ // set prevHiddenIndex - the index of the first hidden option in a group of hidden options
+ // used to determine whether or not a divider should be placed after an optgroup if there are
+ // hidden options between the optgroup and the first visible option
+ prevHiddenIndex = $this.data('prevHiddenIndex');
+ $this.next().data('prevHiddenIndex', (prevHiddenIndex !== undefined ? prevHiddenIndex : index));
+
+ _li.push(generateLI(generateA(text, optionClass, inline, tokens), index, 'hidden is-hidden'));
} else {
- _li.push(generateLI(generateA(text, optionClass, inline), index));
+ var showDivider = this.previousElementSibling && this.previousElementSibling.tagName === 'OPTGROUP';
+
+ // if previous element is not an optgroup and hideDisabled is true
+ if (!showDivider && that.options.hideDisabled) {
+ prevHiddenIndex = $this.data('prevHiddenIndex');
+
+ if (prevHiddenIndex !== undefined) {
+ // select the element **before** the first hidden element in the group
+ var prevHidden = $selectOptions.eq(prevHiddenIndex)[0].previousElementSibling;
+
+ if (prevHidden && prevHidden.tagName === 'OPTGROUP' && !prevHidden.disabled) {
+ showDivider = true;
+ }
+ }
+ }
+
+ if (showDivider) {
+ liIndex++;
+ _li.push(generateLI('', null, 'divider', optID + 'div'));
+ }
+ _li.push(generateLI(generateA(text, optionClass, inline, tokens), index));
}
+
+ that.liObj[index] = liIndex;
});
//If we are not multiple, we don't have a selected item, and we don't have a title, select the first element so something is set in the button
@@ -338,7 +718,7 @@
this.$element.find('option').eq(0).prop('selected', true).attr('selected', 'selected');
}
- return $(_li.join(''));
+ return _li.join('');
},
findLis: function () {
@@ -350,33 +730,44 @@
* @param [updateLi] defaults to true
*/
render: function (updateLi) {
- var that = this;
+ var that = this,
+ notDisabled,
+ $selectOptions = this.$element.find('option');
//Update the LI to match the SELECT
if (updateLi !== false) {
- this.$element.find('option').each(function (index) {
- that.setDisabled(index, $(this).is(':disabled') || $(this).parent().is(':disabled'));
- that.setSelected(index, $(this).is(':selected'));
+ $selectOptions.each(function (index) {
+ var $lis = that.findLis().eq(that.liObj[index]);
+
+ that.setDisabled(index, this.disabled || this.parentNode.tagName === 'OPTGROUP' && this.parentNode.disabled, $lis);
+ that.setSelected(index, this.selected, $lis);
});
}
+ this.togglePlaceholder();
+
this.tabIndex();
- var notDisabled = this.options.hideDisabled ? ':not([disabled])' : '';
- var selectedItems = this.$element.find('option:selected' + notDisabled).map(function () {
- var $this = $(this);
- var icon = $this.data('icon') && that.options.showIcon ? ' ' : '';
- var subtext;
- if (that.options.showSubtext && $this.attr('data-subtext') && !that.multiple) {
- subtext = ' ' + $this.data('subtext') + '';
- } else {
- subtext = '';
- }
- if ($this.data('content') && that.options.showContent) {
- return $this.data('content');
- } else if (typeof $this.attr('title') !== 'undefined') {
- return $this.attr('title');
- } else {
- return icon + $this.html() + subtext;
+
+ var selectedItems = $selectOptions.map(function () {
+ if (this.selected) {
+ if (that.options.hideDisabled && (this.disabled || this.parentNode.tagName === 'OPTGROUP' && this.parentNode.disabled)) return;
+
+ var $this = $(this),
+ icon = $this.data('icon') && that.options.showIcon ? ' ' : '',
+ subtext;
+
+ if (that.options.showSubtext && $this.data('subtext') && !that.multiple) {
+ subtext = ' ' + $this.data('subtext') + '';
+ } else {
+ subtext = '';
+ }
+ if (typeof $this.attr('title') !== 'undefined') {
+ return $this.attr('title');
+ } else if ($this.data('content') && that.options.showContent) {
+ return $this.data('content').toString();
+ } else {
+ return icon + $this.html() + subtext;
+ }
}
}).toArray();
@@ -389,13 +780,15 @@
var max = this.options.selectedTextFormat.split('>');
if ((max.length > 1 && selectedItems.length > max[1]) || (max.length == 1 && selectedItems.length >= 2)) {
notDisabled = this.options.hideDisabled ? ', [disabled]' : '';
- var totalCount = this.$element.find('option').not('[data-divider="true"], [data-hidden="true"]' + notDisabled).length,
+ var totalCount = $selectOptions.not('[data-divider="true"], [data-hidden="true"]' + notDisabled).length,
tr8nText = (typeof this.options.countSelectedText === 'function') ? this.options.countSelectedText(selectedItems.length, totalCount) : this.options.countSelectedText;
title = tr8nText.replace('{0}', selectedItems.length.toString()).replace('{1}', totalCount.toString());
}
}
- this.options.title = this.$element.attr('title');
+ if (this.options.title == undefined) {
+ this.options.title = this.$element.attr('title');
+ }
if (this.options.selectedTextFormat == 'static') {
title = this.options.title;
@@ -406,8 +799,11 @@
title = typeof this.options.title !== 'undefined' ? this.options.title : this.options.noneSelectedText;
}
- this.$button.attr('title', htmlEscape(title));
- this.$newElement.find('.filter-option').html(title);
+ //strip all HTML tags and trim the result, then unescape any escaped tags
+ this.$button.attr('title', htmlUnescape($.trim(title.replace(/<[^>]*>?/g, ''))));
+ this.$button.children('.filter-option').html(title);
+
+ this.$element.trigger('rendered.bs.select');
},
/**
@@ -416,7 +812,7 @@
*/
setStyle: function (style, status) {
if (this.$element.attr('class')) {
- this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker|mobile-device|validate\[.*\]/gi, ''));
+ this.$newElement.addClass(this.$element.attr('class').replace(/selectpicker|mobile-device|bs-select-hidden|validate\[.*\]/gi, ''));
}
var buttonClass = style ? style : this.options.style;
@@ -431,117 +827,251 @@
}
},
- liHeight: function () {
- if (this.options.size === false) return;
+ liHeight: function (refresh) {
+ if (!refresh && (this.options.size === false || this.sizeInfo)) return;
- var $selectClone = this.$menu.parent().clone().find('> .dropdown-toggle').prop('autofocus', false).end().appendTo('body'),
- $menuClone = $selectClone.addClass('open').find('> .dropdown-menu'),
- liHeight = $menuClone.find('li').not('.divider').not('.dropdown-header').filter(':visible').children('a').outerHeight(),
- headerHeight = this.options.header ? $menuClone.find('.popover-title').outerHeight() : 0,
- searchHeight = this.options.liveSearch ? $menuClone.find('.bs-searchbox').outerHeight() : 0,
- actionsHeight = this.options.actionsBox ? $menuClone.find('.bs-actionsbox').outerHeight() : 0;
+ var newElement = document.createElement('div'),
+ menu = document.createElement('div'),
+ menuInner = document.createElement('ul'),
+ divider = document.createElement('li'),
+ li = document.createElement('li'),
+ a = document.createElement('a'),
+ text = document.createElement('span'),
+ header = this.options.header && this.$menu.find('.popover-title').length > 0 ? this.$menu.find('.popover-title')[0].cloneNode(true) : null,
+ search = this.options.liveSearch ? document.createElement('div') : null,
+ actions = this.options.actionsBox && this.multiple && this.$menu.find('.bs-actionsbox').length > 0 ? this.$menu.find('.bs-actionsbox')[0].cloneNode(true) : null,
+ doneButton = this.options.doneButton && this.multiple && this.$menu.find('.bs-donebutton').length > 0 ? this.$menu.find('.bs-donebutton')[0].cloneNode(true) : null;
- $selectClone.remove();
+ text.className = 'text';
+ newElement.className = this.$menu[0].parentNode.className + ' open';
+ menu.className = 'dropdown-menu open';
+ menuInner.className = 'dropdown-menu inner';
+ divider.className = 'divider';
- this.$newElement
- .data('liHeight', liHeight)
- .data('headerHeight', headerHeight)
- .data('searchHeight', searchHeight)
- .data('actionsHeight', actionsHeight);
+ text.appendChild(document.createTextNode('Inner text'));
+ a.appendChild(text);
+ li.appendChild(a);
+ menuInner.appendChild(li);
+ menuInner.appendChild(divider);
+ if (header) menu.appendChild(header);
+ if (search) {
+ var input = document.createElement('input');
+ search.className = 'bs-searchbox';
+ input.className = 'form-control';
+ search.appendChild(input);
+ menu.appendChild(search);
+ }
+ if (actions) menu.appendChild(actions);
+ menu.appendChild(menuInner);
+ if (doneButton) menu.appendChild(doneButton);
+ newElement.appendChild(menu);
+
+ document.body.appendChild(newElement);
+
+ var liHeight = a.offsetHeight,
+ headerHeight = header ? header.offsetHeight : 0,
+ searchHeight = search ? search.offsetHeight : 0,
+ actionsHeight = actions ? actions.offsetHeight : 0,
+ doneButtonHeight = doneButton ? doneButton.offsetHeight : 0,
+ dividerHeight = $(divider).outerHeight(true),
+ // fall back to jQuery if getComputedStyle is not supported
+ menuStyle = typeof getComputedStyle === 'function' ? getComputedStyle(menu) : false,
+ $menu = menuStyle ? null : $(menu),
+ menuPadding = {
+ vert: parseInt(menuStyle ? menuStyle.paddingTop : $menu.css('paddingTop')) +
+ parseInt(menuStyle ? menuStyle.paddingBottom : $menu.css('paddingBottom')) +
+ parseInt(menuStyle ? menuStyle.borderTopWidth : $menu.css('borderTopWidth')) +
+ parseInt(menuStyle ? menuStyle.borderBottomWidth : $menu.css('borderBottomWidth')),
+ horiz: parseInt(menuStyle ? menuStyle.paddingLeft : $menu.css('paddingLeft')) +
+ parseInt(menuStyle ? menuStyle.paddingRight : $menu.css('paddingRight')) +
+ parseInt(menuStyle ? menuStyle.borderLeftWidth : $menu.css('borderLeftWidth')) +
+ parseInt(menuStyle ? menuStyle.borderRightWidth : $menu.css('borderRightWidth'))
+ },
+ menuExtras = {
+ vert: menuPadding.vert +
+ parseInt(menuStyle ? menuStyle.marginTop : $menu.css('marginTop')) +
+ parseInt(menuStyle ? menuStyle.marginBottom : $menu.css('marginBottom')) + 2,
+ horiz: menuPadding.horiz +
+ parseInt(menuStyle ? menuStyle.marginLeft : $menu.css('marginLeft')) +
+ parseInt(menuStyle ? menuStyle.marginRight : $menu.css('marginRight')) + 2
+ }
+
+ document.body.removeChild(newElement);
+
+ this.sizeInfo = {
+ liHeight: liHeight,
+ headerHeight: headerHeight,
+ searchHeight: searchHeight,
+ actionsHeight: actionsHeight,
+ doneButtonHeight: doneButtonHeight,
+ dividerHeight: dividerHeight,
+ menuPadding: menuPadding,
+ menuExtras: menuExtras
+ };
},
setSize: function () {
this.findLis();
+ this.liHeight();
+
+ if (this.options.header) this.$menu.css('padding-top', 0);
+ if (this.options.size === false) return;
+
var that = this,
- menu = this.$menu,
- menuInner = menu.find('.inner'),
- selectHeight = this.$newElement.outerHeight(),
- liHeight = this.$newElement.data('liHeight'),
- headerHeight = this.$newElement.data('headerHeight'),
- searchHeight = this.$newElement.data('searchHeight'),
- actionsHeight = this.$newElement.data('actionsHeight'),
- divHeight = this.$lis.filter('.divider').outerHeight(true),
- menuPadding = parseInt(menu.css('padding-top')) +
- parseInt(menu.css('padding-bottom')) +
- parseInt(menu.css('border-top-width')) +
- parseInt(menu.css('border-bottom-width')),
- notDisabled = this.options.hideDisabled ? ', .disabled' : '',
+ $menu = this.$menu,
+ $menuInner = this.$menuInner,
$window = $(window),
- menuExtras = menuPadding + parseInt(menu.css('margin-top')) + parseInt(menu.css('margin-bottom')) + 2,
+ selectHeight = this.$newElement[0].offsetHeight,
+ selectWidth = this.$newElement[0].offsetWidth,
+ liHeight = this.sizeInfo['liHeight'],
+ headerHeight = this.sizeInfo['headerHeight'],
+ searchHeight = this.sizeInfo['searchHeight'],
+ actionsHeight = this.sizeInfo['actionsHeight'],
+ doneButtonHeight = this.sizeInfo['doneButtonHeight'],
+ divHeight = this.sizeInfo['dividerHeight'],
+ menuPadding = this.sizeInfo['menuPadding'],
+ menuExtras = this.sizeInfo['menuExtras'],
+ notDisabled = this.options.hideDisabled ? '.disabled' : '',
menuHeight,
+ menuWidth,
+ getHeight,
+ getWidth,
selectOffsetTop,
selectOffsetBot,
- posVert = function () {
- // JQuery defines a scrollTop function, but in pure JS it's a property
- //noinspection JSValidateTypes
- selectOffsetTop = that.$newElement.offset().top - $window.scrollTop();
- selectOffsetBot = $window.height() - selectOffsetTop - selectHeight;
- };
- posVert();
- if (this.options.header) menu.css('padding-top', 0);
+ selectOffsetLeft,
+ selectOffsetRight,
+ getPos = function() {
+ var pos = that.$newElement.offset(),
+ $container = $(that.options.container),
+ containerPos;
- if (this.options.size == 'auto') {
+ if (that.options.container && !$container.is('body')) {
+ containerPos = $container.offset();
+ containerPos.top += parseInt($container.css('borderTopWidth'));
+ containerPos.left += parseInt($container.css('borderLeftWidth'));
+ } else {
+ containerPos = { top: 0, left: 0 };
+ }
+
+ var winPad = that.options.windowPadding;
+ selectOffsetTop = pos.top - containerPos.top - $window.scrollTop();
+ selectOffsetBot = $window.height() - selectOffsetTop - selectHeight - containerPos.top - winPad[2];
+ selectOffsetLeft = pos.left - containerPos.left - $window.scrollLeft();
+ selectOffsetRight = $window.width() - selectOffsetLeft - selectWidth - containerPos.left - winPad[1];
+ selectOffsetTop -= winPad[0];
+ selectOffsetLeft -= winPad[3];
+ };
+
+ getPos();
+
+ if (this.options.size === 'auto') {
var getSize = function () {
var minHeight,
- lisVis = that.$lis.not('.hide');
+ hasClass = function (className, include) {
+ return function (element) {
+ if (include) {
+ return (element.classList ? element.classList.contains(className) : $(element).hasClass(className));
+ } else {
+ return !(element.classList ? element.classList.contains(className) : $(element).hasClass(className));
+ }
+ };
+ },
+ lis = that.$menuInner[0].getElementsByTagName('li'),
+ lisVisible = Array.prototype.filter ? Array.prototype.filter.call(lis, hasClass('hidden', false)) : that.$lis.not('.hidden'),
+ optGroup = Array.prototype.filter ? Array.prototype.filter.call(lisVisible, hasClass('dropdown-header', true)) : lisVisible.filter('.dropdown-header');
- posVert();
- menuHeight = selectOffsetBot - menuExtras;
+ getPos();
+ menuHeight = selectOffsetBot - menuExtras.vert;
+ menuWidth = selectOffsetRight - menuExtras.horiz;
+
+ if (that.options.container) {
+ if (!$menu.data('height')) $menu.data('height', $menu.height());
+ getHeight = $menu.data('height');
+
+ if (!$menu.data('width')) $menu.data('width', $menu.width());
+ getWidth = $menu.data('width');
+ } else {
+ getHeight = $menu.height();
+ getWidth = $menu.width();
+ }
if (that.options.dropupAuto) {
- that.$newElement.toggleClass('dropup', (selectOffsetTop > selectOffsetBot) && ((menuHeight - menuExtras) < menu.height()));
- }
- if (that.$newElement.hasClass('dropup')) {
- menuHeight = selectOffsetTop - menuExtras;
+ that.$newElement.toggleClass('dropup', selectOffsetTop > selectOffsetBot && (menuHeight - menuExtras.vert) < getHeight);
}
- if ((lisVis.length + lisVis.filter('.dropdown-header').length) > 3) {
- minHeight = liHeight * 3 + menuExtras - 2;
+ if (that.$newElement.hasClass('dropup')) {
+ menuHeight = selectOffsetTop - menuExtras.vert;
+ }
+
+ if (that.options.dropdownAlignRight === 'auto') {
+ $menu.toggleClass('dropdown-menu-right', selectOffsetLeft > selectOffsetRight && (menuWidth - menuExtras.horiz) < (getWidth - selectWidth));
+ }
+
+ if ((lisVisible.length + optGroup.length) > 3) {
+ minHeight = liHeight * 3 + menuExtras.vert - 2;
} else {
minHeight = 0;
}
- menu.css({
+ $menu.css({
'max-height': menuHeight + 'px',
'overflow': 'hidden',
- 'min-height': minHeight + headerHeight + searchHeight + actionsHeight + 'px'
+ 'min-height': minHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight + 'px'
});
- menuInner.css({
- 'max-height': menuHeight - headerHeight - searchHeight - actionsHeight - menuPadding + 'px',
+ $menuInner.css({
+ 'max-height': menuHeight - headerHeight - searchHeight - actionsHeight - doneButtonHeight - menuPadding.vert + 'px',
'overflow-y': 'auto',
- 'min-height': Math.max(minHeight - menuPadding, 0) + 'px'
+ 'min-height': Math.max(minHeight - menuPadding.vert, 0) + 'px'
});
};
getSize();
this.$searchbox.off('input.getSize propertychange.getSize').on('input.getSize propertychange.getSize', getSize);
- $(window).off('resize.getSize').on('resize.getSize', getSize);
- $(window).off('scroll.getSize').on('scroll.getSize', getSize);
- } else if (this.options.size && this.options.size != 'auto' && menu.find('li' + notDisabled).length > this.options.size) {
- var optIndex = this.$lis.not('.divider' + notDisabled).find(' > *').slice(0, this.options.size).last().parent().index();
- var divLength = this.$lis.slice(0, optIndex + 1).filter('.divider').length;
- menuHeight = liHeight * this.options.size + divLength * divHeight + menuPadding;
+ $window.off('resize.getSize scroll.getSize').on('resize.getSize scroll.getSize', getSize);
+ } else if (this.options.size && this.options.size != 'auto' && this.$lis.not(notDisabled).length > this.options.size) {
+ var optIndex = this.$lis.not('.divider').not(notDisabled).children().slice(0, this.options.size).last().parent().index(),
+ divLength = this.$lis.slice(0, optIndex + 1).filter('.divider').length;
+ menuHeight = liHeight * this.options.size + divLength * divHeight + menuPadding.vert;
+
+ if (that.options.container) {
+ if (!$menu.data('height')) $menu.data('height', $menu.height());
+ getHeight = $menu.data('height');
+ } else {
+ getHeight = $menu.height();
+ }
+
if (that.options.dropupAuto) {
//noinspection JSUnusedAssignment
- this.$newElement.toggleClass('dropup', (selectOffsetTop > selectOffsetBot) && (menuHeight < menu.height()));
+ this.$newElement.toggleClass('dropup', selectOffsetTop > selectOffsetBot && (menuHeight - menuExtras.vert) < getHeight);
}
- menu.css({'max-height': menuHeight + headerHeight + searchHeight + actionsHeight + 'px', 'overflow': 'hidden'});
- menuInner.css({'max-height': menuHeight - menuPadding + 'px', 'overflow-y': 'auto'});
+ $menu.css({
+ 'max-height': menuHeight + headerHeight + searchHeight + actionsHeight + doneButtonHeight + 'px',
+ 'overflow': 'hidden',
+ 'min-height': ''
+ });
+ $menuInner.css({
+ 'max-height': menuHeight - menuPadding.vert + 'px',
+ 'overflow-y': 'auto',
+ 'min-height': ''
+ });
}
},
setWidth: function () {
- if (this.options.width == 'auto') {
+ if (this.options.width === 'auto') {
this.$menu.css('min-width', '0');
- // Get correct width if element hidden
- var selectClone = this.$newElement.clone().appendTo('body');
- var ulWidth = selectClone.find('> .dropdown-menu').css('width');
- var btnWidth = selectClone.css('width', 'auto').find('> button').css('width');
- selectClone.remove();
+ // Get correct width if element is hidden
+ var $selectClone = this.$menu.parent().clone().appendTo('body'),
+ $selectClone2 = this.options.container ? this.$newElement.clone().appendTo('body') : $selectClone,
+ ulWidth = $selectClone.children('.dropdown-menu').outerWidth(),
+ btnWidth = $selectClone2.css('width', 'auto').children('button').outerWidth();
+
+ $selectClone.remove();
+ $selectClone2.remove();
// Set width to whatever's larger, button title or longest option
- this.$newElement.css('width', Math.max(parseInt(ulWidth), parseInt(btnWidth)) + 'px');
- } else if (this.options.width == 'fit') {
+ this.$newElement.css('width', Math.max(ulWidth, btnWidth) + 'px');
+ } else if (this.options.width === 'fit') {
// Remove inline min-width so width can be changed from 'auto'
this.$menu.css('min-width', '');
this.$newElement.css('width', '').addClass('fit-width');
@@ -561,74 +1091,108 @@
},
selectPosition: function () {
+ this.$bsContainer = $('');
+
var that = this,
- drop = '',
- $drop = $(drop),
+ $container = $(this.options.container),
pos,
+ containerPos,
actualHeight,
getPlacement = function ($element) {
- $drop.addClass($element.attr('class').replace(/form-control/gi, '')).toggleClass('dropup', $element.hasClass('dropup'));
+ that.$bsContainer.addClass($element.attr('class').replace(/form-control|fit-width/gi, '')).toggleClass('dropup', $element.hasClass('dropup'));
pos = $element.offset();
+
+ if (!$container.is('body')) {
+ containerPos = $container.offset();
+ containerPos.top += parseInt($container.css('borderTopWidth')) - $container.scrollTop();
+ containerPos.left += parseInt($container.css('borderLeftWidth')) - $container.scrollLeft();
+ } else {
+ containerPos = { top: 0, left: 0 };
+ }
+
actualHeight = $element.hasClass('dropup') ? 0 : $element[0].offsetHeight;
- $drop.css({
- 'top': pos.top + actualHeight,
- 'left': pos.left,
- 'width': $element[0].offsetWidth,
- 'position': 'absolute'
+
+ that.$bsContainer.css({
+ 'top': pos.top - containerPos.top + actualHeight,
+ 'left': pos.left - containerPos.left,
+ 'width': $element[0].offsetWidth
});
};
- this.$newElement.on('click', function () {
+
+ this.$button.on('click', function () {
+ var $this = $(this);
+
if (that.isDisabled()) {
return;
}
- getPlacement($(this));
- $drop.appendTo(that.options.container);
- $drop.toggleClass('open', !$(this).hasClass('open'));
- $drop.append(that.$menu);
+
+ getPlacement(that.$newElement);
+
+ that.$bsContainer
+ .appendTo(that.options.container)
+ .toggleClass('open', !$this.hasClass('open'))
+ .append(that.$menu);
});
- $(window).resize(function () {
+
+ $(window).on('resize scroll', function () {
getPlacement(that.$newElement);
});
- $(window).on('scroll', function () {
- getPlacement(that.$newElement);
- });
- $('html').on('click', function (e) {
- if ($(e.target).closest(that.$newElement).length < 1) {
- $drop.removeClass('open');
- }
+
+ this.$element.on('hide.bs.select', function () {
+ that.$menu.data('height', that.$menu.height());
+ that.$bsContainer.detach();
});
},
- setSelected: function (index, selected) {
- this.findLis();
- this.$lis.filter('[data-original-index="' + index + '"]').toggleClass('selected', selected);
+ /**
+ * @param {number} index - the index of the option that is being changed
+ * @param {boolean} selected - true if the option is being selected, false if being deselected
+ * @param {JQuery} $lis - the 'li' element that is being modified
+ */
+ setSelected: function (index, selected, $lis) {
+ if (!$lis) {
+ this.togglePlaceholder(); // check if setSelected is being called by changing the value of the select
+ $lis = this.findLis().eq(this.liObj[index]);
+ }
+
+ $lis.toggleClass('selected', selected).find('a').attr('aria-selected', selected);
},
- setDisabled: function (index, disabled) {
- this.findLis();
+ /**
+ * @param {number} index - the index of the option that is being disabled
+ * @param {boolean} disabled - true if the option is being disabled, false if being enabled
+ * @param {JQuery} $lis - the 'li' element that is being modified
+ */
+ setDisabled: function (index, disabled, $lis) {
+ if (!$lis) {
+ $lis = this.findLis().eq(this.liObj[index]);
+ }
+
if (disabled) {
- this.$lis.filter('[data-original-index="' + index + '"]').addClass('disabled').find('a').attr('href', '#').attr('tabindex', -1);
+ $lis.addClass('disabled').children('a').attr('href', '#').attr('tabindex', -1).attr('aria-disabled', true);
} else {
- this.$lis.filter('[data-original-index="' + index + '"]').removeClass('disabled').find('a').removeAttr('href').attr('tabindex', 0);
+ $lis.removeClass('disabled').children('a').removeAttr('href').attr('tabindex', 0).attr('aria-disabled', false);
}
},
isDisabled: function () {
- return this.$element.is(':disabled');
+ return this.$element[0].disabled;
},
checkDisabled: function () {
var that = this;
if (this.isDisabled()) {
- this.$button.addClass('disabled').attr('tabindex', -1);
+ this.$newElement.addClass('disabled');
+ this.$button.addClass('disabled').attr('tabindex', -1).attr('aria-disabled', true);
} else {
if (this.$button.hasClass('disabled')) {
- this.$button.removeClass('disabled');
+ this.$newElement.removeClass('disabled');
+ this.$button.removeClass('disabled').attr('aria-disabled', false);
}
- if (this.$button.attr('tabindex') == -1) {
- if (!this.$element.data('tabindex')) this.$button.removeAttr('tabindex');
+ if (this.$button.attr('tabindex') == -1 && !this.$element.data('tabindex')) {
+ this.$button.removeAttr('tabindex');
}
}
@@ -637,37 +1201,62 @@
});
},
+ togglePlaceholder: function () {
+ var value = this.$element.val();
+ this.$button.toggleClass('bs-placeholder', value === null || value === '' || (value.constructor === Array && value.length === 0));
+ },
+
tabIndex: function () {
- if (this.$element.is('[tabindex]')) {
+ if (this.$element.data('tabindex') !== this.$element.attr('tabindex') &&
+ (this.$element.attr('tabindex') !== -98 && this.$element.attr('tabindex') !== '-98')) {
this.$element.data('tabindex', this.$element.attr('tabindex'));
this.$button.attr('tabindex', this.$element.data('tabindex'));
}
+
+ this.$element.attr('tabindex', -98);
},
clickListener: function () {
- var that = this;
+ var that = this,
+ $document = $(document);
- this.$newElement.on('touchstart.dropdown', '.dropdown-menu', function (e) {
- e.stopPropagation();
- });
+ $document.data('spaceSelect', false);
- this.$newElement.on('click', function () {
- that.setSize();
- if (!that.options.liveSearch && !that.multiple) {
- setTimeout(function () {
- that.$menu.find('.selected a').focus();
- }, 10);
+ this.$button.on('keyup', function (e) {
+ if (/(32)/.test(e.keyCode.toString(10)) && $document.data('spaceSelect')) {
+ e.preventDefault();
+ $document.data('spaceSelect', false);
}
});
- this.$menu.on('click', 'li a', function (e) {
+ this.$button.on('click', function () {
+ that.setSize();
+ });
+
+ this.$element.on('shown.bs.select', function () {
+ if (!that.options.liveSearch && !that.multiple) {
+ that.$menuInner.find('.selected a').focus();
+ } else if (!that.multiple) {
+ var selectedIndex = that.liObj[that.$element[0].selectedIndex];
+
+ if (typeof selectedIndex !== 'number' || that.options.size === false) return;
+
+ // scroll to selected option
+ var offset = that.$lis.eq(selectedIndex)[0].offsetTop - that.$menuInner[0].offsetTop;
+ offset = offset - that.$menuInner[0].offsetHeight/2 + that.sizeInfo.liHeight/2;
+ that.$menuInner[0].scrollTop = offset;
+ }
+ });
+
+ this.$menuInner.on('click', 'li a', function (e) {
var $this = $(this),
clickedIndex = $this.parent().data('originalIndex'),
prevValue = that.$element.val(),
- prevIndex = that.$element.prop('selectedIndex');
+ prevIndex = that.$element.prop('selectedIndex'),
+ triggerChange = true;
// Don't close on multi choice menu
- if (that.multiple) {
+ if (that.multiple && that.options.maxOptions !== 1) {
e.stopPropagation();
}
@@ -685,14 +1274,14 @@
if (!that.multiple) { // Deselect all others if not multi select box
$options.prop('selected', false);
$option.prop('selected', true);
- that.$menu.find('.selected').removeClass('selected');
+ that.$menuInner.find('.selected').removeClass('selected').find('a').attr('aria-selected', false);
that.setSelected(clickedIndex, true);
} else { // Toggle the one we have chosen if we are multi select.
$option.prop('selected', !state);
that.setSelected(clickedIndex, !state);
$this.blur();
- if ((maxOptions !== false) || (maxOptionsGrp !== false)) {
+ if (maxOptions !== false || maxOptionsGrp !== false) {
var maxReached = maxOptions < $options.filter(':selected').length,
maxReachedGrp = maxOptionsGrp < $optgroup.find('option:selected').length;
@@ -700,19 +1289,17 @@
if (maxOptions && maxOptions == 1) {
$options.prop('selected', false);
$option.prop('selected', true);
- that.$menu.find('.selected').removeClass('selected');
+ that.$menuInner.find('.selected').removeClass('selected');
that.setSelected(clickedIndex, true);
} else if (maxOptionsGrp && maxOptionsGrp == 1) {
$optgroup.find('option:selected').prop('selected', false);
$option.prop('selected', true);
- var optgroupID = $this.data('optgroup');
-
- that.$menu.find('.selected').has('a[data-optgroup="' + optgroupID + '"]').removeClass('selected');
-
+ var optgroupID = $this.parent().data('optgroup');
+ that.$menuInner.find('[data-optgroup="' + optgroupID + '"]').removeClass('selected');
that.setSelected(clickedIndex, true);
} else {
- var maxOptionsArr = (typeof that.options.maxOptionsText === 'function') ?
- that.options.maxOptionsText(maxOptions, maxOptionsGrp) : that.options.maxOptionsText,
+ var maxOptionsText = typeof that.options.maxOptionsText === 'string' ? [that.options.maxOptionsText, that.options.maxOptionsText] : that.options.maxOptionsText,
+ maxOptionsArr = typeof maxOptionsText === 'function' ? maxOptionsText(maxOptions, maxOptionsGrp) : maxOptionsText,
maxTxt = maxOptionsArr[0].replace('{n}', maxOptions),
maxTxtGrp = maxOptionsArr[1].replace('{n}', maxOptionsGrp),
$notify = $('');
@@ -729,11 +1316,13 @@
if (maxOptions && maxReached) {
$notify.append($('' + maxTxt + '
'));
+ triggerChange = false;
that.$element.trigger('maxReached.bs.select');
}
if (maxOptionsGrp && maxReachedGrp) {
$notify.append($('' + maxTxtGrp + '
'));
+ triggerChange = false;
that.$element.trigger('maxReachedGrp.bs.select');
}
@@ -749,50 +1338,54 @@
}
}
- if (!that.multiple) {
+ if (!that.multiple || (that.multiple && that.options.maxOptions === 1)) {
that.$button.focus();
} else if (that.options.liveSearch) {
that.$searchbox.focus();
}
// Trigger select 'change'
- if ((prevValue != that.$element.val() && that.multiple) || (prevIndex != that.$element.prop('selectedIndex') && !that.multiple)) {
- that.$element.change();
+ if (triggerChange) {
+ if ((prevValue != that.$element.val() && that.multiple) || (prevIndex != that.$element.prop('selectedIndex') && !that.multiple)) {
+ // $option.prop('selected') is current option state (selected/unselected). state is previous option state.
+ changed_arguments = [clickedIndex, $option.prop('selected'), state];
+ that.$element
+ .triggerNative('change');
+ }
}
}
});
this.$menu.on('click', 'li.disabled a, .popover-title, .popover-title :not(.close)', function (e) {
- if (e.target == this) {
+ if (e.currentTarget == this) {
e.preventDefault();
e.stopPropagation();
- if (!that.options.liveSearch) {
- that.$button.focus();
- } else {
+ if (that.options.liveSearch && !$(e.target).hasClass('close')) {
that.$searchbox.focus();
+ } else {
+ that.$button.focus();
}
}
});
- this.$menu.on('click', 'li.divider, li.dropdown-header', function (e) {
+ this.$menuInner.on('click', '.divider, .dropdown-header', function (e) {
e.preventDefault();
e.stopPropagation();
- if (!that.options.liveSearch) {
- that.$button.focus();
- } else {
+ if (that.options.liveSearch) {
that.$searchbox.focus();
+ } else {
+ that.$button.focus();
}
});
this.$menu.on('click', '.popover-title .close', function () {
- that.$button.focus();
+ that.$button.click();
});
this.$searchbox.on('click', function (e) {
e.stopPropagation();
});
-
this.$menu.on('click', '.actions-btn', function (e) {
if (that.options.liveSearch) {
that.$searchbox.focus();
@@ -803,31 +1396,32 @@
e.preventDefault();
e.stopPropagation();
- if ($(this).is('.bs-select-all')) {
+ if ($(this).hasClass('bs-select-all')) {
that.selectAll();
} else {
that.deselectAll();
}
- that.$element.change();
});
this.$element.change(function () {
that.render(false);
+ that.$element.trigger('changed.bs.select', changed_arguments);
+ changed_arguments = null;
});
},
liveSearchListener: function () {
var that = this,
- no_results = $('');
+ $no_results = $('
');
- this.$newElement.on('click.dropdown.data-api touchstart.dropdown.data-api', function () {
- that.$menu.find('.active').removeClass('active');
+ this.$button.on('click.dropdown.data-api', function () {
+ that.$menuInner.find('.active').removeClass('active');
if (!!that.$searchbox.val()) {
that.$searchbox.val('');
- that.$lis.not('.is-hidden').removeClass('hide');
- if (!!no_results.parent().length) no_results.remove();
+ that.$lis.not('.is-hidden').removeClass('hidden');
+ if (!!$no_results.parent().length) $no_results.remove();
}
- if (!that.multiple) that.$menu.find('.selected').addClass('active');
+ if (!that.multiple) that.$menuInner.find('.selected').addClass('active');
setTimeout(function () {
that.$searchbox.focus();
}, 10);
@@ -838,33 +1432,64 @@
});
this.$searchbox.on('input propertychange', function () {
+ that.$lis.not('.is-hidden').removeClass('hidden');
+ that.$lis.filter('.active').removeClass('active');
+ $no_results.remove();
+
if (that.$searchbox.val()) {
-
- if (that.options.searchAccentInsensitive) {
- that.$lis.not('.is-hidden').removeClass('hide').find('a').not(':aicontains(' + normalizeToBase(that.$searchbox.val()) + ')').parent().addClass('hide');
+ var $searchBase = that.$lis.not('.is-hidden, .divider, .dropdown-header'),
+ $hideItems;
+ if (that.options.liveSearchNormalize) {
+ $hideItems = $searchBase.not(':a' + that._searchStyle() + '("' + normalizeToBase(that.$searchbox.val()) + '")');
} else {
- that.$lis.not('.is-hidden').removeClass('hide').find('a').not(':icontains(' + that.$searchbox.val() + ')').parent().addClass('hide');
+ $hideItems = $searchBase.not(':' + that._searchStyle() + '("' + that.$searchbox.val() + '")');
}
- if (!that.$menu.find('li').filter(':visible:not(.no-results)').length) {
- if (!!no_results.parent().length) no_results.remove();
- no_results.html(that.options.noneResultsText + ' "' + htmlEscape(that.$searchbox.val()) + '"').show();
- that.$menu.find('li').last().after(no_results);
- } else if (!!no_results.parent().length) {
- no_results.remove();
- }
+ if ($hideItems.length === $searchBase.length) {
+ $no_results.html(that.options.noneResultsText.replace('{0}', '"' + htmlEscape(that.$searchbox.val()) + '"'));
+ that.$menuInner.append($no_results);
+ that.$lis.addClass('hidden');
+ } else {
+ $hideItems.addClass('hidden');
- } else {
- that.$lis.not('.is-hidden').removeClass('hide');
- if (!!no_results.parent().length) no_results.remove();
+ var $lisVisible = that.$lis.not('.hidden'),
+ $foundDiv;
+
+ // hide divider if first or last visible, or if followed by another divider
+ $lisVisible.each(function (index) {
+ var $this = $(this);
+
+ if ($this.hasClass('divider')) {
+ if ($foundDiv === undefined) {
+ $this.addClass('hidden');
+ } else {
+ if ($foundDiv) $foundDiv.addClass('hidden');
+ $foundDiv = $this;
+ }
+ } else if ($this.hasClass('dropdown-header') && $lisVisible.eq(index + 1).data('optgroup') !== $this.data('optgroup')) {
+ $this.addClass('hidden');
+ } else {
+ $foundDiv = null;
+ }
+ });
+ if ($foundDiv) $foundDiv.addClass('hidden');
+
+ $searchBase.not('.hidden').first().addClass('active');
+ that.$menuInner.scrollTop(0);
+ }
}
-
- that.$menu.find('li.active').removeClass('active');
- that.$menu.find('li').filter(':visible:not(.divider)').eq(0).addClass('active').find('a').focus();
- $(this).focus();
});
},
+ _searchStyle: function () {
+ var styles = {
+ begins: 'ibegins',
+ startsWith: 'ibegins'
+ };
+
+ return styles[this.options.liveSearchStyle] || 'icontains';
+ },
+
val: function (value) {
if (typeof value !== 'undefined') {
this.$element.val(value);
@@ -876,29 +1501,65 @@
}
},
- selectAll: function () {
+ changeAll: function (status) {
+ if (!this.multiple) return;
+ if (typeof status === 'undefined') status = true;
+
this.findLis();
- this.$lis.not('.divider').not('.disabled').not('.selected').filter(':visible').find('a').click();
+
+ var $options = this.$element.find('option'),
+ $lisVisible = this.$lis.not('.divider, .dropdown-header, .disabled, .hidden'),
+ lisVisLen = $lisVisible.length,
+ selectedOptions = [];
+
+ if (status) {
+ if ($lisVisible.filter('.selected').length === $lisVisible.length) return;
+ } else {
+ if ($lisVisible.filter('.selected').length === 0) return;
+ }
+
+ $lisVisible.toggleClass('selected', status);
+
+ for (var i = 0; i < lisVisLen; i++) {
+ var origIndex = $lisVisible[i].getAttribute('data-original-index');
+ selectedOptions[selectedOptions.length] = $options.eq(origIndex)[0];
+ }
+
+ $(selectedOptions).prop('selected', status);
+
+ this.render(false);
+
+ this.togglePlaceholder();
+
+ this.$element
+ .triggerNative('change');
+ },
+
+ selectAll: function () {
+ return this.changeAll(true);
},
deselectAll: function () {
- this.findLis();
- this.$lis.not('.divider').not('.disabled').filter('.selected').filter(':visible').find('a').click();
+ return this.changeAll(false);
+ },
+
+ toggle: function (e) {
+ e = e || window.event;
+
+ if (e) e.stopPropagation();
+
+ this.$button.trigger('click');
},
keydown: function (e) {
var $this = $(this),
- $parent = ($this.is('input')) ? $this.parent().parent() : $this.parent(),
+ $parent = $this.is('input') ? $this.parent().parent() : $this.parent(),
$items,
that = $parent.data('this'),
index,
- next,
- first,
- last,
- prev,
- nextPrev,
prevIndex,
isActive,
+ selector = ':not(.disabled, .hidden, .dropdown-header, .divider)',
keyCodeMap = {
32: ' ',
48: '0',
@@ -950,93 +1611,58 @@
105: '9'
};
- if (that.options.liveSearch) $parent = $this.parent().parent();
- if (that.options.container) $parent = that.$menu;
+ isActive = that.$newElement.hasClass('open');
- $items = $('[role=menu] li a', $parent);
-
- isActive = that.$menu.parent().hasClass('open');
-
- if (!isActive && /([0-9]|[A-z])/.test(String.fromCharCode(e.keyCode))) {
+ if (!isActive && (e.keyCode >= 48 && e.keyCode <= 57 || e.keyCode >= 96 && e.keyCode <= 105 || e.keyCode >= 65 && e.keyCode <= 90)) {
if (!that.options.container) {
that.setSize();
that.$menu.parent().addClass('open');
isActive = true;
} else {
- that.$newElement.trigger('click');
+ that.$button.trigger('click');
}
that.$searchbox.focus();
+ return;
}
if (that.options.liveSearch) {
- if (/(^9$|27)/.test(e.keyCode.toString(10)) && isActive && that.$menu.find('.active').length === 0) {
+ if (/(^9$|27)/.test(e.keyCode.toString(10)) && isActive) {
e.preventDefault();
- that.$menu.parent().removeClass('open');
+ e.stopPropagation();
+ that.$menuInner.click();
that.$button.focus();
}
- $items = $('[role=menu] li:not(.divider):not(.dropdown-header):visible', $parent);
- if (!$this.val() && !/(38|40)/.test(e.keyCode.toString(10))) {
- if ($items.filter('.active').length === 0) {
- if (that.options.searchAccentInsensitive) {
- $items = that.$newElement.find('li').filter(':aicontains(' + normalizeToBase(keyCodeMap[e.keyCode]) + ')');
- } else {
- $items = that.$newElement.find('li').filter(':icontains(' + keyCodeMap[e.keyCode] + ')');
- }
- }
- }
}
- if (!$items.length) return;
-
if (/(38|40)/.test(e.keyCode.toString(10))) {
- index = $items.index($items.filter(':focus'));
- first = $items.parent(':not(.disabled):visible').first().index();
- last = $items.parent(':not(.disabled):visible').last().index();
- next = $items.eq(index).parent().nextAll(':not(.disabled):visible').eq(0).index();
- prev = $items.eq(index).parent().prevAll(':not(.disabled):visible').eq(0).index();
- nextPrev = $items.eq(next).parent().prevAll(':not(.disabled):visible').eq(0).index();
-
- if (that.options.liveSearch) {
- $items.each(function (i) {
- if ($(this).is(':not(.disabled)')) {
- $(this).data('index', i);
- }
- });
- index = $items.index($items.filter('.active'));
- first = $items.filter(':not(.disabled):visible').first().data('index');
- last = $items.filter(':not(.disabled):visible').last().data('index');
- next = $items.eq(index).nextAll(':not(.disabled):visible').eq(0).data('index');
- prev = $items.eq(index).prevAll(':not(.disabled):visible').eq(0).data('index');
- nextPrev = $items.eq(next).prevAll(':not(.disabled):visible').eq(0).data('index');
- }
-
- prevIndex = $this.data('prevIndex');
-
- if (e.keyCode == 38) {
- if (that.options.liveSearch) index -= 1;
- if (index != nextPrev && index > prev) index = prev;
- if (index < first) index = first;
- if (index == prevIndex) index = last;
- }
-
- if (e.keyCode == 40) {
- if (that.options.liveSearch) index += 1;
- if (index == -1) index = 0;
- if (index != nextPrev && index < next) index = next;
- if (index > last) index = last;
- if (index == prevIndex) index = first;
- }
-
- $this.data('prevIndex', index);
+ $items = that.$lis.filter(selector);
+ if (!$items.length) return;
if (!that.options.liveSearch) {
- $items.eq(index).focus();
+ index = $items.index($items.find('a').filter(':focus').parent());
+ } else {
+ index = $items.index($items.filter('.active'));
+ }
+
+ prevIndex = that.$menuInner.data('prevIndex');
+
+ if (e.keyCode == 38) {
+ if ((that.options.liveSearch || index == prevIndex) && index != -1) index--;
+ if (index < 0) index += $items.length;
+ } else if (e.keyCode == 40) {
+ if (that.options.liveSearch || index == prevIndex) index++;
+ index = index % $items.length;
+ }
+
+ that.$menuInner.data('prevIndex', index);
+
+ if (!that.options.liveSearch) {
+ $items.eq(index).children('a').focus();
} else {
e.preventDefault();
- if (!$this.is('.dropdown-toggle')) {
- $items.removeClass('active');
- $items.eq(index).addClass('active').find('a').focus();
+ if (!$this.hasClass('dropdown-toggle')) {
+ $items.removeClass('active').eq(index).addClass('active').children('a').focus();
$this.focus();
}
}
@@ -1046,11 +1672,10 @@
count,
prevKey;
- $items.each(function () {
- if ($(this).parent().is(':not(.disabled)')) {
- if ($.trim($(this).text().toLowerCase()).substring(0, 1) == keyCodeMap[e.keyCode]) {
- keyIndex.push($(this).parent().index());
- }
+ $items = that.$lis.filter(selector);
+ $items.each(function (i) {
+ if ($.trim($(this).children('a').text().toLowerCase()).substring(0, 1) == keyCodeMap[e.keyCode]) {
+ keyIndex.push(i);
}
});
@@ -1068,16 +1693,23 @@
if (count > keyIndex.length) count = 1;
}
- $items.eq(keyIndex[count - 1]).focus();
+ $items.eq(keyIndex[count - 1]).children('a').focus();
}
// Select focused option if "Enter", "Spacebar" or "Tab" (when selectOnTab is true) are pressed inside the menu.
if ((/(13|32)/.test(e.keyCode.toString(10)) || (/(^9$)/.test(e.keyCode.toString(10)) && that.options.selectOnTab)) && isActive) {
if (!/(32)/.test(e.keyCode.toString(10))) e.preventDefault();
if (!that.options.liveSearch) {
- $(':focus').click();
+ var elem = $(':focus');
+ elem.click();
+ // Bring back focus for multiselects
+ elem.focus();
+ // Prevent screen from scrolling if the user hit the spacebar
+ e.preventDefault();
+ // Fixes spacebar selection of dropdown items in FF & IE
+ $(document).data('spaceSelect', true);
} else if (!/(32)/.test(e.keyCode.toString(10))) {
- that.$menu.find('.active a').click();
+ that.$menuInner.find('.active a').click();
$this.focus();
}
$(document).data('keycount', 0);
@@ -1085,31 +1717,27 @@
if ((/(^9$|27)/.test(e.keyCode.toString(10)) && isActive && (that.multiple || that.options.liveSearch)) || (/(27)/.test(e.keyCode.toString(10)) && !isActive)) {
that.$menu.parent().removeClass('open');
+ if (that.options.container) that.$newElement.removeClass('open');
that.$button.focus();
}
},
mobile: function () {
- this.$element.addClass('mobile-device').appendTo(this.$newElement);
- if (this.options.container) this.$menu.hide();
+ this.$element.addClass('mobile-device');
},
refresh: function () {
this.$lis = null;
+ this.liObj = {};
this.reloadLi();
this.render();
- this.setWidth();
- this.setStyle();
this.checkDisabled();
- this.liHeight();
- },
+ this.liHeight(true);
+ this.setStyle();
+ this.setWidth();
+ if (this.$lis) this.$searchbox.trigger('propertychange');
- update: function () {
- this.reloadLi();
- this.setWidth();
- this.setStyle();
- this.checkDisabled();
- this.liHeight();
+ this.$element.trigger('refreshed.bs.select');
},
hide: function () {
@@ -1123,37 +1751,46 @@
remove: function () {
this.$newElement.remove();
this.$element.remove();
+ },
+
+ destroy: function () {
+ this.$newElement.before(this.$element).remove();
+
+ if (this.$bsContainer) {
+ this.$bsContainer.remove();
+ } else {
+ this.$menu.remove();
+ }
+
+ this.$element
+ .off('.bs.select')
+ .removeData('selectpicker')
+ .removeClass('bs-select-hidden selectpicker');
}
};
// SELECTPICKER PLUGIN DEFINITION
// ==============================
- function Plugin(option, event) {
+ function Plugin(option) {
// get the args of the outer function..
var args = arguments;
// The arguments of the function are explicitly re-defined from the argument list, because the shift causes them
- // to get lost
- //noinspection JSDuplicatedDeclaration
- var _option = option,
- option = args[0],
- event = args[1];
- [].shift.apply(args);
+ // to get lost/corrupted in android 2.3 and IE9 #715 #775
+ var _option = option;
- // This fixes a bug in the js implementation on android 2.3 #715
- if (typeof option == 'undefined') {
- option = _option;
- }
+ [].shift.apply(args);
var value;
var chain = this.each(function () {
var $this = $(this);
if ($this.is('select')) {
var data = $this.data('selectpicker'),
- options = typeof option == 'object' && option;
+ options = typeof _option == 'object' && _option;
if (!data) {
var config = $.extend({}, Selectpicker.DEFAULTS, $.fn.selectpicker.defaults || {}, $this.data(), options);
- $this.data('selectpicker', (data = new Selectpicker(this, config, event)));
+ config.template = $.extend({}, Selectpicker.DEFAULTS.template, ($.fn.selectpicker.defaults ? $.fn.selectpicker.defaults.template : {}), $this.data().template, options.template);
+ $this.data('selectpicker', (data = new Selectpicker(this, config)));
} else if (options) {
for (var i in options) {
if (options.hasOwnProperty(i)) {
@@ -1162,11 +1799,11 @@
}
}
- if (typeof option == 'string') {
- if (data[option] instanceof Function) {
- value = data[option].apply(data, args);
+ if (typeof _option == 'string') {
+ if (data[_option] instanceof Function) {
+ value = data[_option].apply(data, args);
} else {
- value = data.options[option];
+ value = data.options[_option];
}
}
}
@@ -1193,8 +1830,8 @@
$(document)
.data('keycount', 0)
- .on('keydown', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role=menu], .bs-searchbox input', Selectpicker.prototype.keydown)
- .on('focusin.modal', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role=menu], .bs-searchbox input', function (e) {
+ .on('keydown.bs.select', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input', Selectpicker.prototype.keydown)
+ .on('focusin.modal', '.bootstrap-select [data-toggle=dropdown], .bootstrap-select [role="listbox"], .bs-searchbox input', function (e) {
e.stopPropagation();
});
diff --git a/RIGS/static/js/button.js b/RIGS/static/js/button.js
old mode 100644
new mode 100755
index 4d569017..843b39c9
--- a/RIGS/static/js/button.js
+++ b/RIGS/static/js/button.js
@@ -1,8 +1,8 @@
/* ========================================================================
- * Bootstrap: button.js v3.3.2
+ * Bootstrap: button.js v3.3.7
* http://getbootstrap.com/javascript/#buttons
* ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
+ * Copyright 2011-2016 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
@@ -19,7 +19,7 @@
this.isLoading = false
}
- Button.VERSION = '3.3.2'
+ Button.VERSION = '3.3.7'
Button.DEFAULTS = {
loadingText: 'loading...'
@@ -31,7 +31,7 @@
var val = $el.is('input') ? 'val' : 'html'
var data = $el.data()
- state = state + 'Text'
+ state += 'Text'
if (data.resetText == null) $el.data('resetText', $el[val]())
@@ -41,10 +41,10 @@
if (state == 'loadingText') {
this.isLoading = true
- $el.addClass(d).attr(d, d)
+ $el.addClass(d).attr(d, d).prop(d, true)
} else if (this.isLoading) {
this.isLoading = false
- $el.removeClass(d).removeAttr(d)
+ $el.removeClass(d).removeAttr(d).prop(d, false)
}
}, this), 0)
}
@@ -56,15 +56,19 @@
if ($parent.length) {
var $input = this.$element.find('input')
if ($input.prop('type') == 'radio') {
- if ($input.prop('checked') && this.$element.hasClass('active')) changed = false
- else $parent.find('.active').removeClass('active')
+ if ($input.prop('checked')) changed = false
+ $parent.find('.active').removeClass('active')
+ this.$element.addClass('active')
+ } else if ($input.prop('type') == 'checkbox') {
+ if (($input.prop('checked')) !== this.$element.hasClass('active')) changed = false
+ this.$element.toggleClass('active')
}
- if (changed) $input.prop('checked', !this.$element.hasClass('active')).trigger('change')
+ $input.prop('checked', this.$element.hasClass('active'))
+ if (changed) $input.trigger('change')
} else {
this.$element.attr('aria-pressed', !this.$element.hasClass('active'))
+ this.$element.toggleClass('active')
}
-
- if (changed) this.$element.toggleClass('active')
}
@@ -104,10 +108,15 @@
$(document)
.on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
- var $btn = $(e.target)
- if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
+ var $btn = $(e.target).closest('.btn')
Plugin.call($btn, 'toggle')
- e.preventDefault()
+ if (!($(e.target).is('input[type="radio"], input[type="checkbox"]'))) {
+ // Prevent double click on radios, and the double selections (so cancellation) on checkboxes
+ e.preventDefault()
+ // The target component still receive the focus
+ if ($btn.is('input,button')) $btn.trigger('focus')
+ else $btn.find('input:visible,button:visible').first().trigger('focus')
+ }
})
.on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
$(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
diff --git a/RIGS/static/js/carousel.js b/RIGS/static/js/carousel.js
old mode 100644
new mode 100755
index 450e1812..6ff954c9
--- a/RIGS/static/js/carousel.js
+++ b/RIGS/static/js/carousel.js
@@ -1,8 +1,8 @@
/* ========================================================================
- * Bootstrap: carousel.js v3.3.2
+ * Bootstrap: carousel.js v3.3.7
* http://getbootstrap.com/javascript/#carousel
* ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
+ * Copyright 2011-2016 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
@@ -17,10 +17,10 @@
this.$element = $(element)
this.$indicators = this.$element.find('.carousel-indicators')
this.options = options
- this.paused =
- this.sliding =
- this.interval =
- this.$active =
+ this.paused = null
+ this.sliding = null
+ this.interval = null
+ this.$active = null
this.$items = null
this.options.keyboard && this.$element.on('keydown.bs.carousel', $.proxy(this.keydown, this))
@@ -30,7 +30,7 @@
.on('mouseleave.bs.carousel', $.proxy(this.cycle, this))
}
- Carousel.VERSION = '3.3.2'
+ Carousel.VERSION = '3.3.7'
Carousel.TRANSITION_DURATION = 600
diff --git a/RIGS/static/js/collapse.js b/RIGS/static/js/collapse.js
old mode 100644
new mode 100755
index 2bc30e7b..12038693
--- a/RIGS/static/js/collapse.js
+++ b/RIGS/static/js/collapse.js
@@ -1,11 +1,12 @@
/* ========================================================================
- * Bootstrap: collapse.js v3.3.2
+ * Bootstrap: collapse.js v3.3.7
* http://getbootstrap.com/javascript/#collapse
* ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
+ * Copyright 2011-2016 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
+/* jshint latedef: false */
+function ($) {
'use strict';
@@ -16,7 +17,8 @@
var Collapse = function (element, options) {
this.$element = $(element)
this.options = $.extend({}, Collapse.DEFAULTS, options)
- this.$trigger = $(this.options.trigger).filter('[href="#' + element.id + '"], [data-target="#' + element.id + '"]')
+ this.$trigger = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
+ '[data-toggle="collapse"][data-target="#' + element.id + '"]')
this.transitioning = null
if (this.options.parent) {
@@ -28,13 +30,12 @@
if (this.options.toggle) this.toggle()
}
- Collapse.VERSION = '3.3.2'
+ Collapse.VERSION = '3.3.7'
Collapse.TRANSITION_DURATION = 350
Collapse.DEFAULTS = {
- toggle: true,
- trigger: '[data-toggle="collapse"]'
+ toggle: true
}
Collapse.prototype.dimension = function () {
@@ -172,7 +173,7 @@
var data = $this.data('bs.collapse')
var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)
- if (!data && options.toggle && option == 'show') options.toggle = false
+ if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
if (typeof option == 'string') data[option]()
})
@@ -203,7 +204,7 @@
var $target = getTargetFromTrigger($this)
var data = $target.data('bs.collapse')
- var option = data ? 'toggle' : $.extend({}, $this.data(), { trigger: this })
+ var option = data ? 'toggle' : $this.data()
Plugin.call($target, option)
})
diff --git a/RIGS/static/js/dropdown.js b/RIGS/static/js/dropdown.js
old mode 100644
new mode 100755
index 200e1c67..04e9c2de
--- a/RIGS/static/js/dropdown.js
+++ b/RIGS/static/js/dropdown.js
@@ -1,8 +1,8 @@
/* ========================================================================
- * Bootstrap: dropdown.js v3.3.2
+ * Bootstrap: dropdown.js v3.3.7
* http://getbootstrap.com/javascript/#dropdowns
* ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
+ * Copyright 2011-2016 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
@@ -19,7 +19,41 @@
$(element).on('click.bs.dropdown', this.toggle)
}
- Dropdown.VERSION = '3.3.2'
+ Dropdown.VERSION = '3.3.7'
+
+ function getParent($this) {
+ var selector = $this.attr('data-target')
+
+ if (!selector) {
+ selector = $this.attr('href')
+ selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
+ }
+
+ var $parent = selector && $(selector)
+
+ return $parent && $parent.length ? $parent : $this.parent()
+ }
+
+ function clearMenus(e) {
+ if (e && e.which === 3) return
+ $(backdrop).remove()
+ $(toggle).each(function () {
+ var $this = $(this)
+ var $parent = getParent($this)
+ var relatedTarget = { relatedTarget: this }
+
+ if (!$parent.hasClass('open')) return
+
+ if (e && e.type == 'click' && /input|textarea/i.test(e.target.tagName) && $.contains($parent[0], e.target)) return
+
+ $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
+
+ if (e.isDefaultPrevented()) return
+
+ $this.attr('aria-expanded', 'false')
+ $parent.removeClass('open').trigger($.Event('hidden.bs.dropdown', relatedTarget))
+ })
+ }
Dropdown.prototype.toggle = function (e) {
var $this = $(this)
@@ -34,7 +68,10 @@
if (!isActive) {
if ('ontouchstart' in document.documentElement && !$parent.closest('.navbar-nav').length) {
// if mobile we use a backdrop because click events don't delegate
- $('
').insertAfter($(this)).on('click', clearMenus)
+ $(document.createElement('div'))
+ .addClass('dropdown-backdrop')
+ .insertAfter($(this))
+ .on('click', clearMenus)
}
var relatedTarget = { relatedTarget: this }
@@ -48,7 +85,7 @@
$parent
.toggleClass('open')
- .trigger('shown.bs.dropdown', relatedTarget)
+ .trigger($.Event('shown.bs.dropdown', relatedTarget))
}
return false
@@ -67,57 +104,25 @@
var $parent = getParent($this)
var isActive = $parent.hasClass('open')
- if ((!isActive && e.which != 27) || (isActive && e.which == 27)) {
+ if (!isActive && e.which != 27 || isActive && e.which == 27) {
if (e.which == 27) $parent.find(toggle).trigger('focus')
return $this.trigger('click')
}
- var desc = ' li:not(.divider):visible a'
- var $items = $parent.find('[role="menu"]' + desc + ', [role="listbox"]' + desc)
+ var desc = ' li:not(.disabled):visible a'
+ var $items = $parent.find('.dropdown-menu' + desc)
if (!$items.length) return
var index = $items.index(e.target)
- if (e.which == 38 && index > 0) index-- // up
- if (e.which == 40 && index < $items.length - 1) index++ // down
- if (!~index) index = 0
+ if (e.which == 38 && index > 0) index-- // up
+ if (e.which == 40 && index < $items.length - 1) index++ // down
+ if (!~index) index = 0
$items.eq(index).trigger('focus')
}
- function clearMenus(e) {
- if (e && e.which === 3) return
- $(backdrop).remove()
- $(toggle).each(function () {
- var $this = $(this)
- var $parent = getParent($this)
- var relatedTarget = { relatedTarget: this }
-
- if (!$parent.hasClass('open')) return
-
- $parent.trigger(e = $.Event('hide.bs.dropdown', relatedTarget))
-
- if (e.isDefaultPrevented()) return
-
- $this.attr('aria-expanded', 'false')
- $parent.removeClass('open').trigger('hidden.bs.dropdown', relatedTarget)
- })
- }
-
- function getParent($this) {
- var selector = $this.attr('data-target')
-
- if (!selector) {
- selector = $this.attr('href')
- selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
- }
-
- var $parent = selector && $(selector)
-
- return $parent && $parent.length ? $parent : $this.parent()
- }
-
// DROPDOWN PLUGIN DEFINITION
// ==========================
@@ -155,7 +160,6 @@
.on('click.bs.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
.on('click.bs.dropdown.data-api', toggle, Dropdown.prototype.toggle)
.on('keydown.bs.dropdown.data-api', toggle, Dropdown.prototype.keydown)
- .on('keydown.bs.dropdown.data-api', '[role="menu"]', Dropdown.prototype.keydown)
- .on('keydown.bs.dropdown.data-api', '[role="listbox"]', Dropdown.prototype.keydown)
+ .on('keydown.bs.dropdown.data-api', '.dropdown-menu', Dropdown.prototype.keydown)
}(jQuery);
diff --git a/RIGS/static/js/modal.js b/RIGS/static/js/modal.js
old mode 100644
new mode 100755
index d50a8560..f84142d8
--- a/RIGS/static/js/modal.js
+++ b/RIGS/static/js/modal.js
@@ -1,8 +1,8 @@
/* ========================================================================
- * Bootstrap: modal.js v3.3.5
+ * Bootstrap: modal.js v3.3.7
* http://getbootstrap.com/javascript/#modals
* ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
+ * Copyright 2011-2016 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
@@ -33,7 +33,7 @@
}
}
- Modal.VERSION = '3.3.5'
+ Modal.VERSION = '3.3.7'
Modal.TRANSITION_DURATION = 300
Modal.BACKDROP_TRANSITION_DURATION = 150
@@ -140,7 +140,9 @@
$(document)
.off('focusin.bs.modal') // guard against infinite focus loop
.on('focusin.bs.modal', $.proxy(function (e) {
- if (this.$element[0] !== e.target && !this.$element.has(e.target).length) {
+ if (document !== e.target &&
+ this.$element[0] !== e.target &&
+ !this.$element.has(e.target).length) {
this.$element.trigger('focus')
}
}, this))
diff --git a/RIGS/static/js/popover.js b/RIGS/static/js/popover.js
old mode 100644
new mode 100755
index be65b11a..efe19567
--- a/RIGS/static/js/popover.js
+++ b/RIGS/static/js/popover.js
@@ -1,8 +1,8 @@
/* ========================================================================
- * Bootstrap: popover.js v3.3.2
+ * Bootstrap: popover.js v3.3.7
* http://getbootstrap.com/javascript/#popovers
* ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
+ * Copyright 2011-2016 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
@@ -19,7 +19,7 @@
if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')
- Popover.VERSION = '3.3.2'
+ Popover.VERSION = '3.3.7'
Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
placement: 'right',
@@ -75,11 +75,6 @@
return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
}
- Popover.prototype.tip = function () {
- if (!this.$tip) this.$tip = $(this.options.template)
- return this.$tip
- }
-
// POPOVER PLUGIN DEFINITION
// =========================
@@ -90,7 +85,7 @@
var data = $this.data('bs.popover')
var options = typeof option == 'object' && option
- if (!data && option == 'destroy') return
+ if (!data && /destroy|hide/.test(option)) return
if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
if (typeof option == 'string') data[option]()
})
diff --git a/RIGS/static/js/scrollspy.js b/RIGS/static/js/scrollspy.js
old mode 100644
new mode 100755
index 0987177f..fe198095
--- a/RIGS/static/js/scrollspy.js
+++ b/RIGS/static/js/scrollspy.js
@@ -1,8 +1,8 @@
/* ========================================================================
- * Bootstrap: scrollspy.js v3.3.2
+ * Bootstrap: scrollspy.js v3.3.7
* http://getbootstrap.com/javascript/#scrollspy
* ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
+ * Copyright 2011-2016 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
@@ -14,10 +14,8 @@
// ==========================
function ScrollSpy(element, options) {
- var process = $.proxy(this.process, this)
-
- this.$body = $('body')
- this.$scrollElement = $(element).is('body') ? $(window) : $(element)
+ this.$body = $(document.body)
+ this.$scrollElement = $(element).is(document.body) ? $(window) : $(element)
this.options = $.extend({}, ScrollSpy.DEFAULTS, options)
this.selector = (this.options.target || '') + ' .nav li > a'
this.offsets = []
@@ -25,12 +23,12 @@
this.activeTarget = null
this.scrollHeight = 0
- this.$scrollElement.on('scroll.bs.scrollspy', process)
+ this.$scrollElement.on('scroll.bs.scrollspy', $.proxy(this.process, this))
this.refresh()
this.process()
}
- ScrollSpy.VERSION = '3.3.2'
+ ScrollSpy.VERSION = '3.3.7'
ScrollSpy.DEFAULTS = {
offset: 10
@@ -41,20 +39,19 @@
}
ScrollSpy.prototype.refresh = function () {
- var offsetMethod = 'offset'
- var offsetBase = 0
+ var that = this
+ var offsetMethod = 'offset'
+ var offsetBase = 0
+
+ this.offsets = []
+ this.targets = []
+ this.scrollHeight = this.getScrollHeight()
if (!$.isWindow(this.$scrollElement[0])) {
offsetMethod = 'position'
offsetBase = this.$scrollElement.scrollTop()
}
- this.offsets = []
- this.targets = []
- this.scrollHeight = this.getScrollHeight()
-
- var self = this
-
this.$body
.find(this.selector)
.map(function () {
@@ -69,8 +66,8 @@
})
.sort(function (a, b) { return a[0] - b[0] })
.each(function () {
- self.offsets.push(this[0])
- self.targets.push(this[1])
+ that.offsets.push(this[0])
+ that.targets.push(this[1])
})
}
@@ -99,7 +96,7 @@
for (i = offsets.length; i--;) {
activeTarget != targets[i]
&& scrollTop >= offsets[i]
- && (!offsets[i + 1] || scrollTop <= offsets[i + 1])
+ && (offsets[i + 1] === undefined || scrollTop < offsets[i + 1])
&& this.activate(targets[i])
}
}
@@ -110,8 +107,8 @@
this.clear()
var selector = this.selector +
- '[data-target="' + target + '"],' +
- this.selector + '[href="' + target + '"]'
+ '[data-target="' + target + '"],' +
+ this.selector + '[href="' + target + '"]'
var active = $(selector)
.parents('li')
diff --git a/RIGS/static/js/tab.js b/RIGS/static/js/tab.js
old mode 100644
new mode 100755
index ddb7fc9c..c4a86354
--- a/RIGS/static/js/tab.js
+++ b/RIGS/static/js/tab.js
@@ -1,8 +1,8 @@
/* ========================================================================
- * Bootstrap: tab.js v3.3.2
+ * Bootstrap: tab.js v3.3.7
* http://getbootstrap.com/javascript/#tabs
* ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
+ * Copyright 2011-2016 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
@@ -14,10 +14,12 @@
// ====================
var Tab = function (element) {
+ // jscs:disable requireDollarBeforejQueryAssignment
this.element = $(element)
+ // jscs:enable requireDollarBeforejQueryAssignment
}
- Tab.VERSION = '3.3.2'
+ Tab.VERSION = '3.3.7'
Tab.TRANSITION_DURATION = 150
@@ -65,7 +67,7 @@
var $active = container.find('> .active')
var transition = callback
&& $.support.transition
- && (($active.length && $active.hasClass('fade')) || !!container.find('> .fade').length)
+ && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)
function next() {
$active
@@ -88,7 +90,7 @@
element.removeClass('fade')
}
- if (element.parent('.dropdown-menu')) {
+ if (element.parent('.dropdown-menu').length) {
element
.closest('li.dropdown')
.addClass('active')
diff --git a/RIGS/static/js/tooltip.js b/RIGS/static/js/tooltip.js
old mode 100644
new mode 100755
index 1856df59..e35d9c7c
--- a/RIGS/static/js/tooltip.js
+++ b/RIGS/static/js/tooltip.js
@@ -1,9 +1,9 @@
/* ========================================================================
- * Bootstrap: tooltip.js v3.3.2
+ * Bootstrap: tooltip.js v3.3.7
* http://getbootstrap.com/javascript/#tooltip
* Inspired by the original jQuery.tipsy by Jason Frame
* ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
+ * Copyright 2011-2016 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */
@@ -15,17 +15,18 @@
// ===============================
var Tooltip = function (element, options) {
- this.type =
- this.options =
- this.enabled =
- this.timeout =
- this.hoverState =
+ this.type = null
+ this.options = null
+ this.enabled = null
+ this.timeout = null
+ this.hoverState = null
this.$element = null
+ this.inState = null
this.init('tooltip', element, options)
}
- Tooltip.VERSION = '3.3.2'
+ Tooltip.VERSION = '3.3.7'
Tooltip.TRANSITION_DURATION = 150
@@ -50,7 +51,12 @@
this.type = type
this.$element = $(element)
this.options = this.getOptions(options)
- this.$viewport = this.options.viewport && $(this.options.viewport.selector || this.options.viewport)
+ this.$viewport = this.options.viewport && $($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
+ this.inState = { click: false, hover: false, focus: false }
+
+ if (this.$element[0] instanceof document.constructor && !this.options.selector) {
+ throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
+ }
var triggers = this.options.trigger.split(' ')
@@ -105,16 +111,20 @@
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget).data('bs.' + this.type)
- if (self && self.$tip && self.$tip.is(':visible')) {
- self.hoverState = 'in'
- return
- }
-
if (!self) {
self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
$(obj.currentTarget).data('bs.' + this.type, self)
}
+ if (obj instanceof $.Event) {
+ self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
+ }
+
+ if (self.tip().hasClass('in') || self.hoverState == 'in') {
+ self.hoverState = 'in'
+ return
+ }
+
clearTimeout(self.timeout)
self.hoverState = 'in'
@@ -126,6 +136,14 @@
}, self.options.delay.show)
}
+ Tooltip.prototype.isInStateTrue = function () {
+ for (var key in this.inState) {
+ if (this.inState[key]) return true
+ }
+
+ return false
+ }
+
Tooltip.prototype.leave = function (obj) {
var self = obj instanceof this.constructor ?
obj : $(obj.currentTarget).data('bs.' + this.type)
@@ -135,6 +153,12 @@
$(obj.currentTarget).data('bs.' + this.type, self)
}
+ if (obj instanceof $.Event) {
+ self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
+ }
+
+ if (self.isInStateTrue()) return
+
clearTimeout(self.timeout)
self.hoverState = 'out'
@@ -181,6 +205,7 @@
.data('bs.' + this.type, this)
this.options.container ? $tip.appendTo(this.options.container) : $tip.insertAfter(this.$element)
+ this.$element.trigger('inserted.bs.' + this.type)
var pos = this.getPosition()
var actualWidth = $tip[0].offsetWidth
@@ -188,13 +213,12 @@
if (autoPlace) {
var orgPlacement = placement
- var $container = this.options.container ? $(this.options.container) : this.$element.parent()
- var containerDim = this.getPosition($container)
+ var viewportDim = this.getPosition(this.$viewport)
- placement = placement == 'bottom' && pos.bottom + actualHeight > containerDim.bottom ? 'top' :
- placement == 'top' && pos.top - actualHeight < containerDim.top ? 'bottom' :
- placement == 'right' && pos.right + actualWidth > containerDim.width ? 'left' :
- placement == 'left' && pos.left - actualWidth < containerDim.left ? 'right' :
+ placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top' :
+ placement == 'top' && pos.top - actualHeight < viewportDim.top ? 'bottom' :
+ placement == 'right' && pos.right + actualWidth > viewportDim.width ? 'left' :
+ placement == 'left' && pos.left - actualWidth < viewportDim.left ? 'right' :
placement
$tip
@@ -235,8 +259,8 @@
if (isNaN(marginTop)) marginTop = 0
if (isNaN(marginLeft)) marginLeft = 0
- offset.top = offset.top + marginTop
- offset.left = offset.left + marginLeft
+ offset.top += marginTop
+ offset.left += marginLeft
// $.fn.offset doesn't round pixel values
// so we use setOffset directly with our own function B-0
@@ -272,10 +296,10 @@
this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
}
- Tooltip.prototype.replaceArrow = function (delta, dimension, isHorizontal) {
+ Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
this.arrow()
- .css(isHorizontal ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
- .css(isHorizontal ? 'top' : 'left', '')
+ .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
+ .css(isVertical ? 'top' : 'left', '')
}
Tooltip.prototype.setContent = function () {
@@ -288,14 +312,16 @@
Tooltip.prototype.hide = function (callback) {
var that = this
- var $tip = this.tip()
+ var $tip = $(this.$tip)
var e = $.Event('hide.bs.' + this.type)
function complete() {
if (that.hoverState != 'in') $tip.detach()
- that.$element
- .removeAttr('aria-describedby')
- .trigger('hidden.bs.' + that.type)
+ if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary.
+ that.$element
+ .removeAttr('aria-describedby')
+ .trigger('hidden.bs.' + that.type)
+ }
callback && callback()
}
@@ -305,7 +331,7 @@
$tip.removeClass('in')
- $.support.transition && this.$tip.hasClass('fade') ?
+ $.support.transition && $tip.hasClass('fade') ?
$tip
.one('bsTransitionEnd', complete)
.emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
@@ -318,7 +344,7 @@
Tooltip.prototype.fixTitle = function () {
var $e = this.$element
- if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
+ if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
$e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
}
}
@@ -338,7 +364,10 @@
// width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
}
- var elOffset = isBody ? { top: 0, left: 0 } : $element.offset()
+ var isSvg = window.SVGElement && el instanceof window.SVGElement
+ // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3.
+ // See https://github.com/twbs/bootstrap/issues/20280
+ var elOffset = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset())
var scroll = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null
@@ -373,7 +402,7 @@
var rightEdgeOffset = pos.left + viewportPadding + actualWidth
if (leftEdgeOffset < viewportDimensions.left) { // left overflow
delta.left = viewportDimensions.left - leftEdgeOffset
- } else if (rightEdgeOffset > viewportDimensions.width) { // right overflow
+ } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
}
}
@@ -399,7 +428,13 @@
}
Tooltip.prototype.tip = function () {
- return (this.$tip = this.$tip || $(this.options.template))
+ if (!this.$tip) {
+ this.$tip = $(this.options.template)
+ if (this.$tip.length != 1) {
+ throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
+ }
+ }
+ return this.$tip
}
Tooltip.prototype.arrow = function () {
@@ -428,7 +463,13 @@
}
}
- self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
+ if (e) {
+ self.inState.click = !self.inState.click
+ if (self.isInStateTrue()) self.enter(self)
+ else self.leave(self)
+ } else {
+ self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
+ }
}
Tooltip.prototype.destroy = function () {
@@ -436,6 +477,13 @@
clearTimeout(this.timeout)
this.hide(function () {
that.$element.off('.' + that.type).removeData('bs.' + that.type)
+ if (that.$tip) {
+ that.$tip.detach()
+ }
+ that.$tip = null
+ that.$arrow = null
+ that.$viewport = null
+ that.$element = null
})
}
@@ -449,7 +497,7 @@
var data = $this.data('bs.tooltip')
var options = typeof option == 'object' && option
- if (!data && option == 'destroy') return
+ if (!data && /destroy|hide/.test(option)) return
if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
if (typeof option == 'string') data[option]()
})
diff --git a/RIGS/static/js/transition.js b/RIGS/static/js/transition.js
old mode 100644
new mode 100755
index ec9ab682..db76596e
--- a/RIGS/static/js/transition.js
+++ b/RIGS/static/js/transition.js
@@ -1,8 +1,8 @@
/* ========================================================================
- * Bootstrap: transition.js v3.3.2
+ * Bootstrap: transition.js v3.3.7
* http://getbootstrap.com/javascript/#transitions
* ========================================================================
- * Copyright 2011-2015 Twitter, Inc.
+ * Copyright 2011-2016 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
* ======================================================================== */