Activate your free membership today | Log-in

Thursday, April 17th, 2008

Spoiler Blocker When JS Isn’t Available

Category: jQuery

Ever gone to a site to read up on your favorite show or get the lowdown on a new movie only to have the whole plot spoiled because you weren't forewarned that the "whole freakin' script" was injected into the article?!?! Yeah, I've been there and it ain't fun!

Chris Coyier of CSS-Tricks came up with a solution called Fade-in Spoiler Revealer which used jQuery to allow the user to click on a div that blocked view of the spoiler and see the contents. This was a very cool technique and caught the attention of Brian Dillard. Brian wondered how this script could be adapted to work with RSS readers and mobile browsers:

My only reservation about Coyier's technique was its reliance on JavaScript, and only JavaScript, to hide spoiler-laden content. With RSS and mobile browsing on the rise, lots of people read content in user-agents without JavaScript support. Shouldn't we try to protect them, too? I commented to this effect on the original article, then realized that I should just write the code myself as proof of concept.

Brian Dillard came up with his own version of a spoiler blocker which, through a little progressive enhancement, accommodates for situations where JS is not enabled (eg: a RSS reader). His code consists of two parts; the jQuery code which hides the spoiler and binds the click event to a fade effect and the HTML which is progressive enhanced.

JAVASCRIPT:
  1.  
  2. $(document).ready(function() {
  3.        
  4.         $(".spoiler")
  5.                 //hide the spoiler
  6.                 .children("span.hidden").hide()
  7.                 //hide the whitespace inside it
  8.                 .children("br").hide()
  9.                 //step back up a level
  10.                 .end()
  11.                 //find the sibling
  12.                 .prev("span.message")
  13.                 //add the click handler to show the spoiler
  14.                 .click(function() {
  15.                         //use a callback So FX execute non-simultaneously;
  16.                         $(this).fadeOut(600, function() {
  17.                                 $(this).next().fadeIn(600);
  18.                         })
  19.                 })
  20.         ;
  21.        
  22. });
  23.  
