Creating a UI/writing HTML from a JSON file - html

I have a really long, unwieldy, unformatted JSON file generated by Lighthouse (a tool that conducts page load time analysis- so this file has the results of the tests). In order to make it formatted to be readable by people, I need to apparently create a UI around this file. My problem is that I'm not sure how to begin working on it.
I've read about something like creating HTML from JSON objects, I think I'd like to try that to just display all the information from the tests in the browser right now... But where would I write that? I have one Node.js file right now, which is running the tests and using JSON.stringify() to stick the JSON'd results into a file. Can I generate the HTML right after I create the JSON? (And the main question- how would I create HTML from a JSON file?)
I'm just starting out with Node and JSON, any tips are highly appreciated.

Yes, you can create HTML from a JSON file.
Here's a simple example done with jQuery, first creating an array of all of the elements, and then using .join("") to parse them. Once parse, they can simply be appended anywhere in the DOM:
var json_file = {
"one": "Hi there",
"two": "Another item",
"three": "Third item"
}
var items = [];
$.each(json_file, function(key, val) {
items.push("<li id='" + key + "'>" + val + "</li>");
});
$("<ul/>", {
"class": "json-list",
html: items.join("")
}).appendTo("body");
// Sample extension showcasing manipulation of inserted HTML
$(".json-list #two").css('color', 'red');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Obviously, the more complicated your JSON (and desired HTML structure), the more complicated the method of parsing the JSON is going to be.
A templating engine would make your job significantly easier,
and there and hunderds of these. Some of the more popular ones are:
EJS
jQuery.dForm
JQuote2
JSON Template
JTemplates
Mustache
PURE
Tempo
Hope this helps! :)

Related

schema.org json-ld using coldfusion

I have not used json with coldfusion hence looking for some advice. I am trying to use coldfusion to get the schema.org json-ld work on a website. I have a query coming from a component which has the data that needs to go in the json. Can someone give me a gist of what needs to be done in order to spit out the json from the query in the below script tags on the page. Thanks in advance.
<script type="application/ld+json"></script>
I used this JSON-LD Schema Markup Generator to determine the fields and schema to use and then created a ColdFusion struct that matched it. For some elements (addresses, social media URLs, multiple locations), you'll need to create an array-of-structs.
There are many optional parameters you can add to each markup type, so it's difficult to program a one-size-fits-all solution. (I finally managed to write a custom tag that works specifically with our internal/custom CMS to auto-generate this for our client webpages.)
Here's a bare-bones ColdFusion sample for type "WebSite". (We've been adding inlining the JSON to the same webpage.)
<cfscript>
SchemaData = {
"#context" = "http://www.schema.org",
"#type" = "WebSite",
"name" = "My Website",
"alternateName" = "My Alternate Website Title (optional)",
"url" = "https://www.mywebsite.com/"
};
writeoutput('<script type="application/ld+json">#SchemaData#</script>');
</cfscript>

convert json to markdown and inject into jade using gulp

