Dragula - Drag elements from one container to different elements - javascript

My question is related to dragula https://github.com/bevacqua/dragula
I am trying to drag elements from one container and drop them (copy not move) into different containers. So, in this way I have one container which contains elements to drag and I want to drop them into different containers but its not working properly and sometimes its not working at all. Please guide me what is wrong with my code.
HTML
/*container which contains elements to drag */
<div class="row">
<div class="col-md-12">
<div class="activityIcons" style="text-align:center;">
<ul class="media-list media-list-container" id="media-list-target-left">
<li class="media" style="display:inline-block;" id="phone">
<div class="media-left media-middle dots" ><i class="icon-phone2 text-indigo-800 dragula-handle" style="font-size:22px;" data-popup="tooltip" title="Phone Call" data-container="body" data-trigger="hover" data-placement="bottom"></i></div>
</li>
<li class="media" style="display:inline-block;" id="history">
<div class="media-left media-middle dots"><i class="icon-history text-orange-600 dragula-handle" style="font-size:22px;" data-popup="tooltip" title="Review Order History" data-container="body" data-trigger="hover" data-placement="bottom"></i></div>
</li>
<li class="media" style="display:inline-block;" id="order">
<div class="media-left media-middle dots"><i class="text-blue-600 icon-cart-add2 dragula-handle" style="font-size:22px;" data-popup="tooltip" title="Place Product Order" data-container="body" data-trigger="hover" data-placement="bottom"></i></div>
</li>
</ul>
</div>
</div>
</div>
/* containers where elements will be dropped */
<div class="activity" id="1" style="margin-top: 5px; padding:5px; border: 1px solid #ccc;">
<div class="row activityDetail" id="1" style="padding:5px; margin:15px;">
<div class="col-md-12" style="border-bottom:1px solid #ddd;">
<span class="text-bold text-black actTime" style="cursor:pointer; margin-right:5px;">Time</span>
<span class="text-bold text-black regionCust" style="cursor:pointer; margin-right:5px;">Region & Customer</span>
<span class="media-list-container" id="activitiesBar1"><span class="dropMsg1">Drop Here</span></span>
<span class="pull-right stats">
<ul></ul>
</span>
</div>
</div>
<div class="row activityDetailTwo" id="2" style="padding:5px; margin:15px;">
<div class="col-md-12" style="border-bottom:1px solid #ddd;">
<span class="text-bold text-black actTimeTwo" id="2" style="cursor:pointer; margin-right:5px;">Time</span>
<span class="text-bold text-black regionCustTwo" id="2" style="cursor:pointer; margin-right:5px;">Region & Customer</span>
<span class="media-list-container" id="bar2"><span class="dropMsg2">Drop Here</span></span>
<span class="pull-right stats">
<ul></ul>
</span>
</div>
</div>
JQuery
dragula([document.getElementById('media-list-target-left'), document.getElementById('activitiesBar1')], {
copy: true,
revertOnSpill: true,
mirrorContainer: document.querySelector('.media-list-container'),
move: function (el, container, handle) {
return handle.classList.contains('dragula-handle');
}
}).on('drop', function(el) {
var actionId = $(el).attr('id');
if($('#activitiesBar1').children('.dropMsg1').length > 0){ $('.dropMsg1').remove(); }
if(actionId == "phone"){ $('.callDuration').modal(); }
if(actionId == "history"){ $('.orderHistoryModal').modal(); }
if(actionId == "order"){ $('.catalog').modal(); }
if(actionId == "chat"){ $('.conversation').modal(); }
if(actionId == "reschedule"){ $('.schedule').modal(); }
if(actionId == "training"){ $('.training').modal(); }
if(actionId == "visit"){ $('.carExpenses').modal(); }
});
dragula([document.getElementById('media-list-target-left'), document.getElementById('bar2')], {
copy: true,
revertOnSpill: true,
mirrorContainer: document.querySelector('#bar2'),
move: function (el, container, handle) {
return handle.classList.contains('dragula-handle');
}
}).on('drop', function(el) {
var actionId = $(el).attr('id');
if($('#bar2').children('.dropMsg2').length > 0){ $('.dropMsg2').remove(); }
if(actionId == "phone"){ $('.callDuration').modal(); }
if(actionId == "history"){ $('.orderHistoryModal').modal(); }
if(actionId == "order"){ $('.catalog').modal(); }
if(actionId == "chat"){ $('.conversation').modal(); }
if(actionId == "reschedule"){ $('.schedule').modal(); }
if(actionId == "training"){ $('.training').modal(); }
if(actionId == "visit"){ $('.carExpenses').modal(); }
});
Your suggestions will be highly appreciated.
Thank you.

Had the same basic requirement (one "source container" to copy from).
I think you are supposed to handle it all within one drake object that has all the containers and handles the behaviour with its options.
The key to have one "source container" to copy from is to have a simple method as copy option:
dragula([document.getElementById('media-list-target-left'), document.getElementById('activitiesBar1'),
document.getElementById('bar2')], {
copy: function (el, source) {
return source.id === 'media-list-target-left';
},
accepts: function (el, target) {
return target.id !== 'media-list-target-left';
}
}
);
So in this case you can copy from media-list-target-left to other containers but not drop elements into this container.

Related

index.js:28 Uncaught TypeError: Cannot read property 'addEventListener' of null ( at toggleActiveOnClick and at Array.forEach)

For a project I have to evolve a piece of code but I can not. This bit of code initially allows me to toggle the 4 clickable elements of a certain form and it works perfectly.
const choices = document.querySelectorAll('.clickable');
const toggleActiveClass = (event) => {
event.currentTarget.classList.toggle('active');
};
const toggleActiveOnClick = (choice) => {
choice.addEventListener('click', toggleActiveClass);
};
choices.forEach(toggleActiveOnClick);
However, now I have to make sure that when I select one or the other of the first 2 elements I can not toggle the other and the same for the next 2. I tried this piece of code but when I open the console in chrome tool i get the error message present in the title of this post. Here is the piece of code in question:
const upsell = document.querySelector('.clickable > .fas fa-shopping-cart');
const crossell = document.querySelector('.clickable > .fas fa-cart-plus');
const standard = document.querySelector('.clickable > .fas fa-gift');
const discount = document.querySelector('.clickable > .fas fa-percent');
const choices = [ upsell, crossell, standard, discount ];
const toggleActiveClass = (event) => {
event.currentTarget.classList.toggle('active');
};
const toggleActiveOnClick = (choice) => {
if (choice === upsell.addEventListener('click', toggleActiveClass)) {
crossell.classList.remove('active');
} else if (choice === crossell.addEventListener('click', toggleActiveClass)) {
upsell.classList.remove('active');
} else if (choice === standard.addEventListener('click', toggleActiveClass)) {
discount.classList.remove('active');
} else if (choice === discount.addEventListener('click', toggleActiveClass)) {
standard.classList.remove('active');
}
};
choices.forEach(toggleActiveOnClick);
Here is the corresponding html
<div class="form-group">
<label for="bundle-type">Bundle Type</label>
<div class="d-flex flex-wrap justify-content-center pt-4">
<div id="test1">
<div class="clickable">
<i class="fas fa-shopping-cart"></i>
<small>Upsell</small>
</div>
</div>
<div id="test2">
<div class="clickable">
<i class="fas fa-cart-plus"></i>
<small>Cros-sell</small>
</div>
</div>
</div>
<label for="bundle-type">Offer Type</label>
<div class="d-flex flex-wrap justify-content-center pt-4">
<div id="test3">
<div class="clickable">
<i class="fas fa-gift"></i>
<small>Standard</small>
</div>
</div>
<div id="test4">
<div class="clickable">
<i class="fas fa-percent"></i>
<small>Discounted</small>
</div>
</div>
</div>
</div>
And the CSS
.clickable i {
font-size: 24px;
margin-bottom: 10px;
}
.clickable:hover i {
color: #167FFB;
}
.clickable.active {
color: inherit;
border-color: inherit;
}
.clickable.active i {
color: #0F60C4;
}
Your selectors are just wrong, and you could have verified them (upsell and the others) with debugging/logging.
class="fas fa-shopping-cart" asssigns two classes to the element, fas and fa-shopping-cart. While it may be possible that after digesting the specification someone can come up with a selector for multiple classes, you could simply ignore fas (which is the same for all of them), and go for the specific ones instead:
console.log("Original attempt:");
const upsell = document.querySelector('.clickable > .fas fa-shopping-cart');
const crossell = document.querySelector('.clickable > .fas fa-cart-plus');
console.log(upsell);
console.log(crossell);
console.log("Simplified attempt:");
const upsellSimple = document.querySelector('.clickable > .fa-shopping-cart');
const crossellSimple = document.querySelector('.clickable > .fa-cart-plus');
console.log(upsellSimple);
console.log(crossellSimple);
<label for="bundle-type">Bundle Type</label>
<div class="d-flex flex-wrap justify-content-center pt-4">
<div id="test1">
<div class="clickable">
<i class="fas fa-shopping-cart"></i>
<small>Upsell</small>
</div>
</div>
<div id="test2">
<div class="clickable">
<i class="fas fa-cart-plus"></i>
<small>Cros-sell</small>
</div>
</div>
</div>
What others tried to point out: addEventListener() has no meaningful return value:
Return value: undefined
The comparisons (if (choice === xy.addEventListener(...)){...}) can not really do anything useful.

