I am creating a function which will take in a URL and then display that URL in a light box. I am having trouble with event.preventDefault() in my function though, it says it is not a function in the error console.
I have tried explicitly passing event to the function but that simply runs the function on page load rather than when clicking
Here is my code:
// Function to display widget
function displaySportsWidget(event, iframeURL) {
// Prevent Default Event Handler
event.preventDefault();
// Build iFrame HTML
var iframe = '<iframe src="' + iframeURL + '" ></iframe>';
var html = iframe;
// Inject HTML to Generate Widget
$('.leagues-wrapper').html(html);
// Display Overlay
$('.leagues-overlay').css('display', 'block');
};
// Event handlers. Pass iFrame URL into function depending on link clicked
$('.leagues-link.league-table').on('click', displaySportsWidget('http://www.example01.com'));
$('.leagues-link.league-form').on('click', displaySportsWidget( 'http://www.example02.com'));
The code
$('.leagues-link.league-table').on('click', displaySportsWidget('http://www.example01.com'));
calls displaySportsWidget and passes its return value into on, exactly the way foo(bar()) calls bar and passes its return value into foo.
If you want to hook up an event handler, you don't call it, you just refer to it. In your case, you can do that like this:
$('.leagues-link.league-table').on('click', function(e) {
displaySportsWidget(e, 'http://www.example01.com');
});
Or if you're open to changing the order of arguments in displaySportsWidget:
function displaySportsWidget(iFrameURL, event) {
// ...
}
...then you can use Function#bind:
$('.leagues-link.league-table').on('click', displaySportsWidget.bind(null, 'http://www.example01.com'));
Function#bind creates a new function that, when called, calls the original function with a given this value (in our case, we don't need any specific one, so I'm passing null) and any arguments you gave bind, followed by any arguments that were given to the bound function. So we'll get the URL (from the bind call) followed by the event object (from when the handler is called).
Function#bind isn't on really old browsers like IE8. If you need to support them, jQuery's $.proxy does something similar:
$('.leagues-link.league-table').on('click', $.proxy(displaySportsWidget, null, 'http://www.example01.com'));
While calling your method you are not passing event as parameter along with image url .so if u pass event as parameter while calling.then your code is going to work.
Thank you
Related
I'm developing an autofill extension. I want to fill an input field with a value, example value = "12345", and then trigger the equivalent of a jQuery $(element).change(), but in pure JavaScript/DOM.
I've tried dispatching the change method,
document.querySelector("input[name=inputIWantToChange]").dispatchEvent(new Event("change"));
but the behavior is different than that of
$("[name=inputIWantToChange]").change()
Looking at jQuery's source code, it would appear that jQuery works by invoking the handler that you have bound to the event (with a fake event that it creates) when you call change() - which means that you're going to have to find a way to be able to invoke a function, and also have the event invoke the same function. Consider the following:
var elem = document.querySelector("input[name=inputIWantToChange]");
elem.addEventListener("change", function (evt) {
onElemChange() // Pass data from the event `evt` here, as needed
});
function onElemChange() {
// Your handler method here
}
When you'd want to invoke a "change event" as you do with jQuery, you can then just call onElemChange with the information you'd have gotten from the event, assuming you'd want to use any of the information from the event.
In ArcGIS JS API I need to trigger a method of my class when the processing after an extent change is complete. I didn't find any special event for this. extent-change triggers too early, when the data are not loaded yet. update-end is triggered also by the function I want to call, making an endless loop. So what I need is to link the two events together, the second one just once. But how?
Most of my events look like this:
this.events.push(on(this.map, "extent-change", lang.hitch(this, this._foo)));
This is not suitable for event linking, so I need to make the linked event some other way. What I've tried:
_foo: function () {
function fooEvent() {
this._bar();
dojo.disconnect(updateHandle);
}
var updateHandle = dojo.connect(map, "onUpdateEnd", fooEvent());
}
_bar is the method I want to run on the end of the extent change. However, this in the event handler means something else, not the class containing the function. I also tried the classname I declared in the declare statement, but with no luck.
_foo() and _bar() are in the same class (let's call it "foobar/baz"). However, inside of the fooEvent() is not its subclass as I hoped - when I try to use this.inherited within it, it's undefined. Another way I try is to add event argument to the handler, but it's undefined as well. So unless there is some better way, I need to understand how to get the object of "foobar/baz" class.
Another way I tried was to use lang.hitch once more, in one of the following ways:
//through the cluster event
var updateHandle = dojo.connect(map, "onUpdateEnd", lang.hitch(this, clusterEvent));
//or directly calling _bar()
var updateHandle = dojo.connect(map, "onUpdateEnd", { langh:lang.hitch(this, this._bar), disc:dojo.disconnect(updateHandle)});
//or through on, leaving a rouge event listener
dojo.on(map, "onUpdateEnd", lang.hitch(this, this._bar));
None of them returns any clear error and though the _bar() method seemed to work for some time, it doesn't work now - this is true for all three of the previous. I don't understand what these listeners do.
I solved this issue by flattening the event listeners. First, I made a flag _reloadFlag, initialized in the constructor as false and then changed to true whenever I want to call _bar, like in _foo. _bar now starts with a test of _reloadFlag either setting it to false or returning nothing. The event listeners now look like this:
this.events.push(on(this.map, "extent-change", lang.hitch(this, this._foo)));
this.events.push(on(this.map, "update-end", lang.hitch(this, this._bar)));
I'm taking a Javascript class and was wondering if there was a way to tell which button was selected when a function is called. I basically have a method like this:
function sendRequest()
{
var url = "http://classwebsite/bookmarks.php";
url += "?userid=crystal";
var transmission = document.getElementById("transmission").value;
url += "&response=" + transmission;
var callback = {success:handleResponse,
failure:handleFailure,
timeout:5000
};
var transaction = YAHOO.util.Connect.asyncRequest("GET", url, callback, null);
}
This method gets called when a button is pressed. It basically gets back the prof's response in the appropriate JSON, XML, etc format and displays it. I want to add an "add" feature to add new rows to the table. That's done by calling the same URL in the above method and just manually putting this in the address bar:
http://classwebsite/bookmarks.php?userid=crystal&action=add&name=yahoo&url=yahoo.com&desc=Yahoo+website
In this scenario, if I had another button called "Add" to add in fields from a form, would I call the same sendRequest() method, and modify the url accordingly? If so, how do I know which button was pressed if both the "List" button and "Add" button would be tied to the same event handler.
Or is it a better design to have another method, that handles addRequest() and just adds fields from the form? Thanks.
If you did use the Yahoo utils like they are supposed to be used (i.e. via YAHOO.util.Event.addListener()), then your button is referenced by this.
See Automatic Scope Correction in the YUI docs.
In addition, please encode URL parameters correctly before you use them.
var transmission = document.getElementById("transmission").value,
url = "http://classwebsite/bookmarks.php"
+ "?userid=crystal"
+ "&response=" + encodeURIComponent(transmission); // <- !!
You should be able to modify the parameters of your javascript function to see the sender.
There is also a hidden array called arguments, that will let you look at what parameters are available to a function, in case you are ever curious.
function sendRequest(sender, args) {
//sender is your clicked button
var url = "http://classwebsite/bookmarks.php";
url += "?userid=crystal";
var transmission = document.getElementById("transmission").value;
url += "&response=" + transmission;
var callback = {success:handleResponse,
failure:handleFailure,
timeout:5000
};
var transaction = YAHOO.util.Connect.asyncRequest("GET", url, callback, null);
}
If a button is pressed then an event should be passed to the function. The event object contains the target of the click among other things.
function sendRequest(e) {
var target;
if(!e) {
e = window.event;
}
// the button clicked can now be accessed as
// we use the ternary because IE uses a different property
target = e.target ? e.target : e.srcElement;
}
Youll note a couple if statements in there... this is because IE differs a bit form the standard. However, i see youre using a Yahoo lib for some of your js. I imagine if you are to use the facilities of this library to bind your events it would also normalize the event object passed in to your callbacks so you wouldnt have to manually create xbrowser accommodations.
I have a function which is a JQuery event handler. Because it is a JQuery event handler, it uses the this variable to refer to the object on which it is invoked (as is normal for that library).
Unfortunately, I need to manually call that method at this point. How do I make this inside the called function behave as if it were called from JQuery?
Example code:
function performAjaxRequest() {
//Function which builds AJAX request in terms of "this"
}
function buildForm(dialogOfForm) {
var inputItem;
dialogOfForm.html('...');
dialogOfForm.dialog('option', 'buttons', {
"Ok" : performAjaxRequest
});
inputItem = dialogOfForm.children(':not(label)');
//Redirect enter to submit the form
inputItem.keypress(function (e) {
if (e.which === 13) {
performAjaxRequest(); //Note that 'this' isn't the dialog box
//as performAjaxRequest expects here, it's
//the input element where the user pressed
//enter!
}
}
}
You can use the function's call method.
someFunction.call(objectToBeThis, argument1, argument2, andSoOnAndSoOn);
If dialog is the object that you need to be set to this then:
performAjaxRequest.apply(dialog, []);
// arguments (instead of []) might be even better
should do the trick.
Otherwise, in jQuery you can simply call the trigger method on the element that you want to have set to this
Say, for example, that you wanted to have a click event happen on a button and you need it to happen now. Simply call:
$("#my_button").trigger("click");
Your #my_button's click handler will be invoked, and this will be set to the #my_button element.
If you need to call a method with a different this ... say for example, with this referring to the jQuery object itself, then you will want to use call or apply on your function.
Chuck and meder have already given you examples of each ... but to have everything all in one place:
// Call
my_function.call(object_to_use_for_this, argument1, argument2, ... argumentN);
// Apply
my_function.apply(object_to_use_for_this, arguments_array);
SEE: A List Apart's Get Out of Binding Situations
Are you looking for..
functionRef.apply( objectContext, arguments);
You should of course learn to master call() and apply() as people have stated but a little helper never hurts...
In jQuery, there is $.proxy. In pure js, you can re-create that niftyness ;) with something like:
function proxyFn( fn , scope ){
return function(){
return fn.apply(scope,arguments);
}
}
Usage Examples:
var myFunctionThatUsesThis = function(A,B){
console.log(this,arguments); // {foo:'bar'},'a','b'
};
// setTimeout or do Ajax call or whatever you suppose loses "this"
var thisTarget = {foo: 'bar'};
setTimeout( proxyFn( myFunctionThatUsesThis, thisTarget) , 1000 , 'a', 'b' );
// or...
var contextForcedCallback = proxyFn( myAjaxCallback , someObjectToBeThis );
performAjaxRequest(myURL, someArgs, contextForcedCallback );
If you dont abuse it, it's a sure-fire tool to never loose the scope of "this".
use a closure
i.e assign this to that early on; then you can do what you like with it.
var that = this;
The following doesn't work... (at least not in Firefox: document.getElementById('linkid').click() is not a function)
<script type="text/javascript">
function doOnClick() {
document.getElementById('linkid').click();
//Should alert('/testlocation');
}
</script>
<a id="linkid" href="/testlocation" onclick="alert(this.href);">Testlink</a>
You need to apply the event handler in the context of that element:
var elem = document.getElementById("linkid");
if (typeof elem.onclick == "function") {
elem.onclick.apply(elem);
}
Otherwise this would reference the context the above code is executed in.
The best way to solve this is to use Vanilla JS, but if you are already using jQuery, there´s a very easy solution:
<script type="text/javascript">
function doOnClick() {
$('#linkid').click();
}
</script>
<a id="linkid" href="/testlocation" onclick="alert(this.href);">Testlink</a>
Tested in IE8-10, Chrome, Firefox.
To trigger an event you basically just call the event handler for that
element. Slight change from your code.
var a = document.getElementById("element");
var evnt = a["onclick"];
if (typeof(evnt) == "function") {
evnt.call(a);
}
Granted, OP stated very similarly that this didn't work, but it did for me. Based on the notes in my source, it seems it was implemented around the time, or after, OP's post. Perhaps it's more standard now.
document.getElementsByName('MyElementsName')[0].click();
In my case, my button didn't have an ID. If your element has an id, preferably use the following (untested).
document.getElementById('MyElementsId').click();
I originally tried this method and it didn't work. After Googling I came back and realized my element was by name, and didn't have an ID. Double check you're calling the right attribute.
Source: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/click
$("#linkid").trigger("click");
Old thread, but the question is still relevant, so...
(1) The example in your question now DOES work in Firefox. However in addition to calling the event handler (which displays an alert), it ALSO clicks on the link, causing navigation (once the alert is dismissed).
(2) To JUST call the event handler (without triggering navigation) merely replace:
document.getElementById('linkid').click();
with
document.getElementById('linkid').onclick();
Have a look at the handleEvent method
https://developer.mozilla.org/en-US/docs/Web/API/EventListener
"Raw" Javascript:
function MyObj() {
this.abc = "ABC";
}
MyObj.prototype.handleEvent = function(e) {
console.log("caught event: "+e.type);
console.log(this.abc);
}
var myObj = new MyObj();
document.querySelector("#myElement").addEventListener('click', myObj);
Now click on your element (with id "myElement") and it should print the following in the console:
caught event: click
ABC
This allows you to have an object method as event handler, and have access to all the object properties in that method.
You can't just pass a method of an object to addEventListener directly (like that: element.addEventListener('click',myObj.myMethod);) and expect myMethod to act as if I was normally called on the object. I am guessing that any function passed to addEventListener is somehow copied instead of being referenced. For example, if you pass an event listener function reference to addEventListener (in the form of a variable) then unset this reference, the event listener is still executed when events are caught.
Another (less elegant) workaround to pass a method as event listener and stil this and still have access to object properties within the event listener would be something like that:
// see above for definition of MyObj
var myObj = new MyObj();
document.querySelector("#myElement").addEventListener('click', myObj.handleEvent.bind(myObj));
If you're using this purely to reference the function in the onclick attribute, this seems like a very bad idea. Inline events are a bad idea in general.
I would suggest the following:
function addEvent(elm, evType, fn, useCapture) {
if (elm.addEventListener) {
elm.addEventListener(evType, fn, useCapture);
return true;
}
else if (elm.attachEvent) {
var r = elm.attachEvent('on' + evType, fn);
return r;
}
else {
elm['on' + evType] = fn;
}
}
handler = function(){
showHref(el);
}
showHref = function(el) {
alert(el.href);
}
var el = document.getElementById('linkid');
addEvent(el, 'click', handler);
If you want to call the same function from other javascript code, simulating a click to call the function is not the best way. Consider:
function doOnClick() {
showHref(document.getElementById('linkid'));
}
In general I would recommend against calling the event handlers 'manually'.
It's unclear what gets executed because of multiple registered
listeners
Danger to get into a recursive and infinite event-loop (click A
triggering Click B, triggering click A, etc.)
Redundant updates to the DOM
Hard to distinguish actual changes in the view caused by the user from changes made as initialisation code (which should be run only once).
Better is to figure out what exactly you want to have happen, put that in a function and call that manually AND register it as event listener.