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.

TinyMCE and the relative URLs SNAFU

My CMS, cms34, uses a few third-party tools for certain complex features. One of the most useful is TinyMCE, a JavaScript/DOM-based drop-in WYSIWYG text editor. If that doesn’t mean anything to you, you probably want to stop here, but in case you’re a glutton for punishment, it is, in short, a way to produce HTML-formatted text with a word processor-like interface. Think Microsoft Word in a web browser, with the results being formatted for display on a web page. Slick.

Anyway, there’s been one nagging problem: When users paste in URLs for links, TinyMCE converts any on-site links into “relative URLs” — it strips out the domain name. This is not necessarily bad; in fact, for the most part I would want it to do that. But for some reason the nature of my CakePHP-based CMS seems to confound TinyMCE’s ability to properly determine the relative URL. And what’s worse, the CMS includes an enewsletter editor which has to have absolute URLs, but TinyMCE was converting them to relative URLs even if the user pasted in an absolute URL.

A little research led me to a handy explanation in the TinyMCE Wiki. Basically, if you want your URLs to always be absolute, make sure your TinyMCE configuration includes the following:

relative_urls : false,
remove_script_host : false,
document_base_url : “http://www.site.com/path1/”

Of course, you’ll want to change the value of document_base_url to be the actual base URL of your website. As it happens, my CMS has a global JavaScript file that creates a variable called baseUrl that I can use anywhere in JavaScript to substitute for the full base URL of the website. So, in my case, I set the value for document_base_url equal to baseUrl.

And, voilà, it seems to work!

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

Assembling the web designer’s toolkit

Web designers need a lot of tools at their disposal. Mostly this comes in the form of commercial software. If you don’t own the full Adobe Creative Suite, you at least have Photoshop (or, if you’re a FOSS contrarian, GIMP). If you’re on a Mac, you probably have BBEdit (or its free sibling, TextWrangler) installed, and if you’re on Windows… well… I don’t know. Does anyone who takes themselves seriously as a designer use Windows? I’m sure we’ll hear from them in the comment section.

But what I’m talking about here is not the commercial software applications you have installed on your desktop. I’m talking about the free libraries you probably need these days to get a “Web 2.0” site up and running.

I’ve been finding myself lately starting each new project by cobbling together the same set of these libraries, so this morning I decided to save myself some time on my next project by putting together a template set with all of them in place. Once I’ve had time to review all of the requisite licenses, I may post the complete package in a zip file here, but for now, here are some pointers to get you started.

jQuery

Where better to start than with this easy-to-use, infinitely extensible JavaScript library? I can’t imagine working without jQuery anymore. It makes just about everything JavaScript-related several orders of magnitude easier to work with. And then of course there are a handful of plug-ins I like to bring along for the ride: color, dimensions, em, hoverIntent, lightbox, mousewheel and jScrollPane. (Actually, several of those are required just for jScrollPane, a complex and tricky-to-implement plugin, but if you need custom scrollbars, it’s worth it.)

Lightbox for jQuery

I especially want to call attention to Lightbox for jQuery, based on the original Lightbox for Scriptaculous (see below). It’s a great way to add some nice polish to your site. Whenever a user clicks on a thumbnail to see a larger version of an image, you no longer need to subject them to an ugly and confusing plain browser window with the image in the upper left corner, or trigger a new pop-up window to appear. Lightbox uses CSS and JavaScript to elegantly apply a translucent mask over the existing page and present the image in a centered layer hovering over the rest of the page, in the same browser window. Slick!

Scriptaculous

On the other side of the JavaScript library fence, we have Scriptaculous, built upon prototype.js. It’s not quite as slick or as powerful as jQuery, but it handles AJAX without additional plugins. Honestly, I haven’t tried much AJAX with jQuery, but since CakePHP‘s built-in AJAX helper relies on Scriptaculous, I’ll probably still have a place for it, for a while. The snag is that jQuery and Scriptaculous, with their default settings, don’t play nicely; they both want to use the $ variable for themselves. But jQuery’s noConflict() method makes it easy to get these two powerhouse libraries to get along.

IE7.js

This is my least favorite of the tools described here, for two reasons: 1) it’s essentially just a patch for Internet Explorer without adding any new functionality for general use, and 2) it reminds me that Internet Explorer exists.

That said, it’s indispensable. The issue here is simple: IE6 doesn’t support a lot of “modern” features that other browsers do, and that are becoming increasingly essential to how the Web works, but unfortunately, IE6 is still one of the two most-used browsers in the world (the other being IE7). Firefox is growing rapidly in popularity; Safari is ubiquitous among Mac users; and the Web is increasingly experienced via mobile devices, but for now, IE is still king of the hill, and a large percentage of IE users can’t, won’t, or don’t even realize they can upgrade beyond version 6.

IE6 can be taught new tricks, however, and that’s the purpose of IE7.js. It’s a JavaScript library that “teaches” IE6 to behave more like IE7, fixing some common and infuriating CSS bugs, adding support for alpha channel transparency in PNG images, and various other “magic” that pretty much all just takes place seamlessly, behind the scenes. Just call this library and let it do its stuff.

SWFObject

If you’re using Flash at all, it’s helpful to bring along SWFObject, another JavaScript library whose sole function is to relieve the attendant headaches of working with <object> and <embed> tags and the suckitude of Internet Explorer browser inconsistencies.

sIFR

In the past, whenever web designers needed text to appear in custom fonts (that is, any fonts that are not already installed on the user’s computer), there was only one option: make an image out of it. Maintenance nightmare. Enter sIFR, a JavaScript-and-Flash-based solution. You’ll still need a copy of Adobe Flash (the full application, not the browser plug-in) to make it work, but the end result is your font encapsulated in a SWF file, and some very clean JavaScript that seamlessly swaps your custom font in place of regular, plain vanilla HTML, and degrades gracefully to a standard font if the user is lacking either JavaScript or the Flash plug-in. And it’s fully semantic and validating.

The only downside of sIFR is that finding the latest version is a bit of a mess. But here’s a good place to start.

TinyMCE

And finally we come to TinyMCE. At last we have a decent solution to the dilemma of allowing users who probably don’t know HTML to enter styled content on your site. It’s not without problems, especially where pasting from Microsoft Word is involved, but TinyMCE is a great WYSIWYG solution, a word processor in a browser window.