GWT ListBox rendering different across browsers - css

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.

Related

CSS specificity testing

Are there any good tools or methods for automatic testing css selectors?
I'm developing a SCSS framework and would like to include automated tests in it.
Specifically I would like to have tests to ensure that the css selectors are working properly.
Say for instance that I have the html:
<input class="btn" disabled id="test"></input>
and css
.btn {
color: red;
...
}
.btn:disabled {
color: green;
...
}
I would like to have a test that ensures that the element above with id=test, have the .btn:disabled as the css class with highest priority (last class with highest specificity) and .btn as the second highest priority. In other words, I would like to ensure that the .btn:disabled and .btn css style is applied on the element and that styles in .btn:disabled are overwriting the styles in .btn.
I'm thinking of doing this in selenium. Are there any good ways of doing this? I would not like to hard code the css values into the tests.
The method I settled with is to use getComputedStyle to get the style with "highest priority". In the css I add a "tag" to the content property. In jasmine I then check if the desired tag is the computedStyle. (I will extend this in scss so that the content property is set by a mixin if test mode is used and not set in production.) This only makes a unit test for the class of highest priority, but not for the second highest etc.
Below is a tests to illustrate the example (only the first and last should pass).
// specs code
describe("CSS", function() {
it("Div element of class test should be handled by .test", () => {
const testdiv = document.getElementById("testdiv")
m = window.getComputedStyle(testdiv).getPropertyValue("content");
expect(m).toEqual('".test"');
});
it("Div element of class test should be handled by div", () => {
const testdiv = document.getElementById("testdiv")
m = window.getComputedStyle(testdiv).getPropertyValue("content");
expect(m).toEqual('"div"');
});
it("Div element should be handled by .test", () => {
const testdiv = document.getElementById("testdiv2")
m = window.getComputedStyle(testdiv).getPropertyValue("content");
expect(m).toEqual('".test"');
});
it("Div element of class test should be handled by div", () => {
const testdiv = document.getElementById("testdiv2")
m = window.getComputedStyle(testdiv).getPropertyValue("content");
expect(m).toEqual('"div"');
});
});
// load jasmine htmlReporter
(function() {
var env = jasmine.getEnv();
env.addReporter(new jasmine.HtmlReporter());
env.execute();
}());
.test {
content: '.test';
}
div {
content: 'div';
}
<script src="https://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.js"></script>
<script src="https://cdn.jsdelivr.net/jasmine/1.3.1/jasmine-html.js"></script>
<link href="https://cdn.jsdelivr.net/jasmine/1.3.1/jasmine.css" rel="stylesheet"/>
<div class="test" id="testdiv">TestDiv</div>
<div id="testdiv2">TestDiv</div>
If I understand the question correctly, you're basically asking for a test (for your example) like this:
if -> Element.ComputedStyle.color = green
then -> test passed
else -> test failed (you have CSS structure errors)
Obviously, the browser will interpret specificity correctly. So you're really testing if changes you made by adding/overriding CSS caused unintended visual consequences.
That seems pretty manual question to answer since you'll have to decide what each of those correct states is and then maintain the tests. If you go this route, I'd look at something like Backstop.js. Though CSS visual regression testing is REALLY complex so be careful how much you expect from it.
The Manual Way
Could you solve the problem somewhat manually by creating a SCSS variable that's usually transparent? Then as you're adding/changing code add that variable and change the color to something like pink that's really obvious? At this point, you should see where things override when you render the page.
If you're making a CSS framework, I'd test against your documentation since that should show you previous examples that would be overridden.
CSS Blocks
You may also want to look into the CSS Blocks API. It's not going to be a "test" exactly but the API provides scoping and compile errors that might help you catch some of those issues sooner than later.
Here's the pertinent part:
With CSS Blocks new resolution system, cascade conflicts will be caught for you before you even know they exist and you will never have to fight a specificity war ever again.
As you have mentioned you can achieve this with Selenium. In terms of methodology, if you're looking to maintain this long term then I would recommend following the Page Object Model. The official documentation on this is available here, and there are some other articles in various language here, here, and here.
Essentially what it boils down to is create classes or models for the pages (or page sections/components (as in a form that has multiple controls)), this class will then have properties/fields for each of the elements on the page that you want to interact with. The advantages of this approach are:
A single place to change if you need to update a selector (maintainability)
The underlaying code which can be ugly can be exposed through a nice interface that uses fluent syntax (readability)
How this looks (since you haven't specified a language I'll go with C#:
public class LoginPage
{
// FindBy attributes should decorate each property to specify the selector
public WebElement UsernameInput { get; set; }
public WebElement PasswordInput { get; set; }
public WebElement LoginButton { get; set; }
public LoginPage()
{
...
}
public LoginPage Load(this LoginPage page)
{
// code to navigate to the login page
}
public LoginPage EnterCredentials(this LoginPage page, string username, string password)
{
// code to fill out inputs
}
public HomePage Login(this LoginPage page)
{
// code to click login button
}
// Other methods
}
How this looks when you use it:
HomePage homePage =
new LoginPage()
.Load()
.EnterCredentials("user", "pass")
.Login();
// Now you can perform operations on the HomePage
CSS Specificity
As per the documentation Specificity is the logic by which the browser decides which CSS property values are the most relevant to an element incase there are two or more conflicting CSS rules that point to the same element and which will be applied. Specificity is calculated based on the matching rules which are composed as per different CSS selectors.
How to calculate Specificity
There are a couple of rules to calculate Specificity based on points which are as follows:
style attribute: 1000
id attribute: 100
class or pseudo-class: 1
Calculating the CSS Specificity
Let us calculate the Specificity of both the CSS
Sample A:
.btn {
color: red;
}
Explanation: Contains a class i.e. btn. So Specificity is 1.
Sample B:
.btn:disabled {
color: green;
...
}
Explanation: Contains a class i.e. btn and a pseudo-class i.e. disabled. So Specificity is 2.
Tests
The CSS specificity can also be visually verified through Specificity Calculator:
Conclusion
As the CSS sample B has a greater Specificity, so CSS sample B will be applied to the element:
<input class="btn" disabled id="test"></input>
Outro
However there are some more granular CSS Specificity Rules on:
Equal specificity: the latest rule counts.
ID selectors have a higher specificity than attribute selectors.
Contextual selectors are more specific than a single element selector.
A class selector beats any number of element selectors.
You can find a detailed documentation in CSS Specificity

How to set style for an element in typescript?(Angular)

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()>

What is the syntax for smoothing an embedded image with CSS?

If I want to embed an image with smoothing I might do something like this:
package
{
public class EmbeddedImages
{
[Embed(source="/assets/image1.png", smoothing="true")]
public static const Image1:Class;
}
}
However, if I have a bunch of buttons with different icons, I want to control which icon to display using CSS, like this:
#namespace s "library://ns.adobe.com/flex/spark";
s|Button.image1
{
icon: Embed('/assets/image1.png');
}
I want the icon to be smooth. So what is the syntax for adding smoothing when embedding with CSS?
I don't have a project to test on, but see the smoothingQuality style of Image. This obviously won't work if the button uses BitmapImage to display the icon since the style is only available for Image. Odds are, it does use BitmapImage, though.
s|Button.image1
{
icon: Embed('/assets/image1.png');
smoothingQuality: "high";
}
Again, I have no way to test this so that is a complete shot in the dark. Worth a try, though
Since it's a mobile project, then the Button icon is a BitmapImage and you could try setting its members
smooth = true;
smoothingQuality = BitmapSmoothingQuality.BEST;
or maybe do that via CSS:
s|ButtonImage {
smoothingQuality: "best";
}

OnMouseOut event not triggered when moving mouse fast (GWT - all browsers)

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?

Addressing in CSS in Flex: Buttons in RichTextEditor only?

I want to change the font characteristics for buttons in the toolbar of the RichTextEditor, but I want them to be different than other buttons in my application. Is there any way to do this with just CSS? I know that I can do it with setStyle if necessary...
One way to do it, since the RichTextEditor's sub-components are declared in MXML and are therefore publicly accessible, is to assign their styleName properties individually at runtime (after the container's creationComplete event fires, to be sure the editor and all its children have been created), like so:
<mx:Style>
.myRTECombo
{
color: #FF0000;
}
</mx:Style>
<mx:Script>
<![CDATA[
private function creationCompleteHandler(event:Event):void
{
rte.fontFamilyCombo.styleName = "myRTECombo";
rte.fontSizeCombo.styleName = "myRTECombo";
}
]]>
</mx:Script>
<mx:RichTextEditor id="rte" />
The Flex docs don't call out the subcomponents ("boldButton", "fontSizeCombo", et al) by ID, but the component's source is available for viewing, so you should be able to get all the info you need from the source code itself. Since I use FlexBuilder, I usually use the Eclipse Ctrl+click shortcut, on the tag/class name, to jump into the associated class-definition file, but you can also open the source file directly at [installDir]/sdks/[version]/frameworks/src/mx/RichTextEditor.mxml to have a look for yourself.
I'm sure there are other approaches (setStyle being one, although its explicit use is generally discouraged for performance reasons), but this ought to work out for you. One thing to note, though, as you'll see when you dig into the component's source, is that many of the buttons in the default button set actually use PNGs (e.g., icon_style_bold.png), not text, which is why my example includes a reference to the ComboBox instead, so you can see how the color changes apply; if you want to change the look of the buttons, be aware they're using the styleable icon property, not font-style settings, for their look and feel.
Hope it helps!
Thanks #Christian Nunciato! This is my final code, in my component that is a RichTextEditor (extends it). In the creationComplete, I call this
private function setUpStyleNames():void {
setUpStyleNamesInner(toolbar.getChildren());
setUpStyleNamesInner(toolBar2.getChildren());
}
private function setUpStyleNamesInner(children:Array):void {
for each (var child:DisplayObject in children) {
if (child is UIComponent) {
UIComponent(child).styleName = "rteInnards";
}
}
}
and then in my styleSheet, I have this
.rteInnards {
color: #FF0000;
fontSize: 25px;
}
Awesome. Thanks again!

Resources