unexpected jquery event behaviour from within contained div - javascript

I am seeing unexpected behaviour on a small HTML widget ive recently created. Three successively embedded divs each one has a marker and a menu which show up on entry into the div and hide on exit. The marker is intended to track the vertical mouse position. Problem here is that the mouseover event fires only when the mouse is over the marker and not when the mouse over the containing div.
http://jsfiddle.net/laurencefass/f47a7a2r/
$( ".outer, .inner, .middle" )
.mouseenter(function(e) {
$(this).children(".content:first").show();
$(this).parents().children(".content:first").hide();
$(this).children(".marker:first").show();
$(this).parents().children(".marker:first").hide();
})
.mouseleave(function(e) {
$(this).children(".content:first").hide();
$(this).parents().children(".content:first").show();
$(this).children(".marker:first").hide();
$(this).parents().children(".marker:first").show();
})
.mouseover(function(e) {
$(".content", $(this)).html("left = " + e.pageX + " right = " + e.pageY);
var marker = $(this).children(".marker");
marker.offset({top:e.pageY - marker.height()/2, right:0});});
.outer, .middle, .inner {
font-size:0.8em;
position:absolute;
border:5px solid black;
background-color:lightgray;
text-align:center;
}
.outer {
top:10%;
left:10%;
width:80%;
height:500%;
}
.middle {
top:5%;
left:20%;
width:60%;
height:60%;
}
.inner {
top:5%;
left:30%;
width:40%;
height:60%;
}
.content {
background-color:aliceblue;
min-height:2em;
min-width:50px;
display:none;
}
.marker {
height:50px;
width:5em;
background-color:black;
position:absolute;
right:0px;
margin-right:2px;
display:none;
color:white;
fontsize:0.8em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
<div class="outer">
<div class="content">outer menu</div>
<div class="marker">widget</div>
<div class="middle">
<div class="content">middle menu</div>
<div class="marker">widget</div>
<div class="inner">
<div class="content">inner menu</div>
<div class="marker">widget</div>
</div>
</div>
</div>

This can be done much easier just using CSS. You can use this functionallity for your widgets too.
.outer:hover>.content,
.middle:hover>.content,
.inner:hover>.content{
display: block;
}
Then you can strip out your mouseenter and mouseleave
$( ".outer, .inner, .middle" )
.mouseover(function(e) {
var marker = $(this).children(".marker");
marker.offset({top:e.pageY - marker.height()/2, right:0});
});
JSFiddle
If you only want to show the widget of the element hovered you have to use jQuery, Furthermore you would probably use mosemove() event to have it at the mouse position all the time.
$( ".outer, .inner, .middle" ).mousemove(function(e) {
e.stopPropagation();
var marker = $(this).children(".marker");
marker.eq(0).show();
marker.offset({top:e.pageY - marker.height()/2, right:0});
});
$( ".inner, .middle" ).mouseenter(function(e) {
if($('.marker', $(this).parent()).eq(0).length){
$('.marker', $(this).parent()).eq(0).hide();
}
});
$( ".outer, .inner, .middle" ).mouseleave(function(e) {
if($('.marker', $(this).eq(0)).length){
$('.marker', $(this).eq(0)).hide();
}
});
JSFiddle

my expectation: a rhs "floating" widget to track the vertical position of the mouse and be visible only as long as the cursor is within scope of the marker's container.

Related

CSS Scale and Transform causing overlaps

In HTML page I am trying to achieve zoom functionality using CSS transform scale property. Inside the HTML page, I am having more div elements and all are placed using absolute position technique. Then I apply the scale property to each div and I was able to see like zoom but all div positions gots collapsed each other. So how to avoid collapse and maintain the gap between each other after applied scaling.
Please suggest me how to stop overlapping and how to calculate left and top position of each element accordingly to scale property.
var zoomScale = 1;
$(document).ready(function(){
$("#zoomin").click(function(){
if(zoomScale >=4 ) return;
zoomScale = zoomScale +1;
dispStatus();
applyZoomIn();
});
function applyZoomIn(){
$(".zoomable").each(function(index){
var left = $(this).position().left;
var top = $(this).position().top;
var newLeft = left*zoomScale +"px";
var newTop = top*zoomScale +"px";
$(this).css('transform',' scale('+zoomScale+','+zoomScale+')')
});
}
function dispStatus(){
$("#displayStatus").text("Current Zoom Scale : "+zoomScale);
}
dispStatus();
});
#container{
width:500px;
height:500px;
border:1px solid red;
position:relative;
overflow:auto;
}
.zoomable{
background-color:lightblue;
border:1px solid red;
width:100px;
height:100px;
position:absolute;
transform-origin: top left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<button id="zoomin"> Zoom In</button>
<div id="displayStatus"></div>
<br/><br/>
<div id="container">
<div class="zoomable">First Div</div>
<div class="zoomable" style="left:105px">Second Div</div>
</div>
JSFiddle Link
You can add .zoomable div into one more parent (called .inner-container) and add zoom functionality to it. So that .container div will not get zoomed and zoomable div will maintain position.
See the Snippet below:
var zoomScale = 1;
$(document).ready(function(){
$("#zoomin").click(function(){
if(zoomScale >=4 ) return;
zoomScale = zoomScale +1;
dispStatus();
applyZoomIn();
});
function applyZoomIn(){
$(".inner-container").css('transform',' scale('+zoomScale+','+zoomScale+')');
}
function dispStatus(){
$("#displayStatus").text("Current Zoom Scale : "+zoomScale);
}
dispStatus();
});
.zoomable{
background-color:lightblue;
width:100px;
height:100px;
position:absolute;
border:1px solid red;
}
#container{
width:500px;
height:500px;
border:1px solid red;
position:relative;
overflow:auto;
}
.inner-container{
transform-origin: top left;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button id="zoomin"> Zoom In</button>
<div id="displayStatus"></div>
<br/><br/>
<div id="container">
<div class="inner-container">
<div class="zoomable">First Div
</div>
<div class="zoomable" style="left:105px">Second Div
</div>
</div>
</div>
<br/><br/>
You can also test it here

JQuery draggable item disappears in droppable on droppable.append(draggable)

Using JQuery draggable/droppables to allow me to drag divs from one container to another and have them inserted as children into the container. I can see the move in HTML but on the screen the div disappears when i release the draggable into the target.
http://jsfiddle.net/laurencefass/tqqLxquL/2/
<div id="left" class="droppable">
<div class="draggable">1</div>
<div class="draggable">2</div>
<div class="draggable">3</div>
<div class="draggable">4</div>
</div>
<div id="right" class="droppable">drag blocks in here</div>
JQuery
$('.draggable').draggable();
$(init);
function init() {
$('.draggable').draggable();
$('.droppable').droppable({
drop: handleDropEvent
});
}
css
.draggable {
width:50px;
height:50px;
background:gray;
padding:5px;
margin:5px;
border-radius:10px;
z-index:100;
display:block;
}
.droppable {
box-sizing:border-box;
border:2px solid black;
width:50%;
float:left;
min-height:300px;
}
Here is a working exemple of what I understood you want to do.
http://jsfiddle.net/tqqLxquL/5/
The dragged element have a left property when dropped, you have to override it.
function handleDropEvent( event, ui ) {
console.log($(ui.draggable[0]));
var $draggable = $(ui.draggable[0]);
$draggable.appendTo(this);
$draggable.css({
left: 0
})
}

close overlay except if "special" Div is clicked with jQuery/Javascript

I have a div called "MyDiv". When this div is clicked an overlay is shown with a "MyDiv_subDiv" appended. When user clicks on the overlay the view should disappear but NOT if iser clicks on "MyDiv_subDiv".
I've found a similar question here and tried it out, here is my code:
var $MyDiv = $('#MyDiv');
var $overlay = $('<div id="overlay"></div>');
var $MyDiv_subDiv = $('<div id="MyDiv_subDiv" class="subDiv">\n\
<div class="subDivContent">\n\
<div class="subDivContent">\n\
<p>some content</p>\n\
</div>\n\
</div>\n\
</div>');
//Add overlay
$("body").append($overlay);
//When overlay is clicked
$overlay.click(function () {
//Hide the overlay
$overlay.hide();
$overlay.empty();
});
$MyDiv.click(function (event) {
event.preventDefault();
$overlay.show();
$overlay.append($MyDiv_subDiv);
});
$MyDiv_subDiv.click(function (event) {
event.stopPropagation();
});
#overlay {
background:rgba(0,0,0,0.7);
width:100%;
height:100%;
position:absolute;
top:0;
left:0;
display:none;
text-align:center;
}
.subDiv{
width: 400px;
height: 125px;
margin: 0 auto;
}
#MyDiv_subDiv{
background-color: lightgreen;
}
#MyDiv{
width: 185px;
height: 80px;
background-color: lightgray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="MyDiv">
Click to show MyDiv_SubDiv
</div>
The problem is: It only works when "MyDiv" is clicked first time. When overlay is closed and "MyDiv" is clicked second time and then click on "MyDiv_subDiv" it disappears - and it shouldn't!
Any help is appreciated!
From jquery.empty
To avoid memory leaks, jQuery removes other constructs such as data
and event handlers from the child elements before removing the
elements themselves.
If you want to remove elements without destroying their data or event
handlers (so they can be re-added later), use .detach() instead.
So you have to use .detach to keep the event.
And as .detach is apply on self, not on child, you have to change
$overlay.empty(); to $MyDiv_subDiv.detach(); or $overlay.children().detach();
or you can rebind the event everytime you append it to $overlay.
var $MyDiv = $('#MyDiv');
var $overlay = $('<div id="overlay"></div>');
var $MyDiv_subDiv = $('<div id="MyDiv_subDiv" class="subDiv">\n\
<div class="subDivContent">\n\
<div class="subDivContent">\n\
<p>some content</p>\n\
</div>\n\
</div>\n\
</div>');
//Add overlay
$("body").append($overlay);
//When overlay is clicked
$overlay.click(function () {
//Hide the overlay
$overlay.hide();
$overlay.children().detach();
});
$MyDiv.click(function (event) {
event.preventDefault();
$overlay.show();
$overlay.append($MyDiv_subDiv);
});
$MyDiv_subDiv.click(function (event) {
event.stopPropagation();
});
#overlay {
background:rgba(0,0,0,0.7);
width:100%;
height:100%;
position:absolute;
top:0;
left:0;
display:none;
text-align:center;
}
.subDiv{
width: 400px;
height: 125px;
margin: 0 auto;
}
#MyDiv_subDiv{
background-color: lightgreen;
}
#MyDiv{
width: 185px;
height: 80px;
background-color: lightgray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="MyDiv">
Click to show MyDiv_SubDiv
</div>

