|
|
@ -59,6 +59,7 @@ $.fn.popup = function(parameters) { |
|
|
|
|
|
|
|
searchDepth = 0, |
|
|
|
triedPositions = false, |
|
|
|
openedWithTouch = false, |
|
|
|
|
|
|
|
element = this, |
|
|
|
instance = $module.data(moduleNamespace), |
|
|
@ -166,10 +167,24 @@ $.fn.popup = function(parameters) { |
|
|
|
clearTimeout(module.showTimer); |
|
|
|
module.hideTimer = setTimeout(module.hide, delay); |
|
|
|
}, |
|
|
|
touchstart: function(event) { |
|
|
|
openedWithTouch = true; |
|
|
|
module.event.start(); |
|
|
|
}, |
|
|
|
resize: function() { |
|
|
|
if( module.is.visible() ) { |
|
|
|
module.set.position(); |
|
|
|
} |
|
|
|
}, |
|
|
|
hideGracefully: function(event) { |
|
|
|
// don't close on clicks inside popup
|
|
|
|
if(event && $(event.target).closest(selector.popup).length === 0) { |
|
|
|
module.debug('Click occurred outside popup hiding popup'); |
|
|
|
module.hide(); |
|
|
|
} |
|
|
|
else { |
|
|
|
module.debug('Click was inside popup, keeping popup open'); |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
@ -312,18 +327,6 @@ $.fn.popup = function(parameters) { |
|
|
|
}) |
|
|
|
; |
|
|
|
}, |
|
|
|
|
|
|
|
hideGracefully: function(event) { |
|
|
|
// don't close on clicks inside popup
|
|
|
|
if(event && $(event.target).closest(selector.popup).length === 0) { |
|
|
|
module.debug('Click occurred outside popup hiding popup'); |
|
|
|
module.hide(); |
|
|
|
} |
|
|
|
else { |
|
|
|
module.debug('Click was inside popup, keeping popup open'); |
|
|
|
} |
|
|
|
}, |
|
|
|
|
|
|
|
exists: function() { |
|
|
|
if(!$popup) { |
|
|
|
return false; |
|
|
@ -438,15 +441,51 @@ $.fn.popup = function(parameters) { |
|
|
|
$module.removeData(metadata.variation); |
|
|
|
return $module.data(metadata.variation) || settings.variation; |
|
|
|
}, |
|
|
|
sizes: function() { |
|
|
|
var |
|
|
|
targetElement = $target[0], |
|
|
|
sizes = {} |
|
|
|
; |
|
|
|
// grab position
|
|
|
|
sizes.target = (settings.inline || settings.popup) |
|
|
|
? $target.position() |
|
|
|
: $target.offset() |
|
|
|
; |
|
|
|
sizes = { |
|
|
|
target: { |
|
|
|
element : $target[0], |
|
|
|
width : $target.outerWidth(), |
|
|
|
height : $target.outerHeight(), |
|
|
|
margin : {} |
|
|
|
}, |
|
|
|
popup: { |
|
|
|
width: $popup.outerWidth(), |
|
|
|
height: $popup.outerHeight() |
|
|
|
}, |
|
|
|
parent: { |
|
|
|
width: $offsetParent.outerWidth(), |
|
|
|
height: $offsetParent.outerHeight() |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
sizes.target.margin.top = (settings.inline) |
|
|
|
? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-top'), 10) |
|
|
|
: 0 |
|
|
|
; |
|
|
|
sizes.target.margin.left = (settings.inline) |
|
|
|
? module.is.rtl() |
|
|
|
? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-right'), 10) |
|
|
|
: parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-left') , 10) |
|
|
|
: 0 |
|
|
|
; |
|
|
|
return sizes; |
|
|
|
}, |
|
|
|
id: function() { |
|
|
|
return id; |
|
|
|
}, |
|
|
|
startEvent: function() { |
|
|
|
if(settings.on == 'hover') { |
|
|
|
return (hasTouch && settings.addTouchEvents) |
|
|
|
? 'touchstart mouseenter' |
|
|
|
: 'mouseenter' |
|
|
|
; |
|
|
|
return 'mouseenter'; |
|
|
|
} |
|
|
|
else if(settings.on == 'focus') { |
|
|
|
return 'focus'; |
|
|
@ -454,10 +493,7 @@ $.fn.popup = function(parameters) { |
|
|
|
return false; |
|
|
|
}, |
|
|
|
scrollEvent: function() { |
|
|
|
return (hasTouch && settings.addTouchEvents) |
|
|
|
? 'touchmove scroll' |
|
|
|
: 'scroll' |
|
|
|
; |
|
|
|
return 'scroll'; |
|
|
|
}, |
|
|
|
endEvent: function() { |
|
|
|
if(settings.on == 'hover') { |
|
|
@ -510,8 +546,8 @@ $.fn.popup = function(parameters) { |
|
|
|
right : screen.left + screen.width |
|
|
|
}, |
|
|
|
popup = { |
|
|
|
width : $popup.width(), |
|
|
|
height : $popup.height(), |
|
|
|
width : $popup.outerWidth(), |
|
|
|
height : $popup.outerHeight(), |
|
|
|
offset : $popup.offset() |
|
|
|
}, |
|
|
|
offstage = {}, |
|
|
@ -610,7 +646,7 @@ $.fn.popup = function(parameters) { |
|
|
|
}, |
|
|
|
|
|
|
|
set: { |
|
|
|
position: function(position, arrowOffset) { |
|
|
|
position: function(position, sizes) { |
|
|
|
|
|
|
|
// exit conditions
|
|
|
|
if($target.length === 0 || $popup.length === 0) { |
|
|
@ -618,140 +654,125 @@ $.fn.popup = function(parameters) { |
|
|
|
return; |
|
|
|
} |
|
|
|
var |
|
|
|
windowWidth = $(window).width(), |
|
|
|
windowHeight = $(window).height(), |
|
|
|
|
|
|
|
targetWidth = $target.outerWidth(), |
|
|
|
targetHeight = $target.outerHeight(), |
|
|
|
|
|
|
|
popupWidth = $popup.outerWidth(), |
|
|
|
popupHeight = $popup.outerHeight(), |
|
|
|
|
|
|
|
parentWidth = $offsetParent.outerWidth(), |
|
|
|
parentHeight = $offsetParent.outerHeight(), |
|
|
|
|
|
|
|
distanceAway = settings.distanceAway, |
|
|
|
|
|
|
|
targetElement = $target[0], |
|
|
|
|
|
|
|
marginTop = (settings.inline) |
|
|
|
? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-top'), 10) |
|
|
|
: 0, |
|
|
|
marginLeft = (settings.inline) |
|
|
|
? module.is.rtl() |
|
|
|
? parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-right'), 10) |
|
|
|
: parseInt( window.getComputedStyle(targetElement).getPropertyValue('margin-left') , 10) |
|
|
|
: 0, |
|
|
|
|
|
|
|
target = (settings.inline || settings.popup) |
|
|
|
? $target.position() |
|
|
|
: $target.offset(), |
|
|
|
|
|
|
|
offset, |
|
|
|
distanceAway, |
|
|
|
target, |
|
|
|
popup, |
|
|
|
parent, |
|
|
|
computedPosition, |
|
|
|
positioning, |
|
|
|
offstagePosition |
|
|
|
; |
|
|
|
position = position || $module.data(metadata.position) || settings.position; |
|
|
|
arrowOffset = arrowOffset || $module.data(metadata.offset) || settings.offset; |
|
|
|
sizes = sizes || module.get.sizes(); |
|
|
|
position = position || $module.data(metadata.position) || settings.position; |
|
|
|
|
|
|
|
offset = $module.data(metadata.offset) || settings.offset; |
|
|
|
distanceAway = settings.distanceAway; |
|
|
|
|
|
|
|
// shorthand
|
|
|
|
target = sizes.target; |
|
|
|
popup = sizes.popup; |
|
|
|
parent = sizes.parent; |
|
|
|
|
|
|
|
if(target.top === 0 && target.left === 0) { |
|
|
|
module.debug('Popup target is hidden, no action taken'); |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
if(searchDepth == settings.maxSearchDepth && settings.lastResort) { |
|
|
|
module.debug('Using last resort position to display', settings.lastResort); |
|
|
|
position = settings.lastResort; |
|
|
|
} |
|
|
|
|
|
|
|
if(settings.inline) { |
|
|
|
module.debug('Adding targets margin to calculation'); |
|
|
|
if(position == 'left center' || position == 'right center') { |
|
|
|
arrowOffset += marginTop; |
|
|
|
distanceAway += -marginLeft; |
|
|
|
offset += target.margin.top; |
|
|
|
distanceAway += -target.margin.left; |
|
|
|
} |
|
|
|
else if (position == 'top left' || position == 'top center' || position == 'top right') { |
|
|
|
arrowOffset += marginLeft; |
|
|
|
distanceAway -= marginTop; |
|
|
|
offset += target.margin.left; |
|
|
|
distanceAway -= target.margin.top; |
|
|
|
} |
|
|
|
else { |
|
|
|
arrowOffset += marginLeft; |
|
|
|
distanceAway += marginTop; |
|
|
|
offset += target.margin.left; |
|
|
|
distanceAway += target.margin.top; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
module.debug('Calculating popup positioning', position); |
|
|
|
|
|
|
|
computedPosition = position; |
|
|
|
if (module.is.rtl()) { |
|
|
|
computedPosition = computedPosition.replace(/left|right/g, function (match) { |
|
|
|
position = position.replace(/left|right/g, function (match) { |
|
|
|
return (match == 'left') |
|
|
|
? 'right' |
|
|
|
: 'left' |
|
|
|
; |
|
|
|
}); |
|
|
|
module.debug('RTL: Popup positioning updated', computedPosition); |
|
|
|
module.debug('RTL: Popup positioning updated', position); |
|
|
|
} |
|
|
|
|
|
|
|
if(searchDepth == settings.maxSearchDepth && settings.lastResort) { |
|
|
|
module.debug('Using last resort position to display', settings.lastResort); |
|
|
|
position = settings.lastResort; |
|
|
|
} |
|
|
|
switch (computedPosition) { |
|
|
|
|
|
|
|
switch (position) { |
|
|
|
case 'top left': |
|
|
|
positioning = { |
|
|
|
top : 'auto', |
|
|
|
bottom : parentHeight - target.top + distanceAway, |
|
|
|
left : target.left + arrowOffset, |
|
|
|
bottom : parent.height - target.top + distanceAway, |
|
|
|
left : target.left + offset, |
|
|
|
right : 'auto' |
|
|
|
}; |
|
|
|
break; |
|
|
|
case 'top center': |
|
|
|
positioning = { |
|
|
|
bottom : parentHeight - target.top + distanceAway, |
|
|
|
left : target.left + (targetWidth / 2) - (popupWidth / 2) + arrowOffset, |
|
|
|
bottom : parent.height - target.top + distanceAway, |
|
|
|
left : target.left + (target.width / 2) - (popup.width / 2) + offset, |
|
|
|
top : 'auto', |
|
|
|
right : 'auto' |
|
|
|
}; |
|
|
|
break; |
|
|
|
case 'top right': |
|
|
|
positioning = { |
|
|
|
bottom : parentHeight - target.top + distanceAway, |
|
|
|
right : parentWidth - target.left - targetWidth - arrowOffset, |
|
|
|
bottom : parent.height - target.top + distanceAway, |
|
|
|
right : parent.width - target.left - target.width - offset, |
|
|
|
top : 'auto', |
|
|
|
left : 'auto' |
|
|
|
}; |
|
|
|
break; |
|
|
|
case 'left center': |
|
|
|
positioning = { |
|
|
|
top : target.top + (targetHeight / 2) - (popupHeight / 2) + arrowOffset, |
|
|
|
right : parentWidth - target.left + distanceAway, |
|
|
|
top : target.top + (target.height / 2) - (popup.height / 2) + offset, |
|
|
|
right : parent.width - target.left + distanceAway, |
|
|
|
left : 'auto', |
|
|
|
bottom : 'auto' |
|
|
|
}; |
|
|
|
break; |
|
|
|
case 'right center': |
|
|
|
positioning = { |
|
|
|
top : target.top + (targetHeight / 2) - (popupHeight / 2) + arrowOffset, |
|
|
|
left : target.left + targetWidth + distanceAway, |
|
|
|
top : target.top + (target.height / 2) - (popup.height / 2) + offset, |
|
|
|
left : target.left + target.width + distanceAway, |
|
|
|
bottom : 'auto', |
|
|
|
right : 'auto' |
|
|
|
}; |
|
|
|
break; |
|
|
|
case 'bottom left': |
|
|
|
positioning = { |
|
|
|
top : target.top + targetHeight + distanceAway, |
|
|
|
left : target.left + arrowOffset, |
|
|
|
top : target.top + target.height + distanceAway, |
|
|
|
left : target.left + offset, |
|
|
|
bottom : 'auto', |
|
|
|
right : 'auto' |
|
|
|
}; |
|
|
|
break; |
|
|
|
case 'bottom center': |
|
|
|
positioning = { |
|
|
|
top : target.top + targetHeight + distanceAway, |
|
|
|
left : target.left + (targetWidth / 2) - (popupWidth / 2) + arrowOffset, |
|
|
|
top : target.top + target.height + distanceAway, |
|
|
|
left : target.left + (target.width / 2) - (popup.width / 2) + offset, |
|
|
|
bottom : 'auto', |
|
|
|
right : 'auto' |
|
|
|
}; |
|
|
|
break; |
|
|
|
case 'bottom right': |
|
|
|
positioning = { |
|
|
|
top : target.top + targetHeight + distanceAway, |
|
|
|
right : parentWidth - target.left - targetWidth - arrowOffset, |
|
|
|
top : target.top + target.height + distanceAway, |
|
|
|
right : parent.width - target.left - target.width - offset, |
|
|
|
left : 'auto', |
|
|
|
bottom : 'auto' |
|
|
|
}; |
|
|
@ -781,7 +802,7 @@ $.fn.popup = function(parameters) { |
|
|
|
position = module.get.nextPosition(position); |
|
|
|
module.debug('Trying new position', position); |
|
|
|
return ($popup) |
|
|
|
? module.set.position(position) |
|
|
|
? module.set.position(position, sizes) |
|
|
|
: false |
|
|
|
; |
|
|
|
} |
|
|
@ -835,6 +856,11 @@ $.fn.popup = function(parameters) { |
|
|
|
.on('click' + eventNamespace, module.toggle) |
|
|
|
; |
|
|
|
} |
|
|
|
if(settings.on == 'hover' && hasTouch) { |
|
|
|
$module |
|
|
|
.on('touchstart' + eventNamespace, module.event.touchstart) |
|
|
|
; |
|
|
|
} |
|
|
|
else if( module.get.startEvent() ) { |
|
|
|
$module |
|
|
|
.on(module.get.startEvent() + eventNamespace, module.event.start) |
|
|
@ -855,21 +881,30 @@ $.fn.popup = function(parameters) { |
|
|
|
; |
|
|
|
} |
|
|
|
}, |
|
|
|
close:function() { |
|
|
|
if(settings.hideOnScroll === true || settings.hideOnScroll == 'auto' && settings.on != 'click') { |
|
|
|
close: function() { |
|
|
|
if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) { |
|
|
|
$document |
|
|
|
.one(module.get.scrollEvent() + elementNamespace, module.hideGracefully) |
|
|
|
.one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully) |
|
|
|
; |
|
|
|
$context |
|
|
|
.one(module.get.scrollEvent() + elementNamespace, module.hideGracefully) |
|
|
|
.one(module.get.scrollEvent() + elementNamespace, module.event.hideGracefully) |
|
|
|
; |
|
|
|
} |
|
|
|
if(settings.on == 'hover' && openedWithTouch) { |
|
|
|
module.verbose('Binding popup close event to document'); |
|
|
|
$document |
|
|
|
.on('touchstart' + elementNamespace, function(event) { |
|
|
|
module.verbose('Touched away from popup'); |
|
|
|
module.event.hideGracefully.call(element, event); |
|
|
|
}) |
|
|
|
; |
|
|
|
} |
|
|
|
if(settings.on == 'click' && settings.closable) { |
|
|
|
module.verbose('Binding popup close event to document'); |
|
|
|
$document |
|
|
|
.on('click' + elementNamespace, function(event) { |
|
|
|
module.verbose('Pop-up clickaway intent detected'); |
|
|
|
module.hideGracefully.call(element, event); |
|
|
|
module.verbose('Clicked away from popup'); |
|
|
|
module.event.hideGracefully.call(element, event); |
|
|
|
}) |
|
|
|
; |
|
|
|
} |
|
|
@ -878,7 +913,7 @@ $.fn.popup = function(parameters) { |
|
|
|
|
|
|
|
unbind: { |
|
|
|
close: function() { |
|
|
|
if(settings.hideOnScroll === true || settings.hideOnScroll == 'auto' && settings.on != 'click') { |
|
|
|
if(settings.hideOnScroll === true || (settings.hideOnScroll == 'auto' && settings.on != 'click')) { |
|
|
|
$document |
|
|
|
.off('scroll' + elementNamespace, module.hide) |
|
|
|
; |
|
|
@ -886,6 +921,12 @@ $.fn.popup = function(parameters) { |
|
|
|
.off('scroll' + elementNamespace, module.hide) |
|
|
|
; |
|
|
|
} |
|
|
|
if(settings.on == 'hover' && openedWithTouch) { |
|
|
|
$document |
|
|
|
.off('touchstart' + elementNamespace) |
|
|
|
; |
|
|
|
openedWithTouch = false; |
|
|
|
} |
|
|
|
if(settings.on == 'click' && settings.closable) { |
|
|
|
module.verbose('Removing close event from document'); |
|
|
|
$document |
|
|
|