angular-drag-and-drop-lists dragged element disappears (chrome) - javascript

I'm using the angular-drag-and-drop-lists package here to create a drag and drop list. However, the element being dragged always disappears. In all of the demos, you can see the dragged element as you move it around with your mouse. But I am unable to see this element in my implementation below.
<div class="list-item"
ng-repeat="item in items | filter:query"
dnd-draggable="column"
dnd-moved="items.splice($index, 1)"
dnd-effect-allowed="move"
dnd-selected="models.selected = item"
ng-class="{'selected': models.selected === item}"
draggable="true"
>
<div class="icon">
<span class="some-button"></span>
</div>
<div class="title">
{{item.title}}
</div>
</div>
I have set my css as follows:
.dndDragging:not(.dndDraggingSource) {
display: block;
background-color: red;
}
.dndDraggingSource {
display: none;
}
.dndPlaceholder {
background-color: #ddd;
}
I am able to see the placeholder, and I have verified that .dndDraggingSource {display: none} correctly makes the original element disappear. However, the element being dragged as identified by .dndDragging:not(.dndDraggingSource) will show up as a correctly-sized red block with no content.
What's going on behind the scenes on drag? Why does this dragged element show up correctly in the demo code? It seems that it is common to use a display: none on .dndDraggingSource, so I'm pretty sure there is another DOM element that's being dragged around. What is that DOM element and how can I inspect it? Based on behavior, I think there's another element being dragged around. But if you inspect the source code in angular-drag-and-drop-lists.js, the element.on('dragstart', function() {} block isn't doing anything to make a copy of the element tagged with .dndDraggingSource.
== Update ==
So, I realized that if you stuff some gibberish into the the div, it shows up. But neither the span nor the {{item.title}} does. Is there something you need to do with the data model to make this work?

Adding to this that apparently Chrome 50 has a bug with the ghosted copy that is displayed during dragging which can cause it to disappear. The issue and solution are outlined here: https://github.com/marceljuenemann/angular-drag-and-drop-lists/issues/256#issuecomment-231742499.
Personally, I solved it by adding the following:
ul[dnd-list] .dndDragging {
transform:translateZ(0);
}

It turns out that this wasn't about the data model at all. It was about positioning. This particular library expects that all children of dnd-list have relative positioning, and those children, which are tagged with ng-repeat and dndDraggable have static positioning. The part about static positioning wasn't exactly obvious.

Related

Hide parent element on dragstart event

Using the Google Chrome browser, I need to drag-and-drop an item from a menu, in a way so that the menu will automatically close/hide/collapse/disappear/(or something similar) as soon as the dragstart event fires. This has to be done in a way such that the DOM space is freed up, so approaches using "visibility" and "opacity" for instance while possible are not good for this situation.
Instead, it is necessary to do something like display:none or pushing the menu off of the web page (without scrollbar). However, I've gotten stuck trying to accomplish this and could use some help (or if an alternative approach comes to mind that accomplishes the same, please let me know. I also tried a z-index approach without success.):
Approach 1 - Trying to hide dragged item's parent element via absolute positioning
https://jsfiddle.net/gratiafide/4m5r186v/
function dragstart_handler(ev) {
ev.dataTransfer.setData("text/plain", ev.target.id);
ev.currentTarget.parentElement.style.cssText = "position:absolute; right:-5000px;";
}
Approach 2 - Trying to hide dragged item's parent via setting display:none
https://jsfiddle.net/gratiafide/Luj7d089/
function drag(event) {
event.dataTransfer.setData("Text", event.target.id);
document.getElementById('parent').style.display = 'none';
}
You will see in both approaches, the dragged item gets dropped in both instances as soon as the CSS rule gets applied to the dragged item's parent element. I just want to be able to keep dragging the element even though I've hidden or moved the parent element out of sight. Thanks in advance for your help!
You seem to want your parents to disappear by dragging your child's element as it is.
The child element is influenced by the CSS style attribute of the parent element. If parents are erased through css properties such as "display", "visibility", and "opacity", the child element is not visible unconditionally.
Hiding using the "absolute" property(but not z-index -1) is also a way, but unwanted scrollbars may occur depending on the "overflow" attribute of the parent element, and the child element position must be added in reverse and recalculated.
As a result of my test, a dragend event occurred in Chrome when the parent element of the element to be dragged was redrawn. But in Firefox, both of your examples work.
Anyway, to explain based on how it works in Chrome, it is to separate the relationship between Child and Parent and use it as a sibling. Modify your HTML as follows.
<div id='relative_div'>
<div id="parent"></div>
<p id="source" ondragstart="dragstart_handler(event);" draggable="true">Drag me to the Drop Zone below</p>
</div>
Next update your CSS as follows. #parent should serve as a background for filling in #relative_div.
#relative_div {
position: relative;
overflow: hidden;
width: 200px;
height: 100px;
padding: 2em;
}
#parent {
position: absolute;
width: 100%;
height: 100%;
left: 0;
top: 0;
background-color: lightgrey;
}
#source {
position: relative;
cursor: grab;
color: blue;
border: 1px solid black;
}
Now, regardless of whether you use #parent's "position" to push it away, or hide it using "display", "opaicty", or "visibility", #source drag does not stop.
ok, I think my comment was wrong and that you want to remove the space on the page occupied by the origin element (rather than freeing up memory).
To achieve this, add document.body.removeChild(document.getElementById('parent')); to your drop handler. I've made a js fiddle to demonstrate (with the id=spacer div removed and an extra paragraph below it to show the element is removed):
https://jsfiddle.net/dj825rbo/
(revision following comment clarifying that the origin element should disappear as the drag begins)
This is horrible, but works (horrible because you can't see the text while it is being dragged). It relies on a hidden element into which the origin's content is stored while the drag is proceeding. Replacing the 'drop' event listener with a 'mouseup' listeners, allows the content of the temp (hidden element to be transferred to the target where the mouse click was released)
https://jsfiddle.net/dj825rbo/1/

How to combine jQuery SlimScroll and sortableUI?

I wish to have two slimscrolled div and be able to drag and drop elements between them. The latter is tested, and is working perfectly with the sortable method, but when I apply the slimscrolls, the two divs receive the overflow: hidden attribute, which makes the dragged elements disappear when moved outside of the div. As per documentation I saw no option to modify the slimscroll's overflow attribute, which I would like to change to overflow-x: visible and overflow-y: hidden, for obvious reasons. The CSS attribute is applied on element level, so workaround with CSS rules are not an option afaik.
I want the slimscroll to be functional, but I want to be able to drag and drop elements between the two slimscrolled divs. How to proceed?
EDIT
In hope of receiving answer I add a code example:
<div id="container1">
<ul><li>...</li></ul>
</div>
<div id="container2">
<ul><li>...</li></ul>
</div>
<script>
$('#container1').slimScroll({...});
$('#container2').slimScroll({...});
$('#container1').sortable({
connectWith: "#container2",
});
</script>
In the above example, elements from #container1 should be dragged to #container2, but due to the overflow:hidden property applied by the slimScroll(), the dragged element will disappear when dragged outside of the area of #container1. I wish to be able to drag the element and also see the element I am dragging.
The issue was a setting in jquery.slimscroll.js. In v1.3.8 starting from the 160th line I did the following;
// wrap content
var wrapper = $(divS)
.addClass(o.wrapperClass)
.css({
position: 'relative',
overflow: 'visible', // <--- change this from 'hidden' to 'visible' !!!
width: o.width,
height: o.height
});
After applying the above change, the problem I described ceased to exist.

Menu position appearing way off when the canvas it not positionned as top element on the page

Using Draw2d and the menu selection code from the demo but I don't get the expected result...
In the demo, the menu appears on the right side of the clicked element. In my version the menu appears way off to the top.
This seems to be caused by the fact that I have some HTML directly above the canvas (header, etc...). On the contrary if the canvas is at the very top of the page it works well.
Found a way to fix this.
It's all about where you append the menu's HTML and relative positionning
In the demo there isn't any HTML above the canvas (on the website it's an iframe so what you see above is not really there from the canvas perspective) so it works.
The demo is misleading because in the code they add the HTML menu in the body tag. They can do that simply because their page is composed of only two elements : the body and the canvas.
In my case and probably yours too, doing this results in adding the HTML menu far far far far away from the canvas itself resulting in a position that is wayoff !
What they do is :
$("body").append(this.overlay);
What you should do is append the HTML menu (this.overlay) as a sibling of the canvas. Do NOT add it in the canvas itself. If you do, you won't catch click events anymore.
Your HTML should look like this :
<div id="some-parent">
<div id="gfx_holder">THE CANVAS</div>
</div>
And the code updated to
$("#some-parent").append(this.overlay);
But it's not finished yet. As the menu is added using position: absolute you'll need your parent containers set to position: relative so the the child's absolute position would become relative to the parent and not web page. It's CSS... You know...
Also, the parent should be the exact same size as the child canvas !
So the HTML should evolve to this :
<div id="some-parent" style="position: relative; height: 800px">
<div id="gfx_holder" style="height: 800px">THE CANVAS</div>
</div>
And when the menu's HTML is added it should look like that at runtime :
<div id="some-parent" style="position: relative; height: 800px">
<div id="gfx_holder" style="height: 800px">THE CANVAS</div>
<div class="overlayMenu" style="top: 230px; left: 197.391px;">⊕</div>
</div>
See ? The overlayMenu has position: absolute which allows it to be rendered at a correct position...
hf

