jQuery parsing html into JSON - javascript

I am currently using the following code:
jQuery('#book-a-service').click(function(){
var selectedServices = jQuery('.selected').parent().parent().html();
console.log(selectedServices);
});
and that returns:
<td rowspan="3">Brakes</td>
<td class="service-title">BRAKES SET</td>
<td class="service-description"><p>Setting of front and rear brakes for proper functioning (excluding bleeding)</p></td>
<td class="service-price">R <span id="price-brakes-set">R75</span><div id="select-brakes-set" class="select-service selected"></div>
</td>
which is what i want, except i need an array of all the elements with '.selected' class in JSON.. i just want to know how i could almost parse it in a way that i only get the contents of the td tags and as for the "service-price" only the numeric value and then how would i insert those values into a json object?
Any Help Greatly Appreciated..

jQuery is not my most formidable frameworks, but this seems to do the trick.
jQuery('#book-a-service').click(function(){
var selected = jQuery('.selected');
selected.each( function() {
var children = jQuery(this).parent().parent().find('td');
var json = {};
console.log(children);
json.type = jQuery(children[0]).text();
json.title = jQuery(children[1]).text();
json.description = jQuery(children[2]).find('p').text();
json.price = jQuery(children[3]).find('span#price-brakes-set').text();
console.log(json);
console.log(JSON.stringify(json));
});
});
in action: http://jsfiddle.net/3n1gm4/DmYbb/

When various elements share the same class and you select them with $(".class"), you can iterate through all of them using:
$(".selected").each(function() {
var element = $(this); // This is the object with class "selected" being used in this iteration
var absoluteParent = $(this).parent().parent();
// Do whatever you want...
var title_element = $(".service-title", absoluteParent); // Get service-title class elements in the context provided by "absoluteParent", I mean, "inside" of absoluteParent
var title = title_element.html();
});
In the specific case of prices, I don't know exactly what is the price (probably R75?). Anyway, it should be inside a div and then select that div to obtain the price. If it is R75, then note that the "id" property should be unique for every DOM object in your HTML.
Also note that, when getting HTML, you're only getting a string, not the actual element, so it will probably not be useful for getting new values in an easy way (you won't be able to navigate through DOM elements with an ordinary string, even if it represents HTML from an actual object). Always get jQuery objects and work with them, unless you actually need the HTML.
For generating a JSON string, just create a global array and add the objects/values you need there. Then you can obtain a JSON string using var jsonText = JSON.stringify(your_array);
Consider not doing this in Javascript, as it's not useful in the majority of cases. Just send the values through POST value to a script (PHP, for example) and in the PHP you will get the actual value. The other way (PHP to Javascript) will be useful to return JSON (using json_encode($a_php_array)) and then, in Javascript, transform to a JS array using var my_array = JSON.parse(the_string_returned_by_php);.

Related

Parsing a list of objects in javascript via index

var Filtered_Region = imageCollection.filterBounds(geometry);
var Filtered_Meta_Reg = Filtered_Region.filterMetadata('CLOUD_COVER','less_than', 20)
var Filtered_Date_Meta_Reg = Filtered_Meta_Reg.filterDate('2019-01-01','2019-12-31')
print(Filtered_Date_Meta_Reg.size())
var Filtered_Free_image = Filtered_Date_Meta_Reg.first();
Using this piece of code in javascript i have a list(??) of class imageCollection objects which are filtered down to 30 using some methods.What i would like to do now is access these elements one by one.
I found that using .first() gives me the first element of this list(please correct me if the type produced is not a list) but i can't access the rest.
What i would like to do is via index use something like Filtered_Date_Meta_Reg[2],Filtered_Date_Meta_Reg[3] and access the 2nd and third element.How could this be done?

Getting array out of data attribute without jQuery

