How to disable the Tab key in ZK? - java

How to disable the Tab key in ZK?
Or, how can I make an event of a Tab key strike?
Situation needs that nothing should happen when user press the Tab key, i. e. the default Tab key functionality must be disabled.

I don't fully like the idea to change established keyboard conventions such as TAB focussing the next input in the tab-order.
However if a special case requires this behavior you can simply add an event listener to capture and prevent the default action for the tab key (keycode 9):
<script>
window.addEventListener(
'keydown',
function(event) {
if(event.keyCode == 9) event.preventDefault();
},
{capture: true}
);
</script>
Tested on Windows 10: Chrome/FF/Edge
This is not ZK specific and the script can be used on any other html/JS page.
As you were asking "how to do this in ZK" I wonder if you had any ZK problem that makes you want to disable the TAB key.
Robert

We have replaced the default behavior of Tab in our application as well, because we wanted more control:
disabling the focus tabbing for textfields which allow tab stops to be inserted.
excluding "unnecessary" fields from the focus tabbing: readonly fields, readonly comboboxes with hidden combobutton, every radio button of a radiogroup except one (saves the user clicks).
custom focus tabbing order (using the tabindex attribute was not sufficient, as our UI is quite dynamic and can hence have multiple components with the same index across different windows/panels/popups... Hence, we have to treat tabindex only in the scope of the closest container parent).
We started with a listener similar to Robert's answer:
$(document).ready(function() {
$(document).keydown(function(event) {
if(event.which === 9) {
var current = getCurrentlyFocusedComponent();
if (current.attr('tabindex') && new Number(current.attr('tabindex')) == -1) {
doNonFocusStuff(current[0], event.shiftKey);
event.preventDefault();
} else {
// default focus tabbing
// or
// custom focus tabbing with:
event.preventDefault();
}
}
});
});
If you want to completly disable Tab for your page, a simple event.preventDefault() will be enough. In the example above you can see that we disable the key only for certain components by setting the the tabindex = -1.
Let me know if you are interested in more details of how we do the focus manually or add tab stops, I can share the code.
As for sending an event when tab is pressed, you can use this line in the listener I showed above:
zAu.send(new zk.Event(zk.$(current), "onTab", {foo: 'some data'}, {toServer: true}));
and attach normal listener on the server side:
tabbedComponent.addEventListener("onTab", e -> Clients.showNotification("tabbed!"));
Read this article for more information on sending custom events to the server: https://www.zkoss.org/wiki/ZK_Client-side_Reference/Communication/AU_Requests/Client-side_Firing#Fire_Event_to_Widget:

Related

JavaFX: How to set a listener to the TabPane header onClick event

This is a weird question so I'll make my best to explain myself properly.
What I'd like is to trigger an event when a Tab in a TabPane get clicked, and by "clicked" I mean just clicked, not necessarily selected.
I already tried using the selectedProperty of the Tab, but that does call the event only if the Tab is clicked when it's not selected, not even if it's clicked when it's already selected.
The reason why I'm doing this is that I'm trying to make a collapsible tab pane that hides the content of the TabPane if you click again on the opened tab, I've already wrote the code for collapsing the TabPane and that works but... I have no idea on how to get a click event from the tab header.
I've even looked into TabPane source code too hoping that I could find the tab header container but I didn't find it there.
No need for a completely new skin - we can access the header nodes by lookup. Beware: implies relying on implementation details, which might change across versions.
The (undocumented!) style id to look for is ".tab-container" - that's the only child of the TabHeaderSkin (== region for a single tab header). It contains the label, the close button (if any) and the focus marker. This "skin" keeps a reference to its tab in its properties (undocumented, of course ;)
So the basic approach is to
lookup all tab-containers after the skin is installed
for each, register an appropriate mouse handler on its parent
on the respective mouseEvent, do whatever is needed
Note that the listeners have to be removed/added when the list of tabs is modified (not included in the snippet below).
In example code:
/**
* looks up the styled part of tab header and installs a mouseHandler
* which calls the work load method.
*
* #param tabPane
*/
private void installTabHandlers(TabPane tabPane) {
Set<Node> headers = tabPane.lookupAll(".tab-container");
headers.forEach(node -> {
// implementation detail: header of tabContainer is the TabHeaderSkin
Parent parent = node.getParent();
parent.setOnMouseClicked(ev -> handleHeader(parent));
});
}
/**
* Workload for tab.
* #param tabHeaderSkin
*/
private void handleHeader(Node tabHeaderSkin) {
// implementation detail: skin keeps reference to associated Tab
Tab tab = (Tab) tabHeaderSkin.getProperties().get(Tab.class);
System.out.println("do stuff for tab: " + tab.getText());
}

Adding input filter to TextField blocks default handling of ESC key

Context: JDK 8 & JavaFX
I have a TextField control that is used in a dialog. It is the first edit control, so it gets the focus when the dialog opens. The dialog has a button configured as the cancel button (Button.setCancelButton(true))
With a plain TextField, if I hit ESC immediately after the dialog opens, the dialog is closed (as expected).
However, once I add a TextFormatter with input filter to the TextField, the ESC keypress appears to be being consumed by the input control and ESC no longer closes the dialog.
The TextFormatter only has an input filter (to restrict the input control to just digits), but the input filter does not get invoked on the ESC keypress - because the content of the field has not changed.
It's a fairly minor issue, but it's annoying not having consistent behaviour, and not being able to just hit ESC to dismiss the dialog. Any ideas on how to ensure that the ESC keypress is propagated/not consumed, so that it is handled by the dialog?
Edit:
My question appears to be a duplicate of this one: Escape from a Number TextField in a JavaFX dialog. Which of course I failed to find despite trawling through Google before posting... TLDR; the TextFormatter class fails to forward the ESC keypress event on.
I think the easiest approach is to avoid trying to “fix” the TextField and TextFormatter, and just add a key listener:
textField.setOnKeyPressed(e -> {
if (e.getCode() == KeyCode.ESCAPE) {
dialog.setResult(ButtonType.CANCEL);
}
});
If the Dialog is not an Alert (or more precisely, is not a Dialog<ButtonType>), you can locate the button and activate it yourself:
textField.setOnKeyPressed(e -> {
if (e.getCode() == KeyCode.ESCAPE) {
Button cancelButton = (Button)
dialog.getDialogPane().lookupButton(ButtonType.CANCEL);
cancelButton.fire();
}
});

Eclipse PreferencePage "Apply" and "OK" greyed-out

I am a newcomer to Eclipse PreferencePages and am currently creating a new FieldEditorPreferencePage for my project. However, having FileFieldEditors() or DirectoryFieldEditors() greys-out the "Apply" and "OK" buttons in my custom preference page. On the other hand, the other FieldEditors (Boolean- and Combo-) do not disable the "Apply" and "OK" buttons.
Furthermore, changing everything to Xtext's LanguageRootPreferencePage seems to work as well (though I'd prefer not to use it as I want the custom preference page to show up in it's own tab).
For example:
//Simplified example of code
public class XPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage, IWorkbenchPropertyPage {
public XPreferencePage() {
super(FieldEditorPreferencePage.GRID);
setDescription("something");
}
protected void initialize() {
super.initalize();
//IPropertyChangeListeners go here
}
protected void createFieldEditors() {
//"Apply" and "OK" works here
g = new BooleanFieldEditor(SConstants.GENERATOR, "Generate Bindings", getFieldEditorParent());
addField(g);
//"Apply" and "OK" is greyed-out starting here
gp = new FileFieldEditor(SConstants.GENERATOR_PATH, "Generator Path:", false, 0, getFieldEditorParent());
gp.setEmptyStringAllowed(true);
addField(gp);
...
}
...
}
Is there anyway to fix this? I followed the tutorial from Eclipse Article-Field-Editors but it doesn't seem to work for me. Reading online says it can be due to negative IntegerField (which I don't have) or that I'm trying to change the default settings (which I don't have either).
I am using Eclipse Mars 4.5.0.
UPDATE: The code above (partially) worked for FileFieldEditors. However, for some reason I need to click FileFieldEditor field and check and uncheck the checkbox directly above the FileFieldEditor for each FileFieldEditor in the preference page before the "Apply" and "OK" buttons are available again.
Furthermore, I have also implemented a IPropertyChangeListener which deactivates certain fields when certain checkboxes are unchecked which means this "check and uncheck" workaround would not work for me. I have also tried setting the default focus to one of my checkboxes but that didn't work
FileFieldEditor(String name, String labelText, Composite parent) defalult validates the path when the text widget loose the focus that is what you are giving invalid as default value.
For e.g. if you give C:\\User\\XXX then this path should physically exist then and only it will not grey out ok and apply button.
You can also use below constructor by setting your validation stratergy.
FileFieldEditor(String name, String labelText,boolean enforceAbsolute, int validationStrategy, Composite parent)
value of validationStrategy
1 for the editor performs validation only when the text widget
loses focus.
0 for the editor performs validation after every key
stroke.

Validate CTabFolder before switching tabs

In a CTabFolder, I'd like to check the content for unsaved data before the user can switch from one tab to another. SWT does not provide a PreSelection event, as stated here.
I found a workaround, suggesting to switch back to the old tab when a selection is triggered, validate the data and then perform the desired switch again, if data is valid.
I do understand the general idea of this workaround, however, it is not working for me. oldPageIndex and newPageIndex do always have the same value, though I did not click on the same tab.
this.tabContainer.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent event) {
int oldPageIndex = tabContainer.getSelectionIndex();
int newPageIndex = tabContainer.indexOf((CTabItem)event.item);
// Here: oldPageIndex == newPageIndex
...
}
});
Is this workaround still working or is there anything I could possibly be doing wrong? Or maybe, has there been any fix for a real PreSelection event in the meantime? I tried using event.doit, but the SelectionEvent is fired, when the tabs have been switched already.
You can use the selection listener but as you have found the getSelectionIndex() does not give you the old tab. So you will have to maintain the old tab index yourself.
This is the technique used by the Eclipse FormEditor.

GWT event prevent default not working in Java

I'm new to GWT and I need to get a right click working. The doco I've read suggests that I need to override the onBrowserEvent() method. I'm just experimenting at this stage. the event is processed and my pop-up appears. However, as soon as I close the pop-up, the usual browser drop down menu appears (with options like "Bookmark this page" and such).
I'm using IceWeasel 24.5.0 (FireFox clone for Debian) and, obviously, Debian (wheezy).
Here's the relevant code:
public ActivityTextCell() {
super(BrowserEvents.MOUSEDOWN, BrowserEvents.MOUSEUP);
}
#Override
public void onBrowserEvent(
com.google.gwt.cell.client.Cell.Context context,
Element parent,
ActivityDTO value,
NativeEvent event,
ValueUpdater<ActivityDTO> valueUpdater) {
super.onBrowserEvent(context, parent, value, event, valueUpdater);
event.preventDefault();
event.stopPropagation();
if (event.getType().equals(BrowserEvents.MOUSEUP)) {
Window.alert("mouse up event");
}
else {
switch ( event.getButton()){
case NativeEvent.BUTTON_RIGHT:
Window.alert("right mouseclick");
break;
case NativeEvent.BUTTON_LEFT:
Window.alert("left mouseclick");
break;
case NativeEvent.BUTTON_MIDDLE:
default:
break; // Do nothing
}
}
The class ActivityTextCell extends AbstractCell.
So what am I missing? How do I stop the browser from reaticng to the mouse click?
Well it certainly wasn't a matter of a few minutes (as can be seen by the fact that it has taken me a week to get back to this), but I have a solution. I tried reversing the order of the the event.preventDefault() and super.onBrowserEvent() but it didn't really help.
I tried a little experiment on a normal web page. It turns out, that the MOUSEDOWN event doesn't do anything in that context and the usual browser selection menu appears on the MOUSEUP. So the if/else logic sort of fell by the wayside.
What did the trick is to include the following in the top level GUI class immediately after adding the main page:
RootLayoutPanel.get().addDomHandler(new ContextMenuHandler() {
#Override
public void onContextMenu(ContextMenuEvent event) {
event.preventDefault();
event.stopPropagation();
}
}, ContextMenuEvent.getType());
This has the additional benefit (for my purposes, at least) of preventing the Browser from reacting to a right click anywhere in the application view.
As an aside: The purpose of preventing the default action is to stop the Browser doing its own thing Stopping propagation is possibly not required, but I left it in anyway (propagation goes fro the node up to the root, not the other way around). The purpose of overridinging onBrowserEvent() is to enable your own application to handel that event. The use of super.onBrowserEvent() is to allow the event to be handled by your code in the first place. I've given the relevant reference in my previous comment. The book "GWT in Action" is well worth a read if you're likely to be doing a lot of GWT coding.
You call super.onBrowserEvent() which triggers the standard browser response.
You should move event.preventDefault() to the if part of your code, and super.onBrowserEvent() to the else part. You want one of them executed depending on a browser event, but not both.

Categories

Resources