Javascript: User-specific dynamic content in an HTML page - javascript

I'm looking to solve the issue of not being able to Save/Apply changes to an .html document when the document.createElement("div"); is used in JavaScript. I want to be able to save the changes made to the document and 'overwrite' the original .html document.
Future Possibilities(these can be ignored):
Deletion of these elements, and saving those changes as well to revert it back to it's original state.
EDIT: --------------
I didn't make this clear, sorry!
THIS CODE IS TO EMBED MULTIPLE YOUTUBE VIDEOS ON A SINGLE PAGE; I WOULD LIKE SOME HELP HAVING SOMETHING OVERWRITE THE ORIGINAL .HTML DOCUMENT. THEREFORE LOADING THIS NEW CONTENT EACH TIME SOMEONE OPENS THE PAGE.
Here is my code:
<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
</head>
<body>
<div id="container">
<div id="header" align="center">Home</div>
<div align="center">
<button onclick="myFunction()">Button</button>
</div>
<div id="parentElement" align="center">
</div>
<script>
function myFunction() {
var parentElement = document.getElementById('parentElement');
var theFirstChild = parentElement.firstChild;
var newElement = document.createElement("div");
parentElement.insertBefore(newElement, theFirstChild);
newElement.setAttribute("id", "newElement");
var embed = prompt("Please enter your YouTube Embed Link");
if (embed != null) {
document.getElementById("newElement").innerHTML = embed;
}
}
</script>
</body>
</html>

I think what you're asking is how to put dynamic content in a static web page. This is not my area of expertise, but I can give you the outlines of how to do what you're trying to do. This is the architecture. You'll have to fill in some implementation details yourself, but I'll try to give you a clear idea of what you'll be googling for at each step of the way.
Suggestions for improvement from real web guys will be eagerly embraced. If there's already an answer on SO that walks a noob through the design of a trivial single-page AJAX/JSON web app, I can't find it. There must be one, though.
This is a lot more complicated than your original idea, but rewriting a web page not a great idea: You're writing arbitrary zeroes and ones from strangers to a file on your server. You need one HTML file per user, if you store their data in HTML files. How do you serve him the right one? What if you change the layout after you have 500 users? You'd be writing a script to alter the text of 500 HTML files. In practice it's just a horrorshow.
What you're groping for is dynamic content via AJAJ, which we usually still call AJAX for historical reasons (prior to the advent of CNC machining, curly braces were difficult to mass produce economically, and so web services commonly used pointy brackets instead).
First, write a web page to serve the user's personal content. It'll save updates as well. May as well use PHP. That "page" isn't a web page; instead of HTML, it returns JSON text with a content-type of application/json. The user can POST text to it in JSON format as well. This "page" is a web service.
On a get request, the web service page, given a username (and appropriate security), will retrieve the user's YouTube video list from MySQL and return it to the caller as JSON.
For now, the content going to and from that web service page is pretty simple. Just a list of URLs. Let's make it an object that has one member, and that one member will be an array of objects that contain information about YouTube videos the user has chosen. For now, each one just has a URL, but we may want to add more detail later, so we won't just make it an array of bare URL strings. At the top level, we'll also be able to add other types of content alongside "YouTubeVideos" if there's a need -- for example, you're going to want a username and a security token.
{
"YouTubeVideos": [
{
"url": "http://youtu.be/LKJDFKLJDF"
},
{
"url": "http://youtu.be/87sdfd234"
}
]
}
In the HTML page, your JS code will first request the user's data from that web service in onLoad. You'll do that using XMLHttpRequest. You'll use the JavaScript function JSON.parse to turn the response text into a JS object.
So write a function called requestUserYTContent or something, and call that from onLoad. This is simplified: There's no validation, exception handling, etc.
// Empty default instance to start out.
var ytInfo = { "YouTubeVideos" : [] };
function requestUserYTContent() {
// ...
// Do stuff with XMLHttpRequest to get the JSON for this user from
// the web service.
// ...
ytInfo = JSON.parse(http_request.responseText);
console.log('Got ' + ytInfo.YouTubeVideo.length + ' videos');
// Once you've got that JSON object, you can loop through the
// videos and do stuff with their urls. We'll stick that loop in
// another function so we can re-use it in cases where the list
// changes for reasons other than a web service call.
var ytDiv = document.getElementById('ytContent');
ytDiv.innerHTML =
generateVidListHTML(ytInfo.YouTubeVideos);
}
function generateVidListHTML(vids) {
var newHTML = '';
for (var i = 0; i < vids.length; ++i) {
var url = vids.YouTubeVideos[i].url;
// ...generate HTML to display this video, and append to
// newHTML
}
return newHTML;
}
So we keep that ytInfo around in a global variable. When the user adds to the list or deletes from it, alter the list, re-generate the HTML with generateVidListHTML(), insert the HTML into the page as above, and then post the newly-altered list as JSON back to the web server to update the user's content in the mySQL database.
You'll POST data back to the web service with XMLHttpRequest. Here's an example. You'd be using a different content-type, of course.
https://stackoverflow.com/a/9713078/424129
In JavaScript in the web page, converting a live JavaScript object back to JSON is easy: https://stackoverflow.com/a/4162803/424129
For simplicity, you may as well just pass the same JSON format back and forth.
When you send JSON back to the web service, it'll need to parse it too. I don't know how to parse JSON in PHP, but I know somebody who does:
https://www.google.com/search?q=how+to+parse+json+in+PHP

