jQuery equivalent for attaching a handler - javascript

What is the equivalent code in jQuery for the below JavaScript function?
function attachSomeHandler(in) {
for(var i = 0; i < in.length; i++) {
if(in[i].type == 'submit')
in[i].attachEvent("onclick", someFunc);
}
}

Assuming the argument in is an array of DOM elements and you already have that array and you want to reproduce the exact same function attachSomeHandler(), you could do this using jQuery:
function attachSomeHandler(in) {
$(in).filter('[type="submit"]').click(someFunc);
}
If you want to back up to a higher level in your code, you can create a single jQuery selector that would get the original array of DOM elements that was already filtered to only have ones with the appropriate type.

Related

Why is .every() not a function?

I've gathered an Array (I think) of required form elements, and have added 'blur' listener.
var formInputs = $(':input').filter('[required]');
formInputs.each(function(i) {
$(this).on('blur', function() { // Each time we leave a 'required' field, check to see if we can activate the 'submit' button.
submitEnabler(formInputs);
});
});
So, once someone has left one of these fields, I want to run through this array using .every() and check if the fields are valid - that is if they have a 'success' class that I have defined.
function isValid(input) {
return input.hasClass('is_glowing_success');
}
function submitEnabler(inputs) {
console.log(inputs.every(isValid));
}
I keep getting back:
Uncaught TypeError: inputs.every is not a function
at submitEnabler
Now, I could do something like this...
for (var i = 0; i < inputs.length; i++) {
if ($(inputs[i]).hasClass('is_glowing_success')) {
console.log('yes');
} else {
console.log('no');
}
}
But, why can't I just use: Array.Prototype.every() ?
Because jQuery objects have no every method, and formInputs is a jQuery object.
If you want an array instead, call get() to get one.
I've gathered an Array (I think) of required form elements...
No, it's just jQuery object. jQuery objects are very array-like, but they aren't arrays. Worse, they have some array-like methods (such as filter and map) that call their callbacks with different arguments than the equivalent Array.prototype methods.
In isValid, you'd need to handle the fact you're now dealing with a raw DOM element, which means either wrapping it with a jQuery object and using hasClass:
function isValid(input) {
return $(input).hasClass('is_glowing_success');
}
or using the DOM's classList:
function isValid(input) {
return input.classList.contains('is_glowing_success');
}
That latter works on all modern browsers, but not all older ones. However, it can be polyfilled on older browsers. More about that on MDN.
jQuery does not have a .every() method. .every is defined at Array.prototype.
You can use .toArray() to convert jQuery object to an Array, within .every() callback function pass current DOM element to jQuery() to get jQuery object representation of element where .hasClass() can be chained.
function submitEnabler(inputs) {
console.log(inputs.toArray().every(isValid));
}
function isValid(input) {
return $(input).hasClass('is_glowing_success');
}
I will suggest you use array.map()
for example where input is the array
input.map(function(input){
return $(input).hasClass('is_glowing_success');
});
this is just an example read more here

Click object by classname

I am trying document.getElementsByClassName('classname').click();, but it doesn't fire the click on the class. Why is that?
Why is that?
Because the getElementsByClassName method returns an array of DOM elements. And calling a click method on an array hardly makes sense. If you want to call this click method you could do that on some particular element of the array. For example if you wanted to call it on the first element (assuming the array is not empty of course):
document.getElementsByClassName('classname')[0].click();
But since you have tagged your question with jQuery you probably just wanted to write:
$('.classname').click();
document.getElementsByClassName('classname') returns an array of DOM nodes.
Try:
var nodes = document.getElementsByClassName('classname');
for(var i = 0; i < nodes.length; i++) {
nodes[i].click();
}
Also remember that getElementsByClassName is not supported by every browser.
try this:
$(function() {
$('.classname').click();
});
Your code will work with
document.getElementsByClassName('classname')[0].click();
But, if you use jquery then
$(document).ready( function(){
$('.classname').on('click',function(event){});
});
OR simply $('.classname').click();
Because that will return a set of elements, which is usually an HTMLCollection. You have to then iterate through it:
https://developer.mozilla.org/en-US/docs/DOM/document.getElementsByClassName
Pure Javascript:
var elements = document.getElementsByClassName('xxx');
for(var i = 0; i < elements.length; i++)
{
elements[i].addEventListener('click',function(){window.alert('Class name is xxx');},false);
}
JQuery:
$(document).ready(function(){
$('.xxx').on('click',function(){window.alert('Class name is xxx');});
});

jquery name selector not working in ie6

var brands = document.getElementsByName("brand");
for(var brand in brands){
$("input[name='brand']").eq(brand).click(function(){
alert("hello22");
loadDataFN(1);
});
}
This code is not executing in ie6,
Any help would be appreciated.
The problem is likely that you are trying to use a for-in construct to iterate over a numeric array. This often won't give expected results. Use an incremental for loop instead:
var brands = document.getElementsByName("brand");
// Use an incremental for loop to iterate an array
for(var i=0; i<brands.length; i++){
$("input[name='brand']").eq(brands[i]).click(function(){
alert("hello22");
loadDataFN(1);
});
}
However,
after seeing the first part of your code, the loop appears unnecessary. You should only need the following, since you are assigning the same function to all brand inputs.
// These will return the same list of elements (as long as you don't have non-input elements named brand)
// though the jQuery version will return them as jQuery objects
// rather than plain DOM nodes
var brands = document.getElementsByName("brand");
$("input[name='brand']");
Therefore, the getElementsByName() and loop are not necessary.
$("input[name='brand']").click(function() {
alert("hello22");
loadDataFN(1);
});
for-in loops are used for iterating over the properties of an object, not over the elements of an array.
Why don't you write the code without jQuery if this doesn't work?
Something like this:
function getInputByName(name) {
var i, j = document.getElementsByTagName('input').length;
for(i=0;i<j;++i) { // You can also use getAttribute, but maybe it won't work in IE6
if(document.getElementsByTagName('input')[i].name === name) {
return document.getElementsByTagName('input')[i];
}
}
return null;
}
I don't know jQuery, but maybe you can do something like this:
$(getInputByName('brand')).eq(brand).click(function(){
alert("hello22");
loadDataFN(1);
});

