I'm running the following html:
<div class="container">
<div class="row">
<div class="col">
<div class="row">
<div class="col">
<div id="container1">
<div class="resizeDiv col-6"></div>
<div class="resizeDiv col-6"></div>
</div>
</div>
<div class="col">
<div id="container2"></div>
</div>
</div>
</div>
</div>
</div>
And this is the JS
var currentParent;
$(".resizeDiv").draggable({
revert: 'invalid',
containment: "#container2",
start: function(){
currentParent = $(this).parent().attr('id');
}
});
$('#container1, #container2').droppable({
accept:'.resizeDiv',
drop: function(event,ui) {
if (currentParent != $(this).attr('id')) {
$(ui.draggable).appendTo($(this)).removeAttr('style');
}
$(this).find("div").on("click", function(){
if($(this).hasClass("col-6")) {
$(this).removeClass("col-6").addClass("col");
} else {
$(this).removeClass("col").addClass("col-6");
}
});
}
});
When I drop one element and I click on it, its class changes from col-6 to col, however when I drop the second item, the toggle classes on the click only works on the second added item and not the first one added.
Here it is a codepen, try adding one item to the second container and the click on it and then drop the second item and try to click on them.
NOTE
Ideally I would like to auto size without the click
Your problem is this
$(this).find("div").on("click", function(){
if($(this).hasClass("col-6")) {
$(this).removeClass("col-6").addClass("col");
} else {
$(this).removeClass("col").addClass("col-6");
}
});
What this does is every time you drop an element it is going to go through ALL divs in that container. That means the ones you already set a click handler on, so when you drop a second item, the first div is going to get a second click handler. If you dropped a third it would get a third and so on.
So when you click the first one you are actually firing off two of these callbacks, and the class gets added in the first and removed in the second.
Since ui.draggable refers to the dragged element use that as a reference to add the click handler
$(ui.draggable).on("click",function(){
let $this = $(this);
if($this.hasClass("col-6")) {
$this.removeClass("col-6").addClass("col");
} else {
$this.removeClass("col").addClass("col-6");
}
//note instead of doing the if else and removeClass().addClass()
//calls you could just do toggleClass('col-6 col')
//it will toggle one off and the other on
$this.toggleClass('col-6 col');
});
If instead you want to get rid of the click handler and just want to add the class directly then do so on ui.draggable
$this = $(this);
$draggable = $(ui.draggable);
if (currentParent != $this.attr('id')) {
$draggable.appendTo($this).removeAttr('style').toggleClass('col-6 col');
}
Also note I am storing the jQuery objects. If you are going to use something like $(this) or $(ui.draggable) multiple times it is better to store it in a variable and use it instead of making multiple calls to jQuery()
The solution I found was to use:
e.stopImmediatePropagation();
Link to doc
Final js code
var currentParent;
$(".resizeDiv").draggable({
revert: 'invalid',
containment: "#container2",
start: function(){
currentParent = $(this).parent().attr('id');
}
});
$('#container1, #container2').droppable({
accept:'.resizeDiv',
drop: function(event,ui) {
if (currentParent != $(this).attr('id')) {
$(ui.draggable).appendTo($(this)).removeAttr('style');
}
$(this).find("div").on("click", function(e){
e.stopImmediatePropagation();
if($(this).hasClass("col-6")) {
$(this).css("background-color", "red");
$(this).removeClass("col-6").addClass("col");
} else {
$(this).css("background-color", "yellow");
$(this).removeClass("col").addClass("col-6");
}
});
}
});
NOTE
Yet I am still trying to auto size if el is dropped next to the other.
Related
I am writing a function where I want to remove an active class from all elements and add it to the one which was just clicked. Problem is that when I click the element all of them get the active class. Please see the code below.
var pagination = $('.pagination div');
function pager() {
pagination.removeClass('active', function(){
$(this).addClass('active');
});
}
$('.pagination div').on("click", function (){
pager();
});
I could use the code below, which works actually, but the reason I want to use the above one is to have possibility adding other functions in it which will be called later on click.
$('.pagination div').on('click',function(){
$('.pagination div').removeClass('active');
$(this).addClass('active');
});
HTML if needed
<div class="pagination">
<div class="pagination1"></div>
<div class="pagination2"></div>
<div class="pagination3"></div>
<div class="pagination4"></div>
</div>
By using a separate function, you are losing your reference to the current object (this). You will need to use a parameter to get your way working.
function pager(element) {
pagination.removeClass('active', function(){
element.addClass('active');
});
}
$('.pagination div').on("click", function (){
pager($(this));
});
I want to use the above one is to have possibility adding other
functions in it which will be called later
Try this:
function pager(el) {
pagination.removeClass('active', function(){
$(el).addClass('active');
});
}
$('.pagination div').on("click", function (){
pager(this);
});
$('div.pagination').on('click', 'div', function(){
$(this).addClass('active').siblings().removeClass('active');
});
How about this:
var pagination = $('.pagination div');
function pager(selector) {
$('.pagination div').removeClass('active');
$(selector).addClass('active');
}
$('.pagination div').on("click", function (){
pager(this);
});
var pagination = $('.pagination div');
function pager(that) {
pagination.removeClass('active', function(){
that.addClass('active');
});
}
$('.pagination div').on("click", function (){
pager($(this));
});
Editable JSFiddle
HTML
<div class="pagination">
<div class="pagination1">Pagination 1</div>
<div class="pagination2">Pagination 2</div>
<div class="pagination3">Pagination 3</div>
<div class="pagination4">Pagination 4</div>
JavaScript
$(function() { // DOM loaded event handler
function pager (element) {
$(".pagination div").removeClass("active");
element.addClass("active");
}
$(".pagination div").click(function() {
var element = $(this);
pager(element);
});
});
CSS
.active {
color : red;
}
I used your function in 2 steps :
First, I remove all active class by using $(".pagination div").removeClass("active"); which actually apply this effect on all sub div
then, I use the element passed through parameter to the function to scope it, and be able to add the proper class
Use id for all the element then add active class to each element which has been click or use e.target this will track the current element
$('.pagination').click(function(e){
$('.pagination').removeClass('active');
$(e.target).addClass('active');
});
I have a element (#dot) which can be dragged. The dragged element (#dot) is just allowed to be in multiple (.way)s but when (#dot) leaves this element then a function should start (for now a alert is enough). I have search on stackoverflow and on other pages but I dont find out somethings like this.
Fiddle
Here is my JS:
$(document).ready(function (){
$('#dot').draggable({
containment: "#world",
});
});
Html:
<div id="world">
<div id="dot"></div>
<div class="way">
</div>
</div>
For now an alert is enough...
My question is, how can i check if the element touches on other element?
Updated answer:
Demo: http://jsbin.com/yorohimi/4
Seems like you can use jQuery draggable and droppable for this:
JS:
$(document).ready(function () {
$('#dot').draggable();
$('.way').droppable({
accept:'#dot',
tolerance:'fit',
over:function(event,ui){
$('p').text('moved inside way');
$('#world').removeClass('green');
},
out:function(event,ui){
$('p').text('moved outside way');
$('#world').addClass('green');
}
});
});
The key is to use tolerance:fit here in droppable. Whenever #dot touches #world the color of #world is changed for visual feedback.
Following method will work only for single .way.
You can compare the position using getBoundingClientRect method and execute your code.
Fiddle: http://jsfiddle.net/9SJam/4/
JS:
$(document).ready(function () {
$('#dot').draggable({
axis: "y",
containment: "#world",
drag: function (event, ui) {
drag_handler($(ui.helper));
}
});
});
function drag_handler(elem) {
var p = elem[0].getBoundingClientRect();
var P = $('.way')[0].getBoundingClientRect();
if ((P.top > p.top) || (P.bottom < p.bottom)) {
console.log('touched');
$('#world').addClass('color');//For visual feedback
} else {
$('#world').removeClass('color'); //For visual feedback
}
}
You need to declare #world as droppable, then you can use it's over event to trigger your function, which is triggered when an accepted draggable is dragged over the droppable.
something like
$( "#world" ).droppable({
over: function() {
// Your logic
}
});
I need hide tooltip on mouseout of link, BUT not if mouseover on tooltip (both have different parents)
For example: we can see it on Facebook when hover on names or avatars friends
I try this but every time i get FALSE
$('a').bind('mouseleave', function () {
var i = $('div.tooltip').is('hover');
if(i===true){
console.log('cursor over the tooltip, so dont hide');
}
else{
console.log('hide tooltip');
}
});
How i can check both condition?
Put both the link and the tool tip in the same parent:
<div id="parent">
link
<div id="tooltip">tooltip</div>
</div>
And then in the script you can just put the mouseleave function on the parent:
$("#parent a").mouseenter(function(){
$("#tooltip").css("display","block"); //or however you handle this
});
$("#parent").mouseleave(function(){
$("#tooltip").css("display","none");
});
If you can't change your markup, use a timed event and abort it when the mouse enter either element, like so:
var timer;
$("a, .tooltip").mouseleave(function() {
timer = setTimeout(doSomething, 10);
}).mouseenter(function() {
clearTimeout(timer);
});
function doSomething() {
console.log('hide tooltip');
}
Here's a FIDDLE
I have a menu which has 8 pictures and I want to write a fade effect for them. I want to show the name of the menu when the mouse goes over it, and hide it when mouse goes out. Here is my code for two of my menu items:
$(".menu_account").mouseover(function(){
$("#menu_name").html('first');
$("#menu_name").fadeIn('slow', function(){
$(".menu_account").mouseout(function(){
$("#menu_name").fadeOut('slow', function(){});
})
});
});
$(".menu_myposts").mouseover(function(){
$("#menu_name").html('second');
$("#menu_name").fadeIn('slow', function(){
$(".menu_myposts").mouseout(function(){
$("#menu_name").fadeOut('slow', function(){});
})
});
});
My problem is when I am on the first item and the name has been appeared, when I move the cursor to the second item before the first fades out, the name's innerHTML changes and it gets ugly. I want to wait for fading out to be completed and start again. I really appreciate any help.
thanx.
Here is my full code:
HTML :
<div id="menu">
<a class="menu_account"></a>
<a class="menu_myposts"></a>
<a class="menu_allposts"></a>
<a class="menu_favorites"></a>
<a class="menu_follow"></a>
<a class="menu_logout"></a>
<a class="menu_help"></a>
<a class="menu_contact"></a>
</div>
<div style="height:20px;width:200px;margin:0 auto;text-align:center;">
<div id="menu_name" style="font-size:30px;color:#A1A1A1;display:none;"></div>
</div>
JS :
$("#menu").ready(function(){
$(".menu_myposts").hover(
function () {
$("#menu_name").html('first');
$("#menu_name").fadeIn('slow', function(){});
},
function () {
$("#menu_name").fadeOut('slow', function(){});
}
);
$(".menu_myposts").hover(
function () {
$("#menu_name").html('second');
$("#menu_name").fadeIn('slow', function(){});
},
function () {
$("#menu_name").fadeOut('slow', function(){});
}
);
});
Correct JS:
$(".menu_item").hover(
function() {
$("#menu_name").html($('#' + this.id + '_name').html());
$("#menu_name").stop(true, true).fadeIn();
},
function() {
$("#menu_name").stop(true, true).fadeOut();
}
);
I guess the mouseout event should be defined outside like this:-
$(".menu_account").mouseover(function(){
$("#menu_name").html('first');
$("#menu_name").fadeIn('slow', function(){
});
});
$(".menu_account").mouseout(function(){
$("#menu_name").fadeOut('slow', function(){});
})
That's why the fadeout happens immediately.
You could reuse the code like this :-
var menuClasses = {'menu_account' : 'first', 'menu_classes' :'second'};
$.each(menuClasses function(index, value) {
$("."+value).hover(dothisOnMouseover(value), dothisOnMouseout())
});
$("td").hover(
function () {
$(this).addClass("hover");
},
function () {
$(this).removeClass("hover");
}
);
function dothisOnMouseover(value)
{
$("#menu_name").html(value);
$("#menu_name").fadeIn('slow', function(){});
}
function dothisOnMouseout()
{
$("#menu_name").html('');
$("#menu_name").fadeOut('slow', function(){});
}
Updates
The solution is to somehow check inside dothisOnMouseout() if the fadeIn() has completed already. But I don't know how to do that. So, I have this other trick to enable mouseover only if fadeOut() is complete -
function dothisOnMouseover(value)
{
//Remove the `onmouseover="dothisOnMouseover()" binding of all other menus here - or may be all menus - check it.
$("#menu_name").html(value);
$("#menu_name").fadeIn('slow', function(){
//On completion of this fade in attach back the `onmouseover="dothisOnMouseover"` event binding all other menus here - Note - do not call `dothisOnMouseout()` here
});
}
Doing so, if you hover on any menu before the fadeOut() completes, nothing will happen. try it out.
I've created a Fiddle that might be interesting. It is similar to the one in this post with the difference that the names of the menu items are created on the fly.
The code from the fiddle:
$("#menu li").hover(
function() {
if (!$(this).data("name")) {
$(this).data("name",
$('<div class="name"></div>')
.text($(this).text())
.hide()
.appendTo("#nameWrapper"));
}
$(this).data("name")
.stop(true, true)
.fadeIn();
},
function() {
$(this).data("name")
.stop(true, true)
.fadeOut();
}
);
The idea is to have a name element for every menu item so you get a nice fade effect when the old name fades out and new one fades in at the same time.
The first part of the first hover function creates a name element if there isn't one. The element is connected with the menu item using the data() function.
The second part of the first hover function just fades in the name element. The second function fades it out.
The trick here is to use stop(true, true) to stop all animation on the element.
EDIT:
You start with a html structure like this one:
<ul id="menu">
<li>First</li>
<li>Second</li>
</ul>
<div id="nameWrapper"></div>
And after a couple of mouseover's over the menu items the nameWrapper div gets filled like so:
<div id="nameWrapper">
<div class="name">First</div>
<div class="name">Second</div>
</div>
The div.name elements is what actually gets shown when you hover over the menu items. The div.name elements are created when you hover over the menu item for the first time, in the folowing code section:
$(this).data("name", // associate the <div class="name"> element with the menu item that is currently hovered - $(this)
$('<div class="name"></div>') // create a div element
.text($(this).text()) // set text inside div to text of the menu item
.hide() // hide the div (it gets faded in later)
.appendTo("#nameWrapper")); // append the element to the element with id nameWrapper
Edit: See this jsFiddle code
I would bind all your menu items at once with a class name with an id attached to each one, like (I'm just guessing your HTML structure here):
<ul id="menu">
<li class="menu-item" id="account">Account</li>
<li class="menu-item" id="myposts">My Posts</li>
</ul>
And your javascript might be something like the below. Keep in mind that it's untested though, and I'm not sure what effect it would have on performance.
bindMouseOver();
$('.menu-item').mouseout(function(){
$('.menu-item').unbind('mouseover'); //disable all mouseovers while fadeOut is happening
$("#menu_name").fadeOut('slow', function(){
bindMouseOver(); //rebind the mouseover event after the fadeOut is completed
});
});
var bindMouseOver = function(){
$('.menu-item').mouseover(function(){
$("#menu_name").html($(this).html()); //use the menu item's innerHTML text, or something else if you prefer
$("#menu_name").fadeIn('slow');
});
};
Here is a JSFiddle I made that kind of simplifies all the JS into one hover listener: Example here
[EDIT] updated to auto load the menu title container...
Code to example:
CSS
#menu_name div{
position:absolute;
display:none;
}
.menu_link{
cursor:pointer;
}
HTML
<div id="menu_name"></div>
<br/>
<div id="menu_account" class="menu_link">link 1</div>
<div id="menu_myposts" class="menu_link">link 2</div>
JavaScript
(function() {
//auto-load the menu title container...
$(".menu_link").each(function(index, item) {
$('#menu_name').append('<div id="' + item.id + '-title">' + item.innerHTML + '</div>');
});
$(".menu_link").hover(
function() {
$('#' + this.id + '-title').fadeIn('medium');
}, function() {
$('#' + this.id + '-title').fadeOut('medium');
});
})();
I setup a jquery dropdown menu that works perfect. It drops down when a user rolls over a link. The problem is that when the user rolls over the content area of the drop down menu, it slides back up. I need to set up the code so that the slidedown box remains in the down position while the user's cursor is still over it.
Here is my HTML:
<ul id="tabnav">
<li class="tab2">My Leases</li>
</ul>
<div id="leases">
<!-- slide down content here -->
</div>
JS Trigger:
<script type="text/javascript">
$(document).ready(function(){
$(".btn-slide").hover(function(){
$("#leases").slideToggle("medium");
$(this).toggleClass("active");
return false;
});
});
</script>
Any ideas?
EDIT: Here is a link to page in question: http://designvillain.com/testbed/600/601.html
I'm not sure if this is what you want, but I'll just drop it here. It waits 500ms before sliding up #leases, and only when appropriate
var isMousedOver;
var hideDropdown = function(a) {
setTimeout( function() {
if (isMousedOver) return;
$("#leases").slideUp("medium");
$(a).removeClass("active");
}, 500);
}
$(".btn-slide").hover(
function(){
$("#leases").stop(true,true).slideDown("medium");
isMousedOver = true;
$(".btn-slide").removeClass("active");
$(this).addClass("active");
var that = this;
$("#leases").data("mouseoutfn", function() { hideDropdown(that) });
},
function(){
isMousedOver = false;
hideDropdown(this);
}
);
$("#leases").hover(
function() {
isMousedOver = true;
},
function() {
isMousedOver = false;
$(this).data("mouseoutfn")();
}
);
Here's a demo: http://jsfiddle.net/mMRZc/
The .hover() binds two events, mouseenter and mouseleave.
I would instead go granular and use the mouseenter() on the .btn-slide and the mouseleave() on the .leases
$(function()
{
$(".btn-slide").mouseenter(function(){
$("#leases").slideToggle("medium");
$(this).toggleClass("active");
});
$("#leases").mouseleave(function(){
$(".btn-slide").toggleClass("active");
$(this).slideToggle("medium");
});
});
EDIT: Note, if the mouse never enters the #leases div, it will not get the mouseleave, and you may need to consider that.
EDIT2: fix my bad finger typing of funciton to function
I assume the div is hidden on page load and you want it to show when you hover over the link? Change toggle to down...
$(document).ready(function(){
$("#leases").hide();
$(".btn-slide").hover(function(){
$("#leases").slideDown("medium");
$(this).toggleClass("active");
return false;
});
});
Does it need to slide back up sometime?