<!DOCTYPE html>
<html>
<head>
<title>Test</title>
<script src="https://code.jquery.com/jquery-1.10.2.js"></script>
</head>
<body>
<div id="container">
<div id="header" align="center">Home</div>
<div align="center">
<button onclick="myFunction()">Button</button>
</div>
<div id="parentElement" align="center">
<div id="newElement" style="display: hidden"></div>
</div>
<script>
function myFunction() {
var embed = prompt("Please enter your YouTube Embed Link");
if (embed != null) {
document.getElementById("newElement").innerHTML = embed;
$('#newElement').css('display','inline');
}
}
</script>
</body>
</html>
just taking out the parent - child element relationship in javascript code and put the new element div in html with display:none style attribute. Then in click function, just make it visible.
Cheers!

It took sometime to understand your requirement infact still now it is not clear .But from your code I understand that you are trying to get a text from prompt message and initally you want to display it in your page.But that is not working since you are not able to execute it.
document.getElementById("newElement").innerHTML
Rather that using innerHTML you can check textContent.
Here is a minor change in your function
if (embed != null) {
newElement.textContent = embed;
}
WORKING COPY

Related

Display JSON in Javascript from Python Bottle

I am trying to access a mongodb record within a javascript function to display the document on a webpage. Using the Bottle framework with pymongo, I have tried to first encode the mongodb document as a JSON object to pass to my javascript function.
#bottle.route('/view/<_id>', method = 'GET')
def show_invoice(_id):
client = pymongo.MongoClient("mongodb://localhost")
db = client.orders
collection = db.myorders
from bson.objectid import ObjectId
result = collection.find_one({'_id': ObjectId(_id)})
temp = json.dumps(result,default=json_util.default)
print "temp: " + temp
return bottle.template('invoice', rows = temp)
When I try to display the document within my HTML page with the javascript function, nothing happens. However, when I call the variable, rows, that I am trying to pass as {{rows}} within the body of the HTML it does display. It seems it is only the JS function that does not display anything.
<!DOCTYPE html>
<html>
<head>
<head>
<title>Invoice Report</title>
<script type="text/javascript">
function fillTable()
{
var obj = {{rows}};
document.write(obj);
}
</script>
</head>
</head>
<body onload="fillTable()">
<div class="invoice">
</div>
<h4>Rows from body</h4> {{rows}}
</body>
</html>
I tried to use jQuery to deserialize the JSON object rows with the function
jQuery.parseJSON(rows);
and even as
jQuery.parseJSON({{rows}});
I also tried to make the variable unescaped everywhere possible as {{!rows}}
So does anybody see what I am doing wrong? How do I take a mongodb document with pymongo, and use bottle to display it on a webpage? I realize that similar questions have been asked, but I can't seem to get anything I have found to work in my particular situation.
The issue isn't with bottle rendering your json, it's with using document.write().
Open a new tab in your browser, and point it to the url: 'about:blank'. This will give you a blank webpage. Now, right click and open your developer tools. Try running document.write('Stuff'); from that context. You shouldn't see any changes to the page.
Instead try:
var body = document.getElementsByTagName("body")[0];
body.innerHTML = "Stuff";
and note the difference.
There are of course, many other ways to achieve this effect, but this is the simplest without any requirements on external javascript libraries.
You can't have both an 'src' attribute and javascript code in the same tag. Place the fillTable function within a new script tag.

