I was wondering if it were possible to pass parameters to a javascript event called from an AJAX extender (in this case AutoComplete) while preserving the EventArgs also being passed. Here's a short sample of what I mean:
<... OnClientItemSelected="DoThis(somevar, eventargs);" />
Script:
function DoThis(somevar, eventargs) {
var blah = somevar;
...
var blah2 = eventargs.get_text();
}
That's the idea. Does anyone know how to do this or if it's possible?
It's not exactly clear what your asking, but...I'll take a stab at it anyway. It sounds like you essentially want to augment the event data passed to the event handler. There are a number of ways to do this:
If you are using jQuery:
First, the bind() method can be invoked with either 2 or 3 arguments:
bind( eventName , eventHandler )
bind( eventName , data , eventHandler )
If bind() is invoked with 3 arguments, the second argument, data, is an arbitrary object handed to the event handler as the .data property of the Event instance passed to the event handler.
Second, the event handler is a closure, the lexical scope of which includes those variables that were in scope at the point the closure was created. For instance, the usual way you would bind an event handler to an event in jQuery is something like this:
$(function(){
var pi = 3.1415926 ;
var phoneticAlphbet = { a = "alpha" , b = "bravo" , c = "charlie" ,
...
x = "x-ray" , y = "yankee" , z = "zulu"
} ;
$('input:radio[name=buttonset1]').click(function(){
// at this point, the variables pi and phonetic alphabet are in-scope,
// as well as any other globals you've created
// do something here
}) ;
}) ;
So that's a second way to pass data to the event handler.
A third way is to hang data off DOM tree elements. jQuery conveniently provides the data() method to do this:
.data( name , value ) sets a value on the wrapped set
.data( name ) retrieves values from the wrapped set
For example, this snippet will save the original value for each and element on the page:
$('input,select').each(function(){
var item = $(this) ;
item.data( 'original-value' , item.val() ) ;
}) ;
Having set it, the value can be retrieved:
$('input#password').change(function(){
var item = $(this) ;
var oldValue = item.data('original-value') ;
var newValue = item.val() ;
if ( oldValue == newValue )
{
alert('the new password must be different than the old password!') ;
}
}) ;
Related
I'm dynamically creating a table row full of checkboxes using JavaScript in the function populateParameterTr(parameters). In this function, I set an event handler such that when the checkbox is made active, a hidden input field is created in the toggleHidden function.
What I'm having trouble with is trying to call toggleHidden to create these hidden input elements after the checkbox is created, ie not in the event handler. Reason being: I want these hidden input fields when the checkboxes are loaded for the first time. From my understanding calling toggleHidden() results in this pointing to the global scope.
I've had a look at bind,call and apply to see if this will help like below:
toggleHidden(display, parameterContainer).bind(checkbox);
Can someone advise me if this can be done. I'm looking at this example as an exercise to get my head around using these methods.
Code:
var populateParameterTr = function(parameters) {
var checkboxes = $('<td></td>');
for (var i in parameters) {
var display = parameters[i].display;
var checkbox = $('<input>').attr({
//...
});
var parameterContainer = $('<div></div>').addClass('parameter').append(checkbox);
checkboxes.append(parameterContainer);
toggleHidden(display, parameterContainer).bind(checkbox);
checkbox.on('change', toggleHidden(display, parameterContainer));
}
}
var toggleHidden = function(display, tableDivide) {
return function() {
if (this.checked) {
var hidden = $('<input>').attr({
//......
});
hidden.appendTo(tableDivide);
} else {
$(this).siblings("input[type='hidden']").remove();
}
};
};
.call and .apply directly executes the function with first param is thisArg, the difference between them is .call accepts parme like .call(thisArg, param1, param2....) , but .apply accepts like .apply(thisArg, [param1, param2....]).
.bind returns a new Function, when it executes, it use the first param when you call .bind as thisArg, and if you gives other param, it'll put it directly to the origin function for you, e.g:
var func = function(param1, param2) {
console.log(param1, param2);
};
var bindFunc = func.bind(null, 1);
bindFunc(2); // log 1, 2 now
Take above knowledge to examine the code you post:
toggleHidden(display, parameterContainer).bind(checkbox);
It Seems you want to call it, and the this is reference to that checkbox, so you can write:
toggleHidden.call(checkbox, display, parameterContainer);
// or
toggleHidden.apply(checkbox, [display, parameterContainer]);
Then this part:
checkbox.on('change', toggleHidden(display, parameterContainer));
Here you want to call toggleHidden when checkbox change, as you're listen to checkbox's change event, and the input param should be pre-defined, you can write
checkbox.on('change', toggleHidden.bind(checkbox, display, parameterContainer));
You can get more info from js call() & apply() vs bind()?, mdn-function-bind, mdn-function-call.
Can I get value from jquery event function?
I want to get something like this:
function Init() {
var my_variable = $some_object.click(function() {
var my_variable = 'value';
return my_variable // I need to get the variable value from click event
// but I don't know ways to do it
});
console.log(my_variable); // I want to have possibility to use the value here
}
No.
The function that sets the event handler will have finished running before the event handler runs.
No, you can't do that. You can only capture the value in a variable defined outside the scope of your handler:
function Init() {
var my_variable = '';
$some_object.click(function() {
my_variable = 'value';
});
console.log(my_variable); //Prints empty string
$some_object.trigger('click');
console.log(my_variable); //Prints 'value'
}
The answer to your question is No!. You cannot return a value from event handler.
Now next thing which made you curious is how to get some data which comes from the event handler itself. This is where event propagation comes and passing some data along with that.
Checkout below fiddle which shows how data which was created in event handler of button click, is being passed for any custom purpose.
http://jsfiddle.net/kowmwq9j/
Below is simple html and understandable javascript code
<div id='parent'>
<button id='test'>CLick</button>
</div>
var a=document.getElementById('test');
a.addEventListener('click', function(){
var str='sample';
//creating a custom event with name 'build' and passing object as data
var event = new CustomEvent('build', { 'detail': str });
//dispatches the event which invokes the affected listeners
this.dispatchEvent(event);
})
//Listening for 'build' event
document.getElementById('parent').addEventListener('build', getData, true);
function getData(e){
alert(e.detail);
}
Links shared which can help one to understand the concept. dispatchEvent & createCustomEvent .Hope that helps to answer your question!
Added some comments & links which will help those who aren't aware of the functions & behavior used.
If I understand the question maybe you can do something like this...
Variable = 5 is used within 2 functions...each function does something with it's value...
the last function uses the totals of the first 2 functions and again does something.. So the point is that u can access the 2 totals variables and use them in the third function... As long as you set your function variable as global...so don't put VAR in front of it. If you set var in front of it u are saying that your variable is private for that function...
Change the value of the original variable and all the values changes ....
variable = 5; // this is a global variable
source = $('div#een h2'); // put your source here
function Init(){
source.on('click', function(){
Total1 = variable * 2;
console.log(Total1); // It outputs 10
});
};
Init();
function Init2(){
source.on('click', function() {
Total2 = variable * 5;
console.log(Total2); // It outputs 25
});
};
Init2();
function Init3(){
source.on('click', function() {
Total3 = Total1 * Total2; // here we use the 2 Totals...
console.log(Total3); // outputs the Total of both totals... should be 250
});
};
Init3();
I'm sure this should be a simple question but I'm still learning so here it goes:
I have some code to run a function on click to assign the clicked element's ID to a variable but I don't know how to pass the "this.id" value to the namespace without making a global variable (which I thought was bad).
<script>
fsa = (function() {
function GetTemplateLoc() {
templateId = document.activeElement.id;
alert(templateId + templateId2);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
//call the functions
$(document).on('click', '.template', function () {
fsa.GetTemplateLoc();
});
</script>
and HTML with random picture:
<img id="template-1" class="template" src="http://fc02.deviantart.net/fs70/f/2010/028/c/b/cb21eda885b4cc6ee3f549a417770596.png"/>
<img id="template-2" class="template" src="http://fc02.deviantart.net/fs70/f/2010/028/c/b/cb21eda885b4cc6ee3f549a417770596.png"/>
The following would work:
var fsa = (function() {
function GetTemplateLoc() {
var templateId = this.id;
alert(templateId);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
//call the functions
$(document).on('click', '.template', fsa.GetTemplateLoc);
jQuery generally calls functions you pass as event handlers with this set to the DOM object the event is associated with.
In this case it will call GetTemplateLoc() with this set to either .template element, so you can use this directly in the function and don't need to pass any parameters.
Important tip: Always declare variables using var. JavaScript has no automatic function-local scope for variables, i.e. every variable declared without var is global, no matter where you declare it. In other words, forgetting var counts as a bug.
Try this : You can directly use this.id to pass id of the clicked element where this refers to the instance of clicked element.
<script>
fsa = (function() {
function GetTemplateLoc(templateId ) {
//templateId = document.activeElement.id;
alert(templateId + templateId2);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
//call the functions
$(document).on('click', '.template', function () {
fsa.GetTemplateLoc(this.id);
});
</script>
If you're able to use jQuery within the GetTemplateLoc function, you could do something like this:
var fsa = (function() {
function GetTemplateLoc($trigger) {
var templateId = $trigger.attr('id'),
templateId2 = $($trigger.siblings('.template')[0]).attr('id');
alert(templateId + ' ' + templateId2);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
$(document).on('click', '.template', function () {
fsa.GetTemplateLoc($(this));
});
You can set GetTemplateLoc to expect a jQuery object as a parameter (the dollar sign at the beginning of $trigger can be used to distinguish it as a jQuery object rather than any other data type, it's not necessary but can help clarify things sometimes).
templateId will store the value of the clicked image's ID, and templateId2 will store the value of the other image's ID. I also added a space between the two variables in the alert.
If you can't use jQuery within GetTemplateLoc, you could do something like this:
var fsa = (function() {
function GetTemplateLoc(trigger) {
var templateId = trigger.id;
var templateId2 = trigger.nextElementSibling == null ? trigger.previousElementSibling.id : trigger.nextElementSibling.id;
alert(templateId + ' ' + templateId2);
}
return {
GetTemplateLoc: GetTemplateLoc,
}
})();
This time, the .template that triggered the event is passed into GetTemplateLoc, but this time it's not a jQuery object. templateId is assigned to the trigger's ID and then templateId2 is assigned in a ternary. First, the nextElementSibling of trigger is checked to see if it's null. If it is, we know that trigger is the second of the two .template elements. Therefore we can set templateId2 to the ID of trigger's previous sibling. If trigger's nextElementSibling is not null, then we know that trigger is the first template and we populate templateId2 with the ID of nextElementSibling. This exact method will only work with two .template's, if there are more you'll need some additional/different logic, probably to retrieve all .template IDs and then loop through them to add them to the alert message. Hope this helps.
Update:
Sorry for the lengthy stupid question. It was a problem with my selector. Ignore post!
I have a widget that is having public functions. that I normally am able to call like:
$("#mygrid").myGrid( "MyFunction", args );
Problem:
But in some cases the function is not getting called.
Here are some trivia
My widget is derived from another (base)widget I created.
The same function works when called for the base widget
The function is not overridden in the child widget.
The same function works for another child widget of the same parent
with the same piece of code I mentioned earlier except the name of
the widget and the DOM element.
Now, here are some important information.
A similar function in the problem widget works and when I stepped inside the call, I found a difference in both the calls in the following function in jquery-ui.js:
$.widget.bridge = function( name, object ) {
var fullName = object.prototype.widgetFullName || name;
$.fn[ name ] = function( options ) {
var isMethodCall = typeof options === "string",
args = slice.call( arguments, 1 ),
returnValue = this;
// allow multiple hashes to be passed on init
options = !isMethodCall && args.length ?
$.widget.extend.apply( null, [ options ].concat(args) ) :
options;
if ( isMethodCall ) {
this.each(function() {
var methodValue,
// Rest of the code.
Here, For my function that is not getting called, it won't enter in that this.each. when I checked the this pointer, there was a difference.
For the function that is getting called, the content of this is like the following:
0: div#myGrid
context: document
length: 1
selector: "#mygrid"
__proto__: Object[0]
But for the function that is NOT getting called, the first item and the length attribute was missing.
context: document
selector: "#mygrid"
__proto__: Object[0]
What Could be the problem?
I have the following code which is designed to create an onchange event handler for all elements with class name 'State'. The only problem is that I want the element to be passed into the 'StateChange' function. How can I update this JS to pass 'this' into the StateChange function? Thanks!
var c = document.getElementsByClassName('State');
for (i = 0; i < c.length; i++) c[i].onchange = createEventHandler( StateChange, c[i] );
Edit: I forgot to provide the createEventHandler function. Sorry about that... Here it is:
function createEventHandler(fn, input) {
return function () {
fn(input);
};
}
Also, some clarification. The purpose of the function is to obviate the need to put the onchange event next to each element with class name = 'State'. The result should be the same as if I were to write:
<select id="MyState1" class="State" onchange="StateChange(this)">
Update:
Re your updated question: You've said that the end result you want is as though you'd done this:
<select id="MyState1" class="State" onchange="StateChange(this)">
Your quoted createEventHandler function does exactly that.
Original Answer(s):
I'm not entirely sure I know exactly what you're trying to do. I can read the question at least two ways:
Inside the StateChange function call, you want this to refer to the element that changed.
Inside the StateChange function call, you want this to be the same as this where you're setting up your event handler.
Option 1: You want this = element within StateChange
You don't actually have to pass the element instance into createEventHandler, because when the event occurs, this will refer to the element because of the way you're hooking it up. But if you prefer to set it explicitly, your createEventHandler function could look like this:
function createEventHandler(handler, element) {
return function(event) {
return handler.call(element, event || window.event);
};
}
What that does is return a function that, when the event is triggered, will call the function you pass in (StateChange) with this set to the element you pass in.. This uses the JavaScript call feature of function objects, which allows you to define what this will be during the function call. You just pass it in as the first argument to call (subsequent arguments are passed on to the function being called).
If you want to rely on the fact that the way you're setting up the handler, this will already be set to the element instance, you can do away with the element argument:
function createEventHandler(handler) {
return function(event) {
return handler.call(this, event || window.event);
};
}
That just passes along the this value set up for the event handler by the browser.
Option 2: You want this = this as of where you're setting up the handler
It's the same principle as the above, just with a different argument. In this case, you'll need to pass this in:
var c = document.getElementsByClassName('State');
for (i = 0; i < c.length; i++) c[i].onchange = createEventHandler( StateChange, this, c[i] );
...and then createEventHandler looks like this:
function createEventHandler(handler, thisArg, element) {
return function(event) {
return handler.call(thisArg, event || window.event, element);
};
}
(Note I've passed in the element as a second argument to StateChange.)
More reading:
Mythical methods
You must remember this
One way is:
var c = document.getElementsByClassName('State');
for (i = 0; i < c.length; i++)
c[i].onchange = createEventHandler(function(){
StateChange(c[i]);
});