So I am trying to set equal height for divs that are in different containers. But I am missing something and can't get it to work. Maybe you will spot the problem?
var howMany = $('.comparison-table__labels-wrap .equal-row').length;
for (var i=0; i<howMany; i++) {
var firstBlock = 'equal-row-' + i;
var firstHeight = $(firstBlock).height();
var secondBlock = '.equal-row-' + i + '-child';
var secondHeight = $(secondBlock).height();
if (firstHeight < secondHeight) {
$(firstBlock).css("height", secondHeight);
} else {
$(secondBlock).css("height", firstHeight);
}
}
.row {
border-color: #232323;
border-width: 1px;
border-style: solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container-1">
<div class="row equal-row-0">Row 0</div>
<div class="row equal-row-1">Row 1</div>
<div class="row equal-row-2">Row 2</div>
<div class="row equal-row-3">Row 3</div>
<div class="row equal-row-4">Row 4</div>
<div class="row equal-row-5">Row 5</div>
<div class="row equal-row-6">Row 6</div>
</div>
<div class="container-2">
<div class="row equal-row-0-child">Row 0</div>
<div class="row equal-row-1-child">Row 1</div>
<div class="row equal-row-2-child">Row 2</div>
<div class="row equal-row-3-child">Row 3</div>
<div class="row equal-row-4-child">Row 4</div>
<div class="row equal-row-5-child">Row 5</div>
<div class="row equal-row-6-child">Row 6</div>
</div>
funny example ;)
function equalizeHeights() {
const firstDivs = document.querySelectorAll(".first div")
const secondDivs = document.querySelectorAll(".second div")
const heights = []
for (let div of firstDivs) {
heights.push(div.clientHeight)
}
for (let i = 0; i < heights.length; i++) {
secondDivs[i].style.height = heights[i] + "px"
}
}
equalizeHeights()
function randomlyChangeHeight() {
const divs = document.querySelectorAll(".first div")
const randomNum = Math.floor(divs.length * Math.random())
const randomHeight = Math.floor(50 + 100 * Math.random())
divs[randomNum].style.height = randomHeight + "px"
}
setInterval(() => {
randomlyChangeHeight();
}, 500)
setTimeout(
() =>
setInterval(equalizeHeights, 250), 250)
.first div {
height: 50px;
}
div div {
transition: height 500ms;
border: 1px solid goldenrod;
text-align: center;
padding: 20px;
box-sizing: border-box;
}
.first,
.second {
width: 50%;
float: left;
}
.first div:nth-child(odd),
.second div:nth-child(even) {
background-color: mediumseagreen;
}
<div class="first">
<div>Row</div>
<div>Row</div>
<div>Row</div>
<div>Row</div>
<div>Row</div>
</div>
<div class="second">
<div>Row</div>
<div>Row</div>
<div>Row</div>
<div>Row</div>
<div>Row</div>
</div>
I think you need $('[class^="equal-row"]') to select all divs that you need. See this:
function setNewHeight() {
var howMany = $('[class^="equal-row"]').length;
//console.log(howMany);
for (var i = 0; i < howMany; i++) {
var firstBlock = '.equal-row-' + i;
var firstHeight = $(firstBlock).height();
//console.log(firstBlock, firstHeight);
var secondBlock = '.equal-row-' + i + '-child';
var secondHeight = $(secondBlock).height();
//console.log(secondBlock, secondHeight);
if (firstHeight < secondHeight) {
$(firstBlock).css("height", secondHeight);
} else {
$(secondBlock).css("height", firstHeight);
}
}
}
setNewHeight();
.container-1 div, .container-2 div{
border: 1px solid #ccc
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<div class="container-1">
<div class="container-1">
<div class="equal-row-0">Row 0
<br> test1
</div>
<div class="equal-row-1">Row 1</div>
<div class="equal-row-2">Row 2</div>
<div class="equal-row-3">Row 3</div>
<div class="equal-row-4">Row 4
<br>test2
</div>
<div class="equal-row-5">Row 5</div>
<div class="equal-row-6">Row 6</div>
</div>
<div class="container-2">
<div class="equal-row-0-child">Row 0</div>
<div class="equal-row-1-child">Row 1</div>
<div class="equal-row-2-child">Row 2</div>
<div class="equal-row-3-child">Row 3</div>
<div class="equal-row-4-child">Row 4</div>
<div class="equal-row-5-child">Row 5</div>
<div class="equal-row-6-child">Row 6
<br>test3
</div>
</div>
Its way better to use an abstract class in the elements. And you can do the number definition in a different attribute. This will make the implementation much easier. See the example bellow:
$('.equal-row').each(function () {
var number = $(this).attr('rel');
var parentHeight = $(this).height();
$('.equal-row-child[rel='+number+']').height(parentHeight)
});
.container-1 .equal-row[rel="0"] {
height: 30px;
}
.container-1 .equal-row[rel="1"] {
height: 45px;
}
.container-1 .equal-row[rel="2"] {
height: 15px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<div class="container-1">
<div rel="0" class="equal-row">Row 0</div>
<div rel="1"class="equal-row">Row 1</div>
<div rel="2" class="equal-row">Row 2</div>
</div>
<div class="container-2">
<div rel="0" class="equal-row-child">Row 0</div>
<div rel="1"class="equal-row-child">Row 1</div>
<div rel="2" class="equal-row-child">Row 2</div>
</div>
If you have any problems, let me now :)
So this works just fine:
(function(){
var howManyCols = $('.comparison-table__labels-wrap .equal-row').length;
for (var i=0; i<howManyCols; i++) {
var height1 = $('.equal-row-' + i).outerHeight();
var col1 = $('.equal-row-' + i);
var height2 = $('.equal-row-' + i + '-child').outerHeight();
var col2 = $('.equal-row-' + i + '-child');
if(height1 < height2) {
$(col1).css("height", height2);
} else {
$(col2).css("height", height1);
}
}
})();
Related
Trying to a create a timeline box with scroll that has overflown items. When scrolling all items fully visible should get the visible class and whenever a new item becomes fully visible should get the visible class. Im missing some math or logic here, to make it accurate. Any tips or alternative methods would be very helpful.
Codepen: https://codepen.io/rKaiser/pen/BaKZgoX
<div id="wrapper" class="history">
<div class="history-inner">
<div class="item i1 wide"></div>
<div class="item i2"></div>
<div class="item i3 wide"></div>
<div class="item i4"></div>
<div class="item i5"></div>
<div class="item i6 wide"></div>
<div class="item i7"></div>
<div class="item i8"></div>
<div class="item i9"></div>
<div class="item i10 wide"></div>
<div class="item i11"></div>
<div class="item i12"></div>
<div class="item i13"></div>
<div class="item i14 wide"></div>
<div class="item i15"></div>
<div class="item i16 wide"></div>
<div class="item i17"></div>
<div class="item i18"></div>
<div class="item i19 wide"></div>
<div class="item i20"></div>
<div class="item i21 wide"></div>
<div class="item i22"></div>
<div class="item i23"></div>
</div>
</div>
.history {
position: relative;
overflow-y: hidden;
}
.history-inner {
display: inline-flex;
}
.item {
width:120px;
height:300px;
display:inline-block;
border:1px solid #ccc;
background: #777;
transition: all .3s ease;
&.wide {
width:170px;
}
&.visible {
background: green !important;
}
}
.item:nth-child(even){
background: #666;
}
js
var historyW = $('.history').outerWidth();
var historyInnerW = $('.history-inner').outerWidth();
var currentHiddenItem = historyW + 5; // bigger than history
var historyPxScr = $('.history').scrollLeft();
var entryNum = 1;
var itemMargin = 0;
$('.history').on('resize scroll', function() {
historyW = $('.history').outerWidth();
historyPxScr = $('.history').scrollLeft();
console.log( historyW + historyPxScr + ' sum');
console.log( currentHiddenItem + ' curr');
// console.log( historyInnerW + ' iii');
if ( historyW + historyPxScr < currentHiddenItem - itemMargin) {
$('.item.i'+entryNum).addClass('visible');
} else {
currentHiddenItem += $('.item.i'+entryNum).outerWidth();
itemMargin = $('.item.i'+entryNum).outerWidth();
//console.log(itemMargin + 'IM');
entryNum += 1;
console.log(entryNum);
console.log(currentHiddenItem);
}
});
I would go for something like this, tried to do it in the jQuery way ;-).
var isFullyVisible = function(elem) {
return elem.getBoundingClientRect().right - window.innerWidth < 0;
}
var checkItemVisibility = function () {
$('.history .item').each(function (index, elem) {
if (isFullyVisible(elem)) {
$(elem).addClass('visible');
} else {
$(elem).removeClass('visible');
}
});
}
$(document).ready(function() {
checkItemVisibility();
$('.history').on('scroll', checkItemVisibility);
});
Tested this code in your codepen and it worked.
Hello and have a nice day!
I want to create simple step by step element with back button.
I have a next markup
<div class="checkout">
<div class="checkout-step">
<div class="content">This is step 1</div>
<div class="button-prev-step">Previous step</div>
<div class="button-next-step">Next step</div>
</div>
<div class="checkout-step">
<div class="content">This is step 2</div>
<div class="button-prev-step">Previous step</div>
<div class="button-next-step">Next step</div>
</div>
<div class="checkout-step">
<div class="content">This is step 3</div>
<div class="button-prev-step">Previous step</div>
<div class="button-next-step">Next step</div>
</div>
</div>
JS (It's not fully complete code, just part of existing code, I don't fully understand how I can do it)
var checkoutStepCounter = 0;
var checkoutStepLength = $('.checkout-step').length;
$('.button-next-step').click(function() {
checkoutStepCounter++;
if( checkoutStepLength < checkoutStepCounter ) {
$(this).find('.checkout-step').hide();
$(this).find('.checkout-step').next('.checkout-step').show();
}
});
$('.button-prev-step').click(function() {
checkoutStepCounter--;
if( checkoutStepLength < checkoutStepCounter ) {
$(this).find('.checkout-step').hide();
$(this).find('.checkout-step').prev('.checkout-step').show();
}
});
CSS:
.button-prev-step, .button-next-step { display: block; width: 100px; height: 20px; background: red; cursor: pointer; }
.checkout-step { display: none; }
https://codepen.io/Frunky/pen/yKNMOM
How to make function nextStep and prevStep? in result I want to slide between the sections, and in total - send filled data to backend. Now I need to add an ability to slide between .checkout-step blocks. May be I need to add simple slider? like slick or owl, but I don't know if it's right way or not
Simple code snippet to show you next and previous button working. You can do some more research and add your desired animation (slide, fade etc.) as per your requirements.
var checkoutSteps = 3;
var currentStep = 1;
$('.button-next-step').click(function() {
if(currentStep < checkoutSteps){
$(".checkout-step-"+currentStep+"").hide();
currentStep++;
$(".checkout-step-"+currentStep+"").show();
}
});
$('.button-prev-step').click(function() {
if(currentStep > 1){
$(".checkout-step-"+currentStep+"").hide();
currentStep--;
$(".checkout-step-"+currentStep+"").show();
}
});
.button-prev-step, .button-next-step { display: inline-block; width: 100px; height: 20px; background: red; cursor: pointer; }
.checkout-step {
width: 300px;
height: 300px;
border: 1px solid #000;
display: none;
}
.checkout-step-1{
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="checkout">
<div class="checkout-step checkout-step-1">
<div class="content">This is step 1</div>
<div class="button-prev-step">Previous step</div>
<div class="button-next-step">Next step</div>
</div>
<div class="checkout-step checkout-step-2">
<div class="content">This is step 2</div>
<div class="button-prev-step">Previous step</div>
<div class="button-next-step">Next step</div>
</div>
<div class="checkout-step checkout-step-3">
<div class="content">This is step 3</div>
<div class="button-prev-step">Previous step</div>
<div class="button-next-step">Next step</div>
</div>
</div>
Hope this helps
The given code is only working in Firefox and not in any other browser.
I have given the Fiddle link for it.The code is working fine in Firefox and the functions are also working but it is not supported by any other browser.
The error shows is
Error due to long Script
Fiddle
Here is the code.
var $boxes;
$(document).ready(function() {
$boxes = $(".box");
setupColumns();
$(window).on("resize", setupColumns);
});
function setupColumns() {
var $columnwrapper = $("#columns");
var w = $("<div>").addClass("column").width();
var cnt = Math.floor($columnwrapper.width() / w);
var cols = [];
for (var i = 0; i < cnt; i++) {
var $col = $("<div>").addClass("column");
cols.push($col);
}
$columnwrapper.append(cols);
var cnt = 0;
$boxes.each(function() {
$(this).detach().appendTo(cols[cnt]);
cnt = (cnt + 1) % cols.length;
});
}
$(".box").click(function() {
if ($(this).height() != 100)
$(this).animate({
height: 100
}, 1000);
else
$(this).animate({
height: 150
}, 1000);
});
.column {
width: 114px;
float: left
}
.box {
height: 100px;
width: 100px;
border: 2px solid;
margin-bottom: 10px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="columns"></div>
<div class="box">HELLO WORLD 1</div>
<div class="box">HELLO WORLD 2</div>
<div class="box">HELLO WORLD 3</div>
<div class="box">HELLO WORLD 4</div>
<div class="box">HELLO WORLD 5</div>
<div class="box">HELLO WORLD 6</div>
<div class="box">HELLO WORLD 7</div>
<div class="box">HELLO WORLD 8</div>
<div class="box">HELLO WORLD 9</div>
<div class="box">HELLO WORLD 10</div>
The problem is due to following line:
var w = $("<div>").addClass("column").width();
Apart from Firefox, in other browsers its returning 0 which causes cnt to become Infinity. That's why you are getting a really long running script that's creating infinite divs and adding them to cols[]
Documentation for .width() says:
The value reported by .width() is not guaranteed to be accurate when
the element or its parent is hidden. To get an accurate value, ensure
the element is visible before using .width().
So what you will need to do is:
var $boxes;
$(document).ready(function() {
$boxes = $(".box");
setupColumns();
$(window).on("resize", setupColumns);
});
function setupColumns() {
var $columnwrapper = $("#columns");
//////////start change////////////
var dummy = $("<div>").addClass("column");
dummy.appendTo($columnwrapper); // add it to wrapper so that it gets displayed
var w = dummy.width(); // this now returns 114
dummy.remove(); // now that we have got the width, remove it
// just to be on safer side:
if(w == 0){
console.log("column width is 0.");
return;
}
//////////end change////////////
var cnt = Math.floor($columnwrapper.width() / w);
var cols = [];
for (var i = 0; i < cnt; i++) {
var $col = $("<div>").addClass("column");
cols.push($col);
}
$columnwrapper.append(cols);
var cnt = 0;
$boxes.each(function() {
$(this).detach().appendTo(cols[cnt]);
cnt = (cnt + 1) % cols.length;
});
}
$(".box").click(function() {
if ($(this).height() != 100)
$(this).animate({
height: 100
}, 1000);
else
$(this).animate({
height: 150
}, 1000);
});
.column {
width: 114px;
float: left
}
.box {
height: 100px;
width: 100px;
border: 2px solid;
margin-bottom: 10px
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="columns"></div>
<div class="box">HELLO WORLD 1</div>
<div class="box">HELLO WORLD 2</div>
<div class="box">HELLO WORLD 3</div>
<div class="box">HELLO WORLD 4</div>
<div class="box">HELLO WORLD 5</div>
<div class="box">HELLO WORLD 6</div>
<div class="box">HELLO WORLD 7</div>
<div class="box">HELLO WORLD 8</div>
<div class="box">HELLO WORLD 9</div>
<div class="box">HELLO WORLD 10</div>
This is maybe because of cross-browser security concept by the modern browsers. If you are trying to run in Google Chrome. You might have to use the older version or install the plugin such as this:
https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=en
Here is jsfiddle of raw code and the result should be like this
<div class="wrapper">
<div class="row">
<div class="col red">R</div>
<div class="col blue">B</div>
<div class="col green">G</div>
<div class="col orange">O</div>
</div>
</div>
The mission is: Last color of previous row should be the first in next row and first color from previuos row should be the second in next row.
I think that I have to use loop and recursion but I don't have enough knowledge to do this.
Thanks in advance :)
You can run through the for loop and do something like this
check this snippet
//last color of previous row should be first in next row
//first color from previous row should be second in next row
var colors = ['red', 'blue', 'green', 'orange'];
$(document).ready(function() {
var rows = $('.row');
rows.each(function(row) {
var index = $(this).index();
var prevRow;
if (index > 0)
prevRow = $(this).prev();
colorColumns($(this).find('.col'), prevRow);
});
});
function colorColumns(cols, prevRow) {
var index = 0;
// alert("hi");
cols.each(function(col) {
var colIndex = $(this).index();
if (prevRow) {
var cols = prevRow.find('.col').length;
var totalCols = cols - 1;
var currentIndex = ((colIndex + totalCols) % cols);
var prevRowColor = $(prevRow).find('.col').eq(currentIndex);
var classes = prevRowColor.attr('class');
var classArr = classes.split(" ");
$(this).addClass(classArr[1]);
} else {
$(this).addClass(colors[colIndex]);
}
});
}
.row {
display: flex;
}
.row .col {
width: 20px;
height: 20px;
border-radius: 100%;
text-align: center;
}
.red {
background: red;
}
.orange {
background: orange;
}
.blue {
background: blue;
}
.green {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="wrapper">
<div class="row">
<div class="col">R</div>
<div class="col">B</div>
<div class="col">G</div>
<div class="col">O</div>
</div>
<div class="row">
<div class="col">R</div>
<div class="col">B</div>
<div class="col">G</div>
<div class="col">О</div>
</div>
<div class="row">
<div class="col">R</div>
<div class="col">B</div>
<div class="col">G</div>
<div class="col">O</div>
</div>
Hope it helps
how can I check if it was the last div? If it was I need to remove all classes "ready"
html:
<div class="green"></div>
<div class="orange"></div>
<div class="red"></div>
<div class="green"></div>
<div class="orange"></div>
js:
$(function() {
setInterval(showBlock, 1000);
function showBlock() {
var x = $("div:first").addClass("ready");
var c = $("div");
$(".ready").css("display", "block");
if (c.hasClass("ready")) {
$(".ready:last").next().addClass("ready");
}
}
})
;
Looking at your code what I understand is you want display one div after each second. For that I'll suggest following approach.
First add hidden class to all divs and then remove it from first hidden div at each second.
$(function() {
$('div').addClass('hidden');
var i = setInterval(showBlock, 1000);
function showBlock() {
var x = $("div.hidden:first").removeClass("hidden");
if($("div.hidden").length == 0) {
clearInterval(i);
}
}
});
.hidden {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="green">Green</div>
<div class="orange">Orange</div>
<div class="red">Red</div>
<div class="green">Green</div>
<div class="orange">Orange</div>
As far as I understand your problem, following solution must work in your case:
$(function() {
setInterval(showBlock, 1000);
function showBlock() {
var ready_divs = $("div.ready").length;
var total_divs = $("div").length;
if(ready_divs!=total_divs){
if(ready_divs==0){
$("div:first").addClass('ready');
}else{
$("div.ready:last").next('div').addClass('ready');
}
}else{
$("div").removeClass('ready')
}
}
});
div{
width: 20px;
height: 20px;
border:1px solid red;
}
div.ready{
border:3px solid blue;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="green"></div>
<div class="orange"></div>
<div class="red"></div>
<div class="green"></div>
<div class="orange"></div>