Have javascript prompt only display after page is loaded [duplicate] - javascript

This question already has answers here:
window.onload vs $(document).ready()
(17 answers)
Closed 6 years ago.
we are building off a battleship game in github.
Battleship
Here user, is prompted with his name and position of his ships and based on the answer, output is displayed on a textarea called domsole.
Domsole = (function($) {
var output;
var init = function(outname) {
output = $('#'+outname);
output.attr('disabled', 'disabled');
};
var ask = function(question) {
write(question);
var text = prompt(question);
write('> ' + text);
return text;
};
var write = function(text) {
output.append(text + "\n");
output.scrollTop(9999999999);
};
return {
ask: ask,
init: init,
write: write
};
})(jQuery);
$(document).ready(function() {
Domsole.init('domsole_out');
});
However, the all the prompts are asked before the page is loaded.
some of the prompts are
this.name = Domsole.ask("What's your name, Playa?");
Domsole.write("Alright, " + this.name + " you shall be.");
........
......
var coord = Domsole.ask("Where would you like to take a shot? Valid input is: x, y");
These code that calls Domsole.write and Domsole.ask are also in document.ready.
Here all the prompts are asked before anything is displayed on the screen? How to resolve this issue?

It's a good habit to put your JS script tags at the end of the body, so that all your HTML loads first.
The browser engine loads HTML and JS in the order they appear in the document, but it's better to take ownership of that load order. One possible event order is:
domsole.js loaded.
battleship.js loaded.
index.html document ready event.
Game starts here.
No JS code should have executed before that last step. So make sure that your prompts are not called prior to that point.

It seems that you don't understand the execution flow of your application. There is no possible way that these questions are displayed before the page is loaded unless you have another call to the init function that you have not mentioned. The output variable will be undefined until the init method is called and would therefore lead to javascript errors if ask was called before init is called. It seems that you are mistaking "loading" for "rendering". If you want to ensure that rendering of the page has been completed before your code is executed than you should use a timeout of around 50ms to call your initialization functions. Any modifications to the page triggered in jquery's ready event will not be displayed until after the event processing is completed. By calling the setTimeout function within the ready event handler you can delay processing until after the rendering of ready event handlers are completed.

Related

Is it possible to substitute "location.href" with invocation of my own function? [duplicate]

This question already has answers here:
How to intercept window.location change
(2 answers)
Closed 5 years ago.
I load a third-party game to my wrapper system, and this game redirects to different places with different parameters. What I need to do is not to allow it to happen, but to capture when it tries to, get the new string it sets "location.href" to and act accordingly. I can run my JS in the game's VM, after all game's code is executed.
Is it possible? I searched the Internet, of course, but didn't find any solution.
/// here is the code I can not change, because it's a part of a 3rd party game I loaded:
function goThere(){
window.location.href = "google.com?some=thing";
}
/// here I can insert something, before the func above is invoked.
var realLocation = window.location;
/// I want the following function to be called every
///time anyone attempts to change location.href:
function onLocationChangeAttempt(newLocation){
alert('Attempt to go to location '+newLocation+'! But we prevented it.');
}
window.location = { get:... set:...} // what goes here? It's the gist of my question.
// and here it's invoked.
goThere();
You can't change it, but you can override it
goThere = function()
{
//your logic
}
You need to add this logic once the third party library has been loaded in your browser session.
Something like
document.addEventListener( "DOMContentLoaded", function(){
goThere = function()
{
//your logic
}
});

How can I execute a JavaScript function on the first page load?

