<script> not returned in AJAX - javascript

I am creating a WordPress theme and using AJAX to load new archive pages. The problem is that the whole < script type="text/javascript">//something//< /script> is not returned in the newly-acquired content.
Suppose I have these codes initially :
<div id="post-1">
<script type="text/javascript">
//some codes here//
</script>
<div class="content">
</div>
</div>
After navigating to the next page and back to this original page using AJAX, I will get these (in Firebug) instead :
<div id="post-1">
<div class="content">
</div>
</div>
The whole chunk of Javascript codes will not be returned, but under the 'Inline' script in 'Script' tab of Firebug, they are still there.
So, I'm wondering what have I done wrong in retrieving the new content using AJAX? Below is the code that I'm using :
jQuery('.ajax-pagination a').live('click', function(e){ //check when pagination link is clicked and stop its action.
e.preventDefault();
var link = jQuery(this).attr('href'); //Get the href attribute
jQuery.ajax({
url: link,
dataType: "text",
context: document.body,
beforeSend: function(){jQuery('#container').fadeOut(500)},
success: function(html) {
var newhtml = $('#container', $(html))
$('#container').html(newhtml);
$("container").find("script").each(function(i) {
eval($(this).text());
});
jQuery('#container').fadeIn(500);
},
error: function() {
alert('Error');
}
});
});
I am trying to run the Javacript loaded via AJAX, but the problem seems to be that the Javascript itself isn't even returned together with the rest of the content.
Thanks for reading such a long question and I really appreciate your help!

The .html() method strips <script> tags from inserted HTML.
You'll need to traverse the HTML before you try to insert it to find all of the script tags and then use jQuery.globalEval to execute their contents.
success: function(html) {
var newhtml = $('#container', $(html));
// execute included script tags - assumes inline for now
$('script', newhtml).each(function() {
$.globalEval($(this).text());
});
$('#container').html(newhtml).fadeIn(500);
}

Related

jQuery not working in MVC partialview after moving the JavaScript code to separate file and reference the file in a script tag cause problems

I am new to web development and I am using .net core MVC with VS2017, and trying to load several partial views inside a div (section1 and section2) using ajax and javascript.
My index page:
<div>
<a asp-action="setupprogram" asp-controller="Setup" data-target="Section1" class="section1">Setup Programs</a>
</div>
<br />
<div id="Section1"></div>
<br />
<div id="Section2"></div>
<br />
When I include the javascript code inside the chtml it run perfectly, but when I remove the jQuery code and put it inside site.js, it didn't work
My site.js code:
$(document).ready(function () {
$("#Sform").submit(function (e) {
e.preventDefault();
var urlsx = $('#UrlsX').val();
var urls = $('#Urls').val();
$.ajax({
url: urls,
type: "POST",
dataType: "html",
data: $('#Sform').serialize(),
success: function (data, textStatus, xhr) {
$('#Section2').html(data);
$("#Section1").load(urlsx)
},
error: function (xhr, textStatus, errorThrown) {
$("#Section2").html(xhr.responseText);
}
});
});
$('.section1').click(function (e) {
e.preventDefault();
$("#Section1").show();
$('#' + $(this).data("target")).load($(this).attr("href"));
});
$('.section2').click(function (e) {
e.preventDefault();
$("#Section1").show();
$("#Section2").show();
$('#' + $(this).data("target")).load($(this).attr("href"));
});
});
the simple way to solve this issue is to include the script tag
<script src="~/js/site.js"></script>
at each partial view to load the JavaScript code after the DOM load and to be able to find the required objects, accounting to this post and also this post
Mmy problem is that the JavaScript code make the page load time too long after few clicks and it themes that the code is looping inside my C# action several times and making the page load time unaccepted.
Also the second partial view do not recognize the code and load in a new page rather than being rendered in the Section2 div.
The site.js file is referanced in the _Layout.cshtml:
<environment names="Development">
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="~/lib/bootstrap/dist/js/bootstrap.js"></script>
<script src="~/js/site.js"></script>#*asp-append-version="true"*#
</environment>
The first patial view that load in section one is as follwoing :
#foreach (var p in Model)
{
<div>
#p.ProgName
<a asp-action="setupprogramEdit" asp-controller="Setup" asp-route-id="#p.ProgID" data-target="Section2" class="section2">Edit</a>
|| <a asp-action="setupprogramdelete" asp-controller="Setup" asp-route-id="#p.ProgID" data-target="Section2" class="section2">Delete</a>
</div>
}
<div>
<a asp-action="setupprogram" asp-controller="Setup" data-target="Section1" class="cancel2">cancel</a>
</div>
First : is it better to keep the JavaScript code inside the chtml view page ?\
Second : any idea how to come over this issue, in case i decided to move the JavaScript code into a separate file ?
Is best to keep the jquery code in a separate file and include that file in your view.
If your page loading time is big, why you don't load the partials when you click the button instead of loading them all at once and keeping them hidden?
Also you are requesting the same partials multiple times?

