0

I am working on a project where I have a div containing a html table, which in turn contains a header row and any number of table body rows.

The rows that are added contain text areas, text boxes and 7 select inputs.

I need to copy literally everything from the div (including buttons etc outside the tables and all the input values in the textareas and select options) to a string. I do this to add the "snapshot" of the div to a file (Using ActiveXObject in IE11), send it to someone else, they open the file and do the reverse of what I do on my side.

I have an 80% working version of this by using $(divID).html() but this doesn't get the select and text input values.

I have used clone() along with fix clone plugin to attempt this now which works well in it's own right (gets everything and when I append to body it makes a perfect copy) but I can't seem to get the object created to string format and back again (object -> text file -> other user -> text file -> object).

Is this possible?

The reason I need to have the data in text format is because I need to be able to transfer my complete "session" to another user and this file needs to be saved to a sharepoint library so it can be accessed. The only way I can get the file to the library at the moment is by sending via email to the library(not capable enough to use js to get file to library right now).

Would I be better off loop through each element on the page and putting everything in JSON format? I'm very new to js and learning as I go.

All suggestions welcome.

1 Answer 1

1

You have to set the attributes on the elements. Usually you are advised to stay away from attributes and use prop() instead because attributes are used when the HTML loads to set defaults and then the properties take over from there. But in this case that is exactly what you want to modify. Also since you are messing with the attributes, it doesn't hurt to create a copy first and modify that.

function serializeWithValues($el) {

  var $orig = $el,
      $t = $orig.clone();

  var $originalSelects = $orig.find('select');

  // Manual clone select values
  $t.find('select').each(function(index, item) {
    //set new select to value of old select
    $(item).val($originalSelects.eq(index).val());
  });

  $t.find(":input").each(function() {
    var $this = $(this);

    switch ($this[0].type) {
      case "checkbox":
      case "radio":
        if ($this.is(":checked"))
          $this.attr("checked", "checked");
        break;
      case "text":
      case "hidden":
        $this.attr("value", $this.val());
        break;
      case "select-one":
        $this.find(":selected").attr("selected", "true");
        break;
      case "select-multiple":
        $this.val() && $this.val().forEach(function(t) {
          $this.find("[value=" + t + "]").attr("selected", "selected");
        })
        break;
      case "textarea":
        $this.html($this.val());
        break;
      default:
        break;
    }

  });

  return JSON.stringify($t.html());
}

function serializeWithValues($el) {

  var $orig = $el,
      $t = $orig.clone();

  var $originalSelects = $orig.find('select');

  // Manual clone select values
  $t.find('select').each(function(index, item) {
    //set new select to value of old select
    $(item).val($originalSelects.eq(index).val());
  });

  $t.find(":input").each(function() {
    var $this = $(this);

    switch ($this[0].type) {
      case "checkbox":
      case "radio":
        if ($this.is(":checked"))
          $this.attr("checked", "checked");
        break;
      case "text":
      case "hidden":
        $this.attr("value", $this.val());
        break;
      case "select-one":
        $this.find(":selected").attr("selected", "true");
        break;
      case "select-multiple":
        $this.val() && $this.val().forEach(function(t) {
          $this.find("[value=" + t + "]").attr("selected", "selected");
        })
        break;
      case "textarea":
        $this.html($this.val());
        break;
      default:
        break;
    }

  });

  return JSON.stringify($t.html());
}

$("button").on("click", function() {

  var dataString = serializeWithValues($("#test"));

  $("#out1").text(dataString);
  rebuild(dataString);


});

// Add the element by string changing ids and radio groups to avoid conflict
var counter = 0;

function rebuild(dataString) {

  var d = $("<div>").append(JSON.parse(dataString));


  d.find("[id]").each(function() {
    $(this).attr("id", $(this).attr("id") + counter++);
  });

  d.find("[type=radio]").each(function(i, r) {
    var n = $(r).attr("name");
    d.find("input[type=radio][name=" + n + "]").attr("name", n + counter++);
  });


  $("body").append(d);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test">
  <input id="inp1" name="inp1" />
  <select id="sel1" name="sel1">
    <option value="1">One</option>
    <option value="2">Two</option>
  </select>
  <select id="sel2" name="sel2" multiple size="2">
    <option value="1">One</option>
    <option value="2">Two</option>
  </select>
  <input type="checkbox" name="chk1" value="1" />
  <input type="checkbox" name="chk2" value="2" />

  <input type="radio" name="rad1" value="1" />
  <input type="radio" name="rad1" value="2" />
  <input type="hidden" name="hid1" value="still here" />
  <textarea name="text1"></textarea>
  <br>
</div>
<button type="button">GetString</button>
<br>
<div id="out1"></div>
<hr>

Sign up to request clarification or add additional context in comments.

1 Comment

I had to change adding the counter to the id here as it was changing all id's within the div including my table. I need to maintain this id as there is button which sorts this table and the function uses the table id. Is there any conflicts I can expect from this? I need also to figure out the select value part too as they are not being maintained, however this is an excellent solution to something I feared impossible! Thanks! I will mark as answer when I figure out my select issue.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.