├── sort_asc.png ├── sort_desc.png ├── GPM_Albums_sorted.png ├── GPM_Albums_default.png ├── LICENSE ├── README.md └── google_play_music_album_sorter.user.js /sort_asc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VipSaran/Google-Play-Music-Album-Sorter/HEAD/sort_asc.png -------------------------------------------------------------------------------- /sort_desc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VipSaran/Google-Play-Music-Album-Sorter/HEAD/sort_desc.png -------------------------------------------------------------------------------- /GPM_Albums_sorted.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VipSaran/Google-Play-Music-Album-Sorter/HEAD/GPM_Albums_sorted.png -------------------------------------------------------------------------------- /GPM_Albums_default.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/VipSaran/Google-Play-Music-Album-Sorter/HEAD/GPM_Albums_default.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 VipSaran 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | **Table of Contents** *generated with [DocToc](https://github.com/thlorenz/doctoc)* 4 | 5 | - [Google-Play-Music-Album-Sorter](#google-play-music-album-sorter) 6 | - [Prerequisites](#prerequisites) 7 | - [Installation](#installation) 8 | - [Limitations](#limitations) 9 | - [To-Do](#to-do) 10 | - [Changelog](#changelog) 11 | 12 | 13 | 14 | # Google-Play-Music-Album-Sorter 15 | 16 | Greasemonkey/Tampermonkey UserScript for extending Google Play Music with album sorting functionality. 17 | 18 | Ascending and descending orders are supported, with last used being remembered. 19 | 20 | **Before:** 21 | 22 | ![ScreenShot](GPM_Albums_default.png?raw=true "Default Albums view") 23 | 24 | **After:** 25 | 26 | ![ScreenShot](GPM_Albums_sorted.png?raw=true "Sorted Albums view") 27 | 28 | ## Prerequisites 29 | 30 | To be able to employ the UserScript, your browser needs to have corresponding extensions installed: 31 | 32 | - Chrome: [Tampermonkey](https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo) 33 | - Firefox: [Greasemonkey](https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/) 34 | 35 | 36 | ## Installation 37 | 38 | Once your browser is equipped with appropriate extension, simply open [this link](https://github.com/VipSaran/Google-Play-Music-Album-Sorter/raw/master/google_play_music_album_sorter.user.js). The extension should recognize the script and offer you to install it. 39 | 40 | 41 | ## Limitations 42 | 43 | - works only on standalone "Albums" view 44 | - sorts only by album year 45 | 46 | 47 | ## To-Do 48 | 49 | - after sorting by year, also sort by name (in same order) 50 | - switch between year and name sorting 51 | 52 | ## Changelog 53 | 54 | 1.1.2 55 | 56 | - fix for parsing non-Albums sections 57 | 58 | 1.1.1 59 | 60 | - adapted to material design GPM 61 | 62 | 1.0.1 63 | 64 | - adapted to content div id change 65 | -------------------------------------------------------------------------------- /google_play_music_album_sorter.user.js: -------------------------------------------------------------------------------- 1 | // ==UserScript== 2 | // @name Google Play Music Album Sorter 3 | // @description Greasemonkey/Tampermonkey UserScript for extending Google Play Music with album sorting functionality 4 | // @namespace http://github.com/VipSaran/Google-Play-Music-Album-Sorter 5 | // @updateURL https://github.com/VipSaran/Google-Play-Music-Album-Sorter/raw/master/google_play_music_album_sorter.user.js 6 | // @version 1.2.1 7 | // @author VipSaran 8 | // @require http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js 9 | // @resource sort_asc https://github.com/VipSaran/Google-Play-Music-Album-Sorter/raw/master/sort_asc.png 10 | // @resource sort_desc https://github.com/VipSaran/Google-Play-Music-Album-Sorter/raw/master/sort_desc.png 11 | // @grant GM_getResourceURL 12 | // @include http://play.google.com/music/listen* 13 | // @include https://play.google.com/music/listen* 14 | // @include http://music.google.com/music/listen* 15 | // @include https://music.google.com/music/listen* 16 | // @match http://play.google.com/music/listen* 17 | // @match https://play.google.com/music/listen* 18 | // @match http://music.google.com/music/listen* 19 | // @match https://music.google.com/music/listen* 20 | // @run-at document-end 21 | // ==/UserScript== 22 | 23 | var DEBUG = false; 24 | 25 | var $ = window.jQuery; 26 | 27 | function GooglePlayMusicAlbumSorter() { 28 | if (DEBUG) console.log('GooglePlayMusicAlbumSorter()'); 29 | } 30 | 31 | GooglePlayMusicAlbumSorter.prototype.loadOrder = function () { 32 | if (DEBUG) console.log('GooglePlayMusicAlbumSorter.loadOrder()'); 33 | return window.localStorage.getItem('order'); 34 | }; 35 | 36 | GooglePlayMusicAlbumSorter.prototype.saveOrder = function (order) { 37 | if (DEBUG) console.log('GooglePlayMusicAlbumSorter.saveOrder()'); 38 | 39 | window.localStorage.setItem('order', order); 40 | }; 41 | 42 | var sectionHeaderText = ''; 43 | var sortingInProgress = false; 44 | var domModifiedTimeout; 45 | var domModifiedCallback = function () { 46 | if (DEBUG) console.log('domModifiedCallback()'); 47 | 48 | if (domModifiedTimeout) { 49 | clearTimeout(domModifiedTimeout); 50 | } 51 | 52 | var laneContent = $('#music-content .lane-content'); 53 | if (DEBUG) console.log('laneContent=', laneContent); 54 | 55 | var sectionHeader = $('.header'); 56 | if (sectionHeader) { 57 | sortingInProgress = true; 58 | 59 | var sortOrder = sorter.loadOrder() || 'asc'; 60 | if (DEBUG) console.log('sortOrder=', sortOrder); 61 | 62 | // if (DEBUG) console.log('$(#gpmas_sorter)=', $('#gpmas_sorter').html()); 63 | if ($('#gpmas_sorter').html() === undefined) { 64 | sectionHeader.append(''); 65 | 66 | $('#gpmas_sorter').click(function (event) { 67 | var currClass = $(this).attr('class'); 68 | if (DEBUG) console.log('gpmas_sorter click', currClass); 69 | 70 | $(this).toggleClass('asc desc'); 71 | 72 | currClass = $(this).attr('class'); 73 | if (DEBUG) console.log('gpmas_sorter click', currClass); 74 | 75 | sorter.saveOrder(currClass); 76 | 77 | domModifiedCallback(); 78 | }); 79 | } 80 | 81 | var albums = $("div").find("[data-type='album']").filter(':not(.player-album)'); 82 | if (DEBUG) console.log('albums=', albums); 83 | 84 | albums.sort(function (a, b) { 85 | var aYear = $(a).find("a.sub-title").html(); 86 | var bYear = $(b).find("a.sub-title").html(); 87 | return sortOrder === 'asc' ? aYear - bYear : bYear - aYear; 88 | }); 89 | 90 | laneContent.children("[data-type='album']").fadeOut("fast").promise().done(function () { 91 | laneContent.empty(); 92 | 93 | for (var i = 0; albums.length > 0; i++) { 94 | var album = albums.get(0); 95 | albums.splice(0, 1); 96 | laneContent.append(album); 97 | } 98 | 99 | laneContent.children("[data-type='album']").each(function (i) { 100 | $(this).delay(i * 50).fadeIn("fast"); 101 | }); 102 | 103 | sortingInProgress = false; 104 | }); 105 | } 106 | }; 107 | 108 | GooglePlayMusicAlbumSorter.prototype.init = function () { 109 | if (DEBUG) console.log('GooglePlayMusicAlbumSorter.init()'); 110 | 111 | $('head').append( 112 | '' 117 | ); 118 | 119 | // if (DEBUG) console.log($('#music-content .lane-content')); 120 | $('#music-content').bind("DOMNodeInserted", function (event) { 121 | if (DEBUG) console.log('DOMNodeInserted', event.target.nodeName); 122 | 123 | var element = $(event.target); 124 | if (!(element.hasClass('g-content') || element.hasClass('cluster'))) { 125 | return; 126 | } 127 | 128 | var sectionHeaderTitleText = $('.header .title').html(); 129 | // if (DEBUG) console.log('sectionHeaderTitleText=', sectionHeaderTitleText); 130 | if (sectionHeaderTitleText !== 'Albums') { 131 | return; 132 | } 133 | 134 | if (domModifiedTimeout) { 135 | clearTimeout(domModifiedTimeout); 136 | } 137 | if (sortingInProgress) { 138 | return; 139 | } 140 | domModifiedTimeout = setTimeout(function () { 141 | domModifiedCallback(); 142 | }, 500); 143 | 144 | }); 145 | }; 146 | 147 | var sorter = new GooglePlayMusicAlbumSorter(); 148 | 149 | $(document).ready(function () { 150 | sorter.init(); 151 | }); --------------------------------------------------------------------------------