jquery html duplicating on drag and drop - html

I am using jQuery and using a drag and drop function. My image keeps duplicating and I have no idea why. Any help would be great. I am pretty sure my issue is at line:
$('#' + seat).append('<div class="studentCard" id="' + id + '"><img class="studentImage" src="Images/' + id + '.jpg" style="height:150px; width:150px;" />' + student + '</div>');
Here is my function:
$('.seat').droppable({
drop: function (event, ui) {
var seat = $(this).attr('id');
var id = $(ui.draggable).attr('id');
var student = $(ui.draggable).html();
$.ajax({
success: function () {
if ($('#' + seat + '> div').length > 0) {
alert('Desk already occupied');
}
else {
$(ui.draggable).remove();
$('#' + seat).append('<div class="studentCard" id="' + id + '"><img class="studentImage" src="Images/' + id + '.jpg" style="height:150px; width:150px;" />' + student + '</div>');
$('div#' + id).draggable({
helper: 'clone'
});
}
}
});
}
});

Consider the following example. You might also consider using Sortable instead.
$(function() {
function moveStudent(source, target) {
$(target).append($(".student", source).detach());
}
$(".student").draggable({
helper: "clone",
revert: "invalid",
zIndex: 100
});
$(".seat").droppable({
accept: function() {
if ($(this).children().length == 0) {
return true;
}
return false;
},
drop: function(event, ui) {
moveStudent(ui.draggable.parent(), this);
}
});
});
.seat {
width: 150px;
height: 150px;
float: left;
margin: 10px;
}
.student {
display: inline-block;
width: 140px;
height: 140px;
border: 1px solid #CCC;
position: relative;
background-color: #FFFFFF;
background-repeat: no-repeat;
background-position: center;
background-size: cover;
margin: 5px;
}
.studentName {
position: absolute;
top: 120px;
left: 5px;
font-size: 11pt;
text-shadow: -1px 0 white, 0 1px white, 1px 0 white, 0 -1px white;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-3.5.1.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="seat-1" class="seat ui-widget-header">
<div id="student-1" class="student" style="background-image: url('https://i.imgur.com/QjxuZB5.png');" data-student-id="1001">
<div class="studentName">Thomas</div>
</div>
</div>
<div id="seat-2" class="seat ui-widget-header">
<div id="student-2" class="student" style="background-image: url('https://imgur.com/Gvmj4y5.png');" data-student-id="1002">
<div class="studentName">Trinity</div>
</div>
</div>
<div id="seat-3" class="seat ui-widget-header">
</div>
<div id="seat-4" class="seat ui-widget-header">
</div>
Instead of creating a new element, you can use .detach() and more easily move the original draggable item to the new drop zone.
It is sometimes better to use accept option to determine if a droppable should accept an item or not. This option does allow the use of a Function:
Function: A function that will be called for each draggable on the page (passed as the first argument to the function). The function must return true if the draggable should be accepted.
See More: https://api.jqueryui.com/droppable/#option-accept
This allows you to re-arrange the items without stacking.

Related

How to drag and drop same element multiple times into another div box in JavaScript or jQuery?

I have two HTML div boxes. Let's say box A and box B. I want to drag and drop box A multiple times into box B. If I drop box A outside of box B then box A will revert back to it's original position. After I dropped the box A (clone) into box B I want to move box A (clone) into any position in box B. For now I did the codes to do that.
Now what I want is after I dropped box A into Box B, then if I drag and drop box A (clone) outside of box B, then box A (clone) need to hide or revert into it's original position (box A parent position).
HTML Codes
<div id="boxB"></div>
<br>
<div class="boxA">BOX A</div>
CSS Codes
#boxB {
width: 200px;
border: 5px solid black;
padding: 50px 50px;
margin: auto;
text-align: center;
background-color: #FFFFFF;
}
.boxA {
width: 40px;
border: 2px solid black;
text-align: center;
background-color: #F5D938;
cursor: pointer;
}
JavaScript + jQuery Codes
$(document).ready(function()
{
var x;
$(".boxA").draggable(
{
helper: "clone",
cursor: "move",
revert: true
});
$("#boxB").droppable(
{
accept: ".boxA",
drop: function(event, ui)
{
x = ui.helper.clone();
ui.helper.remove();
x.appendTo('#boxB');
$(x).draggable();
}
});
});
You can see demo : https://jsfiddle.net/zajjith/3kedjgb0/10/
If I drag and drop box A (clone) outside from box B then that clone box A need to revert back to it's original parent box A position or hide or delete.
I hope you understand what I want. Please check my codes and help me.
Refer to the Example at https://jqueryui.com/droppable/#revert
Using your code, you can do the following.
$(function() {
function getBounds(el) {
var p = $(el).position();
p.right = p.left + $(el).width();
p.bottom = p.top + $(el).height();
return p;
}
function isOver(a, b) {
var ap;
if (typeof a == "object") {
ap = a;
} else {
ap = getBounds(a);
}
var bp = getBounds(b);
return (ap.left > bp.left && ap.right < bp.right) && (ap.top > bp.top && ap.bottom < bp.bottom);
}
$(".boxA").draggable({
helper: "clone",
cursor: "move",
revert: "invalid"
});
$("#boxB").droppable({
accept: ".boxA",
drop: function(event, ui) {
var cl = ui.helper.clone();
cl.appendTo(this).draggable({
appendTo: "body",
stop: function(e, ui) {
if (isOver($.extend({}, ui.position, {
right: ui.position.left + ui.helper.width(),
bottom: ui.position.top + ui.helper.height()
}), $("#boxB")) == false) {
var a = getBounds($("body > .boxA"));
ui.helper.animate({
top: a.top,
left: a.left
}, function() {
ui.helper.remove();
});
} else {
console.log("Drop Inside");
}
}
});
ui.helper.remove();
}
});
});
#boxB {
width: 200px;
border: 5px solid black;
padding: 50px 50px;
margin: auto;
text-align: center;
background-color: #FFFFFF;
}
.boxA {
width: 50px;
border: 2px solid black;
text-align: center;
background-color: #F5D938;
cursor: pointer;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="boxB"></div>
<br />
<div class="boxA">BOX A</div>

Cannot change div height after adding Layout

I have a razor view web page that has a div that i fill data into it in some way (lazy load, or loop, doesn't matter).
If i dont use a Layout, IE:
#{
Layout = "_Layout";
}
Then the div will use my configured height, and also shows a scrollbar if needed (using overflow: auto)
However, when i add a layout, even an empty one, i cannot seem to modify the div's height, which causes it to take all the screen from the layout to the bottom, and shows no scrolling.
What disabled my ability to change the height?
(the div im loading data into is div id container)
index.cshtml:
#{
Layout = "_Layout";
}
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
width: 100%;
}
th, td {
padding: 5px;
text-align: center;
width: 15%;
}
.Good {
background-color: green
}
.Bad {
background-color: red
}
#container {
background: #eee;
}
</style>
<head>
<script src="/JQuery/jquery-3.3.1.min.js"></script>
</head>
<body style="overflow: hidden;">
<div>
<div>
<h3 id="Progression"></h3>
</div>
<div id="container" style="width: 100%; height: 80%; overflow: auto;">
</div>
<div id="progress" style="display: none; height: 20%">
<h4>Loading...</h4>
</div>
</div>
</body>
_Layout.cshtml:
<!DOCTYPE html>
<style>
.main-header {
background: url(/images/bg-header.png) transparent repeat-x 0 0;
}
</style>
<html>
<head>
<meta name="viewport" content="width=device-width" />
</head>
<body>
<header class="main-header" role="banner">
<div>
<a href="/" title="Home" rel="home">
<img src="/images/COMPANY-logo.png" style="background-color:white;" alt="Home">
</a>
</div>
</header>
<div>
#RenderBody()
</div>
</body>
</html>
Empty _Layout.cshtml: (having issues with this layout as well)
<!DOCTYPE html>
<style>
.main-header {
background: url(/images/bg-header.png) transparent repeat-x 0 0;
}
</style>
<html>
<head>
</head>
<body>
<div>
#RenderBody()
</div>
</body>
</html>
Generated page (The empty layout was used):
<!DOCTYPE html>
<style>
.main-header {
background: url(/images/bg-header.png) transparent repeat-x 0 0;
}
</style>
<html>
<head>
</head>
<body>
<div>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
width: 100%;
}
th, td {
padding: 5px;
text-align: center;
width: 15%;
}
.Good {
background-color: green
}
.Bad {
background-color: red
}
#container {
background: #eee;
}
</style>
<head>
<script src="/JQuery/jquery-3.3.1.min.js"></script>
</head>
<body style="overflow: hidden;">
<div>
<div>
<h3 id="Progression"></h3>
</div>
<div id="container" style="width: 100%; height: 80%; overflow: auto;">
</div>
<div id="progress" style="display: none; height: 20%">
<h4>Loading...</h4>
</div>
</div>
</body>
<script>
var pageSize = 50;
var pageIndex = 0;
var totalItemsDisplayed = 0;
$(document).ready(function() {
lazyLoadCards(0);
$('#container').scroll(function() {
var scrollTop = $(this).scrollTop();
var scrollHeight = $(this).prop('scrollHeight');
var clientHeight = $(this).prop('clientHeight');
if (scrollTop + clientHeight === scrollHeight) {
pageIndex++;
lazyLoadCards(pageIndex);
}
});
function lazyLoadCards(index) {
$.ajax({
type: 'GET',
url: '/AllCards/OnScrollEnd',
data: { "startIndex": index, "size": pageSize },
dataType: 'json',
success: function(data) {
if (data != null) {
totalItemsDisplayed += data.length;
for (var i = 0; i < data.length; i++) {
$("#container").append("<h2>" +
data[i].cardNumber +
"</h2>");
}
updateProgression();
}
},
beforeSend: function() {
$("#progress").show();
},
complete: function() {
$("#progress").hide();
},
error: function() {
alert("Error while retrieving data!");
}
});
}
function loadCards(index) {
$.ajax({
type: 'GET',
url: '/AllCards/OnScrollEnd',
data: { "startIndex": index, "size": pageSize },
dataType: 'json',
success: function(data) {
if (data != null) {
totalItemsDisplayed += data.length;
for (var i = 0; i < data.length; i++) {
$("#container").append("<h2>" +
data[i].cardNumber +
"</h2>");
}
updateProgression();
if (data.length > 0) {
loadCards(index + 1);
}
}
},
beforeSend: function() {
$("#progress").show();
},
complete: function() {
$("#progress").hide();
},
error: function() {
alert("Error while retrieving data!");
}
});
}
function updateProgression() {
$('#Progression').text("Displaying " + totalItemsDisplayed + " Cards out of " + 6930);
}
});
</script>
</div>
</body>
</html>
Visual to see current output and desired outcome:
(Note that thetext inside the gray box is just elements with some text. thats what the ajax call does)
Generated code after adding #section and #style and removing body everyone besides _Layout
<!DOCTYPE html>
<html>
<head>
<style>
.main-header {
background: url(/images/bg-header.png) transparent repeat-x 0 0;
}
</style>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
width: 100%;
}
th, td {
padding: 5px;
text-align: center;
width: 15%;
}
.Good {
background-color: green
}
.Bad {
background-color: red
}
#container {
background: #eee;
}
</style>
</head>
<body>
<header class="main-header" role="banner">
<div>
<a href="/" title="Home" rel="home">
<img src="/images/COMPANY-logo.png" style="background-color:white;" alt="Home">
</a>
</div>
</header>
<div>
<div>
<div>
<h3 id="Progression"></h3>
</div>
<div id="container" style="width: 100%; height: 80%; overflow: visible;">
</div>
<div id="progress" style="display: none; height: 20%">
<h4>Loading...</h4>
</div>
</div>
</div>
<script src="/JQuery/jquery-3.3.1.min.js"></script>
<script>
var pageSize = 50;
var pageIndex = 0;
var totalItemsDisplayed = 0;
$(document).ready(function() {
lazyLoadCards(0);
$('#container').scroll(function() {
var scrollTop = $(this).scrollTop();
var scrollHeight = $(this).prop('scrollHeight');
var clientHeight = $(this).prop('clientHeight');
if (scrollTop + clientHeight === scrollHeight) {
pageIndex++;
lazyLoadCards(pageIndex);
}
});
function lazyLoadCards(index) {
$.ajax({
type: 'GET',
url: '/AllCards/OnScrollEnd',
data: { "startIndex": index, "size": pageSize },
dataType: 'json',
success: function(data) {
if (data != null) {
totalItemsDisplayed += data.length;
for (var i = 0; i < data.length; i++) {
$("#container").append("<h2>" +
data[i].cardNumber +
"</h2>");
}
updateProgression();
}
},
beforeSend: function() {
$("#progress").show();
},
complete: function() {
$("#progress").hide();
},
error: function() {
alert("Error while retrieving data!");
}
});
}
function loadCards(index) {
$.ajax({
type: 'GET',
url: '/AllCards/OnScrollEnd',
data: { "startIndex": index, "size": pageSize },
dataType: 'json',
success: function(data) {
if (data != null) {
totalItemsDisplayed += data.length;
for (var i = 0; i < data.length; i++) {
$("#container").append("<h2>" +
data[i].cardNumber +
"</h2>");
}
updateProgression();
if (data.length > 0) {
loadCards(index + 1);
}
}
},
beforeSend: function() {
$("#progress").show();
},
complete: function() {
$("#progress").hide();
},
error: function() {
alert("Error while retrieving data!");
}
});
}
function updateProgression() {
$('#Progression').text("Displaying " + totalItemsDisplayed + " Cards out of " + 6930);
}
});
</script>
</body>
</html>
You should be using sections. Sections allow you to add styles, scripts, etc. on the layout. You can't have the head and body tags anywhere except the layout page.
Empty _Layout.cshtml:
<!DOCTYPE html>
<head>
<style>
.main-header {
background: url(/images/bg-header.png) transparent repeat-x 0 0;
}
</style>
#RenderSection("Styles", required: false)
</head>
<body>
<div>
#RenderBody()
</div>
#RenderSection("Scripts", required: false)
</body>
</html>
Index.cshtml:
#{
Layout = "_Layout";
}
#section Styles {
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
width: 100%;
}
th, td {
padding: 5px;
text-align: center;
width: 15%;
}
.Good {
background-color: green
}
.Bad {
background-color: red
}
#container {
background: #eee;
}
</style>
}
<div>
<div>
<h3 id="Progression"></h3>
</div>
<div id="container" style="width: 100%; height: 80%; overflow: auto;">
</div>
<div id="progress" style="display: none; height: 20%">
<h4>Loading...</h4>
</div>
</div>
#section Scripts {
<script src="/JQuery/jquery-3.3.1.min.js"></script>
}
UPDATE
You need to make the following change:
<div id="container" style="width: 100%;height: 155px;overflow: scroll;display: block;">
You can't use a percentage for height unless you add position:absolute;. If you only want the vertical scroll bar, you'll need to use overflow-y:scroll; instead.

