dynamic or adaptable class in css - javascript

I have a problem where I will be displaying a variable number of items displayed, and they will have a margin setting which is updated uniformly over the set.
So basically to put it simple if I have a set that is [1,2,3,4,5] it might be something like:
1 2 3 4 5
while if the number of number were to double they would require the same amount of space:
1 2 3 4 5 6 7 8 9 10
I have some solutions for this but what hit me was that if I have an css-class (as the margin is uniform over the given set) I could share the layout. So I would have liked it if it were possible to update the class dynamically if that makes sense I haven't found any information of that being possible to do, so if we assume that in the first example the margin is something like margin-right: 10px; then if I could change the class, (similar to how I set style on an element I guess is how I am thinking, but for the whole class), it would be really smooth. So let's assume a functionality to do this I could have a class:
.myclass {
margin-right: 10px;
}
and through our magic function .myclass.setProperty('margin-right', '5px'); (or whatever the syntax would be :P). It would act as if i had defined the class:
.myclass {
margin-right: 5px;
}
I hope that is enough to grasp my ideas and problem thus far. The way I am going about it at the moment is that I use a class for all shared behavior and set style for each element. However this is a bit tedious as it become something like:
for (var i in mynumbers) {
mynumbers.style.marginRight = new_margin;
}
Where new_margin is calculated based on a scale (i.e. it could change many times in a short period of time).
So to the question-part. Is there perhaps a way to achieve something like the first part (a way to dynamically change a class), or any thoughts or ideas how to implement it if the way I am doing it feels like a bad idea or if you feel there are better ways of handling this.
Thanks for reading and hope you find the problem interesting.

Ah, just another typical use case of flex layout:
.container {
display: flex;
border: 1px solid;
justify-content: space-between;
}
<h2>5 elements in a line with equal width gaps</h2>
<div class="container">
<span>1</span><span>2</span><span>3</span><span>4</span><span>5</span>
</div>
<h2>10 elements in a line with equal width gaps</h2>
<div class="container">
<span>1</span><span>2</span><span>3</span><span>4</span><span>5</span>
<span>6</span><span>7</span><span>8</span><span>9</span><span>10</span>
</div>
If your browser supports the feature, you would see something like this:
Here for browser compatibility.
EDIT: another interesting use case, although OP didn't ask about:
.container {
display: flex;
border: 1px solid;
justify-content: space-between;
}
.container:before, .container:after {
content: '';
width: 0;
}
<h2>5 elements in a line with equal width gaps</h2>
<div class="container">
<span>1</span><span>2</span><span>3</span><span>4</span><span>5</span>
</div>
<h2>10 elements in a line with equal width gaps</h2>
<div class="container">
<span>1</span><span>2</span><span>3</span><span>4</span><span>5</span>
<span>6</span><span>7</span><span>8</span><span>9</span><span>10</span>
</div>
If your browser supports the feature, you would see something like this:
Space is divided equally not only between elements, but also include both ends of the container. And you could see how simple the code is!

This sounds like a job for table-layout: fixed. Your browser computes the width of each "column" (element) in the first "table-row" based on the number of columns in the "table".
.table {
display: table;
table-layout: fixed;
width: 100%;
}
.table > span {
display: table-cell;
text-align: center;
}
<div class="table">
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>5</span>
<span>6</span>
<span>7</span>
<span>8</span>
<span>9</span>
</div>
<div class="table">
<span>1</span>
<span>2</span>
<span>3</span>
<span>4</span>
<span>5</span>
</div>

Yes. This is possible. One thing to be aware of is that changing a class's property may cause the browser's renderer to recalculate the entire page's layout (it needs to figure out how your class change affects the overall layout). So if you plan on changing your margin-right in a way to animate the change, it's not going to perform very well depending on the complexity of your page. That said, here is a quick and dirty implementation that should work on everything IE9+:
<html>
<head>
<style>
.thing {
display: inline-block;
width: 20px;
height: 20px;
background: #f00;
}
</style>
</head>
<body>
<div>
<div class="thing myClass"></div>
<div class="thing myClass"></div>
<div class="thing myClass"></div>
<div class="thing myClass"></div>
<div class="thing myClass"></div>
<div class="thing myClass"></div>
</div>
<div>
<button id="doit">Make bigger</button>
</div>
</body>
<script>
var styleTag = document.createElement("style"),
styleSheet, index, cssRule, style;
// Create a <style> tag that will hold our CSS rule
document.head.appendChild(styleTag);
styleSheet = styleTag.sheet;
// Insert an empty .myClass rule into the style sheet
index = styleSheet.insertRule(".myClass {}", styleSheet.cssRules.length);
// Get the 'style' object from the rule. This is nearly identical to elem.style
cssRule = styleSheet.cssRules[index];
style = cssRule.style;
// Sets .myClass { margin-right: 5px; }
style.marginRight = "5px";
// Demo to show that it works when you click a button
document.querySelector("#doit").addEventListener("click", function() {
style.marginRight = "20px";
});
</script>
</html>