Add and remove class different elements

So im currently learning jquery and a little bit of tweenlite for animations (I wanna keep it basic). So im currently building a portfolio grid but I wanna add on a click of an element that the other element is fading in (sliding from right it doesn't matter).
But I can't find a way to make it work that 1 element have 1 box to show and the other element have a different box to show without coping the code over and over and change a simple number everytime, there must be a way to make it work without going to repeat the code over and over.
I created a codepen to show where my struggles are.
I hope I'm pretty clear with describing this problem :)
HTML
<div class="box">
<div class="show">Show 1</div>
</div>
<div class="bigbox">
<div class="removeit">
<div class="bigshow">Bigshow 1</div>
</div>
</div>
<div class="box">
<div class="show">Show 2</div>
</div>
<div class="bigbox">
<div class="removeit">
<div class="bigshow">Bigshow 2</div>
</div>
</div>
</div>
CSS
.container {
overflow: auto;
margin: 0 auto;
width:500px;
}
.box {
height:200px;
width:200px;
background:yellow;
text-align:center;
cursor:pointer;
margin:0 auto;
float:left;
margin-right:50px;
}
.bigbox {
height:100%;
width:100%;
background-color: grey;
z-index:100;
left:0;
opacity: 0;
position: fixed;
display:none;
top:0;
.removeit {
height:100px;
width: 100px;
top: 0;
right:0;
background-color: blue;
margin:0 auto;
cursor:pointer;
}
}
.show {
display:block;
}
.noscroll {
overflow:hidden;
}
Javascript
$(".box").click(function(){
$(".bigbox").addClass("show");
TweenLite.to($('.bigbox'), 0.5, {
opacity:1,
autoAlpha:1
});
});
$(".removeit").click(function(){
TweenLite.to($('.bigbox'), 0.5, {
autoAlpha:0,
opacity:0
});
});
The codepen
http://codepen.io/denniswegereef/pen/MwjOXP
As I mentioned in comments, I think it is possible by finding the common ground between box and bigbox and if we are to not modify HTML. That common ground should be the index value from their respective classes.
So store a clickedIndex variable first, inside the click handler
like so: var clickedIndex=$('.box').index($(this));.
And then feed this clickedIndex to get a selective bigbox like so: var
bigbox=$(".bigbox").eq(clickedIndex);.
And finally, use this bigbox variable further to fade in or out.
Here is your modified JavaScript:
var bigbox = null;
var clickedIndex = -1;
var boxElements=$(".box");
var bigboxElements=$(".bigbox");
var removeItElements=$(".removeit");
boxElements.click(function() {
clickedIndex = boxElements.index($(this));
bigbox = bigboxElements.eq(clickedIndex);
bigbox.addClass("show");
TweenLite.to(bigbox, 0.5, {opacity: 1,autoAlpha: 1});
});
removeItElements.click(function() {
clickedIndex = removeItElements.index($(this));
bigbox = bigboxElements.eq(clickedIndex);
TweenLite.to(bigbox, 0.5, {autoAlpha: 0,opacity: 0});
});
The only problem with this approach is that it is very dependant on the order with which the HTML has been laid out.

Jquery Sortable. Adjusting CSS on Selected / Drag

Using Jquery Sortable. I want to do a simple css switch function so that I can change the background colour of the field I have selected (<div class='bar-across') from a white to a yellow bg using a css class .selected (<div class="bar-across selected">) . When I release the mouse / click, I would like for it to return to its original state.
Fiddle
HTML:
<div id="reorder-list">
<div id="listItem_1" class="bar-across CF"><span class="handle">Drag</span>Item 1</div>
<div id="listItem_2" class="bar-across CF"><span class="handle">Drag</span>Item 2</div>
<div id="listItem_3" class="bar-across CF"><span class="handle">Drag</span>Item 3</div>
</div>
Javascript:
$(document).ready(function () {
$("#reorder-list").sortable({
placeholder: "destination",
forcePlaceholderSize: true,
handle: '.handle',
update: function () {
var order = $('#reorder-list').sortable('serialize');
$("#info").load("billboard-sort.php?" + order);
}
});
});
CSS:
.bar-across {
background:#fff;
border:1px solid #ccc;
margin-bottom:5px;
width: 100%;
}
#reorder-list div .handle {
cursor: move;
padding:0;
float:left;
background:#0C6;
padding: 10px;
}
.destination {
background:#1c5dbb;
width: inherited;
}
.selected {
background:#FF0;
}
/* Clearfix
============================================================================ */
/* Clearfix */
.CF:after {
content:".";
display:block;
height:0;
clear:both;
visibility:hidden;
}
.CF {
display:inline-block;
}
Have a look into the events start and stop in the Sortable API. By using them, you can just add or remove your desired class to/from the current, dragged element. Access is possible via
$(ui.item).doStuff();
where ui is of course the second of the event callback parameter.

Categories

Resources