preventDefault and stopPropagation will not allow to change css property of div

I am working on touch screen and change from onclick on div to touchstart so that speed of click work fast. But problem is that using this way when i touch on div event working fast but css property to change background color is not working now. Here is my code:
<div class="numpad" id="numpad" align="center">
<div style="display:flex;">
<kbd touchpad="call(1)">1
<div class="background"> </div>
</kbd>
<kbd touchpad="call(2)">2
<div class="background">ABC</div>
</kbd>
<kbd touchpad="call(3)">3
<div class="background">DEF</div>
</kbd>
</div>
angular directive:
angular.module('myApp').directive('numpad', function($log) {
return {
restrict: 'E',
templateUrl: 'html/directives/numpadOpenr.html',
require: 'ngModel',
link: function(scope, elem, attrs, ngModel) {
scope.number = ngModel;
scope.call = function(number) {
var value = scope.number.$viewValue || '';
scope.number.$setViewValue(value + number);
};
scope.remove = function() {
var value = scope.number.$viewValue || '';
if (value.length > 0) {
scope.number.$setViewValue(value.substring(0, value.length - 1));
}
};
}
};
});
angular.module('myApp').directive("touchpad", [function () {
return function (scope, elem, attrs) {
elem.bind("touchstart click", function (e) {
e.preventDefault();
e.stopPropagation();
scope.$apply(attrs["touchpad"]);
});
}
}]);
css:
kbd, .key {
display: inline-block;
min-width: 2.2em;
font: normal .85em "Lucida Grande", Lucida, Arial, sans-serif;
text-align: center;
text-decoration: none;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
-ms-border-radius: 3px;
-o-border-radius: 3px;
border-radius: 3px;
cursor: pointer;
color: #555;
}
kbd[title], .key[title] {
cursor: help;
}
kbd {
border: 1px solid #c4c6ca;
padding: 10px 20px;
background-color: transparent;
flex:1;
height: 2.2em;
}
kbd:active {
background: #e6e7e8;
}
.numpad kbd {
margin: 3px;
font-size: xx-large;
background-color: #ffffff;
}
kbd div.background {
font-size:x-small;
}
.numpad kbd:hover, .numpad kbd:active, .numpad kbd:focus {
background-color: #dceef7;
}
Can someone tell me is there any way that css numpad kbd:active, numpad kbd:focus start work using same strategy where i am using e.preventDefault() and e.stopPropagation() ?
I found a solution its little bit ugly but working. If add a timeout function which help to disable entry into onclick function call then it will work. Her is a code.
var doubleClickCheck = true;
scope.call = function(number) {
if (doubleClickCheck) {
var value = scope.number.$viewValue || '';
scope.number.$setViewValue(value + number);
reset();
}
};
scope.remove = function() {
if (doubleClickCheck) {
var value = scope.number.$viewValue || '';
if (value.length > 0) {
scope.number.$setViewValue(value.substring(0, value.length - 1));
}
reset();
}
};
function reset() {
doubleClickCheck = false;
$timeout(function () {
doubleClickCheck = true;
}, 150)
}

