jQuery and IE… Again

So, at work today, I discovered another interesting facet of jQuery and IE.

This is in specific regards to jQuery 1.4.2 and IE7. I haven’t tested this in other versions of IE, but it’s probably as applicable. For jQuery, this will only be a problem in 1.4.2+, as earlier versions of jQuery don’t support this feature.

Let’s get to it.

The situation

I’m generating some HTML forms on-the-fly by passing some JSON objects to a function that returns a jQuery object, which I then append to a modal dialog. It’s pretty elegant, and I may release it as an open-source jQuery plugin at some point. Anyway, part of this function uses jQuery 1.4.2’s ability to generate jQuery DOM objects when HTML strings are passed to the function. Example:

$('<div class="myclass" />');

This is great because it allows me to create a string of HTML and pass it to jQuery, effectively increasing the speed of the program by avoiding function calls (can you imagine calling the attr() method for every attribute, and then the append() method for every element, including child elements??).

The problem

So what’s the problem? Well, this works in IE, so you’d think there isn’t a problem. In fact, I was also convinced (read: tricked) that IE handled this fine, as initial testing returned the expected results. However, because sending an empty string to the jQuery function returns an empty jQuery object, debugging this type of code can be very dangerous, as instead of generating errors, the script will die or stop functioning silently. No errors makes debugging very difficult!

I was using the following code to generate a form tag, append it to an object, and then return it. It looked something like this:

var newForm = $('<form method="post" action="">');

This works in other browsers, but IE chokes. Silently. I discovered this when I started doing some testing on generating the object, independent of my script (which I’d been attempting to debug for well over an hour at this point).

Alerting the length property of the jQuery object has been helpful here. I first tried $('<div />').length and got the result 1. That makes sense. Then I tried $('<div>').length. This also, correctly, returns 1.

Then I tried something else. Since all this hypothetical testing was driving me bananas, I tried the actual form HTML I was using. $('<form method="post" action="">').length returned… 0!! How frustrating! Taking the attributes out and simply using $('<form>').length returns 1 as well, however. To get the correct result, I had to use the self-enclosing form tag: $('<form method="post" action="" />').length. This returned the correct result (1). Finally. That one character fixed my entire program in IE. Wow!

In Summary

TL;DR version: IE chokes and returns an empty jQuery object when you pass an HTML string that has attributes without a self-closure. I hope this saves some folks valuable time debugging this ridiculous phantom. I’m curious if this should be filed as a jQuery bug or not.

Happy coding!

June 14th, 2010 | Remark

jQuery, IE6 and the Display Property

This is a note to myself and anyone else encountering the following JavaScript error in IE6.

Could not get display property. Invalid argument.

This error applies specifically to jQuery when using the animate method. The animate method works only in steps, so you can’t toss in CSS commands sloppily (although other browsers will treat this okay). Instead, you have to specify the CSS separately.

In other words, your original function may look like this:

$("#myObject").animate({
      display : 'block',
      top: '+=10px'
});

But for it to work in IE6, you’ll need to revise it to the more verbose:

$("#myObject").css({
      display: 'block'
}).animate({
      top: '+=10px'
});

In some cases, you may get the old JavaScript error that IE throws whenever it gets confused:

Object doesn't support this property or method.

Always be careful not to use the animate method as short-hand for the css method, as doing so may cause IE6 to simply destroy all of your associated/caller functions and report that they don’t exist. There’s not really any simple way to debug this error, either, so just check for it whenever you can’t figure out what’s wrong.

April 7th, 2010 | 2 Remarks

Floating Comment Form

In 2005, well-known designer Jonathan Snook built a floating comment form into his blog design using CSS. (Editor’s note: the archives at Snook’s Web site say “2006,” but I am fairly certain that this actually occurred in May of 2005. If you have the facts, please let me know in the comments.) Unfortunately, because Snook has redesigned his blog several times since then, you can no longer see this functionality in action. The short version: his old design had an empty sidebar, where a comment form floated and could easily be used to add comments without needing to scroll to the bottom of the page. Convenient, stylish, effective, and you might even say revolutionary. I do not know why Snook has not opted to maintain this feature on his blog — perhaps it was too much of a struggle to maintain, or maybe he didn’t plan for it.

