Events on elements created by jquery - javascript

I'm still learning jquery and I'm facing an issue that probably a lot of people have been facing which is just logic but I can't seem to find a good way to learn how to do that.
So my issue is the following:
I'm creating elements called .lieu on the page using jquery. Basically, when you enter a text and click "OK" you created another .lieu that is supposed to display the text "en passant par le bois des lutins" in the destinations tab.
The first one that is created with html is working but not the other ones.
It seems the script is able to execute on the elements created using html (that's probably due to:)
$( document ).ready(function() {});
How can I make that work using the good method?
Thanks a lot.
$(".validate").click( function(){
var name = $(this).closest(".envies").find("input[name='name']").val();
var lieu = $("<div />", {
"class": "lieu"
})
.css({
left: 0,
top: 0
})
.append($("<p>"+name+"</p>"))
.appendTo(document.body);});
$(".lieu").on("mouseenter", function(checklieu) {
var ordredestinations = $("<div />", {
"class": "lieuliste"
})
.css({
})
.append($("<p>en passant par le bois des lutins</p>"))
.appendTo(".destinations");
});
.destinations {
background-color: lightgrey;
position: fixed;
right: 0;
top: 0;
}
.envies {
background-color: grey;
position: fixed;
right: 300px;
top: 0;
width: 250px;
height: 50px;
}
.lieu{
position: absolute;
left:0px;
top: 100px;
background-color: red;
width: 200px;
height: 100px;
border-radius: 250px;
text-align: center;
vertical-align: middle;
line-height: 100px; /* The same as your div height */
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
<div class="lieu"><p>bois des lutins</p></div>
<div class="destinations"></div>
<div class="envies">
<input type="text" id="name" name="name" size="10" placeholder="name">
<button class="validate">OK</button>
</div>
</body>
<script type="text/javascript"></script>

A think I see your problem.
When a document (webpage) loads, specific targeted jQuery functions like yours..
$(".validate").click( function() {
// ...
});
// and...
$(".lieu").on("mouseenter", function() {
// ...
});
..will only bind upon the document being ready, more than like because you are using these inside $(document).ready(function(). So when doc is ready, the above 2 functions run and bind.
Running functions like you are within doc ready is good practice.
However, if you intend to automatically bind existing executed functions to newly added document elements.. then your first 2 functions are out of scope.
You need to look into .on() https://api.jquery.com/on/
For example, if you want newly added document elements like .lieu divs, to be hit by your mouseover function, then you use .on function like this...
$(document).on("mouseenter", ".lieu", function()
The .on() second param is the .lieu selector, within $(document) as the main jQuery selector object.
Meaning if you append any number of new .lieu divs to the document html, using .on() selector param within $(document) will always be in scope of the mouseover event on this selector.

Related

Scroll function issue in JavaScript

I'm new to frond end development, and unfortunately have some issues calling a JavaScript function.
I have following function:
<script type="text/javascript">
$(document).ready(function () {
$("#table_div").scroll(function () {
alert("test successful");
jQuery('#divHeader').scrollLeft(jQuery('#table_div').scrollLeft());
jQuery('#firstcol').scrollTop(jQuery('#table_div').scrollTop());
jQuery('#lastcol').scrollTop(jQuery('#table_div').scrollTop());
});
});
</script>
and HTML is defined as:
<div id="divHeader" class="firstpanel">
<div id="firstcol" class="firstcolumn">
<div id="table_div" class="contentpanel">
which is styled as:
.contentpanel {
overflow: scroll;
width: 300px;
height: 500px;
position: relative;
}
.firstpanel {
overflow: hidden;
width: 284px;
}
.firstcolumn {
overflow: hidden;
height: 500px;
}
and I'm experiencing a problem, since the "alert" in my JavaScript function is not triggered, when I debug my application. I have made a test in JSFiddle with exacly the same code, and it works very well, since the alert function is called, once I start scrolling my div.
I'm using JQuery 1.5.1 in my application and will prefer to prevent using a newer version in JQuery. Is the JQuery version the issue in this case ?.
You are attaching the event when the element is not render by DOM. You should wrap that code in a $(document).ready() or use delegation events:
$(document).on('scroll', "#table_div", function () {
// code
});

Click Propagation failing in Jquery

For part of the site I'm working on, I have a set of sidebars that can pull out. To have them hide when the users are done with them, I've set up a div with a click event (see below) so that whenever the user clicks somewhere outside of the sidebar, the sidebar closes. The problem that I'm running into, however, is that the click event handler is grabbing the event, running its method, and then the click event seems to stop. I've tried using return true and a few other things I've found around here and the internet, but the click event just seems to die.
$('.clickaway').click(function() {
$('body').removeClass(drawerClasses.join(' '));
return true;
});
EDIT: Here is a fiddle with an example: https://jsfiddle.net/2g7zehtn/1/
The goal is to have the drawer out and still be able to click the button to change the color of the text.
The issue is your .clickaway layer is sitting above everything that's interactive, such as your button. So clicking the button, you're actually clicking the layer.
One thing you could do is apply a higher stacking order for elements you want to interact with, above the .clickaway layer. For example, if we apply position: relative, like this:
.show-drawerHotkey .ColorButton {
position: relative;
}
The element will now be in a higher stacking order (since it comes after the clickaway, and we've applied no z-index to clickaway)
Here's a fiddle that demonstrates: https://jsfiddle.net/2g7zehtn/5/
Using this somewhat famous SO answer as a guide, you can bind to the $(document).mouseup(); event and determine whether certain "toggling" conditions apply:
[EDIT] - Example updated to illustrate clicking a link outside of the containing div.
// Resource: https://stackoverflow.com/questions/1403615/use-jquery-to-hide-a-div-when-the-user-clicks-outside-of-it
var m = $('#menu');
var c = $('#menuContainer');
var i = $('#menuIcon');
i.click(function() {
m.toggle("slow");
});
$(document).mouseup(function(e) {
console.log(e.target); // <-- see what the target is...
if (!c.is(e.target) && c.has(e.target).length === 0) {
m.hide("slow");
}
});
#menuIcon {
height: 15px;
width: 15px;
background-color: steelblue;
cursor: pointer;
}
#menuContainer {
height: 600px;
width: 250px;
}
#menu {
display: none;
height: 600px;
width: 250px;
border: dashed 2px teal;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
I'm a link outside of the container
<div id="menuContainer">
<div id="menuIcon"></div>
<div id="menu"></div>
</div>

Unable to override click events to anchor tag from a user created function

I don't know how to explain my situation, please edit my question if you can explain it more clearly.
I am able to override click events of anchor tag from window.load or document.ready but the problem comes when I am trying it from a user created function.
My JavaScript code is:
$('#up').click(function(){
$('#Vote').html("<div id=\"aniDiv\" style=\"background:green;height:25px;width:80px;position:absolute;float:left\" class=\"base\"></div><div class=\"overlay\"><a style=\"text-decoration:none;color:black\" id='unvote' href=\"#\">You upvoted. Click to take vote back.</a></div>");
$("#aniDiv").animate({width:"10px"});
$("#Vote").width("350px");
attachUnvote();
});
$('#down').click(function(){
$('#Vote').html("<div id=\"aniDiv\" style=\"background:red;height:25px;width:50px;position:absolute;float:left\" class=\"base\"></div><div class=\"overlay\"><a style=\"text-decoration:none;color:black\" id='unvote' href=\"#\">You downvoted. Click to take vote back.</a></div>");
$("#aniDiv").animate({width:"10px"});
$("#Vote").width("350px");
attachUnvote()
});
function attachUnvote()
{
$('#unvote').click(function(){
$('#Vote').html("<a style='text-decoration:none;background-color:green;padding:3px;color:white;' id='up' href='#'>Up</a><a style='text-decoration:none;background-color:red;padding:3px;color:white' id='down' href='#'>Down</a>");
});
}
My objective is that after attachUnvote() function sets the HTML of #Vote element, then it should call the code just above attachUnvote() function. I tried to enclose the code above it in another function and called that function in attachUnvote() but its not working.
You can find Live Demo, HTML and CSS here: http://jsfiddle.net/aishwaryashivapareek/xV3x8/
You can avoid having to attach and unattach these event handlers by using a delegated event handler on the #Vote wrapper.
Your updated code would look like this:
$('#Vote').on('click','#up',function(){
$('#Vote').html("<div id=\"aniDiv\" style=\"background:green;height:25px;width:80px;position:absolute;float:left\" class=\"base\"></div><div class=\"overlay\"><a style=\"text-decoration:none;color:black\" id='unvote' href=\"#\">You upvoted. Click to take vote back.</a></div>");
$("#aniDiv").animate({width:"10px"});
$("#Vote").width("350px");
});
$('#Vote').on('click','#down',function(){
$('#Vote').html("<div id=\"aniDiv\" style=\"background:red;height:25px;width:50px;position:absolute;float:left\" class=\"base\"></div><div class=\"overlay\"><a style=\"text-decoration:none;color:black\" id='unvote' href=\"#\">You downvoted. Click to take vote back.</a></div>");
$("#aniDiv").animate({width:"10px"});
$("#Vote").width("350px");
});
$('#Vote').on('click','#unvote',function(){
$('#Vote').html("<a style='text-decoration:none;background-color:green;padding:3px;color:white;' id='up' href='#'>Up</a><a style='text-decoration:none;background-color:red;padding:3px;color:white' id='down' href='#'>Down</a>");
});
Event delegation is the way to go.
I might be nitpicking here but this also makes coding fun instead of falling into a spaghetti mess. Have some pointers which would make your life easier.
Avoid inline styles. use classes instead. (Would help in separation of concerns)
Use functions to avoid repetitive code.
HTML
<div id='Vote' style="margin:0">
<a class="p-small bg-green" id='up' href="#">Up</a>
<a class="p-small bg-red" id='down' href="#">Down</a>
</div>
CSS
body {
font-family:'segoe ui'
}
.overlay {
width: 100%;
height: 100%;
position: absolute;
left: 10px;
z-index: 10;
}
.base {
width: 100%;
height: 100%;
position: absolute;
left: 0px;
}
/* Default styling for anchors */
a {
text-decoration:none;
color: white;
}
.p-small {
padding: 3px;
}
.bg-red {
background-color:red;
}
.bg-green {
background-color:green;
}
.black {
color: black;
}
#aniDiv {
height: 25px;
width: 80px;
}
JAVASCRIPT
var $defaultDiv = "<a class='p-small bg-green' id='up' href='#'>Up</a>"
+ "<a class='p-small bg-red' id='down' href='#'>Down</a>",
$animatedDiv = "<div id='aniDiv' class='base {{bg}}'></div>"
+ "<div class='overlay'>"
+ "<a class='black' id='unvote' href='#'>You {{vote}}. Click to take vote back.</a></div>";
$('#Vote').on('click', '#up', function() {
animateDiv("bg-green", true);
});
$('#Vote').on('click', '#down', function() {
animateDiv("bg-red", false);
});
$('#Vote').on('click', '#unvote', function() {
$('#Vote').html($defaultDiv);
});
function animateDiv(bgColor, upVoted) {
$('#Vote').html($animatedDiv.replace("{{bg}}", bgColor)
.replace("{{vote}}", upVoted ? "upvoted" : "downvoted"));
$("#aniDiv").animate({
width: "10px"
});
$("#Vote").width("350px");
Working Fiddle

How should i improve my jQuery click funciton?

So i'm learning some jQuery at the moment and got somewhat stuck with this .click function. I'm trying to "turn a light on and off", so to speak.
I am able to do so, but only once. Why is that, that my code only runs for one click event per item, and how should i improve it?
Link to my JSfiddle.
HTML
<div class="lightOn"></div>
<div class="lightOff"></div>
jQuery
$('.lightOn').click(function() {
$(this).removeClass('lightOn');
$(this).addClass('lightOff');
});
$('.lightOff').click(function() {
$(this).removeClass('lightOff');
$(this).addClass('lightOn');
});
CSS
.lightOn {
height: 90px;
width:90px;
background-color:yellow;
border-radius: 100%;
float:left;
margin:10px;
}
.lightOff {
height: 90px;
width:90px;
background-color:grey;
border-radius: 100%;
float:left;
margin:10px;
}
The issue is because you are removing the class you are selecting by, so for successive clicks the element no longer exists. Instead have a common class which remains, but add one to it to light up the object. Try this:
<div class="light"></div>
<div class="light"></div>
.light.on {
background-color:yellow;
}
.light {
height: 90px;
width:90px;
background-color:grey;
border-radius: 100%;
float:left;
margin:10px;
}
$('.light').click(function() {
$(this).toggleClass('on');
});
Example fiddle
This method has the benefit of being able to handle x number of .light elements wihtout having to amend the jQuery selector you use.
The problem is that you bind the functions to elements, not to selectors. That is to say, you bind a function that removes the class lightOn to the element that had that class originally. That function only ever removes the lightOn class and adds the lightOff class, even if that has already been done once.
There are two ways to fix this. One is with on and event delegation, which allows you to do something akin to binding to a selector. It attaches the handler to a parent element, and makes use of the fact that all ancestor elements are notified of events that originated on their descendents. So the function might be bound to document.body, but only elements that originated on an element matching the .lightOn selector will trigger the handler:
$(document.body).on('click', '.lightOn', function() {
$(this).removeClass('lightOn').addClass('lightOff');
}).on('click', '.lightOff', function() {
$(this).removeClass('lightOff').addClass('lightOn');
});
http://jsfiddle.net/lonesomeday/C6f7u/5/
Better, however, is to make use of jQuery's toggleClass function, which removes classes if the element currently has them and adds them if it doesn't.
$('.lightOn,.lightOff').click(function() {
$(this).toggleClass('lightOn lightOff');
});
http://jsfiddle.net/lonesomeday/C6f7u/2/
What about
$('.lightOn, .lightOff').click(function() {
$(this).toggleClass('lightOn lightOff');
});
Demo: Fiddle
You can try using toogleClass of jquery
http://api.jquery.com/toggleClass/
It's a good practice to attach your events to the parent element. In your case this is even mandatory, because you are changing the classes, which are used during the event binding. So, your HTML:
<div class="ligths">
<div class="lightOn"></div>
<div class="lightOff"></div>
</div>
JS:
$(".ligths").on("click", "div", function(e) {
var el = $(this);
if(el.hasClass("lightOn")) {
el.removeClass("lightOn").addClass("lightOff");
} else {
el.removeClass("lightOff").addClass("lightOn");
}
});
JSFiddle: http://jsfiddle.net/C6f7u/7/

jquery ui droppable's greedy setting is not working?

By setting droppable widget's greedy to true, only the top-most element should respond to a drop event. There's really no complexity here but I just cannot get it to work. And this is all I have so not much to work on:
CSS:
.page{
position: absolute;
width: 150px;
height: 150px;
left: 0px;
top: 0px;
text-align: center;
background: #F0FFFF;
border: 1px solid #89B;
}
HTML:
<div class = 'page' id = 'page1'> page1 </div>
<div class = 'page' id = 'page2'> page2 </div>
<div class = 'page' id = 'page3'> page3 </div>
JS:
document.ready = function(){
$('.page').draggable()
$('.page').droppable({
greedy: true,
drop: function( event, ui ){
console.log( 'assert drop once')
}
})
}
what's happening right now is that all the dropped on elements are responding to the drop event. Since there's so little code to hold on to, I have no idea how to diagnose this.
Reading the documentation for the greedy property I'm not sure I understand the same as you:
By default, when an element is dropped on nested droppables, each droppable will receive the element. However, by setting this option to true, any parent droppables will not receive the element.
For me it means if you have a large div droppable which contains another smaller div droppable then if you drop an element in the small one only the small one will receive the event.
Check this demo to understand what I'm explaining : http://jquery-ui.googlecode.com/svn/tags/1.6rc4/demos/droppable/greedy.html

Categories

Resources