I'm writing a Firefox extension, but have issues with user interaction because of getting the right events properly. My extension shall complete the following tasks:
check the currently viewed browser tab on certain structures
do some backend server calls
open dialog
redirecting the user to a landing page
So far so good, it works. I start the sequence with the following eventHandler:
window.gBrowser.selectedTab.addEventListener("load",function(){ Fabogore.Load();},true);
after opening the dialog, I try to remove the EventHandler from within the Dialog:
window.opener.gBrowser.selectedTab.removeEventListener("load",function(){Fabogore.Load();},true);
But the sequence gets triggered again and again, the eventlistener fetches every load event of every single tab, although i used the selectedTab? So the Dialog pops up again and again. I've also tried closing the event Handler in the original Javascript.
Any guesses?
This is easily explained - the function you add as a listener and the function you remove are different. Try running this code:
alert(function(){ Fabogore.Load();} == function(){ Fabogore.Load();});
This will show you false, each time you define a function in your code a new function is created. To solve your problem you need to define one function, store the reference to it and use it both to add and remove the listener:
var listener = function(){ Fabogore.Load();};
var listenerTab = window.gBrowser.selectedTab;
listenerTab.addEventListener("load", listener, true);
[...]
listenerTab.removeEventListener("load", listener, true);
Note that I also stored the value of window.gBrowser.selectedTab in a variable - by the time you decide to remove your listener the selected tab might change already. You want to remove the listener from the tab you added it on and not some other tab.
Related
As said in the title, I am trying to customize the contextmenu event. The situation is this: I want to catch the event, preventing it from firing on some elements (I'm ok here, all good), then I want to call it targeting another element (this is not working). At first I just tried dispatching it by creating a custom event and using myTargetElement.dispatchEvent(), the custom element does fire, but context menu won't open.
The reason I need this is that I want to open the contenteditable context menu when the user clicks anywhere. I've tried something similar to the last example on this MDN page, and I logged the event type, it is firing. Here's some example code of what I'm doing.
HTML
<div id="prevent">This div will prevent default event behaviour.</div>
<div id="my-target" contenteditable>Fire here the event and open context menu</div>
For instance, I cannot put one div inside the other.
JS
function showMenu(){
const preventer = document.getElementById('prevent');
const myTarget = document.getElementById('my-target');
const myEvent = new Event('contextmenu', {
bubbles:false //I had to use this, as setting it true was logging an error on Firefox
});
myTarget.dispatchEvent(myEvent);
console.log(myEvent.type); //it does log the event name
}
The listener that prevents default is not important, as when I just run the showMenu() (even when removing every other bit of js) on console it still has not the intended effect. I'm also able to listen to the 'contextmenu' event when I add a listener and run showMenu().
I'm beginning to think that there is not a direct solution to this, but workarounds and ideas would be really appreciated.
I run into this problem quite often when I decide to try tinkering with a 3rd party site for a browser plugin, let's say I want to make a simple auto-play plugin for a video site that doesn't have an autoplay feature. There's a UI element that I know triggers their internal function for playing the video, but I dont know how to identify that function by inspecting the element in the console.
What tricks / methods can I use to be able to trigger that function manually without the user actually clicking the element?
In Chrome dev tools I think you can add a breakpoint for when an event is fired which might allow you to find the function that the 3rd party calls or you could simulate the click event using this code from MDN:
function simulateClick() {
var event = new MouseEvent('click', {
view: window,
bubbles: true,
cancelable: true
});
var cb = document.getElementById('checkbox');
var cancelled = !cb.dispatchEvent(event);
if (cancelled) {
// A handler called preventDefault.
alert("cancelled");
} else {
// None of the handlers called preventDefault.
alert("not cancelled");
}
}
For more information see MDN.
If you know that clicking a button or an element somewhere results in the video playing, often it'll be simple enough to just call .click() on that button.
With the mouse hovered over the element with the functionality, right click and Inspect at that point, and the Elements panel of the developer console should bring you to the element the mouse is over. Figure out a selector or a process to uniquely identify the element, and then .click() it, eg
document.querySelector('.video-container .play-button').click();
You also may need to wait for the video container / play button to be created in the DOM first, in which case you can use MutationObserver or a setInterval to wait for the site to be ready.
An alternative, trickier method is to, when inspecting the element, go to the Event Listeners panel, and look for listeners attached to click / mousedown (etc) events. Sometimes, these functions are callable from the global scope, in which case you can call those functions directly instead of clicking the element.
If the function isn't callable from the global scope, a hacky method to get a reference to it anyway is to monkeypatch addEventListener before the page loads, listen for when the listener you want gets attached, and then call the function passed. (But the earlier methods are much simpler and preferable when possible)
I'm working on some code where I want send custom events to the window object where I have an event listener that will perform an action. This works fine for one of the listeners, but I have a second one I want to use, but it's not registering all the time. Is there a way to debug this as the javascript console isn't very helpful? Or, is there a way to detect if the event listener has been added to the window object using Javascript? If I look at the HTML element in the inspector, I can see if the event is attached or not manually.
My code looks something like this:
$.when($.ready).then(function () {
// Set up the event listener to capture search terms.
window.addEventListener('search_terms', function(evt) {
saveSearchTerms(evt.detail);
});
window.addEventListener('profile-update', function(evt) {
console.debug('got the event');
console.debug(evt.detail);
updateProfile(evt.detail);
});
});
The firt one works fine. It's the second one that's giving me issues.
Thanks.
Some code that looks like the following is firing the click event via the Enter key, but is not responding to the mouse click.
//a is an anchor element
a.addEventListener('click', function (e)
{
//Do Stuff...
});
This page demonstrates the problem. The relevant bit of code is at line 176. This is in the middle of development and currently only (sort of) works in Chrome.
Also, I just verified that it works if I use mousedown, so it's not just the case of an invisible element sitting in front of the anchor.
Any ideas?
Edit: Now that you've shown us the actual code you're using, the problem is related to the fact that the autoSuggest() function has it's own click handler and in that click handler, it is clearing the container which removes all <a> elements in the container so your link object gets destroyed (probably before your click event gets to process). So, you can get events that happen before the click (like mousedown), but after a click, the element is removed from the DOM.
If you tell us what you're trying to actually do when an auto-suggest item is clicked that is different than the default behavior of the autoSuggest() function and you point to any documentation for that function, then perhaps we could offer a better way to solve your issue.
The link may be firing and taking you off to a new page (or reloading the current page), thus preventing you from seeing the click code run. Usually when you process a click event on a link element, you need to prevent the default behavior:
//a is an anchor element
a.addEventListener('click', function (e) {
e.preventDefault();
//Do Stuff...
});
Another possibility is that you are trying to install the event handler too soon either before the DOM has been loaded or before this particular link has been created and thus no actual click event handler is attached to the DOM object. You can verify whether the event handler is even getting called by temporarily putting an alert("Click handler called"); in the event handler and see if that pops up or not.
In Titanium Appcelerator, I have a project that creates a tabGroup and window via a function.
Ti.App.addEventListener('startCoSelect', function(e) {
// store user name and password globally
// user = e.user;
// pass = e.pass;
tabs.close();
tabs = tms.ui.createCoSelectGroup();
tabs.open();
});
Ti.App.addEventListener('startAppHome', function(e) {
tabs.close();
tabs = tms.ui.createApplicationTabGroup();
tabs.open();
});
var tabs = tms.security.getPermission();
tabs.open();
Within this function is a button, this button has an event listener assigned to it that then calls Ti.App.fireEvent('startCoSelect').
btnLogin.addEventListener("click", function (e) {
Ti.App.fireEvent('startCoSelect');
});
From this event listener a function is called that opens a new tabGroup and window as well as closing the previous tab group as shown above. Inside of the tabGroup created by tms.ui.createCoSelectGroup() is another eventlistener that fires another event
btnSelect.addEventListener("click", function (e) {
Ti.App.fireEvent('startAppHome');
});
and once again another event listener and fireEvent call within the tms.ui.createApplicationTabGroup() function.
I am developing and testing all code within Titanium Studio with Titanium sdk 1.7 using the continuous/nightly builds of both on Mac OS X 10 as well as a completely updated Android and iOS sdk.
My issue is only within Android. The mobile app works perfectly as it should on iPhone. However, on Android (testing with 2.2 API's emulator) I can only fire one event. As an example, the android application will accept the first button "click" event fine and fire the event but then the next fireEvent call (activated by the next button press) will not fire.
I know that the "click" event is firing, by placing an alert inside of each Event Listener, and that it has to be the fireEvent call.
I also know that it doesn't have anything to do with the order of the calls. If I change which event is fired first it will always fire the first one and it will always refuse the fireEvent calls that follow. An example being that I changed which tabGroup and window was opened at launch and the first button click and fireEvent work then afterwards, even though the next click events are registered, the fireEvent call is not.
The Trace and console give no answers or error codes and I am left with only a button that does nothing unless I place an alert or function inside. I have tried having the function call Ti.App.fireEvent() and it doesn't change.
I may be able to post code via pastie but I need to remove crucial information before posting it so it may take a day.
All help is appreciated.