How to not add a delay to a function - javascript

I am new to JavaScript and following this tutorial I have made the game work perfectly and it goes up to the part of were the the level changes when you destroy all the objects. However as I am learning I am trying to figure out how to make it so that it changes level without a delay.
The main part of the bit which switches level is :
if (!this.rockmodel.countLiving()) {
Asteroid.time.events.add(Phaser.Timer.SECOND * gameWindow.delayToStartLevel, this.levelIncrease, this);
}
However if I take out the delayToStartLevel bit, it does not switch level. So I tried to make it looks like this:
Asteroid.time.events.add(this.levelIncrease, this);
But the next level does not show at all. Not sure if I am being an idiot etc, but any help on this matter would be great.
Again just to make some sense, it works fine with the delay, I want to get rid of that function completely but its not working at all.
Thanks.

The time.events.add will add an event to the Phaser game object. In other words it will fire the given function after X milliseconds.
If you do not want a delay then you can just call the function directly, instead of postponing the function call. Something like this:
if (!this.rockmodel.countLiving()) {
this.levelIncrease();
}

Related

Javascript detect when style.display is used regardless of style change

Take the following html:
<div id="somediv" style="display:none;"></div>
<script>
document.getElementById("somediv").style.display = 'none';
</script>
somediv is already hidden, some javascript runs, effectively doing nothing. I need code that detects when style.display has been used in javascript, regardless of if style was changed or not.
I've tried MutationObserver:
var observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutationRecord) {
alert(mutationRecord.target.id);
});
});
observer.observe(document.getElementById("somediv"), { attributes : true, attributeFilter : ['style'] });
The above only triggers if there was a style change. I need it to trigger regardless if there was a style change or not.
So I did come up with an answer. The way it works, is you grab every script tag, replace .style.display with your own function, and finally replace the DOM (which is the real trick):
//loop through <script> tags
$('script').each(function(){
var scripthtml = $(this).html();
if (scripthtml.indexOf('style.display') != -1){
scripthtml = scripthtml.replace(/.style.display = 'none'/g, ".customdisplay('none')");
scripthtml = scripthtml.replace(/.style.display = "none"/g, '.customdisplay("none")');
scripthtml = scripthtml.replace(/.style.display ='none'/g, ".customdisplay('none')");
scripthtml = scripthtml.replace(/.style.display ="none"/g, '.customdisplay("none")');
scripthtml = scripthtml.replace(/.style.display='none'/g, ".customdisplay('none')");
scripthtml = scripthtml.replace(/.style.display="none"/g, '.customdisplay("none")');
$(this).replaceWith('<script>' + scripthtml + '</script>');
}
});
Now here is my .style.display replacement function:
HTMLElement.prototype.customdisplay = function(showhide){
//insert whatever code you want to execute
this.style.display = showhide;
alert('Success! .style.display has been detected!');
};
.replaceWith is what actually changes the DOM. The only thing this script doesn't do, is it isn't able to look through included javascript files. Thank you all for your comments <3.
UPDATE:
When using replaceWith to add the script tag, ipad/iphone/ipod will execute the script tag a second time. to prevent this double execution, you need to do this:
$(this).replaceWith('<script>if (1==0){' + scripthtml + '}</script>');
Your functions will be valid, but anything outside of the function will not be executed.
I don't think you fully realise what you are asking for, but here is a short description of closest options I am aware of:
https://blog.sessionstack.com/how-javascript-works-tracking-changes-in-the-dom-using-mutationobserver-86adc7446401
Basically, MutationObserver is the major improvement over past here that is closest to what you want and supported in modern browsers. But the whole point of all this is it listens to changes.
You are basically asking to detect even non-changes. I don't see you getting out of this problem other than:
Writing a wrapper for the ways you use to change this in code and then instead of calling the change call the wrapper. Simple, easy, requires refactoring all the calls in code.
Overwriting the actual functions that make a change. This saves you the refactor but you are playing with fire here. Rewriting a well-known function on a global level means a PERMANENT source of problems to you and all developers who work on the project.
Polling - in short calling over and over on some element to check properties. Not only it detects changes with a lag of 0 to the polling interval it also uses resources and if you want to monitor everything you will have to write a recursion that descends through the current DOM from the top to each node and check it. You are gonna kill the performance with this. How hard I can't tell but I suspect either polling interval will be long thus increasing the detection lag or your performance will dive down like a gray falcon.
I have 1 big question for you:
What led you to the state where you need this?
You basically want the ability for a program to detect when it is using a specific part of itself (be that as it is, a core part, one implemented by the browser).
This sounds similar to request: hey whenever I change or not change a value in any variable in my code I should be able to react to it.
I am not trying to sound like Naggin Nancy here but instead encourage you to question train of thought that led to this being something you need and figure out whether you want to sink further time into this, because I don't think you are getting that what you desire easily and I suspect it came to be due to poor design decisions in the past.

What is the purpose of adding and then immediately removing an event listener?

I came across the following on github, which forms part of a Class dedicated to managing the behaviour for a drawer-style side navigation.
closeSideNav() {
this.sideNav.classList.remove('side-nav--visible');
this.sideNavContent.classList.add('side-nav__content--animatable');
this.sideNavContent.style.transform = 'translateX(-102%)';
let onSideNavClose = () => {
this.sideNav.removeEventListener('transitionend', onSideNavClose);
}
this.sideNav.addEventListener('transitionend', onSideNavClose);
}
The first three lines of the function need no explanation, but I'm a bit confused by the last three. At first it I thought the transitionend event listener was added and then immediately removed - perhaps signalling to another piece of code not shown here - but now I'm really not used to this pattern.
What's the purpose of these lines?
it is not immediately removed. Its removed after it triggered once . Thats a common pattern for one-time UI actions, e.g. the navigation can just be closed once, a second button press makes no sense and can confuse the running animations etc.

