Cloned Draggable Element is No Longer Draggable - javascript

I want to be able to drag an element from one div into another, keeping the original where it is and making a clone in the second div. Once the cloned element is in the second div it should still be draggable.
I have implemented this twice, once with plain javascript and once using directives in Angular JS.
In the plain javascript implementation everything works as intended; a cloned object can be dragged again.
However, in the Angular JS implementation, cloned objects cannot be dragged. I'm not sure why it isnt keeping the draggable property.
Here is my code:
HTML
<!DOCTYPE html>
<head>
<title>Drag and Drop Test</title>
<!-- JQuery -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!-- Bootstrap CSS CDN -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- Angular JS -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<!-- Jitsi External -->
<script src="https://meet.jit.si/external_api.js"></script>
<!-- Local JS -->
<script type="text/javascript" src="../js/dragdrop.js"></script>
<!-- Local CSS -->
<link rel="stylesheet" href="../css/dragdrop.css">
</head>
<body ng-app="myApp">
<div>
<div class="dragdrop-panel" id="drag-from-div">
<h1>Icons</h1>
<div id="dragme" class="draggablewithjs" draggable="true" ondragstart="drag(event)">
</div>
<div id="dragme2" class="draggablewithangular" drag-item>
</div>
</div>
<div class="dragdrop-panel" id="drop-to-div" drop-area>
<h1>Selected</h1>
</div>
<div class="dragdrop-panel" id="trash-div" drop-area>
<h1>Trash</h1>
</div>
</div>
</body>
Javascript
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
});
app.directive("dropArea", function() {
return {
link: function(scope,elem, attrs) {
elem.bind('drop', function(ev){
ev.preventDefault();
var data;
if (ev.dataTransfer) {
data = ev.dataTransfer.getData('text');
}
else if (ev.originalEvent.dataTransfer){
data = ev.originalEvent.dataTransfer.getData('text');
}
//var dropObj = document.getElementById(data).cloneNode();
//dropObj.id = dropObj.id + "1";
//dropObj.setAttribute('style', 'width:50px;height:50px;background:blue;');
ev.target.appendChild(document.getElementById(data).cloneNode());
});
elem.bind('dragover', function(ev){
ev.preventDefault();
if (ev.target.getAttribute("draggable") == "true"){
ev.originalEvent.dataTransfer.dropEffect = "none";
}
else{
ev.originalEvent.dataTransfer.dropEffect = "all";
}
});
elem.css({
color: "blue"
});
}
}
});
app.directive('dragItem', function() {
return {
restrict: 'A',
replace: 'false',
link: function(scope,elem,attrs){
elem.bind('dragstart', function(ev){
if (ev.dataTransfer) {
ev.dataTransfer.setData("text", ev.target.id);
}
else if (ev.originalEvent.dataTransfer){
ev.originalEvent.dataTransfer.setData("text", ev.target.id);
}
});
elem.bind('dragover', function(ev){
return true;
});
attrs.$set('draggable','true');
}
//draggable="true" ondragstart="drag(event)"
}
});
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data).cloneNode(true));
}
and CSS
.dragdrop-panel {
width:25vw;
margin-right: 5vw;
height: 100vh;
border: 3px solid red;
float: left;
}
.draggablewithjs {
width:50px;
height:50px;
background:blue;
}
.draggablewithangular {
width:50px;
height:50px;
background:red;
}

Related

How do I solve this Javascript/CSS problem?

