Jump to content

Help Porting Javascript Function Into Jquery


chibineku

Recommended Posts

I'm basically on day one of learning jQuery and wanted to see if I could adapt a JavaScript function I have for pull down menus into jQuery. I am not getting on well, however. Here is the original function:

 var getEls = document.getElementById("menu").getElementsByTagName("LI"); var getAgn = getEls; for (var i=0; i<getEls.length; i++) { getEls[i].onclick=function() { for (var x=0; x<getAgn.length; x++) { getAgn[x].className=getAgn[x].className.replace("unclick", ""); getAgn[x].className=getAgn[x].className.replace("click", "unclick"); } if ((this.className.indexOf('unclick'))!=-1) { this.className=this.className.replace("unclick", "");; } else { this.className+=" click"; } } } }

I made an okay start on turning it into jQuery, with these lines:

$(document).ready(function() {  $('#menu > li').click(function() {	 $('#menu >li > ul').toggleClass('unclick');  });});

But that is as far as I got. However, when you watch in Firebug what is happening to the classes, only the last top-level list item with a nested ul is subject to this style swapping. I am out of my depths already. Using `this` is even more complicated than usual in jQuery, so attaching the click handler to the clicked element is tricky. Any guidance? I know not many people here use jQuery, but there have to be a couple, right?Okay, I have swapped $('#menu > li > ul') for $(this) (I was stupidly putting this in quotes before and that works, but the next line,$(this).className.replace("click","unclick") doesn't work. Teency progress. I guess jQuery has different methods for className.replace(), perhaps just using toggle? I will try, but so far its not that much sleeker than regular JS...

Link to comment
Share on other sites

\/ \/ \/ Please see below \/ \/ \/

Link to comment
Share on other sites

Okay, I have this now:

$(document).ready(function() {  $('#menu > li').click(function() {	if(event.target == this) {	 $(this '> ul').toggleClass('unclick');	 $(this '> ul').removeClass('click').end().addClass('unclick');	}	 });});

I get a Firebug error alert:missing ) after argument list[break on this error] $(this '> ul').toggleClass('unclick');\nBut it looks fine to me, and it worked without the if(event.target == this) { } test (although the behaviour was not the required behaviour, hence the addition of this test).

Link to comment
Share on other sites

ne1? pweeese?

Link to comment
Share on other sites

It doesn't look right, but if you take out the event.target test clause, it actually works - it picks the right element. You can watch the classes being added and removed in Firebug and it works the same as the original script. It looks like it might need some other syntax or form of concatenation. But if it ain't broke...

Link to comment
Share on other sites

Yeah, that's not valid Javascript syntax. There's an identifier followed by a string value, there needs to be some sort of operator there in order for it to parse correctly. They would have had to override this to make it a unary operator instead of an identifier, I don't think it's possible to redefine Javascript like that.

Link to comment
Share on other sites

Well, it is being passed as a parameter to a function, you could regex or otherwise the parameter and do the concatenation first. However, it doesn't work. This should have been really easy, lol.

Link to comment
Share on other sites

Well, it is being passed as a parameter to a function
What's being passed? One value? Two values? See if this works:alert(document 'test');That's the same thing, an object followed by a string, with no operator between them. It doesn't even make sense to concatenate those, it doesn't make sense to concatenate an object with a string. If you do that it will cast the object as a string and just print that. e.g., this:alert(document + 'test');shows this:[object HTMLDocument]test
Link to comment
Share on other sites

i've just tried this in a slide down menu and it works with no error (this ul) forget it! does it not work. i use a different colour for dropdown each menu, so i use different class for the ul, so obviously i can access these direct by using ("ul.classname") when you hover over link

Link to comment
Share on other sites

ds: that doesn't seem to work unfortunately.JSG: I take your point, but for the sake of argument, imagine I created a function like this:function concatenate(string) {stringArray = string.split(".",string);concatenatedString = stringArray[0]+stringArray[1];return concatenatedString;}If you call it like this:concatenate("bob.hope");it will return bobhope. It is possible, surely, to find out to what 'this' refers, recreate the DOM selector and append '> ul'. It is if you are facetious enough, anyway :) However, when I said it worked, I had made a mistake, as is my wont, and was looking at the wrong page.

Link to comment
Share on other sites

concatenate("bob.hope");
Right, you're only sending one value to the function. The other way, it had 2 values in the parameter list, but they weren't separated by a comma. A comma is required to send a list of values, so you could separate those with a comma and then inside the function determine the DOM selector for the passed object and concatenate it to the other argument. Strictly speaking about syntax, these are correct:alert(document + 'test');alert(document, 'test');but not this:alert(document 'test');I don't use jQuery, so I'm mainly just talking about syntax here, but pass your object to the Firebug console and see if jQuery already gave it a DOM selector, jQuery might have modified the object constructor to include a property on each object that has the selector for it. You might be able to use the ID also, e.g.:$('#' + this.id + ' > ul')
Link to comment
Share on other sites

Trying to evaluate anything starting with $ or jquery gets an error: '$ is not defined' or 'jquery is not defined'. I can't make it evaluate any expressions using the jquery library because, for the error console, it doesn't exist. Is there a way to evaluate expressions in Firebug without using the error console, or in a way that utilizes the functions I have defined?

Link to comment
Share on other sites

