How to deal with cloning or dynamically loading new form elements (like radio buttons) in Internet Explorer (IE) using jQuery
It's a horrendously long blog title, I know, but I wanted to mash in all the keywords I was looking for when trying to find a solution to this very sticky problem so that other folks running into the same issue can spend the next six hours doing something more productive.
jQuery makes grabbing one group of elements from a page, duplicating them and adding them somewhere else really easy. You just use a combination of clone() and something like append(), as in the following:
$('#surrounding_div').clone().appendTo('#some_other_div);
The problem with dynamically adding form elements in IE
Woot! So easy! Right, until you start goofing with forms and IE (Internet Explorer) (appropriate sound). The problem is that IE doesn't allow you to manipulate the 'name' attribute in the DOM directly. So, something like this won't work:
$('#form_element').clone().attr('name', 'new-name').appendTo('#my-form);
If you do that with a radio button, the interface will tell you that there's a problem, because since the new radio button has the same name as the original one, only one can be selected. Bugger!
Luckily, the solution is clear, but it took forever to figure it out. Instead of adjusting the name attribute directly with something like attr(), you need to edit it manually in a block of html and then add that html to the page. So, something like this would work:
$('#form_element').parent().html().
replace(/orignal_name/, 'new_name').appendTo('#my-form');
There's a couple of key points here:
- Because we're getting the html using $.html(), we need to move up the DOM to grab the element surrounding the element we wish to add using $.parent(), then we can grab the html using $.html().
- I'm using the javascript replace() function to pass a regex pattern and replacement text to the html.
What about dynamically cloning groups of inputs with jQuery?
In my particular use case, I was grabbing a set of form elements and adding them this way. There were a couple of challenges, which was that I couldn't use $.parent() to get the outer element, and the other was that the names of the form elements were being set dynamically. I learned a couple of tricks to help with this:
Use the regex modifier /g to replace all insteances of a pattern. So, when doing replace(), if I needed to replace ALL instances instead of just one, it would look like this:
replace(/original_name/g, 'new_name')
Because I couldn't use $.parent(), in the end I had to wrap an element around the html using simple contatination, like so:
var newHTML = '<div>' + $('#element').html() + '</div>';
I hope that helps you, it was sure a bugger to figure out.
Recent blog entries
Twitter feed:
- Letter to a disgruntled module user http://is.gd/eLI2y3 days ago
- How to easily upgrade Drupal from one minor version to another with a patch file http://is.gd/ezL2s1 week ago
- Restarting my mac for the first time in 24 days #fb2 weeks ago
- Why does it always catch me off guard when people don't look like their profile pics? I should be used to this from my internet datin... #fb2 weeks ago
- @rock_soup What command was that?2 weeks ago
- @dale42 A belated agreement about the devil's work in absolute URLs. :)2 weeks ago
- Save the Planet! Well, the Drupal Planet (actually, the Drupal Planet log files) http://is.gd/egxwt2 weeks ago
- The Save Joseph campaign is over, thank you! (plus, summarization of social networking techniques applied) http://is.gd/eb1Y1 #fb3 weeks ago
- @simonsurtees Great re:evernote offer. In next steps I want to improve API and allow for collaborative content creation. Should be fun!4 weeks ago
- Only 12 hours left to Save Joseph - $150 bounty, infinite karma points, excitement abounds! http://savejoseph.org #fb4 weeks ago
Topics
- activism
- apple software
- book reviews
- design
- Drupal
- drupal administration
- drupal community
- drupal events
- drupal modules
- drupal resources
- freaky stuff
- geeky entertainment
- iphone ipod touch
- jquery
- learning
- life hacks
- looping
- maps
- minimalism
- music
- philosophology
- presentations
- productivity
- rambling
- restraint
- software
- theming
- treadmill desk
- usability
- usability testing
- video demonstrations
- web hosting
- original songs
- This American Life
- evernote
Blog archive
- March 2009 (2)
- April 2009 (15)
- May 2009 (10)
- June 2009 (3)
- July 2009 (3)
- August 2009 (6)
- September 2009 (2)
- October 2009 (4)
- November 2009 (3)
- December 2009 (1)
- January 2010 (1)
- March 2010 (1)
- June 2010 (1)
- July 2010 (46)
- August 2010 (5)










Comments
Thank you SO much for writing about this. What a lifesaver to know what was going on under the hood.
As a heads up, I made what I believe to be an improvement upon your solution. It takes more code, but it is more precise in the replacement since the parent may contain a bunch of HTML that you don't want to muck with and accidentally replace something important. Here's what we did.
var myElement = $('#element');if ($.browser.msie) {
myElement.replaceWith(myElement.outerHTML.replace(/original_name/g, 'new_name'));
} else {
myElement.attr('name', myElement.attr('name').replace(/original_name/, 'new_name'));
}
Note that this works because IE respects outerHTML, but other browsers (notably Firefox) do not. So I use the best way whenever possible, but when it comes to IE, we restrict the replacement to outerHTML which contains the string representation of the element.
This worked fine for us.
Thanks again for the help!
it makes me wonder why jQuery doesn't do this by default...
Post new comment