Help on binding mouseover with jquery.

Teensweb

New Member
Messages
352
Reaction score
1
Points
0
Alright, the problem I face now is simple and silly: I need to make some elements show up when another element is hovered, well this is simple, to understand where my problem arises, take a look at the below code:
Code:
function builder(){
....
$(myelement).bind('mouseenter',function(){el.slideout()});
....
}
Here, slideout() is a well defined custom function for a class of which el is a member.
Now, the problem is, the function builder is called everytime another parent and child system is built, so the el (which is a global variable) changes on each call of the function which means I lose the link between my previous parent and child. Is there any possible way to overcome this problem?
I guess(but I am not sure) that the problem can be solved if el is declared as a local variable of builder() but then, how would I access that variable inside the function(){} in the bind?
 

descalzo

Grim Squeaker
Community Support
Messages
9,373
Reaction score
326
Points
83
Insufficient information to make a meaningful suggestion.
 

Teensweb

New Member
Messages
352
Reaction score
1
Points
0
I'll elaborate- el is an object and I want to access one its member functions(namely slideout) from the function(){} block in my above code.
I thought I could overcome the problem by assigning el to a global variable but since el changes everytime the parent function is called, the glocal changes too,so I can't attach a establish relation between an element and its parent.
 
Last edited:

Teensweb

New Member
Messages
352
Reaction score
1
Points
0
Oh thanx, I worked it out using a closure but is it the only way to work around the prob?
 

Teensweb

New Member
Messages
352
Reaction score
1
Points
0
BTW, can someone tell me how to bind an event to multiple objects through a for loop?
At first I tried going simple like:
Code:
function somefunc(){
var id;
for(i=0;i<10;i++)
$("#"+id+i).bind('mouseleave', function(){});
}
And after realizing that the bind worked only for the last element of the loop(which obviously is not what I want), I changed it to
Code:
function mbind(sId){
  return function(){
  $("#"+sId).bind('mouseleave', function(){});}
}
function somefunc(){
var id;
for(i=0;i<10;i++)
(mbind(id+i))();  
}
expecting it would now work for all elements in the loop, but hell no!
Can anyone help me with this?:frown:
 
Last edited:

descalzo

Grim Squeaker
Community Support
Messages
9,373
Reaction score
326
Points
83
The value of id is undefined in both cases.
 

Teensweb

New Member
Messages
352
Reaction score
1
Points
0
Come on dude, don't be so obtuse! Do you really think that I would play with an undefined variable to make such a fuss? I skipped the defining part there since that's not where my problem arises. What I am still asking is: how to bind the event to all elements on the loop?
 
Last edited:

descalzo

Grim Squeaker
Community Support
Messages
9,373
Reaction score
326
Points
83
Dude, if you don't post your complete code, nobody can tell where you are going wrong.
 

Teensweb

New Member
Messages
352
Reaction score
1
Points
0
Alright then consider that the statement: var id;
is replaced by: var id="sl_";
in both of my above code blocks.
 

descalzo

Grim Squeaker
Community Support
Messages
9,373
Reaction score
326
Points
83
Ok. You don't want to post your entire code. I get it.
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
Oh thanx, I worked it out using a closure but is it the only way to work around the prob?
It's the proper and simplest way to fix the problem. Why would you want another?

BTW, can someone tell me how to bind an event to multiple objects through a for loop?
Rather than binding a listener to each element separately, bind it to all at once by using an appropriate selector in the jQuery call. If no such selector exists, give the elements a class and then use the class as the selector. If some elements might not exist at the time you add the listener, use live rather than bind.
Code:
function someFunc() {
    function leaveit(evt) {...}
    
    $(".foo").mouseleave(leaveit);
    /* to add leaveit to future .foo elements: */
    //$(".foo").live('mouseleave', leavit);
}

