I would like to pull some information from an HTML page that has a script with JSON data in there. The script looks like this:
<script>
window.miPage = new pageInfo();
Details.initialize({
"firstName":"John",
"lastName":"Doe",
"timeFormat":["am","pm"],
"dateFormat":"M/d/yyyy",
"locale":"en"
});
</script>
I'm hoping to be able to pull the lastName value of "Doe" into a variable and use that as part of a jQuery or JS function.
Note, I can't modify the original script above.
Thanks!
Here's how you can do it with DOM.
for(let script of document.querySelectoAll("script")) {
if(script.ismyscript) { // a way to find out if it is the one, you can ignore it
let match = script.innerHTML.match(/^\s*Details\.initialize\((.*)\);$/m);
if(match) {
let json = match[1];
console.log(JSON.parse(json))
}
}
}
Related
I'm trying to parse JSON with jQuery, but I have some problem with it. I want to get JSON link.
const data = $.html(function(){
const entities = Entities.decode((this).toString());
const obj = JSON.parse(entities);
return {
url: obj.url
}
}).get();
console.log(data)
Result:
$.html(...).get is not a function
Code i'm trying to parse:
{"url": "http://download2018.com/ap/_com.GloftGGHM_2018-05-25.apk?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=IFVYHACUO60QSGWW9L9Z%2F20180622%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20180622T145015Z&X-Amz-Expires=2400&X-Amz-SignedHeaders=host&X-Amz-Signature=4bcec8896510ede49eb7150d684274fcefb47c036c82e852a316125b1fbdd742", "resp": "success"}
I'll appreciate your help !
The problem you have is caused by the fact that the JSON has been HTML encoded. To parse it back to an object you will need to first HTML decode it, which you can do using jQuery's html() and text() methods, like this:
var htmlEncodedJSON = "{"url": "http://download2018.com/ap/_com.GloftGGHM_2018-05-25.apk?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=IFVYHACUO60QSGWW9L9Z%2F20180622%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20180622T145015Z&X-Amz-Expires=2400&X-Amz-SignedHeaders=host&X-Amz-Signature=4bcec8896510ede49eb7150d684274fcefb47c036c82e852a316125b1fbdd742", "resp": "success"}";
var $el = $('<div />').html(htmlEncodedJSON);
var obj = JSON.parse($el.text())
console.log(obj.resp); // individual property
console.log(obj); // full object
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
Note that this is not the ideal solution. The best solution would be to not HTML encode the JSON that's coming back from the server.
I'm quite new at using node.js. Right now I'm trying to pull data from MongoDB and display it in a table using Javascript + HTML. However, my table is populating with undefined in all the fields. I think something is definitely wrong with how I'm reading data through to the Javascript function b/c I am able to render the full results from the people.js file straight to the webpage. Thank you in advance!! Below is my code:
Code for my people.js file:
exports.getPeople = (req, res) => {
People.find((err, docs) => {
if (err) { return next(err); }
if (docs != null){
console.log(docs.length)
docs.forEach(function(docs, index) {
console.log(index + " key: " + docs.name)
});
res.render('people', { people: docs });
}
else{
res.render('people', { people: docs() });
}
});
};
My Javascript + HTML that's populating my webpage.
script(type='text/javascript', src='http://code.jquery.com/jquery-1.9.1.js', charset='UTF-8')
script.
$(document).ready(function(){
var obj= '$(people)'
var tbl = "<table>"
var content="";
for(i=0; i<obj.length;i++){
content +=
'<tr>+<td>' +obj[i]["name"]+
'</td><td>'+obj[i]["type"]+
'</td><td>'+obj[i]["min_hours"]+
'</td><td>'+obj[i]["max_hours"]+
'</td><td>'+obj[i]["email"]+
'</td><td>'+obj[i]["phone_number"]+
'</td><td>'+ '<input type="button" value = "Update" onClick="Javacsript:deleteRow(this)">' +
'</td><td>'+'<input type="button" value = "Delete" onClick="Javacsript:deleteRow(this)">';
'</td></tr>';
}
content += "</table>"
$('#myTableData').append(content);
});
As you mentioned, you can render the array results from the people.js file directly into the webpage. So, you don't have to read the data through a JavaScript function using jQuery. The template engine language is built on top of JavaScript and it supports plenty of methods and features to do what you're trying to achieve here. So, for example, you may use an iteration method like each..in to build your table (see docs - Iteration):
// ...
body
table(id="myTableData")
// for each person in the people array (from people.js) ...
each person in people
// build a new table row
tr
// insert table data
td #{person.name}
td #{person.type}
td #{person.min_hours}
td #{person.max_hours}
td #{person.email}
td #{person.phone_number}
// add the update and delete buttons
td
input(type="button" value = "Update" onclick=" ... ")
input(type="button" value = "Delete" onclick=" ... ")
// move to next person in the people array ...
The Problem
var obj = '$(people)' does not work as you may expect. You want obj to hold the people array from the people.js file so that you can loop over each object in the array, but this is not what's happening. obj is actually a string value of length 9, so the for loop evaluates 9 string values (not objects). This is why all of your fields are undefined.
To see what I mean, run this code snippet:
var obj = '$(people)';
for (var i = 0; i < obj.length; i++){
console.log(obj[i]);
console.log(obj[i]["name"]);
}
The reason $(people) does not evaluate to an object is mainly because the parent element, script. causes everything below it to evaluate to plain text. The . after the tag causes the template engine to render plain text (see docs: Block in a Tag).
If you wanted to assign people to obj in your inline script you may try it this way:
script
| var obj = #{people};
But this will cause an Unexpected identifier JavaScript error because of the _id field on each item in people. By default _id is an ObjectID hex value from MongoDb so you would have to either remove the _id field from the docs or add quotes to each doc._id so it evaluates to a string. This would all have to be done in person.js before you return the data.
To see what I mean about the Unexpected identifier error, run this code snippet:
// works
var obj = { _id: '583ab33cdaf857b543c76afe',
name: 'john'};
// Error: Unexpected identifier
var obj = { _id: 583ab33cdaf857b543c76afe,
name: 'john'};
I am working on creating a file where data can be read from a JSON file.
I can add new names to the file but I am unable to delete. When I enter a name to delete it actually adds the name to the file.
Why is it adding & not deleting? The objective is to be able to delete a specific name from the list that will be generated.
Thank you in advance! Here is my code with comments on what I am attempting to do.
// POST request to add to JSON & XML files
router.post('/post/json', function(req, res) {
// Function to read in a JSON file, add to it & convert to XML
function appendJSON(obj) {
// Read in a JSON file
var JSONfile = fs.readFileSync('Staff.json', 'utf8');
// Parse the JSON file in order to be able to edit it
var JSONparsed = JSON.parse(JSONfile);
// Add a new record into country array within the JSON file
JSONparsed.member.push(obj);
// Beautify the resulting JSON file
var JSONformated = JSON.stringify(JSONparsed, null, 4);
// Delte a specific entry from JSON file
var i = member.indexOf(" ");
if (i != -1) {
member.splice(i,1);
}
// Write the updated JSON file back to the system
fs.writeFileSync('Staff.json', JSONformated);
// Convert the updated JSON file to XML
var XMLformated = js2xmlparser.parse('staff', JSON.parse(JSONformated));
// Write the resulting XML back to the system
fs.writeFileSync('Staff.xml', XMLformated);
}
// Call appendJSON function and pass in body of the current POST request
appendJSON(req.body);
// Re-direct the browser back to the page, where the POST request came from
res.redirect('back');
});
Here is an example of the JSON file
{
"member": [
{
"Full_Name": "",
"Address": "",
"Gender": "",
"Phone_Number": ""
}
]
}
The splice function removes the item from the array and returns the deleted item. So if you want to delete an item by an attribute from your JSON like Full_Name you have to find the index of the item first.
var nameToSearch = "MyName";
var itemIndex = -1;
for(var i = 0; i < JSONparsed.member.length; i++) {
if(JSONparsed.member[i].Full_Name === nameToSearch) {
itemIndex = i;
}
}
And then you can delete the item like you did.
if (itemIndex != -1) {
JSONparsed.member.splice(itemIndex,1);
}
The problem you most likely had was that the itemIndex was allways -1 as indexOf did not know which attribute to check and just checks for the whole object.
Also the following lines have to be after the code above. (So after any changes you make to the json)
// Beautify the resulting JSON file
var JSONformated = JSON.stringify(JSONparsed, null, 4);
I also recomend reading this turtorial about javascript debugging. It makes your live a lot easyier to find mistakes.
I'm having a problem getting an array of information stored properly as JSON.
I made a fiddle to illustrate the problem. Enter a set of tags and take a look at the console to see the output.
More explanation:
So I have an input that takes in a comma-separated list of tags, which I then format.
function createTagArray() {
// given an input value of 'tag1, tag2, tag3'
// returns array = ['tag1', 'tag2', 'tag3']
}
I thought what I needed to do next was the following:
loop over the array and create a 'tag' object for each item which also includes an id for the tag and the id of the contact the tag is associated with.
Each object is pushed to tags, an observable array.
function single_tag(id, contactId, tagLabel) {
var self = this;
self.id = id;
self.contactId = contactId;
self.tagLabel = tagLabel;
}
function createTags() {
var array = createTagArray();
for (var i = 0; i < array.length; i++) {
self.tags().push(new single_tag(uuid.generate(), self.contactId, array[i]));
}
}
Then, I converted it into JSON
self.contactInformation = function() {
return ko.toJS({
"id": self.contactId,
"firstname": self.firstname(),
"lastname": self.lastname(),
... other fields ...
"tags": self.tags(),
})
}
But, when I inspect the console output of calling this function, tags is a collection of arrays, not a nice json object.
How do I get it formatted correctly?
I tried this suggestion, and the tag json is structured correctly, but it is stored with escaped quotes, so that seems wrong.
Thanks for all the help!
I would recommend you knockout.mapping plugin for KO, it allow map complicated JSON structure to view model, even without declarations.
From the documentation
Let’s say you have a JavaScript object that looks like this:
var data = {
name: 'Scot',
children: [
{ id : 1, name : 'Alicw' }
]
}
You can map this to a view model without any problems:
var viewModel = ko.mapping.fromJS(data);
Now, let’s say the data is updated to be without any typos:
var data = {
name: 'Scott',
children: [
{ id : 1, name : 'Alice' }
]
}
Two things have happened here: name was changed from Scot to Scott and children[0].name was changed from Alicw to the typo-free Alice. You can update viewModel based on this new data:
ko.mapping.fromJS(data, viewModel);
And name would have changed as expected. However, in the children array, the child (Alicw) would have been completely removed and a new one (Alice) added. This is not completely what you would have expected. Instead, you would have expected that only the name property of the child was updated from Alicw to Alice, not that the entire child was replaced!
...
To solve this, you can specify which key the mapping plugin should use to determine if an object is new or old. You would set it up like this:
var mapping = {
'children': {
key: function(data) {
return ko.utils.unwrapObservable(data.id);
}
}
}
var viewModel = ko.mapping.fromJS(data, mapping);
In the jsfiddle you were using Knockout 3.0 which doesn't have support for textInput. This was added in 3.2. To use version 3.2 you need to use a cdn such as this: http://cdnjs.com/libraries/knockout
There was typeo in your binding. sumbit should be submit.
There was a problem with your constructor for single_tag. id was not used so I removed it:
function single_tag(contactId, tagLabel) {
var self = this;
self.contactId = contactId;
self.tagLabel = tagLabel;
}
Currently also contactId is not set because the observable has not been set to a value.
To convert to JSON you need to use ko.toJSON instead of ko.toJS:
self.contactInformation = function() {
return ko.toJSON({
"firstname": self.firstname(),
"tags": self.tags(),
})
}
Now when the console writes out an array appears:
{
"firstname":"test",
"tags":[
{"tagLabel":"test1"},
{"tagLabel":"test2"},
{"tagLabel":"test3"}
]
}
JsFiddle
So my problem was more basic than I was realizing. I'm using JSON Server to serve up my data, and I was pulling information from two parts of the database (contacts & tags).
When I tried to update my tags, I was trying to apply them to a property that didn't exist on the contact JSON in my database. Posting the tags separately worked though.
i'm newbie in javascript so, in this example exists the geometrycontrols.js (for global controls) and markercontrol.js (for marker controls)
my problem is identify the arrays where "data" is saved...
at the reference i see a savedata function but i have no idea how work with this function...
on the other side, in test.html if i've the outup on the Glog startup and output "data", and let me thinking that comes from array...
My objective is save the coordinates and other all atributes to mysql database, and when i discover where are "data" is the easy part.
if someone worked with this example (or not) can help me i'm grateful
ps: i'm really a newbie on javascript :P
edit1:
I was out for a time, and now I focus in geometrycontrols.js specially in: GeometryControls.prototype.saveData = function(opts){
var me = this;
if(opts.allData === true){
//me.saveAllData();
} else {
//construct a json data record
var geomInfo = opts.geomInfo, index = opts.geomInfo.index;
var record = geomInfo.storage[index];
var recordJSON = {};
recordJSON.type = record.type;
recordJSON.coordinates = [];
//determine geometry type, and copy geometry appropriately
if(record.type === "point"){
recordJSON.coordinates.push({lat:record.geometry.getLatLng().lat(),lng:record.geometry.getLatLng().lng()});
alert(recordJSON.coordinates);
} else {
alert("is not point");
var vertex;
for(var i=0;i<record.geometry.getVertexCount();i++){
vertex = record.geometry.getVertex(i);
recordJSON.coordinates.push({lat:vertex.lat(),lng:vertex.lng()});
}
}
//add title and description
recordJSON.title = record.title[0];
recordJSON.description = record.description[0];
//TODO add styles
recordJSON.style = ""; //TODO} //TODO Make separate prototype function?function postData(data){
//TODO
me.debug(data);
//alert(recordJSON.coordinates);
//alert(data);
};postData(me.serialize(recordJSON));}; `
When I alert(recordJSON.coordinates), the outupt is [object Object] and i've no idea why, in theory this array contains the coordinates...
Here is some code I have used to send the data to MySQL. It uses a little bit of jQuery to do the ajax magic (the line starting with the dollarsign is jQuery).
function postData(data){
me.debug(data);
var dataString = JSON.stringify(data);
me.debug(dataString);
$.post('storage.php', { data: dataString });
};
postData(recordJSON);
As you can see I've modified the way the 'recordJSON' object gets sent to the postData function a bit too: I've removed the serialise function.
Next, create a PHP file (called 'storage.php' in my case) and put this in it:
<?php
$received = json_decode($_POST['data'], true);
echo "just received " . $received['name'];
?>
You now have an array in PHP that you can do with as you please.
In the examplecode above I've modified the jQuery post function a bit, so if it doesn't work, look there.
The data is stored in JSON format in this file: http://gmaps-utility-library-dev.googlecode.com/svn/trunk/geometrycontrols/examples/data/testdata.js -- it's pretty much self-documenting, just follow the example to set your coordinates.
Note that if you need to find the latitude and longitude for a given address this is a good site: http://itouchmap.com/latlong.html