I'm working on a simple card stack which rotates when clicked, my problem is I cant select a specific card and send it to the front and arrange again the cards according to number. I change the codes but luck, I consumed half a day to make it works, still not working.
I hope you understand me.
Thanks
here is a sample code.
codepen
var cardStack = document.getElementsByClassName('card');
var cardArray = []; // Does not change
var stateArray = []; // Changes - keeps track of card state
var prevStateArray = [];
function cardInit() {
for (var i=0; i<cardStack.length; i++) {
var cNum = i + 1;
var cName = 'card' + cNum.toString();
cardStack[i].classList.add(cName);
cardArray.push(cNum);
stateArray = cardArray;
};
};
function stackRefresh() {
prevStateArray = stateArray.slice(0);
stateArray.unshift(stateArray.pop());
}
function nextCard() {
stackRefresh();
for (var i=0; i<cardStack.length; i++) {
var cName = 'card' + prevStateArray[i].toString();
var cNameNew = 'card' + stateArray[i].toString();
cardStack[i].classList.remove(cName);
cardStack[i].classList.add(cNameNew);
};
}
cardInit();
body {
background-color: #2a2a2a;
}
.card {
width: 200px;
height: 320px;
background-color: #fff;
box-shadow: 0px 2px 4px 0px rgba(0,0,0,0.4);
border-radius: 5px;
display: inline-block;
position: absolute;
transform-origin: 0% 50%;
transition: all 1s ease;
}
.card-stack {
display: inline-block;
text-align: center;
position: relative;
left: 50%;
transform: translateX(-100px);
}
.card1 {
z-index: 1000;
left: 0;
}
.card2 {
z-index: 800;
transform: scale(0.99);
filter: brightness(0.9);
left: 20px;
}
.card3 {
z-index: 600;
transform: scale(0.98);
filter: brightness(0.8);
left: 40px;
}
.card4 {
z-index: 400;
transform: scale(0.97);
filter: brightness(0.7);
left: 60px;
animation-name: remove;
animation-duration: 1s;
}
#keyframes remove {
0% {transform: translateX(0px); opacity: 1};
50% {transform: translateX(-80px); opacity: 0};
51% {transform: translateX(10px) scale(0.97); opacity: 0};
100% {transform: translateX(0px) scale(0.97); opacity: 1;}
}
<div class="card-stack" onclick="nextCard();">
<div class="card">A</div>
<div class="card">B</div>
<div class="card">C</div>
<div class="card">D</div>
</div>
Try this sample
I changed html
<div class="card-stack" onclick="nextCard(event);">
...
And js function
function nextCard(e) {
var clickedCssClass = e.srcElement.classList[1];
if (!clickedCssClass) return;
var match = /(\d+)/.exec(clickedCssClass);
var clickedNumber = match[0];
for(var j = 1; j < clickedNumber ; j++){
stackRefresh();
for (var i=0; i<cardStack.length; i++) {
var cName = 'card' + prevStateArray[i].toString();
var cNameNew = 'card' + stateArray[i].toString();
cardStack[i].classList.remove(cName);
cardStack[i].classList.add(cNameNew);
};
}
}
First include the following statement in head section of the html:
<script src="http://code.jquery.com/jquery-3.2.1.js"></script>
Add then change the following tag
<div class="card-stack" onclick="nextCard();">
To
<div class="card-stack">
Finally, I modified the function cardInit as follow:
function cardInit() {
for (var i=0; i<cardStack.length; i++) {
var cNum = i + 1;
var cName = 'card' + cNum.toString();
cardStack[i].classList.add(cName);
$(cardStack[i]).on("click",function()
{
prevClassName=this.classList[1];
$(".card1").removeClass("card1").addClass(prevClassName);
this.className=this.className.replace(prevClassName,"card1");
});
cardArray.push(cNum);
stateArray = cardArray;
};
};
did you mean this?
I have added a moveTop function like
function moveTop() {
event.preventDefault();
event.stopPropagation();
var index = Array.prototype.slice.call(event.target.parentNode.querySelectorAll('.card')).indexOf(event.target)
var temp = stateArray[index];
prevStateArray = stateArray.slice(0);
stateArray.splice(index, 1);
stateArray.unshift(temp);
refreshCards();
}
var cardStack = document.getElementsByClassName('card');
var cardArray = []; // Does not change
var stateArray = []; // Changes - keeps track of card state
var prevStateArray = [];
function cardInit() {
for (var i = 0; i < cardStack.length; i++) {
var cNum = i + 1;
var cName = 'card' + cNum.toString();
cardStack[i].classList.add(cName);
cardArray.push(cNum);
stateArray = cardArray;
};
};
function stackRefresh() {
prevStateArray = stateArray.slice(0);
stateArray.unshift(stateArray.pop());
}
function nextCard() {
stackRefresh();
refreshCards();
}
function refreshCards() {
for (var i = 0; i < cardStack.length; i++) {
var cName = 'card' + prevStateArray[i].toString();
var cNameNew = 'card' + stateArray[i].toString();
cardStack[i].classList.remove(cName);
cardStack[i].classList.add(cNameNew);
};
}
function moveTop() {
event.preventDefault();
event.stopPropagation();
var index = Array.prototype.slice.call(event.target.parentNode.querySelectorAll('.card')).indexOf(event.target)
var temp = stateArray[index];
prevStateArray = stateArray.slice(0);
stateArray.splice(index, 1);
stateArray.unshift(temp);
refreshCards();
}
cardInit();
body {
background-color: #2a2a2a;
}
.card {
width: 200px;
height: 320px;
background-color: #fff;
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.4);
border-radius: 5px;
display: inline-block;
position: absolute;
transform-origin: 0% 50%;
transition: all 1s ease;
text-align: right;
}
.card-stack {
display: inline-block;
text-align: center;
position: relative;
left: 50%;
transform: translateX(-100px);
}
.card1 {
z-index: 1000;
left: 0;
}
.card2 {
z-index: 800;
transform: scale(0.99);
filter: brightness(0.9);
left: 20px;
}
.card3 {
z-index: 600;
transform: scale(0.98);
filter: brightness(0.8);
left: 40px;
}
.card4 {
z-index: 400;
transform: scale(0.97);
filter: brightness(0.7);
left: 60px;
animation-name: remove;
animation-duration: 1s;
}
#keyframes remove {
0% {
transform: translateX(0px);
opacity: 1
}
;
50% {
transform: translateX(-80px);
opacity: 0
}
;
51% {
transform: translateX(10px) scale(0.97);
opacity: 0
}
;
100% {
transform: translateX(0px) scale(0.97);
opacity: 1;
}
}
<div class="card-stack" onclick="nextCard();">
<div class="card" onclick="moveTop()">A</div>
<div class="card" onclick="moveTop()">B</div>
<div class="card" onclick="moveTop()">C</div>
<div class="card" onclick="moveTop()">D</div>
</div>
The problem you are having is that you don't know which card was clicked. My guess is to pass the event when calling nextCard():
onclick="nextCard(event)"
And within the function:
function nextCard(event) {
// detect which card was picked
console.log(event.target);
// logic to bring picked card to the top
...
}
Related
I've been trying to develop a CSS keyframes animation for a navigation bar.
You can see in the code snippet how the animation works - the red line is animated when the user clicks an element of the nav bar. The first element of the nav bar is active by default (the red line is under this element). When an element is clicked, the JS takes the properties of the animation element, as well as the properties of the element that was clicked. These properties are incorporated into new keyframes that are inserted into the single keyframes rule.
When the second element is clicked, the animation runs successfully from element 1 --> 2. The animation also runs successfully from element 1 --> 3.
But after the animation plays from element 1 --> 2, it won't play from element 2 --> 3. The animationend event does not trigger (I checked this). As of now, I'm only concerned with the animation going forwards.
After researching, I tried several methods to fix this. Removing and reattaching the animation class does not work, even with a DOM reflow being triggered. Changing the animation-play-state from 'running' to 'paused' does not work either. Other solutions, such as changing the animation-name to 'none' and then back, only generate more problems, like the position of the animation element being reset upon the ending of the animation. I truly do not know how to fix this.
I would prefer to make a flexible keyframes animation, such as this, rather than brute-forcing it. A brute force scenario would include making 6 different keyframes rules, and I want the code to be applicable to any number of elements in the navigation bar. Adding keyframes rules for every addition of an element would require exponentially more code each addition.
Thanks.
~ Code for demo ~
var keyframes = findKeyframesRule('movey');
$(document).ready(() => {
$('div.one').click(() => {
if (!($('div.one').hasClass('active'))) {
/* unfinished */
}
})
$('div.two').click(() => {
if (!($('div.two').hasClass('active'))) {
/* transfer active class */
$('div.active').removeClass('active');
$('div.two').addClass('active');
var left = ( parseInt($('div.absolute').css('left')) / $(window).width() ) * 100;
/* reset keyframes before animation */
clearKeyframes();
/* add new keyframes for when div.two is clicked */
keyframes.appendRule("0% { width: 15%; left: " + left + "%;}");
keyframes.appendRule("49.99% { width: 30%; left: " + left + "%; right: 70%;}");
keyframes.appendRule("50% { width: 30%; left: unset; right: 70%;}");
keyframes.appendRule("100% { width: 15%; right: 70%;}");
/* first animation - add animation class */
if (!($('div.absolute').hasClass('animateMovey'))) {
$('div.absolute').addClass('animateMovey');
/* animations after first - remove and reattach animation class with new keyframes */
} else {
$('div.absolute').removeClass('animateMovey');
$('div.absolute').addClass('animateMovey');
}
/* ensure animation occurs */
$('div.animateMovey').on('animationend', () => {
console.log('Animation ended');
})
}
})
$('div.three').click(() => {
if (!($('div.three').hasClass('active'))) {
$('div.active').removeClass('active');
$('div.three').addClass('active');
var left = ( parseInt($('div.absolute').css('left')) / $(window).width() ) * 100;
var width = 45 - left;
clearKeyframes();
keyframes.appendRule("0% { width: 15%; left: " + left + "%;}");
keyframes.appendRule("49.99% { width: " + width + "%; left: " + left + "%; right: 55%;}");
keyframes.appendRule("50% { width: " + width + "%; left: unset; right: 55%;}");
keyframes.appendRule("100% { width: 15%; right: 55%;")
if (!($('div.absolute').hasClass('animateMovey'))) {
$('div.absolute').addClass('animateMovey');
} else {
$('div.absolute').removeClass('animateMovey');
$('div.absolute').addClass('animateMovey');
}
$('div.animateMovey').on('animationend', () => {
console.log('Animation ended');
})
}
})
})
function findKeyframesRule(rule) {
var ss = document.styleSheets;
for (var i = 0; i < ss.length; ++i) {
for (var j = 0; j < ss[i].cssRules.length; ++j) {
if (ss[i].cssRules[j].type == window.CSSRule.KEYFRAMES_RULE && ss[i].cssRules[j].name == rule)
return ss[i].cssRules[j];
}
}
return null;
}
function clearKeyframes() {
for (var i = 0; i <= 3; ++i) {
if (keyframes[0]) {
var keyToRemove = keyframes[0].keyText;
keyframes.deleteRule(keyToRemove);
}
}
}
body {
margin: 0;
}
div.nav {
position: relative;
display: block;
overflow: hidden;
width: 100%;
}
div.nav div {
float: left;
width: 15%;
height: 75px;
}
div.nav div:hover {
opacity: 0.5;
}
div.one {
background-color: #7a7a7a;
}
div.two {
background-color: #9e9e9e;
}
div.three {
background-color: #bdbdbd;
}
.active {
box-shadow: inset 3px 5px 6px #000;
}
div.animateMovey {
animation-name: movey;
animation-duration: 0.6s;
animation-fill-mode: forwards;
animation-timing-function: ease-in-out;
}
div.relative {
position: relative;
width: 100%;
height: 20px;
}
div.absolute {
position: absolute;
background-color: #ff8c69;
width: 15%;
height: 100%;
}
#keyframes movey {
100% { }
}
<div>
<div class="nav">
<div class="one active"></div>
<div class="two"></div>
<div class="three"></div>
</div>
<div class="relative">
<div class="absolute"></div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
Interesting question. I'm not sure why the event is not re-triggering in this case, but will suggest a few changes to your approach:
Aim to animate transform and opacity instead of width and left, right
(https://developers.google.com/web/fundamentals/design-and-ux/animations/animations-and-performance)
One way to do this is to use a separate red element under each box, and slide it left or right using transform
Use animation-delay to create the lengthening and shortening effect
Try to reuse the animation logic, so it will work regardless of the number of items.
The challenging part of this effect is managing the opacity of each line. I've used animationEnd to help with that, and it appears to work fine.
Additional comments in the example code. It could be improved by handling clicks while animation is active, consolidating animation functions etc. You could also vary the animation duration depending on the number of items.
let boxes = null;
let lines = null;
let fromIndex = 0;
let toIndex = 0;
const ANIMATION_DURATION = 0.1; // seconds
const animation = {
animating: false,
lines: [],
direction: "right",
inOrOut: "in"
};
function getEls() {
boxes = [...document.querySelectorAll(".box")];
lines = [...document.querySelectorAll(".line")];
}
function setAnimationDuration() {
lines.forEach((line) => {
line.style.animationDuration = `${ANIMATION_DURATION}s`;
});
}
function addEvents() {
boxes.forEach((box, index) => {
box.addEventListener("click", () => {
// User has clicked the currently active box
if (fromIndex === index) return;
// Line is currently animating
if (animation.animating) return;
toIndex = index;
updateActiveBox();
handleLineAnimation();
});
});
document.addEventListener("animationend", (e) => {
// Maintain opacity on lines that animate in
if (animation.inOrOut === "in") {
e.target.style.opacity = 1;
}
});
}
function updateActiveBox() {
boxes[fromIndex].classList.remove("active");
boxes[toIndex].classList.add("active");
}
function updateActiveLine(line) {
lines[fromIndex].classList.remove("active");
line.classList.add("active");
}
function handleLineAnimation() {
animation.animating = true;
animation.lines = [];
if (toIndex > fromIndex) {
animation.direction = "right";
for (let i = fromIndex; i <= toIndex; i++) {
animation.lines.push(lines[i]);
}
} else {
animation.direction = "left";
for (let i = fromIndex; i >= toIndex; i--) {
animation.lines.push(lines[i]);
}
}
animate();
}
function animate() {
const wait = (animation.lines.length - 1) * ANIMATION_DURATION * 1000;
animation.inOrOut = "in";
animateIn();
setTimeout(() => {
resetLine();
updateActiveLine(lines[toIndex]);
animation.inOrOut = "out";
animateOut();
setTimeout(() => {
resetLine();
onAnimationComplete();
}, wait);
}, wait);
}
function animateIn() {
const {
direction,
lines
} = animation;
lines.forEach((line, index) => {
// index = 0 is currently active, no need to animate in
if (index > 0) {
line.classList.add(`animate-in-${direction}`);
line.style.animationDelay = `${(index - 1) * ANIMATION_DURATION}s`;
}
});
}
function animateOut() {
const {
direction,
lines
} = animation;
lines.forEach((line, index) => {
// lines.length - 1 is new active, don't animate out
if (index < lines.length - 1) {
line.classList.remove(`animate-in-${direction}`);
line.classList.add(`animate-out-${direction}`);
line.style.animationDelay = `${index * ANIMATION_DURATION}s`;
}
});
}
function resetLine() {
const {
direction,
lines,
inOrOut
} = animation;
lines.forEach((line) => {
line.classList.remove(`animate-${inOrOut}-${direction}`);
line.style.animationDelay = null;
// After animating out, remove inline opacity
if (inOrOut === "out") {
if (!line.classList.contains("active")) {
line.style.opacity = "";
}
}
});
}
function onAnimationComplete() {
animation.animating = false;
fromIndex = toIndex;
}
function init() {
getEls();
setAnimationDuration();
addEvents();
}
function reset() {
fromIndex = 0;
init();
lines.forEach((line, index) => {
line.classList.remove('active');
line.style.opacity = "";
boxes[index].classList.remove('active');
});
boxes[0].classList.add("active");
lines[0].classList.add("active");
}
init();
// DEBUG
document.getElementById("debug").addEventListener("change", (e) => {
document.querySelector("nav").classList.toggle("debug-on");
});
document.getElementById("add").addEventListener("click", (e) => {
const div = document.createElement("div");
div.classList.add("box");
div.innerHTML = '<div class="new"></div><span class="line"></span>';
document.querySelector("nav").appendChild(div);
reset();
});
document.getElementById("remove").addEventListener("click", (e) => {
const indexToRemove = boxes.length - 1;
if (indexToRemove > 0) {
const box = boxes[indexToRemove];
box.parentNode.removeChild(box);
reset();
}
});
nav {
display: flex;
flex-wrap: wrap;
overflow: hidden;
}
.debug-on .line {
border: 1px solid;
box-sizing: border-box;
opacity: 0.2;
}
.box {
display: flex;
flex-direction: column;
position: relative;
float: left;
flex: 0 0 15%;
/* Allows the line to slide left or right with opacity: 1 */
overflow: hidden;
}
.box>div {
cursor: pointer;
height: 75px;
}
.one {
background-color: #7a7a7a;
}
.two {
background-color: #9e9e9e;
}
.three {
background-color: #bdbdbd;
}
.new {
background-color: pink;
border: 1px solid;
box-sizing: border-box;
}
.line {
background-color: #ff8c69;
height: 20px;
opacity: 0;
pointer-events: none;
width: 100%;
animation-fill-mode: forwards;
animation-timing-function: linear;
}
.active>div {
box-shadow: inset 3px 5px 6px #000;
}
.box:hover div {
opacity: 0.5;
}
.line.active {
opacity: 1;
}
.line.show {
opacity: 1;
}
.animate-in-right {
animation-name: SLIDE_IN_RIGHT;
}
.animate-out-right {
animation-name: SLIDE_OUT_RIGHT;
}
.animate-in-left {
animation-name: SLIDE_IN_LEFT;
}
.animate-out-left {
animation-name: SLIDE_OUT_LEFT;
}
#keyframes SLIDE_IN_RIGHT {
from {
opacity: 1;
transform: translateX(-100%);
}
to {
opacity: 1;
transform: translateX(0);
}
}
#keyframes SLIDE_OUT_RIGHT {
from {
opacity: 1;
transform: translateX(0);
}
to {
opacity: 1;
transform: translateX(100%);
}
}
#keyframes SLIDE_IN_LEFT {
from {
opacity: 1;
transform: translateX(100%);
}
to {
opacity: 1;
transform: translateX(0);
}
}
#keyframes SLIDE_OUT_LEFT {
from {
opacity: 1;
transform: translateX(0);
}
to {
opacity: 1;
transform: translateX(-100%);
}
}
/* for demo only */
.debug {
background: #eee;
padding: 1rem;
display: inline-flex;
flex-direction: column;
font: 14px/1 sans-serif;
position: fixed;
bottom: 0;
right: 0;
}
.debug button {
margin-top: 1rem;
padding: .25rem;
}
<nav>
<div class="box active">
<div class="one"></div>
<span class="line active"></span>
</div>
<div class="box">
<div class="two"></div>
<span class="line"></span>
</div>
<div class="box">
<div class="three"></div>
<span class="line"></span>
</div>
</nav>
<br><br>
<div class="debug">
<label for="debug">Debug Lines <input type="checkbox" id="debug">
</label>
<button id="add">Add cell</button>
<button id="remove">Delete cell</button>
</div>
So the idea of my work is with the 10 slides in my section will have an element append to the slides, which are drinking can products. When the cursor hovers the cans, the cans will increase the size to show the real detail of the can.
Anyway, I have managed to create my carousel active slide, the 3D effect cans that can rotate clockwise and have a list of different colour cans in CSS (different background for each bottle class).
I can only get the first can working on the active slide, but the rest of the slides are blank. I've only create a list of 3 items in the array hoping to fill up the three slides with the drinking can products but no luck? What am I doing wrong?
I'm calling the initApp function, which has the array of cans because I want to append items, but only one at a time...
so in the each.function(index) - I can add the index, and then in initApp(index). and then in the initApp function I can adjust so that bottle[index] gets selected and then added. But nothing seems to work?? What am I doing wrong? I know there is a bunch of ways I can do this.
Like could I skip the initApp() function and add all the code in the .each(function() { my code to append bottle})??
// slider
$("#products>article").on("click", function(){
$("#products>article").removeClass("active");
$(this).addClass("active");
animate();
});
function getActiveArticle(){
var x = 0;
$("#products>article").each(function(e){
if($("#products>article").eq(e).hasClass("active")){
x = e;
return false;
}
});
return x;
}
function gofwd(){
var activeIndex = getActiveArticle();
var minArticles = 0;
var maxArticles = $("#products>article").length - 1;
if(activeIndex >= maxArticles){
activeIndex = minArticles-1;
}
$("#products>article").removeClass("active");
$("#products>article").eq(activeIndex+1).addClass("active");
animate();
}
function gobwd(){
var activeIndex = getActiveArticle();
var minArticles = 1;
var maxArticles = $("#products>article").length;
$("#products>article").removeClass("active");
$("#products>article").eq(activeIndex-1).addClass("active");
animate();
}
$(document).ready(function(){
animate();
});
function animate(){
var articleIndex = getActiveArticle();
var totalMargin = 25 * (articleIndex+1) - (25*(articleIndex));
var articlePosition = Math.floor($("#products>article").eq(articleIndex).offset().left - $("#products").offset().left) - totalMargin;
var productsHalfWidth = $("#products").width()/2;
if(articleIndex == 0){
var halfWidth = 150;
}else{
var halfWidth = 100;
}
var finalPosition = productsHalfWidth - articlePosition - halfWidth;
$("#products").animate({
"left": finalPosition,
}, {
duration: 500,
easing: 'easeOutBack',
});
}
$(window).on("resize", function(){
animate();
});
var autoPlay = setInterval(function(){
gofwd();
}, 3500);
$("#slider").on("mouseenter", function(){
clearInterval(autoPlay);
});
$("#slider").on("mouseleave", function(){
autoPlay = setInterval(function(){
gofwd();
}, 4500);
});
// cans
const getElement = (selector) => document.querySelector(selector);
const createElement = (tag) => document.createElement(tag);
// const addBackground1 = document.style['background'] = 'url ("https://i.postimg.cc/BZ8rj2NM/sleve.png")';
const addSideStyle = ($side, i) => {
let deg = 3.75 * i;
let bgPosition = 972 - (i * 10.125);
$side.style['background-position'] = bgPosition + 'px 0';
$side.style['-webkit-transform'] = 'rotateY(' + deg + 'deg) translateZ(154px)';
$side.style['-moz-transform'] = 'rotateY(' + deg + 'deg) translateZ(154px)';
$side.style['transform'] = 'rotateY(' + deg + 'deg) translateZ(154px)';
};
const createBottle = () => {
const $bottle = createElement('div');
$bottle.classList.add('bottle');
const $bottleLabel = createBottleLabel();
for (let i = 0; i < 96; i = i + 1){
let $bottleSide = createBottleSide(i);
$bottleLabel.append($bottleSide);
}
$bottle.append($bottleLabel);
return $bottle;
};
const createBottleLabel = () => {
const $bottleLabel = createElement('div');
$bottleLabel.classList.add('label');
return $bottleLabel;
}
const createBottleSide = (i) => {
const $bottleSide = createElement('div');
$bottleSide.classList.add('side');
addSideStyle($bottleSide, i);
return $bottleSide;
};
const changeBottleSize = (clickFn) => {
const _bottle = createElement('div');
_bottle.classList.add('bottle');
_bottle.style['transform'] = 'scale(0.9)';
return _bottle;
}
const clickFn = () => {
const $bottleSize = getElement('.container');
// const $bottle1 = changeBottleSize();
// const $bottle2 = changeBottleSize();
// const $bottle3 = changeBottleSize();
$bottleSize.style['transform'] = 'scale(0.9)';
return $bottleSize;
}
$('#products article').each(function(index) {
$(this).append(initApp())
});
const initApp = (index) => {
const $container = getElement('.container');
const $bottle1 = createBottle();
const $bottle2 = createBottle();
const $bottle3 = createBottle();
[$bottle1, $bottle2, $bottle3].forEach(($bottle, i) => {
$bottle.classList.add('bottle' + i);
});
$container.append($bottle1, $bottle2, $bottle3);
};
initApp();
* {
padding: 0;
margin: 0;
font-family: "Arial";
box-sizing: border-box;
}
body {
background-color: #444;
}
#slider {
position: relative;
overflow: hidden;
width: 90vw;
height: 750px;
margin: 50px auto;
background-color: rgba(255, 255, 255, .5);
}
#products {
position: relative;
display: flex;
width: 100%;
height: 100%;
align-items: center;
padding: 0 25px;
}
#products>article:first-child {
margin-left: 0;
}
#products>article {
position: relative;
min-width: 250px;
min-height: 250px;
margin-left: 25px;
font-size: 17px;
cursor: pointer;
/* background-color: rgba(255,0,0,.5); */
transition: all .3s ease-in-out;
}
#products>article.active {
min-width: 300px;
min-height: 300px;
font-size: 20px;
}
#picText {
position: absolute;
color: #fff;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) rotate(-45deg);
}
#id {
color: #fff;
margin: 15px;
}
#gofwd,
#gobwd {
position: absolute;
top: 50%;
padding: 50px 15px;
z-index: 1;
cursor: pointer;
background-color: rgba(255, 255, 255, .6);
transform: translateY(-50%);
transition: all .3s ease-out;
}
#gofwd:hover,
#gobwd:hover {
background-color: #fff;
}
#gobwd {
left: 0;
}
#gofwd {
right: 0;
}
.can {
position: relative;
}
.bottle:hover {
transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg)
/* translate3d(350px, 190px, 40px) */
scale(0.7);
}
.bottle {
transition: all 0.2s;
width: 10.125px;
-webkit-transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg) translate3d(650px, 190px, 40px);
-moz-transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg) translate3d(650px, 190px, 40px);
transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg) translate3d(350px, 190px, 40px);
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
transform-style: preserve-3d;
transform: scale(0.2);
position: absolute;
}
.bottle0 {
top: 40px;
left: 100px;
}
.bottle1 {
top: 100px;
left: 500px;
}
.bottle2 {
top: 100px;
left: 700px;
}
.bottle>img {
position: absolute;
top: -180px;
left: -182px;
width: 374px;
}
.label {
-webkit-animation: spin 10s infinite linear;
-moz-animation: spin 10s infinite linear;
animation: spin 10s infinite linear;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
}
.side {
position: absolute;
width: 10.55px;
height: 679px;
margin-bottom: 400px;
}
.bottle0 .side {
background: url("https://i.postimg.cc/BZ8rj2NM/sleve.png");
}
.bottle1 .side {
background: url("https://i.postimg.cc/Fs2RgnN6/passion.png");
}
.bottle2 .side {
background: url("https://i.postimg.cc/zGzJjm40/raspberry.png");
}
#-webkit-keyframes spin {
from {
-webkit-transform: rotateY(0deg);
transform: rotateY(0deg);
}
to {
-webkit-transform: rotateY(-360deg);
transform: rotateY(-360deg);
}
}
#-moz-keyframes spin {
from {
-moz-transform: rotateY(0deg);
transform: rotateY(0deg);
}
to {
-moz-transform: rotateY(-360deg);
transform: rotateY(-360deg);
}
}
#keyframes spin {
from {
-webkit-transform: rotateY(0deg);
-moz-transform: rotateY(0deg);
transform: rotateY(0deg);
}
to {
-webkit-transform: rotateY(-360deg);
-moz-transform: rotateY(-360deg);
transform: rotateY(-360deg);
}
}
#mixin makeSide() {}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-easing/1.4.1/jquery.easing.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<div id="slider">
<span id="gofwd" onClick="gofwd();">></span>
<span id="gobwd" onClick="gobwd();"><</span>
<div id="products">
<article class="active">
<div class="container"></div>
</article>
<article>
<div class="container">
<p id="id">2</p>
</div>
</article>
<article>
<div class="picture">
<p id="id">3</p>
</div>
</article>
<article>
<div class="picture">
<p id="id">4</p>
</div>
</article>
<article>
<div class="picture">
<p id="id">5</p>
</div>
</article>
<article>
<div class="picture">
<p id="id">6</p>
</div>
</article>
<article>
<div class="picture">
<p id="id">7</p>
</div>
</article>
<article>
<div class="picture">
<p id="id">8</p>
</div>
</article>
<article>
<div class="picture">
<p id="id">9</p>
</div>
</article>
<article>
<div class="picture">
<p id="id">10</p>
</div>
</article>
</div>
</div>
If you look at your Javascript Console you should the following error:
you crated the initApp function as a const after calling it, that won't work. You have two options:
move the const initApp up, or
declare it a function like this:
function initApp(index){
// …
}
I'm trying to have only one button working at one time .. and it does not work in any way ..
Although I do listener on both separately, and ID changed ..
I tried different options and could not reach a solution
help please
https://codepen.io/ido4560/pen/dZxqvZ
html
<div class="buttons">
<button id="buttonStart">Start Game</button>
<button id="buttonReset">Reset</button>
</div>
<div id="main">
<div id="first">
<div data-il="The Zombie" class="anim1"></div>
</div>
<div id="second">
<div data-il="The Man" class="anim2"></div>
</div>
<div id="third">
<div data-il="The Woman" class="anim3"></div>
</div>
</div>
<span>Score: </span>
css
#keyframes zombieWalk {
0% {
background-position: 0px 0px;
}
100% {
background-position: 1191px 0px;
}
}
#keyframes manWalk {
0% {
background-position: -5px 2px;
}
100% {
background-position: -993px 6px;
}
}
#keyframes womanWalk {
0% {
background-position: -21px 0px;
}
100% {
background-position: -1020px 0px;
}
}
body {
background-color: black;
margin: 10px auto;
width: 1000px;
text-align: center;
}
#main {
border: 2px solid white;
}
#main>#first {
background-color: red;
height: 179px;
}
#main>#first>div {
height: 167px;
width: 133px;
background: url(zombie.png) 0px 0px;
background-size: 1323px 168px;
background-color:white;
}
#main>#second {
background-color: blue;
height: 173px;
}
#main>#second>div {
height: 162px;
width: 133px;
background: url(man.png) -5px 2px;
background-size: 1126px 163px;
background-color:white;
}
#main>#third {
background-color: yellow;
height: 168px;
}
#main>#third>div {
height: 167px;
width: 133px;
background: url(woman.png) -21px 0px;
background-size: cover;
background-color:white;
}
#main>#first>.zombieWalk {
animation: zombieWalk 1s steps(9) infinite;
transform: translate(860px, 0px);
animation-play-state: running;
}
#main>#second>.manWalk {
animation: manWalk 1s steps(7) infinite;
transform: translate(860px, 0px);
animation-play-state: running;
}
#main>#third>.womanWalk {
animation: womanWalk 1s steps(6) infinite;
transform: translate(860px, 0px);
animation-play-state: running;
}
.buttons>button {
font-size: 20px;
margin: 10px 50px 20px 50px;
}
span {
color: red;
font-weight: bold;
line-height: 20px;
font-family: arial;
}
abcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgabcdefgab
js
/* Global var */
var div = document.querySelectorAll("#main>div>div");
var flag = 1;
var span = document.querySelector("span");
function runGame() {
var buttonStart = document.getElementById("buttonStart");
console.log(buttonStart);
buttonStart = addEventListener("click", startGame);
var buttonReset = document.getElementById("buttonReset");
console.log(buttonReset);
buttonReset = addEventListener("click", startAgain);
var number = rndNumber();
div[0].style.transition = 'transform ' + (rndNumber()) + 'ms';
//console.log(number);
var number = rndNumber();
div[1].style.transition = 'transform ' + (rndNumber()) + 'ms';
//console.log(number);
var number = rndNumber();
div[2].style.transition = 'transform ' + (rndNumber()) + 'ms';
//console.log(number);
div[0].addEventListener("transitionend", animEnd);
div[1].addEventListener("transitionend", animEnd);
div[2].addEventListener("transitionend", animEnd);
}
function animEnd(e) {
//console.log('im end');
//console.log(e);
console.log(flag);
if (flag == 1) {
var player = e.target.getAttribute("data-il");
//console.log(player + ' first');
span.innerHTML += "<br>";
span.innerText += '#1 ' + player;
//console.log(span);
flag++;
} else if (flag == '2') {
var player = e.target.getAttribute("data-il");
//console.log(player + ' second');
span.innerHTML += "<br>";
span.innerText += '#2 ' + player;
span.innerHTML += "<br>";
flag++;
} else if (flag == '3') {
var player = e.target.getAttribute("data-il");
//console.log(player + ' third');
span.innerText += '#3 ' + player;
}
}
function startGame() {
div[0].className = "zombieWalk";
div[1].className = "manWalk";
div[2].className = "womanWalk";
}
function rndNumber() {
return Math.floor(Math.random() * 10000);
}
function startAgain(){
window.location.reload(false);
}
runGame();
I played around with your code a bit on codepen. Though your question is
a bit vague, but I suspect that the issue you are having is that you are doing:
buttonStart = addEventListener("click", startGame);
buttonReset = addEventListener("click", startAgain);
Instead of
buttonStart.addEventListener("click", startGame);
buttonReset.addEventListener("click", startAgain);
Explanation: You are supposed to apply event listeners to buttonStart and buttonReset and not equate it to them.
I am using a button that triggers 4-5 other buttons with animation. its working fine in Chrome but not in FireFox
I have used a fullscreen background video in my current project, with this button, but in firefox, when i inspect elements, it shows there, but the browser is not displaying the element at all.
inspiration taken by - http://codepen.io/phenax/
'use strict';
(function (document, win) {
var animation_time = 600;
var btn_move_limit = 30;
var item_showing = false;
var className = {
show_items: 'menu--list__show',
revolve: 'menu--list__revolve',
button_cross: 'bar__crossy'
};
var $el = {
toggle_btn: document.querySelector('.js-menu--toggle'),
menu_items: document.querySelector('.js-menu--list'),
items: document.querySelectorAll('.js-item')
};
var constrain = function constrain(val, lim) {
return val > lim ? lim : val < -lim ? -lim : val;
};
var setButtonPosition = function setButtonPosition(left, top) {
$el.toggle_btn.style.left = constrain(left, btn_move_limit) + 'px';
$el.toggle_btn.style.top = constrain(top, btn_move_limit) + 'px';
};
var showAllItems = function showAllItems() {
var item_menu = $el.menu_items.classList;
item_menu.add(className.show_items);
setTimeout(function () {
item_menu.add(className.revolve);
$el.toggle_btn.classList.add(className.button_cross);
item_showing = true;
}, animation_time);
};
var hideAllItems = function hideAllItems() {
var item_menu = $el.menu_items.classList;
item_menu.remove(className.revolve);
$el.toggle_btn.classList.remove(className.button_cross);
setTimeout(function () {
item_menu.remove(className.show_items);
item_showing = false;
setButtonPosition(0, 0);
}, animation_time);
};
var findPosRelative = function findPosRelative(e) {
e = e.pageX ? {
pageX: e.pageX,
pageY: e.pageY
} : e.touches[0];
var offset = {
x: win.innerWidth / 2,
y: win.innerHeight / 2
};
e.pageX = e.pageX - offset.x;
e.pageY = e.pageY - offset.y;
return e;
};
var menuBtnClickHandler = function menuBtnClickHandler() {
if (item_showing)
hideAllItems();
else
showAllItems();
};
var itemClick = function itemClick(e) {
var item_id = e.target.dataset.id;
console.log('Item ID: ' + item_id);
hideAllItems();
};
var mouseMoveMent = function mouseMoveMent(e) {
var left, top;
if (item_showing) {
e = findPosRelative(e);
left = 140 * e.pageX / win.innerWidth;
top = 140 * e.pageY / win.innerHeight;
} else {
left = 0;
top = 0;
}
setButtonPosition(left, top);
};
document.addEventListener('DOMContentLoaded', function () {
$el.toggle_btn.addEventListener('click', menuBtnClickHandler);
for (var i = 0; i < $el.items.length; i++) {
if (window.CP.shouldStopExecution(1)) {
break;
}
$el.items[i].addEventListener('click', itemClick);
}
window.CP.exitedLoop(1);
win.addEventListener('mousemove', mouseMoveMent);
win.addEventListener('touchmove', mouseMoveMent);
});
}(document, window));
.menu--toggle {
position: absolute;
width: 80px;
height: 80px;
border-radius: 50%;
transform: translateX(-50%);
border: none;
outline: none;
cursor: pointer;
left: 0;
top: 0;
color: #222;
z-index: 1;
background-image: url("../images/logo/logo.jpg");
background-position: center;
background-size: cover;
box-shadow: 0 0 0 rgba(204, 169, 44, 0.4);
}
.menu {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
margin-top: -80px;
filter: url("#svgFilter"); }
.menu .item {
position: absolute;
width: 80px;
height: 80px;
border-radius: 50%;
transform: translateX(-50%);
border: none;
outline: none;
cursor: pointer;
left: 0;
top: 0;
background-color: #FFEB3B;
color: #222; }
.menu .item {
transition: all 0.6s ease-in-out; }
.menu--toggle {
transition: all .2s linear; }
.menu--toggle .bar {
width: 20px;
height: 2px;
background-color: #222;
margin: 5px auto;
transition: all 0.6s ease-in-out; }
.menu--toggle.bar__crossy .bar:nth-child(2) {
opacity: 0; }
.menu--toggle.bar__crossy .bar:nth-child(1) {
transform: translateY(7px) rotate(45deg); }
.menu--toggle.bar__crossy .bar:nth-child(3) {
transform: translateY(-7px) rotate(-45deg); }
.menu--list ul {
list-style-type: none;
padding: 0;
margin: 0; }
.menu--list li {
position: absolute;
width: 60px;
height: 80px;
transition: all 0.6s ease-in-out;
transform-origin: 0% 50%; }
.menu--list__show .item {
margin-left: 60px; }
.menu--list__revolve li:nth-child(1) {
transform: rotate(90deg); }
.menu--list__revolve li:nth-child(1) .item {
transform: rotate(270deg); }
.menu--list__revolve li:nth-child(2) {
transform: rotate(180deg); }
.menu--list__revolve li:nth-child(2) .item {
transform: rotate(180deg); }
.menu--list__revolve li:nth-child(3) {
transform: rotate(270deg); }
.menu--list__revolve li:nth-child(3) .item {
transform: rotate(90deg); }
.menu--list__revolve li:nth-child(4) {
transform: rotate(360deg); }
.menu--list__revolve li:nth-child(4) .item {
transform: rotate(0deg); }
<div class="menu">
<nav class="menu--list js-menu--list">
<ul>
<li><button type="button" onClick="window.open('https://www.facebook.com/themadhousecafe', '_blank')" class="fa fa-facebook item js-item" data-id="1"></button></li>
<li><button type="button" onClick="window.open('http://blog.nomadbaker.com/', '_blank')" class="fa item js-item" data-id="2">Blog</button></li>
<li><button type="button" onClick="window.open('#', '_blank')" class="item js-item" data-id="3">Menu</button></li>
<li><button type="button" onClick="window.open('#', '_blank')" class="fa fa-phone item js-item" data-id="4"></button></li>
</ul>
</nav>
<button type="button" class='logo_button menu--toggle js-menu--toggle'>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</button>
</div>
I have made a slider/seeker out of mousedown and mousemove for my <audio> element. My problem is that as soon as the user leaves the element while still holding their mouse button down, it does not register the mousemove. Here's my code:
/** Variables **/
isPlaying = false;
isBuffering = false;
isScrubbing = false;
isScrubberHolding = false;
tempProgress = 0;
time = playerE.currentTime;
dur = playerE.duration;
/** Binds and Properties **/
player.bind("timeupdate", timeUpdate);
scrubber.bind("mousemove", scrubberGrab);
scrubber.bind("mousedown", scrubberClick);
/** Progress and Buffer **/
function progressWidth(progress) {
var calcProgress = ((progress * 100) + "%");
$(".progress").width(calcProgress);
}
/** Time events **/
function timeUpdate(e) {
/** Update Variables **/
time = playerE.currentTime;
dur = playerE.duration;
/** Update Progress and Buffer **/
if (isScrubbing === false) {
var progress = time / dur;
}
var buffered = playerE.buffered.end(0) / dur;
timeConvert(time);
progressWidth(progress);
}
function setPlayerTime(timeset) {
playerE.currentTime = timeset * dur;
}
function timeConvert(s) {
var h = Math.floor(s / 3600);
s -= h * 3600;
var m = Math.floor(s / 60);
s -= m * 60;
var resultSubstring = ((m < 10 ? '0' + m : m) + ":" + (s < 10 ? '0' + s : s)).substring(0, 5);
$('#playerTime').text(resultSubstring);
}
/** Scrubber **/
$(".player-small").mouseenter(function () {
knob.stop().fadeIn(200);
});
setTimeout(function () {
$(".player-small").mouseleave(function () {
knob.stop().fadeOut(200);
});
}, 3000);
function scrubberClick(e) {
isScrubberHolding = true;
isScrubbing = true;
player.trigger('pause');
var $this = $(this);
var x = e.pageX - $this.offset().left;
var percent = x / $this.width();
progressWidth(percent);
tempProgress = percent;
}
$(document).mouseup(function () {
if (isScrubberHolding === true) {
isScrubberHolding = false;
isScrubbing = false;
setPlayerTime(tempProgress)
player.trigger('play');
} else {
isScrubberHolding = false;
}
})
function scrubberGrab(e) {
if (isScrubberHolding === true) {
var $this = $(this);
var x = e.pageX - $this.offset().left;
var percent = x / $this.width();
tempProgress = percent;
progressWidth(percent);
setPlayerTime(percent)
} else {}
}
See it in action:
var player = $('audio');
var playerE = $('audio')[0];
var playerE = $('audio').get(0);
var canvasviz = $('canvas');
var playbutton = $("#playButton");
var buffering = $("#buffering");
var scrubber = $(".scrubber-con");
var progress = $(".progress");
var buffered = $(".buffered");
var knob = $(".knob");
var analyser = $("#analyzer");
var currentAlbum = "";
var countElement = $('#playlistCount');
var titleElement = $('#trackTitle');
/** Variables **/
isPlaying = false;
isBuffering = false;
isScrubbing = false;
isScrubberHolding = false;
tempProgress = 0;
time = playerE.currentTime;
dur = playerE.duration;
/** Binds and Properties **/
player.bind("timeupdate", timeUpdate);
scrubber.bind("mousemove", scrubberGrab);
scrubber.bind("mousedown", scrubberClick);
/** Progress and Buffer **/
function progressWidth(progress) {
var calcProgress = ((progress * 100) + "%");
$(".progress").width(calcProgress);
}
/** Time events **/
function timeUpdate(e) {
/** Update Variables **/
time = playerE.currentTime;
dur = playerE.duration;
/** Update Progress and Buffer **/
if (isScrubbing === false) {
var progress = time / dur;
}
var buffered = playerE.buffered.end(0) / dur;
timeConvert(time);
progressWidth(progress);
}
function setPlayerTime(timeset) {
playerE.currentTime = timeset * dur;
}
function timeConvert(s) {
var h = Math.floor(s / 3600);
s -= h * 3600;
var m = Math.floor(s / 60);
s -= m * 60;
var resultSubstring = ((m < 10 ? '0' + m : m) + ":" + (s < 10 ? '0' + s : s)).substring(0, 5);
$('#playerTime').text(resultSubstring);
}
/** Scrubber **/
$(".player-small").mouseenter(function () {
knob.stop().fadeIn(200);
});
setTimeout(function () {
$(".player-small").mouseleave(function () {
knob.stop().fadeOut(200);
});
}, 3000);
function scrubberClick(e) {
isScrubberHolding = true;
isScrubbing = true;
player.trigger('pause');
var $this = $(this);
var x = e.pageX - $this.offset().left;
var percent = x / $this.width();
progressWidth(percent);
tempProgress = percent;
}
$(document).mouseup(function () {
if (isScrubberHolding === true) {
isScrubberHolding = false;
isScrubbing = false;
setPlayerTime(tempProgress)
player.trigger('play');
} else {
isScrubberHolding = false;
}
})
function scrubberGrab(e) {
if (isScrubberHolding === true) {
var $this = $(this);
var x = e.pageX - $this.offset().left;
var percent = x / $this.width();
tempProgress = percent;
progressWidth(percent);
setPlayerTime(percent)
} else {}
}
.player-small {
height: 55px;
width: 100%;
background: #ff4081;
}
.player-height-anim {}
.player-small .left {
height: 55px;
float: left;
width: 56%;
overflow: hidden;
}
.player-small .right {
height: 40px;
position: relative;
top: 8px;
float: right;
width: calc(44% - 2px);
overflow: hidden;
border-left: solid 2px rgba(0, 0, 0, .05);
}
.transport {
overflow: auto;
}
.play-button-con {
height: 55px;
width: 55px;
float: left;
overflow: hidden;
}
#buffering {
height: 55px;
width: 55px;
animation: rotating 900ms ease infinite;
background-image: url(img/player-buffering.svg);
background-size: contain;
display: none;
}
#-webkit-keyframes rotating {
from {
-ms-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-ms-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-webkit-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
#keyframes rotating {
from {
-ms-transform: rotate(0deg);
-moz-transform: rotate(0deg);
-webkit-transform: rotate(0deg);
-o-transform: rotate(0deg);
transform: rotate(0deg);
}
to {
-ms-transform: rotate(360deg);
-moz-transform: rotate(360deg);
-webkit-transform: rotate(360deg);
-o-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.rotating {
-webkit-animation: rotating 2s linear infinite;
-moz-animation: rotating 2s linear infinite;
-ms-animation: rotating 2s linear infinite;
-o-animation: rotating 2s linear infinite;
animation: rotating 2s linear infinite;
}
#playButton {
width: 55px;
height: 55px;
font-size: 18px;
text-align: center;
background-image: url(img/player-play.svg);
background-size: contain;
image-rendering: crisp-edges;
-webkit-image-rendering: crisp-edges;
}
.playFailed {
pointer-events: none;
}
.next-button-con {
height: 55px;
width: 55px;
float: left;
}
#nextButton {
width: 55px;
height: 55px;
text-align: center;
font-size: 11px;
background-image: url(img/player-next.svg);
background-size: contain;
}
.scrubber-con {
margin: auto;
margin-top: 12px;
height: 30px;
width: calc(100% - 40px);
overflow: visible;
cursor: pointer;
}
.scrubber-container {
float: left;
height: 55px;
width: calc(100% - 154px);
overflow: hidden;
}
.scrubber {
margin: auto;
height: 5px;
background: rgba(0, 0, 0, .04);
position: relative;
top: 13px;
}
.scrubber .knob {
float: right;
height: 13px;
width: 13px;
position: relative;
bottom: 4px;
left: 5px;
background: white;
border-radius: 50px;
display: none;
}
.scrubber .knob:hover {
cursor: grab;
}
.scrubber .knob:active {
cursor: grabbing;
}
.scrubber .progress {
height: 100%;
float: left;
background: white;
width: 0%;
position: relative;
z-index: 1;
}
.scrubber .buffered {
height: 5px;
position: relative;
width: 0%;
background: rgba(0, 0, 0, .2);
transition: ease 1000ms;
}
.time-con {
float: left;
width: 30px;
height: 55px;
}
.time {
position: relative;
top: 20px;
color: white;
font-size: 13px;
}
.player-small .button {
color: white;
float: left;
cursor: pointer;
}
.player-small .button:hover {
background: rgba(0, 0, 0, .12);
}
.analyzer-con {
float: left;
position: relative;
margin-left: 235px;
width: calc(100% - 650px);
height: 60px;
}
#analyzer {
width: 100%;
height: 45px;
margin-top: 8px;
display: none;
}
audio {
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="player-small">
<div class="w-ctrl">
<div class="controls">
<div class="left">
<div class="transport">
<div class="play-button-con">
<div class="button playFailed" id="playButton" onclick="togglePlay()">
</div>
<div id="buffering">
</div>
</div>
<div class="next-button-con">
<div class="button" id="nextButton" onclick="next()"></div>
</div>
<div class="scrubber-container" nmousedown="event.preventDefault ? event.preventDefault() : event.returnValue = false">
<div class="scrubber-con" nmousedown="event.preventDefault ? event.preventDefault() : event.returnValue = false">
<div class="scrubber" draggable="false" nmousedown="event.preventDefault ? event.preventDefault() : event.returnValue = false">
<div class="progress" draggable="false" onmousedown="event.preventDefault ? event.preventDefault() : event.returnValue = false">
<div class="knob" draggable="false" onmousedown="event.preventDefault ? event.preventDefault() : event.returnValue = false"></div>
</div>
<div class="buffered"></div>
</div>
</div>
</div>
<div class="time-con">
<div class="time" id="playerTime">0:00</div>
</div>
</div>
</div>
<div class="right">
<audio id="player" src="your track here" controls="controls" preload="none"></audio>
<div class="info">
<div class="count" id="playlistCount">0/0</div>
<div class="title" id="trackTitle">Track title</div>
</div>
</div>
</div>
</div>
</div>
Grab my custom seeker (left) and move your mouse off the pink area. Now do the same for the audio element (right) you need a track for it to play in order to be able to move its seeker. See how you can drag it even if your mouse is not inside it?
So how can I get this behaviour for my custom seeker?
Since you are binding the mousemove to scrubber, scrubberGrab() will only run when the mouse is over the scrubber element.
Change
scrubber.bind("mousemove", scrubberGrab);
To
$(document).bind("mousemove", scrubberGrab);
function scrubberGrab(e) {
if (isScrubberHolding === true) {
var x = e.pageX - scrubber.offset().left;
var percent = Math.min(Math.max(x / scrubber.width(), 0), 1.0);
tempProgress = percent;
progressWidth(percent);
setPlayerTime(percent);
} else {}
}