jqueryui sortable with keyboard? - jquery-ui

I have a requirement to make the application functionality accessible through keyboard, not just the mouse. The application uses jquery sortable to manage ordered lists. Can anyone suggest ideas how to make the sorting functionality available through keyboard? I'm talking basic sort through drag&drop as ilustrated by the example on http://jqueryui.com/sortable. I have not seen anything mentioned on jqueryui/sortable which makes me believe the framework has no built-in support for keyboard.
Alternatively, are there any other java script sort frameworks that support keyboard?

Well got it to work by using the following:
Added tabindex to all items in the list. This allows the user to tab to and through the individual list items.
added the following js:
$('.sortable li').focus(function() {
$(this).addClass("ui-selecting");
});
$('.sortable li').focusout(function() {
$(this).removeClass("ui-selecting");
});
$('.sortable li').bind('keydown', function(event) {
...
if(event.which == 38) //up
pseudocode:
<current.text := previous.text>
<current.data := previous.data>
<previous.text := current.text>
<previous.data := current.data>
<set_focus(previous)>
if(event.which == 40)
pseudocode:
<current.text := next.text>
<current.data := next.data>
<next.text := current.text>
<next.data := current.data>
<set_focus(next)>
So tabbing allows to navigate to and move through the items while arrows move the items up and down the list.
It works but ofcourse looks very primitive when compared with the drag and drop moving graphics when using the mouse.
Wondering if I could animate the move, at a reasonable effort...

Related

JqueryUI draggable/droppable - Identify the drop target when the drop is invalid

I am using the draggable/droppable plugins of jquery-ui and i have the following scenario.
Three droppable targets (each one accepts a single type of elements, based on class) and multiple elements (one of the three types that are accepted by the droppables).
I am using the revert option on the draggables and the accept on the droppables.
Everything works normally in terms of functionality.
What I need: to identify the drop target when the drop is invalid (dropped on a droppable that does not accept the dragged element)
What is the actual problem: All events of droppable fire only when the dragged element is acceptable by it.
I need that information so that i can display error messages customized for the specific wrong drop-target.
I really cannot wrap my head around this problem (besides using another drag/drop system..), so any pointers/ideas are welcome..
Setting up revert functions may be a good start,
Working Example
$(".draggable1").draggable({
revert: function (droppableObj) {
//if false then no socket object drop occurred.
if (droppableObj === false) {
//revert the selector object by returning true
alert('Not Dropped');
return true;
} else {
//droppableObj was returned,
//we can perform additional checks here if we like
//return false so that the selector object does not revert
return false;
}
}
});
For more info see:
https://stackoverflow.com/a/3418306/1947286
http://www.agilepro.com/blog/2009/12/while-this-functionality-is-built-into.html

Drag and drop in AngularJS

I am trying to implement Drag and Drop using c0deformer's jQuery UI implementation (see here: http://codef0rmer.github.io/angular-dragdrop/#/) The dragging part works fine, but I can't seem to get the functionality I am after in terms of the drop. In this application, I want to be able to drop the draggable items anywhere within a target div, i.e., I don't want the destination scope to be limited to a list-type structure (or a set of repeated divs). Mainly this is because the user will be dragging items on the fly and there will be no way of knowing how many items the user will drag and drop in advance.
I have scoured the web and cannot find an example in Angular that uses drag and drop without effectively dragging from one list to another list. Can this be done? If so, I am not sure how I would appropriately update the scope after an item has been dragged. In this example code below, the dropped items are pushed into the scope of a second list and the new scope is applied. Ideally, the scope of the dropped items is the target div I mentioned above. I'm really new to Angular, so any advice is immensely appreciated.
Snippet from c0deformer:
app.directive('droppable', function($compile) {
return {
restrict: 'A',
link: function(scope,element,attrs){
//This makes an element Droppable
element.droppable({
drop:function(event,ui) {
var dragIndex = angular.element(ui.draggable).data('index'),
dragEl = angular.element(ui.draggable).parent(),
dropEl = angular.element(this);
console.log(dropEl);
if (dragEl.hasClass('list1') && !dropEl.hasClass('list1') && reject !== true) {
scope.list2.push(scope.list1[dragIndex]);
scope.list1.splice(dragIndex, 1);
} else if (dragEl.hasClass('list2') && !dropEl.hasClass('list2') && reject !== true) {
scope.list1.push(scope.list2[dragIndex]);
scope.list2.splice(dragIndex, 1);
}
scope.$apply();
}
});
}
};
});
I recently created an angular directive for drag and drop that doesn't rely on jquery-ui. It uses the html5 drag and drop api. It also doesn't have any requirements on the format of the data to be dragged or dropped, it simply sets up a hook for you to be notified when one element is dragged onto another.
Post here: http://jasonturim.wordpress.com/2013/09/01/angularjs-drag-and-drop/
Demo here: http://logicbomb.github.io/ng-directives/drag-drop.html

Powerpoint Protected Mode with Disabled Ribbon - Automated in Delphi

I am looking for a way to protect powerpoint presentations via Automation using Delphi.
In Word, I can issue this command:
If (WordDocument.ProtectionType = wdNoProtection)
Then WordDocument.Protect (3, VarTrue, VarProtectPass);
In Excel, I can issue this command:
{ If the file was NOT protected, then protect it }
For SheetIndex := 1 To ExcelWorkbook.Sheets.Count Do Begin
VarSheet := SheetIndex;
{ Connect to the work sheet }
ExcelWorksheet.ConnectTo (ExcelWorkbook.Worksheets.Item [VarSheet] As _Worksheet);
ExcelWorksheet.Protect ()...
The problem is that I cannot find a way to do this using the OfficeXP.pas components. We are running Office 2010 on various systems. Any ideas?
What I need is to open powerpoint up with the presentation,
1) For MenuItem1, Disallow any editting by the user. Also, disallow them to re-save it somewhere else.
2) For MenuItem2, Allow the user to edit the presentation.
One approach to this would be via an add-in that traps events:
Trap the PresentationBeforeSave event and if need be, cancel the save.
Trap the WindowSelectionChange event, test to see what's selected (it's passed by the event) and in most cases, DE-select the selection. If the user can't select something, they can't edit/change it.
The event handling routines can be enabled/disabled based on state variables; you might trap the PresentationOpen event, test to see if the new presentation is one of your "protected" ones and if so, set boolIsProtected = True; your other event handlers could test this variable and stop processing the event if False.

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.

