I'm trying to update a set of divs class="oct_days" to give them id based on :nth-child(n). The format of the id is oct_n. I'm trying to accomplish this using a for loop to set this for divs.
window.onload = function addOctDate() {
var cls = document.getElementByClass("oct_days");
for (var n = 1; n < 32; n++) {
cls[n].id = "oct_" + n;
}
};
Fiddle (http://jsfiddle.net/ascottz/D9Exm/)
The idea is to have .oct_days:nth-child(1) have id="oct_1", but id isn't being set.
clsyour issues are this:
window.onload was being run before your html was initialized
you need to call document.getElementsByClassName not
you are starting your iteration at 1, indexes are 0 based and you should start there and add the + 1 as noted below
also, while iterating, its good to only iterate only over the known items in your list
try this code:
function addOctDate() {
var cls = document.getElementsByClassName("oct_days");
for (n=0, length = cls.length; n < length; n++) {
cls[n].id= "oct_" + (n + 1);
}
};
addOctDate()
The function is getElementsByClassName.
The fiddle doesn't work because you're seeing window.onload while your code is already being run inside that event (the dropdown on the left says onLoad). It'll also error out because you don't have 31 elements in the HTML, but it'll still set the IDs.
Your code is very simple to fix
(function () {
// .getElementsByClassName not .getElementByClass
var cls = document.getElementByClassName("oct_days"),
// set the stopping point DYNAMICALLY
len = cls.length,
// start the index at 0;
n = 0;
for (; n < len; n++) {
cls[n].id = "oct_" + (n + 1);
}
// ()(); auto runs the function
})();
Here is a way to add ids to elements and classes using just plain js.
HTML
<div id="test">
Content will append below!
<input type="button" value="click me!" onClick="myFunction();"/>
</div>
CSS
.cool_0 {
background: red;
height: 200px;
width: 100%;
}
.cool_1 {
background: yellow;
height: 200px;
width: 100%;
}
.cool_2 {
background: red;
height: 200px;
width: 100%;
}
.cool_3 {
background: yellow;
height: 200px;
width: 100%;
}
.cool_4 {
background: red;
height: 200px;
width: 100%;
}
.cool_5 {
background: yellow;
height: 200px;
width: 100%;
}
JS
function myFunction(){
var myId = 0;
var counter = 0;
var myDiv = document.getElementById("test")
for(var i = 0; i < 5; i++){
var textNode = document.createTextNode("sup! My current id is "+myId+" !")
var t = document.createElement("div");
t.setAttribute("id", counter++)
t.setAttribute("class", "cool_"+myId++)
t.appendChild(textNode)
myDiv.appendChild(t);
}
}
Related
I am writing a javascript code which will sort arrays in ascending order. But whenever my code meets the correct condition which is arr[1] < arr[2], it stops the loop and prompts the message Congratulations!! This Group is Sorted By the way, I am using jquery also because I made a little game that you can sort all the numbers to ascending order and check if it is sorted or not.
I am not sure if the click event is responsible for the loop to stop. I am really confused with this. Can someone help me?
Here is the code snippet from my project:
HTML
<ul id="sort">
<!--Generated Numbers using javascript-->
</ul>
JAVASCRIPT
$(document).ready(function(){
$("#sort").sortable();
$("#sort").disableSelection();
// var elemArr = document.getElementsByClassName("sort-ui");
// var arr = jQuery.makeArray(elemArr);
// arr = arr.map(data => data.innerHTML);
var arr = [];
function generateNum(){
var min=1;
var max=12;
return Math.floor(Math.random() * (+max - +min)) + +min;
// document.write("Random Number Generated : " + random );
}
function storeToArray() {
var i = 0;
var ul = document.getElementById("sort");
var li;
while(i < 12) {
var rec = generateNum();
arr[i] = rec;
li = document.createElement("li");
li.appendChild(document.createTextNode(arr[i]));
ul.appendChild(li);
++i;
}
}
storeToArray();
$(".btn-check").on("click", function(){
var elemArr = document.getElementsByTagName("li");
var arrCheck = jQuery.makeArray(elemArr);
arrCheck = arrCheck.map(data => data.innerHTML);
var int;
var len = arrCheck.length;
console.log(arrCheck);
for(int = 0; int < len-1; i++) {
if(arrCheck[int] > arrCheck[int+1]){
alert("This Group is Not Sorted");
} else {
alert("Congratulations!! This Group is Sorted");
}
}
});
});
CSS (For you to visualize)
#sort {
list-style: none;
width: 430px;
border: 1px solid;
padding: 20px;
margin: 0 auto;
height: 315px;
}
#sort li {
display: inline-block;
float: left;
width: 100px;
height: 100px;
background: yellow;
font: 600 16px/100px "Arial";
text-align: center;
margin: 0;
border: 3px solid white;
}
.button-c {
width: 200px;
margin: 0 auto;
}
There is mistake in for loop i++ for(int = 0; int < len-1; i++) , It should be int++
let arrCheck = [1, 3 , 3, 4]
let len = arrCheck.length
for(let int = 0; int < len-1; int++) {
if(arrCheck[int] > arrCheck[int+1]){
alert("This Group is Not Sorted");
} else {
alert("Congratulations!! This Group is Sorted");
}
}
Your implementation of the sort function was incorrect. You didn't use the break keyword and your numbers were in string format, so you need to parse them for comparison.
function isSorted(arrCheck) {
var sortVal = true;
var len = arrCheck.length;
console.log(arrCheck);
for(int = 0; int < len-1; int++) {
if(parseInt(arrCheck[int]) > parseInt(arrCheck[int+1])) {
sortVal = false;
break;
}
}
return sortVal;
}
I recently started learning how to use JavaScript in my webpage. My exercise today is to make a button that can give me a V shape.
The code to create the V shape is fine, but it doesn't work when I try to put it in a click handler (i.e. oBtn.click = function (){};).
In the HTML document I have the following code:
<style>
div{
width: 50px;
height: 50px;
border: 1px red solid;
position: absolute;
line-height: 50px;
text-align: center;
margin: 5px;
}
</style>
<script type="text/javascript">
window.onload = function (){
var oBody = document.getElementById('body');
var aDiv = document.getElementsByTagName('div');
var oBtn1 = document.getElementById('btn1');
for (var i = 0; i < 9; i++) {
oBody.innerHTML += '<div>'+ i +'</div>';
}
for (var i = 0; i < aDiv.length; i++) {
aDiv[i].style.left =i*50+'px';
}
oBtn1.onclick = function (){
for (var i = 0; i < aDiv.length/2; i++) {
aDiv[i].style.top = 40+i*50+'px';
}
var x = aDiv.length;
for (var i = 4; i < x; i++) {
aDiv[i].style.top =x*50-i*50-50+40+'px';
}
};
};
</script>
I believe this is close to what you wanted. Runs in chrome, but may not in other browsers (notably IE). Doesn't work as a snippet, sorry. I suspect trying to modify all divs in the body is going to cause you trouble in the long term. A couple of things to notice:
You don't need to get the body by name, you can just use document.body (I'm making an assumption here - however giving an element the id "body" could easily cause confusion)
Your divs must be created before you try to get the array from the DOM
Event handlers are done using the commonly preferred method.
<html>
<head>
<style>
div{
width: 50px;
height: 50px;
border: 1px red solid;
position: absolute;
line-height: 50px;
text-align: center;
margin: 5px;
}
</style><script>
window.addEventListener("DOMContentLoaded", function () {
for (var i = 0; i < 9; i++) {
document.body.innerHTML += '<div>'+ i +'</div>';
}
var aDiv = document.getElementsByTagName('div');
for (var i = 0; i < aDiv.length; i++) {
aDiv[i].style.left =i*50+'px';
}
document.getElementById('btn1').addEventListener("click", function () {
for (var i = 0; i < aDiv.length/2; i++) {
aDiv[i].style.top = 40+i*50+'px';
}
var x = aDiv.length;
for (var i = 4; i < x; i++) {
aDiv[i].style.top =x*50-i*50-50+40+'px';
}
});
}, false);
</script>
</head>
<body>
<input type="button" id="btn1"><br />
</body>
</html>
If I understand this right, you want to execute 'oBtn1.onclick' as a click event? If so, do something like this
function buttonClick (){
for (var i = 0; i < aDiv.length/2; i++) {
aDiv[i].style.top = 40+i*50+'px';
}
oBtn1.addEventListener('click', buttonClick);
what that will do is as soon as the element that contains the id 'oBtn1' is clicked it will execute your for loop.
What does your html look like? If it looks kind of like the below snippet then it should be working, though you should look at using addEventListener for this kind of thing.
window.onload = function (){
var oBody = document.getElementById('body');
var aDiv = document.getElementsByTagName('div');
var oBtn1 = document.getElementById('btn1');
for (var i = 0; i < 9; i++) {
oBody.innerHTML += '<div>'+ i +'</div>';
}
for (var i = 0; i < aDiv.length; i++) {
aDiv[i].style.left =i*50+'px';
}
oBtn1.onclick = function (){
for (var i = 0; i < aDiv.length/2; i++) {
aDiv[i].style.top = 40+i*50+'px';
}
var x = aDiv.length;
for (var i = 4; i < x; i++) {
aDiv[i].style.top =x*50-i*50-50+40+'px';
}
};
};
div{
width: 50px;
height: 50px;
border: 1px red solid;
position: absolute;
line-height: 50px;
text-align: center;
margin: 5px;
}
<button id="btn1">press</button>
<div id="body"></div>
I'm trying to get the tallest height of some elements using the following.
var blocks = [];
for(var i = 1; i < 100; i++) {
blocks[i] = $('.blocks .block-' + i).outerHeight();
}
var tallest = Math.max.apply(Math, blocks);
console.log(tallest);
The heights are getting stored fine within the blocks array but when I output the tallest variable it's just coming up with NaN.
In your code, for loop start with 1 instead of 0 so first element of array got undefined and tallest return NaN.
Instead of adding value to individual array element using blocks[i]. Use push for array.
var blocks = [];
for(var i = 1; i < 100; i++) {
blocks.push($('.blocks .block-' + i).outerHeight() || 0);
}
var tallest = Math.max.apply(Math, blocks);
console.log(tallest);
Check snippet
var blocks = [];
for (var i = 1; i < 10; i++) {
blocks[i] = i;
}
var tallest = Math.max.apply(Math, blocks);
snippet.log('Using element : ' + blocks);
snippet.log('Using element tallest is : ' + tallest);
blocks = [];
for(var j = 1; j < 10; j++) {
blocks.push(j);
}
tallest = Math.max.apply(Math, blocks);
snippet.log('Using push tallest element : ' + tallest);
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
Your array is 0 based - but the DOM is index from 1. Use i - 1 as the array index and use || 0 when recording heights in to the array to prevent non-numeric values being added.
var blocks = [];
for(var i = 1; i < 100; i++) {
blocks[i - 1] = $('.blocks .block-' + i).outerHeight() || 0;
}
As pointed out by others, the problem with your code was the array you defined always had an undefined element in it thereby causing the max function to return NaN as output. In future, please make sure to define the array length you need.
var blocks = [];
for (var i = 0; i < 3; i++) {
blocks[i] = $('.blocks-' + (i + 1)).height();
}
var tallest = Math.max.apply(null, blocks);
alert(tallest);
.blocks {
width: 500px;
height: 300px;
border: 1px solid gray;
}
.blocks .blocks-1 {
width: 150px;
height: 100px;
border: 1px solid red;
float: left;
margin-left: 5px;
}
.blocks .blocks-2 {
width: 150px;
height: 200px;
border: 1px solid orange;
float: left;
margin-left: 5px;
}
.blocks .blocks-3 {
width: 150px;
height: 150px;
border: 1px solid green;
float: left;
margin-left: 5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<div class="blocks">
<div class="blocks-1">
</div>
<div class="blocks-2">
</div>
<div class="blocks-3">
</div>
</div>
Your jQuery selector error, .blocks .block-1 can select:
<div class='blocks'>
<div class='block-1'>1</div>
<div class='block-2'>2</div>
<div class='block-3'>3</div>
</div>
But, I think you should want to meet two classes. Use:
blocks[i-1] = $('.blocks.block-' + i).outerHeight()||0;
Note:$('.blocks.block-' + i) has no spaces.
PURE JS ONLY PLEASE - NO JQUERY
I have a div with overflow scroll, the window (html/body) never overflows itself.
I have a list of anchor links and want to scroll to a position when they're clicked.
Basically just looking for anchor scrolling from within a div, not window.
window.scrollTo etc. don't work as the window never actually overflows.
Simple test case http://codepen.io/mildrenben/pen/RPyzqm
JADE
nav
a(data-goto="#1") 1
a(data-goto="#2") 2
a(data-goto="#3") 3
a(data-goto="#4") 4
a(data-goto="#5") 5
a(data-goto="#6") 6
main
p(data-id="1") 1
p(data-id="2") 2
p(data-id="3") 3
p(data-id="4") 4
p(data-id="5") 5
p(data-id="6") 6
SCSS
html, body {
width: 100%;
height: 100%;
max-height: 100%;
}
main {
height: 100%;
max-height: 100%;
overflow: scroll;
width: 500px;
}
nav {
background: red;
color: white;
position: fixed;
width: 50%;
left: 50%;
}
a {
color: white;
cursor: pointer;
display: block;
padding: 10px 20px;
&:hover {
background: lighten(red, 20%);
}
}
p {
width: 400px;
height: 400px;
border: solid 2px green;
padding: 30px;
}
JS
var links = document.querySelectorAll('a'),
paras = document.querySelectorAll('p'),
main = document.querySelector('main');
for (var i = 0; i < links.length; i++) {
links[i].addEventListener('click', function(){
var linkID = this.getAttribute('data-goto').slice(1);
for (var j = 0; j < links.length; j++) {
if(linkID === paras[j].getAttribute('data-id')) {
window.scrollTo(0, paras[j].offsetTop);
}
}
})
}
PURE JS ONLY PLEASE - NO JQUERY
What you want is to set the scrollTop property on the <main> element.
var nav = document.querySelector('nav'),
main = document.querySelector('main');
nav.addEventListener('click', function(event){
var linkID,
scrollTarget;
if (event.target.tagName.toUpperCase() === "A") {
linkID = event.target.dataset.goto.slice(1);
scrollTarget = main.querySelector('[data-id="' + linkID + '"]');
main.scrollTop = scrollTarget.offsetTop;
}
});
You'll notice a couple of other things I did different:
I used event delegation so I only had to attach one event to the nav element which will more efficiently handle clicks on any of the links.
Likewise, instead of looping through all the p elements, I selected the one I wanted using an attribute selector
This is not only more efficient and scalable, it also produces shorter, easier to maintain code.
This code will just jump to the element, for an animated scroll, you would need to write a function that incrementally updates scrollTop after small delays using setTimeout.
var nav = document.querySelector('nav'),
main = document.querySelector('main'),
scrollElementTo = (function () {
var timerId;
return function (scrollWithin, scrollTo, pixelsPerSecond) {
scrollWithin.scrollTop = scrollWithin.scrollTop || 0;
var pixelsPerTick = pixelsPerSecond / 100,
destY = scrollTo.offsetTop,
direction = scrollWithin.scrollTop < destY ? 1 : -1,
doTick = function () {
var distLeft = Math.abs(scrollWithin.scrollTop - destY),
moveBy = Math.min(pixelsPerTick, distLeft);
scrollWithin.scrollTop += moveBy * direction;
if (distLeft > 0) {
timerId = setTimeout(doTick, 10);
}
};
clearTimeout(timerId);
doTick();
};
}());
nav.addEventListener('click', function(event) {
var linkID,
scrollTarget;
if (event.target.tagName.toUpperCase() === "A") {
linkID = event.target.dataset.goto.slice(1);
scrollTarget = main.querySelector('[data-id="' + linkID + '"]');
scrollElementTo(main, scrollTarget, 500);
}
});
Another problem you might have with the event delegation is that if the a elements contain child elements and a child element is clicked on, it will be the target of the event instead of the a tag itself. You can work around that with something like the getParentAnchor function I wrote here.
I hope I understand the problem correctly now: You have markup that you can't change (as it's generated by some means you have no control over) and want to use JS to add functionality to the generated menu items.
My suggestion would be to add id and href attributes to the targets and menu items respectively, like so:
var links = document.querySelectorAll('a'),
paras = document.querySelectorAll('p');
for (var i = 0; i < links.length; i++) {
links[i].href=links[i].getAttribute('data-goto');
}
for (var i = 0; i < paras.length; i++) {
paras[i].id=paras[i].getAttribute('data-id');
}
I am trying to make a chessboard using javascript and creating 64 divs with it.
The problem is, that it creates only the first div.
Here is the code:
div {
width: 50px;
height: 50px;
display: block;
position: relative;
float: left;
}
<script type="text/javascript">
window.onload=function()
{
var i=0;
var j=0;
var d=document.createElement("div");
for (i=1; i<=8; i++)
{
for (j=1; j<=8; j++)
{
if ((i%2!=0 && j%2==0)||(i%2==0 && j%2!=0))
{
document.body.appendChild(d);
d.className="black";
}
else
{
document.body.appendChild(d);
d.className="white";
}
}
}
}
</script>
As t-j-crowder has noted, the OP's code only creates one div. But, for googlers, there is one way to append multiple elements with a single appendChild in the DOM: by creating a documentFragment.
function createDiv(text) {
var div = document.createElement("div");
div.appendChild(document.createTextNode(text));
return div;
}
var divs = [
createDiv("foo"),
createDiv("bar"),
createDiv("baz")
];
var docFrag = document.createDocumentFragment();
for(var i = 0; i < divs.length; i++) {
docFrag.appendChild(divs[i]); // Note that this does NOT go to the DOM
}
document.body.appendChild(docFrag); // Appends all divs at once
The problem is, that it creates only the first div.
Right, because you've only created one div. If you want to create more than one, you must call createElement more than once. Move your
d=document.createElement("div");
line into the j loop.
If you call appendChild passing in an element that's already in the DOM, it's moved, not copied.
window.onload=function()
{
var i=0;
var j=0;
for (i=1; i<=8; i++)
{
for (j=1; j<=8; j++)
{
if ((i%2!=0 && j%2==0)||(i%2==0 && j%2!=0))
{
var d=document.createElement("div");
document.body.appendChild(d);
d.className="black";
}
else
{
var d=document.createElement("div");
document.body.appendChild(d);
d.className="white";
}
}
}
}
Although what T.J. Crowder writes works fine, I would recommend rewriting it to the code below, using a documentFragment, like Renato Zannon suggested. That way you will only write to the DOM once.
window.onload = function() {
var count = 5,
div,
board = document.getElementById('board'),
fragment = document.createDocumentFragment();
// rows
for (var i = 0; i < count; ++i) {
// columns
for (var j = 0; j < count; ++j) {
div = document.createElement('div');
div.className = (i % 2 != 0 && j % 2 == 0) || (i % 2 == 0 && j % 2 != 0) ? 'black' : 'white';
fragment.appendChild(div);
}
}
board.appendChild(fragment);
};
#board {
background-color: #ccc;
height: 510px;
padding: 1px;
width: 510px;
}
.black,
.white {
float: left;
height: 100px;
margin: 1px;
width: 100px;
}
.black {
background-color: #333;
}
.white {
background-color: #efefef;
}
<div id="board"></div>
function crt_dv(){
dv=document.createElement('div'),document.body.appendChild(dv)
};
crt_dv(),dv.className='white';crt_dv(),dv.className='black';
Also use: for(i=0;i<2;i++)