How to implement toggle functionality on JQuery UI Selectable? - javascript

I'm using JQuery UI - Selectable. I want to deselect the element if it has been pressed and it has already been selected (toggle)
Could you help me to add this functionality please !

Because of all the class callbacks, you're not going to do much better than this:
$(function () {
$("#selectable").selectable({
selected: function (event, ui) {
if ($(ui.selected).hasClass('click-selected')) {
$(ui.selected).removeClass('ui-selected click-selected');
} else {
$(ui.selected).addClass('click-selected');
}
},
unselected: function (event, ui) {
$(ui.unselected).removeClass('click-selected');
}
});
});

You already have that functionality with jQuery UI selectable if you're holding down the Ctrl key while clicking.
If you really need that as the default functionality, you don't need to use selectable, you can do it just as a simple onclick handler, like what nolabel suggested.
Or... you might as well edit jquery.ui.selectable.js and add an option which does just what you need. Shouldn't be too hard, there are 4 places where event.metaKey is checked, make sure if your option is set, just run the codepaths as if event.metaKey was always true.
As the selectables could use some more customisation, you could also make a feature request for jQuery UI developers to include it in the next official version.

You have to inject two simple elements in the code to achieve what you want. This just inverts the metaKey boolean, whenever you need inverted/toggle functionality.
options: {
appendTo: 'body',
autoRefresh: true,
distance: 0,
filter: '*',
tolerance: 'touch',
inverted: false /* <= FIRST*/
},
_mouseStart: function(event) {
var self = this;
this.opos = [event.pageX, event.pageY];
if (this.options.disabled)
return;
var options = this.options;
if (options.inverted) /* <= SECOND*/
event.metaKey = !event.metaKey; /* <= SECOND*/

Related

jQuery trigger onDrop event react node

Is there any known method how to trigger the drop event from React via jQuery?
There seems to be little documentation about this topic, in general you should avoid using both but lets assume in this case it just makes sense.
I tried so far this, but the event seems to not receive on reactside.
$(document).ready(function() {
$(".draggable").draggable({
revert: "invalid"
});
$(".droppable").droppable({
accept: ".draggable",
classes: {
"ui-droppable-active": "ui-state-active",
"ui-droppable-hover": "ui-state-hover"
},
drop: function(event, ui) {
var event = document.createEvent("HTMLEvents");
event.initEvent("drop", true, true);
$(this)[0].dispatchEvent(event);
console.log("works as designed");
}
});
});
I have just finished implementing jQuery UI's drag-n-drop functionality, with .draggable() and .droppable(), in React. As you pointed out, you wouldn't normally want to do this, but sometimes it's the best tool for the job.
Your question doesn't entirely make sense to me. The drop event triggers when the .draggable() jQuery-managed element is dropped onto the .droppable() jQuery-managed element. So when you say that you want to "trigger the drop event from reactjs via jQuery", do you mean that you want to call the same function that jQuery uses when it drops the item, but you want to call that event from within React?? Or are you just trying to say that you want to use jQuery's drag-n-drop functions inside React?? Because those aren't the same thing. I'm going to assume that you're just trying to call jQuery's drag-n-drop features from within React.
import $ from 'jquery';
import 'jquery-ui/ui/widgets/draggable';
import 'jquery-ui/ui/widgets/droppable';
class SomeComponent extends React.Component {
setDroppable() {
const reactComponent = this;
$('.roleListItems').droppable({
drop : function(event, ui) {
const roleId = event.target.getAttribute('roleid');
const userId = ui.draggable[0].getAttribute('userid');
if (!reactComponent.roleUserExists(roleId, userId)) { session.ListOfRolesCarousel.callCreateRoleUser(roleId, userId); }
else { reactComponent.setSelectedRoleId(roleId, true); }
},
tolerance : 'touch',
});
}
setDraggable() {
const grabbingCursor = this.grabbingCursor;
$('.userListItems').draggable({
appendTo : document.getElementById('rolesContainer'),
helper : 'clone',
revert : 'invalid',
snap : '.roleListItems',
snapMode : 'inner',
snapTolerance : 25,
start : function(event, ui) {
ui.helper[0].style.cursor = grabbingCursor;
ui.helper[0].style.width = $('#rolesContainer').width() + 'px';
},
});
}
}
Here I'm:
Importing jQuery, as well as the draggable and droppable widgets
Inside .droppable(), I'm grabbing the values that I need from the dropped element (in this case, it's the roleId and the userId)
Then I call React functions/methods to process those values
Notice that I had to create a variable called reactComponent and set it to this so I could call the React method from inside the drop() function. This is necessary because this has a different meaning once you're inside jQuery's drop() method.

How to disable drag and drop with jquery.shapeshift?

I'm using this plugin grid system with drag and drop functionality:
https://github.com/McPants/jquery.shapeshift.
You can call the shapeshift function and pass it the parameters to enable and disable the drag and drop functionality.
$(".container").shapeshift({
enableDrag: true,
});
I want to be able to turn on and off this feature. I used this code:
var dragState = 0;
$(".switch").on("click", function() {
if(dragState == 0) {
options = {
enableDrag: true,
}
dragState = 1;
} else {
options = {
enableDrag: false,
}
dragState = 0;
}
$(".container").shapeshift(options);
});
When I run this code I can turn on drag and drop but not back off again.
Does anyone have any suggestions or experience with this plugin?
Use http://mcpants.github.io/jquery.shapeshift/ as a reference.
Basicaly all you need to do is:
$(function(){
var sso = {
minColumns: 3,
enableDrag: false
};
var ss = $(".container").shapeshift(sso);
$('button').click(function () {
sso.enableDrag = true;
ss.trigger('ss-destroy');
ss.shapeshift(sso);
});
});
I simplified the example to show what needs to be done in this fiddle:
http://jsfiddle.net/carisch19/hDm4e/2/
Added enable and disable buttons:
http://jsfiddle.net/carisch19/hDm4e/4/
Sorry for answering on such an old question but i was just going through shapeshift.js and understand that for disabling drag and drop we can destroy it but not in such a long way and there is no need to take it to variable.
Hope you will interested in this short way and update your codes.
Below is the code
$('div').trigger("ss-destroy");
Above code is sufficient for destroying and also a very clean and convenient way according to me.
Try once!

FullCalendar delete external events

When I'm trying to delete an external event from my calendar, if I add say 3 external events then drag one to the bin, rather than removing just the one event it deletes all events (even the ones from the separate feeds I am doing.
Any idea why this is and how to fix it? Here is the code:
$(document).ready(function () {
//listens for drop event
$("#calendarTrash").droppable({
tolerance: 'pointer',
drop: function (event, ui) {
var answer = confirm("Delete Event?")
if (answer) {
$('#calendar').fullCalendar('removeEvents', event.id);
}
}
});
/* initialize the external events ------------*/
$('#external-events div.external-event').each(function () {
// create an Event Object (http://arshaw.com/fullcalendar/docs/event_data/Event_Object/)
// it doesn't need to have a start or end
var eventObject = {
title: $.trim($(this).text()) // use the element's text as the event title
};
// store the Event Object in the DOM element so we can get to it later
$(this).data('eventObject', eventObject);
// make the event draggable using jQuery UI
$(this).draggable({
zIndex: 999,
revert: true, // will cause the event to go back to its
revertDuration: 0 // original position after the drag
});
});
});
The event.id in your drop function does not refer to the FullCalendar event. It refers to the drop event that was just triggered.
You will need to use ui.draggable to access your draggable - in this case the FullCalendar event.
Hope this helps! Cool concept BTW!
Update: Check this fiddle for a proof-of-concept
For anyone in the same circumstances,..
eventDragStop: function(event, jsEvent, ui, view) {
if (x) {
$('#calendar').fullCalendar('removeEvents', event._id);
}
Please notice I am using event._id, x is the result of checking which div the item is dragged into returning a true or false. checks which div the event is being dropped into. I also had to change some code in fullcalendar.js
the function eachEventElement, was causing me an issue with the above code, so I changed it too.
function eachEventElement(event, exceptElement, funcName) {
try{
var elements = eventElementsByID[event._id],
i, len = elements.length;
for (i=0; i<len; i++) {
if (!exceptElement || elements[i][0] != exceptElement[0]) {
elements[i][funcName]();
}
}
}
catch(err)
{}
}

jQuery Sortable - cancel and revert not working as expected

Problem (jsFiddle demo of the problem)
I'm having some trouble with the revert setting when used in conjunction with the cancel method in the jQuery sortable. The cancel method, as documented in the jQuery Sortable documentation states:
Cancels a change in the current sortable and reverts it back to how it
was before the current sort started. Useful in the stop and receive
callback functions.
This works fine in both the stop and receive callbacks, however if I add a revert duration to the sortable connected list, it starts to act funny (see jsFiddle here).
Ideally, upon cancelling, the revert could simply not happen, or alternatively in a more ideal world, it would gracefully revert to it's original location. Any ideas how I can get the revert and cancel to play nice?
Expected
Drag from left list to right list
Drop item
Item animates to original location - or - immediately shifts to original location
Actual
Drag from left list to right list
Drop item
Item animates to new location, assuming sortable is successful
Item immediately shifts to original location, as sortable was cancelled
Clarification
The revert property moves the item to the location where the item would drop if successful, and then immediately shifts back to the original location due to the revert occurring before the cancel method. Is there a way to alter the life-cycle so if the cancel method is executed, revert isn't, and instead the item is immediately return to it's original location?
i created a demo for you here:
the jsfiddle code
it seems to produce the output you expect.
i changed the receive callback method from this:
$(ui.sender).sortable('cancel');
to this:
$(ui.sender).sortable( "option", "revert", false );
hopefully, this is what you expected.
After many hours for searching for a solution I decided the only way to achieve what I was trying to do was to amend the way in which the jQuery sortable plugin registered the revert time. The aim was to allow for the revert property to not only accept a boolean or integer, but also accept a function. This was achieved by hooking into the prototype on the ui.sortable with quite a lot of ease, and looks something like this.
jQuery Sortable Hotfix
$.ui.sortable.prototype._mouseStop = function(event, noPropagation)
{
if (!event) return;
// if we are using droppables, inform the manager about the drop
if ($.ui.ddmanager && !this.options.dropBehaviour)
$.ui.ddmanager.drop(this, event);
if (this.options.revert)
{
var self = this;
var cur = self.placeholder.offset();
// the dur[ation] will not determine how long the revert animation is
var dur = $.isFunction(this.options.revert) ? this.options.revert.apply(this.element[0], [event, self._uiHash(this)]) : this.options.revert;
self.reverting = true;
$(this.helper).animate({
left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
}, !isNaN(dur) ? dur : 500, function ()
{
self._clear(event);
});
} else
{
this._clear(event, noPropagation);
}
return false;
}
Implementation
$('ul').sortable({
revert: function(ev, ui)
{
// do something here?
return 10;
}
});
I ended up creating a new event called beforeRevert which should return true or false. If false then the cancel function is called and the item is animated back to its original position. I didn't code this with the helper option in mind, so it would probably need some additional work to support that.
jQuery Sortable Hotfix with animation
var _mouseStop = $.ui.sortable.prototype._mouseStop;
$.ui.sortable.prototype._mouseStop = function(event, noPropagation) {
var options = this.options;
var $item = $(this.currentItem);
var el = this.element[0];
var ui = this._uiHash(this);
var current = $item.css(['top', 'left', 'position', 'width', 'height']);
var cancel = $.isFunction(options.beforeRevert) && !options.beforeRevert.call(el, event, ui);
if (cancel) {
this.cancel();
$item.css(current);
$item.animate(this.originalPosition, {
duration: isNaN(options.revert) ? 500 : options.revert,
always: function() {
$('body').css('cursor', '');
$item.css({position: '', top: '', left: '', width: '', height: '', 'z-index': ''});
if ($.isFunction(options.update)) {
options.update.call(el, event, ui);
}
}
});
}
return !cancel && _mouseStop.call(this, event, noPropagation);
};
Implementation
$('ul').sortable({
revert: true,
beforeRevert: function(e, ui) {
return $(ui.item).hasClass('someClass');
}
});

can jsTree use radio check

i know there is a plugin for jsTree named jquery.tree.checkbox.js.
that make the tree node multi checkable.
i just wondered if there is a plugin to raido check the tree node?
or how can i modify jquery.tree.checkbox.js to achieve that?
This can simply be done by adding the attribute
rules:{
multiple : false
}
Inside the configuration of the tree.
This will make it impossible to choose multiple entries.
#Asaf's answer seems to no longer work on version 3.3.1 in 2016. You now need to set multiple on core:
$jstree.jstree({
core: {
multiple: false,
...
}
});
Setting multiple:false will still allow cascading so you need to turn that off too.
version 3.3.3
$(".tree").jstree({
plugins: ["checkbox"],
core: {
data: ...,
multiple: false
},
checkbox: {
three_state: false,
cascade: "none"
}
});
The radio button option is still not released, so you have to change the chceckbox option as single select.
bind('check_node.jstree', function(e, data) {
var currentNode = data.rslt.obj.attr("id");
$("#tree").jstree("get_checked",null,true).each
(function () {
if(currentNode != this.id){
jQuery.jstree._reference($("#tree")).uncheck_node('#'+this.id);
}
});
});
refer this http://jsfiddle.net/bwTrP/1/
Using jsTree version 3.2.1 with the checkbox plugin it is possible to emulate radiobutton behaviour handling the 'changed' event as follows:
//jstree configuration:
'checkbox': {
three_state: false, //required for the cascade none to work
cascade: 'none' //no auto all_children<->parent selection
},
//...
var resetting = false;
$('#tree').on('changed.jstree', function (e, data) {
if (resetting) //ignoring the changed event
{
resetting = false;
return;
}
if ($("#multiselect").is(':checked') == false && data.selected.length > 1) {
resetting = true; //ignore next changed event
data.instance.uncheck_all(); //will invoke the changed event once
data.instance.check_node(data.node/*currently selected node*/);
}
});
JSFiddle: JSTree radiobutton behaviour example using checkbox plugin

Categories