I am wondering if there is a way to execute a JavaScript function once only on the first ever page load and then not execute on any subsequent reloads.
Is there a way I can go about doing this?
The code below will execute once the onload event fires. The statement checks if the onetime function has NOT been executed before by making use of a flag (hasCodeRunBefore), which is then stored in localStorage.
window.onload = function () {
if (localStorage.getItem("hasCodeRunBefore") === null) {
/** Your code here. **/
localStorage.setItem("hasCodeRunBefore", true);
}
}
Note: If the user clears their browsers' localStorage by any means, then the function will run again because the flag (hasCodeRunBefore) will have been removed.
Good news...
Using localStorage can be tedious because of operators and long winded function names. I created a basic module to simplify this, so the above code would be replaced with:
window.onload = function () {
if (!ls.exists('has_code_run_before')) {
/** Your code here... **/
ls.set.single('has_code_run_before', true);
/** or... you can use a callback. **/
ls.set.single('has_code_run_before', true, function () {
/** Your code here... **/
});
}
};
Update #1
Per #PatrickRoberts comment, you can use the in operator to see if a variable key exists in localStorage, so
if (localStorage.getItem('hasCodeRunBefore') === null)
becomes
if (!('hasCodeRunBefore' in localStorage))
and is less verbose and a lot cleaner.
Secondly, you can set values as you would an object (localStorage.hasCodeRunBefore = true) though it will be stored as a string, not as boolean (or whatever data type your value is).
function toBeExecutedOnFirstLoad(){
// ...
}
if(localStorage.getItem('first') === null){
toBeExecutedOnFirstLoad();
localStorage.setItem('first','nope!');
}
All JavaScript must execute every time a page loads. If the script is on the page, it will execute.
The logic that is executed within the JavaScript included on the page may execute in a different manner depending on the page state, input provided, and any other signals it receives, be it from the server or the client.
If you're using a server side language, you might choose to render a script conditionally, such as the first time a user logs in.
If you need to include the javascript irrespective of context, then you need to listen to other signals.
The simple modern solution is to make use of localStorage. localStorage can be used to store custom string values on custom key values for any given domain.
The code to make use of this would look like:
if (localStorage['...my key here...'] === '...my expected value here...') {
// The page has been visited before
} else {
// The page has not been visited before
// OR
// The user or script has cleared the localStorage value
}
localStorage['...my key here...'] = '...my expected value here...';
That's all well and good if you just need things to work on the client alone. Sometimes you might need the server to know whether or not the page has been visited before.
The (less)simple solution is to use document.cookie:
if (/(?:^|;\s*)...my key here...=...my expected value here...(?:;|$)/.test(document.cookie)) {
// the page has been visited before
} else {
// The page has not been visited before
// OR
// The user or script has cleared the cookie
}
document.cookie = '...my key here...=...my expected value here...';
If you need to defer the execution until the page has finished loading, then simply include the script in an onload callback, either by assigning the event to the window:
window.onload = function () {
// do stuff when the page has loaded
//this will override any other scripts that may have been assigned to .onload
};
or by binding the event handler to the window:
window.addEventListener('load', function () {
// do stuff when the page has loaded
}, false);
It depends on what first page load means to you. It's subjective.
If you want the function to fire once the DOM has been parsed, but only the HTML and no other external resources, bind it to the DOMContentLoaded event.
document.addEventListener('DOMContentLoaded', fn);
Otherwise, if you want to wait for external resources to be loaded and then fire the event, you should bind it to the window object's load event like so:
window.addEventListener('load', fn);
Here are some links from the Mozilla Developer Network that explain the what I just said in more detail:
https://developer.mozilla.org/en-US/docs/Web/Events/load
https://developer.mozilla.org/en-US/docs/Web/Events/DOMContentLoaded
Good luck!
I was facing something similar, the difference in my case was, I wanted to run a code whenever a new instance was being created I needed a certain code to execute, and then later for the rest of the reloads that code should not execute.
For that similar to localStorage solutions above use session storage instead:
fun_RunOnlyOnFirstPageLoad(){}
if(!$window.sessionStorage.getItem(hasRunBefore)){
fun_RunOnlyOnFirstPageLoad();
$window.sessionStorage.setItem(hasRunBefore, true);
}
using the window.sessionStorage instead stores the value only for that session.
this way once the tab is closed (session is over, that value is wiped out) and on every new instantiation, the code is executed.

Ajax .load() won't work when triggered initially

