Journal

Clone Fieldset

12 August 2006 › 12 comments

Clone-o-Matic: Example | Download

Recently, I had the need to be able to asynchronously duplicate portions of a form, arbitrarily based on what the user might want to do. The requirements were such that the script needed to be reusable multiple times per page. After having read the book DHTML Utopia by Stuart Langridge, I knew that something along the lines of his free beer example would be needed.

The example in the book was simple, duplicating a single input text field by constructing the various aspects using DOM scripting. To do this for large chunks of a form would be tedious, and would tie my JavaScript to the specific functionality of the form, necessitating slight rewrites for each instance. Likewise, an innerHTML dump would keep it confined in the *.js file.

So, I thought the cloneNode method might be a better way to go. Initially, after some searching around, I happened upon the solution offered on Quirksmode, Extending Forms. He has a clever way of doing it, with an invisible template, so to speak. This is cloned and set to display: block so that the subsequent duplicates are usable. It also uses an empty span with an ID as the insertion point in the document. It increments a counter so ID / name will stay unique within the form, lest duplicate data be submitted.

This was the launching point for my idea. Yet, I wanted something more modular and reusable, without the need for unusable hidden templates or extraneous span’s. I believe that what I have come up with is a nice plug-and-play method. Essentially, it looks for the nearest parent fieldset, clones it, adds a suffix + counter, then inserts the copy after the original.

The initial fieldset contains both an Add and Delete button, with deletion hidden by CSS. When the copy is made, a class of duplicate is added, causing the Delete button to appear, and the Add button to disappear. I also use it to re-color the fieldset, giving a visual indicator of the cloning.

You might notice that the clone and delete functions are called directly with an onclick event. Before you harp on that being too intrusive, I should mention that it was done this way because traversing through to find class names didn’t account for the elements created after page load. So, rather than iterate through during each cloning, I went for the quicker route of just cloning the function call to cloneMe() and deleteMe() in the fieldset itself.

With JavaScript off, they are simply dead links pointing to an unnamed anchor of #, but could just as easily be hooked up to a server-side environment that would load a new fieldset with a page refresh. Either way, the potential is there for the same essential functionality, offering instantaneous feedback for those with JavaScript, and degrading gracefully in situations without it.

If you so desire, you can also nest fieldsets. The JavaScript is done in such a way that the suffix of :N (with N being the counter) is found, and then stripped out, so a new counter can be added. That way, if you don’t end up with the problem of foo2 + 3 = foo23. I chose the delimiter of [:] because it is valid as part of an ID / name in XHTML, while still being unlikely enough not to conflict with any typical naming scheme using underscores or dashes.

I’m sure it can probably be improved upon, and that is of course why I’m releasing it – so that it can be a starting point for others faced with similar problems to solve. I want to thank Ara Pehlivanian for helping make the script self-referential, and Jonathan Snook for his ideas on incrementing a counter for nested fieldsets. Also, thanks to Jeremy Keith for his insertAfter method, described in his book DOM Scripting. I guess that wraps it up!

Discussion + Dissension

  1. #1 Jon

    Really cool example, Nathan. As you had said, writing up a quick server side solution for those who don’t have JS enabled would pretty much wrap things up and give you a comprehensive way of cloning forms. There was a time a few months ago where having this example would have come in extremely handy but the project was dropped. I’ll be sure to remember it for future use. Good job!

  2. #2 kartooner

    Nice work, Nathan.

    Not only does it look slick, it also functions extremely well. I might be steal.. err, using this on a project I’m currently working on.

  3. #3 Matthijs

    Indeed great work. Have been looking for something like this (also saw the example in Stuarts book), so thanks for showing.

  4. #4 Justin Perkins

    Awesome little bit of code there, nice job.

    Re: inline event handlers…sometimes they just make sense, I wouldn’t pay much attention to those who harp on you :)

  5. #5 Dustin Diaz

    The variables and function names are a bit too generic for sitting out in global land. Things like “deleteme(), cloneMe()” and “suffix” and “counter” are very likely to get overridden when integrating with existing web applications. Otherwise, good job mate. :)
    The inline event handlers are really no big deal, but you should provide a mechanism that could be supported in both cases.

  6. #6 Nathan Smith

    Dustin: Thanks for the feedback, I appreciate it. I suppose it could benefit from some name-spacing. I hope to further develop this script in the future.

  7. #7 Nathan Logan

    Very nice, very nice. It turned out great. And I love the example – you’re one creative guy.

  8. #8 abba bryant

    Am I allowed to convert this to jquery and email it to you? I think it would make a good comparison of “roll your own” vs “roll with jquery” and might actually be a rad showoff for some of the form plugins as well.

    Email me and let me know please.

  9. #9 Nathan Smith

    Abba: Sure, go right ahead! I have been getting a bit more into jQuery myself lately, and am curious to see how it would be done. Thanks for the offer.

  10. #10 Mark Priestap

    Nice work as usual Nathan!

  11. #11 Samalah

    Thanks for sharing such a great script! I’d been looking for something like this for a long time, and it’s so timely and perfect. Thankyou!

  12. #12 Nathan Smith

    Mark: Thanks bro, I appreciate it.

    Samalah: You’re welcome. I’m glad you found it helpful!

Comments closed after 2 weeks.

FYI


Member of 9rulesHosted by Mosso

Advertisement

Ads by SidebarAds

Latest Posts: All - RSS

My Book

Textpattern Solutions I had the privilege of co-writing Textpattern Solutions for the web technology publisher Friends of ED. If you want to develop a professional dynamic web site, without the hassle of writing all the server-side code from scratch, then Textpattern could be just the solution you are looking for.