Detecting last item with display flex - javascript

Following having applied display flex/ display none with javascript, I want a function that detects the last item that contains display flex, in my example that would be the letter B.
Example code:
const containerDiv = document.querySelector('.container');
const listArray = Array.from(containerDiv.children);
listArray.forEach((item) => {
if(item.innerHTML === "A" || item.innerHTML === "B"){
item.style.display = "flex";
} else {
item.style.display = "none";
}
});
<div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
</div>
Any ideas?

Instead of use inline css you can use class and querySelectorAll for catch last item with .flex class
const containerDiv = document.querySelector('.container');
const listArray = Array.from(containerDiv.children);
listArray.forEach((item) => {
if(item.innerHTML === "A" || item.innerHTML === "B"){
item.classList.add("flex");
} else {
item.classList.add("none");
}
});
const divFlex = [...containerDiv.querySelectorAll('div.flex')];
console.log(divFlex[divFlex.length - 1])
.flex{
display:flex;
}
.none{
display:none;
}
<div class="container">
<div class="item">A</div>
<div class="item">B</div>
<div class="item">C</div>
</div>

Related

Condition if multiple elements have a class

I have this HTML:
<div>
<button type="button" id="a"></button>
</div>
<div>
<button type="button" id="b"></button>
</div>
<div>
<button type="button" id="c"></button>
</div>
<div class="hidden" id="a1">
<p>text1</p>
</div>
<div class="hidden" id="b1">
<p>text2</p>
</div>
<div class="hidden" id="c1">
<p>text3</p>
</div>
<div class="hidden" id ="content">
<p>text4</p>
</div>
and CSS:
.hidden {
display: none}
.shows {
display: block}
I want that if I press "a" shows "a1" and "content", b shows "b1" and "content"...
const a = document.getElementById("a")
const b = document.getElementById("b")
const c = document.getElementById("c")
const a1 = document.getElementById("a1")
const b1 = document.getElementById("b1")
const c1 = document.getElementById("c1")
const content = document.getElementById("content")
a.addEventListener('click', function (event) {
if (content.className === "hidden") {
content.className += " shows";
}
if (a1.className === "hidden") {
a1.className += " shows";
} else {
a1.className = "hidden";
}
b.addEventListener('click', function (event) {
if (content.className === "hidden") {
content.className += " shows";
}
if (b1.className === "hidden") {
b1.className += " shows";
} else {
b1.className = "hidden";
}
c.addEventListener('click', function (event) {
if (content.className === "hidden") {
content.className += " shows";
}
if (c1.className === "hidden") {
c1.className += " shows";
} else {
c1.className = "hidden";
}
but i want that when i press one button and all buttons are hidden "content" is hidden too, i know a way to make this is adding this code of each "click"
if (a1.className === "hidden" && b1.className === "hidden" && c1.className === "hidden") {
content.classList.remove("shows");
}
Nut I need another way to make it because I have to add a button each x days... may be adding an array with all buttons
const d1 = [a1, b1, c1]
and add a for in each "click" but I don't know how to do it.
Your question isn't completely clear. Do you mean something like this?
[...document.querySelectorAll("button")].forEach(function(button) {
button.addEventListener("click", function(evt) {
var element = document.getElementById(event.target.id + "1")
if (element.style.display == "block") {
element.style.display = "none";
} else {
element.style.display = "block";
document.getElementById("content").style.display = "block";
}
if (document.getElementById("a1").style.display == "none" && document.getElementById("b1").style.display == "none" && document.getElementById("c1").style.display == "none") {
document.getElementById("content").style.display = "none"
}
})
})
<div>
<button type="button" id="a">a</button>
</div>
<div>
<button type="button" id="b">b</button>
</div>
<div>
<button type="button" id="c">c</button>
</div>
<div id="a1" style="display:none;">
<p>text1</p>
</div>
<div id="b1" style="display:none;">
<p>text2</p>
</div>
<div id="c1" style="display:none;">
<p>text3</p>
</div>
<div id="content" style="display:none;">
<p>text4</p>
</div>

I want to make a stepper component

I want to hide prev btn and the other words
But I want to show them and prev btn one by one when I press next button and display finish btn i am on the latest word.
The buttons, prev, next and finish do the things which are not the same when I have finish button I want to post the words.
I tried many time but not worked. Here is my code that I've tried:
function nextBtn() {
var itemOne = document.getElementById("step-1");
var itemTwo = document.getElementById("step-2");
var itemThree = document.getElementById("step-3");
var itemFour = document.getElementById("step-4");
var prevBtn = document.getElementById("prevBtn");
var nextBtn = document.getElementById("nextBtn");
if (itemOne.style.display == "block" && itemTwo.style.display == "none" && prevBtn.style.display == "none") {
itemOne.style.display = "none";
itemTwo.style.display = "block";
prevBtn.style.display = "block";
}
else {
console.log('Xatolik ishlamayapti');
}
}
#step-1 {
display: block;
}
#step-2 {
display: none;
}
#step-3 {
display: none;
}
#step-4 {
display: none;
}
#prevBtn {
display: none;
}
#nextBtn {
display: block;
}
<div class="step-container">
<div id="step-1">Hello</div>
<div id="step-2">Hi</div>
<div id="step-3">Salom</div>
<div id="step-4">Molas</div>
<button id="prevBtn" #click="prevBtn()">back</button>
<button id="nextBtn" #click="nextBtn()">next</button>
</div>
What's wrong at above link.
Thank you in advance.
The main problem with your approach is that itemOne.style.display == "block" will not evaluate to true because it doesn't consider that the node has some css set externally.
It would make more sense to use html classes for your step divs so that you can select them all at once with querySelectorAll().
The logic would be easier to manage if you use a variable to track which number step is the current step.
Then you can just increase and decrease the variable each time you click on either the previous or next buttons.
const allSteps = document.querySelectorAll('.step')
const totalSteps = allSteps.length
const prevButton = document.querySelector('#prevBtn')
const nextButton = document.querySelector('#nextBtn')
const finishButton = document.querySelector('#finishBtn')
// Hide everything except for #step-1
document
.querySelectorAll(".step:not(#step-1)")
.forEach(step => (step.style.display = "none"))
// Hide the prev button
prevButton.style.display = 'none'
// Hide the finish button
finishButton.style.display = 'none'
let currentStep = 1
function nextBtn() {
currentStep++;
refreshDisplay()
}
function prevBtn() {
currentStep--;
refreshDisplay()
}
function refreshDisplay() {
// hide every step
allSteps.forEach(step => (step.style.display = "none"))
// show only the currentStep
document.querySelector(`#step-${currentStep}`).style.display = 'block'
// hide or show the prevButton
if (currentStep === 1) {
prevButton.style.display = 'none'
} else {
prevButton.style.display = 'inline-block'
}
// hide or show nextButton & finish button
if (currentStep === totalSteps) {
nextButton.style.display = 'none'
finishButton.style.display = 'inline-block'
} else {
nextButton.style.display = 'inline-block'
finishButton.style.display = 'none'
}
}
function finish() {
console.log('you are finished')
}
<div class="step-container">
<div class="step" id="step-1">Hello</div>
<div class="step" id="step-2">Hi</div>
<div class="step" id="step-3">Salom</div>
<div class="step" id="step-4">Molas</div>
<button id="prevBtn" onclick="prevBtn()">back</button>
<button id="nextBtn" onclick="nextBtn()">next</button>
<button id="finishBtn" onclick="finish()">finish</button>
</div>
Something like this?
var activeButton = 0;
function next() {
document.getElementById(activeButton).classList.remove('active');
activeButton++;
document.getElementById(activeButton).classList.add('active');
}
function previous() {
document.getElementById(activeButton).classList.remove('active');
activeButton--;
document.getElementById(activeButton).classList.add('active');
}
.step {
display: none;
}
.active {
display: inline;
}
<button id="0" class="active step">First</button>
<button id="1" class="step">Second</button>
<button id="2" class="step">Third</button>
<button id="3" class="step">Fourth</button>
<button id="4" class="step">Fifth</button>
<button id="5" class="step">Sixth</button>
<button id="6" class="step">Seventh</button>
<hr>
<button id="next" onclick="next()">Next</button>
<button id="next" onclick="previous()">Previous</button>

Keep element in the bottom of dynamically changing panel

I'm using bootstrap and i have text fields which will make panel larger as they're added dynamically. Now these text fields are inside of a panel element and textfield size is col-lg-9 and there's more room in the col-lg-3 right next to it.
I would like to place a button in that col-lg-3 div, which would stay always in the bottom of the panel - so if the panel height increases due to new text field the button stays still in the bottom. I've tried absolute and relative positioning but nothing has helped + some of the methods pointed out break the scalability (which i really need to keep).
I'm adding my code:
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title panel-header-text">Sisesta nimed, mis pannakse tabelisse</h3>
</div>
<div class="panel-body">
<div class="col-lg-9" id="inputcontainer">
<h4>Sisestamisel tekib uus väli (TAB-iga saab vahetada rida). Tühjasid välju ei arvestata!</h4>
<div class="input-group input-group-lg pdgtop">
<span class="input-group-addon" id="basic-addon1">1.</span>
<input type="text" id="one" class="form-control text-controller" placeholder="Sisesta nimi siia">
</div>
</div>
<div class="col-lg-3 konteiner">
<button type="button" class="btn btn-success buttonel">Valmista tabel</button>
</div>
</div>
The javascript:
/*
#FN01: This function handles the creation of new text fields according to the change in the textfield.
*/
var createNew = true;
var counter = 2;
function getNewInsertion() {
var container = document.getElementById("inputcontainer");
var inputs = document.getElementsByClassName("text-controller");
var lastField = inputs[inputs.length-1];
if (document.activeElement.value.length == 0 && createNew == false){ //if new element is chosen createNew will be set true
createNew = true;
}
else if (createNew == true && lastField.value.localeCompare("") != 0 ){
createNew = false;
//Creates Input Field
var input = document.createElement("input");
input.type = "text";
input.className = "form-control text-controller";
input.placeholder = "Sisesta siia nimi";
//Creates Span to hold the count
var span = document.createElement("span");
span.textContent = counter;
span.className = "input-group-addon";
//Creates input group to put span & input field together
var inputgroup = document.createElement("div");
inputgroup.className = "input-group input-group-lg";
inputgroup.appendChild(span);
inputgroup.appendChild(input);
container.appendChild(inputgroup);
counter += 1;
}
return createNew;
}
/*
#FN02: This is the function to delete the last field (empty) in case the one before last is empty.
*/
function canWeDeleteField(){
var inputs = document.getElementsByClassName("input-group");
var lastInput = inputs[inputs.length-1];
var lastArr = lastInput.childNodes
if (inputs.length < 2){
var last = lastArr[3];
}
else{
var last = lastArr[1];
}
console.log(lastArr);
if (inputs.length >= 2){
var last_prev_Input = inputs[inputs.length-2];
var last_prev_Arr = last_prev_Input.childNodes
if (inputs.length == 2){
var last_prev = last_prev_Arr[3];
}
else{
var last_prev = last_prev_Arr[1];
}
if (last.value.localeCompare("") == 0 && last_prev.value.localeCompare("") == 0){
lastInput.parentNode.removeChild(lastInput);
counter = counter - 1;
}
}
}
/*
#FN03: The call-out function which is triggered when key is pressed while focus is on the textfield.
*/
$(function() {
$("#inputcontainer").bind("paste cut keydown",function(e) {
getNewInsertion();
canWeDeleteField();
})
});
AND THE CSS:
.konteiner {
position: relative;
}
.buttonel {
width: 95%;
padding-right: 1%;
position: absolute;
}
You can check the solution to your problem in the following link Bootstrap equal-height columns experiment.
Basically you have to wrap your columns in a div element containing the classes "row" and "row-eq-height".
Here's a snippet of the result (using your code):
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<link rel="stylesheet" href="http://getbootstrap.com/dist/css/bootstrap.min.css">
<style type="text/css">
.row-eq-height {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
}
.buttonel {
position: absolute;
bottom: 0;
}
</style>
</head>
<body>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title panel-header-text">Sisesta nimed, mis pannakse tabelisse</h3>
</div>
<div class="panel-body">
<div class="row row-eq-height">
<div class="col-lg-9 col-md-9" id="inputcontainer">
<h4>Sisestamisel tekib uus väli (TAB-iga saab vahetada rida). Tühjasid välju ei arvestata!</h4>
<div class="input-group input-group-lg pdgtop">
<span class="input-group-addon" id="basic-addon1">1.</span>
<input type="text" id="one" class="form-control text-controller" placeholder="Sisesta nimi siia">
</div>
</div>
<div class="col-lg-3 col-md-3">
<button type="button" class="btn btn-success buttonel">Valmista tabel</button>
</div>
</div>
</div>
</div>
<script type="text/javascript">
var createNew = true;
var counter = 2;
function getNewInsertion() {
var container = document.getElementById("inputcontainer");
var inputs = document.getElementsByClassName("text-controller");
var lastField = inputs[inputs.length - 1];
if (document.activeElement.value.length == 0 && createNew == false) { //if new element is chosen createNew will be set true
createNew = true;
} else if (createNew == true && lastField.value.localeCompare("") != 0) {
createNew = false;
//Creates Input Field
var input = document.createElement("input");
input.type = "text";
input.className = "form-control text-controller";
input.placeholder = "Sisesta siia nimi";
//Creates Span to hold the count
var span = document.createElement("span");
span.textContent = counter;
span.className = "input-group-addon";
//Creates input group to put span & input field together
var inputgroup = document.createElement("div");
inputgroup.className = "input-group input-group-lg";
inputgroup.appendChild(span);
inputgroup.appendChild(input);
container.appendChild(inputgroup);
counter += 1;
}
return createNew;
}
/*
#FN02: This is the function to delete the last field (empty) in case the one before last is empty.
*/
function canWeDeleteField() {
var inputs = document.getElementsByClassName("input-group");
var lastInput = inputs[inputs.length - 1];
var lastArr = lastInput.childNodes
if (inputs.length < 2) {
var last = lastArr[3];
} else {
var last = lastArr[1];
}
console.log(lastArr);
if (inputs.length >= 2) {
var last_prev_Input = inputs[inputs.length - 2];
var last_prev_Arr = last_prev_Input.childNodes
if (inputs.length == 2) {
var last_prev = last_prev_Arr[3];
} else {
var last_prev = last_prev_Arr[1];
}
if (last.value.localeCompare("") == 0 && last_prev.value.localeCompare("") == 0) {
lastInput.parentNode.removeChild(lastInput);
counter = counter - 1;
}
}
}
/*
#FN03: The call-out function which is triggered when key is pressed while focus is on the textfield.
*/
$(function() {
$("#inputcontainer").bind("paste cut keydown", function(e) {
getNewInsertion();
canWeDeleteField();
})
});
</script>
</body>
</html>
Hope it helps!

