JQuery UI sortable - possible to cancel specific elements? - javascript

So I have two lists, connected in one-direction so that items from one can go to the other, but nothing can move into the origin list. What kind of click function do i need so that I can move items back from where they came?
$(function() {
$( ".current-campaign , .past-campaigns, .new-campaign" ).sortable({
connectWith: ".new-campaign",
handle: ".panel-heading",
cancel: ".portlet-toggle",
placeholder: "panel-placeholder",
containment: "document",
delay: 150,
opacity: .75,
revert: 50,
start: function(e, ui){
ui.placeholder.height(ui.item.height());
}
});
New Campaign
<ul class="new-campaign">
</ul>
Past Campaigns
<ul class="past-campaigns">
<li>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title"> Message
<a class="pull-right cancel" href="#"><i class="fa fa-times"></i></a></h3>
<span>Voiced by: Joe</span>
</div>
<div class="panel-body">
Message Copy
</div>
</div>
</li>
</ul>
I've tried doing something like this, but it doesn't work (albeit i'm no pro at javascript)
$( ".cancel ").click(function() {
$( this ).sortable( "cancel" );
});

You need to detach all of the elements on your second list and append the back to the first list. If order is important to you, then you need to create some ordering logic using something like a data-attribute that represents the order the elements on the first list were originally in.
For example:
<li data-order="1">...</li>
<li data-order="2">...</li>
<li data-order="3">...</li>
...
Use jQuery's detach function to remove an element from the DOM, but maintain a reference to it in memory so that you may insert it somewhere else.
Example:
var items = $('li').detach()
$('#someDivId').append(items)
Wrap that in a click function and you should be good to go. The jQuery documentation for the methods mentioned above can be found at:
Detach
Append

Related

How to handle event delegation with priorities?

I have this look-a-like code in my app :
let item;
$('.parent').on('click', function () {
item = $(this).attr('item') || 0;
});
$('.parent').on('click', '.children', this, function () {
doSomething();
});
<div class="parent" item="50">
<div class="children">
</div>
</div>
<div class="parent" item="51">
<div class="children">
</div>
</div>
<div class="parent" item="52">
<div class="children">
</div>
</div>
I have a parent element with several children in it. Clicking anywhere on the parent element will give me an item information, so I will be able to load functions according to this item variable on click on children.
My problem is : I have to delegate the onClick event on children to parent element otherwise the events will trigger in this order :
Click on any child
Click on parent, which is too late because I need item variable first
I have a functionality that replaces the parent element if activated, since it was dynamically inserted into the DOM, I have to delegate the onClick event as well, like this :
$('.grandParent').on('click', '.parent', function () {
item = $(this).attr('item') || 0;
});
Now my problem is that the events are triggering in the wrong order again :
Click on any child
Click on parent
How can I manage to set click event on parent as top priority?
Edit :
I will be more specific. I have a messages list on my page, each .message element contains the message content but also some functionnalities like edit, delete, set as favorite, like, etc.
Like this :
<div class="message" data-item="1">
<a class="edit">E</a>
<a class="delete">X</a>
<a class="favorite">Fav</a>
<a class="like">Like</a>
<div class="content">
Hello world !
</div>
</div>
<div class="message" data-item="2">
<a class="edit">E</a>
<a class="delete">X</a>
<a class="favorite">Fav</a>
<a class="like">Like</a>
<div class="content">
Hello world !
</div>
</div>
Each one of those functionnalities will trigger different functions when clicked : edit(), delete(), like(), etc.
All of them will make AJAX requests which will then send the item variable to my server in order to know what item has to be impacted by this click.
To avoid repetition in my events handlers, I am trying to get the data-item attribute's value with one event bound to click on .message element, relying on the bubbling of children elements.
Get the item where you actually want it and get rid of the handler on parent:
$('.parent').on('click', '.children', function () {
item = $(this).closest('.parent').attr('item');
doSomething();
});
EDIT:
Then get the item when you click on the grandparent:
$('.grandParent').on('click', '.children', function () {
item = $(this).closest('.parent').attr('item');
});
EDIT #2:
Based on the OPs updated requirements, do it like this:
<div class="message" data-item="1">
<a class="action edit" data-type="edit">E</a>
<a class="action delete" data-type="delete">X</a>
<a class="action favorite" data-type="favorite">Fav</a>
<a class="like">Like</a>
<div class="content">
Hello world !
</div>
</div>
<div class="message" data-item="2">
<a class="action edit" data-type="edit">E</a>
<a class="action delete" data-type="delete">X</a>
<a class="action favorite" data-type="favorite">Fav</a>
<a class="like">Like</a>
<div class="content">
Hello world !
</div>
</div>
$(document).on('click','.message .action',function(e) {
const item = $(this).closest('message').attr('item');
switch($(this).data('type')) {
case 'edit': doEdit(item); break;
case 'delete': doDelete(item); break;
case 'favorite': doFavorite(item); break;
}
});
See, one event handler?
It's a very common pattern to do what you're doing. In the absence of a more robust framework (e.g. React), then using plain jQuery this is how it should be done.

Lightslider bugging out inside featherlight on second click

FIDDLE: http://jsfiddle.net/2patspw2/3429/
I am using featherlight as my modal box and am running lightslider inside of it. It runs fine the first time it is clicked, but them for some reason it seems to bug out and duplicate itself. I had thought it might be duplicate slides so I read light slider documentation and added this:
onSliderLoad: function(el) {
el.lightGallery({
selector: '.gal .lslide'
});
This didn't fix the problem, so then I tried doing an each() of function (index) like so:
$('.inline').each(function(index) {
$(document).on("click", '.modal', function() {
// relevant code
});
});
I bound it to a delegated event since I have to activate via an on:click. However the element still seems to duplicate itself?
HTML:
<a href=".inline" class="modal" data-featherlight>Inline</a>
<div class="inline">
<ul class="gal">
<li data-thumb="http://sachinchoolur.github.io/lightslider/img/cS-1.jpg">
<img src="http://sachinchoolur.github.io/lightslider/img/cS-1.jpg"> TEST!!!!
</li>
<li data-thumb="http://sachinchoolur.github.io/lightslider/img/cS-2.jpg">
<img src="http://sachinchoolur.github.io/lightslider/img/cS-2.jpg"> YEAH!!!
</ul>
</div>
<a href=".inline-two" class="modal" data-featherlight>Inline2</a>
<div class="inline-two">
<ul class="gal">
<li data-thumb="http://sachinchoolur.github.io/lightslider/img/cS-1.jpg">
<img src="http://sachinchoolur.github.io/lightslider/img/cS-1.jpg"> asfasdf
</li>
<li data-thumb="http://sachinchoolur.github.io/lightslider/img/cS-2.jpg">
<img src="http://sachinchoolur.github.io/lightslider/img/cS-2.jpg"> YEAH!!!
</ul>
</div>
jQuery:
$(document).each(function(index) {
$('.modal').on("click", function() {
$('.gal').lightSlider({
gallery: true,
item: 1,
loop: true,
thumbItem: 9,
slideMargin: 0,
enableDrag: false,
currentPagerPosition: 'left',
onSliderLoad: function(el) {
el.lightGallery({
selector: '.gal .lslide'
});
}
});
})
});
Why is the carousel essentially duplicate the navigation and bugging out?
Note I tried doing loop: false as well, and it didn't change anything.

jquery ui sortable with angularjs, how to prevent horizontal drag and drop? axis:y not working

I am using jquery ui sortable with angularjs
I am doing this:
$scope.sortableOptions = {
start: function(e, ui) {
$(this).attr('data-previndex', ui.item.index());
},
update: function(e, ui) {
$(this).removeAttr('data-previndex');
},
receive: function(e, ui) {
},
stop: function(event, ui) {
var val = ui.item.attr("val");
$("#list"+val+" li").each(function(i, el){
$scope.updateTop(val,el.id,i);
});
$("#list"+val+"sub li").each(function(i, el){
$scope.updateBottom(val,el.id);
});
},
connectWith: ".group",
axis: 'y',
placeholder: 'placeholder',
helper: "clone",
dropOnEmpty: true,
};
As you can see I have given axis:y so it should allow drag and drop vertically only but horizontal drag and drop also works. I don't need horizontal drag and drop. Is there any other option to solve this issue?
Html looks like:
<div class="row">
<div class="col-md-12 sortable">
<table cellpadding="0" cellspacing="0">
<td ng-repeat="amount_info in amount_data" valign="top" width="300">
<!--sort list-->
<ul ui-sortable="sortableOptions" id="list{{amount_info.amount}}" class="group so_list{{amount_info.amount}}" ng-model="amount_info.sortList" >
<li ng-mouseup="mouseUp(sortItem.ProductId,amount_info.amount)" amount="{{amount_info.amount}}" ng-repeat="sortItem in amount_info.sortList track by $index" ProductId="{{sortItem.ProductId}}" id="prod_{{sortItem.ProductId}}">
<div id="tc_prod">
{{sortItem.Product}} [{{sortItem.ProductId}}]
</div>
</li>
</ul>
<div class="listdivide"></div>
<ul ui-sortable="sortableOptions" id="list{{amount_info.amount}}sub" class="group so_list{{amount_info.amount}}" ng-model="amount_info.nonSortList" >
<li ng-repeat="nonsortItem in amount_info.nonSortList track by $index" productId="{{nonsortItem.ProductId}}" id="prod_{{nonsortItem.ProductId}}" amount="{{amount_info.amount}}">
{{nonsortItem.Product}} [{{nonsortItem.ProductId}}]
</li>
</ul>
</div>
</td>
</table>
</div>
</div>
Each table td has a list in ul. items from one td should not be dragged to another td. But not it is possible. Axis:y is given but no effect. Is there any way to solve this?
axis y should work, here is the working codepen
In this i have used
axis:'y'
and also the same config options as u have given
Solved the issue by adding the following code.
beforeStop: function (event, ui) {
if($(ui.helper).parent().attr('class') != $(ui.placeholder).parent().attr('class')){
return false;
}
},
where each ul should have separate class and check a condition to see if the sender and receiver's classes are same, then allow otherwise return false.

Hide or disable drop down list menu buttons. jQuery of JavaScript.

I have a dynamically created 3 options list which are attached at the end of a table row. I want to hide or disable Edit and Copy options if certain conditions are not met when page loads. How can i do this using either jQuery of JavaScript.
<div class="btn-group ewButtonGroup open">
<button class="dropdown-toggle btn btn-small" data-toggle="dropdown" href="#">Options <b class="caret"></b></button>
<ul class="dropdown-menu ewMenu">
<li><a class="ewRowLink ewView" data-caption="View" href="teamsview.php?showdetail=&TeamID=1">View</a></li>
<li><a class="ewRowLink ewEdit" data-caption="Edit" href="teamsedit.php?TeamID=1">Edit</a></li>
<li><a class="ewRowLink ewCopy" data-caption="Copy" href="teamsadd.php?TeamID=1">Copy</a>
</li>
</ul>
</div>
I have tried the following code which deosnt work.
<script>
$(document).ready(function() {
var Week_Check = $('#ewRowLink ewView span').text();
if ( Week_Check > 10) {
$('.ewRowLink ewView').hide();
}
});
</script>
You have a bad jQuery selector. If you want to hide an element having both of those classes you want to go this way:
$('.ewRowLink.ewView').hide();
By using $('.ewRowLink ewView').hide(); you basically state: hide all ewView (?) elements that are inside other elements having ewRowLink class.
You can use .off() to unbind the event:
$('.ewEdit, .ewCopy').off('click');
or if you want to hide:
$('.ewEdit, .ewCopy').hide();
Yet you need to mention on what condition you want to do this.
<script>
$(document).ready(function() {
var Week_Check = $('#ewRowLink, #ewView').find('span').html();
if ( Week_Check > 10) {
$('.ewRowLink, .ewView').hide();
}
});
</script>

Isotope hide on click

My site has all elements displayed by default.
Isotope has the inbuilt method 'filter' - ie show ONLY this.
I'd like to make a function where I hide/show an element based on clicking on a button on screen - ie hide ONLY this (and show the others) / unhide this (and show the others).
Here's what I'm doing code-wise.
var music = $('#music').isotope();
$('nav button').on('click', function () {
music.isotope({
filter: "div." + $(this).attr("class")
});
With filtering, the filter parameter must match items in your HTML markup, if not the filter will not return anything.
FIDDLE DEMO: http://jsfiddle.net/XWVhc/1/
I can only provide an alternate example as you have not provided any html markup so that we could debug your current code, however, I'll explain how this works.
HTML FOR FILTERS:
Here we have a few simple buttons that will filter our items with the data-filter attribute attached to each button.
<div id="filter-buttons-holder">
<div class="filter-button" data-filter=".dog">DOG</div>
<div class="filter-button" data-filter=".cat">CAT</div>
<div class="filter-button" data-filter=".foo">FOO</div>
<div class="filter-button" data-filter=".bar">BAR</div>
<div class="filter-button selected" data-filter=".dog, .foo, .cat, .bar">SHOW ALL</div>
</div>
HTML FOR ISOTOPE ITEMS:
Here's the markup for our isotope items, notice that each item has a class of isotope-item and also has a class of what 'category' it belongs too, you can add multiple classes and it will still filter as expected.
<div id="module-columns-holder" class="isotope">
<a href="/" class="dog isotope-item">
<div><h1>DOG</h1></div>
</a>
<a href="/" class="cat foo isotope-item">
<div><h1>CAT</h1></div>
</a>
<a href="/" class="dog isotope-item">
<div><h1>DOG</h1></div>
</a>
<a href="/" class="foo isotope-item">
<div><h1>FOO</h1></div>
</a>
<a href="/" class="bar isotope-item">
<div><h1>BAR</h1></div>
</a>
</div>
JAVASCRIPT FILTERING
Here we set up our isotope container, notice the last data attribute is a filter, this is effectively what you're after, however you can specify which 'category' you want to filter on initially.
//Setup isotope for filters
var isotopeContainer = $('#module-columns-holder');
isotopeContainer.isotope({
itemSelector: '.isotope-item',
layoutMode : 'fitRows',
animationOptions : {
queue : false,
duration : 750,
easing: 'linear'
},
filter: '.dog, .cat, .foo, .bar'
});
CLICK EVENT FOR FILTERS
You can attach a filter to the buttons we created earlier so that you can have live filtering
$('#filter-buttons-holder .filter-button').on('click',function(){
var filters = $(this).data('filter');
var parent = $(this).closest('#filter-buttons-holder');
parent.find('.selected').removeClass('selected');
$(this).addClass('selected');
isotopeContainer.isotope({ filter: filters });
return false;
});
Hope this helps

Categories

Resources