Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Add and apply album art to pages. #2615

Merged
merged 5 commits into from

2 participants

@dominickuo
Collaborator

No description provided.

apps/music/style/music.css
((75 lines not shown))
+
+.album-contorls-button {
+ background: -moz-linear-gradient(center top , #00ADEE, #0078A5) repeat scroll 0 0 transparent;
+ border: 1px solid #0076A3;
+ color: #D9EEF7;
+}
+.album-contorls-button:hover {
+ background: -moz-linear-gradient(center top , #0095CC, #00678E) repeat scroll 0 0 transparent;
+}
+.album-contorls-button:active {
+ background: -moz-linear-gradient(center top , #0078A5, #00ADEE) repeat scroll 0 0 transparent;
+ color: #80BED6;
+}
+.album-contorls-button:disabled {
+ opacity: 0.3;
+}
@vingtetun Collaborator

Add line breaks between your block of rules.

@dominickuo Collaborator

OK, done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@vingtetun vingtetun commented on the diff
apps/music/index.html
@@ -32,7 +32,7 @@
<script type="text/javascript" src="js/music.js"></script>
</head>
- <body class="hidden">
+ <body class="invisible">
@vingtetun Collaborator

Why do you switch from hidden -> invisible.

@dominickuo Collaborator

The two classes look like this:

.hidden { display: none; }

.invisible { visibility: hidden; }

Actually, I used different properties in .hidden and .invisible.
The reason I used visibility: hidden instead of display: none is because,
if the body is set to display: none, the styles of body(and its children) will be all 0 or null.
At this time, I need some styles of the elements in the body, it will cause bugs due to the styles are all 0 or null.
So I used visibility: hidden which has the same vision as display: none,
and I can still get the styles at this time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
apps/music/index.html
@@ -58,10 +58,24 @@
<div class="sub-tile"><br></div>
</div>
<div id="views-list" class="view"></div>
- <div id="views-sublist" class="view"></div>
+ <div id="views-sublist" class="view">
+ <div id="views-sublist-header">
+ <div id="views-sublist-header-album">
+ <div id="views-sublist-header-default-image">&#9834;</div>
+ <img id="views-sublist-header-image" />
+ </div>
+ <div id="views-sublist-header-contorls">
+ <div id="views-sublist-header-name">Name</div>
+ <button id="views-sublist-contorls-play" class="album-contorls-button" disabled>Play All</button>
+ <button id="views-sublist-contorls-shuffle" class="album-contorls-button" disabled>Shuffle</button>
@vingtetun Collaborator

Maybe the ids are a bit long :)

@vingtetun Collaborator

Oh... and there is a typo contorls -> controls which is used in the css too...

@dominickuo Collaborator

I corrected the typo, and modified "views-sublist-header-default-image" to "views-sublist-header-default"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
apps/music/js/MetadataParser.js
((5 lines not shown))
callback(metadata);
- }, {
+ }, {tags: ['album', 'artist', 'title', 'picture'],
dataReader: FileAPIReader(file)
});
@vingtetun Collaborator
  {
    tags: ['album', 'artist', 'title', 'picture'],
    dataReader: FileAPIReader(file)
  });
@dominickuo Collaborator

