Pen Settings

HTML

CSS

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URLs added here will be added as <link>s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.

+ add another resource

JavaScript

Babel includes JSX processing.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Packages

Add Packages

Search for and use JavaScript packages from npm here. By selecting a package, an import statement will be added to the top of the JavaScript editor for this package.

Behavior

Auto Save

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

Format on Save

If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.

Editor Settings

Code Indentation

Want to change your Syntax Highlighting theme, Fonts and more?

Visit your global Editor Settings.

HTML

              
                #pomodoro.wrap
	header
		h1 Pomodoro Timer
		p A freeCodeCamp Project
	section.display
		#btn-session-minus
			span.fa.fa-minus
		#btn-session-plus
			span.fa.fa-plus
		.tomatoes
			#btn-session-action
				span.loading
				span.fa
			.timer
				h3#session {{ displaySession }}
				p#status {{ displayStatus }}
	section.setting-break
		h3 Break Length
		p
			span.fa.fa-minus
			span#break {{ displayBreak }}
			span.fa.fa-plus
	a#btn-reset
		span Reset
              
            
!

CSS

              
                // @import "bourbon"

// Fonts
@import 'https://fonts.googleapis.com/css?family=Open+Sans|Pacifico'
@import 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css'
$primary-font: 'Pacifico', cursive
$sans-serif: 'Open Sans', Helvetica, Vedana, sans-serif

// Color
$primary-color: #f44336
$accent-color: #64dd17

// Tomatoes SVG
$tomatoes: url("data:image/svg+xml;base64,PHN2ZyB4bWxuczpkYz0iaHR0cDovL3B1cmwub3JnL2RjL2VsZW1lbnRzLzEuMS8iIHhtbG5zOmNjPSJodHRwOi8vY3JlYXRpdmVjb21tb25zLm9yZy9ucyMiIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyIgeG1sbnM6c3ZnPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDUgNDUiIHN0eWxlPSJlbmFibGUtYmFja2dyb3VuZDpuZXcgMCAwIDQ1IDQ1OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgdmVyc2lvbj0iMS4xIiBpZD0ic3ZnMiI+PG1ldGFkYXRhIGlkPSJtZXRhZGF0YTgiPjxyZGY6UkRGPjxjYzpXb3JrIHJkZjphYm91dD0iIj48ZGM6Zm9ybWF0PmltYWdlL3N2Zyt4bWw8L2RjOmZvcm1hdD48ZGM6dHlwZSByZGY6cmVzb3VyY2U9Imh0dHA6Ly9wdXJsLm9yZy9kYy9kY21pdHlwZS9TdGlsbEltYWdlIi8+PC9jYzpXb3JrPjwvcmRmOlJERj48L21ldGFkYXRhPjxkZWZzIGlkPSJkZWZzNiI+PGNsaXBQYXRoIGlkPSJjbGlwUGF0aDE2IiBjbGlwUGF0aFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggaWQ9InBhdGgxOCIgZD0iTSAwLDM2IDM2LDM2IDM2LDAgMCwwIDAsMzYgWiIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIHRyYW5zZm9ybT0ibWF0cml4KDEuMjUsMCwwLC0xLjI1LDAsNDUpIiBpZD0iZzEwIj48ZyBpZD0iZzEyIj48ZyBjbGlwLXBhdGg9InVybCgjY2xpcFBhdGgxNikiIGlkPSJnMTQiPjxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDguNDM5LDM1LjkwODcpIiBpZD0iZzI0Ij48cGF0aCBpZD0icGF0aDI2IiBzdHlsZT0iZmlsbDojNzdiMjU1O2ZpbGwtb3BhY2l0eToxO2ZpbGwtcnVsZTpub256ZXJvO3N0cm9rZTpub25lIiBkPSJtIDAsMCBjIDEuNjM3LC0xLjYzNiAyLjc3LC0yLjI2NiAzLjI3NCwtNC45MSAwLjI5OCwtMS41NjQgMi4yNjYsLTEuNTEgMi4yNjYsLTEuNTEgMCwwIC0zLjkwMywtMS43NjQgLTUuNTQsLTMuNCAwLDAgNC45MSwxLjYzNiA2LjU0NywxLjYzNiAwLDAgMy4yNzMsLTEuNjM2IDMuMjczLC0zLjI3MyAwLDAgMCwzLjI3MyAtMS42MzYsMy4yNzMgMCwwIDQuOTA5LDAgNC45MDksLTMuMjczIDAsMCAwLDQuOTExIC0xLjYzNiw0LjkxMSAwLDAgNC45MTEsMS42MzYgNi41NDcsMCAwLDAgLTEuNjg1LDEuNzIgLTQuOTExLDEuNjM2IDAsMCAxLjYzOCwxLjYzNyA0LjkxMSwxLjYzNyAwLDAgLTUuMjg4LDEuNTExIC02LjkyNCwtMS43NjMgMCwwIC0xLjM4NiwxLjM4NSAxLjM4NCw0LjE1NSAwLDAgLTQuMjgsLTAuNzU1IC00LjI4LC00LjAyOSAwLDAgLTEuNTUyLDAuMDM5IC0yLjY0NCwxLjI1OSBDIDMuMzk5LC0xLjI1OSAwLDAgMCwwIi8+PC9nPjwvZz48L2c+PC9nPjwvc3ZnPg==")