Closures in For Loops With Onclick Assignment

I'm trying to have a navBar that generates automatically by looping through an array of "Page" objects. Unfortunately, I seem to be falling into the loops/closure trap. I have read several threads related to this and in some cases have copy and pasted solution code and passed in my own variables but I'm struggling to make it assign onclicks correctly.
I know I'm close. In the below code are two options that I have tried.
Am I getting something wrong with the paremeter in parenthesis in the self-calling function? - the ()(divId)? I don't really understand this part.
Could I also be struggling because this is being done as an object method?
Any help much appreciated but go easy on me, I'm learning all this in my spare time! ;)
Thanks in advance.
EDIT: Jsfiddle: https://jsfiddle.net/mcgettrm/fs0mtz6n/
var navBar = {
display: function(){
for(i=0;i<pages.length;i++){
document.getElementById('navBar').innerHTML += pages[i].token;
var divId = pages[i].unique;
// code works fine up to here.
// option one(below): when navBar.display() is called the following code only adds
// the onclick to the final navbar link
document.getElementById(divId).onclick=(function(divId) {
return function() {
alert(divId);
};
})(divId);
//option two(below): when navBar.display() is called the following code logs
// the individual div id's correctly. But, it does it without being clicked. Then,
// only the last item in the loop is clickable.
(function(divId){
document.getElementById(divId).onclick= function(){
console.log(divId);
}
}
)(divId);
}
}
};
I've got it working here - https://jsfiddle.net/pqu9kr85/ it doesn't seem to have been to do with the binding of i more that you needed to build up the navigation html first, making sure it was in the DOM before binding the event. I put two separate loops, one to generate the nav, the second to bind the events. Also updated the page.display() to use this as that will have been affected by the value of i.

Trip.js: onFinishStep and onStartStep

In order to make my webapp more usable, I wanted to use some king of step-by-step user guide within the application, so the user knows what, when and where to click to achieve its aims.
So, after a lot of researching, I came up with trip.js, which is stylable and pretty much customizable.
BUT! When trying to do some of my steps, I missed two functions: onFinishStep and onStartStep.
Yes, you have an event, called onTripChange and, here, taking into account the index of the step, you can do some actions. But, what if I want to make an action just after a step ends? It wouldn't be executed until next step starts, and that would be too late.
I don't know if there is any hidden functionality (or not so hidden) that I may missed, but I've read the Docs and there seems not to be any. Also, looking through the code I cannot find any calls executed this way.
So, what I'm asking for is how to make it to achieve this: two functions, one executed right when the step starts and one executed just when it has ended.
After a little of reading the code, I came up with a little piece of text that would do the result.
As of version 2.0.2, into trip.js file, after line 386 (inside next() function), write the following to execute the function onFinishStep():
if(this.tripData[this.tripIndex].onFinishStep !== undefined) this.tripData[this.tripIndex].onFinishStep()
As of onStartStep(), it would be after line 585 (inside run() function):
if(this.tripData[this.tripIndex].onStartStep !== undefined) this.tripData[this.tripIndex].onStartStep()
That would do the trick. It's working on my tests (Chrome 40, Firefox 35.0.1).
The definition, then, of the steps, would be:
var trip = new Trip([
{ sel : $("#element"), content : '<p>The content</p>', position : "n", onFinishStep: function(){/*your code here*/}},
{ sel : $("#element_2"), content : '<p>The content of step 2</p>', position : "n", onStartStep: function(){/*your code here*/}}
], tripjs_general_options)
trip.start()
Hope it helps someone.
I'd like to thank EragonJ - the author of Trip.js - for such an amazing plugin.
Kind regards.

Greasemonkey, replace every occurence of string every second

i try to figure out a greasemonkey script that replaces every onmousedown on a site with an ondblclick. And i want it to constantly update, like every 1,5 Seconds, because the page refreshes using AJAX.
This is the script i came up with, but it doesn't seem to be working.
window.setInterval(document.body.innerHTML= document.body.innerHTML.replace('onmousedown','ondblclick');,1500);
The page it should work with is internal use only. But a good example would be the google search, where onmousedown is used for the links of the results to swap out the URL before you click it.
I also tried it without the semicolon after the document.body.innerHTML.replace.
I'm really new to JavaScript, but since i'm the only one in the company who can code, this one is stuck with me.
Any help would be appreciated.
Also, a small "side question"
Do i have to use #exclude, or is it enough to only use #include internal.companysite.tld* so it will only work on this site ?
A direct answer: you need to supply a function to setInterval - and it's best to set a variable so that you can later cancel it with clearInterval() if necessary.
function myF(){document.body....;}
var myIntv = setInterval(myF, 1500);
You could also do it using an anonymous function in one line as you're trying to do... do that this way:
var myIntv = setInterval(function(){document.body....;}, 1500);
I wouldn't suggest this as the solution to your problem. What it sounds like you want to do is manipulate the active DOM - not really change the UI. You likely need something like this:
var objs = document.getElementsBy__(); // ById/ByName/etc - depends on which ones you want
for (var i in objs){objs[i].ondblclick = objs[i].onmousedown;objs[i].onmousedown = undefined;} // just an example - but this should convey the basic idea
Even better, if you can use jQuery, then you'll be able to select the proper nodes more easily and manipulate the event handlers in a more manageable way:
$(".class.for.example").each(function(){this.ondblclick = this.onmousedown;this.onmousedown = undefined;}); // just an example - there are multiple ways to set and clear these

Categories