JQuery clone() not maintaining "checked" state

If never been much of a front-end developer, but as most developers I manage my tags pretty well;-) but javascript has always been hell. I always stayed away from it but with JQuery the ballpark has changed a lot! Traversing the DOM has never been simpler, adding elements and attributes, moving them around, Childs play.

Yesterday my college noticed that the functionality I build for selecting checkbox items in div-popup’s didn’t work in IE8. So I’ve been puzzling why this was happing, this morning I found the culprit, it was the usage of the JQuery Clone  method.

JQuery offers a function to copy a element with all its events but as I found out the hard way checked state isn’t maintained during the function execution under Internet Explorer 6/7/8.

Which basically SUCKS!

After a lot of searching, I found out that there is a long standing bug ticket in the JQuery bugtracker. The bug is still unresolved but there where some workaround posted in the comments.

The workaround I chose is to implement was to override the clone function from JQuery itself. Note this clone function wasn’t approved to put in the core of JQuery due to performance reasons.

Overriding is quit simple just put the following script function in a javascript tag in your page (or separate file) . And call the function, the overriding magic is just on line Number 8.

   1:  function overrideJqueryClone() 
   2:  {
   3:      (function () {
   4:          // Store a reference to the original remove method.
   5:          var originalRemoveMethod = jQuery.fn.clone;
   6:   
   7:          // Define overriding method.
   8:          jQuery.fn.clone = function (deep) {
   9:              deep = deep != undefined ? deep : true;
  10:              var $this;
  11:              if (jQuery.browser.msie) {
  12:                  $this = this.add(this.find("*"));
  13:                  // Need to remove events on the element and its descendants
  14:                  $this.each(function () {
  15:                      this._$events = {};
  16:                      for (var type in this.$events)
  17:                          this._$events[type] = jQuery.extend({}, this.$events[type]);
  18:                  }).unbind();
  19:              }
  20:              // Do the clone
  21:              var copy = false, r = this.pushStack(jQuery.map(this, function (a) {
  22:                  if (!copy && deep && (a.hasChildNodes() || jQuery.nodeName(a, "select") || jQuery.nodeName(a, "input"))) copy = true;
  23:                  return a.cloneNode(deep);
  24:              }));
  25:              if (jQuery.browser.msie) {
  26:                  $this.each(function () {
  27:                      // Add the events back to the original and its descendants
  28:                      var events = this._$events;
  29:                      for (var type in events)
  30:                          for (var handler in events[type])
  31:                              jQuery.event.add(this, type, events[type][handler], events[type][handler].data);
  32:                      this._$events = null;
  33:                  });
  34:              }
  35:              // copy form values over
  36:              if (copy) {
  37:                  if (!jQuery.browser.msie)
  38:                      $this = this.add(this.find("*"));
  39:                  var origInputs = $this.filter('select,input[@type=checkbox]');
  40:                  if (origInputs.length) {
  41:                      var inputs = r.add(r.find('*')).filter('select,input[@type=checkbox]');
  42:                      origInputs.each(function (i) {
  43:                          if (this.selectedIndex)
  44:                              inputs[i].selectedIndex = this.selectedIndex;
  45:                          if (this.checked)
  46:                              inputs[i].checked = true;
  47:                      });
  48:                  }
  49:              }
  50:              // Return the cloned set
  51:              return r;
  52:          }
  53:      })();
  54:  }
  55:   

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

 

Simple isn’t it 🙂

Advertisement

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s