And that’s just the thing: planning a design is a critical part of developing how visitors will interact with it. If Snook’s current design didn’t have in mind the option to add a floating comment form, then naturally it would not make sense for him to implement such a form — it wouldn’t fit.

Likewise, since I developed this design for Slightly Remarkable several years ago (I can’t nail down the exact date, but it was sometime in 2006), I never considered the option of creating a floating or dockable comment form. Until the other day, when I decided that Snook’s idea was too indespensible to be forgotten like so many over-hyped “web 2.0″ ideas.

Now, let me say that I am not the first to have decided that a full redesign is unnecessary simply for the purpose of implementing a floating comment form feature. In fact, I believe that many feel this way. Derek Featherstone seemed to think so, which is why he wrote about the concept and how he implemented it into his design. Clever, yes?

I thought so, but I didn’t use Featherstone’s CSS/JavaScript. I opted for a slightly different route, requiring significantly less code (very little CSS, a tad JavaScript, and jQuery), excluding the use of the JavaScript library jQuery (which is actually fairly small, and I do intend to use it later — perhaps to include Ajax in my comment form — so it will be handy to have already cached). The script that I have written allows the comment form to appear normally, at the end of the list of comments, for users without JavaScript; for JavaScript users, however, it literally detaches the comment form from the page, hides it, and displays a nice little “Join the conversation” link button that floats in the bottom right-hand corner of the page. I may add icons to it to make it a little more noticeable, but that’s how it is for the time being. Let’s dig in, shall we?

The first step: modifying the comment form.

I am using Wordpress, so I’ll go ahead and show you how to do this using Wordpress. If you use any other software, you’ll have to do a little digging to find out where you can apply this modification — it’s probably fairly easy, though, since it’s very small change. In essence, you need only encapsulate your comment form <form> element in a <div>, and of course give that <div> an id. I called mine remarksform.

In Wordpress, this file is located in your /wp-content/themes/your-theme-name/comments.php file. With minimal PHP knowledge, you should be able to see where to place your <div> tag. I put mine just before the <h3> tag that says “Leave a Remark” and immediately after the closing </form> tag.

That’s all there is to modifying your (x)HTML. Technically, you could even achieve a dockable comment form without doing this, but I find it is a better idea to detach the entire <div> element, instead of just the <form>. Choose your poison.

Here’s an example of what your HTML might look like.

  1. <div id="remarksform">
  2. <h3 id="respond">Leave a Remark</h3>
  3. <form action="http://slightlyremarkable.com/blog/wp-comments-post.php" method="post" id="commentform"><fieldset>
  4. <legend>&nbsp;</legend><br><br>
  5. <label>Name (required) <input type="text" class="input_text" name="author" id="author" value="" size="22"></label>
  6. <label>Email (required) <input type="text" class="input_text" name="email" id="email" value="" size="22"></label>
  7. <label>Web site <input type="text" name="url" id="url" class="input_text" value="" size="22"></label>
  8. <label>Your remarks<br> <textarea name="comment" id="comment" cols="50" rows="10"></textarea></label>
  9. <p class="commentnotes">Note: HTML is allowed. (<strong>&lt;a href=&quot;&quot; title=&quot;&quot;&gt; &lt;abbr title=&quot;&quot;&gt; &lt;acronym title=&quot;&quot;&gt; &lt;b&gt; &lt;blockquote cite=&quot;&quot;&gt; &lt;cite&gt; &lt;code&gt; &lt;del datetime=&quot;&quot;&gt; &lt;em&gt; &lt;i&gt; &lt;q cite=&quot;&quot;&gt; &lt;strike&gt; &lt;strong&gt; </strong>).</p><br>
  10. <label><input name="submit" type="submit" id="submit" value="Submit Comment"></label>
  11. <input type="hidden" name="comment_post_ID" value="220" class="hide">
  12. <div class="hide"><input type="hidden" id="_wp_unfiltered_html_comment" name="_wp_unfiltered_html_comment" value="279925c214" /></div>
  13. </fieldset></form></div>

