Html 5 nested drag and drop using jQuery - javascript

Hello I've created some demo with html5 drag and drop. I have nested dragable containers. When I'm trying to drag an element on child container it appends element on both containers. How can I fix that part? Please Help me.
Here is my example`
html
<div id="div1">
container 1
<div id="div2">
container 2
</div>
</div>
<br>
<img id="drag1" src="http://www.w3schools.com/html/img_logo.gif" width="336" height="69">
jquery
$(document).ready(function() {
var drag1 = `<img src="http://www.w3schools.com/html/img_logo.gif" width="336" height="69">`
$("#div1").on("dragover", function(e) {
$(this).css('background', 'yellow');
e.preventDefault();
e.stopPropogation();
});
$("#div1").on("dragleave", function(e) {
$(this).css('background', 'none');
e.preventDefault();
e.stopPropogation();
});
$("#div2").on("dragover", function(e) {
$(this).css('background', 'yellow');
e.preventDefault();
e.stopPropogation();
});
$("#div2").on("dragleave", function(e) {
$(this).css('background', 'red');
e.preventDefault();
e.stopPropogation();
});
$("#drag1").on("dragstart", function(e) {
e.originalEvent.dataTransfer.setData("Text", e.target.id);
});
$("#div1").on("drop", function(e) {
e.preventDefault();
var data = e.originalEvent.dataTransfer.getData("Text");
data === 'drag1' && $(this).append(drag1);
});
$("#div2").on("drop", function(e) {
e.preventDefault();
var data = e.originalEvent.dataTransfer.getData("Text");
data === 'drag1' && $(this).append(drag1);
});
});
css
#div1 {
min-width: 350px;
min-height: 70px;
padding: 40px;
border: 1px solid #aaaaaa;
}
#div2 {
width: 350px;
min-height: 70px;
padding: 10px;
border: 1px solid #aaaaaa;
background: red;
}
jsfiddle Example
If I want to drag on child it should drop only on that container but on parent container I don't know how to stop the drag event.
Thanks for your help.

Here is your solution:
http://jsfiddle.net/43xky7ot/
1.) it's not propogation rather it is propagation e.stopPropagation()
2.) you need to stop bubbling when dropping in div2: $("#div2").on("drop", function(e) {e.stopPropagation();})
$(document).ready(function() {
var drag1 = `<img src="http://www.w3schools.com/html/img_logo.gif" width="336" height="69">`
$("#div1").on("dragover", function(e) {
$(this).css('background', 'yellow');
e.preventDefault();
e.stopPropagation();
});
$("#div1").on("dragleave", function(e) {
$(this).css('background', 'none');
e.preventDefault();
e.stopPropagation();
});
$("#div2").on("dragover", function(e) {
$(this).css('background', 'yellow');
e.preventDefault();
e.stopPropagation();
});
$("#div2").on("dragleave", function(e) {
$(this).css('background', 'red');
e.preventDefault();
e.stopPropagation();
});
$("#drag1").on("dragstart", function(e) {
e.originalEvent.dataTransfer.setData("Text", e.target.id);
});
$("#div1").on("drop", function(e) {
e.preventDefault();
var data = e.originalEvent.dataTransfer.getData("Text");
data === 'drag1' && $(this).append(drag1);
});
$("#div2").on("drop", function(e) {
e.preventDefault();
e.stopPropagation();
console.log('div2 dropped');
var data = e.originalEvent.dataTransfer.getData("Text");
data === 'drag1' && $(this).append(drag1);
});
});

Related

Open the menu with Hover and close it by clicking outside the cart

My problem is that by moving the shopping cart button, the card menu opens and by clicking except the card menu, the card box should be closed. I wrote some of these, help me get the solution, thank you.
$(document).ready(function() {
$('.shop').hover(function() {
$('.carts').css('visibility', 'visible');
});
});
You could check if the clicked target (e.target) is not the .carts element (negation with !):
if (!$(e.target).is('.carts')) {
$('.carts').css('visibility', 'hidden');
}
Working example:
$(document).ready(function () {
$('.shop').hover(function () {
$('.carts').css('visibility', 'visible');
});
$('body').click(function(e) {
if (!$(e.target).is('.carts')) {
$('.carts').css('visibility', 'hidden');
}
});
});
.shop {
background-color: yellow;
}
.carts {
background-color: red;
visibility: hidden;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span class="shop">Shop</span>
<div class="carts">Test</div>
$(document).click(function() {
$(".carts").hide();
});
$(".carts").click(function(event) {
event.stopPropagation();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="carts" style="width: 50px;height: 50px;border: 1px solid;"></div>

jquery focus to sibling without focusing out from parent

I am try to iterate through all li elements in ul on keydown event by firing focus() event for next sibling li. In this process, I dont want to focus out from parent ul.
But its not happening. Even changing focus on siblings is causing focusout event on parent. I want that only when someone clicks somewhere else on the screen should focus out of parent be fired.
var KEY_DOWN=40;
$(document).on('keydown', 'li', function(e){
let keyCode = e.keyCode || e.which;
if(keyCode == KEY_DOWN)
{
if($(this).next().length != 0)
{
$(this).next().focus();
}
else
{
$(this).parent().children().first().focus();
}
return false;
}
});
$(document).on('focusout','ul', function(e)
{
console.log('focused')
});
li
{
border: 1px solid black;
}
li:focus
{
background: #999;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul tabindex="-1">
<li tabindex="-1">First</li>
<li tabindex="-1">Second</li>
<li tabindex="-1">Third</li>
</ul>
In the snippet, focused in getting printed on every down key press. How to solve this situation.
Due to event bubbling, the focusout event is logging the message for you when you are focusing out of li too. You can use the event data to check from where you have focused out. (Read more here: jQuery figuring out if parent has lost 'focus')
But I would like to mention how I do it. I would rather like to detect click outside my ul.
var KEY_DOWN=40;
$(document).on('keydown', 'li', function(e){
let keyCode = e.keyCode || e.which;
if(keyCode == KEY_DOWN)
{
if($(this).next().length != 0)
{
$(this).next().focus();
}
else
{
$(this).parent().children().first().focus();
}
return false;
}
});
$(document).on('focusout','ul', function(e)
{
console.log('focused out of li');
});
$(document).click(function() {
console.log('focused out of ul');
});
$('ul').click(function(e) {
e.stopPropagation();
});
li
{
border: 1px solid black;
}
li:focus
{
background: #999;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul tabindex="-1">
<li tabindex="-1">First</li>
<li tabindex="-1">Second</li>
<li tabindex="-1">Third</li>
</ul>
Only way I found was to disable focusout event on parent ul when I am trying to focus any li
var KEY_DOWN=40;
$(document).on('keydown', 'li', function(e){
let keyCode = e.keyCode || e.which;
if(keyCode == KEY_DOWN)
{
$(document).off('blur','ul', doWork);
if($(this).next().length != 0)
{
$(this).next().focus();
}
else
{
$(this).parent().children().first().focus();
}
$(document).on('blur','ul', doWork);
return false;
}
});
doWork = function(e)
{
console.log('focused')
};
$(document).on('blur','ul', doWork);
li
{
border: 1px solid black;
}
li:focus
{
background: #999;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul tabindex="-1">
<li tabindex="-1">First</li>
<li tabindex="-1">Second</li>
<li tabindex="-1">Third</li>
</ul>

How to open a box on screen by clicking a link and hide it when clicked outside in JS

My goal is to have #box2 appear when I click on #box1 but when you click on something other than #box2, it will display none and only #box1 will show.
Here are my 2 boxes, they are just 2 styled divs:
var condition;
$(document).click(function() {
if (condition === 'block') {
$(":not(#box2)").click(function() {
$("#box2").hide();
});
}
})
$('#box1').click(function(e) {
$('#box2').css('display', 'block');
condition = 'block';
});
$('#box2').click(function(e) {
$('#box2').css('display', 'none');
condition = 'none';
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="box1" style="width: 300px; height: 300px; background-color: red; margin-left: 100px; margin-bottom: 50px; position: absolute;">
</div>
<div id="box2" style="width: 300px; height: 300px; background-color: blue; margin-left: 150px; display: none; position: absolute;">
</div>
This current code works correctly the first time but after that, it wont run again. I am just wondering if there is a reset function or where I am going wrong?
Really what I want to do is make this work on an ipad so when the user clicks/taps away from the box, it will close. If there are better ways to do this on the Ipad tablet, please let me know!!
Any ideas?
Don't overcomplicate things. This is all the javascript you need, get rid of everything else:
$(document).click(function () {
$('#box2').hide();
});
$('#box1').click(function (e) {
e.stopPropagation();
$('#box2').show();
});
You could just filter event target at document level:
$(document).on('click', function(e) {
$('#box2').toggle(!!$(e.target).closest('#box1').length);
});
-jsFiddle-
You can listen to all click events of the document and then use the event.target to detect which element is being clicked. if the clicked element is box1 and box2 is not being shown then display it to the user. in any other condition we can hide the box2 if it's not the element being clicked. here is the vanilla JavaScript code to achieve this:
<html>
<body>
<div id='box1'>BOX ONE</div>
<div id='box2' style="display: none;">BOX TWO</div>
<script>
document.addEventListener('click', function(event) {
var secondBox = document.getElementById('box2')
if(event.target.id === 'box1' && secondBox.style.display === 'none'){
secondBox.style.display = 'block'
} else if (event.target.id !== 'box2') {
secondBox.style.display = 'none'
}
})
</script>
</body>
</html>
And if you are into DRY (Do not repeat yourself), you can define a function for this task. Take look at this modified version of the script:
function addOpenHandler(handler, target){
document.addEventListener('click', function(event) {
if(event.target === handler && target.style.display === 'none'){
target.style.display = 'block'
} else if (event.target !== target) {
target.style.display = 'none'
}
})
}
addOpenHandler( document.getElementById('box1'), document.getElementById('box2') )
$(document).click(function () {
if (condition === 'block')
{
$(":not(#box2)").click(function () {
$("#box2").hide();
});
}
})
The line $("#box2").hide(); is firing after every click

How to show a indicator when clicked on a Button in this case

On Click Of the Try Again Button , is it possible to show some processing happening on the device
My jsfiddle
My code as below
$(document).on("click", ".getStarted", function(event) {
// Simulating Net Connection here
var a = 10;
if (a == 10) {
$('#mainlabel').delay(100).fadeIn(300);
$('#nonetconnmain').popup({
history : false
}).popup('open');
event.stopImmediatePropagation();
event.preventDefault();
return false;
}
});
$(document).on('click', '.nonetconnmainclose', function(event) {
$('#nonetconnmain').popup('close');
$(".getStarted").trigger("click");
event.stopImmediatePropagation();
event.preventDefault();
return false;
});
$(document).on("popupbeforeposition", "#nonetconnmain", function(event, ui) {
$('#mainlabel').hide();
});
With my code , the functionality is working , but it seems that the application is not doing any action
So my question is it possible to show any indication (For example , delay , progressbar , anything )
Here ya go
$(document).on("click", ".getStarted", function(event) {
$.mobile.loading("show", {
text: "",
textVisible: true,
theme: "z",
html: ""
});
// Simulating Net Connection here
var a = 10;
if (a == 10) {
setTimeout(function() {
$.mobile.loading("hide");
$('#mainlabel').fadeIn(300);
}, 1000);
$('#nonetconnmain').popup({
history: false
}).popup('open');
event.stopImmediatePropagation();
event.preventDefault();
return false;
}
});
$(document).on('click', '.nonetconnmainclose', function(event) {
$('#nonetconnmain').popup('close');
$(".getStarted").trigger("click");
event.stopImmediatePropagation();
event.preventDefault();
return false;
});
$(document).on("popupbeforeposition", "#nonetconnmain", function(event, ui) {
$('#mainlabel').hide();
});
.popup {
height: 200px;
width: 150px;
}
.popup h6 {
font-size: 1.5em !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script>
<link href="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css" rel="stylesheet" />
<div data-role="page">
<div data-role="popup" id="nonetconnmain" data-dismissible="false" class="ui-content" data-theme="a">
<div class="popup_inner popup_sm">
<div class="popup_content" style="text-align:center;">
<p class="">Please check net connectivcty</p>
<label id="mainlabel" style="margin:100px auto 60px auto;color:Red; line-height:40px;font-size:medium;display:none">Please check</label>
</div>
<div class="popup_footer nonetconnmainclose">
<a class="">Try Again</a>
</div>
</div>
</div>
<button class="getStarted btn btn-a get_btn">Click Here</button>
</div>
You can use a small function (with time as parameter) and use jQuery animate() to create the process effect like below.
var updateProgress = function(t) {
$( "#p" ).css("width",0);
$( "#p" ).show();
$( "#p" ).animate({ "width": "100%" }, t , "linear", function() {
$(this).hide();
});
}
Do notice that the time that is chosen when calling updateProgress() is relevant with the delay and the fade in effect of the text message
updateProgress(3500);
$('#mainlabel').delay(3400).fadeIn(600);
Check it on the snippet below
var updateProgress = function(t) {
$( "#p" ).css("width",0);
$( "#p" ).show();
$( "#p" ).animate({ "width": "100%" }, t , "linear", function() {
$(this).hide();
});
}
$(document).on("click", ".getStarted", function(event) {
var a = 10;
if(a==10)
{
updateProgress(3500);
$('#mainlabel').delay(3400).fadeIn(600);
$('#nonetconnmain').popup({history: false}).popup('open');
event.stopImmediatePropagation();
event.preventDefault();
return false;
}
});
$(document).on('click', '.nonetconnmainclose', function(event) {
$('#nonetconnmain').popup('close');
$(".getStarted").trigger("click");
event.stopImmediatePropagation();
event.preventDefault();
return false;
});
$(document).on("popupbeforeposition", "#nonetconnmain",function( event, ui ) {
$('#mainlabel').hide();
});
.popup {
height: 200px;
width: 400px;
}
.popup h6 {
font-size: 1.5em !important;
}
#p {
border:none;
height:1em;
background: #0063a6;
width:0%;
float:left;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.js"></script>
<link href="http://code.jquery.com/mobile/1.3.2/jquery.mobile-1.3.2.min.css" rel="stylesheet"/>
<div data-role="page">
<div data-role="popup" id="nonetconnmain" data-dismissible="false" class="ui-content" data-theme="a">
<div class="popup_inner popup_sm">
<div class="popup_content" style="text-align:center;">
<p class="">Please check net connectivcty</p>
<div id="p"></div><br>
<label id="mainlabel" style="margin:100px auto 60px auto;color:Red; line-height:40px;font-size:medium;display:none">Please check </label>
</div>
<div class="popup_footer nonetconnmainclose">
<a class="">Try Again</a>
</div>
</div>
</div>
<button class="getStarted btn btn-a get_btn">Click Here</button>
</div>
Fiddle
Probably when you click on try again , you can have a setinterval triggered which can check for online connectivity and when found can close the popup and get started again, also when we do retries in the interval the progress can be shown as progressing dots..
Below is the code, i haven't tried to run the code, but it shows the idea
$(document).on('click', '.nonetconnmainclose', function(event) {
var msgUI = $("#mainlabel");
msgUI.data("previoustext",msgUI.html()).html("retrying...");
var progress = [];
var counter = 0 ,timeout = 5;
var clearIt = setInterval(function(){
var online = navigator.onLine;
progress.push(".");
if(counter > timeout && !online){
msgUI.html(msgUI.data("previoustext"));
counter=0;
}
if(online){
$('#nonetconnmain').popup('close');
$(".getStarted").trigger("click");
counter=0;
clearInterval(clearIt);
}
else{
msgUI.html("retrying" + progress.join(""));
counter++;
}
},1000);
event.stopImmediatePropagation();
event.preventDefault();
return false;
});
Sure,
try appending a loader GIF to one of the div and remember to remove the same when your process is finished.
Kindly refer to StackOverflow
And try appending this
$('#nonetconnmain').append('<center><img style="height: 50px; position:relative; top:100px;" src="cdnjs.cloudflare.com/ajax/libs/semantic-ui/0.16.1/images/…; alt="loading..."></center>');
This will append a loader to your HTML to show some kind of processing.

Parent listener $(this) listening to all selected child elements

When user clicks on add an item a new item append on the parent element, then clicking on that item a textarea prompts to edit its text.
HTML DOM / JS Fiddle
<div class="editor"></div>
add an item
<div class="options">
<br><b>Item Text</b> <br>
<textarea class="itemtext"></textarea>
</div>
JS(jQuery) / JS Fiddle
var $item = "<div class='item'>Text here...</div>",
$itembtn = $('a.additem'),
$editor = $('div.editor'),
$opt = $('div.options');
$itembtn.on('click', function(e){
e.preventDefault();
$editor.show();
$editor.append($item);
});
$($editor).on('click', 'div.item', function(){
var $this = $(this);
$opt.show();
$opt.find('textarea').val($this.text());
$opt.find('textarea').on('keyup', function(){
$this.text($opt.find('textarea').val());
});
});
$($editor).on('blur', 'div.item', function(){
$opt.hide();
});
But it seems that $(this) is not pointing to a single clicked element, instead it is pointing to all the clicked/selected child elements!
And also the blur event is not working!
How i can point $this to only one selected item but not all the clicked items?
Well, this was easy...
Change this:
$($editor).on('click', 'div.item', function(){
var $this = $(this);
console.log($this);
$opt.show();
$opt.find('textarea').val($this.text());
$opt.find('textarea').on('keyup', function(){
$this.text($opt.find('textarea').val());
});
});
Into this:
$($editor).on('click', 'div.item', function(){
var $this = $(this);
console.log($this);
$opt.show();
$opt.find('textarea').unbind('keyup').keyup(function(){
$this.text($opt.find('textarea').val());
}).val($this.text());
});
Since you are adding .on([...]) per element, you are adding always a new event listener. You can .unbind() it so it won't be tied to that element. And then you re-bind it.
In this context, using .on() is BAD
One way is to keep a variable of your current 'active' div (clicked div), and use that to set the text.
Fiddle
var $item = "<div class='item'>Text here...</div>",
$itembtn = $('a.additem'),
$editor = $('div.editor'),
$opt = $('div.options'),
$txt = $opt.find('textarea'),
$curtxt;
$itembtn.on('click', function(e){
e.preventDefault();
$editor.show();
$($item).appendTo($editor).click(function(){
$curtxt = $(this);
$txt.val($curtxt.text());
$opt.show();
$txt.select().focus();
});
});
$txt.keyup(function(){
$curtxt.html($txt.val().replace(/\r?\n/g, '<br>'));
}).blur(function(){
$opt.hide();
});
Before adding the keyup event destroy the keyup event you added on click of the div and yes its done
Use $(element).off('keyup') to unbind the previous keyup event and then add the current event using $(element).on('keyup',function).
Check the snippet
var $item = "<div class='item'>Text here...</div>",
$itembtn = $('a.additem'),
$editor = $('div.editor'),
$opt = $('div.options');
$itembtn.on('click', function(e){
e.preventDefault();
$editor.show();
$editor.append($item);
});
$($editor).on('click', 'div.item', function(){
var $this = $(this);
$opt.show();
var txtEd = $opt.find('textarea');
txtEd.val($this.text());
txtEd.off('keyup').on('keyup', function(){
$this.text($opt.find('textarea').val());
});
});
$($editor).on('blur', 'div.item', function(){
$opt.hide();
});
.editor { margin: 20px 0px; border: 1px solid #888; padding: 5px; display: none; }
.item { background: #ccc; margin: 5px; padding: 5px; }
.options textarea { width: 80%; height: 100px; }
.options { display: none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="editor"></div>
add an item
<div class="options">
<br><b>Item Text</b> <br>
<textarea class="itemtext"></textarea>
</div>

Categories

Resources