How to change PrimeFaces submenu default icons - css

What is the method of adding my own custom icons to the submenu name area in a panelMenu in PF 3.5?
This is the example given on the official documentation web page:
I have to remove the small arrows and replace them with other images. So far, I have understood that the arrows are placed by the primefaces.js (which comes in the PF JAR file). What is the method of replacing them through java? As I am generating a dynamic menu, not a static one. I would like something like this:
I have tried
MenuItem item = new MenuItem();
item.setIcon("ui-icon-print");
But this changes it for the items INSIDE the submenu. e.g. Save and Update. I am asking for the headings or group names, "Ajax Menuitems", "Non-Ajax Menuitem" etc.

Disclaimer: I've tested this with PrimeFaces 6.0, but this will most likely also work with 3.5.
The easiest way to do so (in my opinion) is using CSS. If you inspect the arrow using your browsers debugging tools you will find that the image comes from a background sprite at a specific position.
To create a more specific rule to set your icon it's best to add a style class to your submenu:
<p:submenu label="Ajax Menuitems" styleClass="myIcon">
or in Java:
DefaultSubMenu defaultSubMenu = new DefaultSubMenu("Ajax Menuitems");
defaultSubMenu.setStyleClass("myIcon");
Now you can use that class to create your CSS rules (assuming you've created a sprite):
.myIcon .ui-icon.ui-icon-triangle-1-e {
background-image: url('pathToYourSprite.svg');
background-position: 0 0; /* closed position */
}
.myIcon .ui-icon.ui-icon-triangle-1-s {
background-image: url('pathToYourSprite.svg');
background-position: 0 0; /* opened position */
}

As suggested by #Jasper, I set the styleClass attribute for the submenu and it worked. Here is the code for my xhtml:
<div class="">
<h:form>
<p:panelMenu model= "#{menuBean.getModel()}" type="tiered">
</p:panelMenu>
<p:spacer height="10"></p:spacer>
</h:form>
</div>
CSS:
.icon-1 > h3 > span{
background-image: url(../resources/images/icon_1.png);
margin: 0px 4px 0px 0px;
width: 25px;
height: 25px;
}
.icon-2 > h3 > span {
background-image: url(../resources/images/icon_2.png);
margin: 0px 4px 0px 0px;
width: 25px;
height: 25px;
}
Java:
List<Items> list = //map of items to be added to the panelMenu with a parent-child hierarchy.
String label = "SubMenu 1";
String icon = "icon-1";
Creating a new submenu and adding styleClass:
Submenu submenu = new Submenu();
submenu.setLabel(label);
//submenu.setIcon(icon);
submenu.setStyleClass(icon);
Adding the submenu to the panelMenu:
((MenuModel) container).addSubmenu(submenu);
Creating a new item to go inside the submenu:
MenuItem item = new MenuItem();
item.setValue(label);
item.setTitle(label);
item.setIcon(icon);
if (container instanceof MenuModel) {
((MenuModel) container).addMenuItem(item);
} else if (container instanceof Submenu) {
((Submenu) container).getChildren().add(item);
}
The result:
This method works much better than the first method I tried. For that, I added a custom PanelMenu renderer as explained here: Are user icons supported on root submenus in PrimeFaces 6.0 PanelMenu. It is a lot more work while requiring the same icon styling classes.

to change the icon you have two solutions
First solution
You can look to the Ui-Icon we site and choose the icon that you want to use Icons Site
Second solution
you can use your own icon using css
.mainPageIcon {
background: url(/images/image.png) no-repeat;
height: 16px;
width: 16px;
}
<p:panelMenu style="width:300px" icon="mainPageIcon ">
...
</p:panelMenu >
for Java solution
MenuItem item3 = new MenuItem();
ImageIcon imageIcon = new ImageIcon(ImageIO.read(getClass().getResourceAsStream("/Project1/rawaz/new.gif")));
item3.setIcon("imageIcon");
You can read more Are user icons supported on root submenus in PrimeFaces 6.0 PanelMenu

Related

Use CSS to change the photos within a dropdown menu

I am using a donation widget from another company which I have made use of on my website. I would like to change the size of the photos in the dropdown menu next to the item on the menu. I want to change it to 50x50 pixels.
Unfortunately, all I have is the widget code itself. I do have a image example, that could help to clear up what I'm talking about.
$data.WebPhotoId {
max-width: 50px;
max-height: 50px:
}
dropdown-menu databind= {
max-width:50px;
max-height:50px;
body {
font-size: 16px;
font-family:Helvetica, Arial, sans-serif !important;
color: #676767;
}
}
My question is, is there any way I modify my CSS in order to change the menu item pictures?
Well if it is set with <img src="path/to/image"> you can't do it nicely with CSS.
In that case I would suggest using JavaScript or jQuery for this.
var image = document.getElementsByClassName('image-class')
for(var i = 0; i < image.length; i++) {
image[i].src="path/to/new/image";
}
With CSS you can set background-image: url('path/to/new/image') but I don't think it will work in case where image is set with <img src="path/to/image">

CSS Specificity in Angular Component using /deep/ when a class is outside the component

I made a button component for a Angular Component Library I am putting together. The button works well and the component is implemented like so:
<sio-button
[buttonLabel]="'Button Text'"
[buttonFormat]="'fluid'"
[buttonStyle]="'1L'"
(buttonClicked)="outputButtonClick()" >
</sio-button>
As you can see I pass through various values via the Input() decorator and the button style is set using a short-hand string value, the template looks like so and a method is used to output the desired CSS classes as a string
{{buttonLabel}}
the rendered output looks like so -
<sio-button _ngcontent-c0="" _nghost-c2="" ng-reflect-button-label="Button Text" ng-reflect-button-format="compact"
ng-reflect-button-style="primary-line">
<button _ngcontent-c2="" class="sio-btn sio-btn--primary-line sio-btn--compact" ng-reflect-klass="sio-btn"
ng-reflect-ng-class="sio-btn--primary-line sio-btn-"> Button Text
</button>
</sio-button>
I want to all the user of the UI components library to use my buttons as a button group, this is simple, I just wrap a DIV with a set CSS class so I can amend the CSS of the buttons within as I need to remove the border-right and border-left on the first button and last button contained within the button group like so...
<div class="sio-btn-group">
<sio-button [buttonLabel]="'Button Left'" [buttonFormat]="'compact'" [buttonStyle]="'1L'">
</sio-button> <!-- this needs to lose its borfer-right -->
<sio-button [buttonLabel]="'Button Middle'" [buttonFormat]="'compact'" [buttonStyle]="'1L'">
</sio-button>
<sio-button [buttonLabel]="'Button Right'" [buttonFormat]="'compact'" [buttonStyle]="'1L'">
</sio-button> <!-- this needs to lose its border-left -->
</div>
So in my sio-button SCSS file I wish to write the CSS rule to overwrite the borders for the first and last child (remember that the sio-btn-group DIV is outside the button component) so in my button.component.scss file I add the following
/deep/.sio-btn-group .sio-btn--primary-line {
&:first-of-type {
border-right: none;
}
&:last-of-type {
border-left: none;
}
}
And this doesn't work as the styles are overwritten on all 3 button components. So I change this to
/deep/.sio-btn-group .sio-btn--primary-line {
&:first-child {
border-right: none;
}
&:last-child {
border-left: none;
}
}
This has the same effect as all buttons contained within the .sio-btn-group have their left and right borders removed. If I remove the /deep/ it doesn't work at all and should I add a second /deep/ like so /deep/.sio-btn-group /deep/.sio-btn--primary-line all the left and right borders are removed. What is wrong with my CSS selector? If anyone can help me see what I am doing wrong I would be most appreciative.
If you feel I should add a code pen please says so and I shall add one or should my explanation be confusing please let me know and I shall reword.
This fixed my problem
/deep/.sio-btn-group sio-button {
&:first-of-type {
[class*="-line"] {
border-right: none;
}
}
&:last-of-type {
[class*="-line"] {
border-left: none;
}
}
}

How to create a (CSS) style variant for a dropdown widget, to target its list rows with it?

as the title states, I need to create a 'Compact' style variant for a dropdown widget. But I can't figure out how to target the dropdown items (rows) with it.
This works to target all the dropdowns:
.app-Dropdown-Item {
padding: 0px !important;
}
Here's how I've tried to do it with the style variant to target only specific widgets:
.app-Dropdown--Compact .app-Dropdown-Item {
padding: 0px !important;
}
This has worked for me before, like with Tabs-widget's header:
.app-Tabs--RedBg .app-Tabs-Header {
background-color: red;
color: white;
}
I would suspect it could have something to do with the list items being not immediate sub-items of the dropdown widget, but I'm not sure.
Thanks for your help!
It looks like it is not possible to create custom style variants for dropdown items at this time... So, the only way to style dropdown items individually is to write style for particular dropdown:
.app-PageName-DropdownName-List > .app-Dropdown-Item {
padding: 0px; /* it seems that this rule works without !important */
}

How can I change CSS pseudo-element property dynamically?

I understood:
You can't modify pseudo elements through JavaScript since they are not part of the DOM
I also knew we could add properties in pseudo-element by appending style -- more.
However, the appending solution could only add value. adding doesn't mean the ability of changing dynamically. I also need to the ability of replacing the property value.
Therefore, I tried to use attr() to change background image dynamically. However, currently attr only supports content property - more.
So what else I can try here?
In order to adding more context of the question, basically, I want to dynamically update avatar image in chat. The avatar image is setted in pseudo-element(before and after). Here is the code-pen of Chat UI -- http://codepen.io/clintioo/pen/HAkjq
Thank you very much!
As said in other answers, there is a way to inject styles that will afect your pseudo element.
A somewhat simpler workaround for your specific case could be to just inherit the background from the base element (since you are not using it)
function changebkg () {
target1 = document.getElementById('test');
target1.style.backgroundImage = "url(http://placekitten.com/1000/750)";
}
#test {
font-size: 40px;
position: relative;
display: inline-block;
color: black;
background-size: 0px;
background-color: lightblue;
}
#test:after {
content: "";
position: absolute;
left: 200px;
top: 20px;
width: 200px;
height: 200px;
background-image: inherit;
border: solid 1px;
background-size: contain;
}
<div id="test" onclick="changebkg();">click me</div>
Here is the part in the "duplicate" that shows how to get, add and change CSS pseudo-element property dynamically using Javascript.
Stack snippet
/* on page load */
window.addEventListener('load', function() {
/* get button and add click event to it */
var btn = document.querySelector('button');
btn.addEventListener("click", function(){
/* get first <p> element */
var el1 = document.querySelector('p.first');
/* get second <p> element */
var el2 = document.querySelector('p.second');
/* get first <p> pseudo's "content" property value */
var str = window.getComputedStyle(el1,':before').getPropertyValue('content');
/* get first <p> pseudo's "color" property value */
var col = window.getComputedStyle(el1,':before').getPropertyValue('color');
/* dynamically add a rule to the stylesheet so the second <p>
will get the same "content"/"color" value as the first */
document.styleSheets[0].addRule('p.second:before', 'content: ' + str + ' ; color: ' + col + ';');
/* dynamically add a rule to the stylesheet that override the
first <p> "color" to green */
document.styleSheets[0].addRule('p.first:before', 'color: green;');
});
});
p.first:before {
content:"foo";
color: red;
}
button {
display: block;
width: 220px;
margin-top: 50px;
}
<p class="first">This is a paragraph</p>
<p class="second">This is another paragraph</p>
<button>Change/Add pseudo properties</button>
As you have just learned, attr() isn't supported anywhere else but the content property at the moment. If your requirement is to set other CSS properties dynamically, then I'm afraid you can't do much of that within CSS alone. The closest you can get is to generate static CSS dynamically through a script, as shown in a number of answers to the first question you link to.
In the specific case of user avatars, I don't see why you aren't just marking those up using img elements instead, which would obviate this issue entirely.
You can create a css file and then inject it into the DOM.
var avatar_css_for_avatar = document.createElement('style');
avatar_css_for_avatar.type = 'text/css';
avatar_css_for_avatar.innerHTML = '.user-avatar-id:before { background-image: url(url_of_image); }';
document.getElementsByTagName('head')[0].appendChild(avatar_css_for_avatar);
document.getElementById('someElementId').className = 'user-avatar-id';

Align a button to top

I am building a webapp in .net using some of the AJAX features; in this case it is TabContainer.
Below is a screenshot of the area I want to play with.
The menu on the left is the tabs of TabContainer. The right side is tab's content. I would like to have the "Update PCR" button to be right underneath "Disciplines Affected". The problem is that the left and right side are a part of ONE block, which is TabContainer.
Are there any suggestions to how would I format the CSS of the Button to align right underneath TabContainer's menu? I could add the button as a part of the menu but, then I would have to set the control to AutoPostback, which defeats its purpose in this case in the first place... Any suggestions would be appreciated!
EDIT:
Here is the existing CSS
.ajax_tabController .ajax__tab_tab
{
background-color: #3c6f91;
padding: 5px;
border: 1px solid #ffffff;
color:#ffffff;
border-left: 3px solid #5AB0DB;
}
.ajax_tabController .ajax__tab_hover .ajax__tab_tab
{
background-color:#5AB0DB;
text-decoration:none;
}
.ajax_tabController .ajax__tab_active .ajax__tab_tab
{
background-color:#5AB0DB;
text-decoration: underline;
}
Also, there is CSS that overrides some settings to make TabContainer Vertical instead of Horizontal. I know, that there is a property .UseVerticalStripPlacement but it messes up with the height of the control and throws a JavaScript error.
.ajax__tab_header
{
float: left;
}
.ajax__tab_body
{
margin-left: 160px;
}
.ajax__tab_outer
{
display: block !important;
}
.ajax__tab_tab
{
width: 210px;
height: auto !important;
}
You need to position the top of the button relative to the bottom of the tab elements. This can be done with jquery. See How to position one element relative to another with jQuery?
It's going to be a bit hit and miss, but try something along the lines of:
.updatePcrButton {
position: absolute;
top: 100px; /* These will be whatever the measurement is to */
left: 5px; /* be directly under the last element */
z-index: 99; /* Arbitrary amount to put it above any other elements */
}
This is pretty messy to be honest - it relies on your not changing the position of the control thereafter.
Perhaps a better way would be to add an extra tab to the TabContainer and handle any Tab clicks yourself.
-- Edit -- May be more useful --
Nikita, I had completely forgotten about this as it was in an old Classic ASP app of mine, but you could try these two JS functions that are probably more useful to you:
function curTop(obj){
rv = 0;
while(obj) {
rv += obj.offsetTop;
obj = obj.offsetParent;
}
return rv;
}
function curLeft(obj){
rv = 0;
while(obj) {
rv += obj.offsetLeft;
obj = obj.offsetParent;
}
return rv;
}
They pull the position from the specified object. If you add the height of the button that you want to position under then you may find this improves the location for you and prevents any funny business with CSS.
Kind regards,
Westie.

Resources