Strike effect in Tic tac toe game - javascript

I was working on a Tic Tac Toe game and was trying to make a strike effect for the Winner's squares.
My idea was, I could take first and last squash, get their mid position and use a canvas to create a line but its not working properly.
Following is a sample code with Fiddle link:
function TicTacToe(container) {
let count = 0;
const getLabel = () => count++ % 2 === 0 ? 'X' : 'Y';
function createGrid() {
const handlerFn = function() {
this.innerText = getLabel();
this.removeEventListener('click', handlerFn);
}
Array.from({
length: 9
}, (_, i) => {
const div = document.createElement('div');
div.classList.add('tile')
div.addEventListener('click', handlerFn)
container.append(div);
});
}
function createStrikeLine() {
const tiles = document.querySelectorAll('.tile');
const [ startX, startY ] = getPosition(tiles[0]);
const [ endX, endY ] = getPosition(tiles[8]);
console.log(startX, startY, endX, endY)
const canvas = document.getElementById('ctx-strike');
const context = canvas.getContext('2d');
context.beginPath();
context.moveTo(startX, startY);
context.lineTo(endX, endY);
context.stroke();
context.closePath();
}
function getPosition(element) {
const left = element.offsetLeft;
const top = element.offsetTop;
const height = Math.floor(element.offsetWidth / 2);
return [ left + height, top + height ];
}
createGrid();
createStrikeLine();
}
const containerDiv = document.querySelector('.content');
TicTacToe(containerDiv)
div {
display: flex;
}
.container {
align-items: center;
justify-content: center;
height: 95vh;
width: 95vw;
}
.content {
flex-direction: row;
flex-wrap: wrap;
width: 30vmax;
}
#ctx-strike {
/* position: absolute; */
height: 30vmax;
border: 1px solid black;
}
.tile {
margin: 2px;
background: white;
border: 2px solid gray;
border-radius: 4px;
width: 8vw;
height: 8vw;
align-items: center;
justify-content: center;
font-size: 2em;
}
.strike-through {
position: absolute;
z-index: 1;
border-bottom: 4px solid red;
height: 6vh;
width: 21vmax;
}
.translate-45 {
-webkit-transform: rotate(45deg);
}
<div class="container">
<div class="content"></div>
<canvas id='ctx-strike'></canvas>
</div>
Now I understand, issue is with co-ordinates, but I tried to make the canvas full with, still it fails. So the question,
How to determine correct co-ordinates for any tile?
Is there a better way to make stike effect other than canvas?
Another issue i saw was, entire UI is responsive but not the canvas. If you resize container, tiles expand/shrink but the line remains same

Post the last update:
Another issue i saw was, entire UI is responsive but not the canvas. If you resize container, tiles expand/shrink but the line remains same
I thought of using div and css instead of canvas. Yes, canvas would have been less work, css is able to handle responsiveness a bit.
Idea:
I created 8 classes with possible patterns for strike through:
Row-wise: Players can win in 3 pattern if they choose same value in either of rows.
Column-wise: Players can win in 3 pattern if they choose same value in either of column.
Diagonals: They can choose in either diagonal way.
Now in my validation logic, all I have to do is decide if there is a win, choose win pattern and pass it to my function.
Sample Code
Note: I added dropdown so users can play and check these patterns individually.
function TicTacToe(container) {
const strikePatterns = [
'row-1', 'row-2', 'row-3',
'col-1', 'col-2', 'col-3',
'dig-1', 'dig-2'
];
let count = 0;
const getLabel = () => count++ % 2 === 0 ? 'X' : 'Y';
function createGrid() {
const handlerFn = function() {
this.innerText = getLabel();
this.removeEventListener('click', handlerFn);
}
Array.from({
length: 9
}, (_, i) => {
const div = document.createElement('div');
div.classList.add('tile')
div.addEventListener('click', handlerFn)
container.append(div);
});
}
function createStrikeLine(patternName) {
const div = document.createElement('div');
div.classList.add('strike-through');
div.classList.add(patternName)
container.append(div);
}
createGrid();
function createPatternSelect(value) {
const select = document.createElement('select');
strikePatterns.forEach(function(pattern) {
const option = document.createElement('option');
option.innerText = pattern;
option.value = pattern;
select.append(option);
})
if (value) {
select.value = value;
}
select.addEventListener('change', function(event) {
container.innerHTML = '';
createGrid();
createPatternSelect(this.value);
createStrikeLine(this.value);
})
container.append(select)
}
createPatternSelect();
}
const containerDiv = document.querySelector('.content');
TicTacToe(containerDiv)
div {
display: flex;
}
.container {
align-items: center;
justify-content: center;
height: 95vh;
width: 95vw;
}
.content {
flex-direction: row;
flex-wrap: wrap;
width: 30vmax;
align-items: center;
justify-content: center;
}
#ctx-strike {
position: absolute;
border: 1px solid black;
}
.tile {
margin: 2px;
background: white;
border: 2px solid gray;
border-radius: 4px;
width: 8vw;
height: 8vw;
align-items: center;
justify-content: center;
font-size: 2em;
}
.strike-through {
border-bottom: 2px solid red;
position: absolute;
width: 18vw;
height: 1px;
}
.row-1 {
margin-top: -10vw;
}
.row-2 {
margin-top: 0;
}
.row-3 {
margin-top: 8vw;
}
.col-1 {
margin-left: -9vw;
transform: rotate(90deg);
}
.col-2 {
margin-left: 0;
transform: rotate(90deg);
}
.col-3 {
margin-left: 9vw;
transform: rotate(90deg);
}
.dig-1 {
margin-top: -1vw;
width: 27vw;
transform: rotate(-45deg);
}
.dig-2 {
margin-top: -1vw;
width: 27vw;
transform: rotate(45deg);
}
<div class="container">
<div class="content"></div>
</div>

