Questions and Answers from the List
read 32 comments
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.
The
Question: Filter Function
I have this HTML:
How can I select the second
Any hints?
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...
JavaScript:
Any hints?
Answer
Try this:
This finds all
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:
This should filter the
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
Here, if I want to refer this to the
this somehow. For example:
JavaScript:
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:JavaScript:
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
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".
.click() line [which slides the following div up or dow], you can do something like this...
JavaScript:
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]:
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.
JavaScript:
- // 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 elTop = pos.sTop() + (pos.wHeight() / 2) - (elHeight / 2);
- 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.















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.
-
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
-
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. :)
unfortunately your test page doesn't work with Opera 9.50...
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!
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!
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.
Fantastic article with insights into jQuery. The vCenter plugin is a good demonstration on how to extend jQuery. Thanks!
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.
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.
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
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.
thanks for codes
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
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.
Thank you very much Karl, I really appreciate it
pablo
Hey karl, I noticed it doesn't work in ie6, works liek a charm in all the other browsers.
Thanks
pablo
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.
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
Thanks for your code. Cheers from Peru
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
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.
I was having some issues with the vertical center plugin on IE7.
For some reason, the content was succesfully being vertically centered, but also the width of the window was expanding (and so, adding an horizontal scroll bar).
Finally, I did some changes in the plugin code and was able to fix it.
The changes are this:
//position: 'absolute',
//marginTop: elTop,
paddingTop: elTop
//top: elTop
As you can see, I commented out some lines and added the paddingTop.
So far, it worked for me (on a particular situation) on IE6/7/Win, FF3, Safari/Win, Google Chrome.
But, the question is: could you foreseen any problem with this change?
Thanks.
Well, I've spotted a little bug in my approach (see comment above).
Because of the way jquery.vcenter calculates the value for elTop, it can result on a negative value. Then, that negative value can't be used on paddingTop, because padding cannot have negative values.
The workaround is easy. If elTop < 0, then set it to equal 0.
Like this:
[...]
var elTop = pos.sTop() + (pos.wHeight() / 2) - (elHeight / 2);
if (elTop < 0) {
var elTop = 0;
};
$this.css({
//position: 'absolute',
//marginTop: elTop,
paddingTop: elTop
//top: elTop
});
[...]
Is there a way by which I can find out the exact height of my webpage not the clientHeight from the quirks mode but the height which is cross browser compatible.
But exact height I mean the complete height above the top scrolled area, area viewable and the area below which is yet to be scrolled.
Hi Adeel. Try
$(document).height();.Thanks Karl for the above comment but i was wondering a method outside jQuery in simple javascript,
while here's a tribute to you, my first jQuery plugin - ripped from your post
jQuery.fn.centerMe = function() {
var sTop = function() {
return window.pageYOffset || document.documentElement && document.documentElement.scrollTop || document.body.scrollTop;
}
var sLeft = function() {
return window.pageXOffset || document.documentElement && document.documentElement.scrollLeft || document.body.scrollLeft;
}
var iHeight = function() {
return window.innerHeight || document.documentElement && document.documentElement.clientHeight || document.body.clientHeight;
}
var iWidth = function() {
return window.innerWidth || document.documentElement && document.documentElement.clientWidth || document.body.clientWidth;
}
return this.each(function(index) {
var elmWidth = $(this).width();
var elmHeight = $(this).height();
var scrollTop = sTop();
var scrollLeft = sLeft();
var innerHeight = iHeight();
var innerWidth = iWidth();
var top = scrollTop + (innerHeight / 2) - (elmHeight / 2);
var left = scrollLeft + (innerWidth / 2) - (elmWidth / 2);
$(this).css({
'position':'absolute',
'top':top,
'left':left
});
});
}
Hi Karl,
very good post and quite useful to me as I was today trying to center an image on the screen, which is exactly what the answer to How to Center a DIV Vertically in the Viewport does.
However the code snippet above has a syntax error. Line 17 should be removed, otherwise the curly bracket terminates the definition of vCenter. The code is correct on the jquery.vcenter.js used in the example page though.
Thanks for all your very useful post all the same
Good catch, Rodrigue! I updated the post with the fixed code.
I, too, am having the same issue as DeaR.
I keep getting "Missing } in XML expression." I looked over my JS code quite a bit, but can't seem to find anything wrong with it.
It happens during the execution of the post function.
Has anyone experienced this or may have any possible solution to this problem?
Thanks.
very useful page! thanks
Thanks for all your very useful post all the same