auto update function results on a page

Ok, first off. No jquery, no ajax, just pure javascript.
I have the following code on a page called text.html.
<html><body>
<script>
function live(ID,txt2) {
var a = document.getElementById(ID);
a.innerHTML = (txt2);
}
setInterval(live, 250);
a.innerHTML =(txt2);
</script>
<div id="txt1">Live</div><p />
</body></html>
I have the following code on live2.html
<html>
<body>
<p />
<iframe width="400" height="50" src="text.html" name="frameA" id="frameA"></iframe><p />
<input type="button" value="Live" onClick="document.getElementById('frameA').contentWindow.live('txt1','L I V E')">
<input type="button" value="Rebroadcast" onClick="document.getElementById('frameA').contentWindow.live('txt1','Rebroadcast')"><br />
text
</body>
</html>
The current code works exactly as I wanted it to by updating the information in an iframe. My issue is this. If someone visits text.html directly, I want them to be able to see whatever I've changed that document to.
Example:
I click on a button and the text in the iframe now says rebroadcast.
Someone else visits text.html and they also see rebroadcast. If while they are looking at text.html, I hit the live button, the text.html page will update with the word live.
I can do PHP scripting on this as well. I have tried jquery and have issues with getting it to work correctly and I don't really have the knowledge or access to implement much of anything else.
This is an on-going project. The end result, I hope, will be an iframe that I can update while not actually being on the same page that the frame is located on. (same domain tho) The content will be anything from images, to youtube embeds and pictures. I'm trying to get a more comprehensive idea of how this language works and that's why I'm taking it one step at a time. I have no issue with visiting tutorials or looking at pre-made solutions. Thanks for your help. :)
I think I'm probably missing something. Users will always see the text "Live" because that's what's hard-coded in text.html. It doesn't matter if you change the text through JavaScript since it will only affect the browser that you're seeing. You need to save it to a persistence storage (ie. database) and dynamically display it on the page.
live2.html can use AJAX to send the changes to the server, which can then update live.html. But this is a poor way to do it, since it means that the contents of live.html are updated outside of your version control and/or content management system. It's better to use a real database and generate the page dynamically, as suke said.
First off this is what happens when someone learning programming languages doesn't fully comprehend what a language can and can't do. The original idea was to let a specific group of people know when it was a re-broadcast or when the show was live. I wanted the control of when to change that information to only be available to an admin of sorts. In the end the entire idea got scrapped and entirely impractical. The solution, essentially, doesn't exist in the context of the way I wanted to accomplish this. Years later...
The solution is to have live and rebroadcast inside div tags with CSS. Then use a JavaScript function to change the attributes of the divs to either be hidden or shown. The button or or link would need to exist on the same page as the live or rebroadcast text. This would also mean that there is no need for a separate frame. To have this element controlled from outside the page it's on could only be done by storing a value somewhere else and having that value periodically checked.
JSFiddle
The Script:
var x = document.getElementById("txt1");
var y = document.getElementById("txt2");
function htext() {
x.style.visibility = 'visible';
y.style.visibility = 'hidden';
}
function stext() {
x.style.visibility = 'hidden';
y.style.visibility = 'visible';
}
function ctext() {
var z = getComputedStyle(x).getPropertyValue("visibility");
if (z != 'hidden') {
stext();
} else if (z != 'visible') {
htext();
}
}
The CSS:
#txt1 {
visibility: hidden;
margin-left:0px;
}
#txt2 {
visibility:visible;
margin-left:0px;
}
The HTML:
<span id="txt1">Live</span>
<span id="txt2">Rebroadcast</span>
<br />
click
To be honest. I'm not entirely sure of the programming needed to store information somewhere else and have a check to see if certain conditions are true. The program above will essentially hide and show a div. I could probably go a step further and use JQuery to create and remove the actual div itself. In the end this is essentially close to the solution I ended up using and then later on discarding and giving up on the project.

