Popover appearing in the wrong place - javascript

JS Fiddle here: http://jsfiddle.net/Xw9QK/1/
I am making a popover, and had it working, but then when I started loading the content though ajax and adding a spinner to appear first it now appears in the wrong place.
I think the problem is something to do with the fact the spinner makes a small popover appear and when the content loads it uses the same div to add the ajax content then resizes the box before moving it.
Now sometimes it works, on my site it seems to not work first time, but when closing and opening it again it snaps back to the correct position!
Can anyone see whats going wrong here?
I am using this function to reset the position:
function reset_popover_position(user_id) {
var position = $('#link_' + user_id).position();
console.log(position);
var top_position = (position.top - $('.new_tooltip').outerHeight()) - 10;
console.log(top_position);
var left_position = (position.left - ($('.new_tooltip').outerWidth() / 2) + ($('#link_' + user_id).outerWidth() / 2));
console.log(left_position);
$('.new_tooltip').css({
top: top_position + "px",
left: left_position + "px"
});
return true;
}

A setTimeout fixed the issue. Fiddle.
It is a trick that I use when I deal with dynamic contents height & width.
I think it setTimeout of 1 gives the browser enough time to render the html & so, when setTimeout triggers the actual code that, calculates dimensions, everything gives proper results.
I added setTimeout inside toggle_popover.
setTimeout(function() {
reset_popover_position(user_id);
}, 1);

Related

Setting image position with javascript, not always placing correctly

I'm using the following code to position images on my page:
var adjustImages = function(){
var monsters = [$("#m3"), $("#m4")];
monsters[0].css('right', monsters[0].width() * -0.4 + "px");
monsters[0].css('top', $("#divider-green").height() + $("#divider-orange").height() + (monsters[3].height() / 6) + "px");
monsters[1].css('left', monsters[1].width() * -0.385 + "px");
monsters[1].css('top', $("#divider-green").height() + $("#divider-orange").height() + $("#divider-red").height() + "px");
}
I'm then calling this function when the page loads, and when it's resized:
$(document).ready(function(){
adjustImages();
});
window.onresize = function(event) {
adjustImages();
};
The images are meant to be positioned on the window border (as in, part of the image is off the screen, part it off). This is done by setting right/left to a negative number (relative to the image size).
Sometimes when I refresh the page the images are placed correctly, however other times they are not over the border (but are rather positioned against the border (as if no left/right adjustment was applied). Does anyone know what the cause of this might be?
It looks like you aren't doing any check to see if the image is loaded before doing math based on it's width. That's probably what's causing the inconsistent behavior.
When an image is first created in the DOM, before it's loaded (and if it doesn't have one set directly), it's width and height are 0. What I would do is add a load event listener on your images and then call adjust.
You also want to call adjustImages() if one of the images already has a width greater than 0, because that means it's already loaded by the time the document is ready.
$(document).ready(function(){
$('#m3, #m4').one('load', function () {
adjustImages();
});
if ($('#m3').width > 0 || $('#m4').width > 0) {
adjustImages();
}
});
Now, that code snippet has a bit of a bug because it'll fire once either is loaded, not when both are loaded. You'll want to tweak it, and probably even separate them out so you're doing things individually for each, but it should give you the idea.

how to calculate offset.left position to display image on link hover

I have a JavaScript function that when a user does a mouse-over a thumbnail, a larger preview of the image pops up. The JavaScript calculates the top and left offset position to either display the preview on the right or left of the screen, depending on the screen size.
The function works when the object passed is an image.
My goal is to use the same function as a template, and have it work but instead that using a thumbnail for the hover event, just use a link. So the user does a mouse over the link, and the image preview pops up.
My problem is that the offset left position is not being calculated when using IE8 or IE11, Firefox and Chrome work fine.
The image is always being displayed on the right size of the screen. But this only happens on IE. I guess, I am not sure, but perhaps IE treats the and tag differently to calculate offset?
Here is a copy of the jquery function:
function linkOverShow(a, strSKU) {
$("#pUpImg").attr("src", "/images/items/" + strSKU + ".jpg");
var offset = $(a).offset();
if (offset.left - 350 < 0) {
$('#pUp').css('top', (offset.top - 125)).css('left', (offset.left + 100));
} else {
$('#pUp').css('top', (offset.top - 125)).css('left', (offset.left - 350));
}
$("#pUp").show();
}
On IE, the code only goes to the line:
$('#pUp').css('top', (offset.top - 125)).css('left', (offset.left + 100));
I am hoping to fins someone in this forum that can offer some ideas as to why this is happening, and possibly offer some recommendations to try to solve the issue.
I hope also I am asking this question correctly.
Any help is greatly appreciated.
Thank you much.

jQuery Positioning and Animation

