Get CSS rules into javascript variable - javascript

I am wanting to be able to select chunks of CSS Rules using JavaScript or jQuery and get them into a variable, basically as the preformatted text you would expect in a style-sheet.
Ideally we would carefully comment our CSS styles and have them simply in the <head> <style> tag on the html page. The JavaScript would locate the particular comment that wraps the rules within the <style> tag on the page, and copy those rules to a variable as text, for later use.
/* CSS Rules */
.example{
font-size: 1em;
color:blue;
}
/* end */
In this case the script would find the string /* CSS Rule */, then select all the lines below it until it hits a terminating comment /* end */
Any ideas? I've googled a fair bit for a solution, but guess this is a pretty unusual thing to be doing, having a hard time finding any pointers.

Welp...you could always have an id on your style tag like
<style id="css">div{ background-color:red; }</style>
And then grab the contents with jquery
var cssText = $('#css').html();
But this whole thing would make Ada Lovelace cry, maybe you can find another way to fullfil your requirements?

It's a bit hacky-ish, but here is one way to do this -
Extract the text (use regex or indexOf) - assuming you have the text block, create a data-uri out of it:
var cssURL = "data:text/css;charset=utf8," + encodeURIComponent(cssTxt);
create a link element and set rel to stylesheet (browser is able to deal with type):
var link = document.createElement("link");
link.rel= "stylesheet";
link.href = cssURL;
Add to header to load and parse:
document.getElementsByTagName("head")[0].appendChild(link);
Example
Only the green should show -
var css = ".s1 {border:1px solid red} " +
"/* start */ .s2 {border:1px solid green} /* end */ " +
".s3 {border:1px solid blue}";
// get css text and convert to data-uri
var start = css.indexOf("/* start */");
var end = css.indexOf("/* end */", start);
var cssTxt = css.substring(start, end);
var cssURL = "data:text/css;charset=utf8," + encodeURIComponent(cssTxt);
// create link element and add to header
var link = document.createElement("link");
link.rel= "stylesheet";
link.href = cssURL;
document.getElementsByTagName("head")[0].appendChild(link);
<div class="s1">Class s1 - ignored</div>
<div class="s2">Class s2 - should have green border</div>
<div class="s3">Class s3 - ignored</div>

Related

Javascript .replace method doesn't override CSS style

I've read here that when both CSS and JavaScript target the same element, then the JavaScript changes are applied over CSS.
However, I've encountered a different behaviour.
Here, we have legal case name: Johnson V United Care.
I want to convert all words to uppercase, except the "V", which I want to convert to lowercase.
This is what I want: JOHNSON v UNITED CARE.
However, in the below code, CSS uppercase style seems to override the Javascript code.
I've referred the CSS file in the <head> and the JS file just before the closing </body> tag.
What I am doing wrong?
Note: After I've posted the question, I've thought that the JS code only changes the innerHTML, and subsequently CSS style is applied to this new HTML. So, this does not seem like a priority issue. But I still can't figure how to apply JS code after CSS in order to get the correct result.
(function() {
let title = document.querySelector("h1.title>a");
let a = title.innerHTML;
let b = a.match(/\b[v]\b/i);
title.innerHTML = a.replace(b, b.toString().toLowerCase());
})();
h1.title>a {
text-transform: uppercase;
}
<h1 class="title">Johnson V United Care</h1>
I've read here that when both CSS and JavaScript target the same element, then the JavaScript changes are applied over CSS.
That article is very wrong.
Inline style has precedence over rule-sets. It doesn't matter how the two styles are added to the document. It just looks like JS has precedence because JS is used to add inline style.
What I am doing wrong?
CSS changes how the content is presented.
The CSS says it should be presented in uppercase.
It doesn't matter if, in the actual content, a particular character is lower-case because it was written that way in HTML or changed to be that way with JS.
You are changing the content with JS, and then CSS is presenting that content in uppercase.
I'd approach the problem by writing extra markup and styling that.
h1.title>a .name {
text-transform: uppercase;
}
<h1 class="title"><span class="name">Johnson</span> v <span class="name">United Care</a>
</h1>
Actually, it will not be possible to override the CSS property this way, because they are not working on the same property. You're setting the text-transform property in the CSS and in JS code you are just changing the HTML content of the element but not overriding the text-transform property. This way the precedence order will have not effect.
To solve the problem, you should do all text transformations in JS and remove the text-transform property in CSS.
Here is an example:
const title = document.querySelector('h1.title > a');
const polifyText = (str, char) =>
str
.split(' ')
.map(part => (part.includes(char) ? part.toLowerCase() : part.toUpperCase()))
.join(' ');
let newTitle = title.textContent;
let char = newTitle.match(/\b[v]\b/i);
title.textContent = polifyText(newTitle, char);
h1.title > a {
/* Comment this out */
// text-transform: uppercase;
}
<h1 class="title">Johnson v United Care
</h1>

