Another obscure WordPress problem: setting document.domain for cross-site scripting iframes breaks Gravity Forms AJAX submissions

Whew… that title was almost as long as the variable name I’m about to throw out in a code example.

I spent well over an hour beating my head against the wall on this problem today before narrowing it down to a Gravity Forms issue. The scenario: I have a site that is loading iframes from a different subdomain. As is common in this situation, I wanted to be able to adjust the height of the iframe with JavaScript, to match the height of the page within the iframe and prevent internal scrollbars.

The solution to that problem is readily available on teh interwebz, with the addition of a bit of extra JavaScript to allow cross-site scripting: both the containing page and the contained page need to specify the same document.domain so browsers will let them talk to each other.

Not long after we put this in place, my client informed me that none of their AJAX-based Gravity Forms were working. The spinner would just spin indefinitely, even if (usually) the form actually did submit properly. It didn’t take me long to narrow the problem down to a JavaScript error pertaining to cross-site scripting. I found that AJAX and document.domain don’t mix. Or at least that seemed to be the issue.

But that’s where I hit a wall. No one else seemed to be describing the exact problem I was having. Most solutions involved adding a Access-Control-Allow-Origin header, but that didn’t do anything for me.

Eventually I realized that was because the problem wasn’t with the AJAX, per se. It was the fact that Gravity Forms adds its own hidden iframe where it works some secret mojo on AJAX submissions. And that iframe needed to have document.domain added to it, just like my site and the other subdomain I was loading in iframes did.

So the question then was, is there a Gravity Forms hook to modify its iframe output? Fortunately, the answer is yes.

The gform_ajax_iframe_content filter pretty much does what it says on the tin. Add a filter to insert the necessary JavaScript, and you’re good. The only thing I don’t get about this is the name given to its lone input parameter. I mean, really? (Actually… I do think I understand it, but I don’t understand it.)

Anyway… here’s what you need to make this work. Just replace example.com with the correct domain name. And if you’re running on a version of PHP before 5.3, you won’t be able to use an anonymous function. But you’re not running an old version of PHP, are you?

add_filter('gform_ajax_iframe_content', function($doctype_html_html_head_meta_charset_utf_8_head_body_class_gf_ajax_postback_form_string_body_html) {
  echo "<script>document.domain = 'example.com';</script>\n";
  return $doctype_html_html_head_meta_charset_utf_8_head_body_class_gf_ajax_postback_form_string_body_html;
});

Web standards: a Win-Win-Win situation

Today is the fourth annual “Blue Beanie Day,” a tradition established by the father of web standards, Jeffrey Zeldman.

What are web standards? Simply put, they’re awesome. But seriously… the goal of web standards is to establish a set of best practices for web designers and developers, and a set of open, shared languages and tools for building websites and displaying them in a consistent manner.

At the heart of the modern web standards movement are a set of three core languages: HTML5, for organizing and structuring content; CSS3, for designing the presentation of that content; and JavaScript, for providing rich interaction with that content.

HTML5, CSS3, and JavaScript are all open standards. The specifications are published for anyone to see; they’re open and evolving, for anyone to contribute to; and they’re freely available for anyone to build an application for rendering content delivered via these languages (in common parlance, a web browser, but we’re starting to see “web” content appearing in all sorts of applications for computers and mobile devices these days).

But why are these three web standards so great? Because they create a win-win-win situation:

A win for web designers/developers. By establishing a common set of tools that are open and free to anyone, web designers and developers can get started with no barriers to entry. Plus, by standardizing these tools, the same skills can be applied anywhere a website is being built. And as web browser makers adopt these standards, the last 15 years’ worth of browser-to-browser inconsistency will fade. Our job is made easier, we can get more done in less time, and, with powerful frameworks like jQuery built on top of these standards, this power to do more with less will grow exponentially.

A win for site owners. If you’re paying to build a website, you want to know you’re spending your money wisely. You want your investment to last, and you want to make sure everyone who wants to access your site, can. Web standards are the key to an accessible, reliable, “future-proof” website. Some Internet technologies may come and go; jumping on the latest trend may make your site seem “with it” today, but tomorrow it will be painfully dated… if it even works at all. But these three core web technologies will always be at the heart of the web. Plus, a site built with web standards will automatically be structured well for search engine listings, without the need for expensive and questionable SEO tactics.

