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
Related
I've been looking all over the web for how to do this. I am trying to make Jquerys .html() function in vanilla JavaScript. I want to recreate so I can understand it better. I've tried the following but nothing seems to work, I just don't understand what I am doing wrong.
let $ = function(ele) {
if (ele.charAt(0) == '.' || ele.charAt(0) == '#') {
let newEle = cut(ele,0);
if (ele.charAt(0) == '#')
get(newEle);
else
return document.getElementsByClassName(newEle);
} else
return document.getElementById(ele);
}
$.prototype.html = function(html) {
this.innerHTML = html;
}
$('test').html('hey');
$('.hey')[0].html('hey');
function cut(string,num) {
let a = string.slice(0,num);
let b = string.slice(num + 1,string.length);
return a + b;
}
It doesn't work, the console log reports this error:
Uncaught TypeError: $(...).html is not a function
Please help and thanks in advance.
The problem here is what you are returning from the $ function.
Think about this: document.getElementsByClassName and document.getElementById return dom elements and dom elements don't have a .html function. That is why you are getting the error.
What you need is to return is an object, a wrapper, with a .html function, and a closure over the dom elements that you want to modify.
Because you're returning an object from $, you're overriding the default behavior of new $; instead of resulting in the newly-created object, it results in the object you returned out of $.
Instead, you'd want to remember the results of those getElementsByClassName/getElementById calls in an array or Set you store on this (the newly-created object), and then use that array or Set within html (since you want to loop over all matching elements in the case where you're setting the new HTML).
Side note: Since you're using ES2015+ features anyway (let), you might want to use the simpler class syntax instead of a separate function declaration and assigning to $.prototype:
class $ {
constructor(ele) {
// ...
}
html(html) {
// ..
}
}
I have the follwoing:
HB.formButtons.deactivatingButton = function(inputs) {
inputs.forEach(function(argument){
argument.parent().removeClass(HB.formButtons.SUBMIT_BUTTON_STYLE);
});
}
which I than call in various parts like so:
HB.formButtons.deactivatingButton($(HB.personalDetails.SUBMIT_PERSONAL_DETAILS_SELECTOR), $(HB.personalDetails.CANCEL_PERSONAL_DETAILS_SELECTOR));
The console. throws the following error:
Uncaught TypeError: formsInput.forEach is not a function
Why?
Considering your input to be HTMLCollection, the forEach doesn't work on a collection. forEach works on Array
You can, however, make it work like
HB.formButtons.deactivatingButton = function(inputs) {
[].forEach.call(inputs, function(argument){
argument.parent().removeClass(HB.formButtons.SUBMIT_BUTTON_STYLE);
});
}
If you wanted to pass your function array of two elements you have to use square brackets [].
HB.formButtons.deactivatingButton(
[
$(HB.personalDetails.SUBMIT_PERSONAL_DETAILS_SELECTOR),
$(HB.personalDetails.CANCEL_PERSONAL_DETAILS_SELECTOR)
]);
alternative you can use the special variable arguments in your function. Described at https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments
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.
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);
});
In this very contrived example, I have an array with 3 elements that I'm looping over using the .each() method.
var vals = $w('foo bar baz');
vals.each( function(val) {
alert(val);
if( val == 'bar' ) {
//This exits function(val)
//but still continues with the .each()
return;
}
});
I can easily return out of the function being called by .each() if I need to.
My question is, how can I break out of the .each() loop from inside the function that .each() is calling?
if( val == 'bar' ) {
throw $break;
}
It's documented at the same page you linked. It's an exception specially handled by the each function. When thrown, it prevents your function from being called on further elements.
Your are correct, and Prototype has created an object ($break) that can be thrown from the each-function to enable this functionality. According to the Prototype API docs:
Regular loops can be short-circuited in JavaScript using the break and continue statements. However, when using iterator functions, your code is outside of the loop scope: the looping code happens behind the scene.
In order to provide you with equivalent (albeit less optimal) functionality, Prototype provides two global exception objects, $break and $continue. Throwing these is equivalent to using the corresponding native statement in a vanilla loop. These exceptions are properly caught internally by the each method.
Also, note that the $continue object has been deprecated, and to simulate a continue-statement, use a vanilla return statement instead.
Code example:
var result = [];
$R(1,10).each(function(n) {
if (0 == n % 2)
return; // this equals continue
if (n > 6)
throw $break;
result.push(n);
});
// result -> [1, 3, 5]
You can read more about the each-function here: http://www.prototypejs.org/api/enumerable/each
Based on the documentation for .each() that you linked to, you should use a throw $break; statement, this should cause further iterations to cease.
Simply returning will cause the iterator to continue to the next one.
From that page you linked to, isn't the correct way
if(val == 'bar')
{
throw $break;
}
?