My scenario is I have a list of items that are draggable but not sortable and another list that is sortable. What I want to achieve is to drag from the draggable into the sortable but when I drop the item into the sortable I want to make an ajax request and depending on the answer to insert the item into the sortable or not.
I tried to use on beforeStop or receive events for the sortable to cancel the item being added to the sortable but didn't find a solution.
I made a jsfiddle here http://jsfiddle.net/5pTCd/21/
Why not using your draggable/droppable in an accept/revert setting?
Here is a theoretical way to accomplish an accept/revert drag & drop :
First you need to set your draggable to revert if it is not accepted:
$(".drag").draggable({ revert: 'invalid' });
Then of course you could define what is valid in your droppable :
$(".drop").droppable({ accept: '.drag' });
But thanks to the magic powder included in jQuery UI, you can insert a function as a value for "accept", it's returned value will define what you accept as a valid element:
$(".drop").droppable( { accept: function() {
// return true or false
} });
As an alternative you can use the dragstart event to change the accept option of your droppable :
$(".drag").draggable({
start: function() {
// your ajax call and then a callback with :
$(".drop").droppable("option","accept","#thisItemsID") }
});
Related
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.
We have a rails 3.2.8 app with jquery autocomplete. The app should fire an event after user selects a customer name from the list (#invoice_customer_name_autocomplete). After selecting, an ajax change event is fired. That's all the app should do. However the following code does not do the job (error: "t.item.customer is undefined"). A user can not even select. The text box won't take customer name and the screen gets stuck:
//for autocomplete
$(function() {
return $('#invoice_customer_name_autocomplete').autocomplete({
minLength: 1,
source: $('#invoice_customer_name_autocomplete').data('autocomplete-source'),
select: function(event, ui) {
$('#invoice_customer_name_autocomplete').val(ui.item.customer.name);
},
});
});
$(document).ready(function (){
$('#invoice_customer_name_autocomplete').change(function (){
//ajax call
$.get(window.location, $('form').serialize(), null, "script");
return false;
});
});
If manually changing the customer name, the .change event will fire. However it does not fire after selecting. What's wrong with the code above?
UPDATE:
If the select can trigger a change event on invoice_customer_name_autocomplete, then this is what we want. Tried the code below without success (no change event fired):
select: function(event, ui) {
$(this).trigger('change');
}
You may be using the jQuery Autocomplete plugin I can't be sure, but you're calling it the way you would call the jQuery UI autocomplete.
In case you are using the first
Suggestions:
Use autocomplete in jQuery UI instead of the autocomplete plugin. The latter is deprecated.
Using the correct framework here is a example of it working:
jsFiddle
It is no different from yours, so the thing is that you should log the ui object in order to understand why you are accessing a null object, the easiest way to do it is to log on console the whole object and watch it.
console.log(ui)
Edit:
Regarding the onChange you may check this post: trigger onchange event manually
Hope it helps!
How do you trigger jQuery UI's AutoComplete change event handler programmatically?
Hookup
$("#CompanyList").autocomplete({
source: context.companies,
change: handleCompanyChanged
});
Misc Attempts Thus Far
$("#CompanyList").change();
$("#CompanyList").trigger("change");
$("#CompanyList").triggerHandler("change");
Based on other answers it should work:
How to trigger jQuery change event in code
jQuery Autocomplete and on change Problem
JQuery Autocomplete help
The change event fires as expected when I manually interact with the AutoComplete input via browser; however I would like to programmatically trigger the change event in some cases.
What am I missing?
Here you go. It's a little messy but it works.
$(function () {
var companyList = $("#CompanyList").autocomplete({
change: function() {
alert('changed');
}
});
companyList.autocomplete('option','change').call(companyList);
});
this will work,too
$("#CompanyList").autocomplete({
source : yourSource,
change : yourChangeHandler
})
// deprecated
//$("#CompanyList").data("autocomplete")._trigger("change")
// use this now
$("#CompanyList").data("ui-autocomplete")._trigger("change")
It's better to use the select event instead. The change event is bound to keydown as Wil said. So if you want to listen to change on selection use select like that.
$("#yourcomponent").autocomplete({
select: function(event, ui) {
console.log(ui);
}
});
They are binding to keydown in the autocomplete source, so triggering the keydown will case it to update.
$("#CompanyList").trigger('keydown');
They aren't binding to the 'change' event because that only triggers at the DOM level when the form field loses focus. The autocomplete needs to respond faster than 'lost focus' so it has to bind to a key event.
Doing this:
companyList.autocomplete('option','change').call(companyList);
Will cause a bug if the user retypes the exact option that was there before.
Here is a relatively clean solution for others looking up this topic:
// run when eventlistener is triggered
$("#CompanyList").on( "autocompletechange", function(event,ui) {
// post value to console for validation
console.log($(this).val());
});
Per api.jqueryui.com/autocomplete/, this binds a function to the eventlistener. It is triggered both when the user selects a value from the autocomplete list and when they manually type in a value. The trigger fires when the field loses focus.
The simplest, most robust way is to use the internal ._trigger() to fire the autocomplete change event.
$("#CompanyList").autocomplete({
source : yourSource,
change : yourChangeHandler
})
$("#CompanyList").data("ui-autocomplete")._trigger("change");
Note, jQuery UI 1.9 changed from .data("autocomplete") to .data("ui-autocomplete"). You may also see some people using .data("uiAutocomplete") which indeed works in 1.9 and 1.10, but "ui-autocomplete" is the official preferred form. See http://jqueryui.com/upgrade-guide/1.9/#changed-naming-convention-for-data-keys for jQuery UI namespaecing on data keys.
You have to manually bind the event, rather than supply it as a property of the initialization object, to make it available to trigger.
$("#CompanyList").autocomplete({
source: context.companies
}).bind( 'autocompletechange', handleCompanyChanged );
then
$("#CompanyList").trigger("autocompletechange");
It's a bit of a workaround, but I'm in favor of workarounds that improve the semantic uniformity of the library!
The programmatically trigger to call the autocomplete.change event is via a namespaced trigger on the source select element.
$("#CompanyList").trigger("blur.autocomplete");
Within version 1.8 of jquery UI..
.bind( "blur.autocomplete", function( event ) {
if ( self.options.disabled ) {
return;
}
clearTimeout( self.searching );
// clicks on the menu (or a button to trigger a search) will cause a blur event
self.closing = setTimeout(function() {
self.close( event );
self._change( event );
}, 150 );
});
I was trying to do the same, but without keeping a variable of autocomplete. I walk throught this calling change handler programatically on the select event, you only need to worry about the actual value of input.
$("#CompanyList").autocomplete({
source: context.companies,
change: handleCompanyChanged,
select: function(event,ui){
$("#CompanyList").trigger('blur');
$("#CompanyList").val(ui.item.value);
handleCompanyChanged();
}
});
Well it works for me just binding a keypress event to the search input, like this:
... Instantiate your autofill here...
$("#CompanyList").bind("keypress", function(){
if (nowDoing==1) {
nowDoing = 0;
$('#form_459174').clearForm();
}
});
$('#search').autocomplete( { source: items } );
$('#search:focus').autocomplete('search', $('#search').val() );
This seems to be the only one that worked for me.
This post is pretty old, but for thoses who got here in 2016. None of the example here worked for me. Using keyup instead of autocompletechange did the job. Using jquery-ui 10.4
$("#CompanyList").on("keyup", function (event, ui) {
console.log($(this).val());
});
Hope this help!
Another solution than the previous ones:
//With trigger
$("#CompanyList").trigger("keydown");
//With the autocomplete API
$("#CompanyList").autocomplete("search");
jQuery UI Autocomplete API
https://jsfiddle.net/mwneepop/
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.
I have a sortable list. When a new item is dropped into the list (from a draggable), I'd like to get access to it to perform some operations on it. This is what I have:
$("#mySortableList").sortable({
receive: function(event, ui) {
alert("this is the dropped item: " + ui.item.toString());
}
}).disableSelection();
so "ui.item" is the element that was dropped, but it's not the duplicated item that will now be part of my list. How do I get access to the new item that was dropped? I am using the exact demo from the jquery-ui site here:
http://jqueryui.com/demos/draggable/#sortable
Thanks
You can get the item in the stop event and check that it came from the draggable (it doesn't have a handle attached, which it would if it was from the sortable), like this:
$("#mySortableList").sortable({
stop: function(event, ui) {
//check it wasn't here previously
if(!ui.item.data('tag') && !ui.item.data('handle')) {
ui.item.data('tag', true); //tag new draggable drops
alert("this is the dropped item: " + ui.item.toString());
}
}).disableSelection();
You can see a demo to play/test with here, since a handle doesn't get added, at least not in a way that matters, we're tagging items dropped from the draggable so that they won't fire the alert again when moved inside the sortable.
I am currently removing the received item like this:
$(this).data().sortable.currentItem.remove(); --now to find its INDEX!