Make divs draggable and droppable for certain elements - html

I have a page with divs that are draggable and droppable. Each div contains nested divs that are also draggable. I want to be able to drag nested divs from div 1 and drop them on div 2 and also the other way around. The jsfiddle where I try to do that is at this link http://jsfiddle.net/fWhDn/
If I move the msn.com link (draggable div) from div 2 to div 1, it isn't dropped into that div. What do must I fix to get the right behavior, i.e. where that link becomes part of div 1?

To get this to work you have to append the draggable div to the respective droppable div. You can do this through the drop event inside the droppable init. I set it up for each droppable div in order to get access to the $(this). It's also important to reset the css of the item as if not it will carry over the position it had when you were dragging it. The following is what I added:
$( "#editdiv .droppable" ).droppable({
drop: function( event, ui ) {
var $item = ui.draggable;
$item.fadeOut(function() {
$item.css( {"left":"", "top":"", "bottom":"", "right":"" }).fadeIn();
});
$item.appendTo( this );
}
});
$( "#editdiv_ .droppable" ).droppable({
drop: function( event, ui ) {
var $item = ui.draggable;
$item.fadeOut(function() {
$item.css( {"left":"", "top":"", "bottom":"", "right":"" }).fadeIn();
});
$item.appendTo( this );
}
});
And here's the updated fiddle: http://jsfiddle.net/TpbZk/

Related

How to correctly override .ng-hide class in order to change hiding/showing nature?

When using ng-hide or ng-show directives a .ng-class is added or removed so DOM elements are visible or not.
However they kinda get positional "removed" as for example, hiding or showing two continous div elements one on top of the other.
<div ng-show="condition1">First div</div>
<div ng-show="condition2">Second div</div>
So, if condition1 evaluates to false first div will be hidden BUT second div will take the position which the just hidden div took.
How can I avoid that? I only want DOM elements to be invisible but not to get somehow removed.
First workaround.
I tried to overried .ng-hide class and getting a secondary class, only-hide, for elements on which I wanted this effect:
.ng-hide.only-hide {
visibility: hidden !important;
}
But didn't get results so far.
I achieved it with this second class approach by setting:
.ng-hide.only-hide {
visibility: hidden !important;
display: block !important;
}
As Angular sets .ng-hide with display:none, I make it invisible but present setting display:block.
To preserve and maintain the space occuped by the div you can't use directly ng-hide or ng-show.
You can use the ng-style directive as following:
<div ng-style="conditionHide1">First div</div>
<div ng-style="conditionHide2">Second div</div>
then your conditionHide1 and conditionHide2 should be like
if (condition1)
$scope.conditionHide1= {'visibility': 'hidden'}; // then div1 will hidden.
else
$scope.conditionHide1= {'visibility': 'visible'}; // then div1 will visible.
if (condition2)
$scope.conditionHide2= {'visibility': 'hidden'}; // then div2 will hidden.
else
$scope.conditionHide2= {'visibility': 'visible'}; // then div2 will visible.
You can change the visibility of the button by changing the $scope.conditionHide1 and $scope.conditionHide2 according to your conditions.
Solution2 by using a custom directive:
Create a new directive named condition and relative to an Attribute. Set-up a watch to watch the value of the attribute and, based on the value, set to the element (in this case the div) an appropriate css style. The value is mapped to the variable showDiv which change his value by clicking on the button. Clicking on the button, the value showDiv became the opposite !showDiv and the watch change the visibility from visible to hidden and vice-versa.
angular.module('MyModule', [])
.directive('condition', function() {
return {
restrict: 'A',
link: function(scope, element, attributes) {
scope.$watch(attributes.condition, function(value){
element.css('visibility', value ? 'visible' : 'hidden');
});
}
};
})
.controller('MyController', function($scope) {
$scope.showDiv = true;
});
<script src="//cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='MyModule' ng-controller='MyController'>
<div condition='showDiv'>Div visible/invisible</div>
<button ng-click='showDiv = !showDiv'>Hide div or show it</button>
</div>

Transitioning child div when its parent is clicked

I want to have a div that is set to transition in height when the button inside it has been clicked & transition back down when the button is clicked again.
It has a child div that has a delayed transition in height after the button has been clicked. I've tried it with hover but how can I accomplish that with the click event?
Also, after both divs are at their full height, how can I make the child div transition back down before the parent div does?
If you can do it with :hover, and want to do it with a click event, use the selector :active - its the proper CSS selector for click events.
If you want it to change actions based on a button click, you might have to use javascript, as I don't know any way to do this with pure css. I've included code in a fiddle I found and modified for you.
JS Fiddle demo
$(document).ready(function() {
var $dscr = $('.description'),
$switch = $('.toggle-link'),
$initHeight = 40; // Initial height
$dscr.each(function() {
$.data(this, "realHeight", $(this).height()); // Create new property realHeight
}).css({ overflow: "hidden", height: $initHeight + 'px' });
$switch.toggle(function() {
$dscr.animate({ height: $dscr.data("realHeight") }, 600);
$switch.html("<button>-</button>");
}, function() {
$dscr.animate({ height: $initHeight}, 600);
$switch.html("<button>+</button>");
});
});

JQuery-UI Hover Show/Hide Multiple DIV's (Same Class, Diff ID's) with Position Fit Function