Related

Creating a Simple image carousel using JS Array

I created a simple carousel using HTML, CSS, and Javascript.
Clicking the left button shows the previous slide and the right one shows the next slide.
But my concern is that slide change is not working correctly
when clicking the next button: After the final slide, it won't go to the first slide again.
when clicking the previous button: After the first slide, it won't go again to last the slide again.
So please review my code and let me know my error.
let right = document.querySelector('.nxt');
let left = document.querySelector('.pre');
let slids = document.querySelector('.slids');
let first = document.querySelector('.first');
let scond = document.querySelector('.scond');
let third = document.querySelector('.third');
let fouth = document.querySelector('.fouth');
let slidesArray=[first,scond,third,fouth];
let index= 0;
let activeSlide= slidesArray[index].classList.add('active');
left.addEventListener('click',()=>{
if (++index > 0) {
slidesArray[index].classList.add('active');
}
});
right.addEventListener('click',()=>{
if (index > 0) {
slidesArray[index].classList.add('deactive');
slidesArray[--index].classList.add('active');
}
});
body{
display: flex;
justify-content: center;
align-items: center;
}
.slids>*{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50% ,-50%);
width: 400px;
height: 350px;
font-size: 50px;
font-weight: 600;
display: grid;
place-items: center;
border-radius: 20px;
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
visibility: hidden;
}
.active{
visibility: visible;
}
.first{
background-color: #F7EC09;
}
.scond{
background-color: #3EC70B;
}
.third{
background-color: #3B44F6;
}
.fouth{
background-color: #A149FA;
}
.btn{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50% ,-50%);
display: flex;
gap: 450px;
}
.nxt, .pre{
font-size: 100px;
font-weight: 700;
background: none;
border: none;
cursor: pointer;
}
<body>
<div class="slids">
<div class="first">1</div>
<div class="scond">2</div>
<div class="third">3</div>
<div class="fouth">4</div>
</div>
<div class="btn">
<button class="nxt"><</button>
<button class="pre">></button>
</div>
A chained ternary expression can be used to determine the new index number in a single line:
to = to >= size ? 0 : to < 0 ? size - 1 : to;
Details are commented in example
// Reference the buttons
let next = document.querySelector('.next');
let prev = document.querySelector('.prev');
/*
Collect all div.slide into an array
Define the array's size
Define a number value outside of the function
*/
let slides = [...document.querySelectorAll('.slide')];
let size = slides.length;
let index = 0;
// Bind click event to button.prev
prev.onclick = event => move(index - 1);
// Bind click event to button.next
next.onclick = event => move(index + 1);
/*
Pass newest index number
Ternary expression:
If the given number is greater than or equal to size of the array...
...return 0...
...If the given number is less than 0...
...return last index of array...
...otherwise return the given number
Toggle the current .slide.active and new .slide
Assign index as the given number
*/
function move(to) {
to = to >= size ? 0 : to < 0 ? size - 1 : to;
slides[index].classList.toggle("active");
slides[to].classList.toggle("active");
index = to;
}
html {
font: 300 3vmin/1 Consolas;
}
body {
display: flex;
justify-content: center;
align-items: center;
}
main {
display: flex;
justify-content: center;
align-items: center;
position: relative;
max-width: max-content;
min-height: 100vh;
}
.slides {
display: flex;
justify-content: center;
align-items: center;
position: relative;
width: 420px;
height: 400px;
overflow: hidden;
}
.slide {
display: grid;
place-items: center;
position: absolute;
top: 50%;
left: 50%;
width: 400px;
height: 350px;
border-radius: 20px;
font-size: 50px;
font-weight: 600;
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
visibility: hidden;
transform: translate(-50%, -50%);
}
.active {
visibility: visible;
}
.slide:first-of-type {
background-color: #F7EC09;
}
.slide:nth-of-type(2) {
background-color: #3EC70B;
}
.slide:nth-of-type(3) {
background-color: #3B44F6;
}
.slide:nth-of-type(4) {
background-color: #A149FA;
}
.ctrl {
display: flex;
justify-content: space-between;
position: absolute;
top: 45%;
left: 45%;
width: 150%;
transform: translate(-50%, -50%);
}
.next,
.prev {
border: none;
font-size: 100px;
font-weight: 700;
background: none;
cursor: pointer;
}
<main>
<section class="slides">
<div class="slide active">1</div>
<div class="slide">2</div>
<div class="slide">3</div>
<div class="slide">4</div>
</section>
<menu class="ctrl">
<button class="prev"><</button>
<button class="next">></button>
</menu>
</main>
You need to reset the index of the slide when you click next and reach to maximum slide you need to reset index to 0 to return to first slide, also when you click prev and you in the first slide, you need to reset index to 3 to return the last slide.
let right = document.querySelector(".nxt");
let left = document.querySelector(".pre");
let slids = document.querySelector(".slids");
let first = document.querySelector(".first");
let scond = document.querySelector(".scond");
let third = document.querySelector(".third");
let fouth = document.querySelector(".fouth");
const elementsArr = [first, scond, third, fouth];
let slidesArray = [first, scond, third, fouth];
let index = 0;
let activeSlide = slidesArray[index].classList.add("active");
left.addEventListener("click", () => {
if (index === 3) {
index = -1;
}
index++;
resetActiveElements()
});
right.addEventListener("click", () => {
if (index === 0) index = 4;
index--;
resetActiveElements()
});
const resetActiveElements = () => {
elementsArr.forEach((element, i) => {
if (index === i) {
element.classList.add("active");
} else {
element.classList.remove("active");
}
});
}
body{
display: flex;
justify-content: center;
align-items: center;
}
.slids>*{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50% ,-50%);
width: 400px;
height: 350px;
font-size: 50px;
font-weight: 600;
display: grid;
place-items: center;
border-radius: 20px;
box-shadow: rgba(0, 0, 0, 0.24) 0px 3px 8px;
visibility: hidden;
}
.active{
visibility: visible;
}
.first{
background-color: #F7EC09;
}
.scond{
background-color: #3EC70B;
}
.third{
background-color: #3B44F6;
}
.fouth{
background-color: #A149FA;
}
.btn{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50% ,-50%);
display: flex;
gap: 450px;
}
.nxt, .pre{
font-size: 100px;
font-weight: 700;
background: none;
border: none;
cursor: pointer;
}
<body>
<div class="slids">
<div class="first">1</div>
<div class="scond">2</div>
<div class="third">3</div>
<div class="fouth">4</div>
</div>
<div class="btn">
<button class="nxt"><</button>
<button class="pre">></button>
</div>
/* <div class="btn">
<button class="pre"><</button>
<button class="nxt">></button>
</div> */
let right = document.querySelector('.nxt');
let left = document.querySelector('.pre');
let slids = document.querySelector('.slids');
let first = document.querySelector('.first');
let scond = document.querySelector('.scond');
let third = document.querySelector('.third');
let fouth = document.querySelector('.fouth');
let slidesArray = [first, scond, third, fouth];
let index = 0;
let activeSlide = slidesArray[index].classList.add('active');
left.addEventListener('click', () => {
slidesArray[index].classList.remove('active');
if (index == 0) {
index = 3;
slidesArray[index].classList.add('active');
} else {
index--;
slidesArray[index].classList.add('active');
}
});
right.addEventListener('click', () => {
slidesArray[index].classList.remove('active');
if (index == 3) {
index = 0;
slidesArray[index].classList.add('active');
} else {
index++;
slidesArray[index].classList.add('active');
}
});

