I need a textarea able set a different background color for each line, i have used the ::first-line pseudo-element, but how do i change the styling of another lines?
#field{
height: 100px;
width: 200px;
}
#field::first-line{
background-color: #f33;
}
<textarea id='field'>
I want this to be red.
This to be green.
This to be blue and keep the same if there is not enough space.
And this another color.
</textarea>
A textarea cannot be a "block" container, you can't emulate this behavior with CSS.
I have used a div as backdrop with the same style as the textarea, but added transparency to the textarea background.This way the style added to the backdrop can be seen.
backdropInput()
backdropScroll()
function backdropInput(){
backdropStyle();
backdrop.innerHTML = "";
let colors = ['#f33', '#3f3', '#66f'];
let i = 0
for(section of field.value.split("\n")){
backdrop.innerHTML += "<span style='background-color: "+colors[i]+"'>"+section+"</span><br>"
i < colors.length-1 ? i++ : i = 0
}
}
function backdropScroll(){
backdrop.scrollTop = field.scrollTop;
}
function backdropStyle(){
let css = window.getComputedStyle(field);
let cssstring = "";
for (let i = 0; i < css.length; i++) {
cssstring +=(css[i] +': '+css.getPropertyValue(css[i])+";");
}
backdrop.style = cssstring;
backdrop.style.position = 'absolute';
backdrop.style.zIndex = '-1'
backdrop.style.overflow = 'hidden';
backdrop.style.backgroundColor = '#fff';
backdrop.style.fontColor ='#f00';
backdrop.style.resize = 'none';
}
//=================================================================================
//=================================================================================
//textarea resize
document.getElementById("field").addEventListener("mousedown", function(){
backdrop.style.display = 'none'
})
document.getElementById("field").addEventListener("mouseup", function(){
backdropStyle();
});
#field{
height: 200px;
width: 200px;
background-color: rgba(0, 0, 0, 0);
}
<div id="backdrop"></div>
<textarea id='field' oninput="backdropInput()" onscroll="backdropScroll()">
This is red.
This is green.
This is blue and keep the same if there is not enough space.
This is red.
This is green.
This is blue and keep the same if there is not enough space.
And the colors keep looping
</textarea>
Related
I have several sections with different colors in the background.
I need to dynamically create divs as a result of these sections.
So far I have no worries.
What I'm trying to get as a result, is that each divs has a different color in the background, taking the colors of the sections.
I can get this result with CSS
HTML:
<section class="l-section js-section"></section>
<section class="l-section js-section"></section>
<section class="l-section js-section"></section>
<section class="l-section js-section"></section>
<section class="l-section js-section"></section>
<div class="l-container-test js-container-test"></div>
SCSS:
.l-section{
height: 100vh;
width: 100vw;
&:nth-child(1){
background-color: red;
}
&:nth-child(2){
background-color: green;
}
&:nth-child(3){
background-color: yellow;
}
&:nth-child(4){
background-color: blue;
}
&:nth-child(5){
background-color: pink;
}
}
.l-container-test{
display: flex;
height: 100vh;
width: 100vw;
& > * {
flex: 1;
}
& :nth-child(1){
background-color: red;
}
& :nth-child(2){
background-color: green;
}
& :nth-child(3){
background-color: yellow;
}
// and so on....
}
JS:
function createDivs(){
let fragment = document.createDocumentFragment();
let div = document.createElement(`div`);
div.className = `l-div js-div`;
const container = document.querySelector(`.js-container-test`);
const sections = document.querySelectorAll(`.js-section`);
const divs = document.querySelectorAll(`.js-div`);
let arrColors = [];
fragment.appendChild(div);
for(let i = 0; i < 10; i++){
container.appendChild(fragment.cloneNode(true));
}
sections.forEach(section => {
colors = window.getComputedStyle(section).getPropertyValue(`background-color`);
arrColors.push(colors)
})
console.log(arrColors);
// EDIT
arrColors.forEach((color, index) => {
divs[index].style.backgroundColor = color;
})
}
createDivs();
Here is my working example : https://jsfiddle.net/CedGrvl/e476kvsn/40/
But I think it could be easier, unless I'm wrong, if I could handle these colors with js. In case I add divs, I would like the colors to follow each other.
Knowing that I still have more divs than sections, I would like the color sequence to be logical. If the sections from top to bottom are red, green, blue... the divs should be red, blue, green, red, blue, blue, green...
it is possible that I may be wrong in my logic, I am not necessarily looking for a pure and simple solution but at least some leads
Thank you in advance
EDIT:
I only manage to put the color on the first ones and I understand why. I have to figure out so that the other dives are colored.
Ok I figured it out
https://jsfiddle.net/CedGrvl/cp0zbx8t/1/
function createDivs(){
const container = document.querySelector(`.js-container-test`);
const sections = document.querySelectorAll(`.js-section`);
let arrColors = [];
let arrDivs = [];
let fragment = document.createDocumentFragment();
let div = document.createElement("div");
div.className = 'js-div';
fragment.appendChild(div);
sections.forEach(section => {
let colors = window.getComputedStyle(section).getPropertyValue(`background-color`);
arrColors.push(colors);
});
console.log(arrColors)
function setNumberDivs(numberDiv){
for(let i= 0; i < numberDiv; i++){
container.appendChild(fragment.cloneNode(true));
arrDivs = document.querySelectorAll('.js-div');
}
arrDivs.forEach((div, index) => {
div.style.backgroundColor = arrColors[index%arrColors.length]
console.log(index)
})
console.log(divs)
}
setNumberDivs(10);
}
createDivs();
I am struggling to fill div element with square cells entirely.
right now these square cells fall out of the div, don't fit properly etc.
I am not sure what causes it.
Any ideas?
var cell_side_len = 50;
var grid_width = 400;
var grid_height = 300;
var container = document.getElementById("container");
container.style.border = "solid black";
container.style.width = grid_width+"px";
container.style.height = grid_height+"px";
for(var i = 0; i < grid_width/cell_side_len; i++){
for(var j = 0; j < grid_height/cell_side_len; j++){
var cell = document.createElement('div');
cell.style.height = cell_side_len + 'px';
cell.style.width = cell_side_len + 'px';
cell.style.border = "1px solid black";
cell.style.float = "left";
container.appendChild(cell);
}
}
<div id="container"></div>
Problem you have is the fact the border is NOT part of the width/height. So what you have have is everything is a width of 52px, not 50px. This is the basic box model.
What can you do?
Change your width to 48
or Use box-sizing: border-box;
or Drop the border for outline
or use a modern approach with flexbox or grid.
You are setting the content width of each cell to be 50px, and then adding a 1px border on each side, making each cell have a total width of 52px. This does not fit evenly into the 400px-width container.
You can fix this by saying "when I say width, I mean the content, the padding, and the border all together!". To do so, you should add the following CSS:
box-sizing: border-box;
To do that in JavaScript, you would write
cell.style["box-sizing"] = "border-box";
// or
cell.style.boxSizing = "border-box";
I'm stuck on a project. I need to use javaScript/jQuery to create a box that changes colors when clicked. However, the colors that it cycles through can only be shades of green spanning from black to pure green (i.e. "#000000" --> "#00ff00"). Would it then be possible, once "#00ff00" is displayed, if it further changed the tint all the way to "#ffffff" and then cycled back to "#000000"
Additionally, I would need a second string of code that does the opposite (spans from "#ffffff" to "#00ff00" to "#000000").
In an ideal world, there would also be an output log that presents each selection as it is clicked. How do I approach this?
var div = document.querySelector('#myDiv')
div.dataset.color = 0;
div.addEventListener('click',()=>{
div.dataset.color = parseInt(div.dataset.color)+10;
var c = div.dataset.color%256;
div.style.background = 'rgb(0,'+c+',0)';
})
#myDiv {
width: 200px;
height: 200px;
background: #000000;
}
<div id="myDiv"></div>
Not sure if that's what you looking for, but here's loop black>green>white:
var div = document.querySelector('#myDiv')
div.dataset.color = 0;
div.addEventListener('click',()=>{
div.dataset.color = parseInt(div.dataset.color)+10;
var c = Math.min(div.dataset.color%512,255);
var c2 = Math.max((div.dataset.color%512)-255,0);
div.style.background = 'rgb('+c2+','+c+','+c2+')';
})
#myDiv {
width: 200px;
height: 200px;
background: #000000;
}
<div id="myDiv"></div>
If you have an element whose height is animating using a CSS transition, is there a way to use jQuery or pure Javascript to get its finished height before the transition completes?
Consider the following example: https://jsfiddle.net/qm6zz0kq/
<div id="test"></div>
<style>
#test {
width: 100px;
height: 0;
transition: height 2s ease-in-out;
background: #F00;
}
#test.showing {
height: 100px;
}
</style>
<script>
var testElement = document.getElementById('test');
setTimeout(function() {
testElement.className = 'showing';
}, 100);
setInterval(function() {
testElement.innerHTML = 'Height: ' + testElement.clientHeight;
}, 100);
</script>
How could you modify the interval so it always generates "Height: 100"?
I've considered doing some kind of jQuery clone that doesn't have to transition and measuring its height but in this instance, the CSS is nested enough that I'd have to clone basically of the element's parents to make sure it's correct and that could be expensive.
You can put another hidden div (hidden-test, as an example) that is the same as the div test and add to it the class showing right away (without timeout), then get its height, that will be the same.
Look here an example: https://jsfiddle.net/qm6zz0kq/1/
You could read the actual CSSRule, note though this would just get the value defined in the CSS. For instance if the height was specified as 70% it would give 70% and not the actual px height it would end up as, eg if parents height was 170px, it wouldn't give you the value of 70% of 170px. Also note this will not work if the stylesheet is include from a file <link href="css.css">
var testElement = document.getElementById('test');
setTimeout(function() {
testElement.className = 'showing';
}, 100);
setTimeout(function() {
var rule = getRule("#test.showing");
if(rule){
testElement.innerHTML = 'Height: ' + rule.style.height;
}
}, 100);
function getRule(selector) {
var foundRule = null;
[].slice.call(window.document.styleSheets)
.filter(sheet=>sheet.rules || sheet.cssRules).forEach(sheet=>{
foundRule = foundRule || [].slice.call(sheet.rules||sheet.cssRules)
.filter(rule=>rule.selectorText == selector);
});
if(foundRule && foundRule[0]) return foundRule[0];
}
#test {
width: 100px;
height: 0;
transition: height 2s ease-in-out;
background: #F00;
}
#test.showing {
height: 100px;
}
<div id="test"></div>
You could also put in an element that is a clone. You do not have to also clone the parents like you mention in your question. You just have to insert the element into the same parent. This particular example uses display:none to hide the element, the returned value will not be a calculated value. Again like above if the parent's height is 400px and the height of the element is 75%, 100px will not be returned, 75% would be.
var clone = testElement.cloneNode();
//remove transition so we can get end height
clone.style.transition = "none";
//display:none so we do not have to see the temp element
clone.style.display = "none";
clone.classList.add("showing");
testElement.parentNode.appendChild(clone);
var endHeight = window.getComputedStyle(clone).height;
var testElement = document.getElementById('test');
setTimeout(function() {
testElement.className = 'showing';
}, 100);
//Clone the element
var clone = testElement.cloneNode();
//remove transition so we can get end height
clone.style.transition = "none";
//display:none so we do not have to see the temp element
clone.style.display = "none";
clone.classList.add("showing");
testElement.parentNode.appendChild(clone);
var endHeight = window.getComputedStyle(clone).height;
//Remove it as we dont need it anymore
clone.remove();
setTimeout(function() {
testElement.innerHTML = 'Height: ' + endHeight;
}, 300);
#parent {
height:300px;
}
#test {
width: 100px;
height: 0;
transition: height 2s ease-in-out;
background: #F00;
}
#test.showing {
height: 70%;
}
<div id="parent">
<div id="test"></div>
</div>
If you want the actual calculated height you would need to change the clone to use a couple different stles.
visibility:hidden to hide it instead of display:none as display will make it so we won't get a calculated value.
position:absolute to prevent it from modifying the parents dimensions
clone.style.visibility = "hidden";
clone.style.position = "absolute";
//needed to make sure element is contained by parent
parent.style.position = parent.style.position || "relative";
var endHeight = window.getComputedStyle(clone).height;
var testElement = document.getElementById('test');
setTimeout(function() {
testElement.className = 'showing';
}, 100);
//Clone the element
var clone = testElement.cloneNode();
//remove transition so we can get end height
clone.style.transition = "none";
clone.style.visibility = "hidden";
clone.style.position = "absolute";
clone.classList.add("showing");
var parent = testElement.parentNode;
parent.style.position = parent.style.position || "relative";
parent.appendChild(clone);
var endHeight = window.getComputedStyle(clone).height;
//Remove it as we dont need it anymore
clone.remove();
setTimeout(function() {
testElement.innerHTML = 'Height: ' + endHeight;
}, 300);
#parent {
height:300px;
}
#test {
width: 100px;
height: 0;
transition: height 2s ease-in-out;
background: #F00;
}
#test.showing {
height: 70%;
}
<div id="parent">
<div id="test"></div>
</div>
You can add an 'animationend' event listener to the element .
Example :
testElement.addEventListener('animationend' , showNewHeight);
showNewHeight function(){
// show new height ...do something after animation .
}
Source : http://www.w3schools.com/jsref/event_animationend.asp
hope this helps..
There is a problem in the onclick method, I want borders to be removed on all pictures except one when a new one is clicked
Error is: Uncaught TypeError: object is not a function
on line: images(i).style.display = "none";
<!DOCTYPE html>
<html>
<head>
</head>
<title></title>
<script>
var images = ['01.jpg', '02.jpg', '03.jpg', '04.jpg', '05.jpg', '06.jpg', '07.jpg', '08.jpg', '09.jpg', '10.jpg',
'11.jpg', '12.jpg', '13.jpg', '14.jpg', '15.jpg', '16.jpg', '17.jpg', '18.jpg', '19.jpg', '20.jpg',
'21.jpg', '22.jpg', '23.jpg', '24.jpg', '25.jpg', '26.jpg', '27.jpg', '28.jpg', '29.jpg', '30.jpg',
'31.jpg', '32.jpg', '33.jpg', '34.jpg', '35.jpg', '36.jpg', '37.jpg', '38.jpg', '39.jpg', '40.jpg'];
var end = 'cross.jpg';
//to change index in array to display
var first = 0;
var last = 4;
//sets border on image
function setUpImage(i){
var img = document.createElement('img')
img.src = images[i];
//adds image to screen
document.getElementById('content').appendChild(img);
img.onclick = function(){
//if it doesnt have a border
if(img.style.border != "10px solid blue"){
//puts a blue border around image
img.style.border = "10px solid blue";
//add padding
img.style.padding = "10px 10px 10px 10px";
for(var i=0; i<=images.length; i++){
images(i).style.display = "none";
}
}
}
}
</script>
<style>
#content{
width: 600px;
}
</style>
<body onload="buildImage();">
<div id="content"></div>
<button id="button" onclick="addImages()">More</button>
</body>
your problem is that you did not actually select the img elements but rather the string in you images[] array, you will want to give your images an id so you can select them later, then iterate through them like you were, like this:
//sets border on image
function setUpImage(i){
var img = document.createElement('img')
img.src = images[i];
img.id = images[i];
//adds image to screen
document.getElementById('content').appendChild(img);
img.onclick = function(){
//if it doesnt have a border
if(img.style.border != "10px solid blue"){
for(var i=0; i<=images.length; i++){
document.getElementById(image[i]).style.border = "initial";
}
//puts a blue border around image
img.style.border = "10px solid blue";
//add padding
img.style.padding = "10px 10px 10px 10px";
}
}
}
I would however recomment only using one onclick function and giving this function to the onclick event for each image, like this:
function imgClick(el){
//if it doesnt have a border
if(el.style.border != "10px solid blue"){
for(var i=0; i<=images.length; i++){
document.getElementById(image[i]).style.border = "initial";
}
//puts a blue border around image
el.style.border = "10px solid blue";
//add padding
el.style.padding = "10px 10px 10px 10px";
}
}
and
//sets border on image
function setUpImage(i){
var img = document.createElement('img')
img.src = images[i];
img.id = images[i];
//adds image to screen
document.getElementById('content').appendChild(img);
img.onclick = imgClick(this);
}
You make handy use of querySelectorAll, and CSS classes. In your CSS:
img.bordered { border: 1px solid black; }
And then you make use of this class in JavaScript via:
function clickHandler(evt) {
var container = ... || document.body;
var thisImage = evt.target;
var allImages = topelement.querySelectorAll("img");
// this is a NodeList, we want an array, so we convert:
allImages = [].slice.call(allImages);
allImages.forEach(function(img) {
if(img===thisImage)
return img.classList.remove("bordered");
img.classList.add("bordered");
});
}
And then you bind that function either in HTML:
<img src="..." onclick="clickHandler">
Or in your JS when you create the elements:
...
var img = document.createElement("img");
img.addEventListener("click", clickHandler);
img.src = ...;
container.appendChild(img);
...
Done. All images are now given a CSS class that gives than a border, unless it's the image you clicked, in which case the border class gets removed instead. (If you remove a class that wasn't there, nothing happens, and if you add a class that was already there, also nothing happens).
Note that container var, which should be the element that houses all the images you want to toggle. Generally you wouldn't want to apply this to every possible image on a page, but only a specific set of images.