insert random numbers into a class - javascript

If I do this:
$('.classname').html(Math.floor(Math.random()*10)+1);
All of "classname" is filled with the same number.
Is it possible to fill every instance of "classname" with a different random number?
The only possible way I can think of solving this is to go through each instance of "class name" and apply a random number one by one.

.html()
$(".classname").html(function(idx, oldValue) {
return (Math.floor(Math.random()*10)+1);
});
fiddle

the html method has an "overload" that accepts a function. The function should return the value to set the inner html to. In your case you can do:
$(".classname").html(function() {
return (Math.floor(Math.random()*10)+1);
});
the function is actually called with two arguments. The first is the index of the element in the selection and the second is the current value of the elements inner html

You can use jQuery's .each() function to iterate over each element matching the selector you provide -
$.each('.classname',function(index,elem){
var newRandomNumber = (Math.random()*10)+1;
$(elem).html(Math.floor(newRandomNumber));
});
For every iteration of the each() function, you'll have the index of the element you are on and the element itself in the elem parameters.
http://api.jquery.com/jQuery.each/

try this
$('.classname').each(function(index) {
$(this).html(Math.floor(Math.random()*10)+1);
});

Yes. The easiest way to do so would be using the jQuery each function:
$('.classname').each(function() {
$(this).html(Math.floor(Math.random()*10)+1);
});

Related

Adding active class based on current URL

I am trying to add 'active' class on my link. It is saying
Uncaught TypeError: document.querySelectorAll(...).each is not a function
Here is my code:
const current = window.location.href;
document.querySelectorAll("#nav-tab a").each(function(){
const $this = this;
if($this.attr('href').indexOf(current) !== -1){
$this.classList.add("active");
}
});
Can you help me? Or is there a better way to add a class name based on the current URL?
Thank you so much!
You have a few issues with your code. Your mainly confusing jQuery methods with regular native browser methods/conventions:
You need to use .forEach() and not .each(). The .forEach() method is a method on the NodeList that querySelectorAll() returns.
.attr() is not a valid method. To get an element's attribute you can use .getAttribute(). We can use .href here instead to get the href. Note that getAttribute("href") will retrieve the URL as it is in your mark-up, whereas .href will retrieve the full, eg, if you had href="/foo/bar", .href will give https://example.com/foo/bar, whereas .getAttribute() will return just /foo/bar.
Use the element parameter of the function instead of this. When you use .forEach() you're iterating over the elements in your NodeList (ie: the elements you selected), so you can access each using the first parameter of the forEach callback. The this value in the browser (if not in strict mode) will default to window, so it won't be the element like you're expecting it to be:
const current = window.location.href;
document.querySelectorAll("#nav-tab a").forEach(function(elem){
if(elem.href.includes(current)){
elem.classList.add("active");
}
});
I've also changed .indexOf(...) !== -1 to .includes(), which is a more modern way to check if a string contains another value.
I will point out that you can make your query selector more advanced, which will limit the number of elements you iterate:
const current = window.location.href;
document.querySelectorAll(`#nav-tab a[href*="${current}"]`).forEach(elem => {
elem.classList.add("active");
});
This uses the attribute selector a[href*=...] to select the a elements that have a href that contains the text in stored in current.
I think that you are mistaken jQuery and vanilla javascript
$.each is a jQuery function in you case you can use .forEach
$.attr is a jQuery function in you case you can use .getAttribute
const current = "#test-3";//window.location.href;
document.querySelectorAll("#nav-tab a").forEach((elem) => {
if (elem.getAttribute('href').indexOf(current) !== -1) {
elem.classList.add("active");
}
});
.active { color:red}
<div id="nav-tab">
Test 1
Test 2
Test 3
Test 4
</div>

How to use indexOf() method on parameter?

I am using dragula.js, and using ondrop event in mycode,
drake.on('drop', function (el) {
console.log(el); //result <div>foo bar</div>
var n = typeof(el); //return object
var x = el.indexOf("test"); //error TypeError: el.indexOf is not a function(…)
// do another code
})
I want to check if "test" exist on el parameter, but error occur. thx.
I think it should be as easy as if ('test' in el)
Use the dom. Roughly: el.parentElement.children.indexOf(el)
Solved - https://github.com/bevacqua/dragula/issues/209
indexOf works on strings, so you need to call it using the element's text, rather than the element itself, like so:
el.textContent.indexOf("test");
Edit:
Looks like you want the index of the dragged element rather than matching its text:
[].slice.call(el.parentElement.children).indexOf(el)

for each element of a class, check the contents to see if it contains a string, and then update only that element if it does