The second step: the CSS.

I’m going to outline the CSS that added to my main style.css file. Mileage may vary; you can modify this to your own accord. This may not make sense now, but it will make sense once we get to the meat of the floating comment form feature. For now, create the following CSS (replacing “remarksform” with the id that you gave your comment form <div>).

  1. #remarksform {
  2. width: 60%;
  3. margin: 0 auto;
  4. }
  5.  
  6. #sfloatform {
  7. border: solid 1px #333;
  8. position: fixed;
  9. right: 5px;
  10. bottom:0px;
  11. background: #000;
  12. width: 20%;
  13. }
  14.  
  15. a.flink {
  16. padding: 10px;
  17. text-decoration: none;
  18. color: #999;
  19. display: block;
  20. text-align: center;
  21. }
  22.  
  23. #remarksform a.flink {
  24. display: inline;
  25. font-size: small;
  26. }
  27.  
  28. a.flink:hover {
  29. color: #fff;
  30. font-weight: bold;
  31. }

Next up: jQuery

As I mentioned before, we’re going to make all this magic happen in just a few lines of code, but it’s going to be based upon the incredible jQuery JavaScript library, so go download it, and put it on a location on your server that you can access. I put mine in a js subdirectory in my theme directory. It looks like this: /wp-content/themes/slightlyremarkable3/js/jquery.js. Be sure to include this code in the <head> tag of your header.php file in your theme directory. Here’s what it might look like.

<script src="/wp-content/themes/slightlyremarkable3/js/jquery.js" type="text/javascript"></script>

Finally: the real stuff

So now that all the pieces are in place — we have the HTML as we need it, the CSS for styling elements (that don’t even exist — yet!), and the JavaScript library uploaded and in our header — we need to actually write a script that will produce the feature we’re aiming for: the floating comment form.

Create a new JavaScript file — I called my “functs.js,” since I plan to use it for general functionality later in addition to the comment form, but you can calls yours whatever you want. I also placed this file alongside jQuery in my /themes/your-theme-name/js/ directory. Below is the JavaScript file that does all of the magic for my floating comment form. I’ll explain it after you get to see it.

  1. $(document).ready(function (){
  2. commentform = $("#remarksform");
  3.  
  4. if(commentform.is("div")){
  5.  
  6. commentform.css({
  7. position: "fixed",
  8. width: "40%",
  9. left: "59%",
  10. bottom: "1%",
  11. background: "#000",
  12. border: 'solid 1px #333'
  13. });
  14.  
  15. commentform.children("h3").append("<a href=\"#\" class=\"flink\" id=\"sfloatclose\">(Close me)</a>");
  16. commentform.hide();
  17.  
  18. $("BODY").append("<div id=\"sfloatform\"><a href=\"#\" class=\"flink\">Join the conversation!</a></div>");
  19.  
  20. sfloatform = $("#sfloatform");
  21. sfloatclose= $("#sfloatclose");
  22.  
  23. sfloatform.click(function (){
  24. $(this).hide();
  25. commentform.show('fast');
  26. return false;
  27. });
  28.  
  29. sfloatclose.click(function(){
  30. commentform.hide('fast');
  31. sfloatform.show();
  32. return false;
  33. });
  34.  
  35. }
  36. });

All right, so 30-some-odd lines of code. Not bad, huh? Let’s break it down.

Line 1 is your standard “do not execute JavaScript until the DOM has completed loading” command. This is very common and ensures that our elements are in place and actually exist before it attempts to access or otherwise manipulate them. More information about the DOMReady function is available in the jQuery Wiki.

Line 2 declares a variable, called commentform, to reference the <div> element that encapsulates our comment form. Remember earlier I told you that I called mine remarksform; be sure to change this to your <div>’s id, otherwise this will not work.

Line 4 checks to ensure that you are using a <div> element. If you are not, you will need to change this to reflect it. I recommend the <div> for semantics. The reason this line even exists is simple: this <div> element is not present on pages that do not have a comment form — you do not want this code to run on a page that does not have a comment form, so this if statement dictates that the code should only run if your comment form can be found in the (x)HTML code on the current page.

Lines 6-13 apply CSS code to the commentform object. You could alternatively change the class name and apply these CSS rules to your stylesheet (which may be faster, but I haven’t done any testing, since this seems to work fine — anyone that does test it, be sure to let me know what’s better).

Also, notice that one of the CSS rules applied is the position: fixed style. This will not work in browsers that do not support position: fixed. This naturally means that the comment form may be broken or completely unusable in Internet Explorer 6. But, really, who uses that anymore? If it becomes a problem, I’ll update the script later with IE6 support.

Lines 15-16 create a “close me” link and apply it as part of the h3 heading. If you do not have an h3 element titling your form, then you will need to change this to another element above the form that you can attach a “close me” link to. Notice that the “close me” link also has a class called “flink.” You can change this as you please, but remember that you will need to modify your CSS code as well. Line 16 uses the jQuery hide() function to render the comment form (in its entirety) invisible. This is how we have effectively “detached” the entire comment form area from the page.

Line 18 creates a link button that will be used to evoke the comment form. We don’t want to have the comment form floating around on top and in the way of everything, or hogging up screen real-estate unnecessarily, so of course we’re going to have it hidden by default, and then have a pleasant little link button that will bring it up when it’s needed. This is the opposite of the “close me” function. We have appended this link to the end of the body of our document. It has position: fixed already applied because of our CSS rules.

Lines 20-21 declare variables to identify (1) the sfloatform object (the link button we created in line 18) and (2) the sfloatclose object (the “close me” link that we attached to the h3 element earlier).

