pretty-dropdowns
Advanced tools
Comparing version 4.1.0 to 4.2.0
/*! | ||
* jQuery Pretty Dropdowns Plugin v4.1.0 by T. H. Doan (http://thdoan.github.io/pretty-dropdowns/) | ||
* jQuery Pretty Dropdowns Plugin v4.1.1 by T. H. Doan (http://thdoan.github.io/pretty-dropdowns/) | ||
* | ||
@@ -24,5 +24,7 @@ * jQuery Pretty Dropdowns by T. H. Doan is licensed under the MIT License. | ||
], | ||
nCount, | ||
nHoverIndex, | ||
nLastIndex, | ||
nTimer, | ||
nTimestamp, | ||
handleKeypress = function(e) { | ||
@@ -44,3 +46,3 @@ var $dropdown = $('.prettydropdown > ul.active, .prettydropdown > ul:focus'); | ||
sKey; | ||
nHoverIndex = Math.max(0, $dropdown.children('li.hover').index()); | ||
nHoverIndex = Math.max(0, $dropdown.children('.hover').index()); | ||
nLastIndex = $items.length-1; | ||
@@ -138,2 +140,3 @@ $current = $items.eq(nHoverIndex); | ||
}, | ||
// Highlight menu item | ||
hoverDropdownItem = function(e) { | ||
@@ -145,2 +148,16 @@ var $dropdown = $(e.currentTarget); | ||
}, | ||
// Construct menu item | ||
renderItem = function(el, sClass, bSelected) { | ||
++nCount; | ||
return '<li id="item' + nTimestamp + '-' + nCount + '"' | ||
+ (el ? ' data-value="' + el.value + '"' : '') | ||
+ (el && el.title ? ' title="' + el.title + '"' : '') | ||
+ (el ? ' role="option"' : '') | ||
+ (sClass ? ' class="' + sClass + '"' : '') | ||
+ ((oOptions.height!==50) ? ' style="height:' + (oOptions.height-2) | ||
+ 'px;line-height:' + (oOptions.height-2) + 'px"' : '') + '>' | ||
+ (el ? el.text : '') | ||
+ (bSelected ? oOptions.selectedMarker : '') + '</li>'; | ||
}, | ||
// Reset menu state | ||
resetDropdown = function(o) { | ||
@@ -151,3 +168,3 @@ var $dropdown = $(o.currentTarget||o); | ||
// need to check for .active as a backup. | ||
if (!$dropdown.hasClass('active')) $dropdown = $('.prettydropdown > ul.active'); | ||
if (o.type==='mouseleave' && !$dropdown.hasClass('active')) $dropdown = $('.prettydropdown > ul.active'); | ||
$dropdown.data('hover', false); | ||
@@ -157,8 +174,8 @@ clearTimeout(nTimer); | ||
if ($dropdown.data('hover')) return; | ||
if ($dropdown.hasClass('reverse')) $dropdown.prepend($dropdown.children('li:last-child')); | ||
$dropdown.removeClass('active reverse').css('height', ''); | ||
if ($dropdown.hasClass('reverse')) $dropdown.prepend($dropdown.children(':last-child')); | ||
$dropdown.removeClass('active changing reverse').removeData('clicked').attr('aria-expanded', 'false').css('height', ''); | ||
$dropdown.children().removeClass('hover nohover'); | ||
$dropdown.removeData('clicked').attr('aria-expanded', 'false'); | ||
}, (o.type==='mouseleave' && !$dropdown.data('clicked')) ? oOptions.hoverIntent : 0); | ||
}, | ||
// Set menu item hover state | ||
toggleHover = function($li, bOn, bNoScroll) { | ||
@@ -184,3 +201,18 @@ if (bOn) { | ||
} | ||
}, | ||
// Update selected values for multi-select menu | ||
updateSelected = function($dropdown) { | ||
var $select = $dropdown.parent().children('select'), | ||
sSelected = $select.children().map(function() { | ||
if (this.selected) return this.text; | ||
}).get().join(oOptions.selectedDelimiter); | ||
if (sSelected) { | ||
$dropdown.children('.selected').text(sSelected); | ||
$dropdown.attr('title', ($select[0].title ? $select[0].title + '\n' : '') + 'Selected: ' + sSelected); | ||
} else { | ||
$dropdown.children('.selected').empty(); | ||
$dropdown.attr('title', $select[0].title); | ||
} | ||
}; | ||
oOptions.selectedMarker = ' <span aria-hidden="true">' + oOptions.selectedMarker + '</span>'; | ||
// Validate options | ||
@@ -191,6 +223,7 @@ if (isNaN(oOptions.height) || oOptions.height<8) oOptions.height = 8; | ||
var $select = $(this), | ||
nTimestamp = +new Date(), | ||
sId = this.name || this.id || '', | ||
sLabelId; | ||
if ($select.data('loaded')) return true; // Continue | ||
$select.css('visibility', 'hidden').outerHeight(oOptions.height); | ||
nTimestamp = +new Date(); | ||
// Test whether to add 'aria-labelledby' | ||
@@ -206,4 +239,4 @@ if (this.id) { | ||
} | ||
nCount = 0; | ||
var bMultiple = $select.prop('multiple'), | ||
nCount = 0, | ||
nWidth = $select.outerWidth(), | ||
@@ -215,3 +248,4 @@ // Height - 2px for borders | ||
+ ' style="max-height:' + (oOptions.height-2) + 'px;margin:' | ||
// NOTE: $select.css('margin') returns empty string in Firefox. See | ||
// NOTE: $select.css('margin') returns an empty string in Firefox, so | ||
// we have to get each margin individually. See | ||
// https://github.com/jquery/jquery/issues/3383 | ||
@@ -221,26 +255,24 @@ + $select.css('margin-top') + ' ' | ||
+ $select.css('margin-bottom') + ' ' | ||
+ $select.css('margin-left') + ';">', | ||
renderItem = function(el, sClass) { | ||
++nCount; | ||
return '<li id="item' + nTimestamp + '-' + nCount + '"' | ||
+ (el ? ' data-value="' + el.value + '"' : '') | ||
+ (el && el.title ? ' title="' + el.title + '"' : '') | ||
+ ' role="option"' | ||
+ (sClass ? ' class="' + sClass + '"' : '') | ||
+ ((oOptions.height!==50) ? ' style="height:' + (oOptions.height-2) | ||
+ 'px;line-height:' + (oOptions.height-2) + 'px"' : '') | ||
+ '>' + (el ? el.text : '') + '</li>'; | ||
}; | ||
+ $select.css('margin-left') + ';">'; | ||
if (bMultiple) { | ||
sHtml += renderItem(null, 'selected multiple'); | ||
sHtml += renderItem(null, 'selected'); | ||
$select.children().each(function() { | ||
if (this.selected) { | ||
sHtml += renderItem(this, '', true) | ||
} else { | ||
sHtml += renderItem(this); | ||
} | ||
}); | ||
} else { | ||
$select.children('option:selected').each(function() { | ||
$select.children(':selected').each(function() { | ||
sHtml += renderItem(this, 'selected'); | ||
}); | ||
$select.children(':not(:selected)').each(function() { | ||
sHtml += renderItem(this); | ||
}); | ||
} | ||
$select.children('option:not(:selected)').each(function() { | ||
sHtml += renderItem(this); | ||
}); | ||
sHtml += '</ul>'; | ||
$select.wrap('<div class="prettydropdown ' + oOptions.customClass + ' loading"></div>').before(sHtml).data('loaded', true); | ||
$select.wrap('<div ' + (sId ? 'id="prettydropdown-' + sId + '" ' : '') | ||
+ 'class="prettydropdown ' + (bMultiple ? 'multiple ' : '') | ||
+ oOptions.customClass + ' loading"></div>').before(sHtml).data('loaded', true); | ||
var $dropdown = $select.parent().children('ul'), | ||
@@ -250,2 +282,4 @@ $items = $dropdown.children(), | ||
nOuterWidth; | ||
// Update default selected values for multi-select menu | ||
if (bMultiple) updateSelected($dropdown); | ||
// Calculate width if initially hidden | ||
@@ -270,32 +304,25 @@ if ($dropdown.width()<=0) { | ||
// Only update if different value selected | ||
if ($dropdown.hasClass('active') && $(this).data('value')!==$dropdown.children('li.selected').data('value')) { | ||
if ($dropdown.hasClass('active') && $(this).data('value')!==$dropdown.children('.selected').data('value')) { | ||
// Select highlighted item | ||
if ($select.prop('multiple')) { | ||
if ($li.data('selected')) $li.children('span').remove(); | ||
else $li.append(' <span aria-hidden="true">' + oOptions.selectedMarker + '</span>'); | ||
$li.data('selected', !$li.data('selected')); | ||
// Update first item with comma-separated list of selected values | ||
var aSelected = []; | ||
$items.each(function(nIndex) { | ||
if (nIndex===0) return true; // Skip first item | ||
if ($(this).data('selected')) aSelected.push($select.children().eq(nIndex-1).text()); | ||
// Sync <select> element | ||
$select.children().eq(nIndex-1).prop('selected', $(this).data('selected')); | ||
if ($li.children('span').length) $li.children('span').remove(); | ||
else $li.append(oOptions.selectedMarker); | ||
// Sync <select> element | ||
$dropdown.children(':not(.selected)').each(function(nIndex) { | ||
$select.children().eq(nIndex).prop('selected', $(this).children('span').length>0); | ||
}); | ||
if (aSelected.length) { | ||
$items.eq(0).text(aSelected.join(oOptions.selectedDelimiter)); | ||
$dropdown.attr('title', ($select[0].title ? $select[0].title + '\n' : '') + 'Selected: ' + $items.eq(0).text()); | ||
} else { | ||
$items.eq(0).empty(); | ||
$dropdown.attr('title', $select[0].title); | ||
} | ||
// Update selected values for multi-select menu | ||
updateSelected($dropdown); | ||
} else { | ||
$dropdown.children('li.selected').removeClass('selected'); | ||
$dropdown.children('.selected').removeClass('selected'); | ||
$dropdown.prepend($li.addClass('selected')).removeClass('reverse').attr('aria-activedescendant', $li.attr('id')); | ||
// Sync <select> element | ||
$select.children('option[value="' + $li.data('value') +'"]').prop('selected', true); | ||
$select.children('[value="' + $li.data('value') +'"]').prop('selected', true); | ||
} | ||
$select.trigger('change'); | ||
} | ||
if ($li.index()===0 || !bMultiple || !$dropdown.hasClass('active')) $dropdown.toggleClass('active'); | ||
if ($li.hasClass('selected') || !bMultiple || !$dropdown.hasClass('active')) { | ||
$dropdown.toggleClass('active'); | ||
$dropdown.attr('aria-expanded', $dropdown.hasClass('active')); | ||
} | ||
// Try to keep drop-down menu within viewport | ||
@@ -317,3 +344,3 @@ if ($dropdown.hasClass('active')) { | ||
if (nOffsetTop-nScrollTop>nWinHeight-(nOffsetTop-nScrollTop+oOptions.height)) { | ||
$dropdown.addClass('reverse').append($dropdown.children('li.selected')); | ||
$dropdown.addClass('reverse').append($dropdown.children('.selected')); | ||
if (nOffsetTop-nScrollTop+oOptions.height<nDropdownHeight) { | ||
@@ -327,4 +354,4 @@ $dropdown.outerHeight(nOffsetTop-nScrollTop+oOptions.height); | ||
} | ||
$dropdown.attr('aria-expanded', 'true'); | ||
} else { | ||
if ($dropdown.hasClass('reverse')) $dropdown.addClass('changing'); // Prevent FOUC in reverse menu | ||
$dropdown.data('clicked', true); | ||
@@ -331,0 +358,0 @@ resetDropdown($dropdown[0]); |
{ | ||
"name": "pretty-dropdowns", | ||
"version": "4.1.0", | ||
"version": "4.2.0", | ||
"description": "A simple, lightweight jQuery plugin to create stylized drop-down menus.", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -11,3 +11,3 @@ # jQuery Pretty Dropdowns | ||
- Full keyboard navigation (you can even go directly to a menu item by typing its text) | ||
- Auto-link to `<label for>` using `aria-labelledby` (menu will focus when you click on the label) | ||
- Auto-linked to `<label for>` (menu will get focus when you click on the label) | ||
- Accessible (it plays nicely with screen readers) | ||
@@ -14,0 +14,0 @@ - Sensible (when you open the menu it does its best to keep the menu items within the viewport) |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
45207
7
868