-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix(dropdown): add dropdown fix for 0.97.7
- Loading branch information
Showing
3 changed files
with
265 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,257 @@ | ||
export function applyMaterializeDropdownFix() { | ||
$.fn.dropdown = function (options) { | ||
var defaults = { | ||
inDuration: 300, | ||
outDuration: 225, | ||
constrain_width: true, // Constrains width of dropdown to the activator | ||
hover: false, | ||
gutter: 0, // Spacing from edge | ||
belowOrigin: false, | ||
alignment: 'left', | ||
stopPropagation: false | ||
}; | ||
|
||
// Open dropdown. | ||
if (options === "open") { | ||
this.each(function() { | ||
$(this).trigger('open'); | ||
}); | ||
return false; | ||
} | ||
|
||
// Close dropdown. | ||
if (options === "close") { | ||
this.each(function() { | ||
$(this).trigger('close'); | ||
}); | ||
return false; | ||
} | ||
|
||
this.each(function(){ | ||
var origin = $(this); | ||
var curr_options = $.extend({}, defaults, options); | ||
var isFocused = false; | ||
|
||
// Dropdown menu | ||
var activates = $("#"+ origin.attr('data-activates')); | ||
|
||
function updateOptions() { | ||
if (origin.data('induration') !== undefined) | ||
curr_options.inDuration = origin.data('induration'); | ||
if (origin.data('outduration') !== undefined) | ||
curr_options.outDuration = origin.data('outduration'); | ||
if (origin.data('constrainwidth') !== undefined) | ||
curr_options.constrain_width = origin.data('constrainwidth'); | ||
if (origin.data('hover') !== undefined) | ||
curr_options.hover = origin.data('hover'); | ||
if (origin.data('gutter') !== undefined) | ||
curr_options.gutter = origin.data('gutter'); | ||
if (origin.data('beloworigin') !== undefined) | ||
curr_options.belowOrigin = origin.data('beloworigin'); | ||
if (origin.data('alignment') !== undefined) | ||
curr_options.alignment = origin.data('alignment'); | ||
if (origin.data('stoppropagation') !== undefined) | ||
curr_options.stopPropagation = origin.data('stoppropagation'); | ||
} | ||
|
||
updateOptions(); | ||
|
||
// Attach dropdown to its activator | ||
origin.after(activates); | ||
|
||
/* | ||
Helper function to position and resize dropdown. | ||
Used in hover and click handler. | ||
*/ | ||
function placeDropdown(eventType) { | ||
// Check for simultaneous focus and click events. | ||
if (eventType === 'focus') { | ||
isFocused = true; | ||
} | ||
|
||
// Check html data attributes | ||
updateOptions(); | ||
|
||
// Set Dropdown state | ||
activates.addClass('active'); | ||
origin.addClass('active'); | ||
|
||
// Constrain width | ||
if (curr_options.constrain_width === true) { | ||
activates.css('width', origin.outerWidth()); | ||
|
||
} else { | ||
activates.css('white-space', 'nowrap'); | ||
} | ||
|
||
// Offscreen detection | ||
var windowHeight = window.innerHeight; | ||
var originHeight = origin.innerHeight(); | ||
var offsetLeft = origin.offset().left; | ||
var offsetTop = origin.offset().top - $(window).scrollTop(); | ||
var currAlignment = curr_options.alignment; | ||
var gutterSpacing = 0; | ||
var leftPosition = 0; | ||
|
||
// Below Origin | ||
var verticalOffset = 0; | ||
if (curr_options.belowOrigin === true) { | ||
verticalOffset = originHeight; | ||
} | ||
|
||
// Check for scrolling positioned container. | ||
var scrollYOffset = 0; | ||
var scrollXOffset = 0; | ||
var wrapper = origin.parent(); | ||
if (!wrapper.is('body')) { | ||
if (wrapper[0].scrollHeight > wrapper[0].clientHeight) { | ||
scrollYOffset = wrapper[0].scrollTop; | ||
} | ||
if (wrapper[0].scrollWidth > wrapper[0].clientWidth) { | ||
scrollXOffset = wrapper[0].scrollLeft; | ||
} | ||
} | ||
|
||
|
||
if (offsetLeft + activates.innerWidth() > $(window).width()) { | ||
// Dropdown goes past screen on right, force right alignment | ||
currAlignment = 'right'; | ||
|
||
} else if (offsetLeft - activates.innerWidth() + origin.innerWidth() < 0) { | ||
// Dropdown goes past screen on left, force left alignment | ||
currAlignment = 'left'; | ||
} | ||
// Vertical bottom offscreen detection | ||
if (offsetTop + activates.innerHeight() > windowHeight) { | ||
// If going upwards still goes offscreen, just crop height of dropdown. | ||
if (offsetTop + originHeight - activates.innerHeight() < 0) { | ||
var adjustedHeight = windowHeight - offsetTop - verticalOffset; | ||
activates.css('max-height', adjustedHeight); | ||
} else { | ||
// Flow upwards. | ||
if (!verticalOffset) { | ||
verticalOffset += originHeight; | ||
} | ||
verticalOffset -= activates.innerHeight(); | ||
} | ||
} | ||
|
||
// Handle edge alignment | ||
if (currAlignment === 'left') { | ||
gutterSpacing = curr_options.gutter; | ||
leftPosition = origin.position().left + gutterSpacing; | ||
} | ||
else if (currAlignment === 'right') { | ||
var offsetRight = origin.position().left + origin.outerWidth() - activates.outerWidth(); | ||
gutterSpacing = -curr_options.gutter; | ||
leftPosition = offsetRight + gutterSpacing; | ||
} | ||
|
||
// Position dropdown | ||
activates.css({ | ||
position: 'absolute', | ||
top: origin.position().top + verticalOffset + scrollYOffset, | ||
left: leftPosition + scrollXOffset | ||
}); | ||
|
||
|
||
// Show dropdown | ||
activates.stop(true, true).css('opacity', 0) | ||
.slideDown({ | ||
queue: false, | ||
duration: curr_options.inDuration, | ||
easing: 'easeOutCubic', | ||
complete: function() { | ||
$(this).css('height', ''); | ||
} | ||
}) | ||
.animate( {opacity: 1}, {queue: false, duration: curr_options.inDuration, easing: 'easeOutSine'}); | ||
} | ||
|
||
function hideDropdown() { | ||
// Check for simultaneous focus and click events. | ||
isFocused = false; | ||
activates.fadeOut(curr_options.outDuration); | ||
activates.removeClass('active'); | ||
origin.removeClass('active'); | ||
setTimeout(function() { activates.css('max-height', ''); }, curr_options.outDuration); | ||
} | ||
|
||
// Hover | ||
if (curr_options.hover) { | ||
var open = false; | ||
origin.unbind('click.' + origin.attr('id')); | ||
// Hover handler to show dropdown | ||
origin.on('mouseenter', function(e){ // Mouse over | ||
if (open === false) { | ||
placeDropdown(); | ||
open = true; | ||
} | ||
}); | ||
origin.on('mouseleave', function(e){ | ||
// If hover on origin then to something other than dropdown content, then close | ||
var toEl = e.toElement || e.relatedTarget; // added browser compatibility for target element | ||
if(!$(toEl).closest('.dropdown-content').is(activates)) { | ||
activates.stop(true, true); | ||
hideDropdown(); | ||
open = false; | ||
} | ||
}); | ||
|
||
activates.on('mouseleave', function(e){ // Mouse out | ||
var toEl = e.toElement || e.relatedTarget; | ||
if(!$(toEl).closest('.dropdown-button').is(origin)) { | ||
activates.stop(true, true); | ||
hideDropdown(); | ||
open = false; | ||
} | ||
}); | ||
|
||
// Click | ||
} else { | ||
// Click handler to show dropdown | ||
origin.unbind('click.' + origin.attr('id')); | ||
origin.bind('click.'+origin.attr('id'), function(e){ | ||
if (!isFocused) { | ||
if ( origin[0] == e.currentTarget && | ||
!origin.hasClass('active') && | ||
($(e.target).closest('.dropdown-content').length === 0)) { | ||
e.preventDefault(); // Prevents button click from moving window | ||
if (curr_options.stopPropagation) { | ||
e.stopPropagation(); | ||
} | ||
placeDropdown('click'); | ||
} | ||
// If origin is clicked and menu is open, close menu | ||
else if (origin.hasClass('active')) { | ||
hideDropdown(); | ||
$(document).unbind('click.'+ activates.attr('id') + ' touchstart.' + activates.attr('id')); | ||
} | ||
// If menu open, add click close handler to document | ||
if (activates.hasClass('active')) { | ||
$(document).bind('click.'+ activates.attr('id') + ' touchstart.' + activates.attr('id'), function (e) { | ||
if (!activates.is(e.target) && !origin.is(e.target) && (!origin.find(e.target).length) ) { | ||
hideDropdown(); | ||
$(document).unbind('click.'+ activates.attr('id') + ' touchstart.' + activates.attr('id')); | ||
} | ||
}); | ||
} | ||
} | ||
}); | ||
|
||
} // End else | ||
|
||
// Listen to open and close event - useful for select component | ||
origin.on('open', function(e, eventType) { | ||
placeDropdown(eventType); | ||
}); | ||
origin.on('close', hideDropdown); | ||
|
||
|
||
}); | ||
}; // End dropdown plugin | ||
|
||
$(document).ready(function(){ | ||
$('.dropdown-button').dropdown(); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters