Questions and Answers from the List
I've been feeling guilty lately about my lack of posts to this blog. But when I looked at my profile for the jQuery Google Group and discovered that for the past six months I've posted an average of 100+ times each month, well, I decided to give myself a break. Since I'm sure some people who stumble upon this blog aren't subscribed to the Google group/mailing list, here are a few (edited) questions that have appeared there recently, along with my (edited) answers. I hope some of you find them helpful.
Question: Filter Function
I have this HTML:
-
<p>
-
<b>Text1</b>
-
</p>
-
<b>Text2</b>
How can I select the second <b>, which is not a child of a <p>? As I am a newbie, I played a little bit around with :not, filter(), but unfortunately...
Any hints?
Answer
Try this:
This finds all <b> elements and then filters them. The filter returns only those that do not (!) have a parent paragraph ( $(this).parent('p').length ).
Question: Filter by Option Value
I have several options in a select element, each whose value is an integer. I would love to be able to select those above a threshold, such as something like:
$("#mySelect option[value>5]")
I know I can do this with :gt(index) but I'd rather use the actual value for less hard coding and better readability. I think this would be great in other areas too.
I'm sure there are lots of issues with this since the value is really just text, but a straight string comparison would probably do.
Answer
You could try something like this:
-
return parseInt(this.value, 10)> 5;
-
});
This should filter the option elements, selecting only those whose value is greater than 5.
Question: Puzzle of "this"
I am puzzled by the use of this somehow. For example:
-
$.post("test2.php",{id:txt},function() {
-
this.something
-
};
-
});
Here, if I want to refer this to the $('.delete') element, what shall I write? In the debugger I found that this refers to the function body.
Answer
You could try this:
-
var $thisDelete = $(this);
-
$.post("test2.php",{id:txt},function(){
-
$thisDelete.somejQueryMethod();
-
});
-
});
The $thisDelete variable is now referencing the clicked element wrapped in a jQuery object. This is useful for attaching jQuery methods, chaining, etc. Oh, and by the way, the use of the "$" in $thisDelete isn't necessary, but it has become somewhat of a convention among jQuery developers, as it reminds us that we're dealing with a jQuery object.
Now, when you use $thisDelete inside your $.post, it's still referring to the clicked element.
Question: Swap an Image on Click
I have a simple accordion set up, but I want to be able to change the header's background image from an up arrow state to down arrow state and back automatically. Any ideas on where to go from here?
Answer
After the .click() line [which slides the following div up or dow], you can do something like this...
The first line here stores the clicked header's background image in the "currImage" variable. The second line then sets the background image. It uses a ternary, or conditional, operator to check if the background image is "up-arrow.jpg". If it is, the image is set to "down-arrow.jpg"; if it isn't "up-arrow.jpg", the image is set to "up-arrow.jpg".
Question: How to Center a DIV Vertically in the Viewport
Thing is I got a project on which i want to show a preloader whenever something is sent or some event has been triggered. How could I set the preloader to show itself right on the middle of the screen?? I mean how could I show it on the right middle of the screen even if I got a huge scrollbar on the right side!?
Answer
So here is one way you could get vertical centering in the viewport [with sTop code borrowed from an old copy of Dimensions plugin]:
-
// vertically center something in the viewport
-
-
// make it a plugin!
-
(function($){
-
$.fn.vCenter = function(options) {
-
var pos = {
-
sTop : function() {
-
return window.pageYOffset
-
|| document.documentElement && document.documentElement.scrollTop
-
|| document.body.scrollTop;
-
},
-
wHeight : function() {
-
return window.innerHeight
-
|| document.documentElement && document.documentElement.clientHeight
-
|| document.body.clientHeight;
-
}
-
}
-
};
-
var $this = $(this);
-
var elHeight = $this.height();
-
var elTop = pos.sTop() + (pos.wHeight() / 2) - (elHeight / 2);
-
position: 'absolute',
-
marginTop: '0',
-
top: elTop
-
});
-
}
-
});
-
};
-
-
})(jQuery); // end plugin
-
-
// center an element - could go in your custom js file
-
-
$('#foo').vCenter();
-
-
});
Take a look at the demo page I put together. Click on a "center" button, and see where the div goes. Scroll down and click on another button. The div still goes to the center of the viewable area.
UPDATE: Because this didn't work properly in Opera 9.5 as reported in comment #4 below, I refactored the code for returning the scroll top and window height values. Please continue to report any errors that you discover. I also welcome suggestions for improvements to any of the code here.



December 19th, 2007 at 10:39 pm
Thanks for all the hard work and these gems in particular. Much appreciated.
Just one small critique: your code prettifier is over-zealously html-encoding characters.
December 19th, 2007 at 11:10 pm
-
Hi,
I, for a long time, have the idea, to copy such "quick answers and solutions" from the forum and the irc also to a website as a repository to search for such things like above (selectors, ...)
djot
-
December 19th, 2007 at 11:51 pm
Oliver, thanks for pointing out the problem with the code prettifier. I hope I have it fixed now. There were a few other issues as well with WordPress mangling the markup (again). Glad you liked the post.
December 20th, 2007 at 6:55 am
unfortunately your test page doesn't work with Opera 9.50...
December 20th, 2007 at 11:41 am
Hi bullcrap0,
That is, indeed, unfortunate (as is your name
).
Apparently there was a problem with the way I was getting the viewport height. I stripped out the browser sniffing (not sure why it was in there in the first place, but I generally trust Brandon's code), downloaded and installed Opera 9.50 beta for Windows, and tested the page. I'm happy to report that it appears to be working in that browser now. I'll update the entry above to reflect the change in code.
Thanks a lot for reporting this!
December 20th, 2007 at 1:17 pm
Karl
I am subscribed to the google group and I love jQuery but I really struggle to modify small things. I have a cap frequency cookie function on a show hide slide toggle that doesn't use the jquery cookie plugin by Klaus. My cookie uses oneDay and I have tried everything I can think of to shorten the expire duration to less than 24 hours OR to have it reset at midnight. Any light you can shed would be most welcome. The working cookie show hide function is:
Thanks for all you do Karl!
December 20th, 2007 at 3:46 pm
Hi Susan,
Rather than use the "expires" attribute, you might want to try using "max-age" like so:
var c = "slidedToday=true; max-age=" + (60*60*24) + "; path=/";document.cookie=c;
The "max-age" attribute is measured in seconds, so here we're saying that the cookie is good for 24 hours, but you can set it for whatever time period you want.
Hope that helps.
December 20th, 2007 at 5:19 pm
Fantastic article with insights into jQuery. The vCenter plugin is a good demonstration on how to extend jQuery. Thanks!
December 20th, 2007 at 6:07 pm
Thanks Karl!
I think I understand, and once I switched to my 2nd computer that had no cookies today I did see my slideDown slideUp just once but was still able to toggle. So I think I understood what I need to do
I have
if(!document.cookie.match("slidedToday")){
var oneDay = new Date();
oneDay.setDate(oneDay.getDate()+1);
var c = "slidedToday=true; max-age=" + (60*60*24) + "; path=/";
document.cookie=c;
I do have another show hide that swaps images that wizzud helped me with on the jQuery group
$(document).ready(function(){
var slideTimeout // timer
, sbTrigger = $('#slidebartrigger') // convenience
, sbFirstSlide = true // indicates first time through
;
function toggleSlideboxes(){
if(slideTimeout) clearTimeout(slideTimeout);
var isDown = sbTrigger.is('.closeSlide');
$('#slidebar')['slide' + (isDown ? 'Up' : 'Down')]((isDown ? 3000 :
1000), function(){
if(sbFirstSlide){ sbTrigger.removeClass('firstSlide'); sbFirstSlide
= false; }
sbTrigger[(isDown ? 'remove' : 'add') +
'Class']('closeSlide').one('click', toggleSlideboxes);
if(!isDown) slideTimeout = setTimeout(toggleSlideboxes, 4000);
});
}
toggleSlideboxes();
});
which swaps between a blank, close & replay tab GIF depending on where the slidebar is. Unfortunately I had no luck figuring out how to cap the frequency of my slide with this more complex show hide.
January 1st, 2008 at 2:26 am
for centering a div in the viewport, you might try the Thickbox plugin.
it allows the coder to display various types of content including divs in a "dialog box"
(for examples, follow the supplied link and scroll down to the examples section, which is red.
January 4th, 2008 at 3:25 am
Dear Karl,
Thanx for all the knowledge you're sharing here. Great work.
I always have some problems when using jQuery for Ajax and for other things. Maybe I'm not used to it yet, I'm always missing something.
Let's see this one, I can't figure out why this one doesn't work. When I write script, I try to write everything and put them together in one file, but its doesn't work. see below
function disappear() {
$("#response").fadeOut("slow")
}
$(document).ready(function() {
$("#message_me").click(function() {
$("#form").fadeIn("slow")
})
$("#send").click(function() {
var str = $("#input_form").serialize()
$.post("send-mail.php",str,function(data) {
$("#response").html(data).fadeTo("slow", 0.7)
setTimeout("disappear()", 3000)
})
})
$.get("counter.php", function(data) {
$("#counter").html(data).fadeIn("slow")
})
})
I saved the above script in a separate file, let's say "myscript.js". Then I imported it in my html file like this
Then, when I run this, it's not working. I've been trying to find the error. It says "missing } in XML expression at $("#send").... but then I switched places between $("#send")... and $.get(..., then the error comes out like "missing } XML expression at $.get(... instead. So I don't know what's wrong, Is there any function that needs to be put in between somehow?
Again, now I delete everything except for $.get(.... in myscript.js. And I put them in the html file manually like
function disappear() {
$("#response").fadeOut("slow")
}
$(document).ready(function() {
$("#message_me").click(function() {
$("#form").fadeIn("slow")
})
$("#send").click(function() {
var str = $("#input_form").serialize()
$.post("send-mail.php",str,function(data) {
$("#response").html(data).fadeTo("slow", 0.7)
setTimeout("disappear()", 3000)
})
})
})
Now then, it works fine.....
Can you tell me why it's not working in the uppermost one. cuz I want to put everything in one script file, and not to show any script in the html file.
Thank you very much for any responses, really appreciate your time.
DeaR
March 5th, 2008 at 9:42 pm
I did a quick search but didn't find anything relevant. I'm new to jQuery and I'm a PHP programmer in the spare time and a Java programmer at work. How much object oriented design does jQuery support? Could you perhaps elaborate on that? Thanks.
March 9th, 2008 at 3:08 pm
thanks for codes
March 29th, 2008 at 2:50 am
hi,
I'm trying to figure out how to make this work with more then one paragraph,
basically the second paragraph doesn't appear, i tried different combination that made it appear but once i closed the h2 and re-opened it the second paragraph would not show, i even had the same problem with a paragraph containing a floated image. the image came back but not the paragraph,
if anyone could help me out, that would be great.
thanks.
HTML
Latest Updates..
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam leo. Fusce pharetra risus eu tellus. Ut turpis. Nunc congue lacinia dolor. Vivamus ipsum quam, egestas ac, luctus at, aliquam a, est. Donec fermentum enim id magna. Duis nisi orci, feugiat eget, imperdiet eu, condimentum id, leo. Donec cursus. Vivamus gravida nibh vitae dolor. Sed mattis. Pellentesque ante magna, egestas vel, pharetra in, vulputate ut, est. Quisque felis risus, iaculis in, blandit id, lobortis vel, purus.
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam leo. Fusce pharetra risus eu tellus. Ut turpis. Nunc congue lacinia dolor. Vivamus ipsum quam, egestas ac, luctus at, aliquam a, est. Donec fermentum enim id magna. Duis nisi orci, feugiat eget, imperdiet eu, condimentum id, leo. Donec cursus. Vivamus gravida nibh vitae dolor. Sed mattis. Pellentesque ante magna, egestas vel, pharetra in, vulputate ut, est. Quisque felis risus, iaculis in, blandit id, lobortis vel, purus..
header
Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aliquam leo. Fusce pharetra risus eu tellus. Ut turpis. Nunc congue lacinia dolor. Vivamus ipsum quam, egestas ac, luctus at, aliquam a, est. Donec fermentum enim id magna. Duis nisi orci, feugiat eget, imperdiet eu, condimentum id, leo. Donec cursus. Vivamus gravida nibh vitae dolor. Sed mattis. Pellentesque ante magna, egestas vel, pharetra in, vulputate ut, est. Quisque felis risus, iaculis in, blandit id, lobortis vel, purus.
JQUERY
March 29th, 2008 at 6:02 pm
Hi Pablo,
The .next() method only selects the immediate next sibling. If all your h2 and p elements are siblings, you might need to use the nextUntil plugin:
Then you could do this:
A couple things: If you know the tag name of the element with class "accordion," you should probably use it in the selector. For example, "div.accordion" instead of just ".accordion." Also, you'll probably be better off if you wrap each group of paragraphs in its own div. It's easier to select a single div (no need for the nextUntil plugin) and the animation will be smoother.
April 2nd, 2008 at 12:47 pm
Thank you very much Karl, I really appreciate it
pablo
April 9th, 2008 at 5:48 pm
Hey karl, I noticed it doesn't work in ie6, works liek a charm in all the other browsers.
Thanks
pablo
April 9th, 2008 at 11:32 pm
Hi Pablo,
Do you have a page somewhere that I can look at? It will help me to troubleshoot for you if I can see what you're doing.
April 12th, 2008 at 5:24 pm
Hi Karl, everything is fine, it was basically an internet provider issue, sorry about te delay in replying...was out of town
thanks again for the help
hope all is well
P
May 4th, 2008 at 10:30 am
Thanks for your code. Cheers from Peru
June 17th, 2008 at 9:49 am
In going through the 'Learning jQuery' book, I did some experimenting with the content of 'Chapter 1/alice.html'. Specifically, I have this selector and statement...
$(document).ready(function() {
$('.poem-stanza > div:eq(1)').addClass('blue_txt');
});
The problem is that when this is applied only the FIRST INSTANCE of "second child div of class .poem-stanza" gets the new class. Please note that the alice.html file has TWO INSTANCES of '.poem-stanza > div:eq(1)'.
YKCOWREBBAJ
sevot yhtils eht dna ,gillirb sawT'
;ebaw eht ni elbmig dna eryg diD
,sevogorob eht erew ysmim llA
.ebargtuo shtar emom eht dnA
She puzzled over this for some time, but at last a bright thought struck her. "Why, it's a Looking-glass book, of course! And if I hold it up to a glass, the words will all go the right way again."
This was the poem that Alice read.
JABBERWOCKY
'Twas brillig, and the slithy toves
Did gyre and gimble in the wabe;
All mimsy were the borogoves,
And the mome raths outgrabe.
QUESTION: Why does the 2nd instance get ignored (unprocessed)? How do I modify my statement so that the 2nd instance DOES get processed?
THANKS!
Jon
June 24th, 2008 at 2:20 pm
Hi Jon,
In that case, you might want to use
$('.poem-stanza > div:nth-child(2)').addClass('blue_txt');Keep in mind that :nth-child(n) is 1-based, whereas all the other jQuery selectors are 0-based.
Hope that helps.