This is an example code to show the popover window display below my button:
$.fn.popover.defaults = $.extend({} , $.fn.tooltip.defaults, {
placement: 'bottom', content: ''
Now I want the popover window appear on the place where my cursor moves on(not only top/bottom/left/right, but a specific location which depends on where user put their cursor on).
How to get it?
In bootstrap-tooltip.js, replace (at about line 72)
, enter: function (e) {
with
, enter: function (e) {
var mousePos = { x: -1, y: -1 };
mousePos.x = e.pageX;
mousePos.y = e.pageY;
window.mousePos = mousePos;
and replace (at about line 144)
case 'right':
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
break
with
case 'right':
tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}
break
case 'mouse':
tp = {top: window.mousePos.y, left: window.mousePos.x}
break
Then call your popover like this:
$('.pop').popover({'placement': 'mouse'});
This is a quick-n-dirty way to go about it (hacking core files), but it works. Perhaps someone else has a nicer method. Note that the popover pointer will need some work as it doesn't appear.
This example was tested in Bootstrap 2.0.3, but the code appears similar in 2.2.2.
For bootstrap 3.x.x
Add attribute atMouse:false to the inline class Tooltip.DEFAULTS{}.
Tooltip.DEFAULTS = {
animation: true,
placement: 'top',
selector: false,
template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
trigger: 'hover focus',
title: '',
delay: 0,
html: false,
container: false,
atMouse: false,
viewport: {
selector: 'body',
padding: 0
}
}
Go to the line 1368 inside of method "Tooltip.prototype.enter" and change the following code:
if (obj instanceof $.Event) {
self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
}
to:
if (obj instanceof $.Event) {
self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
self.options.mousePos = {posX: obj['pageX'], posY: obj['pageY']}
}
Inside of the method "Tooltip.prototype.show" add following code:
if(this.options.atMouse) {
pos['posY'] = this.options.mousePos['posY'];
pos['posX'] = this.options.mousePos['posX'];
}
before this line of code:
var calculatedOffset = this.getCalculatedOffset(placement, pos,
actualWidth, actualHeight)
Prepend to the body of Tooltip.prototype.getCalculatedOffset method following code:
if(this.options.atMouse) {
return placement == 'bottom' ? {top: pos.top + pos.height, left: pos.posX - (actualWidth / 2)} :
placement == 'top' ? {top: pos.top - actualHeight, left: pos.posX - (actualWidth / 2)} :
placement == 'left' ? {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.posX - actualWidth} :
{top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.posX}
}
Call tooltip/popover something like this:
$("[data-toggle='popover']").popover({
html: true,
container: 'body',
atMouse: true,
trigger: 'hover',
animation: false,
placement: "top auto"
});
Work for me.
Related
This is my first question, so please give me any pointers on how I could ask better ones.
Anyway, how would I make a togglable menu that displays links, that activates using a bookmarklet. I have tried to find answers, but all were fruitless. Would I need to create a new element for this?
You will need to create the pop-up menu using vanilla JS. I also implemented drag functionality. The only thing this needs is to correctly set the position when a page is scrolled.
DOM layout
The most important elements and styles below are required.
<div style="position:absolute; z-index:2147483647">
<div style="position: relative">
<div style="position:relative; display:inline-block; left:0">Bookmarklet Links</div>
<div style="position:relative; float:right">×</div>
</div>
<div>
<p>Click the links to open a new tab!</p>
<ul>
<li>
Google
</li>
<li>
Bing
</li>
<li>
DuckDuckGO
</li>
</ul>
</div>
</div>
You can save the following bookmarklet:
javascript:!function(){var c=0x1f4,d=0x12c,e='#AAA',f=0x1,g=0x20,h='#444',i='#FFF',j='Bookmarklet\x20Links',k=~~(document['documentElement']['clientWidth']/0x2-c/0x2),l=~~(document['documentElement']['clientHeight']/0x2-d/0x2),m=~~(0.8*g),n=document['createElement']('DIV');Object['assign'](n['style'],{'position':'absolute','left':k+'px','top':l+'px','zIndex':Number['MAX_SAFE_INTEGER'],'width':c+'px','height':d+'px','background':e,'border':f+'px\x20solid\x20black'});var o=document['createElement']('DIV');Object['assign'](o['style'],{'position':'relative','width':c+'px','height':g+'px','background':h,'borderBottom':f+'px\x20solid\x20black'});var p=document['createElement']('DIV');Object['assign'](p['style'],{'position':'relative','display':'inline-block','left':0x0,'width':~~(c-0x2*m)+'px','lineHeight':g+'px','color':i,'fontSize':~~(0.667*g)+'px','marginLeft':~~(m/0x3)+'px'}),p['textContent']=j;var q=document['createElement']('DIV'),r=~~((g-m)/0x2);Object['assign'](q['style'],{'position':'relative','float':'right','right':r+'px','top':r+'px','width':m+'px','height':m+'px','background':'#F00','border':f+'px\x20solid\x20black','color':'#FFF','lineHeight':m+'px','textAlign':'center','fontSize':m+'px','marginLeft':'auto','marginRight':0x0});var s=document['createElement']('DIV');Object['assign'](s['style'],{'padding':'1em'});var t=document['createElement']('P');t['textContent']='Click\x20the\x20links\x20to\x20open\x20a\x20new\x20tab!',s['appendChild'](t);var u=document['createElement']('UL');[{'name':'Google','url':'https://www.google.com'},{'name':'Bing','url':'https://www.bing.com'},{'name':'DuckDuckGO','url':'https://duckduckgo.com'}]['forEach'](c=>{var d=document['createElement']('LI'),e=document['createElement']('A');e['setAttribute']('href',c['url']),e['setAttribute']('target','_blank'),e['textContent']=c['name'],d['appendChild'](e),u['appendChild'](d);}),s['appendChild'](u),q['addEventListener']('click',function c(d){q['removeEventListener']('click',c,!0x1);o['removeChild'](q);n['removeChild'](o);n['removeChild'](s);document['body']['removeChild'](n);},!0x1),q['textContent']='×',o['appendChild'](p),o['appendChild'](q),n['appendChild'](o),n['appendChild'](s),document['body']['appendChild'](n),function(c){var d=function(c){var d=c['getBoundingClientRect'](),e=window['pageXOffset']||document['documentElement']['scrollLeft'],f=window['pageYOffset']||document['documentElement']['scrollTop'];return{'top':d['top']+f,'left':d['left']+e};}(c['parentElement']),e=!0x1,f={'x':0x0,'y':0x0},g={'x':d['left'],'y':d['top']};c['parentElement']['addEventListener']('mousedown',function(d){e=!0x0,f['x']=d['clientX'],f['y']=d['clientY'],c['parentElement']['style']['cursor']='move';}),c['parentElement']['addEventListener']('mouseup',function(d){e=!0x1,g['x']=parseInt(c['parentElement']['style']['left'])||0x0,g['y']=parseInt(c['parentElement']['style']['top'])||0x0,c['parentElement']['style']['cursor']='auto';}),document['addEventListener']('mousemove',function(d){if(!e)return;var h={'x':d['clientX']-f['x'],'y':d['clientY']-f['y']},i={'x':g['x']+h['x'],'y':g['y']+h['y']};i['x']<0x0?i['x']=0x0:i['x']+c['parentElement']['offsetWidth']>document['documentElement']['clientWidth']&&(i['x']=document['documentElement']['clientWidth']-c['parentElement']['offsetWidth']);i['y']<0x0?i['y']=0x0:i['y']+c['parentElement']['offsetHeight']>document['documentElement']['clientHeight']&&(i['y']=document['documentElement']['clientHeight']-c['parentElement']['offsetHeight']);c['parentElement']['style']['left']=i['x']+'px',c['parentElement']['style']['top']=i['y']+'px';});}(o);}(window);
Method of minification and obfuscation
I minified the code below using: https://javascript-minifier.com/
I obfuscated the resulting minified code using: https://obfuscator.io/
For the obfuscator, I set "Identifier Names Generator" to "mangled" and checked "Rename Globals".
Important: Unselect "String Array" or you cannot add new link entries.
Caveats
The script doesn't allow moving beyond the initial width and height. The following width and height methods from this post could be incorporated to fix this limitation.
Source code
(function(window) {
var links = [{
name: 'Google',
url: 'https://www.google.com'
}, {
name: 'Bing',
url: 'https://www.bing.com'
}, {
name: 'DuckDuckGO',
url: 'https://duckduckgo.com'
}];
var props = {
width: 500,
height: 300,
background: '#AAA',
borderThickness: 1,
headerHeight: 32,
headerBackground: '#444',
headerTitleColor: '#FFF',
windowTitle: 'Bookmarklet Links'
};
var windowPosition = {
left: ~~((document.documentElement.clientWidth / 2) - (props.width / 2)),
top: ~~((document.documentElement.clientHeight / 2) - (props.height / 2)),
}
var btnSize = ~~(props.headerHeight * 0.8);
var popupEl = document.createElement('DIV');
Object.assign(popupEl.style, {
position: 'absolute',
left: windowPosition.left + 'px',
top: windowPosition.top + 'px',
zIndex: Number.MAX_SAFE_INTEGER,
width: props.width + 'px',
height: props.height + 'px',
background: props.background,
border: props.borderThickness + 'px solid black'
});
var popupHeader = document.createElement('DIV');
Object.assign(popupHeader.style, {
position: 'relative',
width: (props.width) + 'px',
height: props.headerHeight + 'px',
background: props.headerBackground,
borderBottom: props.borderThickness + 'px solid black'
});
var popupHeaderTitle = document.createElement('DIV');
Object.assign(popupHeaderTitle.style, {
position: 'relative',
display: 'inline-block',
left: 0,
width: ~~(props.width - btnSize * 2) + 'px',
lineHeight: props.headerHeight + 'px',
color: props.headerTitleColor,
fontSize: ~~(props.headerHeight * 0.667) + 'px',
marginLeft: ~~(btnSize / 3) + 'px'
});
popupHeaderTitle.textContent = props.windowTitle;
var closeButton = document.createElement('DIV');
var margin = ~~((props.headerHeight - btnSize) / 2);
Object.assign(closeButton.style, {
position: 'relative',
float: 'right',
right: margin + 'px',
top: margin + 'px',
width: btnSize + 'px',
height: btnSize + 'px',
background: '#F00',
border: props.borderThickness + 'px solid black',
color: '#FFF',
lineHeight: btnSize + 'px',
textAlign: 'center',
fontSize: btnSize + 'px',
marginLeft: 'auto',
marginRight: 0
});
var popupBody = document.createElement('DIV');
Object.assign(popupBody.style, {
padding: '1em'
});
var p = document.createElement('P');
p.textContent = 'Click the links to open a new tab!';
popupBody.appendChild(p);
var listEl = document.createElement('UL');
links.forEach(link => {
var itemEl = document.createElement('LI');
var anchorEl = document.createElement('A');
anchorEl.setAttribute('href', link.url);
anchorEl.setAttribute('target', '_blank');
anchorEl.textContent = link.name;
itemEl.appendChild(anchorEl);
listEl.appendChild(itemEl);
});
popupBody.appendChild(listEl);
closeButton.addEventListener('click', destroyWindow, false);
closeButton.textContent = '×';
popupHeader.appendChild(popupHeaderTitle);
popupHeader.appendChild(closeButton);
popupEl.appendChild(popupHeader);
popupEl.appendChild(popupBody);
document.body.appendChild(popupEl);
draggable(popupHeader);
function destroyWindow(e) {
closeButton.removeEventListener('click', destroyWindow, false);
popupHeader.removeChild(closeButton);
popupEl.removeChild(popupHeader);
popupEl.removeChild(popupBody);
document.body.removeChild(popupEl);
}
/* Source: https://plainjs.com/javascript/styles/get-the-position-of-an-element-relative-to-the-document-24/ */
function offset(el) {
var rect = el.getBoundingClientRect(),
scrollLeft = window.pageXOffset || document.documentElement.scrollLeft,
scrollTop = window.pageYOffset || document.documentElement.scrollTop;
return { top: rect.top + scrollTop, left: rect.left + scrollLeft }
}
/* Source: https://gist.github.com/remarkablemark/5002d27442600510d454a5aeba370579 */
function draggable(el) {
var initialOffset = offset(el.parentElement);
var isMouseDown = false;
var currPos = { x : 0, y : 0 };
var elPos = { x : initialOffset.left, y : initialOffset.top };
el.parentElement.addEventListener('mousedown', onMouseDown);
function onMouseDown(event) {
isMouseDown = true;
currPos.x = event.clientX;
currPos.y = event.clientY;
el.parentElement.style.cursor = 'move';
}
el.parentElement.addEventListener('mouseup', onMouseUp);
function onMouseUp(event) {
isMouseDown = false;
elPos.x = parseInt(el.parentElement.style.left) || 0;
elPos.y = parseInt(el.parentElement.style.top) || 0;
el.parentElement.style.cursor = 'auto';
}
document.addEventListener('mousemove', onMouseMove);
function onMouseMove(event) {
if (!isMouseDown) return;
var delta = { x : event.clientX - currPos.x, y: event.clientY - currPos.y };
var pos = { x : elPos.x + delta.x, y : elPos.y + delta.y };
if (pos.x < 0) {
pos.x = 0;
} else if (pos.x + el.parentElement.offsetWidth > document.documentElement.clientWidth) {
pos.x = document.documentElement.clientWidth - el.parentElement.offsetWidth;
}
if (pos.y < 0) {
pos.y = 0;
} else if (pos.y + el.parentElement.offsetHeight > document.documentElement.clientHeight) {
pos.y = document.documentElement.clientHeight - el.parentElement.offsetHeight;
}
el.parentElement.style.left = pos.x + 'px';
el.parentElement.style.top = pos.y + 'px';
}
}
})(window);
Improving
You will notice that if your cursor goes off-screen while dragging (and you release the button) the window will be stuck in drag. You could detect this globally, but you will also need to figure out how re reinitialize the position to last known "good" position.
document.addEventListener('mouseup', onGlobalMouseUp);
function onGlobalMouseUp(event) {
if (
(event.clientX < 0 || event.clientX > document.documentElement.clientWidth) ||
(event.clientY < 0 || event.clientY > document.documentElement.clientHeight)
) {
if (isMouseDown) {
isMouseDown = false; // Draggged off-screen
popupEl.style.cursor = 'auto';
}
}
}
Lastly, don't spam the bookmarklet button, because it will create multiple instances of the same window. Code can be added to detect the presence of the window before creating a new one. Closing it could hide it, so it will just make the existing one visible again. Multiple windows will break the close listener.
I inherited a client website, and I am not a developer or jQuery developer.
On the client website, at bottom right is supposed to be a div#scrollUp which contains an image of an up arrow and scrolls the browser up to the top of the page when clicked.
The following script is designed to handle the scrolling up behaviour:
! function(a, b, c) {
a.fn.scrollUp = function(b) {
a.data(c.body, "scrollUp") || (a.data(c.body, "scrollUp", !0), a.fn.scrollUp.init(b))
}, a.fn.scrollUp.init = function(d) {
var e = a.fn.scrollUp.settings = a.extend({}, a.fn.scrollUp.defaults, d),
f = e.scrollTitle ? e.scrollTitle : e.scrollText,
g = a("<a/>", {
id: e.scrollName,
href: "#top",
title: f
}).appendTo("body");
e.scrollImg || g.html(e.scrollText), g.css({
display: "none",
position: "fixed",
zIndex: e.zIndex
}), e.activeOverlay && a("<div/>", {
id: e.scrollName + "-active"
}).css({
position: "absolute",
top: e.scrollDistance + "px",
width: "100%",
borderTop: "1px dotted" + e.activeOverlay,
zIndex: e.zIndex
}).appendTo("body"), scrollEvent = a(b).scroll(function() {
switch (scrollDis = "top" === e.scrollFrom ? e.scrollDistance : a(c).height() - a(b).height() - e.scrollDistance, e.animation) {
case "fade":
a(a(b).scrollTop() > scrollDis ? g.fadeIn(e.animationInSpeed) : g.fadeOut(e.animationOutSpeed));
break;
case "slide":
a(a(b).scrollTop() > scrollDis ? g.slideDown(e.animationInSpeed) : g.slideUp(e.animationOutSpeed));
break;
default:
a(a(b).scrollTop() > scrollDis ? g.show(0) : g.hide(0))
}
}), g.click(function(b) {
b.preventDefault(), a("html, body").animate({
scrollTop: 0
}, e.scrollSpeed, e.easingType)
})
}, a.fn.scrollUp.defaults = {
scrollName: "scrollUp",
scrollDistance: 300,
scrollFrom: "top",
scrollSpeed: 300,
easingType: "linear",
animation: "fade",
animationInSpeed: 200,
animationOutSpeed: 200,
scrollText: "Scroll to top",
scrollTitle: !1,
scrollImg: !1,
activeOverlay: !1,
zIndex: 200
}, a.fn.scrollUp.destroy = function(d) {
a.removeData(c.body, "scrollUp"), a("#" + a.fn.scrollUp.settings.scrollName).remove(), a("#" + a.fn.scrollUp.settings.scrollName + "-active").remove(), a.fn.jquery.split(".")[1] >= 7 ? a(b).off("scroll", d) : a(b).unbind("scroll", d)
}, a.scrollUp = a.fn.scrollUp
}(jQuery, window, document);
The script above has comments:
scrollup v2.1.1
Author: Mark Goodyear - http://markgoodyear.com
Git: https://github.com/markgoodyear/scrollup
Copyright 2013 Mark Goodyear.
Licensed under the MIT license
In the header is jQuery.scrollUp();, but the problem is that there is no div#scrollUp produced, meaning the up arrow is not present on the page.
I can't see anywhere in the theme file a mention of #scrollUp, so I assume the Javascript block above, plus the header running jQuery.scrollUp(); is supposed to insert the div#scrollUp - is that correct?
Help appreciated.
Try to put the
$(function () {
$.scrollUp({
zIndex: 2147483647
});
});
on the <script> tag of your page, and let see whats happen.
Instead showing 3rd party plugin javasript code, you better show the code inside your page.
So basically whenever I am loading a Bootstrap Popover with an empty content option and inserting content into it dynamically, the popover loses its correct position.
For example:
$('td.chartSection').each(function () {
var $thisElem = $(this);
$thisElem.popover({
placement: 'top',
trigger: 'hover',
html: true,
container: $thisElem,
delay: {
hide: 500
},
content: ' '
});
});
//After popup is shown, run this event
$('td.chartSection').on('shown.bs.popover', function () {
var $largeChart = $(this).find('.popover .popover-content');
//Insert some dummy content
$largeChart.html("dfjhgqrgf regqef f wrgb wrbgqwtgtrg <br /> wfghjqerghqreg fbvwqbtwfbvfgb <br />efgwetrg");
});
My Question:
Is there a method that can recalculate the popovers position such as $('td.chartSection').popover('recalculate').
Or is there another way to re-position the popover without manually doing this with CSS styles?
WORKING DEMO
Using Bootstrap v3.3.7:
You can extend the Popover constructor to add support for a re-positioning function. You can place this script below where you load bootstrap.
JSFiddle Demo
<script src="bootstrap.js"></script>
<script type="text/javascript">
$(function () {
$.fn.popover.Constructor.prototype.reposition = function () {
var $tip = this.tip()
var autoPlace = true
var placement = typeof this.options.placement === 'function' ? this.options.placement.call(this, $tip[0], this.$element[0]) : this.options.placement
var pos = this.getPosition()
var actualWidth = $tip[0].offsetWidth
var actualHeight = $tip[0].offsetHeight
if (autoPlace) {
var orgPlacement = placement
var viewportDim = this.getPosition(this.$viewport)
placement = placement === 'bottom' &&
pos.bottom + actualHeight > viewportDim.bottom ? 'top' : placement === 'top' &&
pos.top - actualHeight < viewportDim.top ? 'bottom' : placement === 'right' &&
pos.right + actualWidth > viewportDim.width ? 'left' : placement === 'left' &&
pos.left - actualWidth < viewportDim.left ? 'right' : placement
$tip
.removeClass(orgPlacement)
.addClass(placement)
}
var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)
this.applyPlacement(calculatedOffset, placement)
}
})
</script>
Then in your script whenever you need to reposition your tooltip after inserting content. You can just call:
$element.popover('reposition')
No, there isn't a recalculate and there's really no easy way to do it. That said, you can dynamically inject the popovers this way:
$('td.chartSection').on('mouseenter', function() {
var myPopOverContent = 'This is some static content, but could easily be some dynamically obtained data.';
$(this).data('container', 'body');
$(this).data('toggle', 'popover');
$(this).data('placement', 'top');
$(this).data('content', myPopOverContent);
$(this).popover('show');
});
$('td.chartSection').on('mouseout', function() {
$(this).popover('hide');
});
Just replace all of your js in your fiddle with the above and check it out...
I just called
button.popover('show');
And it re-positioned it.
window.dispatchEvent(new Event('resize'));
This works for me.
I had a similar situation where I had a popover which already contained some HTML (a loading spinner) and I was changing the content when an ajax call returned. In my ajax callback function, this was the code I used to change the positioning so it remained centred:
var originalHeight = $(popover).height();
$(popover).find('.popover-content').html(data);
var newHeight = $(popover).height();
var top = parseFloat($(popover).css('top'));
var changeInHeight = newHeight - originalHeight;
$(popover).css({ top: top - (changeInHeight / 2) });
I used this code to adjust the height off the popover when it's already loaded to the page:
var popover = $(this).closest('.popover');
var sender = popover.prev();
var adjustment = (sender.position().top - popover.height()) + 15;
popover.css({ top: adjustment });
Variable sender is the target where the popover is centred from.
this is inspired by #AlexCheuk answer above, but I needed a solution using Bootstrap 2. Also, in my project I didn't need to change popovers' placement, so I cut that out.
$(function() {
$.fn.popover.Constructor.prototype.reposition = function () {
console.log('popover reposition is called');
var $tip = this.tip();
var placement = typeof this.options.placement === 'function' ? this.options.placement.call(this, $tip[0], this.$element[0]) : this.options.placement;
var pos = this.getPosition();
var actualWidth = $tip[0].offsetWidth;
var actualHeight = $tip[0].offsetHeight;
function getCalculatedOffset (placement, pos, actualWidth, actualHeight) {
return placement == 'bottom' ? { top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'top' ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
placement == 'left' ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
/* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width };
}
var calculatedOffset = getCalculatedOffset(placement, pos, actualWidth, actualHeight);
this.applyPlacement(calculatedOffset, placement);
console.log(this);
};
});
To call it:
$element.popover('reposition')
If the popover's position is "top" (as in the question), you can just adjust its absolute positioning from the top of the page.
I've created a function to work out the height of the popover, and then shift it up on the page by its height.
function adjustPopoverHeight($popoverElement) {
var height = $popoverElement.height();
var adjustment = 0 - height - 4;
$popoverElement.css({ top: adjustment });
}
and use with an ajax request to get data:
$.ajax({
type: 'GET',
url: url,
contentType: 'application/json; charset=utf-8',
dataType: 'json'
}).done(function(dat) {
//set the popover content to whatever you like
//adjust height of popover
var $popoverElement = $('.popover');
adjustPopoverHeight($popoverElement);
})
I took the concept of jme11's answer and updated for Bootstrap 3.3.2+
$('button')
.popover({
trigger: 'manual',
html: true,
container: 'body',
})
.click(function() {
var $this = $(this);
var popover_obj = $this.data('bs.popover');
if (popover_obj.tip().hasClass('in')) {
popover_obj.hide();
} else {
var opts = popover_obj.options;
opts.content = $('<div/>').text('hello world');
popover_obj.init('popover', $this, opts);
popover_obj.show();
}
})
;
There's a method called setContent on the popover object, but for some reason it wasn't working for me. If you'd like to try, it would look like this:
popover_obj.setContent($('<div/>').text('hello world'));
After a Popover content update, if you scroll up or down on page content, Popover does an auto-positioning and is readable again, so a simpler workaround to re-position the Popover after dynamic content update is to scroll down and up for 1 pixel on the page via pure javascript:
var y = $(window).scrollTop(); //your current y position on the page
$(window).scrollTop(y+1).scrollTop(y-1);
I experienced positioning issues after dynamically inserting other elements in the DOM and I solved them using the container option. By default my popovers were attached to body.
Attaching them to the closest container solved the position problems.
<div id="test">
<span
data-container="#test" data-toggle="popover" data-placement="top" title="Help"
data-trigger="hover" tabindex="-1" data-html="true"
data-content="Some text">
</div>
I am doing some modal popups but the dialog renders 200px to the left, and about 100px top of where it should.
updated jquery
DevicesRightClickActionsMenuController.prototype.showActionsMenu = function(event) {
rightClicActionskMenuElement.css({
top : $('.printer-context-node').offset().top + $('.printer-context-node').height() - $('.devices-right-click-menu-item').height() * 4 + 'px',
left : $('.printer-context-node').offset().left + $('.printer-context-node').width() + 'px',
position : 'absolute',
zIndex : 1000
});
DevicesRightClickMenuController.prototype.showRightClickMenu = function (xPosition, yPosition, theSerialNumber) {
serialNumber = theSerialNumber;
rightClickMenuElement.css({
position: 'absolute',
top: yPosition,
left: xPosition,
zIndex: 1000,
});
It could be that you're using the wrong properties of the event to display the box, such as pageX/pageY instead of clientX/clientY. If you post some more code it will help narrow this down.
I have the following div :
<div id = "shrink-test" style = "position:absolute;top:100px;left:50%;margin-left:-50px;height:100px;width:100px;background-color: red;" />
and I want to use jQuery's animate() to shrink the div to half of its size but keep the animation and position of my div centered.
I'm trying:
$("#shrink-test").animate(
{
height: 50,
width: 50
});
but it shrinks the div using its top left corner as reference. How can I make it use its center as the reference point?
Thanks for any help!
As your div is positioned absolutely by using top and margin-left, you will need to animate those as well:
$("#shrink-test").animate({
height: 50,
top: 125, // 100 + 50 / 2
width: 50,
marginLeft: -25 // 50 / -2
});
For a programmatical approach it might be easier to use a negative margin for the y-axis, too.
Here's just a simple jQuery plugin for this
$.fn.resize = function( w, h ) {
w = ( undefined !== w ? w : 50 );
h = ( undefined !== h ? h : 50 );
var cw = this.width();
var ch = this.height();
if ( 'static' === this.css( 'position' ) ) {
this.css( {
'position' : 'relative',
'top' : '0px',
'left' : '0px'
} );
}
this.stop().width( cw ).height( ch ).animate( {
'top' : '+=' + ( (ch - h) / 2 ) + 'px',
'left' : '+=' + ( (cw - w) / 2 ) + 'px',
'width' : w + 'px',
'height' : h + 'px'
} );
};
$( function() {
$( '#shrink-test' ).resize(50,50);
} );
Test it here: http://jsfiddle.net/bukfixart/nPjMa/1/
You can animate top and left like so:
$("#shrink-test").animate(
{
height: 50,
width: 50,
top: '+=25px',
left: '+=25px'
});
See this fiddle
You'll have to animate the position on the page at the same time using something like top and left or margin properties, like so:
$("#shrink-test").animate(
{
height: 50,
width: 50,
top: '150px',
left: '75%'
});
Using appropriate values for each.