Why won't this work in Confluence:
AJS.$("body").attr("onload", AJS.$("body").attr("onload") + " myFunction()");
I want to append my own function to the onload attribute of the body element but when I add this code to the Main Layout, Confluence just ignores it. When I try this code using the Chrome debugger, it works just fine.
Edit: I guess I should be a little more clear: The above code seems to work when the Confluence page is loaded the first time. But when the page enters into edit mode, the custom script isn't executed.
As a general rule, wait until the whole page has loaded. In some cases, in particular when plugins are manipulating the DOM, you may have to put in a delay of a second or two before your script runs.
Using JQuery:
{html}
<script type="text/javascript">
AJS.$(document).ready(function() {
AJS.$("#comments-section").hide();
});
</script>
{html}
Using JavaScript:
{html}
<script type="text/javascript">
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (oldonload) {
oldonload();
}
func();
}
}
}
addLoadEvent(function() {
var ele = document.getElementById("comments-section");
ele.style.display = "none";;
})
</script>
{html}
Well, it may depend on many things. For example whether myFunction is already available at the moment when the onload handler wants to execute it.
But why don't you use a more standard way of achieving this:
AJS.$(document).ready(myFunction);
or if you really want to react on the load event
AJS.$(document).load(myFunction);
Base on a discussion with an Atlassian developer, "The proper way to execute a function when the page is loaded is: AJS.$(function($){ ... your code ... });"
This does work for the initial page load but when the page goes into edit mode, this doesn't get executed. Several console.log outputs confirm this.
Related
I need to execute some JavaScript code when the page has fully loaded. This includes things like images.
I know you can check if the DOM is ready, but I don’t know if this is the same as when the page is fully loaded.
That's called load. It came waaaaay before DOM ready was around, and DOM ready was actually created for the exact reason that load waited on images.
window.addEventListener('load', function () {
alert("It's loaded!")
})
For completeness sake, you might also want to bind it to DOMContentLoaded, which is now widely supported
document.addEventListener("DOMContentLoaded", function(event){
// your code here
});
More info: https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded
Usually you can use window.onload, but you may notice that recent browsers don't fire window.onload when you use the back/forward history buttons.
Some people suggest weird contortions to work around this problem, but really if you just make a window.onunload handler (even one that doesn't do anything), this caching behavior will be disabled in all browsers. The MDN documents this "feature" pretty well, but for some reason there are still people using setInterval and other weird hacks.
Some versions of Opera have a bug that can be worked around by adding the following somewhere in your page:
<script>history.navigationMode = 'compatible';</script>
If you're just trying to get a javascript function called once per-view (and not necessarily after the DOM is finished loading), you can do something like this:
<img src="javascript:location.href='javascript:yourFunction();';">
For example, I use this trick to preload a very large file into the cache on a loading screen:
<img src="bigfile"
onload="this.location.href='javascript:location.href=\'javascript:doredir();\';';doredir();">
Try this it Only Run After Entire Page Has Loaded
By Javascript
window.onload = function(){
// code goes here
};
By Jquery
$(window).bind("load", function() {
// code goes here
});
Try this code
document.onreadystatechange = function () {
if (document.readyState == "complete") {
initApplication();
}
}
visit https://developer.mozilla.org/en-US/docs/DOM/document.readyState for more details
Javascript using the onLoad() event, will wait for the page to be loaded before executing.
<body onload="somecode();" >
If you're using the jQuery framework's document ready function the code will load as soon as the DOM is loaded and before the page contents are loaded:
$(document).ready(function() {
// jQuery code goes here
});
the window.onload event will fire when everything is loaded, including images etc.
You would want to check the DOM ready status if you wanted your js code to execute as early as possible, but you still need to access DOM elements.
You may want to use window.onload, as the docs indicate that it's not fired until both the DOM is ready and ALL of the other assets in the page (images, etc.) are loaded.
In modern browsers with modern javascript (>= 2015) you can add type="module" to your script tag, and everything inside that script will execute after whole page loads. e.g:
<script type="module">
alert("runs after") // Whole page loads before this line execute
</script>
<script>
alert("runs before")
</script>
also older browsers will understand nomodule attribute. Something like this:
<script nomodule>
alert("tuns after")
</script>
For more information you can visit javascript.info.
And here's a way to do it with PrototypeJS:
Event.observe(window, 'load', function(event) {
// Do stuff
});
The onload property of the GlobalEventHandlers mixin is an event
handler for the load event of a Window, XMLHttpRequest, element,
etc., which fires when the resource has loaded.
So basically javascript already has onload method on window which get executed which page fully loaded including images...
You can do something:
var spinner = true;
window.onload = function() {
//whatever you like to do now, for example hide the spinner in this case
spinner = false;
};
Completing the answers from #Matchu and #abSiddique.
This:
window.addEventListener('load', (event) => {
console.log('page is fully loaded');
});
Is the same as this but using the onload event handler property:
window.onload = (event) => {
console.log('page is fully loaded');
};
Source:
https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
Live example here:
https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event#live_example
If you need to use many onload use $(window).load instead (jQuery):
$(window).load(function() {
//code
});
2019 update: This is was the answer that worked for me. As I needed multiple ajax requests to fire and return data first to count the list items.
$(document).ajaxComplete(function(){
alert("Everything is ready now!");
});
I need to execute some JavaScript code when the page has fully loaded. This includes things like images.
I know you can check if the DOM is ready, but I don’t know if this is the same as when the page is fully loaded.
That's called load. It came waaaaay before DOM ready was around, and DOM ready was actually created for the exact reason that load waited on images.
window.addEventListener('load', function () {
alert("It's loaded!")
})
For completeness sake, you might also want to bind it to DOMContentLoaded, which is now widely supported
document.addEventListener("DOMContentLoaded", function(event){
// your code here
});
More info: https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded
Usually you can use window.onload, but you may notice that recent browsers don't fire window.onload when you use the back/forward history buttons.
Some people suggest weird contortions to work around this problem, but really if you just make a window.onunload handler (even one that doesn't do anything), this caching behavior will be disabled in all browsers. The MDN documents this "feature" pretty well, but for some reason there are still people using setInterval and other weird hacks.
Some versions of Opera have a bug that can be worked around by adding the following somewhere in your page:
<script>history.navigationMode = 'compatible';</script>
If you're just trying to get a javascript function called once per-view (and not necessarily after the DOM is finished loading), you can do something like this:
<img src="javascript:location.href='javascript:yourFunction();';">
For example, I use this trick to preload a very large file into the cache on a loading screen:
<img src="bigfile"
onload="this.location.href='javascript:location.href=\'javascript:doredir();\';';doredir();">
Try this it Only Run After Entire Page Has Loaded
By Javascript
window.onload = function(){
// code goes here
};
By Jquery
$(window).bind("load", function() {
// code goes here
});
Try this code
document.onreadystatechange = function () {
if (document.readyState == "complete") {
initApplication();
}
}
visit https://developer.mozilla.org/en-US/docs/DOM/document.readyState for more details
Javascript using the onLoad() event, will wait for the page to be loaded before executing.
<body onload="somecode();" >
If you're using the jQuery framework's document ready function the code will load as soon as the DOM is loaded and before the page contents are loaded:
$(document).ready(function() {
// jQuery code goes here
});
the window.onload event will fire when everything is loaded, including images etc.
You would want to check the DOM ready status if you wanted your js code to execute as early as possible, but you still need to access DOM elements.
You may want to use window.onload, as the docs indicate that it's not fired until both the DOM is ready and ALL of the other assets in the page (images, etc.) are loaded.
In modern browsers with modern javascript (>= 2015) you can add type="module" to your script tag, and everything inside that script will execute after whole page loads. e.g:
<script type="module">
alert("runs after") // Whole page loads before this line execute
</script>
<script>
alert("runs before")
</script>
also older browsers will understand nomodule attribute. Something like this:
<script nomodule>
alert("tuns after")
</script>
For more information you can visit javascript.info.
And here's a way to do it with PrototypeJS:
Event.observe(window, 'load', function(event) {
// Do stuff
});
The onload property of the GlobalEventHandlers mixin is an event
handler for the load event of a Window, XMLHttpRequest, element,
etc., which fires when the resource has loaded.
So basically javascript already has onload method on window which get executed which page fully loaded including images...
You can do something:
var spinner = true;
window.onload = function() {
//whatever you like to do now, for example hide the spinner in this case
spinner = false;
};
Completing the answers from #Matchu and #abSiddique.
This:
window.addEventListener('load', (event) => {
console.log('page is fully loaded');
});
Is the same as this but using the onload event handler property:
window.onload = (event) => {
console.log('page is fully loaded');
};
Source:
https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event
Live example here:
https://developer.mozilla.org/en-US/docs/Web/API/Window/load_event#live_example
If you need to use many onload use $(window).load instead (jQuery):
$(window).load(function() {
//code
});
2019 update: This is was the answer that worked for me. As I needed multiple ajax requests to fire and return data first to count the list items.
$(document).ajaxComplete(function(){
alert("Everything is ready now!");
});
I'm a Java developer not well-versed in front-end technologies, so I hope this question isn't too dumb. I have 2 scripts inline on an html page.
<script type="text/javascript">
function printReceipt(orderId,email) {
var printWindowSettings;
var browserUserAgent = navigator.userAgent;
if (browserUserAgent.indexOf("Chrome") > -1) {
printWindowSettings = "status=0,toolbar=0,menubar=0,height=500,width=1000,scrollbars=1";
} else {
printWindowSettings = "status=0,toolbar=0,location=0,menubar=0,height=500,width=1000,scrollbars=1,noopener=1";
}
var path = "/shop/printReceipt?orderid="+orderId;
if (email!=null)
path+="&email=" + email;
var docPrint = window.open(path, '_blank', printWindowSettings);
if (docPrint == null) console.log("window open returned null");
}
</script>
<script type="text/javascript">
bajb_backdetect.OnBack = function()
{
window.history.back=function(){
console.log("Back Button Pressed.")
document.location='/shop/shoppingCart.seam';
}
}
</script>
printReceipt() is invoked in the onClick() handler of an anchor tag.
<div class="pull-left" style="padding-bottom:20px;"><i class="fa fa-print" aria-hidden="true" style="padding-right:6px;"></i>Print Receipt</div>
What I'm finding is that when printReceipt() is invoked, the following script (to manage the back button) gets invoked also. So when printReceipt() is called, my browser navigates to /shop/shoppingCart.seam.
Why would this be? How do I get around this?
I made a bit of research about your issue, and since you mention that you are using a third party script (which is not always the best for a developer), I found something that may help you get rid of it.
This method will need you to delete the third party script you already have (or comment it). Since we are going to handle the back button in a different way.
In the script tag where you had the following code:
bajb_backdetect.OnBack = function() {
window.history.back = function() {
console.log("Back Button Pressed.")
document.location = '/shop/shoppingCart.seam';
}
}
Replace it with this code:
(function(window, location) {
history.replaceState(null, document.title, location.pathname+"#!/history");
history.pushState(null, document.title, location.pathname);
window.addEventListener("popstate", function() {
if(location.hash === "#!/history") {
history.replaceState(null, document.title, location.pathname);
setTimeout(function(){
location.replace("/shop/shoppingCart.seam"); //Here goes your URL
},0);
}
}, false);
}(window, location));
And now, if you did remove the third party script (or commented it), you should be able to see the expected behavior.
If you want to see more about this, there is a question similar to this that has been already answered saying the best approach for handling the window back event is doing it by yourself.
I took this information from this answer, just complemented it with the explanation and code for your specific issue. Hope it helps.
Note: If it still not working, you will need to provide a more open context of your code, since there might be something else causing it to not work.
Probably the anchor being clicked causes the browser to follow the link.
Given this:
click me
Clicking that link will run the function and then the page will reload. Your back detection script will notice that the page is being unloaded and do stuff (apparently).
Change it to:
click me
To prevent the link from being followed.
In my <body> I have a component that inserts a script that is supposed to run only after all the page has completely loaded:
<script>
$('<script id="smallPlacarScriptdId">\
$(window).load(function() {\
$(".main.right").hide();\
$("#rightzero").show();\
$(".comp.smallPlacard.firstChild").click(function () {\
var clicked = $(this).parent().attr("id");\
$("main.right").hide();\
$("#right"+clicked+"").show();\
});\
})\
<\script>').appendTo("body")
</script>
That's not happening and this script (1) is correctly inserted into the DOM but (2) is not working (not hiding .main.right nor showing #rightzero).
I though that by using this approach I would guarantee that it would be the same as just put this script at the bottom of the <body> but it isn't. In fact if I put it (not dynamically like this) in my page it produces the desired result.
I tried setTimeout() to validate my theory but I'm getting an error in jQuery and I'm lost.
That might be the problem:
<\script>').appendTo("body")
Browser might think you are actually closing your script tag. Change it to
</' + 'script>').appendTo("body")
Check this plunker out: http://plnkr.co/edit/Oc6yrFMdPoW2WV257CBQ?p=preview
Just use this code
<script id="smallPlacarScriptdId">
$(window).load(function() {
$("main.right").hide();
$("#rightzero").show();
$(".comp.smallPlacard.firstChild").click(function () {
var clicked = $(this).parent().attr("id");
$("main.right").hide();
$("#right"+clicked+"").show();
});
})
</script>
Sorry I didn't read you question well enough.
Javascript will allow you to access undeclared variables, so use that to your advantage. Check if a variable is set, undefined is treated as a false so no need for initialization. As soon as you enter the code just set it to true so nothing else will execute.
Hopefully this solves the problem for you, but you really should look at from the server avoiding the javascript, it will bloat the page.
<script>
if (!myScriptHasLoaded)
{
myScriptHasLoaded = true;
$(window).load(function() {
$("main.right").hide();
$("#rightzero").show();
$(".comp.smallPlacard.firstChild").click(function () {
var clicked = $(this).parent().attr("id");
$("main.right").hide();
$("#right"+clicked+"").show();
});
});
}
</script>
-=- THIS CODE FUNCTIONS. I AM LEFT TO ASSUME THERE WAS A PROBLEM WITH THE CACHE AS NOTHING HAS BEEN ALTERED BETWEEN NON-FUNCTION/FUNCTION. THANK YOU ALL FOR YOUR HELP (especially Niko who got the ball rolling and helped me form a richer understanding of jquery syntax) -=-
I've written this script by hand, and finally decided to update it to jquery in a bid to get used to that, and streamline the code. This is supposed to render a simple menu (which it did before).
Both .js files are in the same directory as the .html file. This is being tested on my pc, not on a server.
A previous version of this code worked perfectly just linking to taskMaster.js. At that point my code didn't use "$" tagged calls.
Firebug is displaying an error of "ReferenceError: $ is not defined" when it tries to call $(document).ready(function () {
the "net" tab doesn't display either .js files as being loaded; the net tab is completely empty and shows no activity - I believe this is because I'm testing this off my PC; the net panel is empty when I load the functioning code
I've reinstalled a fresh version of jquery on the offchance there was something wrong, to no avail
Broken code "taskMaster.js":
$(document).ready(function () {
//main menu
function Main()
{
var mainList = ["New List","Show Lists","Delete Lists"];
//var onClick = [New,Lists,Delete];
var mainMenu = new Menu("Main Menu","menuMain",mainList/*,null*/);
mainMenu.contentMenu();
}
$(Main);
//menu class
function Menu(name,divClass,content/*,onclick*/)
{
$("#interface").html(null);
//title
formatDiv("interface",name,divClass,name/*,null*/);
//return
if(name != "Main Menu")
{
formatDiv(name,null,"return","^ Main Menu","Main()");
}
//display options
this.contentMenu = function()
{
for(i=0; i<content.length; i++)
{
formatDiv("interface",content+i,"menuContent",content[i]/*,onclick[i]*/);
}
}
}
//format divs
function formatDiv(target,divId,divClass,content/*,onclick*/)
{
$("#"+target).append("<div id=\'" + divId + "\' class=\'" + divClass + "\'>" + content +"</div>");
/*$("#"+divId).click(function()
{
onclick;
});*/
}
});
I commented out unused lines, but it's showing "$" as undefined
Here is the HTML:
<html>
<head>
<script type="text/javascript" src="jquery-1.7.2.min.js"></script>
<script type="text/javascript" src="taskMaster.js"></script>
<link rel="stylesheet" type="text/css" href="taskMaster.css" />
</head>
<body>
<div id="interface">
</div>
</body>
</html>
As far as I can tell there is nothing wrong with this html - the same format worked perfectly fine before. All that's changed is that I've introduced jquery and changed some commands in taskMaster.js to use "$".
Okay, I'm now posting this as an answer, because it is easier to provide some examples here.
First thing is: Whenever you do an operation that accesses the DOM, such as $("#interface").html(null);, you will first need to make sure that the DOM is ready. This is what the "ready" event is for:
$(document).ready(function() {
/* The code here is executed when the DOM is ready! */
});
So if "Main()" is a function that kicks everything off, you can simply list it to be called when the DOM is ready:
function Main() {
/* ... */
}
$(document).ready(Main);
Most the time it is also safe to encapsulate the entire JavaScript code in a "ready" event handler:
$(document).ready(function() {
function Main() { /* ... */ }
function formatDiv(...) { }
// ...
// All functions are defined, now let's go:
Main();
});
Now the click handlers: jQuery's "click()" function expects a function that is to be called when the corresponding DOM elements gets clicked on. You're currently passing strings like "New()" to it, but you should directly pass the functions. To do so, alter the code in "Main()" this way:
// Old: var onClick = ["New()","Lists()","Delete()"];
var onClick = [New, Lists, Delete]; // New
This adds the actual functions to the array, not just their names.