/* Demo application using Ox.AudioPlayer. */ 'use strict'; Ox.load('UI', function() { var columns = [ { format: function(value) { return value ? Ox.Element('') .addClass('symbol') .attr({src: Ox.UI.getImageURL( paused ? 'symbolUnmute' : 'symbolMute' )}) : Ox.Element(); }, id: 'playing', removable: false, title: 'Playing', titleImage: 'mute', visible: true, width: 16 }, { format: function(value) { return value ? Ox.Element('') .addClass('symbol') .attr({src: Ox.UI.getImageURL( 'symbolCheck' )}) : Ox.Element(); }, id: 'checked', removable: false, title: 'Checked', titleImage: 'check', visible: true, width: 16 }, { format: function(value) { return value ? Ox.Element('') .addClass('image') .attr({src: value}) : Ox.Element() }, id: 'artwork', operator: '+', title: 'Artwork', titleImage: 'icon', visible: true, width: 16 }, { align: 'right', id: 'disc', operator: '+', title: 'Disc', titleImage: 'circle', width: 32 }, { align: 'right', id: 'track', operator: '+', title: 'Track', titleImage: 'square', width: 32 }, { id: 'title', operator: '+', removable: false, title: 'Title', visible: true, width: 192 }, { id: 'artist', operator: '+', removable: false, title: 'Artist', visible: true, width: 192 }, { id: 'album', operator: '+', removable: false, title: 'Album', visible: true, width: 192 }, { align: 'right', id: 'year', operator: '+', title: 'Year', visible: true, width: 64 }, { align: 'right', format: function(value) { return Ox.formatDuration(value).substr(4); }, id: 'duration', operator: '-', title: 'Time', visible: true, width: 64 }, { align: 'right', format: function(value) { return Ox.formatValue(value, 'B'); }, id: 'size', operator: '-', title: 'Size', visible: true, width: 64 }, { align: 'right', format: function(value) { return Math.round(value) + ' kbps' }, id: 'bitrate', operator: '-', title: 'Bitrate', visible: true, width: 64 }, { id: 'genre', operator: '+', title: 'Genre', visible: true, width: 128 } ], paused = true, sidebarSize = 192, sort = [ {key: 'artist', operator: '+'}, {key: 'year', operator: '+'}, {key: 'disc', operator: '+'}, {key: 'track', operator: '+'} ], track = 0, tracklistSize = 256, tracks = [ { album: 'The Grey Album', artist: 'Danger Mouse', artwork: 'mp3/Danger Mouse/2004 The Grey Album/artwork.png', bitrate: 128, checked: true, disc: 1, duration: 160.417, file: 'mp3/Danger Mouse/2004 The Grey Album/03 Encore.mp3', genre: 'Hip-Hop', playing: false, size: 2556502, title: 'Encore', track: 3, year: '2004' }, { album: 'No Love Deep Web', artist: 'Death Grips', artwork: 'mp3/Death Grips/2012 No Love Deep Web/artwork.png', bitrate: 128, checked: true, disc: 1, duration: 303.960, file: 'mp3/Death Grips/2012 No Love Deep Web/03 No Love.mp3', genre: 'Electronic', playing: false, size: 4863327, title: 'No Love', track: 3, year: '2012' }, { album: 'No Love Deep Web', artist: 'Death Grips', artwork: 'mp3/Death Grips/2012 No Love Deep Web/artwork.png', bitrate: 128, checked: true, disc: 1, duration: 138.370, file: 'mp3/Death Grips/2012 No Love Deep Web/09 Deep Web.mp3', genre: 'Electronic', playing: false, size: 2214303, title: 'Deep Web', track: 9, year: '2012' } ], artists = getArtists(tracks), albums = getAlbums(artists), view = 'tracks', $toolbar = Ox.Bar({size: 39}), $audioPlayer = Ox.AudioPlayer({ audio: tracks, paused: true, width: window.innerWidth - 190 }) .css({left: '4px', top: '4px'}) .bindEvent({ paused: function(data) { paused = data.paused; $musicList.value(tracks[track].file, 'playing', false); $musicList.value(tracks[track].file, 'playing', true); }, track: function(data) { $musicList.value(tracks[track].file, 'playing', false); track = data.track; $musicList.value(tracks[track].file, 'playing', true); } }) .appendTo($toolbar) .gainFocus(), $viewLabel = Ox.Label({ textAlign: 'center', title: 'Tracks', width: 50 }) .css({ position: 'absolute', right: '136px', top: '4px', padding: '1px 4px 0 4px', borderBottomLeftRadius: 0, borderBottomRightRadius: 0, fontSize: '9px' }) .appendTo($toolbar), $viewButtons = Ox.ButtonGroup({ buttons: [ {id: 'tracks', title: 'list', tooltip: 'View Tracks'}, {id: 'albums', title: 'grid', tooltip: 'View Albums'}, {id: 'artists', title: 'columns', tooltip: 'View Artists'} ], max: 1, min: 1, selectable: true, type: 'image' }) .css({ position: 'absolute', right: '136px', top: '19px' }) .bindEvent({ change: function(data) { view = data.value; $viewLabel.options({title: Ox.toTitleCase(view)}); $rightPanel.replaceElement(0, musicPanel(view)); } }) .appendTo($toolbar), $findSelect = Ox.Select({ items: [ {id: 'all', title: 'Find: All'}, {id: 'tracks', title: 'Find: Tracks'}, {id: 'artists', title: 'Find: Artists'}, {id: 'albums', title: 'Find: Albums'} ], overlap: 'left', type: 'image' }) .css({ position: 'absolute', right: '4px', top: '4px', borderBottomRightRadius: 0 }) .bindEvent({ change: function(data) { $findLabel.options({title: data.title}); } }) .appendTo($toolbar), $findLabel = Ox.Label({ title: 'Find: All', width: 112 }) .css({ position: 'absolute', right: '20px', top: '4px', paddingTop: '1px', borderBottomLeftRadius: 0, borderBottomRightRadius: 0, fontSize: '9px' }) .appendTo($toolbar), $findInput = Ox.Input({ clear: true, width: 128 }) .css({ position: 'absolute', right: '4px', top: '19px', borderTopLeftRadius: 0 }) .appendTo($toolbar), $listsList = Ox.TableList({ columns: [ { format: function(value) { return Ox.Element('') .addClass('symbol') .attr({src: Ox.UI.getImageURL( 'symbol' + Ox.toTitleCase(value) )}); }, id: 'icon', title: 'icon', visible: true, width: 16 }, { id: 'title', title: 'Title', visible: true, width: 136 }, { align: 'right', id: 'items', title: 'Items', visible: true, width: 40 } ], items: [ {icon: 'audio', index: '0', items: 3, title: 'Music'}, {icon: 'playlist', index: '1', items: 0, title: 'Playing'}, {icon: 'click', index: '1', items: 0, title: 'Favorites'}, {icon: 'find', index: '1', items: 1, title: 'Hip-Hop'} ], max: 1, selected: ['0'], sort: [{key: 'index', operator: '+'}], sortable: true, unique: 'index' }), $artworkbar = Ox.Bar({size: 16}), $artworkText = Ox.Element() .css({ paddingTop: '1px', textAlign: 'center' }) .html('Selected Item') .appendTo($artworkbar), $artwork = Ox.Element('') .attr({src: tracks[0].artwork}) .css({ width: sidebarSize + 'px', height: sidebarSize + 'px' }), $artworkPanel = Ox.SplitPanel({ elements: [ {element: $artworkbar, size: 16}, {element: $artwork} ], orientation: 'vertical' }), $leftPanel = Ox.SplitPanel({ elements: [ { element: $listsList }, { collapsible: true, element: $artworkPanel, size: sidebarSize + 16 } ], orientation: 'vertical' }) .bindEvent({ resize: function(data) { sidebarSize = data.size; $listsList.setColumnWidth('title', sidebarSize - 56); $leftPanel.size(1, sidebarSize + 16); $artwork.css({ width: sidebarSize + 'px', height: sidebarSize + 'px' }); //$musicList.size(); } }), $musicList, $musicPanel = musicPanel(view), $statusbar = Ox.Bar({size: 16}), $status = Ox.Element().css({ paddingTop: '3px', fontSize: '9px', textAlign: 'center' }) .html('Loading...') .appendTo($statusbar), $rightPanel = Ox.SplitPanel({ elements: [ {element: $musicPanel}, {element: $statusbar, size: 16} ], orientation: 'vertical' }), $mainPanel = Ox.SplitPanel({ elements: [ { collapsible: true, element: $leftPanel, resizable: true, resize: [128, 192, 256, 320, 384], size: sidebarSize }, { element: $rightPanel } ], orientation: 'horizontal' }), $appPanel = Ox.SplitPanel({ elements: [ {element: $toolbar, size: 39}, {element: $mainPanel} ], orientation: 'vertical' }) .appendTo(Ox.$body); $($viewButtons.find('.OxButton')[0]).css({borderTopLeftRadius: 0}); $($viewButtons.find('.OxButton')[2]).css({borderTopRightRadius: 0}); $findInput.find('input').css({borderTopLeftRadius: 0, borderTopRightRadius: 0}); $findInput.find('.OxButton').css({borderTopRightRadius: 0}); // Ox.print('ARTISTS', artists, 'ALBUMS', albums); function getAlbums(artists) { var albums = [] artists.forEach(function(artist) { artist.items.forEach(function(album) { albums.push(Ox.extend(album, {artist: artist.name})); }); }); return albums; } function getArtists(tracks) { var artists = [], tree = {}; tracks.forEach(function(track, index) { var artist = track.artist, album = track.year + ' ' + track.album, title = Ox.pad(track.disc, 2) + '\n' + Ox.pad(track.track, 2) + '\n' + track.title; if (!tree[artist]) { tree[artist] = {}; } if (!tree[artist][album]) { tree[artist][album] = {}; } if (!tree[artist][album][title]) { tree[artist][album][title] = track; } }); Ox.forEach(tree, function(albums, artist) { artist = { albums: Ox.len(albums), artwork: 'mp3/' + artist + '/artwork.png', id: artist, items: [], name: artist }; Ox.forEach(albums, function(tracks, id) { var title = id.substr(5), year = id.substr(0, 4); artist.items.push({ artwork: tracks[Object.keys(tracks)[0]].artwork, duration: Ox.values(tracks).reduce(function(r, v, i) { return r + v.duration; }, 0), id: [year, title].join('\n'), items: [], size: Ox.values(tracks).reduce(function(r, v, i) { return r + v.size; }, 0), title: title, tracks: Ox.len(tracks), year: year }); Ox.forEach(tracks, function(track, id) { artist.items[artist.items.length - 1].items.push({ artist: track.artist, artwork: track.artwork, bitrate: track.bitrate, checked: track.checked, disc: track.disc, duration: track.duration, id: id, genre: track.genre, playing: track.playing, size: track.size, title: track.title, track: track.track }); }); }); ['duration', 'size', 'tracks'].forEach(function(key) { artist[key] = artist.items.reduce(function(r, v, i) { return r + v[key]; }, 0); }) artist.years = Ox.unique(artist.items.map(function(item) { return item.year; })).sort(); artist.years = [artist.years[0]].concat( artist.years.length > 1 ? [artist.years[artist.years.length - 1]] : [] ); artists.push(artist); }); return artists; } function musicPanel(view) { var $panel; if (view == 'tracks') { var $trackAlbumList = trackAlbumList(); $musicList = Ox.TableList({ columns: columns, columnsMovable: true, columnsRemovable: true, columnsResizable: true, columnsVisible: true, items: tracks, max: 1, scrollbarVisible: true, sort: Ox.clone(sort, true), unique: 'file' }) .bindEvent({ open: function(data) { var file = data.ids[0], index = Ox.indexOf(tracks, function(track) { return track.file == file; }); if (index == track) { $musicList.value(tracks[track].file, 'playing', true); $audioPlayer.options({paused: false, position: 0}); } else { $musicList.value(tracks[track].file, 'playing', false); track = index; $audioPlayer.options({paused: false, track: track}); $musicList.value(tracks[track].file, 'playing', true); } }, openpreview: function(data) { paused = !paused; $audioPlayer.options({paused: paused}); $musicList.closePreview(); } }); $panel = Ox.SplitPanel({ elements: [ { collapsible: true, element: $trackAlbumList, size: 112 + Ox.UI.SCROLLBAR_SIZE }, { element: $musicList } ], orientation: 'vertical' }); } else if (view == 'albums') { $musicList = Ox.IconList({ fixedRatio: 1, item: function(data, sort, size) { var key = Ox.contains(['artist', 'title'], sort[0].key) ? 'year' : sort[0].key, column = Ox.getObjectById(columns, key), info = (column.format || Ox.identity)(data[key]); return { height: size, id: data.id, info: info, title: [data.artist, data.title].join(' — '), url: data.artwork, width: size } }, items: albums, max: 1, pageLength: 120, query: {conditions: [], operator: '&'}, selected: [], size: 128, sort: Ox.clone(sort, true), unique: 'id' }) .bindEvent({ }); var $albumTrackList = albumTrackList(); $panel = Ox.SplitPanel({ elements: [ { element: $musicList }, { element: $albumTrackList, resizable: true, resize: [192, 256, 320], size: tracklistSize } ], orientation: 'horizontal' }); } else if (view == 'artists') { $panel = Ox.ColumnList({ columns: [ { id: 'artist', item: function(data, width) { data.artwork = data.artwork || ''; data.years = data.years || []; var $item = $('
') .css({width: width + 'px', height: '32px'}); $('') .attr({src: data.artwork}) .css({ position: 'relative', left: '2px', top: '2px', width: '28px', height: '28px', borderRadius: '7px' }) .appendTo($item); $('
') .css({ position: 'relative', left: '34px', top: '-28px', width: width - 36 + 'px', fontSize: '13px', textOverflow: 'ellipsis', cursor: 'default', overflow: 'hidden' }) .html(data.name ? data.name : '') .appendTo($item); $('
') .addClass('OxLight') .css({ position: 'relative', left: '34px', top: '-28px', width: width - 36 + 'px', height: '10px', fontSize: '9px', textOverflow: 'ellipsis', whiteSpace: 'nowrap', cursor: 'default', overflow: 'hidden' }) .html( [ data.years.join('-'), Ox.formatCount(data.albums, 'album'), Ox.formatCount(data.tracks, 'track'), Ox.formatDuration(data.duration), Ox.formatValue(data.size, 'B') ].join(' — ') ) .appendTo($item); return $item; }, itemHeight: 32, keys: ['albums', 'artwork', 'duration', 'name', 'size', 'tracks', 'years'] }, { id: 'album', item: function(data, width) { data.artwork = data.artwork || ''; data.tracks = data.tracks || [{duration: 0}]; data.year = data.year || '????'; var $item = $('
') .css({width: width + 'px', height: '32px'}); $('') .attr({src: data.artwork}) .css({ position: 'relative', left: '2px', top: '2px', width: '28px', height: '28px' }) .appendTo($item); $('
') .css({ position: 'relative', left: '34px', top: '-28px', width: width - 36 + 'px', fontSize: '13px', textOverflow: 'ellipsis', cursor: 'default', overflow: 'hidden' }) .html(data.title ? data.title : '') .appendTo($item); $('
') .addClass('OxLight') .css({ position: 'relative', left: '34px', top: '-28px', width: width - 36 + 'px', fontSize: '9px', textOverflow: 'ellipsis', cursor: 'default', overflow: 'hidden' }) .html( [ data.year, Ox.formatCount(data.tracks, 'track'), Ox.formatDuration(data.duration), Ox.formatValue(data.size, 'B') ].join(' — ') ) .appendTo($item); return $item; }, itemHeight: 32, keys: ['artwork', 'duration', 'size', 'title', 'tracks', 'year'] }, { id: 'track', item: function(data, width) { var $item = $('
') .css({width: width + 'px', height: '32px'}); $('') .attr({src: data.artwork}) .css({ position: 'relative', left: '2px', top: '2px', width: '28px', height: '28px' }) .appendTo($item); $('
') .css({ position: 'relative', left: '34px', top: '-28px', width: width - 36 + 'px', fontSize: '13px', textOverflow: 'ellipsis', cursor: 'default', overflow: 'hidden' }) .html(data.title ? data.title : '') .appendTo($item); $('
') .addClass('OxLight') .css({ position: 'relative', left: '34px', top: '-28px', width: width - 36 + 'px', fontSize: '9px', textOverflow: 'ellipsis', cursor: 'default', overflow: 'hidden' }) .html( [ data.duration, Ox.formatValue(data.size, 'B'), Math.round(data.bitrate) + ' kbps' ].join(' — ') ) .appendTo($item); return $item; }, itemHeight: 32, keys: ['artwork', 'bitrate', 'checked', 'duration', 'playing', 'size', 'title'] } ], items: artists, list: 'custom', width: window.innerWidth - sidebarSize - 1 }) .bindEvent({ resize: function(data) { $panel.options({width: data.size}) } }); } return $panel; } function albumTrackList() { var $list = Ox.TableList({ columns: [ Ox.getObjectById(columns, 'playing'), Ox.getObjectById(columns, 'checked'), Ox.extend( Ox.getObjectById(columns, 'title'), {width: tracklistSize - 96 - Ox.UI.SCROLLBAR_SIZE} ), Ox.getObjectById(columns, 'duration') ], items: tracks, max: 1, query: {conditions: [], operator: '&'}, scrollbarVisible: true, selected: [], sort: Ox.clone(sort, true), unique: 'file' }) .bindEvent({ resize: function(data) { tracklistSize = data.size; $list.setColumnWidth('title', tracklistSize - 96 - Ox.UI.SCROLLBAR_SIZE); } }); return $list; } function trackAlbumList() { return Ox.IconList({ fixedRatio: 1, item: function(data, sort, size) { var key = Ox.contains(['artist', 'title'], sort[0].key) ? 'year' : sort[0].key, column = Ox.getObjectById(columns, key), info = (column.format || Ox.identity)(data[key]); return { height: size, id: data.id, info: info, title: [data.artist, data.title].join(' — '), url: data.artwork, width: size } }, items: albums, max: 1, orientation: 'horizontal', pageLength: 100, query: {conditions: [], operator: '&'}, selected: [], size: 64, sort: Ox.clone(sort, true), unique: 'id' }); } });