Detecting a button that is loaded asynchronously - javascript

On a web page I am looking at, there is a lot of data being loaded asynchronously.
Included with that data is a button called "View More". If you either click on the button or simply scroll right to the bottom, more data will be loaded via a "GET" call function.
When I try using this (in FireBug console):
document.getElementById('#button9').click();
or
document.getElementById('button9').click();
I get this result:
TypeError: document.getElementById(...) is null
document.getElementById('#button9').click();
From what I have read about this TypeError, the Id cannot be detected, which I assume is because of the data being asynchronous. Is there a way to detect the element (it doesn't show up on the "page source" but it is there when I click on "Inspect Element with FireBug")?
I would like to detect the element and then make a call to a click event to 'simulate a click' (meaning I would like a click to take place without clicking on the button or scrolling right down) with the output being displayed in the browser (per usual).

If you just want to attach the event, then the bottom will work.
If the problem is that it is null, and you don't know when it will show up, your best bet is to create a loop that runs until it exists.
var obj = document.getElementById('button9');
obj.addEventListener('click', function() {
alert(' you clicked on ' + this);
}, false);
in case its that second instance, and you want to wait until the object events, then use:
checkExists();
function checkExists() {
var obj = document.getElementById('button9');
if (obj != null) {
obj.addEventListener('click', function() {
alert(' you clicked on ' + this);
}, false);
alert('added event');
}
else {
setTimeout(checkExists, 1000);
}
}

This will work, no matter even if you don't know when the object is getting created and added to the DOM
//chrome / ff /IE
$("#button9").bind("DOMSubtreeModified", function() {
// Add click function here
});
//IE 8 and lower
$("#button9").bind("propertychange", function() {
//Add click function here
});
2nd Option
*OR*
Not sure if it supposts IE8 though but it definitely supports all others
document.addEventListener("DOMSubtreeModified", function (e) {
if ($(e.target.id) == "#button9") {
// Do stuff
}
}, false)
Explanation: It checks if the DOM has found an element with the specific ID, if so, execute the click function.

Related

How to prevents events from firing multiple time

For some reason I have to call the same function twice because of that my event are firing twice. How can I prevent this?
function renderSeats(movieImg, title, release_date, dummyPrice = '3000') {
// selected items
//this is only a part of the code .
contianer.addEventListener('click', function (e) {
if (
e.target.classList.contains('seat') &&
!e.target.classList.contains('unavailable')
) {
e.target.classList.toggle('selected');
payoutBtn.classList.add('active');
console.log('yes');
updateCountTotal(); //function call
}
contianer.setAttribute('listener', 'true');
});
const ticketOverlayClose = document.querySelector('.ticket__close-svg');
// overlay deactive
ticketOverlayClose.addEventListener('click', function (e) {
overlayseats.classList.add('hidden');
payoutBtn.classList.add('active');
ticketContainer.classList.remove('active');
});
}
Every time I am calling the function from another function because I have to update the dom, suppose 3 times the event then also fire 3 times
I also attached an image. In the console, you see after I clicking back (it is a single-page app) and again load by page calling our rendered seat function, and this time when I click on the seats the even is firing twice.
[gif][1]:https://i.stack.imgur.com/Ik1CG.gif

Regaining focus in iFrame with jQuery context menu

I've created a fiddle to reproduce the problem.
https://jsfiddle.net/rvwp47Lz/23/
callback: function (key, option) {
console.log("You clicked the test button", this);
// Need the iframe contents to regain focus so the mouse events get caught
setTimeout(function () {
$iframe[0].contentWindow.focus();
}, 100);
}
Basically, what I want to happen is the mouse move events to be caught after closing the context menu.
I can call focus on the iFrame's body or document but it doesn't seem to have any effect.
After you right click one of the items within the iframe and select an item, the mousemove event on the iframes body is no longer called (you can also notice that the hover CSS effect on the items are no longer working).
Ideas?
After some debugging and playing around with jQuery.contextMenu's code it seems the issue actually comes from the itemClick function. I added comments to the code and will add an issue to their github for a possible fix (unless there's some reason they're disabling default here)
// contextMenu item click
itemClick: function (e) {
var $this = $(this),
data = $this.data(),
opt = data.contextMenu,
root = data.contextMenuRoot,
key = data.contextMenuKey,
callback;
// abort if the key is unknown or disabled or is a menu
if (!opt.items[key] || $this.is('.' + root.classNames.disabled + ', .context-menu-submenu, .context-menu-separator, .' + root.classNames.notSelectable)) {
return;
}
// This line is causing the issue since it's preventing the default actions which puts
// mouse events back into place. Chrome must disable mouse move events when the contextmenu event
// gets triggered to improve performance.
//e.preventDefault();
e.stopImmediatePropagation();

JavaScript / DOM: how to prevent blur event if focus is lost to another window (application)

I want to show certain content within an HTML document if the user clicks into a certain form field within this document, and I want to hide that certain content if the user leaves that form field (either by activating another one or by clicking somewhere else onto the page).
I have tried to implement that behavior using the focus and blur events. This works in principle, but there is a problem: The blur event on the respective field is fired not only when the user moves the focus within the same document, but as well when another window (which could be from a different application) becomes activated (gets focus).
How could I avoid that? I don't want to see any changes in the page if the focus goes to a different application (or another browser window or tab).
Thank you very much!
Guard the blur event handler with if ( document.activeElement === this ) { return; }.
The next step will be to prevent the focus event handler from activating when the window regains focus. This can be done using a small pattern:
function onFocus(e) {
if ( this._isFocused ) { return; }
this._isFocused = true;
...
}
function onBlur(e) {
if ( document.activeElement === this ) { return; }
this._isFocused = false;
...
}
Maybe this could work:
function onFocus(element) {
document.getElementById('element').doStuffHere('whateverYouWant');
}
function onBlur(element) {
if (document.hasFocus()) {
document.getElementById('element').doStuffHere('whateverYouWant');
} else {
alert('Please come back!')
}
}
The onBlur() function is executed as soon as the element loses focus and first checks if the document still has the focus. If yes it does the elementLostFocus tasks (I'll call them like that here to make it easy), otherwise it (at least in this example) alerts the user, or you can make it do nothing or just the same elementLostFocus tasks or anthing you want.
The only problem with that solution is that you don't do the elementLostFocus tasks when the window regains focus by clicking outside the desired element after it lost the focus directly from the desired element to another window. But here's a fix for that:
document.onfocus = function() {
if (document.getElementById('element').hasFocus() == false) {
document.getElementById('element').doStuffHere('whateverYouWant');
}
}
It can be that that code doesn't work but it should. At least it should give you an idea based on which you can solve the problem yourself.

How to trigger onbeforeunload with back button in an ajax based application?

I have an ajax based application (ie no page 'reloads` when getting new data).
Initially I wanted to find a way to prevent navigation when unsaved data was present on a form.
I came across window.onbeforeunload.
That didn't work when clicking a links (where content is loaded via ajax and pop/push state changes the url).
I added some handling of the a links but need to use the default window.onbeforeunload to cover the standard means of leaving a page (ie manually entering a new URL or using the back/forwards buttons).
The code below works for:
a links
page refresh
manually entering a new url
But is not triggering window.onbeforeunload when using the back button (in Chrome and Firefox).
Is there something awry with the implementation below or is window.onbeforeunload not meant to be triggered when using the back button?
var save_state = true;
// on entering data into an input field, the save button fades in
// and the save_state changes
$(document).on('keypress', '.class1 input', function() {
if (save_state) {
$(".save_button").fadeIn();
save_state = false;
};
// bind the click event to 'a' (overiding normal link behaviour)
$( "a" ).bind( "click", function(e) {
if (save_state == false) {
e.preventDefault();
alert("Save before leaving.");
// stop the other 'a' bound handlers from being triggered
e.stopPropagation();
return;
}
});
// also cover standard actions when user tries to leave page
// (back/forward or entering a new url manually etc)
window.onbeforeunload = function() {
return 'Save before leaving.';
};
});
// when clicking save, fade out the button and revert the save_state
$(document).on('click', '.save_button button', function(e) {
e.preventDefault();
$(this).parent().fadeOut();
save_state = true;
// 'unbind' onbeforeunload
window.onbeforeunload = null;
});
Edit:
After reading this post, I think it is based on the ajax nature of the app:
As long as you stay within your app, because it's a single-page app,
it doesn't by definition unload, so there's no beforeunload event.
So I think I may need to look at other ways to trigger the event on back/forwards buttons.
I looked in to triggering window.unload on popstate but didn't have any luck with that.
I ended up changing the logic so that as soon as changes were made, they were saved in the database.
I was using selectize.js for the form input handling and just added some extra calls to it.
In selectize.js (here):
if ($target.hasClass('create')) {
self.createItem();
} else {
value = $target.attr('data-value');
became:
if ($target.hasClass('create')) {
self.createItem();
$(".saved_message_div").fadeIn(400).delay(2000).fadeOut(400); // new
updateDatabaseFunction(); // new
} else {
value = $target.attr('data-value');
$(".saved_message_div").fadeIn(400).delay(2000).fadeOut(400); // new
updateDatabaseFunction(); // new
AND (here):
while (values.length) {
self.removeItem(values.pop());
}
self.showInput();
became:
while (values.length) {
self.removeItem(values.pop());
}
$(".saved_message_div").fadeIn(400).delay(2000).fadeOut(400); // new
updateDatabaseFunction(); // new
self.showInput();
And in my own script, the prompt for deleting selectize.js items stayed the same:
onDelete: function(values) {
confirm(values.length > 1 ? 'Are you sure you want to remove these ' + values.length + ' items?' : 'Are you sure you want to remove "' + values[0] + '"?');

disable button in a <li>

okay, if I have six buttons in a list, under the li tag (each on is rel to a part of an array), how can I disable a button while it's doing it's thing? (In this case playing a video)I know it's a little vague (i haven't supplied code or anything of the sort), but that's because I don't know how to go about it. If I could at least get pointed in the right direction, that would be helpful, so that even if I can't figure it out, at least I can be specific with my problem... thanks...EDIT this is what I've now done
<li rel='1' id="first">
<div style="top:0px;">
<img src="graphics/filler.png" alt="" width="280" height="128" onClick="asess"/>
</div>
</li>
and then added the corresponding function
function asess() {
document.getElementById("first").disabled = true;
}
I'm not to concerned with adding the function back just yet, because first I'd like to make this part work.EDIT I've got this, which should work, but I guess it's not "talking" to the button?
$("li, .thumbs").bind("touchstart click", function() {
var $this = $(this);
if (!document.getElementById("first").disabled) {
document.getElementById("first").disabled = true }
else {document.getElementById("first").disabled = false};
});
I know it will only talk to the button with that id (first one) but as long as I can make it work for one, I can do the rest. So, what am I doing wrong?
Each button will have an onclick event handler. To prevent the onclick handler from doing anything the JavaScript method attached to the handler should return false. If you are doing this with jQuery return false; is the same as calling e.preventDefault (or event.preventDefault for IE).
When the normal event handler initiates the action associated with the button it should add the event handler that disables the onclick action.
You will probably need to apply a new CSS style to the button as well so the user knows it's disabled.
When the action completes you need to remove event handler that disables the onclick action and use the normal one again.
You could always just use a flag to say an action is in progress and set this on and off with the actions. If the flag is on then the event handler method returns false.
By using the event handler you could also show an alert to the user when they try and click the button before you return false.
EDIT:
Here is the sort of JavaScript you'll need, the first click starts the process which will stop itself after five seconds using setTimeout('stopAction()', 5000);. If you click the item again during that time you get the wait message.
I would recommend you look at using jQuery to develop a robust cross browser solution.
var inProgress = false;
function asess() {
if(inProgress) {
alert('Please wait ...');
return false;
} else {
startAction();
}
}
function startAction() {
inProgress = true;
alert('Starting');
document.getElementById("first").style.backgroundColor = '#333333';
setTimeout('stopAction()', 5000);
}
function stopAction() {
inProgress = false;
alert('Stopping');
document.getElementById("first").style.backgroundColor = '#FFFFFF';
}
document.getElementById("my_button").disabled = true;
and when you're done.
document.getElementById("my_button").disabled = false;
You could "disable" the element within the click handler and re-enable it when the callback is executed successfully.
Click handler binding to elements with disabled="disabled" attribute is not guaranteed to be consistently implemented across browsers (i.e. the event could/would still fire) and is not allowed except on form elements anyway. I'd just add class="disabled" which gives me additional powers to style the disabled element state by, say, greying it out.
Oh, and jQuery. Naturally, this logic could be reproduced in "normal" javascript but is so tidier with library usage, fiddle:
$('#my-button').click(function() {
var $this = $(this); //cache the reference
if (!$this.hasClass('disabled')) {
$this.addClass('disabled');
alert('hello world!');
setTimeout(function($btn) {
$btn.removeClass('disabled');
}, 5000, $this);
} else {
return false;
}
});

Categories

Resources