I have a DIV representing a BLUE rectangle with text "HELLO" that, when user clicks on it changes its colour to RED and text "BYE", and when user moves mouse cursor out, restores its original colour and text. These styles are described in CSS, and text is controlled from GWT Events (see Java code below).
The issue is that, when I move the mouse very fast, the ONMOUSEOUT event is not fired in any browser. But works fine if I move it slowly.
Any ideas, please? THANKS
MyFile.html
<div id="boxDiv" class="myStyle"></div>
MyFile.java
final Element boxDiv = DOM.getElementById("boxDiv");
DOM.sinkEvents((com.google.gwt.user.client.Element)boxDiv,Event.ONCLICK | Event.ONMOUSEOUT);
DOM.setEventListener((com.google.gwt.user.client.Element)boxDiv,new EventListener(){
public void onBrowserEvent(Event e) {
Element targetDiv = DOM.eventGetTarget(e);
switch (DOM.eventGetType(e)) {
case Event.ONCLICK: onClickHandler(e, targetDiv); break;
case Event.ONMOUSEOUT: onMouseOutHandler(e, targetDiv); break;
}
}
EDIT
Given your modified question and the added complexity of changing text, let's use GWT as GWT is awesome for this kind of thing!
Ok, first our very simple CSS stylesheet:
.myStyle {
background-color: blue;
}
.myStyle-clicked {
background-color: red;
}
Here a very basic Widget that does pretty much exactly what you asked (sorry for changing the text, I tested this and I'm sure it will always work even when moving the mouse extremely fast) in beautiful, simple Java (GWT) code:
private class MyWidget extends Composite {
private Label label = new Label();
private static final String originalText = "Hello world!";
private static final String clickedText = "Goodbye world!";
public MyWidget() {
sinkEvents(Event.ONCLICK | Event.ONMOUSEOUT);
label.setText(originalText);
initWidget(label);
setStyleName("myStyle");
}
#Override
public void onBrowserEvent(Event event) {
super.onBrowserEvent(event);
switch (event.getTypeInt()) {
case Event.ONCLICK:
addStyleDependentName("clicked");
label.setText(clickedText);
break;
case Event.ONMOUSEOUT:
removeStyleDependentName("clicked");
label.setText(originalText);
break;
}
}
}
OLD ANSWER IF YOU ARE JUST WORRIED ABOUT MOUSE_OVER AND MOUSE_OUT
The solution to this problem is to stop doing this programmatically and do it using the native browser's events handling system, which is as fast as you can get.
To do this, use the CSS hover filter. For clicking, you don't need to worry, your problem is just move-in and move-out, which as you found out, are cases where you may not be able to trust the JS to handle very well.
I think all browsers currently support this:
<!DOCTYPE html>
<html>
<head>
<style>
.tt {
background-color: blue;
}
.tt:hover {
background-color: red;
}
</style>
</head>
<body>
<div class="tt">
The content of the body element is displayed in your browser.
</div>
</body>
</html>
I tested this and it works in Chrome, FF and IE9. According to ther w3schools docs, it works also in Safari and Opera.
I am not in java, but i would just suggest to check if there is some other script you may have in your app that interfere with your code.
Perhaps try to isolate the code and execute it without anything else and see what happens?
Related
How can I set the background colour for an item within an if statement in typescript? I used querySelector but the answer can use anything to achieve the result.
The selector is (.mat-step:nth-child(2) .mat-step-header .mat-step-icon-selected).
Here is the code in a stackblitz.
I would appreciate any help!
The stackblitz example can be helpful but there is a lot in there to summarise what you are askign for, this answer is a generic way of doing so, meaning you can apply it to your code as and where you see fit.
Declare you boolean.
public value = true;
Now declare the CSS class you would like to use.
.exmaple-class {
background: red;
}
Then on the selected HTML element you want to apply the class.
<div [class.example-class]="value === true"></div>
or just
<div [class.example-class]="value"></div>
As this still equates to true. If value were set to false then the class would not be applied.
If you want to start building more classes and options for a specific element you can look into Angular's ngStyle.
Add in this, think this is what you are also asking for, little different. It only runs after the view is loaded, not working in you example because the HTML has not yet been drawn.
public ngAfterViewInit(): void
{
this.changeColour();
}
public changeColour() {
document.querySelector<HTMLInputElement>(".mat-step-icon-selected").style.backgroundColor = 'red';
}
}
Then add a click event to ensure that each time you select something the selector is updated.
<div class="center-contrainer" (click)=changeColour()>
So, I have a custom implementation of ListBox for a GWT application
Its xml code looks like this:
<g:FlowPanel addStyleNames="{style.yearRangePanel}">
<g:FlowPanel addStyleNames="{style.rangeSeparator} {style.paddingTop}">
<g:Label addStyleNames="{style.horizontalAlign}" ui:field="integerRangeDropdownLabel">Filter studies by range of enroled patients: </g:Label>
<g:Label addStyleNames="{style.prefixSpace} {style.horizontalAlign}" ui:field="startSampleSizeLabel"/>
</g:FlowPanel>
<g:FlowPanel ui:field="integerRangeDropdownFilterPanel" addStyleNames="{style.yearRangeSliderPanel} {style.paddingTop}">
<g:ListBox ui:field ="integerRangeDropdownListBox" styleName="{style.customListBox}"/>
</g:FlowPanel>
</g:FlowPanel>
And its main java code looks like:
#UiConstructor
public IntegerRangeDropdownFilterComposite (String fieldName, String labelText){
this.initWidget(uiBinder.createAndBindUi(this));
filterChangedEvent = new FilterChangedEvent(fieldName);
FilterConfig filterConfig = clientFactory.getApplicationContext().getConfig(FilterConfig.class);
List<FilterSetting> filterSettings = filterConfig.getFilterConfigBy(fieldName);
FilterSetting filterSetting = filterSettings.get(0);
filterByIntegerRangeSettings = (FilterConfig.FilterByIntegerRangeSettings) filterSetting;
this.increment = Integer.toString(filterByIntegerRangeSettings.getIncrement());
this.minSampleSize = Integer.toString(filterByIntegerRangeSettings.getInitialValue());
this.maxSampleSize = Integer.toString(filterByIntegerRangeSettings.getEnd());
this.setupConfig(fieldName);
}
private void setupConfig(String fieldName){
setupRange(fieldName);
}
#Override
protected void onLoad() {
super.onLoad();
integerRangeDropdownFilterPanel.add((Widget) integerRangeDropdownListBox);
}
public void resetIntegerRangeDropdownFilter() {
filterChangedEvent.resetField();
}
#UiHandler("integerRangeDropdownListBox")
public void clickEnroled(ChangeEvent changeEvent){
if(integerRangeDropdownListBox.getSelectedIndex()!=0) {
String selectedItem = integerRangeDropdownListBox.getSelectedItemText();
minSampleSize = selectedItem.substring(0, (selectedItem.indexOf('-'))).trim();
maxSampleSize = selectedItem.substring((selectedItem.indexOf('-') + 1)).trim();
}
else{
minSampleSize="0";
maxSampleSize="100000";
}
resetIntegerRangeDropdownFilter();
filterChangedEvent.addFilter(Integer.parseInt(minSampleSize), Integer.parseInt(maxSampleSize));
clientFactory.getEventBus().fireEvent(filterChangedEvent);
}
Now, as for the style, I've tried "bootstrapping" it with this line:
<g:ListBox ui:field ="integerRangeDropdownListBox" styleName="btn btn-primary dropdown-toggle"/>
And I've tried customizing it with CSS like this:
.customListBox{
background-color: dodgerblue !important;
color: white;
padding: 5px;
}
<g:ListBox ui:field ="integerRangeDropdownListBox" styleName="{style.customListBox}"/>
Whichever way I do it, it will not render equally across browsers, it only looks "nice" on Google Chrome, while in Safari and Firefox it will have an "uglee" arrow for the dropdown and different scroll bar.
Any ideas as for why this may be happening? Needless to say I've tried google and the forum, but searching for GWT related topics is pretty much useless
First, you should use addStyleNames instead of styleName, because styleName removes all existing style names and replaces them with the style name you provided.
Second, this is not a GWT problem. Browsers render various elements differently. If you want a more uniform look, you need to search for CSS suggestions.
It is exactly as you described your question: The standard GWT ListBox is rendering different across browsers.
The main reason is that it is using a native browser control under the hood.
It creates a HTML select control element here.
You can try that basic HTML control yourself in different browsers here.
So there is not much you can do about that.
On some browser you might be able to style it, but not consistently.
I have a IButton instance and I want to change its name and color after click.
button.addClickHandler(new ClickHandler() {
public void onClick(ClickEvent event) {
if(button.getTitle().equals("Enabled")) {
button.setTitle("Disabled");
button.setTitleStyle("disabledButton");
}
else {
button.setTitle("Enabled");
button.setTitleStyle("enabledButton");
}
}
});
As we do in general GWT project,
I have added following to the default .css file:
.enabledButton {
color:green;
}
.disabledButton {
color:red;
}
But when I run the application, it is not showing either red or green color.
Is there any other way in SmartGWT to apply CSS styles?
IButton is a StatefulCanvas, which means it handles states. This is done by adding suffixes after the base style name. For example if you set the titleStyle to "enableButton" and you move your mouse over the button, it will look for the css class: enableButtonOver. If the button is also focused, it will look for enableButtonFocusedOver etc (there are a couple of suffix combinations). Your example works if you click outside from the browser, so it will lost the focus and simply will use the enableButton css class. You can disable each state by for example setShowFocused(false). See the api.
How does URL fragments interact with CSS? I have a page, say: http://example.boom/is_this_a_bug.html. The code for the page is shown in https://gist.github.com/3777018
When I load the page with the URL like that, the .tab-pane elements are not showed because they overflow their container, and it has an overflow: hidden property.
However, if I load the page by appending a valid fragment (#00) to the URL, then the .tab-pane gets visible, just as if the left:100% was not taken into account. Pressing the button just removes and resets left:100%, and then I get the overflowing tab-panes.
This happens in both Firefox 15.0.1 and Chromium 18.0.1025.168 (Developer Build 134367 Linux) Ubuntu 12.04.
Any ideas why this is happening? Is this a bug, or is documented elsewhere?
Best regards,
Manuel.
When you load a page with a fragment identifier in the URL, if that fragment identifier matches the ID of an element on the page the browser will scroll the page to bring that element into view.
An alternative can be use javascript applied styles.
(function hashStyle() {
if (window.location.hash == '#COLOR') {
var css = document.createElement('style'),
s = document.getElementsByTagName('script')[0],
styles = 'body { background-color: #b0c4de; }';
css.type = 'text/css';
if (css.styleSheet) {
css.styleSheet.cssText = styles;
} else {
css.appendChild(document.createTextNode(styles));
}
s.parentNode.insertBefore(css, s);
}
})();
A friend and myself are trying to workaround IE (7/8). We have built a canonical example here:
http://www.mathgladiator.com/share/ie-select-bug-hover-css-menus.htm
Using a CSS menu, we would like to have selects in them. However, in IE, the menu goes away when you interact with the select box. We believe this has to do with a bug in how selects affect events.
Is there a workaround? At least with pure CSS or DOM hacks?
I do not think there is a pure CSS way around this. This is due to a very common bug to the way IE handles events on select elements.
You can however work around it with Javascript:
<script type="text/javascript">
$(document).ready(function () {
$('.nav_element a').mouseover(function() {
$('.submenu').hide();
$(this).parent().find('.submenu').show();
});
$('.submenu').mouseover(function() {
$(this).show();
});
$('.submenu').mouseout(function (e) {
// Do not close if going over to a select element
if (e.target.tagName.toLowerCase() == 'select') return;
$(this).hide();
});
});
</script>
The code above uses jQuery.
Here is a way to improver select behavior in IE7/8, but it does not fix the issue
Change DOCTYPE
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
Add script
<script>
function ddlOut(e) {
setTimeout(function() { e.className = e.className.replace(' over', ''); }, 1000)
}
</script>
Add css
#nav .over div.submenu
{
display: block;
}
#nav .nav_element{
behavior: expression(
this.onmouseover = new Function("this.className += ' over'"),
this.onmouseout = new Function("ddlOut(this)"),
this.style.behavior = null
);
}
It will work better at least but of course not perfect.
My advice is to change select control to html equivalent. I use OboutDropDown that has a nice view. There are many implementations that can suite you needs.
First you need to expand the :hover surface underneath your menu.
So in your css add width:310px;height:220px to #nav .nav_element a.
(also add a class or an id on the second div styled with top:220px)
Now you just need to simulate a mousedown triggered when you click on the select which will halt when the selection between the options is done - you can probably do the last part if you check for the onfocus state of the select which will stop the mousedown.