Posted code can be a sample rather than the actual code (sample code is preferred over actual code, as actual code includes to much extraneous code), but sample code should be complete so it can be tested. See links in my sig for more (especially Jon Skeet's post).
 
Last edited:

Teensweb

New Member
Messages
352
Reaction score
1
Points
0
@misson: But my objects already belong to another class and I still don't want all the members of that class to have the same funtion bound to the mouseleave. So are you suggesting that there is no way to bind the functions one by one?
It's the proper and simplest way to fix the problem. Why would you want another?
Just to expand my knowledge(assuming that there is another method, if not- forget it)
 
Last edited:

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
@misson: But my objects already belong to another class and I still don't want all the members of that class to have the same funtion bound to the mouseleave.
Elements can have as many classes as you wish. The only limit I'm aware of is the 65536 character limit for attributes in HTML4. HTML5 has no such limit set by the standard (though, due to memory limits, browsers may impose their own).

So are you suggesting that there is no way to bind the functions one by one?
The listener could be bound to each element separately, but it will be more work than doing it in a group. You also haven't shown a complete enough sample to say why your code isn't working.

Just to expand my knowledge(assuming that there is another method, if not- forget it)
There isn't enough code to say for sure. You might be able to use the event object passed to the listener, or some data structure that you can look up the appropriate element. The latter gains you nothing, is more work, uses a global and may still require a closure to hold whatever key you use to look-up the element.
 
Last edited:

Teensweb

New Member
Messages
352
Reaction score
1
Points
0
You also haven't shown a complete enough sample to say why your code isn't working.
So does that mean that the sample I posted should work?
Can you also explain what my code sample lacks in order to provide sufficient info?
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
So does that mean that the sample I posted should work?
No, it's incomplete so it's untestable, and it will fail for reasons other than the full code might be failing. In this particular case, it's not worth trying to get your original approach to work. Just add an additional class to the elements. It's cleaner and simpler and will take less time to implement.

Can you also explain what my code sample lacks in order to provide sufficient info?
Follow the advice in my sig and follow the links in previous posts.
 
Last edited:

Teensweb

New Member
Messages
352
Reaction score
1
Points
0
Well, the binding trouble does not seem to occur when I try a fresh new page and write a loop to bind an event to each elements one by one, so I guess I'll have to post my entire code, its small BTW: can you please see my sample page at:http://firebolt.co.cc/prototype
Well this was my first approach to building the menu, the problem is that the menu does not hide but the second menu(displayed when item2 is hovered) does hide if the last sub item is hovered and then left.
But I finally overcame most problems by changing my approach slightly and ended up with : http://firebolt.co.cc/final/
But I still can't understand why my previous model does not work, it may have some other flaws, but I can't figure out why the mouseleave event does not work for all elements.:confused:
 

vv.bbcc19

Community Advocate
Community Support
Messages
1,524
Reaction score
92
Points
48
Oh thanx, I worked it out using a closure but is it the only way to work around the prob?
NOt particularly
But it is the easiest and straight forward way to implement what you needed.
But be careful..there are traps.
Read this to know closures better..
 

misson

Community Paragon
Community Support
Messages
2,572
Reaction score
72
Points
48
BTW: can you please see my sample page at:http://firebolt.co.cc/prototype
It would be helpful if you would point out which script contains the problematic code. In this case, I guessed "menu.js", but it may not always be so obvious. Remember, there's good lazy (getting the computer to do your work) and bad lazy (making others do work you could easily do). Anytime you make someone else guess, you're being bad lazy.

But I still can't understand why my previous model does not work, it may have some other flaws, but I can't figure out why the mouseleave event does not work for all elements.:confused:

Right at the top of menu.js:
Code:
var el;
function mbind(sId){
  return function(){
    $("#"+sId).bind('mouseleave', function(){setTimeout(slidein(el), 500)});
  }
}
el is a global variable in mbind. The issue is still the same as when descalzo first responded. There are other variables (e.g. pID, x) needlessly defined as globals simply because they lack a var keyword to declare them as locals.

A select few issues with/improvements for the newer implementation:
Code:
... onmouseover="this.className=\'slider_active\'" ...
... onmouseout="this.parentNode.className=\'slider\'" onmouseover="$(this.parentNode).mouseover()" ...
...
if(obj.state&&obj.slideobj.className!="slider_active"){

You don't need to replace element classes. Use jQuery's class manipulation methods.

There are too many magic numbers in the source (such as the slide states). Give them names.

The source could also use better indentation to make it more readable.

Read this to know closures better..
That link is to an article about Google's Closure library, not about function closures, either in JS or in general. The most extensive article on closures I've seen is the comp.lang.javascript FAQ note on closures.

Using "read this" as link text is almost as bad as "click here". Link phrases should be nouns, and should be descriptive. Each link is a vote tying the phrase to the page, so pick your phrase carefully.
 

Teensweb

New Member
Messages
352
Reaction score
1
Points
0
In this case, I guessed "menu.js", but it may not always be so obvious.
I thought that was too obvious to require explicit statement as there were only three js files on my page and two of them were the jquery and its ui repectively, and no one here expect that I wrote both of them too, right?
I'm not being rude here, I know that I have no right to be-maybe I'm just a lazy little boy,bad lazy-in your words. Anyway, guys like you here help me a lot, and 'm thankful to that; so I'll follow your advice and make the info as explicit as possible in future.
el is a global variable in mbind. The issue is still the same as when descalzo first responded. There are other variables (e.g. pID, x) needlessly defined as globals simply because they lack a var keyword to declare them as locals.
My bad, thanks for pointing out.
So then in order to avoid the global, if I replace the call to mbind by:
Code:
$("#"+tp).bind('mouseleave', slidein(this));
It still produces the same result. Can you explain what is the correct method and what I'm doing wrong? I know adding a class as you said is better, but I wanna know why my code fails.
You don't need to replace element classes
Is there any disadvantage with that?
There are too many magic numbers in the source (such as the slide states)
I LOVE numbers, whats wrong with them?
I'll make it more readable as you said...
And last thing:
Using "read this" as link text is almost as bad as "click here". Link phrases should be nouns, and should be descriptive. Each link is a vote tying the phrase to the page, so pick your phrase carefully.
You're some sort of a perfectionist ain't you? Well, personally I like being one at times, but you are way ahead.:)
 
Last edited:
Top