Dojo DnD delete selected items - drag-and-drop

Is there a way to delete selected items from a dojo DnD Source by dragging them out their container, or by pressing DEL key? I tried to achieve this by adding a dojo.connect->onkeypress but It seems Source doesn't listen to this events.
...
In response to Rodrigo QuiƱones I've created a jsfiddle
//[...]
on(dom.byId('sortByItems'), 'keypress', function(evt) {
if (evt.charOrCode == keys.DELETE)
console.log('User wants to unselect:', sortByDnDTarget.getSelectedNodes());
});
//[...]
Thanks in advance.

First off; The dndSource does no listen to keypress events. I believe it never gains 'focus', only items contained in it can get focused. It does however listen to things like 'click' etc.
Secondly, DELETE key is not captured in the keypressed event handler, since this is designed only to capture printable stuff, so <enter>, <del> and <esc> etc. does not apply for that event.
Instead use keyup or keydown listeners - and apply them on window
The following snippet should do what youre aiming for:
sortByDnDTarget.getSelectedNodes().forEach(function(li) {
sortByDnDTarget.delItem(sortByDnDTarget.getItem(li.id));
});

Related

How to prevent closing of cell editing in ag-grid on "Other Cell Focus"

I am working on an editable table in Angular application with ag-grid library. I would like to keep editing cells (in full row edit mode) until I finish with it and then close the editors manually via API. The problem is that the editor is closing on other cell click/focus (on some other line) as described here:
The grid will stop editing when any of the following happen:
Other Cell Focus: If focus in the grid goes to another cell, the editing will stop.
I cannot figure out how to disable this, if it is possible. Installing the onCellMouseDown() hook does not help, because the cellFocused event is fired before cellMouseDown. Therefore, the editing stops before I have a chance to intercept the mousedown event.
Here is my stackblitz little extract with related pieces of code.
The need for such scenario is that I want to validate the entry and not to allow a used to quit the editing if the form is not valid. The only workaround I found so far is that on any click outside of editing cells when the editor closing I reopen it right away in onRowEditingStopped() hook unless the editor has been closed via 'OK' button.
After all, I have managed to provide a custom solution that fits exactly into this problem which I was facing also.
First thing is to disable pointer events to non edited rows when a specific row is currently being edited. On Ag-grid's 'cellEditingStarted' callback I have added the following code:
public cellEditingStarted(event: any): void {
//not all rows are on dom ag-grid takes care of it
const nonSelectedGridRows = document.querySelectorAll('.ag-grid-custom-row:not(.ag-row-selected):not(.ag-row-editing):not(.pointer-events-none)');
forEach(nonSelectedGridRows, row => {
row.classList.add("pointer-events-none");
});
}
Because not all rows exist on dom (Ag-grid creates and destroys while you are scrolling )when a specific cell is being edited, I have also added a rowClassRule which is applied when rows are being created:
this.rowClassRules = {
'pointer-events-none': params => {
if (params.api.getEditingCells().length > 0) {
return true;
}
return false;
}
};
scss:
.pointer-events-none {
pointer-events: none
}
By disabling pointer events, when you click on a non edited cell the cell won't get focus and thus the currently edited cell will stil remain on edit mode. You can provide your own custom validation solution and close the editor manually through API. When you are done, you have to enable pointer events to all grid rows back again:
private enablePointerEvents(): void {
//not all rows are on dom ag-grid takes care of it
const nonSelectedGridRows = document.querySelectorAll('.ag-grid-custom-row.pointer-events-none');
forEach(nonSelectedGridRows, row => {
row.classList.remove("pointer-events-none");
});
}
I implemented the same above approach in Ag-Grid React.
I used getRowStyle callback for adding the css pointerEvents: none on dynemic basis.
It seems to be working for me fine.
Please refer the below code
const getRowStyle = (params) => {
// this is not initialized in read mode
// condition for me ==> currentEditRowIndex.current !== null && params.node.rowIndex !== currentEditRowIndex.current
if (someCondition for Row other than inline edit row) {
return { pointerEvents: "none" };
}
return null;
};
After adding this whenver you start the editing..You will need to call redrawRows so that css changes can be applied.
Hope this will help. Thank You!!
Thought I would share another solution that has been working out okay for me so far.
Using 'pointer-events-none' as suggested in the other answer is flawed because the Enter key can also close the editor.
In my case, I want to prevent the editor from closing when client side validation has failed and the data is invalid. When my conditions are met, I call stopPropagation() on the events to prevent the editor close from happening in the first place. It still has potential problems:
It cancels mousedown, dblclick, keydown, focusout and click for all elements that have a class name starting with ag- so if you happen to use this class prefix for other controls on the page, it could interfere. It also means any controls within the grid (sorting, resizing, etc.) don't work while the condition is met.
Calling stopPropagation() could potentially interfere with your own custom controls. So far I've been okay if I dont use the ag- prefix within the markup from my own custom cell editors and renderers
I hope they can add a proper API function to cancel the row/cell stopEditing function in the future.
["mousedown", "dblclick", "keydown", "focusout", "click"].forEach(function (eventName) {
document.addEventListener(eventName, function (e) {
if ( conditionForCancelingIsMet() ) {
// this appears to cancel some events in agGrid, it works for
// preventing editor closing on clicking other cells for example.
// It would be ideal if this worked for all ag-grid specific events
// and had a proper public API to use!
e["__ag_Grid_Stop_Propagation"] = true;
}
// convert element classList to normal js array so we can use some()
var classArray = [].slice.apply(e.target.classList);
if ( conditionForCancelingIsMet() && classArray.some(c => c.startsWith("ag-")) ) {
// unfortunately some events like pressing the 'enter' key still
// require stopPropagation() and could potentially interfere with unrelated controls
e.stopPropagation();
}
}, true);
});