Card Slider transform translate only working as expected on first click

I am trying to get this card slider to transform cards on each click. Every time the user clicks on any of the cards, the last card in the array goes to the beginning, and all cards are moving as in a carousel, scaling and changing their zIndex. It works perfectly on the first click but then cards start translating differently.
After searching and searching, I read you have to keep track of translations therefore I am using distanceCounter0Elm and distanceCounterElse variables, but it does not seem to work. Also tried to reset all transforms and even a different approach by adding css classes but could not get it to work properly.
Where is my mistake? It might be something very simple but I am not being able to see it. I would really appreciate your help. Many thanks!
<section class="section" id="portfolio">
<h3 class="tituloTrabajos">Nuestros trabajos</h3>
<div class="container" id="grasscoContainer"></div>
</section>
section{
background-color: #021845;
width: 98vw;
height: 180vh;
padding-top: 10vh;
display: flex;
flex-direction: column;
}
.tituloTrabajos{
color: white;
text-align: center;
font-size: 2vw;
margin-bottom: 25vh;
}
.sitesContainer{
display: flex;
justify-content: space-evenly;
align-items: center;
align-content: center;
flex-wrap: wrap;
row-gap: 8vh;
}
.siteDiv{
background-color: #ddf1fc;
}
.sitePic{
width: 38vw;
border-radius: 20px;
}
.container{
position: relative;
height: 150vh;
width: 98vw;
display: flex;
justify-content: center;
overflow: hidden;
}
.eachCard{
width: 38vw;
height: 40vh;
border-radius: 20px;
box-shadow: -5px 0 6px #000, 10px 0 6px #000;
transition: 0.4s ease-out;
position: relative;
border: 5px solid white;
cursor: pointer;
top: 5vh;
}
.eachCard:not(:first-child){
margin-left: -30vw;
}
.originalzIndex2{
z-index: 2;
}
.originalzIndex1{
z-index: 1;
}
.originalScale{
transform: scale(1.2);
}
var grasscoImgs = ["img/grassco2.png", "img/grassco3.png", "img/grassco.png", "img/grassco4.png", "img/grassco6.png"];
var grasscoContainer = document.getElementById("grasscoContainer");
var cards = document.getElementsByClassName("eachCard");
grasscoImgs.forEach(function(image){
var img = document.createElement("img");
img.src = image;
img.classList.add("eachCard");
grasscoContainer.appendChild(img);
img.onclick = slideCards;
});
cards[2].classList.add("originalzIndex2", "originalScale");
cards[3].classList.add("originalzIndex1");
var cardsArr = Array.from(cards);
function slideCards(){
var lastCard = cardsArr.pop();
cardsArr.splice(0, 0, lastCard);
var distanceCounter0Elm = " translate(-32vw)";
var distanceCounterElse = " translate(2vw)";
for (let i = 0; i < cardsArr.length; i++){
if (i == 0){
cardsArr[0].style.transform = distanceCounter0Elm + " scale(0.8)";
cardsArr[0].style.zIndex = "0";
distanceCounter0Elm += " translate(-32vw)";
} else {
cardsArr[1].style.transform = distanceCounterElse + " scale(1)";
cardsArr[2].style.transform = distanceCounterElse + " scale(1.2)";
cardsArr[3].style.transform = distanceCounterElse + " scale(1)";
cardsArr[4].style.transform = distanceCounterElse + " scale(0.8)";
cardsArr[1].style.zIndex = "1";
cardsArr[2].style.zIndex = "2";
cardsArr[3].style.zIndex = "1";
cardsArr[4].style.zIndex = "0";
distanceCounterElse += " translate(2vw)";
};
};
};

