I have a unique situation where I need to completely load, run associated scripts, and render an HTML page in the background. This is a full html page.
Here's how I'm currently doing it which isn't working:
I get the page using a GET XHR call and store it as a string in a variable called template. Once I have the string I use JQuery.parseHTML to parse it into an array of elements (including the scripts) and from there filter until I get the element I need, storing it in a variable called content. Then I insert that element into the DOM.
The problem I'm having is that the DOM elements in content are not completely rendered because their scripts haven't been run.
Here's my code:
function (template) {
var jTemplate = $($.parseHTML(template, document, true));
console.log(jTemplate);
var content = jTemplate.filter('.page-wrap').contents()
.filter('#content-wrapper').contents().filter('#content')
.contents().filter('#main-content');
console.log(content);
$("agency-journal-content").replaceWith(content);
}
How can I go about running the scripts and rendering the DOM in the background and then inserting it into the current document or DOM that the user is seeing.
Related
I want to know what's the best practise for updating DOM after an Ajax call.
For example, imagine we have a list of users and we can add a user with a form which make an Ajax call to insert the user. After the form is submitted and the user added in database, the DOM is edited to add HTML without refreshing the page (with the Ajax success event).
I see two possibility to make this :
Make an Ajax call who add the user in db and return all the DOM structure with html tag, etc.
Make an Ajax who add the user in db and return all the data of an user and create the DOM element in Javascript
What'is the best way to do it (or another way) ?
You can add elements to the DOM with document.createElement(). Then use the innerHTML property to add content to the element. Finally append the element to another with .appendChild().
There is no better way between the two options. You can either prepare your HTML structure in the backend and import the written HTML and directly append it with JavaScript or create the elements frontend in JavaScript.
Here are the main advantages to using the latter:
it's easier to debug JavaScript than PHP (PHP files targetted by AJAX calls are quite hard to debug and to maintain).
returning an object with AJAX instead of an HTML string is easier to use and more maintainable. You can have an API to handle the data. PHP only returns a JSON object.
if JavaScript handles the creation of elements, you can save those in variables. Sometimes, I find it useful to save an HTMLElement in a JavaScript variable so I can later access it to change its properties without having to go through selectors (querySelector() and others).
I would go with the second option
Make an Ajax who add the user in db and return all the data of an user and create the DOM element in Javascript
Breaking it down like so to improve on readability and maintenance
Add action to AJAX that is linked to a function on the backend, (i.e PHP, Python) that does the DB update and more.
Create the Element structures in Javascript (You can maintenance uniformity with other structures on your page). And wrap it in a function.
document.body.onload = addElement;
function addElement ($newuser) {
// create a new div element that would contain user record
var newDiv = document.createElement("div");
// and give it some content
var newContent = document.createTextNode($newuser);
// add the text node to the newly created div
newDiv.appendChild(newContent);
// add the newly created element and its content into the DOM
var currentDiv = document.getElementById("user-container");
document.body.insertBefore(newDiv, currentDiv);
}
I'm trying to fire the click event on an element that is loaded via ajax.
But somehow i cannot select it right to fire the event.
It is basically an image with left, right arrows. if you click on one of the arrows a series of images gets loaded and replaced the images like a gallery. That's works already, i just need to fire the first slide so the user doesn't get that the gallery has been loaded via ajax but was there all the time.
The replacement works fine, but i cannot fire the event on the .slidenav-next element.
There is JS behaviour behind .slidenav-next that needs to be triggered by an click.
Base HTML structure
<div><div class="slidecont"></div></div>
JS to fill it with new HTML structure
$('body').on('click', '.slide', function(e) {
$.ajax({
context: this,
type: "POST",
url: 'index.php',
data: {'id':5}
}).done(function(data) {
$(this).closest('.slidecont').replaceWith(data);
console.log($(data).find('.slidenav-next'));
setTimeout(function () {
$(data).find('.slidenav-next').click();
}, 200);
});
});
HTML structure that gets loaded via ajax
<div></div>
In the end
<div><div></div></div>
If i load this structure:
<div id="xx"></div>
I can trigger it via:
$('#xx > .slidenav-next').click();
or via
$('body').find('.slidenav-next').click();
But that's not so clean. I would like to trigger it from within the loaded data.
var $data = $(data);
$(this).closest('.slidecont').replaceWith($data);
$data.find('.slidenav-next').click();
this way will create a jquery object from the data... that object then gets inserted into the DOM with replaceWith and can be referenced later.
just replacing with data directly doesnt put the data var itself as a element that exists in the DOM and can be referenced from data... data is still just a string...
could also have done something like this at the beginning of the done callback..
var div = document.createElement('div');
div.innerHTML = data; //this creates a child element based on the string in data
var dataEle = div.firstChild; //then we take that child
now dataEle references an element created based on the data string that can be inserted (like with replaceWith(dataEle)) and referenced later (like with $(dataEle).find(...)
More explanation of what was wrong:
you don't need to insert a jquery object as can be seen in the second example. jquery just takes over the job of creating a dom element and maintains access to it so you can reference it later.
the problem you were having is that data was always just a string, you used that string to create a dom element with replaceWith... but data itself was still just a string.
then again when you did $(data).find('.slidenav-next').click(); it was wrapping data in a jquery which created it's own element using the string in data (although data is still just a string) and did indeed fire off the event... however the event got fired off on the the newly created jquery wrapped element that was not ever inserted into the body of the DOM rather than the element you created with replaceWith
you were basically creating two elements from the data string, putting the first one where you wanted it but then firing off the event on the second one which was never inserted anywhere.
I am working on a project where i need to get a specific element from an external html file as a string in my jQuery.
As i understand the .get(); function cannot get a specific element (by class or ID) and the .load() can, but loads it directly into the dom of the file.
Is there another function or a way to go about this?
What i need to do is get a specific html element and replace some macros in it with data from an object and then append it to an element (multiple times.) Therefore i cannot just load it in and replace the macros afterwards.
You can .get it and then only subselect.
$.get('myfile.html', function(response) {
var inside = $(response).find('#inner-id');
// do stuff with inside...
});
I have a chunk of JavaScript code:
<script src='blah.js' type='text/javascript'></script>
How can this be removed or disabled with JavaScript?
If the script tag is received in a string via AJAX:
str = str.replace("<script src='blah.js' type='text/javascript'></script>", "");
However, if the script tag is in the current document, there is no way to disable it, because:
If it is in the part of the document which has already been parsed (i.e. above the current script), it has already been executed. While you can remove the script element, just like any element, there is no way to rewind time and automatically undo the effects the script has.
If it is in the part of the document which has not yet been parsed (i.e. below the current script), you cannot affect it, as it does not exist yet.
You can grab the script like any other element, you can do this:
document.querySelector("script").remove();
If you have a lot of script tags you can just grab the one you want like accessing a array element like so:
document.querySelectorAll("script")[1].remove();
The code above removes the second script tag in a page.
If I use document.write() it clears the whole html document. So how can I take this javascript variable
var beforenoonprice = 6.75;
and have it display to the html document through this div
<div id="beforeNoonCPSlot"></div>
You use the DOM API:
document.getElementById("beforeNoonCPSlot").innerHTML = String(beforenoonprice);
List of DOM API specs.
(In the above, I've explicitly converted the price to a string, but that's just for emphasis; if I hadn't, there would have been an implicit conversion.)
Note that you have to execute that line of code after the element has been created, otherwise we can't find it with document.getElementById. Given that you've said that using document.writeln cleared the whole document, it sounds like you're running your code at a point where the document as a whole has been rendered, so that should be fine.