0

I need help for creating the JSON of the dynamicallly created dom objects which has exactly the same format, which was while receiving the JSON to create the dynamic element.

Please check the JS Fiddle link and the source code below. Now, if you see, in the table I'm getting the data through JSON. The checkbox values in the table are JSON objects. When I select any of the checkboxes and click on Save, the corresponding div is generated and displayed.

Now, I want to save this dynamically created DOM structure using the "Save displayed data and create json'" button and also create the JSON which will be of the same format (containg all the properties (irrespective of the fact, whether they were displayed or not in the corresponding parent. for e.g., the phone number, images all the data should be available in the JSON, even it is not displayed but is available in the original JSON).

JS Fiddle

<!doctype html>
<html>
    <head>
        <style>
            table, th, td {
                border: 1px solid #ddd;
                border-collapse: collapse;
                padding: 10px;
            }

            table {
                margin: auto;
            }

            .parent {
                height: 25%;
                width: 90%;
                padding: 1%;
                margin-left: 1%;
                margin-top: 1%;
                border: 1px solid black;
            }

            .parent:nth-child(odd){
                background: skyblue;
            }

            .parent:nth-child(even){
                background: green;
            }
        </style>
        <body>
          <button onclick="createTable()">Load Table</button>
          <button onclick="saveData()">Save Table data</button>
                <table id="datatable" align="center">
                    <tr><th>Select</th><th>Name</th><th>DOB</th></tr>
                </table>

            <br />
            <button onclick="createJson()">Save displayed data & create JSON</button>
            <br />
            <div class="container">
                <
            </div>

            <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.0/jquery.min.js"></script>
            <script>
                function createTable() {
                    $.getJSON("https://api.randomuser.me/?results=5", function(data) {
                        // First, clear the table
                        $('#datatable tr:has(td)').remove();
                        data.results.forEach(function (record) {
                            var json = JSON.stringify(record);
                            $('#datatable').append(
                                $('<tr>').append(
                                    $('<td>').append(
                                        $('<input>').attr('type', 'checkbox')
                                                    .addClass('selectRow')
                                                    .val(json)
                                    ),
                                    $('<td>').append(
                                        $('<a>').attr('href', record.picture.thumbnail)
                                                .addClass('imgurl')
                                                .attr('target', '_blank')
                                                .text(record.name.first)
                                    ),
                                    $('<td>').append(record.dob)
                                )
                            );
                        })
                    }).fail(function(error) {
                        console.log("**********AJAX ERROR: " + error);
                    });            
                }

                function saveData(){
                    // Scrape the URLs that were already collected into a Set:
                    var used = new Set($('.myLink').map(function () {
                        return $(this).attr('href');
                    }).get());
                    var errors = [];
                    $('input.selectRow:checked').each(function(count) {
                        // Get the JSON that is stored as value for the checkbox
                        var obj = JSON.parse($(this).val());
                        // See if this URL was already collected (that's easy with Set)
                        if (used.has(obj.weburl)) {
                            errors.push(obj.title);
                        } else {
                            // Append it to the collection (use jQuery for appending)
                            $('.container').append(
                                $('<div>').addClass('parent').append(
                                    $('<label>').addClass('dataLabel').text('Name: '),
                                    obj.name.first + ' ' + obj.name.last,
                                    $('<br>'), // line-break between name & pic
                                    $('<img>').attr('src', obj.picture.thumbnail), $('<br>'),
                                    $('<label>').addClass('dataLabel').text('Date of birth: '),
                                    obj.dob, $('<br>'),
                                    $('<label>').addClass('dataLabel').text('Address: '), $('<br>'),
                                    obj.location.street, $('<br>'),
                                    obj.location.city + ' ' + obj.location.postcode, $('<br>'),
                                    obj.location.state, $('<br>')
                                )
                            );
                        }
                        // Clear checkbox:
                        $('input', this).prop('checked', false)
                    });
                    if (errors.length) 
                        alert('The following were already selected:\n' + errors.join('\n'))
                }
            </script>

        </body>
    </head>
</html>

Sample JSON

{
  "results": [
    {
      "gender": "male",
      "name": {
        "title": "mr",
        "first": "romain",
        "last": "hoogmoed"
      },
      "location": {
        "street": "1861 jan pieterszoon coenstraat",
        "city": "maasdriel",
        "state": "zeeland",
        "postcode": 69217
      },
      "email": "romain.hoogmoed@example.com",
      "login": {
        "username": "lazyduck408",
        "password": "jokers",
        "salt": "UGtRFz4N",
        "md5": "6d83a8c084731ee73eb5f9398b923183",
        "sha1": "cb21097d8c430f2716538e365447910d90476f6e",
        "sha256": "5a9b09c86195b8d8b01ee219d7d9794e2abb6641a2351850c49c309f1fc204a0"
      },
      "dob": "1983-07-14 07:29:45",
      "registered": "2010-09-24 02:10:42",
      "phone": "(656)-976-4980",
      "cell": "(065)-247-9303",
      "id": {
        "name": "BSN",
        "value": "04242023"
      },
      "picture": {
        "large": "https://randomuser.me/api/portraits/men/83.jpg",
        "medium": "https://randomuser.me/api/portraits/med/men/83.jpg",
        "thumbnail": "https://randomuser.me/api/portraits/thumb/men/83.jpg"
      },
      "nat": "NL"
    }
  ],
  "info": {
    "seed": "2da87e9305069f1d",
    "results": 1,
    "page": 1,
    "version": "1.1"
  }
}
Sunny
  • 902
  • 3
  • 18
  • 41
  • better share your json instead of api call for data – Vinod Louis Apr 07 '17 at 10:22
  • I've updated the question with sample JSON. – Sunny Apr 07 '17 at 10:25
  • It sounds like you need a model of your user's selection and a model of the source data. Then, you just need to do a projection of that selection, replacing the items with the source data. You don't need to do this in DOM and you shouldn't. – Jimmy Breck-McKye Apr 07 '17 at 10:29
  • I need this to display the selected user's profile in another page using exactly the same code. So, the Json I create out of this, will be taken as an input for the other page like I'm taking it here to display the data in the table. – Sunny Apr 07 '17 at 10:48
  • For saving the DOM, I think we can use "html.clone()" !! For checking the ones which are there in the DOM we can use the class myLink! Further, we can use the 'used' variable which holds all the 'myLink' urls. How to create a JSON out of all of these values? – Sunny Apr 07 '17 at 11:19
  • So, do I understand correctly that you want to generate a subset of the original JSON, based on the user's checkbox selections? Is there any data that the user can change while interacting with the page? – trincot Apr 07 '17 at 11:43
  • The user has an option to swap the 'div.parent' with the previous & next 'div.parent', which will change the DOM structure. – Sunny Apr 11 '17 at 07:01

2 Answers2

1

You could alter your code so that at every save action, you not only add the data to the div, but also to a global variable, in which you would add the exact same data that you have in the checkbox's value attribute.

Then, in another action, you would just need to output that as JSON to where ever you need it (posted to a URL, saved in localStorage, ...).

Here is the code, which has an extra button to output the JSON of the collected items to the console:

function createTable() {
    $.getJSON("https://api.randomuser.me/?results=25", function(data) {
        $('#datatable tr:has(td)').remove();
        data.results.forEach(function (record) {
            var json = JSON.stringify(record);
            $('#datatable').append(
                $('<tr>').append(
                    $('<td>').append(
                        $('<input>').attr('type', 'checkbox')
                                    .addClass('selectRow')
                                    .val(json)
                    ),
                    $('<td>').append(
                        $('<a>').attr('href', record.picture.thumbnail)
                                .addClass('imgurl')
                                .attr('target', '_blank')
                                .text(record.name.first)
                    ),
                    $('<td>').append(record.dob)
                )
            );
        })
    }).fail(function(error) {
        console.log("**********AJAX ERROR: " + error);
    });            
}

var savedData = new Map; // Keyed by image URL. Start with nothing.

function saveData(){
    var errors = [];
    // Add selected to map
    $('input.selectRow:checked').each(function(count) {
        // Get the JSON that is stored as value for the checkbox
        var obj = JSON.parse($(this).val());
        // See if this URL was already collected (that's easy with Set)
        if (savedData.get(obj.picture.thumbnail)) {
            errors.push(obj.name.first);
        } else {
            // Append it to the Map:
            savedData.set(obj.picture.thumbnail, obj);
        }
    });
    refreshDisplay();
    if (errors.length) {
        alert('The following were already selected:\n' + errors.join('\n'));
    }
}

function refreshDisplay() {
    $('.container').html('');
    savedData.forEach(function (obj) {
        // Reset container, and append collected data (use jQuery for appending)
        $('.container').append(
            $('<div>').addClass('parent').append(
                $('<label>').addClass('dataLabel').text('Name: '),
                obj.name.first + ' ' + obj.name.last,
                $('<br>'), // line-break between name & pic
                $('<img>').addClass('myLink').attr('src', obj.picture.thumbnail), $('<br>'),
                $('<label>').addClass('dataLabel').text('Date of birth: '),
                obj.dob, $('<br>'),
                $('<label>').addClass('dataLabel').text('Address: '), $('<br>'),
                obj.location.street, $('<br>'),
                obj.location.city + ' ' + obj.location.postcode, $('<br>'),
                obj.location.state, $('<br>'),
                $('<button>').addClass('removeMe').text('Delete')
            )
        );
    })
    // Clear checkboxes:
    $('.selectRow').prop('checked', false);
}

function logSavedData(){
    // Translate Map to array of values:
    var data = Array.from(savedData, function (pair) {
        return pair[1];
    });
    // Convert to JSON and log to console. You would instead post it
    // to some URL, or save it to localStorage.
    console.log(JSON.stringify(data, null, 2));
}

$(document).on('click', '.removeMe', function() {
    var key = $('.myLink', $(this).parent()).attr('src');
    // Delete this from the saved Data
    savedData.delete(key);
    // And redisplay
    refreshDisplay();
});
table, th, td {
    border: 1px solid #ddd;
    border-collapse: collapse;
    padding: 10px;
}

.parent {
    height: 25%;
    width: 90%;
    padding: 1%;
    margin-left: 1%;
    margin-top: 1%;
    border: 1px solid black;

}

.parent:nth-child(odd){
    background: skyblue;
}

.parent:nth-child(even){
    background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button onclick="createTable()">Create Table</button>
<table id="datatable">
    <tr><th>Select</th><th>Name</th><th>DOB</th></tr>
</table>
<button onclick="saveData()">Save Selected</button>
<br />
<div class="container"></div>
<button onclick="logSavedData()">Get Saved Data</button>
trincot
  • 317,000
  • 35
  • 244
  • 286
  • There's a minor problem in this case. It is allowing me to add the same user from the table, though it exists in the div.container. – Sunny Apr 10 '17 at 11:09
  • Also, lets say there's a delete button in each of the div.parent, clicking on which I can delete the respective div.parent. How do I remove the same from the savedData JSON as well for the deleted div.parent? My button - ; – Sunny Apr 10 '17 at 11:15
  • There was a mistake in the key for the `savedData.set` method call so that you could add the same entry twice. That is corrected now. I changed the way the items are displayed in the `div`: it now always first clears the `div` and populates it from scratch. That way it is reusable for delete operations. There is now also a delete button in each entry. NB: If you have more features to add, and you have trouble doing so, please ask a new question. – trincot Apr 10 '17 at 11:55
  • Hmm yeah..sorry about that! Will keep that in mind next time! By the way, what is the variable 'key' exactly holding? How is the div.parent getting deleted? – Sunny Apr 10 '17 at 12:24
  • The key is the thumbnail image URL (stored in the `src` attribute of the `img` tag). The deletion of the `div.parent` is covered by the refreshDisplay function, which deletes everything first and then creates these divs again from the memory map (*savedData*). – trincot Apr 10 '17 at 12:56
  • Oh ok, thanks for the explanation. I've added another question for the last part I'm trying to achieve. It will also answer your question about html.clone() comment. I've asked another question in succession to this one! Could you please help me with that > http://stackoverflow.com/questions/43338327/sorting-dynamic-array-which-contains-objects-based-on-dom-structure – Sunny Apr 11 '17 at 11:36
0

I think it would be much more helpful to use jquery datatables for this functionality. You can do many things such as bind JSON from ajax calls directly/per column on the datatable and customize the DOM of the rendered html content. There is also a fileSave function that can export data.

NOTE: Any $('cssselector').Datatable content has to be in Json form.

For more info check out datatables ajax data source and custom buttons extension for datatables - from the API documentation. Using a custom button with an appropriate parseandSaveJson function will do the work you need.

Hskdopi
  • 51
  • 1
  • 7