Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wakasann/227318937fe2f47ebb65 to your computer and use it in GitHub Desktop.
Save wakasann/227318937fe2f47ebb65 to your computer and use it in GitHub Desktop.

HTML5 MP3 MixTape DJ Set Player

HTML5 ready, MP3 MixTape & DJ Set Internet Audio Player. Works great in Google Chrome! Click twice to start. Inspired by the SoundManager2 cassette-tape UI project. Uses one long mp3 with multiple songs / tracks and cue's them up to an exact set time. Like a timestamped track-list on Mixcloud.com

I only know enough javascript, to hack it! :-) Right now it does not like to play nice w/ IE 8 and some versions of Firefox. The main change was the placement of the mp3 file inside the html code; to simply call on one JS file.

I like to get it more responsive to size correctly. It can work on an iPone 4S, but it is too big and overlaps. I was able port this into a nice Wordpress plugin, but it would not stay center within the div tags... I also would love to see the names of the song and artist scroll in the tape label field...

If want to reach out to me for any reason you can contact me on my G+ page: https://plus.google.com/+BryanLittle/ Or if your are interested in my music, you can give me a shout out here: FadedShadows Here: https://plus.google.com/+Fadedshadows

The live version of this code is here: http://www.mp3mixtape.us/dubstep/hardcore-euphoric-dubstep-mix-set/

Original design here: http://www.schillmania.com/projects/soundmanager2/demo/cassette-tape/

https://github.com/nulltask/sound-manager-2

A Pen by FadedShadows on CodePen.