So I have a simple tab system which I handle with the .load function to load the desired content. The problem is that the page itself which contains this tab system is a ajax loaded content. And for some reason the initial call of the tab function to display the initial tab content won't work. But after manually choosing a tab, the load function loads the content properly.
her some code to look at:
The tab handler:
function loadTab(tab) {
$(".tab_a:eq("+otab+")").removeClass("tab_slc");
$('#tab_content').hide();
$('#tab_content').load("include/tab_downloadVersions.html .tab:eq("+tab+")");
$(".tab_a:eq("+tab+")").addClass("tab_slc");
$('#tab_content').fadeIn(function() {});
otab = tab;
}
at the end I call loadTab(tab); and the thing should be initialized. but for some reason the content remains empty. As soon as you manually click on a tab (I have an on click function which calls loadTab(tab) everything starts working)
Because the code by itself works, I think the problem is caused by the other script which handles the page itself. It is also a .load function which loads the page, which loads this tab system.
So do multiple .loads don't like each other? and if so, what can I change?
Thanks in advance ;)
EDIT: I could't post the entire code for some reason, but if you go here you can see the site in action with all the scripts:
n.ethz.ch/student/lukal/paint.net
The tab system is on the download page.
EDIT:-----------------------------------------------------------------------------------------------------------------------------
Big Update
So this is still the same issue but with a slight twist: I did what was recommended in the comments and put my secondary .load() call inside the success call of the first one.
$("#content").load("pages/contact #contentInside", function() {
$("#OtherContent").load("include/info #OtherContentInside");
});
So this works.
But now I had the great idea to make a giant load function. It is a slightly better function than just the plain load, cause it does some fading and stuff. But now I have the same problem, but even more complicated. I created the load function as a "plugin" so the function itself is in a different script file and therefore I can't access the inside of the success function. I solved this problem with a return $.ajax(); and a .done() call. The problem here is that there is some rare case where it just skips the secondary load function. So I am searching for a guaranteed way of controlling the order of the .load calls. Any idea?
The mock-up website is up to date with the new scripts if you wish to take a look. And people were complaining about potential virus spread from my link. For some reason I can't post long code snippets so the site is the best source I got to show everything. If you know a more trustworthy way to share my code please let me know.
We cannot see the rest of your code to tell where the initial call is being invoked from. A set up like the following should work:
$(function() {
var tab = 0;
loadTab( tab );
});
function loadTab(tab) {
//WHAT IS otab???
$(".tab_a:eq("+otab+")").removeClass("tab_slc"); //<<<==== otab
$('#tab_content').hide();
$('#tab_content').load("include/tab_downloadVersions.html .tab:eq("+tab+")");
$(".tab_a:eq("+tab+")").addClass("tab_slc");
$('#tab_content').fadeIn(function() {});
otab = tab;
}
Update
The reason it does not work initial is because otab is not defined the first time the function is called. You have initialized otab at the end of the function but you are using it at the beginning of the function.
UPDATE 2
I have had a chance to look at your code and I just found out what the issues are:
You do not have DOM ready
You are not calling the function on page load.
The following version of your code should work -- try not to use global variable as you're doing with otab. Since you're loading this script at the end of the page (an you are using event delegation) you may get away with DOM ready. Adding .trigger('click') or click() as indicated below should resolve the issue.
//Tab-loader
//Haeri Studios
var tab = 0;
var otab = tab;
var counter = 0;
//click detect
$(document).on('click', '.tab_a', function() {
tab = counter == 0 ? tab : ($(this).attr('id'));
loadTab(tab);
counter++;
return false;
})
.trigger('click'); //<<<<<===== This will call the function when the page loads
//Tab setup
function loadTab(tab) {
//Content Setup
$(".tab_a:eq("+otab+")").removeClass("tab_slc");
$('#tab_content').hide();
$('#tab_content').load("include/tab_downloadVersions.html .tab:eq("+tab+")");
$(".tab_a:eq("+tab+")").addClass("tab_slc");
$('#tab_content').fadeIn(function() {});
otab = tab;
}
//Initialize << WHAT ARE YOUR INTENTIONS HERE .. DO YOU REALLY NEED THIS PIECE?
$.ajax({success: function() {
loadTab(tab);
}});
A partial answer to this problem was to call the loadTab function inside the success call of the page load function, like charlietfl pointed out. But the problem is that there is no need to call the tabloader every time a new page gets called. So I would rather not have a rare call in every page setup function.
I am a bit disappointed by the system on stackoverflow. It seems like if you have not a high reputation level, no one gives a "S" about your questions. Well but at least some input was give, for which I am very thankful.
So by digging deeper into google I found out that the callback can be manually placed in the function where ever you like.
so if we have a function:
foo(lol, function() {
//This after
});
this does stuff after foo() is done. But what if we have another function inside foo() which we also need to wait for:
function foo(lol) {
bar(troll, function() {
//This first
});
}
The bar function is not relevant to the success call of foo. This causes the unpredictable outcome of calls.
The trick is to control when the success function of foo gets called.
If we add a parameter(callback) inside foo and call this "parameter" (callback();) inside the success call of bar, we can make sure the order is guaranteed.
And that's it:
function foo(lol, callback) {
bar(troll, function() {
//This first
callback(); //<-This callback placement defines when it should be triggered
});
}
foo(lol, function() {
//This after
});
We get:
//this first
//this after

