How to create different mousedown callbacks dynamically? - javascript

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>

Related

Is there a way in javascript to identify when I mouse over the same element and when on a different?

I have a time variable that updates and want to restart its value only when you mouse over on a different element, if you hover on the same element it should keep updating. How should I approach this? Here's part of the code:
// Change shaders
function changeShader() {
const elements = document.querySelectorAll('.caption');
elements.forEach(element => {
element.addEventListener('mouseover', function() {
if (you hovered on the same element) {
console.log('you moused over the same element');
} else {
console.log('you moused over on a different element');
}
});
});
}
You can save last hovered dom and check if it's the same:
function changeShader() {
let last_hover;
const elements = document.querySelectorAll('.caption');
elements.forEach(element => {
element.addEventListener('mouseover', function() {
if (last_hover == this) {
console.log('you moused over the same element');
} else {
console.log('you moused over on a different element');
}
last_hover = this;
});
});
}
changeShader()
.caption, .no-hover{
padding:10px;
margin-bottom: 25px;
background-color: #ccc;
cursor: pointer;
}
<div class="caption">I am Caption 1</div>
<div class="caption">I am Caption 2</div>
<div class="caption">I am Caption 3</div>
<div class="caption">I am Caption 4</div>
<div class="caption">I am Caption 5</div>
This is one way to do so dynamically with JavaScript. In this example, the code assigns a handler to the onmouseover event of each element, in this case each element is a button.
var flags = new Array(2);
flags[0] = 0;
flags[1] = 0;
var buttons = document.getElementsByTagName("button");
for (let i = 0, max = buttons.length; i < max; i++) {
let temp = i;
buttons[temp].onmouseover= function(){
console.log("Moused over this button " + buttons[temp].id + " " + flags[temp]++ + "x before." );
if ((flags[temp] == 2)) {
this.onmouseover = null;
alert("Done documenting bbutton " + buttons[temp].id);
}
};
}// end for
<style>
#a {
background: #000;
color: lime;
}
#b {
background: #000;
color: cyan;
}
#a:hover,#b:hover {
background: #600;
color: #ffdede;
}
</style>
<div><button id="a">Button A</button>
<button id="b">Button B</button></div>
By setting each button with a unique id attribute, it uses that value to distinguish which button is being moused over.
Note: the CSS is strictly optional -- just wanted to enhance the visuals.

Toggle Increment and decrement count on single element click