HTML:
  1.  
  2. <p class="spoiler">
  3.         In the movie "Citizen Kane," Charles Foster Kane's last
  4.         word, "Rosebud," turns out to be ...
  5.         <span class="message">
  6.                 (<a href="#answer">Click here if you'd like to be spoiled.</a>)
  7.         </span>
  8.         <span class="hidden">
  9.                 <br /><br /><br /><br /><br /><br /><br />
  10.                 <br /><br /><br /><br /><br /><br /><br />
  11.                 <br /><br /><br /><br /><br /><br /><br />
  12.                 <br /><br /><br /><br /><br /><br /><br />
  13.                 <br /><br /><br /><br /><br /><br /><br />
  14.                 <br /><br /><br /><br /><br /><br /><br />
  15.                 <br /><br /><br /><br /><br /><br /><br />
  16.                 <br /><br /><br /><br /><br /><br /><br />
  17.                 <br /><br /><br /><br /><br /><br /><br />
  18.                 <br /><br /><br /><br /><br /><br /><br />
  19.                 <br /><br /><br /><br /><br /><br /><br />
  20.                 <br /><br /><br /><br /><br /><br /><br />
  21.                 <br /><br /><br /><br /><br /><br /><br />
  22.                 <br /><br /><br /><br /><br /><br /><br />
  23.                 <br /><br /><br /><br /><br /><br /><br />
  24.                 <br /><br /><br /><br /><br /><br /><br />
  25.                 <a name="answer"></a>a sled.
  26.         </span>
  27. </p>
  28.  

You can see the demo here. You'll need to turn off JavaScript in order to see it.

This is one way of managing the user experience in user-agents without JavaScript support but I'm sure that the Ajaxian crowd has developed other ways of tackling this same problem. We'd like to hear about it so comment away.

Posted by Rey Bango at 10:46 am
7 Comments

+++--
3.2 rating from 17 votes

Tuesday, April 15th, 2008

jQuery and Prototype Benchmarks

Category: JavaScript, Performance, Prototype, jQuery

Piotr Solnica did a couple of posts on jQuery and Prototype benchmarks back in the day, and John-David Dalton just found them.

In part one, he runs tests such as:

JAVASCRIPT:
  1.  
  2. $('td.first').addClass('marked'); // jQuery
  3.  
  4. $$('td.first').each(function(cell){
  5.   cell.addClassName('marked');
  6. });
  7.  
  8. // or
  9.  
  10. $$('td.first').invoke('addClassName', 'marked');
  11.  

and concludes:

Executed tests show that Prototype seems to be faster then jQuery, with the exception of the new insertion method, which performance should be improved. Although I like jQuery syntax more then Prototype, the performance is way more important then saving few lines of code. Of course tests that I made don’t show how these libraries act in a real application, which is my task for the next part(s) of this article. Despite the results I must admit that I’m very excited about jQuery, my general impression is that this library is more mature then Prototype.

In part two, Piotr uses a custom JavaScript-based testing environment instead of running tests using Firebug profiler. This allows the test suite to run in many browsers, and this time concludes:

Prototype was at least 2 times faster then jQuery in 15 cases, and jQuery was faster then Prototype in 8 cases. What library should I choose? In my case I will stick with Prototype, because it offers the same functionality as jQuery does + more and it’s faster. jQuery is probably better for projects where there’s a need for some fancy UI effects and that’s it, but it’s just an assumption, correct me if I’m wrong…

Posted by Dion Almaer at 5:13 am
17 Comments

++++-
4.6 rating from 160 votes

Thursday, April 10th, 2008

Ajaxian Featured Tutorial: Hacking transparent PNG support into IE6 with IE PNG Fix, CSS and jQuery

Category: CSS, JavaScript, jQuery

During his work in redesigning the Pathfinder web site, Brian Dillard came across the infamous IE6 transparent PNGs issue and used two methods to tackle the issues. He decided to do a nice write-up explaining how he worked around the fact that IE6, while it would render PNGs, would not retain their alpha-channel transparency and produce unexpected colors in place of the transparency.

IE6's lack of transparent PNG support is appalling, but Microsoft does offer a proprietary fix for the same problem: CSS behaviors, which are a non-standard extension to the CSS spec. By applying a special behavior to your PNG images, you can force IE6 to display them with their alpha transparency intact.

Coding this CSS behavior on an image-by-image basis would be tedious. Luckily, developer Angus Turnbull has released an open-source script that can be used to apply the behavior globally: IE PNG Fix. The current production release is v1.0 RC4, but a preview of v1.0 RC5 is also available.

While the IE PNG Fix script to dealt with the majority of the PNG transparency issue, there was still one problem that the script could not correct:

There is, however, one drawback to Turnbull's script: It can't account for PNG background images with a background-position other than top left. It will restore the alpha-channel transparency to such images, but it will reposition them to top left, potentially making your designs look even worse than they would have with an ugly gray halo where the transparency should be.

Brian turned to jQuery to help him resolve this by allowing him to re-insert the background images previously removed from IE6 as foreground images.

Full details, including code, of his solution can be found in his two part series linked below:

Hacking transparent PNG support into IE6 with IE PNG Fix, CSS and jQuery (part 1 of 2)

Hacking transparent PNG support into IE6 with IE PNG Fix, CSS and jQuery (part 2 of 2)

Posted by Rey Bango at 2:12 pm
18 Comments

+++--
3.1 rating from 45 votes

Friday, April 4th, 2008

GQuery: Java, GWT, and jQuery together

Category: GWT, jQuery

Are you a fan of GWT but would like toms jQuery magic mixed in? Ray Cromwell has your back, as he has created GQuery, an implementation of jQuery for GWT.

This means that you can write code like this:

JAVA:
  1.  
  2. public void onModuleLoad() { 
  3.   $("div").css("color", "red").click(new Function() { 
  4.      public void f(Element e) { 
  5.        Window.alert("Hello")
  6.          $(e).as(Effects).fadeOut()
  7.       } 
  8.    })
  9. } 
  10.  

I decided to demonstrate some of the huge benefits of 1.5 by implementing a type-safe JQuery clone in GWT.

That's right, for all those folks who don't want to deal with GWT Widgets, but just want to query, wrap, and manipulate plain old DOM elements in GWT, this article is for you. I'm talking to you, you self-hating Java programmer with an inner Javascript Ninja begging to be let out.

After the GWT compiler gets its hands on it, the example comes in at 5459 bytes. This library can only be achieved with GWT 1.5 features, and gives you:

  • Joel Webber of the GWT Team just submitted a patch to GWT 1.5 that implements every DOM2 Core+HTML class as a subclass of the new JavaScriptObject. This not only made the coding of GQuery very easy, but it produces nicely optimized JavaScript.
  • Static Imports. The $ function would not nearly be as nice without static imports.
  • Generics and Covariant return. The Plugin mechanism utilizes this to fake prototype based overrides of the GQuery object.

Fun little feature, $$

jQuery contains a lot of methods which take essentially property/value pairs in a Javascript object literal. Emulating this with Java syntax would be too tedious (Scala frontend to GWT, please!), however, to ease this use case, I added a global $$ function for manipulation JavaScriptObject/JSON objects easily.

JAVA:
  1.  
  2. Properties literal = $$("{ foo: 'bar', baz: 'bam'}")
  3. $$("{foo: 1, bar : 2}").get("foo") == 1;
  4.  

Posted by Dion Almaer at 12:15 am
1 Comment

+++--
3.8 rating from 38 votes

Tuesday, April 1st, 2008

jQuery gets Classy

Category: jQuery

Finally, you can throw away the concise jQuery code, and you can instead grab a more verbose version Classy Query, that John Resig has provided.

This extra verbosity is perfect for a compiler or a document parser. The important people.

You can now write code like this:

HTML:
  1.  
  2. <script src="jquery.js"></script>
  3. <script src="classy.js"></script>
  4. jQuery.Events.addEventListener(document, "ready", function(){
  5.   jQuery.querySelectorAll("div").forEach(function(elem){
  6.     jQuery.DOM.append(elem, " <b>More...</b>");
  7.   });
  8.  
  9.   jQuery.querySelectorAll("div b").forEach(function(elem){
  10.     jQuery.Events.addEventListener("click", function(elem, event){
  11.       var next = jQuery.Traversal.nextSibling(elem);
  12.       var animation = jQuery.Effects.buildAnimation( next, {height: "toggle"});
  13.       amimation.start();
  14.     });
  15.   });
  16. });
  17. </script>
  18.  

Finally. Check out the source.

Posted by Dion Almaer at 3:50 am
8 Comments

++++-
4.2 rating from 24 votes

Monday, March 31st, 2008

Browser CSS float error detection with jQuery

Category: Browsers, CSS, Debugging, jQuery

Mario Heiderich of Ormigo has created a jQuery based code snippet/bookmarklet that is capable of detecting floating errors and adding a dotted orange border to elements which should be cleared - but aren't.


It saved me a huge bunch of time debugging complex layouts for all browsers - especially IE6. If jQuery isn't already loaded on the page it can easily be fetched with the several jQuerify approaches.

Snippet

JAVASCRIPT:
  1.  
  2. (function(){
  3.     function checkNext(element, floating) {
  4.             if(element.css('clear') != 'none') {
  5.                 var clearing = true;
  6.             } else {
  7.                 if(element.next().length !== 0) {
  8.                     var clearing = false;           
  9.                     checkNext(element.next(), floating);
  10.                 } else {
  11.                     console.log(element);
  12.                     element.css({border:'2px dotted orange;'})
  13.                 }
  14.             }
  15.     }
  16.     $('body *').each(function(){
  17.         var element = $(this);
  18.         if(element.css('float') !== 'none' && element.next().length !== 0) {
  19.             checkNext(element.next(), element.css('float'));
  20.         }
  21.         eval('');
  22.     });
  23. })();