Make both overlapping divs clickable?

Is it possible to make two overlapping divs, both clickable?
I've appended divs to two containers, #container and #container2. Their styles are exactly the same only except one is flex-direction: column; and one is flex-direction: column;. Both position:absolute with #container2 on top. I made each of the appended child clickable to fill its background color. Only the div on top is clickable so far, is there a way to make both clickable? or is there another way to have the bottom div react to my clicks?
window.addEventListener('load', init);
function init() {
calculateGrid();
//calculate grid
function calculateGrid() {
var w = window.innerWidth;
var h = window.innerHeight;
var totalNum = Math.trunc(w / 25) * Math.trunc(h / 25);
function randomInRange(from, to) {
let x = Math.random() * (to - from);
return x + from;
};
for (var i = 0; i < totalNum; i++) {
var div = document.createElement('div');
div.setAttribute('class', 'grid');
div.style.width = randomInRange(3, 10) + 'vw';
div.style.height = randomInRange(5, 10) + 'vh';
document.getElementById('container').appendChild(div);
document.getElementById('container2').appendChild(div.cloneNode(true));
}
};
$(".grid").click(function() {
$(this).toggleClass('selected');
});
};
#container {
width: 100vw;
height: 95vh;
position: absolute;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
flex-direction: column;
overflow: hidden;
}
#container .grid {
border: 1px solid blue;
}
#container2 {
width: 100vw;
height: 95vh;
position: absolute;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
flex-direction: row;
overflow: hidden;
}
#container2 .grid {
border: 1px solid red;
}
.grid {
font-size: 10px;
color: white;
}
#container .selected {
background-color: blue;
}
#container2 .selected {
background-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
<div id="wrapper">
<div id="container"></div>
<div id="container2"></div>
</div>
View on CodePen
One method is to use Document.elementsFromPoint() to return "an array of all elements at the specified coordinates". Iterate through that array, adding the "selected" class to "grid" elements.
window.addEventListener('load', init);
function init() {
// build grid
function calculateGrid() {
var w = window.innerWidth;
var h = window.innerHeight;
var totalNum = Math.trunc(w / 25) * Math.trunc(h / 25);
function randomInRange(from, to) {
let x = Math.random() * (to - from);
return x + from;
};
for (var i = 0; i < totalNum; i++) {
var div = document.createElement('div');
div.setAttribute('class', 'grid');
div.style.width = randomInRange(3, 10) + 'vw';
div.style.height = randomInRange(5, 10) + 'vh';
document.getElementById('container1').appendChild(div);
document.getElementById('container2').appendChild(div.cloneNode(true));
}
};
// handle grid clicks
function handleGridClick(e) {
let elms = document.elementsFromPoint(e.clientX, e.clientY);
Array.from(elms).forEach(elm => {
if (elm.classList.contains('grid'))
elm.classList.add('selected');
});
}
// initialize grid and click handler
calculateGrid();
document.addEventListener('click', handleGridClick);
};
.container {
width: 100vw;
height: 95vh;
position: absolute;
display: flex;
flex-wrap: wrap;
align-content: flex-start;
overflow: hidden;
}
#container1 {
flex-direction: column;
}
#container1 .grid {
border: 1px solid blue;
}
#container1 .grid.selected {
background-color: blue;
}
#container2 .grid {
border: 1px solid red;
}
#container2 .grid.selected {
background-color: red;
}
<div id="wrapper">
<div id="container1" class="container"></div>
<div id="container2" class="container"></div>
</div>
You can't actually hover two items at the same time in plain 'ol HTML/CSS - for that you will need JavaScript as explained in the accepted solution. However, there's a CSS-only solution to allow hovering over the different layers, which was fun to figure out at the very least.
So the idea is that you have these invisible boxes on top of the visible ones. The invisible boxes only have borders such that any time your mouse hits a border, some clever z-index swapping takes place to make the visible containers change their stacking order.
For every .grid item you need to create a corresponding .box item: https://jsfiddle.net/ryanwheale/01v5yz86/93/