Div tabs with Javascript

I organized my tabs this way:
<ul id="tabs">
<li class="selected">DIV1</li>
<li class>DIV2</li>
<li class>DIV3</li>
</ul>
<div id="tabs_content">
<div id="div1" style="display: block;"><textarea name="div1" rows="7" cols="108"></textarea></div>
<div id="div2" style="display: none;"><textarea name="div2" rows="7" cols="108"></textarea></div>
<div id="div3" style="display: none;"><textarea name="div3" rows="7" cols="108"></textarea></div>
</div>
I would like that when I press one of the link inside the <li> element,
the corrispondend Div become visible with display: block and the others are changed to display: none
Also I would like to do the same with the "selected" class on the clicked <li> element.
Is this possible?
I tried with:
function selectTab(src)
{
document.getElementById('div1').style.display = 'none';
document.getElementById('div2').style.display = 'none';
document.getElementById('div3').style.display = 'none';
document.getElementById(src).style.display = 'block';
}
It works if I pass the ID by reference with onclick="" but I would like to avoid this.
Solution:
function selectTab(source, parent)
{
document.getElementById('div1').style.display = 'none';
document.getElementById('div2').style.display = 'none';
document.getElementById('div3').style.display = 'none';
document.getElementById(source).style.display = 'block';
var elements = [].slice.apply(document.getElementsByClassName('selected'));
for (var i = 0; i < elements.length; i++) {
elements[i].className = '';
}
parent.className = 'selected';
}
Possibly this is what you want, cross-browser (IE5.5+)
CSS
.selected {
background-color: green;
}
.hide {
display: none;
}
HTML
<ul id="tabs">
<li class="selected">DIV1
</li>
<li class>DIV2
</li>
<li class>DIV3
</li>
</ul>
<div id="tabs_content">
<div id="div1">
<textarea name="div1" rows="7" cols="108"></textarea>
</div>
<div id="div2" class="hide">
<textarea name="div2" rows="7" cols="108"></textarea>
</div>
<div id="div3" class="hide">
<textarea name="div3" rows="7" cols="108"></textarea>
</div>
</div>
javascript
var tabs = document.getElementById("tabs"),
tabs_content = document.getElementById("tabs_content"),
divs = tabs_content.getElementsByTagName("div"),
divsLength = divs.length,
lis = tabs.getElementsByTagName("li"),
lisLength = lis.length;
tabs.onclick = function (evt) {
var e = evt || window.event,
target = e.target || e.srcElement,
href,
id,
index,
div;
if (target.tagName.toUpperCase() === "A") {
for (index = 0; index < lisLength; index += 1) {
lis[index].className = "";
}
target.parentNode.className = "selected";
href = target.attributes.href.nodeValue;
if (href && href.charAt(0) === "#") {
id = href.slice(1);
for (index = 0; index < divsLength; index += 1) {
div = divs[index];
if (id === div.id) {
div.className = "";
} else {
div.className = "hide";
}
}
}
}
};
jsfiddle
Your selectTab function needs to be necessarily bound to the click event on those list elements. There's no other way you can do it. Your code is good enough. You can simplify things using JQuery as well, as some other answer here points out.
Okay, do this:
In your HTML, add "tab" class to each of the tags.
<li class="selected"><a class="tab" href="#div1">DIV1</a></li>
<li class><a class="tab" href="#div2">DIV2</a></li>
<li class><a class="tab" href="#div3">DIV3</a></li>
In your jquery,
$('.tab').click(function(){
var displaydiv = $(this).attr('href');
$('#div1').hide();
$('#div2').hide();
$('#div3').hide();
$(this).show();
$('"'+displaydiv+'"').show();
$(this).parent().attr('class','selected');
})
<ul id="tabs">
<li class="selected"><a onclick="showTab(this);" href="#div1">DIV1</a></li>
<li><a onclick="showTab(this);" href="#div2">DIV2</a></li>
<li><a onclick="showTab(this);" href="#div3">DIV3</a></li>
</ul>
<div id="tabs_content">
<div id="div1" style="display: block;"><textarea name="div1" rows="7" cols="108"></textarea></div>
<div id="div2" style="display: none;"><textarea name="div2" rows="7" cols="108"></textarea></div>
<div id="div3" style="display: none;"><textarea name="div3" rows="7" cols="108"></textarea></div>
</div>
Use the following javascript:
function showTab(a)
{
var id = a.href.replace('#','');
var tabs = document.getElementById('tabs_content').getElementsByTagName('div');
var index = -1;
for(var i=0,n=tabs.length;i<n;i+=1)
{
var t = tabs[i];
if(t.id === id)
{
t.style.display = 'block';
index = i;
}
else
{
t.style.display = 'none';
}
}
var links = document.getElementById('tabs').getElementsByTagName('li');
for(var i=0,n=links.length;i<n;i+=1)
{
links[i].setAttribute('class', index === i ? 'selected' : '');
}
}
Of course you could also first cache your menu and tabs, that way you can keep a variable. This is the proper way:
function Menu()
{
var self = this;
self.links = document.getElementById('tabs').getElementsByTagName('a');
self.tabs = document.getElementById('tabs_content').getElementsByTagName('div');
self.selectedIndex = 0;
self.n = self.links.length;
for(var i=0;i<self.n;i+=1)
{
// Set onclick for every link in the tabs-menu
self.links[i].onclick = function(ind){return function(){self.update(ind);};}(i);
}
self.update = function(ind)
{
// Hide previous tab
self.links[self.selectedIndex].parentNode.setAttribute('class', '');
self.tabs[self.selectedIndex].style.display = 'none';
// Select and show clicked tab
self.selectedIndex = ind;
self.links[self.selectedIndex].parentNode.setAttribute('class', 'selected');
self.tabs[self.selectedIndex].style.display = 'block';
};
}
setTimeout(function(){new Menu();},1);
Check out the jsfiddle for the Menu class in action: http://jsfiddle.net/3vf4A/1/. Note that even if Javascript is disabled, the a-tag will still get you to the correct area by scrolling to it automatically.