jquery loading script when preparing document

I have a problem with jquery and would appreciate a help from stackoverflow community to solve following problem
Lets assume that there a server side script which creates doc file and following links calls it
<a class="prepare_doc_file" href="somepage.php?action=docfile">docfile</a>
what i need is jquery script, which shows loading image, when doc file if being prepared (or when the link is clicked) and hide it after getting download popup.
I see loading circle in the tab in browser. I need the same thing inside the html document
Thank you
You need to use AJAX, and generate a tempfile to download.
Your php can generate file and save to some temp path. After downloading you can delete this file.
<a class="prepare_doc_file" id="downloadfile" href="somepage.php?action=docfile">docfile</a>
function loadFile(){
document.getElementById('downloadfile').innerHTML='loading, please wait';
$.ajax({
url: 'somepage.php?action=docfile',
complete: function (data) {
document.getElementById('downloadfile').href='path to file'; //path may be returned on php.
document.getElementById('downloadfile').innerHTML='docfile';
}
});
}
<div id="myDiv">
<img src="loading gif image url">
</div>
<script>
$.ajax({
type: "POST",
url: "url to the page where the contnt is",
data: 'parameters if any' ,
success: function(result){
//logics
$("#myDiv").html("<a class="prepare_doc_file" href="somepage.php?action=docfile">docfile</a>");
});
</script>

How do handle dynamically loaded javascript and avoid HTML collision

I've been smashing my head against a brick wall for the past 3 hours trying to figure out how to handle this.
Here's what I am trying to:
When I press a viewProduct button, it loads a page product/view/{id} via a simple jQuery ajax call and insert it in a div.
Here is my main page (index.php)
<script type="text/javascript">
$(function() {
$(".viewProduct").on('click', function() {
var productID = $(this).data('id');
$.ajax({
type: 'GET',
url: "http://mywebappurl.com/product/view/" + productID,
success: function(view) {
$("#productInfo").html(view);
}
});
});
</script>
<button class="viewProduct" data-id="11">View Product</button>
<div id="productInfo"></div>
Product/view contains some HTML (including viewParentProduct) and some javascript.
Here product/view.php
<script type="text/javascript">
$(function() {
// More javascript here....
$("#viewParentProduct").on('click', function() {
var parentProductID = 15; // This number changes depending on the product and comes from PHP
$.ajax({
type: 'GET',
url: "http://mywebappurl.com/order/view/" + parentProductID,
success: function(view) {
$("#parentProductInfo").html(view);
}
});
});
</script>
<button id="viewParentProduct">View parent product</button>
<div id="parentProductInfo"></div>
So far, it works fine. The dynamically loaded javascript executes perfectly. The problem comes when the the parent product also has a parent product. So if I press the viewParentProduct , it loads the same page (product/view) and inject it in the dom, duplicating the HTML elements and javascript.
Visually:
STAGE 1: Click on viewProduct --> product/view/11 is injected into productInfo div
STAGE 2: Click on viewParentProduct --> product/view/15 is injected into parentProductInfo div
STAGE 3: Click on viewParentProduct --> product/view/{someOtherParentProductID} is injected into parentProductInfo div
At this point I am screwed. Since the same HTML/Javascript has been injected in the DOM twice, the next time I press on viewParentProduct, it'll trigger the wrong button and/or load the content of product/view in the wrong parentProductInfo div.
Of course I could do something like this but it's pretty ugly:
$(".viewProduct_11").on('click', .....
<button class="viewProduct_11" data-id="11">View Product</button>
<div id="productInfo_11"></div>
// Where 11 comes from PHP ex: <?php echo $productID; ?>
So my question is: Is there a way to sort of "namespace" a set of javascript-HTML or do you know a way to fix this problem ? Even if I namespaced the javascript, the HTML element's IDs would still be duplicated.
I'm really out of ideas!
-----------------------EDIT-----------------------
I need to have the javascript inside the view (product/view) because it's rather complex. In fact it has nothing to do with the simple snipped I used as an example in this question. I'd rather have the javascript related to the product/view page inside the view itself to improve cohesion. In reality, when clicking on the viewProduct button, the product/view page is loaded in a modal (a div with an overlay) and there can be multiple modal overlapping each other with the same HTML/javascript code coming from product/view. I could work around the javascript collision by wrapping the product/view's javascript in a namespace, however the HTML and the DOM elements and their ID will still be problematic. Hence why I'm looking for a way for namespacing a block of javascript AND HTML...somehow. I'm clueless.
Try this:
index.php
<script type="text/javascript">
$(function() {
$("body").on('click', '.viewProduct', function() {
var elem = $(this),
productID = elem.data('id');
$.ajax({
type: 'GET',
url: "http://mywebappurl.com/product/view/" + productID,
success: function(view) {
elem.next().html(view);
}
});
});
</script>
<div class='viewWrapper'>
<button class="viewProduct" data-id="11">View Product</button>
<div class="productInfo"></div>
</div>
product/view.php
<div class='viewWrapper'>
<button class="viewProduct" data-id="15">View Parent Product</button>
<div class="productInfo"></div>
</div>
// Where 15 comes from PHP ex: <?php echo $productID; ?>
JavaScript from main page will be working for new loaded content.
ex.: http://jsfiddle.net/BV66Z/1/

deferring JavaScript execution in document received via AJAX

I'm receiving this HTML document via AJAX:
<form enctype="multipart/form-data" method="POST" action="admin.php?do=media&action=file-upload">
<div id="uploadForm">
<div id="fileList">
</div>
[Select File]
[Start Upload]
</div>
</form>
<script type="text/javascript">
// $(function(){}); not working when data loaded with ajax request
var ajaxUpload = new plupload.Uploader({
runtimes: 'gears, html5, flash',
url: 'upload.php',
browse_button: 'selectFile',
});
ajaxUpload.bind('Init',function(param){
console.log(param);
console.log($('selectFile'));
});
$('#uploadFile').click(function(){
alert('Something');
});
ajaxUpload.init();
</script>
When I append this to the main document, the JavaScript inside it will immediately run and not be able to find the referenced DOM elements.
It works when I add a time-out on the code, but I would like to know a better way at achieving this.
Update
Modified to reflect the true intent of the question.
This is not possible in the manner which you've described, because the JavaScript is not bound to a condition to run, so it runs immediately.
The code inside the document you're receiving via AJAX should be wrapped inside a function by providing side:
function onDocumentReady()
{
// your code here
}
Then from the loading code:
// get the HTML and JavaScript in data
$('#container').append($(data));
// fire the function to let JavaScript run
onDocumentReady();
If you have multiple requests, the providing side should make the onDocumentReady function unique by adding random alphabets to the function name, e.g. onDocumentReady_123()
Wrap your code inside a $(document).ready. This will ensure that your JavaScript doesn't run until the DOM is loaded and the elements you're targeting will be available on the page:
$(document).ready(function() {
var ajaxUpload = new plupload.Uploader({
runtimes: 'gears, html5, flash',
url: 'upload.php',
browse_button: 'selectFile',
});
ajaxUpload.bind('Init',function(param){
console.log(param);
console.log($('selectFile'));
});
$('#uploadFile').click(function(){
alert('Something');
});
ajaxUpload.init();
});
For more information on how this works, see the documentation for jQuery ready. The site also has information on other useful jQuery commands that may be helpful, and I encourage you to check it out and try the examples that are there. Good luck!
UPDATE:
If I understand correctly, you're getting something like this HTML from the server:
<!-- Pulled HTML from the server using AJAX -->
<div id="uploadForm">
<div id="fileList">
</div>
[Select File]
[Start Upload]
</div>
And maybe trying to inject it dynamically into this:
<form action=""> <!-- inject HTML here --> </form>
If my understanding is correct, then this should allow you to inject the HTML and then only run the JavaScript once the AJAX request completes, and the new DOM has been injected. Keep in mind that, since I don't have all of your code, this is just a conceptual example:
$.ajax({ url:"/somepathtoGetData",
success: function(data) {
// your HTML is in the variable "data", and this injects the HTML into
// the form element on the page
$('form').html( data );
// now that the DOM elements are loaded from the AJAX request, do your
// other stuff with the uploader here
var ajaxUpload = new plupload.Uploader({
runtimes: 'gears, html5, flash',
url: 'upload.php',
browse_button: 'selectFile',
});
ajaxUpload.bind('Init',function(param){
console.log(param);
console.log($('#selectFile')); // added # for id attr
});
$('#uploadFile').click(function(){
alert('Something');
});
ajaxUpload.init();
}
});
UPDATE
Say I have two php files, one is main.php, having such codes: (not including jQuery src, please add your own)
<script type="text/javascript" charset="utf-8">
$(document).ready(function(){
$('#b').click(function(){
$.post("ajax.php",
{
taskaction: "getFormAndJs"
},
function(data){
$('body').append(data);
// $(document).trigger("ready");
},
"text");
})
});
</script>
<body>
aaaaaaaaaaaaa
<input type=button id="b" value="click" />
</body>
another is ajax.php, like this:
<?php
if ($_POST['taskaction'] == 'getFormAndJs') {
echo '
<div id="uploadForm">222</div> <input type=button id="a" value="upload" />
<script>
$("#a").click(function(){
alert(123);
})
</script>
';
}
?>
It seems work on my side (click button a and alert "123"), whether I add the
$(document).trigger("ready");
or not.
Does this look like your situation?

ajax-loaded script not functioning

This code below is loaded via ajax:
<div class="main">
//some content
</div>
<div class="advanced">
//some content
</div>
<div class="other">
//some content
</div>
<div class="pass">
//some content
</div>
<script>$('.advanced,.other,.pass').hide();</script>
They hide fine when loaded normally, but when loaded via ajax it doesn't work anymore. Why is it so? I'm not really sure if $.on() would really help here.
If the example above is loaded via jQuery ajax, why not just call the
$('.advanced,.other,.pass').hide();
upon completion of the ajax request?
For example:
$.ajax({
url: "Your AJAX URL",
dataType: 'html',
type: "POST",
success: function (json) {
// Add you elements to the DOM
},
complete: function () {
$('.advanced,.other,.pass').hide();
}
});
According to jQuery
any embedded JavaScript inside the retrieved data is executed before the HTML is returned as a string.
this could mean that your script executed first, before you managed to do anything with it.

Categories

Resources