How can I apply an external CSS class to a span created with dojo.create? - css

I'm creating a span in my web page with dojo.create, and need to apply CSS to it. I can see how to apply a style to it in the dojo reference, but I'd rather apply it via the external stylesheet (there's quite a few attributes I need to set and I'd rather not do it inline).
So given the example code below, how would I apply the CSS for the printSpan class?
var node = dojo.create("span", {innerHTML:_text, id:"printSpan", class:"printSpan"}, map);

You can write this in your external stylesheet:
.printSpan { color: red; }
This is called the class selector.
By the way, your code should be:
{ innerHTML : _text, id : "printSpan", "class" : "printSpan" }
Notice the colon was inside the "class" string, though it should be outside and printSpan is a different string.

Related

Applying dynamic styling to injected HTML in Angular 2

For an Angular project I'm working on, I'm injecting HTML into a <div> like so:
<div class="myClass" [innerHTML]="htmlToInsert"></div>
The htmlToInsert contains a variety of things, notably <a> tags. Previously we were styling all these tags like so:
.myClass ::ng-deep a {
color: #f00;
text-decoration: none;
}
And this worked fine. But now I need the color of these links to be dynamically generated during component initialization, based on data coming in from elsewhere. All of the dynamic styling I've seen in Angular requires you to apply things directly to the HTML tag, but we don't have them here to work with.
How can I apply dynamic styling to HTML that is also dynamically generated? Can I directly change the CSS class somehow? Would using a pipe be the correct approach here? Is there another method I don't know about? I could maybe refactor code if there is absolutely no other way of doing this.
So if you can't modify the innerHTML you are passing in, you can achieve this functionality with a custom directive. Essentially you would tag your div that contains your innerHTML with a custom directive. That directive then looks for any anchor tags in it and changes the color based on an input.
// component.html
<div anchorColor [color]="dynamicColor" [innerHTML]="htmlToInsert"></div>
// directive.ts
#Directive({selector: '[anchorColor]'})
export class AnchorColorDirective implements OnAfterViewInit {
#Input() color: string;
constructor(private el: ElementRef){
}
// afterViewInit lifecycle hook runs after DOM is rendered
ngAfterViewInit(){
// get anchor element
let anchorEl = this.el.nativeElement.querySelector('a');
// assign color
if(anchorEl){
anchorEl.style.color = this.color;
}
}
}
Here is a working plunkr https://plnkr.co/edit/QSYWSeJaoUflP94Cy4Hm?p=preview

Reading class names in a stylesheet

I have an HTML document that uses multiple style tags. One of those styles has the following content
<style id='pstyle'>
.p0010, .p0016, .p0022, .p0028, .p0032,
.p0034, .p0038, .p0042, .p0044, .p0046,
.p0048, .p0050, .p0052, .p0054, .p0056,
{
max-width:100%;
background-size:100%;
background-image: url('sprites.png');
}
</style>
document.styleSheets allows me to access the full set of stylesheets used by the document. From there - once I have grabbed the right stylesheet - I can use the cssRules array attribute to access the selectorText attribute of each contained style. However, I have been unable to figure out how to find the "right" style sheet. Whilst I can give the stylesheet an id this does not turn up as an attribute of the document.styleSheets[n] object.
I do a great deal of DOM manipulation but it is mostly with the visual elements in the document. I'd be much obliged to anyone who can tell me how I go about identifying the "right" stylesheet
A plain English version of the task
a. Find the style element - bearing in mind that there will be others - with the id pstyle
b. Read the class names defined therein and do whatever
I'm not sure to understand if you want to get the stylesheet associated with the <style> element, or if you want to retrieve the element from the stylesheet.
So here you'll get both :
// from the element
console.log(pstyle.sheet === document.styleSheets[2]);
// from the stylesheet
console.log(document.styleSheets[2].ownerNode === pstyle);
<style id='pstyle'>
</style>
note that in the snippet it's [2] because stacksnippet does inject stylesheets
And now to get the cssRules and selectorText, you just have to read it from the selected styleSheet:
var pstyle = document.getElementById('pstyle');
// from the element
console.log(pstyle.sheet.cssRules[0].selectorText);
// from the stylesheets
for(var sheet of document.styleSheets){
if(sheet.ownerNode === pstyle){
console.log(sheet.cssRules[0].selectorText);
}
}
<style id='pstyle'>
.p0010, .p0016, .p0022, .p0028, .p0032,
.p0034, .p0038, .p0042, .p0044, .p0046,
.p0048, .p0050, .p0052, .p0054, .p0056
{
max-width:100%;
background-size:100%;
background-image: url('sprites.png');
}
</style>

How to get list of custom CSS properties

