OpenStreetMap Click event after moving container - javascript

I recently got aware of a bug in the OSM map:
the map click event seems to trigger at the wrong coordinates if the map div is moved. how would i workaround this problem? i can't guarantee the map div to be fixed, because the site's content may change while the map is shown.
As far as i searched google and stack overflow, i seem to be the only one experiencing that problem...
Here's a fiddle: http://jsfiddle.net/W3f6L/
(set a pointer => click "clickme" => try to set a pointer again)
even the simple setup of the fiddle
<div id="clickme">clickme</div>
<div id="mapdiv"></div>
with js
$("#clickme").click(function(){
$(this).css("height","200px");
});
will reproduce the error.
also pretty odd is, that if you click the clickme and then use the scrollbar to move down, the error vanishes (tough that only happens in the fiddle, i already tried to reproduce this behaviour in the site...)
[EDIT] solution,a bit more generalized than unknown's answer, but based on it....in case someone else stumbles upon a similar problem:
setInterval(function(){
//map container jQuery object...
var o = jQuery(map.div);
if(lastPos == null) lastPos = o.position(); //initally set values
if(lastOff == null) lastOff = o.offset();
//body or whatever div is scrollable, containing the map div
if(lastScroll == null) lastScroll = jQuery("body").scrollTop();
var newPos = o.position(); //getting values at this time
var newOff = o.position();
var newScroll = jQuery("body").scrollTop();
if(lastPos.top != newPos.top ||
lastPos.left != newPos.left ||
lastOff.top != newOff.top ||
lastOff.left != newOff.left ||
lastScroll != newScroll){
//if one of the values has changed, the map needs to be updated
map.updateSize();
}
//reset values for next run
lastPos = newPos;
lastOff = newOff;
lastScroll = newScroll;
},200); //the smaller, the more computing, the bigger the more delay between changes and the map update

You need to update map size using an API updateSize. Try this:
$("#clickme").click(function(){
$(this).css("height","200px");
map.updateSize();
});
DEMO

Related

How to change one element's class depending on another's element position?

I need to create a function checking if slider is in the certain left position. Depending on its position, I need to change another element's class. And it needs to be working every time slider's left position changes.
Everything works for me except the every time feature ;). Setting up setTimeout didn't help either...
Here's my code:
var $slider_pos = jQuery('.contentHolder').css('left');
var $slider_pos = $slider_pos || 0;
var $my_window = jQuery(window).width();
var $sensor = jQuery('.sensor');
function slideCheck(){
if($slider_pos == 0){
$sensor.addClass('red');
} else if($slider_pos == $my_window * -1){
$sensor.addClass('blue');
$sensor.removeClass('red');
}
setTimeout(slideCheck,500);
}
slideCheck();
Your help would be very appreciated for I've been strugling with this one for some time now.
Thank you in advance!

How to know what part of HTML is the user on

so I want to know how I can get what section or part of my html I’m currently on. An example
So how do I know if a user has already scrolled down over part 2 using JavaScript
Or if they’re currently at part 1
<html>
<head>
</head>
<body>
<section class=“part 1”>
</section>
<section class= “part2>
</section>
</body>
</html>
The following codes will give you a little idea about how to handle this situation. Essentially you are going to want to get the scrollbar position which you can do using:
document.documentElement.scrollTop
You also want to get a range where the element you are looking for resides, in our case, it is .part1 and .part2. We can get that range by using offsetTop as the beginning of the limit and offsetTop + clientHeight to determine the end.
You are going to have to keep track of the window scroll event.
The following example is generic:
$(window).scroll(function(e) {
if (document.documentElement.scrollTop > 0
&& document.documentElement.scrollTop < $('.part2').offset().top ) {
$('div').html("At part1")
} else {
$('div').html("At part2")
}
});
JSFiddle
Likewise, if you want a little bit of modularity:
$(window).scroll(function(e) {
let watchList = ['part1', 'part2', 'part3'];
let scrollTop = document.documentElement.scrollTop;
for (var classname of watchList) {
let el = document.getElementsByClassName(classname)[0];
if (scrollTop > el.offsetTop &&
scrollTop < el.offsetTop + el.clientHeight) {
$('div').html("At <strong>"+classname+"</strong>");
}
}
});
JSFiddle
The possibilities are limitless to continue and make this more useful, but I'll leave that up to you.
you can use is[":focus"] function to find which div has focus currently.
if($(".part1").is(":focus"))
{
//you code
}
else if($(".part2").is(":focus"))
{
//you code
}
you can use mouseenter function it fires when the mouse goes into that div for the first time.
$(".part1").on('mouseenter', function(){
//your command
});
you can use mouseover function to find where is mouse right now. it fires when mouse moves inside that div.
$(".part1").on('mouseover', function(){
//your command
});
You can use javascripts offsetTop functionality. This is a parameter that returns how far down from the top a div is in the number of pixels.
It can also return how far down the user has scrolled when called on the window object itself. Then it's just a matter of math. See if the user has scolled down far enough to be past the div in reference.
For example:
var part1DivOffset = document.getElementsByClassName("part 1")[0].offsetTop;
var part2DivOffset = document.getElementsByClassName("part2")[0].offsetTop;
var scrollTop = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
This code will get you 3 variables. The first 2 lines save the offsetTop of the div's. While the third line detects how far down the user has scrolled. Then you can do math with the variables:
if(scrollTop >= part1DivOffset){
//we are past part1
}
if(scrollTop >= part2DivOffset){
//We are past part 2
}
if(scrollTop >= part1DivOffset && scrollTop < part2DivOffset){
//We are past part 1 but not past part 2
}