Currently I know how to inject json data into jade using gulp, but the markdown in my json data are not formatted in the right way. I have heard of marked but not sure how I can use it in my gulp file or jade file.
I am piping data directly using
.pipe(data(JSON.parse(fs.readFileSync(file)))
.pipe(pug())
.pipe(gulp.dest(destdir))
I have tried
.pipe(data(marked(JSON.parse(fs.readFileSync(file)))))
and
.pipe(marked(data(JSON.parse(fs.readFileSync(file)))))
both say TypeError: src.replace is not a function
I am not sure how I can embed marked here or in my jade codes. Any suggestions?
EDITED
So I did some preprocessing of the json object that I got from JSON.parse. I wrote a function to marked the strings in each json object first before inject into my jade data. Something like:
var marked = require("marked")
function preprocess(){
var data = JSON.parse(fs.readFileSync(file));
iterate through data and do marked(string)
return data
}
Now I am able to get the rendered string into jade, but jade is not able to understand the markdown symbols, for example <p> </p> are literally shown in my webpage as <p> </p>. Any workaround?
Since I haven't directly used a workflow like yours before, I cannot directly solve your issue with a single suggestion but I will try to share couple of things that might fix your problem when applied in a combination.
Let's start with Markdown. You can use marked together with gulp-markdown-to-json. A common workflow looks like this:
const gulp = require('gulp');
const markdownToJSON = require('gulp-markdown-to-json');
const marked = require('marked');
marked.setOptions({
pedantic: true,
smartypants: true
});
gulp.task('markdown', () => {
gulp.src('./content/**/*.md')
.pipe(markdownToJSON(marked))
.pipe(gulp.dest('.'))
});
This will take your markdown and wrap it in JSON format also converting the body of the markdown to HTML. If you look at the options of marked, there are methods available to clean up your markdown a bit. They might be useful since you've said there are problems with your formatting.
Now we have a JSON file that we need to pipe to Jade. You can also pipe via the Jade compile task using data(locals).
gulp.task('compilePug', function() {
return gulp.src('templates/**/*.pug')
.pipe(pug({
pretty: true,
data: {
'posts' : JSON.parse(fs.readFileSync('content/json/content.json'))
}
}))
.on('error', onError)
.pipe(gulp.dest('./'));
});
Once you compile, you will have access to your JSON under posts variable right in Jade.
And finally, you mentioned that paragraph tags are appearing in your Jade template. That sounds like you're trying to pipe plain HTML to Jade. Which is fine, in fact, you'll be piping HTML to Jade if you use the gulp workflow I shared in the beginning. You just need to tell Jade that HTML is coming:
!{posts.HTMLfromJSON} // Jade will expect HTML
#{posts.HTMLfromJson} // Jade won't expect HTML it will treat it like plain text
Hope any of these will help you fix the issue.

Animating JSON data?

Dumb question time. I was trying to integrate my JSON data with a flipbook plugin, using a Mustache templating system. Needless to say, this wasn't working at all.
I'm a jQuery noobie, so is there any easy way to bind and animate the JSON data to/with a plugin (with or without the Mustache tags)??
From your question it is a bit hard to deduce what you want, but I feel you got already all the pieces together. First the example you have been linking to in a comment: https://github.com/blasten/turn.js/wiki/Making-pages-dynamically-with-Ajax
This fetches not yet loaded pages via Ajax, and the sample code assumes the Ajax call gets HTML back from the server, as can be seen in the code snippet from there (after adding a missing '}':
$.ajax({url: "app?method=get-page-content&page="+page})
.done(function(data) {
element.html(data);
});
Here the done function processes the data it got back from the server by straight injecting it into the element, which is expected to contain the current page.
I assume next that you do have a server side method, but that method returns JSON instead. Let me assume for the moment that it returns the following structure:
{ "title" : "the title of page N",
"text" : "here is some text for the page N." }
The next thing is to render this JSON into into html in the done funktion, before inserting the result into the page. Looking at the short tutorial on the README.md this might look like:
$.ajax({url: "app?method=get-page-content&page="+page})
.done(function(data) {
var pageHtml = Mustache.render("<h2>{{title}}</h2><p>{{text}}</p>", data);
element.html(pageHtml);
});
If the server returns the proper data you should now see a
<h2>the title of page N</h2><p>here is some text for the page N.</p>
appear on the page.

Populating HTML unordered lists using jQuery with json

I am learning jQuery so please bear with me. I am attempting to populate an HTML unordered list using the following code. The error I am encountering is:
HTMLfile: No such interface. The code breaks on the following jQuery library statement:
fragment.appendchild(script)
Here's the code (a fragment of a successful jQuery Ajax call).
Json contains ID and Name.
success: function(data) {
var $defs = $('<ul id="mylist"></ul>').insertBefore('#lst');
$.each(data.d, function (index, list) {
$(this).appendTo($defs).wrap("<li>" + list.Name + "</li>");
})
},
Thank you
I can't be sure, because there is not enough of your script here, but it may be that your this statement isn't pointing to an HTML element. Console log your this statement to see what it is. I don't know what data.d is, but jQuery likes to replace this statements when you might not expect it to.
Maybe show more of your code?
Learning to understand what this is in JavaScript can be hard enough for people new to the language, so I generally advise people to learn JavaScript, before learning jQuery. Otherwise I think it will take longer to learn JavaScript, and be harder, more error-filled learning experience.

Chrome Extension: DOM traversal

I want to write a Chrome extension that looks at the HTML of the page its on, and if it finds eg <div id="hello"> then it will output, as a HTML list in the popup, 'This page has a friendly div' and if it finds eg I am married to a banana then it will output 'This guy is weird.'
So in other words, searching for specific stuff in the DOM and outputting messages in the popup depending on what it finds.
I had a look at Google Chrome Extension - Accessing The DOM for accessing the dom but I'm afraid I don't really understand it. Then of course there will be traversing the dom and presumably using regex and then conditional statements.
Well that stackoverflow question asked how to let your extension talk to the DOM. There are numerous ways, one way is through chrome.tabs.executeScript, and another way is through Message Passing as I explained in that question.
Back to your question, you could use XPath to search within the DOM. It is pretty powerful. For example you said you want to search for <div id="hello">, you can do it like this:
var nodes = document.evaluate("//div[#id='hello']", document, null,
XPathResult.ANY_TYPE, null)
var resultNode = nodes.iterateNext()
if (resultNode) {
// Found the first node. Output its contents.
alert(resultNode.innerHTML);
}
Now for your second example, same thing ..
I am married to a banana
var nodes = document.evaluate("//a[#href='http://bananas.com']/text()[contains(.,'married')]",
document, null,
XPathResult.ANY_TYPE, null)
var resultNode = nodes.iterateNext()
if (resultNode) {
// Found the first node. Output its contents.
alert('This guy is weird');
}
Well you could use XPath which does work perfectly in Chrome, and you can make your query simple such as finding nodes that you want or even complex with detail. You can query any node, and then do post processing if you wish as well.
Hope that helped. Remember all this should be within a content script in the Chrome Extension. And if you want your extension to communicate to that, you can use Message Passing as I explained in the other post. So basically, within your popup.html, you send a request to the content script to find you text. Your content script will send back a response from its callback. To send the request, you should use chrome.tabs.sendRequest and within the content script.You listen for that request and handle it. As I explained in the other stackoverflow question.
Do NOT use regular expressions to parse HTML. The <center> cannot hold.
With that out of the way... although you can use XPath, I think querySelector is similar in power while being somewhat simpler as well.
You simply pass a CSS selector as a string, and it returns the elements that match the selector. Kinda like using jQuery without needing to load the jQuery library.
Here's how you would use it:
var query = document.querySelector("div#hello");
if (query) {
alert("This page has a friendly div");
}
var query = document.querySelectorAll("a[href='http://bananas.com']");
for (var i = 0; i < query.length; i += 1) {
if (query[i].textContent === "I am married to a banana") {
alert("This guy is weird.");
return;
}
}
document.querySelector finds only a single element, and returns null if that element is not found.
document.querySelectorAll returns a fake-array of elements, or an empty fake-array if none are found.
...however, it sounds like you're wanting to update the browser action popup when something is detected in a webpage, correct? If so, that is possible but immensely more difficult.
Mohamed Mansour's post will get you to the point where you can communicate between content scripts and the background page/popup, but there are other bits that need to be done as well.
Unless the problem is more complex than I think, why not just use jQuery or other convenient js api for this? This is what they were made for - to traverse the dom easily. You can inject jquery and your script that will be using it into required pages in manifest:
"content_scripts": [ {
"js": [ "jquery.js", "script.js" ],
"matches": [ "http://*/*", "https://*/*" ]
}]