*, *:before, *:after, h1, h2, h3, p
	margin: 0
	box-sizing: border-box
html, body
	width: 100%
	background-color: #eee
	font-family: $sans-serif
	color: #777


#pomodoro
	&.wrap
		width: 350px
		margin: 50px auto 100px
		padding: 20px
		text-align: center
		background-color: #fff
		border: 1px solid rgba(255,255,255,0.8)
		border-radius: 20px
		box-shadow: 0px 40px 25px -40px rgba(1,1,1, 0.3)
		perspective: 9999

	header
		margin-bottom: 50px
		h1
			font-family: $primary-font
			font-size: 2.5em
			line-height: 1
			color: $primary-color
		p
			font-size: 1.3em
			font-weight: 200
	.display
		width: 100%
		margin-bottom: 25px
		position: relative
		&:before
			display: block
			content: ""
			background: $tomatoes no-repeat left top
			background-size: cover
			width: 300px
			height: 100px
			position: absolute
			bottom: calc(100% - 100px)
			right: -20%
			transform: translate(-25%,-45%)
			z-index: 9999

		#btn-session-plus, #btn-session-minus
			position: absolute
			background-color: $accent-color
			width: 40px
			height: 40px
			font-size: 1.2em
			box-shadow: 0 5px 2.5px -2.5px rgba(1,1,1,0.3)
			top: 50%
			transform: translate(0,-50%)
			cursor: pointer
			border-radius: 100%
			transition: all 200ms ease-in-out
			&:active
				transform: translate(0,-25px) scale(1.1,1.1)
				box-shadow: 0 10px 2.5px -2.5px rgba(1,1,1,0.3)

		#btn-session-minus
			padding: 5px
			left: 0
		#btn-session-plus
			padding: 5px
			right: 0		

		.tomatoes
			position: relative
			width: 200px
			height: 200px
			margin: 0 auto 0
			background-color: $primary-color
			color: #fff
			border: 3px solid orangered
			border-radius: 100%
			box-shadow: 0 10px 5px -5px rgba(1,1,1,0.3)
			transition: all ease-in-out 300ms
			overflow: hidden

			&._isBreak
				transition: all ease-in-out 300ms
				background-color: $accent-color
				border-color: lighten($accent-color,0.2)
			
			&._isPaused
				transition: all ease-in-out 300ms
				background-color: #777
				border-color: #333

			#btn-session-action, .timer
				position: absolute
				top: 50%
				left: 50%
				transform: translate(-50%,-50%)
			#btn-session-action
				width: 100%
				height: 100%
				cursor: pointer
				z-index: 999
				& > span
					position: absolute 
					display: block
					width: 100%
					height: 100%
					background-color: transparent
				& > .fa
					opacity: 0
					width: 100%
					height: 100%
					line-height: 2
					text-align: center
					color: white
					font-size: 6em
				& > .loading
					background-color: $accent-color
					width: 100%
					height: 100%
					opacity: 0
					transition: all 300ms cubic-bezier(0,-0.66,0.97,1.76)
				&:hover > .fa
					opacity: 0.7
			.timer
				h3
					font-size: 2.5em
					font-weight: 700
				p
					font-size: 1.5em
	.setting-break
		margin: 10px 0 10px
		padding: 10px
		color: $accent-color
		border: 2px solid $accent-color
		border-radius: 20px
		h3
			font-size: 1em
			line-height: 1.5
			margin-bottom: 5px
		p
			display: block
			width: 100%
			span
				display: inline-block
			span.fa
				font-size: 1em
				width: 25px
				height: 25px
				padding: 5px
				background-color: $accent-color
				box-shadow: 0 5px 2.5px -2.5px rgba(1,1,1,0.3)
				color: #fff
				border-radius: 100%
				cursor: pointer
				transition: all 300ms ease-in-out

				&:active
					transform: scale(1.2)
			.break
				margin: 0 25px
				font-size: 1.5em
				font-weight: 700
	#btn-reset
		display: block
		width: 100%
		padding: 10px
		background-color: $primary-color
		color: #fff
		font-size: 1.5em
		font-weight: 700
		border: none
		border-radius: 10px
		cursor: pointer
		transform-origin: center
		perspective-origin: center
		
		span
			display: block
			width: 100%
			background-color: transparent

		&:hover
			background-color: darken($primary-color,10%)
	.btn-animation
		animation: btn-shake 200ms ease-in-out forwards
		& > span
			animation: btn-shake 200ms ease-in-out reverse forwards

