How do handle dynamically loaded javascript and avoid HTML collision - javascript

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/

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?

Javascript included in MVC partial view only runs the first time

I have a button which I use to load a partial view via jquery ajax call, which on success, just replace a div holder by the json string being returned.
The partial view consists of some javascript and html tags. I have to set the jquery.ajax dataType: "html" in order to get the javascript executed in the partial view when it is loaded.
In the parent view:
$("#test2Div").on("click", function () {
$.ajax({
type: "POST",
url: '#Url.Action("GetMainSolution", "Solutions")',
data: { IdEjercicioSolucion: 9 },
cache: false,
dataType: "html",
success: function (response) {
$("#placeHolder").html(response.ViewContent);
}
});
});
The problem is that this is only working fine for the first time I load the partial view. Once it is executed for the first time, it seems that those javascript included in the partial view being rendered are not being executed anymore or something is missed in the DOM. If I refresh the whole page, with F5 and load the partial view again, it will work again for the first time.
Please, any ideas?
EDIT 1: add more sample code:
Parent view: This is the main view. It displays another another partial view which has some fields and a button. Clicking that button invoke UpdateChViewerLayoutForm function, which trys to load the following partial view into aqviewerholder div.
<div id="dvContainer">
<div class="container">
<div class="row">
#Html.Partial("SolutionsCursoSelectedPartial", Model)
</div>
<div class="row">
<div id="aqviewerholder"></div>
</div>
</div>
</div>
<script type="text/javascript">
function UpdateChViewerLayoutForm(s, e) {
$.ajax({
type: "POST",
url: '#Url.Action("GetSolucionsAQV", "Solutions")',
data: { IdES: s.GetValue() },
success: function (response) {
$("#aqviewerholder").html(response.ViewContent);
}
});
}
</script>
Partial view (SolutionsAQv):
#Code
If Model IsNot Nothing Then
#Html.Raw(Model.TextoHTML)
End If
End Code
<script src="~/Content/AQv/rm.js" type="text/javascript"></script>
<script src="~/Content/AQv/bm.js" type="text/javascript"></script>
<script src="~/Content/AQv/nn.js" type="text/javascript"></script>
Please note that the content delivered to model needs to be parsed using the scripts in partial view.
This is working properly in the first load, but not in the following ones. If refresh the whole page, it works again.
I guess it may be something related to the fact that partials views via ajax do not execute javascript? or that javascript is not finding the target in the DOM in the following exceutions?... but I dont really know how to continue...
Thanks a lot
One possibility is that your partial view includes same jQuery or other javascript bundles as the ones in 'main view'. Once they are rendered for the first time, you will have two such sets (one from your main view and one from your partial view). Make sure you have only one bundle on your webpage and not repeating bundles.
This happened to me.
P.S: This is one possibility! No way I'm saying this is the only reason. I just thought this could be a possibility

Include different .php files in JS popup

I have multiple buttons which currently redirect to different pages for users to perform a single action and they would then need to click another button whilst on the confirmation page to go back where they were before. This is old school and inconvenient...
What I would like to do is create 1 single pop-up box which would get triggered (appear) when any of those buttons are clicked. Inside the box, I want the relevant .php file to appear so users can confirm their action and the page would then reload and display a confirmation message.
Example:
"Delete" button needs to trigger the confirmation-popup.php to appear with the delete.php file included in it so users can confirm the deletion.
"Cancel" button needs to trigger the confirmation-popup.php to appear with the cancel.php file included in it so users can confirm the cancellation.
Here's what I've done:
- Created the pop up and included it on their Account page (that's where all the buttons are).
- Added a JS which passes through the button ID to trigger the popup
When either of the buttons is clicked, the popup would appear fine.
I'm stuck at the stage where different "action".php files need to passed and included in the body of the popup. I know I could create multiple popups each for its relevant action, but we all know this isn't best practice and it's doubling up.
Any help would be appreciated!
Edit: Added code after the below comment
HTML:
<button class="button-small button-red" id="confirm-delete">Delete</button>
JS:
$(document).ready(function() {
$("#confirm-delete").click(function() {
if (!$(".confirm-popup").is(":visible")) {
$(".confirm-popup").fadeIn("slow");
return false;
}
});
});
PHP confirm_popup.php:
<div class="confirm-popup">
<?php include 'delete_auction.php'; ?>
</div>
You can open different iframes in the popup based on the button pressed. That will allow you to use one popup and you will just edit the iframe src attribute to the correct php page. For example you can add an HTML attribute to each button that holds the URL of the page that should be opened by the button. Then you will have some JS code that on the button press will read the attribute that holds the URL and puts it in the iframe src attribute inside the popup.
Something like this using jQuery:
<button class="myclass" cotent-url="delete.php">Delete</button>
<button class="myclass" cotent-url="save.php">Save</button>
<div class="popup"><iframe src=""></iframe></div>
<script type="text/javascript">
$('.myclass').click(function(){
$('.popup iframe').attr('src', $(this).attr('content-url'));
})
</script>
Or AJAX way:
<button class="myclass" cotent-url="delete.php">Delete</button>
<button class="myclass" cotent-url="save.php">Save</button>
<div class="popup"></div>
<script type="text/javascript">
$('.myclass').click(function(){
$.ajax({
url: $(this).attr('content-url'),
data: {},
success: function(response) {
$('.popup').html(response);
},
dataType: 'html'
});
})
</script>

can't seem to get this ajax code to work? Won't display "dynamically"

I have a live search bar where if the user types in "M" only results that have an M are shown and so on, i've made each result into a link so when the user clicks it, it'll load to a different page.
Now, I can make it load to another page, however I'm trying to do it on the same page but it just wont work.
The search code is simply a form that takes text, then im using the xmlhttp method to make it live.
Now, displaying it is as follows: (I have given it a class to use in the ajax)
echo "<a href = 'display.php' class='display'>" . $row['carName'] . "</a>";
Ajax:
$(document).ready(function() {
$(".display").each(function(){
var btn = $(this);
btn.on("click",function(){
$("#displayDiv").empty();
$.post("display.php",function(data) {
$("#displayDiv").append(data);
Any help? Currently, clicking it just loads test.php on which I have some text to see its working. I'm trying to get it to load dynamically on the right.
Thanks.
EDIT: it loads test.php which is:
<html>
<body>
<div id="displayDiv">
<h2> Test </h2>
</div>
</body>
</html>
EDIT2: div id which is in the same page as script:
<html>
<div id="displayDiv" style="width: 40%; float:right">
</div>
It's just following the link when you click on it. To stop this you need to change the event handler to:
btn.on("click",function(e){
e.preventDefault();
// rest of your code
});
$(document).ready(function() {
$(".display").on("click", function(e) {
$("#displayDiv").empty();
$.post("display.php", function(data) {
$("#displayDiv").append(data);
}
);
e.preventDefault();
});
});

<script> not returned in AJAX

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);
}

Categories

Resources