mouseover event only applies to the last leaflet map created - javascript

As a part of a plugin that I'm writing for a client, there's a shortcode that shows a leaflet map. The static script & css are loaded in the footer, and I can pass parameters to it via wp_localize_script.
What I need is to add a layer on mouseover event and remove it on mouseout. And as long as there is only one leaflet map per page it works. But if there is more than one map present in the same page, then the mouse events are only applied to the last map.
This is the smallest piece of javascript code that works as I said:
if (typeof map == 'undefined'){
var map = {};
var layer_bg = {};
}
map[id] = L.map(id.toString(10)).setView([51.505, -0.09], 6);
layer_bg[id] = new L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png');
map[id].on('mouseover', function(e) {
console.log(id);
map[id].addLayer( layer_bg[id] ); });
map[id].on('mouseout', function(e) {
map[id].removeLayer( layer_bg[id] ); });
The script receives a different id parameter in each call, but the events apply only to the last id used.
I'm out of ideas to solve this, but I hope there's a simple solution that I've overlooked. Here is a very simple jsfiddle that simulates 2 consecutive calls to the script above:
http://jsfiddle.net/LTYvq/1/

It is a scope problem.
id is a global variable, so everytime you call console.log(id); it will use the global id, which was last set to "map2".
To fix it, put the creation code into a function like so:
function createMap(id) {
if (typeof map == 'undefined'){
map = {};
layer_bg = {};
}
map[id] = L.map(id.toString(10)).setView([51.505, -0.09], 6);
layer_bg[id] = new L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png');
map[id].on('mouseover', function(e) {
console.log(id);
map[id].addLayer( layer_bg[id] ); });
map[id].on('mouseout', function(e) {
map[id].removeLayer( layer_bg[id] ); });
}
and then call
createMap("map1");
createMap("map2");
For more about scopes, see What is the scope of variables in JavaScript?
I updated you Fiddle here: http://jsfiddle.net/LTYvq/3/

Related

How to execute jquery when a variable with a CSS property changes

