Bind event to a div appearing - javascript

Can I create an event so I can execute some javascript whenever an element with a specific ID becomes visible or appears on the page?
The element comes from a remote resource (so isn't in MY html code but appears on page load) and I'd like some code to run when it appears (and only if it appears, it may not appear every load).
Thanks!

You can make a function that will check every X milliseconds if such element appeared on the page (a plain Javascript solution):
(​function ()​ {
var intervalId = window.setInterval(function() {
if (null != document.getElementById('myDivId')) {
// the div appeared on the page
// ... do your stuff here:
alert('its here!');
// optionally stop checking (obviously it's there already
// unless you decide to remove it)
window.clearInterval(intervalId);
};
}, 100); // perform check every 100 milliseconds
}​)()​;
There is the possibility that the DIV is there all the time, only not visible. So your checking function should be a little different:
var el = document.getElementById('myDivId');
if (null != el && (el.offsetWidth > 0 || el.offsetHeight > 0)) {
Basically (el.offsetWidth > 0 || el.offsetHeight > 0) indicates that element is not hidden by its or its parents' CSS properties.

If a selector doesn't find a match, it just won't run, so just having code like this is fine:
$("#elementID").each(function() {
//do something
});
Just run that statement in whatever code loads the ID, or alternatively rig it up in the ajax handler if that's how it's getting loaded like this:
$.ajaxSetup({
complete: function() {
$("#elementID").each(function() {
//do something
});
}
});

You could use live() method:
$('div_id_or_class').live('click', function(){
// ................
});

Related

Can't delete element with Javascript autorun at start

I was gonna simplify the page https://vio.edu.vn/arena (if you're asking) because I see elements that I didn't need was the element _3gMal. I usually like to code in 1 line so this is the code I use
function deleter() {
if (typeof document.getElementsByClassName('_3gMal')[1] == 'object') {
document.getElementsByClassName('_3gMal')[0].remove();
clearInterval(myInterval)
}
var myInterval = setInterval(deleter(), 1)
}
The code that I want it to do is delete the element _3gMal after it's visible but I think there's something wrong so it doesn't work properly. There's no error in the code.

jQuery traversing the DOM using $(this) as a starting point inside setInterval/setTimeOut function?

I've been trying to understand how to (in jQuery) traverse the DOM using $(this) as a starting point inside a setInterval/setTimeOut function and have come across some behavior I have found baffling.
It doesn't seem to be possible to traverse the DOM using $(this) as a starting point inside a setInterval/setTimeOut function
Why is that?
jQuery/javaScript people - get on that.
Sample code to illustrate the behaviour:
jQuery:
// set this code anywhere (inside/outside - document.ready/named-function/...) and run it
var autoTimer = setInterval(function(){
// INSERT EXAMPLE TEST-CODE FROM BELOW HERE
}, 10000)
Test code tried:
// from inside the setInterval/setTimeOut function above
// if $(this)
if($(this).length !== 0) {
alert('hello');
} // alerts hello
// from inside the setInterval/setTimeOut function above
// if html-tag (body/head/html)
if($('body').length !== 0) {
alert('hello');
} // alerts hello
// from inside the setInterval/setTimeOut function above
// if className
if($('.className').length !== 0) {
alert('hello');
} // alerts hello
// from inside the setInterval/setTimeOut function above
// if id
if($('#id').length !== 0) {
alert('hello');
} // alerts hello
So it finds specific elements inside the document just fine and apart from $(this) you can then traverse the DOM from there
ie.
// from inside the setInterval/setTimeOut function above
if ($('.className').find(something).length !== 0)... // works just fine
The problem comes when you want to use $(this) as a starting point for traversing
Traversing test code tried using $(this) as a starting point:
// from inside the setInterval/setTimeOut function above
// traversing up the DOM
if($(this).parents('body').length !== 0) {
alert('hello');
} // no alert (same with closest/parentsUntil/etc up the DOM)
// from inside the setInterval/setTimeOut function above
// traversing sideways in the DOM
if($(this).siblings('body').length !== 0) {
alert('hello');
} // no alert (same with next/prev/etc sideways in the DOM)
// from inside the setInterval/setTimeOut function above
// traversing down the DOM
if($(this).find('body').length !== 0) {
alert('hello');
} // no alert (same with children down the DOM)
So starting from $(this) 'body' (or anything else for that matter) doesn't seem to exist anywhere (up/down/sideways) which is not true from any other starting point from above
I also tried using a named global function as in:
// set outside/inside document.ready
function testCode() {
// INSERT EXAMPLE TRAVERSING TEST-CODE FROM ABOVE HERE
}
// set this code anywhere (inside/outside - document.ready/named-function/...) and run it
var autoTimer = setInterval(testCode, 10000) // no alert
// set this code anywhere (inside/outside - document.ready/named-function/...) and run it
var autoTimer = setInterval(function(){
testCode();
}, 10000) // no alert
So to re-iterate my question:
Why does it seem impossible in jQuery to traverse the DOM (up/down/sideways) inside a setInterval/setTimeOut using $(this) as a starting point?
And what are possible hacks/work-arounds/etc. for this behavior?
Possible none-solutions for hacks/work-arounds/etc.
this answer using $.proxy only works if you use an older version of jQuery - but since as this document attests 'This API has been deprecated in jQuery 3.3'... at the moment this is not a solution.
And neither is the bind method since as the document attests 'As of jQuery 3.0, .bind() has been deprecated' and been superseded by the on method (but I can't see how I would use .on() here to any effect - but maybe that's just due to my lack of imagination).
This is a basic this scoping problem and has little to do with jQuery.
The most straightforward approach is to assign this to another variable outside of the callback:
var that = this;
setInterval(function () {
$(that).parents();
}, 1000);
If you don't care about IE, or if you have a build process, you can use an arrow function, which uses this from the scope outside it:
setInterval(() => {
$(this).parents();
}, 1000);
My personal preference is to avoid the use of this entirely because of all its cockamamie behavior that's giving you so much grief. It's not clear from your examples where your this value is coming from, but here are some ways you can avoid it:
// inside .each()
$('a').each(function (_, el) {
$(el).parents();
});
// inside event handler
$('a').on('click', function (event) {
$(event.target).parents();
});

assigning anonymous functions to buttons

When i use if statements to determine whether a user has viewed the form before, it breaks my whole code.Originally, my code just removed a child, and set the display of the next DIV to "block".This worked perfectly fine. all my variables saved properly in the end, etc.
However, since I added these checks to the buttons, everything has gone haywire.
I've tried using different mixes of appendChild, removeChild, and style.display methods. I even booted it up in notepad++ to help me visualize.
document.getElementById("newUser").addEventListener("click", function(parent, start, personal){
parent.removeChild(start);
document.getElementById.style.display="block";
});
document.getElementById("toGeneral").addEventListener("click", function(){
if(reUser === 0){
oPersonal;
document.getElementById("general").style.display="block";
} else if(reUser === 1){
oPersonal;
parent.appendChild(oShowInfo);
} else {
window.alert("Whoops this function is in progress");
}
return oPersonal;
});
I want my forms to be editable at the end of the form.
In one test (not this one). I was able to move back and forth between pages, but it would stop the loops that kept my variables up.
This one is using the oldChild = parent.removeChild() method to fix that, which may also be part of the issue.
**Note: variables such as
oPersonal
reUser
parent
are stored just above this code at the beginning of the page loop.
New code:
document.getElementById("newUser").addEventListener("click", function(){
parent.removeChild(start);
document.getElementById.style.display="block";
});
document.getElementById("toGeneral").addEventListener("click", function(){
if(reUser === 0){
oPersonal;
document.getElementById("general").style.display="block";
} else if(reUser === 1){
oPersonal;
parent.appendChild(oShowInfo);
} else {
window.alert("Whoops this function is in progress");
}
return oPersonal;
});
You have many problems in this code. First, your click event's handler can not take 3 args like this. When an event is triggered, only this event is passed to the function. So your code should looks like :
document.getElementById("newUser").addEventListener("click", function(event) {
let element = event.target;
let parent = element.parentNode;
parent.removeChild(element);
//Next line is wrong since getElementById is a function and should take args
//document.getElementById.style.display="block";
});
Then on your second element's click event handler, it seems like you are trying to use parent which is not in the same scope.
Also the return statement is strange, what are you trying to do ?

How to change the onload event of body after condition is met

I want to change the onload event of the body once a certain condition is met.
In my case the condition is that I first have to let the page load and get the current onload event and compare that to a certain string if it returns true I will then replace it with a different function to assign to the onload event.
Is this even possible since when the page loads my new onload event will practically do nothing so im guessing is that i have to change it before it reaches the body.
This was something I got from my previous question. I also added a few things:
$(document).ready(function(){
var x = new String(document.body.onload);
x = x.replace(/ /gi,"");
x = x.replace("functiononload(event){","");
x = x.replace("}","");
alert(x);
//what i want to do after i checked the old event if it is equal to something.
window.onload = function() {
newfunction();
x();
}();
});
<body onload="wewewe();">
Why don't you simply use :
$(document).ready(function() {
if (condition) {
// do something
}
else {
// do something other
}
});
body.onload and $(document).ready() are almost identical.

Can I run nest a $('element.class').each() function within the change() function for the same $('element.class')?

Specifically, I want to iterate over every element on the page, each time the value of one changes.
So to paraphrase my code I have:
$('select.filterbox').change(function() {
// stuff
$('select.filterbox').each(function() {
// other stuff
});
});
'stuff' all executes just fine, but 'other stuff' doesn't happen
Here's the full code
// On Filterbox Change
$j('select.filterbox').change(function() {
// Show All Rows
$j('#table1 tr').show();
// For Each Filterbox
$j('select.filterbox').each(function() {
var selVal = $j(this).attr('value');
var col = $j(this).closest('th').parent().children().index($j(this).closest('th'));
alert('Column '+val+' : '+selVal);
// If Selected Value Not Empty
if(selVal != "") {
// For Each Row
$j('#table1 tr').each(function() {
var $tds = $j(this).find('td');
var cellVal = $tds.eq(col).text();
cellVal = $j.trim(cellVal);
// If td text != selected
if( cellVal != selVal ) {
// Hide this row
$j(this).hide();
}
});
}
});
});
Answer: yes you can. I've done a lot of stuff like that recently. Indeed, your code should do it. It is likely that you've made some small but significant error in your code that will need to be hunted down and fixed. I've done a lot of stuff stuff like that recently, too.
More helpful answer: do things to figure out where the breakdown is. replace the "$('select.filterbox').each()" call with something obvious - say, calling .hide() on large chunks of your page. Make sure that line of code is even being called. If it is being called, put the "$('select.filterbox').each()" call back, then move the hide() call inside of it. If that works, then you know that it's running at least once. Change the hide() call to a (this).hide(), and see if you can see which one it's identified. Once you've narrowed down where it's failing you, it'll be a lot easier to figure out what you've done wrong.
You can do this, but it's not optimal to attach separate event handlers to a lot of elements. You can take advantage of event bubbling and just attach a single handler to their parent container. For example:
$("#filters").change(function (evt) {
// evt.target will give you actual element that changed
$("#filters select.filterbox").each(function () {
// other stuff
});
});

Categories

Resources