Ok. I am making a website on github using html and javascript. Earlier, I was using a template to make simple, formatted webpages. I got it to work, but it has an annoying bug: the unformatted webpage shows up before the formatted one. I am using the latest version of jquery (2.1.4) hosted from google and the javascript below:
var heading = document.getElementById("heading").innerHTML;
var pghead = document.getElementById("pghead").innerHTML;
var pgtext = document.getElementById("pgtext").innerHTML;
var template = function () {
var tmp = null;
$.ajax({
'async': false,
'dataType': 'html',
'url': "https://jediguy13.github.io/template.html",
'success': function (data) {
tmp = data;
}
});
return tmp.split("derp");
}();
document.write(template[0] + heading + template[1] + pghead + template[2] + pgtext + template[3]);
document.getElementById("heading").innerHTML = "";
document.getElementById("pghead").innerHTML = "";
document.getElementById("pgtext").innerHTML = "";
And here's a sample webpage:
<div id="heading">Test</div>
<div id="pghead">Test</div>
<div id="pgtext">This is some text in the main body of the webpage</div>
As you can see from the 'async': false. line, Jquery is requesting the template webpage at the same time as the main thread. However, there is always a slight delay in the formatting. I'm betting it is because the document.write is called near the end. What is a better way to get the browser to display just the formatted page?
Example page: website
Don't use document.write(). Ever. If you have an HTML snippet, just attach it to the desired node like this:
$("body").html(template[0] + ...);
If the page is originally empty and all the content is loaded with AJAX, then you'll see a white page that then is filled with your code.
In your case it will NOT be empty as I can guess, so you have to clear the HTML immediately after you fetch it:
heading = $("#heading").html();
$("#heading").html("");
This will minimize the original exposure of the HTML.
At this point you may want to fade it in slowly, like this:
$("body").hide();
// ... make AJAX call and attach it as shown above
$("body").fadeIn();
The fadeIn() is a touch of class you might as well replace with show().
Make the AJAX call asynchronous and put all of this into the AJAX success() method.
This is all together in a complete rewrite. Just copy+paste and tell me if it's working:
var heading, pghead, pgtext;
$("body").hide();
heading = $("#heading").html();
pghead = $("#pghead").html();
pgtext = $("#pgtext").html();
$("#heading").html("");
$("#pghead").html("");
$("#pgtext").html("");
$.ajax({
'async': true,
'dataType': 'html',
'url': "https://jediguy13.github.io/template.html",
'success': function (data) {
template = data.split("derp");
$("body").html(template[0] + heading + template[1] + pghead + template[2] + pgtext + template[3]);
$("body").fadeIn();
}
});
Okay, so first off I'm going to say you shouldn't rely on JS to format your entire page unless you're hosting a single-page application, and even then... probably not the entire page.
To answer your question, the only way to not show the unformatted page is to hide your content until the page loads. Give your body tag or container style='display:none;' and then when your JS has finished executing, show the content with by calling something like $('body').show().
one of my favourite tricks is to place a loader div and keep the content hidden and the loader visible until all JS based layout changes are completed. provided you have the luxury of using Jquery (or CSS3) you can use an easing effect on the opacity to give it a much better feel.
Related
So, a little context: I'm trying to do an ajax call to a webpage in the same domain to get a telephone number to show up as soon as I specify the client on the first page. I do get the data but it seems like not the whole page is loaded in.
I need this:
<div id="1">
<div id="2">
<a id="ineedthis"></a>
</div>
</div>
but instead it's giving me this:
<div id="1">
</div>
This is a website that I'm writing a script for, since I can't edit the source code. This is managed from our ERP program and is pretty limited in customizability.
My best guess is that the target webpage is also still loading in the information from the database, but my ajax call returns the webpage before that happens.
Here is my js code:
function updateClasses(){
var link = $('a[href^="/organisatie-beknopt-prs?BcId="]');
var href = "https://52134.afasinsite.nl" + link.attr("href");
console.log(href);
if(href !== "https://52134.afasinsite.nlundefined"){
$.ajax({
url:href,
type:'GET',
success: function(data){
var tel = $(data).find("#P_C_W_Title_Content");
console.log(tel);
}
});
}
}
setInterval(updateClasses, 1000);
I'm running this once per second to check for a change in the input field on the first page, I don't know if there is a better way for this?
Firstly, you could try running the script/function once a change has been detected.
Something along the lines of :
$('input[name="{inputFieldName}"]').on('change',function(){
updateClasses();
});
//You can also use "keyup" instead of "change", depending on the type of action that you are looking for.
For the Ajax, you could try using Promises. Basically, set up the ajax call and then set a ".done" case for the ajax call has been completed and received some result. A ".fail" can also be used to catch non-code related issues.
function updateClasses(){
var link = $('a[href^="/organisatie-beknopt-prs?BcId="]');
var href = "https://52134.afasinsite.nl" + link.attr("href");
var getPhonePromise = $.ajax({
url: href
});
getPhonePromise.done(function(data) {
var tel = $(data).find("#P_C_W_Title_Content");
console.log(tel);
});
getPhonePromise.fail(function(errRes) { console.log(errRes);});
}
In Javascript, to add text to an already existing div I would use
document.getElementById("container").innerHTML = document.getElementById("container").innerHTML + "Text";
So that the text that is already present in the div wouldn't be deleted and to be able to reset what is written in the div by just using:
document.getElementById("container").innerHTML = "Text";
But, since I'm using jquery to load the text from a txt file with
$( "#container" ).load( "text.txt" );
That doesn't seem possible.
I'm not a big expert on neither JS or Jquery, but is there a way to mix the two to still be able to reset the text in a div or add text to it, while still fetching that text from an external file?
Hope I've been clear enough in explaining what I'm trying to do
Try using AJAX to fetch your data but not populate it:
$.ajax({
url: 'text.txt',
success: function(text){
document.getElementById("container").innerHTML += text;
}
});
Ajax is a lot more full featured - it's the 'harder' cousin of load(), so you can also add an error catcher (as well as a raft of other things):
$.ajax({
url: 'text.txt',
success: function(text){
document.getElementById("container").innerHTML += text;
},
error: function(e){
document.getElementById("container").innerHTML += 'Data could not be loaded! (' + e.statusText + ')';
}
});
You can learn more about AJAX at jQuery docs: http://api.jquery.com/jquery.ajax/
First of all:
You run the risk of loading a file, which may or may not be available. Meaning you could get a file load error. In order to stick with jQuery I would leverage AJAX to load the file like so:
JQuery code:
$(document).ready(function() {
$.ajax({
url : "text.txt",
dataType: "text",
success: function (data) {
data.appendTo("#container")
},
error: function(e){
// Show some error, for example:
alert("Data failed to load from text.txt file")
}
});
});
I believe that appendTo will be a much simpler version of what you've tried to accomplish via document.getElementById("container").innerHTML in order to replace the text. Give it a try and modify this to work exactly as you like. Let me know if you have any questions about it.
To make it clear to you, JQuery is an extension of the existing JavaScript language. Meaning, you can always use your JavaScript within your perceived JQuery code. You can learn how to use the strengths of JQuery to support your JavaScript code with added functionality, a great example of one is the AJAX implementation of file loading you see here. To learn more visit: Learn JQuery.
I want to build a url, send the url and display the returned html page in a div or any block element on the same page.
Ultimately, what I want to do is send a request as soon as the user enters a name, create a div to display the response,
fill the div with the response, hide the div then display a button or tab for the user to click to see the returned document.
But for now I'm just trying to figure out how to get the response into a div on the same page.
This seems like a fundamental HTML activity but I can't figure out how to direct the returned page to a div instead of having it replace the original page.
I would prefer to do this with plain HTML5 and javascript, not JQuery, but if JQuery is the only way I'll tackle that learning curve.
<html>
<body onload="buildPage()">
<div id="documents"></div>
</body>
<script>
function buildPage() {
var name="somename" ; // this will eventually come from user input and be passed in
var documentName = name + ".html";
var url ="http://localhost:8080/docserver/getpage?name=" + documentName;
// create a div to display the requested document
var newDiv = document.createElement("div");
newDiv.id = documentName;
newDiv.style.visibility = "hidden";
// ... probably need to do something here to direct the url response into the new div
// nest the newDiv in the existing div
document.getElementById("documents").appendChild(newDiv) ;
//TBD create a button to display the returned document
}
</script>
</html>
It sounds like you want to make an ajax request, which returns html, then render that html in a div?
I would also recommend using jQuery if you are not. It will make your life a lot easier.
Your file(s) will need to look something like this:
HTML
....
<div id="mydiv"></div>
....
JQUERY
$( document ).ready(function() {
$.ajax({
'type': 'get',
'contentType': 'text/plain',
'url': 'path/to/your/script/',
'dataType': 'html',
'timeout': 50000
}).done(function (data) {
// success
$('#mydiv').html(data);
}).fail(function (error) {
// something went wrong
console.log(error);
});
});
For the sake of simplicity, Let's say your html that is returned is:
HTML
<p>Hello World!</p>
Your page (after the ajax request runs) will look like this:
HTML
....
<div id="mydiv"><p>Hello World!</p></div>
....
This should get you rolling.
To expand on my comment, this code will pretty much do it for you
$.ajax({
url: "mypage.html",
cache: false
})
.done(function( html ) {
$( "#results" ).append( html );
});
With really good supporting documentation found here http://api.jquery.com/jquery.ajax/
Thanks to all that answered my query. Especially jonny who did some impressive hand holding. I really don't understand JQuery so I wanted a pure html/js solution. Here is what I ended up doing.
function buildPage() {
var name="somename" ; // this will eventually come from user input and be passed in
var documentName = name + ".html";
var url="http://localhost:8080/FDS/documents?filename=" + documentName ;
// create a div to display the requested document
var newDiv = document.createElement("div");
newDiv.id = documentName;
//newDiv.style.visibility = "hidden";
// create an iframe to place in the div
var newIframe = document.createElement("iframe") ;
newIframe.src = url ;
// nest the iframe in the div just created
newDiv.appendChild(newIframe) ;
// nest the newDiv in the existing div
document.getElementById("documents").appendChild(newDiv) ;
The missing component was an iframe. I thought I saw JQuery using iframes in the tabs widget but I did not pursue that avenue until it looked like I was going to get only JQuery based replies.
I'm trying ajax (and to a degree a lot of js) for the first time so I'm not sure what I'm doing wrong.
The goal is that a series of thumbnails in a sidebar will change the content of a centrally located div when selected. The link currently looks like this:
<img src="images/thumbs/elon-scissors-logo.jpg" onclick="reloadMiddleWith('about','about','test')"/>
When clicked it runs the below function and changes the background and calls a php source.
function reloadMiddleWith(theme, page, content) {
var new_url = "http://www.chrisjohndesigns.com/" + page + ".php/#" + content;
$('#live-area').addClass(theme);
$.ajax({
url: new_url,
dataType: 'html'
})
.done(function(data) {
// Assuming the request returns HTML, replace content
$('#area-loader').html(data);
});
}
I tested that and it worked fine when it was just the background and the new php page, but rather than making 50 pages to call in (and not even trying arrays or databases at the moment for lack of proper understanding) I thought I would just make 1 or 2 new page that repeat the same container style and just call the one I want to display by id tag. Currently when I try it, it just changes the background but does not change the php content.
The jQuery itself has a handy function jQuery(...).load, using it jQuery would handle all the necessary points:
function reloadMiddleWith(theme, page, content) {
var new_url = "http://www.chrisjohndesigns.com/" + page + ".php/#" + content;
$('#live-area').addClass(theme);
jQuery("#area-loader").load(new_url);
}
for more information check documentation page out.
I would like to refire the styling and processing.js scripts that i linked to in the head so that they display correctly when brought in through an ajax-request. I see where in the ajax request this code needs to be, but i don't know how to tell the code to simply reapply the script. I've seen people using getScript() to do this, but from what i can tell this reloads the script, rather than simply telling it repeat or refire. Do all of the scripts need their own reinitialization? I found the syntax highlighters .highlight() method, but i am yet to get the processing script to load. currently, Processing.loadSketchFromSources($('#processing'), ['mysketch.pde']); does not work. I am using current versions of all libraries. Surprised i haven't been able to find the answer yet, as a lot of people seem to have the same problem. Thanks for your help!
index page:
$(document).ready(function () {
// put all your jQuery here.
//Check if url hash value exists (for bookmark)
$.history.init(pageload);
//highlight the selected link
$('a[href=' + document.location.hash + ']').addClass('selected');
//Search for link with REL set to ajax
$('a[rel=ajax]').live("click",function(){
//grab the full url
var hash = this.href;
//remove the # value
hash = hash.replace(/^.*#/, '');
//for back button
$.history.load(hash);
//clear the selected class and add the class class to the selected link
$('a[rel=ajax]').removeClass('selected');
$(this).addClass('selected');
//hide the content and show the progress bar
//$('#content').hide();
$('#loading').show();
//run the ajax
getPage();
//cancel the anchor tag behaviour
return false;
});
});
function pageload(hash) {
//if hash value exists, run the ajax
if (hash) getPage();
}
function getPage() {
//generate the parameter for the php script
var data = 'page=' + encodeURIComponent(document.location.hash);
$.ajax({
url: "loader.php",
type: "GET",
data: data,
cache: false,
success: function (html) {
//hide the progress bar
$('#loading').hide();
//add the content retrieved from ajax and put it in the #content div
$('#content').html(html);
//display the body with fadeIn transition
$('#content').fadeIn('fast');
//reapply styles?
//apply syntax highlighting. this works
SyntaxHighlighter.highlight();
//relaod processing sketch, currently displays nothing
Processing.loadSketchFromSources($('#processing'), ['mysketch.pde']);
}
});
}
This the ajax-loaded content:
<!--ajax'd content-->
<??>
<h2>code</h2>
<pre class="brush: php">
$last_modified = filemtime("header.php");
echo("last modified: ");
echo(date("m.j.y h:ia", $last_modified));
</pre>
<script type="application/processing">
</script>
<canvas data-processing-sources="mysketch.pde" id="processing">
</canvas>
</div>
</body>
</html>
<??>
So, let's analyze what usually happens when you include an (external or internal) Javascript code: It will automatically execute only the code that is available in the global scope. "Good" scripts will only add one command to the global scope which will then execute the initialization code somewhere in a function/method.
All you need to do is view the external Javascript file and find out what is being executed from the global scope. There is no general answer to that ... some scripts use an object and call its init() method ... but that is totally subject to the imagination of the developer.
If you have javascript that needs to trigger, you MUST add this to the head element:
var head = document.head || document.getElementsByTagName("head")[0];
var script = document.createElement("script");
script.innerHTML = "your AJAX-obtained js code";
head.appendChild(script);
The same trick goes for CSS. Add a element to the head with your CSS declarations as innerHTML. So: make sure to preprocess your AJAX response and split out the JavaScript and CSS elements, then add those to the document header. It's probably easier to make your response a JSON object along the lines of:
{
html: "<html>string<goes>here</goes></html>",
scripts: ["url1","url2","url2",...],
style: ...
}
and then parsing that JSON for the html (which you use as innerHTML for a new document.createElement("div") or something, and then append wherever it needs appending), the scripts (which you turn into elements for HEAD insertion) and the style declarations (which you turn into elements for HEAD insertion).
(On a functional note, your example AJAX response looks like it has PHP code in it. I have no idea what you're using it for, but that looks like a bad response)
Just incase anyone stumbles upon this:
If you have processing.js already loaded, simply call Processing.reload() in your AJAX success/complete function.
Perhaps you already have an element with id="processing" on your page. In that case $("#processing") will only return the first one. If that is the case, change the id or use a class instead.
The other option, which I don't recommend, is to use $("[id=processing]"). That will return every element on the page with id="processing". But, don't use it. Use unique ids in your page, or switch to using classes, whichever works best for you.