Make dots active on Slider

I have this Slider example created with pure JS.
The slider is working great. The only thing left to do would be to activate the three dots so when the 1st slide opens, 1st dot activates, showing different color than the other dots, and so on. Also, you should be able to open the correct slide when clicking dots, so 1st dot opens 1st slide, 2nd dot 2nd slide, and so on.
Could you help me to achieve this? You can find the source code below.
const nextBtn = document.querySelector('.nextBtn');
const prevBtn = document.querySelector('.prevBtn');
const container = document.querySelector('.images');
const offers = document.getElementById('offers');
const link = document.getElementById('links');
let colors = ['#7f86ff', '#2932d1', '#00067f'];
let currentSlide = 0;
let texts = ['Change1', 'Change2', 'Change3'];
let currentText = 0;
let links = ['Link1', 'Link2', 'Link3'];
let currentLink = 0;
function updateSlide(direction) {
currentSlide =
(colors.length + currentSlide + direction)
% colors.length;
container.style.backgroundColor = colors[currentSlide];
container.animate([{opacity:'0.1'}, {opacity:'1.0'}],
{duration: 200, fill:'forwards'})
}
function updateText(direction) {
currentText =
(texts.length + currentText + direction)
% texts.length;
offers.innerHTML = texts[currentText];
offers.animate([{transform:'translateY(-50px)', opacity:'0.0'}, {transform:'translateY(0)', opacity:'1.0'}],
{duration: 200, fill:'forwards'})
}
function updateLink(direction) {
currentLink =
(links.length + currentLink + direction)
% links.length;
link.innerHTML = links[currentLink];
link.animate([{transform:'scale(0,0)'}, {transform:'scale(1.1)'}],
{duration: 200, fill:'forwards'})
}
updateSlide(0);
updateText(0);
updateLink(0);
nextBtn.addEventListener('click', nextSlide);
prevBtn.addEventListener('click', prevSlide);
function nextSlide() {
updateSlide(+1);
updateText(+1);
updateLink(+1);
clearInterval(myInterval);
}
function prevSlide() {
updateSlide(-1);
updateText(-1);
updateLink(-1);
clearInterval();
clearInterval(myInterval);
}
var myInterval = window.setInterval(function(){
updateSlide(+1),updateText(+1),updateLink(+1); },
8000);
body {
min-height: 100vh;
display: flex;
align-items: center;
justify-content: center;
background-color: lightblue;
}
.images {
background-color: #4047c9;
flex: 0 0 80%;
min-height: 70vh;
border-radius: 10px;
position: relative;
display: flex;
flex-direction: column;
justify-content: flex-end;
align-items: center;
color: white;
}
#links {
text-decoration: none;
color: white;
border: solid 2px white;
border-radius: 3px;
padding: 5px 10px;
}
#links:hover {
background-color: #000238;
}
a {
color: white;
text-decoration: none;
}
.dots {
display: flex;
margin-top: 120px;
margin-bottom: 50px;
}
#dot1, #dot2, #dot3 {
width: 20px;
height: 20px;
background-color: rgb(147, 151, 249);
border-radius: 50%;
margin: 0px 5px;
cursor: pointer;
}
#dot1:active, #dot2:active, #dot3:active {
background-color: #fff;
}
.btn {
display: inline-block;
background: white;
color: black;
padding: 10px;
border: none;
cursor: pointer;
}
.prevBtn {
position: absolute;
top: 50%;
left: 0;
transform: translate(-50%, -50%);
}
.nextBtn {
position: absolute;
top: 50%;
right: 0;
transform: translate(50%, -50%);
}
.btn:active {
background-color: grey;
color: white;
}
.btn:hover {
background-color: grey;
color: white;
}
<body>
<div class="images">
<button type="button" class="btn prevBtn">Prev Btn</button>
<button type="button" class="btn nextBtn">Next Btn</button>
<h1 id="offers">Changing text</h1>
Links
<div class="dots">
<span id="dot1"></span>
<span id="dot2"></span>
<span id="dot3"></span>
</div>
</div>
</body>
First off, according to
https://developer.mozilla.org/en-US/docs/Web/CSS/:active
The :active CSS pseudo-class represents an element (such as a button) that is being activated by the user.
So if you want your dots to be active, you’ll have to write a different way of giving them an active state since they are currently <span> tags, I would recommend giving them a class of .active, and adding in Javascript code to add that class on to them, or adding in that style programmatically within the Javascript function.
Based on your other request though, you will most likely also have to make the dots an <a> tag or something along those lines so you can add functionality on to them to let clicking on the dots bring you to any slide. Something probably along the lines of:
function dot1Click() {
updateSlide(1);
updateText(1);
updateLink(1);
dot1.style.backgroundColor = #fff;
}
Then you should have something along the lines of what you want. I'll return to this question when I have more time to iron out a code snippet, but I wanted to give you something to help you get started!