I need to set the scrollleft back to 0 on my wrapper when a specific css property changes. I'm a bit new to jquery and have never used variables, but I'm assuming that I'll need to declare the somewhat complex variable before the function, and then execute the function when the variable changes. Am I correct? It needs to continually respond like this to resize queries. This will be an epic solution for me if it works!
var changer = $(".dummy").css("float"); //whatever the float property is
$(document).ready(){
$(window).resize(function(){
if ($(".dummy").css("float") != changer ){
$(".wrapper").scrollLeft(0);
}
});
here is my suggestion: Use an ID for "dummy", if you have more than one "dummy" in your dom-tree you get an array with html elements from jquery.
$(document).ready(function() {
// First init for "dummy"
var $dummy = $("#dummy"),
dummyFloat = $dummy.css("float");
$(window).resize(function () {
var dynamicDummyFloat = $dummy.css("float");
if (dynamicDummyFloat != dummyFloat) {
$(".wrapper").scrollLeft(0);
dummyFloat = dynamicDummyFloat;
}
});
});
The code that you have written will work fine.

javascript class killing app

just a quick one, im using a oop style for my javascript game but for some reason when i add in a new class it kills any functions from other classes i have included.
Here is the script i am talking about which is my main file which i will include all my class files in:
$(document).ready(function(){
var canvas = document.getElementById("TBG");
var context = canvas.getContext("2d");
var ui = new Gui();
// var level = new Level();
//----------Login/Register Gui --------------
$('#TBG').hide();
$('#load-new').hide();
$('#reg').hide();
$('#login').hide();
//if login_but is clicked do ui.login function
$('#login_but').click(ui.login);
//if reg_but is clicked do ui.register function
$('#reg_but').click(ui.register);
$('#new_but').click(function(){
game_settings("new");
});
$('#load_but').click(function(){
game_settings("load");
});
//if login_sumbit button is clicked do ui.login_ajax function
$("#login_submit").click(ui.login_ajax);
$("#reg_submit").click(ui.register_ajax);
$("#welcome").on("click", "#logout_but", ui.logout);
//___________________________________________________________________
//Initialisation of game
function game_settings(state){
if(state == "load"){
ui.load_game();
//do ajax call to load user last save
level.level_init(0,1);
}
else{
//set beginning params
//Change screens
ui.new_game();
alert("new game");
}
}
});
in the context of the script above, my problem is when i just have the call to new Gui() without the call to new level underneath or commented like you can see, well then all of the functions below under the heading login/register gui works perfectly, but as soon as i put the call to new level in or uncomment it, it kills all of the functions under the login/ register gui heading.
Why is this?
EDIT: here is the level.js file in case you would like to see it and how i am constructing my classes:
function Level(){
this.level_init = function(level, location){
var saved_level = level;
var saved_location = location;
};
this.get_tileset = function(){
};
this.draw = function() {
}
}
Thanks
Tom
SOrry guys, it turns out it was a silly mistake on my behalf i didnt add the script in html!, i need more sleep i think haha! thanks for your input
TOm

Set onCLick callback inside object?

I have a carousel object, with images and a pager. The problem is I can't set the onClick to the pager. I'm obviously missing something here but I don't know what.
The error when I click in a pager item is:
Uncaught TypeError: Object #<HTMLDivElement> has no method 'scrollCarouselTo'
I set my onclick
carouselDots.on('click',function(){
this.scrollCarouselTo(1,5); // <-- problem lies here, how can i call this method?
});
and the scrollTo method
this.scrollCarouselTo=function(dotIndex, numDots)
{
//H_SCROLL.scrollToElement("#carouselItem"+dotIndex, 300);
H_SCROLL.scrollToPage(dotIndex, 0 , 300);
this.highlightCarouselDot(dotIndex, numDots);
}
Last, on my HTML file this is how I set it:
var tempCarousel = new Carousel();
tempCarousel.initialize(params,cont,scrollContainer);
My Carousel class: (parts of it that i think are relevant)
function Carousel() {
var container;
var pager;
var opt;
var thisCarousel;
//render the correct number of dots and highlight the indexed one
this.highlightCarouselDot=function(dotIndex, numDots)
{
var ui_str="";
console.log("numDots" + numDots);
for (var i=0;i<numDots;i++)
{
if (i==dotIndex)
ui_str+='<div class="carouselDot selected" id="carouselDot'+i+'"></div>';
else
ui_str+='<div class="carouselDot" id="carouselDot'+i+'"></div>';
}
console.log(ui_str);
console.log(pager);
pager.html(ui_str);
var carouselDots = $(pager.selector + " .carouselDot");
var dotSelected = $(pager.selector + " .selected");
carouselDots.css('background',opt.pagerImage);
carouselDots.width(opt.pagerSize);
carouselDots.height(opt.pagerSize);
carouselDots.on('click',function(){ //replace with touch
this.scrollCarouselTo(0,5);
});
dotSelected.css('background',opt.pagerSelectedImage);
}
this.scrollCarouselTo=function(dotIndex, numDots)
{
//H_SCROLL.scrollToElement("#carouselItem"+dotIndex, 300);
H_SCROLL.scrollToPage(dotIndex, 0 , 300);
this.highlightCarouselDot(dotIndex, numDots);
}
}
Thank you!
You are having trouble understanding where the scope is changing in your code. Yes this refers to the object you are in, but when you assign an event handler such as onclick, that function is run in the scope of the UI element that was clicked. This means that in your onclick code, this refers to the html object that was clicked, and not the highlightCarouselDot object.
One common solution to this problem is to use an extra variable to store the value of this.
var self = this;
at the start of your object, that way you can refer to self within your event handlers when you want to refer to the outside object.

Need help related to EXT JS tooltip functionality

We are using EXTJS 3.1.0
There is a functionality where we have to add tooltip to an image, using code:
function loadToolTip(objImageId,entity_id,entity_type){
var objImage = document.getElementById(objImageId);
var tp = new Ext.ToolTip({
target: objImage,
autoLoad: {url: ‘some URL’},
showDelay:500
});
var extObjImage = Ext.get(objImageId);
tp.showAt([extObjImage.getX()+25,extObjImage.getY()+25]);
if(tp.anchorEl){
tp.anchorEl.hide();
}
}
This function is called on the mouseover event of a image.
It is possible that the user does mouseover on the image after changing some data and every time we have to get the tool-tip contents from the server.
The problem we are facing is, it creates multiple tool tips every time we do an mouse over.
Ideally we would want it to be displayed only once. We tried giving id to the tool tip object and then calling .destroy() method on that object when mouseout event occurs. This also does not work and at times gives JS error.
This or something similar should work for you:
function loadToolTip(objImageId,entity_id,entity_type){
var extObjImage = Ext.get(objImageId);
var tp = objImage.tp;
if(!tp)
{
var objImage = document.getElementById(objImageId);
tp = new Ext.ToolTip({
target: objImage,
autoLoad: {url: ‘some URL’},
showDelay:500
});
extObjImage.tp = tp;
}
tp.showAt([extObjImage.getX()+25,extObjImage.getY()+25]);
if(tp.anchorEl){
tp.anchorEl.hide();
}
}

How do i call a spcific jquery function form within another function?

I have the following code which is not working
jQuery
jQuery(window).bind("load", function() {
function effects(content_name,active_name)
{
// switch all tabs off
$(active_name).removeClass("active");
// switch this tab on
$(this).addClass("active");
// slide all content up
$(content_name).slideUp();
// slide this content up
var content_show = $(this).attr("title");
$("#"+content_show).slideDown();
}
$("a.tab_1").click(function () {
var content_name = '.content_a';
var active_name = 'a.tab_1.active';
effects(content_name,active_name);
});
$("a.tab_2").click(function () {
var content_name = '.content_b';
var active_name = 'a.tab_2.active';
effects(content_name,active_name);
});
$("a.tab_3").click(function () {
var content_name = '.content_c';
var active_name = 'a.tab_3.active';
effects(content_name,active_name);//create effects with the content
});
});
Its a set of tab groups upto 8 in number. Writing individual functions will have an adverse effect on loading time.
Answer 2 hours later:
Thank you all for pointing out the "effetcs" mistake in the code.
The other mistake was I was doing was not passing "$(this)" as a parameter into the called function "effects".
I Have adjoined the link where the necessary changes are done and the code works.
[jsfiddle] http://jsfiddle.net/phyGS/2/
Replace effetcs with effects at the first block, and replace every occurrence of
effects(content_name,active_name);
with
effects.call(this, content_name, active_name);
This call method assigns a new value to the this property of function effects.

Categories