License.

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Hardcore Euphoric Dubstep Mix Set! By FadedShadows</title>
<style type="text/css">
html {
background-image: url(http://www.mp3mixtape.us/wp-content/uploads/images/dubstep-red-dwarf-flare-960x540.jpg);
}
</style>
<script id="test1" src="js/fadedshadows-cass1.js">
var s;
var currentSong =0;
s = soundManager.createSound({
id: 'tapeSound',
url: 'http://www.mp3mixtape.us/iframes/audio/Dubstep/Hardcore-Europhic-Dubstep-Mix.mp3',
multiShot: false,
whileplaying: function () {
for (var i = tapeUIs.length; i--;) {
tapeUIs[i].setProgress(this.position / this.durationEstimate);
}
},
onplay: genericStart,
onfinish: genericStop,
onpause: genericStop,
onresume: genericStart
});
function playFromTo(nFrom, nTo) {
s.stop(); // optional: stop before re-starting sound (covers overlapping play attempts)
s.play({
from: nFrom,
to: nTo,
onstop: function() {
soundManager._writeDebug('sound stopped at position ' + this.position);
// note that the "to" target may be over-shot by 200+ msec, depending on polling and other factors.
}
});
}
function GimmieSome() {playFromTo(1, 4827000);}
function Railgun() {playFromTo(430000, 4827000);}
function LettingGo() {playFromTo(595000, 4827000);}
function Surrounded() {playFromTo(795000, 4827000);}
function Areyououtthere() {playFromTo(1036000, 4827000);}
function ThrowThat() {playFromTo(1161000, 4827000);}
function Dying() {playFromTo(1330000, 4827000);}
function FadeTheShadowsEX() {playFromTo(1620000, 4827000);}
function ElbowsUp() {playFromTo(2029000, 4827000);}
function GuidedRhythm() {playFromTo(2233000, 4827000);}
function Snozberries() {playFromTo(2453000, 4827000);}
function MindControl() {playFromTo(2645000, 4827000);}
function DoOrDie() {playFromTo(2865000, 4827000);}
function WonderChild() {playFromTo(3098000, 4827000);}
function Rez() {playFromTo(3350000, 4827000);}
function ICouldBetheOne() {playFromTo(3633000, 4827000);}
function Together() {playFromTo(3938000, 4827000);}
function Blossom() {playFromTo(4168000, 4827000);}
function Exogenesis() {playFromTo(4519000, 4827000);}
window.GimmieSome = GimmieSome;
window.Railgun = Railgun;
window.LettingGo = LettingGo;
window.Surrounded = Surrounded;
window.Areyououtthere = Areyououtthere;
window.ThrowThat = ThrowThat;
window.Dying = Dying;
window.FadeTheShadowsEX = FadeTheShadowsEX;
window.ElbowsUp = ElbowsUp;
window.GuidedRhythm = GuidedRhythm;
window.Snozberries = Snozberries;
window.MindControl = MindControl;
window.DoOrDie = DoOrDie;
window.WonderChild = WonderChild;
window.Rez = Rez;
window.ICouldBetheOne = ICouldBetheOne;
window.Together = Together;
window.Blossom = Blossom;
window.Exogenesis = Exogenesis;
</script>
</head>
<body>
<script type="text/javascript">
$(function() {
$('#play1').tipsy();
$('#play2').tipsy();
$('#play3').tipsy();
$('#play4').tipsy();
$('#play5').tipsy();
$('#play6').tipsy();
$('#play7').tipsy();
$('#play8').tipsy();
$('#play9').tipsy();
$('#play10').tipsy();
$('#play11').tipsy();
$('#play12').tipsy();
$('#play13').tipsy();
$('#play14').tipsy();
$('#play15').tipsy();
$('#play16').tipsy();
$('#play17').tipsy();
$('#play18').tipsy();
$('#play19').tipsy();
});
</script>
<div id="container">
<table class="zebra">
<thead>
<tr>
<th>Play</th>
<th>#</th>
<th>Artist</th>
<th>Track Name</th>
<th>Start Time</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<button id="play1" original-title="Click Twice to Play" onclick="GimmieSome();return false">Play</button>
</td>
<td>01</td>
<td>FadedShadows</td>
<td>Gimme Some</td>
<td>00:00</td>
</tr>
<tr>
<td>
<button id="play2" original-title="Click Twice to Play" onclick="Railgun();return false">Play</button>
</td>
<td>02</td>
<td>xKore, Konec</td>
<td>Railgun (FadedShadows Edit)</td>
<td>07:10</td>
</tr>
<tr>
<td>
<button id="play3" original-title="Click Twice to Play" onclick="LettingGo();return false">Play</button>
</td>
<td>03</td>
<td>BT, JES, Fractal</td>
<td>Letting Go (FadedShadows Edit)</td>
<td>09:55</td>
</tr>
<tr>
<td>
<button id="play4" original-title="Click Twice to Play" onclick="Surrounded();return false">Play</button>
</td>
<td>04</td>
<td>BT, Aqualung</td>
<td>Surrounded (Au5 & Fractal Remix)(FadedShadows Edit)</td>
<td>13:15</td>
</tr>
<tr>
<td>
<button id="play5" original-title="Click Twice to Play" onclick="Areyououtthere();return false">Play</button>
</td>
<td>05</td>
<td>FadedShadows</td>
<td>Are you out there (Original Remix)</td>
<td>17:16</td>
</tr>
<tr>
<td>
<button id="play6" original-title="Click Twice to Play" onclick="ThrowThat();return false">Play</button>
</td>
<td>06</td>
<td>SPL,Two Fresh,HeRobust</td>
<td>Throw That (SPL Remix)(FadedShadows Edit)</td>
<td>19:21</td>
</tr>
<tr>
<td>
<button id="play7" original-title="Click Twice to Play" onclick="Dying();return false">Play</button>
</td>
<td>07</td>
<td>AK9, Sikdope</td>
<td>Dying (FadedShadows Edit)</td>
<td>22:10</td>
</tr>
<tr>
<td><button id="play8" original-title="Click Twice to Play" onclick="FadeTheShadowsEX();return false">Play</button></td>
<td>08</td>
<td>FadedShadows</td>
<td>Fade The Shadows (Extended Remix)</td>
<td>27:10</td>
</tr>
<tr>
<td><button id="play9" original-title="Click Twice to Play" onclick="ElbowsUp();return false">Play</button></td>
<td>09</td>
<td>Them Lost Boys</td>
<td>Elbows Up (FadedShadows Edit)</td>
<td>33:49</td>
</tr>
<tr>
<td><button id="play10" original-title="Click Twice to Play" onclick="GuidedRhythm();return false">Play</button></td>
<td>10</td>
<td>Tantrum Desire</td>
<td>Guided Rhythm (Dubstep Mix)(FadedShadows Edit)</td>
<td>37:13</td>
</tr>
<tr>
<td><button id="play11" original-title="Click Twice to Play" onclick="Snozberries();return false">Play</button></td>
<td>11</td>
<td>Dirt Monkey, Shank Aaron</td>
<td>Snozberries (FadedShadows Edit)</td>
<td>40:53</td>
</tr>
<tr>
<td><button id="play12" original-title="Click Twice to Play" onclick="MindControl();return false">Play</button></td>
<td>12</td>
<td>Zomboy</td>
<td>Mind Control (FadedShadows Edit)</td>
<td>44:05</td>
</tr>
<tr>
<td><button id="play13" original-title="Click Twice to Play" onclick="DoOrDie();return false">Play</button></td>
<td>13</td>
<td>Flux Pavilion</td>
<td>Do Or Die (ft. Childish Gambino)(FadedShadows Edit)</td>
<td>47:45</td>
</tr>
<tr>
<td><button id="play14" original-title="Click Twice to Play" onclick="WonderChild();return false">Play</button></td>
<td>14</td>
<td>Dank</td>
<td>Wonder Child (FadedShadows Edit)</td>
<td>51:38</td>
</tr>
<tr>
<td><button id="play15" original-title="Click Twice to Play" onclick="Rez();return false">Play</button></td>
<td>15</td>
<td>Underworld</td>
<td>Rez (Bassnectar Remix)(FadedShadows Edit)</td>
<td>55:50</td>
</tr>
<tr>
<td><button id="play16" original-title="Click Twice to Play" onclick="ICouldBetheOne();return false">Play</button></td>
<td>16</td>
<td>Avicii & Nicky Romero</td>
<td>I Could Be the One (Dank [USA] Remix)(FadedShadows Edit)</td>
<td>1:00:33</td>
</tr>
<tr>
<td><button id="play17" original-title="Click Twice to Play" onclick="Together();return false">Play</button></td>
<td>17</td>
<td>Noisestorm</td>
<td>Together (FadedShadows Edit)</td>
<td>1:05:38</td>
</tr>
<tr>
<td><button id="play18" original-title="Click Twice to Play" onclick="Blossom();return false">Play</button></td>
<td>18</td>
<td>Au5</td>
<td>Blossom (FadedShadows Edit)</td>
<td>1:09:28</td>
</tr>
<tr>
<td><button id="play19" original-title="Click Twice to Play" onclick="Exogenesis();return false">Play</button></td>
<td>19</td>
<td>Rogue</td>
<td>Exogenesis (FadedShadows Edit)</td>
<td>1:15:19</td>
</tr>
</tbody>
</table>
</div>
<div id="tape-loader">
<div class="spinner-box">
<div class="spinner"></div>
</div>
</div>
<div class="draggable clear ma-r90 cutout tape">
<div class="blur-image-wrapper">
<canvas class="blur-image"></canvas>
</div>
<div class="transparency-sheet"></div>
<div class="tape-shell image-mask" data-image-repeat="true" data-mask-url="http://www.mp3mixtape.us/iframes/image/ma-r90-mask.png">
</div>
<div class="tape-gradient image-mask" data-mask-url="http://www.mp3mixtape.us/iframes/image/ma-r90-mask.png"></div>
<div class="left reel-mask"></div>
<div class="right reel-mask"></div>
<canvas class="connecting-tape"></canvas>
<div class="left reel"></div>
<div class="left spokes"></div>
<div class="right reel"></div>
<div class="right spokes"></div>
<div class="progress-notches">
<div class="n1"></div>
<div class="n2"></div>
<div class="n3"></div>
<div class="n4"></div>
<div class="n5"></div>
<div class="n6"></div>
<div class="n7"></div>
<div class="n8"></div>
<div class="n9"></div>
</div>
<form id="tape-form">
<input class="label" value="Hardcore Euphoric Dubstep Mix Set! By FadedShadows">
</form>
<div class="aqua controls">
<div class="bd">
<ul>
<li><a href="#" title="play/pause" class="play">◄</a>
</li>
<li><a href="#" title="rewind" class="rew">«</a>
</li>
<li><a href="#" title="fast-forward" class="ffwd">»</a>
</li>
<li><a href="#" title="stop" class="stop">■</a>
</li>
</ul>
</div>
</div>
</div>
</body>
</html>
(function(window) {
var caughtError = false;
var CanvasImage = function(canvas, image) {
var width, height;
this.image = image;
width = this.image.width;
height = this.image.height;
this.element = canvas || document.createElement('canvas');
// IE 10 complains if 'auto' is used for style.width|height.
this.element.style.width = width+'px';
this.element.style.height = height+'px';
this.element.width = width;
this.element.height = height;
this.context = this.element.getContext('2d');
this.context.drawImage(this.image, 0, 0);
};
CanvasImage.prototype = {
/**
* Runs a blur filter over the image.
* @param {int} strength Strength of the blur.
*/
blur: function (strength) {
this.context.globalAlpha = 0.5; // Higher alpha made it more smooth
// Add blur layers by strength to x and y
// 2 made it a bit faster without noticeable quality loss
for (var y = -strength; y <= strength; y += 2) {
for (var x = -strength; x <= strength; x += 2) {
// Apply layers
this.context.drawImage(this.element, x, y);
// Add an extra layer, prevents it from rendering lines
// on top of the images (does makes it slower though)
if (x>=0 && y>=0) {
this.context.drawImage(this.element, -(x-1), -(y-1));
}
}
}
this.context.globalAlpha = 1.0;
}
};
function imageMask(imageSrc, maskSrc, canvasWidth, canvasHeight, useRepeat, oncomplete) {
/**
* quick-and-dirty "load an image and apply a mask to it" function
* parameters:
* @imageSrc {URL} string Source image URL
* @maskSrc {URL} string Mask image URL
* @oncomplete {Function} function Callback with data: URI of masked image result
*/
var images = [
new Image(),
new Image()
];
// CORS option?
// images[0].crossOrigin = 'anonymous';
// images[1].crossOrigin = 'anonymous';
var canvas = [
document.createElement('canvas'),
document.createElement('canvas')
];
var loadCount = 0;
var loadTarget = images.length;
function applyMask() {
// draw and mask image
var srcWidth = canvasWidth;
var srcHeight = canvasHeight;
var targetWidth = canvasWidth;
var targetHeight = canvasHeight;
var ctx;
var repeatPattern;
canvas[0].width = srcWidth;
canvas[0].height = srcHeight;
canvas[1].width = targetWidth;
canvas[1].height = targetHeight;
ctx = [
canvas[0].getContext('2d'),
canvas[1].getContext('2d')
];
if (!useRepeat) {
// simple 1:1 case
ctx[0].drawImage(images[0], 0, 0);
} else {
// tile the image across the canvas
repeatPattern = ctx[0].createPattern(images[0], 'repeat');
ctx[0].fillStyle = repeatPattern;
ctx[0].fillRect(0, 0, targetWidth, targetHeight);
ctx[0].fillStyle = '';
}
// draw mask on target canvas
ctx[1].drawImage(images[1], 0, 0);
// apply the mask
ctx[0].globalCompositeOperation = 'destination-in';
ctx[0].drawImage(canvas[1], 0, 0);
ctx[0].globalCompositeOperation = null;
// the resulting masked image
return canvas[0];
}
function imageLoaded() {
// load handler
this.onload = this.onerror = null;
loadCount++;
if (loadCount >= loadTarget) {
// apply the mask, providing the resulting data URI to the handler
// TODO: Don't use data URL, just modify canvas directly; likely much faster.
try {
oncomplete(applyMask().toDataURL('image/png'));
} catch(e) {
// may fail with DOM exception 18 under Chrome when offline eg., file:// instead of over HTTP.
if (typeof console !== 'undefined' && typeof console.warn !== 'undefined') {
console.warn('Unable to apply image mask, likely a security exception from offline (file://) use.', e);
if (!caughtError && typeof console.info !== 'undefined') {
console.info('Using static skin image as a workaround.');
}
}
// hack: try applying the body skin instead, without masking. HTML-based screw elements will overlay the skin, but, eh. this is an edge case anyway.
if (!caughtError) {
oncomplete('http://www.mp3mixtape.us/iframes/image/ma-r90-body-skin.png');
caughtError = true;
} else {
oncomplete();
}
}
// cleanup?
canvas = null;
images = null;
}
}
function init() {
// preload source / target images
images[0].onload = images[0].onerror = imageLoaded;
images[1].onload = images[1].onerror = imageLoaded;
// TODO: check .complete (cached) case?
}
init();
}
function TapeUI(oOptions) {
var css = {
playing: 'playing',
stopped: 'stopped',
ready: 'ready',
dropin: 'dropin'
};
var data = {
progress: 0
};
var controlHandler;
var sound;
var dom = {};
var spoolWidth = 91;
var borderMaxWidth = 76;
var reelBoxWidth = 234;
var tapeWidth = 480;
var tapeHeight = parseInt(tapeWidth/1.6, 10);
var blurCanvas;
var maskCanvas;
var maskCanvasLoaded;
var maskContext;
var maskImage;
var maskVisible;
var context;
function getBackgroundURL(node) {
var url;
var cssprop = 'backgroundImage';
if (node.currentStyle) {
// IE
url = node.currentStyle[cssprop];
} else if (document.defaultView && document.defaultView.getComputedStyle) {
// Firefox
url = document.defaultView.getComputedStyle(node, '')[cssprop];
} else {
// inline style?
url = node.style[cssprop];
}
// HACK: strip url() and/or quotes from string
url = url.replace('url(', '').replace(')', '');
url = url.replace(/\'/g, '').replace(/\"/g, '');
return url;
}
function maskedImageReady(node, uri) {
// callback with data: URI of masked image
if (node && uri) {
node.style.backgroundImage = uri;
}
}
function createMaskedImage(node) {
// get background image (or if <img>, src?) and data-mask-image attributes
var imageSrc = getBackgroundURL(node),
elementWidth = node.offsetWidth,
elementHeight = node.offsetHeight,
useRepeat = !!node.getAttribute('data-image-repeat'),
maskSrc = node.getAttribute('data-mask-url');
return imageMask(imageSrc, maskSrc, elementWidth, elementHeight, useRepeat, function(maskURI) {
var uri = (maskURI ? 'url(' + maskURI + ')' : null);
maskedImageReady(node, uri);
});
}
// canvas stuffs
function scaleWidth(w) {
return (w * tapeWidth);
}
function scaleHeight(h) {
return (h * tapeHeight);
}
function initMask(callback) {
if (!dom.node.className.match(/cutout/i)) {
return false;
}
// draw our tape cut-outs
maskCanvas = document.createElement('canvas');
maskImage = new Image();
// Ensure same dimensions
maskCanvas.width = tapeWidth;
maskCanvas.height = tapeHeight;
/*
maskContext = maskCanvas.getContext('2d');
var spoolBoxRadius = 134;
var spoolCoords = [
// left
tapeWidth * 0.29,
tapeHeight * 0.45,
// right
tapeWidth * 0.71,
tapeHeight * 0.45
];
// filled shape color
maskContext.fillStyle = "black";
maskContext.arc(spoolCoords[0], spoolCoords[1], spoolBoxRadius, 0, 4 * Math.PI);
maskContext.arc(spoolCoords[2], spoolCoords[3], spoolBoxRadius, 0, 4 * Math.PI);
maskContext.fill();
*/
maskImage.onload = function() {
var ctx = maskCanvas.getContext('2d');
ctx.drawImage(this, 0, 0);
this.onload = null;
maskCanvasLoaded = true;
callback();
};
// load the mask to apply
maskImage.src = ('http://www.mp3mixtape.us/iframes/image/ma-r90-mask.png');
}
function createBlurImage(callback) {
var url = getBackgroundURL(document.getElementsByTagName('html')[0]);
var image = new Image();
// CORS option?
// image.crossOrigin = 'anonymous';
image.onload = image.onerror = function() {
// in error state, w/h will be empty.
if (this.width || this.height) {
// make + blur
var canvasImage = new CanvasImage(dom.blurNode, this);
// var uri = canvasImage.element.toDataURL('image/png');
// + assign to DOM
dom.blurNode.style.backgroundImage = '';
canvasImage.blur(2);
}
this.onload = this.onerror = null;
if (callback) {
callback();
}
}
image.src = url;
}
function center() {
// given screen x/y, position at center.
// don't center unless draggable.
if (!dragHandler.data.dragTarget.node) {
return false;
}
var screenX = window.innerWidth,
screenX2 = parseInt(screenX/2, 10),
screenY = window.innerHeight,
screenY2 = parseInt(screenY/2, 10),
x, y,
node = dom.node,
blurNode = dom.blurNode;
if (node) {
x = parseInt(screenX2 - (tapeWidth/2), 10);
y = parseInt(screenY2 - (tapeHeight/2), 10);
node.style.left = x + 'px';
node.style.top = y + 'px';
if (blurNode) {
blurNode.style.marginLeft = -x + 'px';
blurNode.style.marginTop = -y + 'px';
}
}
}
var readyCompleteTimer = null;
function readyComplete(loader) {
utils.css.add(dom.node, css.ready);
utils.css.add(dom.node, css.dropin);
if (readyCompleteTimer) {
window.clearTimeout(readyCompleteTimer);
}
readyCompleteTimer = window.setTimeout(function() {
utils.css.remove(dom.node, css.dropin);
// demo hack: remove the loader, too
/*
if (loader) {
document.body.removeChild(loader);
loader = null;
}
*/
}, 1000);
}
function ready() {
// demo hack: hide the loading element, if present
var loader = document.getElementById('tape-loader'),
wrapper = document.getElementById('demo-header-wrapper');
if (loader) {
utils.css.remove(loader, 'visible');
utils.css.add(loader, 'hidden');
if (wrapper) {
utils.css.add(wrapper, 'visible');
}
}
// trigger animations after slight yield (depending on loader element)
window.setTimeout(function() {
// reposition
center();
readyComplete(loader);
}, loader ? 300 : 1);
}
function init() {
var i, j;
sound = oOptions.sound;
dom = {
node: oOptions.node,
canvas: oOptions.node.querySelectorAll('.connecting-tape'),
reels: oOptions.node.querySelectorAll('div.reel'),
spokes: oOptions.node.querySelectorAll('div.spokes'),
label: oOptions.node.querySelectorAll('div.label'),
maskImages: oOptions.node.querySelectorAll('.image-mask'),
blurNode: oOptions.node.querySelectorAll('.blur-image')
}
if (dom.canvas && dom.canvas.length) {
dom.canvas = dom.canvas[0];
initMask(function() {
// force redraw
setProgress(0, true);
});
} else {
dom.canvas = null;
}
// images needing masking?
if (dom.maskImages) {
for (i=0, j=dom.maskImages.length; i<j; i++) {
createMaskedImage(dom.maskImages[i]);
}
}
// blur image?
if (dom.blurNode && dom.blurNode.length) {
dom.blurNode = dom.blurNode[0];
createBlurImage(ready);
} else {
dom.blurNode = null;
ready();
}
// controls
controlHandler = new ControlHandler(dom, sound);
}
var reelStatus = [{
borderWidth: null
}, {
borderWidth: null
}];
function setReelSize(reelCount, reel, size) {
// return value: was an update applied?
var newFrame = 0;
// limit to between 0 and 1
size = Math.min(1, Math.max(0, size));
var borderWidth = Math.floor(borderMaxWidth*size);
var margin;
if (reelStatus[reelCount].borderWidth !== borderWidth) {
reelStatus[reelCount].borderWidth = borderWidth;
reel.style.borderWidth = borderWidth + 'px';
margin = -(Math.floor(spoolWidth/2) + borderWidth) + 'px';
reel.style.marginLeft = margin;
reel.style.marginTop = margin;
newFrame = 1;
}
return newFrame;
}
function deg2rad(degrees) {
return (Math.PI/180)*degrees;
}
var tapeCache = {
leftReel: {
left: null
},
rightReel: {
left: null
}
};
function drawConnectingTape(canvas, progress, forceUpdate) {
// draw a line of tape between the two reels, at angles relative to the amount of tape on each reel.
var leftReelRadius = borderMaxWidth - (borderMaxWidth * progress);
var rightReelRadius = (borderMaxWidth * progress);
var bottomTapeOffset = scaleHeight(0.998);
var leftReel = {
left: Math.floor(scaleWidth(0.29) - (spoolWidth/2) - leftReelRadius) + 4,
top: scaleHeight(0.42)
};
var guideRadius = 16;
var rightReel = {
left: Math.floor(scaleWidth(0.71) + (spoolWidth/2) + rightReelRadius) - 3,
top: scaleHeight(0.42)
};
var leftGuide = {
left: scaleWidth(0.11) - guideRadius,
top: bottomTapeOffset - guideRadius*2
};
var rightGuide = {
left: scaleWidth(0.89) - guideRadius,
top: bottomTapeOffset
};
var bottomLeftPoint = {
from: [leftGuide.left, leftGuide.top],
to: [leftReel.left, leftReel.top]
};
var bottomRightPoint = {
from: [rightGuide.left, rightGuide.top],
to: [rightReel.left, rightReel.top]
};
var bottomMidPoint = {
left: tapeWidth * 0.5,
top: bottomTapeOffset
};
if (!forceUpdate && tapeCache.leftReel.left === leftReel.left && tapeCache.rightReel.left === rightReel.left) {
// no change since last time.
return false;
}
// otherwise, update everything.
tapeCache.leftReel.left = leftReel.left;
tapeCache.rightReel.left = rightReel.left;
var context = canvas.getContext('2d');
canvas.width = tapeWidth;
canvas.height = tapeHeight;
// context.lineWidth = 1;
context.beginPath();
// move to bottom middle
context.moveTo(bottomMidPoint.left, bottomMidPoint.top);
// -> left guide
context.lineTo(bottomLeftPoint.from[0] + guideRadius, bottomLeftPoint.from[1] + guideRadius*2);
// arc
context.arc(bottomLeftPoint.from[0] + guideRadius, bottomLeftPoint.from[1] + guideRadius, guideRadius, deg2rad(90), deg2rad(180), false);
// -> left reel
context.lineTo(leftReel.left, leftReel.top);
context.lineWidth = 0.5;
// move to bottom middle
context.moveTo(bottomMidPoint.left, bottomMidPoint.top);
// -> right guide
context.lineTo(bottomRightPoint.from[0] + guideRadius, bottomRightPoint.from[1]);
// right side
context.arc(bottomRightPoint.from[0] + guideRadius, bottomRightPoint.from[1] - guideRadius, guideRadius, deg2rad(90), deg2rad(0), true); // -30 on last for curve effect
// -> right reel
context.lineTo(rightReel.left, rightReel.top);
context.lineWidth = 1;
context.stroke();
// apply the mask (only the circular areas around the tape)
if (maskCanvas) {
// set composite operation
context.globalCompositeOperation = 'destination-out';
context.drawImage(maskCanvas, 0, 0);
context.globalCompositeOperation = null;
// visibility check
if (maskCanvasLoaded && !maskVisible) {
maskVisible = true;
canvas.style.visibility = 'visible';
}
}
}
function setReelSpeed(reel, speed) {
// base speed plus a given amount based on speed (multiplier?)
}
function applyProgress(progress) {
var newFrames = 0;
setReelSpeed(dom.reels[0], progress);
newFrames += setReelSize(0, dom.reels[0], 1-progress);
newFrames += setReelSize(1, dom.reels[1], progress);
return newFrames;
}
function setProgress(progress, forceUpdate) {
var newFrames = 0;
forceUpdate = forceUpdate || false;
data.progress = progress;
newFrames = applyProgress(progress);
if ((newFrames || forceUpdate) && dom.canvas) {
drawConnectingTape(dom.canvas, progress, forceUpdate);
}
}
function start() {
utils.css.remove(dom.node, css.stopped);
utils.css.add(dom.node, css.playing);
}
function stop() {
utils.css.remove(dom.node, css.playing);
utils.css.add(dom.node, css.stopped);
}
return {
refreshBlurImage: function(callback) {
utils.css.remove(dom.node, css.dropin);
utils.css.remove(dom.node, css.ready);
return createBlurImage(function() {
utils.css.add(dom.node, css.dropin);
utils.css.add(dom.node, css.ready);
readyComplete();
if (callback) {
callback(this);
}
});
},
dom: dom,
init: init,
setProgress: setProgress,
start: start,
stop: stop
};
}
var tapeUIs = [];
function resetTapeUIs() {
for (var i=tapeUIs.length; i--;) {
tapeUIs[i].setProgress(0);
}
}
var ignoreNextClick = false;
var dragHandler = (function() {
var css,
data,
dom,
events;
function findPos(obj) {
var curleft = curtop = 0;
if (obj.offsetParent) {
do {
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
} while (obj = obj.offsetParent);
}
return [curleft, curtop];
}
css = {
dragActive: 'dragging',
dropActive: 'dropping'
};
data = {
dragTarget: {
node: null,
blurNode: null,
blurNodeContainer: null,
x: null,
y: null,
lastX: null,
lastY: null
},
mousedown: {
x: null,
y: null
},
drag: {
xOffset: null,
yOffset: null
},
background: {
xOffset: -151,
yOffset: -119
}
};
events = {
mousedown: function(e) {
var target = data.dragTarget.node,
clickTarget = e.target;
if (!data.dragTarget.node) {
return true;
}
// additional safety check
if (clickTarget && clickTarget.tagName == 'INPUT') {
ignoreNextClick = true;
return true;
}
ignoreNextClick = false;
var xy = findPos(target);
data.dragTarget.x = xy[0];
data.dragTarget.y = xy[1];
data.mousedown.x = e.clientX;
data.mousedown.y = e.clientY;
data.drag.xOffset = data.mousedown.x - data.dragTarget.x;
data.drag.yOffset = data.mousedown.y - data.dragTarget.y;
utils.events.add(document, 'mousemove', events.mousemove);
utils.events.add(document, 'mouseup', events.mouseup);
e.preventDefault();
return false;
},
mousemove: function(e) {
var x, y,
node = data.dragTarget.node,
blurNode = data.dragTarget.blurNode;
if (node) {
x = (e.clientX - data.drag.xOffset);
y = (e.clientY - data.drag.yOffset);
node.style.left = x + 'px';
node.style.top = y + 'px';
if (blurNode) {
blurNode.style.marginLeft = -x + 'px';
blurNode.style.marginTop = -y + 'px';
}
if (!ignoreNextClick) {
ignoreNextClick = true;
utils.css.add(data.dragTarget.node, css.dragActive);
}
}
},
mouseup: function(e) {
utils.css.remove(data.dragTarget.node, css.dragActive);
if (ignoreNextClick) {
// remove drag work
utils.css.add(data.dragTarget.node, css.dropActive);
window.setTimeout(function() {
utils.css.remove(data.dragTarget.node, css.dropActive);
}, 500);
}
utils.events.remove(document, 'mousemove', events.mousemove);
utils.events.remove(document, 'mouseup', events.mouseup);
e.preventDefault();
return false;
}
};
function updateLastXY() {
var target = data.dragTarget.node;
var xy = findPos(target);
data.dragTarget.lastX = xy[0];
data.dragTarget.lastY = xy[1];
}
function addEvents() {
if (data.dragTarget && data.dragTarget.node) {
utils.events.add(data.dragTarget.node, 'mousedown', events.mousedown);
}
}
function init() {
data.dragTarget.node = document.querySelector('.tape.draggable');
data.dragTarget.blurNode = document.querySelector('.tape.draggable .blur-image');
addEvents();
}
return {
data: data,
init: init
}
}());
var utils = (function() {
var addEventHandler = (typeof window.addEventListener !== 'undefined' ? function(o, evtName, evtHandler) {
return o.addEventListener(evtName,evtHandler,false);
} : function(o, evtName, evtHandler) {
o.attachEvent('on'+evtName,evtHandler);
});
var removeEventHandler = (typeof window.removeEventListener !== 'undefined' ? function(o, evtName, evtHandler) {
return o.removeEventListener(evtName,evtHandler,false);
} : function(o, evtName, evtHandler) {
return o.detachEvent('on'+evtName,evtHandler);
});
var classContains = function(o,cStr) {
return (typeof(o.className)!=='undefined'?o.className.match(new RegExp('(\s|^)'+cStr+'(\s|$)')):false);
};
var addClass = function(o,cStr) {
if (!o || !cStr || classContains(o,cStr)) {
return false;
}
o.className = (o.className?o.className+' ':'')+cStr;
};
var removeClass = function(o,cStr) {
if (!o || !cStr || classContains(o,cStr)) {
return false;
}
o.className = o.className.replace(new RegExp('( '+cStr+')|('+cStr+')','g'),'');
};
/*
var isChildOfNode = function(o,sNodeName) {
if (!o || !o.parentNode) {
return false;
}
sNodeName = sNodeName.toLowerCase();
do {
o = o.parentNode;
} while (o && o.parentNode && o.nodeName.toLowerCase() !== sNodeName);
return (o.nodeName.toLowerCase() === sNodeName ? o : null);
};
*/
return {
css: {
has: classContains,
add: addClass,
remove: removeClass
},
/*
dom: {
isChildOfNode: this.isChildOfNode
},
*/
events: {
add: addEventHandler,
remove: removeEventHandler
}
}
}());
function ControlHandler(tapeUIDOM, soundObject) {
var soundObject;
var css, dom, events, eventMap, soundOK;
// percentage to jump with each click of the rewind / fast-forward buttons
var rewind_ffwd_offset = 0.033;
dom = {
oControls: null,
play: null,
rew: null,
ffwd: null,
stop: null
};
events = {
mousedown: function(e) {
// need <a>
var target = e.target,
className = e.target.className;
if (soundOK && typeof eventMap[className] !== 'undefined') {
eventMap[className](e);
return events.stopEvent(e);
}
},
stopEvent: function(e) {
e.preventDefault();
return false;
},
click: function(e) {
// simple/dumb: just toggle the playstate of the tape.
if (ignoreNextClick) {
ignoreNextClick = false;
return events.stopEvent(e);
}
var target = e.target,
className = e.target.className;
if (typeof eventMap[className] == 'undefined') {
soundObject.togglePause();
} else {
return events.mousedown(e);
}
}
};
eventMap = {
'play': function(e) {
soundObject.play();
},
'rew': function() {
// rewind
var newPosition = Math.max(0, soundObject.position - soundObject.duration * rewind_ffwd_offset);
if (soundObject.duration) {
soundObject.setPosition(newPosition);
// if not playing, force update?
tapeUIs[0].setProgress(newPosition/soundObject.duration);
}
},
'ffwd': function() {
// fast-forward
var newPosition;
if (soundObject.duration) {
newPosition = Math.min(soundObject.duration, soundObject.position + soundObject.duration * rewind_ffwd_offset);
soundObject.setPosition(newPosition);
}
},
'stop': function() {
// equivalent to digital pause
soundObject.pause();
}
};
function addEvents() {
utils.events.add(dom.o, 'mousedown', events.mousedown);
utils.events.add(tapeUIDOM.node, 'click', events.click);
}
function init() {
soundOK = soundManager.ok();
dom.o = tapeUIDOM.node.querySelector('.controls');
dom.play = dom.o.querySelector('.play');
dom.rewind = dom.o.querySelector('.rew');
dom.ffwd = dom.o.querySelector('.ffwd');
dom.stop = dom.o.querySelector('.stop');
addEvents();
}
init();
}
function init() {
var hasCanvas = (typeof document.createElement('canvas').getContext !== 'undefined');
if (!hasCanvas) {
// assume a crap browser (e.g., IE 8.)
return false;
}
var tapes,
i, s;
dragHandler.init();
function genericStart() {
for (var i=tapeUIs.length; i--;) {
tapeUIs[i].start();
}
}
function genericStop() {
for (var i=tapeUIs.length; i--;) {
tapeUIs[i].stop();
}
}
if (soundManager.ok()) {
eval(document.getElementById('test1').innerHTML)
}
tapes = document.querySelectorAll('div.tape');
for (i=tapes.length; i--;) {
tapeUIs.push(new TapeUI({
node: tapes[i],
sound: s
}));
tapeUIs[tapeUIs.length-1].init();
}
resetTapeUIs();
}
function delayInit() {
var loader = document.getElementById('tape-loader');
if (loader) {
loader.className = 'visible';
}
window.setTimeout(function() {
init();
}, 20);
}
soundManager.setup({
url: 'http://www.mp3mixtape.us/iframes/swf/',
flashVersion: 9,
useHighPerformance: false,
preferFlash: false,
html5PollingInterval: 50,
onready: delayInit,
ontimeout: delayInit
});
// interface
window.tapeUIs = tapeUIs;
}(window));
/**
* Another BullShit FadedShadows Code Hack Based on the Cassette Tape UI Prototype (09/2012)
*
*/
@font-face {
font-family: 'JustAnotherHandRegular';
src: url('http://www.mp3mixtape.us/iframes/font/justanotherhand-webfont.eot');
src: url('http://www.mp3mixtape.us/iframes/font/justanotherhand-webfont.eot?#iefix') format('embedded-opentype'),
url('http://www.mp3mixtape.us/iframes/font/justanotherhand-webfont.woff') format('woff'),
url('http://www.mp3mixtape.us/iframes/font/justanotherhand-webfont.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
.tape {
position: relative;
display: inline-block;
width: 480px;
height: 300px;
border: 1px solid rgba(0,0,0,0.1);
cursor: pointer;
margin: 0.5em;
z-index: 1;
}
.tape,
.tape .rail-middle {
border-radius: 12px;
}
.tape .rail-middle {
border-top-left-radius: 0px;
border-top-right-radius: 0px;
}
.tape .left,
.tape .right {
position: absolute;
top: 45%;
}
.tape .left {
/* the left side */
left: 29%;
}
.tape .right {
/* the right side */
left: 71%;
}
.tape .reel,
.tape .spokes {
border-radius: 100%;
}
.tape .spokes {
width: 93px;
height: 93px;
}
.tape .reel {
width: 91px;
height: 91px;
background: transparent url(http://www.mp3mixtape.us/iframes/image/tape-texture.png) no-repeat 50% 50%;
border: 76px solid transparent;
border-radius: 100%;
margin-left: -121px;
margin-top: -121px;
}
.tape .reel-mask {
position: absolute;
top: 2.4%;
width: 256px;
height: 256px;
background: #fff;
border-radius: 100%;
margin-left: -128px;
display: none\9; /* IE 8 */
}
.tape .reel.right {
border-width: 0px;
margin-left: -45px;
margin-top: -45px;
}
.tape .spokes {
margin-left: -46px;
margin-top: -46px;
background: transparent url(http://www.mp3mixtape.us/iframes/image/tape-spokes-sxates.png) no-repeat 50% 50%;
background-size: 100% 100%;
z-index: 5;
}
.tape.dark .spokes {
/* hack: override */
background-color: #ccc;
}
.tape .spokes-overlay {
position: absolute;
top: 50%;
left: 50%;
width: 160px;
height: 160px;
background: #fff;
border-radius: 100%;
margin: -80px 0px 0px -80px;
background: transparent url(http://www.mp3mixtape.us/iframes/image/tape-reel.png) no-repeat 50% 50%;
background-size: contain;
}
.tape.clear .spokes {
background: transparent url(http://www.mp3mixtape.us/iframes/image/spool-metal-black.png) no-repeat 50% 50%;
}
.tape.clear .spokes.right {
background: transparent url(http://www.mp3mixtape.us/iframes/image/spool-metal.png) no-repeat 50% 50%;
}
.tape .label {
position: absolute;
top: 59%;
left: 11%;
width: 78.5%;
height: 16%;
background-color: #fff;
background-color: rgba(0,0,0,0.1);
border-radius: 5px;
text-indent: 0.25em;
font: normal 36px JustAnotherHandRegular, helvetica, sans-serif;
line-height: 140%;
color: #111;
text-shadow: 0px 1px 0px rgba(255,255,255,0.5);
box-shadow: 1px 1px 0px rgba(0,0,0,0.05);
/* a slightly-human element */
/*
-moz-transform: rotate(-0.25deg);
-webkit-transform: rotate(-0.25deg);
-o-transform: rotate(-0.25deg);
transform: rotate(-0.25deg);
*/
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
z-index: 6;
}
.tape.ma-r90 .label {
top: 62%;
width: 75%;
left: 13%;
}
.tape.playing .tape-guide,
.tape.playing .spokes {
-moz-animation-duration: 5s;
-moz-animation-name: spin;
-moz-animation-iteration-count: infinite;
-moz-animation-timing-function: linear;
-webkit-animation-duration: 5s;
-webkit-animation-name: spin;
-webkit-animation-iteration-count: infinite;
-webkit-animation-timing-function: linear;
-ms-animation-duration: 5s;
-ms-animation-name: spin;
-ms-animation-iteration-count: infinite;
-ms-animation-timing-function: linear;
-o-animation-duration: 5s;
-o-animation-name: spin;
-o-animation-iteration-count: infinite;
-o-animation-timing-function: linear;
animation-duration: 5s;
animation-name: spin;
animation-iteration-count: infinite;
animation-timing-function: linear;
}
.tape.playing .tape-guide {
-moz-animation-duration: 4.5s;
-webkit-animation-duration: 4.5s;
-ms-animation-duration: 4.5s;
-o-animation-duration: 4.5s;
animation-duration: 4.5s;
z-index: 2;
}
.tape.stopped .tape-guide,
.tape.stopped .spokes {
-moz-animation: none;
-webkit-animation: none;
-ms-animation: none;
-o-animation: none;
animation: none;
}
.tape .reel.right,
.tape .spokes.right {
-moz-animation-duration: 3.5s;
-webkit-animation-duration: 3.5s;
-ms-animation-duration: 3.5s;
-o-animation-duration: 3.5s;
animation-duration: 3.5s;
}
.tape.clear .label {
background: rgba(255,255,255,0.9);
}
.tape.clear .reel.right {
border-width: 0px;
}
@-moz-keyframes spin {
from {
-moz-transform: rotate(360deg);
}
to {
-moz-transform: rotate(0deg);
}
}
@-webkit-keyframes spin {
from {
-webkit-transform: rotate(360deg);
}
to {
-webkit-transform: rotate(0deg);
}
}
@-ms-keyframes spin {
from {
-ms-transform: rotate(360deg);
}
to {
-ms-transform: rotate(0deg);
}
}
@-o-keyframes spin {
from {
-o-transform: rotate(360deg);
}
to {
-o-transform: rotate(0deg);
}
}
@keyframes spin {
from {
transform: rotate(360deg);
}
to {
transform: rotate(0deg);
}
}
.tape-pad-holder {
position: absolute;
bottom: 1px;
left: 50%;
width: 15%;
height: 25%;
margin: 0px 0px 0px -7.5%;
background: #fff;
}
.tape-pad-holder .tape-pad {
position: absolute;
bottom: 0px;
left: 50%;
width: 35%;
height: 45%;
margin: -1px 0px 0px -17.5%;
background: rgba(0,0,0,0.2);
}
.tape.dark .tape-pad-holder .tape-pad {
background: rgba(0,0,0,0.5);
}
.tape-pad-holder .tape-pad-line {
position: absolute;
left: 0px;
top: 50%;
width: 100%;
height: 0px;
margin-top: -2px;
border-top: 1px solid rgba(0,0,0,0.25);
/* hide by default */
display: none;
}
.progress-notches {
position: absolute;
top: 50%;
left: 50%;
width: 25%;
height: 2.5%;
margin: -18px 0px 0px -12.5%;
font-size: 11px;
text-align: center;
white-space: nowrap;
}
.progress-notches div {
display: inline-block;
background: #666;
width: 2%;
margin-left: 4%;
height: 100%;
vertical-align: top;
/* due to rounding errors, this doesn't always work out. */
width: 2px;
}
.progress-notches div:first-of-type {
margin-left: 0px;
}
.tape.ma-r90,
.tape.ma-r90 .rail-left,
.tape.ma-r90 .rail-right {
background: transparent url(http://www.mp3mixtape.us/iframes/image/ma-r90-body-skin.png) 0px 0px no-repeat;
}
.tape .controls {
position: absolute;
left: 0px;
top: -1px;
width: 100%;
height: 20px;
margin-top: -20px;
vertical-align: bottom;
z-index: -1;
overflow: hidden;
}
.tape .controls ul {
position: relative;
margin-top: 21px;
-moz-transition: all 0.2s ease-out;
-moz-transition-property: height, margin;
-ms-transition: all 0.2s ease-out;
-ms-transition-property: height, margin;
-o-transition: all 0.2s ease-out;
-o-transition-property: height, margin;
-webkit-transition: all 0.2s ease-out;
-webkit-transition-property: height, margin;
transition: all 0.2s ease-out;
transition-property: height, margin;
}
.tape:hover .controls ul {
margin-top: 0px;
}
.tape .controls .bd {
margin: 0px auto;
text-align: center;
}
.tape .controls ul {
list-style-type: none;
padding: 0px;
font-size: 0px; /* collapse */
background-color: rgba(255,255,255,0.9);
border-radius: 2px 2px 0px 0px;
overflow: hidden;
/* http://www.colorzilla.com/gradient-editor/ */
background: rgb(255,255,255); /* Old browsers */
background: -moz-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(241,241,241,1) 50%, rgba(225,225,225,1) 51%, rgba(246,246,246,1) 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,1)), color-stop(50%,rgba(241,241,241,1)), color-stop(51%,rgba(225,225,225,1)), color-stop(100%,rgba(246,246,246,1))); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* IE10+ */
background: linear-gradient(to bottom, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* W3C */
box-shadow: 0px 0px 2px rgba(0,0,0,0.1);
}
#tape1 .controls.aqua ul {
/* http://www.colorzilla.com/gradient-editor/ */
background: rgb(255,255,255); /* Old browsers */
background: -moz-linear-gradient(top, rgba(255,255,255,1) 0%, rgba(241,241,241,1) 50%, rgba(225,225,225,1) 51%, rgba(246,246,246,1) 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(255,255,255,1)), color-stop(50%,rgba(241,241,241,1)), color-stop(51%,rgba(225,225,225,1)), color-stop(100%,rgba(246,246,246,1))); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* IE10+ */
background: linear-gradient(to bottom, rgba(255,255,255,1) 0%,rgba(241,241,241,1) 50%,rgba(225,225,225,1) 51%,rgba(246,246,246,1) 100%); /* W3C */
box-shadow: 0px 1px 2px rgba(0,0,0,0.1);
}
.tape .controls ul,
.tape .controls ul li a {
border: 1px solid rgba(255,255,255,0.9);
}
.tape .controls ul li {
border: 1px solid rgba(0,0,0,0.1);
border-right: none;
border-top: none;
border-bottom: none;
}
.tape .controls ul li:first-of-type,
.tape .controls ul li:first-of-type a {
border-left: none;
}
.tape .controls ul {
position: relative;
border: none;
display: inline-block;
height: 20px;
overflow: hidden;
}
.tape .controls ul li {
position: relative;
display: inline-block;
text-align: center;
}
.tape .controls ul li a {
position: relative;
display: block;
text-decoration: none;
color: #999;
font-size: 16px;
line-height: 20px;
padding: 0px 16px;
border-left: none;
border-top: none;
border-bottom: none;
}
.tape .controls ul:hover li a {
color: #999;
text-shadow: 0px 1px 1px #fff;
}
.tape .controls ul li a:hover {
background: #ccc;
color: #fff;
border-color: transparent;
text-shadow: none;
}
.tape .controls.aqua ul li a:hover {
background-color: rgba(0,0,0,0.1);
background: rgb(184,225,252); /* Old browsers */
background: -moz-linear-gradient(top, rgba(184,225,252,1) 0%, rgba(169,210,243,1) 10%, rgba(144,186,228,1) 25%, rgba(144,188,234,1) 37%, rgba(144,191,240,1) 50%, rgba(107,168,229,1) 51%, rgba(162,218,245,1) 83%, rgba(189,243,253,1) 100%); /* FF3.6+ */
background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,rgba(184,225,252,1)), color-stop(10%,rgba(169,210,243,1)), color-stop(25%,rgba(144,186,228,1)), color-stop(37%,rgba(144,188,234,1)), color-stop(50%,rgba(144,191,240,1)), color-stop(51%,rgba(107,168,229,1)), color-stop(83%,rgba(162,218,245,1)), color-stop(100%,rgba(189,243,253,1))); /* Chrome,Safari4+ */
background: -webkit-linear-gradient(top, rgba(184,225,252,1) 0%,rgba(169,210,243,1) 10%,rgba(144,186,228,1) 25%,rgba(144,188,234,1) 37%,rgba(144,191,240,1) 50%,rgba(107,168,229,1) 51%,rgba(162,218,245,1) 83%,rgba(189,243,253,1) 100%); /* Chrome10+,Safari5.1+ */
background: -o-linear-gradient(top, rgba(184,225,252,1) 0%,rgba(169,210,243,1) 10%,rgba(144,186,228,1) 25%,rgba(144,188,234,1) 37%,rgba(144,191,240,1) 50%,rgba(107,168,229,1) 51%,rgba(162,218,245,1) 83%,rgba(189,243,253,1) 100%); /* Opera 11.10+ */
background: -ms-linear-gradient(top, rgba(184,225,252,1) 0%,rgba(169,210,243,1) 10%,rgba(144,186,228,1) 25%,rgba(144,188,234,1) 37%,rgba(144,191,240,1) 50%,rgba(107,168,229,1) 51%,rgba(162,218,245,1) 83%,rgba(189,243,253,1) 100%); /* IE10+ */
background: linear-gradient(to bottom, rgba(184,225,252,1) 0%,rgba(169,210,243,1) 10%,rgba(144,186,228,1) 25%,rgba(144,188,234,1) 37%,rgba(144,191,240,1) 50%,rgba(107,168,229,1) 51%,rgba(162,218,245,1) 83%,rgba(189,243,253,1) 100%); /* W3C */
color: #fff;
}
.tape .controls.aqua ul li a:active {
background: #999;
}
.tape .controls ul li:first-child a {
border-left: none;
}
.tape .controls ul li:last-child a {
border-right: none;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment