How to create click event on random "div" inside a main "div"? - javascript

I have one main "Div" on which after clicking it gets split into n X n matrix. On every click inside it with a random colour div. Until here it's fine, now I want to create a click function on that random colourful div which currently is on any where inside the whole main "div"..
$(window).load(function() {
var no = 1,
$m = $(".main_div"),
size = 200;
$m.live('click', function() {
no++;
var n = no * no,
i, _size;
$m.empty();
for (i = 0; i < n; i++)
$m.append($('<div title=' + i + '/>'));
_size = size / no;
$m.find('> div').css({
width: _size,
height: _size
});
var colors = ["#FFFFFF", "#CC00CC", "#CC6699", "#0099CC", "#FF99FF"];
var rand = Math.floor(Math.random() * colors.length),
randomTotalbox = Math.floor(Math.random() * $('.main_div div').length);
$m.find("div:eq(" + randomTotalbox + ")").css("background-color", colors[rand]);
var rand = Math.floor(Math.random() * colors.length);
});
});
.main_div {
width: 200px;
height: 200px;
background-color: #9F0;
}
.main_div > div {
float: left;
box-shadow: 0 0 1px #000;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main_div" id="demo">
</div>
Here is a fiddle...Code

so you are saying that the clickable div is added to the DOM whenever you click(for example on a button )
that means that those divs were not there in the beginning so you can use
the Babak Naffas answer and also the .delegate method
example
$('body').delegate('.main_div > div','click',function(){
// here goes your instructions
});
for more details you can check:
jQuery: difference between .click() AND .on("click")

If you're asking for an event to be triggered when the NxN <div>s that make up the matrix are clicked, you could try
$(".main_div > div").on('click', function (evt) { ... } );
This will attach the function (the 2nd parameter) to the click event of the <div> from the matrix just like the CSS class you have with the same selector.

Related

Variable values don't save in if loops

I'm attempting to create something that makes a button only work once. In order to do so, I created an if loop. In that if loop, I put it to a function called myFunction and then set a variable, button, to 0 (the if loop only runs if button is =2. It will not run in the first place. What am I doing wrong?
I've already attempted to recreate the variable(saying var button once out of the loop and then saying it again within).
function getRndInteger(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var button = 2;
var x = 0
function ins() {
function removeElement(elementId) {
// Removes an element from the document
var element = document.getElementById(elementId);
element.parentNode.removeChild(element);
}
x = getRndInteger(0, window.innerWidth)
alert(x);
}
function button() {
if (button === 2) {
alert("k")
myFunction();
button = 0;
} else {}
}
function myFunction() {
var para = document.createElement("SPAN");
para.style.position = "absolute";
x = getRndInteger(0, (window.innerWidth - 60))
para.style.left = x + "px"
var p = getRndInteger(0, (window.innerHeight - 60))
para.style.top = p + "px"
para.style.display = "inline-block;"
para.style.height = "50px"
para.style.width = "50px"
para.style.backgroundColor = "red"
para.style.borderRadius = "50px"
para.style.border = "1px solid black"
para.style.animation = "1s a linear"
para.id = "a"
para.onclick = myFunction
document.getElementById("myDIV").appendChild(para);
}
#keyframes a {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
button {
background-color: #010417;
border-radius: 10px;
border: 4px solid white;
color: white;
padding: 10px 26px;
font-size: 20px;
}
<div id="myDIV"></div>
<center>
<button id="button" onClick="button();">Start</button>
</center>
EDIT: Ignore the delete function, doesn't mean anything
The issue with this code is that your event handler function, and the flag (that changes value between 2 and 0) are both named 'button'. Javascript is a relatively accommodating language, so this kind of dual declaration might not throw error right away, but it will obviously cause unexpected behaviour.
Looking at your code:
var button = 2;
function button() {
if (button === 2) {
alert("k")
myFunction();
button = 0;
} else {}
}
In this case (depending on the JS engine), button either refers to the function or the number. If it's the number, then type error will be thrown when button is clicked. Since the code will try to call the number like a function.
If it's a function, then the button === 2 comparison will always be false, and the (empty) else block will get executed. Either way you wouldn't get the expected behavior. You can simply change the variable name to something else, and it should work.
Please note that, as someone pointed out in comments, you should prefer adding disabled attribute to the button over this logic. Unless the aim is to do something other than blocking multiple clicks of the button.

Don't show the same div in random fadeIn/Out one after another

I have a JS which picks out a random div from a "list" of divs, shows it for a few seconds and fades it out, all in a random loop.
Now logically, sometimes the same div is picked directly one after another. I want to prevent this. The best case would be, if the JS would process all divs of the list in a random order, before it will start a new random "round". So e.g. div no. 5 would not be shown again directly on after another.
Here is my JS:
var myVar;
function showDiv() {
var random = Math.floor(Math.random() * $('.notification').length);
$('.notification').eq(random).prependTo('.container').fadeIn(200).delay(3000).fadeOut(200);
createRandomInterval();
}
function createRandomInterval() {
setTimeout(showDiv, 500 + Math.random() * 4000);
}
$(document).ready(function() {
createRandomInterval();
});
Here is my complete fiddle: https://jsfiddle.net/brapbg1h/
What I would do is store the last result, and if it lands on it, then process again.
something like this.
let lastResult = -1;
function getRandom() {
const res = Math.floor(Math.random() * $('.notification').length);
return res === lastResult ? getRandom() : res;
}
function showDiv() {
var random = getRandom();
lastResult = random;
$('.notification').eq(random).prependTo('.container').fadeIn(200).delay(3000).fadeOut(200);
createRandomInterval();
}
Save the random to a global variable, like lastDiv. Check random against lastDiv and it is a match, re-run the function again.
var lastDiv;
function showDiv() {
var random = Math.floor(Math.random() * $('.notification').length);
if(random == lastDiv) {
console.log('random matches lastDiv, re-running.');
return showDiv();
}
lastDiv = random;
$('.notification').eq(random).prependTo('.container').fadeIn(200).delay(3000).fadeOut(200);
createRandomInterval();
}
function createRandomInterval() {
setTimeout(showDiv, 500 + Math.random() * 4000);
}
$(document).ready(function() {
createRandomInterval();
});
.notification {
width: 200px;
height: 50px;
background-color: yellow;
border: 1px solid rgba(0, 0, 0, 0.2);
margin-bottom: 5px;
text-align: center;
padding-top: 20px;
display: none;
/* hide initially so that fadIn() fadeOut() will work */
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.2/jquery.min.js"></script>
<div class="container">
<div class="notification">1</div>
<div class="notification">2</div>
<div class="notification">3</div>
<div class="notification">4</div>
</div>
Previous Div in a variable
If you do not want 2 consequent divs to be the same, just assign the number of the div (since it is from a list) to a variable and if it is equal to current selection run the function again in a do..while loop.
var random;
function showDiv() {
do {
var random = Math.floor(Math.random() * $('.notification').length);
} while(random==previousDiv);
$('.notification').eq(random).prependTo('.container').fadeIn(200).delay(3000).fadeOut(200);
createRandomInterval();
var previousDiv = random;
}

Javascript - Block that should disappear on click reappear elsewhere

I am trying to get three squares (put ramdomly) on page to disappear on click BUt for a reason I don't understand, some of them (usually the 2nd or 3rd one) reappear elsewhere on the page when I click on them.
They should just disappear.
I made a jsffidle: https://jsfiddle.net/DTcHh/9949/
The code:
HTML
<div class="container">
<div id="square-zone">
<!--
here appear the squares
-->
</div>
</div>
Javascript
//randomly place squares
$(function() {
var numInfoSquares = 3;
var $squareZone = $("#square-zone");
var $toAppend = $('<div class="info-square"><span class="square" data-toggle="modal"></span></div>');
for (var c = 0; c < numInfoSquares; c++) {
$squareZone.append(
$toAppend.clone()
.find('.square').attr("data-target", "#myInfoModal" + (c + 1))
.end()
);
};
// place info squares randomly on the page
function getRandomInt(min, max) {
return Math.random() * (max - min + 1) + min;
}
$(".info-square").each(function () {
var topPosition = getRandomInt(8, 70);
var leftPosition = getRandomInt(8, 92);
$(this).css({
"top": topPosition+"%",
"left": leftPosition+"%"
});
});
// clicked squares disappears on click
$(".info-square").click(function () {
$(this).css("display","none");
$(this).next().css("display","block");
});
});
CSS
body {
margin: 10px;
}
#square-zone > div { position: absolute; }
.info-square > span {
display: inline-block;
cursor: pointer;
background: url(http://cliparts.co/cliparts/ATb/jRa/ATbjRan5c.png) no-repeat center center;
width: 30px;
height: 30px;
}
How can I prevent the squares to reappear ?
Well just remove that line from your code which makes it appear again
$(this).next().css("display","block");
// clicked squares disappears on click
$(".info-square").click(function () {
$(this).css("display","none");
//$(this).next().css("display","block");
});
Updated jsfiddle with commented line https://jsfiddle.net/DTcHh/9950/
that is because of $(this).next().css("display","block");.
Assume you are clicking on 2nd element then it is hidden, then you are clicking on the first element now that is hidden but when the above line is executed it will display the second element back as it is the next sibling of the first info-square
//randomly place squares
$(function() {
var numInfoSquares = 3;
var $squareZone = $("#square-zone");
var $toAppend = $('<div class="info-square"><span class="square" data-toggle="modal"></span></div>');
for (var c = 0; c < numInfoSquares; c++) {
$squareZone.append(
$toAppend.clone()
.find('.square').attr("data-target", "#myInfoModal" + (c + 1))
.end()
);
};
// place info squares randomly on the page
function getRandomInt(min, max) {
return Math.random() * (max - min + 1) + min;
}
$(".info-square").each(function() {
var topPosition = getRandomInt(8, 70);
var leftPosition = getRandomInt(8, 92);
$(this).css({
"top": topPosition + "%",
"left": leftPosition + "%"
});
});
// clicked squares disappears on click
$(".info-square").click(function() {
$(this).css("display", "none");
//$(this).next().css("display", "block"); this displayes the next element back if it was already hidden
});
});
/* Latest compiled and minified CSS included as External Resource*/
body {
margin: 10px;
}
#square-zone > div {
position: absolute;
}
.info-square > span {
display: inline-block;
cursor: pointer;
background: url(http://cliparts.co/cliparts/ATb/jRa/ATbjRan5c.png) no-repeat center center;
width: 30px;
height: 30px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="container">
<div id="square-zone">
<!--
here appear the squares
-->
</div>
</div>
Alternately, changing $(this).css("display","none"); to $(this).css("visibility","hidden"); also solves it.
Here's the jsfiddle

Scroll to position WITHIN a div (not window) using pure JS

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');
}

How to create different mousedown callbacks dynamically?

I am trying to create multiple divs each with a mousedown callback.
But that callback function should not be common for all the divs , it should function differently depending upon the div clicked.
Here is the code I am using the generate the divs and setting the callbacks.
//some number
var num=4;
for(var z = 0 ; z < num ;z++)
{
//create a div with id 'z'
$("<div/>",{id:z}).appendTo("#empty");
//displaying the id on the screen
$("#"+z).text(z);
console.log("button "+z+" created");
//Callback function , which is not working as I want it to. See the bottom section for more details
$("#"+z).mousedown(function(){
console.log("Button "+z+" clicked !");
});
}
The above code runs as follows...
On clicking anyone of the divs the message "Button 4 clicked!" is generated in the console.
What should be done in order to achieve what I was aiming for ?
It would be better to use a class for the buttons and create a callback for the item.
var num=4;
for(var z = 0 ; z < num ;z++)
{
//create a div with id 'z'
$("<div/>",{id:z,class:'btn'}).appendTo("#empty");
//displaying the id on the screen
$("#"+z).text(z);
console.log("button "+z+" created");
}
$(".btn").mousedown(function(){
var z = $(this).attr('id');
console.log("Button "+z+" clicked !");
});
Keep track of your button, try modifying your code as:
var num = 4;
var btn;
for (var z = 0; z < num; z++) {
btn = $("<div>", {
id: z,
text: z
}).appendTo("#empty");
btn.on('click', function() {
alert("Button " + $(this).text() + " clicked !");
});
}
#empty div {
padding: 5px;
border: 1px solid grey;
margin-bottom: 2px;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id='empty'></div>
Using single click handler:
$(function() {
var num = 4;
var btn;
var empty = $("#empty");
empty.on('click', 'div.btn', function() {
alert("Button " + $(this).text() + " clicked !");
});
for (var z = 0; z < num; z++) {
btn = $("<div>", {
'id': z,
'text': z,
'class': 'btn'
});
empty.append(btn);
}
});
div.btn {
padding: 5px;
border: 1px solid grey;
margin-bottom: 2px;
cursor: pointer;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div id='empty'></div>
Give your elements a class. Then use the index of the clicked element within that class to know which one was click and act on that:
//some number
var num=4;
for(var z = 0 ; z < num ;z++)
{
$('#divHolder').append('<div class="mydivs"></div>');
}
$('body').on('mousedown', '.mydivs', function() {
// get the index of the clicked div
var curDiv = $('.mydivs').index(this);
// call a function and pass it this index
doStuff(curDiv);
});
function doStuff(clickedDiv){
// the index that was passed in will tell you what
// div was clicked do something with that
$('#show').html( 'you clickded div:' + clickedDiv);
};
.mydivs{
background-color:#cccccc;
margin-top:15px;
height:100px;
width:100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="show"></div>
<div id="divHolder"></div>
One way to resolve this problem is to handle the event outside of the for loop.
Working Code Snippet:
//some number
var num=4;
for(var z = 0 ; z < num ;z++)
{
//create a div with id 'z'
$("<div/>",{id:z}).appendTo("#empty");
//displaying the id on the screen
$("#"+z).text(z);
console.log("button "+z+" created");
}
//Callback function taken out of the for loop and added event delegation since it is a dynamically added element
$(document).on('click', 'div div', function(){
console.log("Button "+ $(this).attr('id') +" clicked !");
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="empty"></div>

Categories

Resources