How to get elements by style property value?

I need to get all div elements with "display: none" style and then remove all of these elements. Also i need to select just that divs which are contained in #somecontainer element. Have to do it in RAW javascript. Any idea?
example html:
<table id="listtabletemp">
<thead>
<tr id="theader">
<td id="theaderleft">loolz</td>
</tr>
</thead>
<tbody>
<tr class="" rel="13117025">
<td><div><style>
.ikthgjyhtr{display:none}
.tVOx{display:inline}
</style>
<div style="display:none">crap here</div>
<div></div>
<div></div>
<div style="display:none">crap here</div>
<div class="230">something good</div>
<div class="ikthgjyhtr">crap here</div>
<div style="display:none">crap here</div>
<div class="ikthgjyhtr">crap here</div>
<div style="display: inline">something good</div>something good
<div style="display: inline">something good</div>
<div class="21">something good</div>
<div style="display:none">crap here</div>
<div style="display:none">crap here</div>
<div style="display:none">crap here</div>
<div class="4">something good</div>
<div class="224">something good</div></div>
</td>
</tr>
</tbody>
</table>
Simple, the DOM is your friend:
function removeDivs() {
var container = document.getElementById("somecontainer");
var divs = container.getElementsByTagName("div");
var empty = [];
var getStyle = function(obj, css){
var style = null;
if(obj.currentStyle) {
style = obj.currentStyle[css];
} else if(window.getComputedStyle) {
style = window.getComputedStyle(obj, null).getPropertyValue(css);
}
return(style);
};
for(var i = 0, len = divs.length; i < len; i++) {
var div = divs[i];
if(div && ((div.style.display && div.style.display == "none") || getStyle(div, "display") == "none")) {
empty.push(div);
}
}
for(var i = 0, len = empty.length; i < len; i++) {
var div = empty[i];
div.parentNode.removeChild(div);
}
}
Quick and dirty, here's something to get you started:
http://jsfiddle.net/kttsJ/
var parent = document.getElementById('parent');
var items = parent.getElementsByTagName('DIV');
var hidden = [];
for (var i in items){
if ((items[i]).getAttribute !== undefined){
if ((items[i]).hasAttribute('style')){
if ((/display\:\s*none/gi).test(items[i].getAttribute('style'))){
hidden.push(items[i]);
}
}
}
}
for (var i in hidden){
hidden[i].parentNode.removeChild(hidden[i]);
}
This removes divs with the "display: none" style. I tested it on the OP's example. Note: I added a "some-container" id when testing.
function removeDivs() {
"use strict";
//Some container.
const someContainer = document.getElementById("some-container");
//Divs inside it.
const divsInside = someContainer.querySelectorAll("div");
//Loop, remove div if "display: none".
divsInside.forEach(function (divInside) {
const style = window.getComputedStyle(divInside);
if (style.display === "none") {
someContainer.removeChild(divInside);
}
});
}
removeDivs();

Categories