Related

How do I align the content of two divs when the data in those divs may change?

I've got two Divs, one holds temperature information, the other humidity.
<div class="weatherwrap">
<div class="tempwrap" title="Current Temperature">
<span id=tempinfo><javascript injected data></span>
</div>
<div class="humidwrap" title="Current Humidity">
<span id="humidinfo"><javascript injected data></i></span>
</div>
</div>
Right now, they render like this:
I'd really prefer it if they always aligned by the decimal point (.), as this consistently creates the most pleasing visual.
However, if the number changes, say - the temperature raises into the positive, or humidity drops by a half percentage point, these two divs will be aligned differently, again. How can I ensure that these two divs will align themselves the most optimal way, even if the length of the information inside them is to change?
I've tried hard coding it, and wrote some very bad JavaScript that adds padding to one based on the length of the other, but I'm not satisfied of the reliability of either solutions.
You can align on the period. Use something like below:
#container {
display: flex;
flex-flow: column nowrap;
outline: 1px black dotted;
}
#container > div {
display: flex;
}
.a {
width: 48px;
text-align:right;
}
.b {
}
.c {
width: 48px;
}
<div id=container>
<div>
<div class=a>12</div><div class=b>.</div><div class=c>12</div>
</div>
<div>
<div class=a>1234</div><div class=b>.</div><div class=c>12</div>
</div>
<div>
<div class=a>12</div><div class=b>.</div><div class=c>1234</div>
</div>
<div>
<div class=a>123456</div><div class=b>.</div><div class=c>12</div>
</div>
</div>

Is it possible to remove an html element and keep your children with javascript?

I have the following structure .. I would like to remove div.son but keepdiv.grandson, is that possible ?! or changing your <tag> would also be a solution .. ex: changing from <fieldset> to a <div>, remembering that I do not have access to HTML, every change must be done using ** javascript **!
<div class="father">
<fieldset class="son">
<div class="grandson">Content here</div>
<div class="grandson">Content here</div>
<div class="grandson">Content here</div>
<div class="grandson">Content here</div>
</fieldset>
</div>
I tried to use the removeChild () function of ** javascript **, but it removes the entire element.
It's possible with vanilla JavaScript by deep cloning the node of grandson before removing anything else. and then appending it back to the parent. Of course if you want to place it somewhere else, you need to append needed logic of DOM traversing. (CSS section is only for visual validation of the result)
const grandson = document.querySelector('.grandson');
const father = grandson.closest('.father');
const clonedGrandson = grandson.cloneNode(true);
father.querySelector('.son').remove();
father.appendChild(clonedGrandson);
.father {
background-color: red;
padding: 20px;
}
.son {
background-color: blue;
padding: 20px;
}
.grandson {
background-color: green;
padding: 20px;
}
<div class="father">
<fieldset class="son">
<div class="grandson">
<p>Save me</p>
</div>
</fieldset>
</div>
You may take a look at this answer, try to use the search bar next time.
https://stackoverflow.com/a/170056/10944905
In case you just want to jump all over the answer.
var cnt = $(".remove-just-this").contents();
$(".remove-just-this").replaceWith(cnt);

How to Center Text in a JavaScript Function?