I want the smaller div box to show up in the larger div.
However, when I drag and drop it, this is what it looks like:
Why isn't the small box's border properly showing in the larger box? I have modified the drop function so that it copies the 2nd div instead of dropping it.
<html>
<head>
<script>
function remove(id){
//var el = document.getElementById("r1").outerHTML = "";
var element = document.getElementById(id);
element.parentNode.parentNode.removeChild(element.parentNode);
console.log('Removed')
}
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
var nodeCopy = document.getElementById(data).cloneNode(true);
nodeCopy.id = 'something';
ev.target.appendChild(nodeCopy);
}
</script>
</head>
<body>
<p>Drag the W3Schools image into the rectangle:</p>
<div id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br>
<div id = "drag1" draggable="true" ondragstart="drag(event)" height="50px" width="50px">
<span id="yo" class="fa fa-close cross" onclick="remove(this.id);"></span>
</div>
</body>
</html>
Hey #Presence as I check the thing which you are saying is working with the HTML and JS which you provided which concludes that you don't have any problem in javascript. Maybe you are facing this issue because of CSS.
You can use the CSS mentioned in the answer or else you can upload your CSS in question from which we can find out which property is giving you the issue.
function remove(id) {
//var el = document.getElementById("r1").outerHTML = "";
var element = document.getElementById(id);
element.parentNode.parentNode.removeChild(element.parentNode);
console.log("Removed");
}
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
var nodeCopy = document.getElementById(data).cloneNode(true);
nodeCopy.id = "something";
ev.target.appendChild(nodeCopy);
}
.dropDiv {
height: 15vh;
border: 2px solid grey;
}
.dragDiv {
height: 9vh;
border: 2px solid grey;
width: 53vw;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<title>Document</title>
</head>
<body>
<p>Drag the W3Schools image into the rectangle:</p>
<div class="dropDiv" id="div1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br>
<div class="dragDiv" id="drag1" draggable="true" ondragstart="drag(event)" height="50px" width="50px">
<span id="yo" class="fa fa-close cross" onclick="remove(this.id);"></span>
</div>
<script src="./index.js"></script>
</body>
</html>
height="50px" width="50px" doesn't work with the div. It is specific to few tags.
You can set the styles in the following ways for div.
Add CSS styling with class. (Preferred solution)
Add In-line styling for the div, like this. style="width: 100px"
Added the code snippet for your reference.
function remove(id){
//var el = document.getElementById("r1").outerHTML = "";
var element = document.getElementById(id);
element.parentNode.parentNode.removeChild(element.parentNode);
console.log('Removed')
}
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
var nodeCopy = document.getElementById(data).cloneNode(true);
nodeCopy.id = 'something';
ev.target.appendChild(nodeCopy);
}
.box{
border: 1px solid black;
}
.big{
width: 120px;
height: 50px;
}
.small{
width: 80px;
height: 30px;
}
<p>Drag the W3Schools image into the rectangle:</p>
<div id="div1" class="big box" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<br>
<div id="drag1" class="small box" draggable="true" ondragstart="drag(event)">
<span id="yo" class="" onclick="remove(this.id);">x</span>
</div>

HTML5 Drag and Drop - pass image using DataTransfer

I try to drag the image and drop it on the target div. However instead of dropping the image itself only the image path is displayed.
Html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="DragAndDrop_2.css">
<script src="DragAndDrop_2.js" type="text/javascript"></script>
</head>
<body>
<img id="my-image" draggable="true" src="images/thumbUp.jpg" height="200">
<div id="target-box"> </div>
</body>
</html>
Stylesheet:
*{
margin:0px;
padding:0px;
}
#target-box {
width:600px;
height:600px;
border:1px solid black;
}
Javascript:
function initialFunction() {
picture = document.getElementById('my-image');
targetBox = document.getElementById('target-box');
picture.addEventListener('drag', drag, false);
targetBox.addEventListener('dragover', function(ev) { ev.preventDefault(); }, false);
targetBox.addEventListener('drop', drop, false);
}
function drag(ev) {
ev.dataTransfer.setData("Text", ev.target.outerHTML);
}
function drop(ev) {
var code = ev.dataTransfer.getData("Text");
targetBox.innerHTML = code;
}
window.addEventListener('load', initialFunction, false);
I heard about some issues with Drag and Drop operation in HTML5. I wonder if in this case it's a bug in API or perhaps I'm missing something.

Jquery - hover changes to click after several resizes

