Extract and execute scripts from AJAX response - javascript

My AJAX response returns something like this:
<div>
..
</div>
<script type="text/javascript">
..
</script>
<script type="text/javascript">
..
</script>
<div>
..
</div>
I want to execute scripts from script tag (should work cross-browserly) and to insert text (divs) to page after.

Your script tags don't need the type="text/javascript" attribute for cross-browser compatibility.
And your JavaScript will execute from the top down. So whatever script comes first will execute first. Add your text insertion last, something like this:
HTML:
<div id="myDiv"></div>
JavaScript:
document.getElementById("myDiv").innerHTML = "hello";

Extract scripts from ajax responses is generally bad practice (caching, security,...).
It's better to handle data (JSON) returned in the ajax response. Consider to use JQuery or another framework since they offer cross-browser functionality and DOM manipulation build-in.
See the following DOM manipulation example:
$(document).ready(function() {
var $grouplist = $('#groups');
$.each(myData, function() {
$('<li>' + this.name + '</li>').appendTo($grouplist);
});
});
# http://jsfiddle.net/qmacro/NJMyD/
If you want to stay with the native functionality without frameworks, javascript offers native dom manipulation functions that may be browser dependant.
When you're adding a new <javascript> element to the body, it should be automatically registered.

Thanks to all.
I created such solution:
var scripts = [];
$(response).each(function(key, element){
if ($(element).is('script')) {
scripts.push(element.innerHTML);
} else {
$('test').append($(element));
}
});
$.each(scripts, function(key, element){
eval(element);
});

Related

javascript not loaded from django template when URL is invoked from jQuery load()

I have a django generated page, and in it I have a jQuery on click handler that loads another django page using the jQuery load() function:
$("#loadit").on("click", function() {
load_it($("#loadit"), url);
});
function load_it(el, url)
{
var el_wf = $('<div />');
el_wf.load(url, function (html, status) {
el.children().remove();
el_wf.show();
el_wf.appendTo(el);
});
}
In that second django template I have some code like this:
<script type="text/javascript" src="/static/scripts/myscript.js"></script>
.
.
.
<div>
<script>
function_in_myscript();
</script>
</div>
When I click on the element in the first page, and the second page is loaded that js function is not invoked. There are no errors, and the rest of the template is run and the page is generated.
But if I go to the second URL directly from my browser the js function is run.
Is there something with load() that is preventing this from working?
JavaScript inserted as DOM text will not execute. The W3C Specification for XMLHttpRequest states: Scripts in the resulting document tree will not be executed, resources referenced will not be loaded and no associated XSLT will be applied.
The solution is to call JavaScript’s eval() function on the text of the script. Using jQuery it is very easy to iterate through the collection of script tags and to eval() contents of the TextNode. However this looks like a bad practice.
Using script tag in second html is not a good way of loading a new js file. I suggest that you use RequireJS for this purpose. RequireJS takes a different approach to script loading than traditional tags. It can run fast and optimize well.
Here is an example to demonstrate the usage, In first File:
<script type="text/javascript" src="/static/scripts/require.js"></script>
.
.
.
<script type="text/javascript">
require.config({
paths: {
myscript: '/static/scripts/myscript'
}
});
$("#loadit").on("click", function() {
load_it($("#loadit"), url);
});
function load_it(el, url)
{
var el_wf = $('<div />');
el_wf.load(url, function (html, status) {
el.children().remove();
el_wf.show();
el_wf.appendTo(el);
require(['myscript'], function(myscript) {
function_in_myscript();
});
});
}
</script>
In that second django template just load the html code. No need for loading script.

Initialize more than one html element using jQuery and Javascript