I have a JavaScript function that displays text based on input in a text field. When a value is entered into the text field, my program will check to see if the value is correct. If it is correct, my program displays, "You are correct!" and if it is incorrect, my program displays, "Try again!"
The text field and button are both centered horizontally on the page, but I cannot figure out how to center the "You are correct!" and "Try again!"
I feel like I have tried everything, but obviously I haven't, considering I can't get it to work.
Here is the code for my JavaScript function:
<center><p>Can you remember how many books I listed at the bottom of the page?</p></center>
<center><input id="numb"></center>
<center><button type="button" onclick="myFunction()">Submit</button></center>
<p id="demo"></p>
<div class="jsFunction">
<script>
function myFunction()
{
var x, text;
// Get the value of the input field with id="numb"
x = document.getElementById("numb").value;
// If x is Not a Number or less than five or greater than five
if (isNaN(x) || x < 5 || x > 5)
{
text = "Try again!";
}
else
{
text = "You are correct!";
}
document.getElementById("demo").innerHTML = text;
}
</script>
</div>
Here is the CSS code for the function:
.jsFunction
{
margin-left: auto;
margin-right: auto;
}
This specific CSS code is only one of many, many attempts I have made at centering the text in the function.
Here is a link to a picture that will show you the problem I am having:
http://i.stack.imgur.com/Hb01j.png
Please help!
Try setting a class on the p tag that contains text-align: center;
Edit
Nesting your script in a div is meaningless as script tags don't get rendered
You can either target #demo in your css (for the text alignment) or add a class align-center that contains the correct style.
I would recommend the latter as the becomes more reusable, whereas you can't reuse an id on the same page
The fact that you are using JavaScript isn't important to this question. I mention it because of the title "How to Center Text in a JavaScript Function" and your attempt to center the actual script element containing your JavaScript code.
You want to center the contents of an element that happens to be controlled by JavaScript, but the answer is CSS-only.
As Ryuu's answer mentions, text-align: center will do the job for (you guessed it) text and other inline-level content.
You should not use the deprecated center tag.
Your attempt to use margins will center something if you apply it to the correct element and the element has a width. That "something" is the element, however, not the contents of the element.
In other words, margin can be used to align the box, not the stuff within the box.
Example 1: centers the element, but the text is still left-aligned.
Example 2: centers the element and its inline-level contents.
.margin-example1 {
width: 200px;
background-color: #ddd;
/* shorthand for margin: 0 auto 0 auto, which is shorthand for specifying each side individually */
margin: 0 auto;
}
.margin-example2 {
width: 200px;
background-color: #aaccee;
margin: 0 auto;
/* we still need this to get the desired behavior */
text-align: center;
}
<div class="margin-example1">Example 1</div>
<div class="margin-example2">Example 2</div>
So how about a text input? Browsers usually style inputs as display:inline-block. This means we can center something inside them (Examples 1 & 2), but to center them within their container we need to change to display:block (Example 3) or because they are inline-like elements themselves, we can set text-align on the parent container (Example 4), see also.
.example1 {
width: 100%;
text-align: center;
}
.example2 {
width: 200px;
text-align: center;
}
.example3 {
display: block;
width: 200px;
text-align: center;
margin: 0 auto;
}
.example4 {
width: 200px;
text-align: center;
}
.example4-parent {
text-align: center;
}
<div>
<input type="text" value="Example 1" class="example1">
</div>
<div>
<input type="text" value="Example 2" class="example2">
</div>
<div>
<input type="text" value="Example 3" class="example3">
</div>
<div class="example4-parent">
<input type="text" value="Example 4" class="example4">
</div>
Layout in CSS can be complicated, but the basics aren't hard.
Note that I have over-simplified my explanation/definitions a bit (you can read all about the formatting model when you are ready).

HTML objects growing and pushing others