Make a splitter very thin and grab it

I want to make a draggle splitter between 2 panels. The following is a working version.
Now, I want to make the width of handle as thin as possible (less than 0.1px?), so there is no way to make the width (appear) smaller than 1px?
Additionally, when the splitter is thin, it is hard to select by the mouse. Is there a way to make a splitter easy to grab?
Taking JSBin as example, how did they manage to realise the splitters among the panels?
(function($) {
$.fn.drags = function(opt) {
opt = $.extend({
handle: "",
cursor: "ew-resize",
min: 10
}, opt);
if (opt.handle === "") {
var $el = this;
} else {
var $el = this.find(opt.handle);
}
var priorCursor = $('body').css('cursor');
return $el.css('cursor', opt.cursor).on("mousedown", function(e) {
priorCursor = $('body').css('cursor');
$('body').css('cursor', opt.cursor);
if (opt.handle === "") {
var $drag = $(this).addClass('draggable');
} else {
var $drag = $(this).addClass('active-handle').parent().addClass('draggable');
}
var z_idx = $drag.css('z-index'),
drg_h = $drag.outerHeight(),
drg_w = $drag.outerWidth(),
pos_y = $drag.offset().top + drg_h - e.pageY,
pos_x = $drag.offset().left + drg_w - e.pageX;
var mouseMove = function(e) {
var prev = $('.draggable').prev();
var next = $('.draggable').next();
var total = prev.outerWidth() + next.outerWidth();
var totalPercentage = parseFloat(prev.css('flex')) + parseFloat(next.css('flex'));
var offset = prev.offset();
if(offset){
var leftPercentage = ((e.pageX - offset.left - drg_w / 2) / total) * totalPercentage;
var rightPercentage = totalPercentage - leftPercentage;
if (leftPercentage * 100 < opt.min || rightPercentage * 100 < opt.min) {
return;
}
prev.css('flex', leftPercentage.toString());
next.css('flex', rightPercentage.toString());
}
}
$drag.css('z-index', 1000).parent().on("mousemove", mouseMove).on("mouseup", function() {
$(this).off("mousemove", mouseMove).off("mouseup");
$('body').css('cursor', priorCursor);
$('.draggable').removeClass('draggable').css('z-index', z_idx);
});
e.preventDefault(); // disable selection
});
}
})(jQuery);
$('.handle').drags();
.flex-box {
display: flex;
width: 100%;
margin: 0;
height: 300px;
}
.flex-box .col {
border: 1px solid grey;
flex: 0.33;
padding: 12px;
overflow-y: auto;
overflow-x: hide;
}
.handle {
width: 1px;
text-align: center;
background: grey;
transition: all ease-in 0.1s;
}
.draggable {
background: grey;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="flex-box">
<div class="col">
<p>Pellentesque ...</p>
</div>
<div class="handle"></div>
<div class="col">
<p>Pellentesque ...</p>
</div>
</div>
If you'd like the handle to appear thinner try applying a negative value to the right "col" e.g. margin-left: -2px; so it overlaps the left "col" border on the left of it. I don't think you can make the width "appear" as 0.1px. Firefox is the only browser that renders such value. (https://css-tricks.com/forums/topic/0-1px-borders/)
.flex-box .col:last-child {
margin-left: -2px;
}
//raise handle layer to top
.handle {
.....
z-index: 9999;
}
Hope this helps...
*Edit:
This is the closest I could get to your request:
.flex-box {
display: flex;
width: 100%;
margin: 0;
height: 300px;
}
.flex-box .col {
border: 1px solid grey;
flex: 0.33;
padding: 12px;
overflow-y: auto;
overflow-x: hide;
}
.flex-box .col:last-child {
margin-left: -6px;
}
.handle {
width: 5px;
text-align: center;
transition: all ease-in 0.1s;
z-index: 999;
overflow: visible;
}
.handle-inner{
width: 5px;
height: 100%;
position: relative;
margin-left: -10px;
}
.draggable {
background: grey;
}
Jsbin :
https://jsbin.com/nupefekuhu/edit?html,css,js,output

Categories