Read and print the CSS values of a class with pure Javascript - javascript

I am trying to create a function, which:
Grabs an element with a specific data element, i.e. "data-findDeclaration = element"
From this element, the class is read
It reads out all the css values appointed to this class
Displays inside another specific data element (i.e. data-writeDeclaration="element") all the classes' rules/values.
Here's where I am so far:
HTML:
<span class="slap0" data-finddeclaration="element">The great white fox</span>
<div class="description" data-writedeclaration="element">
</div>
<span class="slap1" data-finddeclaration="element">The great white fox</span>
<div class="description" data-writedeclaration="element">
</div>
<span class="slap2" data-finddeclaration="element">The great white fox</span>
<div class="description" data-writedeclaration="element">
</div>
<span class="slap3" data-finddeclaration="element">The great white fox</span>
<div class="description" data-writedeclaration="element">
</div>
JS:
function readOutCssRules() {
var dataElement = document.querySelectorAll('[data-finddeclaration="element"]');
var classRules = document.styleSheets[0].rules || document.styleSheets[0].cssRules;
var writeDataElement = document.querySelectorAll('[data-writedeclaration="element"]');
for (var i = 0; i < dataElement.length; i++) {
dataElement[i].className;
if (classRules[i].selectorText == "." + dataElement[i].className) {
console.log(classRules[i].cssText);
writeDataElement[i].innerHTML = classRules[i].cssText;
}
}
}
readOutCssRules();
But the function is not working as expected.
Any ideas?
Thanks in advance.

Your code is working.
You just have to remove one line in the for loop:
for (var i = 0; i < dataElement.length; i++) {
//dataElement[i].className; --> remove this
if (classRules[i].selectorText == "." + dataElement[i].className) {
console.log(classRules[i].cssText);
writeDataElement[i].innerHTML = classRules[i].cssText;
}
}
After that changes it will work, as you can see in this fiddle.

Check this
https://jsfiddle.net/g6tu77mg/1/
var element = classRules[i].cssText
var css= element.substring(element.lastIndexOf("{")+1,element.lastIndexOf("}"));
writeDataElement[i].innerHTML = css;
Output:
The great white fox
color: blue;
The great white fox
color: red;
The great white fox
color: yellow;

Related

Making a "Guess the Color" game and can't figure out how to add the correct answer

I'm stumped on how to make the hex code displayed at the top one of the choices on the "board." This is what I've tried so far.
var colorCode = '#' + Math.random().toString(16).slice(2, 8);
hexCode.innerHTML = colorCode;
var divs = document.getElementsByTagName('div')
for (var i = 0; i < divs.length; i++) {
divs[i].style.backgroundColor = '#' + Math.random().toString(16).slice(2, 8);
}
.panel {
height: 100px;
width: 100px;
border: 2px solid yellow;
border-radius: 25%;
}
<header>
<h1>Guess the Color</h1>
</header>
<main>
<span id="hexCode"></span>
<div id="one" class="panel"></div>
<div id="two" class="panel"></div>
<div id="three" class="panel"></div>
<div id="four" class="panel"></div>
</main>
https://jsfiddle.net/magoo/6vdfcmnL/6/
Is not clear if you want to show the text above every panel or just make one of the panel below the title the correct one; By the way i edited the code to do both.
Try to edit the code like this to check if result as intended.
HTML part:
<header>
<h1>Guess the Color</h1>
</header>
<main>
<!-- question -->
<p id="hexCodeToGuess"></p>
<br>
<!-- one -->
<span id="oneHexCode" class="label"></span>
<div id="one" class="panel"></div>
<!-- two -->
<span id="twoHexCode" class="label"></span>
<div id="two" class="panel"></div>
<!-- three -->
<span id="threeHexCode" class="label"></span>
<div id="three" class="panel"></div>
<!-- four -->
<span id="fourHexCode" class="label"></span>
<div id="four" class="panel"></div>
</main>
Javscript part:
var colorCodeToGuess = '#' + Math.random().toString(16).slice(2, 8);
// set the first label with the question (the color code to guess)
hexCodeToGuess.innerHTML = colorCodeToGuess;
// list of panels
var panels = document.getElementsByClassName('panel');
// list of labels
var labels = document.getElementsByClassName('label');
// generate the position of the right answer panel (random to make it unpredictable)
var correctPanelIndex = getRandomInt(panels.length);
// cycle trough the divs
for (var i = 0; i < panels.length; i++) {
// set by default a random new color
var currentColorCode = '#' + Math.random().toString(16).slice(2, 8);
// the div is in the right answer position => override the current color with the colorCodeToGuess generate at the start (the problem of the previous code)
if(i == correctPanelIndex){
currentColorCode = colorCodeToGuess;
}
// set the color to the panel
panels[i].style.backgroundColor = currentColorCode;
// set the text on a label above the panel
labels[i].innerHTML = currentColorCode;
}
// an useful function to get a random integer passing it the numer of values possible
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
You will notice that one of the panels have the same code of the question of the first code written below the title.
I've also commented the code so you can remove the unwanted logic consciously.
Your question is a little vague but if i got it right you want to display the background color of one of your divs in hex format. The following code will do that. I have added comments on the code to explain what im doing.
//get your panels (using selector is better that using div)
var divs = document.querySelectorAll(".panel");
for (var i = 0; i < divs.length; i++) {
divs[i].style.backgroundColor = '#' + Math.random().toString(16).slice(2, 8);
}
//get the current backgrounds of all panels and add them to an array in hex format
curruntColorsArr = [];
x = document.querySelectorAll(".panel");
for (i = 0; i < x.length; i++) {
//get background color
backgroundColors = x[i].style.backgroundColor
//convert to hex
function rgbToHex(rgb) {
return '#' + rgb.match(/[0-9|.]+/g).map((x, i) => i === 3 ? parseInt(255 * parseFloat(x)).toString(16) : parseInt(x).toString(16)).join('')
}
//push to array
curruntColorsArr.push(rgbToHex(backgroundColors));
}
//get random color from the array and set it to innerHTML
function random_item(items) {
return items[Math.floor(Math.random() * items.length)];
}
const hexCode = document.getElementById("hexCode")
hexCode.innerHTML = random_item(curruntColorsArr)
.panel {
height: 100px;
width: 100px;
border: 2px solid yellow;
border-radius: 25%;
}
<header>
<h1>Guess the Color</h1>
</header>
<main>
<span id="hexCode"></span>
<div id="one" class="panel"></div>
<div id="two" class="panel"></div>
<div id="three" class="panel"></div>
<div id="four" class="panel"></div>
</main>

How to change all items values in a document.getClassName call (Without it just using the first elements value)