I'm looking into custom CSS properties and have come up with the code below.
If I put the CSS inline using a STYLE attribute on the canvas tag (like this: style="--rgLinewidth: 3" ) then I can get the custom CSS values using the script shown below.
But using a tag, as below, then it doesn't show the custom CSS properties.
Is it possible to? And if so how?
<html>
<head>
<style>
canvas#cvs {
--rgLinewidth: 3;
background-color: red;
}
</style>
</head>
<body>
<canvas id="cvs" width="600" height="250">[No canvas support]</canvas>
<script>
canvas = document.getElementById("cvs");
styles = window.getComputedStyle(canvas);
alert(styles.getPropertyValue('background-color'));
alert(styles.getPropertyValue('--rgLinewidth'));
for (var i=0; i<styles.length; i++) {
if (canvas.style[i].indexOf('--rg') === 0) {
var value = styles.getPropertyValue(canvas.style[i]);
alert([canvas.style[i], value]);
}
}
</script>
</body>
</html>
It does not work because you query for computed style and then attempt to retrieve values of corresponding properties from the inline style, where they do not exist -- your canvas does not define an inline style. You need to query the values through the same styles object where you find the properties.
Consider the following function which when passed an element, will search through its computed style and return the value of the first CSS variable whose name starts with --rg:
function find_first_rg_value(el) {
var styles = getComputedStyle(el);
for (var i = 0; i < styles.length; i++) {
if (styles[i].startsWith('--rg')) {
return styles.getPropertyValue(styles[i]);
}
}
}
(Use like find_first_rg_value(canvas))
The difference between my approach and yours is, as I said, that you attempt to fetch the value from canvas.style[i], but canvas.style is effectively empty. Use styles instead.
Computed style (getComputedStyle), as the name implies, contains "summary" style computed per CSS cascading, inheriting, and so on, with inline style, if any, applied on top (overriding priority). Assigning inline style therefore affects the computed style, but querying inline style only gives you inline style you assigned, no more.
This means that in most cases like yours one would want to use getComputedStyle. Additionally, since CSS variables cannot be queried using style.fontName syntax, you need to use getPropertyValue function for these (all dashes intact in the passed property name), regardless if you are dealing with an inline or computed style object.

Dynamically change element styles via custom properties?

For example, you can change the ink colour in paper-tabs by changing --paper-tab-ink: var(--accent-color);. Is it possible to change the value of the CSS custom properties dynamically similar to how you can toggle a class or change the style in JS?
There are different ways to do this, but a simple answer is to use the Polymer.updateStyles() method after making your class changes.
For example, let's say your styles are:
<style>
.yellow x-example {
--light-primary-color: #fdd85f;
}
.red x-example {
--light-primary-color: red;
}
</style>
and you want to make the component use the styles in the .red class. You simply add it as you normally would in javascript, then be sure to also use this function to actually update it on the page.
<div class="yellow" onclick="this.className='red'; Polymer.updateStyles()">
<x-example></x-example>
</div>
Yes, first get the object of your custom element. Then get the customStyle object. Add a style to that object. And then run element.updateStyles();
t.clickListener= function(e) {
var t = Polymer.dom(e).localTarget; //retarget if needed
t.customStyle['--the-color-etc'] = 'pink';
t.updateStyles(); // mandatory for the CSS variables shim
};
See the docs

Css - Apply different CSS rule based on user input

I'm developing a web based source code editor. I'm thinking of adding support for themes (syntax highlighting).
//Default theme
.default-reserved-word
{
background-color : red;
}
//Some other theme
.monokai-reserved-word
{
background-color : green;
}
inside the editor each syntax highlightable word is surrounded by a span tag with the appropriate class:
....
<span class="default-reserved-word">def</span>method name
...
which I want to convert to (when the user clicks a "change theme" button)
....
<span class="monokai-reserved-word">def</span>method name
...
Is there a simple way of switching these CSS rules without going through all the elements and modifying the class attributes?
(FWIW, I need to support IE7+, FF3.6+)
I'd suggest using a different method, perhaps have a theme class on a higher parent container:
<div class="theme-default">
And then use CSS like this:
.theme-default .reserved-word {
color: blue;
}
Whilst this method is not exactly what you've asked for it will simplify the process of changing styles, for a start you won't have to search through loads of spans, finding the current class of theme-name + ' -reserved-word' (etc) and doing a string replace on them.
Add a class name to the root element (<html>) and change that on use input.
.theme1 .reserved-word { color: red; }
.theme2 .reserved-word { color: green; }
and then change
<html class="theme1">
to
<html class="theme2">
with Javascript.
You can use jQuery for that:
var elements = $('.default-reserved-word')
elements.removeClass('default-reserved-word');
elements.addClass('monokai-reserved-word');

Resources