可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have a hidden DIV which contains a toolbar-like menu.
I have a number of DIVs which are enabled to show the menu DIV when the mouse hovers over them.
Is there a built-in function which will move the menu DIV to the top right of the active (mouse hover) DIV? I\'m looking for something like $(menu).position(\"topright\", targetEl);
回答1:
You can now use:
$(\"#my_div\").position({
my: \"left top\",
at: \"left bottom\",
of: this, // or $(\"#otherdiv\")
collision: \"fit\"
});
For fast positioning (jQuery UI/Position).
NOTE: This requires jQuery UI (not just jQuery).
You can download jQuery UI here.
回答2:
tl;dr: (try it here)
If you have the following HTML:
<div id=\"menu\" style=\"display: none;\">
<!-- menu stuff in here -->
<ul><li>Menu item</li></ul>
</div>
<div class=\"parent\">Hover over me to show the menu here</div>
then you can use the following JavaScript code:
$(\".parent\").mouseover(function() {
// .position() uses position relative to the offset parent,
var pos = $(this).position();
// .outerWidth() takes into account border and padding.
var width = $(this).outerWidth();
//show the menu directly over the placeholder
$(\"#menu\").css({
position: \"absolute\",
top: pos.top + \"px\",
left: (pos.left + width) + \"px\"
}).show();
});
But it doesn\'t work!
This will work as long as the menu and the placeholder have the same offset parent. If they don\'t, and you don\'t have nested CSS rules that care where in the DOM the #menu
element is, use:
$(this).append($(\"#menu\"));
just before the line that positions the #menu
element.
But it still doesn\'t work!
You might have some weird layout that doesn\'t work with this approach. In that case, just use jQuery.ui\'s position plugin (as mentioned in an answer below), which handles every conceivable eventuality. Note that you\'ll have to show()
the menu element before calling position({...})
; the plugin can\'t position hidden elements.
Update notes 3 years later in 2012:
(The original solution is archived here for posterity)
So, it turns out that the original method I had here was far from ideal. In particular, it would fail if:
- the menu\'s offset parent is not the placeholder\'s offset parent
- the placeholder has a border/padding
Luckily, jQuery introduced methods (position()
and outerWidth()
) way back in 1.2.6 that make finding the right values in the latter case here a lot easier. For the former case, append
ing the menu element to the placeholder works (but will break CSS rules based on nesting).
回答3:
This is what worked for me in the end.
var showMenu = function(el, menu) {
//get the position of the placeholder element
var pos = $(el).offset();
var eWidth = $(el).outerWidth();
var mWidth = $(menu).outerWidth();
var left = (pos.left + eWidth - mWidth) + \"px\";
var top = 3+pos.top + \"px\";
//show the menu directly over the placeholder
$(menu).css( {
position: \'absolute\',
zIndex: 5000,
left: left,
top: top
} );
$(menu).hide().fadeIn();
};
回答4:
Here is a jQuery function I wrote that helps me position elements.
Here is an example usage:
$(document).ready(function() {
$(\'#el1\').position(\'#el2\', {
anchor: [\'br\', \'tr\'],
offset: [-5, 5]
});
});
The code above aligns the bottom-right of #el1 with the top-right of #el2. [\'cc\', \'cc\'] would center #el1 in #el2. Make sure that #el1 has the css of position: absolute and z-index: 10000 (or some really large number) to keep it on top.
The offset option allows you to nudge the coordinates by a specified number of pixels.
The source code is below:
jQuery.fn.getBox = function() {
return {
left: $(this).offset().left,
top: $(this).offset().top,
width: $(this).outerWidth(),
height: $(this).outerHeight()
};
}
jQuery.fn.position = function(target, options) {
var anchorOffsets = {t: 0, l: 0, c: 0.5, b: 1, r: 1};
var defaults = {
anchor: [\'tl\', \'tl\'],
animate: false,
offset: [0, 0]
};
options = $.extend(defaults, options);
var targetBox = $(target).getBox();
var sourceBox = $(this).getBox();
//origin is at the top-left of the target element
var left = targetBox.left;
var top = targetBox.top;
//alignment with respect to source
top -= anchorOffsets[options.anchor[0].charAt(0)] * sourceBox.height;
left -= anchorOffsets[options.anchor[0].charAt(1)] * sourceBox.width;
//alignment with respect to target
top += anchorOffsets[options.anchor[1].charAt(0)] * targetBox.height;
left += anchorOffsets[options.anchor[1].charAt(1)] * targetBox.width;
//add offset to final coordinates
left += options.offset[0];
top += options.offset[1];
$(this).css({
left: left + \'px\',
top: top + \'px\'
});
}
回答5:
Why complicating too much? Solution is very simple
css:
.active-div{
position:relative;
}
.menu-div{
position:absolute;
top:0;
right:0;
display:none;
}
jquery:
$(function(){
$(\".active-div\").hover(function(){
$(\".menu-div\").prependTo(\".active-div\").show();
},function(){$(\".menu-div\").hide();
})
It works even if,
- Two divs placed anywhere else
- Browser Re-sized
回答6:
You can use the jQuery plugin PositionCalculator
That plugin has also included collision handling (flip), so the toolbar-like menu can be placed at a visible position.
$(\".placeholder\").on(\'mouseover\', function() {
var $menu = $(\"#menu\").show();// result for hidden element would be incorrect
var pos = $.PositionCalculator( {
target: this,
targetAt: \"top right\",
item: $menu,
itemAt: \"top left\",
flip: \"both\"
}).calculate();
$menu.css({
top: parseInt($menu.css(\'top\')) + pos.moveBy.y + \"px\",
left: parseInt($menu.css(\'left\')) + pos.moveBy.x + \"px\"
});
});
for that markup:
<ul class=\"popup\" id=\"menu\">
<li>Menu item</li>
<li>Menu item</li>
<li>Menu item</li>
</ul>
<div class=\"placeholder\">placeholder 1</div>
<div class=\"placeholder\">placeholder 2</div>
Here is the fiddle: http://jsfiddle.net/QrrpB/1657/
回答7:
Something like this?
$(menu).css(\"top\", targetE1.y + \"px\");
$(menu).css(\"left\", targetE1.x - widthOfMenu + \"px\");
回答8:
This works for me:
var posPersonTooltip = function(event) {
var tPosX = event.pageX - 5;
var tPosY = event.pageY + 10;
$(\'#personTooltipContainer\').css({top: tPosY, left: tPosX});