I want to work with an array to pass through using data-attribute.
In my HTML-tag I've this attribute:
data-toshow='["tblp"]'
I can access and use it with jQuery when using
$().data('toshow')
But when using dataset.toshow I don't get the same result. I actually don't get an array.
Can someone explain this to me? And give me the answer how to do the same without the use of jQuery?
jQuery's .data() method automatically tries to convert the string in your custom data attribute to whatever type it appears to be (in this case an array). JavaScript just treats it as a string, so you need to parse the string to get the same array output you get with jQuery. For example:
// jQuery approach
const jqtest = $('div').data('toshow');
console.log(jqtest);
// Plain JavaScript approach
const jstest = JSON.parse(document.querySelector('div').dataset.toshow);
console.log(jstest);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div data-toshow='["tblp"]'></div>
//Use dataset to get a string of all data-* props
const stringVal = document.querySelector('#divA').dataset['toshow'];
//Parse the value of "data-toshow" to get your array
const array = JSON.parse(stringVal);
console.log(array);
<div id="divA" data-toshow='["tblp"]'></div>
Assuming you have HTML similar to:
<div id="theThing" data-toshow='["tblp"]'></div>
or
<div id="theThing" data-toshow='["tblp","arrItem2","arrItem3"]'></div>
//jQuery
var container_jq = $("#theThing");
var container_jq_dataArr = decodeURIComponent(container_jq.data('toshow')).split(",");
//vanilla
var container_vanilla = document.getElementById("theThing");
var container_vanilla_dataArr = JSON.parse(decodeURIComponent(container_vanilla.dataset.toshow));
console.info({jQuery: container_jq_dataArr,vanilla: container_vanilla_dataArr});
jsfiddle in action
Every HTMLElement has dataset property, this property could be null if there is no data attribute in the element, but if there is any data attribute, the dataset property is an array containing all the data values declared on the element.
Given an html like <div data-name='Usher' data-max-number='5'> There are two ways you can get this data attribute using javascript,
One way is to call the element.getAttribute('data-name') or element.getAttribute('data-max-number') of that element.
The second way is through the dataset property of the element. which you would use element.dataset.name to obtain the name attribute or element.dataset.maxNumber
NOTE: How max-number becomes maxNumber. This is how you access hyphen seperated data-set attribute, using camelCase

Replacing Object keyname in an Object reports "is not a function" error

This answer how to change json object name (key)?
provides a method of replace a name/key in a JSON object but I am running into problems getting it to work.
I am obtaining some fields from a library, such as getColumnTitle etc that have numbers appended that identify which column the Title comes from. Because I need the values associated with a row and have a unique column grouping identifier, the appened numbers cause difficulty at the server side. hence I need to remove the numeric suffix or appended numeric value.
This is what I am trying to do with the code below, however I get a
TypeError: getTaskCellData.remove is not a function
error.
Here is the code.
var getColumnTitle = "hour231";
var getTaskCellData = {"hour231":23,"name":"hello world","other":"fields"};
var alphaTitle = getColumnTitle.replace(/[0-9]/g, '');
getTaskCellData.put(alphaTitle, getTaskCellData.remove(getColumnTitle));
console.log(getTaskCellData)
The answer you linked to is for JAVA, not JavaScript... An object literal, as you have it stored in getTaskCellData, doesn't have remove on its prototype, so you can't use that. Personally I don't think it's worth the code to rename an object's property, simply add a new property holding the same value. If you really insist on renaming, you can do the same and additionally use delete.
var getColumnTitle = "hour231";
var getTaskCellData = {"hour231":23,"name":"hello world","other":"fields"};
var alphaTitle = getColumnTitle.replace(/[0-9]/g, '');
getTaskCellData[alphaTitle] = getTaskCellData[getColumnTitle];
delete getTaskCellData[getColumnTitle];
console.log(getTaskCellData)

localStorage save HTML Clone

