I have 2 containers.
Both of them is a draggable and dropable, to be sure I can move tags from one to another.
In the drop function I check the id of containers. Based on the name of the id, I decide, should I add a tag to a user or should I remove it from the user.
Let's says, there is a container div for existsTagsContiner. This contains the tags of the user.
The other container is userTagsContainer what contains all of the tags what are not belongs to user.
Both of these container has a class: .draggableTagContainer
Everything is works fine, when I move the tag from one to other, ajax made the operations, and a message appears for user.
For example, if user moves a tag from existsTagsContiner to userTagsContainer then I should add the tag to user.
But, and here comes my problem: if I am moving a tag from existsTagsContiner to existsTagsContiner (so no movement happened, just a drag and drop in the same container), the message appears too!
Definitely it should not happen. So, what I want to achive is to get the "source" id of the container. If the "source" is the same as $(this).attr('id') in the drop function, I just do nothing.
I've added a comment, where I need to get the original container name.
Here is my code.
$('#existsTagsContiner, #userTagsContainer').droppable({
tolerance: "intersect",
accept: ".draggableTagContainer",
drop: function (event, ui) {
var tagId = $(ui.helper.context).data('id');
$('#tagId').val(tagId);
//At here I need something like $(ui.helper.___SOURCE___)
if ($(this).attr('id') === 'existsTagsContiner') {
$.removeTagFromUser();
} else {
$.saveTagToUser();
}
$('#tagId').val('0');
if (!$(this).find('ul').length) {
$(this).html('<ul>');
}
$(this).find('ul').append($(ui.draggable));
}
});
$('.draggableTagContainer').draggable({
start: function (event, ui) {
$(ui.helper).addClass("draggableTagContainer");
},
appendTo: 'parent',
cursor: "move",
helper: 'clone',
revert: 'invalid',
cancel: ".draggableTagDelete",
});
UPDATE
That could be a workaround, if I add a data-from to the li when start to drag. But maybe there is a built in function for this, this is what I want to know.
This is the workaround. In the start function of draggable add:
$(ui.helper).data('from', $(this).closest('.tagContainer').attr('id'));
in the droppable drop function add:
if ($(this).attr('id') === ui.helper.data('from')) {
return false;
}
Related
I'm trying to create a jquery drag and drop solution and am a little lost with how I achieve the following.
Allow '.todo-task' to be dropped into any of the 4 'backlog, pending, inProgress, completed' div containers.
Use a highlight helper to show where the task will be placed in the container.
Be able to drag and drop with in a container to change to order.
my first issue is that I cannot seem to be able to activate the drag items correctly.
I have created a jsfiddle with the code I have so far. Appreciate any guidance / help
here is my jquery code
$(".task-container").contents().find(".todo-task").draggable({
connectToSortable: ".ui-droppable",
helper: function (event) {
},
iframeFix: true,
// stop: makeSortable()
stop: function (event, ui) {
// alert('stop');
}
});
$(".ui-droppable").sortable({
placeholder: "ui-state-highlight",
opacity: .5,
//dropOnEmpty: true,
helper: 'original',
beforeStop: function (event, ui) {
newItem = ui.item;
},
receive: function (event, ui) {
},
}).disableSelection().droppable({
over: ".ui-droppable",
activeClass: 'highlight',
drop: function (event, ui) {
$(this).addClass("ui-state-highlight");
}
})
I'm not sure exactly what else you're trying to achieve in terms of the "disabled" style CSS, but I just forked and monkeyed around with this for a minute:
jsfiddle
One thing is that I think your jQuery methods are redundant. Why say:
$(".task-container").contents().find(".todo-task").draggable( ...etc.
When you can just as easily do this:
$(".todo-task").draggable( ...etc.
So I cleaned a little bit of that up.
The other thing I did was to make the .task-container droppable.
See the jQuery API: droppable methods
This allows you to sort and move between columns, but like I mentioned this fix seems to behave strangely with your CSS class methods.
I have defined a Marionette View, and I need to reflect the model change event. I have my initialize function like so:
initialize: function(){
_.bindAll(this,"render");
this.model.on('change',this.render);
},
Later, I have defined my jquery-ui element initializers in onDomRefresh method. It is a draggable and resizable element, which can be writeable when you click on it. When clicking outside the element, the text is saved.
onDomRefresh: function(){
var self = this;
if(this.$el.resizable()){
this.$el.resizable('destroy');
}
this.$el.resizable({ handles: "n, e, s, w, se, sw, nw, ne" });
this.$el.on('resize', function (e) {
e.stopPropagation();
});
this.$el.draggable().click(function(e){
$(".selected").removeClass("selected");
$(this).addClass("selected");
$(this).draggable( "option", "disabled", true );
$(this).attr('contenteditable','true');
$(this).css({cursor:'text'});
$(this).css({opacity:'100'});
}).blur(function(){
$(this).draggable( 'option', 'disabled', false);
$(this).attr('contenteditable','false');
$(this).css({cursor:'move'});
self.textchange(); //update and save the text in the model
});
}
The problem comes, when the model has nested some model change events, and the click function is firing more and more times. I have been looking for jquery click event solutions, and none of them seems to work for me.
Tried solutions:
this.$el.draggable().unbind("click").click(function(e){});
this.$el.draggable().off("click").on('click',function(e){});
this.$el.draggable().one('click', function(e){});
//with jquery sparkle
this.$el.draggable().once('click', function(e){});
I also notice that sometimes onDomRefresh method fires two times. Don't know how to fix that. Any ideas are more than welcomed.
I have added this call at the beggining of onDomRefresh() function, which unbinds all the events on the element:
this.$el.unbind();
Now, the click event fires just once after rerendering the view.
I have a custom select menu (multiple) defined as follows:
<select name="DanceStyles" id="DanceStyles" multiple="multiple" data-native-menu="false">
Everything works fine except that I want to move the header's button icon over to the right AND display the Close text. (I have found some mobile users have a problem either realising what the X icon is for or they have trouble clicking it, so I want it on the right with the word 'Close' making too big to miss.) There don't seem to be any options for doing that on the select since its options apply to the select bar itself.
I have tried intercepting the create event and in there, finding the button anchor and adding a create handler for that, doing something like this (I have tried several variations, as you can see by the commenting out):
$('#search').live('pagecreate', function (event) {
$("#DanceStyles").selectmenu({
create: function (event, ui) {
$('ul#DanceStyles-menu').prev().find('a.ui-btn').button({
create: function (event, ui) {
var $btn = $(this);
$btn.attr('class', $btn.attr('class').replace('ui-btn-left', 'ui-btn-right'));
$btn.attr('class', $btn.attr('class').replace('ui-btn-icon-notext', 'ui-btn-icon-left'));
// $(this).button({ iconpos: 'right' });
// $btn.attr('class', $btn.attr('class').replace('ui-btn-icon-notext', 'ui-btn-icon-left'));
// // $btn.attr('data-iconpos', 'left');
$(this).button('refresh');
}
});
}
});
});
So I have tried resetting the button options and calling refresh (didn't work), and changing the CSS. Neither worked and I got weird formatting issues with the close icon having a line break.
Anyone know the right way to do this?
I got this to work cleanly after looking at the source code for the selectmenu plugin. It is not in fact using a button; the anchor tag is the source for the buttonMarkup plugin, which has already been created (natch) before the Create event fires.
This means that the markup has already been created. My first attempt (see my question) where I try to mangle the existing markup is too messy. It is cleaner and more reliable to remove the buttonMarkup and recreate it with my desired options. Note that the '#search' selector is the id of the JQ page-div, and '#DanceStyles' is the id of my native select element. I could see the latter being used for the id of the menu, which is why I select it first and navigate back up and down to the anchor; I couldn't see any other reliable way to get to the anchor.
$('#search').live('pagecreate', function (event) {
$("#DanceStyles").selectmenu({
create: function (event, ui) {
$('ul#DanceStyles-menu').prev().find('a.ui-btn')
.empty()
.text('Done')
.attr('class', 'ui-btn-right')
.attr("data-" + $.mobile.ns + "iconpos", '')
.attr("data-" + $.mobile.ns + "icon", '')
.attr("title", 'Done')
.buttonMarkup({ iconpos: 'left', icon: 'arrow-l' });
}
});
});
The buttonMarkup plugin uses the A element's text and class values when creating itself but the other data- attributes result from the previous buttonMarkup and have to be removed, as does the inner html that the buttonMarkup creates (child span, etc). The title attribute was not recreated, for some reason, so I set it myself.
PS If anyone knows of a better way to achieve this (buttonMarkup('remove')? for example), please let us know.
the way i achieved it was changing a bit of the jquery mobile code so that the close button always came to the right, without an icon and with the text, "Close"
not the best way i agree. but works..
I got a similar case, and I did some dirty hack about this :P
$("#DanceStyles-button").click(function() {
setTimeout(function(){
$("#DanceStyles-dialog a[role=button]").removeClass("ui-icon-delete").addClass("ui-icon-check");
$("#DanceStyles-dialog .ui-title").html("<span style='float:left;margin-left:25px' id='done'>Done</span>Dance Styles");
$("#DanceStyles-dialog .ui-title #done").click(function() {
$("#DanceStyles").selectmenu("close")
});
},1);
} );
I have a drag and drop interface with JQueryUI, and when a user drags an element into one of its containers and drops it, I want to display some information about the selected item.
$(document).ready(function()
{
$( ".element" ).draggable({snap: ".elementContainer"});
$( ".elementContainer" ).droppable({
drop:function(){
$("table").append('<tr><td class="elementContainer ui-droppable"></td></tr>');
}});
});
So it's creating a new element with the UI droppable class. My question is, why won't it fire a "drop" event on the newly created element?
It won't fire because when you run $(".elementContainer").droppable(...) it binds the droppable widgets to the .elementContainer elements that exist at that time, s you'll need to run the plugin again for newly created elements with the class.
Something like this:
$(document).ready(function() {
$( ".element" ).draggable({snap: ".elementContainer"});
$.fn.bindDroppable = function() {
return this.droppable({
drop:function(){
$('<tr><td class="elementContainer"></td></tr>')
.find(".elementContainer").bindDroppable().end().appendTo("table");
}
});
};
$(".elementContainer").bindDroppable();
});
This is the plugin version to cut down on code...but the basic premise is you need to call .droppable(...options...) on all the new <td> elements as well, since the widget code wasn't run on them before...because they didn't exist yet.
While this should be relatively straightforward, I can't figure out how to move (rather than copy) LI elements between ULs.
All I want is to drag any item from list foo to list bar (or vice versa) without duplicating the element.
While connectToSortable does almost exactly what I want (though I'd prefer to avoid sortable), it clones the element - and manually removing the original element by reacting to the stop event turns out to be not so easy (e.g. ensuring that a valid drop actually happened).
A simple "hello world" example would help me greatly.
A Hello World example can be found here: http://jqueryui.com/demos/sortable/#connect-lists. You don't need a draggable at all, only a sortable.
$(function() {
$("#sortable1, #sortable2").sortable({
connectWith: '.connectedSortable'
}).disableSelection();
});
If you want to disallow the sorting of items within one list, this may be a way to go. It's not the most beautiful UI though (the user is given false hope), and the user is also free to determine the drop position in a foreign list.
$(function() {
var sender;
var recvok = false;
$("#sortable1, #sortable2").sortable({
connectWith: '.connectedSortable',
start: function() {
sender = $(this);
recvok = false;
},
over: function() {
recvok = ($(this).not(sender).length != 0);
},
stop: function() {
if (!recvok)
$(this).sortable('cancel');
}
}).disableSelection();
});
This is a really horrible function working around what I feel is an incompleteness in jQuery UI. It saves the sender on sortstart and takes down a flag allowing drop. When another receiver is entered, it checks if it's not the sender and puts the flag up. On sortstop the flag is checked. Warning: this function is ugly to the eye of both the user and the programmer, but it works.