Let's start with the fiddle: http://jsfiddle.net/Gytrn/
Here I am mixing angular and jquery like a bad person, I know, but the underlying question is this:
How can I more elegantly execute the javascript to fade in the paragraph once all the inputs are filled in?
Currently the code is as such:
$('input').focusout(function(){
var allInput = $('input')
var inArr = []
for (var i = 0; i < allInput.length; i++) {
inArr.push($('input:eq('+i+')').val().length)
}
console.log(inArr);
if(inArr.sort()[0]===0){
} else {
$('p').fadeIn(750)
}
});
It feels very heavy handed and I would like to know a better way. Feel free to ignore the fact that I'm using Angular and that there is an Angular way to do this. I would like to know a vanilla js or js and jquery solution to this problem that is more elegant.
Proposed improvements:
1) Inputs cached once, not every time your handler fires
2) focusout handler returns when first empty field found
3) Quick native check of input for emptiness
$(function () {
var allInput = $('input');
$('input').focusout(function () {
for (var i = 0; i < allInput.length; i++) {
if (allInput[i].value.length === 0) {
return;
}
}
$('p').fadeIn(750);
});
});
JSFiddle
There are a bunch of ways to do it
var inputs = $("input");
inputs.on("change", function () {
var allFilled = true;
inputs.each(
function(){
if(this.value.length===0){
allFilled = false;
return false; //break loop
}
}
);
$("#myParagraph").toggle(allFilled);
});
Related
I'm making a table that calls the following method when the value is changed, but the update method dies part through if the variable stuntSet is set to "all"
When I call updateStunts, if stuntSet is set to "all" it never gets out of the for loop. When it's set to anything else it seems to work fine and moves on to call countStuntRefresh(). The strange part is that it completes all the code inside the if statement that checks if stuntSet ==="all" but it never reaches the call for countStuntRefresh();
I've been going through this for an hour and I can't find my mistake. I apologize if it's a simple mistake and I appreciate whatever help you can give.
http://jsbin.com/nicoruvamula/1/
is the link to the full code
var selected = false;
var updateStunts = function() {
for (var i = 0; i < character.stunts.length; i++) {
if (stuntSet === "all") {
selected = document.getElementById("select" + character.stunts[i].name).checked;
character.stunts[i].chosen = selected;
} else if( stuntSet === character.stunts[i].category) {
selected = document.getElementById("select" + character.stunts[i].name).checked;
character.stunts[i].chosen = selected;
}
}
countStuntRefresh();
};
var countStuntRefresh = function() {
character.spentRefresh = 0;
for(var i = 0; i <character.stunts.length; i++){
if (character.stunts[i].chosen) {
character.spentRefresh += character.stunts[i].cost;
}
document.getElementById("stunttest").innerHTML = "Spent Refresh:" + character.spentRefresh;
}
};
When I run the jsbin code, there are several exceptions because document.getElementById("select" + character.stunts[i].name) returns null.
Looking through the code, I noticed that you don't wait for the DOM-ready event. As you already including jQuery, have you tried wrapping your code in a
$(function() { /* your code*/ });
(or will jsbin automagically call your code in onload or DOMReady? not familiar with jsbin...)
Last week a made a function for ellipsing the text inside some selector.
I was calling the function like this:
ellipsiText('.class',50) passing the selector and the max length of the text that i wanted to. This works fine, but im trying to make it a plugin, to call like this: $('.class').ellipsiText(50).
So, i was reading the tutorial in jquery website, and i understood how to do it. But i think i'm having an issue with the "this" seletor. Here is my original function:
function ellipsiText(selector,maxLength){
var array = $(selector).map(function(){
return $(this).text();
}).get();
var i;
var teste = [];
for (i=0;i<array.length;i++){
if (array[i].length > maxLength){
teste.push(array[i].substr(0,maxLength) + "...");
} else {
teste.push(array[i]);
}
}
for (var i=0;i<teste.length;i++){
$(selector).each(function(i){
$(this).text(teste[i]);
});
}
}
and here is my tentative of making a jquery plugin:
(function ($) {
$.fn.ellipsiText = function(length){
var array = $(this).map(function(){
return $(this).text();
}).get();
var i;
var teste = [];
for (i = 0; i < array.length; i++){
if (array[i] > length){
teste.push(array[i].substr(0,length) + "...");
} else {
teste.push(array[i]);
}
}
$(this).each(function(i){
$(this).text(teste[i]);
});
};
}(jQuery));
What am i doing wrong?
Well first thing is not a problem, but instead of $(this) in the first function scope, you can use this.map/this.each.
The problem is, in the second code you do
if (array[i] > length)
instead of
if (array[i].length > length)
Nothing to do with the jQuery plugin!
http://jsfiddle.net/UY88r/
This is untested, but the basic structure is something like this. Also you have so much looping in your code when one loop is needed.
$.fn.ellipsiText= function(options) {
var settings = $.extend({ //nice way to give to give defaults
length : 50,
ellipsi : "..."
}, options );
return this.each(function() { //the return is needed for chaining
var elem = $(this);
var txt = elem.text();
if (txt.length>settings.length) {
elem.text(txt.substr(0,settings.length) + settings.ellipsi );
}
});
};
and call it
$( "div.defaults" ).ellipsiText();
$( "div.foo" ).ellipsiText({
length : 10
});
$( "div.more" ).ellipsiText({
length : 10,
ellipsi : "<more>"
});
You already have a working function, just use it.
$.ellipsiText = ellipsiText;
$.fn.ellipsiText = function (count) {
ellipsiText(this, count);
}
now you can use it like any of the following:
ellipsiText('.class',50);
$.ellipsiText('.class',50);
$('.class').ellipsiText(50);
There's no sense in rewriting the function you already have working when you can just use it.
I'm trying to make a code that will search for a specific text, and if it is found it will click a button. It needs to check for the string continuously, however I am struggling to find a way for that to happen. I'm a complete newb to coding, so any help is appreciated! :)
var findMe = [
//Test
'Hello!',
];
function findText() {
var text = document.querySelector('div[id=BtnText]');
for (var i = 0; i < findMe.length; i++) {
if (BtnText.match(findMe[i])) {
var btnDo = document.querySelector('input[type="submit"][value="Click!"]');
if (btnDo) {
btnDo.click();
}
}
}
}
Just editing your code a little bit.
I am assuming you have HTML like this?
<div id="BtnText">Hello!</div><input type="submit" value="Click!">
You will to change your code to this
var findMe = [
//Test
'Hello!',
];
function findText() {
var div = document.querySelector('div[id=BtnText]');
for (var i = 0; i < findMe.length; i++) {
if (div.innerText.indexOf(findMe[i]) !== -1) {
var btnDo = document.querySelector('input[type="submit"][value="Click!"]');
if (btnDo) {
if (typeof btnDo.onclick == "function") {
btnDo.onclick.apply(elem);
}
}
return true;
}
}
return false;
}
If you want to check continuously. I recommend using setInterval.
var interval = setInterval(function() {
var textFound = findText();
if(textFound) {
clearInterval(interval);
}
},50);
Regular expression:
(new RegExp('word')).test(str)
(new RegExp(/word/)).test(str)
indexOf:
str.indexOf('word') !== -1
search()
searches a string for a specified value, or regular expression, and returns the position of the match.
var n=str.search("word");
or
var n-str.search(/word/);
if(n>0)
{}
with window.find()
if (window.find("word", true)){}
//code
while(window.find("word",true){
//code
}
Why do you need to perform the check continously?
You should get another approach... Or your script will be blocked by Chrome, for example, if it makes the page non responsible. You can go for a timeout, as Taylor Hakes suggested... Or just call your findText function attached to the onChange event on the div.
I have a simple if statement as such:
if ($('html').hasClass('m320')) {
// do stuff
}
This works as expected. However, I want to add more classes to the if statement to check if any of the classes are present in the <html> tag. I need it so it's not all of them but just the presence of at least one class but it can be more.
My use case is that I have classes (e.g. m320, m768) added for various viewport widths so I only want to execute certain Jquery if it's a specific width (class).
Here is what i have tried so far:
1.
if ($('html').hasClass('m320', 'm768')) {
// do stuff
}
2.
if ($('html').hasClass('m320')) || ($('html').hasClass('m768')) {
// do stuff
}
3.
if ($('html').hasClass(['m320', 'm768'])) {
// do stuff
}
None of these seem to work though. Not sure what I am doing wrong but most likely my syntax or structure.
You could use is() instead of hasClass():
if ($('html').is('.m320, .m768')) { ... }
You just had some messed up parentheses in your 2nd attempt.
var $html = $("html");
if ($html.hasClass('m320') || $html.hasClass('m768')) {
// do stuff
}
For fun, I wrote a little jQuery add-on method that will check for any one of multiple class names:
$.fn.hasAnyClass = function() {
for (var i = 0; i < arguments.length; i++) {
if (this.hasClass(arguments[i])) {
return true;
}
}
return false;
}
Then, in your example, you could use this:
if ($('html').hasAnyClass('m320', 'm768')) {
// do stuff
}
You can pass as many class names as you want.
Here's an enhanced version that also lets you pass multiple class names separated by a space:
$.fn.hasAnyClass = function() {
for (var i = 0; i < arguments.length; i++) {
var classes = arguments[i].split(" ");
for (var j = 0; j < classes.length; j++) {
if (this.hasClass(classes[j])) {
return true;
}
}
}
return false;
}
if ($('html').hasAnyClass('m320 m768')) {
// do stuff
}
Working demo: http://jsfiddle.net/jfriend00/uvtSA/
This may be another solution:
if ($('html').attr('class').match(/m320|m768/)) {
// do stuff
}
according to jsperf.com it's quite fast, too.
For anyone wondering about some of the different performance aspects with all of these different options, I've created a jsperf case here: jsperf
In short, using element.hasClass('class') is the fastest.
Next best bet is using elem.hasClass('classA') || elem.hasClass('classB'). A note on this one: order matters! If the class 'classA' is more likely to be found, list it first! OR condition statements return as soon as one of them is met.
The worst performance by far was using element.is('.class').
Also listed in the jsperf is CyberMonk's function, and Kolja's solution.
Here is a slight variation on answer offered by jfriend00:
$.fn.hasAnyClass = function() {
var classes = arguments[0].split(" ");
for (var i = 0; i < classes.length; i++) {
if (this.hasClass(classes[i])) {
return true;
}
}
return false;
}
Allows use of same syntax as .addClass() and .removeClass(). e.g., .hasAnyClass('m320 m768')
Needs bulletproofing, of course, as it assumes at least one argument.
var classes = $('html')[0].className;
if (classes.indexOf('m320') != -1 || classes.indexOf('m768') != -1) {
//do something
}
The hasClass method will accept an array of class names as an argument, you can do something like this:
$(document).ready(function() {
function filterFilesList() {
var rows = $('.file-row');
var checked = $("#filterControls :checkbox:checked");
if (checked.length) {
var criteriaCollection = [];
checked.each(function() {
criteriaCollection.push($(this).val());
});
rows.each(function() {
var row = $(this);
var rowMatch = row.hasClass(criteriaCollection);
if (rowMatch) {
row.show();
} else {
row.hide(200);
}
});
} else {
rows.each(function() {
$(this).show();
});
}
}
$("#filterControls :checkbox").click(filterFilesList);
filterFilesList();
});
This is in case you need both classes present. For either or logic just use ||
$('el').hasClass('first-class') || $('el').hasClass('second-class')
Feel free to optimize as needed
Try this:
if ($('html').hasClass('class1 class2')) {
// do stuff
}
I have a set of complex setTimeout() calls that trigger some jQuery animations.
I would like to be able to clear them all without knowing their various refs.
This code will not work - but should illustrate what I'm trying to do...
window.ref = [];
function doAnimation(i) {
$('div').each(function(index) {
window.ref.push(setTimeout('foo(index,i)',index*1000));
window.ref.push(setTimeout('bar(index,i)',index*2000));
});
}
Then clear them with
clearTimeout(window.ref);
I know this already has an accepted answer, but just because those timeout ids are worthless once you have cleared them, I would have cleared them by saying:
if (window.ref) while(window.ref.length > 0) clearTimeout(window.ref.pop());
thats not correct you should do like this:
window.ref = [];
function doAnimation(i) {
$('div').each(function(index) {
window.ref.push(setTimeout('foo(index,i)',index*1000));
window.ref.push(setTimeout('bar(index,i)',index*2000));
});
}
and then clear like :
for(var i=0;i<window.ref.length;i++){
clearTimeout(window.ref[i]);
}
if (window.ref && window.ref.length > 0) for (var i in window.ref) {
clearTimeout(window.ref[i]);
}
Or do it the jQuery way:
$.each(window.ref, function (index, value) { clearTimeout(value); });