jQueryUI multiple selection by default and have lasso toggle selected status

I'm trying to implement a comparison chart-like table, and a large list of selectable objects would work just perfectly, save for a few functionality changes that I need. I see that both of these have been addressed in previous questions, but neither of them provide complete solutions.
This question addressed the multiple select behavior by default, but only says 'I did it on my own' without providing anything. Looking at the internals of selectable, I see that if I play with the !event.metaKey condition I could probably get the behavior I'm looking for without too much trouble, but was wondering if anyone had a solution that didn't involve editing the internals.
Similarly, this page addresses the lasso toggle effect that I desired, but I'm not sure where in the code the lasso functionality was changed and as the rest of the script (the sortable functionality) is reported to not work in chrome or IE8 (link) and is outdated as this point, I'd rather not rely on the entire thing.
So if anyone could help me out with either of these, I'd appreciate it. Thanks
[Edit] Formatting...
I'm sure there's a better way to do this, but here's what I've did within the selectable js file.
For the always multi-selection:
I added an option 'alwaysMulti' (default false). Then I replaced the three instances of !event.metaKey with (!event.metaKey && !options.alwaysMulti) and the two instances of event.metaKey with (event.metaKey || options.alwaysMulti).
To get the selection lasso to toggle the selected status, I found the changes I needed from the second page I linked to. I also added an option 'lassoToggle' (default false) to trigger this functionality. Within _mouseDrag, there is a condition if (hit), it gets changed to the following:
if (hit) {
// SELECT
selectee.deselect = false;
if (selectee.selected || (options.lassoToggle && (selectee.startselected && event.metaKey)) {
selectee.$element.removeClass('ui-selected');
selectee.selected = false;
selectee.deselect = true;
}
if (selectee.unselecting) {
selectee.$element.removeClass('ui-unselecting');
selectee.unselecting = false;
}
if (!selectee.selecting && (!options.lassoToggle || !selectee.deselect) {
selectee.$element.addClass('ui-selecting');
selectee.selecting = true;
// selectable SELECTING callback
self._trigger("selecting", event, {
selecting: selectee.element
});
}
if(selectee.deselect && options.lassoToggle) {
selectee.$element.removeClass('ui-selecting');
selectee.selecting = false;
selectee.$element.addClass('ui-unselecting');
selectee.unselecting = true;
// selectable UNSELECTING callback
self._trigger("unselecting", event, {
unselecting: selectee.element
});
}
}
Note: The event.metaKey change for the multi-select isn't in that code sample.
Hopefully this helps someone else!

Resources