A win for Internet users. Web content that is built and delivered with a diligent adherence to web standards will work reliably with any device, any software, that is used to access the Internet. Plus, no well-formed, standards-compliant HTML page ever crashed a web browser.

Web standards: Win-Win-Win.

Reason enough (for me) to install Windows (and Google Chrome)

Sure, I own a real NES. Two, in fact. I also own a GBA Micro, Nintendo DS, and a Wii, with emulated versions of all of my favorite NES classics. And then, of course, there’s emulation.

But as a web developer, I just have to geek out on this: the very idea of a working NES emulator running entirely in JavaScript… wow. I’ve known about JSNES for a few months, but I hadn’t had the time and/or inclination to fire it up in Google Chrome (still Windows-only), the only browser so far that has a JavaScript interpreter efficient enough to run it at a decent frame rate.

The last time I tried running it was on the iPhone. Yes… it did run… at about 1.5 FPS. And, of course, there’s no way to access the controls. But in Chrome… it’s actually playable. A smidge slower than the real thing (which would be at 60 FPS), but as you can see, I got it up to 46 FPS. Not bad. Especially considering that I was running Windows 7 with Parallels Desktop on the Mac. Nice!

JSNES

Web 2.0 — opening up a whole new world of Internet Explorer quirks!

Just when I needed it least, Internet Explorer has thrown me another curveball.

I’m hard at work trying to seem like less of a 20th Century web dinosaur by acquiring new skills with these techniques that are loosely lumped together into what some call “Web 2.0.” Key among these is an approach called AJAX (Asynchronous JavaScript and XML). Fun stuff. I’ve been working for the past several days on an interactive registration form for a site at work, using AJAX. Of course, as usual, I’m plugging away in Safari and Firefox, but eventually I decided to check out how things are looking in Internet Explorer.

[When I figure out an emoticon that represents my head exploding, I’ll insert it here.]

IE is consistently barfing on what it claims is a syntax error that I eventually tracked down to the evalScripts function in prototype.js. Well, at least it’s not my own code that’s making it crap out this time. Or is it? With IE you never can tell. Maybe evalScripts is buggy (even though I can find no evidence to that effect) or maybe it’s just the code in my script that’s being thrown at it. Whatever the case, once again all forward progress has come to a grinding halt while I scour the Internet fruitlessly for a solution.

Although this turned out not to be a solution to my problem, I just have to refer you to this developer’s blog entry on a typical IE workaround. Yes, I tried this, even though I was almost positive his problem was completely unrelated to my own (which was the case). Nevertheless, when a problem does arise in IE, the most likely eventual result of one or more days’ worth of sleuthing is the resigned acceptance of such hokey code bloat, rather than anything even remotely satisfying (or even logical).

There you have it. As for my own problem using prototype.js with IE, I did find a solution. Yes, it was my code, and it was something I had seen previously that was pretty much staring me in the face, if I had just bothered to heed Thomas Fuchs’s sage advice.

It all comes down to standard practice for wrapping <script> tags in HTML. I still have the habit of doing it this way:

<!–
//–>

The funny thing about that is that I know it’s completely pointless these days. It’s done so that browsers that don’t support JavaScript don’t inadvertently display the JavaScript code in the web page. But every browser has supported JavaScript since about 1997, so it’s pretty ridiculous to keep doing that. Especially given that, the way the sites I’m working on are so utterly dependent upon JavaScript, you’d never even get to the page in question without it.

However, with XMLHttpRequest (which is at the heart of AJAX), and just the increasing complexity of JavaScript in general, it’s become necessary to wrap script code in a new tag to ensure that browsers handle the code properly. To wit:

// <![CDATA[
// ]]>

Just as Thomas Fuchs said. And just as has been lingering in the back of my mind for the past several weeks, since I first discovered his wonderful tool based on prototype.js, Scriptaculous. I’ve learned my lesson.