how to change bootstrap carousel arrow class

I have this bootstrap carousel with arrows at the top right corner. I have set data-wrap="false" so that it stops when it reaches the end of the Carousel. Also, the left arrow becomes active when the first carousel starts.
Here's what I want to do: I want the class class-fade to change to class-active when the slide becomes active. And then change to class-fade when it becomes non-active again.
I hope this makes sense.
JSFIDDLE: https://jsfiddle.net/6kjnmbcb/
HTML:
<div class="container">
<p>When the carousel comes to an end, change the class <strong>"class-active"</strong> to <strong>"class-fade"</strong>.
<span class="pull-right">
<a class="" href="#CaseCarousel" data-slide="prev"><i class="class-fade"> << </i></a>
<a class="" href="#CaseCarousel" data-slide="next"><i class="class-active"> >> </i></a>
</span>
</p>
<hr />
<div class="row">
<div class="carousel slide" data-interval="false" data-wrap="false" id="CaseCarousel">
<div class="carousel-inner">
<div class="item active">
<div class="col-xs-6">
<p>
Slide1 goes here
</p>
</div>
<div class="col-xs-6">
<p>
Slide2 goes here
</p>
</div>
</div>
<div class="item">
<div class="col-xs-6">
<p>
Slide3 goes here
</p>
</div>
<div class="col-xs-6">
<p>
Slide4 goes here
</p>
</div>
</div>
<div class="item">
<div class="col-xs-6">
<p>
Slide5 goes here
</p>
</div>
<div class="col-xs-6">
<p>
Slide6 goes here
</p>
</div>
</div>
</div>
</div>
</div>
</div>
CSS:
.class-fade {
color: grey;
}
.class-active {
color: red;
}
You need to use slide.bs.carousel event described in bootstrap
$('#CaseCarousel').on('slide.bs.carousel', function (e) {
var controls = document.querySelectorAll('.controls');
if (e.direction === 'left') {
controls[0].className = 'controls class-active';
}
if (e.direction === 'right') {
controls[1].className = 'controls class-active'
}
var inner = document.querySelector('.carousel-inner');
if (e.relatedTarget == inner.lastElementChild) {
controls[1].className = 'controls class-fade'
}
if (e.relatedTarget == inner.firstElementChild) {
controls[0].className = 'controls class-fade'
}
})
There is a full solution
https://jsfiddle.net/oeraa2kL/2/
You can handle the slide.bs.carousel event :
Take a look at this fiddle : https://jsfiddle.net/BaobabCoder/7756yuzb/1/
$(document).on('slide.bs.carousel', '.carousel', function(e) {
var slidesLength = $(this).find('.item').length;
var slideFrom = $(this).find('.active').index();
var slideTo = $(e.relatedTarget).index();
if(slideFrom === 0 || slideTo === 0) {
$('a[href="#CaseCarousel"][data-slide="prev"] i:eq(0)').toggleClass('class-fade');
$('a[href="#CaseCarousel"][data-slide="prev"] i:eq(0)').toggleClass('class-active');
}
else if(slideFrom === slidesLength || slideTo === slidesLength) {
$('a[href="#CaseCarousel"][data-slide="next"] i:eq(0)').toggleClass('class-fade')
$('a[href="#CaseCarousel"][data-slide="next"] i:eq(0)').toggleClass('class-active');
}
});