How could I make it so that given two elements let's say these boxes:
If I clicked over one, it would grow, and the other would shrink like and vice versa:
How can I do this?
I have seen this sort of done with CSS, using the focus tag and adjusting the width. But I have two problems there, first how could I affect the other element, and second as far as I can tell adjusting width will only stretch them right. I have seen people change the way they float the elements to deal with that, but I don't want to move them around the page to do this.
Here are 2 examples without Javascript/jQuery:
Pure CSS - Trigger on click: (example)
Using the checkbox hack in CSS you can effectively toggle the widths of the elements when the checkbox is :checked. Here is what part of the CSS looks like:
input[type=checkbox]:checked ~ .red {
width:70%;
}
input[type=checkbox]:checked ~ .green {
width:20%;
}
Go to the example for the full CSS.
HTML
<input type="checkbox" id="toggle" />
<div class="red">
<label for="toggle"></label>
</div>
<div class="green">
<label for="toggle"></label>
</div>
You might also be interested in the original example I made. It takes a different approach, though it doesn't fully work.
Pure CSS - Trigger on hover: (example)
Unfortunately, neither the adjacent selector, nor the general sibling selector can select previous elements, therefore it makes this a little difficult. I placed 2 general elements before the main elements in order to somewhat solve this issue.
.greenS:hover, .greenS:hover ~ .green,
.redS:hover, .redS:hover ~ .red {
width:72%;
}
.greenS:hover ~ .redS, .greenS:hover ~ .red,
.redS:hover ~ .greenS, .redS:hover ~ .green {
width:22%;
}
HTML
<div class="redS"></div><div class="greenS"></div>
<div class="red"></div>
<div class="green"></div>
Since this was tagged as JS/jQuery, here are 2 alternative solutions.
JS/jQuery - Trigger on click: (example)
$('.red, .green').click(function(){
$('.red').toggleClass('expanded')
.next('.green').toggleClass('contracted');
});
JS/jQuery - Trigger on hover: (example)
$('.red').hover(function(){
$(this).toggleClass('expanded')
.next('.green').toggleClass('contracted');
});
$('.green').hover(function(){
$(this).toggleClass('expanded')
.prev('.red').toggleClass('contracted');
});
See jQuery .animate() method documentation.
Example on jsfiddle:
.box {
width: 100px;
height: 100px;
display: inline-block;
}
#box1 {
background: red;
}
#box2 {
background: blue;
}
<div class="box" id="box1"></div>
<div class="box" id="box2"></div>
$('.box').click(function() {
var currentWidth = $(this).outerWidth(),
siblingCurrentWidth = $(this).siblings('.box').outerWidth();
$(this).animate({'width' : currentWidth/2})
.siblings('.box').animate({'width' : siblingCurrentWidth*2});
});
This is a very simple example with several flaws, but it demonstrates a possibility for what your purpose is.
Simple example http://jsfiddle.net/PeLub/ ( modify how you need) .
<div class="box" id="first"></div>
<div class="box" id="second"></div>
$("#first").click(function(){
$(this).animate({width:'50px'}, 500);
$("#second").animate({width:'150px'}, 500);
});
$("#second").click(function(){
$(this).animate({width:'50px'}, 500);
$("#first").animate({width:'150px'}, 500);
});

show / hide DOM elements in all browsers

I have something very simple but I can not make it work correctly in Webkit and Mozilla
This is my HTML
<li style="padding-bottom: 10px;" class='product'>
<span class ='handle' style="cursor:move; float:left; margin-top:40px; margin-right:8px; margin-bottom:30px; display:none;">
<%= image_tag "page/arrow.png"%>
</span>
<table >
<tr style="border:5px; solid: #444">
<td class="product_contents" style="vertical-align: top;" >
<div class="product_contents" style="width: 480px; font-size: 100%; font-weight: bold; color: #333; margin-bottom: 10px; word-wrap: break-word; overflow: auto;">
STUFF HERE
</div>
<p class="product_contents" style="width: 480px; font-size: 93%; line-height: 150%; word-wrap: break-word; overflow: auto;">
MORE STUFF HERE
</p>
</td>
</tr>
</table>
</li>
And this is my JQuery:
jQuery(function($) {
$(".product").mouseenter(
function () {
$(this).find(".handle").css('display', 'inline'); //show();
$(this).css('background-color','#fffdef');
$(this).find(".product_contents").css('width', '450px');
});
$(".product").mouseleave(
function () {
$(this).find(".handle").css('display', 'none'); //.hide();
$(this).css('background-color','#ffffff');
$(this).find(".product_contents").css('width', '480px');
});
});
Nothing fancy here at all and it works as I expect in Firefox. The image in handle appears on the left and it displaces the content to the right, the content also change colors and size to match the image. PErfect.
But in Webkit it changes the color and the size but there is no displacement. What I want to achieve is pretty basic, there is a better approach?
I can use Jquery but I can not use any plugin.
I'm not sure if I understood your problem right, but I would recommend to try jQuery's show/hide functions:
$(this).find(".handle").show();
$(this).find(".handle").hide();
This one works for me in Firefox, and fails for Conkeror (which was surprising), and fails for SRWare Iron (which is a Chrome-based browser).
The problem seems to be related to the fact that the table is inside a <li> element. For some reason, Firefox treats this table as an inline element, and the other browsers as a block element. Since it is a block element, the table is pushed to the next line, and is not displaced, because the handle is on the previous line. Changing the display style of the table to inline-table fixed the issue for me.
You can hide an element by using the CSS display property and setting it to none.
$("element").style.display = "none"; // hide element
$("element").style.display = "block"; // show element (or inline)

Categories