Microsoft Word JavaScript API - event handler for text selection in document

I read JavaScript API for Office and I couldn't find a handler to notify when user select a text in the word document.
I am aware that we can copy the selected/highlighted text from document as follow:
Word.run(function(context) {
let body = context.document.body;
// ask for the user selected text
let range = context.document.getSelection();
});
This approach is not a registered callback or an event. With this approach I have to request update or to check if user selected anything.
Is there an existing function that I can register for getting notified for user interaction with document?
Thanks in-advance for your help
the getSelection() method does not actually make a selection in the document. it gives you the range that its currently selected. in order to get the events you need to subscribe to the document selection event, you can achieve that fairly simple just with:
function subscribeToEvent() {
Office.context.document.addHandlerAsync(Office.EventType.DocumentSelectionChanged, handler);
}
function handler(evtArgs) {
// here you can handle the event.
console.log("select");
}
On the other hand the range.select() method WILL trigger the selection changed event if you want todo it programmatically. Please check out this Script Lab snippet, it basically subscribe to the event on load, then if you click the RUN button you will see that the last paragraph gets selected and the event triggered.

Event.add for keypress does not work?

We are trying to use tinyMCE for one of our applications. We would like to attach some event handling to particular elements within tinyMCE. We've tried doing it using
Event.add(element, 'keypress', getTag);
Where element is the HTML element we are trying to attach the event to and getTag is the function we'd like called when the keypress event is fired. The particular element we are trying to attach to is a span element with some text in it. We'd like to capture when particular key combinations are entered(like ctrl - F10) between the span tags and popup a menu with options.
The options in the menu will vary depending on the particular span elements the combination is entered in. That's why we want to attach to particular elements instead of globally attaching to all span elements in the document(within tinyMCE). i.e The getTag function will behave differently, using closures, depending on where the combinations are entered.
The problem is when we attach to the particular elements and test them nothing happens for any 'keypress' events. If we try to attach to the span elements using a 'click' event everything works as expected. Once we revert back to using 'keypress' nothing happens again.
Using the debugging tools I've verified a couple of things. The event listeners are attached to the elements. It seems tinyMCE creates a toplevel keypress and click(along with others) to the document within tinyMCE. I'm guessing this is how Editor.onKeyPress().add() like functions work. When I debug the working scenorio using click I can see where the event is fired for both the document and span elements. While debugging the keypress event I only see the event fired for the document element, not the span element. I'm thinking that tinyMCE is suppressing the event, but I can't figure out how, and what needs to be done to stop it.
Use this handler eigther in one of you own plugins or using the tinymce config param setup
ed.onKeyDown.add(function onkeydown(ed, evt) {
var is_in_span = ed.selection.getNode().nodeName == 'SPAN';
// check for caret in SPAN and F10-Key
if (is_in_span && evt.keyCode == '121'){ // you may add other keyCodes here
// do whatever you like here
...
}
});

