I got a problem and dont know how to fix it.
A have the following js script:
$(function () {
$.ajaxSetup({ cache: false });
var timer = window.setTimeout(function () {
$(".alert").fadeTo(1000).slideUp(1000, function () {
$(this).hide();
});
}, 3000);
$(document).on("click", "[data-hide]", function () {
if (timer != null) {
clearTimeout(timer);
$(this).closest("." + $(this).attr("data-hide")).hide();
}
});
});
<div class="well">
<h3>
<strong>#Model.Name</strong>
<span class="pull-right label label-primary">#Model.AverageRaiting.ToString("# stars")</span>
</h3>
<span class="lead">#Model.Description</span>
#Html.DialogFormLink("Update", Url.Action("UpdatePhoto", new {id = #Model.PhotoId}), "Update Photo", Url.Action("Photo"))
#Html.Action("InitializeAlerts")//When this action is executing the document was already ready (by the first time when full page was loading), so I have no chanse to catch any .alerts in js alert file after updating this partial for another one.
</div>
Sometimes I have a situation when document is ready ealier than I have any .alert classes im my partial view. So, how to rewrite the function to execute it after my partial view is updated with valid .alert?
You either need to wait around for $(",alert") to exist first, or you need to add your code inside the loading processing.
If you do not wish to couple your JS files tightly, you can broadcast a "panel loaded" event from the other script, which you catch at the document level.
e.g.
$.ajax({...}).done(function(loadedhtml){
$somepanel.html(loadedhtml);
$(document).trigger("panelloaded", $somepanel);
});
and listen for the generic "panel loaded" event in your main:
e.g.
$(document).on('panelloaded', function(panel){
// Do stuff here to the newly loaded panel
});
If you reload your Partial View i suppose the best thing is to place your code in .ajaxComplete() function.
It will be ready rigth after your ajax request done.
Related
I use CookieBot in our html pages. CookieBot javascript doesn't load in test environment and throws a net::ERR_ABORTED 404 error.
When this happens, the loading spinner in the page keeps displaying after the page loading has been completed.
I tried following options to invoke a listener after page loading is completed. But none of them works:
document.addEventListener("load", (e) => {
console.log("document load");
});
document.addEventListener("DOMContentLoaded", function(event) {
console.log("DOMContentLoaded");
});
$(document).ready(function() {
console.log("ready!");
});
$(document).ready(function() {
console.log("document is ready");
});
$(window).on("load", function(){
console.log("window load!");
});
window.onload = function () {
console.log("window onload!");
};
I guess CookieBot script overrides my listeners. Here is an example where listener is not invoked. When you remove the CookieBot script it runs: https://jsfiddle.net/hkarakose/4by26Lr3/1/
How can I invoke a function after page loading is finished?
You can invoke a function after page loading with:
window.onload = function() {
//here you can write your function and invoke it.
}
Edit:
Maybe I didn't understand your request, but now I'm reading more carefully.
The problem is in the script, right? If you insert the script on HEAD, it will be loaded first.
You could insert the type of the script in this way:
type = "text / plain" with a data-attribute: data-attribute = "script-cookie".
Then change the type once everything has been loaded, like this:
window.onload = function () {
var allPrefScript = document.querySelectorAll ("script [data-attribute =" script-cookie "]");
allPrefScript [0] .setAttribute ("type", "text / javascript");
}
Although #davilink92's answer works, I solved this issue in a more practical way.
I attached external script loading to window load event:
window.addEventListener('load', function () {
$.getScript("https://consent.cookiebot.com/uc.js?cbid=d180eb7a-8f13-4549-bacc-6d4a6dfb5da8&culture=en");
$("#global-loader").fadeOut("slow");
});
In this way, the script couldn't prevent the window load event listener to be invoked by the browser. And thus, I was able to remove the loading spinner after page is loaded.
I have the habit to use document.addEventListener("load", (e) => {console.log("loaded"); })
Can you show us more code to see if your problem is here? I think all of yours tests are correct and I dont understand why it isnt working.
When I load Bootstrap popver content with ajax, the popover is not showing.
Javascript:
var id = 1;
$.post("load.php?pageid",
{
pageid:id;
},
function(data,status){
document.getElementById("body").innerHTML=data;
});
HTML response:
hover for popover
<script>
$(function ()
{ $("#example").popover();
});
</script>
When I place the HTML response above directly in the <body id="body"></body> code, the popover works fine. I dont understand what is going wrong here.
The problem is that you're setting up the popover inside of the function $(). Rather than
$(function ()
{ $("#example").popover();
});
It should be just
$("#example").popover();
Or perhaps better
$(document).ajaxComplete(function() {
$("#example").popover();
});
The reason being that any function inside of $() is run when the document is first finished loading, when the "document ready" event is fired. When that code is pasted inside of the original HTML, it works because it's present when the document finishes loading.
When it's the response from an AJAX call, it won't run inside of $(), because the "document ready" event already fired some time ago.
with the help of jQuery you can initialize all things that needs to be initialized using
$(document).ajaxSuccess(function () {
$("[data-toggle=popover]").popover();
$("[data-toggle=tooltip]").tooltip();
// any other code
});
inspired from Olaf Dietsche answer
<script>$(function () { $('[data-toggle="tooltip"]').tooltip()});</script>
Add this at the end of whatever you are loading in with ajax. You should already have this somewhere to opt-in to the tooltip, but put it again to re-initialize the tooltip.
I'm trying to intercept clicks on this link:
<a id="test-button" href="#">Test</a>
with this js:
(function() {
$('#test-button').click(function (event) {
console.log("This code never gets called.")
event.preventDefault();
$('#alert-placeholder').html(['<div class="alert"><a class="close"',
'data-dismiss="alert">×</a>',
'<span>"+message+"</span></div>'].join())
return false;
})
console.log("yes, this code loads");
debugger;
})();
but the URL '#' loads and the code in the click() function doesn't run. What am I missing?
I'm using this code in a flask app using bootstrap.
Seems like you're trying to attach an event handler to the element that doesn't exist yet
(function() {
})();
only creates a local scope but doesn't guarantee DOM to load. To confirm it - add console.log($('#test-button').length); to your code.
What you need is to wrap your code with
$(function() {
// your code is here
});
instead
My Main View:
#Ajax.ActionLink("append smth", "AddSmth", new AjaxOptions { UpdateTargetId = "smthContainer", InsertionMode.InsertAfter })
<div id="smthContainer"></div>
My Controller:
public ActionResult AddSmth()
{
return PartialView("Smth");
}
Smth partial view:
<input type="text" id="dateOfSmth" />
<script type="text/javascript">
$(document).ready(function () {
$('#dateOfSmth').datepicker();
});
</script>
The problem is that ready function is called before partial view is added to document, so $('#dateOfSmth') is empty. Everything works fine if I replace InsertionMode.InsertAfter with InsertionMode.Replace. Do you have any idea why is not it woking correctly with InsertionMode.InsertAfter?
EDIT: works well when appending view with jQuery:
Add Smth
<script type="text/javascript">
function addSmth() {
$.get('#Html.Raw(Url.Action("AddSmth"))', null, function (view) {
$('#smthContainer').append(view);
});
}
</script>
The code below is from the jQuery codebase:
// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
if (!document.body) {
return setTimeout(jQuery.ready, 1);
}
So the ready event waits till the body element has been created. If the partial view is added after body element has been created then that is why your function is executing too early.
In theory you could do something similar to execute code after the partial view has been loaded.
function createDatePicker( ) {
if ( !document.getElementById("dateOfSmth") ) {
return setTimeout( createDatePicker, 1);
}
// do stuff
}
The ready event is fired a single time - when the DOM has finished being loaded - and doesn't fire again when you insert AJAX loaded content. If you add a ready event handler after that has happened then it will be executed automatically.
The problem is probably caused by a difference in how the two insertion modes - InsertionMode.InsertAfter and InsertionMode.Replace - handle <script> tags in the content.
If you can, simply call your:
$('#dateOfSmth').datepicker();
line after the AJAX content has been loaded.
I need to keep displaying the loading gif until all images
in the returned data (html) have been finished loading.
The data and everything is returned properly, but the .live('load', function() {})
is never executed, have tried without the .live as well. The contents of #ContentBody
just get replaced with the returned html data (#LoadingLayer disappears too of course) and I can see images loading as usual.
<script type="text/javascript">
$("#RightLink").click(function (event) {
event.preventDefault();
var tourl = $(this).attr('data-ajax-url');
$.ajax({
type: "POST",
url: tourl,
dataType: "html",
async: true,
beforeSend: function () {
$("#LoadingLayer").show(); //show layer with image loading gif
$('#ColumnContainer').hide();
},
success: function (data) {
$('#ContentBody').html(data).live('load', function () { $("#LoadingLayer").hide(); });
}
});
});
</script>
HTML layout:
<body>
<div id="ContentBody">
<a id="RightLink" href="/store/ContentBodyGenerator" />
<div id="LoadingLayer"><img src="loading.gif" /></div>
<div id="ColumnContainer">... Main contents, lots of images here</div>
</div>
</body>
Why don't you just hide #LoadingLayer directly?
$('#ContentBody').html(data);
$("#LoadingLayer").hide();
Edit:
I misread your question, I don't think there is an easy way to detect that all images have been loaded. I suggest you try the waitForImages plugin.
Try changing the contents of the "success" function to this...
$('#ContentBody').html(data).live('load', function () {
var imgcount = $(this).find("img").length;
$(this).find("img").one("load", function() {
imgcount--;
if (imgcount == 0) {
$("#LoadingLayer").hide();
}
}).each(function() {
if (this.complete) $(this).load();
});
});
It waits till html(data) is loaded and then gets an image count. It then adds an event handler to each of the images to decrement the image count when the image is loaded. The one("load" code means only allows the following code to run once, and the each code basically says "if it's already loaded (as per cached images) then run the load event".
Once the image count is 0 it hides the loading layer.
Without a URL where I can run this through the console I can't be 100% sure it's accurate, so it may need a fiddle about. If you get stuck give us a shout.
Try binding the load event to the images. Keep track of how many have loaded, and remove the loading layer only after they've all loaded. This is untested code but should give you an idea:
success:function(data){
// Set the content
$('#ContentBody').html(data);
// How many images do we have?
var images = $('#ContentBody img'),
leftToLoad = images.size();
// Listen for load event *FOR IMAGES*
images.bind('load', function (){
// Hey look we loaded one, was that the last one?
if(--leftToLoad === 0){
// Yep, we're done
$("#LoadingLayer").hide();
}
});
}
If you'd rather use live than handling in the ajax callback, do this in your $(document).ready callback:
$('#ContentBody img').live('load', function(){...});
Should do the trick.
Cheers