From 35657f8698bf3c54a3dcd3a403e6de41b6e3449a Mon Sep 17 00:00:00 2001 From: lukeIam Date: Fri, 8 Nov 2013 22:44:30 +0100 Subject: [PATCH] Webserver: - Create/edit/delete playlists in the app - Fixed projektconfiguration (some project builds were disabled) - hide menue lines if the user has no right --- ClientServerLib/ClientServerLib/CServer.cs | 36 ++- .../ClientServerLib/CWebservice.cs | 32 +- .../ClientServerLib/DataStructs.cs | 40 ++- .../ClientServerLib/ICWebservice.cs | 21 +- ClientServerLib/ClientServerLib/UserRights.cs | 7 +- .../ClientServerLib/UserRoleControl.cs | 9 +- Vocaluxe.sln | 6 + Vocaluxe/Base/CConfig.cs | 8 +- Vocaluxe/Base/CPlaylists.cs | 28 +- Vocaluxe/Base/Server/CVocaluxeServer.cs | 80 +++-- Vocaluxe/Lib/Playlist/CPlaylistFile.cs | 30 +- Vocaluxe/Vocaluxe.csproj | 12 + Vocaluxe/Website/css/style.css | 13 +- Vocaluxe/Website/img/addPlaylist.png | Bin 0 -> 3760 bytes Vocaluxe/Website/img/playlists.png | Bin 0 -> 29197 bytes Vocaluxe/Website/index.html | 54 +++- .../Website/js/jquery-ui-1.10.3.custom.min.js | 6 + .../Website/js/jquery.ui.touch-punch.min.js | 11 + Vocaluxe/Website/js/main.js | 292 +++++++++++++++++- 19 files changed, 572 insertions(+), 113 deletions(-) create mode 100644 Vocaluxe/Website/img/addPlaylist.png create mode 100644 Vocaluxe/Website/img/playlists.png create mode 100644 Vocaluxe/Website/js/jquery-ui-1.10.3.custom.min.js create mode 100644 Vocaluxe/Website/js/jquery.ui.touch-punch.min.js diff --git a/ClientServerLib/ClientServerLib/CServer.cs b/ClientServerLib/ClientServerLib/CServer.cs index d115d11f..d2ef677d 100644 --- a/ClientServerLib/ClientServerLib/CServer.cs +++ b/ClientServerLib/ClientServerLib/CServer.cs @@ -84,14 +84,14 @@ namespace ServerLib private static GetAllSongsDelegate _GetAllSongs; public static GetAllSongsDelegate GetAllSongs { - get { return CServer._GetAllSongs; } + internal get { return CServer._GetAllSongs; } set { CServer._GetAllSongs = value; } } private static GetCurrentSongIdDelegate _GetCurrentSongId; public static GetCurrentSongIdDelegate GetCurrentSongId { - get { return CServer._GetCurrentSongId; } + internal get { return CServer._GetCurrentSongId; } set { CServer._GetCurrentSongId = value; } } @@ -103,7 +103,7 @@ namespace ServerLib private static GetPlaylistsDelegate _GetPlaylists; public static GetPlaylistsDelegate GetPlaylists { - get { return _GetPlaylists; } + internal get { return _GetPlaylists; } set { _GetPlaylists = value; } } @@ -111,45 +111,59 @@ namespace ServerLib private static GetPlaylistDelegate _GetPlaylist; public static GetPlaylistDelegate GetPlaylist { - get { return _GetPlaylist; } + internal get { return _GetPlaylist; } set { _GetPlaylist = value; } } private static AddSongToPlaylistDelegate _AddSongToPlaylist; public static AddSongToPlaylistDelegate AddSongToPlaylist { - get { return _AddSongToPlaylist; } + internal get { return _AddSongToPlaylist; } set { _AddSongToPlaylist = value; } } private static RemoveSongFromPlaylistDelegate _RemoveSongFromPlaylist; public static RemoveSongFromPlaylistDelegate RemoveSongFromPlaylist { - get { return _RemoveSongFromPlaylist; } + internal get { return _RemoveSongFromPlaylist; } set { _RemoveSongFromPlaylist = value; } } private static MoveSongInPlaylistDelegate _MoveSongInPlaylist; public static MoveSongInPlaylistDelegate MoveSongInPlaylist { - get { return _MoveSongInPlaylist; } + internal get { return _MoveSongInPlaylist; } set { _MoveSongInPlaylist = value; } } private static PlaylistContainsSongDelegate _PlaylistContainsSong; public static PlaylistContainsSongDelegate PlaylistContainsSong { - get { return _PlaylistContainsSong; } + internal get { return _PlaylistContainsSong; } set { _PlaylistContainsSong = value; } } private static GetPlaylistSongsDelegate _GetPlaylistSongs; public static GetPlaylistSongsDelegate GetPlaylistSongs { - get { return _GetPlaylistSongs; } + internal get { return _GetPlaylistSongs; } set { _GetPlaylistSongs = value; } } + private static RemovePlaylistDelegate _RemovePlaylist; + public static RemovePlaylistDelegate RemovePlaylist + { + internal get { return _RemovePlaylist; } + set { _RemovePlaylist = value; } + } + + private static AddPlaylistDelegate _AddPlaylist; + public static AddPlaylistDelegate AddPlaylist + { + internal get { return _AddPlaylist; } + set { _AddPlaylist = value; } + } + #endregion #region user management @@ -188,9 +202,9 @@ namespace ServerLib internal get { return CServer._GetUserIdFromUsername; } set { CServer._GetUserIdFromUsername = value; } } - - + #endregion + public CServer(int port, bool encrypted) { _Init(port, encrypted); diff --git a/ClientServerLib/ClientServerLib/CWebservice.cs b/ClientServerLib/ClientServerLib/CWebservice.cs index d5d63d70..15990d3c 100644 --- a/ClientServerLib/ClientServerLib/CWebservice.cs +++ b/ClientServerLib/ClientServerLib/CWebservice.cs @@ -301,7 +301,7 @@ namespace ServerLib public void AddSongToPlaylist(int songId, int playlistId, bool allowDuplicates) { - if (_CheckRight(EUserRights.AddSongToPlaylist) || _CheckRight(EUserRights.EditPlaylists)) + if (_CheckRight(EUserRights.AddSongToPlaylist)) { CServer.AddSongToPlaylist(songId, playlistId, allowDuplicates); } @@ -309,17 +309,17 @@ namespace ServerLib public void RemoveSongFromPlaylist(int position, int playlistId, int songId) { - if (_CheckRight(EUserRights.EditPlaylists)) + if (_CheckRight(EUserRights.RemoveSongsFromPlaylists)) { CServer.RemoveSongFromPlaylist(position, playlistId, songId); } } - public void MoveSongInPlaylist(int oldPosition, int newPosition, int playlistId, int songId) + public void MoveSongInPlaylist(int newPosition, int playlistId, int songId) { - if (_CheckRight(EUserRights.EditPlaylists)) + if (_CheckRight(EUserRights.ReorderPlaylists)) { - CServer.MoveSongInPlaylist(oldPosition, newPosition, playlistId, songId); + CServer.MoveSongInPlaylist(newPosition, playlistId, songId); } } @@ -333,9 +333,21 @@ namespace ServerLib return CServer.GetPlaylistSongs(playlistId); } - public bool IsPlaylistEditable(int playlistId) + public void RemovePlaylist(int playlistId) { - return _CheckRight(EUserRights.EditPlaylists); + if (_CheckRight(EUserRights.DeletePlaylists)) + { + CServer.RemovePlaylist(playlistId); + } + } + + public int AddPlaylist(string playlistName) + { + if (_CheckRight(EUserRights.CreatePlaylists)) + { + return CServer.AddPlaylist(playlistName); + } + return -1; } #endregion @@ -354,6 +366,11 @@ namespace ServerLib CServer.SetUserRole(profileId, userRole); } } + + public bool HasUserRight(int right) + { + return _CheckRight((EUserRights)right); + } private static bool _CheckRight(EUserRights requestedRight) { @@ -382,5 +399,6 @@ namespace ServerLib } #endregion + } } diff --git a/ClientServerLib/ClientServerLib/DataStructs.cs b/ClientServerLib/ClientServerLib/DataStructs.cs index 298fbba1..cf52fd80 100644 --- a/ClientServerLib/ClientServerLib/DataStructs.cs +++ b/ClientServerLib/ClientServerLib/DataStructs.cs @@ -108,20 +108,7 @@ namespace ServerLib public delegate SSongInfo[] GetAllSongsDelegate(); public delegate int GetCurrentSongIdDelegate(); - - public delegate SPlaylistInfo[] GetPlaylistsDelegate(); - - public delegate SPlaylistInfo GetPlaylistDelegate(int playlistId); - - public delegate void AddSongToPlaylistDelegate(int songId, int playlistId, bool allowDuplicates); - - public delegate void RemoveSongFromPlaylistDelegate(int position, int playlistId, int songId); - - public delegate void MoveSongInPlaylistDelegate(int oldPosition, int newPosition, int playlistId, int songId); - - public delegate bool PlaylistContainsSongDelegate(int songId, int playlistId); - - public delegate SPlaylistSongInfo[] GetPlaylistSongsDelegate(int playlistId); + [DataContract] public struct SSongInfo @@ -144,6 +131,28 @@ namespace ServerLib public int SongId { get; set; } } + #endregion + + #region playlists + public delegate SPlaylistInfo[] GetPlaylistsDelegate(); + + public delegate SPlaylistInfo GetPlaylistDelegate(int playlistId); + + public delegate void AddSongToPlaylistDelegate(int songId, int playlistId, bool allowDuplicates); + + public delegate void RemoveSongFromPlaylistDelegate(int position, int playlistId, int songId); + + public delegate void MoveSongInPlaylistDelegate(int newPosition, int playlistId, int songId); + + public delegate bool PlaylistContainsSongDelegate(int songId, int playlistId); + + public delegate SPlaylistSongInfo[] GetPlaylistSongsDelegate(int playlistId); + + public delegate void RemovePlaylistDelegate(int playlistId); + + public delegate int AddPlaylistDelegate(string playlistName); + + [DataContract] public struct SPlaylistSongInfo { [DataMember] @@ -155,7 +164,8 @@ namespace ServerLib [DataMember] public int GameMode; } - + + [DataContract] public struct SPlaylistInfo { [DataMember] diff --git a/ClientServerLib/ClientServerLib/ICWebservice.cs b/ClientServerLib/ClientServerLib/ICWebservice.cs index 3a6e3326..92e1a76a 100644 --- a/ClientServerLib/ClientServerLib/ICWebservice.cs +++ b/ClientServerLib/ClientServerLib/ICWebservice.cs @@ -150,8 +150,8 @@ namespace ServerLib [OperationContract] [WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, - UriTemplate = "/moveSongInPlaylist?oldPosition={oldPosition}&newPosition={newPosition}&playlistId={playlistId}&songId={songId}")] - void MoveSongInPlaylist(int oldPosition, int newPosition, int playlistId, int songId); + UriTemplate = "/moveSongInPlaylist?newPosition={newPosition}&playlistId={playlistId}&songId={songId}")] + void MoveSongInPlaylist(int newPosition, int playlistId, int songId); [OperationContract] [WebInvoke(Method = "GET", @@ -166,9 +166,14 @@ namespace ServerLib SPlaylistSongInfo[] GetPlaylistSongs(int playlistId); [OperationContract, WebInvoke(Method = "GET", - ResponseFormat = WebMessageFormat.Json, - UriTemplate = "/isPlaylistEditable?playlistId={playlistId}")] - bool IsPlaylistEditable(int playlistId); + ResponseFormat = WebMessageFormat.Json, + UriTemplate = "/removePlaylist?playlistId={playlistId}")] + void RemovePlaylist(int playlistId); + + [OperationContract, WebInvoke(Method = "GET", + ResponseFormat = WebMessageFormat.Json, + UriTemplate = "/addPlaylist?playlistName={playlistName}")] + int AddPlaylist(string playlistName); #endregion @@ -186,6 +191,12 @@ namespace ServerLib UriTemplate = "/setUserRole?profileId={profileId}&userRole={userRole}")] void SetUserRole(int profileId, int userRole); + [OperationContract] + [WebInvoke(Method = "GET", + ResponseFormat = WebMessageFormat.Json, + UriTemplate = "/hasUserRight?right={right}")] + bool HasUserRight(int right); + #endregion } } \ No newline at end of file diff --git a/ClientServerLib/ClientServerLib/UserRights.cs b/ClientServerLib/ClientServerLib/UserRights.cs index 14c874f0..246ca978 100644 --- a/ClientServerLib/ClientServerLib/UserRights.cs +++ b/ClientServerLib/ClientServerLib/UserRights.cs @@ -10,7 +10,10 @@ namespace ServerLib UploadPhotos = 0x02, ViewOtherProfiles = 0x04, UseKeyboard = 0x08, - EditPlaylists = 0x16, - AddSongToPlaylist = 0x32 + ReorderPlaylists = 0x16, + AddSongToPlaylist = 0x32, + CreatePlaylists = 0x64, + DeletePlaylists = 0x128, + RemoveSongsFromPlaylists = 0x256 } } diff --git a/ClientServerLib/ClientServerLib/UserRoleControl.cs b/ClientServerLib/ClientServerLib/UserRoleControl.cs index 3c5eaa0e..5af1a6ba 100644 --- a/ClientServerLib/ClientServerLib/UserRoleControl.cs +++ b/ClientServerLib/ClientServerLib/UserRoleControl.cs @@ -9,8 +9,13 @@ namespace ServerLib {EUserRoles.Administrator, (EUserRights.EditAllProfiles| EUserRights.UploadPhotos| - EUserRights.ViewOtherProfiles)| - EUserRights.UseKeyboard}, + EUserRights.ViewOtherProfiles| + EUserRights.UseKeyboard| + EUserRights.AddSongToPlaylist| + EUserRights.ReorderPlaylists| + EUserRights.CreatePlaylists| + EUserRights.DeletePlaylists| + EUserRights.RemoveSongsFromPlaylists)}, {EUserRoles.AuthenticatedUser, (EUserRights.UploadPhotos| EUserRights.ViewOtherProfiles| diff --git a/Vocaluxe.sln b/Vocaluxe.sln index 16d994af..ccccbf04 100644 --- a/Vocaluxe.sln +++ b/Vocaluxe.sln @@ -189,24 +189,28 @@ Global {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugLinux|Mixed Platforms.ActiveCfg = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugLinux|Mixed Platforms.Build.0 = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugLinux|x64.ActiveCfg = Debug|Any CPU + {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugLinux|x64.Build.0 = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugLinux|x86.ActiveCfg = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|Any CPU.ActiveCfg = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|Any CPU.Build.0 = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|Mixed Platforms.ActiveCfg = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|Mixed Platforms.Build.0 = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|x64.ActiveCfg = Debug|Any CPU + {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|x64.Build.0 = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.DebugWin|x86.ActiveCfg = Debug|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|Any CPU.ActiveCfg = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|Any CPU.Build.0 = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|Mixed Platforms.ActiveCfg = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|Mixed Platforms.Build.0 = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|x64.ActiveCfg = Release|Any CPU + {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|x64.Build.0 = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseLinux|x86.ActiveCfg = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseWin|Any CPU.ActiveCfg = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseWin|Any CPU.Build.0 = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseWin|Mixed Platforms.ActiveCfg = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseWin|Mixed Platforms.Build.0 = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseWin|x64.ActiveCfg = Release|Any CPU + {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseWin|x64.Build.0 = Release|Any CPU {EC5167E4-CCFB-4CEE-987C-CF816F1062A3}.ReleaseWin|x86.ActiveCfg = Release|Any CPU {55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugLinux|Any CPU.ActiveCfg = Debug|Any CPU {55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugLinux|Any CPU.Build.0 = Debug|Any CPU @@ -218,6 +222,7 @@ Global {55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugWin|Mixed Platforms.ActiveCfg = Debug|Any CPU {55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugWin|Mixed Platforms.Build.0 = Debug|Any CPU {55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugWin|x64.ActiveCfg = Debug|Any CPU + {55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugWin|x64.Build.0 = Debug|Any CPU {55F89808-4E79-4FFE-BC13-48258913F5C9}.DebugWin|x86.ActiveCfg = Debug|Any CPU {55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseLinux|Any CPU.ActiveCfg = Release|Any CPU {55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseLinux|Any CPU.Build.0 = Release|Any CPU @@ -229,6 +234,7 @@ Global {55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|Mixed Platforms.ActiveCfg = Release|Any CPU {55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|Mixed Platforms.Build.0 = Release|Any CPU {55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|x64.ActiveCfg = Release|Any CPU + {55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|x64.Build.0 = Release|Any CPU {55F89808-4E79-4FFE-BC13-48258913F5C9}.ReleaseWin|x86.ActiveCfg = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution diff --git a/Vocaluxe/Base/CConfig.cs b/Vocaluxe/Base/CConfig.cs index 9902d6b9..b350c067 100644 --- a/Vocaluxe/Base/CConfig.cs +++ b/Vocaluxe/Base/CConfig.cs @@ -124,7 +124,7 @@ namespace Vocaluxe.Base public static EOffOn ServerActive = EOffOn.TR_CONFIG_OFF; public static EOffOn ServerEncryption = EOffOn.TR_CONFIG_OFF; public static int ServerPort = 3000; - public static string ServerPassword = "vocaluxe"; + //public static string ServerPassword = "vocaluxe"; //Lists to save parameters and values private static readonly List _Params = new List(); @@ -299,7 +299,7 @@ namespace Vocaluxe.Base if (ServerPort < 1 || ServerPort > 65535) ServerPort = 3000; - xmlReader.GetValue("//root/Server/ServerPassword", out ServerPassword, ServerPassword); + //xmlReader.GetValue("//root/Server/ServerPassword", out ServerPassword, ServerPassword); #endregion Server } @@ -573,8 +573,8 @@ namespace Vocaluxe.Base writer.WriteComment("Server Port (default: 3000) [1..65535]"); writer.WriteElementString("ServerPort", ServerPort.ToString()); - writer.WriteComment("Server Password (default: vocaluxe)"); - writer.WriteElementString("ServerPassword", ServerPassword); + //writer.WriteComment("Server Password (default: vocaluxe)"); + //writer.WriteElementString("ServerPassword", ServerPassword); writer.WriteEndElement(); #endregion Server diff --git a/Vocaluxe/Base/CPlaylists.cs b/Vocaluxe/Base/CPlaylists.cs index 2c9e2d6a..9f0793c1 100644 --- a/Vocaluxe/Base/CPlaylists.cs +++ b/Vocaluxe/Base/CPlaylists.cs @@ -1,18 +1,18 @@ -#region license -// This file is part of Vocaluxe. +#region license +// This file is part of Vocaluxe. // -// Vocaluxe is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // -// Vocaluxe is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. // -// You should have received a copy of the GNU General Public License -// along with Vocaluxe. If not, see . +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . #endregion using System; @@ -77,7 +77,7 @@ namespace Vocaluxe.Base foreach (string file in files) { - var playlist = new CPlaylistFile(file); + CPlaylistFile playlist = new CPlaylistFile(file, files.IndexOf(file)); _Playlists.Add(playlist); } } @@ -125,7 +125,7 @@ namespace Vocaluxe.Base public static int NewPlaylist() { - var pl = new CPlaylistFile {PlaylistName = "New Playlist"}; + CPlaylistFile pl = new CPlaylistFile { PlaylistName = "New Playlist", Id = _Playlists.Count }; _Playlists.Add(pl); return _Playlists.Count - 1; } diff --git a/Vocaluxe/Base/Server/CVocaluxeServer.cs b/Vocaluxe/Base/Server/CVocaluxeServer.cs index cfaf864e..879fcb4d 100644 --- a/Vocaluxe/Base/Server/CVocaluxeServer.cs +++ b/Vocaluxe/Base/Server/CVocaluxeServer.cs @@ -47,7 +47,6 @@ namespace Vocaluxe.Base.Server _Clients = new Dictionary(); _Server = new CServer(CConfig.ServerPort, CConfig.ServerEncryption == EOffOn.TR_CONFIG_ON); - //TODO: remove CConfig.ServerPassword CServer.SendKeyEvent = _SendKeyEvent; CServer.GetProfileData = _GetProfileData; @@ -64,6 +63,15 @@ namespace Vocaluxe.Base.Server CServer.SetUserRole = _SetUserRole; CServer.GetUserIdFromUsername = _GetUserIdFromUsername; CServer.GetDelayedImage = _GetDelayedImage; + CServer.GetPlaylists = _GetPlaylists; + CServer.GetPlaylist = _GetPlaylist; + CServer.AddSongToPlaylist = _AddSongToPlaylist; + CServer.RemoveSongFromPlaylist = _RemoveSongFromPlaylist; + CServer.MoveSongInPlaylist = _MoveSongInPlaylist; + CServer.PlaylistContainsSong = _PlaylistContainsSong; + CServer.GetPlaylistSongs = _GetPlaylistSongs; + CServer.RemovePlaylist = _RemovePlaylist; + CServer.AddPlaylist = _AddPlaylist; _Discover = new CDiscover(CConfig.ServerPort, CCommands.BroadcastKeyword); Controller.Init(); @@ -432,31 +440,32 @@ namespace Vocaluxe.Base.Server #region playlist - public static SPlaylistInfo[] GetPlaylists() + private static SPlaylistInfo[] _GetPlaylists() { return (from p in CPlaylists.Playlists select _GetPlaylistInfo(p)).ToArray(); } - public static SPlaylistInfo GetPlaylist(int playlistId) + private static SPlaylistInfo _GetPlaylist(int playlistId) { - if (CPlaylists.Playlists.Length <= playlistId) + if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0) { throw new ArgumentException("invalid playlistId"); } return _GetPlaylistInfo(CPlaylists.Playlists[playlistId]); } - public static void AddSongToPlaylist(int songId, int playlistId, bool allowDuplicates) + private static void _AddSongToPlaylist(int songId, int playlistId, bool allowDuplicates) { - if (CPlaylists.Playlists.Length <= playlistId) + if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0) { throw new ArgumentException("invalid playlistId"); } - if (allowDuplicates || PlaylistContainsSong(songId, playlistId)) + if (allowDuplicates || !_PlaylistContainsSong(songId, playlistId)) { CPlaylists.AddPlaylistSong(playlistId, songId); + CPlaylists.SavePlaylist(playlistId); } else { @@ -464,57 +473,58 @@ namespace Vocaluxe.Base.Server } } - public static void RemoveSongFromPlaylist(int position, int playlistId, int songId) + private static void _RemoveSongFromPlaylist(int position, int playlistId, int songId) { - if (CPlaylists.Playlists.Length <= playlistId) + if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0) { throw new ArgumentException("invalid playlistId"); } - if (!PlaylistContainsSong(songId, playlistId)) + if (!_PlaylistContainsSong(songId, playlistId)) { throw new ArgumentException("invalid songId"); } - if (CPlaylists.Playlists[playlistId].Songs.Count <= position || CPlaylists.Playlists[playlistId].Songs[position].SongID != songId) + if (position < 0 || CPlaylists.Playlists[playlistId].Songs.Count <= position + || CPlaylists.Playlists[playlistId].Songs[position].SongID != songId) { throw new ArgumentException("invalid position"); } CPlaylists.Playlists[playlistId].DeleteSong(position); + CPlaylists.SavePlaylist(playlistId); } - public static void MoveSongInPlaylist(int oldPosition, int newPosition, int playlistId, int songId) + private static void _MoveSongInPlaylist(int newPosition, int playlistId, int songId) { - if (CPlaylists.Playlists.Length <= playlistId) + if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0) { throw new ArgumentException("invalid playlistId"); } - if (!PlaylistContainsSong(songId, playlistId)) + if (!_PlaylistContainsSong(songId, playlistId)) { throw new ArgumentException("invalid songId"); } - if (CPlaylists.Playlists[playlistId].Songs.Count <= oldPosition || CPlaylists.Playlists[playlistId].Songs[oldPosition].SongID != songId) - { - throw new ArgumentException("invalid oldPosition"); - } - if (CPlaylists.Playlists[playlistId].Songs.Count < newPosition ) + + if (CPlaylists.Playlists[playlistId].Songs.Count < newPosition) { throw new ArgumentException("invalid newPosition"); } - CPlaylists.MovePlaylistSong(playlistId,oldPosition, newPosition); + int oldPosition = CPlaylists.Playlists[playlistId].Songs.FindIndex(s => s.SongID == songId); + CPlaylists.MovePlaylistSong(playlistId, oldPosition, newPosition); + CPlaylists.SavePlaylist(playlistId); } - public static bool PlaylistContainsSong(int songId, int playlistId) + private static bool _PlaylistContainsSong(int songId, int playlistId) { - if (CPlaylists.Playlists.Length <= playlistId) + if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0) { throw new ArgumentException("invalid playlistId"); } return CPlaylists.Playlists[playlistId].Songs.Any(s => s.SongID == songId); } - public static SPlaylistSongInfo[] GetPlaylistSongs(int playlistId) + private static SPlaylistSongInfo[] _GetPlaylistSongs(int playlistId) { - if (CPlaylists.Playlists.Length <= playlistId) + if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0) { throw new ArgumentException("invalid playlistId"); } @@ -540,7 +550,7 @@ namespace Vocaluxe.Base.Server SPlaylistSongInfo[] result = new SPlaylistSongInfo[playlist.Songs.Count]; for (int i = 0; i < playlist.Songs.Count; i++) { - result[i] = _GetPlaylistSongInfo(playlist.Songs[i], 1 /*TODO:PlaylistID???*/, i); + result[i] = _GetPlaylistSongInfo(playlist.Songs[i], playlist.Id, i); } return result; } @@ -549,13 +559,31 @@ namespace Vocaluxe.Base.Server { return new SPlaylistInfo { - PlaylistId = 1, /*TODO: PlaylistId*/ + PlaylistId = playlist.Id, PlaylistName = playlist.PlaylistName, SongCount = playlist.Songs.Count, LastChanged = DateTime.Now.ToLongDateString() }; } + private static void _RemovePlaylist(int playlistId) + { + if (CPlaylists.Playlists.Length <= playlistId || playlistId < 0) + { + throw new ArgumentException("invalid playlistId"); + } + CPlaylists.DeletePlaylist(playlistId); + } + + private static int _AddPlaylist(string playlistName) + { + int newPlaylistId = CPlaylists.NewPlaylist(); + CPlaylists.Playlists[newPlaylistId].PlaylistName = playlistName; + CPlaylists.SavePlaylist(newPlaylistId); + + return newPlaylistId; + } + #endregion #region user management diff --git a/Vocaluxe/Lib/Playlist/CPlaylistFile.cs b/Vocaluxe/Lib/Playlist/CPlaylistFile.cs index d40234e9..58d2f575 100644 --- a/Vocaluxe/Lib/Playlist/CPlaylistFile.cs +++ b/Vocaluxe/Lib/Playlist/CPlaylistFile.cs @@ -1,18 +1,18 @@ -#region license -// This file is part of Vocaluxe. +#region license +// This file is part of Vocaluxe. // -// Vocaluxe is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. +// Vocaluxe is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // -// Vocaluxe is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. +// Vocaluxe is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. // -// You should have received a copy of the GNU General Public License -// along with Vocaluxe. If not, see . +// You should have received a copy of the GNU General Public License +// along with Vocaluxe. If not, see . #endregion using System; @@ -31,6 +31,7 @@ namespace Vocaluxe.Lib.Playlist { public string PlaylistName; public string PlaylistFile; + public int Id = -1; public List Songs = new List(); public CPlaylistFile() @@ -39,8 +40,9 @@ namespace Vocaluxe.Lib.Playlist PlaylistFile = string.Empty; } - public CPlaylistFile(string file) + public CPlaylistFile(string file, int id) { + Id = id; PlaylistFile = file; _LoadPlaylist(); } @@ -217,7 +219,7 @@ namespace Vocaluxe.Lib.Playlist if (destNr < 0 || destNr > Songs.Count - 1) return; - var ps = new CPlaylistSong(songID, gm); + CPlaylistSong ps = new CPlaylistSong(songID, gm); Songs.Insert(destNr, ps); } } diff --git a/Vocaluxe/Vocaluxe.csproj b/Vocaluxe/Vocaluxe.csproj index 622735f7..5505580c 100644 --- a/Vocaluxe/Vocaluxe.csproj +++ b/Vocaluxe/Vocaluxe.csproj @@ -343,6 +343,9 @@ css PreserveNewest + + PreserveNewest + PreserveNewest @@ -355,6 +358,9 @@ PreserveNewest + + PreserveNewest + PreserveNewest @@ -391,10 +397,16 @@ PreserveNewest js + + PreserveNewest + js PreserveNewest + + PreserveNewest + js PreserveNewest diff --git a/Vocaluxe/Website/css/style.css b/Vocaluxe/Website/css/style.css index f568b912..e3210c83 100644 --- a/Vocaluxe/Website/css/style.css +++ b/Vocaluxe/Website/css/style.css @@ -50,10 +50,10 @@ text-align: center; } -#displaySongContent span { - font-size: 18px; - font-weight: bold; -} + #displaySongContent span { + font-size: 18px; + font-weight: bold; + } .imageLoaderImg { height: 100%; @@ -80,3 +80,8 @@ -webkit-border-radius: 0px !important; border-radius: 0px !important; } + +.cursorStyleClickable { + cursor: pointer; +} + diff --git a/Vocaluxe/Website/img/addPlaylist.png b/Vocaluxe/Website/img/addPlaylist.png new file mode 100644 index 0000000000000000000000000000000000000000..acdfe91c2409ce3a9b8709f0fc62bdcf5fcdacfd GIT binary patch literal 3760 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 z z3z5^!^4@?V+r3p%f2E4>*8|Yg$P2hDgQ@?d1i=l6b&2+Rh={&{ZRT|p`j{*aaes;G zt2~pYu)rSkUg4E7g+W*>Mx^A!2UZ*4c}L^=oPud*QG|OHrfV=y7l_dHnZ|>6?60=2 z|5U3Wm!bljc2LmZsCjc+wEuko_)4|>{YqY`n>Lu_wgc&)5i2Xym6pgLYw*73jr@60 z@A1cY`Ed19V)?#U5U|nDprgUoyP5V??Jq>^9Hlw@%I-dqW_ZYZ+q!-`-6u_i6_>st z+qdO)9Y;HdQdeBiY$D# zk$=<{82yv>09okl!~gm?Knug@0C1NsR9NZ5%cHpAwls5@7Xo%RS8W6Rq$MNl#&30m zQ8V0Rg2aKsgOTij?}KOB-@}M8Z04o$Ap;6U?oNjk;;m1*h z@Yhs-+r}WZ{{S_vsNOHjjD%Q$v}Z*@(GxHtI+;iZfot6Xj3ro_2pTLaf)1V>_LUE< ztb$rm?!l;q47`*BJzu59=CEOeeCcwOy194IDlWB(B7}f1wTtDOqqN!Wmj^^=r8Bve z9|_r_$j0BdX7>si_b=$Q-%BLbGZ1DU3nP+5XEcyn$5;+MsBalz2hV&^9p9Nm?L51~!ZU3>QmcEq+KXc(l$zSw^K@Ckd=zlB=TkqEi`A$y2meb( ziVv&oth94zJJ5Nj7`7>@TZ%p|_IWMG&{y4;S%v^y^(WtHj9RSqMjgqmO=L z4yQML&=Fut(%iyAgS@AgRKRI3$p1PL972Q#t04nRMCT@8=&b-{=KeI-xd$09$8{_6 z3|mhRydU#SIzdh!3yeANA3Wit_N179Vq-MEyT(^wSo)jGr)aR~-5`ayBw3ZMH2NNY z1=@1;G;YsLK=31_7r@HE>{PLY1Vaea>p4>MLcxV%O`=xPy@hh3 z461)S#69R!rMk2yS>+8Zzx@{dd-Och#Pfk?YZVDtWDZ9Jg9O*j4x_dYH_3agu9D}^ zM1;aXAIhw3xU>rixJ*gMUNf4f632E)2>BlyR_FDtwdZZrH*27vIAxL~`bdGl(xEE7 zX8MC!F(^3!)F@2aPZPK;22yB`qQA(GTBVVKCbLqJ8>V97Ud8LO!!865CW72SZoi@Nn}}&$xpqZ=SCotOd0NY_0xq%_taSA@x>HGi9#r0l8DLXE>|yelr(ThpSNXcIa(;T_b!*wgYud#y)tE&!wP2K^O~9Q!qmqm?4& z-Qg<*UE(;}PQ^lL7U8gkOT=;Qc2n#Fo!aJh64Qq_PKp$8${I*Q7%ICyer@j@LQOBJ zm)oeC(R__&-kDy#|NX-(iKswbII4s!7? zu&BxqE7a`%UblT7+_&I{DxdrZxEUvlLu=Yxhg-1vJnrfU;vr4m1g?)yQ2Bb@o0qQb zyu4fw?^`FHtsG>1FSE-OuT4e~W-B^gLJ#{nY_o%;+VtzLo1Mu~fFSnF$6=%@deHFR~pjGoG%5opZO;xqH|=tGK!C$srA zR)F7GnI7wJ_%Z4(dHmQoOCyErXg`L3H3)d?E_3)Ul~6Jf;yw|t*Nr`~XFA>GE)G6* z32jfWvylDrWA3ehq;j5vqfN?t1)PrxOQH4=S3IXao@SCeNA~!GDJEl=eDKoq{Q|`- zL|%9-OtXsVNV$ROS-rw4!%vjDo*Pq+GCqn9QSb%A%ZWXlbd)?b>UjUBh-YQ;9ast| zRD6!)N~$oWHXHlC7GT1&-Mbf;?IB+eN$XufG*#_|)2r?7Qi65~L$4Pn z)U-JtKG}6_mnjL>(9`i`UB*>~x7ova(!VV|5(#4v7I@Kl;VPIkQB+zL_AsL>NAE46 zdn-0u$t#ER-l1;u6I)qK=sgcB*5f5y;@DGs9Ng>Iqs>eK7e(rL3jrH+Rz_1 zAJzFe-I;RkBVTri3w|BVn+YUG7D8A}$yK#8xz<%TgLF&^8QTON zj8^sZOR(DUUA=$Txhc8d>jE9n4}E(HKUK`4#euIrbIc+$2jx z<7?8g9Yt-8w{`Q8hSxD@vFE*VD()(<>rp^;A+V1ZetoBtHdvq(p=DhJH4dBIYiJ7@ zke?kDviK&*_5R?7@tD~yJNx8%|B~H1+^4$B>}#9P_8{0E)Udi+A-@@mfRFI%;OGV_ zsQjln934(DX30sc!#|cmxv}-ZbIxEJno;j{wfw63zs3HkFsy%K1M9uDGU|T3L4)0o z`Tg;k8@gO4R9tG+*ou!>vPsXCu_RB^o^UcsJ^Et$t$1%~@vYn)t?(e(Z3n{xqWP47}zQ(LgoI1rrYkmpr zQb=Ds6|V4Z?&&zx-?J_MpV+m-7UtXsfsJi-Ni&C6v6=?urKr^epQA3!p83u3HL<7m z^S^3Vp8aIOodE@{q(mx7=5(*h-gk>Kzn2t>c!?3plRvb>-H>1+ejZrj1EORm>6_kG z^~Fx7qAtgBS1BeuaBkS>u{v(n0<2?&sX=A}eFt z&16E%?gOzW!0pRe!%Io0Rq`}c>KHmbjDF&nYUg;X%UX1Hky zUMgwMu!czctK>-&pXk;@5ujACRyUCGWibqiA&z%HBpCax4Lzle>FGCRMD(kYtLHJ}T`W|;93Ju8LlD6Xz8KGJ`|JXUtUoh`W?fcl7&(`wBOVvK zCneYf{Rve<=rlczNNBb7SN-zrZF$Ejk=X%W z9DTzOo+s!2v4xa;ThV0hOE2tmuYk!JePmLm>^CdJ_;xv1Y za8b?*<$OHu@{&x_M;>3PPSe?QO8l@Ww0*PNq%jAO=bV-n%XpMS=A-_LFMYPAd{SwJ z9QP&A`>bTkkW^6D#74RAxQox@^s@mAETnwsk0q%mMjVFMe{QGI2DWlS%K zH2I98JxM5G4<33NA0w=n^pjvU1RmEIU{zrly7YpZrDpEnw+`fRqiEV}_Wj)3IS)Sx z-I|bEt5ho86p~i;eu%#q;uM_#pMKJ~(DoE0IJ|fDc>wiDjb&+GN+lC{>~m)LEyBB7 zFbehPc|y}FL%5a+_Lq+hoVXkQQC;^FaN%0_JG2n}=zKl6u-0=Imy1_60#|q5{nwgj zW7u?*y{Rk`lEPtvMY4lQ@jLQQLNMHFzJK38He>V1zoaB7NTC%Ij>CwFe`15XktQhk zHQR=#^S&9PmM}L~ZN%jQ{t<jNbu!dM5@3MG;Y(pzZQmib+{%S?OC4P9Mi-I1g45mFy#^KpCU? zI7a7Y74xP4n+f)vQ;h7E<@nYR%H*@-r4uUw$|UexBnlydtTW+5s3 zFLdUjDL%R%yCJKTnXeeNW7h$HKlRWpsnR7jRPb_USGaoKpnCUlUCijQEZ|h~pC(y_ z<2??>si(rANT=U@=zTFw{vH6Sy+d)FUS}DI(ZGs{2q?Zsg&~oexVR7_tOl>}E2kI$ z+1y2G6ch;>mJ;KhUJ3hxxS#_5JETYmGUT|&BLNnToMnIj%s|=_9zwk|@s$`@xhIVt zWdl=YplcutX{1AVaS;ZZWGL4>tk{K9Iowei=V{-f?q`VTaa%OhK;ryLt#4_P|>&6a|m!z z>$A54gzz3M-{jRoPeJT&ElWXLBFLtDRi*h^{~bV~ViHI-&<&3buy%FN= zin@~g776Sh5v@^*b#=A10IhG}-2F2OU#*w@C~2;>t|!g{8s<&U1EteEe3P{lRm~ z$C^5epqhW0q8q5<4W9F-CV#NL08{OwEc+yjFffl)N=0aS8u6Fqft=CE)j$kqd=B;H zInV3O9m>v@r00N^HF5N9fX`cb4?H8d=2+o~z>|%{L#=*G;+GE`zYhFeSya+q*#X^r z0}F`6&|RtW=hl*i283$jBm*5dc1l{Q=CpCrfHdMr&eN1rorli77MBD9sc3PA8m{-8 z-;XScp&JrWj;L`-b^(o}fCsi6zMS|=Vr)RLME|D-@rHeV&RxAqfB1GN+L?s+9>310 znaRA$+7WlN5}9NSWCTH1*w2GC1%r1!NkKtY5mRFALS8E(RZNt$rO{aac;6voRp3i8 zw6A|~+WBvg^lEX&G6!O8?TX98E0J}5<`3~5?kO}tIwC`G1-;zL-j0V(_irgak#Wi9 zXYT)d4LOps`#eIZjQaP<%6?lG4x2I`;HX|Eh?XbE6fu7s5+q9$)}*r0XPs$swVELr zZ-!VnBWQzb4evop;r8+WPhe|=-Nfz$RkFs(ao8P8R!;JKIvkp`uh8>j#F!Ni-(F6f z9c6VBms!Hc2)A!=6O5l82MlvzFQQDKgq1J*J9El3$qxHN3Y~E(1ozR(>xlD;1~7j* zY4|%geiqr}6NEsA3@XW}p(oIe9*6hL%~J-aqPbkDWScs&4)|``vTO?yGTcc@f1Z3z zd;9u`B!=@}PrAdNLJ!363bPY*Ku|a(>bvWA^+Ikf!=zWIsC-LI9W7V2I8KkJD_yk% zu8drz!F}&BJP1wM4->FkrtcZ0BeuvddJMf|;ABrHEvrAdZQx@6%Ut>R0NG^e=${4ev;n&X_T9N!hD4T=@zY?&3Jqag^aT7E|-W`23&qr-p_PW zRa!Z4v=I229GDY|qs!}ePvJaXO*B|I*YHO9iA=APZowgGF0d#u3EQl?eWf!-2FF$y zp01$w#T5pn*G`z0@Kt6U%`HPa9?MI-9}`~WSmVw~x-nuuV(5YHQrKHPM1FWvk%SK_ z4_9dC9LAfCC<$*O*VKZfsQzE#B6&z2A-4Zpl=f|H7Q{%-REVcZ8#^g|9=X6`6O2-a ztSguARKm2-^!-6LDrzGEDNY1Y}hpZ*t~3UgLc zP}TpAAcESd+=OVcun!$FjYdItNw)X{>X!0Fa-llQ#bs4o5FoQQFAVC6>>&;`T z(oE}ElzJ<}_WZ3q>lAGL2)=C!sqjl}(GpQdZvJw|LU+8+ul6a;Irq4jAs*VF{v`}e zp380PKsS-lO|TqTPDHZimz)>A){s(M#km0umFW;U1@5iQ+Lf)3v)Qhg^)V2lb71b3 zsomnTy)=6DtbUpd5rt#xvtJH4Yc1HLNWasgUle#69`V0mKI!fc$2`OtA@ofv_MbM% zMLh5I>E4p@6I^inIPp9*K`}CAOtc?ju$S&-_Pw%F-=h*U_x$*F2Qs9UXRB4{liu{; zUcwbq%Sl(xf=EZ|_>vmm38r?Sp`vx)dlu^<=j^8Z`qduxgm2hF9V@wo4!1u5`bG%S M(>BohplKKKe}Wfo>i_@% literal 0 HcmV?d00001 diff --git a/Vocaluxe/Website/index.html b/Vocaluxe/Website/index.html index 06aed5fd..6858595d 100644 --- a/Vocaluxe/Website/index.html +++ b/Vocaluxe/Website/index.html @@ -7,6 +7,8 @@ + + @@ -58,11 +60,18 @@

