jQueryUI and problem with sortable events - jquery-ui

I'm working with the 'Connect list trough tabs' demo. I modified the code a little bit. I added the 'foo' class to the tabs-1 and tabs-2 elements.
I also added the following script:
$(".foo ul").sortable({
stop: function (event, ui) {
var tabId = $(this).attr('id');
var elementIndex = ui.item.index();
alert('tab id: ' + tabId + ' | element index: ' + elementIndex);
}});
It works super fine when I change the sort order of elements inside same tab, but I have the problem when I drop the element from the first tab to the second tab (or vice versa), because the element is firstly placed on the first position in tab1 (tab id = sortable1, element index = 0), and after that it is dropped to the second tab on the last position. The problem is because the sortable event is not fired for the second time.
I'm missing something but don't know what :)
Any help would be greatly appreciated.
Thank you!
EDIT:
Demo can be found on the following link: http://jqueryui.com/demos/sortable/#connect-lists-through-tabs

Did you ever find an answer to this? Because I'm currently having the same problem - trying a range of ways around it, but so far to no success.
EDIT
Scratch that, just found what I think is the most efficient way to resolve. Bind the event "DOMNodeInserted" to the <ul> list class you're using, and you can test the list item by searching its current DOM position:
$(".connectedSortable").bind("DOMNodeInserted", function() {
$('#tabs').find('li#staff-'+currentStaffId).each(function() {
listDeptID = $(this).parent().parent().attr('id');
listDeptID = listDeptID.split('-');
listDeptID = listDeptID[1];
....
In this example of mine, I have my list items with the id of staff-x with the id of that staff member, so the find returns one array element, and runs quite efficiently.
HTH
Jester.

Related

Handling moving of item across lists in angular-ui sortable?

I am using angular-ui sortable version 1.2
I want to handle the move of an item from one list to another, and update the back-end accordingly.
jquery-ui-sortable defines a bunch of events, including the receive event
From within that event handler, I cannot find a way to access the angular model item which was moved, and its new parent list.
See this codepen sample.
You can see that I can access the item via the scope() in the update event, but not in the receive event.
Any suggestions for a way to handle these moves? either via the receive event or otherwise?
Reorder the items in one list
UI sortable behaves intuitive if you have one list of items and just want to reorder the list. In this case you do the following if you have an array of objects in your controller like this:
$scope.yourObjects = [
{title:'Alabama'}, {title:'Ohio'}, {title:'Colorado'}
];
in your html you may create a list of these items by using ng-repeat:
<ul ui-sortable="sortableOptionsA" class="list items-container" ng-model="yourObjects">
<li class="item sortable" ng-repeat="item in yourObjects">{{item.title}}</li>
</ul>
where sortableOptions is:
$scope.sortableOptionsA = {
stop : function(e, ui) {
var item = ui.item.scope().item;
var fromIndex = ui.item.sortable.index;
var toIndex = ui.item.sortable.dropindex;
console.log('moved', item, fromIndex, toIndex);
}
};
As you can see, in the stop function we have access to all relevant information we need to be informed about the movement.
Connect 2 list of items
Now the problem get's a little bit complicated. UI Sortable gives us no information about the drop-targets that we can use directly in any way. If we move one item from one list to another list the following events are fired:
start: We have access to the item that will be moved including the scope of this item.
update: We have access to the item that is moved including the scope of this item.
Now the item is deleted from it's source list
removed: The item was removed from the source list. The scope is no longer valid (e.g. undefined).
received: The item is about to be dropped in the second list. scope is still undefined, we have only access to the sender e.g. the drag source.
Now the item is inserted in the target list.
update: The item is dropped at the target list. but we have no access to the item scope nor does there a target object exist in the event objects. The jQuery UI Sortable did not provide these information and the angular wrapper did not expose the target model in any way :(
stop: If all steps of the drag'n'drop process are done, the stop event is fired. But we have also no access to the items target scope or the target list.
What can we do if we want to get informed about a movement and which item was moved to what kind of list?
The item that was moved is accessible by ui.item.sortable.moved in the stop event. This is our item that was moved.
Which list is the drop-target can be determined by Angular's $watch function. We just listen to changes to the lists and know, which list was modified. One caveat: the source and the target list are changing, but the target list is changed at last (see the above event order). If we listen to the changes in this way:
$scope.dropTarget = null;
$scope.$watchCollection('lists[0].items', function() {
console.log('watch 0');
$scope.dropTarget = $scope.lists[0];
});
$scope.$watchCollection('lists[1].items', function() {
console.log('watch 1');
$scope.dropTarget = $scope.lists[1];
});
we have all information to get to know wich item was moved to what kind of list and what are the from and the to index:
stop:function(e, ui){
var item = ui.item.sortable.moved;
var fromIndex = ui.item.sortable.index;
var toIndex = ui.item.sortable.dropindex;
console.log(item, fromIndex, toIndex, $scope.dropTarget);
},
PLUNKR with a lot of debug code that shows what kind of information is available during the drag'n'drop process.
Remark: if you move one item from the 'Connected lists' to 'One sortable list' the log output is wrong - because there is no listener to the 'One sortable list' list!

Grab all fieldset elements inside div

In my ASP MVC 3 view I have a number of fieldset elements that are hidden when the page loads. Based upon a user selection of a group of radio buttons, I need to make the corresponding fieldset visible.
I'd like to do this in jquery by making an array of the fieldset elements, then cycle through them, adjusting their visibility property if they match the selected radio button or not. Is this possible?
Since there is so much code in the fieldsets I attached the screen shot below to save space/make it more readable. The fieldsets I am trying to alter are inside of the RightDiv. If you need any more detail, please let me know. Thx
You can try this:
$(function(){
$('[name="TransactionType"]').change(function(){
var id = '#' + this.className; //Get the id from the clicked radio classname
$('#RightDiv').find('fieldset').hide();// hide all fieldsets;
$('#RightDiv').find(id).show(); // show the selected one.
});
});
Just note that in your html helper you are providing the the first overload as same name for all. All is well except i believe it will create duplicate ids for each of these. You may want to override it in the HTMLattributes.
#Html.RadioButton("TransactionType", false, new{#class="Enroll", id="Radio1"})
#Html.RadioButton("TransactionType", false, new{#class="New", id="Radio2"})
Sorry, posted a bit too soon on this. Tried the following below and it worked just fine.
$(document).ready(function () {
$('input[name=TransactionType]').change(function () {
var radioValue = $(this);
var elements = [];
$('#RightDiv').children().each(function () {
elements.push($(this));
});
});
});

Is there any way to control the layout of the close button on a jQuery Mobile custom select menu?

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);
} );

JQuery UI Multiselect how to get selected options values

wasted my day while searching how to get selected options values in JQuery UI widget by Michael Aufreiter. Here's the link to his demo site and github: http://quasipartikel.at/multiselect/
As a result I just need value fields of selected options without POST/GET sendings to PHP script.
I tried many methods and resultless.
Need your help and ideas
*Found many topics about jquery ui multiselect but useless because of Aufreiter :s *
That should work. Tested with Chrome console
$("#countries").val();
I went to the site you've got listed above, and was able to run this in my chrome console:
$('.ui-multiselect .selected li').each(function(idx,el){ console.log(el.title); });
It seems like the values you want are stored in the title attributes of the list items within the div.selected element.
Edit:
Doh! Well of course you want the values. Sorry mate. Completely missed that. The real goods are stored in the jQuery data() objects. In this case, the key you want is 'optionLink'. It maintains a reference to an option element. Each list item in the '.selected' div used the jQuery.data() method to add the underlying option to it.
So, you need to get the selected list items, iterate through, grab the 'optionLink' from the data jQuery data store, and then get the value.
The following code works on the example page:
$('.ui-multiselect .selected li').each(function(idx,el){
console.log(el);
var link = $(el).data('optionLink');
// link now points to a jQuery wrapped <option> tag
// I do a test on link first. not sure why, but one of them was undefined.
// however, I got all four values. So I'm not sure what the first <li>
// is. I'm thinking it's the header...
if(link){
// here's your value. add it to an array, or whatever you need to do.
console.log(link.val());
}
});
This is the first I've seen of the multiselect. It's slick. But I sympathize with your frustration trying to get something out. A 'getSelectedOptions()' method would be nice.
Cheers
Try accessing the selected values on the close event.
e.g.
$("#dropdown").multiselect({
header: false,
selectedList : 1,
height: "auto",
}).multiselectfilter().bind("multiselectclose", function(event, ui) {
var value = $("#dropdown").val();
});
Hope that helps.
Best solution
$('#select').multiselect({
selectAllValue: 'multiselect-all',
enableCaseInsensitiveFiltering: true,
enableFiltering: true,
height: "auto",
close: function() {
debugger;
var values = new Array();
$(this).multiselect("getChecked").each(function(index, item) {
values.push($(item).val());
});
$("input[id*=SelectedValues]").val(values.join(","));
}
});
You can try this:
$('#ListBoxId').multiselect({
isOpen: true,
keepOpen: true,
filter: true
});

How to delete a jqgrid row without reloading the entire grid?

I have a webpage with multiple jqgrids each with inline editing enabled, "action" column (edit icons) enabled and pager disabled. I need to handle the delete event for each row so that I can process the delete without reloading server-side data. I've looked at the approach mentioned in jqGrid Delete a Row and it's very helpful except I have two questions that are stumping me -
Are there more details around the rp_ge parameter in the delOptions.onClickSubmit event?
My column has the delOptions set as this -
delOptions: {onclickSubmit: function(rp_ge, rowid) {return onRowDelete(rp_ge,rowid);}},processing:true }},
Is there a way to get the grid id from within that event? I'd like to have a generic function that I can use to handle delete events from all the grids on the page. The rp_ge parameter has a gbox which sometimes contains the grid id appended? But I have no idea what it is since i'm not able to figure out when it's populated, when it's not.
function onRowDelete(rp_ge, rowid) {
//hardcoded grid id.. don't like it.
var gridid = '#Grid_X';
//what is this gbox?? can i get grid id predictable from it?
//var gridid = rp_ge.gbox.replace("#gbox_", "");
var grid = $('#Grid_X');
rp_ge.processing = true;
var result = grid.delRowData(rowid);
if (result) {
$("#delmod" + grid[0].id).hide();
}
return true;
}
In the jqGrid Delete a Row approach, the code $("#delmod"+grid[0].id).hide(); is hiding the popup delete confirmation dialog manually. What I noticed is that when the dialog pops-up, jqgrid de-emphasizes the background page (makes it light greyish). But after the popup is manually closed (hidden actually?), the background remains de-emphasized. So it looks like the page doesn't have focus (or even disabled). Any way this can be fixed? This can also be seen on the demo that Oleg wrote.
Any help would be appreciated.
(PS - I would've commented on the same post but I don't have enough points to comment on someone else's answer yet.)
In answer to your second point.
Several examples by Oleg such as this one have the following modification.
$("#delmod" + grid[0].id).hide();
is replaced with
$.jgrid.hideModal(
"#delmod"+grid_id,
{gb:"#gbox_"+grid_id,jqm:rp_ge.jqModal,onClose:rp_ge.onClose}
);
This will return focus after the delete operation.

Resources