I have tried to lead my html element to fire my customized JS file's method.
Third textarea appears nicely.
First and second textareas does not effect any of the settings i am trying to change in myJSFile.js file.
Here's my problem : js file loads the last textarea nicely, but cannot initialize previous ones properly using my js methods.
I'm doing something wrong with my JS file, and i'd appreciate if you help me.
P.S. : Initalizing some plugin and working on CKEditor.
Here's my HTML file :
<textarea id="myTextAreaID" name="myTextArea"></textarea>
<script type="text/javascript" src="../public/js/myJSFile.js"onload="setTextAreaValues('myTextAreaID')"></script>
<textarea id="myTextAreaID2" name="myTextArea2"></textarea>
<script type="text/javascript" src="../public/js/myJSFile.js"onload="setTextAreaValues('myTextAreaID2')"></script>
<textarea id="myTextAreaID3" name="myTextArea3"></textarea>
<script type="text/javascript" src="../public/js/myJSFile.js"onload="setTextAreaValues('myTextAreaID3')"></script>
Here's myJSFile.js file
var textAreaID;
$(function(){
var myTextArea = $('#'+textAreaID);
//something is being loaded here, and it is loaded fine.
});
function setTextAreaParameters(param){
textAreaID = param;
}
Thanks in advance.
This is not very good idea to do it like this, however it's interesting to understand why it happens. In your code below you are defining global variable textAreaID:
var textAreaID;
$(function() {
var myTextArea = $('#' + textAreaID);
//something is being loaded here, and it is loaded fine.
});
function setTextAreaParameters(param) {
textAreaID = param;
}
This script is injected three times into document. After the last script tag the value of textAreaID variable will be myTextAreaID3, because it's global and the last setTextAreaParameters invocation will override previous. Remember that scripts are loaded synchronously in your case (no async or deferred attribute), it means that onload callbacks don't wait and immediately set textAreaID to new values.
However DOMContentLoaded event has not yet fired. This is the event you are subscribing with this code:
$(function() {
// DOMContentLoaded
});
When it eventually does - only the third textarea will be processed - the one with id myTextAreaID3.
Better approach would be to have only one script tag and set textareas the same className attribute:
<textarea id="myTextAreaID2" name="myTextArea2" class="editor"></textarea>
Then in the script probably have some sort of map with configuration parameters for each individual textarea.
You are including the same script three times, but the browser is probably smart enough to only load it once (no reason to load the same script on the same page more than once).
What you need to do is to include the script only once, say before the end of the body tag
...
<script type="text/javascript" src="../public/js/myJSFile.js"></script>
</body>
and then in the JS file, wait for the document to load, and handle all text areas accordingly:
$(function() {
$('textarea').each(function(i, j) {
console.log('do something for the ' + i + 'th text area');
});
})

remove script tag from ajax response data

i am working on a single page application using jQuery. whole html pages are sent as response to browser as ajax response.
$.post(url, function (data) {
$("#resp").html(data);
$("#resp").find("script").each(function (i) {
//alert($(this).text());
eval($(this).text());
});
});
how to remove script tags from data and than assign html to the div ?
the issue i am facing is the scripts that are written in the response page. they were not getting added to the DOM at first, so i used eval(), now the scripts are getting added twice in some situations.
The easiest way would be to use the .load() function with a fragment selector, since that will strip out <script> tags prior to updating content and result in them not being executed. If you're working with entire HTML pages though there may not be a suitable selector for you to use. However, I'd suggest trying this first:
$('#resp').load(url + ' body');
That would give you just the content between the <body> and </body> tags in the HTML page requested via AJAX.
If that doesn't work, I guess you could try manually stripping out <script> tags from the response prior to adding to the DOM:
$.post(url, function(data) {
var tempDiv = $('<div>').html(data).find('script').remove();
$('#resp').html(tempDiv.html());
});
That creates a new <div> element that isn't part of the document, sets its HTML to the returned HTML from the AJAX request, searches for <script> elements inside that, and then removes them. However, even though the element isn't part of the current document yet, the scripts may still end up being executed (I've never had a reason to do this so I haven't tested it).
with the help of Anthony's answer this is what i did to get it working :
$.post(url, function (data) {
var tempDiv = $('<div>').html(data);
var raw = $('<div>').html(data);
$(tempDiv).find("script").remove();
$("#resp").html(tempDiv.html());
$(scripts).find("script").each(function (i) {
//alert($(this).text());
eval($(this).text());
});
});
i could not understand why
var tempDiv = $('<div>').html(data).find('script').remove();
did'nt work though.

Scripts not running when using get function in jquery