i have this code
var a = $('p a').hover(function() {
$('#div1').toggle();
});
$('#div1').position({my: 'left top', at: 'left bottom', of: 'a', collision: 'fit'}).hide();
});
It shows / hides and positions ONLY FOR ONE SPECIFIC DIV (by ID ) to the text link.
If i have more than one DIV and more links , how can i globalise the hover and position function to apply for ALL DIVS with the SAME CLASS, but DIfferent ID's, with each text link specifically?
Someone told me instead of using
$('#div1').toggle();
i could use the Class Selector
$('.ThisDIV').toggle();
but this metod is not working to me for more than one DIV...
For ex. i have 2 or more DIV's:
<div id="div1" class="ThisDIV">
and
<div id="div2" class="ThisDIV">
and two links: link1 and link2.
I want when i hover LINK1 show DIV1 and hover LINK2 show DIV2, of course with the Position Function inside the screen (not showing the DIV outside the scree width).
Is so complicated my request...?
You can give common name to your links (to make the difference with other links on the page) and then create exactly the same number of divs with ids div1, div2,.... Then use this code:
$(function() {
$('a[name="special-link"]').each(function(index) {
var correspondingDiv = $('#div' + (index + 1));
$(this).hover(function() {
correspondingDiv.toggle();
});
correspondingDiv.position({my: 'left top', at: 'left bottom', of: this, collision: 'fit'}).hide();
});
});
Doing so you are iterating through all your links and connects them with corresponding divs.
See Feeble. Common class is used only for divs styles.

With JQueryUI Draggable, how to select object being dragged

I am using JQueryUI draggable and I would like to be able to add styling to the draggable element while it is being dragged. I have tried variations on this code:
$(".ui-widget-content").draggable({
drag: function(event, ui) {
$(this).css("width", "50px");
});
However, my attempts have failed and I believe it it because I don't know how to get the draggable element from the ui object. What am I missing?
No need for extra JavaScript. Just use this CSS selector:
.ui-draggable-dragging {
/*
This class is applied to the element while it is being dragged.
This is done automatically by jQueryUI.
*/
width: 50px;
}
Read the docs here: http://jqueryui.com/demos/draggable/#overview-main

Item of sortable element loses its CSS styles when it is being dragged? (If appendTo: 'body')

I have a sortable list of items that returns results based on what the user types in the search box. The results always overflows and here i am using the following css for it:
#list { overflow-x: visible; overflow-y: hidden; }
This allows me to have only a vertical scrollbar. I then drag the individual li's that are in the list over to a droppable area. The sortable functionality is added to the list using the JQuery below:
$("#list").sortable({
connectWith: ".connectedSortable",
helper: 'clone',
appendTo: 'body',
zIndex: 999
});
The reason i use the appendTo: 'body' is to ensure that the item that is being dragged is on top of everything and will not be under the list's other items when being dragged. However, whenever I drag any item from the list, the DIVs that are in the item will have their CSS styling gone.
I understand that this is due to the fact that when the item is dragged, it is appended to 'body' and thus does not have any parent to inherit the original CSS styles.
My question is how do i style the dragged item back to its original styling to make sure it stays the same even if I am dragging/not dragging it? through the events?
EDIT:
Found the reason for the css messing up. It was a random br thrown in between two div's causing it to be interpreted differently when the item was being dragged and appended to the body.
You have two options to sort the problem. One is to create your own helper with the function. This way you can style is any way you want, wrap it in an element, add classes, etc.
The following demo shows the difference, the top one works, the bottom one is broken. http://jsfiddle.net/hPEAb/
$('ul').sortable({
appendTo: 'body',
helper: function(event,$item){
var $helper = $('<ul></ul>').addClass('styled');
return $helper.append($item.clone());
}
});
The other option is not to use append:'body', but to play with zIndex. Your zIndex:999 clearly has no effect, since the default value is 1000. :) The problem with zIndex is that it only matters for siblings, elements within the same parent. So if you have another sortable on your form with a greater zIndex than your current sortable, its items could easily be on top of your dragged one, regardless of the zIndex of your currently dragged item.
The solution is to push your whole sortable on top when dragging starts and restore it when it stops:
$('#mySortable').sortable({
start: function(){
// Push sortable to top
$(this).css('zIndex', 999);
},
stop: function(){
// Reset zIndex
$(this).css('zIndex', 0);
}
});
If the original value matters, you can even save the original zIndex with .data() and retrieve it afterwards.
Thank you DarthJDG. I am aware this thread is a little old but I hope to help others that had the same issue I did.
I had to edit your solution a little bit because the styling was off when appending the item to the helper. I ended up just recreating the list element. Just in case others run into the same issue I did.
I added this into the area where I created the sortable.
I took the text out of the sortable and created a new list item with that as text.
Javascript:
appendTo: 'body',
helper: function(event,$item){
console.log(event);
var $helper = $('<ul class = "styled" id="' + event.originalEvent.target.id + '"><li>' + event.originalEvent.target.innerText + '</li></ul>');
return $helper;
}
I was then able to add custom styling to the draggable object, including custom text with out an issue. The styling I ended up using was that of JQuery Smoothness.
CSS:
.styled li{
margin-left: 0px;
}
.styled{
cursor:move;
text-align:left;
margin-left: 0px;
padding: 5px;
font-size: 1.2em;
width: 390px;
border: 1px solid lightGrey;
background: #E6E6E6 url(https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/themes/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x;
font-weight: normal;
color: #555;
list-style-type: none;
}