Changing HTML Data Before Page Rendering

I've been searching for an answer to this and can't seem to find out how to do it...or if it is possible.
I have a JavaScript Program that displays an .HTML page. I have an API from another company that sends us information as well. I would like to be able to change the contents of the .HTML page before the user sees it. Is this possible?
For example, suppose page.html is:
<HTML>
<HEADER>
<TITLE>
The Company Name
</TITLE>
</HEADER>
<BODY>
Some stuff
</BODY>
</<HTML>
page.html is housed on our server and using JavaScript/HTML I would like to change the value of "The Company Name" with the value from the API before the page is rendered to the user. Is this possible?
window.onload would not do the trick if you want to be sure that your users don't see the page before edition, as onload waits for everything to be loaded, including images.
What I recommend is :
to change the title in a block in the head : <script>document.title="test"</script>
to hide initially the page, by enclosing it in a <div id=wholepage style="display:none;">
to change the page content in a standard <script> block included at the end of your body
to render your big div visible at end, using document.getElementById('wholepage').style.display='block';
A simple Javascript function will do the trick:
window.onload = function() { document.getElementByTagNames("title")[0].value = "Yourvalue"; }
You could load the HTML from the page into a string variable. Then you'd use regex on the string and search for the starting expression and ending expression , and do a replace on that content. Javascript has a replace method.
var str="<HTML><HEADER><TITLE>The Company Name</TITLE></HEADER><BODY>Some stuff</BODY></<HTML>";
str=str.replace("<TITLE>","<DUMMY>");
str=str.replace("</TITLE>","</DUMMY><TITLE>your real title</TITLE>");
Essentially you would rename the title tag into a non existent tag like dummy, then append the real title tag to the end of it.
Then you can display the HTML content in the string/variable in a page at runtime.

Most secure javascript JSON Inline technique

I'm using varnish+esi to return external json content from a RESTFul API.
This technique allows me to manage request and refresh data without using webserver resources for each request.
e.g:
<head>
....
<script>
var data = <esi:include src='apiurl/data'>;
</script>
...
After include the esi varnish will return:
var data = {attr:1, attr2:'martin'};
This works fine, but if the API returns an error, this technique will generate a parse error.
var data = <html><head><script>...api js here...</script></head><body><h1 ... api html ....
I solved this problem using a hidden div to parse and catch the error:
...
<b id=esi-data style=display:none;><esi:include src='apiurl/data'></b>
<script>
try{
var data = $.parseJSON($('#esi-data').html());
}catch{ alert('manage the error here');}
....
I've also tried using a script type text/esi, but the browser renders the html inside the script tag (wtf), e.g:
<script id=esi-data type='text/esi'><esi:include src='apiurl/data'></script>
Question:
Is there any why to wrap the tag and avoid the browser parse it ?
Let me expand upon the iframe suggestion I made in my comment—it's not quite what you think!
The approach is almost exactly the same as what you're doing already, but instead of using a normal HTML element like a div, you use an iframe.
<iframe id="esi-data" src="about:blank"><esi:include src="apiurl/data"></iframe>
var $iframe = $('#esi-data');
try {
var data = $.parseJSON($iframe.html());
} catch (e) { ... }
$iframe.remove();
#esi-data { display: none; }
How is this any different from your solution? Two ways:
The data/error page are truly hidden from your visitors. An iframe has an embedded content model, meaning that any content within the <iframe>…</iframe> tags gets completely replaced in the DOM—but you can still retrieve the original content using innerHTML.
It's valid HTML5… sort-of. In HTML5, markup inside iframe elements is treated as text. Sure, you're meant to be able to parse it as a fragment, and it's meant to contain only phrasing content (and no script elements!), but it's essentially just treated as text by the validator—and by browsers.
Scripts from the error page won't run. The content gets parsed as text and replaced in the DOM with another document—no chance for any script elements to be processed.
Take a look at it in action. If you comment out the line where I remove the iframe element and inspect the DOM, you can confirm that the HTML content is being replaced with an empty document. Also note that the embedded script tag never runs.
Important: this approach could still break if the third party added an iframe element into their error page for some reason. Unlikely as this may be, you can bulletproof the approach a little more by combining your technique with this one: surround the iframe with a hidden div that you remove when you're finished parsing.
Here I go with another attempt.
Although I believe you already have the possibly best solution for this, I could only imagine that you work around it with a fairly low-performance method of calling esi:insert in a separate HTML window, then retrieve the contents as if you were using AJAX on the server. Perhaps similar to this? Then check the contents you retrieved, maybe by using json_decode and on success generate an error JSON string.
The greatest downside I see to this is that I believe this would be very consuming and most likely even delays your requests as the separate page is called as if your server yourself was a client, parsed, then sent back.
I'd honestly stick to your current solution.
this is a rather tricky problem with no real elegant solution, if not with no solution at all
I asked you if it was an HTML(5) or XHTML(5) document, because in the later case a CDATA section can be used to wrap the content, changing slightly your solution to something like this :
...
<b id='esi-data' style='display:none;'>
<![CDATA[ <esi:include src='apiurl/data'> ]]>
</b>
<script>
try{
var data = $.parseJSON($('#esi-data').html());
}catch{ alert('manage the error here');}
....
Of crouse this solution works if :
you're using XHTML5 and
the error contains no CDATA section (because CDATA section nesting is impossible).
I don't know if switching from one serialization to the other is an option, but I wanted to clarify the intent of my question. It will hopefully help you out :).
Can't you simply change your API to return JSON { "error":"error_code_or_text" } on error? You can even do something meaningful in your interface to alert user about error if you do it that way.
<script>var data = 999;</script>
<script>
data = <esi:include src='apiurl/data'>;
</script>
<script>
if(data == 999) alert("there was an error");
</script>
If there is an error and "data" is not JSON, then a javascript error will be thrown. The next script block will pick that up.

