Permanently Change CSS Property with JavaScript/D3Js/Jquery

Targeting pseudo elements with d3 - is it possible?

It is not possible the way you're trying to do it.

The querySelector methods, on which D3's select functions are based, never return results for pseudo-element selectors.

Furthermore, the D3 style method works by setting inline style attributes on the selected elements. You cannot set inline styles for pseudo-elements, so setting the style attribute on the parent element won't work either.

What you could do is select the parent elements, give them a class name, and then use CSS stylesheet rules to target the :before/:after pseudo-elements for objects of that class. If you would need to dynamically create the CSS rules, see this Q&A.

However, it is probably easiest to just create empty <span> or <div> child elements, and style those instead.

How do I create a style sheet for an SVG element?

As @RobertLongson points out in the comments, the problem is that the SVG specs define a svg:style element interface, but it doesn't implement the CSS OM interfaces associated with a stylesheet's owner element.

Here are a couple work-around approaches (while waiting for the SVG 2 specs to implement the latest CSS OM specs):

  1. Use an (X)HTML style element. If your SVG code is inline within an (X)HTML document, then the HTML <style> element can be used to style the SVG. Just make sure that you either create the style element in the default namespace or explicitly create it in the XHTML namespace, so that you get an instance of HTMLStyleElement, not SVGStyleElement.

    Add the newly-created HTMLStyleElement to the head of your document, and the CSS stylesheet object will be created for you:

    var hs = document.createElement("style");
    hs.type = "text/css";
    document.head.insertBefore(hs, null);
    hs.sheet.insertRule("circle{fill:red;}", 0);

    This answer goes into more detail about dynamically creating stylesheets in HTML, including a working example.

  2. (Theoretically) Use an xml-stylesheet processing instruction. If your SVG code is in a stand-alone SVG file, then you can use XML processing instructions to link external stylesheets. The processing instruction node provides access to the stylesheet object.

    However, unlike a <style> element, which can be empty, the processing instruction node must link to a file, or the browser will never initialize the stylesheet object. I tried to get around that by defining the external file as an empty data URI of the correct MIME type. It usually, but not consistently, works in FF/Chrome when run from the console, but not from an embedded script. In Chrome, the sheet property is always null, the same way Chrome treats cross-domain stylesheets; Firefox gives an explicit security error. I assume it won't work at all in IE, which doesn't like non-image data URI files.

    var xs = document.createProcessingInstruction(
    "xml-stylesheet",
    "href='data:text/css,' type='text/css'");
    document.insertBefore(xs, document.rootElement);
    xs.sheet.insertRule("circle{fill:blue;}", 0);

    You weren't clear about why you were trying to dynamically create a style sheet. If the intent is to actually link to a valid stylesheet on a same-domain server, then the security problems wouldn't be an issue; the problem is that data URIs are treated as cross-origin.

  3. Use a svg:style element, but then access the stylesheet object using document.styleSheets (from the comments to the other answer, it seems this is what you're already doing). Cycle through all the stylesheets until you find the one that has your style element as the owner node:

    var ss = document.createElementNS("http://www.w3.org/2000/svg", "style");
    svgElement.appendChild(ss);
    var sheets = document.styleSheets,
    sheet;
    for(var i=0, length=sheets.length; i<length; i++){
    sheet=sheets.item(i);
    if (sheet.ownerNode == ss) break;
    }
    sheet.insertRule("circle{fill:green;}", 0);

    This should work regardless of whether or not your SVG is in a stand-alone file.

how to remove css property using javascript?

You have two options:

OPTION 1:

You can use removeProperty method. It will remove a style from an element.

el.style.removeProperty('zoom');

OPTION 2:

You can set it to the default value:

el.style.zoom = "";

The effective zoom will now be whatever follows from the definitions set in the stylesheets (through link and style tags). So this syntax will only modify the local style of this element.

D3.js HTML table from JSON file-- How to create empty values so there aren't missing td elements?

I needed to take a different approach to creating the table. This stackoverflow post was extremely helpful. Then I restructured my JSON to fit, so that there were not separate object properties for "year" and "value" but that they were married-- where the former value for year became the key. So for instance, this:

    {
"year": 1980,
"value": 0.23
}

became this:

    {
"1980": 0.23
}

Here's a new plunker that shows the code working correctly, and the full code is also below:

    <!DOCTYPE html>
<html>
<head>
<style>
body{
font-family:Arial, sans-serif;
font-size:14px;
}
table{
border-spacing:0;
padding:0;
}
#buildcontent table#years td{
width:20px;
padding-left:5px;
padding-right:5px;
}
table#years td{
border-top:1px solid #ddd;
border-bottom:0px;
font-weight:bold;
padding-left:5px;
padding-top:3px;
height:18px;
}
th{
text-align:left;
font-weight:normal !important;
border-top:1px solid #ddd;
border-left:1px solid #ddd;
border-bottom:1px solid #ddd;
height:25px;
padding-left:5px;
width: 50px;
font-weight:bold !important;
}
td{
border:1px solid #ddd;
width:20px;
height:25px;
padding-left:5px;
}
tr.row-odd,
.row-odd{
background: #eee;
}
</style>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="//code.jquery.com/jquery-1.10.2.js"></script>
</head>
<body>
<div id="buildcontent">
<table>
<thead id="years">
</thead>
<tbody id="countries">
</tbody>
</table>
</div>
<script>

d3.json("data.json", function(json) {
json.forEach(function(d){
d.value = Math.round((+d.value + 0.00001) * 1000) / 1000;
});

var newData = [],
countries = {};
json.forEach(function (d) {
var country = countries[d.country];
if (!country) {
newData.push(country = countries[d.country] = {});
}
country[d.year] = d.value,
countries[d.country].Country = d.country;
});

// add years
var nestyr = d3.nest()
.key(function(d) { return d.year; })
.sortKeys(d3.ascending)
.map(json);

var yearstring = Object.keys(nestyr);
yearstring.unshift("Country");

function tabulate(newData, columns) {
var table = d3.select('body').append('table')
var thead = table.append('thead')
var tbody = table.append('tbody');

// append the header row
thead.append('tr')
.selectAll('th')
.data(columns).enter()
.append('th')
.text(function (column) { return column; });

// create a row for each object in the data
var rows = tbody.selectAll('tr')
.data(newData)
.enter()
.append('tr');

// add stripes to the table
rows.attr("class", function(d, i){ if (i++ % 2 === 0){return 'row-even'}else {return 'row-odd'}});

// create a cell in each row for each column
var cells = rows.selectAll('td')
.data(function (row) {
return columns.map(function (column) {
return {column: column, value: row[column]};
});
})
.enter()
.append('td')
.attr("class", function(d){ return d.year; })
.text(function (d) { return d.value; });

return table;
}

// render the table(s)
tabulate(newData, yearstring);

});

</script>
</body>
</html>

How can I remove or replace SVG content?

Here is the solution:

d3.select("svg").remove();

This is a remove function provided by D3.js.



Related Topics



Leave a reply



Submit