That's weird, it should be able to find that. I can use ExtJS functions in the error console, for example. Maybe just add a line to write that from the regular code:

$(document).ready(function() {  $('#menu > li').click(function() {	if(event.target == this) {	  console.log(this);	}	 });});

Link to comment
Share on other sites

1) that's awesome, I didn't know you could do that2) it says 'event is not defined'...This works:

$(document).ready(function() {	$('#menu2')[0].style.display="none";  $('#menu')[0].style.display="block";  $('#menu > li').click(function() {	if(this == $('#menu > li')[1]) {	  alert("this");	}	 });});

Ignore the first two statements, they just swap the visibility of the regular and javascript menus. The problem with this is, it only works if I use the correct index. I don't want to start doing for loops, because that defeats the purpose of trying to use jQuery for this - it's meant to be simpler (eventually).

Link to comment
Share on other sites

how about this:$(document).ready(function(){ $("#menu li").click(function(){ $(this).find("ul").toggleClass('unclick').toggleClass('click'); });} );based roughly on you website<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /><title>Untitled Document</title><script type="text/javascript" src="jquery-1.3.2.js"></script><script type="text/javascript">/*<![CDATA[*//*---->*/$(document).ready(function(){ $("#menu li").click(function(){ $(this).find("ul").toggleClass('unclick').toggleClass('click'); });} );/*--*//*]]>*/</script> <style type="text/css">.click{background-color:#CC66FF; display:block;}.unclick{background-color:#FFCC33; display:none;}</style></head><body><ul id="menu"><li class="">topdaddy<ul class="sub unclick"><li>bbbbbbbb</li><li>cccccccc</li><li>dddddddd</li></ul></li><li class="">topdaddy2<ul class="sub unclick"><li>eeeeeeeeeee</li><li>fffffffffffff</li><li>gggggggggg</li></ul></li></ul></body></html>

Link to comment
Share on other sites

if you wish to use sublevel 2 i had to use anchor for parent level, but i'm sure theres a workaround for this, just require correct jquery selector?anyway<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /><title>Untitled Document</title><script type="text/javascript" src="jquery-1.3.2.js"></script><script type="text/javascript">/*<![CDATA[*//*---->*/$(document).ready(function(){ $("#menu li.topdaddy a").click(function(){ $(this).next("ul").toggleClass('unclick').toggleClass('click'); });} );/*--*//*]]>*/</script> <style type="text/css">ul{list-style:none;float: left; padding: 0; margin: 0;cursor:pointer; }ul ul { border:1px solid #000;} ul#menu li {float: left; width:150px; position:relative;}ul#menu li a {float: left; display:block; height:26px; width:150px; border:1px solid #360; background-color:#0066CC; text-align:center;}#menu li li { float: left; padding: 0; width: 150px; height:26px; text-indent: 7px;}ul#menu li li a { border:none; background-color:#cc66ff; text-align:left; text-indent: 7px;}.click{background-color:#CC66FF; display:block;}#menu ul ul.click{background-color:#00FF00; display:block; position:absolute; left: 10px; top:23px; z-index: 99;}.unclick{background-color:#FFCC33; display:none;}</style></head><body><ul id="menu"><li class="topdaddy"><a>topdaddy</a><ul class="sub unclick"><li>bbbbbbbb</li><li class="topdaddy"><a>topdaddy1sub</a><ul class="sub unclick"><li>eeeeeeeeeee</li><li>fffffffffffff</li><li>gggggggggg</li></ul></li><li>cccccccc</li><li>dddddddd</li></ul></li><li class="topdaddy"><a>topdaddy2</a><ul class="sub unclick"><li>eeeeeeeeeee</li><li>fffffffffffff</li><li>gggggggggg</li></ul></li></ul></body></html>

Link to comment
Share on other sites

Dude, soo close - the only modification I had to make was between toggling the two classes, you have to return to the current object using end(), which gives this:

$(document).ready(function() {  $('#menu2')[0].style.display="none";  $('#menu')[0].style.display="block";  $("#menu li").click(function(){	$(this).find("ul").toggleClass('unclick').end().toggleClass('click');	});	});

Which works! Thanks so much. I like when learning experiences don't go too easy, but this was harder than it should've been. As for sub-level menu items, I will give that a go, though I don't need them for my current project.Thanks again, guys - I really appreciate the help, even from JSG who doesn't even use jQuery!

Link to comment
Share on other sites

I was skeptical at first, but it really simplifies your interaction with the DOM and generally shortens your code. Obviously you need to include the library, which is something like 20kb, but that only needs to load once per session. Its a laugh that I say it simplifies things, given how much work this menu was, but I think it'll be easier to learn than JavaScript and once mastered, it offers a great deal of powerful methods, and plugin libraries too. I am most looking forward to playing with the AJAX methods - one word and a couple of parameters to create an XMLHTTPRequest object, send your headers and get the response text! I know I could do it myself, but it's faster to DL jQuery than it is to roll my own. Given that I only use JavaScript for non-essential glitz and never as a stand-alone way of delivering functionality, I don't feel bad about cheating and not necessarily understanding how each function works. That said, you can DL the developer version of jQuery with very detailed comments for each function - practically each line - so you can learn as much as you like, and tweak where needed if you have the necessary skill level.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...