I have a variable being set in a plugin JS file, and in my own custom JS file, I'm calling the same event to piggypack on the developers work.
The issue is I need to access a variable set in the plugin javascript event. It's currently being set as follows in the plugin JS:
$('#link').live('click', function() {
var test = 123456;
var another = 'string';
$('body').trigger({
'test' : test,
'another' : another
});
});
Now, in my own custom JS, I'm calling the same method on the #link to add my own code to execute.
$('#link').on('click', function(){
// I need to access the another variable set previously
});
What I don't really get is when the jquery docs say that the trigger method is passing arguments to the event handler. What does that mean exactly? How would I access the variable set in a previous event?
Thanks in advance as always.
NORMALLY, you would pass extra parameters to an event, IF it has a custom event, you can access that:
$('#link').live('click', function() {
var test = 123456;
var another = 'string';
$('body').trigger('HIT',{
'test': test,
'another': another
});
});
$('body').on('HIT', function(e,param1) {
$('#hitter').append('hi');
$('#hitter').append(param1.test);
});
after this HIT event, the value of #hitter would have "hi123456" appended to it. To access the "another" is simply param1.another, which returns "string".
Related
I have created the following function.
function showAllSelectOpts(select)
{
selectLength = select.children().length;
select.attr('size',selectLength);
select.css('height','auto');
select.focusout(function(){
select.attr('size','1');
});
}
When it is called directly on a select element like this showAllSelectOpts(mySelect); it works fine, but when called within another function, as below using the keyword "this", it returns the error. Type error: select.children not a function
$('select').on('focus',function(){
showAllSelectOpts(this);
})
Is this a scope issue or what, and how can I resolve it?
In an event handler, this is a reference to the DOM element, not a jQuery object. But your showAllSelectOpts expects its argument to be a jQuery object.
Either change the call to wrap the DOM element with $():
showAllSelectOpts($(this));
...or update showAllSelectOpts to do so itself:
function showAllSelectOpts(select)
{
select = $(select); // ***
selectLength = select.children().length;
select.attr('size',selectLength);
select.css('height','auto');
select.focusout(function(){
select.attr('size','1');
});
}
Side note: As A.Wolff points out, your function attaches a new focusout handler to the select every time it's called. You only want one.
I'd remove that part of the handler entirely, and replace it with a single focusout:
function showAllSelectOpts(select)
{
var selectLength = select.children().length;
select.attr('size',selectLength);
select.css('height','auto');
}
$('select')
.on('focus',function(){
showAllSelectOpts($(this));
})
.on('focusout', function(){
$(this).attr('size', '1');
});
Also note that I added a var for selectLength in showAllSelectOpts (although actually, you could just remove the variable entirely); without one, the code is falling prey to The Horror of Implicit Globals (that's a post on my anemic little blog). Be sure to declare your variables.
jQuery event listener callbacks set this as the HTMLElement that the event was fired on.
In your callback you are expecting a jQuery object, but you have the HTMLElement.
You can pass the HTMLElement to a jQuery constructor and pass it into the showAllSelectOpts function
$('select').on('focus',function(){
showAllSelectOpts($(this));
})
Try this one -
$('select').on('focus',function() {
showAllSelectOpts($(this)); })
Try this:
var myselect = $('select');
$('select').on('focus',function(){
showAllSelectOpts(myselect);
})
A better way could be:
$('select').on('focus',function(event){
showAllSelectOpts($(event.target));
})
Why your code not working?
$('select').on('focus',function(){
//Here `this` is bound with the dom html element, not the $('select') object.
showAllSelectOpts(this);
})
These previous answers fix it. I'd just add here to create it as an extension since $(this) refers to a prototype of one method call.
$.fn.showAllSelectOpts=function() {
$(this).on('focus',()=>{
$(this)
.css('height','auto')
.attr('size',$(this).children().length)
.focusout(()=>{
$(this).attr('size','1');
});
});
};
$('select').showAllSelectOpts();
I want to assign a function to a custom attribute of a DOM-element. Using jQuery.
.prop(String, function) will not assign the function to the specified property, but will invoke the function and assign its result.
I have an ugly solution:
$("#a").prop(
"customAttr",
function() {
return function() {
$("#a").text("B");
};
}
);
http://jsfiddle.net/rapik/fyn6zh85/
Is there any better way to do it (using jQuery)?
I'm guessing that the reason you're trying to associate this function with these objects is so that you can cause the function to be invoked when something specific happens in the application. A better way to do this is to use events.
// set up the event handler
$("#a").on('somecustomevent', function() { $(this).text("B"); });
// Then, where you want that function to be invoked, trigger it.
$("#a").trigger('somecustomevent');
I have created a javascript file that contains the following:
(function ($) {
//Define a Drupal behaviour with a custom name
Drupal.behaviors.jarrowDynamicTextfieldValidator = {
attach: function (context) {
//Add an eventlistener to the document reacting on the
//'clientsideValidationAddCustomRules' event.
$(document).bind('clientsideValidationAddCustomRules', function(event){
//Add your custom method with the 'addMethod' function of jQuery.validator
//http://docs.jquery.com/Plugins/Validation/Validator/addMethod#namemethodmessage
jQuery.validator.addMethod("typeValidator", function(value, element, param) {
...bunch of code here...
}, jQuery.format('Field can not be empty'));
});
}
};
})(jQuery);
What I would like to do is add an change listener to a select box so that when the selection changes it would call this validation function. I am not sure if I can do this since the validation code is buried within several functions. Is this possible?
the way your original code is showing it, no, you wouldn't be able to call any of those functions because they're anonymous and are within the scope of the parent functions.
If you were to declare a variable for the function outside of the function that calls it, then you'd be able to reuse the function, because it will be global to the scope of the other function. Note: if you wanted the variable to be completely global, or rather, have it be accessible no matter where you are in the code, just don't write the var in front of the variable, it will then be "global", which is actually the equivalent of putting the variable within the window namespace.
Here's an example of that, using your code:
(function ($) {
var customCallback = function(event){
//Add your custom method with the 'addMethod' function of jQuery.validator
//http://docs.jquery.com/Plugins/Validation/Validator/addMethod#namemethodmessage
jQuery.validator.addMethod("typeValidator", function(value, element, param) {
...bunch of code here...
}, jQuery.format('Field can not be empty'));
};
//Define a Drupal behaviour with a custom name
Drupal.behaviors.jarrowDynamicTextfieldValidator = {
attach: function (context) {
//Add an eventlistener to the document reacting on the
//'clientsideValidationAddCustomRules' event.
$(document).bind('clientsideValidationAddCustomRules', customCallback);
}
};
//now you can use that function again...
$('#something').on('someEvent', customCallback );
})(jQuery);
Please note that you'll have to make some adjustments to that function to make sure all of your variables are available and things like that due to variable scope. So, this may need some tweaking to make it work for your scenario.
Normally you wouldn't be able to call that anonymous function without modifying the code a little, however that seems to be the way of registering custom validation rules for the jQuery Validation Plugin and once registered, you can definitely use that custom rule through the plugin's API.
For instance, the following code adds a custom rule:
jQuery.validator.addMethod("typeValidator", function(value, element, param) {
...bunch of code here...
}, jQuery.format('Field can not be empty'));
Now you can initialize the plugin on your form and call the valid function to validate the form.
$('#someForm').validate({
rules: {
someField: {
typeValidator: true //use the custom validation rule
}
}
});
Now you can check if the form is valid using $('#someForm').valid().
Have a look at the plugin's API for more infos.
I wonder if somebody could please help me understand something that seems odd with JS?
The below code works. The function inlineEditEvent.init() is called, and then t.copy() is called correctly (where var t = this;).
However, if I was to replace that with this.copy(), I get the error this.copy is not a function.
What's the difference here? Why does the below work, but not the way as described in the last paragraph? Thanks.
jQuery(function($){
$(document).ready(function(){inlineEditEvent.init();});
inlineEditEvent = {
init : function(){
var t = this;
/** Copy the row on click */
$('#the-list').on('click', '.row-actions a.single-copy', function(){
return t.copy();
});
}, // init
copy : function(){
// Do stuff here
}
} // inlineEditEvent
});
You're setting t as a context variable of this (of your init function). Once inside your click handler, this is now referring to the click handler, no longer the init function. Therefore, this.copy() is not a function.
this refers to this within the functions scope. That's why you need to set a self variable, so it's accessible within the scope of the function. Considering you're using jQuery, you could use $.proxy:
$.proxy(function(){
return this.copy();
},this)
t.copy(); appears in a different function to var t = this;. The value of this changes inside each function.
When you say var t= this; it refers to what this meant in that context. Later on when you are trying to refer to this, it is referring to a.single-copy instead since that is the new context it is in.
Let's say I have a jquery plugin that has an onSelect attribute. The user sets it to a function, and when that function is called, this refers to the object the plugin is applied to. All is good.
If I want to write a plugin that wraps this plugin, in order to inject some code into the onSelect, I do something like this:
// Get whatever the user put in
var extOnSelect = options['onSelect'];
// delete the onSelect attribute
delete options['onSelect'];
// re-add onSelect as an anonymous function that calls my method and the user's
var options = $.extend({
'onSelect': function() { onSelect(); extOnSelect(); }
}, options);
// call the plugin that I am wrapping / injecting extra onSelect code into
$(this).externalPlugin(options);
Then it will pass in my own onSelect code, while preserving what the user entered.
The only problem is, within each of those two functions this no longer refers to the object, it now refers to I think the generic inline function.
What's the best solution to fix this?
Use apply and the arguments object:
extOnSelect.apply(this, arguments);
to call extOnSelect exactly like the current function.
You could use call, but then you would need to pass the event object (and other possibe arguments) explicitly.
I think you need to use call method of javascript functions.
var options = $.extend({
'onSelect': function() { onSelect.call(this); extOnSelect.call(this); }
}, options);