I have a element which has an integer count.
<span class="likes-count"> 2 </span>
And a div when clicked have to toggle the increment and decrement of the value.
<div class="liked"></div>
Problem:
I have called a function on $('.liked').clicked which increments the value and changes the class to .notliked
And another onclick function decrements the value, but it's not working properly.
Please review my code. I guess this is not the best way to do this.
Here's my demo code.
$(document).ready(function() {
$(".notliked").click(function() {
var $this = $(this);
$this.removeClass('notliked');
$this.addClass('liked')
$count = $('.likes-count');
$count.html((parseInt($count.html(),10) || 0) + 1);
});
$(".liked").click(function() {
var $this = $(this);
$this.removeClass('liked');
$this.addClass('notliked');
$count = $('.likes-count');
$count.html((parseInt($count.html(),10) || 0) - 1);
});
});
.heart {
color: #fff;
height:50px;
cursor:pointer;
width:50px;
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<span class="likes-count"> 2 </span>
<div class="liked heart">Click</div>
You need to delegate the click event. At the beginning $(".notliked") returns 0 elements and so it's never executed.
In order to increment/decrement the text value you can use:
.text( function ) like:
$count.text(function(idx, txt) {
// convert text to number and increment by one
return +txt + 1;
});
The snippet:
$(document).on('click', ".notliked", function() {
var $this = $(this);
$this.removeClass('notliked');
$this.addClass('liked')
$count = $('.likes-count');
$count.text(function(idx, txt) {
return +txt + 1;
});
});
$(document).on('click', ".liked", function() {
var $this = $(this);
$this.removeClass('liked');
$this.addClass('notliked');
$count = $('.likes-count');
$count.text(function(idx, txt) {
return (+txt == 0) ? 0 : (+txt - 1);
});
});
.heart {
color: #fff;
height:50px;
cursor:pointer;
width:50px;
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<span class="likes-count"> 0 </span>
<div class="liked heart">Click</div>

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

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.

Fadein with variable as selector

I'm currently trying to make a hover effect (make a div fadein, and then out when not hovering) on my list of pictures that users has uploadet. Since i dont want all my pictures to hover when one of the pictures are selected, i have made PHP echo out a variable for the divs ids.
In my jQuery code below, i got a loop where i count from 1 to 16 (thats the number of pictures in my gallery) and the selector has the name of the divs.
PHP Part:
echo "<div class='cell1' id=sovs$sovs style='overflow: hidden; position: relative;'>
<a href=image.php?p=$presentnew->upload_id>
<img style='min-width: 177px; min-height: 177px;' src='content/$presentnew->user_name/thumbs/medium_$presentnew->file_name'>
<div class='celltext'>
<b style='color: white; line-height: 28px; margin-left: 5px; font-size: 10pt;'><a style='color: white;' href='profil.php?bruger=$presentnew->user_name'>$presentnew->user_name</a></b>
</div>
</a>
</div>";
$sovs++;
}
Javascript Part:
for (var h = 1; h <= 16; h++) {
$(function() {
$("#sovs" + h).hover(
function() {
alert("g");
});
});
}​
The code above is just a test where i want my divs to respond to the function.
problem is that they dont do that. they will respond if i change the name of the selector to, for instance $('#sovs1').
Can anybody enlighten me on what I am doing wrong?
$(document).ready(function(){
for(var h=1; h<=16; h++){
$("#sovs"+h).mouseover(function(){
alert("G");
});
}
});
Works, but if i attach the fadeIn function to it, it doesn't
You will have to give a lot more info to get an answer, just one important thing:
for (var h = 1; h <= 16; h++) {
$(function() { // <======= This will create 16! dom ready event handlers
$("#sovs" + h).hover(
function() {
alert("g");
});
});
}​
Move it to an outer scope (If needed at all..)
$(function() {
for (var h = 1; h <= 16; h++) {
$("#sovs" + h).hover(function() {
alert("g");
});
}
}​
Try this code, to see if the problem is with delegate event VS direct event.
$(function() {
for (var h = 1; h <= 16; h++) {
$('body').on('mousemove', "#sovs" + h, function() {
alert('g');
});
}
}​
$(document).ready(function() {
for(var h=1; h<=16; h++) {
$("#sovs"+h).live('hover', function() {
alert("g");
});
}
});

.click inside stop: function (event, ui) run X times (where X is the number of items) instead of just once

The code below is (hopefully) a minimized testcase of my original problem. I'm trying to set up a system where you drag list items from the left menu (draggable items) and then drop'em to the box on the right hand side. Once they're dropped, you should be able to click the "draggable item" text and expand their fieldsets.
The problem is, however, that once you have dropped the items and clicked to expand them (say you have 3 items), the first one will give you 3 alert boxes, the second one will give you 2 and the last one will only give you 1. In other words, from the top, it will give you x alert boxes (where X is the number of items).
Looking at the code, I really can't figure out why this happens, other than it seems that having the .click stuff inside stop: seems to be related, given the fact that the example on http://api.jquery.com/click/ works fine.
(BTW: The stuff inside the alert box is supposed to be the ID of the item you clicked.)
Any ideas?
<!doctype>
<html>
<head>
<title>testcase</title>
<style type="text/css">
body { padding: 50px; font-family: Arial; font-size: .9em }
#column, #data { float: left }
#column { width: 13% }
ul, ol { padding: 0; border: 0 }
li { list-style: none }
.droptarget { padding: 10px; border: 1px solid #999; height: 10px; width: 350px; margin-right: 1.2% }
.ui-draggable-dragging, .ui-sortable-helper { background: #f90; width: 100px; display: block }
</style>
<script src="http://code.jquery.com/jquery-1.4.1.js" type="text/javascript" charset="utf-8"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/jquery-ui.min.js" type="text/javascript"></script>
<script type="text/javascript">
function hideAllElements() {
var elements = $('.dtContent');
var elementsLength = elements.length
for (var j = 0; j < elementsLength; j++) {
elements[j].style.display = 'none';
}
}
var randNum = 0;
function randNoDups() {
tmpRand = randNum;
while (tmpRand == randNum) {
tmpRand = Math.round(Math.random() * 50000000);
}
randNum = tmpRand;
return tmpRand;
}
$(function () {
var i = 0;
$(".draggable").draggable({
connectToSortable: ".sortable",
helper: 'clone'
});
$(".contentGroupList").sortable({
connectWith: '.contentGroupList',
stop: function (event, ui) {
var currentId = ui.item.children(0).attr('id');
var currentNumber = currentId.split("dt");
var randomKey = randNoDups();
ui.item.children(0).attr({
id: ui.item.children(0).attr('id') + randomKey
});
if ((i + 1) == $('.droptarget').children().size()) {
hideAllElements();
var $formContainer = $('<fieldset>').addClass('dtContent').attr({
id: 'fs' + currentNumber[1] + randomKey
});
var $table = $('<table>').appendTo($formContainer);
var $submit = $('<input>').attr({type: 'submit'}).appendTo($formContainer);
ui.item.append($formContainer);
ui.item.attr({id: 'listItem' + i});
$("span").click(function () { alert($(this).attr('id')); });
i++;
}
}
});
});
</script>
</head>
<body>
<div id="column">
<ul id="draggables">
<li class="draggable"><span class="dt" id="dt0">Draggable item</span></li>
</ul>
</div>
<div id="contentGroups-1" class="contentGroup">
<ul class="droptarget sortable contentGroupList"></ul>
</div>
</body>
</html>
The problem is probably here:
$("span").click(function () { alert($(this).attr('id')); });
This will find every span in the document and alert it's id. Try using the ui object instead:
ui.item.click(function() {
alert(this.id);
});

Categories

Resources