// Animarion
@keyframes btn-shake
	0%
		transform: translate(-5%,0)
	20%
		transform: translate(0px,0)
	50%
		transform: translate(5%,0)
	100%
		transform: translate(0,0)
              
            
!

JS

              
                (function(){
// Build vm object
	var vm = new Vue({
		el: "#pomodoro",
		data: {
			sessionTotal: 0,
			session: 15,
			breakTotal: 0,
			break: 3,
			lap: 1,
			isPaused: true,
			isBreak: false
		},
		computed: {
			displaySession: function(){
				if(this.isBreak){
					return this.secToString(this.break);
				}
				return this.secToString(this.session);
			},
			displayBreak: function(){
				return this.secToString(this.break);
			},
			displayStatus: function(){
				if(this.isBreak){
					return "Break Session"
				}
				if(this.isPaused){
					return "Paused"
				}
				return "Session "+ this.lap;
			},
			progress: function(){
				if(this.isBreak){
					return this.getPercent("break");
				}else{
					return this.getPercent("session");
				}
			}
		},
		methods: {
			secToString : function(sec){
				var hours, minutes, seconds, result;
				seconds = Math.floor((sec)%60);
				minutes = Math.floor((sec/60)%60);
				hours = Math.floor((sec/60/60)%60);
				result = [hours, minutes, seconds].map(function(val){

					if(val < 10){
						return "0"+val;
					}

					return val;
				});
				// Hide hours when don't need
				if(result[0] == "00") {
					result.shift();
				}
				return result.join(":");
			},
			getPercent: function(value){
				return ((this[value] / this[value+"Total"]) * 100) ;
			},
			hideSettings: function(toggle){
				var $settings = $("#btn-session-minus, #btn-session-plus, .setting-break");
				if(toggle){
					$settings.hide(400);
				} else {
					$settings.show(300)
				}
			},
			reset: function(){
				this.stopTimer();
				this.lap = 1;
				this.isBreak = false;
				this.isPaused = true;
				this.session = this.sessionTotal;
				this.break = this.breakTotal;
				this.sessionTotal = 0;
				this.breakTotal = 0;
			},
			startTimer: function(timer){
				var that = this;
				timerSession = setInterval(function(){
					vm[timer]--;
				},1000);
			},
			stopTimer: function () {
				if(timerSession){
					clearInterval(timerSession);
				}
			}
		},
		watch: {
			progress: function(progress){
				var	translateY = "translateY(" + (progress) + "%)",
					opacity = 1 - (progress / 110);
				$(".loading").css("transform", translateY);
				$(".loading").css("opacity",opacity);

			},
			isPaused: function(isPaused){
				var timer = this.isBreak ? "break" : "session";
				var $icon = $("#btn-session-action > .fa");
				if(!isPaused){
					if(this[timer] <= 0){
						this.stopTimer();
					}
					this.startTimer(timer);
					$icon
						.addClass("fa-pause")
						.removeClass("fa-play");
				} 
				if(isPaused){
					this.stopTimer();
					$icon
						.addClass("fa-play")
						.removeClass("fa-pause");
				}
			},
			isBreak: function(isBreak){
				if(isBreak){
					this.startTimer("break");
					$(".tomatoes").addClass("_isBreak");
					$(".loading").css("background-color","#f44336");
				} else {
					this.startTimer("session");
					$(".tomatoes").removeClass("_isBreak");
					$(".loading").css("background-color","#64dd17");
				}
			},
			session: function(sessionVal){
				if(!this.isBreak && sessionVal <= 0){
					this.stopTimer();
					this.break = this.breakTotal;
					this.isBreak = true;
				}
			},
			break: function(breakVal){
				if(this.isBreak && breakVal <= 0){
					this.stopTimer();
					this.lap++;
					this.session = this.sessionTotal;
					this.isBreak = false;
				}
			}
		}
	});

// Button Session and Break Handling for Pomodoro Settings

	$('#btn-session-plus').on('mousedown', function(){
		sessionInterval = setInterval(function(){
			vm.session++
		}, 100);
	}).on("mouseup mouseleave", function(){
		clearInterval(sessionInterval);
		vm.resetSeasonTotal();
	});

	$('#btn-session-minus').on('mousedown', function(){
		sessionInterval = setInterval(function(){
			if(vm.session > 0){
				vm.session--
			}
		}, 100);
	}).on("mouseup mouseleave", function(){
		clearInterval(sessionInterval);
		resetSeasonTotal();
	});

	$('#btn-break-plus').on('mousedown', function(){
		breakInterval = setInterval(function(){
			vm.break++
		}, 100);
	}).on("mouseup mouseleave", function(){
		clearInterval(breakInterval);
		resetBreakTotal();
	});

	$('#btn-break-minus').on('mousedown', function(){
		breakInterval = setInterval(function(){
			if(vm.break > 0){
				vm.break--
			}
		}, 100);
	}).on("mouseup mouseleave", function(){
		clearInterval(breakInterval);
		resetBreakTotal();
	});

//Button Action Handling
	$("#btn-session-action").on("click", function(){
		// Initial Action
		if(vm.sessionTotal === 0 && vm.breakTotal === 0) {
			vm.sessionTotal = vm.session;
			vm.breakTotal = vm.break;
		}

		// Toggle button (Play and Pause)
		if(!vm.isPaused){
			// Triger pause event
			$(".tomatoes").addClass("_isPaused");
			vm.isPaused = true;
			$("#btn-reset").show(400);
		} else {
			// Triger play event
			$(".tomatoes").removeClass("_isPaused");
			vm.hideSettings(true);
			vm.isPaused = false;
			$("#btn-reset").hide(400);
		}
	});
	$("#btn-reset").hide();
	$("#btn-reset").on('click', function(){
		$(this).addClass('btn-animation');
		$(this).one('webkitAnimationEnd oanimationend msAnimationEnd animationend', function(e) {
				$(this).removeClass('btn-animation');
		});
		// Show settings
		vm.hideSettings(false);

		// Reset to Default
		vm.reset();
		$(this).hide(400);
	});
})();
              
            
!
999px

Console