Deactive bootstrap active label click

I have several groups with a selection of three buttons. I'm trying to make it so that when someone selects the N/A button, it disables the other two buttons. When the N/A button is deselected, the other two buttons are enabled. I have it working on my machine, that the other two buttons are colored as disabled, and have the "disabled" attribute set properly. The problem is, that the buttons/labels can still be clicked on and set the label to active.
I'm having trouble getting my JSFiddle to operate the same as on my machine. It won't disable the other two buttons on the initial N/A click, but it may just be something with JSFiddle. Here is my code, if you want to try it on your own machine:
https://jsfiddle.net/trout0525/huz8macm/7/
<div id="plan-wrapper">
<div class="row plan-title-row">
<div class="col-lg-6" id="plan-title">
Loading...
</div>
<div class="col-lg-6">
<div class="pull-right" id="countdown">
Countdown
</div>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<div class="panel panel-default" style="margin-bottom: 4px;">
<div class="panel-body">
<div class="row" id="master-progress">
</div>
</div>
</div>
</div>
</div>
<div id="plan-file-title" style="margin: 0 0 4px 5px;"></div>
<div class="row">
<div class="col-md-12">
<ul class="nav nav-tabs">
<li role="presentation" class="active"><a data-toggle="tab" href="#planTeam">Team</a></li>
<li role="presentation" class=""><a data-toggle="tab" href="#planResources">Resources</a></li>
<li role="presentation" class=""><a data-toggle="tab" href="#planStatus">Status</a></li>
</ul>
<div class="tab-content" style="background-color: white; padding: 10px; border-left: 1px solid #ddd; border-right: 1px solid #ddd; border-bottom: 1px solid #ddd;">
<div id="planTeam" class="tab-pane fade in active">
</div>
<div id="planResources" class="tab-pane fade">
</div>
<div id="planStatus" class="tab-pane fade">
</div>
</div>
</div>
</div>
</div>
Any help would be great.
Got it done on JSFiddle with removal of typos and debugging through developer console, yet it's currently with Chrome, not IE:
https://jsfiddle.net/trout0525/huz8macm/9/
$(".btn-group .btn").on('click', function (e) {
e.preventDefault();
e.stopPropagation();
var $selectedButton = $(this),
$panelDefault = $selectedButton.closest('.panel-default'),
$controlPanel = $panelDefault.find('.panel-heading .pull-right'),
parent = $selectedButton.closest('.panel-default').attr('data-stepId'),
stepId = $selectedButton.closest('li').attr('id'),
spcStat = $selectedButton.attr('id').match(/^(.*?)\d+$/)[1];
var buttonIsActive = $selectedButton.hasClass('active'),
buttonIsDisabled = $selectedButton.attr('disabled');
if ( buttonIsActive || buttonIsDisabled ) {
$selectedButton.removeClass('active');
} else {
$selectedButton.addClass('active');
}
if ($selectedButton.hasClass('not-applicable')) {
var naIsActive = $selectedButton.hasClass('active'),
allButtons = $selectedButton.closest('.btn-group');
if (naIsActive) {
$selectedButton.siblings().removeClass('active');
$(allButtons)
.find('.btn_draft_complete')
.attr('disabled', 'disabled')
.attr('title', 'Disabled. To enable: deselect N/A for this substep')
.find('input')
.css('point-events', 'auto');
$(allButtons)
.find('.btn_done')
.attr('disabled', 'disabled')
.attr('title', 'Disabled. To enable: deselect N/A for this substep')
.find('input')
.css('point-events', 'auto');
} else {
$(allButtons)
.find('.btn_draft_complete')
.removeAttr('disabled')
.attr('title', 'Mark step as Draft Complete')
.find('input')
.removeAttr('disabled')
$(allButtons)
.find('.btn_done')
.removeAttr('disabled')
.attr('title', 'Mark step as Draft Complete')
.find('input')
.removeAttr('disabled')
}
}
});

