Elementor Countdown: FlipClock
Today, we’re making a FlipClock countdown timer. The countdown timer flips digits with a smooth, 3D animation, creating a dynamic and engaging effect.
Its sleek, dark green design and subtle shadows grab attention, building anticipation and leaving a lasting impression on visitors.
As usual, we will use Elementor free version. No Elementor pro. No extra plugins. Just clean HTML with CSS and JavaScript. No worries about bloating your site due to heavy loads.

It is also fully responsive. So feel free to use it on your landing page.
Perfect for the hero section to highlight limited-time offers or event deadlines. Use it on product pages to drive urgency for sales or in pop-ups to boost conversions.
Here are the steps to integrate it into your Elementor website:
Create three HTML blocks.
Paste the separate HTML, CSS, and JavaScript codes into them.
HTML
<!-- WPUtopia Countdown Timer Component -->
<div id="wputopia-countdown-container">
<div class="wputopia-container">
<div class="wputopia-countdown"></div>
</div>
</div>
CSS
<!-- Embedded CSS -->
<style>
/* WPUtopia Countdown Timer CSS */
#wputopia-countdown-container {
font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-webkit-user-select: none;
user-select: none;
color: #888;
text-shadow: 0 1px 0 rgba(0, 0, 0, .3);
width: 100%;
padding:10px;
box-sizing: border-box;
background: -moz-radial-gradient(center, ellipse cover, rgba(150, 150, 150, 1) 0%, rgba(89, 89, 89, 1) 100%);
background: -webkit-gradient(radial, center center, 0px, center center, 100%, color-stop(0%, rgba(150, 150, 150, 1)), color-stop(100%, rgba(89, 89, 89, 1)));
background: -webkit-radial-gradient(center, ellipse cover, rgba(150, 150, 150, 1) 0%, rgba(89, 89, 89, 1) 100%);
background: -o-radial-gradient(center, ellipse cover, rgba(150, 150, 150, 1) 0%, rgba(89, 89, 89, 1) 100%);
background: -ms-radial-gradient(center, ellipse cover, rgba(150, 150, 150, 1) 0%, rgba(89, 89, 89, 1) 100%);
background: radial-gradient(ellipse at center, rgba(150, 150, 150, 1) 0%, rgba(89, 89, 89, 1) 100%);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#969696', endColorstr = '#595959', GradientType = 1);
}
.wputopia-container {
text-align: center;
position: relative;
width: 100%;
margin: 20px auto;
box-sizing: border-box;
padding: 0 10px;
}
.wputopia-countdown {
height: 90px;
width: 100%;
display: block;
text-align: center;
max-width: 800px;
margin: 0 auto;
white-space: nowrap;
font-size: 0;
}
/* Reset */
.wputopia-countdown * {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.wputopia-countdown .wputopia-countdownFix {
z-index: 3 !important;
}
.wputopia-countdown .wputopia-clockFix {
z-index: 1 !important;
}
.wputopia-countdown li span .wputopia-inn {
/*backface-visibility*/
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-ms-backface-visibility: hidden;
-o-backface-visibility: hidden;
backface-visibility: hidden;
}
.wputopia-countdown ul {
list-style: none;
display: inline-block;
vertical-align: top;
}
.wputopia-countdown li {
line-height: 87px;
}
/* Skeleton */
.wputopia-countdown ul.wputopia-flip {
position: relative;
float: none;
display: inline-block;
vertical-align: top;
margin-right: 0.5%;
height: 100%;
width: 8%;
font-size: calc(8px + 1.5vw);
font-weight: bold;
/*border-radius*/
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
-ms-border-radius: 6px;
border-radius: 6px;
/*box-shadow*/
-webkit-box-shadow: 0 2px 5px rgba(0, 0, 0, .7);
-moz-box-shadow: 0 2px 5px rgba(0, 0, 0, .7);
-ms-box-shadow: 0 2px 5px rgba(0, 0, 0, .7);
box-shadow: 0 2px 5px rgba(0, 0, 0, .7);
}
/* Responsive styles */
@media only screen and (max-width: 800px) {
.wputopia-countdown {
height: 80px;
}
.wputopia-countdown ul.wputopia-flip {
width: 8%;
font-size: calc(7px + 1.5vw);
}
.wputopia-countdown ul.wputopia-flip:nth-child(2n+2):not(:last-child):after,
.wputopia-countdown ul.wputopia-nth-child-2np2-notlast:after {
font-size: calc(7px + 1vw);
}
}
@media only screen and (max-width: 600px) {
.wputopia-countdown {
height: 60px;
}
.wputopia-countdown ul.wputopia-flip {
width: 8%;
font-size: calc(6px + 1.5vw);
}
.wputopia-countdown ul.wputopia-flip li {
line-height: 60px !important;
}
.wputopia-countdown ul.wputopia-flip:nth-child(2n+2):not(:last-child):after,
.wputopia-countdown ul.wputopia-nth-child-2np2-notlast:after {
font-size: calc(6px + 1vw);
}
}
@media only screen and (max-width: 450px) {
.wputopia-countdown {
height: 50px;
}
.wputopia-countdown ul.wputopia-flip {
width: 8%;
font-size: calc(5px + 1.5vw);
}
.wputopia-countdown ul.wputopia-flip li {
line-height: 50px !important;
}
.wputopia-countdown ul.wputopia-flip:nth-child(2n+2):not(:last-child):after,
.wputopia-countdown ul.wputopia-nth-child-2np2-notlast:after {
font-size: calc(5px + 1vw);
}
}
@media only screen and (max-width: 350px) {
.wputopia-countdown {
height: 40px;
}
.wputopia-countdown ul.wputopia-flip {
width: 8%;
font-size: calc(4px + 1.5vw);
}
.wputopia-countdown ul.wputopia-flip li {
line-height: 40px !important;
}
.wputopia-countdown ul.wputopia-flip:nth-child(2n+2):not(:last-child):after,
.wputopia-countdown ul.wputopia-nth-child-2np2-notlast:after {
font-size: calc(4px + 1vw);
}
}
/* Colon Separator */
.wputopia-countdown ul.wputopia-flip:nth-child(2n+2):not(:last-child):after {
position: absolute;
top: 50%;
transform: translateY(-50%);
right: -8px;
content: ":";
display: block;
color: #fff;
font-size: calc(8px + 1vw); /* Use calc for responsive font size */
text-shadow: 1px 1px 3px rgba(0, 0, 0, .6);
}
/* Colon Separator - IE */
.wputopia-countdown ul.wputopia-nth-child-2np2-notlast {
margin-right: 10px;
}
.wputopia-countdown ul.wputopia-nth-child-2np2-notlast:after {
position: absolute;
top: 50%;
transform: translateY(-50%);
right: -8px;
content: ":";
display: block;
color: #fff;
font-size: calc(8px + 1vw); /* Use calc for responsive font size */
text-shadow: 1px 1px 3px rgba(0, 0, 0, .6);
}
.wputopia-countdown ul.wputopia-flip:nth-child(2n+2) {
margin-right: 10px;
}
.wputopia-countdown ul.wputopia-flip li {
z-index: 1;
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
}
.wputopia-countdown ul.wputopia-flip li span {
display: block;
height: 100%;
/*perspective*/
-webkit-perspective: 200px;
-moz-perspective: 200px;
-ms-perspective: 200px;
-o-perspective: 200px;
perspective: 200px;
}
.wputopia-countdown ul.wputopia-flip li span div {
z-index: 1;
position: absolute;
left: 0;
width: 100%;
height: 50%;
overflow: hidden;
}
.wputopia-countdown ul.wputopia-flip li span div .wputopia-shadow {
position: absolute;
width: 100%;
height: 100%;
z-index: 2;
}
.wputopia-countdown ul.wputopia-flip li span div.wputopia-up {
/*transform-origin*/
-webkit-transform-origin: 50% 100%;
-moz-transform-origin: 50% 100%;
-ms-transform-origin: 50% 100%;
-o-transform-origin: 50% 100%;
transform-origin: 50% 100%;
top: 0;
}
.wputopia-countdown ul.wputopia-flip li span div.wputopia-up:after {
content: "";
position: absolute;
bottom: 0px;
left: 0;
z-index: 5;
width: 100%;
height: 1px;
background-color: rgba(0,0,0,.4);
}
.wputopia-countdown ul.wputopia-flip li span div.wputopia-down {
/*transform-origin*/
-webkit-transform-origin: 50% 0%;
-moz-transform-origin: 50% 0%;
-ms-transform-origin: 50% 0%;
-o-transform-origin: 50% 0%;
transform-origin: 50% 0%;
bottom: 0;
}
.wputopia-countdown ul.wputopia-flip li span div div.wputopia-inn {
position: absolute;
left: 0;
z-index: 1;
width: 100%;
height: 200%;
color: #ccc;
text-shadow: 0 1px 2px #000;
text-align: center;
background-color: #127C02;
/*border-radius*/
-webkit-border-radius: 6px;
-moz-border-radius: 6px;
-ms-border-radius: 6px;
border-radius: 6px;
}
.wputopia-countdown ul.wputopia-flip li span div.wputopia-up div.wputopia-inn {
top: 0;
}
.wputopia-countdown ul.wputopia-flip li span div.wputopia-down div.wputopia-inn {
bottom: 0;
}
/* PLAY */
.wputopia-play ul li.wputopia-previous {
z-index: 2;
}
.wputopia-play ul li.wputopia-current {
/*animation*/
-webkit-animation: wputopia-asd .5s .5s linear both;
-moz-animation: wputopia-asd .5s .5s linear both;
-ms-animation: wputopia-asd .5s .5s linear both;
-o-animation: wputopia-asd .5s .5s linear both;
animation: wputopia-asd .5s .5s linear both;
z-index: 3;
}
@-webkit-keyframes wputopia-asd {
0% { z-index: 2; }
5% { z-index: 4; }
100% { z-index: 4; }
}
@-moz-keyframes wputopia-asd {
0% { z-index: 2; }
5% { z-index: 4; }
100% { z-index: 4; }
}
@-ms-keyframes wputopia-asd {
0% { z-index: 2; }
5% { z-index: 4; }
100% { z-index: 4; }
}
@-o-keyframes wputopia-asd {
0% { z-index: 2; }
5% { z-index: 4; }
100% { z-index: 4; }
}
@keyframes wputopia-asd {
0% { z-index: 2; }
5% { z-index: 4; }
100% { z-index: 4; }
}
.wputopia-play ul li.wputopia-current .wputopia-down {
z-index: 2;
/*animation*/
-webkit-animation: wputopia-turn .5s .5s linear both;
-moz-animation: wputopia-turn .5s .5s linear both;
-ms-animation: wputopia-turn .5s .5s linear both;
-o-animation: wputopia-turn .5s .5s linear both;
animation: wputopia-turn .5s .5s linear both;
}
@-webkit-keyframes wputopia-turn {
0% { -webkit-transform: rotateX(90deg); }
100% { -webkit-transform: rotateX(0deg); }
}
@-moz-keyframes wputopia-turn {
0% { -moz-transform: rotateX(90deg); }
100% { -moz-transform: rotateX(0deg); }
}
@-ms-keyframes wputopia-turn {
0% { -ms-transform: rotateX(90deg); }
100% { -ms-transform: rotateX(0deg); }
}
@-o-keyframes wputopia-turn {
0% { -o-transform: rotateX(90deg); }
100% { -o-transform: rotateX(0deg); }
}
@keyframes wputopia-turn {
0% { transform: rotateX(90deg); }
100% { transform: rotateX(0deg); }
}
.wputopia-play ul li.wputopia-previous .wputopia-up {
z-index: 2;
/*animation*/
-webkit-animation: wputopia-turn2 .5s linear both;
-moz-animation: wputopia-turn2 .5s linear both;
-ms-animation: wputopia-turn2 .5s linear both;
-o-animation: wputopia-turn2 .5s linear both;
animation: wputopia-turn2 .5s linear both;
}
@-webkit-keyframes wputopia-turn2 {
0% { -webkit-transform: rotateX(0deg); }
100% { -webkit-transform: rotateX(-90deg); }
}
@-moz-keyframes wputopia-turn2 {
0% { -moz-transform: rotateX(0deg); }
100% { -moz-transform: rotateX(-90deg); }
}
@-ms-keyframes wputopia-turn2 {
0% { -ms-transform: rotateX(0deg); }
100% { -ms-transform: rotateX(-90deg); }
}
@-o-keyframes wputopia-turn2 {
0% { -o-transform: rotateX(0deg); }
100% { -o-transform: rotateX(-90deg); }
}
@keyframes wputopia-turn2 {
0% { transform: rotateX(0deg); }
100% { transform: rotateX(-90deg); }
}
/* SHADOW */
.wputopia-play ul li.wputopia-previous .wputopia-up .wputopia-shadow {
/*linear-gradient*/
background: -webkit-gradient(linear, left top, left bottom, color-stop(rgba(0, 0, 0, .1), 0), color-stop(rgba(0, 0, 0, 1), 1));
background: -webkit-linear-gradient(top, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 1) 100%);
background: -moz-linear-gradient(top, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 1) 100%);
background: -o-linear-gradient(top, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 1) 100%);
background: linear-gradient(top, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 1) 100%);
background: -webkit-linear-gradient(to bottom, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 1) 100%);
background: -moz-linear-gradient(to bottom, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 1) 100%);
background: -o-linear-gradient(to bottom, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 1) 100%);
background: linear-gradient(to bottom, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 1) 100%);
/*animation*/
-webkit-animation: wputopia-show .5s linear both;
-moz-animation: wputopia-show .5s linear both;
-ms-animation: wputopia-show .5s linear both;
-o-animation: wputopia-show .5s linear both;
animation: wputopia-show .5s linear both;
}
.wputopia-play ul li.wputopia-current .wputopia-up .wputopia-shadow {
/*linear-gradient*/
background: -webkit-gradient(linear, left top, left bottom, color-stop(rgba(0, 0, 0, .1), 0), color-stop(rgba(0, 0, 0, 1), 1));
background: -webkit-linear-gradient(top, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 1) 100%);
background: -moz-linear-gradient(top, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 1) 100%);
background: -o-linear-gradient(top, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 1) 100%);
background: linear-gradient(top, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 1) 100%);
background: -webkit-linear-gradient(to bottom, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 1) 100%);
background: -moz-linear-gradient(to bottom, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 1) 100%);
background: -o-linear-gradient(to bottom, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 1) 100%);
background: linear-gradient(to bottom, rgba(0, 0, 0, .1) 0%, rgba(0, 0, 0, 1) 100%);
/*animation*/
-webkit-animation: wputopia-hide .5s .3s linear both;
-moz-animation: wputopia-hide .5s .3s linear both;
-ms-animation: wputopia-hide .5s .3s linear both;
-o-animation: wputopia-hide .5s .3s linear both;
animation: wputopia-hide .5s .3s linear both;
}
/*DOWN*/
.wputopia-play ul li.wputopia-previous .wputopia-down .wputopia-shadow {
/*linear-gradient*/
background: -webkit-gradient(linear, left top, left bottom, color-stop(rgba(0, 0, 0, 1), 0), color-stop(rgba(0, 0, 0, .1), 1));
background: -webkit-linear-gradient(top, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, .1) 100%);
background: -moz-linear-gradient(top, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, .1) 100%);
background: -o-linear-gradient(top, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, .1) 100%);
background: linear-gradient(top, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, .1) 100%);
background: -webkit-linear-gradient(to bottom, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, .1) 100%);
background: -moz-linear-gradient(to bottom, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, .1) 100%);
background: -o-linear-gradient(to bottom, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, .1) 100%);
background: linear-gradient(to bottom, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, .1) 100%);
/*animation*/
-webkit-animation: wputopia-show .5s linear both;
-moz-animation: wputopia-show .5s linear both;
-ms-animation: wputopia-show .5s linear both;
-o-animation: wputopia-show .5s linear both;
animation: wputopia-show .5s linear both;
}
.wputopia-play ul li.wputopia-current .wputopia-down .wputopia-shadow {
/*linear-gradient*/
background: -webkit-gradient(linear, left top, left bottom, color-stop(rgba(0, 0, 0, 1), 0), color-stop(rgba(0, 0, 0, .1), 1));
background: -webkit-linear-gradient(top, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, .1) 100%);
background: -moz-linear-gradient(top, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, .1) 100%);
background: -o-linear-gradient(top, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, .1) 100%);
background: linear-gradient(top, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, .1) 100%);
background: -webkit-linear-gradient(to bottom, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, .1) 100%);
background: -moz-linear-gradient(to bottom, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, .1) 100%);
background: -o-linear-gradient(to bottom, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, .1) 100%);
background: linear-gradient(to bottom, rgba(0, 0, 0, 1) 0%, rgba(0, 0, 0, .1) 100%);
/*animation*/
-webkit-animation: wputopia-hide .5s .3s linear both;
-moz-animation: wputopia-hide .5s .3s linear both;
-ms-animation: wputopia-hide .5s .3s linear both;
-o-animation: wputopia-hide .5s .3s linear both;
animation: wputopia-hide .5s .3s linear both;
}
@-webkit-keyframes wputopia-show {
0% { opacity: 0; }
100% { opacity: 1; }
}
@-moz-keyframes wputopia-show {
0% { opacity: 0; }
100% { opacity: 1; }
}
@-ms-keyframes wputopia-show {
0% { opacity: 0; }
100% { opacity: 1; }
}
@-o-keyframes wputopia-show {
0% { opacity: 0; }
100% { opacity: 1; }
}
@keyframes wputopia-show {
0% { opacity: 0; }
100% { opacity: 1; }
}
@-webkit-keyframes wputopia-hide {
0% { opacity: 1; }
100% { opacity: 0; }
}
@-moz-keyframes wputopia-hide {
0% { opacity: 1; }
100% { opacity: 0; }
}
@-ms-keyframes wputopia-hide {
0% { opacity: 1; }
100% { opacity: 0; }
}
@-o-keyframes wputopia-hide {
0% { opacity: 1; }
100% { opacity: 0; }
}
@keyframes wputopia-hide {
0% { opacity: 1; }
100% { opacity: 0; }
}
</style>
JS
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://unpkg.com/wordpress-dev-necessary/dist/necessary.min.js"></script>
<!-- Embedded JavaScript -->
<script>
//<![CDATA[
(function($) {
// Initialize when document is ready
$(document).ready(function() {
var wputopiaFlip = new WPUtopiaFlipClock({
isCountdown: true,
startTime: '31:00:00:05',
containerElement: $('.wputopia-countdown'),
face: {
days: {
maxValue: 31
},
hours: {
maxValue: 23
},
minutes: {
maxValue: 59
},
seconds: {
maxValue: 59
}
}
});
// Add window resize handler to make the clock responsive
$(window).on('resize', function() {
wputopiaFlip.setDimensions();
});
// Initial call to setDimensions after a short delay to ensure everything is rendered
setTimeout(function() {
wputopiaFlip.setDimensions();
}, 100);
});
/**
* WPUtopiaFlipClock
* @param options
* @constructor
*/
WPUtopiaFlipClock = function (options) {
this.tickInterval = false;
this.digitSelectors = [];
this.options = this.createConfig(options);
this.init();
};
/**
* returns merged config based on passed config + default config
* @param options - config object
* @returns options merged config objects
*/
WPUtopiaFlipClock.prototype.createConfig = function(options) {
return $.extend({}, this.getDefaultConfig(), options);
};
/**
* returns default config object
*/
WPUtopiaFlipClock.prototype.getDefaultConfig = function() {
return {
tickDuration: 1000,
isCountdown: false,
startTime: '23:59:51',
maxTime: '23:59:59',
minTime: '00:00:00',
containerElement: $('.wputopia-container'),
segmentSelectorPrefix: 'wputopia-flipclock-',
face: {
hours: {
maxValue: 23
},
minutes: {
maxValue: 59
},
seconds: {
maxValue: 59
}
}
};
};
/**
* check browser feature support
*/
WPUtopiaFlipClock.prototype.initFeatureDetection = function() {
$.support.transition = (function(){
var thisBody = document.body || document.documentElement,
thisStyle = thisBody.style,
support = thisStyle.transition !== undefined;
if (!support) {
support = thisStyle.WebkitTransition !== undefined;
}
if (!support) {
support = thisStyle.MozTransition !== undefined;
}
if (!support) {
support = thisStyle.MsTransition !== undefined;
}
if (!support) {
support = thisStyle.OTransition !== undefined;
}
return support;
})();
};
/**
* return browser support for given feature
* @param feature
* @returns {*}
*/
WPUtopiaFlipClock.prototype.isFeatureSupported = function(feature) {
if(feature) {
if(typeof $.support !== undefined) {
if(typeof $.support[feature] !== undefined) {
return $.support[feature];
}
}
}
return false;
};
/**
* init
*/
WPUtopiaFlipClock.prototype.init = function() {
this.options.containerElement.empty();
if (this.tickInterval !== false) {
clearInterval(this.tickInterval);
this.tickInterval = false;
}
this.appendMarkupToContainer();
// Initial dimensions will be set after appending markup
this.setupFallbacks();
this.start();
};
/**
* setupFallbacks
*/
WPUtopiaFlipClock.prototype.setupFallbacks = function() {
this.initFeatureDetection();
if (this.isFeatureSupported('transition')) {
$('ul.wputopia-flip li:first-child', this.options.containerElement).css("z-index", 2);
} else {
// < IE9 can't do css animations (@keyframe) - need to fix z-index here since we're setting z-indices inside the keyframe-steps
$('ul.wputopia-flip li:first-child', this.options.containerElement).css("z-index", 3);
// < IE9 doesn't understand nth-child css selector => fallback class that has to be addressed via css separatly
$('ul.wputopia-flip:nth-child(2n+2):not(:last-child)', this.options.containerElement).addClass('wputopia-nth-child-2np2-notlast');
}
};
/**
* Sets digit dimensions based on its containers height
*/
WPUtopiaFlipClock.prototype.setDimensions = function() {
var containerHeight = this.options.containerElement.height();
// Only set the line-height to match container height
$('ul.wputopia-flip', this.options.containerElement).find('li').css({
lineHeight: containerHeight + 'px'
});
// Ensure all flip elements have the same height
$('ul.wputopia-flip', this.options.containerElement).css({
height: containerHeight + 'px',
display: 'inline-block',
float: 'none',
verticalAlign: 'top'
});
};
/**
* Creates segments out of 'digits', calculates ticks per digit based on segment maxValue
* @param faceSegmentGroupName
* @returns {Array}
*/
WPUtopiaFlipClock.prototype.createSegment = function(faceSegmentGroupName) {
var faceSegmentGroup = this.options.face[faceSegmentGroupName],
segmentSelectorAddons = ['-ten', '-one'],
rounded = Math.ceil(faceSegmentGroup.maxValue/10),
segment = [];
if (faceSegmentGroup.maxValue/10 > 1) {
segment = [
{
selector: this.options.segmentSelectorPrefix + faceSegmentGroupName + segmentSelectorAddons[0],
ticks: rounded
},{
selector: this.options.segmentSelectorPrefix + faceSegmentGroupName + segmentSelectorAddons[1],
ticks: 10
}
];
} else {
segment = [
{
selector: this.options.segmentSelectorPrefix + faceSegmentGroupName + segmentSelectorAddons[1],
ticks: 10
}
]
}
return segment;
};
/**
* Appends the markup for each digit to the container
*/
WPUtopiaFlipClock.prototype.appendMarkupToContainer = function() {
var baseZIndex = 0;
for (var faceSegmentGroup in this.options.face) {
this.options.face[faceSegmentGroup].segments = this.createSegment(faceSegmentGroup);
for (var i=0; i < this.options.face[faceSegmentGroup].segments.length; i++) {
var faceSegmentElement = this.createFaceSegment( this.options.face[faceSegmentGroup].segments[i] );
this.digitSelectors.push(this.options.face[faceSegmentGroup].segments[i].selector);
this.options.containerElement.append( faceSegmentElement );
// assign common data-attribute to segments of the same group
faceSegmentElement.data('face-segment-group', faceSegmentGroup);
faceSegmentElement.addClass(faceSegmentGroup);
faceSegmentElement.css("z-index", baseZIndex++);
}
}
this.digitSelectors.reverse();
};
/**
* Creates face segments
* @param faceSegment
* @returns {*|jQuery|HTMLElement}
*/
WPUtopiaFlipClock.prototype.createFaceSegment = function(faceSegment) {
var faceElement = $('<ul>', {
"class": "wputopia-flip " + faceSegment.selector
});
for (var i = 0; i < faceSegment.ticks; i++) {
var digit = i;
faceElement.append( this.createFaceDigit(digit) );
}
return faceElement;
};
/**
* Creates digit markup
* @param digit
* @returns {string}
*/
WPUtopiaFlipClock.prototype.createFaceDigit = function(digit) {
var digitInnerFragment = '<div class="wputopia-shadow"></div><div class="wputopia-inn">' + digit + '</div>';
return '<li data-digit=' + digit + ' ><span>' +
'<div class="wputopia-up">' + digitInnerFragment + '</div>' +
'<div class="wputopia-down">' + digitInnerFragment + '</div>' +
'</span></li>';
};
/**
* Starts the clock
*/
WPUtopiaFlipClock.prototype.start = function() {
this.setToTime(this.options.startTime);
var self = this;
this.tickInterval = setInterval(function () {
self.tick();
}, this.options.tickDuration);
};
/**
* Stops the Clock after the current interval is finished
*/
WPUtopiaFlipClock.prototype.stop = function() {
clearInterval(this.tickInterval);
};
/**
* Resets to 00:00:00....
* needed when using this as an actual clock - e.g. can reset to 0 after 23:59:59
*/
WPUtopiaFlipClock.prototype.resetDigits = function() {
this.options.containerElement.removeClass('wputopia-play');
for (var i=0; i<this.digitSelectors.length; i++) {
var active = $(this.getDigitSelectorByIndex(i) + ".wputopia-current", this.options.containerElement),
all = $(this.getDigitSelectorByIndex(i), this.options.containerElement),
first = $(this.getDigitSelectorByIndex(i) + ":first-child", this.options.containerElement);
all.eq(0).addClass("wputopia-clockFix");
all.removeClass("wputopia-current");
first.addClass("wputopia-current");
all.removeClass("wputopia-previous");
active.addClass("wputopia-previous");
}
this.options.containerElement.addClass('wputopia-play');
};
/**
* Sets the clock to a time based on passed string
* @param time {string} 00:00:00...
*/
WPUtopiaFlipClock.prototype.setToTime = function(time) {
var timeArray = time.replace(/:/g, '').split('').reverse();
for (var i=0; i<this.digitSelectors.length; i++) {
var digit = $(this.getDigitSelectorByIndex(i), this.options.containerElement).eq(parseInt(timeArray[i]));
this.options.containerElement.removeClass('wputopia-play');
digit.addClass("wputopia-current");
this.options.containerElement.addClass('wputopia-play');
}
};
/**
* Set Segment to its maximum value
* @param segmentGroupName
*/
WPUtopiaFlipClock.prototype.setFaceSegmentGroupMaxValue = function(segmentGroupName) {
var self = this;
var group = this.getFaceSegmentGroupDom(segmentGroupName);
group.each(function(idx) {
self.options.containerElement.removeClass('wputopia-play');
var maxValue = self.options.face[segmentGroupName].maxValue.toString().split('');
$(this).find('li.wputopia-current').removeClass('wputopia-current');
$(this).find('li[data-digit="'+maxValue[idx]+'"]').addClass('wputopia-current');
self.options.containerElement.addClass('wputopia-play');
});
};
/**
* actual callback for the tick/interval
*/
WPUtopiaFlipClock.prototype.tick = function() {
this.doTick(0);
};
/**
* Returns current time as int
* @returns {Number}
*/
WPUtopiaFlipClock.prototype.getCurrentTime = function() {
var currentTime = [];
$('li.wputopia-current', this.options.containerElement).each(function() {
currentTime.push($(this).data('digit'));
});
return parseInt(currentTime.join(''), 10);
};
/**
* gets digit selector string for the given index in the digitselectors array
* @param digitIndex
* @returns {string}
*/
WPUtopiaFlipClock.prototype.getDigitSelectorByIndex = function(digitIndex) {
return 'ul.' + this.digitSelectors[digitIndex] + ' li';
};
/**
* Return the segment group name for a passed digit element
* @param digitElement
* @returns {*}
*/
WPUtopiaFlipClock.prototype.getFaceSegmentGroupNameByDigitElement = function(digitElement) {
return digitElement.parent().data('face-segment-group');
};
/**
* Return the segment group object for a passed digit element
* @param digitElement
* @returns {*}
*/
WPUtopiaFlipClock.prototype.getFaceSegmentByDigitElement = function(digitElement) {
return this.options.face[this.getFaceSegmentGroupNameByDigitElement(digitElement)];
};
/**
* Return segment group dom objects by segment group name
* @param segmentGroupName
* @returns {*|jQuery|HTMLElement}
*/
WPUtopiaFlipClock.prototype.getFaceSegmentGroupDom = function(segmentGroupName) {
return $('.' + segmentGroupName, this.options.containerElement)
};
/**
* Return dom object for the currently active digit for a segment group name
* @param segmentGroupName
* @returns {*|jQuery|HTMLElement}
*/
WPUtopiaFlipClock.prototype.getCurrentDigitDom = function(segmentGroupName) {
return $('.' + segmentGroupName + ' li.wputopia-current', this.options.containerElement)
};
/**
* Returns the value a segment group is currently representing selected by digit element
* @param digitElement
* @returns {string}
*/
WPUtopiaFlipClock.prototype.getCurrentFaceSegmentGroupValue = function(digitElement) {
var segmentGroupName = this.getFaceSegmentGroupNameByDigitElement(digitElement),
values = [];
this.getCurrentDigitDom(segmentGroupName).each(function(idx) {
values[idx] = $(this).data('digit');
});
return values.join('');
};
/**
* handles the tick logic
* @param digitIndex
*/
WPUtopiaFlipClock.prototype.doTick = function(digitIndex) {
var nextDigit, pseudoSelector;
// check if we reached maxTime and start over at 00:00:00
if (this.options.isCountdown === false) {
if (this.isMaxTimeReached()) {
this.resetDigits();
return;
}
}
this.options.containerElement.removeClass('wputopia-play');
if (this.options.isCountdown === true) {
pseudoSelector = ":first-child";
} else {
pseudoSelector = ":last-child";
}
var activeDigit = $(this.getDigitSelectorByIndex(digitIndex) + ".wputopia-current", this.options.containerElement);
if (activeDigit.html() == undefined) {
if (this.options.isCountdown) {
activeDigit = $(this.getDigitSelectorByIndex(digitIndex) + ":last-child", this.options.containerElement);
nextDigit = activeDigit.prev("li");
} else {
activeDigit = $(this.getDigitSelectorByIndex(digitIndex), this.options.containerElement).eq(0);
nextDigit = activeDigit.next("li");
}
activeDigit.addClass("wputopia-previous").removeClass("wputopia-current");
nextDigit.addClass("wputopia-current");
} else if (activeDigit.is(pseudoSelector)) {
$(this.getDigitSelectorByIndex(digitIndex), this.options.containerElement).removeClass("wputopia-previous");
// countdown target reached, halt
if (this.options.isCountdown === true) {
if (this.isMinTimeReached()) {
this.stop();
return;
}
}
activeDigit.addClass("wputopia-previous").removeClass("wputopia-current");
if (this.options.isCountdown === true) {
activeDigit.addClass("wputopia-countdownFix");
activeDigit = $(this.getDigitSelectorByIndex(digitIndex) + ":last-child", this.options.containerElement);
} else {
activeDigit = $(this.getDigitSelectorByIndex(digitIndex), this.options.containerElement).eq(0);
activeDigit.addClass("wputopia-clockFix");
}
activeDigit.addClass("wputopia-current");
// animate the next segment once (if there is one)
if (typeof this.digitSelectors[digitIndex + 1] !== "undefined") {
this.doTick(digitIndex + 1);
}
} else {
$(this.getDigitSelectorByIndex(digitIndex), this.options.containerElement).removeClass("wputopia-previous");
activeDigit.addClass("wputopia-previous").removeClass("wputopia-current");
if (this.options.isCountdown === true) {
nextDigit = activeDigit.prev("li");
} else {
nextDigit = activeDigit.next("li");
}
nextDigit.addClass("wputopia-current");
}
// set segment to maxValue if it would move past it
var group = this.getFaceSegmentByDigitElement(activeDigit);
if (this.getCurrentFaceSegmentGroupValue(activeDigit) > group.maxValue) {
this.setFaceSegmentGroupMaxValue(this.getFaceSegmentGroupNameByDigitElement(activeDigit));
}
this.options.containerElement.addClass('wputopia-play');
this.cleanZIndexFix(activeDigit, this.digitSelectors[digitIndex]);
};
/**
* isMaxTimeReached
* @returns {boolean}
*/
WPUtopiaFlipClock.prototype.isMaxTimeReached = function() {
return this.getCurrentTime() >= parseInt(this.options.maxTime.replace(/:/g, ''), 10);
};
/**
* isMinTimeReached
* @returns {boolean}
*/
WPUtopiaFlipClock.prototype.isMinTimeReached = function() {
return this.getCurrentTime() <= parseInt(this.options.minTime.replace(/:/g, ''), 10);
};
/**
* Fixes flickering top half of digit
*
* @param activeDigit
* @param selector
*/
WPUtopiaFlipClock.prototype.cleanZIndexFix = function(activeDigit, selector) {
if (this.options.isCountdown === true) {
var fix = $('.' + selector + ' .wputopia-countdownFix', this.options.containerElement);
if (fix.length > 0) {
if (!fix.hasClass("wputopia-previous")) {
if (!fix.hasClass("wputopia-current")) {
fix.removeClass("wputopia-countdownFix");
}
}
}
} else {
activeDigit.siblings().removeClass("wputopia-clockFix");
}
};
})(jQuery);
//]]>
</script>
That’s it. Easy-peasy.
If you like it, don’t forget to like and comment.
Support My Work
If you enjoy my content, consider buying me a coffee or shopping through my Rakuten link to support me!