title: Using jQuery remove() to add items. When adding back same items, class changes are preserved
body: <p>I have some elements in my HTML which are generated entirely by jQuery, and then removed when no longer needed.</p>
  
  <p>Something along these lines:</p>
  
  <pre><code>var div = $('&lt;div/&gt;').attr('id', 'addedItem');
  $('body').append(div);
  </code></pre>
  
  <p>For example, then when closed we do:</p>
  
  <pre><code>$('#addedItem').remove();
  </code></pre>
  
  <p>BUT... during the course of it's use, we might change the classes of <code>addedItem</code> due to adding another feature to it, for example, adding <code>tinyMCE</code> to a <code>textArea</code></p>
  
  <pre><code>$('#textAreaId').tinymce({ vars });
  </code></pre>
  
  <p>Adds a rich text editor to a text area (providing all the correct scripts are loaded), I have added a new line to the end of <code>tinymce()</code>:</p>
  
  <pre><code>$(applyTo).addClass('editorLoaded');
  </code></pre>
  
  <p>To stop the code from trying to add the editor to the same element twice.</p>
  
  <p>This all works lovely... BUT...</p>
  
  <p>If I close this window down and thus call the line <code>$('#addedItem').remove();</code> and then later on (without page reload) I want to re-add to the page and display again, the classes added to the elements remain.</p>
  
  <p>So, in short. An element with an ID <code>addedItem</code> is added to the <code>body</code> by jQuery, stuff is done to it and it gets a class attribute added to it. After it's finished with jQuery completely removes the element. A bit later on, we add a new element with the ID <code>addedItem</code> to the <code>body</code> using jQuery again, it's a fresh element, but yet it retains it's class attribute added before removal!</p>
  
  <p>According to jQuery DOCS <code>remove()</code> behaviour should be:</p>
  
  <blockquote>
    <p>In addition to the elements themselves, all bound events and jQuery
    data associated with the elements are removed.</p>
  </blockquote>
  
  <p>Which I take to mean it should remove any classes added to the elements with jQuery as well as data etc... maybe I am reading it wrong, misinterpreting, or something else!</p>
  
  <p>Can anyone help me to remove these elements and ALL references to them in browser memory/cache/whatever so I can manage this issue.</p>
  
  <p>jQuery version is 1.7.1 if that's any help</p>
  
  <p>==========   EDIT > MORE CODE  ADDED ================</p>
  
  <p>The above outlined my problem, here's the actual code then </p>
  
  <pre><code>// create a modal window with a top right X closer from any element
  $.fn.makeModal = function (vars) {
      var theId = $(this).attr('id');
      var exists = false;
      try {
          if ($('#' + theId + '_wrap').length &gt; 0) { // firstly check the element has already been "made modal"
              exists = true;
          };
      } catch (err) {
          exists = false;
      };
  
      if (!exists) { // if this is the first time
          var win = this;
          var h;
          var w;
          var persist;
          var alert;
          if (vars) {
              h = vars.height;
              w = vars.width;
              persist = vars.persist;
              alert = vars.alert;
          };
          if (typeof h == "string") {
              h = (h.replace('px', '') * 1); // clean out px if dimensions posted in px
          };
          if (typeof w == "string") {
              w = (w.replace('px', '') * 1); // clean out px if dimensions posted in px
          };
          var hRatio = 0.70;
          var wRatio = 0.5;
          var minW = 480;
          if (!h) { h = $(window).height() * hRatio }; // default case if no height passed
          if (!w) {
              w = $(window).width() * wRatio;
              minW = 480;
              if (w &lt; minW) { w = minW };
          }; // default case if no width passed
  
  // **** END BASIC VARIABLES
  
          var wrapper = $('&lt;div/&gt;').attr('id', theId + '_wrap').addClass('modalContainer').css({ 'top': ($(window).height() - h) / 2, 'left': ($(window).width() - w) / 2, 'width': w, 'height': h }); // create a wrapper for the main content
          var close = $('&lt;span/&gt;').addClass('closeModal').html('X').css({ 'z-index': getMaxZIndex() + 5 });
  
  // creat  close button
          if (alert) {
              $(close).addClass('alert');
              $(wrapper).addClass('alert');
          } else {
              $(close).addClass('cross');
          };
          if (persist) {
              $(wrapper).addClass('persist');
          }; // persist variable allows you to determine whether to delete or simply hide element on close
          $(win).addClass('modalContent').css({ 'display': 'block', 'width': w - 20, 'height': h - 20 }).appendTo(wrapper);
  
          $('body').append(wrapper).opaqueBg();
  
          $(wrapper).prepend(close).fadeIn('fast').css({ 'z-index': getMaxZIndex() + 3 });
          $(close).modalCloser();
  
          $(document).on('keyup', function (e) {
              if (e.keyCode == 27) {
                  closeModal(wrapper);
                  $(document).unbind('keyup');
              };
          });
      } else {
          $('body').opaqueBg();
          $('#' + theId + '_wrap').fadeIn('fast') // .children().css({ 'display': 'block' });
      };
      // END OF MODAL WINDOWS
  };
  </code></pre>
  
  <p>The jQuery function above creates a modal window out of any element dynamically created or otherwise.</p>
  
  <p>Associated functions for closing etc:</p>
  
  <pre><code>//  top right X closer actions
  $.fn.modalCloser = function (callBack) {
      $(this).bind('click', function () {
          $(this).closest('div.modalContainer').fadeOut(function () {
              closeModal(this, callBack);
          });
      });
  };
  // close modal element by item
  function closeModal(ele, callBack) {
      if (!ele) {
          ele = '.modalContainer'
      };
      if ($(ele).hasClass('noClose')) {
          alert("Please wait... we're working on something.");
      } else {
      $(ele).fadeOut(function () {
          var nextZ = getMaxZIndex('.modalContainer');
          if (nextZ &gt; 0) {
              $('#screenBlank').css({ 'z-index': nextZ });
          } else {
              $('#screenBlank').fadeOut(function () { $(this).remove(); });
          };
          if (!$(this).hasClass('persist')) {
              $(this).remove();
          };
          if (callBack) {
              callBack();
          };
      });
      };
  };
  // end modal window controls
  
  // **************************************************************************************************************************************************************** 
  
  // create opaque background for modal window to sit on
  $.fn.opaqueBg = function () {
      $('#screenBlank').remove();
      var z = getMaxZIndex() + 2;
      var sb = $('&lt;div/&gt;').attr('id', 'screenBlank').addClass('noPrint centreLoader').css({ 'display': 'none', 'position': 'absolute', 'text-align': 'center', 'z-index': z, 'background-color': 'rgba(10, 0, 0, 0.7)', 'width': '100%', 'height': $(document).height(), 'top': '0px', 'left': '0px' });
      $('body').prepend(sb);
      $(sb).fadeIn().bind('click', function () {
          closeModal('.modalContainer');
      });
  };
  
  // find the maximum z-Index of elements on the page, used to ensure tooltips are always shown above anything else
  // note, this will only work if major containing elements have explicitly set z-index
  function getMaxZIndex(ele) {
      if (!ele) {
          ele = "div";
      };
      var zIndexMax = 0;
      $(ele).each(function () {
          if ($(this).css('display') != "none") {
              var z = parseInt($(this).css('z-index'));
              if (z &gt; zIndexMax) { zIndexMax = z };
          };
      });
      return zIndexMax;
  };
  // end finding maximum z-index 
  </code></pre>
  
  <p>So all of the above is a generic set of functions for all kinds of purposes within my project.</p>
  
  <p>The particular purpose that prompted this post was creating a textarea within a modal window with <code>tinymce</code> applied, this works like this:</p>
  
  <pre><code>    $('#notePad .plus').on('click', function () {
          var h = $('&lt;h2/&gt;').html('Add Note');
          var txt = $('&lt;textarea/&gt;').attr('id', 'noteEditorContent').attr('name', 'newNote').css({ 'width': '100%', 'height': '400px' });
          var wrpper = $('&lt;div/&gt;').css({ 'width': '750', 'height': '380', 'margin': 'auto' }).append(txt);
          var button = $('&lt;span/&gt;').addClass('greenButton').html('Save').css({ 'float': 'right', 'margin': '40px 20px 0px 20px', 'width': '80px' }).bind('click', function () {
              saveStaffNote($('#noteEditorContent').val(), true);
          });
          var div = $('&lt;div&gt;').attr('id', 'notePadEditor').append(h).append(wrpper).append(button);
          $(txt).richEditor('simple', function () {
              $(div).makeModal({ 'width': '800', 'height': '530', 'persist': true });
              // CALLING THE makeModal() function above
          });
      });
  </code></pre>
  
  <p>AND FINALLY, the application of <code>tinymce</code> is this function:</p>
  
  <pre><code>// === loading Rich Text Editors //
  $.fn.richEditor = function (theTheme, callBack) {
      var applyTo = this;
      var tinyMceVars = {
          // Location of TinyMCE script
          script_url: '/Admin/Plugins/richEditor/tiny_mce.js',
          // General options
          theme: theTheme,
          plugins: "autolink,lists,pagebreak,style,layer,table,advhr,advimage,advlink,emotions,iespell,inlinepopups,insertdatetime,preview,searchreplace,contextmenu,paste,directionality,fullscreen,noneditable,visualchars,nonbreaking,xhtmlxtras,advlist",
          // Theme options
          theme_advanced_buttons1: "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,formatselect,fontselect,fontsizeselect,|,bullist,numlist,|,undo,redo,|,code,preview,fullscreen,|,cleanup,help",
          theme_advanced_buttons2: "cut,copy,paste,pastetext,|,insertdate,inserttime,|,link,unlink,anchor,image,|,forecolor,backcolor,|,search,replace",
          theme_advanced_buttons3: "tablecontrols,|,hr,removeformat,visualaid,|,charmap,emotions,iespell",
          theme_advanced_toolbar_location: "top",
          theme_advanced_toolbar_align: "left",
          theme_advanced_statusbar_location: "bottom",
          theme_advanced_resizing: true,
          relative_urls: false,
          remove_script_host: false,
          document_base_url: window.location.protocol + "//" + window.location.hostname,
          external_link_list_url: window.location.protocol + "//" + window.location.hostname + "/Admin/Scripts/Lists/link_list.js",
          external_image_list_url: window.location.protocol + "//" + window.location.hostname + "/Admin/Scripts/Lists/image_list.js"
      };
  
      if ($(applyTo).hasClass('editorLoaded') == false) {
          try { // try to apply the editor, if fails it's because the scripts are not loaded, so load them!
              $(applyTo).tinymce(tinyMceVars);
          } catch (err) {
              $.getScript("/Admin/Plugins/richEditor/jquery.tinymce.js", function () {
                  $(applyTo).tinymce(tinyMceVars);
              });
          } finally { // finally apply richEdit class to avoid re-writing and perform a callback if required
              $(applyTo).removeClass('richEdit').addClass('editorLoaded');
              if (callBack) {
                  callBack();
              };
          };
      };
  };
  </code></pre>