Skip to content

Commit

Permalink
fix(dropdown): add dropdown fix for 0.97.7
Browse files Browse the repository at this point in the history
  • Loading branch information
Thanood committed Sep 15, 2016
1 parent 2ee24af commit d3eb997
Show file tree
Hide file tree
Showing 3 changed files with 265 additions and 0 deletions.
7 changes: 7 additions & 0 deletions src/config-builder.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import {applyMaterializeDropdownFix} from './dropdown/dropdown-fix';

/**
* Plugin configuration builder
*/
Expand Down Expand Up @@ -138,6 +140,11 @@ export class ConfigBuilder {
return this;
}

useDropdownFix() : ConfigBuilder {
applyMaterializeDropdownFix();
return this;
}

useFab() : ConfigBuilder {
this.globalResources.push('./fab/fab');
return this;
Expand Down
257 changes: 257 additions & 0 deletions src/dropdown/dropdown-fix.js
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();
});
}
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ export * from './datepicker/datepicker.default-parser';
export * from './datepicker/datepicker';
export * from './dropdown/dropdown-element';
export * from './dropdown/dropdown';
export * from './dropdown/dropdown-fix';
export * from './fab/fab';
export * from './file/file';
export * from './footer/footer';
Expand Down

0 comments on commit d3eb997

Please sign in to comment.