$(d).attr("id") is undefined javascript - javascript

I have a variable d that I use like this:
$(function() {
for(i = 1; i <= 31; i++) {
var d = '#days' + i;
if ($(d).attr("id").substr(4,2) == 11) {
$(d).addClass("date_has_event");
//console.log("diez");
} else {
console.log("otro");
}
}
}
However I get the following error in firebug:
$(d).attr("id") is undefined
index.html (L23) (?)()()
jquery.min.js (L27) onreadystatechange()()
jquery.min.js (L27) onreadystatechange()()
jquery.min.js (L21) nodeName()([function(), function()], function(), undefined)
onreadystatechange()()
I really don't understand why. Does anyone know?
Edit
I'm sorry for the poor explanation I had to run, here's what's going on a little bit more detailed. I am generating a calendar using javascript. each td has a different id (hence the #days + i) and I am running it from 1 to 31 so I can cover the longer months. However I am getting the error I mentioned above. I am also using the jQuery library to enable me to select more easily (i.e. instead of getElementById just #days)

Why not just check if i == 11, then do your processing on it? It would still only fire on $('#days11'). Edit: If you need to make sure the element exists as well, just slap that into the conditional.
$(function(){
for(i = 1; i <= 31; i++){
var d = '#days' + i;
// if($(d) && i == 11){
if(i == 11){
$(d).addClass("date_has_event");
//console.log("diez");
}else{
console.log("otro");
}
}
}

Ok, new answer. the way you are doing this is not very "jqueryish". lets step back a bit. from what I can tell you have an html structure something like:
<div id="days1"></div>
<div id="days2"></div>
...
You are then running this against every item with a days(num) id? A better solution is this, if you want to add a class to every element with a date in it, first apply a class:
<div class="days"></div>
<div class="days"></div>
Your code can then be
$(function(){
$(".days").each(function(i){
if($(this).substr(4,2) == 11){
$(this).addClass("date_has_event");
}
});
});

Since you are selecting by id, this is redundant:
if ($(d).attr("id").substr(4,2) == 11)
because the ID attribute of d is d.
Is most simple to do:
if (i == 11)

Missing the closing bracket?
$(function() {
for(i = 1; i <= 31; i++) {
var d = '#days' + i;
if (i == 11) {
$(d).addClass("date_has_event");
//console.log("diez");
} else {
console.log("otro");
}
}
// shouldn't the next line be });
}

Related

Javascript - add css style to element with class

I want to add only one css style in JS. I don't want to include jQuery for only one thing.
My code:
document.addEventListener('DOMContentLoaded', function() {
if (navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1) {
var productAttr = document.getElementsByClassName('product-attributes');
productAttr.style.top = "-90px";
}
});
The error from console is:
TypeError: 'undefined' is not an object (evaluating 'productAttr.style.top = "-90px"')
If I want change other styles f.e. opacity or color, I get the same problem.
How can I fix this ?
Thanks in advance for help.
You need to loop through your results because getElementsByClassName() returns a collection of elements:
for(var i = 0; i < productAttr.length; i++)
{
productAttr[i].style.top = "-90px";
}
Maybe it's because you can not give negative values in CSS
top:"-90px" === bottom "90px"
Maybe now it would work
document.addEventListener('DOMContentLoaded', function() {
if (navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1) {
var productAttr = document.getElementsByClassName('product-attributes');
productAttr.style.bottom = "90px";
}
});
It's preferred to have an id assigned to the targeted element then target using getElementById() as there cannot be elements with the same id, hence getElementByClassName() will return an array if there are multiple elements with the same className. If you need to target multiple elements, you should for-loop through them while applying the change to the nth item being looped:
for(x = 0; x < array.length; x++){
array[x].style.top = '-90px';
}
Gentle reminder: also remember to have position: relative|absolute|fixed to ensure 'top' attribute works
edited with thanks to Sebastien Daniel
When selecting a class you have to indicate what number is as an Tag, it is not like the id that there is only one.
It would be something like this code depending on which of the classes you want to apply it:
document.addEventListener('DOMContentLoaded', function() {
if (navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Chrome') == -1) {
var productAttr = document.getElementsByClassName('product-attributes');
productAttr[0].style.top = "-90px";
productAttr[1].style.top = "-90px";
productAttr[2].style.top = "-90px";
}
});

Adding spans to a parent with JavaScript

I wrote a JavaScript function that takes the current number of spans of the class mini in the paragraph element with an id mega, which is at least 1, and if there are less than 4, adds enough to make 4. If there was no second mini, then the second mini, which the function should create, should say 2nd, if a third one is created, it should say 3rd, and if a fourth is created, it should say 4th. For example, if there are already 2 mini spans, the program, should add 2 more, the first one added saying 3rd and the second one saying 4rd. Here's the code:
function addSpans(currentNumOfSpans)
{
var mega = document.getElementById("mega");
var mini = document.createElement("span");
mini.className = "mini";
if (currentNumOfSpans < 4)
{
if (currentNumOfSpans < 3)
{
if (currentNumOfSpans < 2)
{
mini.innerHTML = "2<sup>nd</sup>;
mega.appendChild(mini);
}
mini.innerHTML = "3<sup>rd</sup>;
mega.appendChild(mini);
}
mini.innerHTML = "4<sup>th</sup>;
mega.appendChild(mini);
}
}
Soooo.... If currentNumOfSpans is 3, it works fine, and adds 4th to mega. However, if currentNumOfSpans is 1 or 2, while it should add 2nd3rd4th or 3rd4th, respectively, it just adds 4th. Can someone help me figure out what's wrong with this. Any help's appreciated, thanks!
Note: If you notice any typos, please comment or edit, but they aren't the problem, I've checked over my code in a syntax checker, but I often make errors in my code on SO because I use a tiny phone keyboard. So basically, typo's, whichI probably made, aren't the real problem. Thanks!
Your example included a few typos, most of which could be found by running your code through a debugger, like http://jshint.com.
However, I would use a more functional approach. The following method is not hard coded like yours, so you could use it for multiple elements, or use a different number of spans with very minimal changes to the usage, I've shown this in the demo below.
function getSuffix(i) {
var j = i % 10, k = i % 100;
if (j == 1 && k != 11) return i + "<sup>st</sup>";
if (j == 2 && k != 12) return i + "<sup>nd</sup>";
if (j == 3 && k != 13) return i + "<sup>rd</sup>";
return i + "<sup>th</sup>";
}
function addSpans(scope, length) {
var spans = scope.querySelectorAll('.mini');
var current = length - (length - spans.length);
while(current < length) {
var span = document.createElement('span');
span.className = 'mini';
span.innerHTML = getSuffix(++current);
scope.appendChild(span);
}
}
var wrap = document.querySelector('.wrap'), divs;
var clone = wrap.cloneNode(true);
wrap.parentNode.appendChild(clone);
divs = wrap.querySelectorAll('.mega');
for(var i in Object.keys(divs)) addSpans(divs[i], 4);
divs = clone.querySelectorAll('.mega');
for(var i in Object.keys(divs)) addSpans(divs[i], 6 + (i * 2));
.mega { font-size: 0; } .mini { display: inline-block; width: 40px; font-size: 16px; }
<div class="wrap">
<div class="mega"></div>
<div class="mega"><span class="mini">1<sup>st</sup></span></div>
<div class="mega"><span class="mini">1<sup>st</sup></span><span class="mini">2<sup>nd</sup></span></div>
<div class="mega"><span class="mini">1<sup>st</sup></span><span class="mini">2<sup>nd</sup></span><span class="mini">3<sup>rd</sup></span></div>
<div class="mega"><span class="mini">1<sup>st</sup></span><span class="mini">2<sup>nd</sup></span><span class="mini">3<sup>rd</sup></span><span class="mini">4<sup>th</sup></span></div>
</div>

jQuery breaking my fizzbuzz, why?

Trying to solve the fizzbuzz problem in javascript with a little html. I want to put the answers in a <ul> and display them on the page. To do this, I need to take the fizz-buzz's and somehow add them in a <li> element to the UL, with a prepend or append in jQuery. My code runs fine, until I add jQuery to the equation to prepend the <li>s into the html. I currently have the numbers/fizz-buzzes popping up with alerts.
I have tried putting in $(document).ready(function() {}, wrapping all javascript inside brackets. If I do, it breaks, even if there is 0 jQuery actually in the javascript section. Simply breaks, as if the page is never actually ready and thus the javascript will never run.
Assuming I can get any jQuery in to work, can I simply put jQuery statemments inside of my elseif statements?
example:
else if (n1 % 5 === 0) {
$("ul").prepend("<li>n1</li>")
}
Javascript:
var number = prompt("number?");
var num_int = parseInt(number);
var smack = new Array(num_int);
//populating array with numbers 1 through num_int
for (i = 0; i < smack.length; i++) {
smack[i] = i+1;
} //test again still working?
smack.forEach(function(n1) { //going through each array element, checking for fizz/buzz
if (n1 % 3 === 0 && n1 % 5 === 0) {
alert("fizz-buzz")
}
else if (n1 % 3 === 0) {
alert("fizz")
}
else if (n1 % 5 === 0) {
alert("buzz")
}
else {
alert(n1)
}
}); //end of forEach
HTML:
<hmtl>
<head>
<script src="scripts.js"></script>
<script src="jquery-1.11.2.js"></script>
</head>
<body>
<p>
<h1>Fizzbuzz</h1>
<ul id="hard">
<li>test</li>
</ul>
</p>
</body>
</html>
JSFiddle
Thanks in advance for any help! I'm sure this is a ridiculously easy question for anyone who has experience. I'm just getting into it, and while the math/logic section of fizzbuzz was pretty straightforward, getting it to display correctly is killing me.
You should load jquery before your script.js
Here's a demo
I added $('#hard').append
Changing the JQuery part to:
var number = prompt("number?");
var num_int = parseInt(number);
var smack = new Array(num_int);
//populating array with numbers 1 through num_int
for (i = 0; i < smack.length; i++) {
smack[i] = i+1;
} //test again still working?
smack.forEach(function(n1) { //going through each array element, checking for fizz/buzz
if (n1 % 3 === 0 && n1 % 5 === 0) {
$('#hard').append("<li>fizz-buzz</li>");
}
else if (n1 % 3 === 0) {
$('#hard').append("<li>fizz</li>");
}
else if (n1 % 5 === 0) {
$('#hard').append("<li>buzz</li>");
}
else {
$('#hard').append("<li>"+n1+"</li>");
}
}); //end of forEach
would help.
The changes here is inside the if conditions. You append your li to the ul each time and you will have your answers in the list.
Hope this helped.

Adding class to all childrens(in first level o hierarchy) of specified element in javascript without jquery

I want to change this from jquery to javascript:
$('#id_of_element').children('div').addClass('some_class');
So far all i have is this(not working):
document.getElementById('id_of_element').getElementsByTagName('div').addClass('some_class');
I have to change all my code from jquery to javascript. Is there any site with have examples of functions in javascript next to jquery? Thanks in advance for all help :)
Try
var el = document.getElementById('elem'),
//modern browsers IE >= 10
classList = 'classList' in el;
for (var i = 0; i < el.children.length; i++) {
var child = el.children[i];
if (child.tagName == 'DIV') {
if (classList) {
child.classList.add('test');
} else {
child.className += ' test'
}
}
}
Demo: Fiddle
If anyone wants to loop through all children, this worked for me:
const addClassList = (element) => {
Object.values(element.children).forEach((e) => {
e.classList.add('myClass');
if (e.children.length > 0) addClassList(e);
});
};
addClassList(myElement);
NOTE:
Does not work with conditional rendering
Remove the hash(#): in javascript you don't need to use # when selecting id.
document.getElementById('id_of_element').getElementsByTagName('div').addClass('some_class');

Strange behaviour whilst setting style.display in a simple function loop

Consider the following JavaScript:
function step(show)
{
for(var i = 1; i <= 5; i++)
{
document.getElementById('step' + show).style.display = show == i ? 'block' : 'none';
}
}
step(2);
In combination with this HTML:
<div id="step1">1</div>
<div id="step2">2</div>
<div id="step3">3</div>
<div id="step4">4</div>
<div id="step5">5</div>
I'd expect only #step2 to be shown, but instead I see the opposite result:
1
3
4
5
Here is a JSFiddle. What is causing this strange behaviour and how can I fix it?
I think you want:
document.getElementById('step' + i).style.display = show == i ? 'block' : 'none';
Notice the change here ------------------------^
DEMO: http://jsfiddle.net/5DNjc/2/
Without the change, you're always modifying the element with an id using the passed in parameter (static). So technically, you're always setting the display (of the target element) based on whether the last element passes the condition. The changing value is i.
To me, it makes it more readable if you separate out the logic, and might've helped you not encounter the problem in the first place :) Something like:
function step(show) {
for(var i = 1; i <= 5; i++) {
var curDiv = document.getElementById('step' + i);
var shouldBeShown = (i === show);
var newDisplay = shouldBeShown ? 'block' : 'none';
curDiv.style.display = newDisplay;
}
}
DEMO: http://jsfiddle.net/5DNjc/3/
document.getElementById('step' + i).style.display = show == i ? 'block' : 'none';
http://jsfiddle.net/3REbr/2/

Categories

Resources