define([
|
'require',
|
'dgrid/List',
|
'dgrid/OnDemandGrid',
|
'dgrid/Selection',
|
'dgrid/Keyboard',
|
'dgrid/extensions/ColumnHider',
|
'dojo/_base/declare',
|
'dojo/_base/array',
|
'dojo/dom-construct',
|
'dojo/Stateful',
|
'dojo/when',
|
'dstore/RequestMemory',
|
'dojo/domReady!'
|
], function (require, List, Grid, Selection, Keyboard, Hider,
|
declare, arrayUtil, domConstruct, Stateful, when, RequestMemory) {
|
// Create DOM
|
var headerNode = domConstruct.create('div', { id: 'header' });
|
var listNode = domConstruct.create('div', { id: 'list-container' });
|
var genresNode = domConstruct.create('div', { id: 'genres' }, listNode);
|
var artistsNode = domConstruct.create('div', { id: 'artists' }, listNode);
|
var albumsNode = domConstruct.create('div', { id: 'albums' }, listNode);
|
var gridNode = domConstruct.create('div', { id: 'grid' });
|
// Use require.toUrl for portability (looking up via module path)
|
var songStore = new RequestMemory({ target: require.toUrl('./data.json') });
|
|
domConstruct.create('div', {
|
id: 'header-content',
|
innerHTML: 'dTuned'
|
}, headerNode);
|
arrayUtil.forEach([ headerNode, listNode, gridNode ], function (node) {
|
document.body.appendChild(node);
|
});
|
|
// a formatting function for the Duration column.
|
function timeFormatter(t) {
|
var tmp = parseInt(t, 10);
|
var min;
|
var sec;
|
|
if (isNaN(tmp)) {
|
return t;
|
}
|
|
min = Math.floor(tmp / 60);
|
sec = tmp % 60;
|
// don't forget to pad seconds.
|
return '' + min + ':' + (sec < 10 ? '0' : '') + sec;
|
}
|
|
function unique(arr) {
|
// Create a unique list of items from the passed array
|
// (removing duplicates).
|
var ret = [];
|
|
// First, set up a hashtable for unique objects.
|
var obj = {};
|
for (var i = 0, l = arr.length; i < l; i++) {
|
if (!(arr[i] in obj)) {
|
obj[arr[i]] = true;
|
}
|
}
|
|
// Now push the unique objects back into an array, and return it.
|
for (var p in obj) {
|
ret.push(p);
|
}
|
ret.sort();
|
return ret;
|
}
|
|
function pickField(fieldName) {
|
return function (object) {
|
return object[fieldName];
|
};
|
}
|
|
// Create the main grid to appear below the genre/artist/album lists.
|
var grid = new (declare([Grid, Selection, Keyboard, Hider]))({
|
collection: songStore,
|
columns: {
|
name: 'Name',
|
time: { label: 'Duration', formatter: timeFormatter },
|
year: 'Year',
|
artist: 'Artist',
|
album: 'Album',
|
genre: 'Genre'
|
}
|
}, gridNode);
|
|
// define a List constructor with the features we want mixed in,
|
// for use by the three lists in the top region
|
var TunesList = declare([List, Selection, Keyboard], {
|
selectionMode: 'single'
|
});
|
|
// define our three lists for the top.
|
var genresList = new TunesList({}, genresNode);
|
var artistsList = new TunesList({}, artistsNode);
|
var albumsList = new TunesList({}, albumsNode);
|
|
// create the unique lists and render them
|
var genres, artists, albums;
|
|
songStore.fetch().then(function (songs) {
|
genres = unique(arrayUtil.map(songs, pickField('genre')));
|
artists = unique(arrayUtil.map(songs, pickField('artist')));
|
albums = unique(arrayUtil.map(songs, pickField('album')));
|
|
genres.unshift('All (' + genres.length + ' Genre' + (genres.length !== 1 ? 's' : '') + ')');
|
artists.unshift('All (' + artists.length + ' Artist' + (artists.length !== 1 ? 's' : '') + ')');
|
albums.unshift('All (' + albums.length + ' Album' + (albums.length !== 1 ? 's' : '') + ')');
|
|
genresList.renderArray(genres);
|
artistsList.renderArray(artists);
|
albumsList.renderArray(albums);
|
});
|
|
// As items are selected in each of the genre, artist, and album dgrid lists the
|
// associated value will be set on this stateful object so the main grid can
|
// watch for updates and filter accordingly
|
var gridFilter = new Stateful();
|
|
// This function is used further down by the select handler for the artists list.
|
// It builds a filtered list of album names depending on the selected genre and artist.
|
function getFilteredAlbumList(gridFilter, songStore, selectedArtist) {
|
var filterOptions = {};
|
|
if (gridFilter.get('genre')) {
|
filterOptions.genre = gridFilter.get('genre');
|
}
|
|
if (selectedArtist) {
|
filterOptions.artist = selectedArtist;
|
}
|
|
return songStore.filter(filterOptions).fetch().then(function (filteredObjects) {
|
var list = unique(arrayUtil.map(filteredObjects, pickField('album')));
|
list.unshift('All (' + list.length +
|
' Album' + (list.length !== 1 ? 's' : '') + ')');
|
return list;
|
});
|
}
|
|
gridFilter.watch(function () {
|
var filter;
|
|
if (this.genre || this.artist || this.album) {
|
filter = {};
|
|
if (this.genre) {
|
filter.genre = this.genre;
|
}
|
if (this.artist) {
|
filter.artist = this.artist;
|
}
|
if (this.album) {
|
filter.album = this.album;
|
}
|
|
grid.set('collection', songStore.filter(filter));
|
}
|
else {
|
if (grid.collection !== songStore) {
|
grid.set('collection', songStore);
|
}
|
}
|
});
|
|
// start listening for selections on the lists.
|
genresList.on('dgrid-select', function (event) {
|
// filter the albums, artists and grid
|
var row = event.rows[0];
|
var selectedGenre = row.data;
|
var filteredArtistList;
|
|
if (row.id === '0') {
|
// remove filtering
|
gridFilter.set('genre', undefined);
|
filteredArtistList = artists;
|
}
|
else {
|
gridFilter.set('genre', selectedGenre);
|
// filter the store on the current genre
|
filteredArtistList = songStore.filter({ genre: selectedGenre }).fetch().then(function (filteredObjects) {
|
// map the full album objects to a unique array of artist names (strings)
|
var list = unique(arrayUtil.map(filteredObjects, pickField('artist')));
|
// add the "All" option at the top
|
list.unshift('All (' + list.length +
|
' Artist' + (list.length !== 1 ? 's' : '') + ')');
|
return list;
|
});
|
}
|
|
when(filteredArtistList, function (list) {
|
artistsList.refresh(); // clear contents
|
artistsList.renderArray(list);
|
artistsList.select('0'); // reselect "all", triggering albums+grid refresh
|
});
|
});
|
|
artistsList.on('dgrid-select', function (event) {
|
// filter the albums, grid
|
var row = event.rows[0];
|
var selectedArtist = row.data;
|
var filteredAlbumList;
|
|
if (row.id === '0') {
|
gridFilter.set('artist', undefined);
|
|
if (gridFilter.get('genre')) {
|
// filter only by genre
|
filteredAlbumList = getFilteredAlbumList(gridFilter, songStore);
|
} else {
|
// remove filtering entirely
|
filteredAlbumList = albums;
|
}
|
}
|
else {
|
// create filter based on artist
|
gridFilter.set('artist', selectedArtist);
|
filteredAlbumList = getFilteredAlbumList(gridFilter, songStore, selectedArtist);
|
}
|
|
when(filteredAlbumList, function (list) {
|
albumsList.refresh(); // clear contents
|
albumsList.renderArray(list);
|
albumsList.select('0'); // reselect "all" item, triggering grid refresh
|
});
|
});
|
|
albumsList.on('dgrid-select', function (event) {
|
// filter the grid
|
var row = event.rows[0];
|
var selectedAlbum = row.data;
|
|
if (row.id === '0') {
|
// show all albums
|
gridFilter.set('album', undefined);
|
} else {
|
gridFilter.set('album', selectedAlbum);
|
}
|
});
|
|
// set the initial selections on the lists.
|
genresList.select('0');
|
});
|