Inline CSS looks different when looping through - css

I have a solution which have boxes. If the user wants three boxes it will look like this:
The user can also choose 2 different colors for _each_box. If the user choose one color for one box, the box background color will be changed to that color. If the user enter two colors instead, a linear gradient will be set. These data will be sent as a variable via props:
firstColorBox1
secondColorBox1
firstColorBox2
secondColorBox2
and so on. These can have values such as "red" or hex-codes. I also have another props "nrofboxes" which is the number of boxes. I use this variable for my for loops.
To dynamically change the css of the boxes, I am using inline CSS which is manipulated via props. In short, I have a state with an empty array. Each box inline style properties will be saved in this array and extracted via its index in a for-loop. Too handle each box specific css style I have done like this:
I have an empy array in state where each individual style object till be added to:
boxStyle: []
in componentDidMount
for (var i = 1; i <= Number(this.props.nrofboxes); i++){
let style = {backgroundColor:"", };
let concatToState;
if(this.props["firstColorBox" + i] || this.props["secondColorBox" + i] ) {
if(this.props["firstColorBox" + i] && this.props["secondColorBox" + i] ){
style["backgroundImage"] = `linear-gradient(${this.props["firstColorBox" + i]}, ${this.props["secondColorBox" + i]})`
concatToState = this.state.boxStyle.concat(style);
this.setState({boxStyle:concatToState})
}
else if(this.props["firstColorBox" + i]) {
style.backgroundColor = `${this.props["firstColorBox" + i]}`
concatToState = this.state.boxStyle.concat(style);
this.setState({boxStyle:concatToState})
} }}
Above I have a loop for each box, and I check if it has value in both props and if so --> add linear gradient, and if not --> add background color. Notice how I go through each box dynamically via:
this.props["firstColorBox" + i]
I then add the value of the color/props to an object, and concat it to state:
style.backgroundColor = `${this.props["firstColorBox" + i]}`
concatToState = this.state.boxStyle.concat(style);
this.setState({boxStyle:concatToState})
The idea is to take the index of the specific box style in the state array in a for loop in render.
In render, I output all boxes via a for loop:
for (var i = 1; i <= Number(nrofboxes); i++){
boxes.push(
<div className={globalStyles["a-Grid-col"] + " " + globalStyles["w-sm12"] + " " + globalStyles["w-lg" + size] + " " + globalStyles["w-xl" + size] + " " + styles["w-link-box-container"]}>
<div className={styles["link-box"]} >
<a href={this.props["linkurl" + i]} style={this.state.boxStyle[i]} >
<h4 className={styles["link-box-header-container"]}>
<small className={styles["link-box-header-title"] + " " + (this.props.themefontcolor ? styles["w-themed-color"] : "")}>{this.props["linktitle" + i]}</small>
<span className={styles["link-box-header-text"] + " " + (this.props.themefontcolor ? styles["w-themed-color"] : "")}>{this.props["linktext" + i]}</span>
</h4>
</a>
</div>
</div>
);
}
As you can see above, I try to get each specific style object from the state via the for loop like this:
style={this.state.boxStyle[i]}
However, it does not work. If the firstColorBox1 is = "red", the expected behaviour would be that only the first box will be red but it looks like this:
2 problems: instead of a red background color, the border is red. And not only that, all three boxes are affected by it instead of only the first one.
And if I hardcode the inline style to be red like this:
style={{backgroundColor:"red"}}
it will look like this:
It should be equal, but there is no red border and the backgroundColor is set properly. Why is that? I guess something with my loops is wrong.

Related

Setting css class with variable in Xaringan with remark.js

I often need to change dynamically the font size or other properties for xaringan slides. Instead of defining a lot of different CSS classes I would like to define a general fontsize class and then passing a % value as variable. Something like this https://stackoverflow.com/a/17894116/9032257:
# Header 1
.fontsize50[
- some text
- some text
]
But fontisize50 is not hard coded on the CSS file. Is that possible?
Update
I have tried to use the approach proposed on Remark documentation https://github.com/gnab/remark/issues/72#issuecomment-62225566. I am able to dynamically the font size of a single word but not applying the font-size property to an entire section.
Adding this function to a macro.js file and setting the beforeInit YAML:
remark.macros.fontsize = function (size = "100%") {
var txt = this;
tag = "<span style=" + "'font-size:" + size + "'>" + txt + "</span>";
return tag
};
Then using this:
# Header 1
<!-- This Works -->
Hello ![:fontsize 200%](World)!
<!-- This Not -->
Hello ![:fontsize 200%](
- bullet 1
- bullet 2
- bullet 3
)
Change the fontsize according to the percentage only in the first case. I would like to have the same behavior as having a CSS class:
.font50 {
font-size: 50%;
}
And then using:
Hello
.font50[
- bullet 1
- bullet 2
- bullet 3
]
But I am not able to do this.

Change one color in all css style by javascript

I have a template with multiples class using one color, can I dynamically change that color to another using javascript?
When the page loads, locate all the div, span, p, h, with color #512a69 and change it to #ef7e8e.
Is it possible?
Thanks.
Here is a solution which I'll explain step-by-step.
First, call colorReplace("#512a69", "#ef7e8e");. The first value is the target color, and the second is the replacement color.
Inside it, $('*').map(function(i, el) { will select all tags in the DOM tree. For each element, its getComputedStyle(el) styles array is returned. You can customize the selector for faster processing (e.g. $('div').map(function(i, el)) {).
All style attributes containing "color" (e.g. background-color, -moz-outline-color, etc.), it will be checked if the color value is equal to your target color. If so, it will be replaced with the target color.
Colors are returned like rgba(0,0,0,0) or rgb(0,0,0), not like #FFFFFF, so a quick conversion is done from rgb to hex for the comparison. That uses the internal rgb2hex() function.
I hope this is what you are looking for.
function colorReplace(findHexColor, replaceWith) {
// Convert rgb color strings to hex
// REF: https://stackoverflow.com/a/3627747/1938889
function rgb2hex(rgb) {
if (/^#[0-9A-F]{6}$/i.test(rgb)) return rgb;
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
// Select and run a map function on every tag
$('*').map(function(i, el) {
// Get the computed styles of each tag
var styles = window.getComputedStyle(el);
// Go through each computed style and search for "color"
Object.keys(styles).reduce(function(acc, k) {
var name = styles[k];
var value = styles.getPropertyValue(name);
if (value !== null && name.indexOf("color") >= 0) {
// Convert the rgb color to hex and compare with the target color
if (value.indexOf("rgb(") >= 0 && rgb2hex(value) === findHexColor) {
// Replace the color on this found color attribute
$(el).css(name, replaceWith);
}
}
});
});
}
// Call like this for each color attribute you want to replace
colorReplace("#512a69", "#ef7e8e");
Source: https://stackoverflow.com/a/30724171/1136132

What code will force a reselection in TinyMCE 4.6?

I'm having a problem with TinyMCE 4.6. I've implemented a custom button that bumps the font size of selected text:
ed.addButton('finc', {
image: '/tinymce/plugins/zackel/button_images/big.png',
title: '+ font size',
id : 'finc',
onclick:function(editor,url) {
console.log("************ In finc: ", ed);
var delta;
var currentFontSize = new Number($(ed.selection.getNode()).css('font-size').replace('px',''));
console.log("************ finc: currentFontSize = " + currentFontSize);
var node = ed.selection.getNode(); // <======= LINE 565
var nodeName = node.nodeName; // for example 'DIV ' or 'P'
console.log("************ finc: node is ", node, "nodeName = " + nodeName);
if (currentFontSize >= 24) {
delta = 2;
}
else {
delta = 1;
}
currentFontSize = currentFontSize + delta;
console.log("************ finc: New font size = " + currentFontSize);
ed.formatter.register('incfont', {
inline : 'span',
styles : {'font-size' : currentFontSize + 'px'}
});
ed.formatter.apply('incfont');
console.log("********** finc: posting to val box " + currentFontSize);
$("div#px_val button").text(currentFontSize + 'px'); // show value in value box
}
});
If the text is initially in a P the button works fine but puts the text into a span inside the P when it's done. If I then just hit the button again it fails because the node it brings back on line 565 is still the P, which still has the original font size. So if he initial font size is 16, it goes to 17 but then every bump after that stays at 17. If I deselect the text after bumping it and reselect it, line 565 gets the span and the bumps work every time.
How can I force a reselection from my code, so 565 finds the span the second time instead of the P, without me deselecting and reselecting the text?
Thanks
It seems to me that I understand you problem, but i believe that the text re-selection should not happen every time you apply the formatting - just only in the case TinyMCE is adding the new SPAN.
Here is my proposal:
var delta;
var currentFontSize = new Number($(ed.selection.getNode()).css('font-size').replace('px',''));
var node = ed.selection.getNode();
var nodeName = node.nodeName; // for example 'DIV ' or 'P'
if (currentFontSize >= 24) {
delta = 2;
}
else {
delta = 1;
}
currentFontSize = currentFontSize + delta;
ed.formatter.register('incfont', {
inline : 'span',
styles : {'font-size' : currentFontSize + 'px'}
});
var cnt = ed.selection.getContent({format : 'html'});
var lenBefore = $(cnt).length;
ed.formatter.apply('incfont');
var cnt = ed.selection.getContent({format : 'html'});
var lenAfter = $(cnt).length;
if(lenAfter > lenBefore) {
var newText = ed.selection.selectedRange.startContainer;
var rng = ed.dom.createRng();
rng.setStart(newText, 0);
rng.setEnd(newText, newText.nodeValue.length);
ed.selection.setRng(rng);
ed.nodeChanged();
}
Explanation:
when you apply the formatter for the first time, TinyMCE is adding the SPAN and you will find the new selection inside the ed.selection.selectedRange.startContainer node of type text. This is the same as the first child node of type text of the newly inserted SPAN. For subsequent actions, there shall be no need to do any re-selection.
Moreover, IMHO i feel somehow unusual to change the font size in mouse click, i would prefer a standard plugin button which works only with a already existing text selection (but this is up to you):
Of course, the main question of the re-selection is solved, and the plugin will work repeatedly with subsequent mouse clicks also by using a plugin button.
Just in case, as said before, you may also check at the very top if there is any content:
var hasContent = ed.selection.getContent({format : 'text'}.length > 0);
if(!hasContent) return;
So i believe the whole stuff should do the job but anyway, i feel there is still room for some improvements, for example if you need also to reduce the font size, and thus you will also need to delete the already existing - but no longer necessary - SPAN which contain the formatting.

Angular Ui-Grid: Highlight entire row with pinned column

I'm using ui-grid and the first column have to be pinned on the left. When the user hovers on one row, I want to highlight the entire row, which is the logical thing to do.
The problem is that ui-grid creates two distinct elements, one for the pinned column and the other on for the "regular" ones. So I don't know how to highlight the entire row at once, and solutions with CSS don't work.
.ui-grid-row:hover .ui-grid-cell {
background-color: red;
}
Plunker here: http://plnkr.co/edit/HPxrc68JNMqyp4G9xLFA?p=preview.
Do you know how to do that ? Ideally just with ui-grid settings and CSS.
Thanks!
I solved it!
I used a row template that grabs the row id, defines ng-mouseover and ng-mouseout functions that fills the background for all the cells in the row. For whatever reason I had to wrap the entire template in a div, simply adding something to the class of the template broke the entire table.
Content of the rowTemplate:
<div class="row-uid-{{row.uid}}">
<div ng-repeat="(colRenderIndex, col) in colContainer.renderedColumns track by col.uid"
ng-mouseover="grid.appScope.onRowHover(row.uid);"
ng-mouseout="grid.appScope.onRowOut(row.uid);"
ui-grid-one-bind-id-grid="rowRenderIndex + '-' + col.uid + '-cell'"
class="ui-grid-cell"
ng-class="{ 'ui-grid-row-header-cell': col.isRowHeader}"
role="{{col.isRowHeader ? 'rowheader' : 'gridcell'}}"
ui-grid-cell>
</div>
</div>
Added functions in the controller:
$scope.onRowHover = function (rowUid) {
_.each(angular.element('.row-uid-' + rowUid + ' .ui-grid-cell-contents'), function (row) {
angular.element(row).css('background-color', 'red');
});
};
$scope.onRowOut = function (rowUid) {
_.each(angular.element('.row-uid-' + rowUid + ' .ui-grid-cell-contents'), function (row) {
angular.element(row).css('background-color', 'white');
});
};

how to bind image in Listbox with data

Hi all i have one problem in list box in which i would like to bind image with data on condition . Like when user is active i like to display different image , when he is not working like to display different image . this time i am displaying name in different color on his status like not working then in Red color, working with green color.
My html is
<asp:ListBox ID="ddlDriver" Width="100%" AutoPostBack="true" OnSelectedIndexChanged="ddlDriver_SelectedIndexChanged"
runat="server" BackColor="White" Height="380px">
</asp:ListBox>
Code :
if (_driv.DriverStatus == 1)
{
ddlDriver.Items[i].Text = ddlDriver.Items[i].Value + "-" + ddlDriver.Items[i].Text + " " + OrderTota;
ddlDriver.Items[i].Attributes.CssStyle.Add(HtmlTextWriterStyle.Color, "red");
}
else if (_driv.DriverStatus == 2)
{
ddlDriver.Items[i].Text = ddlDriver.Items[i].Value + "-" + ddlDriver.Items[i].Text + " " + OrderTota;
ddlDriver.Items[i].Attributes.CssStyle.Add(HtmlTextWriterStyle.Color, "green");
}
please help me about this issue.
You may define two css classes with appropriate background-image property and conditionally set class on items in code-behind

Resources