So I have a piece of code:
jQuery.fn.center = function(parent) {
parent = this.parent();
this.css({
"position": "absolute",
"top": ((($(parent).height() - this.outerHeight()) / 2) + $(parent).scrollTop() + "px"),
"left": ((($(parent).width() - this.outerWidth()) / 2) + $(parent).scrollLeft() + "px")
});
return this;
}
This code grabs an element and moves it to the center of the parent. Works nicely. There are a couple of things I would like it to do aside of what it's doing.
I need it to float above all other elements in that parent. A z index more or less. I tried to apply a z-index, but it didn't seem to work. I dunno if I may have been doing it wrong, or if there is a better way.
I need it to move back to the position it was in. The way this works, is the block is gonna be positioned on the page (via CSS), and when the user clicks, it moves it to the center of the page, as the code is already doing. Is there any way that, if a user clicks an exit button, I can program said button to move it back to where it originally was? i don't know if I can pass variables around in jQuery.
This option is more for aesthetics, and i don't deem it necessary, but would like it if you have a little extra time. I would like the block to slide from it's position to the center of the page, and back, as opposed to just popping there. As I stated, this is just aesthetics and i really don't need that to happen.
Much appreciated to anyone that can help me out.
I tried to implement a similar requirement but It should have all the features that you were looking for. Try DEMO
I need it to float above all other elements in that parent. A z index
more or less. I tried to apply a z-index, but it didn't seem to work.
I dunno if I may have been doing it wrong, or if there is a better
way.
I always use z-index in range of 1001 or greater for such cases. Even in the demo, it works fine. Try this and let us know if you still not working for you.
I need it to move back to the position it was in. The way this works,
is the block is gonna be positioned on the page (via CSS), and when
the user clicks, it moves it to the center of the page, as the code is
already doing. Is there any way that, if a user clicks an exit button,
I can program said button to move it back to where it originally was?
i don't know if I can pass variables around in jQuery.
I stored the original position of the element using .data API and restored it back to its original position when close(exit) button is clicked.
This option is more for aesthetics, and i don't deem it necessary, but
would like it if you have a little extra time. I would like the block
to slide from it's position to the center of the page, and back, as
opposed to just popping there. As I stated, this is just aesthetics
and i really don't need that to happen.
You can use .animate instead of CSS which will transcend the element from it original position to the destination position in specified time.
In order for it to float above all other elements, you're right in that you'll need to use z-index for that, but you'll need to make sure that each element is positioned and each element has a z-index value to start with, including the parent. The parent will also need to be positioned.
In order to revert back to their original positions, you'll have to grab their current left and top offsets. In your click event listener, move the element back to its old position.
jQuery.fn.center = function(parent) {
var oldTop = this.css('top');
var oldLeft = this.css('left');
parent = this.parent();
this.css({
"position": "absolute",
"top": ((($(parent).height() - this.outerHeight()) / 2) + $(parent).scrollTop() + "px"),
"left": ((($(parent).width() - this.outerWidth()) / 2) + $(parent).scrollLeft() + "px")
});
this.click(function(e) {
this.css('top', oldTop);
this.css('left', oldLeft);
});
return this;
}
In order to do the animation (instead of just jumping to the position), you can animate the left and top values using jQuery.
this.animate({
'top': ((($(parent).height() - this.outerHeight()) / 2) + $(parent).scrollTop() + "px"),
'left': ((($(parent).width() - this.outerWidth()) / 2) + $(parent).scrollLeft() + "px")
});
EDIT You may want to consider using this.offset(). This returns an object containing the methods left and top.
var offset = this.offset();
var oldTop = offset.top;
var oldLeft = offset.left;

jquery: calculating 'margin-left' or 'left' relative to $(window).scrollLeft() is really jagged in Firefox — using .animate() or .css()