I want to use the localStorage to save an Object which contains HTML-Clones.
var myObject["test"] = document.getElementByID("someElement").cloneNode(true);
myObject["test2"] = document.getElementByID("someOtherElement").cloneNode(true);
localStorage.saveObject = JSON.stringify(myObject);
But the Object saveObject still equals {}. It seems, that stringify can't stringify an HTML Node and if, in any way, I happen to solve the problem to save it, is it possible to parse this Object back to an HTML node?
Someone knows a solution?
Your node references will be removed from the stringified object because JSON, by definition, cannot contain functions or node references - only primitives or sub-arrays/objects. In other words, there's no way you can keep references to nodes in your local storage. You would instead need to log references to them by ID, class or some other means.
[EDIT, in response to OP's comment]
JSON and JS objects are not the same thing. The former is derived from the latter, but they are not the same. JSON is a storage means, and so cannot contain references to anything dynamic. HTML elements do not exist permanently; they exist as runtime (DOM) concepts that disappear once the page is left. Thus, they cannot be stored in any meaningful way.
JSON is therefore able to store only primitive data - strings, numbers and booleans - along with structures that allow it to nest - arrays and sub-JSON definitions.
So what happens when you run stringify on your object is the unsuitable parts are stripped out. In your case, that's both properties. So instead, you need to store references to the elements in a more permanent, revisitable format - by ID or class, or some other reminder mechanism.
var obj = {el1: '#some_element', el2: '.some_other_element'};
localStorage.saveObject = JSON.stringify(obj);
There I save my two elements as references to their IDs (first) and class (second).
Then, when you come to reload your local storage, you look up the elements based on those factors, by feeding them, for example, to a jQuery selector.
One workaround is to:
Get the outerHTML of the node you want to clone
Store the outerHTML (a string) in local storage.
On load create a new element, append it to the document.
Assign the outerHTML saved in your localstorage to the new element.
Quick example:
window.saveArray = new Array();
var clone = document.getElementByID("someElement").cloneNode(true);
saveArray.push(clone.outerHTML);
function save(){
localStorage["elements"] = JSON.stringify(saveArray);
}
function load(){
var tempsave = JSON.parse(localStorage["elements"]);
for (var i = 0; i < tempsave.length; i++){
var element = document.createElement('div');
document.getElementById('element-container').appendChild(element);
element.outerHTML = tempsave[i];
}
}
To save an HTML node as string you can use XMLSerializer.
var node = document.getElementByID("elementID");
var serializer = new XMLSerializer();
var htmlStr = serializer.serializeToString(node);
localStorage.setItem("saved", htmlStr);
Now you can set it as innerHTML of a node.
document.getElementById("elementContainerID").innerHTML = localStorage.getItem("saved");
Notice! If you are copying input elements that have been given new values, they will not be saved. As the node will be copied with the value attribute inputElement.getAttribute("value") and not with the new given one inputElement.value. To work around this, you may copy all input values to the value attribute before you serializer the node.
document.querySelectorAll("input").forEach((el) => el.setAttribute("value", el.value));

How do I scan JSON with jquery to determine the number of instances of a certain string?

I have some JSON which looks generally like this...
{"appJSON": [
{
"title":"Application Title",
"category":"Business",
"industry":"Retail",
"language":"English",
"tags":[
{"tags":"Sales"},{"tags":"Reporting"},{"tags":"Transportation"},{"tags":"Hospitality"}
],
},
{
"title":"Airline Quality Assurance",
...
...
...]}
I'm looping through JSON to get an array of all of the unique Tags in the data.
My question is, now that I have an array of the different unique Tags in the JSON, how do I best determine the number of times each Tag occurs?
So basically I'm looking to generate a list of all of the tags found in the JSON (which I already have) with the number of times each one occurs (which I don't already have).
Thanks a lot in advance!
I'm assuming when you find a new tag you check to see if you already have that tag somewhere. If you don't you add it to your list. Why not when you check do something like.
var nextTag=//get the next tag in the JSON list
var newTag=true;
for(var i=0;i<tags.length;i++){
if(nextTag === tags[i]){
tagCount[i]++;
newTag=false;
break;
}
}
if(newTag){
tags[tags.length]=nextTag;
tagCount[tagCount.length]=1;
}
This uses two arrays where tagCount[i] is the number of times tag in tags[i] occurs. You could uses an object to do this or however you wanted to.
As an alternative, here's a function which will fill an associative array; the keys will be the tags and the values will be the number of occurrences of that tag.
var tagCounts = []; // Global variable here, but could be an object property or any array you like really
function countTags(tags, tagCounts)
{
$.each(tags, function(i, item) {
var tag = item.tags; // This would change depending on the format of your JSON
if(tagCounts[tag] == undefined) // If there's not an index for this tag
tagCounts[tag] = 0;
tagCounts[tag]++;
});
}
So you can call this function on any number of arrays of tags, passing in your tagCounts (totals) array, and it will aggregate the totals.
var tags1 = [{"tags":"Sales"},{"tags":"Reporting"},{"tags":"Transportation"},{"tags":"Hospitality"}];
var tags2 = [{"tags":"Reporting"},{"tags":"Transportation"}];
var tags3 = [{"tags":"Reporting"},{"tags":"Hospitality"}];
countTags(tags1, tagCounts);
countTags(tags2, tagCounts);
countTags(tags3, tagCounts);
Then you can read them out like so:
for(var t in tagCounts)
// t will be the tag, tagCounts[t] will be the number of occurrences
Working example here: http://jsfiddle.net/UVUrJ/1/
qw3n's answer is actually a more efficient way of doing things, as you're only looping through all the tags onceā€”but unless you have a really huge JSON source the difference isn't going to be noticeable.

Categories

Resources