Making Input Text to open up drop down list in AngularJS

I am trying to create a directive in AngularJS which acts as Input and Select box together. Just like when you type in search textbox a dropdown list popups for assisting user to select. The selection is working fine via mouseclick, but I want my user to use arrow keys to move up and down and select on enter as well. Below is my HTML , CSS and Javascript code. Your quick assistance in this regard will be appreciated.
/*******CSS Code******/
.input-dropdown {
position: relative;
display: inline-block;
}
.input-dropdown .dropdown {
display: none;
position: absolute;
top: 100%;
left: 0;
width: 100%;
margin-top: 2px;
background: #EEE;
}
.input-dropdown .dropdown div {
cursor: pointer;
padding: 2px 5px;
}
.input-dropdown input:focus + .dropdown {
display: block;
}
/*******AngularJS Code*****************/
var app = angular.module('myApp', []);
app.controller('MainCtrl', function ($scope) {
$scope.values = ['Chrome', 'Firefox', 'IE'];
$scope.pick = function (value) {
console.log('Picked', value)
};
});
app.directive('inputDropdown', function ($compile) {
var template =
'<input ng-model="ngModel">' +
'<div class="dropdown">' +
'<div ng-repeat="value in list | filter: ngModel">' +
'<div ng-mousedown="select($event, value)">{{value}}</div>' +
'</div>' +
'</div>';
return {
restrict: 'EA',
scope: {
ngModel: '=',
list: '=',
onSelect: '&'
},
template: template,
link: function (scope, element, attrs) {
element.addClass('input-dropdown');
scope.select = function (e, value) {
scope.ngModel = value;
scope.onSelect({ $event: e, value: value });
};
}
};
});
HTML Code:
<html ng-app="myApp">
<head>
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<body ng-controller="MainCtrl">
<input-dropdown ng-model="preference" list="values" on-select="pick(value)"></input-dropdown> {{preference}}
</body>
</html>