I am trying to build a basic tab-navigation. When I hover about a tab (step), then the background of the tab gets green.
But after several hovers/resizes of the browser, hover doesnt't work anymore. Then I have to click on the tab in order to get the green background. It kind of freezes.
Thats the jsFiddle:
https://jsfiddle.net/rob_the_mob_87/L84kyym1/
Here is my minimal code:
index.html
<html>
<head>
<title>Tabs</title>
<script
src="https://code.jquery.com/jquery-3.2.1.js"
integrity="sha256-DZAnKJ/6XZ9si04Hgrsxu/8s717jcIzLy3oi35EouyE="
crossorigin="anonymous"></script>
<script type="text/javascript" src="js/static.js">
</script>
<link rel="stylesheet" type="text/css" href="./css/main.css">
</head>
<body>
<div class="process_step active" id="1">Step 1</div>
<div class="process_step" id="2">Step 2</div>
</body>
</html>
main.css
.process_step{
}
.active{
background-color: green;
}
static.js
$(document).ready(function () {
bindShowStepHandlers()
});
this.bindShowStepHandlers = function () {
$('.process_step').each(function() {
$(this).hover(function () {
var clickedStepId = $(this).attr('id');
openStep(clickedStepId);
});
});
}
this.openStep = function (clickedStepId) {
$('.process_step').each(function() {
var stepId = $(this).attr('id');
if (stepId == clickedStepId) {
$(this).addClass('active');
} else {
$(this).removeClass('active');
}
});
}
check this snippet below. i think it is what you want..
$(document).ready(function() {
bindShowStepHandlers()
});
this.bindShowStepHandlers = function() {
$('.process_step').each(function() {
$(this).on('mouseenter',function() {
$(this).addClass('active');
});
$(this).on('mouseleave',function() {
$(this).removeClass('active');
});
});
}
.process_step {}
.active {
background-color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="process_step active" id="1">Step 1</div>
<div class="process_step" id="2">Step 2</div>

When button is clicked, the div jumps out of place

Problem
When I click the buttons for playoff season or regular, the divs that holds the content players-list and players-regular appear to jump out of place when they fade in and out. How do I prevent this from happening?
I've tried using position fixed on some of elements, but things would get way out of place. I've included a JSFiddle here: http://jsfiddle.net/onlyandrewn/gcthaffs/
Click listener
// Click listener, toggles between sheets
$('button').click(function() {
$('button').removeClass("active");
$(this).toggleClass("active");
if ($('button.regular').hasClass('active')) {
$('#players-list').fadeOut(500);
$('.note').fadeOut(500);
$('#players-regular').fadeIn(2000);
} else {
$('#players-regular').fadeOut(500);
$('#players-list').fadeIn(2000);
$('.note').fadeIn(2000);
}
});
index.html
<!DOCTYPE html>
<html lang="en" class="no-js">
<head>
<meta charset="UTF-8">
<title>Wheat Kings' leading point scorers</title>
<meta name="description" content="Wheat Kings' leading point scorers">
<meta name="author" content="Andrew Nguyen">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="assets/css/style.css">
<link href='http://fonts.googleapis.com/css?family=Lato:300,400,700,900' rel='stylesheet' type='text/css'>
</head>
<body>
<h1>Wheat Kings leading goal scorers</h1>
<p class="year"></p>
<button class="playoffs active">Playoffs</button>
<button class="regular">Regular Season</button>
<div class="top">
<div id="players-list"></div>
<div id="players-regular"></div>
<p class="note">Note: Since there was a five-way tie for 6th place, players who scored two goals were then ranked by their total points in the playoffs. The other two players not listed here are Nolan Patrick and Macoy Erkamps.</p>
</div><!-- /.top -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tabletop.js/1.3.5/tabletop.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/handlebars.js/3.0.0/handlebars.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.js"></script>
<!-- This is where the template for facts goes -->
<script id="players" type="text/x-handlebars-template">
<div class="container">
<div class="group">
<div class="{{row}}">
<p class="goals">{{goals}}</p>
<img src="{{image}}" alt="" class="head">
<p class="name">{{name}}</p>
<p class="position">{{position}}</p>
</div><!-- /.group -->
</div><!-- /.row -->
</div><!-- /.container -->
</script>
<script type="text/javascript">
// Click listener, toggles between sheets
$('button').click(function() {
$('button').removeClass("active");
$(this).toggleClass("active");
if ($('button.regular').hasClass('active')) {
$('#players-list').fadeOut(500);
$('.note').fadeOut(500);
$('#players-regular').fadeIn(2000);
} else {
$('#players-regular').fadeOut(500);
$('#players-list').fadeIn(2000);
$('.note').fadeIn(2000);
}
});
// Original
var public_spreadsheet_url = "https://docs.google.com/spreadsheets/d/1RMN49oyRlTxW5kv8MnYJwQRttis2csgVFH46kyORCaQ/pubhtml";
$(document).ready( function() {
Tabletop.init( { key: public_spreadsheet_url,
callback: showInfo,
parseNumbers: true } );
});
function showInfo(data, tabletop) {
var source = $("#players").html();
var template = Handlebars.compile(source);
// The actual name of the sheet, not entire .csv
$.each(tabletop.sheets("Playoffs").all(), function(i, fact) {
var html = template(fact);
// You need an element with this id or class in your HTML
$("#players-list").append(html);
$('.container').eq(i).addClass(data.Playoffs.elements[i]);
// This logs all the objects in the sheet
// console.log(data);
// This logs just validity
// console.log(data.Playoffs.elements[i]);
})
// If you need to get data from a second sheet in single Google Doc
$.each(tabletop.sheets("Regular").all(), function(i, fact) {
var html = template(fact);
// You need an element with this id or class in your HTML
$("#players-regular").append(html);
$('.container').eq(i).addClass(data.Regular.elements[i]);
// This logs all the objects in the sheet
// console.log(data);
// This logs just validity
// console.log(data.Regular.elements[i]);
});
}
</script>
</body>
</html>
base.scss
/*----------------------------------
MAIN STYLES
----------------------------------*/
html {
font-size: 62.5%; /* 10px browser default */
}
body {
max-width: 600px;
padding: 10px;
}
.top {
max-width: 600px;
}
#players-list,
#players-regular {
}
h1 {
font-family: 'Lato', sans-serif;
font-weight: 900;
border-bottom: 1px solid #ccc;
padding-bottom: 8px;
}
.note {
position: relative;
width: 95%;
left: 3%;
}
This is happening because the fadeOut is not done when the fadeIn starts. You end up with both divs visible for a short period of time, and when the fadeOut is done the first div is hidden and you see the jump.
How about something like this:
$('#players-list').fadeOut(500, function() {
$('#players-regular').fadeIn(500);
});
This way the second div is displayed only when the first one is completely hidden.
Also, decrease the animation duration a bit, it makes for better user experience ;).

