I'm using jQuery version 1.5.
I am looking at jQuery's change() function
and specifically at this bit:
.change( [ eventData ], handler(eventObject) )
eventData: A map of data that will be passed to the event handler.
handler(eventObject): A function to execute each time the event is triggered.
What exactly is a "map of data" in JavaScript? How can I use the following test function as an event handler?
var myHandler = function(msg){alert(msg);};
I've tried this:
$("select#test").change(["ok"], myHandler);
and the alert reports [object Object]
See event.data. The data is not passed as argument to handler, but as property of the event object:
$("select#test").change({msg: "ok"}, function(event) {
alert(event.data.msg);
});
The handler always only accepts one argument, which is the event object. This is the reason why your alert shows "[object Object]", your function is printing the event object.
If you want to use functions with custom arguments, you have to wrap them into another function:
$("select#test").change({msg: "ok"}, function(event) {
myHandler(event.data.msg);
});
or just
$("select#test").change(function(event) {
myHandler("ok");
});
Btw. the selector is better written as $('#test'). IDs are (should be) unique. There is no need to prepend the tag name.
What exactly is a "map of data" in Javascript?
Basically just an object, e.g.:
var data = {
foo: "I'm foo",
bar: "I'm bar"
};
All JavaScript objects are essentially maps (aka "dictionaries" aka "associative arrays").
How can I use the following test function as an event handler?
By wrapping it in another function:
$("select#test").change(function() {
myHandler($(this).val());
});
That calls myHandler with the value of the select box whenever it changes.
If you want to use the eventData part, add an object prior to the handler:
$("select#test").change({
foo: "I'm foo"
}, function(event) {
myHandler(event.data.foo, $(this).val());
});
That calls myHandler with the "I'm foo" as the first argument, then the value of the select box, whenever it changes.
Related
I have a function as follows:
$("#submitBtn").on('click', function () {
....
});
I am using the following in invoke the click it in a portion of code by doing:
$('#submitBtn').click();
Is there a way to set a input parameter to the click.
For example, I need to pass a string value to the click so that the function can take appropriate steps. Note that the value of p is not from any element from the page. It is something I will be pro-grammatically setting based on some conditions.
var p = 'sourceinfo';
$('#submitBtn').click(p);
Alright, the best way to do this is by adding custom data-attribute params to the element before chaining it with the click event:
$("#submitBtn").data("params", {
one: "Parameter 1",
two: "Parameter 2"
}).click();
And you can use params like this:
$("#submitBtn").on('click', function () {
// Parameter 1
alert( $(this).data("params").one );
// Parameter 2
alert( $(this).data("params").two );
// Do other stuff
});
Check working demo
You can use the event handler .trigger() instead of .click()
Syntax :
.trigger( eventType [, extraParameters ] )
Example:
.trigger('click',[param1,param2])
After that you can get those params from your call back function after event param
Click is a event generated and cannot pass the message/data. Instead you can pass the args to the listener(calling method).so that it can be captured to that method.
for e.g
<button onclick="handleClick('msg',event)"></button>
You can use .trigger() instead.
$('#submitBtn').trigger('click', [arg1, ...]);
You can retrieve the parameters passed when attaching the click handler
$('#submitBtn').on('click', function(e, arg1, ...) {
});
You can you jQuery(this).attr('action') ... Inside the function
And on the element add attribute as follow data-action('myaction')
I am trying to pass the argument to the JQuery event handler when a button is being clicked. In plain JavaScript i was using onclick="function(argument)"
Now i am transferring all of my inline click events to external call like one with Jquery i.e
$(".selector").click(function(){
//some code
});
However, in this case i am confused how i can pass the arguments from the HTML tag and how should i receive the arguments in the Jquery event handler.
Please help.
An optional object of data passed to an event method when the current executing handler is bound.
In your case it will be something like this -
$(".selector").on("click", function(event){
//you can access the parameter value as follows
console.log(event.target.value);
});
Refer the official documentation here Pass arguments from a button click to Jquery event handler
The .click() function receives an EventData object that gets passed as the first argument to the handler, you can use that object inside the handler.
For example:
$('.selector').click(function(data) {
$(data).addClass('newClass');
});
If you are trying to pass data from the HTML the cleanest way might be to store that data into the data attribute of your tag.
The HTML
<div id="mydiv" data-arg="Hello world!">Click me</div>
The JS
$('#mydiv').click(function(data) {
var arg = $(data).attr('data-arg');
console.log(arg);
});
For what you are trying to achieve
The HTML
<button id="dark" data-stroke-width="0.5"
class="txtcolor uk-button" type="button">1px</button>
The JS
$('button#dark').click(function(data) {
selectStroke($(data).attr('data-stroke-width'));
});
Check the documentation for click
A sample:
// say your selector and click handler looks something like this...
$("some selector").click({param1: "Hello", param2: "World"}, cool_function);
// in your function, just grab the event object and go crazy...
function cool_function(event){
alert(event.data.param1);
alert(event.data.param2);
}
var param_obj = {data : {param1: "Hello", param2: "World"}};
cool_function(param_obj);
$("dark").click({param1: 0.5}, selectStroke);
or
var i = 0.5;
$("dark").click({param1: i}, selectStroke);
or if you do not want change functionality of the handler
var i = 0.5;
$("dark").click({param1: i}, function() {
selectStroke(event.data.param1);
);
I'm currently attempting to test some code that uses drag-and-drop. I found some other questions that were kinda related to this, but they were way too specific to help me, or not related enough.
This being a test, I'm struggling on trying to automatically execute code inside a .on('drop',function(e){....} event. The main issue is not that I can't run the code inside, but it's that I can't transfer the dataTransfer property, and I can't seem to fake it because it's read-only. Is there anyway to fake the dataTransfer property or otherwise get around it?
I came up with this JSFiddle that serves as a template of what I'm trying to do: https://jsfiddle.net/gnq50hsp/53/
Essentially if you are able to explain to me (if this is at all possible) how I can possibly fake the dataTransfer property, I should be all set.
Side notes:
I'm totally open to other ways of somehow getting inside that code, like for example, maybe its possible to trigger the event and pass in a fake event object with a fake dataTransfer object.
To see the drag-drop behavior, change the JavaScript load type from no-wrap head to on-Load, then you should see what I'm trying to simulate.
Important to note that I cannot modify any of the code inside the event handlers, only inside the outside function
Using Karma/Jasmine so use of those tools are also possible like spies
Also, I'm using Chrome.
Thanks in advance, and let me know for any questions/clarifications!
You should be able to override pretty much everything you want using Object.defineProperty. Depending on what you want to test it can be very simple or very complex. Faking the dataTransfer can be a bit tricky, since there's a lot of restrictions and behaviors linked to it, but if you simply want to test the drop function, it's fairly easy.
Here's a way, this should give you some ideas as to how to fake some events and data:
//Event stuff
var target = $('#target');
var test = $('#test');
test.on('dragstart', function(e) {
e.originalEvent.dataTransfer.setData("text/plain", "test");
});
target.on('dragover', function(e) {
//e.dataTransfer.setData('test');
e.preventDefault();
e.stopPropagation();
});
target.on('dragenter', function(e) {
e.preventDefault();
e.stopPropagation();
});
//What I want to simulate:
target.on('drop', function(e) {
console.log(e)
//Issue is that I can't properly override the dataTransfer property, since its read-only
document.getElementById('dataTransferDisplay').innerHTML = e.originalEvent.dataTransfer.getData("text");
});
function simulateDrop() {
// You'll need the original event
var fakeOriginalEvent = new DragEvent('drop');
// Using defineProperty you can override dataTransfer property.
// The original property works with a getter and a setter,
// so assigning it won't work. You need Object.defineProperty.
Object.defineProperty(fakeOriginalEvent.constructor.prototype, 'dataTransfer', {
value: {}
});
// Once dataTransfer is overridden, you can define getData.
fakeOriginalEvent.dataTransfer.getData = function() {
return 'test'
};
// TO have the same behavior, you need a jquery Event with an original event
var fakeJqueryEvent = $.Event('drop', {
originalEvent: fakeOriginalEvent
});
target.trigger(fakeJqueryEvent)
}
https://jsfiddle.net/0tbp4wmk/1/
As per jsfiddel link you want to achieve drag and drop feature. jQuery Draggable UI already provides this feature why you can not use that?
For create custom event on your way you have to follow two alternative ways
$('your selector').on( "myCustomEvent", {
foo: "bar"
}, function( event, arg1, arg2 ) {
console.log( event.data.foo ); // "bar"
console.log( arg1 ); // "bim"
console.log( arg2 ); // "baz"
});
$( document ).trigger( "myCustomEvent", [ "bim", "baz" ] );
On above example
In the world of custom events, there are two important jQuery methods: .on() and .trigger(). In the Events chapter, we saw how to use these methods for working with user events; for this chapter, it's important to remember two things:
.on() method takes an event type and an event handling function as arguments. Optionally, it can also receive event-related data as its second argument, pushing the event handling function to the third argument. Any data that is passed will be available to the event handling function in the data property of the event object. The event handling function always receives the event object as its first argument.
.trigger() method takes an event type as its argument. Optionally, it can also take an array of values. These values will be passed to the event handling function as arguments after the event object.
Here is an example of the usage of .on() and .trigger() that uses custom data in both cases:
OR
jQuery.event.special.multiclick = {
delegateType: "click",
bindType: "click",
handle: function( event ) {
var handleObj = event.handleObj;
var targetData = jQuery.data( event.target );
var ret = null;
// If a multiple of the click count, run the handler
targetData.clicks = ( targetData.clicks || 0 ) + 1;
if ( targetData.clicks % event.data.clicks === 0 ) {
event.type = handleObj.origType;
ret = handleObj.handler.apply( this, arguments );
event.type = handleObj.type;
return ret;
}
}
};
// Sample usage
$( "p" ).on( "multiclick", {
clicks: 3
}, function( event ) {
alert( "clicked 3 times" );
});
On above example
This multiclick special event maps itself into a standard click event, but uses a handle hook so that it can monitor the event and only deliver it when the user clicks on the element a multiple of the number of times specified during event binding.
The hook stores the current click count in the data object, so multiclick handlers on different elements don't interfere with each other. It changes the event type to the original multiclick type before calling the handler and restores it to the mapped "click" type before returning:
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;
I have the code (inside one object)
onclick: this._addX.bind(this)
and then inside another object
onclick: this._addY.bind(this)
Now, _addX() and _addY are nearly identical, except they both end up calling (on the click event) a function with different argument values, say _addX calls foo('x') and _addY calls foo('y'). So I tried:
onclick: this._add.bind(this,'x') and
onclick: this._add.bind(this,'y') in the two objects. And of course I changed _add to accept an argument.
At runtime, when _add is called, it does not see any incoming arguments! I have fumbled around with different syntaxes but nothing works. Any ideas? The original syntax works fine (no arguments) but forces me to duplicate a large function with only one line different, which pains me. Thanks in advance.
_add: function(which) {
var me = this;
var checkFull = function(abk) {
if (abk.isFull) {
alert("full");
} else {
alert(which); // which is always undefined here!
}
};
getAddressBook(checkFull); //checkFull is a fn called by getAddressBook
},
this works and it keeps the scope within an element click event with the scope set to the class and not the element--there is no point in passing scope to the add method, it already has that:
var foo = new Class({
Implements: [Options],
add: function(what) {
alert(what);
},
initialize: function(options) {
this.setOptions(options);
this.options.element.addEvents({
click: function() {
this.add(this.options.what);
}.bind(this)
});
}
});
window.addEvent("domready", function() {
new foo({
element: $("foo"),
what: "nothin'"
});
});
just make an element with id=foo and click it to test (alerts nothin'). if your onclick is a function / event handler within your class as opposed to a normal element click event, then things are going to differ slightly - post a working skeleton of your work on http://mootools.net/shell/
If you read my previous answer, disregard it. The MooTools .bind method supports passing parameters. So something else isn't working as you expect:
onclick: this._add.bind(this, 'y');
Here is a simple setup on JSBin to show how bind truly does pass parameters.
The only purpose of bind is to "tell" the JS what object you mean when you say this. i.e. you pass as a parameter to bind an instance of the object you wish the this key word will refer to inside the function you used the bind on.