Jump to content

Any jQuery wizards here?


End User

Recommended Posts

I've decided to go over to the Dark Side and learn jQuery :) and I'm wondering if anyone here is familiar with it or (hopefully) skilled at using it. I have a few basic things/concepts I'm trying to wrap my head around and would like put a couple of questions to someone who really understands it.

Link to comment
Share on other sites

Well first of all, jQuery isn't the Dark Side. I use jQuery quite a bit but knowing regular Javascript is really important for understanding jQuery. Also, using simple JS can be more effective for performance than calling a jQuery function. jQuery is great for simplifying some tasks that would be quite a lot of work in regular JS like creating animation effects. Anyways, what are your questions?

Link to comment
Share on other sites

Well first of all, jQuery isn't the Dark Side.
I was kidding, but I guess I need to polish up my delivery. (As my wife would say, "It's like a joke, only smaller.")
I use jQuery quite a bit but knowing regular Javascript is really important for understanding jQuery. Also, using simple JS can be more effective for performance than calling a jQuery function. jQuery is great for simplifying some tasks that would be quite a lot of work in regular JS like creating animation effects.
In the past I've always used a collection of special-purpose JS snippets, one for table sorting, one for fiddling with opacity, another as a tiny AJAX library that I hacked into shape, etc etc. I liked the tiny footprint of the code and the ability to get under the hood and tinker (and being able to understand exactly what was going on). Lately, though, it seems to be more trouble than it's worth- occasionally the pieces don't want to play well together or IE changes subtly and a lot of stuff suddenly just stops working. So I decided to just go with the flow and learn one of the utility libraries. After a bit of research I picked jQuery (it seems to have good support, lots of pre-made plugins, wide acceptance, etc). In a lot of my applications performance (speed) isn't a critical factor- I just need to be able to make things happen reliably and predictably. Which brings me to the next part...
Anyways, what are your questions?
At this point I'm not even sure I know what questions to ask, lol. I've gotten a couple of books on jQuery and started plowing through them, but they've left out some pretty basic stuff (maybe it's supposed to be obvious, I don't know). Anyway, here are a couple of Grade-A newbie questions:1) It looks like *everything* is supposed to go inside the $(document).ready(function(). Is that correct? That is,
$(document).ready(function()// loads and loads of jQuery and regular javascript code here...});// here be dragons, no js code

Can functions inside the doc.ready() function be called from outside by plain old JS? Can functions inside the doc.ready() function call JS that's outside the doc.ready() function?Will regular JS returned in an AJAX statement run normally? I ask because there seems to be a lot of talk about use of the live() binding function or statement to have jquery recognize stuff that is added to the page as a result of an AJAX call (like links that are supposed to trigger jquery functions). In the same vein, a question regarding jQuery recognizing classes on html that is returned via AJAX: I have a page that upon start up, calls several JQ functions to load a couple of divs, the HTML that comes back contain links that are supposed to activate further jQuery actions when clicked on. To make this work I've had to use ".live('click', function()" to have the links recognized. Is this the way it's supposed to work, or am I doing something wrong? For example, my page loads, the startup functions are called and a div gets some html stuffed into it (via an AJAX call) that contains something like this:

<div id='folders'><a class="fldr" href="1"><div>Folder #1</div></a><a class="fldr" href="2"><div>Folder #2</div></a><a class="fldr" href="3"><div>Folder #3</div></a><a class="fldr" href="4"><div>Folder #4</div></a><a class="fldr" href="5"><div>Folder #5</div></a></div>

These are just divs that serve as clickable links to navigate among the various folders. I've found that I have to use the code below in order to keep the 'fldr' class able to be "seen" by jquery:

$('.fldr').live('click', function() {	showFolder($(this).attr("href"));	return false; });

If I don't do this then I can't seem to select onto the "fldr" class and trigger anything. Is that the way it's supposed to work or have I missed the plot?I thank you for your patience reading through all this, and for any enlightenment you can throw my way. I've actually managed to get some stuff working, but mostly by trial and error at this point. I couldn't swear that I have any idea what I'm doing (yet).

Link to comment
Share on other sites

Don't bother with jQuery if your JS skills are not on par. In the end you will just be confused and use jQuery for every little thing that normal JavaScript can do better as big dave said. jQuery is a helpful library that can make cross browser writing easier. Yet I only really use it for effects and getElementsByClassName.$(document).ready(function()// loads and loads of jQuery and regular javascript code here...});You put your jQuery in here and it will run as the page loads. Normal Javascript runs AFTER images load on a page this lets you run the code before the images are loaded.I haven't really played with it much but I think no jQuery can run on its own without being in another function or inside .ready(). [?]>Can functions inside the doc.ready() function be called from outside by plain old JS?>Can functions inside the doc.ready() function call JS that's outside the doc.ready() function?Why would you want to define a function inside of a event?>If I don't do this then I can't seem to select onto the "fldr" class and trigger anything. Is that the way it's supposed to work or have I missed the plot?Did you put your code in .ready()?

Link to comment
Share on other sites

Don't bother with jQuery if your JS skills are not on par.
My JS skills are on par for working with jQuery, I'm just new to it so I have some basic questions.
...but I think no jQuery can run on its own without being in another function or inside .ready(). [?]
That's more or less the conclusion I've come to, although none of the books state it explicitly. It's implied in a few places but they don't really lay it out clearly.
>Can functions inside the doc.ready() function be called from outside by plain old JS?>Can functions inside the doc.ready() function call JS that's outside the doc.ready() function?Why would you want to define a function inside of a event?
I don't; I'm asking if functions can call each other across the jQuery "boundary", for want of a better word. In other words, can I have plaon old javascript call JQ functions (which all appear to be inside the doc.ready() body)?
>If I don't do this then I can't seem to select onto the "fldr" class and trigger anything. Is that the way it's supposed to work or have I missed the plot?Did you put your code in .ready()?
Yes, that's where the functions I'm using reside. If I understand the whole JQ paradigm correctly, elements (like links) added to the page after the initial page load have to be re-bound by using live(). At least that's the only way I've been able to get them to activate JQ functions. And that's why I asked if this is normal or if I'm missing something along the way. I'm not sure if elements added by JQ itself undergo binding automatically or not, but that's not what I'm doing at this point. I'm simply making an AJAX call, getting the HTML back (with links in it) and then doing something like $('#maincont').html(data); to put the returned HTML into a div. Unless I use live() they don't appear to be able to access the JQ functions. In short, a lot of what I'm doing seems to be working, but I wonder if someone who's jQuery-savvy would look at my code and go "Ack! That's not the way you're supposed to do it."
Link to comment
Share on other sites

Sounds like you're asking a lot of the same questions I asked when I started using jQuery. The important thing to note is that jQuery uses an unobtrusive JS approach, meaning you separate your behavior code from your presentation code (html and css). So instead of having event handlers in all your html tags that call JS functions, you just bind events and handlers to particular objects within document.ready(). If you dont bind a particular event, the code will execute once the document is ready.

I don't; I'm asking if functions can call each other across the jQuery "boundary", for want of a better word. In other words, can I have plaon old javascript call JQ functions (which all appear to be inside the doc.ready() body)?
You can't call a jQuery function on a regular JS object. For example, you can't do the following:
document.getElementById('myid').fadeIn(200);

To use jQuery functions like fadeIn(), you need to retrieve the element and turn it into a jQuery object before you can apply jQuery methods. Thus you would have to do:

$('#myid').fadeIn(200);

Yes, that's where the functions I'm using reside. If I understand the whole JQ paradigm correctly, elements (like links) added to the page after the initial page load have to be re-bound by using live(). At least that's the only way I've been able to get them to activate JQ functions. And that's why I asked if this is normal or if I'm missing something along the way.
Yes that is correct.
Link to comment
Share on other sites

The important thing to note is that jQuery uses an unobtrusive JS approach ... instead of having event handlers in all your html tags that call JS functions, you just bind events and handlers to particular objects within document.ready(). If you dont bind a particular event, the code will execute once the document is ready.
Geez, if only they put what you just wrote at the front of the jQuery books it would save everyone a boatload of time and trouble. You said in a couple of lines what 400 pages of my first jQuery book never quite got around to explicitly stating. Thank you. I'd sort of come to the same conclusion, but I wasn't absolutely certain. (The first book I've got isn't bad, but they do leave out some key stuff that would be nice to have examples of. It's "JQUERY: Novice to Ninja", published by Sitepoint. In spite of its shortcomings, I'd definitely recommend it as a beginner book.) Okay, so you have to write code to bind or select everything ahead of time that you want to use. Elements in the HTML that you don't bind just sit there. Am I right so far?Code that doesn't bind to anything in the doc.ready() runs as soon as doc.ready() executes. Correct? And *all* the jQuery -all of it- code goes in the doc.ready() function, right?(I understand you can also insert and bind stuff on the fly, but I haven't gotten that far yet.)
You can't call a jQuery function on a regular JS object. For example, you can't do the following:
document.getElementById('myid').fadeIn(200);

To use jQuery functions like fadeIn(), you need to retrieve the element and turn it into a jQuery object before you can apply jQuery methods. Thus you would have to do:

$('#myid').fadeIn(200);

Okay, I think I got that now...the key word being "before", correct? I know you can target any element by putting the selector on it, but I guess that's my next question. Lets say I have a div in the page with the id "foo". I haven't written any code to do anything with "foo" and it's not referenced anywhere in any code, it's just sitting in the page. How would I turn that div into an object I can act on, like turn it into a clickable link (that is, something that would be able to activate a function)? I know you can access it and fiddle with its properties and contents (color, test, size, etc), but how would I turn it into an actionable link, for example? Through the live() function?
Link to comment
Share on other sites

Code that doesn't bind to anything in the doc.ready() runs as soon as doc.ready() executes. Correct?
Correct
Lets say I have a div in the page with the id "foo". I haven't written any code to do anything with "foo" and it's not referenced anywhere in any code, it's just sitting in the page. How would I turn that div into an object I can act on, like turn it into a clickable link (that is, something that would be able to activate a function)?
$(document).ready(function(){   $('#foo').click(function(){	  //code you want to execute when you click div#foo   });});

OR

$(document).ready(function(){   $('#foo').bind('click', function(){	  //code you want to execute when you click div#foo   });});

Both do the same thing. The first way is just a shorthand way of the 2nd. If you notice, every event you pass it a function. When the document was ready, we passed a function to the ready event. We passed another function to the click event.

Link to comment
Share on other sites

Thank you. Just a few more questions for the moment if you'll bear with me. :)1) I do an AJAX call that returns a blob of HTML with some select lists in it. I'm guessing that before I can set the value of the dropdowns with jquery that I would need to bind the controls. Or, can they be accessed directly by regular javascript commands, i.e. document.getElementById('some_select_box').value = 'something' ? 2) If the HTML that's returned contains javascript, will the javascript run without needing to do anything? Normally javascript returned via AJAX won't run because the page doesn't "know" it's there. Does jQuery allow the returned javascript to be recognized and run, or...? If not, is there a way to 'wake it up' so the returned javascript will run?And finally, I'm trying to figure out what the best way to implement a simple menu set is. For example, my page contains a half-dozen links that should each load a different page via AJAX (i.e. settings, folders, contacts, etc). I'd like to write a single function to catch some element (perhaps the href or id) and have the function determine what page to load instead of crafting a function for each menu item. Is there a generally accepted way to do this? I figured I could give the links all the same class so they could be accessed as a group, use .attr to get the id or href value, and then give that to the function to do the steering...but maybe there's a more logical or sensible way to do it. I want to avoid reinventing the wheel if possible. Does this way make sense, or is there a better way to do this?

Link to comment
Share on other sites

1) I do an AJAX call that returns a blob of HTML with some select lists in it. I'm guessing that before I can set the value of the dropdowns with jquery that I would need to bind the controls. Or, can they be accessed directly by regular javascript commands, i.e. document.getElementById('some_select_box').value = 'something' ?
I'm pretty sure you can access it directly with regular JS using document.getElementById() since those returned elements are now in the DOM. Someone correct me if I am wrong.
2) If the HTML that's returned contains javascript, will the javascript run without needing to do anything? Normally javascript returned via AJAX won't run because the page doesn't "know" it's there. Does jQuery allow the returned javascript to be recognized and run, or...? If not, is there a way to 'wake it up' so the returned javascript will run?
I've actually had trouble doing this in the past. It's probably best to just keep an external JS file referenced in the head of your document and put all your JS there.
And finally, I'm trying to figure out what the best way to implement a simple menu set is. For example, my page contains a half-dozen links that should each load a different page via AJAX (i.e. settings, folders, contacts, etc). I'd like to write a single function to catch some element (perhaps the href or id) and have the function determine what page to load instead of crafting a function for each menu item. Is there a generally accepted way to do this? I figured I could give the links all the same class so they could be accessed as a group, use .attr to get the id or href value, and then give that to the function to do the steering...but maybe there's a more logical or sensible way to do it. I want to avoid reinventing the wheel if possible. Does this way make sense, or is there a better way to do this?
I'd probably also use the id or href of the anchor tag to pass to your server side script to do the steering. Also, just wanted to mention that jQuery allows you to bind data to any element using the .data() method, but that wouldn't make sense here because you'd have to write some code to bind data to each link. But it's a worthy function to be aware of so you don't have to use global variables.
Link to comment
Share on other sites

I'm making some headway here, thanks to your replies. :)Happy Note: It seems that javascript returned by a jQuery AJAX call does seem to run without having to do anything else. My simple test case just pops an alert(), but it works. This is a huge plus. Next step/question: my HTML blob that's returned by the jQuery AJAX call has a set of save buttons. Originally these buttons called a javascript function which in turn made an AJAX request. To change this so it uses jQuery, I'm guessing that I need to call a similar function that I'll put within the jQuery doc.ready() blockHere's some example content from the HTML blob:

<img name='img_$folder_id' id='img_5' src='$folder_icon'><input type='button' id='btn5' class='fldrsave' value='Save' onclick='saveFolderIcon("$folder_id", "mg_$folder_id");'>

I currently have this in the doc.ready() block, and it pops the 'test' alert prompt when I click any of the "Save" buttons:

$('.fldrsave').live('click', function(){  alert('test');});

How do I transfer the "$folder_id" and "mg_$folder_id" parameters to the function?

Link to comment
Share on other sites

Well the way you are doing it, you arent even running the function saveFolderIcon() since it doesn't exist, and you can remove the event handler for it.

onclick='saveFolderIcon("$folder_id", "mg_$folder_id");'

You are triggering the alert by the fact that your button has a class of fldrsave and you are binding a function to all elements with this class. Using unobtrusive JS like this, you can't pass parameters to the function you have. To solve this, since these parameters are dynamic, the way I've done this in the past is by having some elements nearby that hold these values such as hidden spans or hidden inputs, and using jquery methods to select these elements. jquery offers methods that allow you to find elements in relation to the current one you have, such as parent(), siblings(), prev(), next(), etc. This will make your jquery code more complicated, but it wont require you to have any event handler inside your submit button.The alternative would be to just keep the event handler you have, and create a function called saveFolderIcon(), and make your jquery ajax call in there. For example,

function saveFolderIcon(arg1, arg2) {   //make your jquery ajax call in here   $.ajax()}

This approach would probably be more familiar and straightforward to you since you're just starting out with jquery.

Link to comment
Share on other sites

Ahhh, okay. Makes sense. Thank you. I found a couple of suggested techniques on the web, one of which was to attach all the params to the id, broken up by dashes:id="name-john-city-fresno"That seems...sleazy, lol, and I can see all kinds of situations where that would have problems (like if the data had a dash in it). I'm not sure what the max length is for an id but I would imagine that might also cause trouble. Another similar suggestion was to use the "rel" attribute in the same way. It supposedly has no inherent length limit, but again, it seems like a clumsy way to do things. I like the hidden field approach you described; it's clean and logical. Calling a ".ajax" function in the original javascript is a nice alternative, but I think I'm going to go with the hidden field. It makes more sense in several ways, and also allows the data to be retrieved for other purposes as well.

Well the way you are doing it, you arent even running the function saveFolderIcon() since it doesn't exist, and you can remove the event handler for it.
onclick='saveFolderIcon("$folder_id", "mg_$folder_id");'

You are triggering the alert by the fact that your button has a class of fldrsave and you are binding a function to all elements with this class. Using unobtrusive JS like this, you can't pass parameters to the function you have. To solve this, since these parameters are dynamic, the way I've done this in the past is by having some elements nearby that hold these values such as hidden spans or hidden inputs, and using jquery methods to select these elements. jquery offers methods that allow you to find elements in relation to the current one you have, such as parent(), siblings(), prev(), next(), etc. This will make your jquery code more complicated, but it wont require you to have any event handler inside your submit button.The alternative would be to just keep the event handler you have, and create a function called saveFolderIcon(), and make your jquery ajax call in there. For example,

function saveFolderIcon(arg1, arg2) {   //make your jquery ajax call in here   $.ajax()}

This approach would probably be more familiar and straightforward to you since you're just starting out with jquery.

Link to comment
Share on other sites

Some more newbie questions....I found this comment on a page and it raised some questions for me:"You can have as many document.ready() functions as you need on one page, and they will be called in succession."Is it common or normal to have more than one doc.ready() function? At the moment I have only one, based on all the examples shown in the various books I'm plowing through, and all my code is inside of it. Is that wrong, or...? Do I *need* multiple doc.ready() functions, and if so, what would be a typical case or reason for having more than one?Also, (lol) I'm not sure I'm totally clear on calling function...functions that I declare within the doc.ready() block can be called from within the doc.ready() block. How do I call a function in the doc.ready() block from outside, i.e. from some external javascript?For example, I have this code that is partially working in some external javascript, in a function called "saveFolderIcon(fid, sel_id)".

$.ajax({type: 'POST',url: 'function_handler.php',data: {	act: 'save_folder_icon', 	folder: fid ,	img: imgfile	},cache: false, success: function(data){	loadTree();}});

The ajax part works perfectly, it updates the data in the table successfully. After it does that I'm trying to run a function called "loadTree()" that's inside the doc.ready() block. It just reloads the folder tree so the user can see the updated icon in the tree. But I can't get it to work. I'm pretty sure it's some minor syntactical issue because the loadTree() functions works when the page is first loaded. (It's called by a "loadTree();" statement in the doc.ready() block, and it works correctly.)I've tried ...success: loadTree();... and several other variations but haven't hit on it yet. Any idea where I'm going wrong here?

Link to comment
Share on other sites

Is it common or normal to have more than one doc.ready() function? At the moment I have only one, based on all the examples shown in the various books I'm plowing through, and all my code is inside of it. Is that wrong, or...?
It doesn't matter how many you have. Maybe for organizational purposes you would want more than one, but one is enough and typically I only have one and I just put tons of comments within it that deal with different sections of my site.
Also, (lol) I'm not sure I'm totally clear on calling function...functions that I declare within the doc.ready() block can be called from within the doc.ready() block. How do I call a function in the doc.ready() block from outside, i.e. from some external javascript?For example, I have this code that is partially working in some external javascript, in a function called "saveFolderIcon(fid, sel_id)".
$.ajax({type: 'POST',url: 'function_handler.php',data: {	act: 'save_folder_icon', 	folder: fid ,	img: imgfile	},cache: false, success: function(data){	loadTree();}});

The ajax part works perfectly, it updates the data in the table successfully. After it does that I'm trying to run a function called "loadTree()" that's inside the doc.ready() block. It just reloads the folder tree so the user can see the updated icon in the tree. But I can't get it to work. I'm pretty sure it's some minor syntactical issue because the loadTree() functions works when the page is first loaded. (It's called by a "loadTree();" statement in the doc.ready() block, and it works correctly.)I've tried ...success: loadTree();... and several other variations but haven't hit on it yet. Any idea where I'm going wrong here?

Regular JS functions don't need to be declared within doc.ready. Regular functions in the head aren't executed until they are triggered by some event. The reason you put most of your jquery code in doc.ready is because when the page loads, all the html elements have not been rendered yet, and if you put something like $('#id').fadeIn() in the head, it's wont be able to find an element with and id of 'id'. Thus, doc.ready executes the code once all the elements have been loaded. Try moving your function loadTree() outside of doc ready and see what happens. Also, use Firefox's error console to determine what JS errors occur. It's really useful when debugging JS.
Link to comment
Share on other sites

Archived

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

×
×
  • Create New...