2.2.0 Pushing beta to prod, lots of changes
This commit is contained in:
parent
db8cb0865a
commit
58d46ec544
16 changed files with 752 additions and 399 deletions
32
README
32
README
|
@ -2,17 +2,35 @@ MiniSub - HTML5 Mini Player for Subsonic
|
|||
|
||||
Imagine you can stream all your music from home, to any device, where ever you are. That is Subsonic! Now imagine having a Web App to stream your music that is as beautiful and well designed as it is functional, that is MiniSub!
|
||||
|
||||
MiniSub is an HTML5 Mini Player for the Subsonic streaming server.
|
||||
MiniSub is an HTML5 Web Player for the Subsonic streaming server.
|
||||
|
||||
Features
|
||||
- HTML5 Audio with Flash fallback (provided by the SoundManager2 library)
|
||||
- Flexible Layout (will scale to whatever size your browser window is)
|
||||
- Customizable (features can be turned on/off and settings are saved)
|
||||
- Keyboard shortcuts (back, forward, play/pause, skip to artist)
|
||||
- Playlists (create new, add to existing, delete)
|
||||
- Artist/Album Ratings
|
||||
- Chat and Now Playing
|
||||
- Last.fm
|
||||
- Keyboard shortcuts (back, forward, play/pause, skip to artist, volume control)
|
||||
- Playlist support (create new, add to existing, delete)
|
||||
- Podcast support (includes description field on hover)
|
||||
- Favorite/Starred support for Albums & Songs
|
||||
- Chat support (when the chat window is open it will auto-update in the background)
|
||||
- Now Playing support (see what others are streaming at the moment)
|
||||
- Easy installation (Chrome App or manual install)
|
||||
- FF/Chome support (IE9 works but is a little rough around the edges)
|
||||
- Sortable Columns
|
||||
- Light/Dark Theme
|
||||
- Last.fm support
|
||||
- Autopilot Mode (click one button and songs continue to play)
|
||||
- AutoSave Mode (saves position and current playlist if you close or refresh your browser)
|
||||
|
||||
You will need a Subsonic server to be able to play your own music. Subsonic is a free, web-based media streamer, providing ubiquitous access to your music. Use it to share your music with friends, or to listen to your own music while at work. Please see http://www.subsonic.org
|
||||
|
||||
Chrome App: https://chrome.google.com/webstore/detail/minisub/jccdpflnecheidefpofmlblgebobbloc
|
||||
Forum: http://forum.subsonic.org/forum/viewforum.php?f=12
|
||||
Donations: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=VMTENRSJWQ234
|
||||
|
||||
Change Log inside...
|
||||
|
||||
**Permissions**
|
||||
* You will have to allow MiniSub to "Access your data on all websites". This is required because your Subsonic server could be at any URL `http://*/*` or `https://*/*`
|
||||
* I NEVER access, read, modify, store, or transmit your personal data.
|
||||
* [https://github.com/tsquillario/MiniSub/blob/master/manifest.json](https://github.com/tsquillario/MiniSub/blob/master/manifest.json)
|
||||
* [http://developer.chrome.com/extensions/xhr.html](http://developer.chrome.com/extensions/xhr.html)
|
||||
|
|
71
README.rst
71
README.rst
|
@ -1,51 +1,36 @@
|
|||
=======
|
||||
MiniSub
|
||||
=======
|
||||
**HTML5 Mini Player for Subsonic**
|
||||
MiniSub - HTML5 Mini Player for Subsonic
|
||||
|
||||
Imagine you can stream all your music from home, to any device, where ever you
|
||||
are. That is Subsonic! Now imagine having a Web App to stream your music that
|
||||
is as beautiful and well designed as it is functional, that is MiniSub!
|
||||
Imagine you can stream all your music from home, to any device, where ever you are. That is Subsonic! Now imagine having a Web App to stream your music that is as beautiful and well designed as it is functional, that is MiniSub!
|
||||
|
||||
MiniSub is an HTML5 Mini Player for the Subsonic streaming server.
|
||||
MiniSub is an HTML5 Web Player for the Subsonic streaming server.
|
||||
|
||||
Features
|
||||
````````
|
||||
* Flexible Layout (will scale to whatever size your browser window is)
|
||||
* Customizable (features can be turned on/off and settings are saved)
|
||||
* Keyboard shortcuts (back, forward, play/pause, skip to artist)
|
||||
* Playlists (create new, add to existing, delete)
|
||||
* Artist/Album Ratings
|
||||
* Chat and Now Playing
|
||||
* Last.fm
|
||||
* Supports Podcasts.
|
||||
- HTML5 Audio with Flash fallback (provided by the SoundManager2 library)
|
||||
- Flexible Layout (will scale to whatever size your browser window is)
|
||||
- Keyboard shortcuts (back, forward, play/pause, skip to artist, volume control)
|
||||
- Playlist support (create new, add to existing, delete)
|
||||
- Podcast support (includes description field on hover)
|
||||
- Favorite/Starred support for Albums & Songs
|
||||
- Chat support (when the chat window is open it will auto-update in the background)
|
||||
- Now Playing support (see what others are streaming at the moment)
|
||||
- Easy installation (Chrome App or manual install)
|
||||
- FF/Chome support (IE9 works but is a little rough around the edges)
|
||||
- Sortable Columns
|
||||
- Light/Dark Theme
|
||||
- Last.fm support
|
||||
- Autopilot Mode (click one button and songs continue to play)
|
||||
- AutoSave Mode (saves position and current playlist if you close or refresh your browser)
|
||||
|
||||
You will need a Subsonic server to be able to play your own music. Subsonic is
|
||||
a free, web-based media streamer, providing ubiquitous access to your music.
|
||||
Use it to share your music with friends, or to listen to your own music while
|
||||
at work. Please see http://www.subsonic.org
|
||||
You will need a Subsonic server to be able to play your own music. Subsonic is a free, web-based media streamer, providing ubiquitous access to your music. Use it to share your music with friends, or to listen to your own music while at work. Please see http://www.subsonic.org
|
||||
|
||||
Chrome App: https://chrome.google.com/webstore/detail/minisub/jccdpflnecheidefpofmlblgebobbloc
|
||||
Forum: http://forum.subsonic.org/forum/viewforum.php?f=12
|
||||
Donations: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=VMTENRSJWQ234
|
||||
|
||||
Change Log inside...
|
||||
|
||||
License
|
||||
```````
|
||||
Copyright (c) 2011-2012 Trevor Squillario
|
||||
https://github.com/tsquillario/MiniSub
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
**Permissions**
|
||||
* You will have to allow MiniSub to "Access your data on all websites". This is required because your Subsonic server could be at any URL `http://*/*` or `https://*/*`
|
||||
* I NEVER access, read, modify, store, or transmit your personal data.
|
||||
* [https://github.com/tsquillario/MiniSub/blob/master/manifest.json](https://github.com/tsquillario/MiniSub/blob/master/manifest.json)
|
||||
* [http://developer.chrome.com/extensions/xhr.html](http://developer.chrome.com/extensions/xhr.html)
|
||||
|
|
BIN
images/arrow_left_gl_8x8.png
Normal file
BIN
images/arrow_left_gl_8x8.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 175 B |
BIN
images/arrow_right_gl_8x8.png
Normal file
BIN
images/arrow_right_gl_8x8.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 181 B |
52
index.html
52
index.html
|
@ -17,6 +17,7 @@
|
|||
<script src="js/plugins/jquery.dateFormat-1.0.js" type="text/javascript"></script>
|
||||
<script src="js/plugins/jquery.disable.text.select.pack.js" type="text/javascript"></script>
|
||||
<script src="js/plugins/jquery.hotkeys.js" type="text/javascript"></script>
|
||||
<script src="js/plugins/jquery.stupidtable.js" type="text/javascript"></script>
|
||||
<script src="js/plugins/jquery.linkify-1.0-min.js" type="text/javascript"></script>
|
||||
<script src="js/plugins/jquery.periodic.js" type="text/javascript"></script>
|
||||
<script src="js/plugins/jquery.scrollTo-1.4.2-min.js" type="text/javascript"></script>
|
||||
|
@ -54,23 +55,23 @@
|
|||
<a href="#" class="button" id="action_IncreaseWidth" title="Increase Width"><img src="images/plus_8x8.png" /></a>
|
||||
</div>
|
||||
<div class="subactions floatleft">
|
||||
<div id="songactions">
|
||||
<a href="#" class="button" id="action_SelectAll" title="Select All">All</a>
|
||||
<a href="#" class="button" id="action_SelectNone" title="Select None">None</a>
|
||||
<a href="#" class="button" id="action_AddToPlaylist" title="Add Selected To Playlist">+ Playlist</a>
|
||||
<div id="songActions">
|
||||
<a href="#" class="button disabled" id="action_SelectAll" title="Select All">All</a>
|
||||
<a href="#" class="button disabled" id="action_SelectNone" title="Select None">None</a>
|
||||
<a href="#" class="button disabled" id="action_AddToPlaylist" title="Add Selected To Playlist">+ Playlist</a>
|
||||
<div id="submenu_AddToPlaylist" class="submenu shadow" style="display: none;"></div>
|
||||
<a href="#" class="button" id="action_AddToCurrent" title="Add Selected To Current Playlist">+ Current</a>
|
||||
<a href="#" class="button" id="action_AddAllToCurrent" title="Add All to Current Playlist">+All</a>
|
||||
<a href="#" class="button" id="action_PlayAlbum" title="Play Album"><img src="images/play_gl_6x8.png" /></a>
|
||||
<a href="#" class="button disabled" id="action_AddToCurrent" title="Add Selected To Current Playlist">+ Current</a>
|
||||
<a href="#" class="button disabled" id="action_AddAllToCurrent" title="Add All to Current Playlist">+All</a>
|
||||
<a href="#" class="button disabled" id="action_PlayAlbum" title="Play Album"><img src="images/play_gl_6x8.png" /></a>
|
||||
</div>
|
||||
<input type="text" id="Search" class="medium" />
|
||||
<input type="text" id="Search" class="medium" title="Wildcards (*) supported"/>
|
||||
<select id="SearchType" name="SearchType">
|
||||
<option value="song">Song</option>
|
||||
<option value="album">Album</option>
|
||||
</select>
|
||||
<a href="#" class="button" id="action_Search" title="Search"><img class="pad" src="images/magnifying_glass_alt_12x12.png" /></a>
|
||||
</div>
|
||||
<div id="Albums" class="lgsection floatleft">
|
||||
<div id="Albums" class="section lgsection floatleft">
|
||||
<div class="loading"></div>
|
||||
<div id="Artists" class="smsection floatleft" tabindex="0">
|
||||
<div class="padder">
|
||||
|
@ -91,11 +92,11 @@
|
|||
<div id="BottomContainer"><ul id="BottomIndex"></ul></div>
|
||||
</div>
|
||||
<table id="AlbumContainer" class="simplelist songlist noselect" cellspacing="1">
|
||||
<thead id="AlbumHeader"></thead>
|
||||
<tbody id="AlbumRows"></tbody>
|
||||
<thead></thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div id="status_Library" class="status alignleft" data-type="" data-offset=""><img src="images/arrow_left_gl_8x8.png" /> <a id="action_PreviousAlbumList" class="previous" href="#">Previous</a> | <a id="action_NextAlbumList" class="next" href="#">Next</a> <img src="images/arrow_right_gl_8x8.png" /></div>
|
||||
</div>
|
||||
<div id="tabCurrent" class="tabcontent">
|
||||
<div class="actions floatleft">
|
||||
|
@ -103,19 +104,21 @@
|
|||
<a href="#" class="button" id="action_Empty" title="Remove All">Empty</a>
|
||||
</div>
|
||||
<div class="subactions floatleft">
|
||||
<a href="#" class="button" id="action_CurrentSelectAll" title="Select All">All</a>
|
||||
<a href="#" class="button" id="action_CurrentSelectNone" title="Select None">None</a>
|
||||
<a href="#" class="button" id="action_AddCurrentToPlaylist" title="Add Selected To Playlist">+ Playlist</a>
|
||||
<div id="currentActions">
|
||||
<a href="#" class="button disabled" id="action_CurrentSelectAll" title="Select All">All</a>
|
||||
<a href="#" class="button disabled" id="action_CurrentSelectNone" title="Select None">None</a>
|
||||
<a href="#" class="button disabled" id="action_AddCurrentToPlaylist" title="Add Selected To Playlist">+ Playlist</a>
|
||||
<div id="submenu_AddCurrentToPlaylist" class="submenu shadow" style="display: none;"></div>
|
||||
<a href="#" class="button" id="action_AutoPilot" title="Autopilot"><img class="pad" src="images/steering_wheel_gd_12x12.png" /></a>
|
||||
</div>
|
||||
<div id="CurrentPlaylist" class="fullsection floatleft noselect">
|
||||
</div>
|
||||
<div id="CurrentPlaylist" class="section fullsection floatleft noselect">
|
||||
<table id="CurrentPlaylistContainer" class="simplelist songlist" cellspacing="1">
|
||||
<thead></thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div id="status"></div>
|
||||
<div id="status_Current" class="status">0 song(s), 00:00:00 total time</div>
|
||||
</div>
|
||||
<div id="tabPlaylists" class="tabcontent">
|
||||
<div class="actions floatleft">
|
||||
|
@ -129,7 +132,7 @@
|
|||
<a href="#" class="button" id="action_RemoveSongs" title="Remove selected song(s) from playlist">Remove Song(s)</a>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
<div id="Tracks" class="lgsection floatleft noselect">
|
||||
<div id="Tracks" class="section lgsection floatleft noselect">
|
||||
<div class="loading"></div>
|
||||
<div id="Playlists" class="smsection floatleft noselect">
|
||||
<div class="padder">
|
||||
|
@ -146,6 +149,7 @@
|
|||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div id="status_Playlists" class="status">0 song(s), 00:00:00 total time</div>
|
||||
</div>
|
||||
<div id="tabPodcasts" class="tabcontent">
|
||||
<div class="actions floatleft">
|
||||
|
@ -154,7 +158,7 @@
|
|||
<div class="subactions floatleft">
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
<div id="Podcasts" class="lgsection floatleft noselect">
|
||||
<div id="Podcasts" class="section lgsection floatleft noselect">
|
||||
<div class="loading"></div>
|
||||
<div id="PodcastList" class="smsection floatleft noselect">
|
||||
<div class="padder">
|
||||
|
@ -167,6 +171,7 @@
|
|||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div id="status_Podcasts" class="status">0 song(s), 00:00:00 total time</div>
|
||||
</div>
|
||||
<div id="tabPreferences" class="tabcontent">
|
||||
<div class="actions floatleft">
|
||||
|
@ -174,7 +179,7 @@
|
|||
<a href="#" class="button" id="SavePreferences" title="Save Preferences">Save</a>
|
||||
</div>
|
||||
<div class="clear"></div>
|
||||
<div class="lgsection floatleft">
|
||||
<div class="section lgsection floatleft">
|
||||
<div class="subsection floatleft">
|
||||
<h3 class="title">Login</h3>
|
||||
<label for="Username">Username <span class="red">*</span></label><br />
|
||||
|
@ -272,10 +277,15 @@
|
|||
<span class="changes">- </span>
|
||||
</li>
|
||||
-->
|
||||
<li class="log"><span class="version">10/15/2012 - 2.2.0</span>
|
||||
<span class="changes">- Column sorting for all headers in all tables! (Thanks to <a href="https://github.com/joequery/Stupid-Table-Plugin" target="_blank">joequery</a>)</span>
|
||||
<span class="changes">- Fancy Webkit styled scrollbars for those of you with browsers that don't suck (Works with Dark theme)</span>
|
||||
<span class="changes">- Auto Albums feature Next & Previous links to page through results</span>
|
||||
<span class="changes">- Forced to include permissions ("http://*/*" & "https://*/*"). Your Subsonic server can be at any URL. Will be asked to accept "Access your data on all websites".</span>
|
||||
</li>
|
||||
<li class="log"><span class="version">10/8/2012 - 2.1.5</span>
|
||||
<span class="changes">- Added song count and total time to Current Playlist</span>
|
||||
<span class="changes">- Migrated to version 2 of Chrome App manifest.json</span>
|
||||
<span class="changes">- Added to manifest.json > "content_security_policy": "script-src 'self' https://*/; object-src 'self'"</span>
|
||||
</li>
|
||||
<li class="log"><span class="version">10/7/2012 - 2.1.2</span>
|
||||
<span class="changes">- Current Playlist will stay focused on the current track (Thanks <a href="https://github.com/tsquillario/MiniSub/issues/42" target="_blank">Concept211</a>)</span>
|
||||
|
|
19
js/app.js
19
js/app.js
|
@ -10,6 +10,7 @@ var passwordenc;
|
|||
var server;
|
||||
var smwidth;
|
||||
var volume = 50;
|
||||
var currentVersion = '2.2.0';
|
||||
|
||||
function getCookie(value) {
|
||||
if ($.cookie(value)) {
|
||||
|
@ -96,6 +97,9 @@ if (getCookie('password')) {
|
|||
setCookie('passwordenc', 'enc:' + HexEncode(getCookie('password')));
|
||||
setCookie('password', null);
|
||||
}
|
||||
if (getCookie('Volume')) {
|
||||
volume = parseInt(getCookie('Volume'));
|
||||
}
|
||||
var version = '1.6.0';
|
||||
|
||||
function loadTabContent(tab) {
|
||||
|
@ -113,19 +117,28 @@ function loadTabContent(tab) {
|
|||
case '#tabCurrent':
|
||||
if (debug) { console.log("TAG CURRENT"); }
|
||||
var header = generateSongHeaderHTML();
|
||||
$("#CurrentPlaylistContainer thead").html(header);
|
||||
window.location.hash = '#tabCurrent';
|
||||
updateStatus(countCurrentPlaylist('#CurrentPlaylistContainer'));
|
||||
$('#CurrentPlaylistContainer thead').html(header);
|
||||
var count = $('#CurrentPlaylistContainer tbody tr.song').size();
|
||||
updateStatus('#status_Current', countCurrentPlaylist('#CurrentPlaylistContainer'));
|
||||
if (count > 0) {
|
||||
$('#currentActions a.button').removeClass('disabled');
|
||||
}
|
||||
var songid = $('#CurrentPlaylistContainer tbody tr.playing').attr('childid');
|
||||
if (songid !== undefined) {
|
||||
$('#CurrentPlaylist').scrollTo($('#' + songid), 400);
|
||||
}
|
||||
break;
|
||||
case '#tabPlaylists':
|
||||
if (debug) { console.log("TAG PLAYLIST"); }
|
||||
loadPlaylists();
|
||||
loadFolders();
|
||||
loadAutoPlaylists();
|
||||
updateStatus('#status_Playlists', countCurrentPlaylist('#TrackContainer'));
|
||||
break;
|
||||
case '#tabPodcasts':
|
||||
if (debug) { console.log("TAG PODCAST"); }
|
||||
loadPodcasts();
|
||||
updateStatus('#status_Podcasts', countCurrentPlaylist('#PodcastContainer'));
|
||||
break;
|
||||
case '#tabVideos':
|
||||
if (debug) { console.log("TAG VIDEOS"); }
|
||||
|
|
262
js/libs/api.js
262
js/libs/api.js
|
@ -81,7 +81,7 @@ function loadArtists(id, refresh) {
|
|||
} else {
|
||||
indexes[0] = data["subsonic-response"].indexes.child;
|
||||
}
|
||||
var appendto = '#AlbumRows';
|
||||
var appendto = '#AlbumContainer tbody';
|
||||
$(appendto).empty();
|
||||
$.each(indexes, function (i, child) {
|
||||
if (i % 2 === 0) {
|
||||
|
@ -102,8 +102,6 @@ function loadArtists(id, refresh) {
|
|||
var errorcode = data["subsonic-response"].error.code;
|
||||
var errormsg = data["subsonic-response"].error.message;
|
||||
alert('Status: ' + error + ', Code: ' + errorcode + ', Message: ' + errormsg);
|
||||
//var errorhtml = '<li class=\"item\"><span>' + error + '</span></li>';
|
||||
//$(errorhtml).appendTo("#IndexList");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@ -187,13 +185,13 @@ function getAlbums(id, action, appendto) {
|
|||
timeout: 10000,
|
||||
success: function (data) {
|
||||
if (action == '') {
|
||||
$('#AlbumRows').empty();
|
||||
$('#AlbumContainer tbody').empty();
|
||||
}
|
||||
if (action === 'autoplay') {
|
||||
$('#CurrentPlaylistContainer tbody').empty();
|
||||
}
|
||||
if (action == 'link') {
|
||||
$('#AlbumRows').empty();
|
||||
$('#AlbumContainer tbody').empty();
|
||||
$('#action_tabLibrary').trigger('click');
|
||||
}
|
||||
if (data["subsonic-response"].directory.child !== undefined) {
|
||||
|
@ -216,18 +214,21 @@ function getAlbums(id, action, appendto) {
|
|||
}
|
||||
if (child.isDir == true) { isDir = true; }
|
||||
var html = generateRowHTML(child, appendto, rowcolor);
|
||||
$(html).appendTo(appendto);
|
||||
$(html).appendTo(appendto).hide().fadeIn('fast');
|
||||
});
|
||||
toggleAlbumListNextPrev('#status_Library', false, '', '');
|
||||
if (appendto == '#CurrentPlaylistContainer') {
|
||||
updateMessage(children.length + ' Song(s) Added');
|
||||
}
|
||||
if (appendto == '#AlbumRows' && isDir == true) {
|
||||
if (appendto == '#AlbumContainer tbody' && isDir == true) {
|
||||
header = generateAlbumHeaderHTML();
|
||||
$('#songActions a.button').addClass('disabled');
|
||||
}
|
||||
if (appendto == '#AlbumRows' && isDir == false) {
|
||||
if (appendto == '#AlbumContainer tbody' && isDir == false) {
|
||||
header = generateSongHeaderHTML();
|
||||
$('#songActions a.button').removeClass('disabled');
|
||||
}
|
||||
$("#AlbumHeader").html(header);
|
||||
$("#AlbumContainer thead").html(header);
|
||||
if (action == 'autoplay') {
|
||||
autoPlay();
|
||||
}
|
||||
|
@ -235,23 +236,28 @@ function getAlbums(id, action, appendto) {
|
|||
}
|
||||
});
|
||||
}
|
||||
function getAlbumListBy(id) {
|
||||
var size;
|
||||
if (getCookie('AutoAlbumSize') === null) {
|
||||
size = 15;
|
||||
} else {
|
||||
function getAlbumListBy(id, offset) {
|
||||
var size, url;
|
||||
if (getCookie('AutoAlbumSize')) {
|
||||
size = getCookie('AutoAlbumSize');
|
||||
} else {
|
||||
size = 15;
|
||||
}
|
||||
if (offset > 0) {
|
||||
url = baseURL + '/getAlbumList.view?u=' + username + '&p=' + password + '&v=' + version + '&c=' + applicationName + '&f=json&size=' + size + '&type=' + id + '&offset=' + offset
|
||||
} else {
|
||||
url = baseURL + '/getAlbumList.view?u=' + username + '&p=' + password + '&v=' + version + '&c=' + applicationName + '&f=json&size=' + size + '&type=' + id
|
||||
}
|
||||
$.ajax({
|
||||
url: baseURL + '/getAlbumList.view?u=' + username + '&p=' + password + '&v=' + version + '&c=' + applicationName + '&f=json&size=' + size + '&type=' + id,
|
||||
url: url,
|
||||
method: 'GET',
|
||||
dataType: 'json',
|
||||
timeout: 10000,
|
||||
success: function (data) {
|
||||
if (data["subsonic-response"].albumList.album !== undefined) {
|
||||
$("#AlbumRows").empty();
|
||||
$("#AlbumContainer tbody").empty();
|
||||
var header = generateAlbumHeaderHTML();
|
||||
$("#AlbumHeader").html(header);
|
||||
$("#AlbumContainer thead").html(header);
|
||||
// There is a bug in the API that doesn't return a JSON array for one artist
|
||||
var albums = [];
|
||||
if (data["subsonic-response"].albumList.album.length > 0) {
|
||||
|
@ -274,14 +280,34 @@ function getAlbumListBy(id) {
|
|||
if (album.isDir === true) {
|
||||
albumhtml = generateAlbumHTML(rowcolor, album.id, album.parent, album.coverArt, album.title, album.artist, album.userRating, starred);
|
||||
}
|
||||
$(albumhtml).appendTo("#AlbumRows");
|
||||
$(albumhtml).appendTo("#AlbumContainer tbody").hide().fadeIn('fast');
|
||||
});
|
||||
$('#songActions a.button').addClass('disabled');
|
||||
toggleAlbumListNextPrev('#status_Library', true, id, offset);
|
||||
} else {
|
||||
$('#AlbumRows').empty();
|
||||
$('#AlbumContainer tbody').empty();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function toggleAlbumListNextPrev(el, on, type, offset) {
|
||||
if (el != '') {
|
||||
if (on) {
|
||||
$(el).addClass('on');
|
||||
$('#status_Library').data('type', type);
|
||||
if (offset === undefined) {
|
||||
$('#status_Library').data('offset', '0');
|
||||
} else {
|
||||
$('#status_Library').data('offset', offset);
|
||||
}
|
||||
} else {
|
||||
$(el).removeClass('on');
|
||||
$(el).stop().fadeOut();
|
||||
$('#status_Library').data('type', '');
|
||||
$('#status_Library').data('offset', '0');
|
||||
}
|
||||
}
|
||||
}
|
||||
function getRandomSongList(action, appendto, genre, folder) {
|
||||
var size, gstring;
|
||||
gstring = '';
|
||||
|
@ -342,7 +368,7 @@ function getRandomSongList(action, appendto, genre, folder) {
|
|||
$(html).appendTo(appendto);
|
||||
});
|
||||
if (appendto === '#TrackContainer tbody') {
|
||||
updateMessage(countCurrentPlaylist('#TrackContainer'));
|
||||
updateStatus('#status_Playlists', countCurrentPlaylist('#TrackContainer'));
|
||||
}
|
||||
if (appendto === '#CurrentPlaylistContainer tbody') {
|
||||
updateMessage(items.length + ' Song(s) Added');
|
||||
|
@ -443,7 +469,7 @@ function getStarred(action, appendto, type) {
|
|||
$(html).appendTo(appendto);
|
||||
});
|
||||
if (appendto == '#TrackContainer tbody') {
|
||||
updateMessage(countCurrentPlaylist('#TrackContainer'));
|
||||
updateStatus('#status_Playlists', countCurrentPlaylist('#TrackContainer'));
|
||||
}
|
||||
if (appendto == '#CurrentPlaylistContainer tbody') {
|
||||
updateMessage(items.length + ' Song(s) Added');
|
||||
|
@ -526,31 +552,32 @@ function search(type, query) {
|
|||
dataType: 'json',
|
||||
timeout: 10000,
|
||||
success: function (data) {
|
||||
$("#AlbumContainer tbody").empty();
|
||||
if (data["subsonic-response"].searchResult2 !== "") {
|
||||
$("#AlbumRows").empty();
|
||||
var header;
|
||||
var children = [];
|
||||
if (type === 'song') {
|
||||
header = generateSongHeaderHTML();
|
||||
if (data["subsonic-response"].searchResult2.song !== undefined) {
|
||||
header = generateSongHeaderHTML();
|
||||
if (data["subsonic-response"].searchResult2.song.length > 0) {
|
||||
children = data["subsonic-response"].searchResult2.song;
|
||||
} else {
|
||||
children[0] = data["subsonic-response"].searchResult2.song;
|
||||
}
|
||||
$("#AlbumContainer thead").html(header);
|
||||
}
|
||||
}
|
||||
if (type === 'album') {
|
||||
header = generateAlbumHeaderHTML();
|
||||
if (data["subsonic-response"].searchResult2.album !== undefined) {
|
||||
header = generateAlbumHeaderHTML();
|
||||
if (data["subsonic-response"].searchResult2.album.length > 0) {
|
||||
children = data["subsonic-response"].searchResult2.album;
|
||||
} else {
|
||||
children[0] = data["subsonic-response"].searchResult2.album;
|
||||
}
|
||||
$("#AlbumContainer thead").html(header);
|
||||
}
|
||||
}
|
||||
$("#AlbumHeader").html(header);
|
||||
$.each(children, function (i, child) {
|
||||
if (i % 2 === 0) {
|
||||
rowcolor = 'even';
|
||||
|
@ -569,7 +596,7 @@ function search(type, query) {
|
|||
if (child.duration !== undefined) { duration = child.duration; } else { duration = ''; }
|
||||
albumhtml = generateSongHTML(rowcolor, child.id, child.parent, track, child.title, '', child.artist, child.album, child.coverArt, child.userRating, starred, duration);
|
||||
}
|
||||
$(albumhtml).appendTo("#AlbumRows");
|
||||
$(albumhtml).appendTo("#AlbumContainer tbody");
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -648,6 +675,84 @@ function loadPlaylists(refresh) {
|
|||
});
|
||||
}
|
||||
}
|
||||
function savePlaylist(playlistid) {
|
||||
var songs = [];
|
||||
$('#TrackContainer tr.song').each(function (index) {
|
||||
songs.push($(this).attr('childid'));
|
||||
});
|
||||
if (songs.length > 0) {
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: baseURL + '/createPlaylist.view?u=' + username + '&p=' + password,
|
||||
dataType: 'json',
|
||||
timeout: 10000,
|
||||
data: { v: version, c: applicationName, f: "json", playlistId: playlistid, songId: songs },
|
||||
success: function () {
|
||||
getPlaylist(playlistid);
|
||||
updateMessage('Playlist Updated!');
|
||||
},
|
||||
traditional: true // Fixes POST with an array in JQuery 1.4
|
||||
});
|
||||
}
|
||||
}
|
||||
function getPlaylist(id, action, appendto) {
|
||||
$.ajax({
|
||||
url: baseURL + '/getPlaylist.view?u=' + username + '&p=' + password + '&v=' + version + '&c=' + applicationName + '&f=json&id=' + id,
|
||||
method: 'GET',
|
||||
dataType: 'json',
|
||||
timeout: 10000,
|
||||
success: function (data) {
|
||||
if (data["subsonic-response"].playlist.entry !== undefined) {
|
||||
if (appendto === '#TrackContainer tbody') {
|
||||
$(appendto).empty();
|
||||
var header = generateSongHeaderHTML();
|
||||
$("#TrackContainer thead").html(header);
|
||||
}
|
||||
if (action === 'autoplay') {
|
||||
$(appendto).empty();
|
||||
}
|
||||
// There is a bug in the API that doesn't return a JSON array for one artist
|
||||
var children = [];
|
||||
var playlist = data["subsonic-response"].playlist;
|
||||
if (playlist.entry.length > 0) {
|
||||
children = playlist.entry;
|
||||
} else {
|
||||
children[0] = playlist.entry;
|
||||
}
|
||||
|
||||
var rowcolor;
|
||||
var html;
|
||||
var count = children.length;
|
||||
$.each(children, function (i, child) {
|
||||
if (i % 2 === 0) {
|
||||
rowcolor = 'even';
|
||||
} else {
|
||||
rowcolor = 'odd';
|
||||
}
|
||||
var track, starred, duration;
|
||||
if (child.starred !== undefined) { starred = true; } else { starred = false; }
|
||||
if (child.track === undefined) { track = " "; } else { track = child.track; }
|
||||
if (child.duration !== undefined) { duration = child.duration; } else { duration = ''; }
|
||||
html = generateSongHTML(rowcolor, child.id, child.parent, track, child.title, '', child.artist, child.album, child.coverArt, child.userRating, starred, duration);
|
||||
$(html).appendTo(appendto);
|
||||
});
|
||||
if (appendto === '#TrackContainer tbody') {
|
||||
updateStatus('#status_Playlists', countCurrentPlaylist('#TrackContainer'));
|
||||
}
|
||||
if (appendto === '#CurrentPlaylistContainer tbody') {
|
||||
updateMessage(children.length + ' Song(s) Added');
|
||||
}
|
||||
if (action === 'autoplay') {
|
||||
autoPlay();
|
||||
}
|
||||
} else {
|
||||
if (appendto === '#TrackContainer tbody') {
|
||||
$(appendto).empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function loadPlaylistsForMenu(menu) {
|
||||
$('#' + menu).empty();
|
||||
$.ajax({
|
||||
|
@ -814,6 +919,7 @@ function addToCurrent(addAll) {
|
|||
$(this).clone().appendTo('#CurrentPlaylistContainer tbody');
|
||||
});
|
||||
}
|
||||
$('#CurrentPlaylistContainer tbody tr.song').removeClass('selected');
|
||||
updateMessage(count + ' Song(s) Added');
|
||||
}
|
||||
}
|
||||
|
@ -870,6 +976,25 @@ function loadCurrentPlaylist() {
|
|||
if (debug) { console.log('HTML5::loadStorage not supported on your browser' + html.length + ' characters'); }
|
||||
}
|
||||
}
|
||||
function saveTrackPosition() {
|
||||
var el = $('#songdetails_song');
|
||||
var songid = el.attr('childid');
|
||||
if (songid !== undefined) {
|
||||
var albumid = el.attr('parentid');
|
||||
var sm = soundManager.getSoundById('audio');
|
||||
var position = sm.position;
|
||||
if (position != null && position >= 5000) {
|
||||
var currentSong = {
|
||||
songid: songid,
|
||||
albumid: albumid,
|
||||
position: position
|
||||
};
|
||||
setCookie('CurrentSong', JSON.stringify(currentSong));
|
||||
saveCurrentPlaylist();
|
||||
}
|
||||
}
|
||||
if (debug) { console.log('Saving Track Position: songid:' + songid + ', albumid:' + albumid + ', position:' + position); }
|
||||
}
|
||||
function downloadItem(id, type) {
|
||||
var url;
|
||||
if (type == 'item' && id) {
|
||||
|
@ -883,84 +1008,7 @@ function downloadItem(id, type) {
|
|||
window.location = url;
|
||||
}
|
||||
}
|
||||
function savePlaylist(playlistid) {
|
||||
var songs = [];
|
||||
$('#TrackContainer tr.song').each(function (index) {
|
||||
songs.push($(this).attr('childid'));
|
||||
});
|
||||
if (songs.length > 0) {
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: baseURL + '/createPlaylist.view?u=' + username + '&p=' + password,
|
||||
dataType: 'json',
|
||||
timeout: 10000,
|
||||
data: { v: version, c: applicationName, f: "json", playlistId: playlistid, songId: songs },
|
||||
success: function () {
|
||||
getPlaylist(playlistid);
|
||||
updateMessage('Playlist Updated!');
|
||||
},
|
||||
traditional: true // Fixes POST with an array in JQuery 1.4
|
||||
});
|
||||
}
|
||||
}
|
||||
function getPlaylist(id, action, appendto) {
|
||||
$.ajax({
|
||||
url: baseURL + '/getPlaylist.view?u=' + username + '&p=' + password + '&v=' + version + '&c=' + applicationName + '&f=json&id=' + id,
|
||||
method: 'GET',
|
||||
dataType: 'json',
|
||||
timeout: 10000,
|
||||
success: function (data) {
|
||||
if (data["subsonic-response"].playlist.entry !== undefined) {
|
||||
if (appendto === '#TrackContainer tbody') {
|
||||
$(appendto).empty();
|
||||
var header = generateSongHeaderHTML();
|
||||
$("#TrackContainer thead").html(header);
|
||||
}
|
||||
if (action === 'autoplay') {
|
||||
$(appendto).empty();
|
||||
}
|
||||
// There is a bug in the API that doesn't return a JSON array for one artist
|
||||
var children = [];
|
||||
var playlist = data["subsonic-response"].playlist;
|
||||
if (playlist.entry.length > 0) {
|
||||
children = playlist.entry;
|
||||
} else {
|
||||
children[0] = playlist.entry;
|
||||
}
|
||||
|
||||
var rowcolor;
|
||||
var html;
|
||||
var count = children.length;
|
||||
$.each(children, function (i, child) {
|
||||
if (i % 2 === 0) {
|
||||
rowcolor = 'even';
|
||||
} else {
|
||||
rowcolor = 'odd';
|
||||
}
|
||||
var track, starred, duration;
|
||||
if (child.starred !== undefined) { starred = true; } else { starred = false; }
|
||||
if (child.track === undefined) { track = " "; } else { track = child.track; }
|
||||
if (child.duration !== undefined) { duration = child.duration; } else { duration = ''; }
|
||||
html = generateSongHTML(rowcolor, child.id, child.parent, track, child.title, '', child.artist, child.album, child.coverArt, child.userRating, starred, duration);
|
||||
$(html).appendTo(appendto);
|
||||
});
|
||||
if (appendto === '#TrackContainer tbody') {
|
||||
updateMessage(countCurrentPlaylist('#TrackContainer'));
|
||||
}
|
||||
if (appendto === '#CurrentPlaylistContainer tbody') {
|
||||
updateMessage(children.length + ' Song(s) Added');
|
||||
}
|
||||
if (action === 'autoplay') {
|
||||
autoPlay();
|
||||
}
|
||||
} else {
|
||||
if (appendto === '#TrackContainer tbody') {
|
||||
$(appendto).empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadPodcasts(refresh) {
|
||||
if (debug) { console.log("LOAD PODCASTS"); }
|
||||
|
@ -1040,7 +1088,6 @@ function getPodcast(id, action, appendto) {
|
|||
var count = 0;
|
||||
$.each(children, function (i, child) {
|
||||
if (child.status == "skipped") return; // Skip podcasts that are not yet downloaded
|
||||
|
||||
if (i % 2 === 0) {
|
||||
rowcolor = 'even';
|
||||
} else {
|
||||
|
@ -1050,16 +1097,17 @@ function getPodcast(id, action, appendto) {
|
|||
var description = 'Published: ' + date + '\n\n';
|
||||
description += child.description;
|
||||
|
||||
var starred, duration;
|
||||
var starred, duration, publishdate;
|
||||
if (child.starred !== undefined) { starred = true; } else { starred = false; }
|
||||
if (child.duration !== undefined) { duration = child.duration; } else { duration = ''; }
|
||||
if (child.publishDate !== undefined) { publishdate = child.publishDate.substring(0, child.publishDate.indexOf(" ")); } else { publishdate = ''; }
|
||||
var time = secondsToTime(child.duration);
|
||||
html = generateSongHTML(rowcolor, child.streamId, child.parent, child.track, child.title, description, child.artist, child.album, child.coverArt, child.userRating, starred, duration);
|
||||
html = generateSongHTML(rowcolor, child.streamId, child.parent, publishdate, child.title, description, child.artist, child.album, child.coverArt, child.userRating, starred, duration);
|
||||
$(html).appendTo(appendto);
|
||||
count++;
|
||||
});
|
||||
if (appendto === '#PodcastContainer tbody') {
|
||||
updateMessage(count + ' Song(s)');
|
||||
updateStatus('#status_Podcasts', countCurrentPlaylist('#PodcastContainer'));
|
||||
}
|
||||
if (appendto === '#CurrentPlaylistContainer tbody') {
|
||||
updateMessage(count + ' Song(s) Added');
|
||||
|
|
|
@ -14,7 +14,7 @@ function generateRowHTML(child, appendto, rowcolor) {
|
|||
}
|
||||
function generateAlbumHeaderHTML() {
|
||||
var html;
|
||||
html = '<tr><th></th><th></th><th>Album</th><th>Artist</th></tr>';
|
||||
html = '<tr><th></th><th></th><th class=\"type-string\">Album</th><th class=\"type-string\">Artist</th></tr>';
|
||||
return html;
|
||||
}
|
||||
function generateAlbumHTML(rowcolor, childid, parentid, coverart, title, artist, rating, starred) {
|
||||
|
@ -41,7 +41,7 @@ function generateAlbumHTML(rowcolor, childid, parentid, coverart, title, artist,
|
|||
}
|
||||
function generateSongHeaderHTML() {
|
||||
var html;
|
||||
html = '<tr><th></th><th>Track</th><th>Title</th><th>Artist</th><th>Album</th><th class=\"alignright\">Time</th></tr>';
|
||||
html = '<tr><th></th><th class=\"type-int\">Track</th><th class=\"type-string\">Title</th><th class=\"type-string\">Artist</th><th class=\"type-string\">Album</th><th class=\"alignright\">Time</th></tr>';
|
||||
return html;
|
||||
}
|
||||
function generateSongHTML(rowcolor, childid, parentid, track, title, description, artist, album, coverart, rating, starred, duration) {
|
||||
|
@ -76,11 +76,12 @@ function generateSongHTML(rowcolor, childid, parentid, track, title, description
|
|||
} else {
|
||||
coverartSrc = baseURL + '/getCoverArt.view?v=' + version + '&c=' + applicationName + '&f=json&size=25&id=' + coverart;
|
||||
}
|
||||
html += '<td class=\"album\"><a href="#" class=\"albumlink\"><img src=\"' + coverartSrc + '\" />' + album + '</a></td>';
|
||||
html += '<td class=\"album\" data-order-by=\"' + album + '\"><a href="#" class=\"albumlink\"><img src=\"' + coverartSrc + '\" />' + album + '</a></td>';
|
||||
html += '<td class=\"time\">' + time + '</td>';
|
||||
html += '</tr>';
|
||||
return html;
|
||||
}
|
||||
// Depreciated: 10/17/2012
|
||||
function refreshRowColor(el) {
|
||||
$.each($(el + ' tr.song'), function (i) {
|
||||
$(this).removeClass('even odd');
|
||||
|
|
|
@ -19,7 +19,7 @@ function playSong(el, songid, albumid, position, loadonly) {
|
|||
}
|
||||
$.each(children, function (i, child) {
|
||||
if (child.id == songid) {
|
||||
title = child.title;
|
||||
title = child.title.toString();
|
||||
artist = child.artist;
|
||||
album = child.album;
|
||||
coverart = child.coverArt;
|
||||
|
@ -67,6 +67,7 @@ function playSong(el, songid, albumid, position, loadonly) {
|
|||
url: baseURL + '/stream.view?u=' + username + '&p=' + password + '&v=' + version + '&c=' + applicationName + '&id=' + songid + '&salt=' + salt,
|
||||
stream: true,
|
||||
type: 'audio/mp3',
|
||||
multiShot: false,
|
||||
whileloading: function () {
|
||||
//if (debug) { console.log('loaded:' + this.bytesLoaded + ' total:' + this.bytesTotal); }
|
||||
var percent = this.bytesLoaded / this.bytesTotal;
|
||||
|
@ -105,9 +106,8 @@ function playSong(el, songid, albumid, position, loadonly) {
|
|||
scrubber.click(function (e) {
|
||||
var x = (e.pageX - this.offsetLeft) / scrubber.width();
|
||||
var position = Math.round(dp * 1000 * x);
|
||||
soundManager.play('audio', {
|
||||
position: position
|
||||
});
|
||||
var s = soundManager.getSoundById('audio');
|
||||
s.setPosition(position);
|
||||
});
|
||||
scrubber.mouseover(function (e) {
|
||||
$('.audiojs .scrubber').stop().animate({ height: '8px' });
|
||||
|
@ -141,10 +141,11 @@ function playSong(el, songid, albumid, position, loadonly) {
|
|||
});
|
||||
if (position == 0) {
|
||||
soundManager.play('audio');
|
||||
soundManager.setVolume('audio', volume);
|
||||
} else {
|
||||
var p = position;
|
||||
//soundManager.play('audio', { position: p });
|
||||
seekAndPlay('audio', p);
|
||||
soundManager.setVolume('audio', volume);
|
||||
}
|
||||
var submenu = $('div#submenu_CurrentPlaylist');
|
||||
if (submenu.is(":visible")) {
|
||||
|
@ -175,9 +176,8 @@ function playSong(el, songid, albumid, position, loadonly) {
|
|||
}
|
||||
function seekAndPlay(soundID, soundPosition) {
|
||||
var s = soundManager.getSoundById(soundID);
|
||||
if (!s) {
|
||||
return false;
|
||||
}
|
||||
if (s) {
|
||||
s.unload();
|
||||
if (s.readyState === 0) { // hasn't started loading yet...
|
||||
// load the whole sound, and play when it's done
|
||||
s.load({
|
||||
|
@ -193,6 +193,7 @@ function seekAndPlay(soundID, soundPosition) {
|
|||
position: soundPosition
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
function scrobbleSong(submission) {
|
||||
var songid = $('#songdetails_song').attr('childid');
|
||||
|
@ -320,22 +321,3 @@ function nextPlay() {
|
|||
//song = $('#CurrentPlaylistContainer tr.playing').next();
|
||||
}
|
||||
}
|
||||
function saveTrackPosition() {
|
||||
var el = $('#songdetails_song');
|
||||
var songid = el.attr('childid');
|
||||
if (songid !== undefined) {
|
||||
var albumid = el.attr('parentid');
|
||||
var sm = soundManager.getSoundById('audio');
|
||||
var position = sm.position;
|
||||
if (position != null && position >= 5000) {
|
||||
var currentSong = {
|
||||
songid: songid,
|
||||
albumid: albumid,
|
||||
position: position
|
||||
};
|
||||
setCookie('CurrentSong', JSON.stringify(currentSong));
|
||||
saveCurrentPlaylist();
|
||||
}
|
||||
}
|
||||
if (debug) { console.log('Saving Track Position: songid:' + songid + ', albumid:' + albumid + ', position:' + position); }
|
||||
}
|
|
@ -112,12 +112,15 @@ function updateMessage(msg) {
|
|||
msgIndex++;
|
||||
}
|
||||
}
|
||||
function updateStatus(msg) {
|
||||
$('#status').html(msg);
|
||||
if ($('#tabLibrary').not(':visible')) {
|
||||
if ($('#status').html() != '') {
|
||||
$('#status').fadeIn();
|
||||
function updateStatus(el, msg) {
|
||||
if (msg == '') {
|
||||
$(el).html('0 song(s), 00:00:00 total time');
|
||||
} else {
|
||||
$(el).html(msg);
|
||||
}
|
||||
if ($(el).html() != '') {
|
||||
$(el).addClass('on');
|
||||
$(el).fadeIn();
|
||||
}
|
||||
}
|
||||
// Convert to unicode support
|
||||
|
@ -254,6 +257,21 @@ function checkVersion(runningVersion, minimumVersion) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
function checkVersionNewer(runningVersion, newVersion) {
|
||||
if (runningVersion.major < newVersion.major) {
|
||||
return true;
|
||||
} else {
|
||||
if (runningVersion.minor < newVersion.minor) {
|
||||
return true;
|
||||
} else {
|
||||
if (runningVersion.patch < newVersion.patch) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function switchTheme(theme) {
|
||||
switch (theme) {
|
||||
case 'dark':
|
||||
|
|
141
js/plugins/jquery.stupidtable.js
Normal file
141
js/plugins/jquery.stupidtable.js
Normal file
|
@ -0,0 +1,141 @@
|
|||
// Stupid jQuery table plugin.
|
||||
|
||||
// Call on a table
|
||||
// sortFns: Sort functions for your datatypes.
|
||||
(function ($) {
|
||||
$.fn.stupidtable = function (sortFns) {
|
||||
var table = this; sortFns = sortFns || {};
|
||||
|
||||
// ==================================================== //
|
||||
// Utility functions //
|
||||
// ==================================================== //
|
||||
|
||||
// Merge sort functions with some default sort functions.
|
||||
sortFns = $.extend({}, {
|
||||
"int": function (a, b) { return parseInt(a, 10) - parseInt(b, 10); },
|
||||
"float": function (a, b) { return parseFloat(a) - parseFloat(b); },
|
||||
"string": function (a, b) { if (a < b) return -1; if (a > b) return +1; return 0; }
|
||||
}, sortFns);
|
||||
|
||||
// Array comparison. See http://stackoverflow.com/a/8618383
|
||||
var arrays_equal = function (a, b) { return !!a && !!b && !(a < b || b < a); }
|
||||
|
||||
// Return the resulting indexes of a sort so we can apply
|
||||
// this result elsewhere. This returns an array of index numbers.
|
||||
// return[0] = x means "arr's 0th element is now at x"
|
||||
var sort_map = function (arr, sort_function) {
|
||||
var sorted = arr.slice(0).sort(sort_function);
|
||||
var map = [];
|
||||
var index = 0;
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
index = $.inArray(arr[i], sorted);
|
||||
|
||||
// If this index is already in the map, look for the next index.
|
||||
// This handles the case of duplicate entries.
|
||||
while ($.inArray(index, map) != -1) {
|
||||
index++;
|
||||
}
|
||||
map.push(index);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
// Apply a sort map to the array.
|
||||
var apply_sort_map = function (arr, map) {
|
||||
var clone = arr.slice(0);
|
||||
for (var i = 0; i < map.length; i++) {
|
||||
newIndex = map[i];
|
||||
clone[newIndex] = arr[i];
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
// Returns true if array is sorted, false otherwise.
|
||||
// Checks for both ascending and descending
|
||||
var is_sorted_array = function (arr, sort_function) {
|
||||
var clone = arr.slice(0);
|
||||
var reversed = arr.slice(0).reverse();
|
||||
var sorted = arr.slice(0).sort(sort_function);
|
||||
|
||||
// Check if the array is sorted in either direction.
|
||||
return arrays_equal(clone, sorted) || arrays_equal(reversed, sorted);
|
||||
}
|
||||
|
||||
// ==================================================== //
|
||||
// Begin execution! //
|
||||
// ==================================================== //
|
||||
// Do sorting when THs are clicked
|
||||
table.delegate("th", "click", function () {
|
||||
var trs = table.find("tbody tr");
|
||||
var i = $(this).index();
|
||||
var classes = $(this).attr("class");
|
||||
var type = null;
|
||||
var sort = {
|
||||
asc: 'ascending',
|
||||
desc: 'descending'
|
||||
};
|
||||
var direction = sort.asc;
|
||||
var total = trs.length;
|
||||
|
||||
if (total > 0) {
|
||||
if (classes) {
|
||||
classes = classes.split(/\s+/);
|
||||
|
||||
for (var j = 0; j < classes.length; j++) {
|
||||
if (classes[j].search("type-") != -1) {
|
||||
type = classes[j];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (type) {
|
||||
type = type.split('-')[1];
|
||||
}
|
||||
}
|
||||
if (type) {
|
||||
table.find('th').removeClass('sorted');
|
||||
var sortMethod = sortFns[type];
|
||||
|
||||
// Gather the elements for this column
|
||||
column = [];
|
||||
|
||||
// Push either the value of the 'data-order-by' attribute if specified
|
||||
// or just the text() value in this column to column[] for comparison.
|
||||
trs.each(function (index, tr) {
|
||||
var e = $(tr).children().eq(i);
|
||||
var order_by = e.attr('data-order-by') || e.text();
|
||||
column.push(order_by);
|
||||
});
|
||||
|
||||
// If the column is already sorted, just reverse the order. The sort
|
||||
// map is just reversing the indexes.
|
||||
if (is_sorted_array(column, sortMethod)) {
|
||||
if ($(this).hasClass(sort.desc)) {
|
||||
direction = sort.asc;
|
||||
} else {
|
||||
direction = sort.desc
|
||||
}
|
||||
table.find('th').removeClass(sort.asc + ' ' + sort.desc);
|
||||
column.reverse();
|
||||
var theMap = [];
|
||||
for (var i = column.length - 1; i >= 0; i--) {
|
||||
theMap.push(i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
direction = sort.asc;
|
||||
// Get a sort map and apply to all rows
|
||||
theMap = sort_map(column, sortMethod);
|
||||
}
|
||||
|
||||
var sortedTRs = $(apply_sort_map(trs, theMap));
|
||||
|
||||
// Replace the content of tbody with the sortedTRs. Strangely (and
|
||||
// conveniently!) enough, .append accomplishes this for us.
|
||||
table.find("tbody").append(sortedTRs);
|
||||
$(this).addClass('sorted');
|
||||
$(this).addClass(direction);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
})(jQuery);
|
|
@ -63,7 +63,7 @@ function resizeContent() {
|
|||
}
|
||||
}
|
||||
var tabwidth = $('.tabcontent').width();
|
||||
$('#AlbumContainer, #TrackContainer, #PodcastContainer, #CurrentPlaylistContainer').css({ 'width': (tabwidth - smwidth - 40) + 'px' });
|
||||
$('#AlbumContainer, #TrackContainer, #PodcastContainer, #CurrentPlaylistContainer').css({ 'width': (tabwidth - smwidth - 45) + 'px' });
|
||||
$('#CurrentPlaylistContainer').css({ 'width': (tabwidth - 30) + 'px' });
|
||||
$('#player').css({ 'width': tabwidth + 'px' });
|
||||
}
|
||||
|
@ -78,6 +78,6 @@ function resizeSMSection(x) {
|
|||
$('#BottomContainer').css({ 'width': (newsmwidth - 23) + 'px' });
|
||||
setCookie('defaultsmwidth', newwidth);
|
||||
var ulwidth = newsmwidth + 6;
|
||||
$('#AlbumContainer, #TrackContainer, #PodcastContainer').css({ 'margin-left': ulwidth + 'px' });
|
||||
$('#AlbumContainer, #TrackContainer, #PodcastContainer').css({ 'margin-left': (ulwidth + 15) + 'px' });
|
||||
}
|
||||
}
|
||||
|
|
136
js/ui-ready.js
136
js/ui-ready.js
|
@ -54,6 +54,22 @@
|
|||
if (getCookie('AutoPilot')) {
|
||||
setCookie('AutoPilot', null)
|
||||
}
|
||||
// Version check
|
||||
if (getCookie('CurrentVersion')) {
|
||||
if (checkVersionNewer(parseVersionString(getCookie('CurrentVersion')), parseVersionString(currentVersion))) {
|
||||
updateMessage('MiniSub updated to ' + currentVersion);
|
||||
setCookie('CurrentVersion', currentVersion);
|
||||
}
|
||||
} else {
|
||||
setCookie('CurrentVersion', currentVersion);
|
||||
}
|
||||
|
||||
// Table Sorting
|
||||
|
||||
$('#CurrentPlaylistContainer').stupidtable();
|
||||
$('#TrackContainer').stupidtable();
|
||||
$('#PodcastContainer').stupidtable();
|
||||
$('#AlbumContainer').stupidtable();
|
||||
|
||||
// Tabs
|
||||
$('.tabcontent').hide(); //Hide all content
|
||||
|
@ -91,12 +107,14 @@
|
|||
|
||||
// Tabs - Click Event
|
||||
$("ul.tabs li a").click(function () {
|
||||
var currentTab = window.location.hash;
|
||||
var activeTab = $(this).attr("href"); //Find the href attribute value to identify the active tab + content
|
||||
if (currentTab != activeTab) {
|
||||
$("ul.tabs li a").removeClass("active"); //Remove any "active" class
|
||||
$(this).addClass("active"); //Add "active" class to selected tab
|
||||
$(".tabcontent").hide(); //Hide all tab content
|
||||
|
||||
var activeTab = $(this).attr("href"); //Find the href attribute value to identify the active tab + content
|
||||
$(activeTab).fadeIn('fast'); //Fade in the active ID content
|
||||
}
|
||||
loadTabContent(activeTab);
|
||||
});
|
||||
|
||||
|
@ -140,6 +158,7 @@
|
|||
if (volume <= 100 && volume > 0 && source == '') {
|
||||
volume += -10;
|
||||
soundManager.setVolume('audio', volume);
|
||||
setCookie('Volume', volume);
|
||||
updateMessage('Volume: ' + volume + '%');
|
||||
}
|
||||
}
|
||||
|
@ -147,6 +166,7 @@
|
|||
if (volume < 100 && volume >= 0 && source == '') {
|
||||
volume += 10;
|
||||
soundManager.setVolume('audio', volume);
|
||||
setCookie('Volume', volume);
|
||||
updateMessage('Volume: ' + volume + '%');
|
||||
}
|
||||
}
|
||||
|
@ -164,7 +184,7 @@
|
|||
$('#AutoAlbumContainer li').removeClass('selected');
|
||||
$('#ArtistContainer li').removeClass('selected');
|
||||
$(this).addClass('selected');
|
||||
getAlbums($(this).attr("id"), '', '#AlbumRows');
|
||||
getAlbums($(this).attr("id"), '', '#AlbumContainer tbody');
|
||||
});
|
||||
$('#BottomIndex li a').live('click', function () {
|
||||
var el = 'a[name = "index_' + $(this).text() + '"]';
|
||||
|
@ -213,7 +233,14 @@
|
|||
$('tr.album').live('click', function (e) {
|
||||
var albumid = $(this).attr('childid');
|
||||
var artistid = $(this).attr('parentid');
|
||||
getAlbums(albumid, '', '#AlbumRows');
|
||||
getAlbums(albumid, '', '#AlbumContainer tbody');
|
||||
return false;
|
||||
});
|
||||
|
||||
$('tr.album').live('click', function (e) {
|
||||
var albumid = $(this).attr('childid');
|
||||
var artistid = $(this).attr('parentid');
|
||||
getAlbums(albumid, '', '#AlbumContainer tbody');
|
||||
return false;
|
||||
});
|
||||
|
||||
|
@ -292,7 +319,6 @@
|
|||
$('table.songlist tr.song a.remove').live('click', function (event) {
|
||||
var track = $(this).parent().parent();
|
||||
$(track).remove();
|
||||
refreshRowColor('table.songlist');
|
||||
return false;
|
||||
});
|
||||
$('table.songlist tr.song a.rate').live('click', function (event) {
|
||||
|
@ -314,7 +340,9 @@
|
|||
$('table.songlist tr.song a.albumlink').live('click', function (event) {
|
||||
var parentid = $(this).parent().parent().attr('parentid');
|
||||
if (parentid != '' && parentid !== undefined) {
|
||||
getAlbums(parentid, 'link', '#AlbumRows');
|
||||
$('#AutoAlbumContainer li').removeClass('selected');
|
||||
$('#ArtistContainer li').removeClass('selected');
|
||||
getAlbums(parentid, 'link', '#AlbumContainer tbody');
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
@ -324,7 +352,8 @@
|
|||
});
|
||||
|
||||
// Music Library Click Events
|
||||
$('a#action_AddToPlaylist').click(function () {
|
||||
$('#action_AddToPlaylist').click(function () {
|
||||
if (!$(this).hasClass('disabled')) {
|
||||
var submenu = $('div#submenu_AddToPlaylist');
|
||||
if (submenu.is(":visible")) {
|
||||
submenu.fadeOut();
|
||||
|
@ -337,6 +366,7 @@
|
|||
//show the menu directly over the placeholder
|
||||
submenu.css({ "left": (pos.left) + "px", "top": (pos.top + height + 14) + "px" }).fadeIn(400);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$("#submenu_AddToPlaylist a").live("click", function (event) {
|
||||
|
@ -358,19 +388,25 @@
|
|||
//setTimeout(function () { if (submenu_active == false) $('div.submenu').stop().fadeOut(); }, 400);
|
||||
});
|
||||
$('a#action_AddToCurrent').click(function () {
|
||||
if (!$(this).hasClass('disabled')) {
|
||||
addToCurrent(false);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$('a#action_AddAllToCurrent').click(function () {
|
||||
if (!$(this).hasClass('disabled')) {
|
||||
addToCurrent(true);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$('a#action_PlayAlbum').click(function () {
|
||||
if (!$(this).hasClass('disabled')) {
|
||||
$('#CurrentPlaylistContainer tbody').empty();
|
||||
addToCurrent(true);
|
||||
// Start playing song
|
||||
var first = $('#CurrentPlaylistContainer tr.song').first();
|
||||
changeTrack(first);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$('#action_RefreshArtists').click(function () {
|
||||
|
@ -391,15 +427,19 @@
|
|||
return false;
|
||||
});
|
||||
$('#action_SelectAll').click(function () {
|
||||
if (!$(this).hasClass('disabled')) {
|
||||
$('#Albums tr.song').each(function () {
|
||||
$(this).addClass('selected');
|
||||
});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$('#action_SelectNone').click(function () {
|
||||
if (!$(this).hasClass('disabled')) {
|
||||
$('#Albums tr.song').each(function () {
|
||||
$(this).removeClass('selected');
|
||||
});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$('input#Search').keydown(function (e) {
|
||||
|
@ -410,16 +450,55 @@
|
|||
});
|
||||
$('#action_Search').click(function () {
|
||||
var query = $('#Search').val();
|
||||
if (query != '') {
|
||||
var type = $('#SearchType').val();
|
||||
search(type, query);
|
||||
$('#Search').val("");
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$('#action_PreviousAlbumList').live('click', function () {
|
||||
var type = $('#status_Library').data('type');
|
||||
var offset = 0;
|
||||
if ($('#status_Library').data('offset') != '') {
|
||||
offset = $('#status_Library').data('offset');
|
||||
}
|
||||
var currOffset = 15;
|
||||
if (getCookie('AutoAlbumSize')) {
|
||||
currOffset = getCookie('AutoAlbumSize');
|
||||
}
|
||||
if (offset > 0) {
|
||||
$('#status_Library').data('offset', parseInt(offset) - parseInt(currOffset));
|
||||
getAlbumListBy(type, parseInt(offset) - parseInt(currOffset));
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$('#action_NextAlbumList').live('click', function () {
|
||||
var currOffset = 15;
|
||||
if (getCookie('AutoAlbumSize')) {
|
||||
currOffset = getCookie('AutoAlbumSize');
|
||||
}
|
||||
var count = $('#AlbumContainer tr.album').size();
|
||||
if (count == currOffset) {
|
||||
var type = $('#status_Library').data('type');
|
||||
var offset = 0;
|
||||
if ($('#status_Library').data('offset') != '') {
|
||||
offset = $('#status_Library').data('offset');
|
||||
}
|
||||
$('#status_Library').data('offset', parseInt(offset) + parseInt(currOffset));
|
||||
getAlbumListBy(type, parseInt(offset) + parseInt(currOffset));
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// Current Playlist Click Events
|
||||
$('#action_Shuffle').live('click', function () {
|
||||
//$('#CurrentPlaylistContainer tbody tr.song').shuffle();
|
||||
$('#CurrentPlaylistContainer tbody tr.song:not(#CurrentPlaylistContainer tbody tr.playing)').shuffle();
|
||||
refreshRowColor('#CurrentPlaylistContainer tbody');
|
||||
/* Sets currently playing song first in list after sort
|
||||
$('#CurrentPlaylistContainer tbody tr.song').shuffle();
|
||||
$('#CurrentPlaylistContainer tbody tr.playing').insertBefore($('#CurrentPlaylistContainer tbody tr:first'));
|
||||
*/
|
||||
$('#CurrentPlaylistContainer thead').find('th').removeClass('sorted ascending descending');
|
||||
var songid = $('#CurrentPlaylistContainer tbody tr.playing').attr('childid');
|
||||
if (songid !== undefined) {
|
||||
$('#CurrentPlaylist').scrollTo($('#' + songid), 400);
|
||||
|
@ -431,7 +510,8 @@
|
|||
deleteCurrentPlaylist();
|
||||
return false;
|
||||
});
|
||||
$('a#action_AddCurrentToPlaylist').click(function () {
|
||||
$('#action_AddCurrentToPlaylist').click(function () {
|
||||
if (!$(this).hasClass('disabled')) {
|
||||
var submenu = $('div#submenu_AddCurrentToPlaylist');
|
||||
if (submenu.is(":visible")) {
|
||||
submenu.fadeOut();
|
||||
|
@ -444,6 +524,7 @@
|
|||
//show the menu directly over the placeholder
|
||||
submenu.css({ "left": (pos.left) + "px", "top": (pos.top + height + 14) + "px" }).fadeIn(400);
|
||||
}
|
||||
}
|
||||
});
|
||||
$("#submenu_AddCurrentToPlaylist a").live("click", function (event) {
|
||||
var id = $(this).attr('childid');
|
||||
|
@ -506,31 +587,34 @@
|
|||
});
|
||||
$('#songdetails').mouseout(function () {
|
||||
$(this).removeClass('hover')
|
||||
//$('div.submenu').hide();
|
||||
});
|
||||
$('#CurrentPlaylist').mouseenter(function () {
|
||||
var html = $('#status').html();
|
||||
if (html != '') {
|
||||
$('#status').fadeIn();
|
||||
$('.tabcontent').mouseenter(function () {
|
||||
$('.status').each(function (i) {
|
||||
if ($(this).hasClass('on')) {
|
||||
$(this).fadeIn();
|
||||
}
|
||||
});
|
||||
$('#CurrentPlaylist').mouseleave(function () {
|
||||
$('#status').stop().fadeOut();
|
||||
});
|
||||
|
||||
$('.tabcontent').mouseleave(function () {
|
||||
$('.status').stop().fadeOut();
|
||||
});
|
||||
$('#action_CurrentSelectAll').click(function () {
|
||||
if (!$(this).hasClass('disabled')) {
|
||||
var count = 0;
|
||||
$('#CurrentPlaylist tr.song').each(function () {
|
||||
$(this).addClass('selected');
|
||||
count++;
|
||||
});
|
||||
updateMessage(count + ' Song(s) Selected');
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$('#action_CurrentSelectNone').click(function () {
|
||||
if (!$(this).hasClass('disabled')) {
|
||||
$('#CurrentPlaylist tr.song').each(function () {
|
||||
$(this).removeClass('selected');
|
||||
});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$('#action_AutoPilot').click(function () {
|
||||
|
@ -546,6 +630,7 @@
|
|||
if ($('#CurrentPlaylistContainer tbody').html() == '') {
|
||||
$('#CurrentPlaylistContainer tbody').empty();
|
||||
getRandomSongList('', '#CurrentPlaylistContainer tbody', '', '');
|
||||
$('#currentActions a.button').removeClass('disabled');
|
||||
}
|
||||
}
|
||||
$(this).attr("title", msg);
|
||||
|
@ -623,8 +708,8 @@
|
|||
return false;
|
||||
});
|
||||
$('#action_ShufflePlaylist').live('click', function () {
|
||||
$('#TrackContainer thead').find('th').removeClass('sorted ascending descending');
|
||||
$('#TrackContainer tbody tr.song').shuffle();
|
||||
refreshRowColor('#TrackContainer tbody');
|
||||
return false;
|
||||
});
|
||||
|
||||
|
@ -857,6 +942,7 @@
|
|||
return false;
|
||||
});
|
||||
|
||||
/*
|
||||
// JQuery UI Sortable - Drag and drop sorting
|
||||
var fixHelper = function (e, ui) {
|
||||
ui.children().each(function () {
|
||||
|
@ -865,17 +951,11 @@
|
|||
return ui;
|
||||
};
|
||||
$("#CurrentPlaylistContainer tbody").sortable({
|
||||
helper: fixHelper,
|
||||
stop: function () {
|
||||
refreshRowColor('#CurrentPlaylistContainer tbody');
|
||||
}
|
||||
helper: fixHelper
|
||||
}).disableSelection();
|
||||
$("#TrackContainer tbody").sortable({
|
||||
helper: fixHelper,
|
||||
stop: function () {
|
||||
refreshRowColor('#TrackContainer tbody');
|
||||
}
|
||||
helper: fixHelper
|
||||
}).disableSelection();
|
||||
|
||||
*/
|
||||
}); // End document.ready
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
"manifest_version": 2,
|
||||
"name": "MiniSub (Beta)",
|
||||
"description": "MiniSub - HTML5 Mini Player for Subsonic",
|
||||
"version": "2.1.7",
|
||||
"version": "2.2.0",
|
||||
"app": {
|
||||
"launch": {
|
||||
"local_path": "index.html"
|
||||
|
|
|
@ -15,9 +15,6 @@ h3.title {
|
|||
color: #f2f2f2;
|
||||
}
|
||||
|
||||
.odd { background: none; }
|
||||
.even { background: #272727; }
|
||||
|
||||
#content
|
||||
{
|
||||
background: #222222;
|
||||
|
@ -98,14 +95,18 @@ h3.title {
|
|||
{
|
||||
color: #d6d469;
|
||||
background: #2e2e2e;
|
||||
border: 1px solid #5a5a5a;
|
||||
border: 1px solid #1d1d1d;
|
||||
}
|
||||
#status
|
||||
.status
|
||||
{
|
||||
background: #222;
|
||||
border-top: 1px solid #1D1D1D;
|
||||
border-left: 1px solid #1D1D1D;
|
||||
}
|
||||
.status a
|
||||
{
|
||||
color: #d6d469;
|
||||
}
|
||||
#player
|
||||
{
|
||||
background: #2E2E2E;
|
||||
|
@ -146,7 +147,7 @@ a.button:hover {
|
|||
-moz-box-shadow: 0 2px 0 rgba(242, 242, 242, 0.2)
|
||||
-webkit-box-shadow:0 2px 5px rgba(242, 242, 242, 0.2);
|
||||
box-shadow: 0 1px 2px rgba(242, 242, 242, 0.15);
|
||||
border: solid 1px #5a5a5a;
|
||||
border-color: #5a5a5a;
|
||||
}
|
||||
a.button:active {
|
||||
color: #000;
|
||||
|
@ -155,8 +156,22 @@ a.button:active {
|
|||
a.selected {
|
||||
color: #939393;
|
||||
border-color: #5a5a5a;
|
||||
-moz-box-shadow: 0 2px 0 rgba(0, 0, 0, 0.2) -webkit-box-shadow:0 2px 5px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
|
||||
-moz-box-shadow: 0 2px 0 rgba(242, 242, 242, 0.2)
|
||||
-webkit-box-shadow:0 2px 5px rgba(242, 242, 242, 0.2);
|
||||
box-shadow: 0 1px 2px rgba(242, 242, 242, 0.15);
|
||||
background: #161616;
|
||||
background: -webkit-gradient(linear,0% 40%,0% 70%,from(#161616),to(#111111));
|
||||
background: -moz-linear-gradient(linear,0% 40%,0% 70%,from(#161616),to(#111111));
|
||||
}
|
||||
a.disabled {
|
||||
color: #3D3D3D;
|
||||
background: #2E2E2E;
|
||||
}
|
||||
a.disabled:hover {
|
||||
color: #3D3D3D;
|
||||
border-color: #1d1d1d;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
ul.simplelist li
|
||||
{
|
||||
|
@ -196,8 +211,13 @@ ul.simplelist li.selected
|
|||
}
|
||||
table.songlist th {
|
||||
color: #F2F2F2;
|
||||
border-bottom: 1px solid #2e2e2e;
|
||||
background: #2E2E2E;
|
||||
}
|
||||
table.songlist tr:hover
|
||||
table.songlist th:hover, table.songlist th.sorted {
|
||||
background: #272727;
|
||||
}
|
||||
table.songlist tr.album:hover
|
||||
{
|
||||
background: #1d1d1d;
|
||||
}
|
||||
|
@ -212,6 +232,10 @@ table.songlist tr.album td.albumart img
|
|||
table.songlist tr.song {
|
||||
border-bottom: 1px solid #232323;
|
||||
}
|
||||
table.songlist tr.song:hover
|
||||
{
|
||||
background: #1d1d1d;
|
||||
}
|
||||
table.songlist tr.song td.album img
|
||||
{
|
||||
border: 1px solid #232323;
|
||||
|
@ -225,12 +249,15 @@ table.songlist tr.song td.album a:hover
|
|||
color: #d6d469;
|
||||
text-decoration: underline;
|
||||
}
|
||||
table.songlist tr:nth-child(odd) { background-color: #272727; }
|
||||
table.songlist tr:nth-child(even) { background-color: #2e2e2e; }
|
||||
table.songlist tr.playing {
|
||||
background: #161616;
|
||||
}
|
||||
table.songlist tr.selected
|
||||
{
|
||||
background: #3a3a3a;
|
||||
}
|
||||
table.songlist tr.playing {
|
||||
background: #161616;
|
||||
border-bottom: 1px solid #232323;
|
||||
}
|
||||
#submenu_CurrentPlaylist
|
||||
{
|
||||
|
@ -255,3 +282,9 @@ fieldset
|
|||
background: #232323;
|
||||
border: 1px solid #1D1D1D;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: rgba(34, 34, 34, 0.8);
|
||||
}
|
||||
::-webkit-scrollbar-thumb:window-inactive {
|
||||
background: rgba(34, 34, 34, 0.2);
|
||||
}
|
154
style/Style.css
154
style/Style.css
|
@ -31,8 +31,10 @@ h3.title
|
|||
.alignright { text-align: right; }
|
||||
.aligncenter { text-align: center; }
|
||||
.padright { padding: 0 10px 0 0; }
|
||||
/* Old: Using CSS3
|
||||
.odd { background: #fff; }
|
||||
.even { background: #f4f4f4; }
|
||||
*/
|
||||
.red { color: #E64F4C; }
|
||||
.italic { font-style: italic; }
|
||||
.beer { font-size: 17px; }
|
||||
|
@ -161,7 +163,7 @@ a#logo:hover
|
|||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
background: #fff;
|
||||
border-right: 1px solid #cbcbcb;
|
||||
border-right: 1px solid #f2f2f2;
|
||||
position: absolute;
|
||||
top: 39px;
|
||||
left: 60px;
|
||||
|
@ -225,7 +227,7 @@ a#logo:hover
|
|||
position: absolute;
|
||||
z-index: 99;
|
||||
top: 0;
|
||||
left: 790px;
|
||||
right: 10px;
|
||||
}
|
||||
#messages .message
|
||||
{
|
||||
|
@ -236,11 +238,13 @@ a#logo:hover
|
|||
margin: 2px 0 2px 0;
|
||||
background: #fff;
|
||||
border: 1px solid #A6CBF3;
|
||||
border-radius: 4px 4px 4px 4px;
|
||||
box-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
|
||||
opacity: 0.8;
|
||||
}
|
||||
#status
|
||||
.status
|
||||
{
|
||||
display: none;
|
||||
width: 180px;
|
||||
overflow: hidden;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
|
@ -249,10 +253,32 @@ a#logo:hover
|
|||
bottom: 86px;
|
||||
right: 4px;
|
||||
background: #f2f2f2;
|
||||
padding: 2px 5px;
|
||||
padding: 2px 10px;
|
||||
border-top: 1px solid #CBCBCB;
|
||||
border-left: 1px solid #CBCBCB;
|
||||
opacity: .7;
|
||||
opacity: .9;
|
||||
}
|
||||
.status a
|
||||
{
|
||||
color: #545454;
|
||||
text-decoration: none;
|
||||
font-size: 12px;
|
||||
}
|
||||
.status a:hover
|
||||
{
|
||||
text-decoration: underline;
|
||||
}
|
||||
.status a.previous
|
||||
{
|
||||
margin: 0 5px 0 0;
|
||||
}
|
||||
.status a.next
|
||||
{
|
||||
margin: 0 0 0 5px;
|
||||
}
|
||||
.on
|
||||
{
|
||||
display: block;
|
||||
}
|
||||
/* Library Style */
|
||||
ul.simplelist
|
||||
|
@ -337,13 +363,9 @@ ul.mainlist li.item a.add:hover
|
|||
{
|
||||
background: url('../images/plus_8x8.png') no-repeat 6px center #DEECFB;
|
||||
}
|
||||
#AlbumContainer
|
||||
#AlbumContainer, #TrackContainer, #PodcastContainer
|
||||
{
|
||||
margin: 5px 5px 5px 206px;
|
||||
}
|
||||
#TrackContainer, #PodcastContainer
|
||||
{
|
||||
margin: 5px 5px 5px 206px;
|
||||
margin: 5px 5px 5px 221px;
|
||||
}
|
||||
#CurrentPlaylistContainer tr.song a.add
|
||||
{
|
||||
|
@ -381,9 +403,25 @@ table.songlist th
|
|||
{
|
||||
font-size: 14px;
|
||||
font-variant: small-caps;
|
||||
padding: 5px 4px;
|
||||
padding: 5px 5px 5px 12px;
|
||||
cursor: pointer;
|
||||
border-bottom: 1px solid #ffffff;
|
||||
background: #fff;
|
||||
}
|
||||
table.songlist tr:hover
|
||||
table.songlist th:hover
|
||||
{
|
||||
background: #fafafa;
|
||||
}
|
||||
table.songlist th.sorted {
|
||||
background: #F2F3F4;
|
||||
}
|
||||
table.songlist th.sorted.ascending:after {
|
||||
content: " \2191";
|
||||
}
|
||||
table.songlist th.sorted.descending:after {
|
||||
content: " \2193";
|
||||
}
|
||||
table.songlist tr.album:hover
|
||||
{
|
||||
background: #EEF5FD;
|
||||
}
|
||||
|
@ -480,6 +518,7 @@ table.songlist tr.album a.favorite
|
|||
display: block;
|
||||
background: url('../images/star_yo_12x12.png') 2px center no-repeat;
|
||||
}
|
||||
|
||||
table.songlist tr.song
|
||||
{
|
||||
cursor: pointer;
|
||||
|
@ -499,13 +538,9 @@ table.songlist tr.song td.itemactions
|
|||
height: 18px;
|
||||
}
|
||||
table.songlist tr.song td.track
|
||||
{
|
||||
width: 40px;
|
||||
text-align: right;
|
||||
}
|
||||
table.songlist tr.song td.published
|
||||
{
|
||||
width: 80px;
|
||||
text-align: right;
|
||||
}
|
||||
table.songlist tr.song td.title
|
||||
{
|
||||
|
@ -604,6 +639,8 @@ table.songlist tr.song a.favorite
|
|||
display: block;
|
||||
background: url('../images/star_yo_12x12.png') center 3px no-repeat;
|
||||
}
|
||||
table.songlist tr:nth-child(odd) { background-color:#f4f4f4; }
|
||||
table.songlist tr:nth-child(even) { background-color:#fff; }
|
||||
table.songlist tr.playing
|
||||
{
|
||||
background-color: #DEEBFA;
|
||||
|
@ -622,50 +659,6 @@ table.songlist tr.selected td:first-child
|
|||
{
|
||||
background: url('../images/check_8x7.png') 10px 16px no-repeat;
|
||||
}
|
||||
table.songlist tr.selected td.album a
|
||||
{
|
||||
color: #f2f2f2;
|
||||
}
|
||||
/* tablesorter style */
|
||||
table.tablesorter {
|
||||
font-family:arial;
|
||||
background-color: #CDCDCD;
|
||||
margin:10px 0pt 15px;
|
||||
font-size: 8pt;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
table.tablesorter thead tr th, table.tablesorter tfoot tr th {
|
||||
background-color: #e6EEEE;
|
||||
border: 1px solid #FFF;
|
||||
font-size: 8pt;
|
||||
padding: 4px;
|
||||
}
|
||||
table.tablesorter thead tr .header {
|
||||
background-image: url(../images/bg.gif);
|
||||
background-repeat: no-repeat;
|
||||
background-position: center right;
|
||||
cursor: pointer;
|
||||
}
|
||||
table.tablesorter tbody td {
|
||||
color: #3D3D3D;
|
||||
padding: 4px;
|
||||
background-color: #FFF;
|
||||
vertical-align: top;
|
||||
}
|
||||
table.tablesorter tbody tr.odd td {
|
||||
background-color:#F0F0F6;
|
||||
}
|
||||
table.tablesorter thead tr .headerSortUp {
|
||||
background-image: url(../images/asc.gif);
|
||||
}
|
||||
table.tablesorter thead tr .headerSortDown {
|
||||
background-image: url(../images/desc.gif);
|
||||
}
|
||||
table.tablesorter thead tr .headerSortDown, table.tablesorter thead tr .headerSortUp {
|
||||
background-color: #8dbdd8;
|
||||
}
|
||||
|
||||
#ArtistContainer
|
||||
{
|
||||
min-height: 360px;
|
||||
|
@ -714,7 +707,7 @@ background-color: #8dbdd8;
|
|||
margin: 4px 0 0 0;
|
||||
padding: 0 0 0 5px;
|
||||
}
|
||||
#songactions
|
||||
#songActions
|
||||
{
|
||||
float: left;
|
||||
}
|
||||
|
@ -1122,14 +1115,45 @@ a.selected {
|
|||
border-color: #999;
|
||||
-moz-box-shadow: 0 2px 0 rgba(0, 0, 0, 0.2) -webkit-box-shadow:0 2px 5px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.15);
|
||||
background: #fdfdfd;
|
||||
background: -webkit-gradient(linear,0% 40%,0% 70%,from(#ffffff),to(#fdfdfd));
|
||||
background: -moz-linear-gradient(linear,0% 40%,0% 70%,from(#ffffff),to(#fdfdfd));
|
||||
}
|
||||
a.disabled {
|
||||
color: #B7B7B7;
|
||||
background: #f1f1f1;
|
||||
}
|
||||
a.disabled:hover {
|
||||
color: #B7B7B7;
|
||||
border-color: #dcdcdc;
|
||||
-moz-box-shadow: none;
|
||||
box-shadow: none;
|
||||
}
|
||||
a.button img.pad { margin: 1px 0 -1px 0; }
|
||||
|
||||
.shadow
|
||||
{
|
||||
box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
/* Scrollbar Style */
|
||||
::-webkit-scrollbar {
|
||||
width: 14px;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
-webkit-box-shadow: inset 0 0 2px rgba(0,0,0,0.2);
|
||||
-webkit-border-radius: 12px;
|
||||
border-radius: 12px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
-webkit-border-radius: 12px;
|
||||
border-radius: 12px;
|
||||
background: rgba(237, 237, 237, 0.4);
|
||||
-webkit-box-shadow: inset 0 0 2px rgba(0,0,0,0.2);
|
||||
}
|
||||
::-webkit-scrollbar-thumb:window-inactive {
|
||||
background: rgba(237, 237, 237, 0.2);
|
||||
}
|
||||
|
||||
/* Form Style */
|
||||
input
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue