There is a way to change a background or text color to a row in PrimeReact Datatable that is using rowClassName={rowClass} where rowClass is a function that allows returning a class configured in the CSS file.
but... what if I want to choose an arbitrary color? for example, one fetched from a database in #RRGGBB format?
Reading de documentation I can't see a way to call a function to return the style string. Another way could be, creating dynamically the class name, for example...
class RRGGBB for a selected color, define this class with background: #RRGGBB and let rowClassName={rowClass} call rowClass function returning this dynamically created class...
I have this approach, but don't work:
const mycolor = "#00ff00";
function createStyle() {
const style = document.createElement("style");
// add CSS styles
style.innerHTML = `
.lulu {
color: white;
background-color: ${mycolor};
}
`;
// append the style to the DOM in <head> section
document.head.appendChild(style);
}
createStyle();
const rowClass = (data) => {
return {
"lulu": data.category === "Accessories"
};
};
.....
<DataTable value={products} rowClassName={rowClass}>
this code is a modified version of the sample code by prime react, here, in sandbox:
https://codesandbox.io/s/o6k1n
thanks!
I have solved it...
What I did is to create a dynamic css, and then use it:
function createStyle(color) {
var style = document.getElementsByTagName("style");
var colortag = color.replace("#", "mycolor");
//Assuming there is a style section in the head
var pos = style[0].innerHTML.indexOf(colortag);
if(pos<0)
style[1].innerHTML += "."+colortag+`
{
color: ${color}!important;
}
`;
return colortag;
const rowClass = (data) => {
var colortag;
if (data.COLOR!=undefined)
colortag=createStyle(data.COLOR);
return { [colortag]: ata.COLOR!=undefined };
}
<DataTable ref={dt} value={Data} rowClassName={rowClass}>
<column>......</column>
</DataTable>
With this code, if in the data there is a field called COLOR:"#RRGGBB" then it will create a style with this color and use it as text color. The same can be applied to background or whatever
Related
Brush extent needs to be changed only from a dropdown as shown here: https://jsfiddle.net/dani2011/67jopfj8/3/
Need to disable brush extending by:
1) Extending an existing brush using the handles/resize-area of the brush
Gray circles are the handels:
2) Dragging a new brush by clicking on the brush background, where the
haircross cursor appears.
JavaScript file
Removed the handles of the brush:
timeSlider.on('preRedraw',function (chart)
{
var timesliderSVG = d3.select("#bitrate-timeSlider-chart").selectAll("g.brush").selectAll("g.resize").selectAll("*").data(data[0]).exit().remove();})
If using css instead:
#bitrate-timeSlider-chart g.resize {
display:none;
visibility:hidden;
Now it looks like this:
.
The rect and the path elements inside "resize e","resize w" were removed:
However,the "resize e", "resize w" for extanding the brush still exist:
g.resize.e and g.resize.w dimesions are 0*0:
Furthurmore,after deleting "resize e","resize w" in the "developer tools/elements" in chrome,they reappear after moving the brush.
Tried to remove the resize-area in brushstart,brush,brushend:
timeSlider.on('renderlet', function (chart) {
var brushg = d3.select("#bitrate-timeSlider-chart").selectAll("g.brush");
var resizeg = brushg.selectAll("g.resize").selectAll("*").data(data[0]);
var timesliderSVG4 =
brushg.on("brushstart", function () {resizeg.exit().remove()}).on("brush", function () { resizeg.exit().remove() }).on("brushend", function () {resizeg.exit().remove() })
dc.js file
Tried to change setHandlePaths,resizeHandlePath:
1)
Remarked the _chart.setHandlePaths(gBrush):
_chart.renderBrush = function (g) {....
// _chart.setHandlePaths(gBrush);
...}
2) Changed _chart.setHandlePaths = function (gBrush) for example by removing the gbrush.path:
// gBrush.selectAll('.resize path').exit().remove();
3) Remarked/changed _chart.resizeHandlePath = function (d) {...}.
d3.js file
1) Remarked/changed resize such as:
mode: "move" //mode: "resize" ,
var resize = g.selectAll(".resize").data(resizes[0], d3_identity);
Using resizes[0] disable the brush rendering on the background but still can re-extend the existing brush
2) Remarked/changed d3_svg_brushResizes
3) In d3.svg.brush = function():
a) Added .style("display","none"):
background.enter().append("rect").attr("class", "background").style("visibility", "hidden").style("display", "none").style("cursor", "none");
b) background.exit().remove();
The cursor now is "pointer" instead of "haircross" extending the brush to a full width
c) d3_svg_brushCursor disabled makes the whole brush disappear
4) Changed the pointer-events as specified here: https://developer.mozilla.org/en/docs/Web/CSS/pointer-events
5) console.log in different places to track the different brush events:
function d3_event_dragSuppress(node) {
console.log("here2 ");
}
if (d3_event_dragSelect) {
console.log("here3 d3_event_dragSelect");
...
}
return function (suppressClick) {
console.log("suppressClick1");
...
var off = function () {
console.log("suppressClick2");
...
w.on(click, function () {
console.log("suppressClick3")
...
function d3_mousePoint(container, e) {
console.log("d3_mousePoint1")
...
if (svg.createSVGPoint) {
console.log("createSVGPoint");
...
if (window.scrollX || window.scrollY) {
console.log("createSVGPoint1");
svg = d3.select("body").append("svg").style({
...
function dragstart(id, position, subject, move, end) {
console.log("dragstart")
...
function moved() {
console.log("moved ");
console.log("transition1");
...
if (d3.event.changedTouches) {
console.log("brushstart1");
...
} else {
console.log("brushstart2");
..
if (dragging) {
console.log("dragging4");
....
if (d3.event.keyCode == 32) {
if (!dragging) {
console.log("notdragging1");
...
function brushmove() {
console.log("brushmove");
...
if (!dragging) {
console.log("brushmove!dragging");
if (d3.event.altKey) {
console.log("brushmove!dragging1");
...
if (resizingX && move1(point, x, 0)) {
console.log("resizeXMove1");
...
if (resizingY && move1(point, y, 1)) {
console.log("resizeYMove1");
...
if (moved) {
console.log("moved");
...
}
function move1(point, scale, i) {
if (dragging) {
console.log("dragging1");
...
if (dragging) {
console.log("dragging2");
...
} else {
console.log("dragging10");
...
if (extent[0] != min || extent[1] != max) {
console.log("dragging11");
if (i) console.log("dragging12"); yExtentDomain = null;
console.log("dragging13");
function brushend() {
console.log("brushend");
...
The two changes that seemed to get closest to the needed result are in d3.js:
1) Using resizes[0] disables the brush rendering on the background but still can re-extend the existing brush
var resize = g.selectAll(".resize").data(resizes[0], d3_identity);
2) Removing the brush's background changes the cursor to "pointer" instead of "haircross",extending the brush to a full width only when clicking on the graph
`background.exit().remove();`
Any help would be very appreciated!
This is from the accepted answer in Disable d3 brush resize, as suggested by #altocumulus. I didn't see a response from #Dani on this idea in particular, but thought I'd go ahead and try it, since I've seen other people try it in the past. (Probably on the dc.js users group.)
It looks a little twitchy, because d3.js will draw the brush at the new extent, and then a moment later we reset the extent to what we want, but functionally it seems to do what we want.
In dc.js the function that handles brush "rounding" is coordinateGridMixin.extendBrush:
_chart.extendBrush = function () {
var extent = _brush.extent();
if (_chart.round()) {
extent[0] = extent.map(_chart.round())[0];
extent[1] = extent.map(_chart.round())[1];
_g.select('.brush')
.call(_brush.extent(extent));
}
return extent;
};
Notice that it's following the same pattern as Lars' answer. Well, this is sort of like rounding, right? Let's override it.
First, let's store the current number of hours when it's set through the dropdown:
var graphSpan;
function addHours(amountHours) {
graphSpan = amountHours;
// ...
Next let's override coordinateGridMixin.extendBrush:
timeSlider.extendBrush = function() {
var extent = timeSlider.brush().extent();
if(graphSpan) {
extent[1] = moment(extent[0]).add(graphSpan, 'hours');
}
return extent;
}
We just replace the function. If we needed to reuse the old implementation in our function, we could use dc.override.
If graphSpan has been set, we add that amount to the beginning to get the end. If it's not set, we allow the user to specify the brush width - you'd need to default the graphSpan and the select widget if you wanted that part to work automatically.
Well, let's admit it: it's very twitchy, but it works:
EDIT: Got rid of the twitch! The problem was that dc.js was setting the brush extent asynchronously after a little while (in response to the filter event). If we also set it during extentBrush then it never shows the wrong extent:
timeSlider.extendBrush = function() {
var extent = timeSlider.brush().extent();
if(graphSpan) {
extent[1] = moment(extent[0]).add(graphSpan, 'hours');
timeSlider.brush().extent(extent);
}
return extent;
}
https://jsfiddle.net/gordonwoodhull/xdo05chk/1/
What worked for me:
in d3:
disable resize handles
d3.selectAll('.brush>.handle').remove();
disable crosshair
d3.selectAll('.brush>.overlay').remove();
or
in css:
disable resize handles -
.handle {
pointer-events: none;
}
disable crosshair -
.overlay {
pointer-events: none;
}
I'm trying to make a combined map/chart visualization work. I want to be able to mouseover/select a country on the map, and have an effect applied not only to the country but also to the line on the chart representing the country's data (of whatever, let's say population growth over the last decade).
In the done section of the map initialization, I use a callback highlightMap and pass in the countryName. This in theory would also be called by the chart when I mouseover that.
Questions:
1) In highlightMap my attempt to get the country element and change it's border width doesn't work. What's the right way to grab a map subunit and apply an effect to it?
2) Is this the right way to do this in general?
var map;
function setupMap(mouseoverCallback, mouseoutCallback) {
var width = mapWidth;
var height = mapHeight;
map = new Datamap({
element: document.getElementById(mapContainerDiv),
projection: 'mercator',
// responsive: true,
width: width,
height: height,
fills: {
defaultFill: "#ffffff"
},
geographyConfig: {
borderColor: '#000000',
},
data: {},
done: function(datamap) {
datamap.svg.selectAll('.datamaps-subunit').on('mouseover', function(geography) {
var countryName = geography.properties.name;
highlightMap(countryName);
});
datamap.svg.selectAll('.datamaps-subunit').on('mouseout', function(geography) {
var countryName = geography.properties.name;
highlightMap(countryName);
});
}
});
}
function highlightMap(name, highlight) {
var code = country2Code[name];
if (highlight) {
var countryElement = map.svg.select("#datamaps-subunit "+code);
countryElement.attr('stroke-width', 10); // Change border of country to something nutty
// reset color
...
}
}
Sort out your selectors:
.datamaps-subunit is not the same as #datamaps-subunit
Moreover, each country geometry has an additional class (like "ESP" or "USA") with the country code
To later select the country you just use map.svg.selectAll(".datamaps-subunit.ESP") or map.svg.selectAll(".datamaps-subunit.USA")
Notice there is no space between class names, as they are applied to the same SVG element
Use select() or selectAll() depending on how many elements you expect to get (one or possibly many)
EDIT: A much easier option would be to simply add this rule to your CSS sheet:
.datamaps-subunit:hover {
stroke-width: 2px;
}
I'm trying to add an event for all elements with "p" tag.
But instead of adding an event script colors all links in red
<script>
//create links
var code = ""
for (i=0;i<10;i++){
code += "<p><a href='#'>Link " + i + "</a></p>"
}
document.getElementById('links').innerHTML = code;
//add Events
for(i=0;i<document.getElementsByTagName("p").length;i++){
document.getElementsByTagName("p")[i].onmouseover = document.getElementsByTagName("p")[i].childNodes[0].style.color="green"
document.getElementsByTagName("p")[i].onmouseout = document.getElementsByTagName("p")[i].childNodes[0].style.color="red"
}
}
</script>
There is My code
Event handlers need to be functions. So you need something like this:
document.getElementsByTagName("p")[i].onmouseover = function() {
// You don't want to use i in a function in a loop since i will
// be different by the time the function gets called
// this is document.getElementsByTagName("p")[i]
this.childNodes[0].style.color="green"
}
You should probably also create the nodeList for the <p> tags outside of the loop so you're not traversing the DOM each time.
var paras = document.getElementsByTagName('p');
for(i=0;i<paras.length;i++){
paras[i].onmouseover = function() { /* */ };
paras[i].onmouseout = function() { /* */ };
}
Is there an easy way to add a simple border to an image?
I'm loading in image thumbs, and would like to add a border at runtime, instead of having to edit all the thumbs.
I'm using Spark Image.
Thanks!
EDIT:
I need to add a 1 px white border around these thumbs. I set the size of the tumbs to be 90x90, to make them fit if they are either horisontal or vertical, but the actual images in my example scales down to 90x51 (this is not fixed, only 90x90 as a maximum is fixed)
This is my code for adding thumbNails to a TileGroup (loading the gallery from an xml file):
private function loadPopUpThumbs():void{
if(curThumbImg <= totThumbImg){
var thumbImg:Image = new Image();
var _loader:Loader = new Loader();
var imageNr:int = curThumbImg;
var thumbContainer:BorderContainer = new BorderContainer();
_loader.contentLoaderInfo.addEventListener(Event.COMPLETE,function(e:Event):void{
thumbImg.source = e.currentTarget.content;
popUpImgGroup.addElement(thumbImg);
thumbImg.width = 90;
thumbImg.height = 90;
thumbImg.scaleMode = "letterbox";
thumbImg.verticalAlign = "bottom";
thumbImg.smooth = true;
thumbImg.id = "thumbImg" + imageNr;
//thumbImg.drawRoundRect(0,0,thumbImg.width,thumbImg.height, null, 0xffffff);
thumbImg.addEventListener(MouseEvent.CLICK, function(evt:MouseEvent):void{
popUpThumbClicked(imageNr.toString());
});
trace("Thumb added: " + popUpXMLList.(attribute('nr')==imageNr.toString()).#thumbURL);
curThumbImg++;
loadPopUpThumbs();
});
_loader.load(new URLRequest(encodeURI(popUpXMLList.(attribute('nr')==imageNr.toString()).#thumbURL)));
}else{
trace("DONE Adding thubs!!!");
}
}
Also: Would it be possible to add a linebreak in the items added to the TileGroup?
In my XML file I've defined a group attribute, so that I'm able to devide the images into groups. If I click a image from one group, I can skip next/prev within that group, but not to the next group. Is there any way for me to insert a linebreak to my TileGroup, so that I can listen for when the prevGroup != curGroup, and then add in some sort of spacing before continuing adding the next thumbs? All I need is a way to skip a line in the tileGroup :)
Thanks!
You can create new custom Image Class, extends spark Image. Very simple and clean. And set border size and color with css. See example:
package classes
{
import flash.display.CapsStyle;
import flash.display.JointStyle;
import flash.display.LineScaleMode;
import spark.components.Image;
public class ImageBorder extends Image
{
public function ImageBorder()
{
super();
}
override protected function updateDisplayList(unscaledWidth:Number, unscaledHeight:Number):void
{
super.updateDisplayList(unscaledWidth, unscaledHeight);
if (imageDisplay && imageDisplay.bitmapData)
{
var borderSize:Number = getStyle("borderSize") || 0;
var borderColor:Number = getStyle("borderColor") || 0xffffff;
var half:Number = borderSize/2;
imageDisplay.left = imageDisplay.top = imageDisplay.right = imageDisplay.bottom = borderSize;
graphics.clear();
graphics.lineStyle(borderSize, borderColor, 1, false, LineScaleMode.NONE, CapsStyle.NONE, JointStyle.MITER);
graphics.moveTo(0, half);
graphics.lineTo(unscaledWidth -half, half);
graphics.lineTo(unscaledWidth - half, unscaledHeight-half);
graphics.lineTo(half, unscaledHeight-half);
graphics.lineTo(half, half);
}
}
}
}
In application use with css:
<fx:Style>
#namespace s "library://ns.adobe.com/flex/spark";
#namespace mx "library://ns.adobe.com/flex/mx";
#namespace classes "classes.*";
classes|ImageBorder
{
borderSize : 10;
borderColor : "0xff00ff";
}
</fx:Style>
<classes:ImageBorder source=" your source url " />
Spark image is a SkinnableComponent.
You can create your custom skin that supports borders in any
convenient way, like styles or properties.
Or you can set that
skin if you want to see border or remove it if you don't want
Or you can put it inside BorderContainer, and set borderVisible to
true when you want to see the border.
I change the color of some cells in the gridComplete: function(){ . This override the hover or selected color. I want to make the hover and selected colors the highest level. i.e. if I selected a colored row, it changes to the selected color.
I suppose your question continues your previous question about the the color of the some cells. I created another demo which code is longer as my previous example from my answer to your previous question.
The main problem with the setting of the color of the cell (<td> element) is that the class of cell has of course higher priority as the classes of row because by the definition of the row classes was no "!important" attribute used. So to be able to make the selected of hovered cell be exactly like other standard cells one have to remove the cell class which changes its color. After "unselecting" or "unhovering" the corresponding row one should restore the removed cell class (the 'ui-state-error ui-state-error-text' classes). I implemented this behavior with the following code:
var grid = $("#list");
var saveErrorStateInData = function(ptr) {
var redCells = $("td.ui-state-error",ptr);
if (redCells.length > 0) {
var errorCells=[];
$.each(redCells,function(index, value) {
errorCells.push(value);
$(value).removeClass("ui-state-error ui-state-error-text");
});
$(ptr).data('errorCells',errorCells);
}
};
var restoreErrorStateFromData = function(ptr) {
var errorCells = $(ptr).data('errorCells');
if (errorCells && typeof errorCells.length !== "undefined"
&& errorCells.length>0) {
$.each(errorCells,function(index, value) {
$(value).addClass("ui-state-error ui-state-error-text");
});
}
};
grid.jqGrid({
// all jqGrid parameters
beforeSelectRow: function(rowid, e) {
var selrowid = $(this).getGridParam('selrow');
restoreErrorStateFromData($("#"+selrowid)[0]);
ptr = $(e.target).closest("tr.jqgrow");
saveErrorStateInData(ptr);
return true;
}
}).bind('mouseover',function(e) {
var ptr = $(e.target).closest("tr.jqgrow");
if($(ptr).attr("class") !== "subgrid") {
$(ptr).addClass("ui-state-hover");
saveErrorStateInData(ptr);
}
return false;
}).bind('mouseout',function(e) {
var ptr = $(e.target).closest("tr.jqgrow");
var selrowid = grid.getGridParam('selrow');
$(ptr).removeClass("ui-state-hover");
if (ptr.length === 1 && ptr[0].id !== selrowid) {
restoreErrorStateFromData(ptr);
}
return false;
});
On the demo you will see how all this work.
Sorry for answering this old question, but I hope someone else might find it useful. After searching quite a while for a solution, I came up with this:
Add a dummy class (with no styles) to the column using the jqGrid colmodel option 'classes'.
Add a style setting the background using a selector like this:
tr.jqgrow:not(.ui-state-hover):not(.ui-state-highlight) td.mydummycol {
background-color: #ffd !important;
}
This way the background is only applied if the row is not selected or in the hover state.