JavaFX TableView: Cannot Override '-fx-text-fill'! - javafx-2

On JavaFX2.2, I created my own style class to represent table cells that contain invalid data. But my style class seems unable to override -fx-text-fill in the hover, selected, and focused states. Here is my style class:
.invalid-table-cell {
-fx-text-fill: red;
}
.invalid-table-cell:hover {
-fx-background-color: salmon;
-fx-text-fill: blue; /* No worky */
}
.invalid-table-cell:selected {
-fx-background-color: purple;
-fx-text-fill: orchid; /* No worky */
}
.invalid-table-cell:focused:hover {
-fx-background-color: red;
-fx-text-fill: green; /* No worky */
}
When my app runs, I can see changes in -fx-background-color, but I see no changes in -fx-text-fill in any of the special states.
What am I doing wrong?

!important is likely required due to the specificity of your css rules versus the css rules of the default caspian or modena stylesheets (though my css skills are limited in terms of evaluating this).
SceneBuilder 1.1 has a css analyzer that can help determine what css rules and attributes are being activated. That may help in debugging css rule activation in general, though it is not much help in this specific case unfortunately as you can't set the styles on table cells through SceneBuilder 1.1.
One work-around is to copy all of the table-view css rules from the modena or caspian css (unfortunately there is a lot of them) and place the rules in your user stylesheet. Prepend the style selection element .invalid-table-cell to each of the table css rules in your user stylesheet and modify the rules as appropriate to achieve your desired look and feel. This will ensure that your ruleset has the correct level of specificity to override the default rules. It is unfortunately, a pretty arduous process and perhaps your !important overrides might be a better solution for you.
A slightly easier way to customize styles is to override predefined constants, for example something like below (which I haven't tried and just demonstrates a principle as the exact selector and rules needed may differ):
.invalid-table-cell {
-fx-selection-bar-text: goldenrod;
}
As much of the default table cell styles are defined using -fx-text-fill: -fx-selection-bar-text;, just setting this value to the appropriate value allows you to override all of those default table cell styles. But it overrides them all to the same value, so if you need different values for different css psuedo-states like in your question, then you will need to define those rules explicitly as outlined earlier.

Following jewelsea's advice, I increased the specificity of my CSS rules to match the specificity of the corresponding rules in capsian.css. Because I was curious, I increased the specificity of my own rules incrementally and discovered that anything less specific than the following rules does not work in my situation.
.table-view:cell-selection .table-row-cell:filled .invalid-table-cell:hover {
/* Works! */
}
.table-view:focused .table-row-cell:filled .invalid-table-cell:selected:focused {
/* Works! */
}
.table-view:focused .table-row-cell:filled .invalid-table-cell:focused:selected:hover {
/* Works! */
}

Related

Custom Header Layout - Spartacus Storefront

Has anyone solved or knows how to solve the following situation given the implementation of the header in Spartacus?
I would like to show in the header, a layout on the right of two level blocks, and on the left of a single level block.
Objective Header Layout
I can't think of how to do it since I can't see how to wrap certain slots, given the Spartacus implementation for the header.
Given the implementation of the header in Spartacus, inside the StorefrontComponent I cannot replace it using the ConfigModule.withConfig ({...}, as CmsConfig)
I understand and already tried that I can replace the header, implementing an Outlet (cxOutletRef = "header"), but this makes it impossible to edit it through SmartEdit, which is not acceptable to me.
Any suggestion? Or possible solution?
As a last option it occurs to me that I can create a component type from the back, and map it from Angular using "ConfigModule.withConfig ({...}, as CmsConfig)" implementing the "conflicting two-level" block from scratch or even the entire header.
Thank you !
////// CORRECTION 09/23/20 //////
Outlets do not prevent editing via SmartEdit. It's necessary to indicate the Slot to which the component corresponds, this is easy to implement using the PageSlotComponent.
✔ Example:
<ng-template cxOutletRef="cx-header">
<header
cxSkipLink="cx-header"
[cxFocus]="{ disableMouseFocus: true }"
[class.is-expanded]="isExpanded$ | async"
(keydown.escape)="collapseMenu()"
(click)="collapseMenuIfClickOutside($event)"
>
<cx-page-slot position="MiniCart"></cx-page-slot>
</header>
<cx-page-slot position="BottomHeaderSlot"> </cx-page-slot>
<cx-global-message></cx-global-message>
</ng-template>
In this way, SmartEdit does allow you to edit the MiniCart component, within its corresponding slot.
🚫 Wrong way:
<ng-template cxOutletRef="cx-header">
<header
cxSkipLink="cx-header"
[cxFocus]="{ disableMouseFocus: true }"
[class.is-expanded]="isExpanded$ | async"
(keydown.escape)="collapseMenu()"
(click)="collapseMenuIfClickOutside($event)"
>
<cx-mini-cart></cx-mini-cart>
</header>
<cx-page-slot position="BottomHeaderSlot"> </cx-page-slot>
<cx-global-message></cx-global-message>
</ng-template>
you can indeed solve this with a custom layout configuration and additional CSS, but it's not necessary. I give you a few options to consider:
Option 1: Change the generated DOM
You can either provide a custom layout config as #pwavg suggests, or even introducing a custom storefront component.
If you introduce a custom layout config, you're limited by the sections we use in the storefront component. If you insist on custom sections (ie. an element that wraps the searchbox, login, mincart and nav), you need to introduce a custom storefront component. The disadvantage here is that you'll deviating away from standard Spartacus component, which might result in missing features in the future.
Option 2: Pure CSS
A pure CSS solution is the easiest. You do not need to change any actual DOM, but apply some custom CSS rules to the standard DOM. Grid system is indeed designed for this. It's a bit complex to start with, but would do the job.
You can actually achieve this with flexbox as well, but you'd need to move the logo slot out of the flexbox flow.
Here's an actual quick and dirty code snippet to demonstrate changing by a few CSS rules only. It comes with a few assumptions/limitations, but for most cases it might be fine.
header {
cx-page-slot.SiteLogo {
// we absolute position the logo, so it flows outside the flexbox system. this requires
// an hard-coded top position, that might be fine, but I don't know the details.
position: absolute;
top: 60px;
}
cx-page-slot.SearchBox {
// align searchbox to the left, not sure if that's required, but looks better
margin: 14px auto 14px 150px;
}
cx-page-slot.NavigationBar {
margin-left: 150px;
overflow: hidden;
}
// manipulate a very high logo to demonstrate this works
cx-page-slot.SiteLogo img {
height: 100px;
}
}
Result (sorry for the logo ;) )
Option 3: cx-header Outlet
I would say you should be able to use outlets as well, as this will get you closer to option 1 (changing the actual DOM). I can't think of a reason why it would not work in SmartEdit - but happy to learn if it is the case. I'd recommend in this case to use the cx-header outletRef, so you would replace the entire header.
I am not super experienced with Spartacus so this might not be the correct way. Just trying to think with you on this.
I think you can just extend you layoutconfig and style the slots with CSSGrid. So for example you layout could be something like this:
layoutSlots: {
header: {
lg: {
slots: [
'SiteLinks',
'SiteLogin',
'HeaderLinks',
'SiteLogo',
'NavigationBar',
'SearchBox',
'MiniCart',
'NavigationBar2',
],
},
slots: ... (for mobile view)
},
},
And create a custom css grid for the positions of the slot.
If you want to have more markup control you could use cxOutletRef to replace the header with something like:
<ng-template cxOutletRef="cx-header">
<header>
<div class="header-top">
<cx-page-layout section="headerTop"></cx-page-layout>
</div>
<div class="header-bottom">
<cx-page-layout section="headerBottom"></cx-page-layout>
</div>
</header>
</ng-template>
And then divide the slots between headerTop and headerBottom in you config.

CSS variables not working in dialog::backdrop

I'm trying to change the background color of a dialog element's backdrop using a custom CSS property but it won't take. Is this a bug in Chrome or is there a reason for this?
document.querySelector('dialog').showModal();
:root {
--color-backdrop: red;
}
dialog::backdrop {
background: var(--color-backdrop);
}
<dialog>
<p>This is a dialog. My backdrop should be red.</p>
</dialog>
The spec states the following about ::backdrop pseudo-element:
It does not inherit from any element and is not inherited from. No restrictions are made on what properties apply to this pseudo-element either.
And to quote Xindorn Quan, a member of WHATWG, regarding CSS Custom Properties:
CSS variables are propagated via inheritance into descendants, so if a pseudo-element doesn't inherit from anything, CSS variables which are not defined for the pseudo-element directly would have no effect on the pseudo-element.
Finally, this is one solution for this kind of problem:
document.querySelector('dialog').showModal();
::backdrop {
--color-backdrop: red;
}
dialog::backdrop {
background: var(--color-backdrop);
}
<dialog><p>This is a dialog. My backdrop should be red.</p></dialog>
It seems to be useful for multiple modals with ::backdrop, as a way of organizing their "root", so to speak.

SASS; change font-family if size of element is above 16px

I don't even know if this is possible, I have to bring an RTL version of the website that is LTR.. I'm using Foundation 5 with Node and Grunt.Basically a file that overwrites some css rules of the original ltr file..
The client asked me to; Use a special font-family when the size of the element's text is above 16px.. Since other devs change the sass/css constantly I need a tool (or SASS formula) that allows to automatically switch the font-family when deploying the files with Grunt.
So instead of spending lots of time "scanning" the whole css/sass files for font-sizes and re-creating those rules with correct font-family.. I need something that automatically detects if the font-size is set then checks if it is above 16px, then if so, it changes the font family of the element.
Thanks
For me best way to do that is to use one SASS mixin to apply the font-size and check the value to apply the custom font :
#mixin custom-font-size($pixel) {
font-size: $pixel;
#if $pixel > 16 {
font-family: 'Comic Sans MS';
}
}
and call it like so :
#include custom-font-size(10px);

JavaFX ScrollPane border and background

I'm having some problem regarding the default background and border of the ScrollPane.
Using this style made the problem clearer to see.
setStyle("-fx-background-color:blue; -fx-border-color:crimson;");
I've tried this style and got no luck only the red border gone and left me with the blue one.
setStyle("-fx-background-color:blue; -fx-background-insets:0; -fx-border-color:crimson; -fx-border-width:0; -fx-border-insets:0;");
I've looked at this old post JavaFX Hide ScrollPane gray border and http://docs.oracle.com/javafx/2/ui_controls/editor.htm
This line of code doesn't work neither
scrollPane.getStyleClass().add("noborder-scroll-pane");
Thanks
In the current version of JavaFX 8, you can use the edge-to-edge style class to remove the border entirely:
<ScrollPane styleClass="edge-to-edge"/>
I have found a solution and would liked to post it here so others won't need to waste their time find it again.
By looking at the default css of JavaFx (caspian.css) which has been extracted from the library using this command.
jar xf jfxrt.jar com/sun/javafx/scene/control/skin/caspian/caspian.css
I could see that the one I missed is
-fx-padding: 0;
So this is the css class I'm using.
.scroll-pane {
-fx-background-insets: 0;
-fx-padding: 0;
}
.scroll-pane:focused {
-fx-background-insets: 0;
}
.scroll-pane .corner {
-fx-background-insets: 0;
}
Try use this first
.scroll-pane > .viewport {
-fx-background-color: transparent;
}
Before setting the background color
There seems to be a simple solution, which is to use "-fx-background: rgb(80,80,80);", that is,
scrollPane.setStyle("-fx-background: rgb(80,80,80);");
At least this works perfectly for me, while "-fx-background-color: rgb(80,80,80);" or "-fx-control-inner-background: rgb(80,80,80);" do not work in javafx 8. "-fx-background-color: rgb(80,80,80);" did work in earlier versions of javafx.
You can use:
-fx-background-color: transparent;
-fx-control-inner-background: transparent;
If you set only -fx-background-color, you will see the color change is applied to only the ScrollPane's inner edges, and the color of the center area is still not changed.
The -fx-control-inner-background property will change the color of that center area.
Honestly, your question was not clear enough, but I am only providing this answer to help others if I can.
What is causing this problem is you have the ScrollPane and inside it something called viewport that is bound to the ScrollPane. The properties that you apply for the ScrollPane object does not apply for the viewport. If you want to apply the properties for both ONLY, not the children too, you have to use the stylesheet property, not the style property itself, which uses in-line css code. For example, if you want to make the ScrollPane transparent, you have to apply the property for both, assuming the name of file is "scrollPane.css", like so:
#mainScrollPane > .viewport {
-fx-background-color: transparent;
}
#mainScrollPane {
-fx-background-color: transparent;
}
However, you need to apply a special Id property for the ScrollPane object, so it does not apply for the children:
ScrollPane scrollPane = new ScrollPane(root);
scrollPane.setId("mainScrollPane");
scrollPane.getStyleSheets().add("scrollPane.css");
Rather than use FXML or CSS I prefer to consume the event, but this only works on the portion that has content. If your scrollPane is larger than its content you also have to fill the remaining space.
scrollPane.getContent().setOnMousePressed(Event::consume);
scrollPane.setFitToHeight(true);
scrollPane.setFitToWidth(true);

How change the menubutton icon in primefaces?

I would like to put a custom icon in a p:menuButton, is this possible?
Yest it is possible. All you need to do is to override primefaces css classes generated for the p:menuButton.
Approach:
In the rendered web page you can right click on the generated p:menuButton and -> inspect element. There you can inspect all of the related css classes.
You can try to experiment with them (which I would advice, if you have time) for better understanding of css selectors and so on ...
The .ui-menubutton .ui-state-default .ui-icon are the classes that you need.
So now when you know which css classes are related to the icon you can override them :
Add .ui-menubutton .ui-state-default .ui-icon rule to your stylesheet (I assume you have one and it is sucesfully imported and working. If not check here.)
yourStyles.css :
.ui-menubutton .ui-state-default .ui-icon {
background: orange; /** insert your background image **/
}
This will override icons of all p:menuButtons used in your project. If you want to reduce it to some particular p:menuButton then add its ID to the style definition.
#menubID.ui-menubutton .ui-state-default .ui-icon {
background: orange; /** insert your background image **/
}

Resources