I have a horizontally scrolling website, and I have a block that I want to stay in frame at all times as the user scrolls right. It looks perfectly smooth in webkit browsers, but is crazy jagged in Firefox and I don't really care about IEs.
function fixMyId(){
$('#myId').css({'margin-left': 150 + $(window).scrollLeft()});
}
function fixMyIdAlt(){
$('#myId').stop().animate({'margin-left': 150 + $(window).scrollLeft()}, 300);
}
And then I have it triggered on window scroll.
What would be a best way to average out the scrolling, so that maybe every so many seconds or pixels of scrolling it fires the function, or upon stopping the scrolling it animates the block into place? I tried playing with delay() but that doesn't do anything. And this one just looks stupid (plus I have no idea what the overhead of this kind of crunching is):
function fixMyIdStupid(){
window.scrollCounter++;
if(window.scrollCounter % 20 == 0) $('#myId').stop().animate({'margin-left': 150 + $(window).scrollLeft()}, 300);
}
So what do I do? setTimeout and setInterval may be required, but those always make my head hurt.
EDIT: Here's a jsfiddle of it in action: http://jsfiddle.net/xsxSq/
The #f0f square is the #myId.
I tried to do such things as well, problem is that the scroll event isn't fired as much as you want. A nice workaround was subscribing the calculation function to the mousemove event, so it triggers A LOT. But on the other hand, I came up with another solution.
Why not turn things around and ask yourself:
Lets make it a position:fixed object and calculate what happens on resize. Because you actually are trying to create a position-x:fixed; and a position-y:absolute;
I actually did the following for the opposite kind of thing. A block that has to be exactly in the middle of the x-document, but in the y it was fixed.
$(document).ready(function ()
{
replaceFixed();
$(window).resize(replaceFixed);
$('#content').ajaxSuccess(replaceFixed);
$(window).scroll(replaceFixed);
function replaceFixed()
{
var jEl = $('#centeredFixedContainer');
var winW = $(window).width();
var docW = $(document).width();
var scrL = $(window).scrollLeft();
var divW = jEl.width();
var result = 0;
// window bigger than the element
if(winW > divW)
{
result = -scrL + ((docW-winW)/2);
}
else
{
result = $('#mainContainer').offset().left - scrL;
}
jEl.css('left',result);
}
});
Copying this code will not give you the solution, but will indicate another way to look at your problem.

Javascript mechanism to autoscroll to the bottom of a growing page?

Hopefully, this will be an easy answer for someone with Javascript time behind them...
I have a log file that is being watched by a script that feeds new lines in the log out to any connected browsers. A couple people have commented that what they want to see is more of a 'tail -f' behavior - the latest lines will always be at the bottom of the browser page until the viewer scrolls back up to see something. Scrolling back to the bottom should return you to the auto-scrolling behavior.
My google strikeout on this one is - hopefully - just a matter of not knowing anything at all about javascript and therefore, not knowing what keywords to search for. I don't need a complete solution - just a 'close enough' that lets me jump in and get my hands dirty.
EDIT:
I've been attempting the scrollTop/scrollHeight idea, but am clearly missing something. I've done next to nothing with Javascript, so again I'm probably asking very low-level questions:
<html><body>
<script type="text/javascript">
for (i=0; i<100; i++)
{
document.write("" + i + "<br />");
document.scrollTop = document.scrollHeight;
}
</script>
</body></html>
This was one of many permutations. Obviously, I can't output the log line-by-line in javascript, but I'm just trying to see the correct behavior. What's the missing link I need here?
EDIT AGAIN:
This has turned into a far more interesting problem that I first expected. The code suggestion using window.scroll does do the trick. I started playing with restricting the scroll to only take place when the browser was at the bottom of the document body. This is easy enough to do in theory, but in practice it hits a snag:
Every time you get new text from the server, the size of the body increases and your current scroll position is no longer at the bottom of the document. You can no longer tell the difference (using scrollHeight, clientHeight and scrollTop) whether the user has scrolled up or if the text has just shot beyond their view.
I think that if this is going to work, I'm going to have to commit myself to having a JS event that fires when the user scrolls and turns off scrolling if they are above the bottom of the window, but turns it back on if they have scrolled down to the point where they are effectively at the bottom of the view. I'm looking at the onScroll event and, given that the math on the variables I mentioned works out pretty well, I think I am on the right path here. Thanks for your input, everyone!
x = 0; //horizontal coord
y = document.height; //vertical coord
window.scroll(x,y);
To scroll the whole document use this:
window.scrollTo(0, document.body.scrollHeight);
if you have just a single scrollable div or something then the process is different:
var obj = $('id');
obj.scrollTop = obj.scrollHeight;
for (i = 0; i < 100; i++) {
document.write("" + i + "<br />");
window.scroll(0,document.body.offsetHeight);
}
Nice jQuery function gets this done
$('html,body').animate({ scrollTop: element.offset().top }, 'slow');
This worked for me, used it to AutoScroll to a dropdown menu to bring it into focus
This Explains What set time interval is - http://www.w3schools.com/jsref/met_win_setinterval.asp
This Explains What set time out is - http://www.w3schools.com/jsref/met_win_settimeout.asp
This will scroll the page with javascript and will stop after 6 seconds
<script type = "text/javascript" >
var x;
function autoscroll(){
self.scrollBy(0,x)
}
function playautoscroll(){
x = 1;
setInterval('autoscroll()',0.01);
stop();}
function onetozero(){
x=0;
}
function stop(){
setTimeout ("onetozero()",6000);
}
window.onload=playautoscroll
</script>
obj.scrollTop = obj.scrollHeight;

Categories