Drag and drop html element

I have a div which can be dragged. If it's dragged, I would like to add its text to mouse and after leaving the mouse I want to show some menu like copy.
I have tried this:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<style>
#div1
{
width:350px;
height:70px;
padding:10px;
border:1px solid #aaaaaa;
}
</style>
<script>
function drag(ev)
{
ev.dataTransfer.setData("Text",ev.target.id);
}
function drop(ev)
{
ev.preventDefault();
//console.log(ev.dataTransfer);
//var data=ev.dataTransfer.getData("Text");
//ev.target.appendChild(document.getElementById(data));
alert(ev.target.id);
}
function allowDrop(ev){
ev.preventDefault();
}
</script>
</head>
<body>
<a draggable="true" ondragstart="drag(event)" id="drag-id" >dragme</a>
<div id="div1" style="border: solid 1px; width:40px; height:40px;" ondrop="return drop(event)" ondragover="allowDrop(event)"></div>
</body>
</html>
SOLUTION using fake drag 'n drop.
The problem here is that it only works inside the body element.
var fakeDrag = {
setup: function(){
fakeDrag.el = document.createElement('span');
fakeDrag.el.style['pointer-events'] = 'none';
fakeDrag.el.style['position'] = 'absolute';
fakeDrag.el.style['display'] = 'none';
fakeDrag.el.textContent = 'dragging';
document.body.appendChild(fakeDrag.el);
},
dragging: false,
drag: function(event){
if(event.target.classList.contains('drag')){
fakeDrag.dragging = true;
fakeDrag.source = event.target;
fakeDrag.el.style['display'] = 'inline';
}
},
dragmove: function(event){
fakeDrag.el.style['top'] = ++event.clientY+'px';
fakeDrag.el.style['left'] = ++event.clientX+'px';
},
drop: function(event){
if(event.target.classList.contains('drop') && fakeDrag.dragging){
event.target.textContent = fakeDrag.source.textContent;
}
fakeDrag.dragging = false;
fakeDrag.el.style['display'] = 'none';
}
};
fakeDrag.setup();
For menu you use it:
<div id="context_menu" style="width:150px;border:1px solid black;background-color:#EEEEEE;visibility:hidden;position:absolute;line-height:30px; padding-left: 10px">
<div id="copy" onclick="CopyFunction(this)" divIDMenu="">copy</div>
<div id="paste"onclick="PasteFunction(this)" divIDCopy="" divIDMenu="">paste</div>
<div id="cut" onclick="cutFunction(this)"divIDMenu="">cut</div>
<div id="delete" onclick="deleteFunction(this)" divIDMenu="">delete</div>
<div id="reload" onclick="reloadFunction(this)" divIDMenu="">reload</div>
</div>

Categories

Resources