Back to Parent

<!DOCTYPE html>
<html>
	<head>
		<title>Pin Box</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
		<style>
			
			*{
				font-family: Helvetica;
			}


			body{
				width: 100%;
				margin: 0;
				padding: 0;
			}



			p#num{
				position: absolute;
				top: 40px;
				left: 40px;
				font-size: 18px;
				padding: 10px;
				color: white;
				background: #a4c6e4;
				border-radius: 2px;
			}

			div#img, div#info-graphic{
				position: fixed;
				top: 0;
				left: 0;
				width: 100vw;
				
			}

			div#img{
				margin: 2vh 0;
				height: 76vh;
				background-size: contain;
				background-repeat: no-repeat;
				background-position: 50% 50%;
			}

			div#info-graphic{
				display: none;
				height: 80vh;
			}

			div#yes, div#no{
				position: fixed;
				left: 50vw;
				top: 40vh;
				width: 200px;
				font-size: 72px;
				line-height: 80px;
				height: 80px;
				margin-left: -102px;
				margin-top: -42px;
				border-radius: 5px;
				text-align: center;
				background: white;
				border: 2px solid;
				display: none;
			}

			div#yes{ 
				color: #4dac16;
				border-color: #4dac16;
			} 
			div#no{ 
				color: #e64959;
				border-color: #e64959; 
			}
			

			div#bottom{
				width: 100%;
				height: 20vh;
				background: #a4c6e4;
				position: fixed;
				bottom: 0;
			}

			div#bottom div.thumb, div#info-graphic div.bar{
				position: relative;
				float: left;
				margin: 2vh 0 0 2vw;
				font-size: 24px;
				line-height: 40px;
				text-align: center;
				color: white;
			}

			div#info-graphic div.bar{
				background: #80b3e4;
				margin-top: 0;
			}

			div#info-graphic div.bar#highest-vote{
				background: #60e66a;
			}

			div#bottom div.thumb{
				background: white;
				background-size: contain;
				background-repeat: no-repeat;
				background-position: 50% 50%;
				height: 16vh;
			}

			div#thumb-highlight{
				position: absolute;
				margin: 2vh 0 0 2vw;
				height: 16vh;
				border: 4px solid #e5a033;
				transition: left 0.6s ease-in-out;
				-webkit-transform: translate(-4px, -4px);
				transform: translate(-4px, -4px);
			}
			

			div#bottom div.thumb div.yes-icon,
			div#bottom div.thumb div.no-icon{
				position: relative;
				left: 50%;
				top: 50%;
				width: 6vw;
				height: 6vw;
				margin-top: -3vw;
				margin-left: -3vw;
				background-size: contain;
				background-repeat: no-repeat;
			}

			div#bottom div.thumb div.yes-icon{
				background-image: url('yes.png');
			}

			div#bottom div.thumb div.no-icon{
				background-image: url('no.png');
			}

		</style>

		<script>

    		var SparkCore = function(deviceID, accessToken, name){
						this.deviceID = deviceID;
						this.accessToken = accessToken;
						this.name = name;
					};
				
			// @para x2: String, Function
			// @para x1: Object { String: Function [,String: Function] [,...] }
			SparkCore.prototype.subscribe = function(name, handler) {

				// if there is no event has been registered on this Spark
				if(!this.eventSource){
					this.eventSource = new EventSource("https://api.spark.io/v1/devices/" + this.deviceID + "/events/?access_token=" + this.accessToken);

					console.log('event source created on:', this.deviceID, this.accessToken);

					this.subscribe('error', function(e){console.log(e)});
				}

				//if passed in event, register it
				if(typeof name === 'string'){

					console.log('event registered:', name);

					this.eventSource.addEventListener(name, handler, false);
				}
					
				//if passed in objects, dissemble them and call subscribe again
				else if(typeof name === 'object')
					for (n in name){
						if(name.hasOwnProperty(n)){
							this.subscribe(n, name[n]);
						}
					}
				return this;
	    	};

	    	SparkCore.prototype.callFn = function(name, args){

	    		var url = "https://api.spark.io/v1/devices/" + this.deviceID + "/" + name + 
		                        "?access_token=" + this.accessToken;

		        $.post( url ,  { "args": args });

		        return this;
    		};

    		function addArray(sum, add){
    			console.log(sum, add);
				if(sum.length !== add.length) return;

				return sum.map(function(v, i){
					return v + add[i];
				})
			}


	    </script>

	</head>


	<body>


		<div id="img"></div>
		<div id="info-graphic"></div>
		<p id="num"></p>
		<div id="yes">YES</div>
		<div id="no">NO</div>
		<div id="bottom"></div>




		<script>

			var url = "REPLACE_NAME.jpg",
				spark = new SparkCore('54ff67066678574939510867', '2d07a5c34425054c40c827f3f8bb70e8933d797f'),
				switchDelay = 1000,


				imgGrp = [{
					'pfx': 'clock',
					'num': 8,
					'voteSum': [7, 3, 2, 4, 3, 2, 4, 1] // dummy data for demo
				},{
					'pfx': 'zimg',
					'num': 6,
					'voteSum': [2, 4, 3, 2, 4, 8] // dummy data for demo
				}],

				nowImgGrp = 0,
				nowImg = 0,
				voteBuffer = [],
				showInfoGraphic = false,

				model = {
						addVoteToSum: function addVoteToSum(){
							console.log(imgGrp[nowImgGrp].voteSum);
							imgGrp[nowImgGrp].voteSum = addArray(imgGrp[nowImgGrp].voteSum, voteBuffer);
							console.log(imgGrp[nowImgGrp].voteSum);

							return this;
						}
					},

				view = {
						showInfoGraphic: function showInfoGraphic(){
								$('#img').hide();
								$('#info-graphic').show();
								return this;
							},

						hideInfoGraphic: function hideInfoGraphic(){
								//$('#img').css('display', 'block');
								$('#img').show();
								$('#info-graphic').hide();
								return this;
							},

						replaceMainImage: function replaceMainImage(){
								if(nowImg < imgGrp[nowImgGrp].num){
									$('#img').css(
										'background-image', 
										'url(' + url.replace('REPLACE_NAME', imgGrp[nowImgGrp].pfx + nowImg ) + ')'
										);
								}
								
								return this;
							},

						dynamicThumbnailWidth: function(){
								return (100 - ( imgGrp[nowImgGrp].num + 1 )*2)/imgGrp[nowImgGrp].num
							},

						updateNumTag: function updateNumTag(){
								if(nowImg < imgGrp[nowImgGrp].num ){
									$('#num').show();
									$('#num').html((nowImg+1) + '/' + imgGrp[nowImgGrp].num);
								}else{
									$('#num').hide();
								}
								return this;
							}, 
					
						updateBottom: function updateBottom(){

								if(nowImg == 0){
									$('#bottom').empty();

									// create highlight border
									$('<div>')
										.attr('id', 'thumb-highlight')
										.css({
											'left': 0,
											'width':  view.dynamicThumbnailWidth() + 'vw'
										})
										.appendTo($('#bottom'))


									// create thumbnails
									for(var i = 0; i< imgGrp[nowImgGrp].num; i++){

										$('<div>')
											.attr('class', 'thumb')
											.css({
												'background-image': 'url(' + url.replace('REPLACE_NAME', imgGrp[nowImgGrp].pfx + i) + ')',
												'width': view.dynamicThumbnailWidth()  + 'vw'
											})
											.appendTo($('#bottom'));
									}


								}else if(nowImg < imgGrp[nowImgGrp].num){

									$('#thumb-highlight').css('left',
										nowImg * ( 2 + (100 - ( imgGrp[nowImgGrp].num + 1 )*2)/imgGrp[nowImgGrp].num) + 'vw'
									);

								}else{

									$('#thumb-highlight').hide();
								}

								return this;
							
							},

						generateInfoGraphic: function generateInfoGraphic(){
								var i,
									maxVote = Math.max.apply( null, imgGrp[nowImgGrp].voteSum );
									mapVote = function(vote){
										return vote/maxVote * 60;
									}

								for(i = 0; i < imgGrp[nowImgGrp].num ; i++) {
									$('<div>')
										.css({
											'height': mapVote(imgGrp[nowImgGrp].voteSum[i]) + 'vh',
											'width': view.dynamicThumbnailWidth() + 'vw',
											'top': (80 - mapVote(imgGrp[nowImgGrp].voteSum[i])) + 'vh'
										})
										.attr({
											'class': 'bar',
											'id': imgGrp[nowImgGrp].voteSum[i] === maxVote ? 'highest-vote' : undefined
										})
										.html( imgGrp[nowImgGrp].voteSum[i] )
										.appendTo($('#info-graphic'))
									
								}
								
								return this;
							},

						clearInfoGraphic: function clearInfoGraphic(){
								$('#info-graphic').empty();
							}
					};

			spark.subscribe({
				"vote/yes": voteYesHandler,
				"vote/no": voteNoHandler
			})

			function voteYesHandler(){
				if( nowImg < imgGrp[nowImgGrp].num){

					// debug
					console.log('Voted Yes');

					// model
					voteBuffer.push(1);

					// view
					$('#yes')
						.css('display', 'block');

					$('<div>')
						.attr('class', 'yes-icon')
						.appendTo($('#bottom .thumb:nth-child(' + (nowImg+2) + ')'));
				}

				// controller
				goNext();
			}

			function voteNoHandler(){
				if( nowImg < imgGrp[nowImgGrp].num){
					// debug
					console.log('Voted No');

					// model
					voteBuffer.push(0);

					// view
					$('#no').css('display', 'block');

					$('<div>')
						.attr('class', 'no-icon')
						.appendTo($('#bottom .thumb:nth-child(' + (nowImg+2) + ')'));
				}

				// controller
				goNext();
			}

			function goNext(){
				// model
				nowImg++;

				// end a critic:
				// process data -> show info graphic
				if(nowImg === imgGrp[nowImgGrp].num){
					
					imgGrp[nowImgGrp].votes = imgGrp[nowImgGrp].votes || [];
					imgGrp[nowImgGrp].votes.push(voteBuffer);

					model.addVoteToSum();

					//clear vote buffer
					voteBuffer = [];
					
					setTimeout(function(){
							view
							.generateInfoGraphic()
							.showInfoGraphic();	
						}, switchDelay)
					

				// end a group:
				// hide info graphic -> show next group
				}else if( nowImg === ( imgGrp[nowImgGrp].num + 1 ) ){

					nowImg = 0;
					nowImgGrp++;

					//end all critic
					if( nowImgGrp === imgGrp.length ){
						nowImgGrp = 0;
					}

					view
						.hideInfoGraphic()
						.clearInfoGraphic()
				}

				setTimeout(goNextExec, nowImg > 0 ? switchDelay : 0);
			}


			function goNextExec(){

				spark.callFn('reset');

				//view
				$('#yes, #no')
					.hide();

				view
					.replaceMainImage()
					.updateNumTag()
					.updateBottom()

			}
			
			
			function init(){
				view
					.replaceMainImage(imgGrp[nowImgGrp].pfx + nowImg)
					.updateNumTag()
					.updateBottom();
			}


			init();
			
			
		</script>
	</body>
</html>
Click to Expand

Content Rating

Is this a good/useful/informative piece of content to include in the project? Have your say!

0