Create a very low specificity css property

I am trying to create a very low specificity css property using javascript. Just like !unimportant (which doesn't exists)
I don't know whether this is possible or not.
My reason to look for something like !unimportant is that I am writing a small javascript plugin. In which I want to add a default style to a element which should be later easily overriden by the user.
But if I write:
element.style.backgroundColor = "green";
The user will not be able to override the above style easily without using !important. So, I added a dynamic style tag by using the following code:
var style = document.createElement('style');
// WebKit hack :(
style.appendChild(document.createTextNode(""));
document.head.appendChild(style);
and then to the above code, I added a dynamic stylesheet using the following code:
var element = document.getElementById('main');
// To use attribute names to apply the styles
element.setAttribute('custom-el', '1');
var sheet = style.sheet;
var properties = "background-color: green;";
var elName = "[custom-el]";
if (sheet.insertRule) {
sheet.insertRule(elName + "{" + properties + "}", 0);
} else if (sheet.addRule) {
sheet.addRule(elName, properties, 0);
}
Now the background-color: green can be overriden by using the following code:
div.main {
background-color: red;
}
But as you can see in css, I used higher specificity to override background-color: green i.e div + .green.
But I want the overriden to happen even when user writes the following css:
.main{ /* Could be simple class name or id name or even tag name */
background-color: red;
}
Fiddle
This might seems to be a small issue. but it is a big problem for me. Please help.
I would simply write like this:
element.style.backgroundColor = element.style.backgroundColor || "green";
Where, if backgroundColor is undefined then it uses green as backgroundColor else it would take the backgroundColor from stylesheet.
Finally I got the answer..
document.head.insertBefore(style, document.head.children[0]);
I should just insert the dynamic stylesheet above already present stylesheets in the head tag.
Working Fiddle
Unfortunately, this is not working in any IE version. I am still looking for answer.

How to change different language to different font-size at same line without unique each container?

How to change different language to different font-size at same line without unique each container? is it possible? with css or javascript?
div{
font-family: "English", "中文"
font-size: 20px;
// I need to make "中文" font-size 10px.
}
<div>This is English. 這是中文 This is English</div>
<div>This is English. 這是中文這是中文這是中文 This is English</div>
...
If you alter the text using JavaScript (since your question allowed for JavaScript), you can use CSS upon the results changed by JavaScript (which as others have said, requires adding a container).
For example :
window.onload = function () {
// Note that the following might also be used for Japanese or Korean
// Note also that I have not included (deprecated) compatibility characters. As
// per http://www.unicode.org/reports/tr38/#BlockListing , to cover those
// you would need to add:
// 1. \u3358-\u3370\u337B-\u337F\u33E0-\u33FE (e.g., immediately after "\u32CB")
// 2. \uFA2E-\uFA6D\uFA70-\uFAD9 (e.g., immediately after "\uFA29")
// 3. Replace \uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29 with \uF900-\uFA2D OR if you want to keep the compat. listed separately from non-compat. (though there is no need for this), add the following, e.g., before \uFA0E: \uF900-\uFA0D\uFA10\uFA12\uFA15-\uFA1E\uFA20\uFA22\uFA25\uFA26\uFA2A-\uFA2D
// 4. Immediately before ")+\s?)+/g", add |\ud87e[\udc00-\ude1d]
// The portion \u2E80 up to \u32CB is for punctuation and special characters like radicals,
// but this does not support some punctuation characters which might be reused outside of
// CJK as well as in CJK.
var chineseChars = /((?:[\u2E80-\u2E99\u2E9B-\u2EF3\u2F00-\u2FD5\u2FF0\u2FFB\u3000-\u303F\u3105-\u312D\u3190-\u31B7\u31C0-\u31E3\u3220-\u3243\u3280-\u32B0\u32C0-\u32CB\u4E00-\u9FCC\u3400-\u4DB5\uFA0E\uFA0F\uFA11\uFA13\uFA14\uFA1F\uFA21\uFA23\uFA24\uFA27-\uFA29]|[\ud840-\ud868][\udc00-\udfff]|\ud869[\udc00-\uded6\udf00-\udfff]|[\ud86a-\ud86c][\udc00-\udfff]|\ud86d[\udc00-\udf34\udf40-\udfff]|\ud86e[\udc00-\udc1d])+\s?)+/g;
document.body.innerHTML = document.body.innerHTML.replace(
chineseChars,
'<span lang="zh">$1</span>'
);
};
with your CSS:
body {font-size: 12px;}
span:lang(zh) {font-size: 10px}
JSFiddle
My use of lang="zh" is based on an assumption that you know these to be used for Chinese as opposed to Japanese or Korean. If you do not know, you can change the span in JS to this:
'<span class="cjk">$1</span>'
and the Chinese part of the CSS to this:
span.cjk {font-size: 10px}
That won't make any assumptions about the language, only the characters.
JSFiddle
http://jsbin.com/qozidepi/1/watch?js,output
JS:
// Get the div
var div = document.getElementById("text");
// Get the value
var value = div.innerHTML;
// Regular expression finds Chinese characters and wraps them
// in a span tag, which have font-size 40px
value = value.replace(/([\u3400-\u9FBF]+)/g, function(match){
return "<span>" + match + "</span>";
});
// Set the div's value
div.innerHTML = value;

Apply Theme/Dynamic CSS to a Page/any HTML Element

At some point, Users might get bored of the Style/Theme of the WEB applications.
They might think, "Only If I could make it look the way I like it"
example:
I myself is a user of Stack Overflow. What if I Like the Page-headerBar to look Blue/Purple
Page itself to have a Black background and white text color
...
My need:
Not just change the class attribute but the complete CSS definition itself.
If we force the users to select from a set of Stylesheets, that would be constricting them to a small space, So I like to avoid that.
* Note * I need it in pure javascript not using any jquery plugin or any jquery script
You Can Try This Its Pure Javascript
<script>
function applyit()
{
var ref = document.querySelector("#divel");
var bdy = document.getElementsByTagName("body")[0];
var style = (bdy.querySelector("#thm") || document.createElement("style"));
style.setAttribute("id","thm");
var reqCSS = prompt("Enter the CSS Body","color:#AA5533;");
style.innerHTML = ".cus{"+reqCSS+"}";
bdy.appendChild(style);
ref.setAttribute("class","cus");
}
</script>
<style> .def { color:#0000FF; } </style>
<div id="divel" class="def">
<h3>This is a heading in a div element Which Has The Color Change</h3>
<p>This is p tag in a div element Which Has The Color Change.</p>
</div>
<p onclick="applyit();">Click Here To Change The Color For Heading and p tag.</p>
Note:
We could store the User Preferred style in browserStorage/Server to improve UserExperience

Dynamically add css to page via javascript

I'm making a widget that will be added to external websites, and I have made a page that generates css for them to style it (text color, background color, font size, etc). I end up with a textarea filled with css for them to copy/paste to their website.
Is there a way to add this css to the current page in order to have a live preview?
If you want to add CSS as text
var style = document.createElement('style');
style.innerHTML = 'content';
document.head.appendChild(style);
If you want to add a CSS file
var link = document.createElement('link');
link.setAttribute('rel', 'stylesheet');
link.setAttribute('href', 'css/my.css');
document.head.appendChild(link);
I have traditionally appended a <style> block when doing elements.
var style_rules = [];
style_rules.push("#" + myElemId + " { /* Rules */ } ");
/* ... */
var style = '<style type="text/css">' + style_rules.join("\n") + "</style>";
$("head").append(style);
An important thing to note is that because you don't know what any of the existing styles is, or what id's might conflict on the page, it's very useful to keep track of your id's inside your JavaScript application, then using those to populate the injected <style> block. I also tend to run my names through a prefix function to ensure that the generic names of wrapper, and unit do not conflict (they are turned into something like myunique_wrapper and myunique_unit.
Incorporating a basic CSS reset like #myWrapper {margin: 0; padding: 0} can be a decent starting platform for building your own custom styles.
Addressing your unique case, a live preview so to speak, I would designate a div with standard elements. Then when they click "update" read in the rules and append them to the head. If you want to negate any residual effects from past rules you can remove the last <style> element or better yet give your <style> element an id. I'm not sure if that kind of selection would work, but it should.
var element = document.createElement('style');
element.setAttribute('type', 'text/css');
if ('textContent' in element) {
element.textContent = css;
} else {
element.styleSheet.cssText = css;
}
document.getElementsByTagName('head')[0].appendChild(element);
Can you add a style tag to the DOM, with the contents of the text-area in it? You may want to give it an id so you can change it later.
I recommend you start using a decent framework for your web/JavaScript development, personally I'd go with jQuery.
http://api.jquery.com/css/
There are some code snippets here that show you how to quickly set css properties for elements.

Categories