Multiple Google Street Views on the same page

I am trying to embed two Google Street View controls on the same page, it should look something like this:
How the end result should look like
I want my visitors to use the controls on both elements to navigate around the area with their mouse. Is this possible on the same HTML page?
Example of multiple (3) streetView panoramas
(taken from various examples in the documentation, uses (but doesn't really require) JQuery.
code snippet:
function initPano() {
var panoramas = [];
panoDivs = document.getElementsByClassName('pano');
$(".pano").each(function(idx, el) {
console.log("idx=" + idx + " lat:" + parseFloat($(this).data("lat")) + " lng:" + parseFloat($(this).data("lng")) + " heading:" + parseFloat($(this).data("heading")));
var panorama = new google.maps.StreetViewPanorama(
el, {
position: {
lat: parseFloat($(this).data("lat")),
lng: parseFloat($(this).data("lng"))
},
pov: {
heading: parseFloat($(this).data("heading")),
pitch: 0
},
visible: true
});
panoramas.push(panorama);
});
}
google.maps.event.addDomListener(window, "load", initPano);
html,
body {
margin: 0;
padding: 0;
}
.pano {
height: 200px;
width: 200px;
margin: 2px;
padding: 2px;
}
.col {
height: 200px;
width: 620px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js"></script>
<div class="col">
<div style="float:left" class="pano" data-lat="42.345573" data-lng="-71.098326" data-heading="34"></div>
<div style="float:right" class="pano" data-lat="40.729884" data-lng="-73.990988" data-heading="265"></div>
<div class="pano" data-lat="37.869260" data-lng="-122.254811" data-heading="165"></div>
</div>