Done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
apps/music/js/music.js
((5 lines not shown))
this.view.appendChild(li);
+
+ // Set source to image and crop it to be fitted when it's onloded
+ var image = result.metadata.picture;
+ if (image) {
+ img.onload = function(evt) {
+ cropImage(evt);
+ }.bind(this);
@vingtetun Collaborator

You don't need bind.

@dominickuo Collaborator

Yap, : P
And I added a function called setItemImage to ListView.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
apps/music/js/music.js
((16 lines not shown))
this.view.scrollTop = 0;
},
+ setAlbumSrc: function slv_setAlbumSrc(url) {
+ // Set source to image and crop it to be fitted when it's onloded
+ this.albumImage.src = url;
+ this.albumImage.classList.remove('fadeIn');
+
+ this.albumImage.onload = function(evt) {
+ cropImage(evt);
+ this.albumImage.classList.add('fadeIn');
+ }.bind(this);
@vingtetun Collaborator

Use addEventListener instead of onload directly.

@dominickuo Collaborator

Done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@vingtetun vingtetun commented on the diff
apps/music/js/music.js
((5 lines not shown))
- this.index++;
@vingtetun Collaborator

Why don't you keep this line since you want to do it at the end and you have to do a this.index+1 a few lines after.

@dominickuo Collaborator

The reason I put this.index++; at the end of the SubListView.update() is because I wished all the operations in this function can be done, then the index increases.
Although I can use index after this.index++; when I need this.index+1, but this may confuse reviewers and me cause the index is changed before SubListView.update() in finished.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
apps/music/js/music.js
@@ -450,6 +535,22 @@ var PlayerView = {
songData.metadata.album : navigator.mozL10n.get('unknownAlbum');
this.currentIndex = targetIndex;
+ // Reset the image to be ready for fade-in
+ this.coverImage.src = '';
+ this.coverImage.classList.remove('fadeIn');
+
+ // Set source to image and crop it to be fitted when it's onloded
+ var image = songData.metadata.picture;
+ if (image) {
+ this.coverImage.onload = function(evt) {
+ cropImage(evt);
+
+ this.coverImage.classList.add('fadeIn');
+ }.bind(this);
@vingtetun Collaborator

Use addEventListener instead of onload.

@dominickuo Collaborator

Done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@vingtetun vingtetun commented on the diff
apps/music/js/music.js
@@ -699,5 +804,5 @@ window.addEventListener('localized', function showBody() {
document.documentElement.dir = navigator.mozL10n.language.direction;
// <body> children are hidden until the UI is translated
- document.body.classList.remove('hidden');
+ document.body.classList.remove('invisible');
@vingtetun Collaborator

This is consistent in all the other file (i don't like that but that's how it is done for the moment). Please keep hidden instead of invisible.

@dominickuo Collaborator

I have explained why I changed "hidden" to "invisible" in the previous comment.
If this is still an issue to you, I can change back to "hidden";

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@vingtetun vingtetun commented on the diff
apps/music/js/utils.js
@@ -32,3 +32,34 @@ function formatTime(secs) {
return formatedTime;
}
+
+// This function is for cropping the onloaded IMG.
+// If a DIV(parent) contains a IMG(child),
+// the IMG will be cropped and fitted to vertical or horizontal center.
+// DIV(parent) - overflow: hidden;
+// IMG(child) - position: absolute;
+function cropImage(evt) {
+ var image = evt.target;
+
+ var parentWidth = image.parentElement.clientWidth;
+ var parentHeight = image.parentElement.clientHeight;
+
+ var childRatio = image.naturalWidth / image.naturalHeight;
+ var parentRatio = parentWidth / parentHeight;
+
@vingtetun Collaborator

var style = image.style;

@dominickuo Collaborator

Done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@vingtetun vingtetun merged commit 067bcfc into mozilla-b2g:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
This page is out of date. Refresh to see the latest.
View
22 apps/music/index.html
@@ -32,7 +32,7 @@
<script type="text/javascript" src="js/music.js"></script>
</head>
- <body class="hidden">
+ <body class="invisible">
@vingtetun Collaborator

Why do you switch from hidden -> invisible.

@dominickuo Collaborator

The two classes look like this:

.hidden { display: none; }

.invisible { visibility: hidden; }

Actually, I used different properties in .hidden and .invisible.
The reason I used visibility: hidden instead of display: none is because,
if the body is set to display: none, the styles of body(and its children) will be all 0 or null.
At this time, I need some styles of the elements in the body, it will cause bugs due to the styles are all 0 or null.
So I used visibility: hidden which has the same vision as display: none,
and I can still get the styles at this time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
<div id="title">
<button id="title-back" class="title-back-button">
<span id="title-back-text">&#8249;</span>
@@ -58,10 +58,24 @@
<div class="sub-tile"><br></div>
</div>
<div id="views-list" class="view"></div>
- <div id="views-sublist" class="view"></div>
+ <div id="views-sublist" class="view">
+ <div id="views-sublist-header">
+ <div id="views-sublist-header-album">
+ <div id="views-sublist-header-default">&#9834;</div>
+ <img id="views-sublist-header-image" />
+ </div>
+ <div id="views-sublist-header-controls">
+ <div id="views-sublist-header-name">Name</div>
+ <button id="views-sublist-controls-play" class="album-controls-button" disabled>Play All</button>
+ <button id="views-sublist-controls-shuffle" class="album-controls-button" disabled>Shuffle</button>
+ </div>
+ </div>
+ <div id="views-sublist-anchor"></div>
+ </div>
<div id="views-player" class="view">
<div id="player-cover">
- <div id="player-cover-image">&#9834;</div>
+ <div id="player-cover-default-image">&#9834;</div>
+ <img id="player-cover-image" />
<div id="player-cover-caption">
<div id="player-cover-artist" data-l10n-id="songArtist">Song Artist</div>
<div id="player-cover-album" data-l10n-id="songAlbum">Song Album</div>
@@ -81,8 +95,8 @@
<span id="player-seek-remaining">00:00</span>
</div>
<div id="player-controls">
- <button id="player-controls-play" class="player-controls-button">&#9654;</button>
<button id="player-controls-previous" class="player-controls-button">&#9621;&#9664;&#9664;</button>
+ <button id="player-controls-play" class="player-controls-button">&#9654;</button>
<button id="player-controls-next" class="player-controls-button">&#9654;&#9654;&#9615;</button>
</div>
<audio id="player-audio" class="hidden" controls autoplay></audio>
View
2  apps/music/js/MetadataParser.js
@@ -26,9 +26,11 @@ var metadataParser = (function() {
metadata.album = tags.album;
metadata.artist = tags.artist;
metadata.title = tags.title;
+ metadata.picture = tags.picture;
callback(metadata);
}, {
+ tags: ['album', 'artist', 'title', 'picture'],
dataReader: FileAPIReader(file)
});
View
139 apps/music/js/music.js
@@ -203,6 +203,14 @@ var ListView = {
this.view.scrollTop = 0;
},
+ setItemImage: function lv_setItemImage(item, image) {
+ // Set source to image and crop it to be fitted when it's onloded
+ if (image) {
+ item.addEventListener('load', cropImage);
+ item.src = createBase64URL(image);
+ }
+ },
+
update: function lv_update(option, result) {
if (result === null)
return;
@@ -213,26 +221,57 @@ var ListView = {
this.dataSource.push(result);
var li = document.createElement('li');
- li.className = 'song';
+ li.className = 'list-item';
var a = document.createElement('a');
a.href = '#';
+ a.dataset.index = this.index;
+
+ var parent = document.createElement('div');
+ parent.className = 'list-image-parent';
+ var div = document.createElement('div');
+ div.className = 'list-default-image';
+ div.innerHTML = '&#9834;';
+ var img = document.createElement('img');
+ img.className = 'list-image';
+
+ parent.appendChild(div);
+ parent.appendChild(img);
+
+ var image = result.metadata.picture;
+ this.setItemImage(img, image);
switch (option) {
case 'album':
- a.textContent = result.metadata.album;
+ var albumSpan = document.createElement('span');
+ var artistSpan = document.createElement('span');
+ albumSpan.className = 'list-main-title';
+ artistSpan.className = 'list-sub-title';
+ albumSpan.textContent = result.metadata.album;
+ artistSpan.textContent = result.metadata.artist;
+ a.appendChild(albumSpan);
+ a.appendChild(artistSpan);
+
a.dataset.keyRange = result.metadata.album;
a.dataset.option = option;
break;
case 'artist':
- a.textContent = result.metadata.artist;
+ var artistSpan = document.createElement('span');
+ artistSpan.className = 'list-single-title';
+ artistSpan.textContent = result.metadata.artist;
+ a.appendChild(artistSpan);
+
a.dataset.keyRange = result.metadata.artist;
a.dataset.option = option;
break;
case 'playlist':
- a.textContent = result.metadata.title;
+ var titleSpan = document.createElement('span');
+ titleSpan.className = 'list-single-title';
+ titleSpan.textContent = result.metadata.title;
+ a.appendChild(titleSpan);
+
a.dataset.keyRange = 'all';
a.dataset.option = 'title';
@@ -242,8 +281,11 @@ var ListView = {
}
li.appendChild(a);
+ li.appendChild(parent);
this.view.appendChild(li);
+
+ this.index++;
},
handleEvent: function lv_handleEvent(evt) {
@@ -255,13 +297,29 @@ var ListView = {
var option = target.dataset.option;
if (option) {
+ SubListView.clean();
+
+ var index = target.dataset.index;
+ var data = this.dataSource[index];
+ var image = data.metadata.picture;
+
+ if (image)
+ SubListView.setAlbumSrc(createBase64URL(image));
+
+ if (option === 'artist') {
+ SubListView.setAlbumName(data.metadata.artist);
+ } else if (option === 'album') {
+ SubListView.setAlbumName(data.metadata.album);
+ } else {
+ SubListView.setAlbumName(data.metadata.title);
+ }
+
var keyRange = (target.dataset.keyRange != 'all') ?
IDBKeyRange.only(target.dataset.keyRange) : null;
musicdb.enumerate('metadata.' + option, keyRange, 'next',
SubListView.update.bind(SubListView));
- SubListView.clean();
changeMode(MODE_SUBLIST);
}
@@ -284,6 +342,11 @@ var SubListView = {
return this._dataSource;
},
+ get anchor() {
+ delete this._anchor;
+ return this._anchor = document.getElementById('views-sublist-anchor');
+ },
+
set dataSource(source) {
this._dataSource = source;
},
@@ -292,16 +355,36 @@ var SubListView = {
this.dataSource = [];
this.index = 0;
+ this.albumImage = document.getElementById('views-sublist-header-image');
+ this.albumName = document.getElementById('views-sublist-header-name');
+
this.view.addEventListener('click', this);
},
clean: function slv_clean() {
this.dataSource = [];
this.index = 0;
- this.view.innerHTML = '';
+ this.albumImage.src = '';
+ this.anchor.innerHTML = '';
this.view.scrollTop = 0;
},
+ setAlbumSrc: function slv_setAlbumSrc(url) {
+ // Set source to image and crop it to be fitted when it's onloded
+ this.albumImage.src = url;
+ this.albumImage.classList.remove('fadeIn');
+ this.albumImage.addEventListener('load', slv_showImage.bind(this));
+
+ function slv_showImage(evt) {
+ cropImage(evt);
+ this.albumImage.classList.add('fadeIn');
+ };
+ },
+
+ setAlbumName: function slv_setAlbumName(name) {
+ this.albumName.textContent = name;
+ },
+
update: function slv_update(result) {
if (result === null)
return;
@@ -309,7 +392,7 @@ var SubListView = {
this.dataSource.push(result);
var li = document.createElement('li');
- li.className = 'song';
+ li.className = 'list-song-item';
var a = document.createElement('a');
a.href = '#';
@@ -318,13 +401,17 @@ var SubListView = {
navigator.mozL10n.get('unknownTitle');
a.dataset.index = this.index;
- a.textContent = (this.index + 1) + '. ' + songTitle;
- this.index++;
@vingtetun Collaborator

Why don't you keep this line since you want to do it at the end and you have to do a this.index+1 a few lines after.

@dominickuo Collaborator

The reason I put this.index++; at the end of the SubListView.update() is because I wished all the operations in this function can be done, then the index increases.
Although I can use index after this.index++; when I need this.index+1, but this may confuse reviewers and me cause the index is changed before SubListView.update() in finished.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ var titleSpan = document.createElement('span');
+ titleSpan.className = 'list-song-title';
+ titleSpan.textContent = (this.index + 1) + '. ' + songTitle;
+ a.appendChild(titleSpan);
li.appendChild(a);
- this.view.appendChild(li);
+ this.anchor.appendChild(li);
+
+ this.index++;
},
handleEvent: function slv_handleEvent(evt) {
@@ -383,6 +470,7 @@ var PlayerView = {
this.timeoutID;
this.caption = document.getElementById('player-cover-caption');
+ this.coverImage = document.getElementById('player-cover-image');
this.coverControl = document.getElementById('player-cover-buttons');
this.seekBar = document.getElementById('player-seek-bar-progress');
@@ -403,6 +491,7 @@ var PlayerView = {
this.seekBar.addEventListener('mousemove', this);
this.audio.addEventListener('timeupdate', this);
+ this.audio.addEventListener('ended', this);
},
// This function is for the animation on the album art (cover).
@@ -433,6 +522,23 @@ var PlayerView = {
);
},
+ setCoverImage: function pv_setCoverImage(image) {
+ // Reset the image to be ready for fade-in
+ this.coverImage.src = '';
+ this.coverImage.classList.remove('fadeIn');
+
+ // Set source to image and crop it to be fitted when it's onloded
+ if (image) {
+ this.coverImage.src = createBase64URL(image);
+ this.coverImage.addEventListener('load', pv_showImage.bind(this));
+ }
+
+ function pv_showImage(evt) {
+ cropImage(evt);
+ this.coverImage.classList.add('fadeIn');
+ };
+ },
+
play: function pv_play(target) {
this.isPlaying = true;
@@ -441,6 +547,7 @@ var PlayerView = {
if (target) {
var targetIndex = parseInt(target.dataset.index);
var songData = this.dataSource[targetIndex];
+ var image = songData.metadata.picture;
TitleBar.changeTitleText((songData.metadata.title) ?
songData.metadata.title : navigator.mozL10n.get('unknownTitle'));
@@ -450,6 +557,8 @@ var PlayerView = {
songData.metadata.album : navigator.mozL10n.get('unknownAlbum');
this.currentIndex = targetIndex;
+ this.setCoverImage(image);
+
musicdb.getFile(this.dataSource[targetIndex].name, function(file) {
// On B2G devices, file.type of mp3 format is missing
// use file extension instead of file.type
@@ -483,7 +592,7 @@ var PlayerView = {
},
next: function pv_next() {
- var songElements = SubListView.view.children;
+ var songElements = SubListView.anchor.children;
if (this.currentIndex >= this.dataSource.length - 1)
return;
@@ -494,7 +603,7 @@ var PlayerView = {
},
previous: function pv_previous() {
- var songElements = SubListView.view.children;
+ var songElements = SubListView.anchor.children;
if (this.currentIndex <= 0)
return;
@@ -553,6 +662,7 @@ var PlayerView = {
switch (evt.type) {
case 'click':
switch (target.id) {
+ case 'player-cover-default-image':
case 'player-cover-image':
this.showInfo();
@@ -594,6 +704,9 @@ var PlayerView = {
case 'timeupdate':
this.updateSeekBar();
break;
+ case 'ended':
+ this.next();
+ break;
default:
return;
@@ -699,5 +812,5 @@ window.addEventListener('localized', function showBody() {
document.documentElement.dir = navigator.mozL10n.language.direction;
// <body> children are hidden until the UI is translated
- document.body.classList.remove('hidden');
+ document.body.classList.remove('invisible');
@vingtetun Collaborator

This is consistent in all the other file (i don't like that but that's how it is done for the moment). Please keep hidden instead of invisible.

@dominickuo Collaborator

I have explained why I changed "hidden" to "invisible" in the previous comment.
If this is still an issue to you, I can change back to "hidden";

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
});
View
32 apps/music/js/utils.js
@@ -32,3 +32,35 @@ function formatTime(secs) {
return formatedTime;
}
+
+// This function is for cropping the onloaded IMG.
+// If a DIV(parent) contains a IMG(child),
+// the IMG will be cropped and fitted to vertical or horizontal center.
+// DIV(parent) - overflow: hidden;
+// IMG(child) - position: absolute;
+function cropImage(evt) {
+ var image = evt.target;
+ var style = image.style;
+
+ var parentWidth = image.parentElement.clientWidth;
+ var parentHeight = image.parentElement.clientHeight;
+
+ var childRatio = image.naturalWidth / image.naturalHeight;
+ var parentRatio = parentWidth / parentHeight;
+
@vingtetun Collaborator

var style = image.style;

@dominickuo Collaborator

Done.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ if (childRatio > parentRatio) {
+ style.width = 'auto';
+ style.height = parentHeight + 'px';
+
+ style.left = -(parentHeight * childRatio - parentWidth) / 2 + 'px';
+ } else {
+ style.width = parentWidth + 'px';
+ style.height = 'auto';
+
+ style.top = -(parentWidth / childRatio - parentHeight) / 2 + 'px';
+ }
+}
+
+function createBase64URL(image) {
+ return 'data:' + image.format + ';base64,' + Base64.encodeBytes(image.data);
+}
View
238 apps/music/style/music.css
@@ -267,7 +267,7 @@ body.player-mode #views-player {
font-size: 2.5em;
line-height: 1.9em;
text-align: left;
- text-indent: 5%;
+ text-indent: 3%;
opacity: 0.75;
text-shadow: black 1px 1px;
white-space: nowrap;
@@ -318,6 +318,97 @@ body.player-mode #views-player {
height: 90%;
}
+#views-sublist-header,
+#views-sublist-anchor {
+ position: relative;
+ float: left;
+ width: 100%;
+}
+
+#views-sublist-header {
+ height: 8em;
+}
+
+#views-sublist-anchor {
+ width: 100%;
+}
+
+#views-sublist-header-album,
+#views-sublist-header-controls {
+ position: relative;
+ float: left;
+}
+
+#views-sublist-header-album {
+ width: 8em;
+ height: 8em;
+ overflow: hidden;
+ background-image: -moz-radial-gradient(50% 50%, ellipse farthest-corner, rgba(255, 255, 255, 1) 0%, rgba(0, 0, 0, 0.4) 100%);
+}
+
+#views-sublist-header-default {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ text-align: center;
+ font-size: 8em;
+ line-height: 100%;
+ opacity: 0.4;
+ color: orange;
+ text-shadow: 0.2em 0.5em 0.1em #660000, -0.3em 0.1em 0.1em #006600, 0.4em -0.3em 0.1em #000066;
+}
+
+#views-sublist-header-image {
+ position: absolute;
+ opacity: 0;
+}
+
+#views-sublist-header-name {
+ position:relative;
+ width: -moz-calc(100% - 1em);
+ height: 2em;
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+ font-size: 2em;
+ line-height: 2em;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+#views-sublist-header-controls {
+ width: -moz-calc(100% - 8em);
+ height: 8em;
+}
+
+#views-sublist-controls-play,
+#views-sublist-controls-shuffle {
+ position:relative;
+ float: left;
+ width: 50%;
+ font-size: 2em;
+ height: -moz-calc(100% - 2em);
+}
+
+.album-controls-button {
+ background: -moz-linear-gradient(center top , #00ADEE, #0078A5) repeat scroll 0 0 transparent;
+ border: 1px solid #0076A3;
+ color: #D9EEF7;
+}
+
+.album-controls-button:hover {
+ background: -moz-linear-gradient(center top , #0095CC, #00678E) repeat scroll 0 0 transparent;
+}
+
+.album-controls-button:active {
+ background: -moz-linear-gradient(center top , #0078A5, #00ADEE) repeat scroll 0 0 transparent;
+ color: #80BED6;
+}
+
+.album-controls-button:disabled {
+ opacity: 0.3;
+}
+
#tiles-recently {
text-align: center;
font-size: 4em;
@@ -386,9 +477,10 @@ body.player-mode #views-player {
background-image: -moz-radial-gradient(50% 50%, ellipse farthest-corner, rgba(255, 255, 255, 1) 0%, rgba(0, 0, 0, 0.4) 100%);
}
-#player-cover-image {
+#player-cover-default-image {
position: absolute;
width: 100%;
+ height: 100%;
text-align: center;
font-size: 28em;
line-height: 100%;
@@ -397,6 +489,29 @@ body.player-mode #views-player {
text-shadow: 0.2em 0.5em 0.1em #660000, -0.3em 0.1em 0.1em #006600, 0.4em -0.3em 0.1em #000066;
}
+@-moz-keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+
+ to {
+ opacity: 1;
+ }
+}
+
+.fadeIn {
+ -moz-animation-name: fadeIn;
+ -moz-animation-duration: 1500ms;
+ -moz-animation-timing-function: ease-in-out;
+ -moz-animation-fill-mode: forwards;
+ -moz-animation-delay: 500ms;
+}
+
+#player-cover-image {
+ position: absolute;
+ opacity: 0;
+}
+
.slideDown {
-moz-transform: translateY(100%);
-moz-transition: -moz-transform 700ms ease-in-out;
@@ -417,7 +532,7 @@ body.player-mode #views-player {
position: absolute;
width: 100%;
height: 16%;
- background-color: rgba(0, 0, 0, 0.15);
+ background-color: rgba(0, 0, 0, 0.3);
}
#player-cover-caption {
@@ -440,7 +555,7 @@ body.player-mode #views-player {
height: auto;
text-align: left;
font-size: 1.8em;
- text-indent: 10%;
+ text-indent: 11%;
}
#player-cover-album {
@@ -448,7 +563,7 @@ body.player-mode #views-player {
height: auto;
text-align: left;
font-size: 1.5em;
- text-indent: 10%;
+ text-indent: 11%;
}
#player-cover-buttons {
@@ -648,28 +763,129 @@ body.player-mode #views-player {
display: none;
}
-li.song {
+.invisible {
+ visibility: hidden;
+}
+
+li.list-item {
list-style-type: none;
+ position: relative;
+ width: 100%;
}
-li.song a {
- font-size: 1.8em;
+li.list-item a {
+ display: block;
+ color: #fff;
+ text-decoration: none;
+ outline: none;
+ margin: 0;
+ text-shadow: black 1px 1px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ width: 84%;
+ margin-left: 11%;
+ margin-right: 5%;
+ height: 6em;
+}
+
+li.list-item a:active {
+ color: black;
+ text-shadow: rgba(255, 255, 255, 0.5) 1px 1px;
+ background-color: orange;
+}
+
+li.list-song-item {
+ list-style-type: none;
+ position: relative;
+ width: 100%;
+}
+
+li.list-song-item a {
display: block;
color: #fff;
text-decoration: none;
border-bottom: solid 1px #666;
outline: none;
margin: 0;
- padding: 1em;
text-shadow: black 1px 1px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
+ width: 100%;
+ height: 6em;
}
-li.song a:active {
+li.list-song-item a:active {
color: black;
- font-weight: bold;
text-shadow: rgba(255, 255, 255, 0.5) 1px 1px;
background-color: orange;
}
+
+/* title width is 100% - 1em(padding) - 6em(albumArt) */
+.list-main-title,
+.list-sub-title,
+.list-single-title,
+.list-song-title {
+ position: absolute;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+ pointer-events: none;
+}
+
+.list-main-title {
+ top: 10%;
+ width: -moz-calc(84% - 7em/2);
+ font-size: 2em;
+ color: white;
+}
+
+.list-sub-title {
+ top: 50%;
+ width: -moz-calc(84% - 7em/1.6);
+ font-size: 1.6em;
+ color: gray;
+}
+
+.list-single-title {
+ top: 28%;
+ width: -moz-calc(84% - 7em/2);
+ font-size: 2em;
+ color: white;
+}
+
+.list-song-title {
+ top: 28%;
+ width: -moz-calc(89% - 0.5em);
+ padding-left: 11%;
+ padding-right: 0.5em;
+ font-size: 2em;
+ color: white;
+}
+
+.list-image-parent {
+ position: absolute;
+ right: 5%;
+ top: 0px;
+ height: 6em;
+ width: 6em;
+ overflow: hidden;
+ background-color: gray;
+ box-shadow: 0 0 1px black;
+}
+
+.list-default-image {
+ position: absolute;
+ width: 100%;
+ height: 100%;
+ text-align: center;
+ font-size: 6em;
+ line-height: 100%;
+ opacity: 0.4;
+ color: orange;
+}
+
+.list-image {
+ position: absolute;
+}
Something went wrong with that request. Please try again.