Moving DIV disable button 0px left-margin

I have a little problem. Im trying to create my own slider using jQuery and some css/javascript.
I got my slider to work moving a Div 660px to the left and right by clicking a button.
But, I would like to have the right button disabled when the left margin is 0. And I would like the whole div to rewind back to 0px after some clicks.
Is this possible?
Here is my code:
<script language="javascript">
function example_animate(px) {
$('#slide').animate({
'marginLeft' : px
});
}
</script>
<div class="container">
<div class="row">
<div class="contr-left">
<a type="button" value="Move Left" onclick="example_animate('-=600px')"><i class="fa fa-chevron-circle-left fa-2x" aria-hidden="true" ></i></a>
</div>
<div id="carreview" class="carousel" data-ride="carousel" style="opacity: 1; display: block;">
<div class="wrapper-outer">
<div class="wrapper-inner" id="slide">
<?php get_template_part('loop-reviews');?>
</div>
</div>
<div class="contr-right">
<a type="button" value="Move Right" onclick="example_animate('+=600px')"><i class="fa fa-chevron-circle-right fa-2x" aria-hidden="true" ></i></a>
</div>
</div>
</div>
</div>
The code im using is from this page: Page
Well, with the code from Rayn i got the button to hide, but now it won't show when left-margin is 1px or something. So I'm trying this now: (doesn't work btw)
Im trying this now: (doesn't work btw)`function example_animate(px) {
$('#slide').animate({
'marginLeft' : px
});
var slidemarginleft = $('#slide').css('margin-left'); //this gets the value of margin-left
if(slidemarginleft == '0px'){
$('.contr-right').hide();
} else (slidemarginleft == '1px') {
$('.contr-right').show();
}
}`
Also I'm seeing that the margin-left isn't set in the style sheet but in the
<div style="margin-left:0px">content</div>
You can do an if statement after each click to check if the element has 0px
function example_animate(px) {
$('#slide').animate({
'marginLeft' : px
});
var slidemarginleft = $('#slide').css('margin-left'); //this gets the value of margin-left
if(slidemarginleft == '0px'){
$('.contr-right').hide();
}
}
Use this
function example_animate(px) {
$('#slide').animate({
'marginLeft' : px
});
if($('.xman').css("marginLeft")=='0px'){
$('.contr-left').attr('disabled',true);
}
}
Disable Button when margin-left: 0px
You can use jquery's .prop() method to disable a button if a condition is met. Here is an example (in pseudo code):
function disableButton() {
$(element).prop('disabled', true);
}
function checkMargin() {
if ($(element).css("margin") === 0) {
disableButton()
}
}
checkMargin()
Rewind to 0px after some clicks
Here, I'd just set a count for clicks and trigger a function when it meets the threshold you want. Pseudo code:
var threshold = 5
var clicks = 0
$(element).click(function(){
clicks++
if (clicks === 5) {
rewind();
}
clicks - 5
})
function rewind() {
$(element).css( "margin", "0" );
checkMargin()
}
Here is my working code, thanks for all the help:
<script>
function example_animate(px) {
$('#slide').animate({
'marginLeft' : px
});
var slidemarginleft = $('#slide').css('margin-left'); //this gets the value of margin-left
if(slidemarginleft < '-3000px'){
$('#slide').animate({marginLeft: '0px'}, 400);
}
var hide = $('#slide').css('margin-left'); //this gets the value of margin-left
if(hide >= '-50px'){
$('.contr-left').addClass('showMe');
}
var hideMe = $('#slide').css('margin-left'); //this gets the value of margin-left
if(hideMe <= '-50px'){
$('.contr-left').removeClass('showMe');
}
}
</script>
<!-- /Review script -->
<section id="reviews">
<div class="container">
<div class="row">
<div class="container">
<div class="row">
<h4>Reviews</h4>
</div>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-sm-1" style="width:40px;">
<div class="row">
<div class="contr-left">
<a type="button" value="Move Left" onclick="example_animate('+=510px')"><i class="fa fa-chevron-circle-left fa-2x" aria-hidden="true" ></i></a>
</div>
</div>
</div>
<div class="col-sm-10">
<div class="row">
<div id="carreview" class="carousel" data-ride="carousel" style="opacity: 1; display: block;">
<div class="wrapper-outer">
<div class="wrapper-inner" id="slide" style="margin-left:0px;">
<?php get_template_part('loop-reviews');?>
</div>
</div>
</div>
</div>
</div>
<div class="col-sm-1" style="width:40px;">
<div class="row">
<div class="contr-right">
<a type="button" value="Move Right" onclick="example_animate('-=510px')"><i class="fa fa-chevron-circle-right fa-2x" aria-hidden="true" ></i></a>
</div>
</div>
</div>
</div>
<div class="btn btn-06">Bekijk alle reviews</div>
</div>
</section>

Filter by checkbox show/hide target divs jquery [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I'm having trouble targetting the divs I need to show/hide when my jQuery runs.
I need to hide <div class="grid-cell> otherwise flexbox won't display correctly once the div's are hidden.
I'm having trouble getting it to hit the correct divs and it's not working now after changing my code a bit.
https://jsfiddle.net/s1e93j92/6/
<input type="checkbox" class="checkbox" name="High" data-category-type="high">High
<input type="checkbox" class="checkbox" name="low" data-category-type="low" > Low
<input type="checkbox" class="checkbox" name="low" data-category-name="bread" > bread
<div class="wrap">
<div class="grid grid--flexcells grid--gutters grid--1of2">
<div class="grid-cell">
<div class="box">
<div id="categories" data-category-type="high" data-category-name="low">
<a href="#">
<div class="image"><img src="#"></div>
</a>
</div>
</div>
</div>
<div class="grid-cell">
<div class="box">
<div id="Categories" data-category-type="high" data-category-name="bread">
<a href="#">
<div class="image"><img src="#"></div>
</a>
</div>
</div>
</div>
<div class="grid-cell">
<div class="box">
<div id="Categories" data-category-type="high" data-category-name="low">
<a href="#">
<div class="image"><img src="#"></div>
</a>
</div>
</div>
</div>
<div class="grid-cell">
<div class="box">
<div id="Categories" data-category-type="low" data-category-name="bread">
<a href="#">
<div class="image"><img src="#"></div>
</a>
</div>
</div>
</div>
</div>
.wrap{width:80%; height:200px; border:1px solid #ccc;}
.grid { display: flex; flex-wrap: wrap; list-style: none; margin: 0; padding: 0; }
.grid--1of2 > .grid-cell { flex: 0 0 50%; }
.image{width:100%; height:100px; border:1px solid #ff00ff}
$('.checkbox ').on('click', function (e) {
var $this = $(this),
$links = $('.checkbox');
if ($this.hasClass('selected')) {
$this.removeClass('selected');
} else {
$this.addClass('selected');
}
var selectedDivs = $('.box > categories > a > div').hide();
var anySelectedCheckbox = false;
$.each($links, function (k, v) {
$this = $(v);
if ($this.hasClass('selected')) {
anySelectedCheckbox = true;
var cat = $this.data('categoryType');
var nam = $this.data('categoryName');
selectedDivs = selectedDivs.filter('[data-category-type="'+cat+'"], [data-category-name="'+nam+'"]');
}
});
selectedDivs.show();
if(!anySelectedCheckbox) {
$('.box > div').show();
}
});
As the comment suggests, it's not perfectly clear what you're trying to do, but I think I got it. I didn't make any changes to your HTML or CSS. Just modified your JavaScript a little.
$('.checkbox').on('click', function (e) {
var $this = $(this),
$links = $('.checkbox');
if ($this.hasClass('selected')) {
$this.removeClass('selected');
} else {
$this.addClass('selected');
}
$('.box').hide();
if ($(".checkbox:checked").length > 0) {
// any one is checked
$.each($links, function (k, v) {
$this = $(v);
if ($this.hasClass('selected')) {
anySelectedCheckbox = true;
var cat = $this.data('categoryType');
var nam = $this.data('categoryName');
$('.box:has(div[data-category-type="' + cat + '"],div[data-category-name="+nam+"] )').show();
}
});
} else {
// none is checked
$('.box').show();
}
});
http://jsfiddle.net/yzyyqqey/

Categories