This works just fine:
d3.selectAll('ul li')
.style('background', 'red');
However, this doesn't do anything:
d3.selectAll('ul li:before')
.style('background', 'red');
The selection returned by d3.selectAll('ul li:before') is empty, even though the :before elements do exist, and have some existing CSS styling.
Is it possible to target pseudo elements with d3?
And if it is, a quick follow up question: How would I target all the :before pseudo-elements directly on (ie, not within) a particular selection?
Eg:
var listItems = d3.selectAll('ul li');
var beforeElements = listItems.selectAll('&:before'); // SASS-style selector obviously won't work here
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.
Related
this is somewhat related to my previous post where I learned a bit more about actions.
I have been trying to figure out how to work with this nifty feature but I seem to be a bit stuck in the past few hours.
In my Component I create an SVG viewbox like so:
<svg id="pitch" viewBox={`0 0 ${width} ${height}`} use:foo>
</svg>
then drawPitch is this function:
function foo(node) {
// the node has been mounted in the DOM
let g = node.append('h1');
g.text("This is the text I'd like to render to check that it works");
return {
destroy() {
// the node has been removed from the DOM
}
};
}
From what I've understood in the docs, the use:foo will pass the calling node to foo, so I thought directly appending svg elements to it should work.
Do I need to update it somehow?
Here is a repl with reproducible code.
I get the following error:
Missing "./types/runtime/internal/keyed_each.js" export in "svelte" package
Thank you!
I would expect the code in foo to start with d3.select(node), and everything to work based off that. Otherwise the DOM tree generated by d3 will not be connected to your document at all. Alternatively the resulting element (selection.node()) has to be appended to node at some point.
The error sounds highly unrelated and probably would require more context.
Note: You cannot add HTML directly to SVGs, SVGs are for canvas-like vector graphics, not document layouts. If you want to insert text, use the <text> element.
With Ckeditor 4x, when you add custom styles, you cannot use the "Remove format" button it not remove the style (class).
It seem to be working good only when use the default styles.
There are a couple of things to explain here because of design decisions taken in the past it is not as easy as it seems.
By default only inline styles are removed with RemoveFormat.
In order to remove block styles applied by the Styles drop-down, you need to unselect them in that drop-down (it works in toggle mode). You will than stay with a raw tag like H1 which you can change to another tag like P with the help of the Format drop-down. It has to be done in that order.
It seems the best solution would be to overwrite the addRemoveFormatFilter method. Let's say for example that you want to remove format only from h1-h3:
var editor = CKEDITOR.replace('textarea_id');
editor.on( 'pluginsLoaded', function( ev ) {
editor.addRemoveFormatFilter( function( element ) {
return element.is( 'h3' ) || element.is( 'h1' ) || element.is( 'h2' );
});
});
Of course you can use more advanced code here and not just a simple check if something is a particular element or not. You could for example use the checkElementRemovable method to check if a particular element matches a particular style.
Please note that it is necessary to select the whole block element to remove its format. In some cases e.g. a header holding a floated image it might be necessary to select this element using the element's path because it is hard to select it using the mouse.
I want to apply the ckeditor inline editing to all elements with a specific attribute.
The problem is that its only applying to the very first element with the attribute, and not the rest.
How can i apply the ckeditor inline text editing to all elements with a specific attribute?
$(".edit-element").ckeditor();
PS: im using ckeditor on elements that have contenteditable="true" and not textareas.
How about converting it to use .each? You can then also check the amount of elements you are targeting very easily (see comment);
$(".edit-element").each(function() {
// Log element with something like console.log(this);
$(this).ckeditor();
});
I tried this the first time and it didnt work. this time i noticed it was sending out this error
Uncaught Error: The specified element mode is not supported on element: "a".
and so I enabled the editor to work on "a" tags and span by adding this
CKEDITOR.dtd.$editable.span = 1
CKEDITOR.dtd.$editable.a = 1
If the source of something I write in my CKEDITOR looks like this:
This is my text. <strong>This part is bold.</strong> This part isn't.
I can highlight the bolded part and unbold it by pressing CTRL+B. However, if I add a class to that strong tag (due to another plugin I'm working on), I can only unbold clean strong tags - no attributes, styles, or classes. For example, consider this scenario:
This is my text. <strong>This part is bold.</strong> This part isn't. <strong class="whatever">This part is bolded AND has a custom class.</strong>
Only the first bolded segmented will be unbolded - the 2nd is pretty much stuck as is until I remove the ".whatever" class. Is there any way to get it to ignore strong tags with classes, and just do them regardless of what other attributes they have? I'm guessing it has to do with that "Advanced Content Filter" or something, but I can't figure out what.
After much hairpulling, I (think) I have the answer. In the CKEDITOR style definition, an applied style (ex, a strong tag) needs to have all of its attributes parsed through the content filter. If an attribute that is not dealt with by this filter remains when it comes time to actually remove the textNode from the style tags and replace it back into the parent element, the tags (and thus the style) will NOT be removed if there are any attributes remaining on the element. There is a (very poorly) documented workaround to this: the alwaysRemoveElement property can be set to true on the style DEFINITION (why the definition, and not the style itself, I have no idea).
Long story short, a little snippet of code that will force the removal of all style tags, even if their attributes don't match exactly with the filter. Hopefully it doesn't cause bugs somewhere else...
//this = Your Editor Instance
this.data.editor.on( 'instanceReady', function(){
//Filter through the existing contentRules, looking for styleCommands
$.each(this.activeFilter.allowedContent, function(i,v) {
var name = v.featureName, command = this.commands[v.featureName];
if (name && command && command.contentForms && command.style) {
command.style._.definition.alwaysRemoveElement = true;
}
}.bind(this));
}.bind(this));
As the previous answer, just add this in the config:
CKEDITOR.config.coreStyles_bold : { element: 'strong', overrides: 'b' ,alwaysRemoveElement: true},
It was also difficult for me to find this workaround, in my case I was adding an id to the strong element.
Several of the reusable charts examples, such as the histogram, include the following:
// select the svg element, if it exists
var svg = d3.select(this).selectAll("svg").data([data]);
// append the svg element, if it doesn't exist
svg.enter().append("svg") ...
...where this is the current DOM element and data is the data that's been bound to it. As I understand it, this idiom allows a chart to be created the first time the chart function is called, but not 'recreated', if you like, following subsequent calls. However, could anyone explain this idiom in detail? For example:
Why is .selectAll("svg") used and not .select("svg")?
Why isn't .empty() used to check for an empty selection?
Can any single-element array be passed to .data()? (I assume the purpose of this array is simply to return the enter selection.)
Thanks in advance for any help.
When this is called the first time, there's no SVG and therefore the .enter() selection will contain the data passed to it. On subsequent calls, the .enter() selection will be empty and therefore nothing new added.
Concerning the specific questions:
.selectAll() returns an array which can then be matched to the array passed to .data().
.empty() could be used, but it's not necessary -- if the selection is empty, nothing happens. Checking .empty() would add an if statement and have exactly the same effect.
Yes. Have a look this tutorial for example for some more detail on selections.