All songs

-

List all available songs

+

Lists all available songs

  • - + + +

    All playlists

    +

    Lists all playlists

    +
    +
  • +
  • +

    Profiles

    Shows all profiles

    @@ -76,7 +85,7 @@
  • - +

    Keyboard

    Send keys

    @@ -176,15 +185,18 @@

    @@ -284,6 +296,34 @@ +
    +
    +

    Select a playlist

    + Add +
    + + +
    +
      +
      + +
      + + +
      +
      +

      Playlist

      + Save +
      + + +
      +
        +
        + +
        + +
        diff --git a/Vocaluxe/Website/js/jquery-ui-1.10.3.custom.min.js b/Vocaluxe/Website/js/jquery-ui-1.10.3.custom.min.js new file mode 100644 index 00000000..1e73c62c --- /dev/null +++ b/Vocaluxe/Website/js/jquery-ui-1.10.3.custom.min.js @@ -0,0 +1,6 @@ +/*! jQuery UI - v1.10.3 - 2013-11-03 +* http://jqueryui.com +* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.mouse.js, jquery.ui.sortable.js +* Copyright 2013 jQuery Foundation and other contributors; Licensed MIT */ + +(function(e,t){function i(t,i){var s,n,r,o=t.nodeName.toLowerCase();return"area"===o?(s=t.parentNode,n=s.name,t.href&&n&&"map"===s.nodeName.toLowerCase()?(r=e("img[usemap=#"+n+"]")[0],!!r&&a(r)):!1):(/input|select|textarea|button|object/.test(o)?!t.disabled:"a"===o?t.href||i:i)&&a(t)}function a(t){return e.expr.filters.visible(t)&&!e(t).parents().addBack().filter(function(){return"hidden"===e.css(this,"visibility")}).length}var s=0,n=/^ui-id-\d+$/;e.ui=e.ui||{},e.extend(e.ui,{version:"1.10.3",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),e.fn.extend({focus:function(t){return function(i,a){return"number"==typeof i?this.each(function(){var t=this;setTimeout(function(){e(t).focus(),a&&a.call(t)},i)}):t.apply(this,arguments)}}(e.fn.focus),scrollParent:function(){var t;return t=e.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(e.css(this,"position"))&&/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(e.css(this,"overflow")+e.css(this,"overflow-y")+e.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!t.length?e(document):t},zIndex:function(i){if(i!==t)return this.css("zIndex",i);if(this.length)for(var a,s,n=e(this[0]);n.length&&n[0]!==document;){if(a=n.css("position"),("absolute"===a||"relative"===a||"fixed"===a)&&(s=parseInt(n.css("zIndex"),10),!isNaN(s)&&0!==s))return s;n=n.parent()}return 0},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++s)})},removeUniqueId:function(){return this.each(function(){n.test(this.id)&&e(this).removeAttr("id")})}}),e.extend(e.expr[":"],{data:e.expr.createPseudo?e.expr.createPseudo(function(t){return function(i){return!!e.data(i,t)}}):function(t,i,a){return!!e.data(t,a[3])},focusable:function(t){return i(t,!isNaN(e.attr(t,"tabindex")))},tabbable:function(t){var a=e.attr(t,"tabindex"),s=isNaN(a);return(s||a>=0)&&i(t,!s)}}),e("").outerWidth(1).jquery||e.each(["Width","Height"],function(i,a){function s(t,i,a,s){return e.each(n,function(){i-=parseFloat(e.css(t,"padding"+this))||0,a&&(i-=parseFloat(e.css(t,"border"+this+"Width"))||0),s&&(i-=parseFloat(e.css(t,"margin"+this))||0)}),i}var n="Width"===a?["Left","Right"]:["Top","Bottom"],r=a.toLowerCase(),o={innerWidth:e.fn.innerWidth,innerHeight:e.fn.innerHeight,outerWidth:e.fn.outerWidth,outerHeight:e.fn.outerHeight};e.fn["inner"+a]=function(i){return i===t?o["inner"+a].call(this):this.each(function(){e(this).css(r,s(this,i)+"px")})},e.fn["outer"+a]=function(t,i){return"number"!=typeof t?o["outer"+a].call(this,t):this.each(function(){e(this).css(r,s(this,t,!0,i)+"px")})}}),e.fn.addBack||(e.fn.addBack=function(e){return this.add(null==e?this.prevObject:this.prevObject.filter(e))}),e("").data("a-b","a").removeData("a-b").data("a-b")&&(e.fn.removeData=function(t){return function(i){return arguments.length?t.call(this,e.camelCase(i)):t.call(this)}}(e.fn.removeData)),e.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),e.support.selectstart="onselectstart"in document.createElement("div"),e.fn.extend({disableSelection:function(){return this.bind((e.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(e){e.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),e.extend(e.ui,{plugin:{add:function(t,i,a){var s,n=e.ui[t].prototype;for(s in a)n.plugins[s]=n.plugins[s]||[],n.plugins[s].push([i,a[s]])},call:function(e,t,i){var a,s=e.plugins[t];if(s&&e.element[0].parentNode&&11!==e.element[0].parentNode.nodeType)for(a=0;s.length>a;a++)e.options[s[a][0]]&&s[a][1].apply(e.element,i)}},hasScroll:function(t,i){if("hidden"===e(t).css("overflow"))return!1;var a=i&&"left"===i?"scrollLeft":"scrollTop",s=!1;return t[a]>0?!0:(t[a]=1,s=t[a]>0,t[a]=0,s)}})})(jQuery);(function(e,t){var i=0,s=Array.prototype.slice,a=e.cleanData;e.cleanData=function(t){for(var i,s=0;null!=(i=t[s]);s++)try{e(i).triggerHandler("remove")}catch(n){}a(t)},e.widget=function(i,s,a){var n,r,o,h,l={},u=i.split(".")[0];i=i.split(".")[1],n=u+"-"+i,a||(a=s,s=e.Widget),e.expr[":"][n.toLowerCase()]=function(t){return!!e.data(t,n)},e[u]=e[u]||{},r=e[u][i],o=e[u][i]=function(e,i){return this._createWidget?(arguments.length&&this._createWidget(e,i),t):new o(e,i)},e.extend(o,r,{version:a.version,_proto:e.extend({},a),_childConstructors:[]}),h=new s,h.options=e.widget.extend({},h.options),e.each(a,function(i,a){return e.isFunction(a)?(l[i]=function(){var e=function(){return s.prototype[i].apply(this,arguments)},t=function(e){return s.prototype[i].apply(this,e)};return function(){var i,s=this._super,n=this._superApply;return this._super=e,this._superApply=t,i=a.apply(this,arguments),this._super=s,this._superApply=n,i}}(),t):(l[i]=a,t)}),o.prototype=e.widget.extend(h,{widgetEventPrefix:r?h.widgetEventPrefix:i},l,{constructor:o,namespace:u,widgetName:i,widgetFullName:n}),r?(e.each(r._childConstructors,function(t,i){var s=i.prototype;e.widget(s.namespace+"."+s.widgetName,o,i._proto)}),delete r._childConstructors):s._childConstructors.push(o),e.widget.bridge(i,o)},e.widget.extend=function(i){for(var a,n,r=s.call(arguments,1),o=0,h=r.length;h>o;o++)for(a in r[o])n=r[o][a],r[o].hasOwnProperty(a)&&n!==t&&(i[a]=e.isPlainObject(n)?e.isPlainObject(i[a])?e.widget.extend({},i[a],n):e.widget.extend({},n):n);return i},e.widget.bridge=function(i,a){var n=a.prototype.widgetFullName||i;e.fn[i]=function(r){var o="string"==typeof r,h=s.call(arguments,1),l=this;return r=!o&&h.length?e.widget.extend.apply(null,[r].concat(h)):r,o?this.each(function(){var s,a=e.data(this,n);return a?e.isFunction(a[r])&&"_"!==r.charAt(0)?(s=a[r].apply(a,h),s!==a&&s!==t?(l=s&&s.jquery?l.pushStack(s.get()):s,!1):t):e.error("no such method '"+r+"' for "+i+" widget instance"):e.error("cannot call methods on "+i+" prior to initialization; "+"attempted to call method '"+r+"'")}):this.each(function(){var t=e.data(this,n);t?t.option(r||{})._init():e.data(this,n,new a(r,this))}),l}},e.Widget=function(){},e.Widget._childConstructors=[],e.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
        ",options:{disabled:!1,create:null},_createWidget:function(t,s){s=e(s||this.defaultElement||this)[0],this.element=e(s),this.uuid=i++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=e.widget.extend({},this.options,this._getCreateOptions(),t),this.bindings=e(),this.hoverable=e(),this.focusable=e(),s!==this&&(e.data(s,this.widgetFullName,this),this._on(!0,this.element,{remove:function(e){e.target===s&&this.destroy()}}),this.document=e(s.style?s.ownerDocument:s.document||s),this.window=e(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:e.noop,_getCreateEventData:e.noop,_create:e.noop,_init:e.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetName).removeData(this.widgetFullName).removeData(e.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled "+"ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:e.noop,widget:function(){return this.element},option:function(i,s){var a,n,r,o=i;if(0===arguments.length)return e.widget.extend({},this.options);if("string"==typeof i)if(o={},a=i.split("."),i=a.shift(),a.length){for(n=o[i]=e.widget.extend({},this.options[i]),r=0;a.length-1>r;r++)n[a[r]]=n[a[r]]||{},n=n[a[r]];if(i=a.pop(),s===t)return n[i]===t?null:n[i];n[i]=s}else{if(s===t)return this.options[i]===t?null:this.options[i];o[i]=s}return this._setOptions(o),this},_setOptions:function(e){var t;for(t in e)this._setOption(t,e[t]);return this},_setOption:function(e,t){return this.options[e]=t,"disabled"===e&&(this.widget().toggleClass(this.widgetFullName+"-disabled ui-state-disabled",!!t).attr("aria-disabled",t),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_on:function(i,s,a){var n,r=this;"boolean"!=typeof i&&(a=s,s=i,i=!1),a?(s=n=e(s),this.bindings=this.bindings.add(s)):(a=s,s=this.element,n=this.widget()),e.each(a,function(a,o){function h(){return i||r.options.disabled!==!0&&!e(this).hasClass("ui-state-disabled")?("string"==typeof o?r[o]:o).apply(r,arguments):t}"string"!=typeof o&&(h.guid=o.guid=o.guid||h.guid||e.guid++);var l=a.match(/^(\w+)\s*(.*)$/),u=l[1]+r.eventNamespace,c=l[2];c?n.delegate(c,u,h):s.bind(u,h)})},_off:function(e,t){t=(t||"").split(" ").join(this.eventNamespace+" ")+this.eventNamespace,e.unbind(t).undelegate(t)},_delay:function(e,t){function i(){return("string"==typeof e?s[e]:e).apply(s,arguments)}var s=this;return setTimeout(i,t||0)},_hoverable:function(t){this.hoverable=this.hoverable.add(t),this._on(t,{mouseenter:function(t){e(t.currentTarget).addClass("ui-state-hover")},mouseleave:function(t){e(t.currentTarget).removeClass("ui-state-hover")}})},_focusable:function(t){this.focusable=this.focusable.add(t),this._on(t,{focusin:function(t){e(t.currentTarget).addClass("ui-state-focus")},focusout:function(t){e(t.currentTarget).removeClass("ui-state-focus")}})},_trigger:function(t,i,s){var a,n,r=this.options[t];if(s=s||{},i=e.Event(i),i.type=(t===this.widgetEventPrefix?t:this.widgetEventPrefix+t).toLowerCase(),i.target=this.element[0],n=i.originalEvent)for(a in n)a in i||(i[a]=n[a]);return this.element.trigger(i,s),!(e.isFunction(r)&&r.apply(this.element[0],[i].concat(s))===!1||i.isDefaultPrevented())}},e.each({show:"fadeIn",hide:"fadeOut"},function(t,i){e.Widget.prototype["_"+t]=function(s,a,n){"string"==typeof a&&(a={effect:a});var r,o=a?a===!0||"number"==typeof a?i:a.effect||i:t;a=a||{},"number"==typeof a&&(a={duration:a}),r=!e.isEmptyObject(a),a.complete=n,a.delay&&s.delay(a.delay),r&&e.effects&&e.effects.effect[o]?s[t](a):o!==t&&s[o]?s[o](a.duration,a.easing,n):s.queue(function(i){e(this)[t](),n&&n.call(s[0]),i()})}})})(jQuery);(function(e){var t=!1;e(document).mouseup(function(){t=!1}),e.widget("ui.mouse",{version:"1.10.3",options:{cancel:"input,textarea,button,select,option",distance:1,delay:0},_mouseInit:function(){var t=this;this.element.bind("mousedown."+this.widgetName,function(e){return t._mouseDown(e)}).bind("click."+this.widgetName,function(i){return!0===e.data(i.target,t.widgetName+".preventClickEvent")?(e.removeData(i.target,t.widgetName+".preventClickEvent"),i.stopImmediatePropagation(),!1):undefined}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),this._mouseMoveDelegate&&e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(i){if(!t){this._mouseStarted&&this._mouseUp(i),this._mouseDownEvent=i;var s=this,a=1===i.which,n="string"==typeof this.options.cancel&&i.target.nodeName?e(i.target).closest(this.options.cancel).length:!1;return a&&!n&&this._mouseCapture(i)?(this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){s.mouseDelayMet=!0},this.options.delay)),this._mouseDistanceMet(i)&&this._mouseDelayMet(i)&&(this._mouseStarted=this._mouseStart(i)!==!1,!this._mouseStarted)?(i.preventDefault(),!0):(!0===e.data(i.target,this.widgetName+".preventClickEvent")&&e.removeData(i.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(e){return s._mouseMove(e)},this._mouseUpDelegate=function(e){return s._mouseUp(e)},e(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),i.preventDefault(),t=!0,!0)):!0}},_mouseMove:function(t){return e.ui.ie&&(!document.documentMode||9>document.documentMode)&&!t.button?this._mouseUp(t):this._mouseStarted?(this._mouseDrag(t),t.preventDefault()):(this._mouseDistanceMet(t)&&this._mouseDelayMet(t)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,t)!==!1,this._mouseStarted?this._mouseDrag(t):this._mouseUp(t)),!this._mouseStarted)},_mouseUp:function(t){return e(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,t.target===this._mouseDownEvent.target&&e.data(t.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(t)),!1},_mouseDistanceMet:function(e){return Math.max(Math.abs(this._mouseDownEvent.pageX-e.pageX),Math.abs(this._mouseDownEvent.pageY-e.pageY))>=this.options.distance},_mouseDelayMet:function(){return this.mouseDelayMet},_mouseStart:function(){},_mouseDrag:function(){},_mouseStop:function(){},_mouseCapture:function(){return!0}})})(jQuery);(function(e){function t(e,t,i){return e>t&&t+i>e}function i(e){return/left|right/.test(e.css("float"))||/inline|table-cell/.test(e.css("display"))}e.widget("ui.sortable",e.ui.mouse,{version:"1.10.3",widgetEventPrefix:"sort",ready:!1,options:{appendTo:"parent",axis:!1,connectWith:!1,containment:!1,cursor:"auto",cursorAt:!1,dropOnEmpty:!0,forcePlaceholderSize:!1,forceHelperSize:!1,grid:!1,handle:!1,helper:"original",items:"> *",opacity:!1,placeholder:!1,revert:!1,scroll:!0,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1e3,activate:null,beforeStop:null,change:null,deactivate:null,out:null,over:null,receive:null,remove:null,sort:null,start:null,stop:null,update:null},_create:function(){var e=this.options;this.containerCache={},this.element.addClass("ui-sortable"),this.refresh(),this.floating=this.items.length?"x"===e.axis||i(this.items[0].item):!1,this.offset=this.element.offset(),this._mouseInit(),this.ready=!0},_destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled"),this._mouseDestroy();for(var e=this.items.length-1;e>=0;e--)this.items[e].item.removeData(this.widgetName+"-item");return this},_setOption:function(t,i){"disabled"===t?(this.options[t]=i,this.widget().toggleClass("ui-sortable-disabled",!!i)):e.Widget.prototype._setOption.apply(this,arguments)},_mouseCapture:function(t,i){var s=null,a=!1,n=this;return this.reverting?!1:this.options.disabled||"static"===this.options.type?!1:(this._refreshItems(t),e(t.target).parents().each(function(){return e.data(this,n.widgetName+"-item")===n?(s=e(this),!1):undefined}),e.data(t.target,n.widgetName+"-item")===n&&(s=e(t.target)),s?!this.options.handle||i||(e(this.options.handle,s).find("*").addBack().each(function(){this===t.target&&(a=!0)}),a)?(this.currentItem=s,this._removeCurrentsFromItems(),!0):!1:!1)},_mouseStart:function(t,i,s){var a,n,r=this.options;if(this.currentContainer=this,this.refreshPositions(),this.helper=this._createHelper(t),this._cacheHelperProportions(),this._cacheMargins(),this.scrollParent=this.helper.scrollParent(),this.offset=this.currentItem.offset(),this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left},e.extend(this.offset,{click:{left:t.pageX-this.offset.left,top:t.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()}),this.helper.css("position","absolute"),this.cssPosition=this.helper.css("position"),this.originalPosition=this._generatePosition(t),this.originalPageX=t.pageX,this.originalPageY=t.pageY,r.cursorAt&&this._adjustOffsetFromHelper(r.cursorAt),this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]},this.helper[0]!==this.currentItem[0]&&this.currentItem.hide(),this._createPlaceholder(),r.containment&&this._setContainment(),r.cursor&&"auto"!==r.cursor&&(n=this.document.find("body"),this.storedCursor=n.css("cursor"),n.css("cursor",r.cursor),this.storedStylesheet=e("").appendTo(n)),r.opacity&&(this.helper.css("opacity")&&(this._storedOpacity=this.helper.css("opacity")),this.helper.css("opacity",r.opacity)),r.zIndex&&(this.helper.css("zIndex")&&(this._storedZIndex=this.helper.css("zIndex")),this.helper.css("zIndex",r.zIndex)),this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName&&(this.overflowOffset=this.scrollParent.offset()),this._trigger("start",t,this._uiHash()),this._preserveHelperProportions||this._cacheHelperProportions(),!s)for(a=this.containers.length-1;a>=0;a--)this.containers[a]._trigger("activate",t,this._uiHash(this));return e.ui.ddmanager&&(e.ui.ddmanager.current=this),e.ui.ddmanager&&!r.dropBehaviour&&e.ui.ddmanager.prepareOffsets(this,t),this.dragging=!0,this.helper.addClass("ui-sortable-helper"),this._mouseDrag(t),!0},_mouseDrag:function(t){var i,s,a,n,r=this.options,o=!1;for(this.position=this._generatePosition(t),this.positionAbs=this._convertPositionTo("absolute"),this.lastPositionAbs||(this.lastPositionAbs=this.positionAbs),this.options.scroll&&(this.scrollParent[0]!==document&&"HTML"!==this.scrollParent[0].tagName?(this.overflowOffset.top+this.scrollParent[0].offsetHeight-t.pageY=0;i--)if(s=this.items[i],a=s.item[0],n=this._intersectsWithPointer(s),n&&s.instance===this.currentContainer&&a!==this.currentItem[0]&&this.placeholder[1===n?"next":"prev"]()[0]!==a&&!e.contains(this.placeholder[0],a)&&("semi-dynamic"===this.options.type?!e.contains(this.element[0],a):!0)){if(this.direction=1===n?"down":"up","pointer"!==this.options.tolerance&&!this._intersectsWithSides(s))break;this._rearrange(t,s),this._trigger("change",t,this._uiHash());break}return this._contactContainers(t),e.ui.ddmanager&&e.ui.ddmanager.drag(this,t),this._trigger("sort",t,this._uiHash()),this.lastPositionAbs=this.positionAbs,!1},_mouseStop:function(t,i){if(t){if(e.ui.ddmanager&&!this.options.dropBehaviour&&e.ui.ddmanager.drop(this,t),this.options.revert){var s=this,a=this.placeholder.offset(),n=this.options.axis,r={};n&&"x"!==n||(r.left=a.left-this.offset.parent.left-this.margins.left+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollLeft)),n&&"y"!==n||(r.top=a.top-this.offset.parent.top-this.margins.top+(this.offsetParent[0]===document.body?0:this.offsetParent[0].scrollTop)),this.reverting=!0,e(this.helper).animate(r,parseInt(this.options.revert,10)||500,function(){s._clear(t)})}else this._clear(t,i);return!1}},cancel:function(){if(this.dragging){this._mouseUp({target:null}),"original"===this.options.helper?this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper"):this.currentItem.show();for(var t=this.containers.length-1;t>=0;t--)this.containers[t]._trigger("deactivate",null,this._uiHash(this)),this.containers[t].containerCache.over&&(this.containers[t]._trigger("out",null,this._uiHash(this)),this.containers[t].containerCache.over=0)}return this.placeholder&&(this.placeholder[0].parentNode&&this.placeholder[0].parentNode.removeChild(this.placeholder[0]),"original"!==this.options.helper&&this.helper&&this.helper[0].parentNode&&this.helper.remove(),e.extend(this,{helper:null,dragging:!1,reverting:!1,_noFinalSort:null}),this.domPosition.prev?e(this.domPosition.prev).after(this.currentItem):e(this.domPosition.parent).prepend(this.currentItem)),this},serialize:function(t){var i=this._getItemsAsjQuery(t&&t.connected),s=[];return t=t||{},e(i).each(function(){var i=(e(t.item||this).attr(t.attribute||"id")||"").match(t.expression||/(.+)[\-=_](.+)/);i&&s.push((t.key||i[1]+"[]")+"="+(t.key&&t.expression?i[1]:i[2]))}),!s.length&&t.key&&s.push(t.key+"="),s.join("&")},toArray:function(t){var i=this._getItemsAsjQuery(t&&t.connected),s=[];return t=t||{},i.each(function(){s.push(e(t.item||this).attr(t.attribute||"id")||"")}),s},_intersectsWith:function(e){var t=this.positionAbs.left,i=t+this.helperProportions.width,s=this.positionAbs.top,a=s+this.helperProportions.height,n=e.left,r=n+e.width,o=e.top,h=o+e.height,l=this.offset.click.top,u=this.offset.click.left,c="x"===this.options.axis||s+l>o&&h>s+l,d="y"===this.options.axis||t+u>n&&r>t+u,p=c&&d;return"pointer"===this.options.tolerance||this.options.forcePointerForContainers||"pointer"!==this.options.tolerance&&this.helperProportions[this.floating?"width":"height"]>e[this.floating?"width":"height"]?p:t+this.helperProportions.width/2>n&&r>i-this.helperProportions.width/2&&s+this.helperProportions.height/2>o&&h>a-this.helperProportions.height/2},_intersectsWithPointer:function(e){var i="x"===this.options.axis||t(this.positionAbs.top+this.offset.click.top,e.top,e.height),s="y"===this.options.axis||t(this.positionAbs.left+this.offset.click.left,e.left,e.width),a=i&&s,n=this._getDragVerticalDirection(),r=this._getDragHorizontalDirection();return a?this.floating?r&&"right"===r||"down"===n?2:1:n&&("down"===n?2:1):!1},_intersectsWithSides:function(e){var i=t(this.positionAbs.top+this.offset.click.top,e.top+e.height/2,e.height),s=t(this.positionAbs.left+this.offset.click.left,e.left+e.width/2,e.width),a=this._getDragVerticalDirection(),n=this._getDragHorizontalDirection();return this.floating&&n?"right"===n&&s||"left"===n&&!s:a&&("down"===a&&i||"up"===a&&!i)},_getDragVerticalDirection:function(){var e=this.positionAbs.top-this.lastPositionAbs.top;return 0!==e&&(e>0?"down":"up")},_getDragHorizontalDirection:function(){var e=this.positionAbs.left-this.lastPositionAbs.left;return 0!==e&&(e>0?"right":"left")},refresh:function(e){return this._refreshItems(e),this.refreshPositions(),this},_connectWith:function(){var e=this.options;return e.connectWith.constructor===String?[e.connectWith]:e.connectWith},_getItemsAsjQuery:function(t){var i,s,a,n,r=[],o=[],h=this._connectWith();if(h&&t)for(i=h.length-1;i>=0;i--)for(a=e(h[i]),s=a.length-1;s>=0;s--)n=e.data(a[s],this.widgetFullName),n&&n!==this&&!n.options.disabled&&o.push([e.isFunction(n.options.items)?n.options.items.call(n.element):e(n.options.items,n.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),n]);for(o.push([e.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):e(this.options.items,this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"),this]),i=o.length-1;i>=0;i--)o[i][0].each(function(){r.push(this)});return e(r)},_removeCurrentsFromItems:function(){var t=this.currentItem.find(":data("+this.widgetName+"-item)");this.items=e.grep(this.items,function(e){for(var i=0;t.length>i;i++)if(t[i]===e.item[0])return!1;return!0})},_refreshItems:function(t){this.items=[],this.containers=[this];var i,s,a,n,r,o,h,l,u=this.items,c=[[e.isFunction(this.options.items)?this.options.items.call(this.element[0],t,{item:this.currentItem}):e(this.options.items,this.element),this]],d=this._connectWith();if(d&&this.ready)for(i=d.length-1;i>=0;i--)for(a=e(d[i]),s=a.length-1;s>=0;s--)n=e.data(a[s],this.widgetFullName),n&&n!==this&&!n.options.disabled&&(c.push([e.isFunction(n.options.items)?n.options.items.call(n.element[0],t,{item:this.currentItem}):e(n.options.items,n.element),n]),this.containers.push(n));for(i=c.length-1;i>=0;i--)for(r=c[i][1],o=c[i][0],s=0,l=o.length;l>s;s++)h=e(o[s]),h.data(this.widgetName+"-item",r),u.push({item:h,instance:r,width:0,height:0,left:0,top:0})},refreshPositions:function(t){this.offsetParent&&this.helper&&(this.offset.parent=this._getParentOffset());var i,s,a,n;for(i=this.items.length-1;i>=0;i--)s=this.items[i],s.instance!==this.currentContainer&&this.currentContainer&&s.item[0]!==this.currentItem[0]||(a=this.options.toleranceElement?e(this.options.toleranceElement,s.item):s.item,t||(s.width=a.outerWidth(),s.height=a.outerHeight()),n=a.offset(),s.left=n.left,s.top=n.top);if(this.options.custom&&this.options.custom.refreshContainers)this.options.custom.refreshContainers.call(this);else for(i=this.containers.length-1;i>=0;i--)n=this.containers[i].element.offset(),this.containers[i].containerCache.left=n.left,this.containers[i].containerCache.top=n.top,this.containers[i].containerCache.width=this.containers[i].element.outerWidth(),this.containers[i].containerCache.height=this.containers[i].element.outerHeight();return this},_createPlaceholder:function(t){t=t||this;var i,s=t.options;s.placeholder&&s.placeholder.constructor!==String||(i=s.placeholder,s.placeholder={element:function(){var s=t.currentItem[0].nodeName.toLowerCase(),a=e("<"+s+">",t.document[0]).addClass(i||t.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper");return"tr"===s?t.currentItem.children().each(function(){e(" ",t.document[0]).attr("colspan",e(this).attr("colspan")||1).appendTo(a)}):"img"===s&&a.attr("src",t.currentItem.attr("src")),i||a.css("visibility","hidden"),a},update:function(e,a){(!i||s.forcePlaceholderSize)&&(a.height()||a.height(t.currentItem.innerHeight()-parseInt(t.currentItem.css("paddingTop")||0,10)-parseInt(t.currentItem.css("paddingBottom")||0,10)),a.width()||a.width(t.currentItem.innerWidth()-parseInt(t.currentItem.css("paddingLeft")||0,10)-parseInt(t.currentItem.css("paddingRight")||0,10)))}}),t.placeholder=e(s.placeholder.element.call(t.element,t.currentItem)),t.currentItem.after(t.placeholder),s.placeholder.update(t,t.placeholder)},_contactContainers:function(s){var a,n,r,o,h,l,u,c,d,p,f=null,m=null;for(a=this.containers.length-1;a>=0;a--)if(!e.contains(this.currentItem[0],this.containers[a].element[0]))if(this._intersectsWith(this.containers[a].containerCache)){if(f&&e.contains(this.containers[a].element[0],f.element[0]))continue;f=this.containers[a],m=a}else this.containers[a].containerCache.over&&(this.containers[a]._trigger("out",s,this._uiHash(this)),this.containers[a].containerCache.over=0);if(f)if(1===this.containers.length)this.containers[m].containerCache.over||(this.containers[m]._trigger("over",s,this._uiHash(this)),this.containers[m].containerCache.over=1);else{for(r=1e4,o=null,p=f.floating||i(this.currentItem),h=p?"left":"top",l=p?"width":"height",u=this.positionAbs[h]+this.offset.click[h],n=this.items.length-1;n>=0;n--)e.contains(this.containers[m].element[0],this.items[n].item[0])&&this.items[n].item[0]!==this.currentItem[0]&&(!p||t(this.positionAbs.top+this.offset.click.top,this.items[n].top,this.items[n].height))&&(c=this.items[n].item.offset()[h],d=!1,Math.abs(c-u)>Math.abs(c+this.items[n][l]-u)&&(d=!0,c+=this.items[n][l]),r>Math.abs(c-u)&&(r=Math.abs(c-u),o=this.items[n],this.direction=d?"up":"down"));if(!o&&!this.options.dropOnEmpty)return;if(this.currentContainer===this.containers[m])return;o?this._rearrange(s,o,null,!0):this._rearrange(s,null,this.containers[m].element,!0),this._trigger("change",s,this._uiHash()),this.containers[m]._trigger("change",s,this._uiHash(this)),this.currentContainer=this.containers[m],this.options.placeholder.update(this.currentContainer,this.placeholder),this.containers[m]._trigger("over",s,this._uiHash(this)),this.containers[m].containerCache.over=1}},_createHelper:function(t){var i=this.options,s=e.isFunction(i.helper)?e(i.helper.apply(this.element[0],[t,this.currentItem])):"clone"===i.helper?this.currentItem.clone():this.currentItem;return s.parents("body").length||e("parent"!==i.appendTo?i.appendTo:this.currentItem[0].parentNode)[0].appendChild(s[0]),s[0]===this.currentItem[0]&&(this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}),(!s[0].style.width||i.forceHelperSize)&&s.width(this.currentItem.width()),(!s[0].style.height||i.forceHelperSize)&&s.height(this.currentItem.height()),s},_adjustOffsetFromHelper:function(t){"string"==typeof t&&(t=t.split(" ")),e.isArray(t)&&(t={left:+t[0],top:+t[1]||0}),"left"in t&&(this.offset.click.left=t.left+this.margins.left),"right"in t&&(this.offset.click.left=this.helperProportions.width-t.right+this.margins.left),"top"in t&&(this.offset.click.top=t.top+this.margins.top),"bottom"in t&&(this.offset.click.top=this.helperProportions.height-t.bottom+this.margins.top)},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var t=this.offsetParent.offset();return"absolute"===this.cssPosition&&this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])&&(t.left+=this.scrollParent.scrollLeft(),t.top+=this.scrollParent.scrollTop()),(this.offsetParent[0]===document.body||this.offsetParent[0].tagName&&"html"===this.offsetParent[0].tagName.toLowerCase()&&e.ui.ie)&&(t={top:0,left:0}),{top:t.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:t.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if("relative"===this.cssPosition){var e=this.currentItem.position();return{top:e.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:e.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}return{top:0,left:0}},_cacheMargins:function(){this.margins={left:parseInt(this.currentItem.css("marginLeft"),10)||0,top:parseInt(this.currentItem.css("marginTop"),10)||0}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var t,i,s,a=this.options;"parent"===a.containment&&(a.containment=this.helper[0].parentNode),("document"===a.containment||"window"===a.containment)&&(this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,e("document"===a.containment?document:window).width()-this.helperProportions.width-this.margins.left,(e("document"===a.containment?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]),/^(document|window|parent)$/.test(a.containment)||(t=e(a.containment)[0],i=e(a.containment).offset(),s="hidden"!==e(t).css("overflow"),this.containment=[i.left+(parseInt(e(t).css("borderLeftWidth"),10)||0)+(parseInt(e(t).css("paddingLeft"),10)||0)-this.margins.left,i.top+(parseInt(e(t).css("borderTopWidth"),10)||0)+(parseInt(e(t).css("paddingTop"),10)||0)-this.margins.top,i.left+(s?Math.max(t.scrollWidth,t.offsetWidth):t.offsetWidth)-(parseInt(e(t).css("borderLeftWidth"),10)||0)-(parseInt(e(t).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,i.top+(s?Math.max(t.scrollHeight,t.offsetHeight):t.offsetHeight)-(parseInt(e(t).css("borderTopWidth"),10)||0)-(parseInt(e(t).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top])},_convertPositionTo:function(t,i){i||(i=this.position);var s="absolute"===t?1:-1,a="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,n=/(html|body)/i.test(a[0].tagName);return{top:i.top+this.offset.relative.top*s+this.offset.parent.top*s-("fixed"===this.cssPosition?-this.scrollParent.scrollTop():n?0:a.scrollTop())*s,left:i.left+this.offset.relative.left*s+this.offset.parent.left*s-("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():n?0:a.scrollLeft())*s}},_generatePosition:function(t){var i,s,a=this.options,n=t.pageX,r=t.pageY,o="absolute"!==this.cssPosition||this.scrollParent[0]!==document&&e.contains(this.scrollParent[0],this.offsetParent[0])?this.scrollParent:this.offsetParent,h=/(html|body)/i.test(o[0].tagName);return"relative"!==this.cssPosition||this.scrollParent[0]!==document&&this.scrollParent[0]!==this.offsetParent[0]||(this.offset.relative=this._getRelativeOffset()),this.originalPosition&&(this.containment&&(t.pageX-this.offset.click.leftthis.containment[2]&&(n=this.containment[2]+this.offset.click.left),t.pageY-this.offset.click.top>this.containment[3]&&(r=this.containment[3]+this.offset.click.top)),a.grid&&(i=this.originalPageY+Math.round((r-this.originalPageY)/a.grid[1])*a.grid[1],r=this.containment?i-this.offset.click.top>=this.containment[1]&&i-this.offset.click.top<=this.containment[3]?i:i-this.offset.click.top>=this.containment[1]?i-a.grid[1]:i+a.grid[1]:i,s=this.originalPageX+Math.round((n-this.originalPageX)/a.grid[0])*a.grid[0],n=this.containment?s-this.offset.click.left>=this.containment[0]&&s-this.offset.click.left<=this.containment[2]?s:s-this.offset.click.left>=this.containment[0]?s-a.grid[0]:s+a.grid[0]:s)),{top:r-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+("fixed"===this.cssPosition?-this.scrollParent.scrollTop():h?0:o.scrollTop()),left:n-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+("fixed"===this.cssPosition?-this.scrollParent.scrollLeft():h?0:o.scrollLeft())}},_rearrange:function(e,t,i,s){i?i[0].appendChild(this.placeholder[0]):t.item[0].parentNode.insertBefore(this.placeholder[0],"down"===this.direction?t.item[0]:t.item[0].nextSibling),this.counter=this.counter?++this.counter:1;var a=this.counter;this._delay(function(){a===this.counter&&this.refreshPositions(!s)})},_clear:function(e,t){this.reverting=!1;var i,s=[];if(!this._noFinalSort&&this.currentItem.parent().length&&this.placeholder.before(this.currentItem),this._noFinalSort=null,this.helper[0]===this.currentItem[0]){for(i in this._storedCSS)("auto"===this._storedCSS[i]||"static"===this._storedCSS[i])&&(this._storedCSS[i]="");this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else this.currentItem.show();for(this.fromOutside&&!t&&s.push(function(e){this._trigger("receive",e,this._uiHash(this.fromOutside))}),!this.fromOutside&&this.domPosition.prev===this.currentItem.prev().not(".ui-sortable-helper")[0]&&this.domPosition.parent===this.currentItem.parent()[0]||t||s.push(function(e){this._trigger("update",e,this._uiHash())}),this!==this.currentContainer&&(t||(s.push(function(e){this._trigger("remove",e,this._uiHash())}),s.push(function(e){return function(t){e._trigger("receive",t,this._uiHash(this))}}.call(this,this.currentContainer)),s.push(function(e){return function(t){e._trigger("update",t,this._uiHash(this))}}.call(this,this.currentContainer)))),i=this.containers.length-1;i>=0;i--)t||s.push(function(e){return function(t){e._trigger("deactivate",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over&&(s.push(function(e){return function(t){e._trigger("out",t,this._uiHash(this))}}.call(this,this.containers[i])),this.containers[i].containerCache.over=0);if(this.storedCursor&&(this.document.find("body").css("cursor",this.storedCursor),this.storedStylesheet.remove()),this._storedOpacity&&this.helper.css("opacity",this._storedOpacity),this._storedZIndex&&this.helper.css("zIndex","auto"===this._storedZIndex?"":this._storedZIndex),this.dragging=!1,this.cancelHelperRemoval){if(!t){for(this._trigger("beforeStop",e,this._uiHash()),i=0;s.length>i;i++)s[i].call(this,e);this._trigger("stop",e,this._uiHash())}return this.fromOutside=!1,!1}if(t||this._trigger("beforeStop",e,this._uiHash()),this.placeholder[0].parentNode.removeChild(this.placeholder[0]),this.helper[0]!==this.currentItem[0]&&this.helper.remove(),this.helper=null,!t){for(i=0;s.length>i;i++)s[i].call(this,e);this._trigger("stop",e,this._uiHash())}return this.fromOutside=!1,!0},_trigger:function(){e.Widget.prototype._trigger.apply(this,arguments)===!1&&this.cancel()},_uiHash:function(t){var i=t||this;return{helper:i.helper,placeholder:i.placeholder||e([]),position:i.position,originalPosition:i.originalPosition,offset:i.positionAbs,item:i.currentItem,sender:t?t.element:null}}})})(jQuery); \ No newline at end of file diff --git a/Vocaluxe/Website/js/jquery.ui.touch-punch.min.js b/Vocaluxe/Website/js/jquery.ui.touch-punch.min.js new file mode 100644 index 00000000..33d6f97e --- /dev/null +++ b/Vocaluxe/Website/js/jquery.ui.touch-punch.min.js @@ -0,0 +1,11 @@ +/* + * jQuery UI Touch Punch 0.2.2 + * + * Copyright 2011, Dave Furfero + * Dual licensed under the MIT or GPL Version 2 licenses. + * + * Depends: + * jquery.ui.widget.js + * jquery.ui.mouse.js + */ +(function(b){b.support.touch="ontouchend" in document;if(!b.support.touch){return;}var c=b.ui.mouse.prototype,e=c._mouseInit,a;function d(g,h){if(g.originalEvent.touches.length>1){return;}g.preventDefault();var i=g.originalEvent.changedTouches[0],f=document.createEvent("MouseEvents");f.initMouseEvent(h,true,true,window,1,i.screenX,i.screenY,i.clientX,i.clientY,false,false,false,false,0,null);g.target.dispatchEvent(f);}c._touchStart=function(g){var f=this;if(a||!f._mouseCapture(g.originalEvent.changedTouches[0])){return;}a=true;f._touchMoved=false;d(g,"mouseover");d(g,"mousemove");d(g,"mousedown");};c._touchMove=function(f){if(!a){return;}this._touchMoved=true;d(f,"mousemove");};c._touchEnd=function(f){if(!a){return;}d(f,"mouseup");d(f,"mouseout");if(!this._touchMoved){d(f,"click");}a=false;};c._mouseInit=function(){var f=this;f.element.bind("touchstart",b.proxy(f,"_touchStart")).bind("touchmove",b.proxy(f,"_touchMove")).bind("touchend",b.proxy(f,"_touchEnd"));e.call(f);};})(jQuery); \ No newline at end of file diff --git a/Vocaluxe/Website/js/main.js b/Vocaluxe/Website/js/main.js index 924b8b85..3e2b385e 100644 --- a/Vocaluxe/Website/js/main.js +++ b/Vocaluxe/Website/js/main.js @@ -2,6 +2,9 @@ var ownProfileId = -1; var profileIdRequest = -1; var songIdRequest = -1; var allSongsCache = null; +var playlistIdRequest = -1; +var playlistRequestName = ""; +var customSelectPlaylistSongCallback = null; var sessionId = ""; $(document).ready(function () { @@ -197,6 +200,8 @@ function initPageLoadHandler() { url: "getSong?songId=" + songIdRequest, headers: { "session": sessionId } }).done(function (result) { + $('#displaySongAddPlaylist').hide(); + if (result.Title != null) { $('#displaySongTitle').text(result.Title); } @@ -239,6 +244,14 @@ function initPageLoadHandler() { if (result.Title != null || result.Artist != null) { $('#displaySongLinks').show(); + $('#displaySongAddPlaylist').unbind('click').click(function () { + customSelectPlaylistSongCallback = function (playlistId) { + request({ url: "addSongToPlaylist?songId=" + result.SongId + "&playlistId=" + playlistId + "&duplicates=false" }, "Add to playlist..."); + history.back(); + }; + $.mobile.changePage("#selectPlaylist", { transition: "slidefade" }); + }); + $('#displaySongLinkYoutube').unbind('click').click(function () { showYoutube(result.Artist, result.Title); }); @@ -253,6 +266,16 @@ function initPageLoadHandler() { } else { $('#displaySongLinks').hide(); } + + request({ + url: "hasUserRight?right=" + 0x32 + }).done(function (result2) { + if (result2) { + $('#displaySongAddPlaylist').show(); + } else { + $('#displaySongAddPlaylist').hide(); + } + }); }); // Save promise on page so the transition handler can find it. @@ -280,8 +303,7 @@ function initPageLoadHandler() { if (allSongsCache == null) { var promise = request({ - url: "getAllSongs", - headers: { "session": sessionId } + url: "getAllSongs" }).done(function (data) { allSongsCache = data; handleGetAllSongs(); @@ -350,6 +372,272 @@ function initPageLoadHandler() { //pageLoadHandler for login $(document).on('pagebeforeshow', '#login', pagebeforeshowLogin); + //pageLoadHandler for main + $(document).on('pagebeforeshow', '#main', function () { + request({ + url: "hasUserRight?right=" + 0x02 + }).done(function (result) { + if (result) { + $('#mainPageTakePhotoLink').parent().parent().parent().show(); + } else { + $('#mainPageTakePhotoLink').parent().parent().parent().hide(); + } + }); + + request({ + url: "hasUserRight?right=" + 0x08 + }).done(function (result) { + if (result) { + $('#mainPageKeyboard').parent().parent().parent().show(); + } else { + $('#mainPageKeyboard').parent().parent().parent().hide(); + } + }); + + request({ + url: "hasUserRight?right=" + 0x04 + }).done(function (result) { + if (result) { + $('#mainPageSelectProfile').parent().parent().parent().show(); + } else { + $('#mainPageSelectProfile').parent().parent().parent().hide(); + } + }); + }); + + //pageLoadHandler for selectPlaylist + $(document).on('pagebeforeshow', '#selectPlaylist', function () { + function handleGetAllPlaylists(data) { + $('#selectPlaylistContentList').children().remove(); + $('#selectPlaylistAddPlaylistButton').hide(); + + function handleSelectSongLineClick(e) { + playlistIdRequest = parseInt(e.currentTarget.parentElement.parentElement.parentElement.id.replace("selectPlaylistLine_", "")); + playlistRequestName = $(e.currentTarget.parentElement.parentElement.parentElement).find('h2').text(); + if (customSelectPlaylistSongCallback != null) { + customSelectPlaylistSongCallback(playlistIdRequest, playlistRequestName); + customSelectPlaylistSongCallback = null; + } else { + + $.mobile.changePage("#displayPlaylist", { transition: "slidefade" }); + } + } + + function handleSelectSongLineDeleteClick(e) { + var playlistToDeleteId = parseInt(e.currentTarget.parentElement.id.replace("selectPlaylistLine_", "")); + var playlistToDeleteName = $(e.currentTarget.parentElement).find('h2').text(); + if (window.confirm("Do you really want to delete this playlist:\n" + playlistToDeleteName)) { + request({ url: "removePlaylist?playlistId=" + playlistToDeleteId }, "Loading...").done(function () { + request({ + url: "getPlaylists" + }).done(function (data2) { + handleGetAllPlaylists(data2); + }); + }); + } + } + + for (var id in data) { + var line = $('
      1. '/*+' '*/ + + '

        ' + data[id].PlaylistName + '

        ' + + data[id].SongCount + + ' songs

        Delete
      2. ') + .appendTo('#selectPlaylistContentList'); + line.find('a:not(.delete)').click(handleSelectSongLineClick); + line.find('a.delete').click(handleSelectSongLineDeleteClick); + } + + $('#selectPlaylistContentList').listview('refresh'); + + request({ + url: "hasUserRight?right=" + 0x128 + }).done(function (result) { + if (result) { + $('#selectPlaylistContentList').find('.delete').show(); + $('#selectPlaylistContentList').listview('refresh'); + } else { + $('#selectPlaylistContentList').find('.delete').hide(); + $('#selectPlaylistContentList').listview('refresh'); + } + }); + + $('#selectPlaylistAddPlaylistButton').unbind('click').hide().click(function () { + var name = prompt("Name of the new playlist:", "NewPlaylistName"); + if (name != null + && name.replace(" ", "") != "" + && $('h2').filter(function () { return this.textContent == name; }).length == 0) { + request({ url: "addPlaylist?playlistName=" + name }, "Creating...").done(function () { + request({ + url: "getPlaylists" + }).done(function (data2) { + handleGetAllPlaylists(data2); + }); + }); + } else { + alert("This is not a name."); + } + }); + + request({ + url: "hasUserRight?right=" + 0x64 + }).done(function (result) { + if (result) { + $('#selectPlaylistAddPlaylistButton').show(); + } else { + $('#selectPlaylistAddPlaylistButton').hide(); + } + }); + } + + var promise = request({ + url: "getPlaylists" + }).done(function (data) { + handleGetAllPlaylists(data); + }); + + // Save promise on page so the transition handler can find it. + $(this).data('promise', promise); + + }); + + //pageLoadHandler for displayPlaylist + $(document).on('pagebeforeshow', '#displayPlaylist', function () { + function handleGetAllPlaylistSongs(data) { + $('#displayPlaylistHeader').find('h1').text(playlistRequestName); + + $('#displayPlaylistSaveButton').hide().unbind('click').click(function () { + var promises = []; + $('#displayPlaylistContentList').find('li').each(function (indx, elem) { + var newPos = $(elem).index(); + var oldPos = $(elem).data("oldPos"); + if (newPos != oldPos) { + var movedId = elem.id.replace("selectSongLine_", ""); + + promises.push(request({ + url: "moveSongInPlaylist?&newPosition=" + newPos + "&playlistId=" + playlistIdRequest + "&songId=" + movedId + }, "Resorting...")); + } + }); + + $.when.apply(promises).done(function () { + //reload data + request({ + url: "getPlaylistSongs?playlistId=" + playlistIdRequest + }).done(function (data2) { + handleGetAllPlaylistSongs(data2); + }); + }); + }); + + $('#displayPlaylistContentList').children().remove(); + + function handleSelectPlaylistSongLineClick(e) { + songIdRequest = parseInt(e.currentTarget.parentElement.parentElement.parentElement.id.replace("selectSongLine_", "")); + $.mobile.changePage("#displaySong", { transition: "slidefade" }); + } + + function handleSelectPlaylistSongLineDeleteClick(e) { + var songToDeleteId = parseInt(e.currentTarget.parentElement.id.replace("selectSongLine_", "")); + var songToDeleteName = $(e.currentTarget.parentElement).find('h2').text(); + + if (window.confirm("Do you really want to delete this song from playlist:\n" + songToDeleteName)) { + request({ + url: "/removeSongFromPlaylist?position=" + $('#selectSongLine_' + songToDeleteId).index() + + "&playlistId=" + playlistIdRequest + + "&songId=" + songToDeleteId + }, "Loading...").done(function () { + //reload data + request({ + url: "getPlaylistSongs?playlistId=" + playlistIdRequest + }).done(function (data2) { + handleGetAllPlaylistSongs(data2); + }); + }); + } + + + } + + var sortedData = []; + + for (var id1 in data) { + sortedData[data[id1].PlaylistPosition] = data[id1].Song; + } + var i = 0; + for (var id in sortedData) { + var line = $('
      3. ' + + sortedData[id].Artist + + '

        ' + + sortedData[id].Title + + '

        Delete
      4. ') + .appendTo('#displayPlaylistContentList').data("oldPos", i++); + + line.find('a:not(.delete)').click(handleSelectPlaylistSongLineClick); + line.find('a.delete').click(handleSelectPlaylistSongLineDeleteClick); + + var img = line.find("img")[0]; + + addImage(img, sortedData[id].Cover, "img/noCover.png"); + } + + $('#displayPlaylistContentList').listview('refresh'); + + request({ + url: "hasUserRight?right=" + 0x256 + }).done(function (result) { + if (result) { + $('#displayPlaylistContentList').find('.delete').show(); + $('#displayPlaylistContentList').listview('refresh'); + } else { + $('#displayPlaylistContentList').find('.delete').hide(); + $('#displayPlaylistContentList').listview('refresh'); + } + }); + + request({ + url: "hasUserRight?right=" + 0x16 + }).done(function (result) { + if (result) { + $('#displayPlaylistContentList').sortable({ + axis: 'y', + sort: function () { + $('#displayPlaylistSaveButton').show(); + + var $lis = $(this).children('li'); + $lis.each(function () { + var $li = $(this); + var hindex = $lis.filter('.ui-sortable-helper').index(); + if (!$li.is('.ui-sortable-helper')) { + var index = $li.index(); + index = index < hindex ? index + 1 : index; + + $li.val(index); + + if ($li.is('.ui-sortable-placeholder')) { + $lis.filter('.ui-sortable-helper').val(index); + } + } + }); + } + }); + } + }); + } + + var promise = request({ + url: "getPlaylistSongs?playlistId=" + playlistIdRequest + }).done(function (data) { + handleGetAllPlaylistSongs(data); + }); + + // Save promise on page so the transition handler can find it. + $(this).data('promise', promise); + + }); } function pagebeforeshowLogin() {