Jquery trouble randomly selecting divs in a grid - javascript

I have a grid of 9 divs nested in columns of three. When the grid (#left) is clicked , 2 divs from the middle row, row="1" should have the class .show randomly applied to it, in the column where the no class was applied the div on the bottom row, row="2" should have the class '.show' applied. The attached picture shows the possible random outcomes. The same outcome should never appear consecutively.
I attached a code snippet of my code, currently, my index selection is not working as desired and I have struggled to find the reason why.
var obj = {
bindEvents: function() {
var _this = this;
$('#left').on("click", $.proxy(_this.interaction, _this));
},
interaction: function() {
var selector = this.randomGenerator(0, 3);
console.log('selector = ' + selector());
var $midRow = $('#left').find('div[row=1]');
var $bottomRow = $('#left').find('div[row=2]');
$midRow.removeClass('show');
$bottomRow.removeClass('show');
$midRow.not(':eq(' + selector() + ')').addClass('show');
$bottomRow.eq(selector()).addClass('show');
},
randomGenerator: function(min, max) {
var last;
console.log('last = ' + last);
return function () {
var random;
do {
random = Math.floor(Math.random() * (max - min)) + min;
} while (random === last);
last = random;
return random;
};
},
}
obj.bindEvents();
#left {
display: flex;
}
div[row] {
border: 1px solid black;
width: 20px;
background-color: yellow;
}
.show {
background-color: red !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="left">
<div col="0">
<div row="0">0</div>
<div row="1">1</div>
<div row="2">2</div>
</div>
<div col="1">
<div row="0">0</div>
<div row="1">1</div>
<div row="2">2</div>
</div>
<div col="2">
<div row="0">0</div>
<div row="1">1</div>
<div row="2">2</div>
</div>
</div>

You do not pass any element to the functions.
There is no this... You have to provide it.
EDIT
When you call selector(), you are aware that it is a function... And that a new number is produced each time you call the function.
If you want the same "number" to be used in both .eq() statement, run the function just once and keep the number in a variable.
See changes in code.
var obj = {
bindEvents: function(el) { // pass an element!
//var _this = this;
//$('#left').on("click", $.proxy(_this.interaction, _this));
el.on("click", $.proxy(obj.interaction(el), el)); // Call the obj function.
},
interaction: function(el) { // pass an element again!
var selector = obj.randomGenerator(0, 3); // Call the obj function.
// Get a number
var number = selector();
console.log('selector = ' + number);
var $midRow = $('#left').find('div[row=1]');
var $bottomRow = $('#left').find('div[row=2]');
$midRow.removeClass('show');
$bottomRow.removeClass('show');
$midRow.not(':eq(' + number + ')').addClass('show');
$bottomRow.eq(number).addClass('show');
},
randomGenerator: function(min, max) {
var last;
console.log('last = ' + last);
return function () {
var random;
do {
random = Math.floor(Math.random() * (max - min)) + min;
} while (random === last);
last = random;
return random;
};
},
}
obj.bindEvents($("#left"));
#left {
display: flex;
}
div[row] {
border: 1px solid black;
width: 20px;
background-color: yellow;
}
.show {
background-color: red !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="left">
<div col="0">
<div row="0">0</div>
<div row="1">1</div>
<div row="2">2</div>
</div>
<div col="1">
<div row="0">0</div>
<div row="1">1</div>
<div row="2">2</div>
</div>
<div col="2">
<div row="0">0</div>
<div row="1">1</div>
<div row="2">2</div>
</div>
</div>

Related

How to save new background color via `colorpicker` to `localStorage`?

I know there's a lot of similar questions.. I've tried them but I really can't incorporate it to my project.
I'm trying to save to localStorage the new background-color selected using the native colorpicker.
I'm almost there but I just can't figure out how to make it work.
Please see my code so far:
function changeBgColor(color) {
if (color) window.localStorage.setItem('bgColor', color);
else if (!(color = window.localStorage.getItem('bgColor'))) return;
document.getElementById('colorpicker').addEventListener('input', function() {
var elements = document.getElementsByClassName("card-bg")
for (var i = 0; i < elements.length; i++) {
elements[i].style.background = this.value;
}
})
}
window.addEventListener('DOMContentLoaded', () => changeBgColor());
.card1 {
width: 200px;
height: 200px;
background-color: #222;
margin: 10px 0 0 0;
}
<div class="card1 card-bg">Set A</div>
<div class="card1 card-bg">Set A</div>
<div class="card1 card-bg">Set A</div>
<br>
<input type="color" id="colorpicker" onselect="changeBgColor();">
The important feature for me are:
To change background color using input="color"
Use class selector since I have multiple divs I want to target with the same input
Save the value to localStorage
That's all really. I just need to figure out the part where the value gets saved to localStorage.
After I make this work, I will need to replicate it for a different set of divs..
Thank you in advance for any help.
If check had = assignment instead of == comparison
Here is a working refactored snippet:
let pretend_local_storage = null
function setupBackgroundColorChange() {
const elements = document.querySelectorAll(".card-bg")
document.getElementById('colorpicker').addEventListener('input', function(e) {
color = e.target.value
if (color === pretend_local_storage) return
pretend_local_storage = color
elements.forEach((element) => element.style.background = color)
})
}
window.onDOMContentLoaded = setupBackgroundColorChange();
.card1 {
width: 200px;
height: 200px;
background-color: #222;
margin: 10px 0 0 0;
}
<div class="card1 card-bg">Set A</div>
<div class="card1 card-bg">Set A</div>
<div class="card1 card-bg">Set A</div>
<br>
<input type="color" id="colorpicker" onselect="changeBgColor();">
Local Storage example:
localStorage.getItem('bgColor', null)
function setupBackgroundColorChange() {
const elements = document.querySelectorAll(".card-bg")
setColor(elements, localStorage.getItem('bgColor', '#000'))
document.getElementById('colorpicker').addEventListener('input', function (e) {
color = e.target.value
if (color === localStorage.getItem('bgColor')) return
localStorage.setItem('bgColor', color)
setColor(elements, color)
})
}
function setColor(elements, color) {
elements.forEach((element) => element.style.background = color)
}
window.onDOMContentLoaded = setupBackgroundColorChange();
First of all i would use onchange trigger. To be honest, you dont need any condition inside the function. you can set the color to localStorage and that is it.
/* this lines check if already set color to localStorage */
if (window.localStorage.getItem('bgColor')) {
var elements = document.getElementsByClassName("card-bg")
for (var i = 0; i < elements.length; i++) {
elements[i].style.background = this.value;
}
}
function changeBgColor() {
let color = document.getElementById('colorpicker').value;
const bg_curr = localStorage.getItem('bgColor');
console.log(color, bg_curr);
localStorage.setItem('bgColor', color);
document.getElementById('colorpicker').addEventListener('input', function() {
var elements = document.getElementsByClassName("card-bg")
for (var i = 0; i < elements.length; i++) {
elements[i].style.background = color;
}
})
}
window.addEventListener('DOMContentLoaded', () => changeBgColor());
.card1 {
width: 200px;
height: 200px;
background-color: #222;
margin: 10px 0 0 0;
}
<input type="color" id="colorpicker" onchange="changeBgColor();">
<div class="card1 card-bg">Set A</div>
<div class="card1 card-bg">Set A</div>
<div class="card1 card-bg">Set A</div>
<br>

how to find the shortest element [duplicate]

This question already has answers here:
Obtain smallest value from array in Javascript?
(18 answers)
Closed 1 year ago.
I have four divs inside a wrap
need the shortest of the first three (a, b, or c) to be red
let a = $('#cola').height();
let b = $('#colb').height();
let c = $('#colc').height();
//$(shortest).css('background', 'red');
.wrap{
text-align:center;
}
.col{
display:inline-block;
vertical-align:top;
width:14%;
background:gold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='wrap'>
<div class='col cola' id='cola'><br><br><br><br></div>
<div class='col colb' id='colb'><br><br></div>
<div class='col colc' id='colc'><br><br><br><br><br><br></div>
<div class='col cold' id='cold'><br><br></div>
</div>
You could create a jQuery plugin that can select the first element where it has the shortest height. I even included a selection method for the tallest.
/* jquery.shortest-element.js */
(function($) {
$.reduce = function(arr, callback, initialValue) {
$.each(arr, function(index, currValue) {
initialValue = callback.call(currValue, initialValue, currValue, index, arr);
});
return initialValue;
};
$.fn.reduce = function(callback, initialValue) {
return $.reduce(this, callback, initialValue);
};
$.fn.shortest = function() {
return $(this.reduce(function(prev) {
var height = $(this).height();
return height < prev.height ? { el: this, height: height } : prev;
}, { height: Number.MAX_VALUE }).el);
};
$.fn.tallest = function() {
return $(this.reduce(function(prev) {
var height = $(this).height();
return height > prev.height ? { el: this, height: height } : prev;
}, { height: Number.MIN_VALUE }).el);
};
})(jQuery);
$('.col').shortest().css('background', 'red');
$('.wrap > *').tallest().css('background', 'green');
.wrap {
text-align: center;
}
.col {
display: inline-block;
vertical-align: top;
width: 14%;
background: gold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrap">
<div class="col cola" id="cola"><br><br><br><br></div>
<div class="col colb" id="colb"><br><br></div>
<div class="col colc" id="colc"><br><br><br><br><br><br></div>
<div class="col cold" id="cold"><br><br></div>
</div>
hope this answer can help your problem. I put code from here
its a small code from you
let a = $('#cola')
let b = $('#colb')
let c = $('#colc')
// its joining your variable into array of object with label
let myArray = [
{label : "cola", height : a.height()},
{label : "colb", height : b.height()},
{label : "colc", height : c.height()}
]
// its a magic from https://stackoverflow.com/questions/8864430/compare-javascript-array-of-objects-to-get-min-max
// you can improve this code for better performance
let lowest = Number.POSITIVE_INFINITY;
let label
let tmp;
for (let i=myArray.length-1; i>=0; i--) {
tmp = myArray[i].height;
if (tmp < lowest) {
lowest = tmp
label = myArray[i].label
}
};
// printing your shortest col
console.log(lowest)
console.log(label)
// then setting the shortest component to red
$(`#${label}`).css("background","red")
.wrap{
text-align:center;
}
.col{
display:inline-block;
vertical-align:top;
width:14%;
background:gold;
}
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<div class='wrap'>
<div class='col cola' id='cola'><br><br><br><br></div>
<div class='col colb' id='colb'><br><br></div>
<div class='col colc' id='colc'><br><br><br><br><br><br></div>
<div class='col cold' id='cold'><br><br></div>
</div>
Another really simple plugin function approach. Only returns one element and in case of ties returns the first found
$.fn.shortest=function(){
return this.toArray().reduce(($a, el) => {
const $el = $(el);
return $el.height() < $a.height() ? $el : $a
}, this.first())
}
$('.wrap .col').shortest().css('background', 'red')
.wrap{
text-align:center;
}
.col{
display:inline-block;
vertical-align:top;
width:14%;
background:gold;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='wrap'>
<div class='col cola' id='cola'><br><br><br><br></div>
<div class='col colb' id='colb'><br><br></div>
<div class='col colc' id='colc'><br><br><br><br><br><br></div>
<div class='col cold' id='cold'><br><br></div>
</div>

Switch classes on click next or back

I'm trying to setup multiple-step form in which the first step is visible by default and rest of the steps are hidden with class "hide". I'd like to switch the class with Next and Back button so only one step is visible at a time. Could you please help with this (Already spent an hour on this)
<div class="steps">
<div class="step1">step1</div>
<div class="step2 hide">step2</div>
<div class="step3 hide">step3</div>
<div class="step4 hide">step4</div>
</div>
<div class="back">Back</div>
<div class="next">Next</div>
$('.next').click(function(){
$('div:not(.hide)').next().removeClass('hide');
$('.hide').prev().removeClass('hide')
})
Try combining the 2 actions into one, like so:
$('.next').click(function(){
$('.steps div:not(.hide)').addClass('hide').next().removeClass('hide');
})
That way, you add the .hide class on your current div and then remove it on the next one.
You can use something similar for the Back button, by replacing .next() with .previous()
$('.next').click(function() {
// find the div that is not hidden
var $current = $('.steps div:not(.hide)');
// only perform logic if there is a proceeding div
if ($current.next().length) {
// show the next div
$current.next().removeClass('hide');
// hide the old current div
$current.addClass('hide')
}
});
$('.back').click(function() {
// find the div that is not hidden
var $current = $('.steps div:not(.hide)');
// only perform logic if there is a preceeding div
if ($current.prev().length) {
// show the previous div
$current.prev().removeClass('hide');
// hide the old current div
$current.addClass('hide')
}
});
.hide { display: none; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="steps">
<div class="step1">step1</div>
<div class="step2 hide">step2</div>
<div class="step3 hide">step3</div>
<div class="step4 hide">step4</div>
</div>
<div class="back">Back</div>
<div class="next">Next</div>
You can add a current step variable to track the currently displayed step and two css for styling and showing your content.
jQuery(function($) {
let currentstep = 1;
let maxsteps = 4;
function showstep(step) {
let step_c = '.step' + step;
for (i = 1; i <= maxsteps; i++) {
var step_selector = '.step' + i;
$(step_selector).removeClass('show');
$(step_selector).addClass('hide');
}
$(step_c).removeClass('hide');
$(step_c).addClass('show');
};
$('.next').click(function() {
currentstep = currentstep + 1;
currentstep = (currentstep % (maxsteps + 1));
if (currentstep == 0) currentstep = 1;
showstep(currentstep);
});
$('.back').click(function() {
currentstep = currentstep - 1;
currentstep = (currentstep % (maxsteps + 1));
if (currentstep == 0) currentstep = 4;
showstep(currentstep);
});
});
.hide {
display: none;
}
.show {
display: block;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="steps">
<div class="step1 show">step1</div>
<div class="step2 hide">step2</div>
<div class="step3 hide">step3</div>
<div class="step4 hide">step4</div>
</div>
<div class="back">Back</div>
<div class="next">Next</div>
I converted Taplar's answer to a jQuery plugin.
You are essentially navigating left or right by one, using the previous and next functions. These functions navigate through the sibling elements.
(function() {
$.fn.moveRight = function(className) {
var $curr = this.find('div:not(.' + className + ')');
if ($curr.next().length) $curr.next().removeClass(className);
else this.find('div:first-child').removeClass(className);
$curr.addClass(className);
return this;
};
$.fn.moveLeft = function(className) {
var $curr = this.find('div:not(.' + className + ')');
if ($curr.prev().length) $curr.prev().removeClass(className);
else this.find('div:last-child').removeClass(className);
$curr.addClass(className);
return this;
};
})(jQuery);
$('.next').on('click', (e) => $('.steps').moveRight('hide'));
$('.back').on('click', (e) => $('.steps').moveLeft('hide'));
.hide {
display: none;
}
.nav {
width: 260px;
text-align: center;
}
.nav .nav-btn::selection { background: transparent; }
.nav .nav-btn::-moz-selection { background: transparent; }
.nav .nav-btn {
display: inline-block;
cursor: pointer;
}
.steps {
width: 260px;
height: 165px;
border: thin solid black;
text-align: center;
line-height: 165px;
font-size: 3em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="steps">
<div class="step1">step1</div>
<div class="step2 hide">step2</div>
<div class="step3 hide">step3</div>
<div class="step4 hide">step4</div>
</div>
<div class="nav">
<div class="nav-btn back">[ << Back ]</div>
<div class="nav-btn next">[ Next >> ]</div>
</div>

how to change color of elements one by one using javascript(jquery) and then reset the result again one by one

how to change color of elements one by one using javascript(jquery) and then reset the result again one by one
.cub {
background: aqua;
width: 200px;
height: 200px;
display: inline-block;
}
You can add class and remove class using jQuery. First assign another class to these divs so no other divs will be affected.
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
var counter = 0;
var divs = $('.box'), div = null;
setInterval(function(){
div = $(divs[counter]);
if(div.hasClass('cub')){
div.removeClass('cub');
} else {
div.addClass('cub');
}
counter = (counter + 1) % 4;
}, 500);
Please try this code if it works. I was not able to check it but it should work.
<div class="cub"></div>
<div class="cub"></div>
<div class="cub"></div>
<div class="cub"></div>
.cub{ background-color: white; }
.cub.highlighted{ background-color: aqua; }
<script>
var highlighting = true;
$(document).ready(function(){
var highlightingInterval = setInterval(function(){
if( $(".cub.highlighted").length == 0 )
highlighting = true;
else if( $(".cub.highlighted").length == 4 )
highlighting = false;
if( highlighting )
{
$(".cub").not(".highlighted").eq(0).addClass("highlighted");
}
else
{
var targetIndex = $(".cub.highlighted").length - 1; $(".cub.highlighted").eq(targetIndex).removeClass("highlighted");
}
}, 2000 );//setInterval
});//document ready
</script>

How to convert jQuery function into angular js?

I am very new to AngularJs, I have written a slider function in jQuery. Now I want to convert thih function into Angular. Here is my code below::
<div class="slide-container">
<div class="slide-scroller" style="left: 0px;">
<div class="slideContent" style="background-color: #f00;">one</div>
<div class="slideContent" style="background-color: #0f0;">two</div>
<div class="slideContent" style="background-color: #00f;">three</div>
</div>
</div>
<input type="button" id="left">
<input type="button" id="right">
.slide-container {height: 100px; overflow: hidden; position: relative;}
.slide-scroller { height: 100px; overflow:hidden; position: absolute; top: 0px;}
.slide-scroller .slideContent { height: 100px; overflow: hidden; float: left;}
function slider() {
var slideWidth, speed, sc, slideScroller, scSlide, totalSlide, scrollerWidth, maxLeft;
slideWidth = $(window).width(); // [ get the device width ]
speed = 0.6; // [ control speed 1 = 1s]
sc = $(".slide-container"); // [ getting the container ]
slideScroller = $('.slide-scroller'); // [ getting slider scroller ]
scSlide = $('.slideContent'); // [ getting slide contetnts ]
totalSlide = $(scSlide).length; // [ total slide contents ]
scrollerWidth = totalSlide * slideWidth; // [ slide scroller width ]
maxLeft = -parseInt(scrollerWidth) + parseInt(slideWidth); // [maxmimum left slide value]
// adding some initial attributes
$(sc && scSlide).css({width: slideWidth});
$(slideScroller).css({width: scrollerWidth});
$(slideScroller).css('transition', 'all ease '+speed+'s');
// left click function
$("#left").click(function () {
var xvalue = $(slideScroller).css('left'); //console.log('left :: ', xvalue);
var newvalue = parseInt(xvalue) - parseInt(slideWidth); // console.log('newValue :: ', newvalue);
if (newvalue >= maxLeft) {//console.info('no more left left');
$(slideScroller).css('left', newvalue);
}
else {
return false;
}
});
// right click function
$("#right").click(function () {
var xvaluetwo = $(slideScroller).css('left'); console.log('lefttwo :: ', xvaluetwo);
var newvaluetwo = parseInt(xvaluetwo) + parseInt(slideWidth); console.log('newValuetwo :: ', newvaluetwo);
if (newvaluetwo <= 0) {//console.info('no more right left');
$(slideScroller).css('left', newvaluetwo);
}
else {
return false;
}
});
}
$(document).ready(function () {
slider();
});
I have linked jQuery.min library and called the function in document.ready
Please help me how to make in AngularJS
in HTML:
<div class="slide-container" ng-init="initSlider()">
<div class="slide-scroller" ng-repeat="item in sliderList" style="left: 0px;">
<div class="slideContent" style="background-color: {{item.bgColor}}">{item.content}</div>
</div>
</div>
<input type="button" id="left">
<input type="button" id="right">
in Controller:
$scope.initSlider = function(){
slider()
}

Categories