window.location not evaluating until entire call stack is processed?

I have a bit of javascript, triggered from an HTML button, that calls a function. This is using Jquery as well, so there are a couple of underlying functions from that that get called in this process, too. In my script I make a couple of changes to window.location in order to communicate to a remote system (which is supposed to fire off different scripts in response to these calls). This window.location definition is not using the HTTP protocol, but FMP, a registered - on my machine anyway - protocol for FileMaker Pro.
Sample code:
function compareJSON() {
dataSession=({ //build object for output });
$.each( dataSession.chapters , function( indexC, value ) {
//compare objects to some others, testing and changing data
});
//Call remote script on other system
window.location= "fmp://blah.dee.com/Blar?script=SaveJSON&$JSONobject=" + JSON.stringify( dataSession );
//Call remote script on other system
window.location="fmp://blah.dee.com/Blar?script=EditJSON";
}
(Keep in mind, since this is using Jquery, that simply pressing the button that calls this compareJSON() function creates a stack of 2 or 3 other functions before running my function. But, even if it were being called directly in some manner, the compare function itself would be on the stack and thus window.location wouldn't get evaluated until the end of that function.)
The problem is that it looks like the Window.Location isn't being finalized/set/sent/whatever until the ENTIRE JS call stack is finished. So, when I click the button that starts these function calls the stack gets a few Jquery functions put on it (e.g. 'handler', 'default', 'each loop'...), then it hits the JS code that I wrote, which in turn adds a few more function calls to the stack; and then there are a few more Jquery functions that added to the stack, etc. But these stacked window.location definitions made in my functions don't actually trigger the remote system until I step all the way through the JS call stack and exit everything. So the window.location is only defined/set to be whatever was last set in the function calls, instead of including all the intervening definitions/sets that occurred in the stack. It's like a variable that gets changed multiple times in the call stack but only gets read once at the end.
Is there a way to force window.location to be evaluated when it is set instead of waiting for whatever the last setting was?
Thanks,
J
You may want to use an iframe:
function callScript(url) {
var ifr = document.createElement('iframe');
ifr.src = url;
// you can even add ifr.onload = function() {doSomething();}; if you want
}
This will allow any number of calls at once.
This might not work, but the timeout idea is to change something like this:
// code code code ...
window.location = newUrl;
// more code ...
into:
// code code code ...
window.location = newUrl;
setTimeout(function() {
// more code ...
}, 1);
That allows the browser an interval in which it can do something before starting the next event loop for the timer handler.

Javascript startpoint

Is there any way to make my browser tell me what is the first JavaScript that is executed when I click on for instance a div.
Let me break it down:
Code example:
<div id='hello'> Hi There </div>
jQuery('hello').bind('click', function() { alert('hello') });
The code above will naturally display hello when I click on it. But is there a way to make firebug or console in Chrome to automatically break on the first very first JavaScript call without explicit set the break point.
In a complex JavaScript web pages there is a lot of binds but takes hours to find what is the actual code behind it.
you can get all events of an element with console.log($(element).data("events"));
So if I'm following the question you have this scenario:
jQuery('#hello') //function call 1
.bind('click', function(){ function call 2
alert('hello');
});
One method to do this would be to override the function you want to test. You cache the actual function, overwrite it with yours to do debugging in, then execute your cache with the original arguments.
(function(){
var _jquery = jQuery;
jQuery = function(){
console.log('debug');
_jquery(arguments);
}
})();

Categories

Resources