Detect if jQuery plugin is applied to multiple elements?

I'm working on a jQuery plugin that can be applied to multiple elements. The plugin includes some animation effects and I need to manage the event queue based on if the plugin is used on multiple elements (instead of one).
What's the best way to detect if the plugin has been applied to a single element or to multiple elements?
Edit...
The length property works correctly if the plugin is passed multiple elements (such as $('.myClass').plugin()) but if the plugin is called on multiple, single elements (such as $('#myElem1').plugin() and $('#myElem2').plugin()) then the length returns one for each call.
Is there are a way to detect multiple instances when the plugin is used as in the second example/
this inside the plugin, depending on your style, refers to the jQuery object, so you can just check the .length property, for example:
jQuery.fn.plugin = function(options) {
if(this.length > 1) //being applied to multiple elements
};
For your edit: tracking the total may be a better option, for example:
(function($) {
$.pluginCount = 0;
$.fn.plugin = function(options) {
$.pluginCount += this.length; //add to total
if($.pluginCount > 1) //overall being applied to multiple elements
};
})(jQuery)
Assuming you apply your plugin by $('some selector').myPlugin(), the "this" keyword will refer to the jquery object you've called the plugin on inside your plugin function.
So, to summarize:
(function( $ ){
$.fn.myPlugin = function() {
if(this.size() > 1) {
//code for multiple elements
}
else if(this.size() == 1) {
//code for 1 element
}
}
})( jQuery );
$('div.to-pluginize').myPlugin();
If you want a generic way to test whether or not a plugin has been applied to a arbitrary set of elements, here is one approach:
// say we want to apply this to a bunch of elements
​​$.fn.test = function(str) {
this.each(function() {
// set a boolean data property for each element to which the plugin is applied
$(this).data('test', true);
alert(str);
});
};
// use a simple plugin to extract the count of a specified plugin
// from a set of elements
$.fn.pluginApplied = function(pluginName) {
var count = 0;
this.each(function() {
if($(this).data(pluginName)) {
count++;
}
});
return count;
};
with this markup:
Hello
<br />
Hello
Here is a test:
$("a").test('test');
alert($("*").pluginApplied('test'));​​​​​​​​​​​​​​​​ // alerts '2'
Demo: http://jsfiddle.net/B5QVC/

Refer to a html List item object properly in javascript for Event Registration

I would like to know how I can refer to a list item object if I had for example the following html list
<div id="subdiv_2">
<div id="subdiv_3">
<ul>
<li>Item1</li>
<li>Item2</li>
<li>Item3</li>
</ul>
</div>
</div>
How is it possible to register an onclick to the Item2 li without it having to have a unique elementId
eg I can do so for subdiv_3 because it has a unique ID and isn't in the list by
document.getElementById('subdiv_3').addEventListener('click', function();, false);
My goal is ultimately to assign a function to each list object, for the number of list objects with unique parameters based upon the list object number eg:
for(i=0;i<list.length;i++){
"document.getElementById(list.item"+i+").addEventListener(\'click\',function("+i+");,false);";
}
You could get all the children elements of subdiv_3 that are <li>. Then iterate through that loop adding the functions as you go.
div = document.getElementById('subdiv_3');
els = div.getElementsByTagName('li');
for (var i=0, len=els.length; i<len; i++) {
alert(i); // add your functions here
}
Looking at your code sample, when you're in the loop creating your functions you may run into closure scoping problems. (All the functions will appear to use the same value of i.) Check out my answer to this question to deal with that problem: How to Add Event Handler with Arguments to an Array of Elements in Javascript?
#Supernovah: You can actually assign a real function to setTimeot(). That rids you of the string formatting, which will stand in your way when you want to do more complex things than just setting one property.
This is the code:
function attachToList() {
var div = document.getElementById('menu2');
var els = div.getElementsByTagName('li');
// create a closure returning an anonymous inner function
var fn = function(li) {
return function() {
li.style.backgroundColor = "#FFFFCC";
};
};
for (var i=0, len=els.length; i<len; i++) {
// create function instance suitable for current iteration
var changeLi = fn(els[i]);
// pass function reference to setTimeout()
setTimeout(changeLi, 250*i);
}
}
And a short explanation:
Using a closure is the trick that makes sure when setTimeout() triggers, all variables still have the expected values.
You do this by writing a function that returns a function. The outer function takes parameters, the inner function does not. But it refers to the parameters of the outer function. In the loop, you call the outer function (with correct parameters) and get a whole new inner function every time, each which has it's own version of the parameter values. This is the one you assign to setTimeout().
In reponse to the comment on Benry's Answer By Benry, After using his code, the following proves that each elementLi can be referred to with els[i]
function attachToList(){
div = document.getElementById('menu2');
els = div.getElementsByTagName('li');
for (var i=0, len=els.length; i<len; i++) {
setTimeout('els['+i+'].style.backgroundColor=\"#FFFFCC\";',(250*i));
}
}

Categories