I'm trying to change the individual product prices on my page, since the encoding is all messed up thanks to the e-commerce platform i use. I'm needing to split on a £ sign, which seems to work well for individual items
I've tried changing the way I do this by using getElementID, but it's no good due to how the e-commerce platform operates, and I can't change any backend stff.
<div class="products-price">
<!--START: ITEMPRICE-->
<span class="subfix">[ITEMPRICE]</span>
<!--END: ITEMPRICE-->
</div>
jQuery(document).ready(function () {
var total = document.getElementsByClassName('subfix')
for (i = 0; i < total.length; i++) {
total[i].textContent.split('£')[1];
}
});
You also have to set the text to that element
jQuery(document).ready(function() {
var total = document.getElementsByClassName('subfix')
for (i = 0; i < total.length; i++) {
total[i].textContent=total[i].textContent.split('£')[1];
}
});
<div class="products-price">
<span class="subfix"> </span>
</div>
If I understand your question correctly you would like to change the price, but the currency symbol is what makes it difficult?
You could acheive it like this:
jQuery(document).ready(function() {
var total = document.getElementsByClassName('subfix')
for (i = 0; i < total.length; i++) {
var price = parseInt(total[i].textContent.split('£')[1])
var newPrice = price + 5;
total[i].textContent = "£" + newPrice;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="products-price">
<span class="subfix">£4</span>
</div>
<div class="products-price">
<span class="subfix">£8</span>
</div>
<div class="products-price">
<span class="subfix">£32</span>
</div>
<div class="products-price">
<span class="subfix">£2</span>
</div>
<div class="products-price">
<span class="subfix">£12</span>
</div>
<div class="products-price">
<span class="subfix">£6</span>
</div>
.split('£').pop();
If you want the last element returned use .pop(), then overwrite the <span> with .textContent in same iteration. .split() can use regular expressions and regex can now match unicode. The following is a regex that matches a standard pound symbol and a full width pound symbol in unicode:
/\u{a3}|\u{ffe1}/u
Demo
var total = document.getElementsByClassName('subfix')
for (i = 0; i < total.length; i++) {
var price = total[i].textContent.split(/\u{a3}|\u{ffe1}/u).pop();
total[i].textContent = price;
console.log(price);
}
span {
display: block;
}
.as-console-wrapper {
width: 50%;
margin-left: 50%;
min-height: 100%;
}
<div class="products-price">
<span class="subfix">£10.00</span>
<span class="subfix">£53.00</span>
<span class="subfix">£101.09</span>
<span class="subfix">£90.01</span>
<span class="subfix">£22.00</span>
<span class="subfix">£18.55</span>
<span class="subfix">£10.20</span>
<span class="subfix">£70.67</span>

Javascript - Input text and output to multiple areas

I'm trying to input text in a field, and have it output to multiple fields.
Currently, it only outputs to the first field.
Here's the input:
<form class="form" onchange="myFunction()">
<div class="mb-4">
<p>The quick sly fox jumped over the <input id="object" class="inline borderless-input"></p>
</div>
</form>
JS controlling the output:
function myFunction()
{
//Object
var x = document.getElementById("object");
var div = document.getElementById("objectDisplay");
div.innerHTML = x.value;
}
Here's a codepen I'm working with: Codepen
ID's have to be unique. Use classes and a for loop to cycle through each one and change it. This cannot be done with document.getElementById. See https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementById for some basic information about document.getElementById. document.getElementsByClassName returns an array filled with existing elements with a certain class. In this case, objectDisplay. If you want to read more about that then take a look here: https://developer.mozilla.org/en-US/docs/Web/API/Document/getElementsByClassName.
The new code should look like this:
function myFunction() {
//Object
var x = document.getElementById("object");
var div = document.getElementsByClassName("objectDisplay");
for (i = 0; i < div.length; i++) {
div[i].innerHTML = x.value;
}
}
.container {
padding: 10px;
}
.text-strong {
font-weight: bold;
}
.inline {
display: inline;
}
.borderless-input {
background-color: transparent;
border-style: solid;
border-width: 0px 0px 1px 0px;
padding: .5rem .75rem;
text-align: center;
}
<div class="container">
<div class="row">
<div class="col-lg-12">
<form class="form" onchange="myFunction()">
<div class="mb-4">
<p>The quick sly fox jumped over the <input id="object" class="inline borderless-input"></p>
</div>
</form>
</div>
</div>
</div>
<div class="container">
<div class="row">
<div class="col-lg-12">
<h3><strong>Output</strong></h3>
</div>
</div>
<div class="row">
<div class="col-lg-12">
<p>The quick sly fox jumped over the <span class="objectDisplay inline"></span>.</p>
<p>The quick sly fox jumped over the <span class="objectDisplay inline"></span>.</p>
<p>The quick sly fox jumped over the <span class="objectDisplay inline"></span>.</p>
</div>
</div>
</div>
<!-- For Testing Only -->
<div class="container">
<div class="row">
<div class="col-lg-10 offset-lg-1 mx-auto">
<!-- Test Here -->
</div>
</div>
</div>
Identify your inputs with class instead of id
<p>The quick sly fox jumped over the <span id="objectDisplay" class="objectDisplay inline"></span>.</p>
use this
var divs = document.getElementsByClassName("objectDisplay");
for(var i = 0; i < divs.length; i++){
divs[i].innerHTML = x.value;
}
instead of
var div = document.getElementById("objectDisplay");
div.innerHTML = x.value;
I found a similar question see the link: jQuery id selector works only for the first element.
but briefly, you're using the same ID for more than one element, try using the class selector, example document.getElementsByClassName ('your-class') or document.querySelectorAll ('your-class'), remembering that in querySelectorAll for classes: '.your-class' and Id: '# my-id'.
function myFunction(){
//Object
var x = document.getElementById("object");
var div = document.querySelectorAll(".col-lg-12 span");
for(var i = 0; i < div.length;i = i + 1){
div[i].innerHTML = x.value;
}
}
IDs are unique so you should have only one ID per page. Try changing objectDisplay to a class and then selecting them all and looping through each as below
function myFunction(el)
{
//Object
var x = document.getElementById("object");
var divs = document.querySelectorAll(".objectDisplay");
var inputValue = el.value;
for(var i=0; i < divs.length; i++){
divs[i].innerHTML = inputValue;
}
}
<form class="form">
<div class="mb-4">
<p>The quick sly fox jumped over the <input id="object" class="inline borderless-input" onchange="myFunction(this)" value=""></p>
</div>
</form>
<div class="objectDisplay"></div>
<div class="objectDisplay"></div>

Affect an element when another element is hovered

How can I affect an element when another element is hovered, and the two elements are in this structure:
<div id="parent_element">
<div id="class-open-1"></div>
<div id="class-close-1"></div>
</div>
or they might be in this structure:
<div id="parent_element">
<div id="div1">
<div id="class-open-1"></div>
</div>
</div>
<div id="parent_element"></div>
<div id="div2">
<div id="class-close-1"></div>
</div>
</div>
I have tried this solution which works perfectly for the first case, but does not work for the second case:
_style.innerHTML = ".class-open" + j + ":hover{ background-color: cyan; } .class-open-" + j + ":hover ~ .class-close-" + j + " { background-color: cyan; }
the j changes , so I am only hovering the classnames that have the same j
this solution works for the case one, but doesnt work for both cases.
I have also tried this :
_style.innerHTML = ".class-open" + j + ":hover{ background-color: cyan; } .class-open-" + j + ":hover .class-close-" + j + " { background-color: cyan; }
But this changes the background-color, and doesn't only hover.
I only need css or javascript to solve this, any suggestions?
I am looking for a solution that works for BOTH cases.
You're going to need to use JavaScript mouseover or jQuery .hover(). This shows mouseover from the MDN.
myElement.addEventListener("mouseover", (event) => {
// do something to the other element.
}
Try this friend:
div#one
{
background-color:red;
}
div#one:hover ~ div#two
{
background-color:yellow;
}
<div id="one">
ONEE
</div>
<div>
SIMPLE DIV
</div>
<div>
SIMPLE DIV
</div>
<div>
SIMPLE DIV
</div>
<div>
SIMPLE DIV
</div>
<div>
SIMPLE DIV
</div>
<div id="two">
two
</div>
if (/\bclass-/.test(target.className)) {
var _style = document.createElement('style');
var j = target.className.match(/\d+$/)[0];
target.style.backgroundColor = "red";
_style.innerHTML = ".class-close-" + j + " { background-color: red; }";
setTimeout(function () {
target.style.backgroundColor = "";
_style.innerHTML = '.class-close-' + j + ' { background-color: ""; }';
}, 500);
document.head.appendChild(_style);
}
Here is the solution I made, but still looking for the "good effect" of Hover instead of just deleting the style after the 500ms..
Hope this helps someone.
If you can control the template code [which I believe we do in most cases], then if one element is inside other element, it can be solved just using css.
Else, if they have different parent, JS would be the direction which people have already suggested.

HTML - How do I insert a <span></span> tag into each line of a <pre></pre> block without hard coding?

I was just trying to add line numbers at the beginning of source code using CSS.
I realized the effect I wanted, as follows:
However, the HTML code required continual use of <span>...</span> tags:
<pre class="code">
<span>var links = document.getElementsByClassName("link");</span>
<span>for(var i = 0; i < links.length; i++){</span>
<span> links[i].onclick=function(){</span>
<span> alert(i+1);</span>
<span> };</span>
<span>}</span>
</pre>
With the span tags positioned at home/end of lines I can let the line numbers show as expected.
But I think there must be another better solution to prevent me adding all these span tags hard-coded, maybe using Javascript, or jQuery I don't mind but don't know how. Please help.
NOTE:
My problem is not how to display line numbers when the <span> tags are already there. Instead, I wanted to know if the origin HTML code contains NO <span> tags, how can I automatically add them into the suitable places and so I can apply the CSS styles.
This can be achieved by using CSS counters
This does not require any JavaScript (or jQuery) which means no need for each libraries or scripts and was introduced way back in CSS 2.1 so has great browser support across the board.
pre {
background: #eee;
counter-reset: section; /* Reset the counter to 0 for each new pre */
}
pre span:before {
counter-increment: section; /* Increment the section counter*/
content: counter(section); /* Display the counter */
padding: 0 5px;
border-right: 1px solid #777;
margin-right: 5px;
color: #777
}
<pre class="code">
<span>var links = document.getElementsByClassName("link");</span>
<span>for(var i = 0; i < links.length; i++){</span>
<span> links[i].onclick=function(){</span>
<span> alert(i+1);</span>
<span> };</span>
<span>}</span>
</pre>
<pre class="code">
<span>var links = document.getElementsByClassName("link");</span>
<span>for(var i = 0; i < links.length; i++){</span>
<span> links[i].onclick=function(){</span>
<span> alert(i+1);</span>
<span> };</span>
<span>}</span>
</pre>
I have combined #Stewartside answer with what you have actually asked for.
Below you can see a simple plain JavaScript to replace any line in element with code class to be wrapped in span which applies #Stewartside css.
var codeElement = document.getElementsByClassName("code"); //array of code blocks
var formattedCode = codeElement[0].textContent.replace("\r\n", "\n").split("\n");
var codeLength = formattedCode.length;
formattedCode.forEach(function(line, index, array) {
if (codeLength - 1 == index) return;
array[index] = "<span>" + line + "</span>";
});
codeElement[0].innerHTML = formattedCode.join("\n");
$(".code-jquery").each(function(index, codeElement) {
var formattedCode = $(codeElement).html().replace("\r\n", "\n").split("\n");
var codeLength = formattedCode.length;
$(codeElement).text("");
$.each(formattedCode, function(index, line) {
if (codeLength - 1 == index) return;
$(codeElement).append("<span>" + line + "</span>\n")
});
});
pre {
background: #eee;
counter-reset: section; /* Reset the counter to 0 for each new pre */
}
pre span:before {
counter-increment: section; /* Increment the section counter*/
content: counter(section); /* Display the counter */
padding: 0 5px;
border-right: 1px solid #777;
margin-right: 5px;
color: #777
}
pre.code-jquery span {
color: green;
}
<pre class="code">
var links = document.getElementsByClassName("link");
for(var i = 0; i < links.length; i++) {
links[i].onclick = function() {
alert(i+1);
};
}
</pre>
//jQuery version
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<pre class="code-jquery">
var links = document.getElementsByClassName("link");
for(var i = 0; i < links.length; i++) {
links[i].onclick = function() {
alert(i+1);
};
}
</pre>
So you basically need to append a span before each line. Here is the codepen link. I am currently using jQuery's insertBefore() method for it.
See below for the explanation of the code :-
$('.code') will give you the pre tag. Now the jQuery .find() method will give you all the spans inside the pre tag. Now jQuery .each() function is basically a for loop ( in simple terms ) which will loop for all the span tags inside the pre tag.
.insertBefore() function simply inserts whatever there is in the selector to the element mentioned inside the function.
var iCount = 1;
$('.code').find('span').each(function(){
$( "<span>"+iCount+"| </span>" ).insertBefore( this);
iCount++;
});
pre{
background: #eee
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<pre class="code">
<span>var links = document.getElementsByClassName("link");</span>
<span>for(var i = 0; i < links.length; i++){</span>
<span> links[i].onclick=function(){</span>
<span> alert(i+1);</span>
<span> };</span>
<span>}</span>
</pre>

Categories