Lines 23-27 set the onClick event of the sfloatform object (the link button, line 18). Upon clicking the link button, it hides itself, shows the commentform object using jQuery’s default smooth transition (this can be controlled, by the way, and made to appear however you like!), and returns false so that the link doesn’t jump you to the top of the page (because its href is set to “#”).

Lines 29-33 set the onClick event of the sfloatclose object (the “close me” link, line 15). Upon clicking the “close me” button, the entire commentform object is hidden (once again, using jQuery’s default smooth transition, and this is customizable to different kinds of transitions such as fading out), the sfloatform object (link button, line 18) is once again revealed, and again the function returns false to avoid page-jumping.

Clean up

That’s about all there is to it. Do note that this script probably makes your comment form look terrible in Internet Explorer 6 or earlier, so if you’re aiming to continue supporting older versions of IE6, then the script will require some modifications. I’ll be happy to update the script with an IE6-compatible version if I get enough requests for it. Otherwise, enjoy the script. If you have questions, post a comment (using the notably amazing comment form). I’m also open to suggestions, such as better transitions or other, more intuitive ways of using the floating comment form idea.

Update: Jonathan Snook has imparted his wisdom by confirming April 2005 was when the floating comment form became a reality. Links updated accordingly. Thanks, Jonathan.

Update 2: I booted up VMWare for kicks, popped IE6/WinXP open to see what abomination IE6 has made of my Web site. It’s bad — real bad — but the comment form does actually show up, so besides looking like a pile of crap, the Web site actually works (with JavaScript errors). Well, at least it’s not a big deal at the moment.

Update 3: Ideas for changes to my script follow.

  • IE6 support (speak of the devil)
  • Class-based link button functionality (any (x)HTML element with a specific class-name will evoke the floating comment form)
  • Ajax support
  • Replying to specific comments (via Ajax)
  • A Wordpress widget/plugin

January 25th, 2009 | 9 Remarks

jQuery and UIs

I have become keen on JavaScript libraries since the early days… Prototype, Rico, Scriptaculous, moofx, and so on. They’re very powerful and useful for all sorts of things. I don’t go into the purpose or utility of JavaScript libraries here — I’ll leave that debate to others. What I am going to talk about is how useful jQuery, my library of choice (yes, I’m a John Resig fanboy), is. In specific, user interface design.

To get started, let me just throw out a quick example. It’s rough and I put a lot more in it than I would ever actually use in a web design, plus it’s images-free (no graphics). Still, it’s pretty sleek and requires (this is a big part) no additional plugins. In other words, you can build things like this using jQuery right out of the box.

View the example.

So you’ve seen the example, and you were blown away. I’m not going to cater to the “JavaScript newbie” here. As others will agree, if you don’t know JavaScript to begin with, you shouldn’t be using libraries or frameworks for it (or even writing the code at all, unless you intend on learning it correctly). In fact, I’m not even going to dissect my code because the comments should allow you to follow along (if you can’t already tell what’s going on because of how simple jQuery is). Really, I just wanted to bring to light the utility of jQuery and how it can be used. I thought this little script I wrote deserved more attention, particularly because I may be using it (in a modified way) in the future…

Oh yes, the future. My new company, Webtronic Media (which is still in progress and has not been officially launched), will be using the jQuery library for visual (and other functional) aspects of our site. Our intention is to produce sleek, Flash-esque visuals on top of XHTML 1.1 strict standard front-end code, but without the huge Flash player plugin (or processing!). We’re on the bleeding edge, and we want our web site’s presentation to reflect our passion for the balances of beauty and function, compatibility and efficiency. All I have to say is that you will all be blown away when Webtronic Media launches.

September 27th, 2008 | Remark

Minor Changes

I am slowly making minor changes throughout the site, one step at a time. The idea is to get into the habit of updating and playing with the site, little by little, rather than completely overhauling the site, only to abandon it again a few weeks later. (This is also why I have not created another blog design, although that may happen anyway.)

In any case, I’m sure you’re curious as to what minor change I’ve made today. Well, if you look on the blog home page at the leftmost of three near the bottom of the page, you’ll see a section titled “Blogmarks.” These are powered by del.icio.us (and a Wordpress plugin). I wanted to make the descriptions that I saved with my del.icio.us links to be available for those interested, but I didn’t want it to ruin my web page’s design. If the descriptions were displayed by default, it would create imbalance, lack of consistency and structure, and just look terrible.

My solution, of course, was JavaScript. A Show Descriptions/Hide Descriptions link appears only for JavaScript users, and a program automatically hides the descriptions when the page loads (so users without JavaScript will just get the less-amazing version of my design, with the descriptions showing by default).

The solution worked quite well. My JavaScript is powered by the moo.fx library (along with a lighter version of the Protoype library) because it is lightweight and relatively fast. However, Firefox has always had kind of its own hangup with the script, so the visual effect produced wasn’t as smooth as I wanted. I found that this was partially due to the fact that I was running the visual effects on multiple elements (ten of them) simultaneously. What I decided to do today was modify the script to apply the visual effects to one element at a time, creating a quasi-staircase effect rather than a slinky effect. Head on over to the blog home page and try it out for yourself. The effect you see is the change that I made. It’s optimized for speed and looks pretty sweet.

If you’re interested in the code, feel free to snoop around the source. The HTML that is output was generated by PHP, with the exception of the show/hide link that is output by JavaScript. There are LINK tags to the JavaScript files (the libraries and my separate script) so you can see what the code looks like. (The commented part in my script is what I removed, and two lines below the commented area is what I added, plus the function showDelinks() and some global variables for said function.)

Anyway, I’m proud of the fact that I’m making changes. Small, yes, but I am working progressively, and that’s a critical step at this point. And besides, it’s a pretty nifty script, if I do say so myself. =)