Change the order of event handling in GWT

I have a Suggest box which has 2 hadlers: SelectionHandler for selecting items in SuggestionList and keyDownHandler on TextBox of SuggestBox. I want to prevent default action on event(for example on Enter pressed) when the suggestion list is currently showing. The problem is that SelectionEvent is always fires before KeyDownEvent and suggestion list is closed after SuggestionEvent fired, so in KeyDownEventHandler suggestion list is already closed. And I can't use prevent default action on Enter with checking the suggestion list is showing like this:
if ((nativeCode == KeyCodes.KEY_TAB || nativeCode == KeyCodes.KEY_ENTER) && display.isSuggestionListShowing()) {
event.preventDefault();
}
where display.isSuggestionListShowing() is the method which calls isShowing on SuggestBox .
So how can i change the order of event handling(Selection before KeyDown to the keyDown before Selection) in this case?
I'm assuming you mean SuggestBox instead of SuggestionList, as there is no class by that name in the gwt-user jar.
The SuggestBox uses the keydown event to provide the SelectEvent - if it can't see the keys change (from the browser, which actually picks up the user's action), it can't provide the logical selection event.
This means that reordering events doesn't really make sense - you can't have the effect before the cause. In many cases, the browser emits events in a certain order, and there is no way to change this, so you have to think differently about the problem.
(Also worth pointing out that preventDefault() only prevents the browser from doing its default behavior - other handlers will still fire as normal.)
One option would be to preview all events before they get to the SuggestBox, and cancel the event in certain cases - look into com.google.gwt.user.client.Event.addNativePreviewHandler(NativePreviewHandler) for how this can be done.
I'm not seeing any other option right away - all of the actual logic for handling the keydown is wrapped up in the inner class in the private method of com.google.gwt.user.client.ui.SuggestBox.addEventsToTextBox(), leaving no options for overriding it.

Dojo: dijit.form.select won't fire "onClick" event the first time clicked

I've been through the Dojo docs as well as the API and tried Google but can't find a solution to my problem, I hope anybody here can help me out.
I'm trying to create a dijit.form.select programmatically (using Dojo 1.4) and connect to the "onClick"-event of the widget.
Here's a part of my code:
var dataSelect = new dijit.form.Select({
id : "myselect",
name : "myselect",
labelAttr: "label",
labelType: "html"
},
"selectid");
dataSelect.addOption({value: "value", label: "first item label"});
dojo.connect(dataSelect, "onClick", function() {
alert("clicked!");
});
What it does: A select-box is created replacing an input-field with the ID "selectid", an option "first item label" is created. Everythings all right until here.
Then I connect to the "onClick"-event of the select, which is supposed to load more options via AJAX (but will just display an alert for testing purposes in this example).
The problem: When I click on the little arrow next to the dropdown, the event is fired (OK). But when I click on the select box itself (the area containing the option), the event is NOT fired the first time I click it (unless I clicked on the arrow before).
When I click the select box a second time (and every time after that), the event will fire!
I've tried to use "onFocus" instead of "onClick" which does work, but then the dropdown will not open when first clicked, even if I use the "openDropDown"-function (which does work when connecting to "onClick"!).
Is it me, did I run into a Dojo bug or is it a strange feature I just don't get?
Any help is appreciated.
Greetings,
Select0r
Here is a cross-browser solution:
var sizeSelect = new dijit.form.Select({
id: "sizeSelect",
name: "state",
options: size,
onChange: function(val) {
dojo.style(dojo.byId("textInput"), {"fontSize":val});
}
}, "sizeSelect");
Try to connect not to the widget itself but to it's dom node:
dojo.connect(dataSelect.domNode, "onclick", function() {
alert("clicked!");
});
Select (which extends _HasDropDown) has fancy code to handle:
mouse down on select widget
mouse move to one of the options
mouse up
Maybe that's canceling the click event.
Maybe you can connect to _loadChildren() instead.
The root cause for this issue is that the _onDropDownMouseDown method of dijit._HasDropDown will manipulate the dom node, which cause the e.target of onmousedown and onmouseup changes for the first initialization.
As we know, the onclick event will be triggered only when the target of onmousedown and onmouseup are the same target.
So in this case, the onclick event is not triggered.
It seems that in Dojo 1.5, the problem still remains.