Get Websites Title

I am trying to retrieve the title of a URL for a link.
For example get the title of this:
<a class="stack" href="http://stackoverflow.com" title="Stack Overflow">
will be generated dynamically from something like this: $('.stack').attr("title", "....");.
Is that possible with javascript or jQuery to retrieve the title of a URL?
Thanks alot
Took a little time to make, but this example allows you download a web page from your web page. Then extract the title from the title tags.
<html>
<head>
<!-- jQuery include -->
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<!-- This include allows cross domain get requests -->
<script type="text/javascript" src="https://raw.github.com/jamespadolsey/jQuery-Plugins/master/cross-domain-ajax/jquery.xdomainajax.js"></script>
<!-- Sample -->
<script type="text/javascript">
$(document).ready(function(){
//gets the href of the first anchor
var url = $("a").first().attr("href");
//sets a get request to get the html source
$.get(url, function(data){
//uses get string between function to get the text between the title tags
//then calls it in a message box
alert(getStringBetween(data.responseText, "<title>", "</title>"));
});
});
function getStringBetween(input, start, end){
var index = input.indexOf(start);
if(index != -1){
index += start.length;
var endIndex = input.indexOf(end, index + 1);
if(endIndex != -1)
return input.substr(index, endIndex - index);
}
return false;
}
</script>
</head>
<body>
Google
</body>
</html>
Yep, just use document.title. Simple and effective.
$('.stack').attr("title", document.title);
EDIT: It looks like I misunderstood your question. If you want to get the title of another page, not the currently loaded page, you could do some cross-domain AJAX trickery, but it's not generally a good idea. I'd just grab the page title server side (in whatever you are using to generate the page [php, asp, etc]) and output it.
For security reasons, you cannot read content from a different website using Javascript, even just to read the title.
You could write a server-side proxy that requests a remote page and finds its <title> tag using an HTML parser.
However, you shouldn't do this at the client side; it will waste time and resources.
If you really want to do this, do it once on the server as a pre-processing step when you create a new page.
Unless the URL's href is on the domain of the current document, using JavaScript to try to get the title of the target document would require cross-domain scripting which is not generally allowed (using traditional methods) by browsers. Unless you're real fancy with proxies (not entirely sure how that is done), you'll need a server-side language to load the document first.

Categories