June 12th, 2008 | Remark

JavaScript’s Bad Name

This article is, in essence, a load of hogwash aimed at frightening the everyday computer user, possibly to the point of disabling JavaScript altogether (which is suggested, believe it or not, in the article). My blood really boils when I hear people making such comments about JavaScript. JavaScript is powerful, versatile, useful, practical, and anything that sounds that good must have some sort of flaw. Yes, JavaScript is not 100% secure 100% of the time, but for the most part it is, and for the most part (unless you’re visiting warez sites) you won’t be attacked by it. The best thing to do is get a good browser and avoid suspicious web sites. It’s very simple, but of course News.com doesn’t point this out, because the goal of their “FAQ” is to turn the modernized “Web 2.0-style” Internet of today into the plain text, non-interactive, boring resource it was in the past.

Someone please help me understand what they hope to accomplish by publishing this article. This article is the kind of thinking browser developers used to have, and as a result it’s taken many years for CSS to become even partially supported by more than just a couple user agents. Stop living in the stone-age! People who hate change may be satisfied with the way things currently are, but not everyone is, and modernization is critical to any industry, because otherwise it becomes stagnant, boring and useless. The Web should advance a free market (yes, that means the whole “net neutrality” thing is a bunch of junk, too), not one controlled by the fearful and limited by the ignorant. I’m not saying anyone should be ignorant of the facts, but when you write an article and your tone indicates a distaste for something, people naturally respond in agreement and therefore have a bad first impression because they are skeptical.

Anything that has a purpose has potential flaws. We’re a democracy in a republic, but try as we might, we aren’t perfect. There have been presidencies that were crime-ridden and powers that were abused, and in the same way that these were serious issues that were eventually resolved, JavaScript has some security issues that will eventually be resolved (and many, in fact, most, have been already). There is no need to fear or avoid what has potential for both good and evil. Let’s stop thinking like monkeys and get our heads on straight, instead of suggesting we suppress all possible change because our current system “works fine” or “is bad enough” as it is.

July 29th, 2006 | Remark

Ajax Toybox

Justin’s examples include an ajax-powered clock, RSS news feed ticker, calculator, and city/state look-up. You can check out the demo or read what Justin has to say about it. Thanks, Justin!

March 13th, 2006 | 2 Remarks

Google Homepage Translate

It’s still rough around the edges and the code needs to be optimized heavily (also you can’t run multiple instances of the Google Translate module on the same page, although I don’t know why you would need to), but it’s basically done.

If you’re a Google Personalized Homepage user (like you should be), the way to use the module is simple. Go to your personalized homepage, and click the “Add Content” link at the top-left of the page. On the bar that expands out, look down for “Add your own content.” Click it, and it’ll give you a text field to enter the address to an RSS feed or a module. Type in: http://base.google.com/base/items?oid=2965185083363856584 and hit “Go.” The Google Translate module should appear on your personalized homepage now. Feel free to leave comments, suggestions, and so forth, but remember it’s not refined; I only had a few minutes to work on this thing yesterday, and there are a lot of optimizations that could take place to make it work better all around. Enjoy!

December 15th, 2005 | 3 Remarks

Greasemonkey Hacks

The best part about this book, I’m not quite sure about yet. Thus far it looks to be very informative and useful as a resource, but there’s much more to this book for me.

Before the book was published, sometime mid-summer, I got an email from Mark Pilgrim asking for permission to use my Smart Firefox Greasemonkey script in his book (the script is featured on pages 86-89). Although I would have consented immediately regardless, Mark offered in return a free copy of the book when it was published and a small paragraph about me in the credits section. Thus, for writing a free Greasemonkey script, I got a free book and some publicity (as my web address is printed in the “about me” paragraph). Is that cool or what?

November 30th, 2005 | Remark