Replacing Bootstrap Dropdown with Dropup (Different activity on two near identical implementations)

I'm working on a project over at github pages, which I replace a bootstrap .dropdown with .dropup if the div's overflow-y: scroll will cause the dropdown menu to be cutoff / overflow. You can see the function working properly at this jsfiddle. Notice if you click on the ellipsis icon to the right on the top rows, it will drop down, if you click on the icon on the bottom rows, it will drop up.
Now, my actual implementation (github page), the code is exactly the same (below), but it wants to replace all .dropdown classes with .dropup when opened, including the top-most row which gets cut off, seen in the photo below.
I've been struggling with this for a week and can't quite figure it out. I've tried a few different things that I thought fixed it but ended up just being a hack and didn't work on mobile, or replaced some but not all etc.
Here is the Javascript / jQuery I'm using, which can be seen in the jsfiddle and my github source here.
$(document).on("shown.bs.dropdown", ".dropdown", function () {
// calculate the required sizes, spaces
var $ul = $(this).children(".dropdown-menu");
var $button = $(this).children(".song-menu");
var ulOffset = $ul.offset();
// how much space would be left on the top if the dropdown opened that direction
var spaceUp = (ulOffset.top - $button.height() - $ul.height()) - $('#playlist').scrollTop();
// how much space is left at the bottom
var spaceDown = $('#playlist').scrollTop() + $('#playlist').height() - ((ulOffset.top + 10) + $ul.height());
// switch to dropup only if there is no space at the bottom AND there is space at the top, or there isn't either but it would be still better fit
if (spaceDown < 0 && (spaceUp >= 0 || spaceUp > spaceDown))
$(this).addClass("dropup");
}).on("hidden.bs.dropdown", ".dropdown", function() {
// always reset after close
$(this).removeClass("dropup");
});
Edit:
To clear up any confusion, here's an example of the behavior without my added .dropup function. jsfiddle Notice when you click the last menu item, it opens the menu but requires scrolling. I specifically want to remove the .dropdown class and add .dropup in this case, so no scrolling is required.
It took some basic math, but I managed to figure out what you desired to do. This code changes the bootstrap classes between dropup and dropdown depending on the room available for a normal dropdown.
I calculated this by detracting the height of the button, dropdownmenu and how far the button was scrolled down in the scrollContainer from the height of the scrollContainer. I got the value how much the div was scrolled down by using the buttons offset and detracting the offset from the scrollContainer.
Here is my jQuery (I selected the .playlist class because this was attached to your scrollContainer, but you should replace it by an id or select it by other means):
$(".dropdown, .dropup").click(function(){
var dropdownClassCheck = $(this).hasClass('dropdown');
var buttonOffset = $(this).offset().top;
var scrollboxOffset = $('.playlist').offset().top;
var buttonHeight = $(this).height();
var scrollBoxHeight = $('.playlist').height();
var dropDownButtonHeight = $(this).children('ul').height();
dropdownSpaceCheck = scrollBoxHeight>buttonOffset-scrollboxOffset+buttonHeight+dropDownButtonHeight;
if(dropdownClassCheck && !dropdownSpaceCheck){
$(this).removeClass('dropdown').addClass('dropup');
}
else if(!dropdownClassCheck && dropdownSpaceCheck){
$(this).removeClass('dropup').addClass('dropdown');
}
});
A working JSFiddle
Let me know if there are parts of the code that could be improved/done easier or if there are any problems with my solution.
I have not thoroughly checked, but .scrollTop() is probably why the code fails when combined with other elements in the DOM, so here is a solution without it:
function checkHeights(){
// LOOP through each dropdown
$('.dropdown,.dropup').each(function(index,element){
var $dropDown = $(element),
$dropDownMenu = $dropDown.find('.dropdown-menu'),
dropDownTop = $dropDown.offset().top,
visibleHeight = $dropDown.height(),
hiddenHeight = $dropDownMenu.height(),
ddTop = dropDownTop - hiddenHeight,
ddBottom = dropDownTop + visibleHeight + hiddenHeight;
// LOOP through all parents
$dropDown.parents().each(function(ix,el){
var $el = $(el);
// CHECK if any of them have overflow property set
if( $el.css('overflow') !== 'visible' ){
var limitTop = $el.offset().top,
limitBottom = limitTop + $el.height();
// CHECK if parent is better fit when dropped upside
if( limitBottom < ddBottom && ( ddTop - limitTop ) > ( limitBottom - ddBottom ) )
$dropDown.removeClass('dropdown').addClass('dropup');
else
$dropDown.removeClass('dropup').addClass('dropdown');
// BREAK LOOP
return false;
}
});
});
}
$(document).ready(function() {
checkHeights();
$('.playlist').scroll(checkHeights);
});
JS Fiddle here.
This one does not require any class or id given to it except for dropdown,dropdown-menu, and dropup (all of which are Bootstrap defaults) and would work fine even if there are multiple playlists on page.
UPDATE
The code is modified and wrapped in a function in order to allow being called when scroll event fires.
I think that the problem it's that you have a big header, and the jsFiddle don't. So ulOffset.top it's always big, and spaceDown is always negative
Replace parent div.dropdown with div.dropup.