Code version 1:
var one = "one";
$.each($(".Buttons"),(function() {
if ($("this:contains(one)")) {
$(this).addClass( "currentButton" );
};
}));
Code version 2:
var one = "one";
$(".Buttons").each(function(a, e) {
if ($("e:contains(one)"))
{ $(e).addClass( "currentButton" ); };
});
I think you see what I'm trying to do. My problem is only updating the specific element where the text is matched, but all elements are updated when only one matches.
Edit: HTML below:
<input type="submit" class="Buttons" value="one">
<input type="submit" class="Buttons" value="two">
<input type="submit" class="Buttons" value="one & two">
I am using inputs as they are programmatically added buttons using asp.net/c#
I have attempted a couple of solutions and I'm still having every element have the class added.
I updated this jsfiddle with inputs and now it's not being affected at all. I'm guessing :contains won't check input value.
Using my original method I fixed it as follows, or alternatively see the answer from Elias:
$(".Buttons").each(function() {
if ($(this).attr("value") == one) {
$(this).addClass("currentButton");
};
});
The easiest way to do what you're doing is a one-liner, though:
var one = "one";
$(".Buttons").filter(":contains('"+one+"')").addClass("currentButton");
//or
$(".Buttons").filter(":contains('one')").addClass("currentButton");
check fiddle
This does imply your :contains selector is a constant value, if you need it to change according to somethign else, wrap it in a function:
function changeClass(contains)
{
contains = contains || 'one';//default value
$('.Buttons').filter(":contains('"+contains+"')").addClass('currentButton');
}
Of course, as always, you can change everything to parameters so this function is more likely to be reusable:
function changeClass(selector, filter, newClass)
{
$(selector).filter(filter).addClass(newClass);
}
changeClass('.Buttons', ':contains("one")', 'currentButton');
Your problems were being caused by enclosing either this or e inside the string delimiters, which effectively turned them into string constants, not references to the DOM nodes you were trying to change
What happened is that both:
if ($("e:contains(one)"))
{
$(e).addClass( "currentButton" );
}
and
if ($("this:contains(one)"))
{
$(this).addClass( "currentButton" );
}
evaluated to :
if ([])
{
$(this).addClass('currentButton');
}
In other words: you were passing string constants to the main jQuery function ($()) which probably tried to make the bet of things, and likely treated them as selectors. Sadly, they came up empty, so an empty array-like jQuery object was returned, and any object/array is a truthy value in JS, so the expressions checked evalueted to true, hence, nodes classes were changed.
You could just as well have written:
if ($('foobar, see if it matters what I write here'))
{
console.log('It doesn\'t');
}
And it'll log It doesn't time and time again.
Edit
In response to your comment, if what you actually want is to filter, based on the elements' value attribute:
$('.Buttons').filter(function()
{//this function will be applied to each element returned by the $('.Buttons') selector
//only those for which this callback returns true will get the currentButton class
return /\bone\b/i.test($(this).val());
//or, equally valid:
return ($(this).val().indexOf('one') !== -1);
}).addClass('currentButton');
Note that /\bone\b/i will accept "ONe" as well as "One" or "one", but won't return true if the value attribute contains "bones", whereas indexOf is CaseSensitive, but doesn't check if one is part of a word or not.
for a case sensitive regex, you can use /\bone\b/, without the i.
A more strict, but lot shorter version of the same thing could be:
$('.Buttons[value~="'+one+'"]').addClass("currentButton");
But there are so many jQ selectors that you can use, best keep a reference close to your chest
DEMO
Using is():
var one = "one";
$(".Buttons").each(function () {
if ($(this).is(":contains('"+one+"')")) {
$(this).addClass("currentButton");
};
});
You can do this pretty simply without an each function. jQuery selectors will do the filtering for you, and then you update every element that matched the selector.
var text = "text to test for";
$(".Buttons:contains(" + text + ")").addclass("currentButton");
Here is a jsFiddle to demonstrate.
$("e:contains(one)") here one is being considered as a string literal.
try like, "e:contains('"+one+"')" now one will be evaluated to your string.
var one = "one";
$(".Buttons").filter(function () {
return $(":contains('"+one+"')",this);
}).addClass("currentButton");
or
var one = "one";
$(".Buttons").filter(function () {
return this.innerHTML == 'one'; // note: innerHTML may be deprecated soon, avoid it
}).addClass("currentButton");
jsFiddle demo

Basic jQuery function

Could someone please explain, why do we need each(function (i)
what does (i) do? seems like i could be any letters.
why (i) is necessary? I don't quite understand. Many Thanks
<body>
<div>Click here</div>
<div>to iterate through</div>
<div>these divs.</div>
<script>
$(document.body).click(function () {
$( "div" ).each(function (i) {
if ( this.style.color != "blue" ) {
this.style.color = "blue";
} else {
this.style.color = "";
}
});
});
</script>
The first parameter for the callback function is the index of the iteration in the loop. i.e. the loop counter. In your case you don't need it at all, as you are not using it:
$("div").each(function() {
if (this.style.color != "blue") {
this.style.color = "blue";
} else {
this.style.color = "";
}
});
The second parameter is the element for the current iteration, i.e. the same as this is referring to. You could use that parameter instead of this. Of course, to use the second parameter you have to specify the first parameter also, even if you don't use it:
$("div").each(function(i, e) {
if (e.style.color != "blue") {
e.style.color = "blue";
} else {
e.style.color = "";
}
});
That can be any name you want, it's the index of The item, in case that's useful in the function. It's explained in the jQuery documentation. http://api.jquery.com/each/
You can call i whatever you want in the callback function, the each method will call that callback for each object that matches your each selector (In your case all divs) and will pass it to your callback parameter (i) or whatever you call so you can manipulate each of those objects for each iteration.
Hope i made myself clear,
Cheers
Well, I don't know if this is what you are asking but according to documentation
.each( function(index, Element) )
That's the signature, so i in your case would be the argument for the index of current item. So if there 10 things in your div, every time the function is called it would pass the index i for i-th element in your div.
.each is used for iterating over the collection of elements it is applied to. The first parameter (i, in your example) provides the index value of the current element within the collection.
The full signature is:
.each( function(index, Element) )
while you are using the overload of:
.each( function(index) )
And it doesn't really matter how you name the parameter in your function specification (index, i, blah, param1, etc), the index value will be passed into that parameter.
In your example, this parameter value provides no additional benefit as it is not required by your use case, however, there are plenty of use cases where it is an essential parameter.
i,j,k are a standard notation for integers. It is naturally used for looping through enumerable lists (like arrays or nodelists) where each element index is an integer. For imbricated loops the first level will use i, the second j, etc.
This is just a convention and in practice you can use other names, for example "index" as shown in the jQuery documentation that makes your code more readable. The drawback is that it makes your script longer, but with today's widespread use of minification/compression this should not be a concern.
And of course if you don't reference the index within the loop you can just omit it.

jquery attr(name,value) method's value parameter

I'm reading Bibeault's jQuery in Action and I'm having troublel understanding the value parameter of the attr() method. The book says that the parameter can be a function whose parameters are index and previousValue. What is the purpose of these parameters? I don't understand the text's explanation.
Specifically I want to know:
Are these parameters mandatory?
What is an example of how these parameters are used?
Can I use other parameters within the function?
1) No parameters are mandatory in javascript. You use whatever amount you want. These parameters are available for you in your function.
2) examples:
Let's say you have this html:
Now, run this snippet:
$('a').attr('title', function(index, previousValue){
return previousValue + ' - An external link';
});
This will add the string " - An external link" to the end of every title.
Now, look at this:
$('a').attr('title', function(index, previousValue){
return previousValue + ' - Link number ' + index;
});
This will result in the following html:
As you can see, you can see, these parameters are very handy.
3) Not sure what you mean by using other parameters. Please clarify.
It seems that you are not familiar with Javascript's scope lookup chain. You do not have to explicitly pass parameters to a function. If they're defined in a scope above it, the function will have access to it:
var num1 = 23;
var num2 = 54;
$('a').attr('title', function(){
return num1 + num2;
});
It's actually pretty simple. The attr() function has three possible modes; the one you refer to takes a callback to get the value.
For example:
$('.someClass').attr('rel', function(index, value)
{
// index refers to the elements index of the set; so of all elements with the
// css class 'someClass', the index will refer to that position in the list.
// If three elements match, the callback will be invoked 3 times, with 0, 1, 2
// as the index when each element, respectively, is invoked.
// value refers to the current value of the attribute.
// Return the value you want to set.
return 'SomeRelValue';
});
The parameters are not mandatory; if you simply omit them from the callback signature, you simply dont have access to that information. You cannot pass other parameters to this method. You might want to use this function when you will match a lot of elements, and want to insert some data based on their ordinal position of the selector element.
For example:
$('.someElements').attr('rel', function(index, value)
{
return value + index;
});
For each element matching the selector, you set the rel attribute to what it was plus the index of the selector. So element one, if it had a rel of 'sampleRel', is set to 'sampleRel1', element two with rel' sampleRel' becomes 'sampleRel2', etc etc
There's a good example in jQuery's documentation, which I'll shorten here:
Here's the relevant HTML:
<div>Zero-th </div>
<div>First </div>
<div>Second </div>
If you then run this javascript it'll apply unique id's to each div:
$("div").attr("id", function (arr) {
return "div-id" + arr;
});
The $ function returns all of the div's so the arr argument allows you to specify the attribute value based on the index.
The function passed to attr also received a value specifying the old attribute value, but as this is javascript the function doesn't have to name that argument and it's still available in the arguments.
attr is a way to access attributes on an element. the overload which allows a function will allow you to use the function return to set the value (the index param to the function would be the index into the selection, previousValue being the value it had until now).
I've never used this overload myself, but assume it would be nice if you're making attribute values based on some sort of function.
They are not mandatory, passing different number of parameters gives different functionality:
attr('name') - gets the value of name
attr('name','value') - sets the value of name
attr('name',function(i,v){return v+i;}); - sets the value of name to the previous value + the index in the collection.
example:
lets say we have five spans with the class hiccup and name 'yup'.
$('span.hiccup').attr('name',function(i,v){return v + i;});
will give each span a name 'yup1' - 'yup5'.
Additionally, you have access to this inside the function, which refers to the element itself. Given this, you could probably do some really interesting stuff.
As always, jQuery has awesome documentation of all of this:
http://api.jquery.com/attr

Categories