I'm using the $.get() function to extract some data from my site. Everything works great however on one of the pages the information I need to extract is dynamically created and then inserted into a <div> tag.
So in the <script> tag, a function is run and then the data is inserted into <div id="infoContainer"></div>. I need to get the information from #infoContainer, however when I try to do so in the $.get() function, it just says it's empty. I have figured out that it is because the <script> tag is not being run. Is there another way to do this?
Edit:I am making a PhoneGap application for my site using jQuery to move content around so it's more streamlined for mobiles.
This is the code on my page:
$(document).ready(function () {
var embedTag = document.createElement("embed");
var infoContainer = document.getElementById("infoContainer");
if (infoContainer != null) {
embedTag.setAttribute("height", "139");
embedTag.setAttribute("width", "356");...other attributes
infoContainer.appendChild(embedTag);
});
});
As you can see, it puts content into the #infoContainer tag. However, when I try to extract info from that tag through the get function it shows it as empty.I have done the same to extract headings and it works great. All I can gather is the script tag is not firing.
This should provide you the contents of the element:
$('#infoContainer').html();
Maybe your script is executing before the DOM is loaded.
So if you are manipulating DOM elements you should wait till DOM is loaded to manipulate it. Alternately you can place your script tag at the end of your HTML document.
// These three are equivalent, choose one:
document.addEventListener('DOMContentLoaded', initializeOrWhatever);
$( initializeOrWhatever );
$.ready( initializeOrWhatever );
function initializeOrWhatever(){
// By the time this is called, the DOM is loaded and you can read/write to it
$.getJSON('/foo/', { myData: $('#myInput').val() }, onResponse);
function onResponse(res){
$(document).html('<h1>Hello '+res+'</h1>');
};
};
Otherwise... post more specifics and code
You have no ID to reference. Try setting one before you append
embedTag.setAttribute("id", "uniqueID");
It looks like you are wanting to use jQuery, but your example code has vanilla JavaScript. Your entire function can be simplified using the following jQuery (jsFiddle):
(function () {
var embedTag = $(document.createElement("embed"));
var infoContainer = $("#infoContainer");
if (infoContainer.length) {
embedTag.attr({"height": 139, "width": 356});
infoContainer.append(embedTag);
}
console.log(infoContainer.html()); // This gets you the contents of #infoContainer
})();
jQuery's .get() method is for sending GET requests to a server-side script. I don't think it does what you are wanting to do.

Run JavaScript function on element defined with jQuery

Not sure I titled this well.. show's that I'm in unfamiliar territory. How can I run a JavaScript function based off of the element called in a jQuery function?
Theory:
<script type="text/javascript">
$.fillit('video');
</script>
(run fillit on video tag present in page.. interchangable with other elements)
$.fillit = function(){
this is where it says "run on the tag defined in the jQuery function"
}):
$.fn.extend({
fillit : function(){...}
});
then...
$('.video').fillit();
Edit (after comments)
To fill a dom element with other elements/html:
var img = document.createElement('img');
img.setAttribute('src', 'somesrc.jpg');
$('.video').append(img);
or
$('.video').html('<img src="somesrc.jpg"/>');
You can do it the way you described like so
<script type="text/javascript" language="javascript">
$.fillit = function(content)
{
$("result").html(content);
}
//call function
$.fillit("HELLO WORLD");
</script>
or as Alexander just posted if you want to do it on the selected element.
I don't think adding functions directly to jquery with $.func = is a good idea though. If jQuery ever adds a fillit method your method will conflict with theirs.
technopeasant, it sounds like you are using a jquery plugin (in your example, a plugin called 'fillit') and it is asking you to run the plugin on a tag or series of tags. Sorry if I misunderstood your question.
If that is the case, all you need to do is one of two things. If you are trying to run it on a very specific element in the HTML page (one with an id like <div id="myvideo"></div>) then all you need to do is run:
$('#myvideo').fillit();
//Notice the '#' symbol, that looks up the element with an id of 'myvideo'
If you want to run the plugin on a series of elements (like all <p> tags in the entire document, you'd run something like:
$('p').fillit()
//notice no '#', it's just looking up all <p> tags regardless of ID.
Take a look at the jQuery documentation regarding selectors to get a more concrete idea of how these selectors work:
http://docs.jquery.com/How_jQuery_Works
Someone answered with a link to this: http://docs.jquery.com/Plugins/Authoring
exactly what I was looking for. claim your kudos!
(function( $ ){
$.fn.fillit = function() {
this.fadeIn('normal', function(){
var container = $("<div />").attr("id", "filled")
.appendTo(container);
});
};
})( jQuery );

Categories