Detect when a div is touching top jquery

I am trying to detect when a div is at the top of the page with Jquery/Javascript. Anyone any idea's where I might start?
You can listen to the scroll event using jQuery, and every time it changes, get the offset value of the div and compare it with 0.
I would use a function like this:
function elementAtViewportTop(elem) {
if(!elem || typeof elem !== "object") return false;
if(elem instanceof jQuery) elem = elem[0];
var elemClientRect = elem.getBoundingClientRect();
return (elemClientRect.top <= 0 && elemClientRect.top > -(elemClientRect.height));
}
elem.getBoundingClientRect().top will be zero if the element reaches the top of the window (getBoundingClientRect()).
When you add an event listener for scroll to the window and call that function every time on your element, it will work fine:
Demo

Javascript Zoom on different tabs

I have made a simple zoom in and out function with button as well as mousewheel function. The main concept is to limit the maximum zoom level and minimum zoom level.
I have successfully made it in two ways
BIN 1
BIN 2
But i tried to make this in a tab section with unique ID or by class.
My script
var zoomLevel = 100;
var maxZoomLevel = 150;
var minZoomLevel = 50;
var initW=0,initH=0;
function zoom(zm) {
var img=document.getElementById("pic");
if(zm > 1){
if(zoomLevel < maxZoomLevel){
zoomLevel+=10;
}else{
return;
}
}else if(zm < 1){
if(zoomLevel > minZoomLevel){
zoomLevel-=10;
}else{
return;
}
}
img.style.width = (initW*zoomLevel/100)+"px";
img.style.height = (initH*zoomLevel/100)+"px";
img.style.marginLeft = ((initW-img.width)/2) + "px";
img.style.marginTop = ((initH-img.height)/2) + "px";
}
window.onload=function(){
var img=document.getElementById("pic");
initW=img.width;
initH=img.height;
img.onmousewheel=function(e){
e=e||window.event;
if(e.wheelDelta>=120) zoom(1.1);
else zoom(0.9);
};
if(/Firefox/.test(navigator.userAgent)){
img.addEventListener("DOMMouseScroll",function(e){
if(e.detail<0) zoom(1.1);
else if(e.detail>0) zoom(0.9);
e.preventDefault();
},false);
}
};
Here i am getting my element by using GetElementById to access my image tag is there any way to get access all the img tags in other tabs too.
I also tried getElementsbyClassName but its not working it just retrieving the nodeslist.
How can i access all three images here
Current BIN
you need to use different ID's
var img=document.getElementById("pic1");
var img=document.getElementById("pic2");`
You have assigned all three images the same id (id="pic"). You can't do that, ids must be unique.
If you change their ids, (ex: pic, pic2, pic3), and pass that in to your zoom function as an argument, then all the tabs will zoom.
So change the zoom function to look like this:
function zoom(zm, id) {
var img=document.getElementById(id);
...
}
And make your html look like this (just one for an example):
<div id="tabs-2">
<input type="button" value ="-" onClick="zoom(0.9, 'pic2')"/>
<input type="button" value ="+" onClick="zoom(1.1, 'pic2')"/>
<div id="thediv">
<img id="pic2" src="http://stereo-ssc.nascom.nasa.gov/beacon/t0193.jpg"/>
</div>
</div>
Now all three will zoom individually. Here's a jsbin showing it.
But, there's a bug. The variable you use to track the zoom state is being shared between the tabs. This means the "zoom limit" is not really enforced: you can just zoom one tab all the way down, then the next tab all the way up. Repeat this to make any of the images as big or as small as you want. I don't think this is what you want, but I'm going to leave it an exercise for you to fix.

Categories