ExtJS 4.2: Div inside span tag when layout=auto

I am trying to understand the reason behind doing this.
<fieldset id="fieldset-1015" class="x-fieldset x-fieldset-with-title x-fieldset-with-header x-fieldset-default" style="border-width:0;">
<legend id="fieldset-1015-legend" class="x-fieldset-header x-fieldset-header-default">
<div id="fieldset-1015-body" class="x-fieldset-body ">
<span id="fieldset-1015-outerCt" style="display: table; width: 100%; table-layout: fixed;">
<div id="fieldset-1015-innerCt" class="" style="display:table-cell;height:100%;vertical-align:top;">
</div>
</span>
</div>
</fieldset>
I know this a very debatable question. But I want to understand why ExtJS chose to do it this way for their layouts.
I don't see divs inside span in other layout like layout=container
Block elements inside inline elements is discussed in these questions(and many more) -
can tags have any type of tags inside them?
Is putting a div inside an anchor ever correct?
Answer for your question is in comment in code (source: http://cdn.sencha.io/ext-4.2.0-gpl/ext-all-debug-w-comments.js):
// All browsers that support display:table use this template.
// An outerCt with display:table shrink-wraps contents, and contains child
// margins. The table-cell innerCt is required in order to support percentage
// heights on child elements. Originally the outerCt started out as a div, but
// was changed to a span to work around an obscure firefox 3.6 bug where
// placing a Container inside of a fieldset's legend element causes the legend
// to blow up if the outerCt is a div.

Why is this DIV rendering with no dimensions?

http://clifgriffin.com/blockade2/
Ok, I have an unordered list that serves as a list of menu links. In each li there is a div that is set to absolute positioning, bottom: 0. The idea is you hover over the link in the li and jQuery animates the height to show the hidden menu div.
It's a simple concept, but I am apparently confused.
The issue I'm having is that the div that contains the slide down menu doesn't take up any dimensions (according to Firefox and Chrome's calculated style information) when I put it in the li. If I put it anywhere else on the page it renders PERFECTLY. You can see what I mean from the link. The gray menu looking thing at the top is how it is supposed to render inside the li but doesn't.
<div class="ram">
<div class="gray_middle">
<ul>
<li>Guest Services</li>
<li>Concierge / Local Attractions</li>
<li>East Restaurant</li>
<li>Aquarium Lounge</li>
<li>Health Club</li>
<li>Sandcampers Program</li>
<li>Treasure Chest Gift Shop</li>
</ul>
</div>
<div class="gray_bottom">
<img src="images/top_menu_slidedown_gray_bottom.png" />
</div>
There is a bit of javascript going on that is supposed to find the height of the menu div and set the id of the containing li equal to the height so that it can be referenced later. Doesn't matter...the point is, when the div is in the li, its computed height is 0. When it is outside, it's correct.
Any ideas?
This is driving me absolutely batty. I have never had this many issues with something so simple.
Thanks in advance,
Clif
P.S. I added some HTML comments to the destination so that you can better see what I mean.
Absolutely positioned elements are "outside" of a container and can't really determine its size.
Relatively positioned elements impact container size (and content flow) but then they move elsewhere.
Also, for absolutely and relatively positioned elements, you should always give an explicit X,Y position. This avoids some rendering differences, cross browser.
Anyway, I made the following CSS changes and that submenu seemed to render OK on FF 3.6.4:
For <li id="49"> add: height: 230px; overflow: hidden; .
For div.subMenu add: top: 17px; and delete: bottom:0; .
For gray_middle add: height:160px; top:0; and delete: padding-top:20px; .
When you absolutely position an element, it won't expand the size of it's container to the size required to accommodate it.
EXAMPLE
HTML
<div id="outer"><div id="inner">In</div>Out</div>
CSS
#outer {
background-color: red;
}
#inner {
width: 100px;
position: absolute;
top: 100px;
background-color: blue;
}
See it live here - http://www.jsfiddle.net/r7MgY/86/
Hi clifgriffin Had a quick look at you HTML, shame you didn't give us the CSS aswell, but ... there are a few things I'm not sure on - the header says generator WordPress 2.9.2 but the html does look like "familiar" WordPress. If it is WordPress generated then check the wp_list_pages & wp_list_categories tags you are using. Also I serously recommend an upgrade to WP3.0 as it has MUCH more functionality (custome post/page types etc) plus a "built" in menu function.
I think you may be using too much CSS. Most of what you want to acheive can be done with a lot less.
Guest Services
Concierge / Local Attractions
East Restaurant
Aquarium Lounge
Health Club
Sandcampers Program
Treasure Chest Gift Shop
You can then give the ul an ID (remember ID's need to be unique) this will help with any Java you want to use also add to your ram class with a background image class images/top_menu_slidedown_gray_bottom.png. As you use the ram class again without the image. e.g. <div class="ram backgroundimageclass"> You are then saving a lot of "code" and download times etc.
If you give the ram class the attribute "position: relative;" you can then give the UL id the attribute "position: absolute;" the li's can be styled such as
ul#ID li {line-height 30px; etc ...)
ul#ID li:hover {line-height 30px; etc ...)
ul#ID li:hover a {line-height 30px; etc ...)
and so on.
Ohh forgot ... also why not add this code in the head
<meta http-equiv="X-UA-Compatible" content="chrome=1">
And this just after the tag
<!-- DO NOT REMOVE -->
<!-- THIS SECTION SETS THE LAYOUT FOR GOOGLE CHROME FRAME IF YOU NEED FURTHER INFO LOOK HERE http://code.google.com/chrome/chromeframe/ -->
<!-- Google Chrome Frame is a free plug-in that helps you enjoy modern HTML5 web apps within Internet Explorer. -->
<div id="prompt"><!-- if IE without GCF, prompt goes here --></div>
<script type="text/javascript">
CFInstall.check({
mode: "inline", // the default
node: "prompt"
});
</script>
<!-- END THE LAYOUT FOR GOOGLE CHROME FRAME -->
This allows "detection" of the browser and gives them the option (if not installed) to use Google Chrome Frame, you can:
Start using open web technologies - like the HTML5 canvas tag - right away, even technologies that aren't yet supported in Internet Explorer 6, 7, or 8.
Take advantage of JavaScript performance improvements to make your apps faster and more responsive. Enabling Google Chrome Frame is simple. For most web pages, all you have to do is add a single tag to your pages like above and detect whether your users have installed Google Chrome Frame.
If Google Chrome Frame is not installed, you can direct your users to an installation page.
If Google Chrome Frame is installed, it detects the tag you added and works automatically.
Cliff Just "totally" realised what you are trying to do here - sorry took so long to "twig"
OK you can do this with much more ease than you are trying to do at the moment. All it needs is a little JQuery and some basic CSS. No need to positions absolute etc.
In your CSS use { display: none; } for the class="subMenu" as you know this will "hide" it, I might also be tempted to do the same in your JQuery functions to be "doubly sure". Then in the JQuery create a mouseover effect (mouse over "better" than hover) for the class top_menu_links (I think you could take out the classes "aco" and "white_middle" or at least combine them in the css for the relevant ul) to show the .next('ul); you can slide it etc. Then a mouseout function on the ul. That way the ul stays visable until a mouse out event. I have done this quite successfully on a WP theme to display a "dynamic" list of categories on a mouse over event on a div made to look like a button. Sorry don't have the code to hand but will look later and "pass it over"
In addition you can set the ul background image as the approp. <img src="images/top_menu_slidedown_white_bottom.png" /> (or grey) just by setting it to background position: bottom repeat: none; and a bottom padding the height of the image. No need for alt tags etc.
Sorry been "out for a bit" anyhow here is a code I have used to "recreate" your bottom menu. It doesn't do as you suggest it closes after either a mouseout of the "menu item" or the "submenu". To get it to work on the top menu, just change the position from bottom to top:
$(document).ready(function() {
$('.indexMenu').mouseover(function(){
$(this).children().show();
$(this).children().mouseover(function(){
$(this).children().show();
});
});
$('.indexMenu').mouseout(function(){
$('.sub_menu').hide();
});
});
Here is the "html"
<div class="indexMenu">
Menu 1
<div class="sub_menu">
Item
<br />
Item
<br />
Item
</div>
</div>
<div class="indexMenu">
Menu 2
<div class="sub_menu">
Item
<br />
Item
<br />
Item
<br />
Item
</div>
</div>
<div class="indexMenu">
<div class="sub_menu">
Menu 3
<br />
Item
<br />
Item
<br />
Item
<br />
Item
</div>
</div>
<div class="indexMenu">
Menu 4
<div class="sub_menu">
Item
</div>
</div>
Obviously you can "use" any thing in submenu a ul,ol, etc...
And the "simple CSS
.indexMenu {
position: relative;
bottom: 3px;
width: 240px;
height: 32px;
float: left;
line-height: 30px;
border-top: 2px solid #FFFFFF;
text-align:center;
text-transform:uppercase;
text-shadow: 1px 1px 1px rgba(255, 255, 255, 1);
font-weight: 900;
color:#333333;
}
.sub_menu {
display: none;
position: absolute;
bottom: 33px;
width: 240px;
background-color:#DBF3FD;
opacity:0.8;
filter: alpha(opacity=80);
}
OK I've added a filter in the submenu to have a certain transparency
Gentleman,
Thanks for all of your responses! I'm sorry it took me so long to get back to this post.
This whole issue has revealed a few things I don't yet understand about the way HTML elements are rendered.
I was able to solve this problem by switching the main menu blocks to div elements instead of li elements.
This makes no sense to me in that both are rendered approximately the same way as far as I can tell from looking through the computed styles. But, for whatever reason, once the container is a div the contained divs rendered with their proper dimensions which allowed the rest of my code to work properly. I didn't even have to change the attached CSS!
As the main goal of this project was to finish and make the customer happy, I didn't experiment beyond this finding.
I welcome theories on why this would be.
Thanks again.
Clif

Categories