From 6fbd5cf46407a212fadb52eee00c7ac7690430ea Mon Sep 17 00:00:00 2001 From: LukePulverenti Luke Pulverenti luke pulverenti Date: Mon, 16 Jul 2012 12:50:44 -0400 Subject: All calls to get items now require passing in a userId. Made the model project portable. Also filled in more api calls. --- MediaBrowser.Api/HttpHandlers/StudiosHandler.cs | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 MediaBrowser.Api/HttpHandlers/StudiosHandler.cs (limited to 'MediaBrowser.Api/HttpHandlers/StudiosHandler.cs') diff --git a/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs b/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs new file mode 100644 index 0000000000..6b83b9e64f --- /dev/null +++ b/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs @@ -0,0 +1,26 @@ +using System; +using MediaBrowser.Common.Net; +using MediaBrowser.Common.Net.Handlers; +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Api.HttpHandlers +{ + public class StudiosHandler : JsonHandler + { + public StudiosHandler(RequestContext ctx) + : base(ctx) + { + } + + protected sealed override object ObjectToSerialize + { + get + { + Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder; + Guid userId = Guid.Parse(QueryString["userid"]); + + return ApiService.GetAllStudios(parent, userId); + } + } + } +} -- cgit v1.2.3 From 80b3ad7bd20329e6a5bbf6eeb76af62c87434a7c Mon Sep 17 00:00:00 2001 From: LukePulverenti Luke Pulverenti luke pulverenti Date: Thu, 19 Jul 2012 22:22:44 -0400 Subject: Moved the http server to it's own assembly. added comments and made other minor re-organizations. --- MediaBrowser.Api/ApiService.cs | 91 +---- MediaBrowser.Api/HttpHandlers/GenreHandler.cs | 6 - MediaBrowser.Api/HttpHandlers/GenresHandler.cs | 10 +- MediaBrowser.Api/HttpHandlers/ImageHandler.cs | 24 +- .../HttpHandlers/InProgressItemsHandler.cs | 6 - MediaBrowser.Api/HttpHandlers/ItemHandler.cs | 33 +- MediaBrowser.Api/HttpHandlers/ItemListHandler.cs | 10 +- MediaBrowser.Api/HttpHandlers/JsonHandler.cs | 16 + MediaBrowser.Api/HttpHandlers/MediaHandler.cs | 26 +- MediaBrowser.Api/HttpHandlers/PersonHandler.cs | 8 +- .../HttpHandlers/RecentlyAddedItemsHandler.cs | 6 - MediaBrowser.Api/HttpHandlers/StudioHandler.cs | 6 - MediaBrowser.Api/HttpHandlers/StudiosHandler.cs | 11 +- MediaBrowser.Api/HttpHandlers/UsersHandler.cs | 8 +- MediaBrowser.Api/MediaBrowser.Api.csproj | 7 +- MediaBrowser.Api/Model/BaseItemInfo.cs | 15 - MediaBrowser.Api/Plugin.cs | 73 +++- .../ApiInteraction/ApiController.cs | 77 ++-- .../ApiInteraction/DictionaryBaseItem.cs | 412 --------------------- MediaBrowser.Common/Json/JsonSerializer.cs | 12 +- MediaBrowser.Common/Logging/Logger.cs | 4 - MediaBrowser.Common/MediaBrowser.Common.csproj | 12 - MediaBrowser.Common/Net/CollectionExtensions.cs | 14 - .../Net/Handlers/BaseEmbeddedResourceHandler.cs | 70 ---- MediaBrowser.Common/Net/Handlers/JsonHandler.cs | 36 -- MediaBrowser.Common/Net/HttpServer.cs | 42 --- MediaBrowser.Common/Net/Request.cs | 18 - MediaBrowser.Common/Net/RequestContext.cs | 112 ------ MediaBrowser.Common/Net/Response.cs | 77 ---- MediaBrowser.Common/Net/StreamExtensions.cs | 19 - MediaBrowser.Common/Plugins/BasePlugin.cs | 6 +- .../Plugins/BasePluginConfiguration.cs | 7 +- MediaBrowser.Common/packages.config | 1 - .../Events/ItemResolveEventArgs.cs | 11 +- MediaBrowser.Controller/IO/DirectoryWatchers.cs | 4 +- MediaBrowser.Controller/IO/Shortcut.cs | 3 + MediaBrowser.Controller/Kernel.cs | 126 ++++++- MediaBrowser.Controller/Library/ItemController.cs | 6 + .../MediaBrowser.Controller.csproj | 4 + MediaBrowser.Controller/Resolvers/AudioResolver.cs | 2 + .../Resolvers/BaseItemResolver.cs | 19 + .../Resolvers/FolderResolver.cs | 1 + MediaBrowser.Controller/Resolvers/VideoResolver.cs | 14 +- MediaBrowser.Controller/UserController.cs | 35 +- MediaBrowser.Controller/Xml/BaseItemXmlParser.cs | 30 +- MediaBrowser.Controller/Xml/FolderXmlParser.cs | 4 + MediaBrowser.Controller/Xml/XmlExtensions.cs | 13 +- .../Handlers/EmbeddedResourceHandler.cs | 8 +- .../MediaBrowser.HtmlBrowser.csproj | 4 + MediaBrowser.HtmlBrowser/Plugin.cs | 6 +- MediaBrowser.Model/Entities/ApiBaseItem.cs | 39 ++ MediaBrowser.Model/Entities/BaseItem.cs | 78 ++-- MediaBrowser.Model/Entities/Folder.cs | 44 +-- MediaBrowser.Model/MediaBrowser.Model.csproj | 1 + MediaBrowser.Model/Users/User.cs | 1 - MediaBrowser.Movies/Entities/Movie.cs | 2 +- MediaBrowser.Movies/Metadata/MovieXmlParser.cs | 2 +- MediaBrowser.Net/CollectionExtensions.cs | 14 + .../Handlers/BaseEmbeddedResourceHandler.cs | 58 +++ MediaBrowser.Net/Handlers/BaseHandler.cs | 111 ++++++ MediaBrowser.Net/Handlers/BaseJsonHandler.cs | 11 + MediaBrowser.Net/HttpServer.cs | 42 +++ MediaBrowser.Net/MediaBrowser.Net.csproj | 66 ++++ MediaBrowser.Net/Properties/AssemblyInfo.cs | 36 ++ MediaBrowser.Net/Request.cs | 18 + MediaBrowser.Net/RequestContext.cs | 118 ++++++ MediaBrowser.Net/StreamExtensions.cs | 19 + MediaBrowser.Net/packages.config | 4 + MediaBrowser.TV/Entities/Episode.cs | 6 +- MediaBrowser.TV/Entities/Series.cs | 6 +- MediaBrowser.TV/Metadata/EpisodeXmlParser.cs | 13 +- MediaBrowser.TV/Metadata/SeriesXmlParser.cs | 4 +- MediaBrowser.sln | 6 + 73 files changed, 1053 insertions(+), 1211 deletions(-) create mode 100644 MediaBrowser.Api/HttpHandlers/JsonHandler.cs delete mode 100644 MediaBrowser.Api/Model/BaseItemInfo.cs delete mode 100644 MediaBrowser.Common/ApiInteraction/DictionaryBaseItem.cs delete mode 100644 MediaBrowser.Common/Net/CollectionExtensions.cs delete mode 100644 MediaBrowser.Common/Net/Handlers/BaseEmbeddedResourceHandler.cs delete mode 100644 MediaBrowser.Common/Net/Handlers/JsonHandler.cs delete mode 100644 MediaBrowser.Common/Net/HttpServer.cs delete mode 100644 MediaBrowser.Common/Net/Request.cs delete mode 100644 MediaBrowser.Common/Net/RequestContext.cs delete mode 100644 MediaBrowser.Common/Net/Response.cs delete mode 100644 MediaBrowser.Common/Net/StreamExtensions.cs create mode 100644 MediaBrowser.Model/Entities/ApiBaseItem.cs create mode 100644 MediaBrowser.Net/CollectionExtensions.cs create mode 100644 MediaBrowser.Net/Handlers/BaseEmbeddedResourceHandler.cs create mode 100644 MediaBrowser.Net/Handlers/BaseHandler.cs create mode 100644 MediaBrowser.Net/Handlers/BaseJsonHandler.cs create mode 100644 MediaBrowser.Net/HttpServer.cs create mode 100644 MediaBrowser.Net/MediaBrowser.Net.csproj create mode 100644 MediaBrowser.Net/Properties/AssemblyInfo.cs create mode 100644 MediaBrowser.Net/Request.cs create mode 100644 MediaBrowser.Net/RequestContext.cs create mode 100644 MediaBrowser.Net/StreamExtensions.cs create mode 100644 MediaBrowser.Net/packages.config (limited to 'MediaBrowser.Api/HttpHandlers/StudiosHandler.cs') diff --git a/MediaBrowser.Api/ApiService.cs b/MediaBrowser.Api/ApiService.cs index 2687ce81a0..e495937790 100644 --- a/MediaBrowser.Api/ApiService.cs +++ b/MediaBrowser.Api/ApiService.cs @@ -1,10 +1,16 @@ using System; using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; using MediaBrowser.Controller; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Users; namespace MediaBrowser.Api { + /// + /// Contains some helpers for the api + /// public static class ApiService { public static BaseItem GetItemById(string id) @@ -14,86 +20,29 @@ namespace MediaBrowser.Api return Kernel.Instance.GetItemById(guid); } - public static IEnumerable GetAllStudios(Folder parent, Guid userId) + /// + /// Takes a BaseItem and returns the actual object that will be serialized by the api + /// + public static ApiBaseItemWrapper GetSerializationObject(BaseItem item, bool includeChildren, Guid userId) { - Dictionary data = new Dictionary(); - - IEnumerable allItems = Kernel.Instance.GetParentalAllowedRecursiveChildren(parent, userId); - - foreach (var item in allItems) + ApiBaseItemWrapper wrapper = new ApiBaseItemWrapper() { - if (item.Studios == null) - { - continue; - } - - foreach (string val in item.Studios) - { - if (!data.ContainsKey(val)) - { - data.Add(val, 1); - } - else - { - data[val]++; - } - } - } + Item = item, + UserItemData = Kernel.Instance.GetUserItemData(userId, item.Id), + ItemType = item.GetType() + }; - List list = new List(); - - foreach (string key in data.Keys) + if (includeChildren) { - list.Add(new CategoryInfo() - { - Name = key, - ItemCount = data[key] - - }); - } - - return list; - } + var folder = item as Folder; - public static IEnumerable GetAllGenres(Folder parent, Guid userId) - { - Dictionary data = new Dictionary(); - - IEnumerable allItems = Kernel.Instance.GetParentalAllowedRecursiveChildren(parent, userId); - - foreach (var item in allItems) - { - if (item.Genres == null) - { - continue; - } - - foreach (string val in item.Genres) + if (folder != null) { - if (!data.ContainsKey(val)) - { - data.Add(val, 1); - } - else - { - data[val]++; - } + wrapper.Children = Kernel.Instance.GetParentalAllowedChildren(folder, userId).Select(c => GetSerializationObject(c, false, userId)); } } - List list = new List(); - - foreach (string key in data.Keys) - { - list.Add(new CategoryInfo() - { - Name = key, - ItemCount = data[key] - - }); - } - - return list; + return wrapper; } } } diff --git a/MediaBrowser.Api/HttpHandlers/GenreHandler.cs b/MediaBrowser.Api/HttpHandlers/GenreHandler.cs index f43e3e1b02..477705e827 100644 --- a/MediaBrowser.Api/HttpHandlers/GenreHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/GenreHandler.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Model.Entities; @@ -10,11 +9,6 @@ namespace MediaBrowser.Api.HttpHandlers /// public class GenreHandler : ItemListHandler { - public GenreHandler(RequestContext ctx) - : base(ctx) - { - } - protected override IEnumerable ItemsToSerialize { get diff --git a/MediaBrowser.Api/HttpHandlers/GenresHandler.cs b/MediaBrowser.Api/HttpHandlers/GenresHandler.cs index 794b746cd4..e8e3fd80b7 100644 --- a/MediaBrowser.Api/HttpHandlers/GenresHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/GenresHandler.cs @@ -1,17 +1,11 @@ using System; -using MediaBrowser.Common.Net; -using MediaBrowser.Common.Net.Handlers; +using MediaBrowser.Controller; using MediaBrowser.Model.Entities; namespace MediaBrowser.Api.HttpHandlers { public class GenresHandler : JsonHandler { - public GenresHandler(RequestContext ctx) - : base(ctx) - { - } - protected sealed override object ObjectToSerialize { get @@ -19,7 +13,7 @@ namespace MediaBrowser.Api.HttpHandlers Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder; Guid userId = Guid.Parse(QueryString["userid"]); - return ApiService.GetAllGenres(parent, userId); + return Kernel.Instance.GetAllGenres(parent, userId); } } } diff --git a/MediaBrowser.Api/HttpHandlers/ImageHandler.cs b/MediaBrowser.Api/HttpHandlers/ImageHandler.cs index ed6dcc3a9d..ae6228ae87 100644 --- a/MediaBrowser.Api/HttpHandlers/ImageHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/ImageHandler.cs @@ -1,27 +1,14 @@ using System; using System.IO; -using System.IO.Compression; using System.Linq; -using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Model.Entities; +using MediaBrowser.Net.Handlers; namespace MediaBrowser.Api.HttpHandlers { - public class ImageHandler : Response + public class ImageHandler : BaseHandler { - public ImageHandler(RequestContext ctx) - : base(ctx) - { - Headers["Content-Encoding"] = "gzip"; - - WriteStream = s => - { - WriteReponse(s); - s.Close(); - }; - } - private string _ImagePath = string.Empty; private string ImagePath { @@ -149,12 +136,9 @@ namespace MediaBrowser.Api.HttpHandlers } } - private void WriteReponse(Stream stream) + protected override void WriteResponseToOutputStream(Stream stream) { - using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Compress, false)) - { - ImageProcessor.ProcessImage(ImagePath, gzipStream, Width, Height, MaxWidth, MaxHeight, Quality); - } + ImageProcessor.ProcessImage(ImagePath, stream, Width, Height, MaxWidth, MaxHeight, Quality); } private string GetImagePath() diff --git a/MediaBrowser.Api/HttpHandlers/InProgressItemsHandler.cs b/MediaBrowser.Api/HttpHandlers/InProgressItemsHandler.cs index e13cee866c..2bee275a45 100644 --- a/MediaBrowser.Api/HttpHandlers/InProgressItemsHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/InProgressItemsHandler.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Model.Entities; @@ -7,11 +6,6 @@ namespace MediaBrowser.Api.HttpHandlers { class InProgressItemsHandler : ItemListHandler { - public InProgressItemsHandler(RequestContext ctx) - : base(ctx) - { - } - protected override IEnumerable ItemsToSerialize { get diff --git a/MediaBrowser.Api/HttpHandlers/ItemHandler.cs b/MediaBrowser.Api/HttpHandlers/ItemHandler.cs index dd508d1037..2ff2354939 100644 --- a/MediaBrowser.Api/HttpHandlers/ItemHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/ItemHandler.cs @@ -1,48 +1,19 @@ using System; -using MediaBrowser.Api.Model; -using MediaBrowser.Common.Net; -using MediaBrowser.Common.Net.Handlers; -using MediaBrowser.Controller; +using MediaBrowser.Net.Handlers; using MediaBrowser.Model.Entities; namespace MediaBrowser.Api.HttpHandlers { public class ItemHandler : JsonHandler { - public ItemHandler(RequestContext ctx) - : base(ctx) - { - } - protected sealed override object ObjectToSerialize { get { Guid userId = Guid.Parse(QueryString["userid"]); - return GetSerializationObject(ItemToSerialize, true, userId); - } - } - - public static object GetSerializationObject(BaseItem item, bool includeChildren, Guid userId) - { - BaseItemInfo wrapper = new BaseItemInfo() - { - Item = item, - UserItemData = Kernel.Instance.GetUserItemData(userId, item.Id) - }; - - if (includeChildren) - { - var folder = item as Folder; - - if (folder != null) - { - wrapper.Children = Kernel.Instance.GetParentalAllowedChildren(folder, userId); - } + return ApiService.GetSerializationObject(ItemToSerialize, true, userId); } - - return wrapper; } protected virtual BaseItem ItemToSerialize diff --git a/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs b/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs index ed6e895f38..54af1b7e91 100644 --- a/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs @@ -1,26 +1,20 @@ using System; using System.Collections.Generic; using System.Linq; -using MediaBrowser.Common.Net; -using MediaBrowser.Common.Net.Handlers; +using MediaBrowser.Net.Handlers; using MediaBrowser.Model.Entities; namespace MediaBrowser.Api.HttpHandlers { public abstract class ItemListHandler : JsonHandler { - public ItemListHandler(RequestContext ctx) - : base(ctx) - { - } - protected sealed override object ObjectToSerialize { get { return ItemsToSerialize.Select(i => { - return ItemHandler.GetSerializationObject(i, false, UserId); + return ApiService.GetSerializationObject(i, false, UserId); }); } diff --git a/MediaBrowser.Api/HttpHandlers/JsonHandler.cs b/MediaBrowser.Api/HttpHandlers/JsonHandler.cs new file mode 100644 index 0000000000..e663085ec7 --- /dev/null +++ b/MediaBrowser.Api/HttpHandlers/JsonHandler.cs @@ -0,0 +1,16 @@ +using System.IO; +using MediaBrowser.Common.Json; +using MediaBrowser.Net.Handlers; + +namespace MediaBrowser.Api.HttpHandlers +{ + public abstract class JsonHandler : BaseJsonHandler + { + protected abstract object ObjectToSerialize { get; } + + protected override void WriteResponseToOutputStream(Stream stream) + { + JsonSerializer.SerializeToStream(ObjectToSerialize, stream); + } + } +} diff --git a/MediaBrowser.Api/HttpHandlers/MediaHandler.cs b/MediaBrowser.Api/HttpHandlers/MediaHandler.cs index d04ff21996..47aab3c410 100644 --- a/MediaBrowser.Api/HttpHandlers/MediaHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/MediaHandler.cs @@ -1,23 +1,12 @@ using System; using System.IO; -using System.IO.Compression; -using MediaBrowser.Common.Net; using MediaBrowser.Model.Entities; +using MediaBrowser.Net.Handlers; namespace MediaBrowser.Api.HttpHandlers { - class MediaHandler : Response + class MediaHandler : BaseHandler { - public MediaHandler(RequestContext ctx) - : base(ctx) - { - WriteStream = s => - { - WriteReponse(s); - s.Close(); - }; - } - private string _MediaPath = string.Empty; private string MediaPath { @@ -46,6 +35,14 @@ namespace MediaBrowser.Api.HttpHandlers return item.Path; } + public override bool GzipResponse + { + get + { + return false; + } + } + public override string ContentType { get @@ -87,7 +84,7 @@ namespace MediaBrowser.Api.HttpHandlers } } - private void WriteReponse(Stream stream) + protected override void WriteResponseToOutputStream(Stream stream) { try { @@ -100,6 +97,5 @@ namespace MediaBrowser.Api.HttpHandlers { } } - } } diff --git a/MediaBrowser.Api/HttpHandlers/PersonHandler.cs b/MediaBrowser.Api/HttpHandlers/PersonHandler.cs index 6a9d376791..3c1a0ecf3a 100644 --- a/MediaBrowser.Api/HttpHandlers/PersonHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/PersonHandler.cs @@ -1,16 +1,10 @@ -using MediaBrowser.Common.Net; -using MediaBrowser.Controller; +using MediaBrowser.Controller; using MediaBrowser.Model.Entities; namespace MediaBrowser.Api.HttpHandlers { public class PersonHandler : ItemHandler { - public PersonHandler(RequestContext ctx) - : base(ctx) - { - } - protected override BaseItem ItemToSerialize { get diff --git a/MediaBrowser.Api/HttpHandlers/RecentlyAddedItemsHandler.cs b/MediaBrowser.Api/HttpHandlers/RecentlyAddedItemsHandler.cs index 8d85eedf4e..f36c9c9975 100644 --- a/MediaBrowser.Api/HttpHandlers/RecentlyAddedItemsHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/RecentlyAddedItemsHandler.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Model.Entities; @@ -7,11 +6,6 @@ namespace MediaBrowser.Api.HttpHandlers { class RecentlyAddedItemsHandler : ItemListHandler { - public RecentlyAddedItemsHandler(RequestContext ctx) - : base(ctx) - { - } - protected override IEnumerable ItemsToSerialize { get diff --git a/MediaBrowser.Api/HttpHandlers/StudioHandler.cs b/MediaBrowser.Api/HttpHandlers/StudioHandler.cs index 9426d0b7c0..019ced0281 100644 --- a/MediaBrowser.Api/HttpHandlers/StudioHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/StudioHandler.cs @@ -1,5 +1,4 @@ using System.Collections.Generic; -using MediaBrowser.Common.Net; using MediaBrowser.Controller; using MediaBrowser.Model.Entities; @@ -10,11 +9,6 @@ namespace MediaBrowser.Api.HttpHandlers /// public class StudioHandler : ItemListHandler { - public StudioHandler(RequestContext ctx) - : base(ctx) - { - } - protected override IEnumerable ItemsToSerialize { get diff --git a/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs b/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs index 6b83b9e64f..66daca7774 100644 --- a/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs @@ -1,17 +1,12 @@ using System; -using MediaBrowser.Common.Net; -using MediaBrowser.Common.Net.Handlers; +using MediaBrowser.Net.Handlers; +using MediaBrowser.Controller; using MediaBrowser.Model.Entities; namespace MediaBrowser.Api.HttpHandlers { public class StudiosHandler : JsonHandler { - public StudiosHandler(RequestContext ctx) - : base(ctx) - { - } - protected sealed override object ObjectToSerialize { get @@ -19,7 +14,7 @@ namespace MediaBrowser.Api.HttpHandlers Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder; Guid userId = Guid.Parse(QueryString["userid"]); - return ApiService.GetAllStudios(parent, userId); + return Kernel.Instance.GetAllStudios(parent, userId); } } } diff --git a/MediaBrowser.Api/HttpHandlers/UsersHandler.cs b/MediaBrowser.Api/HttpHandlers/UsersHandler.cs index aa8dac11e4..816d4e83ac 100644 --- a/MediaBrowser.Api/HttpHandlers/UsersHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/UsersHandler.cs @@ -1,16 +1,10 @@ -using MediaBrowser.Common.Net; -using MediaBrowser.Common.Net.Handlers; +using MediaBrowser.Net.Handlers; using MediaBrowser.Controller; namespace MediaBrowser.Api.HttpHandlers { class UsersHandler : JsonHandler { - public UsersHandler(RequestContext ctx) - : base(ctx) - { - } - protected override object ObjectToSerialize { get diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index f493da552a..dd5c072324 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -37,6 +37,7 @@ False ..\packages\Rx-Main.1.0.11226\lib\Net4\System.Reactive.dll + @@ -51,6 +52,7 @@ + @@ -58,7 +60,6 @@ - @@ -75,6 +76,10 @@ {7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b} MediaBrowser.Model + + {5da08d1c-0d52-4b1b-aa66-e4a171d938f6} + MediaBrowser.Net + diff --git a/MediaBrowser.Api/Model/BaseItemInfo.cs b/MediaBrowser.Api/Model/BaseItemInfo.cs deleted file mode 100644 index 646c273905..0000000000 --- a/MediaBrowser.Api/Model/BaseItemInfo.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.Collections.Generic; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Users; - -namespace MediaBrowser.Api.Model -{ - public class BaseItemInfo - { - public BaseItem Item { get; set; } - - public UserItemData UserItemData { get; set; } - - public IEnumerable Children { get; set; } - } -} diff --git a/MediaBrowser.Api/Plugin.cs b/MediaBrowser.Api/Plugin.cs index 91bd906c8b..af885ef825 100644 --- a/MediaBrowser.Api/Plugin.cs +++ b/MediaBrowser.Api/Plugin.cs @@ -3,6 +3,8 @@ using System.Reactive.Linq; using MediaBrowser.Api.HttpHandlers; using MediaBrowser.Common.Plugins; using MediaBrowser.Controller; +using MediaBrowser.Net; +using MediaBrowser.Net.Handlers; namespace MediaBrowser.Api { @@ -12,25 +14,70 @@ namespace MediaBrowser.Api { var httpServer = Kernel.Instance.HttpServer; - httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/users", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new UsersHandler(ctx))); + httpServer.Where(ctx => ctx.LocalPath.IndexOf("/api/", StringComparison.OrdinalIgnoreCase) != -1).Subscribe(ctx => + { + BaseHandler handler = GetHandler(ctx); - httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/media", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new MediaHandler(ctx))); - - httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/item", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new ItemHandler(ctx))); - - httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/image", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new ImageHandler(ctx))); - - httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/genre", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new GenreHandler(ctx))); + if (handler != null) + { + ctx.Respond(handler); + } + }); + } - httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/genres", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new GenresHandler(ctx))); + private BaseHandler GetHandler(RequestContext ctx) + { + BaseHandler handler = null; - httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/studio", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new StudioHandler(ctx))); + string localPath = ctx.LocalPath; - httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/studios", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new StudiosHandler(ctx))); + if (localPath.EndsWith("/api/item", StringComparison.OrdinalIgnoreCase)) + { + handler = new ItemHandler(); + } + else if (localPath.EndsWith("/api/image", StringComparison.OrdinalIgnoreCase)) + { + handler = new ImageHandler(); + } + else if (localPath.EndsWith("/api/users", StringComparison.OrdinalIgnoreCase)) + { + handler = new UsersHandler(); + } + else if (localPath.EndsWith("/api/media", StringComparison.OrdinalIgnoreCase)) + { + handler = new MediaHandler(); + } + else if (localPath.EndsWith("/api/genre", StringComparison.OrdinalIgnoreCase)) + { + handler = new GenreHandler(); + } + else if (localPath.EndsWith("/api/genres", StringComparison.OrdinalIgnoreCase)) + { + handler = new GenresHandler(); + } + else if (localPath.EndsWith("/api/studio", StringComparison.OrdinalIgnoreCase)) + { + handler = new StudioHandler(); + } + else if (localPath.EndsWith("/api/studios", StringComparison.OrdinalIgnoreCase)) + { + handler = new StudiosHandler(); + } + else if (localPath.EndsWith("/api/recentlyaddeditems", StringComparison.OrdinalIgnoreCase)) + { + handler = new RecentlyAddedItemsHandler(); + } + else if (localPath.EndsWith("/api/inprogressitems", StringComparison.OrdinalIgnoreCase)) + { + handler = new InProgressItemsHandler(); + } - httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/recentlyaddeditems", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new RecentlyAddedItemsHandler(ctx))); + if (handler != null) + { + handler.RequestContext = ctx; + } - httpServer.Where(ctx => ctx.LocalPath.EndsWith("/api/inprogressitems", StringComparison.OrdinalIgnoreCase)).Subscribe(ctx => ctx.Respond(new InProgressItemsHandler(ctx))); + return handler; } } } diff --git a/MediaBrowser.Common/ApiInteraction/ApiController.cs b/MediaBrowser.Common/ApiInteraction/ApiController.cs index f237573550..b3a51c512e 100644 --- a/MediaBrowser.Common/ApiInteraction/ApiController.cs +++ b/MediaBrowser.Common/ApiInteraction/ApiController.cs @@ -2,11 +2,12 @@ using System.Collections.Generic; using System.IO; using System.IO.Compression; +using System.Linq; using System.Net; using System.Threading.Tasks; using MediaBrowser.Common.Json; -using MediaBrowser.Model.Users; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Users; namespace MediaBrowser.Common.ApiInteraction { @@ -21,19 +22,20 @@ namespace MediaBrowser.Common.ApiInteraction WebClient = new WebClient(); } - public async Task GetRootItem(Guid userId) + public async Task> GetRootItem(Guid userId) { string url = ApiUrl + "/item?userId=" + userId.ToString(); - Stream stream = await WebClient.OpenReadTaskAsync(url); - - using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) + using (Stream stream = await WebClient.OpenReadTaskAsync(url)) { - return DictionaryBaseItem.FromApiOutput(gzipStream); + using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) + { + return DeserializeBaseItemWrapper(gzipStream); + } } } - public async Task GetItem(Guid id, Guid userId) + public async Task> GetItem(Guid id, Guid userId) { string url = ApiUrl + "/item?userId=" + userId.ToString(); @@ -42,11 +44,12 @@ namespace MediaBrowser.Common.ApiInteraction url += "&id=" + id.ToString(); } - Stream stream = await WebClient.OpenReadTaskAsync(url); - - using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) + using (Stream stream = await WebClient.OpenReadTaskAsync(url)) { - return DictionaryBaseItem.FromApiOutput(gzipStream); + using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) + { + return DeserializeBaseItemWrapper(gzipStream); + } } } @@ -54,11 +57,12 @@ namespace MediaBrowser.Common.ApiInteraction { string url = ApiUrl + "/users"; - Stream stream = await WebClient.OpenReadTaskAsync(url); - - using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) + using (Stream stream = await WebClient.OpenReadTaskAsync(url)) { - return JsonSerializer.DeserializeFromStream>(gzipStream); + using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) + { + return JsonSerializer.DeserializeFromStream>(gzipStream); + } } } @@ -66,11 +70,12 @@ namespace MediaBrowser.Common.ApiInteraction { string url = ApiUrl + "/genres?userId=" + userId.ToString(); - Stream stream = await WebClient.OpenReadTaskAsync(url); - - using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) + using (Stream stream = await WebClient.OpenReadTaskAsync(url)) { - return JsonSerializer.DeserializeFromStream>(gzipStream); + using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) + { + return JsonSerializer.DeserializeFromStream>(gzipStream); + } } } @@ -78,11 +83,12 @@ namespace MediaBrowser.Common.ApiInteraction { string url = ApiUrl + "/genre?userId=" + userId.ToString() + "&name=" + name; - Stream stream = await WebClient.OpenReadTaskAsync(url); - - using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) + using (Stream stream = await WebClient.OpenReadTaskAsync(url)) { - return JsonSerializer.DeserializeFromStream(gzipStream); + using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) + { + return JsonSerializer.DeserializeFromStream(gzipStream); + } } } @@ -90,11 +96,12 @@ namespace MediaBrowser.Common.ApiInteraction { string url = ApiUrl + "/studios?userId=" + userId.ToString(); - Stream stream = await WebClient.OpenReadTaskAsync(url); - - using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) + using (Stream stream = await WebClient.OpenReadTaskAsync(url)) { - return JsonSerializer.DeserializeFromStream>(gzipStream); + using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) + { + return JsonSerializer.DeserializeFromStream>(gzipStream); + } } } @@ -102,12 +109,20 @@ namespace MediaBrowser.Common.ApiInteraction { string url = ApiUrl + "/studio?userId=" + userId.ToString() + "&name=" + name; - Stream stream = await WebClient.OpenReadTaskAsync(url); - - using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) + using (Stream stream = await WebClient.OpenReadTaskAsync(url)) { - return JsonSerializer.DeserializeFromStream(gzipStream); + using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) + { + return JsonSerializer.DeserializeFromStream(gzipStream); + } } } + + private static ApiBaseItemWrapper DeserializeBaseItemWrapper(Stream stream) + { + ApiBaseItemWrapper data = JsonSerializer.DeserializeFromStream>(stream); + + return data; + } } } diff --git a/MediaBrowser.Common/ApiInteraction/DictionaryBaseItem.cs b/MediaBrowser.Common/ApiInteraction/DictionaryBaseItem.cs deleted file mode 100644 index 2bd6f1bcd5..0000000000 --- a/MediaBrowser.Common/ApiInteraction/DictionaryBaseItem.cs +++ /dev/null @@ -1,412 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using MediaBrowser.Common.Json; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Users; -using System.Linq; - -namespace MediaBrowser.Common.ApiInteraction -{ - public class DictionaryBaseItem : BaseItem - { - private Dictionary Dictionary { get; set; } - - public UserItemData UserItemData { get; set; } - public IEnumerable Children { get; set; } - - public DictionaryBaseItem(Dictionary dictionary) - { - Dictionary = dictionary; - } - - public override string Name - { - get - { - return GetString("Name"); - } - set - { - SetValue("Name", value); - } - } - - public override string ArtImagePath - { - get - { - return GetString("ArtImagePath"); - } - set - { - SetValue("ArtImagePath", value); - } - } - - public override string AspectRatio - { - get - { - return GetString("AspectRatio"); - } - set - { - SetValue("AspectRatio", value); - } - } - - public override string BannerImagePath - { - get - { - return GetString("BannerImagePath"); - } - set - { - SetValue("BannerImagePath", value); - } - } - - public override string CustomPin - { - get - { - return GetString("CustomPin"); - } - set - { - SetValue("CustomPin", value); - } - } - - public override string CustomRating - { - get - { - return GetString("CustomRating"); - } - set - { - SetValue("CustomRating", value); - } - } - - public override string DisplayMediaType - { - get - { - return GetString("DisplayMediaType"); - } - set - { - SetValue("DisplayMediaType", value); - } - } - - public override string LogoImagePath - { - get - { - return GetString("LogoImagePath"); - } - set - { - SetValue("LogoImagePath", value); - } - } - - public override string OfficialRating - { - get - { - return GetString("OfficialRating"); - } - set - { - SetValue("OfficialRating", value); - } - } - - public override string Overview - { - get - { - return GetString("Overview"); - } - set - { - SetValue("Overview", value); - } - } - - public override string Path - { - get - { - return GetString("Path"); - } - set - { - SetValue("Path", value); - } - } - - public override string PrimaryImagePath - { - get - { - return GetString("PrimaryImagePath"); - } - set - { - SetValue("PrimaryImagePath", value); - } - } - - public override string SortName - { - get - { - return GetString("SortName"); - } - set - { - SetValue("SortName", value); - } - } - - public override string Tagline - { - get - { - return GetString("Tagline"); - } - set - { - SetValue("Tagline", value); - } - } - - public override string TrailerUrl - { - get - { - return GetString("TrailerUrl"); - } - set - { - SetValue("TrailerUrl", value); - } - } - - public override DateTime DateCreated - { - get - { - return GetDateTime("DateCreated"); - } - set - { - SetValue("DateCreated", value); - } - } - - public override DateTime DateModified - { - get - { - return GetDateTime("DateModified"); - } - set - { - SetValue("DateModified", value); - } - } - - public override float? UserRating - { - get - { - return GetNullableFloat("UserRating"); - } - set - { - SetValue("UserRating", value); - } - } - - public override string ThumbnailImagePath - { - get - { - return GetString("ThumbnailImagePath"); - } - set - { - SetValue("ThumbnailImagePath", value); - } - } - - public override int? ProductionYear - { - get - { - return GetNullableInt("ProductionYear"); - } - set - { - SetValue("ProductionYear", value); - } - } - - public override TimeSpan? RunTime - { - get - { - return GetNullableTimeSpan("RunTime"); - } - set - { - SetValue("RunTime", value); - } - } - - public bool IsFolder - { - get - { - return GetBool("IsFolder"); - } - } - - public override Guid Id - { - get - { - return GetGuid("Id"); - } - set - { - SetValue("Id", value); - } - } - - public TimeSpan? GetNullableTimeSpan(string name) - { - string val = Dictionary[name] as string; - - if (string.IsNullOrEmpty(val)) - { - return null; - } - - return TimeSpan.Parse(val); - } - - public int? GetNullableInt(string name) - { - string val = Dictionary[name] as string; - - if (string.IsNullOrEmpty(val)) - { - return null; - } - - return int.Parse(val); - } - - public float? GetNullableFloat(string name) - { - string val = Dictionary[name] as string; - - if (string.IsNullOrEmpty(val)) - { - return null; - } - - return float.Parse(val); - } - - public DateTime? GetNullableDateTime(string name) - { - string val = Dictionary[name] as string; - - if (string.IsNullOrEmpty(val)) - { - return null; - } - - return DateTime.Parse(val); - } - - public DateTime GetDateTime(string name) - { - DateTime? val = GetNullableDateTime(name); - - return val ?? DateTime.MinValue; - } - - public bool? GetNullableBool(string name) - { - string val = Dictionary[name] as string; - - if (string.IsNullOrEmpty(val)) - { - return null; - } - - return val != "false"; - } - - public Guid GetGuid(string name) - { - string val = GetString(name); - - if (string.IsNullOrEmpty(val)) - { - return Guid.Empty; - } - - return Guid.Parse(val); - } - - public bool GetBool(string name) - { - bool? val = GetNullableBool(name); - - return val ?? false; - } - - public string GetString(string name) - { - return Dictionary[name] as string; - } - - private void SetValue(string name, T value) - { - Dictionary[name] = value; - } - - public static DictionaryBaseItem FromApiOutput(Stream stream) - { - Dictionary data = JsonSerializer.DeserializeFromStream>(stream); - - string baseItem = data["Item"] as string; - - DictionaryBaseItem item = new DictionaryBaseItem(JsonSerializer.DeserializeFromString>(baseItem)); - - if (data.ContainsKey("UserItemData")) - { - item.UserItemData = JsonSerializer.DeserializeFromString(data["UserItemData"].ToString()); - } - - if (data.ContainsKey("Children")) - { - item.Children = JsonSerializer.DeserializeFromString>>(data["Children"].ToString()).Select(c => new DictionaryBaseItem(c)); - } - - return item; - } - } -} diff --git a/MediaBrowser.Common/Json/JsonSerializer.cs b/MediaBrowser.Common/Json/JsonSerializer.cs index 55663357ab..a882334897 100644 --- a/MediaBrowser.Common/Json/JsonSerializer.cs +++ b/MediaBrowser.Common/Json/JsonSerializer.cs @@ -1,23 +1,24 @@ using System.IO; +using System; namespace MediaBrowser.Common.Json { public class JsonSerializer { - public static void SerializeToStream(T o, Stream stream) + public static void SerializeToStream(T obj, Stream stream) { Configure(); - ServiceStack.Text.JsonSerializer.SerializeToStream(o, stream); + ServiceStack.Text.JsonSerializer.SerializeToStream(obj, stream); } - public static void SerializeToFile(T o, string file) + public static void SerializeToFile(T obj, string file) { Configure(); using (StreamWriter streamWriter = new StreamWriter(file)) { - ServiceStack.Text.JsonSerializer.SerializeToWriter(o, streamWriter); + ServiceStack.Text.JsonSerializer.SerializeToWriter(obj, streamWriter); } } @@ -44,12 +45,11 @@ namespace MediaBrowser.Common.Json return ServiceStack.Text.JsonSerializer.DeserializeFromString(data); } - + private static void Configure() { ServiceStack.Text.JsConfig.ExcludeTypeInfo = true; ServiceStack.Text.JsConfig.IncludeNullValues = false; - ServiceStack.Text.JsConfig.DateHandler = ServiceStack.Text.JsonDateHandler.ISO8601; } } } diff --git a/MediaBrowser.Common/Logging/Logger.cs b/MediaBrowser.Common/Logging/Logger.cs index 5f4c2ff795..d1ae9b8f35 100644 --- a/MediaBrowser.Common/Logging/Logger.cs +++ b/MediaBrowser.Common/Logging/Logger.cs @@ -1,8 +1,4 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace MediaBrowser.Common.Logging { diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index f822b1a2bd..252c9c8cca 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -35,9 +35,6 @@ - - ..\packages\Rx-Main.1.0.11226\lib\Net4\System.Reactive.dll - @@ -48,15 +45,6 @@ - - - - - - - - - diff --git a/MediaBrowser.Common/Net/CollectionExtensions.cs b/MediaBrowser.Common/Net/CollectionExtensions.cs deleted file mode 100644 index 98d24dfc04..0000000000 --- a/MediaBrowser.Common/Net/CollectionExtensions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Linq; - -namespace MediaBrowser.Common.Net -{ - public static class CollectionExtensions - { - public static IDictionary> ToDictionary(this NameValueCollection source) - { - return source.AllKeys.ToDictionary>(key => key, source.GetValues); - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Common/Net/Handlers/BaseEmbeddedResourceHandler.cs b/MediaBrowser.Common/Net/Handlers/BaseEmbeddedResourceHandler.cs deleted file mode 100644 index e64773f33f..0000000000 --- a/MediaBrowser.Common/Net/Handlers/BaseEmbeddedResourceHandler.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System.IO; -using System.IO.Compression; -using System; - -namespace MediaBrowser.Common.Net.Handlers -{ - public abstract class BaseEmbeddedResourceHandler : Response - { - public BaseEmbeddedResourceHandler(RequestContext ctx, string resourcePath) - : base(ctx) - { - ResourcePath = resourcePath; - - Headers["Content-Encoding"] = "gzip"; - - WriteStream = s => - { - WriteReponse(s); - s.Close(); - }; - } - - protected string ResourcePath { get; set; } - - public override string ContentType - { - get - { - string extension = Path.GetExtension(ResourcePath); - - if (extension.EndsWith("jpeg", StringComparison.OrdinalIgnoreCase) || extension.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)) - { - return "image/jpeg"; - } - else if (extension.EndsWith("png", StringComparison.OrdinalIgnoreCase)) - { - return "image/png"; - } - else if (extension.EndsWith("ico", StringComparison.OrdinalIgnoreCase)) - { - return "image/ico"; - } - else if (extension.EndsWith("js", StringComparison.OrdinalIgnoreCase)) - { - return "application/x-javascript"; - } - else if (extension.EndsWith("css", StringComparison.OrdinalIgnoreCase)) - { - return "text/css"; - } - else if (extension.EndsWith("html", StringComparison.OrdinalIgnoreCase)) - { - return "text/html; charset=utf-8"; - } - - return "text/plain; charset=utf-8"; - } - } - - private void WriteReponse(Stream stream) - { - using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Compress, false)) - { - GetEmbeddedResourceStream().CopyTo(gzipStream); - } - } - - protected abstract Stream GetEmbeddedResourceStream(); - } -} diff --git a/MediaBrowser.Common/Net/Handlers/JsonHandler.cs b/MediaBrowser.Common/Net/Handlers/JsonHandler.cs deleted file mode 100644 index ecfdd311a1..0000000000 --- a/MediaBrowser.Common/Net/Handlers/JsonHandler.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.IO; -using System.IO.Compression; -using MediaBrowser.Common.Json; - -namespace MediaBrowser.Common.Net.Handlers -{ - public abstract class JsonHandler : Response - { - public JsonHandler(RequestContext ctx) - : base(ctx) - { - Headers["Content-Encoding"] = "gzip"; - - WriteStream = s => - { - WriteReponse(s); - s.Close(); - }; - } - - public override string ContentType - { - get { return "application/json"; } - } - - protected abstract object ObjectToSerialize { get; } - - private void WriteReponse(Stream stream) - { - using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Compress, false)) - { - JsonSerializer.SerializeToStream(ObjectToSerialize, gzipStream); - } - } - } -} diff --git a/MediaBrowser.Common/Net/HttpServer.cs b/MediaBrowser.Common/Net/HttpServer.cs deleted file mode 100644 index fad8d13eb9..0000000000 --- a/MediaBrowser.Common/Net/HttpServer.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Net; -using System.Reactive.Linq; - -namespace MediaBrowser.Common.Net -{ - public class HttpServer : IObservable, IDisposable - { - private readonly HttpListener listener; - private readonly IObservable stream; - - public HttpServer(string url) - { - listener = new HttpListener(); - listener.Prefixes.Add(url); - listener.Start(); - stream = ObservableHttpContext(); - } - - private IObservable ObservableHttpContext() - { - return Observable.Create(obs => - Observable.FromAsyncPattern(listener.BeginGetContext, - listener.EndGetContext)() - .Select(c => new RequestContext(c)) - .Subscribe(obs)) - .Repeat() - .Retry() - .Publish() - .RefCount(); - } - public void Dispose() - { - listener.Stop(); - } - - public IDisposable Subscribe(IObserver observer) - { - return stream.Subscribe(observer); - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Common/Net/Request.cs b/MediaBrowser.Common/Net/Request.cs deleted file mode 100644 index 795c9c36ba..0000000000 --- a/MediaBrowser.Common/Net/Request.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace MediaBrowser.Common.Net -{ - public class Request - { - public string HttpMethod { get; set; } - public IDictionary> Headers { get; set; } - public Stream InputStream { get; set; } - public string RawUrl { get; set; } - public int ContentLength - { - get { return int.Parse(Headers["Content-Length"].First()); } - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Common/Net/RequestContext.cs b/MediaBrowser.Common/Net/RequestContext.cs deleted file mode 100644 index d3635f34a5..0000000000 --- a/MediaBrowser.Common/Net/RequestContext.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; -using System.Linq; -using System.Net; - -namespace MediaBrowser.Common.Net -{ - public class RequestContext - { - public HttpListenerRequest Request { get; private set; } - public HttpListenerResponse Response { get; private set; } - - public string LocalPath - { - get - { - return Request.Url.LocalPath; - } - } - - public RequestContext(HttpListenerContext context) - { - Response = context.Response; - Request = context.Request; - } - - public void Respond(Response handler) - { - Response.AddHeader("Access-Control-Allow-Origin", "*"); - - Response.KeepAlive = true; - - foreach (var header in handler.Headers) - { - Response.AddHeader(header.Key, header.Value); - } - - int statusCode = handler.StatusCode; - Response.ContentType = handler.ContentType; - - TimeSpan cacheDuration = handler.CacheDuration; - - if (Request.Headers.AllKeys.Contains("If-Modified-Since")) - { - DateTime ifModifiedSince; - - if (DateTime.TryParse(Request.Headers["If-Modified-Since"].Replace(" GMT", string.Empty), out ifModifiedSince)) - { - // If the cache hasn't expired yet just return a 304 - if (IsCacheValid(ifModifiedSince, cacheDuration, handler.LastDateModified)) - { - statusCode = 304; - } - } - } - - Response.SendChunked = true; - Response.StatusCode = statusCode; - - if (statusCode != 304) - { - if (cacheDuration.Ticks > 0) - { - CacheResponse(Response, cacheDuration, handler.LastDateModified); - } - handler.WriteStream(Response.OutputStream); - } - else - { - Response.OutputStream.Flush(); - Response.OutputStream.Close(); - } - } - - private void CacheResponse(HttpListenerResponse response, TimeSpan duration, DateTime? dateModified) - { - DateTime lastModified = dateModified ?? DateTime.Now; - - response.Headers[HttpResponseHeader.CacheControl] = "Public"; - response.Headers[HttpResponseHeader.Expires] = DateTime.Now.Add(duration).ToString("r"); - response.Headers[HttpResponseHeader.LastModified] = lastModified.ToString("r"); - } - - private bool IsCacheValid(DateTime ifModifiedSince, TimeSpan cacheDuration, DateTime? dateModified) - { - if (dateModified.HasValue) - { - DateTime lastModified = NormalizeDateForComparison(dateModified.Value); - ifModifiedSince = NormalizeDateForComparison(ifModifiedSince); - - return lastModified <= ifModifiedSince; - } - - DateTime cacheExpirationDate = ifModifiedSince.Add(cacheDuration); - - if (DateTime.Now < cacheExpirationDate) - { - return true; - } - - return false; - } - - /// - /// When the browser sends the IfModifiedDate, it's precision is limited to seconds, so this will account for that - /// - private DateTime NormalizeDateForComparison(DateTime date) - { - return new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second); - } - - } -} \ No newline at end of file diff --git a/MediaBrowser.Common/Net/Response.cs b/MediaBrowser.Common/Net/Response.cs deleted file mode 100644 index 44b4e29622..0000000000 --- a/MediaBrowser.Common/Net/Response.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.IO; - -namespace MediaBrowser.Common.Net -{ - public abstract class Response - { - protected RequestContext RequestContext { get; private set; } - - protected NameValueCollection QueryString - { - get - { - return RequestContext.Request.QueryString; - } - } - - public Response(RequestContext ctx) - { - RequestContext = ctx; - - WriteStream = s => { }; - Headers = new Dictionary(); - } - - public abstract string ContentType { get; } - - public virtual int StatusCode - { - get - { - return 200; - } - } - - public virtual TimeSpan CacheDuration - { - get - { - return TimeSpan.FromTicks(0); - } - } - - public virtual DateTime? LastDateModified - { - get - { - return null; - } - } - - public IDictionary Headers { get; set; } - public Action WriteStream { get; set; } - } - - /*public class ByteResponse : Response - { - public ByteResponse(byte[] bytes) - { - WriteStream = async s => - { - await s.WriteAsync(bytes, 0, bytes.Length); - s.Close(); - }; - } - } - - public class StringResponse : ByteResponse - { - public StringResponse(string message) - : base(Encoding.UTF8.GetBytes(message)) - { - } - }*/ -} \ No newline at end of file diff --git a/MediaBrowser.Common/Net/StreamExtensions.cs b/MediaBrowser.Common/Net/StreamExtensions.cs deleted file mode 100644 index c10e458ada..0000000000 --- a/MediaBrowser.Common/Net/StreamExtensions.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.IO; -using System.Reactive.Linq; - -namespace MediaBrowser.Common.Net -{ - public static class StreamExtensions - { - public static IObservable ReadBytes(this Stream stream, int count) - { - var buffer = new byte[count]; - return Observable.FromAsyncPattern((cb, state) => stream.BeginRead(buffer, 0, count, cb, state), ar => - { - stream.EndRead(ar); - return buffer; - })(); - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Common/Plugins/BasePlugin.cs b/MediaBrowser.Common/Plugins/BasePlugin.cs index 3438b09c20..be72dabca3 100644 --- a/MediaBrowser.Common/Plugins/BasePlugin.cs +++ b/MediaBrowser.Common/Plugins/BasePlugin.cs @@ -1,8 +1,4 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; +using System.IO; using MediaBrowser.Common.Json; namespace MediaBrowser.Common.Plugins diff --git a/MediaBrowser.Common/Plugins/BasePluginConfiguration.cs b/MediaBrowser.Common/Plugins/BasePluginConfiguration.cs index ad7972d949..d3e47c84a4 100644 --- a/MediaBrowser.Common/Plugins/BasePluginConfiguration.cs +++ b/MediaBrowser.Common/Plugins/BasePluginConfiguration.cs @@ -1,9 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - + namespace MediaBrowser.Common.Plugins { public class BasePluginConfiguration diff --git a/MediaBrowser.Common/packages.config b/MediaBrowser.Common/packages.config index 15a978d36c..aad898882a 100644 --- a/MediaBrowser.Common/packages.config +++ b/MediaBrowser.Common/packages.config @@ -1,5 +1,4 @@  - \ No newline at end of file diff --git a/MediaBrowser.Controller/Events/ItemResolveEventArgs.cs b/MediaBrowser.Controller/Events/ItemResolveEventArgs.cs index c05c139fb0..7c4af71ebc 100644 --- a/MediaBrowser.Controller/Events/ItemResolveEventArgs.cs +++ b/MediaBrowser.Controller/Events/ItemResolveEventArgs.cs @@ -1,11 +1,13 @@ using System; using System.Collections.Generic; -using MediaBrowser.Model.Entities; using System.IO; -using System.Linq; +using MediaBrowser.Model.Entities; namespace MediaBrowser.Controller.Events { + /// + /// This is an EventArgs object used when resolving a Path into a BaseItem + /// public class ItemResolveEventArgs : PreBeginResolveEventArgs { public IEnumerable> FileSystemChildren { get; set; } @@ -57,6 +59,11 @@ namespace MediaBrowser.Controller.Events } } + /// + /// This is an EventArgs object used before we begin resolving a Path into a BaseItem + /// File system children have not been collected yet, but consuming events will + /// have a chance to cancel resolution based on the Path, Parent and FileAttributes + /// public class PreBeginResolveEventArgs : EventArgs { public string Path { get; set; } diff --git a/MediaBrowser.Controller/IO/DirectoryWatchers.cs b/MediaBrowser.Controller/IO/DirectoryWatchers.cs index dd27695834..8d102e80ce 100644 --- a/MediaBrowser.Controller/IO/DirectoryWatchers.cs +++ b/MediaBrowser.Controller/IO/DirectoryWatchers.cs @@ -24,9 +24,9 @@ namespace MediaBrowser.Controller.IO pathsToWatch.Add(rootFolder.Path); - foreach (Folder folder in rootFolder.FolderChildren) + foreach (Folder folder in rootFolder.Children.OfType()) { - foreach (Folder subFolder in folder.FolderChildren) + foreach (Folder subFolder in folder.Children.OfType()) { if (Path.IsPathRooted(subFolder.Path)) { diff --git a/MediaBrowser.Controller/IO/Shortcut.cs b/MediaBrowser.Controller/IO/Shortcut.cs index 376d16a795..83e2c0eda3 100644 --- a/MediaBrowser.Controller/IO/Shortcut.cs +++ b/MediaBrowser.Controller/IO/Shortcut.cs @@ -5,6 +5,9 @@ using System.Text; namespace MediaBrowser.Controller.IO { + /// + /// Contains helpers to interact with shortcut files (.lnk) + /// public static class Shortcut { #region Signitures were imported from http://pinvoke.net diff --git a/MediaBrowser.Controller/Kernel.cs b/MediaBrowser.Controller/Kernel.cs index 3f6e7bbb0e..9cbef68740 100644 --- a/MediaBrowser.Controller/Kernel.cs +++ b/MediaBrowser.Controller/Kernel.cs @@ -7,7 +7,6 @@ using System.Text; using System.Threading.Tasks; using MediaBrowser.Common.Json; using MediaBrowser.Common.Logging; -using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; using MediaBrowser.Controller.Events; using MediaBrowser.Controller.IO; @@ -16,6 +15,7 @@ using MediaBrowser.Controller.Resolvers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Users; +using MediaBrowser.Net; namespace MediaBrowser.Controller { @@ -79,7 +79,7 @@ namespace MediaBrowser.Controller ReloadHttpServer(); - ReloadPlugins(); + LoadPlugins(); // Get users from users folder // Load root media folder @@ -94,7 +94,7 @@ namespace MediaBrowser.Controller Logger.LoggerInstance.LogSeverity = Configuration.LogSeverity; } - private void ReloadPlugins() + private void LoadPlugins() { // Find plugins Plugins = PluginController.GetAllPlugins(); @@ -261,7 +261,7 @@ namespace MediaBrowser.Controller /// public IEnumerable GetParentalAllowedChildren(Folder folder, Guid userId) { - return folder.Children.ToList().Where(i => IsParentalAllowed(i, userId)); + return folder.Children.Where(i => IsParentalAllowed(i, userId)); } /// @@ -307,7 +307,7 @@ namespace MediaBrowser.Controller { DateTime now = DateTime.Now; - return GetParentalAllowedRecursiveChildren(parent, userId).Where(i => (now - i.DateCreated).TotalDays < Configuration.RecentItemDays); + return GetParentalAllowedRecursiveChildren(parent, userId).Where(i => !(i is Folder) && (now - i.DateCreated).TotalDays < Configuration.RecentItemDays); } /// @@ -330,6 +330,11 @@ namespace MediaBrowser.Controller { return GetParentalAllowedRecursiveChildren(parent, userId).Where(i => { + if (i is Folder) + { + return false; + } + var userdata = GetUserItemData(userId, i.Id); return userdata != null && userdata.PlaybackPosition.Ticks > 0; @@ -359,5 +364,116 @@ namespace MediaBrowser.Controller { return GetParentalAllowedRecursiveChildren(parent, userId).Where(f => f.People != null && f.People.Any(s => s.Name.Equals(personName, StringComparison.OrdinalIgnoreCase))); } + + /// + /// Gets all studios from all recursive children of a folder + /// The CategoryInfo class is used to keep track of the number of times each studio appears + /// + public IEnumerable GetAllStudios(Folder parent, Guid userId) + { + Dictionary data = new Dictionary(); + + // Get all the allowed recursive children + IEnumerable allItems = Kernel.Instance.GetParentalAllowedRecursiveChildren(parent, userId); + + foreach (var item in allItems) + { + // Add each studio from the item to the data dictionary + // If the studio already exists, increment the count + if (item.Studios == null) + { + continue; + } + + foreach (string val in item.Studios) + { + if (!data.ContainsKey(val)) + { + data.Add(val, 1); + } + else + { + data[val]++; + } + } + } + + // Now go through the dictionary and create a Category for each studio + List list = new List(); + + foreach (string key in data.Keys) + { + // Get the original entity so that we can also supply the PrimaryImagePath + Studio entity = Kernel.Instance.ItemController.GetStudio(key); + + if (entity != null) + { + list.Add(new CategoryInfo() + { + Name = entity.Name, + ItemCount = data[key], + PrimaryImagePath = entity.PrimaryImagePath + }); + } + } + + return list; + } + + /// + /// Gets all genres from all recursive children of a folder + /// The CategoryInfo class is used to keep track of the number of times each genres appears + /// + public IEnumerable GetAllGenres(Folder parent, Guid userId) + { + Dictionary data = new Dictionary(); + + // Get all the allowed recursive children + IEnumerable allItems = Kernel.Instance.GetParentalAllowedRecursiveChildren(parent, userId); + + foreach (var item in allItems) + { + // Add each genre from the item to the data dictionary + // If the genre already exists, increment the count + if (item.Genres == null) + { + continue; + } + + foreach (string val in item.Genres) + { + if (!data.ContainsKey(val)) + { + data.Add(val, 1); + } + else + { + data[val]++; + } + } + } + + // Now go through the dictionary and create a Category for each genre + List list = new List(); + + foreach (string key in data.Keys) + { + // Get the original entity so that we can also supply the PrimaryImagePath + Genre entity = Kernel.Instance.ItemController.GetGenre(key); + + if (entity != null) + { + list.Add(new CategoryInfo() + { + Name = entity.Name, + ItemCount = data[key], + PrimaryImagePath = entity.PrimaryImagePath + }); + } + } + + return list; + } + } } diff --git a/MediaBrowser.Controller/Library/ItemController.cs b/MediaBrowser.Controller/Library/ItemController.cs index b872e8dbae..fee53e3bb6 100644 --- a/MediaBrowser.Controller/Library/ItemController.cs +++ b/MediaBrowser.Controller/Library/ItemController.cs @@ -323,6 +323,12 @@ namespace MediaBrowser.Controller.Library return null; } + public Genre GetGenre(string name) + { + // not yet implemented + return null; + } + public Year GetYear(int value) { // not yet implemented diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj index 719d279eeb..1f57090a67 100644 --- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj +++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj @@ -66,6 +66,10 @@ {7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b} MediaBrowser.Model + + {5da08d1c-0d52-4b1b-aa66-e4a171d938f6} + MediaBrowser.Net + diff --git a/MediaBrowser.Controller/Resolvers/AudioResolver.cs b/MediaBrowser.Controller/Resolvers/AudioResolver.cs index f9ce5ecd70..2ca54e71d4 100644 --- a/MediaBrowser.Controller/Resolvers/AudioResolver.cs +++ b/MediaBrowser.Controller/Resolvers/AudioResolver.cs @@ -8,6 +8,8 @@ namespace MediaBrowser.Controller.Resolvers { protected override Audio Resolve(ItemResolveEventArgs args) { + // Return audio if the path is a file and has a matching extension + if (!args.IsFolder) { if (IsAudioFile(args.Path)) diff --git a/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs b/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs index e2c49e90c1..dccdf57e1b 100644 --- a/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs +++ b/MediaBrowser.Controller/Resolvers/BaseItemResolver.cs @@ -15,6 +15,9 @@ namespace MediaBrowser.Controller.Resolvers return null; } + /// + /// Sets initial values on the newly resolved item + /// protected virtual void SetItemValues(T item, ItemResolveEventArgs args) { // If the subclass didn't specify this @@ -23,6 +26,7 @@ namespace MediaBrowser.Controller.Resolvers item.Path = args.Path; } + // If the subclass didn't specify this if (args.Parent != null) { item.Parent = args.Parent; @@ -40,9 +44,14 @@ namespace MediaBrowser.Controller.Resolvers if (item != null) { + // Set initial values on the newly resolved item + SetItemValues(item, args); + // Make sure the item has a name EnsureName(item); + + // Make sure DateCreated and DateModified have values EnsureDates(item); } @@ -59,6 +68,9 @@ namespace MediaBrowser.Controller.Resolvers } + /// + /// Ensures DateCreated and DateModified have values + /// private void EnsureDates(T item) { // If the subclass didn't supply dates, add them here @@ -73,6 +85,9 @@ namespace MediaBrowser.Controller.Resolvers } } + /// + /// Fills in image paths based on files win the folder + /// protected virtual void PopulateImages(T item, ItemResolveEventArgs args) { List backdropFiles = new List(); @@ -88,6 +103,7 @@ namespace MediaBrowser.Controller.Resolvers string ext = Path.GetExtension(filePath); + // Only support png and jpg files if (!ext.EndsWith("png", StringComparison.OrdinalIgnoreCase) && !ext.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)) { continue; @@ -137,6 +153,9 @@ namespace MediaBrowser.Controller.Resolvers } } + /// + /// Weed this to keep a list of resolvers, since Resolvers are built with generics + /// public interface IBaseItemResolver { BaseItem ResolvePath(ItemResolveEventArgs args); diff --git a/MediaBrowser.Controller/Resolvers/FolderResolver.cs b/MediaBrowser.Controller/Resolvers/FolderResolver.cs index 5c57c6bb3c..6101a45fd8 100644 --- a/MediaBrowser.Controller/Resolvers/FolderResolver.cs +++ b/MediaBrowser.Controller/Resolvers/FolderResolver.cs @@ -29,6 +29,7 @@ namespace MediaBrowser.Controller.Resolvers item.IsRoot = args.Parent == null; + // Read data from folder.xml, if it exists PopulateFolderMetadata(item, args); } diff --git a/MediaBrowser.Controller/Resolvers/VideoResolver.cs b/MediaBrowser.Controller/Resolvers/VideoResolver.cs index ba51dab875..df304c3290 100644 --- a/MediaBrowser.Controller/Resolvers/VideoResolver.cs +++ b/MediaBrowser.Controller/Resolvers/VideoResolver.cs @@ -1,20 +1,26 @@ -using System.IO; +using System.Collections.Generic; +using System.IO; using MediaBrowser.Controller.Events; using MediaBrowser.Model.Entities; -using System.Linq; -using System.Collections.Generic; namespace MediaBrowser.Controller.Resolvers { + /// + /// Resolves a Path into a Video + /// public class VideoResolver : BaseVideoResolver diff --git a/MediaBrowser.HtmlBrowser/Plugin.cs b/MediaBrowser.HtmlBrowser/Plugin.cs index 1599881d0b..db3f72f6f5 100644 --- a/MediaBrowser.HtmlBrowser/Plugin.cs +++ b/MediaBrowser.HtmlBrowser/Plugin.cs @@ -1,6 +1,6 @@ using System; using System.Reactive.Linq; -using MediaBrowser.Common.Net.Handlers; +using MediaBrowser.Net.Handlers; using MediaBrowser.Common.Plugins; using MediaBrowser.Controller; using MediaBrowser.HtmlBrowser.Handlers; @@ -13,7 +13,7 @@ namespace MediaBrowser.HtmlBrowser { var httpServer = Kernel.Instance.HttpServer; - httpServer.Where(ctx => ctx.LocalPath.IndexOf("/browser/", StringComparison.OrdinalIgnoreCase) != -1).Subscribe(ctx => + /*httpServer.Where(ctx => ctx.LocalPath.IndexOf("/browser/", StringComparison.OrdinalIgnoreCase) != -1).Subscribe(ctx => { string localPath = ctx.LocalPath; string srch = "/browser/"; @@ -24,7 +24,7 @@ namespace MediaBrowser.HtmlBrowser ctx.Respond(new EmbeddedResourceHandler(ctx, resource)); - }); + });*/ } } } diff --git a/MediaBrowser.Model/Entities/ApiBaseItem.cs b/MediaBrowser.Model/Entities/ApiBaseItem.cs new file mode 100644 index 0000000000..bdab9239a1 --- /dev/null +++ b/MediaBrowser.Model/Entities/ApiBaseItem.cs @@ -0,0 +1,39 @@ +using System; +using System.Collections.Generic; +using System.Runtime.Serialization; +using MediaBrowser.Model.Users; + +namespace MediaBrowser.Model.Entities +{ + /// + /// This is a concrete class that the UI can use to deserialize + /// It is flat in the sense that it will be used regardless of the type of BaseItem involved + /// + public class ApiBaseItem : BaseItem + { + } + + /// + /// This is the full return object when requesting an Item + /// + public class ApiBaseItemWrapper + where T : BaseItem + { + public T Item { get; set; } + + public UserItemData UserItemData { get; set; } + + public IEnumerable> Children { get; set; } + + [IgnoreDataMember] + public Type ItemType { get; set; } + + public string Type + { + get + { + return ItemType.Name; + } + } + } +} diff --git a/MediaBrowser.Model/Entities/BaseItem.cs b/MediaBrowser.Model/Entities/BaseItem.cs index 165328ac7b..46f859c9dc 100644 --- a/MediaBrowser.Model/Entities/BaseItem.cs +++ b/MediaBrowser.Model/Entities/BaseItem.cs @@ -6,70 +6,70 @@ namespace MediaBrowser.Model.Entities { public abstract class BaseItem { - public virtual string Name { get; set; } - public virtual string SortName { get; set; } + public string Name { get; set; } + public string SortName { get; set; } - public virtual Guid Id { get; set; } + public Guid Id { get; set; } - public virtual DateTime DateCreated { get; set; } + public DateTime DateCreated { get; set; } - public virtual DateTime DateModified { get; set; } + public DateTime DateModified { get; set; } - public virtual string Path { get; set; } + /// + /// When the item first debuted. For movies this could be premiere date, episodes would be first aired + /// + public DateTime? PremiereDate { get; set; } + + public string Path { get; set; } [IgnoreDataMember] public Folder Parent { get; set; } - public virtual string PrimaryImagePath { get; set; } - public virtual string LogoImagePath { get; set; } - public virtual string ArtImagePath { get; set; } - public virtual string ThumbnailImagePath { get; set; } - public virtual string BannerImagePath { get; set; } + public string PrimaryImagePath { get; set; } + public string LogoImagePath { get; set; } + public string ArtImagePath { get; set; } + public string ThumbnailImagePath { get; set; } + public string BannerImagePath { get; set; } - public virtual IEnumerable BackdropImagePaths { get; set; } + public IEnumerable BackdropImagePaths { get; set; } - public virtual string OfficialRating { get; set; } + public string OfficialRating { get; set; } - public virtual string CustomRating { get; set; } - public virtual string CustomPin { get; set; } + public string CustomRating { get; set; } + public string CustomPin { get; set; } - public virtual string Overview { get; set; } - public virtual string Tagline { get; set; } + public string Overview { get; set; } + public string Tagline { get; set; } [IgnoreDataMember] - public virtual IEnumerable People { get; set; } + public IEnumerable People { get; set; } - public virtual IEnumerable Studios { get; set; } + public IEnumerable Studios { get; set; } - public virtual IEnumerable Genres { get; set; } + public IEnumerable Genres { get; set; } - public virtual string DisplayMediaType { get; set; } + public string DisplayMediaType { get; set; } - public virtual float? UserRating { get; set; } - public virtual TimeSpan? RunTime { get; set; } + public float? UserRating { get; set; } + public TimeSpan? RunTime { get; set; } - public virtual string AspectRatio { get; set; } - public virtual int? ProductionYear { get; set; } + public string AspectRatio { get; set; } + public int? ProductionYear { get; set; } + + /// + /// If the item is part of a series, this is it's number in the series. + /// This could be episode number, album track number, etc. + /// + public int? IndexNumber { get; set; } [IgnoreDataMember] - public virtual IEnumerable + diff --git a/MediaBrowser.Model/Users/User.cs b/MediaBrowser.Model/Users/User.cs index 316e5b55c7..3761d981d4 100644 --- a/MediaBrowser.Model/Users/User.cs +++ b/MediaBrowser.Model/Users/User.cs @@ -6,7 +6,6 @@ namespace MediaBrowser.Model.Users { public class User : BaseItem { - public string Password { get; set; } public string MaxParentalRating { get; set; } private Dictionary _ItemData = new Dictionary(); diff --git a/MediaBrowser.Movies/Entities/Movie.cs b/MediaBrowser.Movies/Entities/Movie.cs index 2c44e7917e..585b5b7773 100644 --- a/MediaBrowser.Movies/Entities/Movie.cs +++ b/MediaBrowser.Movies/Entities/Movie.cs @@ -1,6 +1,6 @@ using System.Collections.Generic; -using MediaBrowser.Model.Entities; using System.Runtime.Serialization; +using MediaBrowser.Model.Entities; namespace MediaBrowser.Movies.Entities { diff --git a/MediaBrowser.Movies/Metadata/MovieXmlParser.cs b/MediaBrowser.Movies/Metadata/MovieXmlParser.cs index d8bbb49cbf..67650fa985 100644 --- a/MediaBrowser.Movies/Metadata/MovieXmlParser.cs +++ b/MediaBrowser.Movies/Metadata/MovieXmlParser.cs @@ -17,7 +17,7 @@ namespace MediaBrowser.Movies.Metadata case "IMDB": case "IMDbId": string IMDbId = reader.ReadElementContentAsString() ?? string.Empty; - if (!string.IsNullOrEmpty(IMDbId)) + if (!string.IsNullOrWhiteSpace(IMDbId)) { item.ImdbId = IMDbId; } diff --git a/MediaBrowser.Net/CollectionExtensions.cs b/MediaBrowser.Net/CollectionExtensions.cs new file mode 100644 index 0000000000..a6b59904f3 --- /dev/null +++ b/MediaBrowser.Net/CollectionExtensions.cs @@ -0,0 +1,14 @@ +using System.Collections.Generic; +using System.Collections.Specialized; +using System.Linq; + +namespace MediaBrowser.Net +{ + public static class CollectionExtensions + { + public static IDictionary> ToDictionary(this NameValueCollection source) + { + return source.AllKeys.ToDictionary>(key => key, source.GetValues); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Net/Handlers/BaseEmbeddedResourceHandler.cs b/MediaBrowser.Net/Handlers/BaseEmbeddedResourceHandler.cs new file mode 100644 index 0000000000..d7f579d05a --- /dev/null +++ b/MediaBrowser.Net/Handlers/BaseEmbeddedResourceHandler.cs @@ -0,0 +1,58 @@ +using System; +using System.IO; + +namespace MediaBrowser.Net.Handlers +{ + public abstract class BaseEmbeddedResourceHandler : BaseHandler + { + public BaseEmbeddedResourceHandler(string resourcePath) + : base() + { + ResourcePath = resourcePath; + } + + protected string ResourcePath { get; set; } + + public override string ContentType + { + get + { + string extension = Path.GetExtension(ResourcePath); + + if (extension.EndsWith("jpeg", StringComparison.OrdinalIgnoreCase) || extension.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)) + { + return "image/jpeg"; + } + else if (extension.EndsWith("png", StringComparison.OrdinalIgnoreCase)) + { + return "image/png"; + } + else if (extension.EndsWith("ico", StringComparison.OrdinalIgnoreCase)) + { + return "image/ico"; + } + else if (extension.EndsWith("js", StringComparison.OrdinalIgnoreCase)) + { + return "application/x-javascript"; + } + else if (extension.EndsWith("css", StringComparison.OrdinalIgnoreCase)) + { + return "text/css"; + } + else if (extension.EndsWith("html", StringComparison.OrdinalIgnoreCase)) + { + return "text/html; charset=utf-8"; + } + + return "text/plain; charset=utf-8"; + } + } + + protected override void WriteResponseToOutputStream(Stream stream) + { + GetEmbeddedResourceStream().CopyTo(stream); + } + + protected abstract Stream GetEmbeddedResourceStream(); + } +} diff --git a/MediaBrowser.Net/Handlers/BaseHandler.cs b/MediaBrowser.Net/Handlers/BaseHandler.cs new file mode 100644 index 0000000000..7a2bcffe97 --- /dev/null +++ b/MediaBrowser.Net/Handlers/BaseHandler.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.IO.Compression; + +namespace MediaBrowser.Net.Handlers +{ + public abstract class BaseHandler + { + /// + /// Response headers + /// + public IDictionary Headers = new Dictionary(); + + /// + /// The action to write the response to the output stream + /// + public Action WriteStream { get; set; } + + /// + /// The original RequestContext + /// + public RequestContext RequestContext { get; set; } + + /// + /// The original QueryString + /// + protected NameValueCollection QueryString + { + get + { + return RequestContext.Request.QueryString; + } + } + + /// + /// Gets the MIME type to include in the response headers + /// + public abstract string ContentType { get; } + + /// + /// Gets the status code to include in the response headers + /// + public virtual int StatusCode + { + get + { + return 200; + } + } + + /// + /// Gets the cache duration to include in the response headers + /// + public virtual TimeSpan CacheDuration + { + get + { + return TimeSpan.FromTicks(0); + } + } + + /// + /// Gets the last date modified of the content being returned, if this can be determined. + /// This will be used to invalidate the cache, so it's not needed if CacheDuration is 0. + /// + public virtual DateTime? LastDateModified + { + get + { + return null; + } + } + + public virtual bool GzipResponse + { + get + { + return true; + } + } + + public BaseHandler() + { + WriteStream = s => + { + WriteReponse(s); + s.Close(); + }; + } + + private void WriteReponse(Stream stream) + { + if (GzipResponse) + { + using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Compress, false)) + { + WriteResponseToOutputStream(gzipStream); + } + } + else + { + WriteResponseToOutputStream(stream); + } + } + + protected abstract void WriteResponseToOutputStream(Stream stream); + + } +} \ No newline at end of file diff --git a/MediaBrowser.Net/Handlers/BaseJsonHandler.cs b/MediaBrowser.Net/Handlers/BaseJsonHandler.cs new file mode 100644 index 0000000000..725b89c32e --- /dev/null +++ b/MediaBrowser.Net/Handlers/BaseJsonHandler.cs @@ -0,0 +1,11 @@ + +namespace MediaBrowser.Net.Handlers +{ + public abstract class BaseJsonHandler : BaseHandler + { + public override string ContentType + { + get { return "application/json"; } + } + } +} diff --git a/MediaBrowser.Net/HttpServer.cs b/MediaBrowser.Net/HttpServer.cs new file mode 100644 index 0000000000..aa24538d05 --- /dev/null +++ b/MediaBrowser.Net/HttpServer.cs @@ -0,0 +1,42 @@ +using System; +using System.Net; +using System.Reactive.Linq; + +namespace MediaBrowser.Net +{ + public class HttpServer : IObservable, IDisposable + { + private readonly HttpListener listener; + private readonly IObservable stream; + + public HttpServer(string url) + { + listener = new HttpListener(); + listener.Prefixes.Add(url); + listener.Start(); + stream = ObservableHttpContext(); + } + + private IObservable ObservableHttpContext() + { + return Observable.Create(obs => + Observable.FromAsyncPattern(listener.BeginGetContext, + listener.EndGetContext)() + .Select(c => new RequestContext(c)) + .Subscribe(obs)) + .Repeat() + .Retry() + .Publish() + .RefCount(); + } + public void Dispose() + { + listener.Stop(); + } + + public IDisposable Subscribe(IObserver observer) + { + return stream.Subscribe(observer); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Net/MediaBrowser.Net.csproj b/MediaBrowser.Net/MediaBrowser.Net.csproj new file mode 100644 index 0000000000..6f1b7cccfe --- /dev/null +++ b/MediaBrowser.Net/MediaBrowser.Net.csproj @@ -0,0 +1,66 @@ + + + + + Debug + AnyCPU + {5DA08D1C-0D52-4B1B-AA66-E4A171D938F6} + Library + Properties + MediaBrowser.Net + MediaBrowser.Net + v4.5 + 512 + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + ..\packages\Rx-Main.1.0.11226\lib\Net4\System.Reactive.dll + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MediaBrowser.Net/Properties/AssemblyInfo.cs b/MediaBrowser.Net/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..00964b6a26 --- /dev/null +++ b/MediaBrowser.Net/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("MediaBrowser.Net")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("MediaBrowser.Net")] +[assembly: AssemblyCopyright("Copyright © 2012")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("eacc40b5-e24e-4467-8000-f40874048d45")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/MediaBrowser.Net/Request.cs b/MediaBrowser.Net/Request.cs new file mode 100644 index 0000000000..43f854233e --- /dev/null +++ b/MediaBrowser.Net/Request.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace MediaBrowser.Net +{ + public class Request + { + public string HttpMethod { get; set; } + public IDictionary> Headers { get; set; } + public Stream InputStream { get; set; } + public string RawUrl { get; set; } + public int ContentLength + { + get { return int.Parse(Headers["Content-Length"].First()); } + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Net/RequestContext.cs b/MediaBrowser.Net/RequestContext.cs new file mode 100644 index 0000000000..4c1350701c --- /dev/null +++ b/MediaBrowser.Net/RequestContext.cs @@ -0,0 +1,118 @@ +using System; +using System.Linq; +using System.Net; +using MediaBrowser.Net.Handlers; + +namespace MediaBrowser.Net +{ + public class RequestContext + { + public HttpListenerRequest Request { get; private set; } + public HttpListenerResponse Response { get; private set; } + + public string LocalPath + { + get + { + return Request.Url.LocalPath; + } + } + + public RequestContext(HttpListenerContext context) + { + Response = context.Response; + Request = context.Request; + } + + public void Respond(BaseHandler handler) + { + Response.AddHeader("Access-Control-Allow-Origin", "*"); + + Response.KeepAlive = true; + + foreach (var header in handler.Headers) + { + Response.AddHeader(header.Key, header.Value); + } + + int statusCode = handler.StatusCode; + Response.ContentType = handler.ContentType; + + TimeSpan cacheDuration = handler.CacheDuration; + + if (Request.Headers.AllKeys.Contains("If-Modified-Since")) + { + DateTime ifModifiedSince; + + if (DateTime.TryParse(Request.Headers["If-Modified-Since"].Replace(" GMT", string.Empty), out ifModifiedSince)) + { + // If the cache hasn't expired yet just return a 304 + if (IsCacheValid(ifModifiedSince, cacheDuration, handler.LastDateModified)) + { + statusCode = 304; + } + } + } + + Response.SendChunked = true; + Response.StatusCode = statusCode; + + if (statusCode != 304) + { + if (handler.GzipResponse) + { + Response.AddHeader("Content-Encoding", "gzip"); + } + + if (cacheDuration.Ticks > 0) + { + CacheResponse(Response, cacheDuration, handler.LastDateModified); + } + handler.WriteStream(Response.OutputStream); + } + else + { + Response.OutputStream.Flush(); + Response.OutputStream.Close(); + } + } + + private void CacheResponse(HttpListenerResponse response, TimeSpan duration, DateTime? dateModified) + { + DateTime lastModified = dateModified ?? DateTime.Now; + + response.Headers[HttpResponseHeader.CacheControl] = "Public"; + response.Headers[HttpResponseHeader.Expires] = DateTime.Now.Add(duration).ToString("r"); + response.Headers[HttpResponseHeader.LastModified] = lastModified.ToString("r"); + } + + private bool IsCacheValid(DateTime ifModifiedSince, TimeSpan cacheDuration, DateTime? dateModified) + { + if (dateModified.HasValue) + { + DateTime lastModified = NormalizeDateForComparison(dateModified.Value); + ifModifiedSince = NormalizeDateForComparison(ifModifiedSince); + + return lastModified <= ifModifiedSince; + } + + DateTime cacheExpirationDate = ifModifiedSince.Add(cacheDuration); + + if (DateTime.Now < cacheExpirationDate) + { + return true; + } + + return false; + } + + /// + /// When the browser sends the IfModifiedDate, it's precision is limited to seconds, so this will account for that + /// + private DateTime NormalizeDateForComparison(DateTime date) + { + return new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second); + } + + } +} \ No newline at end of file diff --git a/MediaBrowser.Net/StreamExtensions.cs b/MediaBrowser.Net/StreamExtensions.cs new file mode 100644 index 0000000000..b4925cc7fd --- /dev/null +++ b/MediaBrowser.Net/StreamExtensions.cs @@ -0,0 +1,19 @@ +using System; +using System.IO; +using System.Reactive.Linq; + +namespace MediaBrowser.Net +{ + public static class StreamExtensions + { + public static IObservable ReadBytes(this Stream stream, int count) + { + var buffer = new byte[count]; + return Observable.FromAsyncPattern((cb, state) => stream.BeginRead(buffer, 0, count, cb, state), ar => + { + stream.EndRead(ar); + return buffer; + })(); + } + } +} \ No newline at end of file diff --git a/MediaBrowser.Net/packages.config b/MediaBrowser.Net/packages.config new file mode 100644 index 0000000000..47102a263f --- /dev/null +++ b/MediaBrowser.Net/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/MediaBrowser.TV/Entities/Episode.cs b/MediaBrowser.TV/Entities/Episode.cs index 9838e939b1..aa3227a77d 100644 --- a/MediaBrowser.TV/Entities/Episode.cs +++ b/MediaBrowser.TV/Entities/Episode.cs @@ -1,13 +1,9 @@ -using System; -using System.Collections.Generic; -using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Entities; namespace MediaBrowser.TV.Entities { public class Episode : Video { public string SeasonNumber { get; set; } - public string EpisodeNumber { get; set; } - public DateTime? FirstAired { get; set; } } } diff --git a/MediaBrowser.TV/Entities/Series.cs b/MediaBrowser.TV/Entities/Series.cs index 0034c9fe5b..f63580314c 100644 --- a/MediaBrowser.TV/Entities/Series.cs +++ b/MediaBrowser.TV/Entities/Series.cs @@ -1,12 +1,10 @@ -using System; -using System.Collections.Generic; -using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Entities; namespace MediaBrowser.TV.Entities { public class Series : Folder { - public string TVDBSeriesId { get; set; } + public string TvdbId { get; set; } public string Status { get; set; } } } diff --git a/MediaBrowser.TV/Metadata/EpisodeXmlParser.cs b/MediaBrowser.TV/Metadata/EpisodeXmlParser.cs index 1c68580b15..7df64b405b 100644 --- a/MediaBrowser.TV/Metadata/EpisodeXmlParser.cs +++ b/MediaBrowser.TV/Metadata/EpisodeXmlParser.cs @@ -16,7 +16,7 @@ namespace MediaBrowser.TV.Metadata { string filename = reader.ReadElementContentAsString(); - if (!string.IsNullOrEmpty(filename)) + if (!string.IsNullOrWhiteSpace(filename)) { string metadataFolder = Path.GetDirectoryName(item.Path); item.PrimaryImagePath = Path.Combine(metadataFolder, filename); @@ -24,7 +24,12 @@ namespace MediaBrowser.TV.Metadata break; } case "EpisodeNumber": - item.EpisodeNumber = reader.ReadElementContentAsString() ?? string.Empty; + string number = reader.ReadElementContentAsString() ?? string.Empty; + + if (!string.IsNullOrWhiteSpace(number)) + { + item.IndexNumber = int.Parse(number); + } break; case "SeasonNumber": @@ -39,13 +44,13 @@ namespace MediaBrowser.TV.Metadata { string firstAired = reader.ReadElementContentAsString() ?? string.Empty; - if (!string.IsNullOrEmpty(firstAired)) + if (!string.IsNullOrWhiteSpace(firstAired)) { DateTime airDate; if (DateTime.TryParse(firstAired, out airDate) && airDate.Year > 1850) { - item.FirstAired = airDate; + item.PremiereDate = airDate; item.ProductionYear = airDate.Year; } } diff --git a/MediaBrowser.TV/Metadata/SeriesXmlParser.cs b/MediaBrowser.TV/Metadata/SeriesXmlParser.cs index f4c0719008..9fdf1e7ca4 100644 --- a/MediaBrowser.TV/Metadata/SeriesXmlParser.cs +++ b/MediaBrowser.TV/Metadata/SeriesXmlParser.cs @@ -12,7 +12,7 @@ namespace MediaBrowser.TV.Metadata switch (reader.Name) { case "id": - item.TVDBSeriesId = reader.ReadElementContentAsString() ?? string.Empty; + item.TvdbId = reader.ReadElementContentAsString() ?? string.Empty; break; case "SeriesName": @@ -26,7 +26,7 @@ namespace MediaBrowser.TV.Metadata case "Runtime": { string text = reader.ReadElementContentAsString() ?? string.Empty; - if (!string.IsNullOrEmpty(text)) + if (!string.IsNullOrWhiteSpace(text)) { int runtime; diff --git a/MediaBrowser.sln b/MediaBrowser.sln index 6f94baf31d..23e78b42f9 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -21,6 +21,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Common", "Medi EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Model", "MediaBrowser.Model\MediaBrowser.Model.csproj", "{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Net", "MediaBrowser.Net\MediaBrowser.Net.csproj", "{5DA08D1C-0D52-4B1B-AA66-E4A171D938F6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -43,6 +45,10 @@ Global {5758B2C7-949A-421D-B268-70A950CF8741}.Debug|Any CPU.Build.0 = Debug|Any CPU {5758B2C7-949A-421D-B268-70A950CF8741}.Release|Any CPU.ActiveCfg = Release|Any CPU {5758B2C7-949A-421D-B268-70A950CF8741}.Release|Any CPU.Build.0 = Release|Any CPU + {5DA08D1C-0D52-4B1B-AA66-E4A171D938F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5DA08D1C-0D52-4B1B-AA66-E4A171D938F6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5DA08D1C-0D52-4B1B-AA66-E4A171D938F6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5DA08D1C-0D52-4B1B-AA66-E4A171D938F6}.Release|Any CPU.Build.0 = Release|Any CPU {78AEA637-AF42-4F43-8E2B-0F2F0E2931F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {78AEA637-AF42-4F43-8E2B-0F2F0E2931F3}.Debug|Any CPU.Build.0 = Debug|Any CPU {78AEA637-AF42-4F43-8E2B-0F2F0E2931F3}.Release|Any CPU.ActiveCfg = Release|Any CPU -- cgit v1.2.3 From 0a48b5e31aa712acd988626a88c52c47467945b2 Mon Sep 17 00:00:00 2001 From: LukePulverenti Luke Pulverenti luke pulverenti Date: Sat, 21 Jul 2012 14:39:47 -0400 Subject: Added a BaseKernel for the UI and Server to share, and made some other minor re-organizations. --- MediaBrowser.Api/HttpHandlers/ImageHandler.cs | 2 +- MediaBrowser.Api/HttpHandlers/ItemHandler.cs | 1 - MediaBrowser.Api/HttpHandlers/ItemListHandler.cs | 1 - MediaBrowser.Api/HttpHandlers/JsonHandler.cs | 2 +- MediaBrowser.Api/HttpHandlers/MediaHandler.cs | 2 +- MediaBrowser.Api/HttpHandlers/StudiosHandler.cs | 1 - MediaBrowser.Api/HttpHandlers/UsersHandler.cs | 3 +- MediaBrowser.Api/MediaBrowser.Api.csproj | 4 - MediaBrowser.Api/Plugin.cs | 4 +- .../ApiInteraction/ApiController.cs | 128 -------------------- .../Configuration/BaseConfiguration.cs | 19 +++ MediaBrowser.Common/Kernel/BaseKernel.cs | 130 +++++++++++++++++++++ MediaBrowser.Common/Kernel/KernelContext.cs | 9 ++ MediaBrowser.Common/Logging/BaseLogger.cs | 1 - MediaBrowser.Common/Logging/LogRow.cs | 1 - MediaBrowser.Common/Logging/LogSeverity.cs | 14 +++ MediaBrowser.Common/MediaBrowser.Common.csproj | 19 ++- MediaBrowser.Common/Net/CollectionExtensions.cs | 14 +++ .../Net/Handlers/BaseEmbeddedResourceHandler.cs | 58 +++++++++ MediaBrowser.Common/Net/Handlers/BaseHandler.cs | 111 ++++++++++++++++++ .../Net/Handlers/BaseJsonHandler.cs | 11 ++ MediaBrowser.Common/Net/HttpServer.cs | 42 +++++++ MediaBrowser.Common/Net/Request.cs | 18 +++ MediaBrowser.Common/Net/RequestContext.cs | 118 +++++++++++++++++++ MediaBrowser.Common/Net/StreamExtensions.cs | 19 +++ MediaBrowser.Common/Plugins/PluginController.cs | 38 ++++-- MediaBrowser.Common/packages.config | 1 + .../Configuration/ServerConfiguration.cs | 16 +++ MediaBrowser.Controller/Kernel.cs | 78 ++----------- .../MediaBrowser.Controller.csproj | 5 +- .../Handlers/EmbeddedResourceHandler.cs | 3 +- .../MediaBrowser.HtmlBrowser.csproj | 4 - MediaBrowser.HtmlBrowser/Plugin.cs | 2 +- MediaBrowser.Model/Configuration/Configuration.cs | 19 --- MediaBrowser.Model/Logging/LogSeverity.cs | 14 --- MediaBrowser.Model/MediaBrowser.Model.csproj | 2 - MediaBrowser.Net/CollectionExtensions.cs | 14 --- .../Handlers/BaseEmbeddedResourceHandler.cs | 58 --------- MediaBrowser.Net/Handlers/BaseHandler.cs | 111 ------------------ MediaBrowser.Net/Handlers/BaseJsonHandler.cs | 11 -- MediaBrowser.Net/HttpServer.cs | 42 ------- MediaBrowser.Net/MediaBrowser.Net.csproj | 66 ----------- MediaBrowser.Net/Properties/AssemblyInfo.cs | 36 ------ MediaBrowser.Net/Request.cs | 18 --- MediaBrowser.Net/RequestContext.cs | 118 ------------------- MediaBrowser.Net/StreamExtensions.cs | 19 --- MediaBrowser.Net/packages.config | 4 - MediaBrowser.Program/App.config | 2 +- MediaBrowser.Program/Program.cs | 21 +--- MediaBrowser.sln | 6 - 50 files changed, 649 insertions(+), 791 deletions(-) delete mode 100644 MediaBrowser.Common/ApiInteraction/ApiController.cs create mode 100644 MediaBrowser.Common/Configuration/BaseConfiguration.cs create mode 100644 MediaBrowser.Common/Kernel/BaseKernel.cs create mode 100644 MediaBrowser.Common/Kernel/KernelContext.cs create mode 100644 MediaBrowser.Common/Logging/LogSeverity.cs create mode 100644 MediaBrowser.Common/Net/CollectionExtensions.cs create mode 100644 MediaBrowser.Common/Net/Handlers/BaseEmbeddedResourceHandler.cs create mode 100644 MediaBrowser.Common/Net/Handlers/BaseHandler.cs create mode 100644 MediaBrowser.Common/Net/Handlers/BaseJsonHandler.cs create mode 100644 MediaBrowser.Common/Net/HttpServer.cs create mode 100644 MediaBrowser.Common/Net/Request.cs create mode 100644 MediaBrowser.Common/Net/RequestContext.cs create mode 100644 MediaBrowser.Common/Net/StreamExtensions.cs create mode 100644 MediaBrowser.Controller/Configuration/ServerConfiguration.cs delete mode 100644 MediaBrowser.Model/Configuration/Configuration.cs delete mode 100644 MediaBrowser.Model/Logging/LogSeverity.cs delete mode 100644 MediaBrowser.Net/CollectionExtensions.cs delete mode 100644 MediaBrowser.Net/Handlers/BaseEmbeddedResourceHandler.cs delete mode 100644 MediaBrowser.Net/Handlers/BaseHandler.cs delete mode 100644 MediaBrowser.Net/Handlers/BaseJsonHandler.cs delete mode 100644 MediaBrowser.Net/HttpServer.cs delete mode 100644 MediaBrowser.Net/MediaBrowser.Net.csproj delete mode 100644 MediaBrowser.Net/Properties/AssemblyInfo.cs delete mode 100644 MediaBrowser.Net/Request.cs delete mode 100644 MediaBrowser.Net/RequestContext.cs delete mode 100644 MediaBrowser.Net/StreamExtensions.cs delete mode 100644 MediaBrowser.Net/packages.config (limited to 'MediaBrowser.Api/HttpHandlers/StudiosHandler.cs') diff --git a/MediaBrowser.Api/HttpHandlers/ImageHandler.cs b/MediaBrowser.Api/HttpHandlers/ImageHandler.cs index ae6228ae87..33beb29019 100644 --- a/MediaBrowser.Api/HttpHandlers/ImageHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/ImageHandler.cs @@ -1,9 +1,9 @@ using System; using System.IO; using System.Linq; +using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Controller; using MediaBrowser.Model.Entities; -using MediaBrowser.Net.Handlers; namespace MediaBrowser.Api.HttpHandlers { diff --git a/MediaBrowser.Api/HttpHandlers/ItemHandler.cs b/MediaBrowser.Api/HttpHandlers/ItemHandler.cs index 2ff2354939..a54d65524f 100644 --- a/MediaBrowser.Api/HttpHandlers/ItemHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/ItemHandler.cs @@ -1,5 +1,4 @@ using System; -using MediaBrowser.Net.Handlers; using MediaBrowser.Model.Entities; namespace MediaBrowser.Api.HttpHandlers diff --git a/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs b/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs index 54af1b7e91..a94c2061e1 100644 --- a/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq; -using MediaBrowser.Net.Handlers; using MediaBrowser.Model.Entities; namespace MediaBrowser.Api.HttpHandlers diff --git a/MediaBrowser.Api/HttpHandlers/JsonHandler.cs b/MediaBrowser.Api/HttpHandlers/JsonHandler.cs index e663085ec7..a891d7d68d 100644 --- a/MediaBrowser.Api/HttpHandlers/JsonHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/JsonHandler.cs @@ -1,6 +1,6 @@ using System.IO; using MediaBrowser.Common.Json; -using MediaBrowser.Net.Handlers; +using MediaBrowser.Common.Net.Handlers; namespace MediaBrowser.Api.HttpHandlers { diff --git a/MediaBrowser.Api/HttpHandlers/MediaHandler.cs b/MediaBrowser.Api/HttpHandlers/MediaHandler.cs index 47aab3c410..73f8de7d82 100644 --- a/MediaBrowser.Api/HttpHandlers/MediaHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/MediaHandler.cs @@ -1,7 +1,7 @@ using System; using System.IO; +using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Model.Entities; -using MediaBrowser.Net.Handlers; namespace MediaBrowser.Api.HttpHandlers { diff --git a/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs b/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs index 66daca7774..d2898104fc 100644 --- a/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs @@ -1,5 +1,4 @@ using System; -using MediaBrowser.Net.Handlers; using MediaBrowser.Controller; using MediaBrowser.Model.Entities; diff --git a/MediaBrowser.Api/HttpHandlers/UsersHandler.cs b/MediaBrowser.Api/HttpHandlers/UsersHandler.cs index 816d4e83ac..d10561e435 100644 --- a/MediaBrowser.Api/HttpHandlers/UsersHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/UsersHandler.cs @@ -1,5 +1,4 @@ -using MediaBrowser.Net.Handlers; -using MediaBrowser.Controller; +using MediaBrowser.Controller; namespace MediaBrowser.Api.HttpHandlers { diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index dd5c072324..c0942cbb98 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -76,10 +76,6 @@ {7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b} MediaBrowser.Model - - {5da08d1c-0d52-4b1b-aa66-e4a171d938f6} - MediaBrowser.Net - diff --git a/MediaBrowser.Api/Plugin.cs b/MediaBrowser.Api/Plugin.cs index af885ef825..9a4db15185 100644 --- a/MediaBrowser.Api/Plugin.cs +++ b/MediaBrowser.Api/Plugin.cs @@ -1,10 +1,10 @@ using System; using System.Reactive.Linq; using MediaBrowser.Api.HttpHandlers; +using MediaBrowser.Common.Net; +using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Common.Plugins; using MediaBrowser.Controller; -using MediaBrowser.Net; -using MediaBrowser.Net.Handlers; namespace MediaBrowser.Api { diff --git a/MediaBrowser.Common/ApiInteraction/ApiController.cs b/MediaBrowser.Common/ApiInteraction/ApiController.cs deleted file mode 100644 index b3a51c512e..0000000000 --- a/MediaBrowser.Common/ApiInteraction/ApiController.cs +++ /dev/null @@ -1,128 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Net; -using System.Threading.Tasks; -using MediaBrowser.Common.Json; -using MediaBrowser.Model.Entities; -using MediaBrowser.Model.Users; - -namespace MediaBrowser.Common.ApiInteraction -{ - public class ApiController - { - public string ApiUrl { get; set; } - - private WebClient WebClient { get; set; } - - public ApiController() - { - WebClient = new WebClient(); - } - - public async Task> GetRootItem(Guid userId) - { - string url = ApiUrl + "/item?userId=" + userId.ToString(); - - using (Stream stream = await WebClient.OpenReadTaskAsync(url)) - { - using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) - { - return DeserializeBaseItemWrapper(gzipStream); - } - } - } - - public async Task> GetItem(Guid id, Guid userId) - { - string url = ApiUrl + "/item?userId=" + userId.ToString(); - - if (id != Guid.Empty) - { - url += "&id=" + id.ToString(); - } - - using (Stream stream = await WebClient.OpenReadTaskAsync(url)) - { - using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) - { - return DeserializeBaseItemWrapper(gzipStream); - } - } - } - - public async Task> GetAllUsers() - { - string url = ApiUrl + "/users"; - - using (Stream stream = await WebClient.OpenReadTaskAsync(url)) - { - using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) - { - return JsonSerializer.DeserializeFromStream>(gzipStream); - } - } - } - - public async Task> GetAllGenres(Guid userId) - { - string url = ApiUrl + "/genres?userId=" + userId.ToString(); - - using (Stream stream = await WebClient.OpenReadTaskAsync(url)) - { - using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) - { - return JsonSerializer.DeserializeFromStream>(gzipStream); - } - } - } - - public async Task GetGenre(string name, Guid userId) - { - string url = ApiUrl + "/genre?userId=" + userId.ToString() + "&name=" + name; - - using (Stream stream = await WebClient.OpenReadTaskAsync(url)) - { - using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) - { - return JsonSerializer.DeserializeFromStream(gzipStream); - } - } - } - - public async Task> GetAllStudios(Guid userId) - { - string url = ApiUrl + "/studios?userId=" + userId.ToString(); - - using (Stream stream = await WebClient.OpenReadTaskAsync(url)) - { - using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) - { - return JsonSerializer.DeserializeFromStream>(gzipStream); - } - } - } - - public async Task GetStudio(string name, Guid userId) - { - string url = ApiUrl + "/studio?userId=" + userId.ToString() + "&name=" + name; - - using (Stream stream = await WebClient.OpenReadTaskAsync(url)) - { - using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Decompress, false)) - { - return JsonSerializer.DeserializeFromStream(gzipStream); - } - } - } - - private static ApiBaseItemWrapper DeserializeBaseItemWrapper(Stream stream) - { - ApiBaseItemWrapper data = JsonSerializer.DeserializeFromStream>(stream); - - return data; - } - } -} diff --git a/MediaBrowser.Common/Configuration/BaseConfiguration.cs b/MediaBrowser.Common/Configuration/BaseConfiguration.cs new file mode 100644 index 0000000000..bf53686ab3 --- /dev/null +++ b/MediaBrowser.Common/Configuration/BaseConfiguration.cs @@ -0,0 +1,19 @@ +using MediaBrowser.Common.Logging; + +namespace MediaBrowser.Common.Configuration +{ + /// + /// Serves as a common base class for the Server and UI Configurations + /// + public class BaseConfiguration + { + public LogSeverity LogSeverity { get; set; } + public int HttpServerPortNumber { get; set; } + + public BaseConfiguration() + { + LogSeverity = LogSeverity.Info; + HttpServerPortNumber = 8096; + } + } +} diff --git a/MediaBrowser.Common/Kernel/BaseKernel.cs b/MediaBrowser.Common/Kernel/BaseKernel.cs new file mode 100644 index 0000000000..d6c13ce380 --- /dev/null +++ b/MediaBrowser.Common/Kernel/BaseKernel.cs @@ -0,0 +1,130 @@ +using System.Configuration; +using System.IO; +using System.Reflection; +using MediaBrowser.Common.Configuration; +using MediaBrowser.Common.Json; +using MediaBrowser.Common.Logging; +using MediaBrowser.Common.Net; +using MediaBrowser.Common.Plugins; + +namespace MediaBrowser.Common.Kernel +{ + /// + /// Represents a shared base kernel for both the UI and server apps + /// + public abstract class BaseKernel + where TConfigurationType : BaseConfiguration, new() + { + /// + /// Gets the path to the program data folder + /// + public string ProgramDataPath { get; private set; } + + /// + /// Gets the current configuration + /// + public TConfigurationType Configuration { get; private set; } + + /// + /// Both the UI and server will have a built-in HttpServer. + /// People will inevitably want remote control apps so it's needed in the UI too. + /// + public HttpServer HttpServer { get; private set; } + + public PluginController PluginController { get; private set; } + + /// + /// Gets the kernel context. The UI kernel will have to override this. + /// + protected KernelContext KernelContext { get { return KernelContext.Server; } } + + protected virtual string HttpServerUrlPrefix + { + get + { + return "http://+:" + Configuration.HttpServerPortNumber + "/mediabrowser/"; + } + } + + public BaseKernel() + { + ProgramDataPath = GetProgramDataPath(); + + PluginController = new PluginController() { PluginsPath = Path.Combine(ProgramDataPath, "Plugins") }; + + Logger.LoggerInstance = new FileLogger(Path.Combine(ProgramDataPath, "Logs")); + } + + public virtual void Init() + { + ReloadConfiguration(); + + ReloadHttpServer(); + + ReloadPlugins(); + } + + /// + /// Gets the path to the application's ProgramDataFolder + /// + /// + private string GetProgramDataPath() + { + string programDataPath = ConfigurationManager.AppSettings["ProgramDataPath"]; + + // If it's a relative path, e.g. "..\" + if (!Path.IsPathRooted(programDataPath)) + { + string path = Assembly.GetExecutingAssembly().Location; + path = Path.GetDirectoryName(path); + + programDataPath = Path.Combine(path, programDataPath); + + programDataPath = Path.GetFullPath(programDataPath); + } + + if (!Directory.Exists(programDataPath)) + { + Directory.CreateDirectory(programDataPath); + } + + return programDataPath; + } + + private void ReloadConfiguration() + { + // Deserialize config + Configuration = GetConfiguration(ProgramDataPath); + + Logger.LoggerInstance.LogSeverity = Configuration.LogSeverity; + } + + private void ReloadHttpServer() + { + if (HttpServer != null) + { + HttpServer.Dispose(); + } + + HttpServer = new HttpServer("http://+:" + Configuration.HttpServerPortNumber + "/mediabrowser/"); + } + + protected virtual void ReloadPlugins() + { + // Find plugins + PluginController.Init(KernelContext); + } + + private static TConfigurationType GetConfiguration(string directory) + { + string file = Path.Combine(directory, "config.js"); + + if (!File.Exists(file)) + { + return new TConfigurationType(); + } + + return JsonSerializer.DeserializeFromFile(file); + } + } +} diff --git a/MediaBrowser.Common/Kernel/KernelContext.cs b/MediaBrowser.Common/Kernel/KernelContext.cs new file mode 100644 index 0000000000..6aa1e83bdf --- /dev/null +++ b/MediaBrowser.Common/Kernel/KernelContext.cs @@ -0,0 +1,9 @@ + +namespace MediaBrowser.Common.Kernel +{ + public enum KernelContext + { + Server, + UI + } +} diff --git a/MediaBrowser.Common/Logging/BaseLogger.cs b/MediaBrowser.Common/Logging/BaseLogger.cs index 407c8baa76..51c6632d56 100644 --- a/MediaBrowser.Common/Logging/BaseLogger.cs +++ b/MediaBrowser.Common/Logging/BaseLogger.cs @@ -2,7 +2,6 @@ using System.Diagnostics; using System.Text; using System.Threading; -using MediaBrowser.Model.Logging; namespace MediaBrowser.Common.Logging { diff --git a/MediaBrowser.Common/Logging/LogRow.cs b/MediaBrowser.Common/Logging/LogRow.cs index d1e234250c..39c69eb454 100644 --- a/MediaBrowser.Common/Logging/LogRow.cs +++ b/MediaBrowser.Common/Logging/LogRow.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Text; -using MediaBrowser.Model.Logging; namespace MediaBrowser.Common.Logging { diff --git a/MediaBrowser.Common/Logging/LogSeverity.cs b/MediaBrowser.Common/Logging/LogSeverity.cs new file mode 100644 index 0000000000..2abab1a448 --- /dev/null +++ b/MediaBrowser.Common/Logging/LogSeverity.cs @@ -0,0 +1,14 @@ +using System; + +namespace MediaBrowser.Common.Logging +{ + [Flags] + public enum LogSeverity + { + None = 0, + Debug = 1, + Info = 2, + Warning = 4, + Error = 8 + } +} diff --git a/MediaBrowser.Common/MediaBrowser.Common.csproj b/MediaBrowser.Common/MediaBrowser.Common.csproj index 252c9c8cca..1f68a3da7a 100644 --- a/MediaBrowser.Common/MediaBrowser.Common.csproj +++ b/MediaBrowser.Common/MediaBrowser.Common.csproj @@ -34,7 +34,12 @@ ..\packages\ServiceStack.Text.3.8.5\lib\net35\ServiceStack.Text.dll + + + False + ..\packages\Rx-Main.1.0.11226\lib\Net4\System.Reactive.dll + @@ -42,9 +47,20 @@ - + + + + + + + + + + + + @@ -63,6 +79,7 @@ MediaBrowser.Model + - @@ -46,7 +45,6 @@ - diff --git a/MediaBrowser.Net/CollectionExtensions.cs b/MediaBrowser.Net/CollectionExtensions.cs deleted file mode 100644 index a6b59904f3..0000000000 --- a/MediaBrowser.Net/CollectionExtensions.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Linq; - -namespace MediaBrowser.Net -{ - public static class CollectionExtensions - { - public static IDictionary> ToDictionary(this NameValueCollection source) - { - return source.AllKeys.ToDictionary>(key => key, source.GetValues); - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Net/Handlers/BaseEmbeddedResourceHandler.cs b/MediaBrowser.Net/Handlers/BaseEmbeddedResourceHandler.cs deleted file mode 100644 index d7f579d05a..0000000000 --- a/MediaBrowser.Net/Handlers/BaseEmbeddedResourceHandler.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.IO; - -namespace MediaBrowser.Net.Handlers -{ - public abstract class BaseEmbeddedResourceHandler : BaseHandler - { - public BaseEmbeddedResourceHandler(string resourcePath) - : base() - { - ResourcePath = resourcePath; - } - - protected string ResourcePath { get; set; } - - public override string ContentType - { - get - { - string extension = Path.GetExtension(ResourcePath); - - if (extension.EndsWith("jpeg", StringComparison.OrdinalIgnoreCase) || extension.EndsWith("jpg", StringComparison.OrdinalIgnoreCase)) - { - return "image/jpeg"; - } - else if (extension.EndsWith("png", StringComparison.OrdinalIgnoreCase)) - { - return "image/png"; - } - else if (extension.EndsWith("ico", StringComparison.OrdinalIgnoreCase)) - { - return "image/ico"; - } - else if (extension.EndsWith("js", StringComparison.OrdinalIgnoreCase)) - { - return "application/x-javascript"; - } - else if (extension.EndsWith("css", StringComparison.OrdinalIgnoreCase)) - { - return "text/css"; - } - else if (extension.EndsWith("html", StringComparison.OrdinalIgnoreCase)) - { - return "text/html; charset=utf-8"; - } - - return "text/plain; charset=utf-8"; - } - } - - protected override void WriteResponseToOutputStream(Stream stream) - { - GetEmbeddedResourceStream().CopyTo(stream); - } - - protected abstract Stream GetEmbeddedResourceStream(); - } -} diff --git a/MediaBrowser.Net/Handlers/BaseHandler.cs b/MediaBrowser.Net/Handlers/BaseHandler.cs deleted file mode 100644 index 7a2bcffe97..0000000000 --- a/MediaBrowser.Net/Handlers/BaseHandler.cs +++ /dev/null @@ -1,111 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.IO; -using System.IO.Compression; - -namespace MediaBrowser.Net.Handlers -{ - public abstract class BaseHandler - { - /// - /// Response headers - /// - public IDictionary Headers = new Dictionary(); - - /// - /// The action to write the response to the output stream - /// - public Action WriteStream { get; set; } - - /// - /// The original RequestContext - /// - public RequestContext RequestContext { get; set; } - - /// - /// The original QueryString - /// - protected NameValueCollection QueryString - { - get - { - return RequestContext.Request.QueryString; - } - } - - /// - /// Gets the MIME type to include in the response headers - /// - public abstract string ContentType { get; } - - /// - /// Gets the status code to include in the response headers - /// - public virtual int StatusCode - { - get - { - return 200; - } - } - - /// - /// Gets the cache duration to include in the response headers - /// - public virtual TimeSpan CacheDuration - { - get - { - return TimeSpan.FromTicks(0); - } - } - - /// - /// Gets the last date modified of the content being returned, if this can be determined. - /// This will be used to invalidate the cache, so it's not needed if CacheDuration is 0. - /// - public virtual DateTime? LastDateModified - { - get - { - return null; - } - } - - public virtual bool GzipResponse - { - get - { - return true; - } - } - - public BaseHandler() - { - WriteStream = s => - { - WriteReponse(s); - s.Close(); - }; - } - - private void WriteReponse(Stream stream) - { - if (GzipResponse) - { - using (GZipStream gzipStream = new GZipStream(stream, CompressionMode.Compress, false)) - { - WriteResponseToOutputStream(gzipStream); - } - } - else - { - WriteResponseToOutputStream(stream); - } - } - - protected abstract void WriteResponseToOutputStream(Stream stream); - - } -} \ No newline at end of file diff --git a/MediaBrowser.Net/Handlers/BaseJsonHandler.cs b/MediaBrowser.Net/Handlers/BaseJsonHandler.cs deleted file mode 100644 index 725b89c32e..0000000000 --- a/MediaBrowser.Net/Handlers/BaseJsonHandler.cs +++ /dev/null @@ -1,11 +0,0 @@ - -namespace MediaBrowser.Net.Handlers -{ - public abstract class BaseJsonHandler : BaseHandler - { - public override string ContentType - { - get { return "application/json"; } - } - } -} diff --git a/MediaBrowser.Net/HttpServer.cs b/MediaBrowser.Net/HttpServer.cs deleted file mode 100644 index aa24538d05..0000000000 --- a/MediaBrowser.Net/HttpServer.cs +++ /dev/null @@ -1,42 +0,0 @@ -using System; -using System.Net; -using System.Reactive.Linq; - -namespace MediaBrowser.Net -{ - public class HttpServer : IObservable, IDisposable - { - private readonly HttpListener listener; - private readonly IObservable stream; - - public HttpServer(string url) - { - listener = new HttpListener(); - listener.Prefixes.Add(url); - listener.Start(); - stream = ObservableHttpContext(); - } - - private IObservable ObservableHttpContext() - { - return Observable.Create(obs => - Observable.FromAsyncPattern(listener.BeginGetContext, - listener.EndGetContext)() - .Select(c => new RequestContext(c)) - .Subscribe(obs)) - .Repeat() - .Retry() - .Publish() - .RefCount(); - } - public void Dispose() - { - listener.Stop(); - } - - public IDisposable Subscribe(IObserver observer) - { - return stream.Subscribe(observer); - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Net/MediaBrowser.Net.csproj b/MediaBrowser.Net/MediaBrowser.Net.csproj deleted file mode 100644 index 6f1b7cccfe..0000000000 --- a/MediaBrowser.Net/MediaBrowser.Net.csproj +++ /dev/null @@ -1,66 +0,0 @@ - - - - - Debug - AnyCPU - {5DA08D1C-0D52-4B1B-AA66-E4A171D938F6} - Library - Properties - MediaBrowser.Net - MediaBrowser.Net - v4.5 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - ..\packages\Rx-Main.1.0.11226\lib\Net4\System.Reactive.dll - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/MediaBrowser.Net/Properties/AssemblyInfo.cs b/MediaBrowser.Net/Properties/AssemblyInfo.cs deleted file mode 100644 index 00964b6a26..0000000000 --- a/MediaBrowser.Net/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("MediaBrowser.Net")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("MediaBrowser.Net")] -[assembly: AssemblyCopyright("Copyright © 2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("eacc40b5-e24e-4467-8000-f40874048d45")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/MediaBrowser.Net/Request.cs b/MediaBrowser.Net/Request.cs deleted file mode 100644 index 43f854233e..0000000000 --- a/MediaBrowser.Net/Request.cs +++ /dev/null @@ -1,18 +0,0 @@ -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace MediaBrowser.Net -{ - public class Request - { - public string HttpMethod { get; set; } - public IDictionary> Headers { get; set; } - public Stream InputStream { get; set; } - public string RawUrl { get; set; } - public int ContentLength - { - get { return int.Parse(Headers["Content-Length"].First()); } - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Net/RequestContext.cs b/MediaBrowser.Net/RequestContext.cs deleted file mode 100644 index 4c1350701c..0000000000 --- a/MediaBrowser.Net/RequestContext.cs +++ /dev/null @@ -1,118 +0,0 @@ -using System; -using System.Linq; -using System.Net; -using MediaBrowser.Net.Handlers; - -namespace MediaBrowser.Net -{ - public class RequestContext - { - public HttpListenerRequest Request { get; private set; } - public HttpListenerResponse Response { get; private set; } - - public string LocalPath - { - get - { - return Request.Url.LocalPath; - } - } - - public RequestContext(HttpListenerContext context) - { - Response = context.Response; - Request = context.Request; - } - - public void Respond(BaseHandler handler) - { - Response.AddHeader("Access-Control-Allow-Origin", "*"); - - Response.KeepAlive = true; - - foreach (var header in handler.Headers) - { - Response.AddHeader(header.Key, header.Value); - } - - int statusCode = handler.StatusCode; - Response.ContentType = handler.ContentType; - - TimeSpan cacheDuration = handler.CacheDuration; - - if (Request.Headers.AllKeys.Contains("If-Modified-Since")) - { - DateTime ifModifiedSince; - - if (DateTime.TryParse(Request.Headers["If-Modified-Since"].Replace(" GMT", string.Empty), out ifModifiedSince)) - { - // If the cache hasn't expired yet just return a 304 - if (IsCacheValid(ifModifiedSince, cacheDuration, handler.LastDateModified)) - { - statusCode = 304; - } - } - } - - Response.SendChunked = true; - Response.StatusCode = statusCode; - - if (statusCode != 304) - { - if (handler.GzipResponse) - { - Response.AddHeader("Content-Encoding", "gzip"); - } - - if (cacheDuration.Ticks > 0) - { - CacheResponse(Response, cacheDuration, handler.LastDateModified); - } - handler.WriteStream(Response.OutputStream); - } - else - { - Response.OutputStream.Flush(); - Response.OutputStream.Close(); - } - } - - private void CacheResponse(HttpListenerResponse response, TimeSpan duration, DateTime? dateModified) - { - DateTime lastModified = dateModified ?? DateTime.Now; - - response.Headers[HttpResponseHeader.CacheControl] = "Public"; - response.Headers[HttpResponseHeader.Expires] = DateTime.Now.Add(duration).ToString("r"); - response.Headers[HttpResponseHeader.LastModified] = lastModified.ToString("r"); - } - - private bool IsCacheValid(DateTime ifModifiedSince, TimeSpan cacheDuration, DateTime? dateModified) - { - if (dateModified.HasValue) - { - DateTime lastModified = NormalizeDateForComparison(dateModified.Value); - ifModifiedSince = NormalizeDateForComparison(ifModifiedSince); - - return lastModified <= ifModifiedSince; - } - - DateTime cacheExpirationDate = ifModifiedSince.Add(cacheDuration); - - if (DateTime.Now < cacheExpirationDate) - { - return true; - } - - return false; - } - - /// - /// When the browser sends the IfModifiedDate, it's precision is limited to seconds, so this will account for that - /// - private DateTime NormalizeDateForComparison(DateTime date) - { - return new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second); - } - - } -} \ No newline at end of file diff --git a/MediaBrowser.Net/StreamExtensions.cs b/MediaBrowser.Net/StreamExtensions.cs deleted file mode 100644 index b4925cc7fd..0000000000 --- a/MediaBrowser.Net/StreamExtensions.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System; -using System.IO; -using System.Reactive.Linq; - -namespace MediaBrowser.Net -{ - public static class StreamExtensions - { - public static IObservable ReadBytes(this Stream stream, int count) - { - var buffer = new byte[count]; - return Observable.FromAsyncPattern((cb, state) => stream.BeginRead(buffer, 0, count, cb, state), ar => - { - stream.EndRead(ar); - return buffer; - })(); - } - } -} \ No newline at end of file diff --git a/MediaBrowser.Net/packages.config b/MediaBrowser.Net/packages.config deleted file mode 100644 index 47102a263f..0000000000 --- a/MediaBrowser.Net/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/MediaBrowser.Program/App.config b/MediaBrowser.Program/App.config index 04df0f820e..5aff9b3508 100644 --- a/MediaBrowser.Program/App.config +++ b/MediaBrowser.Program/App.config @@ -1,7 +1,7 @@  - + diff --git a/MediaBrowser.Program/Program.cs b/MediaBrowser.Program/Program.cs index 1933ad1260..ff7ad002f3 100644 --- a/MediaBrowser.Program/Program.cs +++ b/MediaBrowser.Program/Program.cs @@ -1,6 +1,4 @@ using System; -using System.Configuration; -using System.IO; using MediaBrowser.Controller; namespace MediaBrowser.Program @@ -18,24 +16,7 @@ namespace MediaBrowser.Program Console.WriteLine("Loading"); - string installDir = ConfigurationManager.AppSettings["DataPath"]; - - if (!Path.IsPathRooted(installDir)) - { - string path = System.Reflection.Assembly.GetExecutingAssembly().Location; - path = Path.GetDirectoryName(path); - - installDir = Path.Combine(path, installDir); - - installDir = Path.GetFullPath(installDir); - } - - if (!Directory.Exists(installDir)) - { - Directory.CreateDirectory(installDir); - } - - Kernel kernel = new Kernel(installDir); + Kernel kernel = new Kernel(); kernel.Init(); diff --git a/MediaBrowser.sln b/MediaBrowser.sln index 23e78b42f9..6f94baf31d 100644 --- a/MediaBrowser.sln +++ b/MediaBrowser.sln @@ -21,8 +21,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Common", "Medi EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Model", "MediaBrowser.Model\MediaBrowser.Model.csproj", "{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MediaBrowser.Net", "MediaBrowser.Net\MediaBrowser.Net.csproj", "{5DA08D1C-0D52-4B1B-AA66-E4A171D938F6}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -45,10 +43,6 @@ Global {5758B2C7-949A-421D-B268-70A950CF8741}.Debug|Any CPU.Build.0 = Debug|Any CPU {5758B2C7-949A-421D-B268-70A950CF8741}.Release|Any CPU.ActiveCfg = Release|Any CPU {5758B2C7-949A-421D-B268-70A950CF8741}.Release|Any CPU.Build.0 = Release|Any CPU - {5DA08D1C-0D52-4B1B-AA66-E4A171D938F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5DA08D1C-0D52-4B1B-AA66-E4A171D938F6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5DA08D1C-0D52-4B1B-AA66-E4A171D938F6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5DA08D1C-0D52-4B1B-AA66-E4A171D938F6}.Release|Any CPU.Build.0 = Release|Any CPU {78AEA637-AF42-4F43-8E2B-0F2F0E2931F3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {78AEA637-AF42-4F43-8E2B-0F2F0E2931F3}.Debug|Any CPU.Build.0 = Debug|Any CPU {78AEA637-AF42-4F43-8E2B-0F2F0E2931F3}.Release|Any CPU.ActiveCfg = Release|Any CPU -- cgit v1.2.3 From 7d48e20aea2e2a08137ec23d0076b86755f648d3 Mon Sep 17 00:00:00 2001 From: LukePulverenti Luke Pulverenti luke pulverenti Date: Mon, 30 Jul 2012 15:03:07 -0400 Subject: Reworked CategoryInfo and added ImageType enum --- MediaBrowser.Api/HttpHandlers/ImageHandler.cs | 30 ++++++++++++++++++------- MediaBrowser.Api/HttpHandlers/StudiosHandler.cs | 2 +- MediaBrowser.Common/Kernel/BaseKernel.cs | 13 +++++++++-- MediaBrowser.Controller/Kernel.cs | 22 +++++++++--------- MediaBrowser.Logging/StreamLogger.cs | 3 +++ MediaBrowser.Model/Entities/ApiBaseItem.cs | 13 ++++++++++- MediaBrowser.Model/Entities/CategoryInfo.cs | 10 ++++----- MediaBrowser.Model/Entities/ImageType.cs | 13 +++++++++++ MediaBrowser.Model/MediaBrowser.Model.csproj | 1 + 9 files changed, 77 insertions(+), 30 deletions(-) create mode 100644 MediaBrowser.Model/Entities/ImageType.cs (limited to 'MediaBrowser.Api/HttpHandlers/StudiosHandler.cs') diff --git a/MediaBrowser.Api/HttpHandlers/ImageHandler.cs b/MediaBrowser.Api/HttpHandlers/ImageHandler.cs index 33beb29019..c61768a6d0 100644 --- a/MediaBrowser.Api/HttpHandlers/ImageHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/ImageHandler.cs @@ -136,6 +136,21 @@ namespace MediaBrowser.Api.HttpHandlers } } + private ImageType ImageType + { + get + { + string imageType = QueryString["type"]; + + if (string.IsNullOrEmpty(imageType)) + { + return Model.Entities.ImageType.Primary; + } + + return (ImageType)Enum.Parse(typeof(ImageType), imageType, true); + } + } + protected override void WriteResponseToOutputStream(Stream stream) { ImageProcessor.ProcessImage(ImagePath, stream, Width, Height, MaxWidth, MaxHeight, Quality); @@ -152,7 +167,6 @@ namespace MediaBrowser.Api.HttpHandlers string id = QueryString["id"]; string personName = QueryString["personname"]; - string imageType = QueryString["type"] ?? string.Empty; string imageIndex = QueryString["index"]; BaseItem item; @@ -168,28 +182,28 @@ namespace MediaBrowser.Api.HttpHandlers int index = string.IsNullOrEmpty(imageIndex) ? 0 : int.Parse(imageIndex); - return GetImagePathFromTypes(item, imageType, index); + return GetImagePathFromTypes(item, ImageType, index); } - private string GetImagePathFromTypes(BaseItem item, string imageType, int imageIndex) + private string GetImagePathFromTypes(BaseItem item, ImageType imageType, int imageIndex) { - if (imageType.Equals("logo", StringComparison.OrdinalIgnoreCase)) + if (imageType == ImageType.Logo) { return item.LogoImagePath; } - else if (imageType.Equals("backdrop", StringComparison.OrdinalIgnoreCase)) + else if (imageType == ImageType.Backdrop) { return item.BackdropImagePaths.ElementAt(imageIndex); } - else if (imageType.Equals("banner", StringComparison.OrdinalIgnoreCase)) + else if (imageType == ImageType.Banner) { return item.BannerImagePath; } - else if (imageType.Equals("art", StringComparison.OrdinalIgnoreCase)) + else if (imageType == ImageType.Art) { return item.ArtImagePath; } - else if (imageType.Equals("thumbnail", StringComparison.OrdinalIgnoreCase)) + else if (imageType == ImageType.Thumbnail) { return item.ThumbnailImagePath; } diff --git a/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs b/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs index d2898104fc..ff48ae6e36 100644 --- a/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs @@ -6,7 +6,7 @@ namespace MediaBrowser.Api.HttpHandlers { public class StudiosHandler : JsonHandler { - protected sealed override object ObjectToSerialize + protected override object ObjectToSerialize { get { diff --git a/MediaBrowser.Common/Kernel/BaseKernel.cs b/MediaBrowser.Common/Kernel/BaseKernel.cs index f997aea5dd..820d94831a 100644 --- a/MediaBrowser.Common/Kernel/BaseKernel.cs +++ b/MediaBrowser.Common/Kernel/BaseKernel.cs @@ -6,12 +6,12 @@ using System.Configuration; using System.IO; using System.Linq; using System.Reflection; -using MediaBrowser.Model.Configuration; using MediaBrowser.Common.Json; using MediaBrowser.Common.Net; using MediaBrowser.Common.Plugins; -using MediaBrowser.Model.Progress; using MediaBrowser.Logging; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Progress; namespace MediaBrowser.Common.Kernel { @@ -267,12 +267,18 @@ namespace MediaBrowser.Common.Kernel return null; } + /// + /// Disposes all resources currently in use. + /// public void Dispose() { DisposeHttpServer(); DisposeLogger(); } + /// + /// Disposes the current HttpServer + /// private void DisposeHttpServer() { if (HttpServer != null) @@ -281,6 +287,9 @@ namespace MediaBrowser.Common.Kernel } } + /// + /// Disposes the current Logger instance + /// private void DisposeLogger() { if (Logger.LoggerInstance != null) diff --git a/MediaBrowser.Controller/Kernel.cs b/MediaBrowser.Controller/Kernel.cs index 025add7c51..a6a0594965 100644 --- a/MediaBrowser.Controller/Kernel.cs +++ b/MediaBrowser.Controller/Kernel.cs @@ -318,7 +318,7 @@ namespace MediaBrowser.Controller /// Gets all studios from all recursive children of a folder /// The CategoryInfo class is used to keep track of the number of times each studio appears /// - public IEnumerable GetAllStudios(Folder parent, Guid userId) + public IEnumerable> GetAllStudios(Folder parent, Guid userId) { Dictionary data = new Dictionary(); @@ -348,7 +348,7 @@ namespace MediaBrowser.Controller } // Now go through the dictionary and create a Category for each studio - List list = new List(); + List> list = new List>(); foreach (string key in data.Keys) { @@ -357,11 +357,10 @@ namespace MediaBrowser.Controller if (entity != null) { - list.Add(new CategoryInfo() + list.Add(new CategoryInfo() { - Name = entity.Name, - ItemCount = data[key], - PrimaryImagePath = entity.PrimaryImagePath + Item = entity, + ItemCount = data[key] }); } } @@ -373,7 +372,7 @@ namespace MediaBrowser.Controller /// Gets all genres from all recursive children of a folder /// The CategoryInfo class is used to keep track of the number of times each genres appears /// - public IEnumerable GetAllGenres(Folder parent, Guid userId) + public IEnumerable> GetAllGenres(Folder parent, Guid userId) { Dictionary data = new Dictionary(); @@ -403,7 +402,7 @@ namespace MediaBrowser.Controller } // Now go through the dictionary and create a Category for each genre - List list = new List(); + List> list = new List>(); foreach (string key in data.Keys) { @@ -412,11 +411,10 @@ namespace MediaBrowser.Controller if (entity != null) { - list.Add(new CategoryInfo() + list.Add(new CategoryInfo() { - Name = entity.Name, - ItemCount = data[key], - PrimaryImagePath = entity.PrimaryImagePath + Item = entity, + ItemCount = data[key] }); } } diff --git a/MediaBrowser.Logging/StreamLogger.cs b/MediaBrowser.Logging/StreamLogger.cs index f1a16c7ad1..c4ad7b80f6 100644 --- a/MediaBrowser.Logging/StreamLogger.cs +++ b/MediaBrowser.Logging/StreamLogger.cs @@ -4,6 +4,9 @@ using System.Text; namespace MediaBrowser.Logging { + /// + /// Provides a Logger that can write to any Stream + /// public class StreamLogger : BaseLogger { private Stream Stream { get; set; } diff --git a/MediaBrowser.Model/Entities/ApiBaseItem.cs b/MediaBrowser.Model/Entities/ApiBaseItem.cs index 665a2f6c66..b3fbbbcdef 100644 --- a/MediaBrowser.Model/Entities/ApiBaseItem.cs +++ b/MediaBrowser.Model/Entities/ApiBaseItem.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using MediaBrowser.Model.Users; namespace MediaBrowser.Model.Entities @@ -26,5 +27,15 @@ namespace MediaBrowser.Model.Entities public bool IsFolder { get; set; } public string Type { get; set; } + + public bool IsType(Type type) + { + return IsType(type.Name); + } + + public bool IsType(string type) + { + return Type.Equals(type, StringComparison.OrdinalIgnoreCase); + } } } diff --git a/MediaBrowser.Model/Entities/CategoryInfo.cs b/MediaBrowser.Model/Entities/CategoryInfo.cs index adf8ac7d96..934a0ae1d1 100644 --- a/MediaBrowser.Model/Entities/CategoryInfo.cs +++ b/MediaBrowser.Model/Entities/CategoryInfo.cs @@ -2,16 +2,14 @@ namespace MediaBrowser.Model.Entities { /// - /// This is a stub class used by the api to get IBN types in a compact format + /// This is a stub class used by the api to get IBN types along with their item counts /// - public class CategoryInfo + public class CategoryInfo { /// - /// The name of the genre, year, studio, etc + /// The actual genre, year, studio, etc /// - public string Name { get; set; } - - public string PrimaryImagePath { get; set; } + public T Item { get; set; } /// /// The number of items that have the genre, year, studio, etc diff --git a/MediaBrowser.Model/Entities/ImageType.cs b/MediaBrowser.Model/Entities/ImageType.cs new file mode 100644 index 0000000000..d9bb06cbca --- /dev/null +++ b/MediaBrowser.Model/Entities/ImageType.cs @@ -0,0 +1,13 @@ + +namespace MediaBrowser.Model.Entities +{ + public enum ImageType + { + Primary, + Art, + Backdrop, + Banner, + Logo, + Thumbnail + } +} diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index 9338b3884e..0157fcbf85 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -47,6 +47,7 @@ + -- cgit v1.2.3 From 3f1af19ce7702a3310842f812563e580b2ca4408 Mon Sep 17 00:00:00 2001 From: LukePulverenti Luke Pulverenti luke pulverenti Date: Wed, 15 Aug 2012 09:20:29 -0400 Subject: Re-worked provider id's, api client, moved people to the api item wrapper and added server error handling --- MediaBrowser.Api/ApiService.cs | 19 ++- MediaBrowser.Api/HttpHandlers/BaseMediaHandler.cs | 11 +- MediaBrowser.Api/HttpHandlers/GenresHandler.cs | 14 +- MediaBrowser.Api/HttpHandlers/ImageHandler.cs | 75 ++++++++-- MediaBrowser.Api/HttpHandlers/ItemHandler.cs | 17 ++- MediaBrowser.Api/HttpHandlers/ItemListHandler.cs | 14 +- MediaBrowser.Api/HttpHandlers/JsonHandler.cs | 20 --- MediaBrowser.Api/HttpHandlers/PersonHandler.cs | 12 +- .../HttpHandlers/PluginConfigurationHandler.cs | 12 +- MediaBrowser.Api/HttpHandlers/PluginsHandler.cs | 36 +++-- MediaBrowser.Api/HttpHandlers/StudiosHandler.cs | 14 +- .../HttpHandlers/UserConfigurationHandler.cs | 12 +- MediaBrowser.Api/HttpHandlers/UsersHandler.cs | 12 +- MediaBrowser.Api/HttpHandlers/YearsHandler.cs | 14 +- MediaBrowser.Api/ImageProcessor.cs | 4 +- MediaBrowser.Api/MediaBrowser.Api.csproj | 1 - MediaBrowser.ApiInteraction/ApiClient.cs | 34 +++-- MediaBrowser.ApiInteraction/BaseClient.cs | 52 ------- MediaBrowser.ApiInteraction/IHttpClient.cs | 11 ++ .../MediaBrowser.ApiInteraction.csproj | 2 +- .../Configuration/ApplicationPaths.cs | 9 +- MediaBrowser.Common/Net/Handlers/BaseHandler.cs | 96 ++++++++----- .../Net/Handlers/BaseJsonHandler.cs | 51 ++++++- .../Net/Handlers/StaticFileHandler.cs | 158 ++++++++++----------- MediaBrowser.Common/Net/MimeTypes.cs | 2 + MediaBrowser.Controller/Xml/BaseItemXmlParser.cs | 28 +++- MediaBrowser.Model/Entities/ApiBaseItem.cs | 7 +- MediaBrowser.Model/Entities/BaseItem.cs | 45 ++++++ MediaBrowser.Model/Entities/MetadataProviders.cs | 11 ++ MediaBrowser.Model/MediaBrowser.Model.csproj | 1 + MediaBrowser.Movies/MediaBrowser.Movies.csproj | 1 - MediaBrowser.Movies/Metadata/MovieXmlParser.cs | 32 ----- MediaBrowser.Movies/Resolvers/MovieResolver.cs | 4 +- MediaBrowser.TV/Entities/Series.cs | 6 +- MediaBrowser.TV/Metadata/EpisodeXmlParser.cs | 3 +- MediaBrowser.TV/Metadata/SeriesXmlParser.cs | 7 +- 36 files changed, 474 insertions(+), 373 deletions(-) delete mode 100644 MediaBrowser.Api/HttpHandlers/JsonHandler.cs delete mode 100644 MediaBrowser.ApiInteraction/BaseClient.cs create mode 100644 MediaBrowser.ApiInteraction/IHttpClient.cs create mode 100644 MediaBrowser.Model/Entities/MetadataProviders.cs delete mode 100644 MediaBrowser.Movies/Metadata/MovieXmlParser.cs (limited to 'MediaBrowser.Api/HttpHandlers/StudiosHandler.cs') diff --git a/MediaBrowser.Api/ApiService.cs b/MediaBrowser.Api/ApiService.cs index c14705be67..7c52e0e5c6 100644 --- a/MediaBrowser.Api/ApiService.cs +++ b/MediaBrowser.Api/ApiService.cs @@ -58,6 +58,8 @@ namespace MediaBrowser.Api { wrapper.Children = Kernel.Instance.GetParentalAllowedChildren(folder, userId).Select(c => GetSerializationObject(c, false, userId)); } + + wrapper.People = item.People; } return wrapper; @@ -136,15 +138,18 @@ namespace MediaBrowser.Api _FFMpegPath = Path.Combine(FFMpegDirectory, filename); - if (!File.Exists(_FFMpegPath)) + // Always re-extract the first time to handle new versions + if (File.Exists(_FFMpegPath)) + { + File.Delete(_FFMpegPath); + } + + // Extract ffprobe + using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MediaBrowser.Api.FFMpeg." + filename)) { - // Extract ffprobe - using (Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MediaBrowser.Api.FFMpeg." + filename)) + using (FileStream fileStream = new FileStream(_FFMpegPath, FileMode.Create)) { - using (FileStream fileStream = new FileStream(_FFMpegPath, FileMode.Create)) - { - stream.CopyTo(fileStream); - } + stream.CopyTo(fileStream); } } } diff --git a/MediaBrowser.Api/HttpHandlers/BaseMediaHandler.cs b/MediaBrowser.Api/HttpHandlers/BaseMediaHandler.cs index da397fec93..fd85993c8e 100644 --- a/MediaBrowser.Api/HttpHandlers/BaseMediaHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/BaseMediaHandler.cs @@ -107,17 +107,18 @@ namespace MediaBrowser.Api.HttpHandlers } } - public override void ProcessRequest(HttpListenerContext ctx) + public override async Task ProcessRequest(HttpListenerContext ctx) { HttpListenerContext = ctx; if (!RequiresConversion()) { - new StaticFileHandler() { Path = LibraryItem.Path }.ProcessRequest(ctx); - return; + await new StaticFileHandler() { Path = LibraryItem.Path }.ProcessRequest(ctx); + } + else + { + await base.ProcessRequest(ctx); } - - base.ProcessRequest(ctx); } protected abstract string GetCommandLineArguments(); diff --git a/MediaBrowser.Api/HttpHandlers/GenresHandler.cs b/MediaBrowser.Api/HttpHandlers/GenresHandler.cs index e8e3fd80b7..0c38a23962 100644 --- a/MediaBrowser.Api/HttpHandlers/GenresHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/GenresHandler.cs @@ -1,20 +1,18 @@ using System; +using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Controller; using MediaBrowser.Model.Entities; namespace MediaBrowser.Api.HttpHandlers { - public class GenresHandler : JsonHandler + public class GenresHandler : BaseJsonHandler { - protected sealed override object ObjectToSerialize + protected override object GetObjectToSerialize() { - get - { - Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder; - Guid userId = Guid.Parse(QueryString["userid"]); + Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder; + Guid userId = Guid.Parse(QueryString["userid"]); - return Kernel.Instance.GetAllGenres(parent, userId); - } + return Kernel.Instance.GetAllGenres(parent, userId); } } } diff --git a/MediaBrowser.Api/HttpHandlers/ImageHandler.cs b/MediaBrowser.Api/HttpHandlers/ImageHandler.cs index c53afb5c48..8264380980 100644 --- a/MediaBrowser.Api/HttpHandlers/ImageHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/ImageHandler.cs @@ -2,6 +2,8 @@ using System.IO; using System.Linq; using System.Threading.Tasks; +using MediaBrowser.Common.Logging; +using MediaBrowser.Common.Net; using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Controller; using MediaBrowser.Model.Entities; @@ -10,12 +12,12 @@ namespace MediaBrowser.Api.HttpHandlers { public class ImageHandler : BaseHandler { - private string _ImagePath = string.Empty; + private string _ImagePath = null; private string ImagePath { get { - if (string.IsNullOrEmpty(_ImagePath)) + if (_ImagePath == null) { _ImagePath = GetImagePath(); } @@ -24,18 +26,61 @@ namespace MediaBrowser.Api.HttpHandlers } } - public override string ContentType + private Stream _SourceStream = null; + private Stream SourceStream { get { - string extension = Path.GetExtension(ImagePath); + EnsureSourceStream(); + + return _SourceStream; + } + } - if (extension.EndsWith("png", StringComparison.OrdinalIgnoreCase)) + + private bool _SourceStreamEnsured = false; + private void EnsureSourceStream() + { + if (!_SourceStreamEnsured) + { + try + { + _SourceStream = File.OpenRead(ImagePath); + } + catch (FileNotFoundException ex) + { + StatusCode = 404; + Logger.LogException(ex); + } + catch (DirectoryNotFoundException ex) + { + StatusCode = 404; + Logger.LogException(ex); + } + catch (UnauthorizedAccessException ex) + { + StatusCode = 403; + Logger.LogException(ex); + } + finally { - return "image/png"; + _SourceStreamEnsured = true; } + } + } + + public override string ContentType + { + get + { + EnsureSourceStream(); - return "image/jpeg"; + if (SourceStream == null) + { + return null; + } + + return MimeTypes.GetMimeType(ImagePath); } } @@ -49,14 +94,14 @@ namespace MediaBrowser.Api.HttpHandlers protected override DateTime? GetLastDateModified() { - try - { - return File.GetLastWriteTime(ImagePath); - } - catch + EnsureSourceStream(); + + if (SourceStream == null) { - return base.GetLastDateModified(); + return null; } + + return File.GetLastWriteTime(ImagePath); } private int? Height @@ -142,7 +187,7 @@ namespace MediaBrowser.Api.HttpHandlers if (string.IsNullOrEmpty(imageType)) { - return Model.Entities.ImageType.Primary; + return ImageType.Primary; } return (ImageType)Enum.Parse(typeof(ImageType), imageType, true); @@ -153,7 +198,7 @@ namespace MediaBrowser.Api.HttpHandlers { return Task.Run(() => { - ImageProcessor.ProcessImage(ImagePath, stream, Width, Height, MaxWidth, MaxHeight, Quality); + ImageProcessor.ProcessImage(SourceStream, stream, Width, Height, MaxWidth, MaxHeight, Quality); }); } diff --git a/MediaBrowser.Api/HttpHandlers/ItemHandler.cs b/MediaBrowser.Api/HttpHandlers/ItemHandler.cs index a54d65524f..28def271f8 100644 --- a/MediaBrowser.Api/HttpHandlers/ItemHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/ItemHandler.cs @@ -1,18 +1,23 @@ using System; +using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Model.Entities; namespace MediaBrowser.Api.HttpHandlers { - public class ItemHandler : JsonHandler + public class ItemHandler : BaseJsonHandler { - protected sealed override object ObjectToSerialize + protected sealed override object GetObjectToSerialize() { - get - { - Guid userId = Guid.Parse(QueryString["userid"]); + Guid userId = Guid.Parse(QueryString["userid"]); + + BaseItem item = ItemToSerialize; - return ApiService.GetSerializationObject(ItemToSerialize, true, userId); + if (item == null) + { + return null; } + + return ApiService.GetSerializationObject(item, true, userId); } protected virtual BaseItem ItemToSerialize diff --git a/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs b/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs index a94c2061e1..0d9d3d0a89 100644 --- a/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs @@ -1,22 +1,20 @@ using System; using System.Collections.Generic; using System.Linq; +using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Model.Entities; namespace MediaBrowser.Api.HttpHandlers { - public abstract class ItemListHandler : JsonHandler + public abstract class ItemListHandler : BaseJsonHandler { - protected sealed override object ObjectToSerialize + protected override object GetObjectToSerialize() { - get + return ItemsToSerialize.Select(i => { - return ItemsToSerialize.Select(i => - { - return ApiService.GetSerializationObject(i, false, UserId); + return ApiService.GetSerializationObject(i, false, UserId); - }); - } + }); } protected abstract IEnumerable ItemsToSerialize diff --git a/MediaBrowser.Api/HttpHandlers/JsonHandler.cs b/MediaBrowser.Api/HttpHandlers/JsonHandler.cs deleted file mode 100644 index bffa841745..0000000000 --- a/MediaBrowser.Api/HttpHandlers/JsonHandler.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.IO; -using System.Threading.Tasks; -using MediaBrowser.Common.Net.Handlers; -using MediaBrowser.Common.Serialization; - -namespace MediaBrowser.Api.HttpHandlers -{ - public abstract class JsonHandler : BaseJsonHandler - { - protected abstract object ObjectToSerialize { get; } - - protected override Task WriteResponseToOutputStream(Stream stream) - { - return Task.Run(() => - { - JsonSerializer.SerializeToStream(ObjectToSerialize, stream); - }); - } - } -} diff --git a/MediaBrowser.Api/HttpHandlers/PersonHandler.cs b/MediaBrowser.Api/HttpHandlers/PersonHandler.cs index c70ad39ca6..103e49cd2d 100644 --- a/MediaBrowser.Api/HttpHandlers/PersonHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/PersonHandler.cs @@ -1,15 +1,13 @@ -using MediaBrowser.Controller; +using MediaBrowser.Common.Net.Handlers; +using MediaBrowser.Controller; namespace MediaBrowser.Api.HttpHandlers { - public class PersonHandler : JsonHandler + public class PersonHandler : BaseJsonHandler { - protected sealed override object ObjectToSerialize + protected override object GetObjectToSerialize() { - get - { - return Kernel.Instance.ItemController.GetPerson(QueryString["name"]); - } + return Kernel.Instance.ItemController.GetPerson(QueryString["name"]); } } } diff --git a/MediaBrowser.Api/HttpHandlers/PluginConfigurationHandler.cs b/MediaBrowser.Api/HttpHandlers/PluginConfigurationHandler.cs index 5f5203dae0..4dc317ecc1 100644 --- a/MediaBrowser.Api/HttpHandlers/PluginConfigurationHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/PluginConfigurationHandler.cs @@ -1,19 +1,17 @@ using System; using System.Linq; +using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Controller; namespace MediaBrowser.Api.HttpHandlers { - public class PluginConfigurationHandler : JsonHandler + public class PluginConfigurationHandler : BaseJsonHandler { - protected override object ObjectToSerialize + protected override object GetObjectToSerialize() { - get - { - string pluginName = QueryString["name"]; + string pluginName = QueryString["name"]; - return Kernel.Instance.Plugins.First(p => p.Name.Equals(pluginName, StringComparison.OrdinalIgnoreCase)).Configuration; - } + return Kernel.Instance.Plugins.First(p => p.Name.Equals(pluginName, StringComparison.OrdinalIgnoreCase)).Configuration; } } } diff --git a/MediaBrowser.Api/HttpHandlers/PluginsHandler.cs b/MediaBrowser.Api/HttpHandlers/PluginsHandler.cs index 63797026d7..a44e126921 100644 --- a/MediaBrowser.Api/HttpHandlers/PluginsHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/PluginsHandler.cs @@ -1,4 +1,5 @@ using System.Linq; +using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Controller; using MediaBrowser.Model.Plugins; @@ -7,31 +8,28 @@ namespace MediaBrowser.Api.HttpHandlers /// /// Provides information about installed plugins /// - public class PluginsHandler : JsonHandler + public class PluginsHandler : BaseJsonHandler { - protected override object ObjectToSerialize + protected override object GetObjectToSerialize() { - get + var plugins = Kernel.Instance.Plugins.Select(p => { - var plugins = Kernel.Instance.Plugins.Select(p => + return new PluginInfo() { - return new PluginInfo() - { - Path = p.Path, - Name = p.Name, - Enabled = p.Enabled, - DownloadToUI = p.DownloadToUI, - Version = p.Version - }; - }); + Path = p.Path, + Name = p.Name, + Enabled = p.Enabled, + DownloadToUI = p.DownloadToUI, + Version = p.Version + }; + }); - if (QueryString["uionly"] == "1") - { - plugins = plugins.Where(p => p.DownloadToUI); - } - - return plugins; + if (QueryString["uionly"] == "1") + { + plugins = plugins.Where(p => p.DownloadToUI); } + + return plugins; } } } diff --git a/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs b/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs index ff48ae6e36..a381af15fe 100644 --- a/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs @@ -1,20 +1,18 @@ using System; +using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Controller; using MediaBrowser.Model.Entities; namespace MediaBrowser.Api.HttpHandlers { - public class StudiosHandler : JsonHandler + public class StudiosHandler : BaseJsonHandler { - protected override object ObjectToSerialize + protected override object GetObjectToSerialize() { - get - { - Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder; - Guid userId = Guid.Parse(QueryString["userid"]); + Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder; + Guid userId = Guid.Parse(QueryString["userid"]); - return Kernel.Instance.GetAllStudios(parent, userId); - } + return Kernel.Instance.GetAllStudios(parent, userId); } } } diff --git a/MediaBrowser.Api/HttpHandlers/UserConfigurationHandler.cs b/MediaBrowser.Api/HttpHandlers/UserConfigurationHandler.cs index 06c3ea86dd..f9d3536b6d 100644 --- a/MediaBrowser.Api/HttpHandlers/UserConfigurationHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/UserConfigurationHandler.cs @@ -1,18 +1,16 @@ using System; +using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Controller; namespace MediaBrowser.Api.HttpHandlers { - public class UserConfigurationHandler : JsonHandler + public class UserConfigurationHandler : BaseJsonHandler { - protected override object ObjectToSerialize + protected override object GetObjectToSerialize() { - get - { - Guid userId = Guid.Parse(QueryString["userid"]); + Guid userId = Guid.Parse(QueryString["userid"]); - return Kernel.Instance.GetUserConfiguration(userId); - } + return Kernel.Instance.GetUserConfiguration(userId); } } } diff --git a/MediaBrowser.Api/HttpHandlers/UsersHandler.cs b/MediaBrowser.Api/HttpHandlers/UsersHandler.cs index d10561e435..64f68f62f1 100644 --- a/MediaBrowser.Api/HttpHandlers/UsersHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/UsersHandler.cs @@ -1,15 +1,13 @@ -using MediaBrowser.Controller; +using MediaBrowser.Common.Net.Handlers; +using MediaBrowser.Controller; namespace MediaBrowser.Api.HttpHandlers { - class UsersHandler : JsonHandler + class UsersHandler : BaseJsonHandler { - protected override object ObjectToSerialize + protected override object GetObjectToSerialize() { - get - { - return Kernel.Instance.Users; - } + return Kernel.Instance.Users; } } } diff --git a/MediaBrowser.Api/HttpHandlers/YearsHandler.cs b/MediaBrowser.Api/HttpHandlers/YearsHandler.cs index 6f47870282..044866dca3 100644 --- a/MediaBrowser.Api/HttpHandlers/YearsHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/YearsHandler.cs @@ -1,20 +1,18 @@ using System; +using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Controller; using MediaBrowser.Model.Entities; namespace MediaBrowser.Api.HttpHandlers { - public class YearsHandler : JsonHandler + public class YearsHandler : BaseJsonHandler { - protected override object ObjectToSerialize + protected override object GetObjectToSerialize() { - get - { - Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder; - Guid userId = Guid.Parse(QueryString["userid"]); + Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder; + Guid userId = Guid.Parse(QueryString["userid"]); - return Kernel.Instance.GetAllYears(parent, userId); - } + return Kernel.Instance.GetAllYears(parent, userId); } } } diff --git a/MediaBrowser.Api/ImageProcessor.cs b/MediaBrowser.Api/ImageProcessor.cs index a798123e45..014f655984 100644 --- a/MediaBrowser.Api/ImageProcessor.cs +++ b/MediaBrowser.Api/ImageProcessor.cs @@ -8,9 +8,9 @@ namespace MediaBrowser.Api { public static class ImageProcessor { - public static void ProcessImage(string path, Stream toStream, int? width, int? height, int? maxWidth, int? maxHeight, int? quality) + public static void ProcessImage(Stream sourceImageStream, Stream toStream, int? width, int? height, int? maxWidth, int? maxHeight, int? quality) { - Image originalImage = Image.FromFile(path); + Image originalImage = Image.FromStream(sourceImageStream); var newWidth = originalImage.Width; var newHeight = originalImage.Height; diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj index 4bd6d89e82..e6a1816f6d 100644 --- a/MediaBrowser.Api/MediaBrowser.Api.csproj +++ b/MediaBrowser.Api/MediaBrowser.Api.csproj @@ -56,7 +56,6 @@ - diff --git a/MediaBrowser.ApiInteraction/ApiClient.cs b/MediaBrowser.ApiInteraction/ApiClient.cs index 5685638f60..0750223b6d 100644 --- a/MediaBrowser.ApiInteraction/ApiClient.cs +++ b/MediaBrowser.ApiInteraction/ApiClient.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Net.Http; using System.Threading.Tasks; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Entities; @@ -10,20 +9,32 @@ using MediaBrowser.Model.Users; namespace MediaBrowser.ApiInteraction { - public class ApiClient : BaseClient + public class ApiClient : IDisposable { - public IJsonSerializer JsonSerializer { get; set; } + /// + /// Gets or sets the server host name (myserver or 192.168.x.x) + /// + public string ServerHostName { get; set; } - public ApiClient() - : base() - { - } + /// + /// Gets or sets the port number used by the API + /// + public int ServerApiPort { get; set; } - public ApiClient(HttpClientHandler handler) - : base(handler) + /// + /// Gets the current api url based on hostname and port. + /// + protected string ApiUrl { + get + { + return string.Format("http://{0}:{1}/mediabrowser/api", ServerHostName, ServerApiPort); + } } + public IHttpClient HttpClient { get; set; } + public IJsonSerializer JsonSerializer { get; set; } + /// /// Gets an image url that can be used to download an image from the api /// @@ -278,5 +289,10 @@ namespace MediaBrowser.ApiInteraction return JsonSerializer.DeserializeFromStream>>(stream); } } + + public void Dispose() + { + HttpClient.Dispose(); + } } } diff --git a/MediaBrowser.ApiInteraction/BaseClient.cs b/MediaBrowser.ApiInteraction/BaseClient.cs deleted file mode 100644 index 8799ca5412..0000000000 --- a/MediaBrowser.ApiInteraction/BaseClient.cs +++ /dev/null @@ -1,52 +0,0 @@ -using System; -using System.Net; -using System.Net.Http; - -namespace MediaBrowser.ApiInteraction -{ - /// - /// Provides a base class used by the api and image services - /// - public abstract class BaseClient : IDisposable - { - /// - /// Gets or sets the server host name (myserver or 192.168.x.x) - /// - public string ServerHostName { get; set; } - - /// - /// Gets or sets the port number used by the API - /// - public int ServerApiPort { get; set; } - - /// - /// Gets the current api url based on hostname and port. - /// - protected string ApiUrl - { - get - { - return string.Format("http://{0}:{1}/mediabrowser/api", ServerHostName, ServerApiPort); - } - } - - protected HttpClient HttpClient { get; private set; } - - public BaseClient() - : this(new HttpClientHandler()) - { - } - - public BaseClient(HttpClientHandler clientHandler) - { - clientHandler.AutomaticDecompression = DecompressionMethods.Deflate; - - HttpClient = new HttpClient(clientHandler); - } - - public void Dispose() - { - HttpClient.Dispose(); - } - } -} diff --git a/MediaBrowser.ApiInteraction/IHttpClient.cs b/MediaBrowser.ApiInteraction/IHttpClient.cs new file mode 100644 index 0000000000..40659e0191 --- /dev/null +++ b/MediaBrowser.ApiInteraction/IHttpClient.cs @@ -0,0 +1,11 @@ +using System; +using System.IO; +using System.Threading.Tasks; + +namespace MediaBrowser.ApiInteraction +{ + public interface IHttpClient : IDisposable + { + Task GetStreamAsync(string url); + } +} diff --git a/MediaBrowser.ApiInteraction/MediaBrowser.ApiInteraction.csproj b/MediaBrowser.ApiInteraction/MediaBrowser.ApiInteraction.csproj index 682d974da6..965b4487da 100644 --- a/MediaBrowser.ApiInteraction/MediaBrowser.ApiInteraction.csproj +++ b/MediaBrowser.ApiInteraction/MediaBrowser.ApiInteraction.csproj @@ -40,7 +40,7 @@ - + diff --git a/MediaBrowser.Common/Configuration/ApplicationPaths.cs b/MediaBrowser.Common/Configuration/ApplicationPaths.cs index dc87749cfb..efe6f0c9e0 100644 --- a/MediaBrowser.Common/Configuration/ApplicationPaths.cs +++ b/MediaBrowser.Common/Configuration/ApplicationPaths.cs @@ -1,12 +1,5 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using System.Configuration; using System.IO; -using System.ComponentModel.Composition; -using System.ComponentModel.Composition.Hosting; -using System.Configuration; using System.Reflection; namespace MediaBrowser.Common.Configuration diff --git a/MediaBrowser.Common/Net/Handlers/BaseHandler.cs b/MediaBrowser.Common/Net/Handlers/BaseHandler.cs index 89803d8d74..f9ef065ecc 100644 --- a/MediaBrowser.Common/Net/Handlers/BaseHandler.cs +++ b/MediaBrowser.Common/Net/Handlers/BaseHandler.cs @@ -185,7 +185,7 @@ namespace MediaBrowser.Common.Net.Handlers } } - public virtual void ProcessRequest(HttpListenerContext ctx) + public virtual async Task ProcessRequest(HttpListenerContext ctx) { HttpListenerContext = ctx; @@ -196,46 +196,61 @@ namespace MediaBrowser.Common.Net.Handlers ctx.Response.KeepAlive = true; - if (SupportsByteRangeRequests && IsRangeRequest) + try { - ctx.Response.Headers["Accept-Ranges"] = "bytes"; - } - - // Set the initial status code - // When serving a range request, we need to return status code 206 to indicate a partial response body - StatusCode = SupportsByteRangeRequests && IsRangeRequest ? 206 : 200; + if (SupportsByteRangeRequests && IsRangeRequest) + { + ctx.Response.Headers["Accept-Ranges"] = "bytes"; + } - ctx.Response.ContentType = ContentType; + // Set the initial status code + // When serving a range request, we need to return status code 206 to indicate a partial response body + StatusCode = SupportsByteRangeRequests && IsRangeRequest ? 206 : 200; - TimeSpan cacheDuration = CacheDuration; + ctx.Response.ContentType = ContentType; - if (ctx.Request.Headers.AllKeys.Contains("If-Modified-Since")) - { - DateTime ifModifiedSince; + TimeSpan cacheDuration = CacheDuration; - if (DateTime.TryParse(ctx.Request.Headers["If-Modified-Since"].Replace(" GMT", string.Empty), out ifModifiedSince)) + if (ctx.Request.Headers.AllKeys.Contains("If-Modified-Since")) { - // If the cache hasn't expired yet just return a 304 - if (IsCacheValid(ifModifiedSince, cacheDuration, LastDateModified)) + DateTime ifModifiedSince; + + if (DateTime.TryParse(ctx.Request.Headers["If-Modified-Since"].Replace(" GMT", string.Empty), out ifModifiedSince)) { - StatusCode = 304; + // If the cache hasn't expired yet just return a 304 + if (IsCacheValid(ifModifiedSince, cacheDuration, LastDateModified)) + { + StatusCode = 304; + } } } - } - if (StatusCode == 200 || StatusCode == 206) + PrepareResponse(); + + if (IsResponseValid) + { + await ProcessUncachedRequest(ctx, cacheDuration); + } + else + { + ctx.Response.StatusCode = StatusCode; + ctx.Response.SendChunked = false; + } + } + catch (Exception ex) { - ProcessUncachedResponse(ctx, cacheDuration); + // It might be too late if some response data has already been transmitted, but try to set this + ctx.Response.StatusCode = 500; + + Logger.LogException(ex); } - else + finally { - ctx.Response.StatusCode = StatusCode; - ctx.Response.SendChunked = false; DisposeResponseStream(); } } - private async void ProcessUncachedResponse(HttpListenerContext ctx, TimeSpan cacheDuration) + private async Task ProcessUncachedRequest(HttpListenerContext ctx, TimeSpan cacheDuration) { long? totalContentLength = TotalContentLength; @@ -269,7 +284,7 @@ namespace MediaBrowser.Common.Net.Handlers // Set the status code ctx.Response.StatusCode = StatusCode; - if (StatusCode == 200 || StatusCode == 206) + if (IsResponseValid) { // Finally, write the response data Stream outputStream = ctx.Response.OutputStream; @@ -288,23 +303,11 @@ namespace MediaBrowser.Common.Net.Handlers outputStream = CompressedStream; } - try - { - await WriteResponseToOutputStream(outputStream); - } - catch (Exception ex) - { - Logger.LogException(ex); - } - finally - { - DisposeResponseStream(); - } + await WriteResponseToOutputStream(outputStream); } else { ctx.Response.SendChunked = false; - DisposeResponseStream(); } } @@ -317,9 +320,16 @@ namespace MediaBrowser.Common.Net.Handlers response.Headers[HttpResponseHeader.LastModified] = lastModified.ToString("r"); } + /// + /// Gives subclasses a chance to do and prep work, and also to validate data and set an error status code, if needed + /// + protected virtual void PrepareResponse() + { + } + protected abstract Task WriteResponseToOutputStream(Stream stream); - private void DisposeResponseStream() + protected virtual void DisposeResponseStream() { if (CompressedStream != null) { @@ -366,5 +376,13 @@ namespace MediaBrowser.Common.Net.Handlers { return null; } + + private bool IsResponseValid + { + get + { + return StatusCode == 200 || StatusCode == 206; + } + } } } \ No newline at end of file diff --git a/MediaBrowser.Common/Net/Handlers/BaseJsonHandler.cs b/MediaBrowser.Common/Net/Handlers/BaseJsonHandler.cs index 30113198b9..03de398c90 100644 --- a/MediaBrowser.Common/Net/Handlers/BaseJsonHandler.cs +++ b/MediaBrowser.Common/Net/Handlers/BaseJsonHandler.cs @@ -1,11 +1,58 @@ - +using System.IO; +using System.Threading.Tasks; +using MediaBrowser.Common.Serialization; + namespace MediaBrowser.Common.Net.Handlers { public abstract class BaseJsonHandler : BaseHandler { public override string ContentType { - get { return "application/json"; } + get { return MimeTypes.JsonMimeType; } + } + + private bool _ObjectToSerializeEnsured = false; + private object _ObjectToSerialize; + + private void EnsureObjectToSerialize() + { + if (!_ObjectToSerializeEnsured) + { + _ObjectToSerialize = GetObjectToSerialize(); + + if (_ObjectToSerialize == null) + { + StatusCode = 404; + } + + _ObjectToSerializeEnsured = true; + } + } + + private object ObjectToSerialize + { + get + { + EnsureObjectToSerialize(); + return _ObjectToSerialize; + } + } + + protected abstract object GetObjectToSerialize(); + + protected override void PrepareResponse() + { + base.PrepareResponse(); + + EnsureObjectToSerialize(); + } + + protected override Task WriteResponseToOutputStream(Stream stream) + { + return Task.Run(() => + { + JsonSerializer.SerializeToStream(ObjectToSerialize, stream); + }); } } } diff --git a/MediaBrowser.Common/Net/Handlers/StaticFileHandler.cs b/MediaBrowser.Common/Net/Handlers/StaticFileHandler.cs index 3eb908938f..5656f92739 100644 --- a/MediaBrowser.Common/Net/Handlers/StaticFileHandler.cs +++ b/MediaBrowser.Common/Net/Handlers/StaticFileHandler.cs @@ -28,37 +28,44 @@ namespace MediaBrowser.Common.Net.Handlers } } - private bool FileStreamDiscovered = false; - private FileStream _FileStream = null; - private FileStream FileStream + private bool _SourceStreamEnsured = false; + private Stream _SourceStream = null; + private Stream SourceStream { get { - if (!FileStreamDiscovered) + EnsureSourceStream(); + return _SourceStream; + } + } + + private void EnsureSourceStream() + { + if (!_SourceStreamEnsured) + { + try { - try - { - _FileStream = File.OpenRead(Path); - } - catch (FileNotFoundException) - { - StatusCode = 404; - } - catch (DirectoryNotFoundException) - { - StatusCode = 404; - } - catch (UnauthorizedAccessException) - { - StatusCode = 403; - } - finally - { - FileStreamDiscovered = true; - } + _SourceStream = File.OpenRead(Path); + } + catch (FileNotFoundException ex) + { + StatusCode = 404; + Logger.LogException(ex); + } + catch (DirectoryNotFoundException ex) + { + StatusCode = 404; + Logger.LogException(ex); + } + catch (UnauthorizedAccessException ex) + { + StatusCode = 403; + Logger.LogException(ex); + } + finally + { + _SourceStreamEnsured = true; } - - return _FileStream; } } @@ -74,14 +81,14 @@ namespace MediaBrowser.Common.Net.Handlers { get { - string contentType = ContentType; - // Can't compress these if (IsRangeRequest) { return false; } + string contentType = ContentType; + // Don't compress media if (contentType.StartsWith("audio/", StringComparison.OrdinalIgnoreCase) || contentType.StartsWith("video/", StringComparison.OrdinalIgnoreCase)) { @@ -95,26 +102,19 @@ namespace MediaBrowser.Common.Net.Handlers protected override long? GetTotalContentLength() { - try - { - return FileStream.Length; - } - catch - { - return base.GetTotalContentLength(); - } + return SourceStream.Length; } protected override DateTime? GetLastDateModified() { - try - { - return File.GetLastWriteTime(Path); - } - catch + EnsureSourceStream(); + + if (SourceStream == null) { - return base.GetLastDateModified(); + return null; } + + return File.GetLastWriteTime(Path); } public override string ContentType @@ -125,48 +125,48 @@ namespace MediaBrowser.Common.Net.Handlers } } + protected override void PrepareResponse() + { + base.PrepareResponse(); + + EnsureSourceStream(); + } + protected async override Task WriteResponseToOutputStream(Stream stream) { - try + if (IsRangeRequest) { - if (FileStream != null) + KeyValuePair requestedRange = RequestedRanges.First(); + + // If the requested range is "0-" and we know the total length, we can optimize by avoiding having to buffer the content into memory + if (requestedRange.Value == null && TotalContentLength != null) { - if (IsRangeRequest) - { - KeyValuePair requestedRange = RequestedRanges.First(); - - // If the requested range is "0-" and we know the total length, we can optimize by avoiding having to buffer the content into memory - if (requestedRange.Value == null && TotalContentLength != null) - { - await ServeCompleteRangeRequest(requestedRange, stream); - } - else if (TotalContentLength.HasValue) - { - // This will have to buffer a portion of the content into memory - await ServePartialRangeRequestWithKnownTotalContentLength(requestedRange, stream); - } - else - { - // This will have to buffer the entire content into memory - await ServePartialRangeRequestWithUnknownTotalContentLength(requestedRange, stream); - } - } - else - { - await FileStream.CopyToAsync(stream); - } + await ServeCompleteRangeRequest(requestedRange, stream); + } + else if (TotalContentLength.HasValue) + { + // This will have to buffer a portion of the content into memory + await ServePartialRangeRequestWithKnownTotalContentLength(requestedRange, stream); + } + else + { + // This will have to buffer the entire content into memory + await ServePartialRangeRequestWithUnknownTotalContentLength(requestedRange, stream); } } - catch (Exception ex) + else { - Logger.LogException("WriteResponseToOutputStream", ex); + await SourceStream.CopyToAsync(stream); } - finally + } + + protected override void DisposeResponseStream() + { + base.DisposeResponseStream(); + + if (SourceStream != null) { - if (FileStream != null) - { - FileStream.Dispose(); - } + SourceStream.Dispose(); } } @@ -188,10 +188,10 @@ namespace MediaBrowser.Common.Net.Handlers if (rangeStart > 0) { - FileStream.Position = rangeStart; + SourceStream.Position = rangeStart; } - await FileStream.CopyToAsync(responseStream); + await SourceStream.CopyToAsync(responseStream); } /// @@ -200,7 +200,7 @@ namespace MediaBrowser.Common.Net.Handlers private async Task ServePartialRangeRequestWithUnknownTotalContentLength(KeyValuePair requestedRange, Stream responseStream) { // Read the entire stream so that we can determine the length - byte[] bytes = await ReadBytes(FileStream, 0, null); + byte[] bytes = await ReadBytes(SourceStream, 0, null); long totalContentLength = bytes.LongLength; @@ -226,7 +226,7 @@ namespace MediaBrowser.Common.Net.Handlers long rangeLength = 1 + rangeEnd - rangeStart; // Only read the bytes we need - byte[] bytes = await ReadBytes(FileStream, Convert.ToInt32(rangeStart), Convert.ToInt32(rangeLength)); + byte[] bytes = await ReadBytes(SourceStream, Convert.ToInt32(rangeStart), Convert.ToInt32(rangeLength)); // Content-Length is the length of what we're serving, not the original content HttpListenerContext.Response.ContentLength64 = rangeLength; diff --git a/MediaBrowser.Common/Net/MimeTypes.cs b/MediaBrowser.Common/Net/MimeTypes.cs index a49cbaa98c..41df463f71 100644 --- a/MediaBrowser.Common/Net/MimeTypes.cs +++ b/MediaBrowser.Common/Net/MimeTypes.cs @@ -5,6 +5,8 @@ namespace MediaBrowser.Common.Net { public static class MimeTypes { + public static string JsonMimeType = "application/json"; + public static string GetMimeType(string path) { string ext = Path.GetExtension(path); diff --git a/MediaBrowser.Controller/Xml/BaseItemXmlParser.cs b/MediaBrowser.Controller/Xml/BaseItemXmlParser.cs index de9a94b034..38b8584fc0 100644 --- a/MediaBrowser.Controller/Xml/BaseItemXmlParser.cs +++ b/MediaBrowser.Controller/Xml/BaseItemXmlParser.cs @@ -10,7 +10,7 @@ namespace MediaBrowser.Controller.Xml /// /// Provides a base class for parsing metadata xml /// - public abstract class BaseItemXmlParser + public class BaseItemXmlParser where T : BaseItem, new() { /// @@ -215,6 +215,32 @@ namespace MediaBrowser.Controller.Xml break; } + case "TMDbId": + string tmdb = reader.ReadString(); + if (!string.IsNullOrWhiteSpace(tmdb)) + { + item.SetProviderId(MetadataProviders.Tmdb, tmdb); + } + break; + + case "TVcomId": + string TVcomId = reader.ReadString(); + if (!string.IsNullOrWhiteSpace(TVcomId)) + { + item.SetProviderId(MetadataProviders.Tvcom, TVcomId); + } + break; + + case "IMDB_ID": + case "IMDB": + case "IMDbId": + string IMDbId = reader.ReadString(); + if (!string.IsNullOrWhiteSpace(IMDbId)) + { + item.SetProviderId(MetadataProviders.Imdb, IMDbId); + } + break; + case "Genres": FetchFromGenresNode(reader.ReadSubtree(), item); break; diff --git a/MediaBrowser.Model/Entities/ApiBaseItem.cs b/MediaBrowser.Model/Entities/ApiBaseItem.cs index e6bd716547..e40fdc25f8 100644 --- a/MediaBrowser.Model/Entities/ApiBaseItem.cs +++ b/MediaBrowser.Model/Entities/ApiBaseItem.cs @@ -11,14 +11,9 @@ namespace MediaBrowser.Model.Entities public class ApiBaseItem : BaseItem { // TV Series - public string TvdbId { get; set; } public string Status { get; set; } public IEnumerable AirDays { get; set; } public string AirTime { get; set; } - - // Movie - public string TmdbId { get; set; } - public string ImdbId { get; set; } } /// @@ -49,6 +44,8 @@ namespace MediaBrowser.Model.Entities return Type.Equals(type, StringComparison.OrdinalIgnoreCase); } + public IEnumerable People { get; set; } + /// /// If the item does not have a logo, this will hold the Id of the Parent that has one. /// diff --git a/MediaBrowser.Model/Entities/BaseItem.cs b/MediaBrowser.Model/Entities/BaseItem.cs index c6de496bdd..322bac564c 100644 --- a/MediaBrowser.Model/Entities/BaseItem.cs +++ b/MediaBrowser.Model/Entities/BaseItem.cs @@ -33,6 +33,7 @@ namespace MediaBrowser.Model.Entities public string Overview { get; set; } public string Tagline { get; set; } + [IgnoreDataMember] public IEnumerable People { get; set; } public IEnumerable Studios { get; set; } @@ -56,5 +57,49 @@ namespace MediaBrowser.Model.Entities public IEnumerable - public IEnumerable> GetAllStudios(Folder parent, Guid userId) + public IEnumerable> GetAllStudios(Folder parent, Guid userId) { Dictionary data = new Dictionary(); @@ -439,7 +433,7 @@ namespace MediaBrowser.Controller } // Now go through the dictionary and create a Category for each studio - List> list = new List>(); + List> list = new List>(); foreach (string key in data.Keys) { @@ -448,10 +442,10 @@ namespace MediaBrowser.Controller if (entity != null) { - list.Add(new CategoryInfo() + list.Add(new IBNItem() { Item = entity, - ItemCount = data[key] + BaseItemCount = data[key] }); } } @@ -463,7 +457,7 @@ namespace MediaBrowser.Controller /// Gets all genres from all recursive children of a folder /// The CategoryInfo class is used to keep track of the number of times each genres appears /// - public IEnumerable> GetAllGenres(Folder parent, Guid userId) + public IEnumerable> GetAllGenres(Folder parent, Guid userId) { Dictionary data = new Dictionary(); @@ -493,7 +487,7 @@ namespace MediaBrowser.Controller } // Now go through the dictionary and create a Category for each genre - List> list = new List>(); + List> list = new List>(); foreach (string key in data.Keys) { @@ -502,10 +496,10 @@ namespace MediaBrowser.Controller if (entity != null) { - list.Add(new CategoryInfo() + list.Add(new IBNItem() { Item = entity, - ItemCount = data[key] + BaseItemCount = data[key] }); } } diff --git a/MediaBrowser.Model/Configuration/UserConfiguration.cs b/MediaBrowser.Model/Configuration/UserConfiguration.cs deleted file mode 100644 index 5616f6dd60..0000000000 --- a/MediaBrowser.Model/Configuration/UserConfiguration.cs +++ /dev/null @@ -1,16 +0,0 @@ - -namespace MediaBrowser.Model.Configuration -{ - /// - /// This holds settings that can be personalized on a per-user, per-device basis. - /// - public class UserConfiguration - { - public int RecentItemDays { get; set; } - - public UserConfiguration() - { - RecentItemDays = 14; - } - } -} diff --git a/MediaBrowser.Model/DTO/ApiBaseItem.cs b/MediaBrowser.Model/DTO/ApiBaseItem.cs index d6b0f4a047..eca45c9f8b 100644 --- a/MediaBrowser.Model/DTO/ApiBaseItem.cs +++ b/MediaBrowser.Model/DTO/ApiBaseItem.cs @@ -20,14 +20,14 @@ namespace MediaBrowser.Model.DTO /// /// This is the full return object when requesting an Item /// - public class BaseItemWrapper - where T : BaseItem + public class BaseItemContainer + where TItemType : BaseItem { - public T Item { get; set; } + public TItemType Item { get; set; } public UserItemData UserItemData { get; set; } - public IEnumerable> Children { get; set; } + public IEnumerable> Children { get; set; } public bool IsFolder { get; set; } @@ -45,7 +45,8 @@ namespace MediaBrowser.Model.DTO return Type.Equals(type, StringComparison.OrdinalIgnoreCase); } - public IEnumerable People { get; set; } + public IEnumerable People { get; set; } + public IEnumerable Studios { get; set; } /// /// If the item does not have a logo, this will hold the Id of the Parent that has one. @@ -60,7 +61,7 @@ namespace MediaBrowser.Model.DTO /// /// This is strictly for convenience so the UI's don't have to use the verbose generic syntax of BaseItemWrapper /// - public class ApiBaseItemWrapper : BaseItemWrapper + public class ApiBaseItemContainer : BaseItemContainer { } } diff --git a/MediaBrowser.Model/DTO/CategoryInfo.cs b/MediaBrowser.Model/DTO/CategoryInfo.cs deleted file mode 100644 index e6b2aeafb0..0000000000 --- a/MediaBrowser.Model/DTO/CategoryInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ - -namespace MediaBrowser.Model.DTO -{ - /// - /// This is a stub class used by the api to get IBN types along with their item counts - /// - public class CategoryInfo - { - /// - /// The actual genre, year, studio, etc - /// - public T Item { get; set; } - - /// - /// The number of items that have the genre, year, studio, etc - /// - public int ItemCount { get; set; } - } -} diff --git a/MediaBrowser.Model/DTO/IBNItem.cs b/MediaBrowser.Model/DTO/IBNItem.cs new file mode 100644 index 0000000000..8a0620767f --- /dev/null +++ b/MediaBrowser.Model/DTO/IBNItem.cs @@ -0,0 +1,38 @@ +using MediaBrowser.Model.Entities; + +namespace MediaBrowser.Model.DTO +{ + /// + /// This is a stub class used by the api to get IBN types along with their item counts + /// + public class IBNItem + { + /// + /// The actual genre, year, studio, etc + /// + public T Item { get; set; } + + /// + /// The number of items that have the genre, year, studio, etc + /// + public int BaseItemCount { get; set; } + } + + /// + /// This is used by BaseItemContainer + /// + public class BaseItemPerson + { + public PersonInfo PersonInfo { get; set; } + public string PrimaryImagePath { get; set; } + } + + /// + /// This is used by BaseItemContainer + /// + public class BaseItemStudio + { + public string Name { get; set; } + public string PrimaryImagePath { get; set; } + } +} diff --git a/MediaBrowser.Model/Entities/Person.cs b/MediaBrowser.Model/Entities/Person.cs index 690a2de857..e85f8a9050 100644 --- a/MediaBrowser.Model/Entities/Person.cs +++ b/MediaBrowser.Model/Entities/Person.cs @@ -6,7 +6,6 @@ namespace MediaBrowser.Model.Entities /// public class Person : BaseEntity { - public PersonType PersonType { get; set; } } /// diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj index dd9034ed56..14c7843edf 100644 --- a/MediaBrowser.Model/MediaBrowser.Model.csproj +++ b/MediaBrowser.Model/MediaBrowser.Model.csproj @@ -32,12 +32,11 @@ 4 - - + diff --git a/MediaBrowser.Model/Users/User.cs b/MediaBrowser.Model/Users/User.cs index 63698dc857..85776fb8b8 100644 --- a/MediaBrowser.Model/Users/User.cs +++ b/MediaBrowser.Model/Users/User.cs @@ -10,5 +10,12 @@ namespace MediaBrowser.Model.Users private Dictionary _ItemData = new Dictionary(); public Dictionary ItemData { get { return _ItemData; } set { _ItemData = value; } } + + public int RecentItemDays { get; set; } + + public User() + { + RecentItemDays = 14; + } } } -- cgit v1.2.3 From ed018a8bea89f4a19dbfca2e21eb7207df2db332 Mon Sep 17 00:00:00 2001 From: LukePulverenti Luke Pulverenti luke pulverenti Date: Fri, 17 Aug 2012 13:37:26 -0400 Subject: Moved some logic into domain entities, which is possible now that we're embracing DTO's --- MediaBrowser.Api/ApiService.cs | 7 +- MediaBrowser.Api/HttpHandlers/GenresHandler.cs | 5 +- MediaBrowser.Api/HttpHandlers/ItemListHandler.cs | 17 ++- MediaBrowser.Api/HttpHandlers/StudiosHandler.cs | 7 +- MediaBrowser.Api/HttpHandlers/YearsHandler.cs | 5 +- MediaBrowser.Controller/Kernel.cs | 163 +---------------------- MediaBrowser.Model/Entities/BaseItem.cs | 9 ++ MediaBrowser.Model/Entities/Folder.cs | 121 +++++++++++++++++ MediaBrowser.Model/Users/User.cs | 13 ++ 9 files changed, 177 insertions(+), 170 deletions(-) (limited to 'MediaBrowser.Api/HttpHandlers/StudiosHandler.cs') diff --git a/MediaBrowser.Api/ApiService.cs b/MediaBrowser.Api/ApiService.cs index 25a7ff9ec1..5a787c0e42 100644 --- a/MediaBrowser.Api/ApiService.cs +++ b/MediaBrowser.Api/ApiService.cs @@ -6,6 +6,7 @@ using MediaBrowser.Common.Configuration; using MediaBrowser.Controller; using MediaBrowser.Model.DTO; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Users; namespace MediaBrowser.Api { @@ -26,10 +27,12 @@ namespace MediaBrowser.Api /// public static BaseItemContainer GetSerializationObject(BaseItem item, bool includeChildren, Guid userId) { + User user = Kernel.Instance.Users.First(u => u.Id == userId); + BaseItemContainer wrapper = new BaseItemContainer() { Item = item, - UserItemData = Kernel.Instance.GetUserItemData(userId, item.Id), + UserItemData = user.GetItemData(item.Id), Type = item.GetType().Name, IsFolder = (item is Folder) }; @@ -57,7 +60,7 @@ namespace MediaBrowser.Api if (folder != null) { - wrapper.Children = Kernel.Instance.GetParentalAllowedChildren(folder, userId).Select(c => GetSerializationObject(c, false, userId)); + wrapper.Children = folder.GetParentalAllowedChildren(user).Select(c => GetSerializationObject(c, false, userId)); } // Attach People by transforming them into BaseItemPerson (DTO) diff --git a/MediaBrowser.Api/HttpHandlers/GenresHandler.cs b/MediaBrowser.Api/HttpHandlers/GenresHandler.cs index 902871fa11..dd20d2e426 100644 --- a/MediaBrowser.Api/HttpHandlers/GenresHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/GenresHandler.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; +using System.Linq; using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Controller; using MediaBrowser.Model.DTO; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Users; namespace MediaBrowser.Api.HttpHandlers { @@ -13,8 +15,9 @@ namespace MediaBrowser.Api.HttpHandlers { Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder; Guid userId = Guid.Parse(QueryString["userid"]); + User user = Kernel.Instance.Users.First(u => u.Id == userId); - return Kernel.Instance.GetAllGenres(parent, userId); + return Kernel.Instance.GetAllGenres(parent, user); } } } diff --git a/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs b/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs index b3d85687fe..b4c13540c8 100644 --- a/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/ItemListHandler.cs @@ -5,6 +5,7 @@ using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Controller; using MediaBrowser.Model.DTO; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Users; namespace MediaBrowser.Api.HttpHandlers { @@ -24,34 +25,36 @@ namespace MediaBrowser.Api.HttpHandlers get { Folder parent = ApiService.GetItemById(ItemId) as Folder; + + User user = Kernel.Instance.Users.First(u => u.Id == UserId); if (ListType.Equals("inprogressitems", StringComparison.OrdinalIgnoreCase)) { - return Kernel.Instance.GetInProgressItems(parent, UserId); + return parent.GetInProgressItems(user); } else if (ListType.Equals("recentlyaddeditems", StringComparison.OrdinalIgnoreCase)) { - return Kernel.Instance.GetRecentlyAddedItems(parent, UserId); + return parent.GetRecentlyAddedItems(user); } else if (ListType.Equals("recentlyaddedunplayeditems", StringComparison.OrdinalIgnoreCase)) { - return Kernel.Instance.GetRecentlyAddedUnplayedItems(parent, UserId); + return parent.GetRecentlyAddedUnplayedItems(user); } else if (ListType.Equals("itemswithgenre", StringComparison.OrdinalIgnoreCase)) { - return Kernel.Instance.GetItemsWithGenre(parent, QueryString["name"], UserId); + return parent.GetItemsWithGenre(QueryString["name"], user); } else if (ListType.Equals("itemswithyear", StringComparison.OrdinalIgnoreCase)) { - return Kernel.Instance.GetItemsWithYear(parent, int.Parse(QueryString["year"]), UserId); + return parent.GetItemsWithYear(int.Parse(QueryString["year"]), user); } else if (ListType.Equals("itemswithstudio", StringComparison.OrdinalIgnoreCase)) { - return Kernel.Instance.GetItemsWithStudio(parent, QueryString["name"], UserId); + return parent.GetItemsWithStudio(QueryString["name"], user); } else if (ListType.Equals("itemswithperson", StringComparison.OrdinalIgnoreCase)) { - return Kernel.Instance.GetItemsWithPerson(parent, QueryString["name"], UserId); + return parent.GetItemsWithPerson(QueryString["name"], null, user); } throw new InvalidOperationException(); diff --git a/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs b/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs index b33988b3ec..ffd69006d3 100644 --- a/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; +using System.Linq; using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Controller; using MediaBrowser.Model.DTO; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Users; namespace MediaBrowser.Api.HttpHandlers { @@ -13,8 +15,9 @@ namespace MediaBrowser.Api.HttpHandlers { Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder; Guid userId = Guid.Parse(QueryString["userid"]); - - return Kernel.Instance.GetAllStudios(parent, userId); + User user = Kernel.Instance.Users.First(u => u.Id == userId); + + return Kernel.Instance.GetAllStudios(parent, user); } } } diff --git a/MediaBrowser.Api/HttpHandlers/YearsHandler.cs b/MediaBrowser.Api/HttpHandlers/YearsHandler.cs index 8a58a2a19d..801244b0da 100644 --- a/MediaBrowser.Api/HttpHandlers/YearsHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/YearsHandler.cs @@ -1,9 +1,11 @@ using System; using System.Collections.Generic; +using System.Linq; using MediaBrowser.Common.Net.Handlers; using MediaBrowser.Controller; using MediaBrowser.Model.DTO; using MediaBrowser.Model.Entities; +using MediaBrowser.Model.Users; namespace MediaBrowser.Api.HttpHandlers { @@ -13,8 +15,9 @@ namespace MediaBrowser.Api.HttpHandlers { Folder parent = ApiService.GetItemById(QueryString["id"]) as Folder; Guid userId = Guid.Parse(QueryString["userid"]); + User user = Kernel.Instance.Users.First(u => u.Id == userId); - return Kernel.Instance.GetAllYears(parent, userId); + return Kernel.Instance.GetAllYears(parent, user); } } } diff --git a/MediaBrowser.Controller/Kernel.cs b/MediaBrowser.Controller/Kernel.cs index 375b11a593..c11a407509 100644 --- a/MediaBrowser.Controller/Kernel.cs +++ b/MediaBrowser.Controller/Kernel.cs @@ -197,167 +197,16 @@ namespace MediaBrowser.Controller return RootFolder.FindById(id); } - /// - /// Determines if an item is allowed for a given user - /// - public bool IsParentalAllowed(BaseItem item, Guid userId) - { - // not yet implemented - return true; - } - - /// - /// Gets allowed children of an item - /// - public IEnumerable GetParentalAllowedChildren(Folder folder, Guid userId) - { - return folder.Children.Where(i => IsParentalAllowed(i, userId)); - } - - /// - /// Gets allowed recursive children of an item - /// - public IEnumerable GetParentalAllowedRecursiveChildren(Folder folder, Guid userId) - { - foreach (var item in GetParentalAllowedChildren(folder, userId)) - { - yield return item; - - var subFolder = item as Folder; - - if (subFolder != null) - { - foreach (var subitem in GetParentalAllowedRecursiveChildren(subFolder, userId)) - { - yield return subitem; - } - } - } - } - - /// - /// Gets user data for an item, if there is any - /// - public UserItemData GetUserItemData(Guid userId, Guid itemId) - { - User user = Users.First(u => u.Id == userId); - - if (user.ItemData.ContainsKey(itemId)) - { - return user.ItemData[itemId]; - } - - return null; - } - - /// - /// Gets all recently added items (recursive) within a folder, based on configuration and parental settings - /// - public IEnumerable GetRecentlyAddedItems(Folder parent, Guid userId) - { - DateTime now = DateTime.Now; - - User user = Users.First(u => u.Id == userId); - - return GetParentalAllowedRecursiveChildren(parent, userId).Where(i => !(i is Folder) && (now - i.DateCreated).TotalDays < user.RecentItemDays); - } - - /// - /// Gets all recently added unplayed items (recursive) within a folder, based on configuration and parental settings - /// - public IEnumerable GetRecentlyAddedUnplayedItems(Folder parent, Guid userId) - { - return GetRecentlyAddedItems(parent, userId).Where(i => - { - var userdata = GetUserItemData(userId, i.Id); - - return userdata == null || userdata.PlayCount == 0; - }); - } - - /// - /// Gets all in-progress items (recursive) within a folder - /// - public IEnumerable GetInProgressItems(Folder parent, Guid userId) - { - return GetParentalAllowedRecursiveChildren(parent, userId).Where(i => - { - if (i is Folder) - { - return false; - } - - var userdata = GetUserItemData(userId, i.Id); - - return userdata != null && userdata.PlaybackPosition.Ticks > 0; - }); - } - - /// - /// Finds all recursive items within a top-level parent that contain the given studio and are allowed for the current user - /// - public IEnumerable GetItemsWithStudio(Folder parent, string studio, Guid userId) - { - return GetParentalAllowedRecursiveChildren(parent, userId).Where(f => f.Studios != null && f.Studios.Any(s => s.Equals(studio, StringComparison.OrdinalIgnoreCase))); - } - - /// - /// Finds all recursive items within a top-level parent that contain the given person and are allowed for the current user - /// - /// Specify this to limit results to a specific PersonType - public IEnumerable GetItemsWithPerson(Folder parent, string person, PersonType? personType, Guid userId) - { - return GetParentalAllowedRecursiveChildren(parent, userId).Where(c => - { - if (c.People != null) - { - if (personType.HasValue) - { - return c.People.Any(p => p.Name.Equals(person, StringComparison.OrdinalIgnoreCase) && p.PersonType == personType.Value); - } - else - { - return c.People.Any(p => p.Name.Equals(person, StringComparison.OrdinalIgnoreCase)); - } - } - - return false; - }); - } - /// - /// Finds all recursive items within a top-level parent that contain the given genre and are allowed for the current user - /// - public IEnumerable GetItemsWithGenre(Folder parent, string genre, Guid userId) - { - return GetParentalAllowedRecursiveChildren(parent, userId).Where(f => f.Genres != null && f.Genres.Any(s => s.Equals(genre, StringComparison.OrdinalIgnoreCase))); - } - - /// - /// Finds all recursive items within a top-level parent that contain the given year and are allowed for the current user - /// - public IEnumerable GetItemsWithYear(Folder parent, int year, Guid userId) - { - return GetParentalAllowedRecursiveChildren(parent, userId).Where(f => f.ProductionYear.HasValue && f.ProductionYear == year); - } - - /// - /// Finds all recursive items within a top-level parent that contain the given person and are allowed for the current user - /// - public IEnumerable GetItemsWithPerson(Folder parent, string personName, Guid userId) - { - return GetParentalAllowedRecursiveChildren(parent, userId).Where(f => f.People != null && f.People.Any(s => s.Name.Equals(personName, StringComparison.OrdinalIgnoreCase))); - } - /// /// Gets all years from all recursive children of a folder /// The CategoryInfo class is used to keep track of the number of times each year appears /// - public IEnumerable> GetAllYears(Folder parent, Guid userId) + public IEnumerable> GetAllYears(Folder parent, User user) { Dictionary data = new Dictionary(); // Get all the allowed recursive children - IEnumerable allItems = Kernel.Instance.GetParentalAllowedRecursiveChildren(parent, userId); + IEnumerable allItems = parent.GetParentalAllowedRecursiveChildren(user); foreach (var item in allItems) { @@ -403,12 +252,12 @@ namespace MediaBrowser.Controller /// Gets all studios from all recursive children of a folder /// The CategoryInfo class is used to keep track of the number of times each studio appears /// - public IEnumerable> GetAllStudios(Folder parent, Guid userId) + public IEnumerable> GetAllStudios(Folder parent, User user) { Dictionary data = new Dictionary(); // Get all the allowed recursive children - IEnumerable allItems = Kernel.Instance.GetParentalAllowedRecursiveChildren(parent, userId); + IEnumerable allItems = parent.GetParentalAllowedRecursiveChildren(user); foreach (var item in allItems) { @@ -457,12 +306,12 @@ namespace MediaBrowser.Controller /// Gets all genres from all recursive children of a folder /// The CategoryInfo class is used to keep track of the number of times each genres appears /// - public IEnumerable> GetAllGenres(Folder parent, Guid userId) + public IEnumerable> GetAllGenres(Folder parent, User user) { Dictionary data = new Dictionary(); // Get all the allowed recursive children - IEnumerable allItems = Kernel.Instance.GetParentalAllowedRecursiveChildren(parent, userId); + IEnumerable allItems = parent.GetParentalAllowedRecursiveChildren(user); foreach (var item in allItems) { diff --git a/MediaBrowser.Model/Entities/BaseItem.cs b/MediaBrowser.Model/Entities/BaseItem.cs index d2745e460f..c9d5b936b6 100644 --- a/MediaBrowser.Model/Entities/BaseItem.cs +++ b/MediaBrowser.Model/Entities/BaseItem.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Runtime.Serialization; +using MediaBrowser.Model.Users; namespace MediaBrowser.Model.Entities { @@ -101,5 +102,13 @@ namespace MediaBrowser.Model.Entities { SetProviderId(provider.ToString(), value); } + + /// + /// Determines if a given user has access to this item + /// + internal bool IsParentalAllowed(User user) + { + return true; + } } } diff --git a/MediaBrowser.Model/Entities/Folder.cs b/MediaBrowser.Model/Entities/Folder.cs index 293d7a9909..98f1d8229a 100644 --- a/MediaBrowser.Model/Entities/Folder.cs +++ b/MediaBrowser.Model/Entities/Folder.cs @@ -1,5 +1,8 @@ using System; +using System.Collections.Generic; +using System.Linq; using System.Runtime.Serialization; +using MediaBrowser.Model.Users; namespace MediaBrowser.Model.Entities { @@ -18,6 +21,124 @@ namespace MediaBrowser.Model.Entities [IgnoreDataMember] public BaseItem[] Children { get; set; } + /// + /// Gets allowed children of an item + /// + public IEnumerable GetParentalAllowedChildren(User user) + { + return Children.Where(c => c.IsParentalAllowed(user)); + } + + /// + /// Gets allowed recursive children of an item + /// + public IEnumerable GetParentalAllowedRecursiveChildren(User user) + { + foreach (var item in GetParentalAllowedChildren(user)) + { + yield return item; + + var subFolder = item as Folder; + + if (subFolder != null) + { + foreach (var subitem in subFolder.GetParentalAllowedRecursiveChildren(user)) + { + yield return subitem; + } + } + } + } + + /// + /// Finds all recursive items within a top-level parent that contain the given genre and are allowed for the current user + /// + public IEnumerable GetItemsWithGenre(string genre, User user) + { + return GetParentalAllowedRecursiveChildren(user).Where(f => f.Genres != null && f.Genres.Any(s => s.Equals(genre, StringComparison.OrdinalIgnoreCase))); + } + + /// + /// Finds all recursive items within a top-level parent that contain the given year and are allowed for the current user + /// + public IEnumerable GetItemsWithYear(int year, User user) + { + return GetParentalAllowedRecursiveChildren(user).Where(f => f.ProductionYear.HasValue && f.ProductionYear == year); + } + + /// + /// Finds all recursive items within a top-level parent that contain the given studio and are allowed for the current user + /// + public IEnumerable GetItemsWithStudio(string studio, User user) + { + return GetParentalAllowedRecursiveChildren(user).Where(f => f.Studios != null && f.Studios.Any(s => s.Equals(studio, StringComparison.OrdinalIgnoreCase))); + } + + /// + /// Finds all recursive items within a top-level parent that contain the given person and are allowed for the current user + /// + /// Specify this to limit results to a specific PersonType + public IEnumerable GetItemsWithPerson(string person, PersonType? personType, User user) + { + return GetParentalAllowedRecursiveChildren(user).Where(c => + { + if (c.People != null) + { + if (personType.HasValue) + { + return c.People.Any(p => p.Name.Equals(person, StringComparison.OrdinalIgnoreCase) && p.PersonType == personType.Value); + } + else + { + return c.People.Any(p => p.Name.Equals(person, StringComparison.OrdinalIgnoreCase)); + } + } + + return false; + }); + } + + /// + /// Gets all recently added items (recursive) within a folder, based on configuration and parental settings + /// + public IEnumerable GetRecentlyAddedItems(User user) + { + DateTime now = DateTime.Now; + + return GetParentalAllowedRecursiveChildren(user).Where(i => !(i is Folder) && (now - i.DateCreated).TotalDays < user.RecentItemDays); + } + + /// + /// Gets all recently added unplayed items (recursive) within a folder, based on configuration and parental settings + /// + public IEnumerable GetRecentlyAddedUnplayedItems(User user) + { + return GetRecentlyAddedItems(user).Where(i => + { + var userdata = user.GetItemData(i.Id); + + return userdata == null || userdata.PlayCount == 0; + }); + } + + /// + /// Gets all in-progress items (recursive) within a folder + /// + public IEnumerable GetInProgressItems(User user) + { + return GetParentalAllowedRecursiveChildren(user).Where(i => + { + if (i is Folder) + { + return false; + } + + var userdata = user.GetItemData(i.Id); + + return userdata != null && userdata.PlaybackPosition.Ticks > 0; + }); + } + /// /// Finds an item by ID, recursively /// diff --git a/MediaBrowser.Model/Users/User.cs b/MediaBrowser.Model/Users/User.cs index 85776fb8b8..dcef153c59 100644 --- a/MediaBrowser.Model/Users/User.cs +++ b/MediaBrowser.Model/Users/User.cs @@ -17,5 +17,18 @@ namespace MediaBrowser.Model.Users { RecentItemDays = 14; } + + /// + /// Gets user data for an item, if there is any + /// + public UserItemData GetItemData(Guid itemId) + { + if (ItemData.ContainsKey(itemId)) + { + return ItemData[itemId]; + } + + return null; + } } } -- cgit v1.2.3 From f32f000298114231f114f41b7c7c4534a0300de2 Mon Sep 17 00:00:00 2001 From: LukePulverenti Luke Pulverenti luke pulverenti Date: Fri, 17 Aug 2012 15:07:21 -0400 Subject: Removed more kernel methods and deprecated the Configuration and HtmlBrowser projects. They've both been replaced by the new WebDashboard project. --- MediaBrowser.Api/HttpHandlers/GenresHandler.cs | 56 +- MediaBrowser.Api/HttpHandlers/StudiosHandler.cs | 56 +- MediaBrowser.Api/HttpHandlers/YearsHandler.cs | 53 +- .../MediaBrowser.Configuration.csproj | 78 - MediaBrowser.Configuration/Plugin.cs | 15 - .../Properties/AssemblyInfo.cs | 36 - MediaBrowser.Configuration/packages.config | 4 - MediaBrowser.Controller/Kernel.cs | 160 - .../Handlers/EmbeddedResourceHandler.cs | 22 - .../Html/apple-touch-icon-114x114.png | Bin 9997 -> 0 bytes .../Html/applesplashscreen.png | Bin 2435 -> 0 bytes MediaBrowser.HtmlBrowser/Html/favicon.ico | Bin 1150 -> 0 bytes MediaBrowser.HtmlBrowser/Html/index.html | 36 - .../Html/thirdparty/jquery-1.7.1.min.js | 4 - .../jquery.mobile.iconpack/images/ajax-loader.png | Bin 366 -> 0 bytes .../images/icons-18-black-pack.png | Bin 11352 -> 0 bytes .../images/icons-18-white-pack.png | Bin 12001 -> 0 bytes .../images/icons-36-black-pack.png | Bin 15978 -> 0 bytes .../images/icons-36-white-pack.png | Bin 17333 -> 0 bytes .../jqm-icon-pack-1.1.1-original.css | 129 - .../jquery.mobile110/images/ajax-loader.gif | Bin 7825 -> 0 bytes .../jquery.mobile110/images/ajax-loader.png | Bin 340 -> 0 bytes .../jquery.mobile110/images/icons-18-black.png | Bin 1767 -> 0 bytes .../jquery.mobile110/images/icons-18-white.png | Bin 1806 -> 0 bytes .../jquery.mobile110/images/icons-36-black.png | Bin 3611 -> 0 bytes .../jquery.mobile110/images/icons-36-white.png | Bin 3648 -> 0 bytes .../jquery.mobile110/jquery.mobile-1.1.0.css | 2053 ------ .../jquery.mobile110/jquery.mobile-1.1.0.js | 7551 -------------------- .../jquery.mobile110/jquery.mobile-1.1.0.min.css | 2 - .../jquery.mobile110/jquery.mobile-1.1.0.min.js | 177 - .../jquery.mobile.structure-1.1.0.css | 946 --- .../jquery.mobile.structure-1.1.0.min.css | 2 - .../jquery.mobile110/jquery.mobile.theme-1.1.0.css | 1167 --- .../jquery.mobile.theme-1.1.0.min.css | 2 - .../MediaBrowser.HtmlBrowser.csproj | 111 - MediaBrowser.HtmlBrowser/Plugin.cs | 34 - .../Properties/AssemblyInfo.cs | 36 - MediaBrowser.HtmlBrowser/packages.config | 4 - .../MediaBrowser.WebDashboard.csproj | 67 + MediaBrowser.WebDashboard/Plugin.cs | 15 + .../Properties/AssemblyInfo.cs | 36 + MediaBrowser.sln | 18 +- 42 files changed, 286 insertions(+), 12584 deletions(-) delete mode 100644 MediaBrowser.Configuration/MediaBrowser.Configuration.csproj delete mode 100644 MediaBrowser.Configuration/Plugin.cs delete mode 100644 MediaBrowser.Configuration/Properties/AssemblyInfo.cs delete mode 100644 MediaBrowser.Configuration/packages.config delete mode 100644 MediaBrowser.HtmlBrowser/Handlers/EmbeddedResourceHandler.cs delete mode 100644 MediaBrowser.HtmlBrowser/Html/apple-touch-icon-114x114.png delete mode 100644 MediaBrowser.HtmlBrowser/Html/applesplashscreen.png delete mode 100644 MediaBrowser.HtmlBrowser/Html/favicon.ico delete mode 100644 MediaBrowser.HtmlBrowser/Html/index.html delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery-1.7.1.min.js delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/ajax-loader.png delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/icons-18-black-pack.png delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/icons-18-white-pack.png delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/icons-36-black-pack.png delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/icons-36-white-pack.png delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/jqm-icon-pack-1.1.1-original.css delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/ajax-loader.gif delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/ajax-loader.png delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/icons-18-black.png delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/icons-18-white.png delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/icons-36-black.png delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/icons-36-white.png delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/jquery.mobile-1.1.0.css delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/jquery.mobile-1.1.0.js delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/jquery.mobile-1.1.0.min.css delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/jquery.mobile-1.1.0.min.js delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/jquery.mobile.structure-1.1.0.css delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/jquery.mobile.structure-1.1.0.min.css delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/jquery.mobile.theme-1.1.0.css delete mode 100644 MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/jquery.mobile.theme-1.1.0.min.css delete mode 100644 MediaBrowser.HtmlBrowser/MediaBrowser.HtmlBrowser.csproj delete mode 100644 MediaBrowser.HtmlBrowser/Plugin.cs delete mode 100644 MediaBrowser.HtmlBrowser/Properties/AssemblyInfo.cs delete mode 100644 MediaBrowser.HtmlBrowser/packages.config create mode 100644 MediaBrowser.WebDashboard/MediaBrowser.WebDashboard.csproj create mode 100644 MediaBrowser.WebDashboard/Plugin.cs create mode 100644 MediaBrowser.WebDashboard/Properties/AssemblyInfo.cs (limited to 'MediaBrowser.Api/HttpHandlers/StudiosHandler.cs') diff --git a/MediaBrowser.Api/HttpHandlers/GenresHandler.cs b/MediaBrowser.Api/HttpHandlers/GenresHandler.cs index dd20d2e426..f7d259e456 100644 --- a/MediaBrowser.Api/HttpHandlers/GenresHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/GenresHandler.cs @@ -17,7 +17,61 @@ namespace MediaBrowser.Api.HttpHandlers Guid userId = Guid.Parse(QueryString["userid"]); User user = Kernel.Instance.Users.First(u => u.Id == userId); - return Kernel.Instance.GetAllGenres(parent, user); + return GetAllGenres(parent, user); + } + + /// + /// Gets all genres from all recursive children of a folder + /// The CategoryInfo class is used to keep track of the number of times each genres appears + /// + public IEnumerable> GetAllGenres(Folder parent, User user) + { + Dictionary data = new Dictionary(); + + // Get all the allowed recursive children + IEnumerable allItems = parent.GetParentalAllowedRecursiveChildren(user); + + foreach (var item in allItems) + { + // Add each genre from the item to the data dictionary + // If the genre already exists, increment the count + if (item.Genres == null) + { + continue; + } + + foreach (string val in item.Genres) + { + if (!data.ContainsKey(val)) + { + data.Add(val, 1); + } + else + { + data[val]++; + } + } + } + + // Now go through the dictionary and create a Category for each genre + List> list = new List>(); + + foreach (string key in data.Keys) + { + // Get the original entity so that we can also supply the PrimaryImagePath + Genre entity = Kernel.Instance.ItemController.GetGenre(key); + + if (entity != null) + { + list.Add(new IBNItem() + { + Item = entity, + BaseItemCount = data[key] + }); + } + } + + return list; } } } diff --git a/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs b/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs index ffd69006d3..54c33416dc 100644 --- a/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/StudiosHandler.cs @@ -17,7 +17,61 @@ namespace MediaBrowser.Api.HttpHandlers Guid userId = Guid.Parse(QueryString["userid"]); User user = Kernel.Instance.Users.First(u => u.Id == userId); - return Kernel.Instance.GetAllStudios(parent, user); + return GetAllStudios(parent, user); + } + + /// + /// Gets all studios from all recursive children of a folder + /// The CategoryInfo class is used to keep track of the number of times each studio appears + /// + private IEnumerable> GetAllStudios(Folder parent, User user) + { + Dictionary data = new Dictionary(); + + // Get all the allowed recursive children + IEnumerable allItems = parent.GetParentalAllowedRecursiveChildren(user); + + foreach (var item in allItems) + { + // Add each studio from the item to the data dictionary + // If the studio already exists, increment the count + if (item.Studios == null) + { + continue; + } + + foreach (string val in item.Studios) + { + if (!data.ContainsKey(val)) + { + data.Add(val, 1); + } + else + { + data[val]++; + } + } + } + + // Now go through the dictionary and create a Category for each studio + List> list = new List>(); + + foreach (string key in data.Keys) + { + // Get the original entity so that we can also supply the PrimaryImagePath + Studio entity = Kernel.Instance.ItemController.GetStudio(key); + + if (entity != null) + { + list.Add(new IBNItem() + { + Item = entity, + BaseItemCount = data[key] + }); + } + } + + return list; } } } diff --git a/MediaBrowser.Api/HttpHandlers/YearsHandler.cs b/MediaBrowser.Api/HttpHandlers/YearsHandler.cs index 801244b0da..071b980a7d 100644 --- a/MediaBrowser.Api/HttpHandlers/YearsHandler.cs +++ b/MediaBrowser.Api/HttpHandlers/YearsHandler.cs @@ -17,7 +17,58 @@ namespace MediaBrowser.Api.HttpHandlers Guid userId = Guid.Parse(QueryString["userid"]); User user = Kernel.Instance.Users.First(u => u.Id == userId); - return Kernel.Instance.GetAllYears(parent, user); + return GetAllYears(parent, user); + } + + /// + /// Gets all years from all recursive children of a folder + /// The CategoryInfo class is used to keep track of the number of times each year appears + /// + private IEnumerable> GetAllYears(Folder parent, User user) + { + Dictionary data = new Dictionary(); + + // Get all the allowed recursive children + IEnumerable allItems = parent.GetParentalAllowedRecursiveChildren(user); + + foreach (var item in allItems) + { + // Add the year from the item to the data dictionary + // If the year already exists, increment the count + if (item.ProductionYear == null) + { + continue; + } + + if (!data.ContainsKey(item.ProductionYear.Value)) + { + data.Add(item.ProductionYear.Value, 1); + } + else + { + data[item.ProductionYear.Value]++; + } + } + + // Now go through the dictionary and create a Category for each studio + List> list = new List>(); + + foreach (int key in data.Keys) + { + // Get the original entity so that we can also supply the PrimaryImagePath + Year entity = Kernel.Instance.ItemController.GetYear(key); + + if (entity != null) + { + list.Add(new IBNItem() + { + Item = entity, + BaseItemCount = data[key] + }); + } + } + + return list; } } } diff --git a/MediaBrowser.Configuration/MediaBrowser.Configuration.csproj b/MediaBrowser.Configuration/MediaBrowser.Configuration.csproj deleted file mode 100644 index ff3cd25577..0000000000 --- a/MediaBrowser.Configuration/MediaBrowser.Configuration.csproj +++ /dev/null @@ -1,78 +0,0 @@ - - - - - Debug - AnyCPU - {933CC468-E22B-48D8-8BCA-2E026F411CA2} - Library - Properties - MediaBrowser.Configuration - MediaBrowser.Configuration - v4.5 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - False - ..\packages\Rx-Main.1.0.11226\lib\Net4\System.Reactive.dll - - - - - - - - - - - - - - {9142eefa-7570-41e1-bfcc-468bb571af2f} - MediaBrowser.Common - - - {17e1f4e6-8abd-4fe5-9ecf-43d4b6087ba2} - MediaBrowser.Controller - - - {7eeeb4bb-f3e8-48fc-b4c5-70f0fff8329b} - MediaBrowser.Model - - - - - - - - xcopy "$(TargetPath)" "$(SolutionDir)\ProgramData\Plugins\$(ProjectName)\" /y - - - \ No newline at end of file diff --git a/MediaBrowser.Configuration/Plugin.cs b/MediaBrowser.Configuration/Plugin.cs deleted file mode 100644 index ffa3e38d0d..0000000000 --- a/MediaBrowser.Configuration/Plugin.cs +++ /dev/null @@ -1,15 +0,0 @@ -using System.ComponentModel.Composition; -using MediaBrowser.Common.Plugins; -using MediaBrowser.Model.Plugins; - -namespace MediaBrowser.Configuration -{ - [Export(typeof(BasePlugin))] - public class Plugin : BaseGenericPlugin - { - public override string Name - { - get { return "Web-based Configuration"; } - } - } -} diff --git a/MediaBrowser.Configuration/Properties/AssemblyInfo.cs b/MediaBrowser.Configuration/Properties/AssemblyInfo.cs deleted file mode 100644 index 919388d51d..0000000000 --- a/MediaBrowser.Configuration/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("MediaBrowser.Configuration")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("MediaBrowser.Configuration")] -[assembly: AssemblyCopyright("Copyright © 2012")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("c109d2b1-2368-43a2-bed1-ec2cfb33e741")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/MediaBrowser.Configuration/packages.config b/MediaBrowser.Configuration/packages.config deleted file mode 100644 index 47102a263f..0000000000 --- a/MediaBrowser.Configuration/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/MediaBrowser.Controller/Kernel.cs b/MediaBrowser.Controller/Kernel.cs index c11a407509..9bf7021e14 100644 --- a/MediaBrowser.Controller/Kernel.cs +++ b/MediaBrowser.Controller/Kernel.cs @@ -12,7 +12,6 @@ using MediaBrowser.Controller.Events; using MediaBrowser.Controller.IO; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Resolvers; -using MediaBrowser.Model.DTO; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Progress; using MediaBrowser.Model.Users; @@ -197,165 +196,6 @@ namespace MediaBrowser.Controller return RootFolder.FindById(id); } - /// - /// Gets all years from all recursive children of a folder - /// The CategoryInfo class is used to keep track of the number of times each year appears - /// - public IEnumerable> GetAllYears(Folder parent, User user) - { - Dictionary data = new Dictionary(); - - // Get all the allowed recursive children - IEnumerable allItems = parent.GetParentalAllowedRecursiveChildren(user); - - foreach (var item in allItems) - { - // Add the year from the item to the data dictionary - // If the year already exists, increment the count - if (item.ProductionYear == null) - { - continue; - } - - if (!data.ContainsKey(item.ProductionYear.Value)) - { - data.Add(item.ProductionYear.Value, 1); - } - else - { - data[item.ProductionYear.Value]++; - } - } - - // Now go through the dictionary and create a Category for each studio - List> list = new List>(); - - foreach (int key in data.Keys) - { - // Get the original entity so that we can also supply the PrimaryImagePath - Year entity = Kernel.Instance.ItemController.GetYear(key); - - if (entity != null) - { - list.Add(new IBNItem() - { - Item = entity, - BaseItemCount = data[key] - }); - } - } - - return list; - } - - /// - /// Gets all studios from all recursive children of a folder - /// The CategoryInfo class is used to keep track of the number of times each studio appears - /// - public IEnumerable> GetAllStudios(Folder parent, User user) - { - Dictionary data = new Dictionary(); - - // Get all the allowed recursive children - IEnumerable allItems = parent.GetParentalAllowedRecursiveChildren(user); - - foreach (var item in allItems) - { - // Add each studio from the item to the data dictionary - // If the studio already exists, increment the count - if (item.Studios == null) - { - continue; - } - - foreach (string val in item.Studios) - { - if (!data.ContainsKey(val)) - { - data.Add(val, 1); - } - else - { - data[val]++; - } - } - } - - // Now go through the dictionary and create a Category for each studio - List> list = new List>(); - - foreach (string key in data.Keys) - { - // Get the original entity so that we can also supply the PrimaryImagePath - Studio entity = Kernel.Instance.ItemController.GetStudio(key); - - if (entity != null) - { - list.Add(new IBNItem() - { - Item = entity, - BaseItemCount = data[key] - }); - } - } - - return list; - } - - /// - /// Gets all genres from all recursive children of a folder - /// The CategoryInfo class is used to keep track of the number of times each genres appears - /// - public IEnumerable> GetAllGenres(Folder parent, User user) - { - Dictionary data = new Dictionary(); - - // Get all the allowed recursive children - IEnumerable allItems = parent.GetParentalAllowedRecursiveChildren(user); - - foreach (var item in allItems) - { - // Add each genre from the item to the data dictionary - // If the genre already exists, increment the count - if (item.Genres == null) - { - continue; - } - - foreach (string val in item.Genres) - { - if (!data.ContainsKey(val)) - { - data.Add(val, 1); - } - else - { - data[val]++; - } - } - } - - // Now go through the dictionary and create a Category for each genre - List> list = new List>(); - - foreach (string key in data.Keys) - { - // Get the original entity so that we can also supply the PrimaryImagePath - Genre entity = Kernel.Instance.ItemController.GetGenre(key); - - if (entity != null) - { - list.Add(new IBNItem() - { - Item = entity, - BaseItemCount = data[key] - }); - } - } - - return list; - } - /// /// Gets all users within the system /// diff --git a/MediaBrowser.HtmlBrowser/Handlers/EmbeddedResourceHandler.cs b/MediaBrowser.HtmlBrowser/Handlers/EmbeddedResourceHandler.cs deleted file mode 100644 index 8a118da2a2..0000000000 --- a/MediaBrowser.HtmlBrowser/Handlers/EmbeddedResourceHandler.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.IO; -using System.Reflection; -using MediaBrowser.Common.Net.Handlers; - -namespace MediaBrowser.HtmlBrowser.Handlers -{ - class EmbeddedResourceHandler : BaseEmbeddedResourceHandler - { - public EmbeddedResourceHandler(string resourcePath) - : base(resourcePath) - { - - } - - protected override Stream GetEmbeddedResourceStream() - { - string path = ResourcePath.Replace("/", "."); - - return Assembly.GetExecutingAssembly().GetManifestResourceStream("MediaBrowser.HtmlBrowser.Html." + path); - } - } -} diff --git a/MediaBrowser.HtmlBrowser/Html/apple-touch-icon-114x114.png b/MediaBrowser.HtmlBrowser/Html/apple-touch-icon-114x114.png deleted file mode 100644 index 9372be6bf4..0000000000 Binary files a/MediaBrowser.HtmlBrowser/Html/apple-touch-icon-114x114.png and /dev/null differ diff --git a/MediaBrowser.HtmlBrowser/Html/applesplashscreen.png b/MediaBrowser.HtmlBrowser/Html/applesplashscreen.png deleted file mode 100644 index cafb9c4463..0000000000 Binary files a/MediaBrowser.HtmlBrowser/Html/applesplashscreen.png and /dev/null differ diff --git a/MediaBrowser.HtmlBrowser/Html/favicon.ico b/MediaBrowser.HtmlBrowser/Html/favicon.ico deleted file mode 100644 index 40cdb1bae8..0000000000 Binary files a/MediaBrowser.HtmlBrowser/Html/favicon.ico and /dev/null differ diff --git a/MediaBrowser.HtmlBrowser/Html/index.html b/MediaBrowser.HtmlBrowser/Html/index.html deleted file mode 100644 index 7fcb778c1c..0000000000 --- a/MediaBrowser.HtmlBrowser/Html/index.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - Media Browser - - - - - - - - - - - -
-
-
-

- - Home - Setup -
-
- -
-
-
-
-
- - - - - - diff --git a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery-1.7.1.min.js b/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery-1.7.1.min.js deleted file mode 100644 index 198b3ff07d..0000000000 --- a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery-1.7.1.min.js +++ /dev/null @@ -1,4 +0,0 @@ -/*! jQuery v1.7.1 jquery.com | jquery.org/license */ -(function(a,b){function cy(a){return f.isWindow(a)?a:a.nodeType===9?a.defaultView||a.parentWindow:!1}function cv(a){if(!ck[a]){var b=c.body,d=f("<"+a+">").appendTo(b),e=d.css("display");d.remove();if(e==="none"||e===""){cl||(cl=c.createElement("iframe"),cl.frameBorder=cl.width=cl.height=0),b.appendChild(cl);if(!cm||!cl.createElement)cm=(cl.contentWindow||cl.contentDocument).document,cm.write((c.compatMode==="CSS1Compat"?"":"")+""),cm.close();d=cm.createElement(a),cm.body.appendChild(d),e=f.css(d,"display"),b.removeChild(cl)}ck[a]=e}return ck[a]}function cu(a,b){var c={};f.each(cq.concat.apply([],cq.slice(0,b)),function(){c[this]=a});return c}function ct(){cr=b}function cs(){setTimeout(ct,0);return cr=f.now()}function cj(){try{return new a.ActiveXObject("Microsoft.XMLHTTP")}catch(b){}}function ci(){try{return new a.XMLHttpRequest}catch(b){}}function cc(a,c){a.dataFilter&&(c=a.dataFilter(c,a.dataType));var d=a.dataTypes,e={},g,h,i=d.length,j,k=d[0],l,m,n,o,p;for(g=1;g0){if(c!=="border")for(;g=0===c})}function S(a){return!a||!a.parentNode||a.parentNode.nodeType===11}function K(){return!0}function J(){return!1}function n(a,b,c){var d=b+"defer",e=b+"queue",g=b+"mark",h=f._data(a,d);h&&(c==="queue"||!f._data(a,e))&&(c==="mark"||!f._data(a,g))&&setTimeout(function(){!f._data(a,e)&&!f._data(a,g)&&(f.removeData(a,d,!0),h.fire())},0)}function m(a){for(var b in a){if(b==="data"&&f.isEmptyObject(a[b]))continue;if(b!=="toJSON")return!1}return!0}function l(a,c,d){if(d===b&&a.nodeType===1){var e="data-"+c.replace(k,"-$1").toLowerCase();d=a.getAttribute(e);if(typeof d=="string"){try{d=d==="true"?!0:d==="false"?!1:d==="null"?null:f.isNumeric(d)?parseFloat(d):j.test(d)?f.parseJSON(d):d}catch(g){}f.data(a,c,d)}else d=b}return d}function h(a){var b=g[a]={},c,d;a=a.split(/\s+/);for(c=0,d=a.length;c)[^>]*$|#([\w\-]*)$)/,j=/\S/,k=/^\s+/,l=/\s+$/,m=/^<(\w+)\s*\/?>(?:<\/\1>)?$/,n=/^[\],:{}\s]*$/,o=/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,p=/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,q=/(?:^|:|,)(?:\s*\[)+/g,r=/(webkit)[ \/]([\w.]+)/,s=/(opera)(?:.*version)?[ \/]([\w.]+)/,t=/(msie) ([\w.]+)/,u=/(mozilla)(?:.*? rv:([\w.]+))?/,v=/-([a-z]|[0-9])/ig,w=/^-ms-/,x=function(a,b){return(b+"").toUpperCase()},y=d.userAgent,z,A,B,C=Object.prototype.toString,D=Object.prototype.hasOwnProperty,E=Array.prototype.push,F=Array.prototype.slice,G=String.prototype.trim,H=Array.prototype.indexOf,I={};e.fn=e.prototype={constructor:e,init:function(a,d,f){var g,h,j,k;if(!a)return this;if(a.nodeType){this.context=this[0]=a,this.length=1;return this}if(a==="body"&&!d&&c.body){this.context=c,this[0]=c.body,this.selector=a,this.length=1;return this}if(typeof a=="string"){a.charAt(0)!=="<"||a.charAt(a.length-1)!==">"||a.length<3?g=i.exec(a):g=[null,a,null];if(g&&(g[1]||!d)){if(g[1]){d=d instanceof e?d[0]:d,k=d?d.ownerDocument||d:c,j=m.exec(a),j?e.isPlainObject(d)?(a=[c.createElement(j[1])],e.fn.attr.call(a,d,!0)):a=[k.createElement(j[1])]:(j=e.buildFragment([g[1]],[k]),a=(j.cacheable?e.clone(j.fragment):j.fragment).childNodes);return e.merge(this,a)}h=c.getElementById(g[2]);if(h&&h.parentNode){if(h.id!==g[2])return f.find(a);this.length=1,this[0]=h}this.context=c,this.selector=a;return this}return!d||d.jquery?(d||f).find(a):this.constructor(d).find(a)}if(e.isFunction(a))return f.ready(a);a.selector!==b&&(this.selector=a.selector,this.context=a.context);return e.makeArray(a,this)},selector:"",jquery:"1.7.1",length:0,size:function(){return this.length},toArray:function(){return F.call(this,0)},get:function(a){return a==null?this.toArray():a<0?this[this.length+a]:this[a]},pushStack:function(a,b,c){var d=this.constructor();e.isArray(a)?E.apply(d,a):e.merge(d,a),d.prevObject=this,d.context=this.context,b==="find"?d.selector=this.selector+(this.selector?" ":"")+c:b&&(d.selector=this.selector+"."+b+"("+c+")");return d},each:function(a,b){return e.each(this,a,b)},ready:function(a){e.bindReady(),A.add(a);return this},eq:function(a){a=+a;return a===-1?this.slice(a):this.slice(a,a+1)},first:function(){return this.eq(0)},last:function(){return this.eq(-1)},slice:function(){return this.pushStack(F.apply(this,arguments),"slice",F.call(arguments).join(","))},map:function(a){return this.pushStack(e.map(this,function(b,c){return a.call(b,c,b)}))},end:function(){return this.prevObject||this.constructor(null)},push:E,sort:[].sort,splice:[].splice},e.fn.init.prototype=e.fn,e.extend=e.fn.extend=function(){var a,c,d,f,g,h,i=arguments[0]||{},j=1,k=arguments.length,l=!1;typeof i=="boolean"&&(l=i,i=arguments[1]||{},j=2),typeof i!="object"&&!e.isFunction(i)&&(i={}),k===j&&(i=this,--j);for(;j0)return;A.fireWith(c,[e]),e.fn.trigger&&e(c).trigger("ready").off("ready")}},bindReady:function(){if(!A){A=e.Callbacks("once memory");if(c.readyState==="complete")return setTimeout(e.ready,1);if(c.addEventListener)c.addEventListener("DOMContentLoaded",B,!1),a.addEventListener("load",e.ready,!1);else if(c.attachEvent){c.attachEvent("onreadystatechange",B),a.attachEvent("onload",e.ready);var b=!1;try{b=a.frameElement==null}catch(d){}c.documentElement.doScroll&&b&&J()}}},isFunction:function(a){return e.type(a)==="function"},isArray:Array.isArray||function(a){return e.type(a)==="array"},isWindow:function(a){return a&&typeof a=="object"&&"setInterval"in a},isNumeric:function(a){return!isNaN(parseFloat(a))&&isFinite(a)},type:function(a){return a==null?String(a):I[C.call(a)]||"object"},isPlainObject:function(a){if(!a||e.type(a)!=="object"||a.nodeType||e.isWindow(a))return!1;try{if(a.constructor&&!D.call(a,"constructor")&&!D.call(a.constructor.prototype,"isPrototypeOf"))return!1}catch(c){return!1}var d;for(d in a);return d===b||D.call(a,d)},isEmptyObject:function(a){for(var b in a)return!1;return!0},error:function(a){throw new Error(a)},parseJSON:function(b){if(typeof b!="string"||!b)return null;b=e.trim(b);if(a.JSON&&a.JSON.parse)return a.JSON.parse(b);if(n.test(b.replace(o,"@").replace(p,"]").replace(q,"")))return(new Function("return "+b))();e.error("Invalid JSON: "+b)},parseXML:function(c){var d,f;try{a.DOMParser?(f=new DOMParser,d=f.parseFromString(c,"text/xml")):(d=new ActiveXObject("Microsoft.XMLDOM"),d.async="false",d.loadXML(c))}catch(g){d=b}(!d||!d.documentElement||d.getElementsByTagName("parsererror").length)&&e.error("Invalid XML: "+c);return d},noop:function(){},globalEval:function(b){b&&j.test(b)&&(a.execScript||function(b){a.eval.call(a,b)})(b)},camelCase:function(a){return a.replace(w,"ms-").replace(v,x)},nodeName:function(a,b){return a.nodeName&&a.nodeName.toUpperCase()===b.toUpperCase()},each:function(a,c,d){var f,g=0,h=a.length,i=h===b||e.isFunction(a);if(d){if(i){for(f in a)if(c.apply(a[f],d)===!1)break}else for(;g0&&a[0]&&a[j-1]||j===0||e.isArray(a));if(k)for(;i1?i.call(arguments,0):b,j.notifyWith(k,e)}}function l(a){return function(c){b[a]=arguments.length>1?i.call(arguments,0):c,--g||j.resolveWith(j,b)}}var b=i.call(arguments,0),c=0,d=b.length,e=Array(d),g=d,h=d,j=d<=1&&a&&f.isFunction(a.promise)?a:f.Deferred(),k=j.promise();if(d>1){for(;c
a",d=q.getElementsByTagName("*"),e=q.getElementsByTagName("a")[0];if(!d||!d.length||!e)return{};g=c.createElement("select"),h=g.appendChild(c.createElement("option")),i=q.getElementsByTagName("input")[0],b={leadingWhitespace:q.firstChild.nodeType===3,tbody:!q.getElementsByTagName("tbody").length,htmlSerialize:!!q.getElementsByTagName("link").length,style:/top/.test(e.getAttribute("style")),hrefNormalized:e.getAttribute("href")==="/a",opacity:/^0.55/.test(e.style.opacity),cssFloat:!!e.style.cssFloat,checkOn:i.value==="on",optSelected:h.selected,getSetAttribute:q.className!=="t",enctype:!!c.createElement("form").enctype,html5Clone:c.createElement("nav").cloneNode(!0).outerHTML!=="<:nav>",submitBubbles:!0,changeBubbles:!0,focusinBubbles:!1,deleteExpando:!0,noCloneEvent:!0,inlineBlockNeedsLayout:!1,shrinkWrapBlocks:!1,reliableMarginRight:!0},i.checked=!0,b.noCloneChecked=i.cloneNode(!0).checked,g.disabled=!0,b.optDisabled=!h.disabled;try{delete q.test}catch(s){b.deleteExpando=!1}!q.addEventListener&&q.attachEvent&&q.fireEvent&&(q.attachEvent("onclick",function(){b.noCloneEvent=!1}),q.cloneNode(!0).fireEvent("onclick")),i=c.createElement("input"),i.value="t",i.setAttribute("type","radio"),b.radioValue=i.value==="t",i.setAttribute("checked","checked"),q.appendChild(i),k=c.createDocumentFragment(),k.appendChild(q.lastChild),b.checkClone=k.cloneNode(!0).cloneNode(!0).lastChild.checked,b.appendChecked=i.checked,k.removeChild(i),k.appendChild(q),q.innerHTML="",a.getComputedStyle&&(j=c.createElement("div"),j.style.width="0",j.style.marginRight="0",q.style.width="2px",q.appendChild(j),b.reliableMarginRight=(parseInt((a.getComputedStyle(j,null)||{marginRight:0}).marginRight,10)||0)===0);if(q.attachEvent)for(o in{submit:1,change:1,focusin:1})n="on"+o,p=n in q,p||(q.setAttribute(n,"return;"),p=typeof q[n]=="function"),b[o+"Bubbles"]=p;k.removeChild(q),k=g=h=j=q=i=null,f(function(){var a,d,e,g,h,i,j,k,m,n,o,r=c.getElementsByTagName("body")[0];!r||(j=1,k="position:absolute;top:0;left:0;width:1px;height:1px;margin:0;",m="visibility:hidden;border:0;",n="style='"+k+"border:5px solid #000;padding:0;'",o="
"+""+"
",a=c.createElement("div"),a.style.cssText=m+"width:0;height:0;position:static;top:0;margin-top:"+j+"px",r.insertBefore(a,r.firstChild),q=c.createElement("div"),a.appendChild(q),q.innerHTML="
t
",l=q.getElementsByTagName("td"),p=l[0].offsetHeight===0,l[0].style.display="",l[1].style.display="none",b.reliableHiddenOffsets=p&&l[0].offsetHeight===0,q.innerHTML="",q.style.width=q.style.paddingLeft="1px",f.boxModel=b.boxModel=q.offsetWidth===2,typeof q.style.zoom!="undefined"&&(q.style.display="inline",q.style.zoom=1,b.inlineBlockNeedsLayout=q.offsetWidth===2,q.style.display="",q.innerHTML="
",b.shrinkWrapBlocks=q.offsetWidth!==2),q.style.cssText=k+m,q.innerHTML=o,d=q.firstChild,e=d.firstChild,h=d.nextSibling.firstChild.firstChild,i={doesNotAddBorder:e.offsetTop!==5,doesAddBorderForTableAndCells:h.offsetTop===5},e.style.position="fixed",e.style.top="20px",i.fixedPosition=e.offsetTop===20||e.offsetTop===15,e.style.position=e.style.top="",d.style.overflow="hidden",d.style.position="relative",i.subtractsBorderForOverflowNotVisible=e.offsetTop===-5,i.doesNotIncludeMarginInBodyOffset=r.offsetTop!==j,r.removeChild(a),q=a=null,f.extend(b,i))});return b}();var j=/^(?:\{.*\}|\[.*\])$/,k=/([A-Z])/g;f.extend({cache:{},uuid:0,expando:"jQuery"+(f.fn.jquery+Math.random()).replace(/\D/g,""),noData:{embed:!0,object:"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",applet:!0},hasData:function(a){a=a.nodeType?f.cache[a[f.expando]]:a[f.expando];return!!a&&!m(a)},data:function(a,c,d,e){if(!!f.acceptData(a)){var g,h,i,j=f.expando,k=typeof c=="string",l=a.nodeType,m=l?f.cache:a,n=l?a[j]:a[j]&&j,o=c==="events";if((!n||!m[n]||!o&&!e&&!m[n].data)&&k&&d===b)return;n||(l?a[j]=n=++f.uuid:n=j),m[n]||(m[n]={},l||(m[n].toJSON=f.noop));if(typeof c=="object"||typeof c=="function")e?m[n]=f.extend(m[n],c):m[n].data=f.extend(m[n].data,c);g=h=m[n],e||(h.data||(h.data={}),h=h.data),d!==b&&(h[f.camelCase(c)]=d);if(o&&!h[c])return g.events;k?(i=h[c],i==null&&(i=h[f.camelCase(c)])):i=h;return i}},removeData:function(a,b,c){if(!!f.acceptData(a)){var d,e,g,h=f.expando,i=a.nodeType,j=i?f.cache:a,k=i?a[h]:h;if(!j[k])return;if(b){d=c?j[k]:j[k].data;if(d){f.isArray(b)||(b in d?b=[b]:(b=f.camelCase(b),b in d?b=[b]:b=b.split(" ")));for(e=0,g=b.length;e-1)return!0;return!1},val:function(a){var c,d,e,g=this[0];{if(!!arguments.length){e=f.isFunction(a);return this.each(function(d){var g=f(this),h;if(this.nodeType===1){e?h=a.call(this,d,g.val()):h=a,h==null?h="":typeof h=="number"?h+="":f.isArray(h)&&(h=f.map(h,function(a){return a==null?"":a+""})),c=f.valHooks[this.nodeName.toLowerCase()]||f.valHooks[this.type];if(!c||!("set"in c)||c.set(this,h,"value")===b)this.value=h}})}if(g){c=f.valHooks[g.nodeName.toLowerCase()]||f.valHooks[g.type];if(c&&"get"in c&&(d=c.get(g,"value"))!==b)return d;d=g.value;return typeof d=="string"?d.replace(q,""):d==null?"":d}}}}),f.extend({valHooks:{option:{get:function(a){var b=a.attributes.value;return!b||b.specified?a.value:a.text}},select:{get:function(a){var b,c,d,e,g=a.selectedIndex,h=[],i=a.options,j=a.type==="select-one";if(g<0)return null;c=j?g:0,d=j?g+1:i.length;for(;c=0}),c.length||(a.selectedIndex=-1);return c}}},attrFn:{val:!0,css:!0,html:!0,text:!0,data:!0,width:!0,height:!0,offset:!0},attr:function(a,c,d,e){var g,h,i,j=a.nodeType;if(!!a&&j!==3&&j!==8&&j!==2){if(e&&c in f.attrFn)return f(a)[c](d);if(typeof a.getAttribute=="undefined")return f.prop(a,c,d);i=j!==1||!f.isXMLDoc(a),i&&(c=c.toLowerCase(),h=f.attrHooks[c]||(u.test(c)?x:w));if(d!==b){if(d===null){f.removeAttr(a,c);return}if(h&&"set"in h&&i&&(g=h.set(a,d,c))!==b)return g;a.setAttribute(c,""+d);return d}if(h&&"get"in h&&i&&(g=h.get(a,c))!==null)return g;g=a.getAttribute(c);return g===null?b:g}},removeAttr:function(a,b){var c,d,e,g,h=0;if(b&&a.nodeType===1){d=b.toLowerCase().split(p),g=d.length;for(;h=0}})});var z=/^(?:textarea|input|select)$/i,A=/^([^\.]*)?(?:\.(.+))?$/,B=/\bhover(\.\S+)?\b/,C=/^key/,D=/^(?:mouse|contextmenu)|click/,E=/^(?:focusinfocus|focusoutblur)$/,F=/^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,G=function(a){var b=F.exec(a);b&&(b[1]=(b[1]||"").toLowerCase(),b[3]=b[3]&&new RegExp("(?:^|\\s)"+b[3]+"(?:\\s|$)"));return b},H=function(a,b){var c=a.attributes||{};return(!b[1]||a.nodeName.toLowerCase()===b[1])&&(!b[2]||(c.id||{}).value===b[2])&&(!b[3]||b[3].test((c["class"]||{}).value))},I=function(a){return f.event.special.hover?a:a.replace(B,"mouseenter$1 mouseleave$1")}; -f.event={add:function(a,c,d,e,g){var h,i,j,k,l,m,n,o,p,q,r,s;if(!(a.nodeType===3||a.nodeType===8||!c||!d||!(h=f._data(a)))){d.handler&&(p=d,d=p.handler),d.guid||(d.guid=f.guid++),j=h.events,j||(h.events=j={}),i=h.handle,i||(h.handle=i=function(a){return typeof f!="undefined"&&(!a||f.event.triggered!==a.type)?f.event.dispatch.apply(i.elem,arguments):b},i.elem=a),c=f.trim(I(c)).split(" ");for(k=0;k=0&&(h=h.slice(0,-1),k=!0),h.indexOf(".")>=0&&(i=h.split("."),h=i.shift(),i.sort());if((!e||f.event.customEvent[h])&&!f.event.global[h])return;c=typeof c=="object"?c[f.expando]?c:new f.Event(h,c):new f.Event(h),c.type=h,c.isTrigger=!0,c.exclusive=k,c.namespace=i.join("."),c.namespace_re=c.namespace?new RegExp("(^|\\.)"+i.join("\\.(?:.*\\.)?")+"(\\.|$)"):null,o=h.indexOf(":")<0?"on"+h:"";if(!e){j=f.cache;for(l in j)j[l].events&&j[l].events[h]&&f.event.trigger(c,d,j[l].handle.elem,!0);return}c.result=b,c.target||(c.target=e),d=d!=null?f.makeArray(d):[],d.unshift(c),p=f.event.special[h]||{};if(p.trigger&&p.trigger.apply(e,d)===!1)return;r=[[e,p.bindType||h]];if(!g&&!p.noBubble&&!f.isWindow(e)){s=p.delegateType||h,m=E.test(s+h)?e:e.parentNode,n=null;for(;m;m=m.parentNode)r.push([m,s]),n=m;n&&n===e.ownerDocument&&r.push([n.defaultView||n.parentWindow||a,s])}for(l=0;le&&i.push({elem:this,matches:d.slice(e)});for(j=0;j0?this.on(b,null,a,c):this.trigger(b)},f.attrFn&&(f.attrFn[b]=!0),C.test(b)&&(f.event.fixHooks[b]=f.event.keyHooks),D.test(b)&&(f.event.fixHooks[b]=f.event.mouseHooks)}),function(){function x(a,b,c,e,f,g){for(var h=0,i=e.length;h0){k=j;break}}j=j[a]}e[h]=k}}}function w(a,b,c,e,f,g){for(var h=0,i=e.length;h+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,d="sizcache"+(Math.random()+"").replace(".",""),e=0,g=Object.prototype.toString,h=!1,i=!0,j=/\\/g,k=/\r\n/g,l=/\W/;[0,0].sort(function(){i=!1;return 0});var m=function(b,d,e,f){e=e||[],d=d||c;var h=d;if(d.nodeType!==1&&d.nodeType!==9)return[];if(!b||typeof b!="string")return e;var i,j,k,l,n,q,r,t,u=!0,v=m.isXML(d),w=[],x=b;do{a.exec(""),i=a.exec(x);if(i){x=i[3],w.push(i[1]);if(i[2]){l=i[3];break}}}while(i);if(w.length>1&&p.exec(b))if(w.length===2&&o.relative[w[0]])j=y(w[0]+w[1],d,f);else{j=o.relative[w[0]]?[d]:m(w.shift(),d);while(w.length)b=w.shift(),o.relative[b]&&(b+=w.shift()),j=y(b,j,f)}else{!f&&w.length>1&&d.nodeType===9&&!v&&o.match.ID.test(w[0])&&!o.match.ID.test(w[w.length-1])&&(n=m.find(w.shift(),d,v),d=n.expr?m.filter(n.expr,n.set)[0]:n.set[0]);if(d){n=f?{expr:w.pop(),set:s(f)}:m.find(w.pop(),w.length===1&&(w[0]==="~"||w[0]==="+")&&d.parentNode?d.parentNode:d,v),j=n.expr?m.filter(n.expr,n.set):n.set,w.length>0?k=s(j):u=!1;while(w.length)q=w.pop(),r=q,o.relative[q]?r=w.pop():q="",r==null&&(r=d),o.relative[q](k,r,v)}else k=w=[]}k||(k=j),k||m.error(q||b);if(g.call(k)==="[object Array]")if(!u)e.push.apply(e,k);else if(d&&d.nodeType===1)for(t=0;k[t]!=null;t++)k[t]&&(k[t]===!0||k[t].nodeType===1&&m.contains(d,k[t]))&&e.push(j[t]);else for(t=0;k[t]!=null;t++)k[t]&&k[t].nodeType===1&&e.push(j[t]);else s(k,e);l&&(m(l,h,e,f),m.uniqueSort(e));return e};m.uniqueSort=function(a){if(u){h=i,a.sort(u);if(h)for(var b=1;b0},m.find=function(a,b,c){var d,e,f,g,h,i;if(!a)return[];for(e=0,f=o.order.length;e":function(a,b){var c,d=typeof b=="string",e=0,f=a.length;if(d&&!l.test(b)){b=b.toLowerCase();for(;e=0)?c||d.push(h):c&&(b[g]=!1));return!1},ID:function(a){return a[1].replace(j,"")},TAG:function(a,b){return a[1].replace(j,"").toLowerCase()},CHILD:function(a){if(a[1]==="nth"){a[2]||m.error(a[0]),a[2]=a[2].replace(/^\+|\s*/g,"");var b=/(-?)(\d*)(?:n([+\-]?\d*))?/.exec(a[2]==="even"&&"2n"||a[2]==="odd"&&"2n+1"||!/\D/.test(a[2])&&"0n+"+a[2]||a[2]);a[2]=b[1]+(b[2]||1)-0,a[3]=b[3]-0}else a[2]&&m.error(a[0]);a[0]=e++;return a},ATTR:function(a,b,c,d,e,f){var g=a[1]=a[1].replace(j,"");!f&&o.attrMap[g]&&(a[1]=o.attrMap[g]),a[4]=(a[4]||a[5]||"").replace(j,""),a[2]==="~="&&(a[4]=" "+a[4]+" ");return a},PSEUDO:function(b,c,d,e,f){if(b[1]==="not")if((a.exec(b[3])||"").length>1||/^\w/.test(b[3]))b[3]=m(b[3],null,null,c);else{var g=m.filter(b[3],c,d,!0^f);d||e.push.apply(e,g);return!1}else if(o.match.POS.test(b[0])||o.match.CHILD.test(b[0]))return!0;return b},POS:function(a){a.unshift(!0);return a}},filters:{enabled:function(a){return a.disabled===!1&&a.type!=="hidden"},disabled:function(a){return a.disabled===!0},checked:function(a){return a.checked===!0},selected:function(a){a.parentNode&&a.parentNode.selectedIndex;return a.selected===!0},parent:function(a){return!!a.firstChild},empty:function(a){return!a.firstChild},has:function(a,b,c){return!!m(c[3],a).length},header:function(a){return/h\d/i.test(a.nodeName)},text:function(a){var b=a.getAttribute("type"),c=a.type;return a.nodeName.toLowerCase()==="input"&&"text"===c&&(b===c||b===null)},radio:function(a){return a.nodeName.toLowerCase()==="input"&&"radio"===a.type},checkbox:function(a){return a.nodeName.toLowerCase()==="input"&&"checkbox"===a.type},file:function(a){return a.nodeName.toLowerCase()==="input"&&"file"===a.type},password:function(a){return a.nodeName.toLowerCase()==="input"&&"password"===a.type},submit:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"submit"===a.type},image:function(a){return a.nodeName.toLowerCase()==="input"&&"image"===a.type},reset:function(a){var b=a.nodeName.toLowerCase();return(b==="input"||b==="button")&&"reset"===a.type},button:function(a){var b=a.nodeName.toLowerCase();return b==="input"&&"button"===a.type||b==="button"},input:function(a){return/input|select|textarea|button/i.test(a.nodeName)},focus:function(a){return a===a.ownerDocument.activeElement}},setFilters:{first:function(a,b){return b===0},last:function(a,b,c,d){return b===d.length-1},even:function(a,b){return b%2===0},odd:function(a,b){return b%2===1},lt:function(a,b,c){return bc[3]-0},nth:function(a,b,c){return c[3]-0===b},eq:function(a,b,c){return c[3]-0===b}},filter:{PSEUDO:function(a,b,c,d){var e=b[1],f=o.filters[e];if(f)return f(a,c,b,d);if(e==="contains")return(a.textContent||a.innerText||n([a])||"").indexOf(b[3])>=0;if(e==="not"){var g=b[3];for(var h=0,i=g.length;h=0}},ID:function(a,b){return a.nodeType===1&&a.getAttribute("id")===b},TAG:function(a,b){return b==="*"&&a.nodeType===1||!!a.nodeName&&a.nodeName.toLowerCase()===b},CLASS:function(a,b){return(" "+(a.className||a.getAttribute("class"))+" ").indexOf(b)>-1},ATTR:function(a,b){var c=b[1],d=m.attr?m.attr(a,c):o.attrHandle[c]?o.attrHandle[c](a):a[c]!=null?a[c]:a.getAttribute(c),e=d+"",f=b[2],g=b[4];return d==null?f==="!=":!f&&m.attr?d!=null:f==="="?e===g:f==="*="?e.indexOf(g)>=0:f==="~="?(" "+e+" ").indexOf(g)>=0:g?f==="!="?e!==g:f==="^="?e.indexOf(g)===0:f==="$="?e.substr(e.length-g.length)===g:f==="|="?e===g||e.substr(0,g.length+1)===g+"-":!1:e&&d!==!1},POS:function(a,b,c,d){var e=b[2],f=o.setFilters[e];if(f)return f(a,c,b,d)}}},p=o.match.POS,q=function(a,b){return"\\"+(b-0+1)};for(var r in o.match)o.match[r]=new RegExp(o.match[r].source+/(?![^\[]*\])(?![^\(]*\))/.source),o.leftMatch[r]=new RegExp(/(^(?:.|\r|\n)*?)/.source+o.match[r].source.replace(/\\(\d+)/g,q));var s=function(a,b){a=Array.prototype.slice.call(a,0);if(b){b.push.apply(b,a);return b}return a};try{Array.prototype.slice.call(c.documentElement.childNodes,0)[0].nodeType}catch(t){s=function(a,b){var c=0,d=b||[];if(g.call(a)==="[object Array]")Array.prototype.push.apply(d,a);else if(typeof a.length=="number")for(var e=a.length;c",e.insertBefore(a,e.firstChild),c.getElementById(d)&&(o.find.ID=function(a,c,d){if(typeof c.getElementById!="undefined"&&!d){var e=c.getElementById(a[1]);return e?e.id===a[1]||typeof e.getAttributeNode!="undefined"&&e.getAttributeNode("id").nodeValue===a[1]?[e]:b:[]}},o.filter.ID=function(a,b){var c=typeof a.getAttributeNode!="undefined"&&a.getAttributeNode("id");return a.nodeType===1&&c&&c.nodeValue===b}),e.removeChild(a),e=a=null}(),function(){var a=c.createElement("div");a.appendChild(c.createComment("")),a.getElementsByTagName("*").length>0&&(o.find.TAG=function(a,b){var c=b.getElementsByTagName(a[1]);if(a[1]==="*"){var d=[];for(var e=0;c[e];e++)c[e].nodeType===1&&d.push(c[e]);c=d}return c}),a.innerHTML="",a.firstChild&&typeof a.firstChild.getAttribute!="undefined"&&a.firstChild.getAttribute("href")!=="#"&&(o.attrHandle.href=function(a){return a.getAttribute("href",2)}),a=null}(),c.querySelectorAll&&function(){var a=m,b=c.createElement("div"),d="__sizzle__";b.innerHTML="

";if(!b.querySelectorAll||b.querySelectorAll(".TEST").length!==0){m=function(b,e,f,g){e=e||c;if(!g&&!m.isXML(e)){var h=/^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec(b);if(h&&(e.nodeType===1||e.nodeType===9)){if(h[1])return s(e.getElementsByTagName(b),f);if(h[2]&&o.find.CLASS&&e.getElementsByClassName)return s(e.getElementsByClassName(h[2]),f)}if(e.nodeType===9){if(b==="body"&&e.body)return s([e.body],f);if(h&&h[3]){var i=e.getElementById(h[3]);if(!i||!i.parentNode)return s([],f);if(i.id===h[3])return s([i],f)}try{return s(e.querySelectorAll(b),f)}catch(j){}}else if(e.nodeType===1&&e.nodeName.toLowerCase()!=="object"){var k=e,l=e.getAttribute("id"),n=l||d,p=e.parentNode,q=/^\s*[+~]/.test(b);l?n=n.replace(/'/g,"\\$&"):e.setAttribute("id",n),q&&p&&(e=e.parentNode);try{if(!q||p)return s(e.querySelectorAll("[id='"+n+"'] "+b),f)}catch(r){}finally{l||k.removeAttribute("id")}}}return a(b,e,f,g)};for(var e in a)m[e]=a[e];b=null}}(),function(){var a=c.documentElement,b=a.matchesSelector||a.mozMatchesSelector||a.webkitMatchesSelector||a.msMatchesSelector;if(b){var d=!b.call(c.createElement("div"),"div"),e=!1;try{b.call(c.documentElement,"[test!='']:sizzle")}catch(f){e=!0}m.matchesSelector=function(a,c){c=c.replace(/\=\s*([^'"\]]*)\s*\]/g,"='$1']");if(!m.isXML(a))try{if(e||!o.match.PSEUDO.test(c)&&!/!=/.test(c)){var f=b.call(a,c);if(f||!d||a.document&&a.document.nodeType!==11)return f}}catch(g){}return m(c,null,null,[a]).length>0}}}(),function(){var a=c.createElement("div");a.innerHTML="
";if(!!a.getElementsByClassName&&a.getElementsByClassName("e").length!==0){a.lastChild.className="e";if(a.getElementsByClassName("e").length===1)return;o.order.splice(1,0,"CLASS"),o.find.CLASS=function(a,b,c){if(typeof b.getElementsByClassName!="undefined"&&!c)return b.getElementsByClassName(a[1])},a=null}}(),c.documentElement.contains?m.contains=function(a,b){return a!==b&&(a.contains?a.contains(b):!0)}:c.documentElement.compareDocumentPosition?m.contains=function(a,b){return!!(a.compareDocumentPosition(b)&16)}:m.contains=function(){return!1},m.isXML=function(a){var b=(a?a.ownerDocument||a:0).documentElement;return b?b.nodeName!=="HTML":!1};var y=function(a,b,c){var d,e=[],f="",g=b.nodeType?[b]:b;while(d=o.match.PSEUDO.exec(a))f+=d[0],a=a.replace(o.match.PSEUDO,"");a=o.relative[a]?a+"*":a;for(var h=0,i=g.length;h0)for(h=g;h=0:f.filter(a,this).length>0:this.filter(a).length>0)},closest:function(a,b){var c=[],d,e,g=this[0];if(f.isArray(a)){var h=1;while(g&&g.ownerDocument&&g!==b){for(d=0;d-1:f.find.matchesSelector(g,a)){c.push(g);break}g=g.parentNode;if(!g||!g.ownerDocument||g===b||g.nodeType===11)break}}c=c.length>1?f.unique(c):c;return this.pushStack(c,"closest",a)},index:function(a){if(!a)return this[0]&&this[0].parentNode?this.prevAll().length:-1;if(typeof a=="string")return f.inArray(this[0],f(a));return f.inArray(a.jquery?a[0]:a,this)},add:function(a,b){var c=typeof a=="string"?f(a,b):f.makeArray(a&&a.nodeType?[a]:a),d=f.merge(this.get(),c);return this.pushStack(S(c[0])||S(d[0])?d:f.unique(d))},andSelf:function(){return this.add(this.prevObject)}}),f.each({parent:function(a){var b=a.parentNode;return b&&b.nodeType!==11?b:null},parents:function(a){return f.dir(a,"parentNode")},parentsUntil:function(a,b,c){return f.dir(a,"parentNode",c)},next:function(a){return f.nth(a,2,"nextSibling")},prev:function(a){return f.nth(a,2,"previousSibling")},nextAll:function(a){return f.dir(a,"nextSibling")},prevAll:function(a){return f.dir(a,"previousSibling")},nextUntil:function(a,b,c){return f.dir(a,"nextSibling",c)},prevUntil:function(a,b,c){return f.dir(a,"previousSibling",c)},siblings:function(a){return f.sibling(a.parentNode.firstChild,a)},children:function(a){return f.sibling(a.firstChild)},contents:function(a){return f.nodeName(a,"iframe")?a.contentDocument||a.contentWindow.document:f.makeArray(a.childNodes)}},function(a,b){f.fn[a]=function(c,d){var e=f.map(this,b,c);L.test(a)||(d=c),d&&typeof d=="string"&&(e=f.filter(d,e)),e=this.length>1&&!R[a]?f.unique(e):e,(this.length>1||N.test(d))&&M.test(a)&&(e=e.reverse());return this.pushStack(e,a,P.call(arguments).join(","))}}),f.extend({filter:function(a,b,c){c&&(a=":not("+a+")");return b.length===1?f.find.matchesSelector(b[0],a)?[b[0]]:[]:f.find.matches(a,b)},dir:function(a,c,d){var e=[],g=a[c];while(g&&g.nodeType!==9&&(d===b||g.nodeType!==1||!f(g).is(d)))g.nodeType===1&&e.push(g),g=g[c];return e},nth:function(a,b,c,d){b=b||1;var e=0;for(;a;a=a[c])if(a.nodeType===1&&++e===b)break;return a},sibling:function(a,b){var c=[];for(;a;a=a.nextSibling)a.nodeType===1&&a!==b&&c.push(a);return c}});var V="abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",W=/ jQuery\d+="(?:\d+|null)"/g,X=/^\s+/,Y=/<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,Z=/<([\w:]+)/,$=/",""],legend:[1,"
","
"],thead:[1,"","
"],tr:[2,"","
"],td:[3,"","
"],col:[2,"","
"],area:[1,"",""],_default:[0,"",""]},bh=U(c);bg.optgroup=bg.option,bg.tbody=bg.tfoot=bg.colgroup=bg.caption=bg.thead,bg.th=bg.td,f.support.htmlSerialize||(bg._default=[1,"div
","
"]),f.fn.extend({text:function(a){if(f.isFunction(a))return this.each(function(b){var c=f(this);c.text(a.call(this,b,c.text()))});if(typeof a!="object"&&a!==b)return this.empty().append((this[0]&&this[0].ownerDocument||c).createTextNode(a));return f.text(this)},wrapAll:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapAll(a.call(this,b))});if(this[0]){var b=f(a,this[0].ownerDocument).eq(0).clone(!0);this[0].parentNode&&b.insertBefore(this[0]),b.map(function(){var a=this;while(a.firstChild&&a.firstChild.nodeType===1)a=a.firstChild;return a}).append(this)}return this},wrapInner:function(a){if(f.isFunction(a))return this.each(function(b){f(this).wrapInner(a.call(this,b))});return this.each(function(){var b=f(this),c=b.contents();c.length?c.wrapAll(a):b.append(a)})},wrap:function(a){var b=f.isFunction(a);return this.each(function(c){f(this).wrapAll(b?a.call(this,c):a)})},unwrap:function(){return this.parent().each(function(){f.nodeName(this,"body")||f(this).replaceWith(this.childNodes)}).end()},append:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.appendChild(a)})},prepend:function(){return this.domManip(arguments,!0,function(a){this.nodeType===1&&this.insertBefore(a,this.firstChild)})},before:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this)});if(arguments.length){var a=f.clean(arguments);a.push.apply(a,this.toArray());return this.pushStack(a,"before",arguments)}},after:function(){if(this[0]&&this[0].parentNode)return this.domManip(arguments,!1,function(a){this.parentNode.insertBefore(a,this.nextSibling)});if(arguments.length){var a=this.pushStack(this,"after",arguments);a.push.apply(a,f.clean(arguments));return a}},remove:function(a,b){for(var c=0,d;(d=this[c])!=null;c++)if(!a||f.filter(a,[d]).length)!b&&d.nodeType===1&&(f.cleanData(d.getElementsByTagName("*")),f.cleanData([d])),d.parentNode&&d.parentNode.removeChild(d);return this},empty:function() -{for(var a=0,b;(b=this[a])!=null;a++){b.nodeType===1&&f.cleanData(b.getElementsByTagName("*"));while(b.firstChild)b.removeChild(b.firstChild)}return this},clone:function(a,b){a=a==null?!1:a,b=b==null?a:b;return this.map(function(){return f.clone(this,a,b)})},html:function(a){if(a===b)return this[0]&&this[0].nodeType===1?this[0].innerHTML.replace(W,""):null;if(typeof a=="string"&&!ba.test(a)&&(f.support.leadingWhitespace||!X.test(a))&&!bg[(Z.exec(a)||["",""])[1].toLowerCase()]){a=a.replace(Y,"<$1>");try{for(var c=0,d=this.length;c1&&l0?this.clone(!0):this).get();f(e[h])[b](j),d=d.concat(j)}return this.pushStack(d,a,e.selector)}}),f.extend({clone:function(a,b,c){var d,e,g,h=f.support.html5Clone||!bc.test("<"+a.nodeName)?a.cloneNode(!0):bo(a);if((!f.support.noCloneEvent||!f.support.noCloneChecked)&&(a.nodeType===1||a.nodeType===11)&&!f.isXMLDoc(a)){bk(a,h),d=bl(a),e=bl(h);for(g=0;d[g];++g)e[g]&&bk(d[g],e[g])}if(b){bj(a,h);if(c){d=bl(a),e=bl(h);for(g=0;d[g];++g)bj(d[g],e[g])}}d=e=null;return h},clean:function(a,b,d,e){var g;b=b||c,typeof b.createElement=="undefined"&&(b=b.ownerDocument||b[0]&&b[0].ownerDocument||c);var h=[],i;for(var j=0,k;(k=a[j])!=null;j++){typeof k=="number"&&(k+="");if(!k)continue;if(typeof k=="string")if(!_.test(k))k=b.createTextNode(k);else{k=k.replace(Y,"<$1>");var l=(Z.exec(k)||["",""])[1].toLowerCase(),m=bg[l]||bg._default,n=m[0],o=b.createElement("div");b===c?bh.appendChild(o):U(b).appendChild(o),o.innerHTML=m[1]+k+m[2];while(n--)o=o.lastChild;if(!f.support.tbody){var p=$.test(k),q=l==="table"&&!p?o.firstChild&&o.firstChild.childNodes:m[1]===""&&!p?o.childNodes:[];for(i=q.length-1;i>=0;--i)f.nodeName(q[i],"tbody")&&!q[i].childNodes.length&&q[i].parentNode.removeChild(q[i])}!f.support.leadingWhitespace&&X.test(k)&&o.insertBefore(b.createTextNode(X.exec(k)[0]),o.firstChild),k=o.childNodes}var r;if(!f.support.appendChecked)if(k[0]&&typeof (r=k.length)=="number")for(i=0;i=0)return b+"px"}}}),f.support.opacity||(f.cssHooks.opacity={get:function(a,b){return br.test((b&&a.currentStyle?a.currentStyle.filter:a.style.filter)||"")?parseFloat(RegExp.$1)/100+"":b?"1":""},set:function(a,b){var c=a.style,d=a.currentStyle,e=f.isNumeric(b)?"alpha(opacity="+b*100+")":"",g=d&&d.filter||c.filter||"";c.zoom=1;if(b>=1&&f.trim(g.replace(bq,""))===""){c.removeAttribute("filter");if(d&&!d.filter)return}c.filter=bq.test(g)?g.replace(bq,e):g+" "+e}}),f(function(){f.support.reliableMarginRight||(f.cssHooks.marginRight={get:function(a,b){var c;f.swap(a,{display:"inline-block"},function(){b?c=bz(a,"margin-right","marginRight"):c=a.style.marginRight});return c}})}),c.defaultView&&c.defaultView.getComputedStyle&&(bA=function(a,b){var c,d,e;b=b.replace(bs,"-$1").toLowerCase(),(d=a.ownerDocument.defaultView)&&(e=d.getComputedStyle(a,null))&&(c=e.getPropertyValue(b),c===""&&!f.contains(a.ownerDocument.documentElement,a)&&(c=f.style(a,b)));return c}),c.documentElement.currentStyle&&(bB=function(a,b){var c,d,e,f=a.currentStyle&&a.currentStyle[b],g=a.style;f===null&&g&&(e=g[b])&&(f=e),!bt.test(f)&&bu.test(f)&&(c=g.left,d=a.runtimeStyle&&a.runtimeStyle.left,d&&(a.runtimeStyle.left=a.currentStyle.left),g.left=b==="fontSize"?"1em":f||0,f=g.pixelLeft+"px",g.left=c,d&&(a.runtimeStyle.left=d));return f===""?"auto":f}),bz=bA||bB,f.expr&&f.expr.filters&&(f.expr.filters.hidden=function(a){var b=a.offsetWidth,c=a.offsetHeight;return b===0&&c===0||!f.support.reliableHiddenOffsets&&(a.style&&a.style.display||f.css(a,"display"))==="none"},f.expr.filters.visible=function(a){return!f.expr.filters.hidden(a)});var bD=/%20/g,bE=/\[\]$/,bF=/\r?\n/g,bG=/#.*$/,bH=/^(.*?):[ \t]*([^\r\n]*)\r?$/mg,bI=/^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,bJ=/^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,bK=/^(?:GET|HEAD)$/,bL=/^\/\//,bM=/\?/,bN=/)<[^<]*)*<\/script>/gi,bO=/^(?:select|textarea)/i,bP=/\s+/,bQ=/([?&])_=[^&]*/,bR=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,bS=f.fn.load,bT={},bU={},bV,bW,bX=["*/"]+["*"];try{bV=e.href}catch(bY){bV=c.createElement("a"),bV.href="",bV=bV.href}bW=bR.exec(bV.toLowerCase())||[],f.fn.extend({load:function(a,c,d){if(typeof a!="string"&&bS)return bS.apply(this,arguments);if(!this.length)return this;var e=a.indexOf(" ");if(e>=0){var g=a.slice(e,a.length);a=a.slice(0,e)}var h="GET";c&&(f.isFunction(c)?(d=c,c=b):typeof c=="object"&&(c=f.param(c,f.ajaxSettings.traditional),h="POST"));var i=this;f.ajax({url:a,type:h,dataType:"html",data:c,complete:function(a,b,c){c=a.responseText,a.isResolved()&&(a.done(function(a){c=a}),i.html(g?f("
").append(c.replace(bN,"")).find(g):c)),d&&i.each(d,[c,b,a])}});return this},serialize:function(){return f.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?f.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||bO.test(this.nodeName)||bI.test(this.type))}).map(function(a,b){var c=f(this).val();return c==null?null:f.isArray(c)?f.map(c,function(a,c){return{name:b.name,value:a.replace(bF,"\r\n")}}):{name:b.name,value:c.replace(bF,"\r\n")}}).get()}}),f.each("ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split(" "),function(a,b){f.fn[b]=function(a){return this.on(b,a)}}),f.each(["get","post"],function(a,c){f[c]=function(a,d,e,g){f.isFunction(d)&&(g=g||e,e=d,d=b);return f.ajax({type:c,url:a,data:d,success:e,dataType:g})}}),f.extend({getScript:function(a,c){return f.get(a,b,c,"script")},getJSON:function(a,b,c){return f.get(a,b,c,"json")},ajaxSetup:function(a,b){b?b_(a,f.ajaxSettings):(b=a,a=f.ajaxSettings),b_(a,b);return a},ajaxSettings:{url:bV,isLocal:bJ.test(bW[1]),global:!0,type:"GET",contentType:"application/x-www-form-urlencoded",processData:!0,async:!0,accepts:{xml:"application/xml, text/xml",html:"text/html",text:"text/plain",json:"application/json, text/javascript","*":bX},contents:{xml:/xml/,html:/html/,json:/json/},responseFields:{xml:"responseXML",text:"responseText"},converters:{"* text":a.String,"text html":!0,"text json":f.parseJSON,"text xml":f.parseXML},flatOptions:{context:!0,url:!0}},ajaxPrefilter:bZ(bT),ajaxTransport:bZ(bU),ajax:function(a,c){function w(a,c,l,m){if(s!==2){s=2,q&&clearTimeout(q),p=b,n=m||"",v.readyState=a>0?4:0;var o,r,u,w=c,x=l?cb(d,v,l):b,y,z;if(a>=200&&a<300||a===304){if(d.ifModified){if(y=v.getResponseHeader("Last-Modified"))f.lastModified[k]=y;if(z=v.getResponseHeader("Etag"))f.etag[k]=z}if(a===304)w="notmodified",o=!0;else try{r=cc(d,x),w="success",o=!0}catch(A){w="parsererror",u=A}}else{u=w;if(!w||a)w="error",a<0&&(a=0)}v.status=a,v.statusText=""+(c||w),o?h.resolveWith(e,[r,w,v]):h.rejectWith(e,[v,w,u]),v.statusCode(j),j=b,t&&g.trigger("ajax"+(o?"Success":"Error"),[v,d,o?r:u]),i.fireWith(e,[v,w]),t&&(g.trigger("ajaxComplete",[v,d]),--f.active||f.event.trigger("ajaxStop"))}}typeof a=="object"&&(c=a,a=b),c=c||{};var d=f.ajaxSetup({},c),e=d.context||d,g=e!==d&&(e.nodeType||e instanceof f)?f(e):f.event,h=f.Deferred(),i=f.Callbacks("once memory"),j=d.statusCode||{},k,l={},m={},n,o,p,q,r,s=0,t,u,v={readyState:0,setRequestHeader:function(a,b){if(!s){var c=a.toLowerCase();a=m[c]=m[c]||a,l[a]=b}return this},getAllResponseHeaders:function(){return s===2?n:null},getResponseHeader:function(a){var c;if(s===2){if(!o){o={};while(c=bH.exec(n))o[c[1].toLowerCase()]=c[2]}c=o[a.toLowerCase()]}return c===b?null:c},overrideMimeType:function(a){s||(d.mimeType=a);return this},abort:function(a){a=a||"abort",p&&p.abort(a),w(0,a);return this}};h.promise(v),v.success=v.done,v.error=v.fail,v.complete=i.add,v.statusCode=function(a){if(a){var b;if(s<2)for(b in a)j[b]=[j[b],a[b]];else b=a[v.status],v.then(b,b)}return this},d.url=((a||d.url)+"").replace(bG,"").replace(bL,bW[1]+"//"),d.dataTypes=f.trim(d.dataType||"*").toLowerCase().split(bP),d.crossDomain==null&&(r=bR.exec(d.url.toLowerCase()),d.crossDomain=!(!r||r[1]==bW[1]&&r[2]==bW[2]&&(r[3]||(r[1]==="http:"?80:443))==(bW[3]||(bW[1]==="http:"?80:443)))),d.data&&d.processData&&typeof d.data!="string"&&(d.data=f.param(d.data,d.traditional)),b$(bT,d,c,v);if(s===2)return!1;t=d.global,d.type=d.type.toUpperCase(),d.hasContent=!bK.test(d.type),t&&f.active++===0&&f.event.trigger("ajaxStart");if(!d.hasContent){d.data&&(d.url+=(bM.test(d.url)?"&":"?")+d.data,delete d.data),k=d.url;if(d.cache===!1){var x=f.now(),y=d.url.replace(bQ,"$1_="+x);d.url=y+(y===d.url?(bM.test(d.url)?"&":"?")+"_="+x:"")}}(d.data&&d.hasContent&&d.contentType!==!1||c.contentType)&&v.setRequestHeader("Content-Type",d.contentType),d.ifModified&&(k=k||d.url,f.lastModified[k]&&v.setRequestHeader("If-Modified-Since",f.lastModified[k]),f.etag[k]&&v.setRequestHeader("If-None-Match",f.etag[k])),v.setRequestHeader("Accept",d.dataTypes[0]&&d.accepts[d.dataTypes[0]]?d.accepts[d.dataTypes[0]]+(d.dataTypes[0]!=="*"?", "+bX+"; q=0.01":""):d.accepts["*"]);for(u in d.headers)v.setRequestHeader(u,d.headers[u]);if(d.beforeSend&&(d.beforeSend.call(e,v,d)===!1||s===2)){v.abort();return!1}for(u in{success:1,error:1,complete:1})v[u](d[u]);p=b$(bU,d,c,v);if(!p)w(-1,"No Transport");else{v.readyState=1,t&&g.trigger("ajaxSend",[v,d]),d.async&&d.timeout>0&&(q=setTimeout(function(){v.abort("timeout")},d.timeout));try{s=1,p.send(l,w)}catch(z){if(s<2)w(-1,z);else throw z}}return v},param:function(a,c){var d=[],e=function(a,b){b=f.isFunction(b)?b():b,d[d.length]=encodeURIComponent(a)+"="+encodeURIComponent(b)};c===b&&(c=f.ajaxSettings.traditional);if(f.isArray(a)||a.jquery&&!f.isPlainObject(a))f.each(a,function(){e(this.name,this.value)});else for(var g in a)ca(g,a[g],c,e);return d.join("&").replace(bD,"+")}}),f.extend({active:0,lastModified:{},etag:{}});var cd=f.now(),ce=/(\=)\?(&|$)|\?\?/i;f.ajaxSetup({jsonp:"callback",jsonpCallback:function(){return f.expando+"_"+cd++}}),f.ajaxPrefilter("json jsonp",function(b,c,d){var e=b.contentType==="application/x-www-form-urlencoded"&&typeof b.data=="string";if(b.dataTypes[0]==="jsonp"||b.jsonp!==!1&&(ce.test(b.url)||e&&ce.test(b.data))){var g,h=b.jsonpCallback=f.isFunction(b.jsonpCallback)?b.jsonpCallback():b.jsonpCallback,i=a[h],j=b.url,k=b.data,l="$1"+h+"$2";b.jsonp!==!1&&(j=j.replace(ce,l),b.url===j&&(e&&(k=k.replace(ce,l)),b.data===k&&(j+=(/\?/.test(j)?"&":"?")+b.jsonp+"="+h))),b.url=j,b.data=k,a[h]=function(a){g=[a]},d.always(function(){a[h]=i,g&&f.isFunction(i)&&a[h](g[0])}),b.converters["script json"]=function(){g||f.error(h+" was not called");return g[0]},b.dataTypes[0]="json";return"script"}}),f.ajaxSetup({accepts:{script:"text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"},contents:{script:/javascript|ecmascript/},converters:{"text script":function(a){f.globalEval(a);return a}}}),f.ajaxPrefilter("script",function(a){a.cache===b&&(a.cache=!1),a.crossDomain&&(a.type="GET",a.global=!1)}),f.ajaxTransport("script",function(a){if(a.crossDomain){var d,e=c.head||c.getElementsByTagName("head")[0]||c.documentElement;return{send:function(f,g){d=c.createElement("script"),d.async="async",a.scriptCharset&&(d.charset=a.scriptCharset),d.src=a.url,d.onload=d.onreadystatechange=function(a,c){if(c||!d.readyState||/loaded|complete/.test(d.readyState))d.onload=d.onreadystatechange=null,e&&d.parentNode&&e.removeChild(d),d=b,c||g(200,"success")},e.insertBefore(d,e.firstChild)},abort:function(){d&&d.onload(0,1)}}}});var cf=a.ActiveXObject?function(){for(var a in ch)ch[a](0,1)}:!1,cg=0,ch;f.ajaxSettings.xhr=a.ActiveXObject?function(){return!this.isLocal&&ci()||cj()}:ci,function(a){f.extend(f.support,{ajax:!!a,cors:!!a&&"withCredentials"in a})}(f.ajaxSettings.xhr()),f.support.ajax&&f.ajaxTransport(function(c){if(!c.crossDomain||f.support.cors){var d;return{send:function(e,g){var h=c.xhr(),i,j;c.username?h.open(c.type,c.url,c.async,c.username,c.password):h.open(c.type,c.url,c.async);if(c.xhrFields)for(j in c.xhrFields)h[j]=c.xhrFields[j];c.mimeType&&h.overrideMimeType&&h.overrideMimeType(c.mimeType),!c.crossDomain&&!e["X-Requested-With"]&&(e["X-Requested-With"]="XMLHttpRequest");try{for(j in e)h.setRequestHeader(j,e[j])}catch(k){}h.send(c.hasContent&&c.data||null),d=function(a,e){var j,k,l,m,n;try{if(d&&(e||h.readyState===4)){d=b,i&&(h.onreadystatechange=f.noop,cf&&delete ch[i]);if(e)h.readyState!==4&&h.abort();else{j=h.status,l=h.getAllResponseHeaders(),m={},n=h.responseXML,n&&n.documentElement&&(m.xml=n),m.text=h.responseText;try{k=h.statusText}catch(o){k=""}!j&&c.isLocal&&!c.crossDomain?j=m.text?200:404:j===1223&&(j=204)}}}catch(p){e||g(-1,p)}m&&g(j,k,m,l)},!c.async||h.readyState===4?d():(i=++cg,cf&&(ch||(ch={},f(a).unload(cf)),ch[i]=d),h.onreadystatechange=d)},abort:function(){d&&d(0,1)}}}});var ck={},cl,cm,cn=/^(?:toggle|show|hide)$/,co=/^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,cp,cq=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]],cr;f.fn.extend({show:function(a,b,c){var d,e;if(a||a===0)return this.animate(cu("show",3),a,b,c);for(var g=0,h=this.length;g=i.duration+this.startTime){this.now=this.end,this.pos=this.state=1,this.update(),i.animatedProperties[this.prop]=!0;for(b in i.animatedProperties)i.animatedProperties[b]!==!0&&(g=!1);if(g){i.overflow!=null&&!f.support.shrinkWrapBlocks&&f.each(["","X","Y"],function(a,b){h.style["overflow"+b]=i.overflow[a]}),i.hide&&f(h).hide();if(i.hide||i.show)for(b in i.animatedProperties)f.style(h,b,i.orig[b]),f.removeData(h,"fxshow"+b,!0),f.removeData(h,"toggle"+b,!0);d=i.complete,d&&(i.complete=!1,d.call(h))}return!1}i.duration==Infinity?this.now=e:(c=e-this.startTime,this.state=c/i.duration,this.pos=f.easing[i.animatedProperties[this.prop]](this.state,c,0,1,i.duration),this.now=this.start+(this.end-this.start)*this.pos),this.update();return!0}},f.extend(f.fx,{tick:function(){var a,b=f.timers,c=0;for(;c-1,k={},l={},m,n;j?(l=e.position(),m=l.top,n=l.left):(m=parseFloat(h)||0,n=parseFloat(i)||0),f.isFunction(b)&&(b=b.call(a,c,g)),b.top!=null&&(k.top=b.top-g.top+m),b.left!=null&&(k.left=b.left-g.left+n),"using"in b?b.using.call(a,k):e.css(k)}},f.fn.extend({position:function(){if(!this[0])return null;var a=this[0],b=this.offsetParent(),c=this.offset(),d=cx.test(b[0].nodeName)?{top:0,left:0}:b.offset();c.top-=parseFloat(f.css(a,"marginTop"))||0,c.left-=parseFloat(f.css(a,"marginLeft"))||0,d.top+=parseFloat(f.css(b[0],"borderTopWidth"))||0,d.left+=parseFloat(f.css(b[0],"borderLeftWidth"))||0;return{top:c.top-d.top,left:c.left-d.left}},offsetParent:function(){return this.map(function(){var a=this.offsetParent||c.body;while(a&&!cx.test(a.nodeName)&&f.css(a,"position")==="static")a=a.offsetParent;return a})}}),f.each(["Left","Top"],function(a,c){var d="scroll"+c;f.fn[d]=function(c){var e,g;if(c===b){e=this[0];if(!e)return null;g=cy(e);return g?"pageXOffset"in g?g[a?"pageYOffset":"pageXOffset"]:f.support.boxModel&&g.document.documentElement[d]||g.document.body[d]:e[d]}return this.each(function(){g=cy(this),g?g.scrollTo(a?f(g).scrollLeft():c,a?c:f(g).scrollTop()):this[d]=c})}}),f.each(["Height","Width"],function(a,c){var d=c.toLowerCase();f.fn["inner"+c]=function(){var a=this[0];return a?a.style?parseFloat(f.css(a,d,"padding")):this[d]():null},f.fn["outer"+c]=function(a){var b=this[0];return b?b.style?parseFloat(f.css(b,d,a?"margin":"border")):this[d]():null},f.fn[d]=function(a){var e=this[0];if(!e)return a==null?null:this;if(f.isFunction(a))return this.each(function(b){var c=f(this);c[d](a.call(this,b,c[d]()))});if(f.isWindow(e)){var g=e.document.documentElement["client"+c],h=e.document.body;return e.document.compatMode==="CSS1Compat"&&g||h&&h["client"+c]||g}if(e.nodeType===9)return Math.max(e.documentElement["client"+c],e.body["scroll"+c],e.documentElement["scroll"+c],e.body["offset"+c],e.documentElement["offset"+c]);if(a===b){var i=f.css(e,d),j=parseFloat(i);return f.isNumeric(j)?j:i}return this.css(d,typeof a=="string"?a:a+"px")}}),a.jQuery=a.$=f,typeof define=="function"&&define.amd&&define.amd.jQuery&&define("jquery",[],function(){return f})})(window); \ No newline at end of file diff --git a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/ajax-loader.png b/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/ajax-loader.png deleted file mode 100644 index 0973ae040f..0000000000 Binary files a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/ajax-loader.png and /dev/null differ diff --git a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/icons-18-black-pack.png b/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/icons-18-black-pack.png deleted file mode 100644 index 07d96586cd..0000000000 Binary files a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/icons-18-black-pack.png and /dev/null differ diff --git a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/icons-18-white-pack.png b/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/icons-18-white-pack.png deleted file mode 100644 index 0159f628f4..0000000000 Binary files a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/icons-18-white-pack.png and /dev/null differ diff --git a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/icons-36-black-pack.png b/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/icons-36-black-pack.png deleted file mode 100644 index 562e839b9b..0000000000 Binary files a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/icons-36-black-pack.png and /dev/null differ diff --git a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/icons-36-white-pack.png b/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/icons-36-white-pack.png deleted file mode 100644 index 81f082a4ad..0000000000 Binary files a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/images/icons-36-white-pack.png and /dev/null differ diff --git a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/jqm-icon-pack-1.1.1-original.css b/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/jqm-icon-pack-1.1.1-original.css deleted file mode 100644 index 0e424b20f6..0000000000 --- a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile.iconpack/jqm-icon-pack-1.1.1-original.css +++ /dev/null @@ -1,129 +0,0 @@ -/* - jQuery Mobile Icon Pack - andy matthews - @commadelimited -*/ - -/* Icons ------------------------------------------------------------------------------------------------------------*/ - -.ui-icon, -.ui-icon-searchfield:after { - background: #666666; - background: rgba(0,0,0,.4); - background-image: url('images/icons-18-white-pack.png'); - background-repeat: no-repeat; - -moz-border-radius: 9px; - -webkit-border-radius: 9px; - border-radius: 9px; -} - - -/* Alt icon color ------------------------------------------------------------------------------------------------------------*/ - -.ui-icon-alt { - background: #ffffff; - background: rgba(255,255,255,.3); - background-image: url('images/icons-18-black-pack.png'); - background-repeat: no-repeat; -} - -/* restore default loading image */ -.ui-icon-loading { - background-image: url("images/ajax-loader.png"); - background-size: 35px 35px; - border-radius: 20px 20px 20px 20px; - height: 40px; - width: 40px; -} - -/* HD/"retina" sprite ------------------------------------------------------------------------------------------------------------*/ - -@media only screen and (-webkit-min-device-pixel-ratio: 1.5), - only screen and (min--moz-device-pixel-ratio: 1.5), - only screen and (min-resolution: 240dpi) { - - .ui-icon-plus, .ui-icon-minus, .ui-icon-delete, .ui-icon-arrow-r, - .ui-icon-arrow-l, .ui-icon-arrow-u, .ui-icon-arrow-d, .ui-icon-check, - .ui-icon-gear, .ui-icon-refresh, .ui-icon-forward, .ui-icon-back, - .ui-icon-grid, .ui-icon-star, .ui-icon-alert, .ui-icon-info, .ui-icon-home, .ui-icon-search, .ui-icon-searchfield:after, - .ui-icon-checkbox-off, .ui-icon-checkbox-on, .ui-icon-radio-off, .ui-icon-radio-on, .ui-icon-email , .ui-icon-page, - .ui-icon-question , .ui-icon-foursquare , .ui-icon-twitter , .ui-icon-facebook , .ui-icon-dollar , .ui-icon-euro, - .ui-icon-pound , .ui-icon-apple , .ui-icon-chat , .ui-icon-trash , .ui-icon-bell , .ui-icon-mappin , .ui-icon-direction, - .ui-icon-heart , .ui-icon-wrench , .ui-icon-play , .ui-icon-pause , .ui-icon-stop , .ui-icon-person , .ui-icon-music, - .ui-icon-rss , .ui-icon-wifi , .ui-icon-phone , .ui-icon-power , .ui-icon-lock , .ui-icon-flag , .ui-icon-calendar, - .ui-icon-lightning , .ui-icon-drink , .ui-icon-android , .ui-icon-edit { - background-image: url('images/icons-36-white-pack.png'); - -moz-background-size: 774px 54px; - -o-background-size: 774px 54px; - -webkit-background-size: 774px 54px; - background-size: 774px 54px; - } - .ui-icon-alt { - background-image: url('images/icons-36-black-pack.png' ); - } -} - -/* first row */ -.ui-icon-plus { background-position: -0 -0; } -.ui-icon-minus { background-position: -36px -0; } -.ui-icon-delete { background-position: -72px -0; } -.ui-icon-arrow-r { background-position: -108px -0; } -.ui-icon-arrow-l { background-position: -144px -0; } -.ui-icon-arrow-u { background-position: -180px -0; } -.ui-icon-arrow-d { background-position: -216px -0; } -.ui-icon-check { background-position: -252px -0; } -.ui-icon-gear { background-position: -288px -0; } -.ui-icon-refresh { background-position: -324px -0; } -.ui-icon-forward { background-position: -360px -0; } -.ui-icon-back { background-position: -396px -0; } -.ui-icon-grid { background-position: -432px -0; } -.ui-icon-star { background-position: -468px -0; } -.ui-icon-alert { background-position: -504px -0; } -.ui-icon-info { background-position: -540px -0; } -.ui-icon-home { background-position: -576px -0; } -.ui-icon-search,.ui-icon-searchfield:after { background-position: -612px -0; } -.ui-icon-checkbox-off { background-position: -684px -0; } -.ui-icon-checkbox-on { background-position: -648px -0; } -.ui-icon-radio-off { background-position: -756px -0; } -.ui-icon-radio-on { background-position: -718px -0; } - -/* begin icon pack definitions */ -/* second row */ -.ui-icon-email { background-position: -0 -18px; } -.ui-icon-page { background-position: -36px -18px; } -.ui-icon-question { background-position: -72px -18px; } -.ui-icon-foursquare { background-position: -108px -18px; } -.ui-icon-twitter { background-position: -144px -18px; } -.ui-icon-facebook { background-position: -180px -18px; } -.ui-icon-dollar { background-position: -216px -18px; } -.ui-icon-euro { background-position: -252px -18px; } -.ui-icon-pound { background-position: -288px -18px; } -.ui-icon-apple { background-position: -324px -18px; } -.ui-icon-chat { background-position: -360px -18px; } -.ui-icon-trash { background-position: -396px -18px; } -.ui-icon-bell { background-position: -432px -18px; } -.ui-icon-mappin { background-position: -468px -18px;} -.ui-icon-direction { background-position: -504px -18px; } -.ui-icon-heart { background-position: -540px -18px; } -.ui-icon-wrench { background-position: -576px -18px; } -.ui-icon-play { background-position: -612px -18px; } -.ui-icon-pause { background-position: -648px -18px; } -.ui-icon-stop { background-position: -684px -18px; } -.ui-icon-person { background-position: -720px -18px; } -.ui-icon-music { background-position: -756px -18px; } - -/* third row */ -.ui-icon-rss { background-position: -0 -36px; } -.ui-icon-wifi { background-position: -36px -36px; } -.ui-icon-phone { background-position: -72px -36px; } -.ui-icon-power { background-position: -109px -36px; } -.ui-icon-lock { background-position: -144px -36px; } -.ui-icon-flag { background-position: -180px -36px; } -.ui-icon-calendar { background-position: -216px -36px; } -.ui-icon-lightning { background-position: -252px -36px; } -.ui-icon-drink { background-position: -288px -36px; } -.ui-icon-android { background-position: -324px -36px; } -.ui-icon-edit { background-position: -360px -36px; } \ No newline at end of file diff --git a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/ajax-loader.gif b/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/ajax-loader.gif deleted file mode 100644 index fd1a189c21..0000000000 Binary files a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/ajax-loader.gif and /dev/null differ diff --git a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/ajax-loader.png b/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/ajax-loader.png deleted file mode 100644 index 13b208dddd..0000000000 Binary files a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/ajax-loader.png and /dev/null differ diff --git a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/icons-18-black.png b/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/icons-18-black.png deleted file mode 100644 index ce1b758ad5..0000000000 Binary files a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/icons-18-black.png and /dev/null differ diff --git a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/icons-18-white.png b/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/icons-18-white.png deleted file mode 100644 index 1ab0127237..0000000000 Binary files a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/icons-18-white.png and /dev/null differ diff --git a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/icons-36-black.png b/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/icons-36-black.png deleted file mode 100644 index 1a59d7c375..0000000000 Binary files a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/icons-36-black.png and /dev/null differ diff --git a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/icons-36-white.png b/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/icons-36-white.png deleted file mode 100644 index 5647bdc945..0000000000 Binary files a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/images/icons-36-white.png and /dev/null differ diff --git a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/jquery.mobile-1.1.0.css b/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/jquery.mobile-1.1.0.css deleted file mode 100644 index 06dbf8f929..0000000000 --- a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/jquery.mobile-1.1.0.css +++ /dev/null @@ -1,2053 +0,0 @@ -/* -* jQuery Mobile Framework 1.1.0 db342b1f315c282692791aa870455901fdb46a55 -* http://jquerymobile.com -* -* Copyright 2011 (c) jQuery Project -* Dual licensed under the MIT or GPL Version 2 licenses. -* http://jquery.org/license -* -*/ -/* Swatches */ -/* A ------------------------------------------------------------------------------------------------------------*/ -.ui-bar-a { - border: 1px solid #333 /*{a-bar-border}*/; - background: #111111 /*{a-bar-background-color}*/; - color: #ffffff /*{a-bar-color}*/; - font-weight: bold; - text-shadow: 0 /*{a-bar-shadow-x}*/ -1px /*{a-bar-shadow-y}*/ 1px /*{a-bar-shadow-radius}*/ #000000 /*{a-bar-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #3c3c3c /*{a-bar-background-start}*/), to( #111 /*{a-bar-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #3c3c3c /*{a-bar-background-start}*/, #111 /*{a-bar-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #3c3c3c /*{a-bar-background-start}*/, #111 /*{a-bar-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #3c3c3c /*{a-bar-background-start}*/, #111 /*{a-bar-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #3c3c3c /*{a-bar-background-start}*/, #111 /*{a-bar-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #3c3c3c /*{a-bar-background-start}*/, #111 /*{a-bar-background-end}*/); -} -.ui-bar-a, -.ui-bar-a input, -.ui-bar-a select, -.ui-bar-a textarea, -.ui-bar-a button { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; -} -.ui-bar-a .ui-link-inherit { - color: #fff /*{a-bar-color}*/; -} -.ui-bar-a .ui-link { - color: #7cc4e7 /*{a-bar-link-color}*/; - font-weight: bold; -} -.ui-bar-a .ui-link:hover { - color: #2489CE /*{a-bar-link-hover}*/; -} -.ui-bar-a .ui-link:active { - color: #2489CE /*{a-bar-link-active}*/; -} -.ui-bar-a .ui-link:visited { - color: #2489CE /*{a-bar-link-visited}*/; -} -.ui-body-a, -.ui-overlay-a { - border: 1px solid #444 /*{a-body-border}*/; - background: #222 /*{a-body-background-color}*/; - color: #fff /*{a-body-color}*/; - text-shadow: 0 /*{a-body-shadow-x}*/ 1px /*{a-body-shadow-y}*/ 1px /*{a-body-shadow-radius}*/ #111 /*{a-body-shadow-color}*/; - font-weight: normal; - background-image: -webkit-gradient(linear, left top, left bottom, from( #444 /*{a-body-background-start}*/), to( #222 /*{a-body-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #444 /*{a-body-background-start}*/, #222 /*{a-body-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #444 /*{a-body-background-start}*/, #222 /*{a-body-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #444 /*{a-body-background-start}*/, #222 /*{a-body-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #444 /*{a-body-background-start}*/, #222 /*{a-body-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #444 /*{a-body-background-start}*/, #222 /*{a-body-background-end}*/); -} -.ui-overlay-a { - background-image: none; - border-width: 0; -} -.ui-body-a, -.ui-body-a input, -.ui-body-a select, -.ui-body-a textarea, -.ui-body-a button { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; -} -.ui-body-a .ui-link-inherit { - color: #fff /*{a-body-color}*/; -} -.ui-body-a .ui-link { - color: #2489CE /*{a-body-link-color}*/; - font-weight: bold; -} -.ui-body-a .ui-link:hover { - color: #2489CE /*{a-body-link-hover}*/; -} -.ui-body-a .ui-link:active { - color: #2489CE /*{a-body-link-active}*/; -} -.ui-body-a .ui-link:visited { - color: #2489CE /*{a-body-link-visited}*/; -} -.ui-btn-up-a { - border: 1px solid #111 /*{a-bup-border}*/; - background: #333 /*{a-bup-background-color}*/; - font-weight: bold; - color: #fff /*{a-bup-color}*/; - text-shadow: 0 /*{a-bup-shadow-x}*/ 1px /*{a-bup-shadow-y}*/ 1px /*{a-bup-shadow-radius}*/ #111 /*{a-bup-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #444444 /*{a-bup-background-start}*/), to( #2d2d2d /*{a-bup-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #444444 /*{a-bup-background-start}*/, #2d2d2d /*{a-bup-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #444444 /*{a-bup-background-start}*/, #2d2d2d /*{a-bup-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #444444 /*{a-bup-background-start}*/, #2d2d2d /*{a-bup-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #444444 /*{a-bup-background-start}*/, #2d2d2d /*{a-bup-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #444444 /*{a-bup-background-start}*/, #2d2d2d /*{a-bup-background-end}*/); -} -.ui-btn-up-a a.ui-link-inherit { - color: #fff /*{a-bup-color}*/; -} -.ui-btn-hover-a { - border: 1px solid #000 /*{a-bhover-border}*/; - background: #444444 /*{a-bhover-background-color}*/; - font-weight: bold; - color: #fff /*{a-bhover-color}*/; - text-shadow: 0 /*{a-bhover-shadow-x}*/ 1px /*{a-bhover-shadow-y}*/ 1px /*{a-bhover-shadow-radius}*/ #111 /*{a-bhover-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #555555 /*{a-bhover-background-start}*/), to( #383838 /*{a-bhover-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #555555 /*{a-bhover-background-start}*/, #383838 /*{a-bhover-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #555555 /*{a-bhover-background-start}*/, #383838 /*{a-bhover-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #555555 /*{a-bhover-background-start}*/, #383838 /*{a-bhover-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #555555 /*{a-bhover-background-start}*/, #383838 /*{a-bhover-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #555555 /*{a-bhover-background-start}*/, #383838 /*{a-bhover-background-end}*/); -} -.ui-btn-hover-a a.ui-link-inherit { - color: #fff /*{a-bhover-color}*/; -} -.ui-btn-down-a { - border: 1px solid #000 /*{a-bdown-border}*/; - background: #222 /*{a-bdown-background-color}*/; - font-weight: bold; - color: #fff /*{a-bdown-color}*/; - text-shadow: 0 /*{a-bdown-shadow-x}*/ 1px /*{a-bdown-shadow-y}*/ 1px /*{a-bdown-shadow-radius}*/ #111 /*{a-bdown-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #202020 /*{a-bdown-background-start}*/), to( #2c2c2c /*{a-bdown-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #202020 /*{a-bdown-background-start}*/, #2c2c2c /*{a-bdown-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #202020 /*{a-bdown-background-start}*/, #2c2c2c /*{a-bdown-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #202020 /*{a-bdown-background-start}*/, #2c2c2c /*{a-bdown-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #202020 /*{a-bdown-background-start}*/, #2c2c2c /*{a-bdown-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #202020 /*{a-bdown-background-start}*/, #2c2c2c /*{a-bdown-background-end}*/); -} -.ui-btn-down-a a.ui-link-inherit { - color: #fff /*{a-bdown-color}*/; -} -.ui-btn-up-a, -.ui-btn-hover-a, -.ui-btn-down-a { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; - text-decoration: none; -} -/* B ------------------------------------------------------------------------------------------------------------*/ -.ui-bar-b { - border: 1px solid #456f9a /*{b-bar-border}*/; - background: #5e87b0 /*{b-bar-background-color}*/; - color: #fff /*{b-bar-color}*/; - font-weight: bold; - text-shadow: 0 /*{b-bar-shadow-x}*/ 1px /*{b-bar-shadow-y}*/ 1px /*{b-bar-shadow-radius}*/ #3e6790 /*{b-bar-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #6facd5 /*{b-bar-background-start}*/), to( #497bae /*{b-bar-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #6facd5 /*{b-bar-background-start}*/, #497bae /*{b-bar-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #6facd5 /*{b-bar-background-start}*/, #497bae /*{b-bar-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #6facd5 /*{b-bar-background-start}*/, #497bae /*{b-bar-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #6facd5 /*{b-bar-background-start}*/, #497bae /*{b-bar-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #6facd5 /*{b-bar-background-start}*/, #497bae /*{b-bar-background-end}*/); -} -.ui-bar-b, -.ui-bar-b input, -.ui-bar-b select, -.ui-bar-b textarea, -.ui-bar-b button { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; -} -.ui-bar-b .ui-link-inherit { - color: #fff /*{b-bar-color}*/; -} -.ui-bar-b .ui-link { - color: #ddf0f8 /*{b-bar-link-color}*/; - font-weight: bold; -} -.ui-bar-b .ui-link:hover { - color: #ddf0f8 /*{b-bar-link-hover}*/; -} -.ui-bar-b .ui-link:active { - color: #ddf0f8 /*{b-bar-link-active}*/; -} -.ui-bar-b .ui-link:visited { - color: #ddf0f8 /*{b-bar-link-visited}*/; -} -.ui-body-b, -.ui-overlay-b { - border: 1px solid #999 /*{b-body-border}*/; - background: #f3f3f3 /*{b-body-background-color}*/; - color: #222222 /*{b-body-color}*/; - text-shadow: 0 /*{b-body-shadow-x}*/ 1px /*{b-body-shadow-y}*/ 0 /*{b-body-shadow-radius}*/ #fff /*{b-body-shadow-color}*/; - font-weight: normal; - background-image: -webkit-gradient(linear, left top, left bottom, from( #ddd /*{b-body-background-start}*/), to( #ccc /*{b-body-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #ddd /*{b-body-background-start}*/, #ccc /*{b-body-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #ddd /*{b-body-background-start}*/, #ccc /*{b-body-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #ddd /*{b-body-background-start}*/, #ccc /*{b-body-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #ddd /*{b-body-background-start}*/, #ccc /*{b-body-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #ddd /*{b-body-background-start}*/, #ccc /*{b-body-background-end}*/); -} -.ui-overlay-b { - background-image: none; - border-width: 0; -} -.ui-body-b, -.ui-body-b input, -.ui-body-b select, -.ui-body-b textarea, -.ui-body-b button { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; -} -.ui-body-b .ui-link-inherit { - color: #333333 /*{b-body-color}*/; -} -.ui-body-b .ui-link { - color: #2489CE /*{b-body-link-color}*/; - font-weight: bold; -} -.ui-body-b .ui-link:hover { - color: #2489CE /*{b-body-link-hover}*/; -} -.ui-body-b .ui-link:active { - color: #2489CE /*{b-body-link-active}*/; -} -.ui-body-b .ui-link:visited { - color: #2489CE /*{b-body-link-visited}*/; -} -.ui-btn-up-b { - border: 1px solid #044062 /*{b-bup-border}*/; - background: #396b9e /*{b-bup-background-color}*/; - font-weight: bold; - color: #fff /*{b-bup-color}*/; - text-shadow: 0 /*{b-bup-shadow-x}*/ 1px /*{b-bup-shadow-y}*/ 1px /*{b-bup-shadow-radius}*/ #194b7e /*{b-bup-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #5f9cc5 /*{b-bup-background-start}*/), to( #396b9e /*{b-bup-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #5f9cc5 /*{b-bup-background-start}*/, #396b9e /*{b-bup-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #5f9cc5 /*{b-bup-background-start}*/, #396b9e /*{b-bup-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #5f9cc5 /*{b-bup-background-start}*/, #396b9e /*{b-bup-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #5f9cc5 /*{b-bup-background-start}*/, #396b9e /*{b-bup-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #5f9cc5 /*{b-bup-background-start}*/, #396b9e /*{b-bup-background-end}*/); -} -.ui-btn-up-b a.ui-link-inherit { - color: #fff /*{b-bup-color}*/; -} -.ui-btn-hover-b { - border: 1px solid #00415e /*{b-bhover-border}*/; - background: #4b88b6 /*{b-bhover-background-color}*/; - font-weight: bold; - color: #fff /*{b-bhover-color}*/; - text-shadow: 0 /*{b-bhover-shadow-x}*/ 1px /*{b-bhover-shadow-y}*/ 1px /*{b-bhover-shadow-radius}*/ #194b7e /*{b-bhover-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #6facd5 /*{b-bhover-background-start}*/), to( #4272a4 /*{b-bhover-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #6facd5 /*{b-bhover-background-start}*/, #4272a4 /*{b-bhover-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #6facd5 /*{b-bhover-background-start}*/, #4272a4 /*{b-bhover-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #6facd5 /*{b-bhover-background-start}*/, #4272a4 /*{b-bhover-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #6facd5 /*{b-bhover-background-start}*/, #4272a4 /*{b-bhover-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #6facd5 /*{b-bhover-background-start}*/, #4272a4 /*{b-bhover-background-end}*/); -} -.ui-btn-hover-b a.ui-link-inherit { - color: #fff /*{b-bhover-color}*/; -} -.ui-btn-down-b { - border: 1px solid #225377 /*{b-bdown-border}*/; - background: #4e89c5 /*{b-bdown-background-color}*/; - font-weight: bold; - color: #fff /*{b-bdown-color}*/; - text-shadow: 0 /*{b-bdown-shadow-x}*/ 1px /*{b-bdown-shadow-y}*/ 1px /*{b-bdown-shadow-radius}*/ #194b7e /*{b-bdown-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #295b8e /*{b-bdown-background-start}*/), to( #3e79b5 /*{b-bdown-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #295b8e /*{b-bdown-background-start}*/, #3e79b5 /*{b-bdown-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #295b8e /*{b-bdown-background-start}*/, #3e79b5 /*{b-bdown-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #295b8e /*{b-bdown-background-start}*/, #3e79b5 /*{b-bdown-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #295b8e /*{b-bdown-background-start}*/, #3e79b5 /*{b-bdown-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #295b8e /*{b-bdown-background-start}*/, #3e79b5 /*{b-bdown-background-end}*/); -} -.ui-btn-down-b a.ui-link-inherit { - color: #fff /*{b-bdown-color}*/; -} -.ui-btn-up-b, -.ui-btn-hover-b, -.ui-btn-down-b { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; - text-decoration: none; -} -/* C ------------------------------------------------------------------------------------------------------------*/ -.ui-bar-c { - border: 1px solid #B3B3B3 /*{c-bar-border}*/; - background: #eeeeee /*{c-bar-background-color}*/; - color: #3E3E3E /*{c-bar-color}*/; - font-weight: bold; - text-shadow: 0 /*{c-bar-shadow-x}*/ 1px /*{c-bar-shadow-y}*/ 1px /*{c-bar-shadow-radius}*/ #fff /*{c-bar-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #f0f0f0 /*{c-bar-background-start}*/), to( #ddd /*{c-bar-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #f0f0f0 /*{c-bar-background-start}*/, #ddd /*{c-bar-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #f0f0f0 /*{c-bar-background-start}*/, #ddd /*{c-bar-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #f0f0f0 /*{c-bar-background-start}*/, #ddd /*{c-bar-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #f0f0f0 /*{c-bar-background-start}*/, #ddd /*{c-bar-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #f0f0f0 /*{c-bar-background-start}*/, #ddd /*{c-bar-background-end}*/); -} -.ui-bar-c .ui-link-inherit { - color: #3E3E3E /*{c-bar-color}*/; -} -.ui-bar-c .ui-link { - color: #7cc4e7 /*{c-bar-link-color}*/; - font-weight: bold; -} -.ui-bar-c .ui-link:hover { - color: #2489CE /*{c-bar-link-hover}*/; -} -.ui-bar-c .ui-link:active { - color: #2489CE /*{c-bar-link-active}*/; -} -.ui-bar-c .ui-link:visited { - color: #2489CE /*{c-bar-link-visited}*/; -} -.ui-bar-c, -.ui-bar-c input, -.ui-bar-c select, -.ui-bar-c textarea, -.ui-bar-c button { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; -} -.ui-body-c, -.ui-overlay-c { - border: 1px solid #aaa /*{c-body-border}*/; - color: #333333 /*{c-body-color}*/; - text-shadow: 0 /*{c-body-shadow-x}*/ 1px /*{c-body-shadow-y}*/ 0 /*{c-body-shadow-radius}*/ #fff /*{c-body-shadow-color}*/; - background: #f9f9f9 /*{c-body-background-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #f9f9f9 /*{c-body-background-start}*/), to( #eeeeee /*{c-body-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #f9f9f9 /*{c-body-background-start}*/, #eeeeee /*{c-body-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #f9f9f9 /*{c-body-background-start}*/, #eeeeee /*{c-body-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #f9f9f9 /*{c-body-background-start}*/, #eeeeee /*{c-body-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #f9f9f9 /*{c-body-background-start}*/, #eeeeee /*{c-body-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #f9f9f9 /*{c-body-background-start}*/, #eeeeee /*{c-body-background-end}*/); -} -.ui-overlay-c { - background-image: none; - border-width: 0; -} -.ui-body-c, -.ui-body-c input, -.ui-body-c select, -.ui-body-c textarea, -.ui-body-c button { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; -} -.ui-body-c .ui-link-inherit { - color: #333333 /*{c-body-color}*/; -} -.ui-body-c .ui-link { - color: #2489CE /*{c-body-link-color}*/; - font-weight: bold; -} -.ui-body-c .ui-link:hover { - color: #2489CE /*{c-body-link-hover}*/; -} -.ui-body-c .ui-link:active { - color: #2489CE /*{c-body-link-active}*/; -} -.ui-body-c .ui-link:visited { - color: #2489CE /*{c-body-link-visited}*/; -} -.ui-btn-up-c { - border: 1px solid #ccc /*{c-bup-border}*/; - background: #eee /*{c-bup-background-color}*/; - font-weight: bold; - color: #222 /*{c-bup-color}*/; - text-shadow: 0 /*{c-bup-shadow-x}*/ 1px /*{c-bup-shadow-y}*/ 0 /*{c-bup-shadow-radius}*/ #ffffff /*{c-bup-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #ffffff /*{c-bup-background-start}*/), to( #f1f1f1 /*{c-bup-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #ffffff /*{c-bup-background-start}*/, #f1f1f1 /*{c-bup-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #ffffff /*{c-bup-background-start}*/, #f1f1f1 /*{c-bup-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #ffffff /*{c-bup-background-start}*/, #f1f1f1 /*{c-bup-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #ffffff /*{c-bup-background-start}*/, #f1f1f1 /*{c-bup-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #ffffff /*{c-bup-background-start}*/, #f1f1f1 /*{c-bup-background-end}*/); -} -.ui-btn-up-c a.ui-link-inherit { - color: #2F3E46 /*{c-bup-color}*/; -} -.ui-btn-hover-c { - border: 1px solid #bbb /*{c-bhover-border}*/; - background: #dfdfdf /*{c-bhover-background-color}*/; - font-weight: bold; - color: #222 /*{c-bhover-color}*/; - text-shadow: 0 /*{c-bhover-shadow-x}*/ 1px /*{c-bhover-shadow-y}*/ 0 /*{c-bhover-shadow-radius}*/ #ffffff /*{c-bhover-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #f6f6f6 /*{c-bhover-background-start}*/), to( #e0e0e0 /*{c-bhover-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #f9f9f9 /*{c-bhover-background-start}*/, #e0e0e0 /*{c-bhover-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #f6f6f6 /*{c-bhover-background-start}*/, #e0e0e0 /*{c-bhover-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #f6f6f6 /*{c-bhover-background-start}*/, #e0e0e0 /*{c-bhover-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #f6f6f6 /*{c-bhover-background-start}*/, #e0e0e0 /*{c-bhover-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #f6f6f6 /*{c-bhover-background-start}*/, #e0e0e0 /*{c-bhover-background-end}*/); -} -.ui-btn-hover-c a.ui-link-inherit { - color: #2F3E46 /*{c-bhover-color}*/; -} -.ui-btn-down-c { - border: 1px solid #bbb /*{c-bdown-border}*/; - background: #d6d6d6 /*{c-bdown-background-color}*/; - font-weight: bold; - color: #222 /*{c-bdown-color}*/; - text-shadow: 0 /*{c-bdown-shadow-x}*/ 1px /*{c-bdown-shadow-y}*/ 0 /*{c-bdown-shadow-radius}*/ #ffffff /*{c-bdown-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #d0d0d0 /*{c-bdown-background-start}*/), to( #dfdfdf /*{c-bdown-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #d0d0d0 /*{c-bdown-background-start}*/, #dfdfdf /*{c-bdown-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #d0d0d0 /*{c-bdown-background-start}*/, #dfdfdf /*{c-bdown-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #d0d0d0 /*{c-bdown-background-start}*/, #dfdfdf /*{c-bdown-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #d0d0d0 /*{c-bdown-background-start}*/, #dfdfdf /*{c-bdown-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #d0d0d0 /*{c-bdown-background-start}*/, #dfdfdf /*{c-bdown-background-end}*/); -} -.ui-btn-down-c a.ui-link-inherit { - color: #2F3E46 /*{c-bdown-color}*/; -} -.ui-btn-up-c, -.ui-btn-hover-c, -.ui-btn-down-c { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; - text-decoration: none; -} -/* D ------------------------------------------------------------------------------------------------------------*/ -.ui-bar-d { - border: 1px solid #bbb /*{d-bar-border}*/; - background: #bbb /*{d-bar-background-color}*/; - color: #333 /*{d-bar-color}*/; - text-shadow: 0 /*{d-bar-shadow-x}*/ 1px /*{d-bar-shadow-y}*/ 0 /*{d-bar-shadow-radius}*/ #eee /*{d-bar-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #ddd /*{d-bar-background-start}*/), to( #bbb /*{d-bar-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #ddd /*{d-bar-background-start}*/, #bbb /*{d-bar-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #ddd /*{d-bar-background-start}*/, #bbb /*{d-bar-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #ddd /*{d-bar-background-start}*/, #bbb /*{d-bar-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #ddd /*{d-bar-background-start}*/, #bbb /*{d-bar-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #ddd /*{d-bar-background-start}*/, #bbb /*{d-bar-background-end}*/); -} -.ui-bar-d, -.ui-bar-d input, -.ui-bar-d select, -.ui-bar-d textarea, -.ui-bar-d button { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; -} -.ui-bar-d .ui-link-inherit { - color: #333333 /*{d-bar-color}*/; -} -.ui-bar-d .ui-link { - color: #2489CE /*{d-bar-link-color}*/; - font-weight: bold; -} -.ui-bar-d .ui-link:hover { - color: #2489CE /*{d-bar-link-hover}*/; -} -.ui-bar-d .ui-link:active { - color: #2489CE /*{d-bar-link-active}*/; -} -.ui-bar-d .ui-link:visited { - color: #2489CE /*{d-bar-link-visited}*/; -} -.ui-body-d, -.ui-overlay-d { - border: 1px solid #bbb /*{d-body-border}*/; - color: #333333 /*{d-body-color}*/; - text-shadow: 0 /*{d-body-shadow-x}*/ 1px /*{d-body-shadow-y}*/ 0 /*{d-body-shadow-radius}*/ #fff /*{d-body-shadow-color}*/; - background: #ffffff /*{d-body-background-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #fff), to( #fff /*{d-body-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #fff /*{d-body-background-start}*/, #fff /*{d-body-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #fff /*{d-body-background-start}*/, #fff /*{d-body-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #fff /*{d-body-background-start}*/, #fff /*{d-body-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #fff /*{d-body-background-start}*/, #fff /*{d-body-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #fff /*{d-body-background-start}*/, #fff /*{d-body-background-end}*/); -} -.ui-overlay-d { - background-image: none; - border-width: 0; -} -.ui-body-d, -.ui-body-d input, -.ui-body-d select, -.ui-body-d textarea, -.ui-body-d button { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; -} -.ui-body-d .ui-link-inherit { - color: #333333 /*{d-body-color}*/; -} -.ui-body-d .ui-link { - color: #2489CE /*{d-body-link-color}*/; - font-weight: bold; -} -.ui-body-d .ui-link:hover { - color: #2489CE /*{d-body-link-hover}*/; -} -.ui-body-d .ui-link:active { - color: #2489CE /*{d-body-link-active}*/; -} -.ui-body-d .ui-link:visited { - color: #2489CE /*{d-body-link-visited}*/; -} -.ui-btn-up-d { - border: 1px solid #bbb /*{d-bup-border}*/; - background: #fff /*{d-bup-background-color}*/; - font-weight: bold; - color: #333 /*{d-bup-color}*/; - text-shadow: 0 /*{d-bup-shadow-x}*/ 1px /*{d-bup-shadow-y}*/ 0 /*{d-bup-shadow-radius}*/ #fff /*{d-bup-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #fafafa), to( #f6f6f6 /*{d-bup-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #fafafa /*{d-bup-background-start}*/, #f6f6f6 /*{d-bup-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #fafafa /*{d-bup-background-start}*/, #f6f6f6 /*{d-bup-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #fafafa /*{d-bup-background-start}*/, #f6f6f6 /*{d-bup-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #fafafa /*{d-bup-background-start}*/, #f6f6f6 /*{d-bup-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #fafafa /*{d-bup-background-start}*/, #f6f6f6 /*{d-bup-background-end}*/); -} -.ui-btn-up-d a.ui-link-inherit { - color: #333 /*{d-bup-color}*/; -} -.ui-btn-hover-d { - border: 1px solid #aaa /*{d-bhover-border}*/; - background: #eeeeee /*{d-bhover-background-color}*/; - font-weight: bold; - color: #333 /*{d-bhover-color}*/; - cursor: pointer; - text-shadow: 0 /*{d-bhover-shadow-x}*/ 1px /*{d-bhover-shadow-y}*/ 0 /*{d-bhover-shadow-radius}*/ #fff /*{d-bhover-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #eee), to( #fff /*{d-bhover-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #eee /*{d-bhover-background-start}*/, #fff /*{d-bhover-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #eee /*{d-bhover-background-start}*/, #fff /*{d-bhover-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #eee /*{d-bhover-background-start}*/, #fff /*{d-bhover-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #eee /*{d-bhover-background-start}*/, #fff /*{d-bhover-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #eee /*{d-bhover-background-start}*/, #fff /*{d-bhover-background-end}*/); -} -.ui-btn-hover-d a.ui-link-inherit { - color: #333 /*{d-bhover-color}*/; -} -.ui-btn-down-d { - border: 1px solid #aaa /*{d-bdown-border}*/; - background: #eee /*{d-bdown-background-color}*/; - font-weight: bold; - color: #333 /*{d-bdown-color}*/; - text-shadow: 0 /*{d-bdown-shadow-x}*/ 1px /*{d-bdown-shadow-y}*/ 0 /*{d-bdown-shadow-radius}*/ #ffffff /*{d-bdown-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #e5e5e5 /*{d-bdown-background-start}*/), to( #f2f2f2 /*{d-bdown-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #e5e5e5 /*{d-bdown-background-start}*/, #f2f2f2 /*{d-bdown-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #e5e5e5 /*{d-bdown-background-start}*/, #f2f2f2 /*{d-bdown-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #e5e5e5 /*{d-bdown-background-start}*/, #f2f2f2 /*{d-bdown-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #e5e5e5 /*{d-bdown-background-start}*/, #f2f2f2 /*{d-bdown-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #e5e5e5 /*{d-bdown-background-start}*/, #f2f2f2 /*{d-bdown-background-end}*/); -} -.ui-btn-down-d a.ui-link-inherit { - color: #333 /*{d-bdown-color}*/; -} -.ui-btn-up-d, -.ui-btn-hover-d, -.ui-btn-down-d { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; - text-decoration: none; -} -/* E ------------------------------------------------------------------------------------------------------------*/ -.ui-bar-e { - border: 1px solid #F7C942 /*{e-bar-border}*/; - background: #fadb4e /*{e-bar-background-color}*/; - color: #333 /*{e-bar-color}*/; - text-shadow: 0 /*{e-bar-shadow-x}*/ 1px /*{e-bar-shadow-y}*/ 0 /*{e-bar-shadow-radius}*/ #fff /*{e-bar-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #fceda7 /*{e-bar-background-start}*/), to( #fbef7e /*{e-bar-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #fceda7 /*{e-bar-background-start}*/, #fbef7e /*{e-bar-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #fceda7 /*{e-bar-background-start}*/, #fbef7e /*{e-bar-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #fceda7 /*{e-bar-background-start}*/, #fbef7e /*{e-bar-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #fceda7 /*{e-bar-background-start}*/, #fbef7e /*{e-bar-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #fceda7 /*{e-bar-background-start}*/, #fbef7e /*{e-bar-background-end}*/); -} -.ui-bar-e, -.ui-bar-e input, -.ui-bar-e select, -.ui-bar-e textarea, -.ui-bar-e button { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; -} -.ui-bar-e .ui-link-inherit { - color: #333333 /*{e-bar-color}*/; -} -.ui-bar-e .ui-link { - color: #2489CE /*{e-bar-link-color}*/; - font-weight: bold; -} -.ui-bar-e .ui-link:hover { - color: #2489CE /*{e-bar-link-hover}*/; -} -.ui-bar-e .ui-link:active { - color: #2489CE /*{e-bar-link-active}*/; -} -.ui-bar-e .ui-link:visited { - color: #2489CE /*{e-bar-link-visited}*/; -} -.ui-body-e, -.ui-overlay-e { - border: 1px solid #F7C942 /*{e-body-border}*/; - color: #222222 /*{e-body-color}*/; - text-shadow: 0 /*{e-body-shadow-x}*/ 1px /*{e-body-shadow-y}*/ 0 /*{e-body-shadow-radius}*/ #fff /*{e-body-shadow-color}*/; - background: #fff9df /*{e-body-background-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #fffadf /*{e-body-background-start}*/), to( #fff3a5 /*{e-body-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #fffadf /*{e-body-background-start}*/, #fff3a5 /*{e-body-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #fffadf /*{e-body-background-start}*/, #fff3a5 /*{e-body-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #fffadf /*{e-body-background-start}*/, #fff3a5 /*{e-body-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #fffadf /*{e-body-background-start}*/, #fff3a5 /*{e-body-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #fffadf /*{e-body-background-start}*/, #fff3a5 /*{e-body-background-end}*/); -} -.ui-overlay-e { - background-image: none; - border-width: 0; -} -.ui-body-e, -.ui-body-e input, -.ui-body-e select, -.ui-body-e textarea, -.ui-body-e button { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; -} -.ui-body-e .ui-link-inherit { - color: #333333 /*{e-body-color}*/; -} -.ui-body-e .ui-link { - color: #2489CE /*{e-body-link-color}*/; - font-weight: bold; -} -.ui-body-e .ui-link:hover { - color: #2489CE /*{e-body-link-hover}*/; -} -.ui-body-e .ui-link:active { - color: #2489CE /*{e-body-link-active}*/; -} -.ui-body-e .ui-link:visited { - color: #2489CE /*{e-body-link-visited}*/; -} -.ui-btn-up-e { - border: 1px solid #F4C63f /*{e-bup-border}*/; - background: #fadb4e /*{e-bup-background-color}*/; - font-weight: bold; - color: #222 /*{e-bup-color}*/; - text-shadow: 0 /*{e-bup-shadow-x}*/ 1px /*{e-bup-shadow-y}*/ 0 /*{e-bup-shadow-radius}*/ #fff /*{e-bup-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #ffefaa /*{e-bup-background-start}*/), to( #ffe155 /*{e-bup-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #ffefaa /*{e-bup-background-start}*/, #ffe155 /*{e-bup-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #ffefaa /*{e-bup-background-start}*/, #ffe155 /*{e-bup-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #ffefaa /*{e-bup-background-start}*/, #ffe155 /*{e-bup-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #ffefaa /*{e-bup-background-start}*/, #ffe155 /*{e-bup-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #ffefaa /*{e-bup-background-start}*/, #ffe155 /*{e-bup-background-end}*/); -} -.ui-btn-up-e a.ui-link-inherit { - color: #222 /*{e-bup-color}*/; -} -.ui-btn-hover-e { - border: 1px solid #F2C43d /*{e-bhover-border}*/; - background: #fbe26f /*{e-bhover-background-color}*/; - font-weight: bold; - color: #111 /*{e-bhover-color}*/; - text-shadow: 0 /*{e-bhover-shadow-x}*/ 1px /*{e-bhover-shadow-y}*/ 0 /*{e-bhover-shadow-radius}*/ #fff /*{e-bhover-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #fff5ba /*{e-bhover-background-start}*/), to( #fbdd52 /*{e-bhover-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #fff5ba /*{e-bhover-background-start}*/, #fbdd52 /*{e-bhover-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #fff5ba /*{e-bhover-background-start}*/, #fbdd52 /*{e-bhover-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #fff5ba /*{e-bhover-background-start}*/, #fbdd52 /*{e-bhover-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #fff5ba /*{e-bhover-background-start}*/, #fbdd52 /*{e-bhover-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #fff5ba /*{e-bhover-background-start}*/, #fbdd52 /*{e-bhover-background-end}*/); -} -.ui-btn-hover-e a.ui-link-inherit { - color: #333 /*{e-bhover-color}*/; -} -.ui-btn-down-e { - border: 1px solid #F2C43d /*{e-bdown-border}*/; - background: #fceda7 /*{e-bdown-background-color}*/; - font-weight: bold; - color: #111 /*{e-bdown-color}*/; - text-shadow: 0 /*{e-bdown-shadow-x}*/ 1px /*{e-bdown-shadow-y}*/ 0 /*{e-bdown-shadow-radius}*/ #ffffff /*{e-bdown-shadow-color}*/; - background-image: -webkit-gradient(linear, left top, left bottom, from( #f8d94c /*{e-bdown-background-start}*/), to( #fadb4e /*{e-bdown-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #f8d94c /*{e-bdown-background-start}*/, #fadb4e /*{e-bdown-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #f8d94c /*{e-bdown-background-start}*/, #fadb4e /*{e-bdown-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #f8d94c /*{e-bdown-background-start}*/, #fadb4e /*{e-bdown-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #f8d94c /*{e-bdown-background-start}*/, #fadb4e /*{e-bdown-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #f8d94c /*{e-bdown-background-start}*/, #fadb4e /*{e-bdown-background-end}*/); -} -.ui-btn-down-e a.ui-link-inherit { - color: #333 /*{e-bdown-color}*/; -} -.ui-btn-up-e, -.ui-btn-hover-e, -.ui-btn-down-e { - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; - text-decoration: none; -} -/* Structure */ -/* links within "buttons" ------------------------------------------------------------------------------------------------------------*/ -a.ui-link-inherit { - text-decoration: none !important; -} -/* Active class used as the "on" state across all themes ------------------------------------------------------------------------------------------------------------*/ -.ui-btn-active { - border: 1px solid #2373a5 /*{global-active-border}*/; - background: #5393c5 /*{global-active-background-color}*/; - font-weight: bold; - color: #fff /*{global-active-color}*/; - cursor: pointer; - text-shadow: 0 /*{global-active-shadow-x}*/ 1px /*{global-active-shadow-y}*/ 1px /*{global-active-shadow-radius}*/ #3373a5 /*{global-active-shadow-color}*/; - text-decoration: none; - background-image: -webkit-gradient(linear, left top, left bottom, from( #5393c5 /*{global-active-background-start}*/), to( #6facd5 /*{global-active-background-end}*/)); /* Saf4+, Chrome */ - background-image: -webkit-linear-gradient( #5393c5 /*{global-active-background-start}*/, #6facd5 /*{global-active-background-end}*/); /* Chrome 10+, Saf5.1+ */ - background-image: -moz-linear-gradient( #5393c5 /*{global-active-background-start}*/, #6facd5 /*{global-active-background-end}*/); /* FF3.6 */ - background-image: -ms-linear-gradient( #5393c5 /*{global-active-background-start}*/, #6facd5 /*{global-active-background-end}*/); /* IE10 */ - background-image: -o-linear-gradient( #5393c5 /*{global-active-background-start}*/, #6facd5 /*{global-active-background-end}*/); /* Opera 11.10+ */ - background-image: linear-gradient( #5393c5 /*{global-active-background-start}*/, #6facd5 /*{global-active-background-end}*/); - font-family: Helvetica, Arial, sans-serif /*{global-font-family}*/; -} -.ui-btn-active a.ui-link-inherit { - color: #fff /*{global-active-color}*/; -} -/* button inner top highlight ------------------------------------------------------------------------------------------------------------*/ -.ui-btn-inner { - border-top: 1px solid #fff; - border-color: rgba(255,255,255,.3); -} -/* corner rounding classes ------------------------------------------------------------------------------------------------------------*/ -.ui-corner-tl { - -moz-border-radius-topleft: .6em /*{global-radii-blocks}*/; - -webkit-border-top-left-radius: .6em /*{global-radii-blocks}*/; - border-top-left-radius: .6em /*{global-radii-blocks}*/; -} -.ui-corner-tr { - -moz-border-radius-topright: .6em /*{global-radii-blocks}*/; - -webkit-border-top-right-radius: .6em /*{global-radii-blocks}*/; - border-top-right-radius: .6em /*{global-radii-blocks}*/; -} -.ui-corner-bl { - -moz-border-radius-bottomleft: .6em /*{global-radii-blocks}*/; - -webkit-border-bottom-left-radius: .6em /*{global-radii-blocks}*/; - border-bottom-left-radius: .6em /*{global-radii-blocks}*/; -} -.ui-corner-br { - -moz-border-radius-bottomright: .6em /*{global-radii-blocks}*/; - -webkit-border-bottom-right-radius: .6em /*{global-radii-blocks}*/; - border-bottom-right-radius: .6em /*{global-radii-blocks}*/; -} -.ui-corner-top { - -moz-border-radius-topleft: .6em /*{global-radii-blocks}*/; - -webkit-border-top-left-radius: .6em /*{global-radii-blocks}*/; - border-top-left-radius: .6em /*{global-radii-blocks}*/; - -moz-border-radius-topright: .6em /*{global-radii-blocks}*/; - -webkit-border-top-right-radius: .6em /*{global-radii-blocks}*/; - border-top-right-radius: .6em /*{global-radii-blocks}*/; -} -.ui-corner-bottom { - -moz-border-radius-bottomleft: .6em /*{global-radii-blocks}*/; - -webkit-border-bottom-left-radius: .6em /*{global-radii-blocks}*/; - border-bottom-left-radius: .6em /*{global-radii-blocks}*/; - -moz-border-radius-bottomright: .6em /*{global-radii-blocks}*/; - -webkit-border-bottom-right-radius: .6em /*{global-radii-blocks}*/; - border-bottom-right-radius: .6em /*{global-radii-blocks}*/; - } -.ui-corner-right { - -moz-border-radius-topright: .6em /*{global-radii-blocks}*/; - -webkit-border-top-right-radius: .6em /*{global-radii-blocks}*/; - border-top-right-radius: .6em /*{global-radii-blocks}*/; - -moz-border-radius-bottomright: .6em /*{global-radii-blocks}*/; - -webkit-border-bottom-right-radius: .6em /*{global-radii-blocks}*/; - border-bottom-right-radius: .6em /*{global-radii-blocks}*/; -} -.ui-corner-left { - -moz-border-radius-topleft: .6em /*{global-radii-blocks}*/; - -webkit-border-top-left-radius: .6em /*{global-radii-blocks}*/; - border-top-left-radius: .6em /*{global-radii-blocks}*/; - -moz-border-radius-bottomleft: .6em /*{global-radii-blocks}*/; - -webkit-border-bottom-left-radius: .6em /*{global-radii-blocks}*/; - border-bottom-left-radius: .6em /*{global-radii-blocks}*/; -} -.ui-corner-all { - -moz-border-radius: .6em /*{global-radii-blocks}*/; - -webkit-border-radius: .6em /*{global-radii-blocks}*/; - border-radius: .6em /*{global-radii-blocks}*/; -} -.ui-corner-none { - -moz-border-radius: 0; - -webkit-border-radius: 0; - border-radius: 0; -} -/* Form field separator ------------------------------------------------------------------------------------------------------------*/ -.ui-br { - border-bottom: rgb(130,130,130); - border-bottom: rgba(130,130,130,.3); - border-bottom-width: 1px; - border-bottom-style: solid; -} -/* Interaction cues ------------------------------------------------------------------------------------------------------------*/ -.ui-disabled { - opacity: .3; -} -.ui-disabled, -.ui-disabled a { - cursor: default !important; - pointer-events: none; -} -.ui-disabled .ui-btn-text { - -ms-filter:"progid:DXImageTransform.Microsoft.Alpha(opacity=30)"; - filter: alpha(opacity=30); - zoom: 1; -} -/* Icons ------------------------------------------------------------------------------------------------------------*/ -.ui-icon, -.ui-icon-searchfield:after { - background: #666 /*{global-icon-color}*/; - background: rgba(0,0,0,.4) /*{global-icon-disc}*/; - background-image: url(images/icons-18-white.png) /*{global-icon-set}*/; - background-repeat: no-repeat; - -moz-border-radius: 9px; - -webkit-border-radius: 9px; - border-radius: 9px; -} -/* Alt icon color ------------------------------------------------------------------------------------------------------------*/ -.ui-icon-alt { - background: #fff; - background: rgba(255,255,255,.3); - background-image: url(images/icons-18-black.png); - background-repeat: no-repeat; -} -/* HD/"retina" sprite ------------------------------------------------------------------------------------------------------------*/ -@media only screen and (-webkit-min-device-pixel-ratio: 1.5), - only screen and (min--moz-device-pixel-ratio: 1.5), - only screen and (min-resolution: 240dpi) { - - .ui-icon-plus, .ui-icon-minus, .ui-icon-delete, .ui-icon-arrow-r, - .ui-icon-arrow-l, .ui-icon-arrow-u, .ui-icon-arrow-d, .ui-icon-check, - .ui-icon-gear, .ui-icon-refresh, .ui-icon-forward, .ui-icon-back, - .ui-icon-grid, .ui-icon-star, .ui-icon-alert, .ui-icon-info, .ui-icon-home, .ui-icon-search, .ui-icon-searchfield:after, - .ui-icon-checkbox-off, .ui-icon-checkbox-on, .ui-icon-radio-off, .ui-icon-radio-on { - background-image: url(images/icons-36-white.png); - -moz-background-size: 776px 18px; - -o-background-size: 776px 18px; - -webkit-background-size: 776px 18px; - background-size: 776px 18px; - } - .ui-icon-alt { - background-image: url(images/icons-36-black.png); - } -} -/* plus minus */ -.ui-icon-plus { - background-position: -0 50%; -} -.ui-icon-minus { - background-position: -36px 50%; -} -/* delete/close */ -.ui-icon-delete { - background-position: -72px 50%; -} -/* arrows */ -.ui-icon-arrow-r { - background-position: -108px 50%; -} -.ui-icon-arrow-l { - background-position: -144px 50%; -} -.ui-icon-arrow-u { - background-position: -180px 50%; -} -.ui-icon-arrow-d { - background-position: -216px 50%; -} -/* misc */ -.ui-icon-check { - background-position: -252px 50%; -} -.ui-icon-gear { - background-position: -288px 50%; -} -.ui-icon-refresh { - background-position: -324px 50%; -} -.ui-icon-forward { - background-position: -360px 50%; -} -.ui-icon-back { - background-position: -396px 50%; -} -.ui-icon-grid { - background-position: -432px 50%; -} -.ui-icon-star { - background-position: -468px 50%; -} -.ui-icon-alert { - background-position: -504px 50%; -} -.ui-icon-info { - background-position: -540px 50%; -} -.ui-icon-home { - background-position: -576px 50%; -} -.ui-icon-search, -.ui-icon-searchfield:after { - background-position: -612px 50%; -} -.ui-icon-checkbox-off { - background-position: -684px 50%; -} -.ui-icon-checkbox-on { - background-position: -648px 50%; -} -.ui-icon-radio-off { - background-position: -756px 50%; -} -.ui-icon-radio-on { - background-position: -720px 50%; -} -/* checks,radios */ -.ui-checkbox .ui-icon { - -moz-border-radius: 3px; - -webkit-border-radius: 3px; - border-radius: 3px; -} -.ui-icon-checkbox-off, -.ui-icon-radio-off { - background-color: transparent; -} -.ui-checkbox-on .ui-icon, -.ui-radio-on .ui-icon { - background-color: #4596ce /*{global-active-background-color}*/; /* NOTE: this hex should match the active state color. It's repeated here for cascade */ -} -/* loading icon */ -.ui-icon-loading { - background: url(images/ajax-loader.gif); - background-size: 46px 46px; -} -/* Button corner classes ------------------------------------------------------------------------------------------------------------*/ -.ui-btn-corner-tl { - -moz-border-radius-topleft: 1em /*{global-radii-buttons}*/; - -webkit-border-top-left-radius: 1em /*{global-radii-buttons}*/; - border-top-left-radius: 1em /*{global-radii-buttons}*/; -} -.ui-btn-corner-tr { - -moz-border-radius-topright: 1em /*{global-radii-buttons}*/; - -webkit-border-top-right-radius: 1em /*{global-radii-buttons}*/; - border-top-right-radius: 1em /*{global-radii-buttons}*/; -} -.ui-btn-corner-bl { - -moz-border-radius-bottomleft: 1em /*{global-radii-buttons}*/; - -webkit-border-bottom-left-radius: 1em /*{global-radii-buttons}*/; - border-bottom-left-radius: 1em /*{global-radii-buttons}*/; -} -.ui-btn-corner-br { - -moz-border-radius-bottomright: 1em /*{global-radii-buttons}*/; - -webkit-border-bottom-right-radius: 1em /*{global-radii-buttons}*/; - border-bottom-right-radius: 1em /*{global-radii-buttons}*/; -} -.ui-btn-corner-top { - -moz-border-radius-topleft: 1em /*{global-radii-buttons}*/; - -webkit-border-top-left-radius: 1em /*{global-radii-buttons}*/; - border-top-left-radius: 1em /*{global-radii-buttons}*/; - -moz-border-radius-topright: 1em /*{global-radii-buttons}*/; - -webkit-border-top-right-radius: 1em /*{global-radii-buttons}*/; - border-top-right-radius: 1em /*{global-radii-buttons}*/; -} -.ui-btn-corner-bottom { - -moz-border-radius-bottomleft: 1em /*{global-radii-buttons}*/; - -webkit-border-bottom-left-radius: 1em /*{global-radii-buttons}*/; - border-bottom-left-radius: 1em /*{global-radii-buttons}*/; - -moz-border-radius-bottomright: 1em /*{global-radii-buttons}*/; - -webkit-border-bottom-right-radius: 1em /*{global-radii-buttons}*/; - border-bottom-right-radius: 1em /*{global-radii-buttons}*/; -} -.ui-btn-corner-right { - -moz-border-radius-topright: 1em /*{global-radii-buttons}*/; - -webkit-border-top-right-radius: 1em /*{global-radii-buttons}*/; - border-top-right-radius: 1em /*{global-radii-buttons}*/; - -moz-border-radius-bottomright: 1em /*{global-radii-buttons}*/; - -webkit-border-bottom-right-radius: 1em /*{global-radii-buttons}*/; - border-bottom-right-radius: 1em /*{global-radii-buttons}*/; -} -.ui-btn-corner-left { - -moz-border-radius-topleft: 1em /*{global-radii-buttons}*/; - -webkit-border-top-left-radius: 1em /*{global-radii-buttons}*/; - border-top-left-radius: 1em /*{global-radii-buttons}*/; - -moz-border-radius-bottomleft: 1em /*{global-radii-buttons}*/; - -webkit-border-bottom-left-radius: 1em /*{global-radii-buttons}*/; - border-bottom-left-radius: 1em /*{global-radii-buttons}*/; -} -.ui-btn-corner-all { - -moz-border-radius: 1em /*{global-radii-buttons}*/; - -webkit-border-radius: 1em /*{global-radii-buttons}*/; - border-radius: 1em /*{global-radii-buttons}*/; -} -/* radius clip workaround for cleaning up corner trapping */ -.ui-corner-tl, -.ui-corner-tr, -.ui-corner-bl, -.ui-corner-br, -.ui-corner-top, -.ui-corner-bottom, -.ui-corner-right, -.ui-corner-left, -.ui-corner-all, -.ui-btn-corner-tl, -.ui-btn-corner-tr, -.ui-btn-corner-bl, -.ui-btn-corner-br, -.ui-btn-corner-top, -.ui-btn-corner-bottom, -.ui-btn-corner-right, -.ui-btn-corner-left, -.ui-btn-corner-all { - -webkit-background-clip: padding-box; - -moz-background-clip: padding; - background-clip: padding-box; -} -/* Overlay / modal ------------------------------------------------------------------------------------------------------------*/ -.ui-overlay { - background: #666; - opacity: .5; - filter: Alpha(Opacity=50); - position: absolute; - width: 100%; - height: 100%; -} -.ui-overlay-shadow { - -moz-box-shadow: 0px 0px 12px rgba(0,0,0,.6); - -webkit-box-shadow: 0px 0px 12px rgba(0,0,0,.6); - box-shadow: 0px 0px 12px rgba(0,0,0,.6); -} -.ui-shadow { - -moz-box-shadow: 0px 1px 4px /*{global-box-shadow-size}*/ rgba(0,0,0,.3) /*{global-box-shadow-color}*/; - -webkit-box-shadow: 0px 1px 4px /*{global-box-shadow-size}*/ rgba(0,0,0,.3) /*{global-box-shadow-color}*/; - box-shadow: 0px 1px 4px /*{global-box-shadow-size}*/ rgba(0,0,0,.3) /*{global-box-shadow-color}*/; -} -.ui-bar-a .ui-shadow, -.ui-bar-b .ui-shadow , -.ui-bar-c .ui-shadow { - -moz-box-shadow: 0px 1px 0 rgba(255,255,255,.3); - -webkit-box-shadow: 0px 1px 0 rgba(255,255,255,.3); - box-shadow: 0px 1px 0 rgba(255,255,255,.3); -} -.ui-shadow-inset { - -moz-box-shadow: inset 0px 1px 4px rgba(0,0,0,.2); - -webkit-box-shadow: inset 0px 1px 4px rgba(0,0,0,.2); - box-shadow: inset 0px 1px 4px rgba(0,0,0,.2); -} -.ui-icon-shadow { - -moz-box-shadow: 0px 1px 0 rgba(255,255,255,.4) /*{global-icon-shadow}*/; - -webkit-box-shadow: 0px 1px 0 rgba(255,255,255,.4) /*{global-icon-shadow}*/; - box-shadow: 0px 1px 0 rgba(255,255,255,.4) /*{global-icon-shadow}*/; -} -/* Focus state - set here for specificity (note: these classes are added by JavaScript) ------------------------------------------------------------------------------------------------------------*/ -.ui-btn:focus { - outline: 0; -} -.ui-focus, -.ui-btn:focus { - -moz-box-shadow: 0px 0px 12px #387bbe /*{global-active-background-color}*/; - -webkit-box-shadow: 0px 0px 12px #387bbe /*{global-active-background-color}*/; - box-shadow: 0px 0px 12px #387bbe /*{global-active-background-color}*/; -} -/* unset box shadow in browsers that don't do it right ------------------------------------------------------------------------------------------------------------*/ -.ui-mobile-nosupport-boxshadow * { - -moz-box-shadow: none !important; - -webkit-box-shadow: none !important; - box-shadow: none !important; -} -/* ...and bring back focus */ -.ui-mobile-nosupport-boxshadow .ui-focus, -.ui-mobile-nosupport-boxshadow .ui-btn:focus { - outline-width: 1px; - outline-style: dotted; -} -/* some unsets - more probably needed */ -.ui-mobile, .ui-mobile body { height: 99.9%; } -.ui-mobile fieldset, .ui-page { padding: 0; margin: 0; } -.ui-mobile a img, .ui-mobile fieldset { border-width: 0; } -/* responsive page widths */ -.ui-mobile-viewport { margin: 0; overflow-x: visible; -webkit-text-size-adjust: none; -ms-text-size-adjust:none; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); } -/* Issue #2066 */ -body.ui-mobile-viewport, -div.ui-mobile-viewport { overflow-x: hidden; } -/* "page" containers - full-screen views, one should always be in view post-pageload */ -.ui-mobile [data-role=page], .ui-mobile [data-role=dialog], .ui-page { top: 0; left: 0; width: 100%; min-height: 100%; position: absolute; display: none; border: 0; } -.ui-mobile .ui-page-active { display: block; overflow: visible; } -/* on ios4, setting focus on the page element causes flashing during transitions when there is an outline, so we turn off outlines */ -.ui-page { outline: none; } -/*orientations from js are available */ -@media screen and (orientation: portrait){ -.ui-mobile, .ui-mobile .ui-page { min-height: 420px; } -} -@media screen and (orientation: landscape){ -.ui-mobile, .ui-mobile .ui-page { min-height: 300px; } -} -/* loading screen */ -.ui-loading .ui-loader { display: block; } -.ui-loader { display: none; z-index: 9999999; position: fixed; top: 50%; box-shadow: 0 1px 1px -1px #fff; left: 50%; border:0; } -.ui-loader-default { background: none; opacity: .18; width: 46px; height: 46px; margin-left: -23px; margin-top: -23px; } -.ui-loader-verbose { width: 200px; opacity: .88; height: auto; margin-left: -110px; margin-top: -43px; padding: 10px; } -.ui-loader-default h1 { font-size: 0; width: 0; height: 0; overflow: hidden; } -.ui-loader-verbose h1 { font-size: 16px; margin: 0; text-align: center; } -.ui-loader .ui-icon { background-color: #000; display: block; margin: 0; width: 44px; height: 44px; padding: 1px; -webkit-border-radius: 36px; -moz-border-radius: 36px; border-radius: 36px; } -.ui-loader-verbose .ui-icon { margin: 0 auto 10px; opacity: .75; } -.ui-loader-textonly { padding: 15px; margin-left: -115px; } -.ui-loader-textonly .ui-icon { display: none; } -.ui-loader-fakefix { position: absolute; } -/*fouc*/ -.ui-mobile-rendering > * { visibility: hidden; } -/*headers, content panels*/ -.ui-bar, .ui-body { position: relative; padding: .4em 15px; overflow: hidden; display: block; clear:both; } -.ui-bar { font-size: 16px; margin: 0; } -.ui-bar h1, .ui-bar h2, .ui-bar h3, .ui-bar h4, .ui-bar h5, .ui-bar h6 { margin: 0; padding: 0; font-size: 16px; display: inline-block; } -.ui-header, .ui-footer { position: relative; border-left-width: 0; border-right-width: 0; } -.ui-header .ui-btn-left, -.ui-header .ui-btn-right, -.ui-footer .ui-btn-left, -.ui-footer .ui-btn-right { position: absolute; top: 3px; } -.ui-header .ui-btn-left, -.ui-footer .ui-btn-left { left: 5px; } -.ui-header .ui-btn-right, -.ui-footer .ui-btn-right { right: 5px; } -.ui-footer .ui-btn-icon-notext, -.ui-header .ui-btn-icon-notext { top: 6px; } -.ui-header .ui-title, .ui-footer .ui-title { min-height: 1.1em; text-align: center; font-size: 16px; display: block; margin: .6em 30% .8em; padding: 0; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; outline: 0 !important; } -.ui-footer .ui-title { margin: .6em 15px .8em; } -/*content area*/ -.ui-content { border-width: 0; overflow: visible; overflow-x: hidden; padding: 15px; } -/* icons sizing */ -.ui-icon { width: 18px; height: 18px; } -/* non-js content hiding */ -.ui-nojs { position: absolute; left: -9999px; } -/* accessible content hiding */ -.ui-hide-label label, -.ui-hidden-accessible { position: absolute !important; left: -9999px; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); } -/* Transitions originally inspired by those from jQtouch, nice work, folks */ -.ui-mobile-viewport-transitioning, -.ui-mobile-viewport-transitioning .ui-page { - width: 100%; - height: 100%; - overflow: hidden; -} -.in { - -webkit-animation-timing-function: ease-out; - -webkit-animation-duration: 350ms; - -moz-animation-timing-function: ease-out; - -moz-animation-duration: 350ms; -} -.out { - -webkit-animation-timing-function: ease-in; - -webkit-animation-duration: 225ms; - -moz-animation-timing-function: ease-in; - -moz-animation-duration: 225; -} -@-webkit-keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } -} -@-moz-keyframes fadein { - from { opacity: 0; } - to { opacity: 1; } -} -@-webkit-keyframes fadeout { - from { opacity: 1; } - to { opacity: 0; } -} -@-moz-keyframes fadeout { - from { opacity: 1; } - to { opacity: 0; } -} -.fade.out { - opacity: 0; - -webkit-animation-duration: 125ms; - -webkit-animation-name: fadeout; - -moz-animation-duration: 125ms; - -moz-animation-name: fadeout; -} -.fade.in { - opacity: 1; - -webkit-animation-duration: 225ms; - -webkit-animation-name: fadein; - -moz-animation-duration: 225ms; - -moz-animation-name: fadein; -} -.pop { - -webkit-transform-origin: 50% 50%; - -moz-transform-origin: 50% 50%; -} -.pop.in { - -webkit-transform: scale(1); - -moz-transform: scale(1); - opacity: 1; - -webkit-animation-name: popin; - -moz-animation-name: popin; - -webkit-animation-duration: 350ms; - -moz-animation-duration: 350ms; -} -.pop.out { - -webkit-animation-name: fadeout; - -moz-animation-name: fadeout; - opacity: 0; - -webkit-animation-duration: 100ms; - -moz-animation-duration: 100ms; -} -.pop.in.reverse { - -webkit-animation-name: fadein; - -moz-animation-name: fadein; -} -.pop.out.reverse { - -webkit-transform: scale(.8); - -moz-transform: scale(.8); - -webkit-animation-name: popout; - -moz-animation-name: popout; -} -@-webkit-keyframes popin { - from { - -webkit-transform: scale(.8); - opacity: 0; - } - to { - -webkit-transform: scale(1); - opacity: 1; - } -} -@-moz-keyframes popin { - from { - -moz-transform: scale(.8); - opacity: 0; - } - to { - -moz-transform: scale(1); - opacity: 1; - } -} -@-webkit-keyframes popout { - from { - -webkit-transform: scale(1); - opacity: 1; - } - to { - -webkit-transform: scale(.8); - opacity: 0; - } -} -@-moz-keyframes popout { - from { - -moz-transform: scale(1); - opacity: 1; - } - to { - -moz-transform: scale(.8); - opacity: 0; - } -} -/* keyframes for slidein from sides */ -@-webkit-keyframes slideinfromright { - from { -webkit-transform: translateX(100%); } - to { -webkit-transform: translateX(0); } -} -@-moz-keyframes slideinfromright { - from { -moz-transform: translateX(100%); } - to { -moz-transform: translateX(0); } -} -@-webkit-keyframes slideinfromleft { - from { -webkit-transform: translateX(-100%); } - to { -webkit-transform: translateX(0); } -} -@-moz-keyframes slideinfromleft { - from { -moz-transform: translateX(-100%); } - to { -moz-transform: translateX(0); } -} -/* keyframes for slideout to sides */ -@-webkit-keyframes slideouttoleft { - from { -webkit-transform: translateX(0); } - to { -webkit-transform: translateX(-100%); } -} -@-moz-keyframes slideouttoleft { - from { -moz-transform: translateX(0); } - to { -moz-transform: translateX(-100%); } -} -@-webkit-keyframes slideouttoright { - from { -webkit-transform: translateX(0); } - to { -webkit-transform: translateX(100%); } -} -@-moz-keyframes slideouttoright { - from { -moz-transform: translateX(0); } - to { -moz-transform: translateX(100%); } -} -.slide.out, .slide.in { - -webkit-animation-timing-function: ease-out; - -webkit-animation-duration: 350ms; - -moz-animation-timing-function: ease-out; - -moz-animation-duration: 350ms; -} -.slide.out { - -webkit-transform: translateX(-100%); - -webkit-animation-name: slideouttoleft; - -moz-transform: translateX(-100%); - -moz-animation-name: slideouttoleft; -} -.slide.in { - -webkit-transform: translateX(0); - -webkit-animation-name: slideinfromright; - -moz-transform: translateX(0); - -moz-animation-name: slideinfromright; -} -.slide.out.reverse { - -webkit-transform: translateX(100%); - -webkit-animation-name: slideouttoright; - -moz-transform: translateX(100%); - -moz-animation-name: slideouttoright; -} -.slide.in.reverse { - -webkit-transform: translateX(0); - -webkit-animation-name: slideinfromleft; - -moz-transform: translateX(0); - -moz-animation-name: slideinfromleft; -} -.slidefade.out { - -webkit-transform: translateX(-100%); - -webkit-animation-name: slideouttoleft; - -moz-transform: translateX(-100%); - -moz-animation-name: slideouttoleft; - -webkit-animation-duration: 225ms; - -moz-animation-duration: 225ms; -} -.slidefade.in { - -webkit-transform: translateX(0); - -webkit-animation-name: fadein; - -moz-transform: translateX(0); - -moz-animation-name: fadein; - -webkit-animation-duration: 200ms; - -moz-animation-duration: 200ms; -} -.slidefade.out.reverse { - -webkit-transform: translateX(100%); - -webkit-animation-name: slideouttoright; - -moz-transform: translateX(100%); - -moz-animation-name: slideouttoright; - -webkit-animation-duration: 200ms; - -moz-animation-duration: 200ms; -} -.slidefade.in.reverse { - -webkit-transform: translateX(0); - -webkit-animation-name: fadein; - -moz-transform: translateX(0); - -moz-animation-name: fadein; - -webkit-animation-duration: 200ms; - -moz-animation-duration: 200ms; -} -/* slide down */ -.slidedown.out { - -webkit-animation-name: fadeout; - -moz-animation-name: fadeout; - -webkit-animation-duration: 100ms; - -moz-animation-duration: 100ms; -} -.slidedown.in { - -webkit-transform: translateY(0); - -webkit-animation-name: slideinfromtop; - -moz-transform: translateY(0); - -moz-animation-name: slideinfromtop; - -webkit-animation-duration: 250ms; - -moz-animation-duration: 250ms; -} -.slidedown.in.reverse { - -webkit-animation-name: fadein; - -moz-animation-name: fadein; - -webkit-animation-duration: 150ms; - -moz-animation-duration: 150ms; -} -.slidedown.out.reverse { - -webkit-transform: translateY(-100%); - -moz-transform: translateY(-100%); - -webkit-animation-name: slideouttotop; - -moz-animation-name: slideouttotop; - -webkit-animation-duration: 200ms; - -moz-animation-duration: 200ms; -} -@-webkit-keyframes slideinfromtop { - from { -webkit-transform: translateY(-100%); } - to { -webkit-transform: translateY(0); } -} -@-moz-keyframes slideinfromtop { - from { -moz-transform: translateY(-100%); } - to { -moz-transform: translateY(0); } -} -@-webkit-keyframes slideouttotop { - from { -webkit-transform: translateY(0); } - to { -webkit-transform: translateY(-100%); } -} -@-moz-keyframes slideouttotop { - from { -moz-transform: translateY(0); } - to { -moz-transform: translateY(-100%); } -} -/* slide up */ -.slideup.out { - -webkit-animation-name: fadeout; - -moz-animation-name: fadeout; - -webkit-animation-duration: 100ms; - -moz-animation-duration: 100ms; -} -.slideup.in { - -webkit-transform: translateY(0); - -webkit-animation-name: slideinfrombottom; - -moz-transform: translateY(0); - -moz-animation-name: slideinfrombottom; - -webkit-animation-duration: 250ms; - -moz-animation-duration: 250ms; -} -.slideup.in.reverse { - -webkit-animation-name: fadein; - -moz-animation-name: fadein; - -webkit-animation-duration: 150ms; - -moz-animation-duration: 150ms; -} -.slideup.out.reverse { - -webkit-transform: translateY(100%); - -moz-transform: translateY(100%); - -webkit-animation-name: slideouttobottom; - -moz-animation-name: slideouttobottom; - -webkit-animation-duration: 200ms; - -moz-animation-duration: 200ms; -} -@-webkit-keyframes slideinfrombottom { - from { -webkit-transform: translateY(100%); } - to { -webkit-transform: translateY(0); } -} -@-moz-keyframes slideinfrombottom { - from { -moz-transform: translateY(100%); } - to { -moz-transform: translateY(0); } -} -@-webkit-keyframes slideouttobottom { - from { -webkit-transform: translateY(0); } - to { -webkit-transform: translateY(100%); } -} -@-moz-keyframes slideouttobottom { - from { -moz-transform: translateY(0); } - to { -moz-transform: translateY(100%); } -} -/* The properties in this rule are only necessary for the 'flip' transition. - * We need specify the perspective to create a projection matrix. This will add - * some depth as the element flips. The depth number represents the distance of - * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate - * value. - */ -.viewport-flip { - -webkit-perspective: 1000; - -moz-perspective: 1000; - position: absolute; -} -.flip { - -webkit-backface-visibility:hidden; - -webkit-transform:translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */ - -moz-backface-visibility:hidden; - -moz-transform:translateX(0); -} -.flip.out { - -webkit-transform: rotateY(-90deg) scale(.9); - -webkit-animation-name: flipouttoleft; - -webkit-animation-duration: 175ms; - -moz-transform: rotateY(-90deg) scale(.9); - -moz-animation-name: flipouttoleft; - -moz-animation-duration: 175ms; -} -.flip.in { - -webkit-animation-name: flipintoright; - -webkit-animation-duration: 225ms; - -moz-animation-name: flipintoright; - -moz-animation-duration: 225ms; -} -.flip.out.reverse { - -webkit-transform: rotateY(90deg) scale(.9); - -webkit-animation-name: flipouttoright; - -moz-transform: rotateY(90deg) scale(.9); - -moz-animation-name: flipouttoright; -} -.flip.in.reverse { - -webkit-animation-name: flipintoleft; - -moz-animation-name: flipintoleft; -} -@-webkit-keyframes flipouttoleft { - from { -webkit-transform: rotateY(0); } - to { -webkit-transform: rotateY(-90deg) scale(.9); } -} -@-moz-keyframes flipouttoleft { - from { -moz-transform: rotateY(0); } - to { -moz-transform: rotateY(-90deg) scale(.9); } -} -@-webkit-keyframes flipouttoright { - from { -webkit-transform: rotateY(0) ; } - to { -webkit-transform: rotateY(90deg) scale(.9); } -} -@-moz-keyframes flipouttoright { - from { -moz-transform: rotateY(0); } - to { -moz-transform: rotateY(90deg) scale(.9); } -} -@-webkit-keyframes flipintoleft { - from { -webkit-transform: rotateY(-90deg) scale(.9); } - to { -webkit-transform: rotateY(0); } -} -@-moz-keyframes flipintoleft { - from { -moz-transform: rotateY(-90deg) scale(.9); } - to { -moz-transform: rotateY(0); } -} -@-webkit-keyframes flipintoright { - from { -webkit-transform: rotateY(90deg) scale(.9); } - to { -webkit-transform: rotateY(0); } -} -@-moz-keyframes flipintoright { - from { -moz-transform: rotateY(90deg) scale(.9); } - to { -moz-transform: rotateY(0); } -} -/* The properties in this rule are only necessary for the 'flip' transition. - * We need specify the perspective to create a projection matrix. This will add - * some depth as the element flips. The depth number represents the distance of - * the viewer from the z-plane. According to the CSS3 spec, 1000 is a moderate - * value. - */ -.viewport-turn { - -webkit-perspective: 1000; - -moz-perspective: 1000; - position: absolute; -} -.turn { - -webkit-backface-visibility:hidden; - -webkit-transform:translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */ - -webkit-transform-origin: 0; - - -moz-backface-visibility:hidden; - -moz-transform:translateX(0); /* Needed to work around an iOS 3.1 bug that causes listview thumbs to disappear when -webkit-visibility:hidden is used. */ - -moz-transform-origin: 0; -} -.turn.out { - -webkit-transform: rotateY(-90deg) scale(.9); - -webkit-animation-name: flipouttoleft; - -moz-transform: rotateY(-90deg) scale(.9); - -moz-animation-name: flipouttoleft; - -webkit-animation-duration: 125ms; - -moz-animation-duration: 125ms; -} -.turn.in { - -webkit-animation-name: flipintoright; - -moz-animation-name: flipintoright; - -webkit-animation-duration: 250ms; - -moz-animation-duration: 250ms; - -} -.turn.out.reverse { - -webkit-transform: rotateY(90deg) scale(.9); - -webkit-animation-name: flipouttoright; - -moz-transform: rotateY(90deg) scale(.9); - -moz-animation-name: flipouttoright; -} -.turn.in.reverse { - -webkit-animation-name: flipintoleft; - -moz-animation-name: flipintoleft; -} -@-webkit-keyframes flipouttoleft { - from { -webkit-transform: rotateY(0); } - to { -webkit-transform: rotateY(-90deg) scale(.9); } -} -@-moz-keyframes flipouttoleft { - from { -moz-transform: rotateY(0); } - to { -moz-transform: rotateY(-90deg) scale(.9); } -} -@-webkit-keyframes flipouttoright { - from { -webkit-transform: rotateY(0) ; } - to { -webkit-transform: rotateY(90deg) scale(.9); } -} -@-moz-keyframes flipouttoright { - from { -moz-transform: rotateY(0); } - to { -moz-transform: rotateY(90deg) scale(.9); } -} -@-webkit-keyframes flipintoleft { - from { -webkit-transform: rotateY(-90deg) scale(.9); } - to { -webkit-transform: rotateY(0); } -} -@-moz-keyframes flipintoleft { - from { -moz-transform: rotateY(-90deg) scale(.9); } - to { -moz-transform: rotateY(0); } -} -@-webkit-keyframes flipintoright { - from { -webkit-transform: rotateY(90deg) scale(.9); } - to { -webkit-transform: rotateY(0); } -} -@-moz-keyframes flipintoright { - from { -moz-transform: rotateY(90deg) scale(.9); } - to { -moz-transform: rotateY(0); } -} -/* flow transition */ -.flow { - -webkit-transform-origin: 50% 30%; - -moz-transform-origin: 50% 30%; - -webkit-box-shadow: 0 0 20px rgba(0,0,0,.4); - -moz-box-shadow: 0 0 20px rgba(0,0,0,.4); -} -.ui-dialog.flow { - -webkit-transform-origin: none; - -moz-transform-origin: none; - -webkit-box-shadow: none; - -moz-box-shadow: none; -} -.flow.out { - -webkit-transform: translateX(-100%) scale(.7); - -webkit-animation-name: flowouttoleft; - -webkit-animation-timing-function: ease; - -webkit-animation-duration: 350ms; - -moz-transform: translateX(-100%) scale(.7); - -moz-animation-name: flowouttoleft; - -moz-animation-timing-function: ease; - -moz-animation-duration: 350ms; -} -.flow.in { - -webkit-transform: translateX(0) scale(1); - -webkit-animation-name: flowinfromright; - -webkit-animation-timing-function: ease; - -webkit-animation-duration: 350ms; - -moz-transform: translateX(0) scale(1); - -moz-animation-name: flowinfromright; - -moz-animation-timing-function: ease; - -moz-animation-duration: 350ms; -} -.flow.out.reverse { - -webkit-transform: translateX(100%); - -webkit-animation-name: flowouttoright; - -moz-transform: translateX(100%); - -moz-animation-name: flowouttoright; -} -.flow.in.reverse { - -webkit-animation-name: flowinfromleft; - -moz-animation-name: flowinfromleft; -} -@-webkit-keyframes flowouttoleft { - 0% { -webkit-transform: translateX(0) scale(1); } - 60%, 70% { -webkit-transform: translateX(0) scale(.7); } - 100% { -webkit-transform: translateX(-100%) scale(.7); } -} -@-moz-keyframes flowouttoleft { - 0% { -moz-transform: translateX(0) scale(1); } - 60%, 70% { -moz-transform: translateX(0) scale(.7); } - 100% { -moz-transform: translateX(-100%) scale(.7); } -} -@-webkit-keyframes flowouttoright { - 0% { -webkit-transform: translateX(0) scale(1); } - 60%, 70% { -webkit-transform: translateX(0) scale(.7); } - 100% { -webkit-transform: translateX(100%) scale(.7); } -} -@-moz-keyframes flowouttoright { - 0% { -moz-transform: translateX(0) scale(1); } - 60%, 70% { -moz-transform: translateX(0) scale(.7); } - 100% { -moz-transform: translateX(100%) scale(.7); } -} -@-webkit-keyframes flowinfromleft { - 0% { -webkit-transform: translateX(-100%) scale(.7); } - 30%, 40% { -webkit-transform: translateX(0) scale(.7); } - 100% { -webkit-transform: translateX(0) scale(1); } -} -@-moz-keyframes flowinfromleft { - 0% { -moz-transform: translateX(-100%) scale(.7); } - 30%, 40% { -moz-transform: translateX(0) scale(.7); } - 100% { -moz-transform: translateX(0) scale(1); } -} -@-webkit-keyframes flowinfromright { - 0% { -webkit-transform: translateX(100%) scale(.7); } - 30%, 40% { -webkit-transform: translateX(0) scale(.7); } - 100% { -webkit-transform: translateX(0) scale(1); } -} -@-moz-keyframes flowinfromright { - 0% { -moz-transform: translateX(100%) scale(.7); } - 30%, 40% { -moz-transform: translateX(0) scale(.7); } - 100% { -moz-transform: translateX(0) scale(1); } -} -/* content configurations. */ -.ui-grid-a, .ui-grid-b, .ui-grid-c, .ui-grid-d { overflow: hidden; } -.ui-block-a, .ui-block-b, .ui-block-c, .ui-block-d, .ui-block-e { margin: 0; padding: 0; border: 0; float: left; min-height:1px;} -/* grid solo: 100 - single item fallback */ -.ui-grid-solo .ui-block-a { width: 100%; float: none; } -/* grid a: 50/50 */ -.ui-grid-a .ui-block-a, .ui-grid-a .ui-block-b { width: 50%; } -.ui-grid-a .ui-block-a { clear: left; } -/* grid b: 33/33/33 */ -.ui-grid-b .ui-block-a, .ui-grid-b .ui-block-b, .ui-grid-b .ui-block-c { width: 33.333%; } -.ui-grid-b .ui-block-a { clear: left; } -/* grid c: 25/25/25/25 */ -.ui-grid-c .ui-block-a, .ui-grid-c .ui-block-b, .ui-grid-c .ui-block-c, .ui-grid-c .ui-block-d { width: 25%; } -.ui-grid-c .ui-block-a { clear: left; } -/* grid d: 20/20/20/20/20 */ -.ui-grid-d .ui-block-a, .ui-grid-d .ui-block-b, .ui-grid-d .ui-block-c, .ui-grid-d .ui-block-d, .ui-grid-d .ui-block-e { width: 20%; } -.ui-grid-d .ui-block-a { clear: left; } -/* fixed page header & footer configuration */ -.ui-header-fixed, -.ui-footer-fixed { - left: 0; - right: 0; - width: 100%; - position: fixed; - z-index: 1000; -} -.ui-header-fixed { - top: 0; -} -.ui-footer-fixed { - bottom: 0; -} -.ui-header-fullscreen, -.ui-footer-fullscreen { - opacity: .9; -} -.ui-page-header-fixed { - padding-top: 2.5em; -} -.ui-page-footer-fixed { - padding-bottom: 3em; -} -.ui-page-header-fullscreen .ui-content, -.ui-page-footer-fullscreen .ui-content { - padding: 0; -} -.ui-fixed-hidden { - position: absolute; -} -.ui-page-header-fullscreen .ui-fixed-hidden, -.ui-page-footer-fullscreen .ui-fixed-hidden { - left: -99999em; -} -.ui-header-fixed .ui-btn, -.ui-footer-fixed .ui-btn { - z-index: 10; -} -.ui-navbar { overflow: hidden; } -.ui-navbar ul, .ui-navbar-expanded ul { list-style:none; padding: 0; margin: 0; position: relative; display: block; border: 0;} -.ui-navbar-collapsed ul { float: left; width: 75%; margin-right: -2px; } -.ui-navbar-collapsed .ui-navbar-toggle { float: left; width: 25%; } -.ui-navbar li.ui-navbar-truncate { position: absolute; left: -9999px; top: -9999px; } -.ui-navbar li .ui-btn, .ui-navbar .ui-navbar-toggle .ui-btn { display: block; font-size: 12px; text-align: center; margin: 0; border-right-width: 0; max-width: 100%; } -.ui-navbar li .ui-btn { margin-right: -1px; } -.ui-navbar li .ui-btn:last-child { margin-right: 0; } -.ui-header .ui-navbar li .ui-btn, .ui-header .ui-navbar .ui-navbar-toggle .ui-btn, -.ui-footer .ui-navbar li .ui-btn, .ui-footer .ui-navbar .ui-navbar-toggle .ui-btn { border-top-width: 0; border-bottom-width: 0; } -.ui-navbar .ui-btn-inner { padding-left: 2px; padding-right: 2px; } -.ui-navbar-noicons li .ui-btn .ui-btn-inner, .ui-navbar-noicons .ui-navbar-toggle .ui-btn-inner { padding-top: .8em; padding-bottom: .9em; } -/*expanded page styles*/ -.ui-navbar-expanded .ui-btn { margin: 0; font-size: 14px; } -.ui-navbar-expanded .ui-btn-inner { padding-left: 5px; padding-right: 5px; } -.ui-navbar-expanded .ui-btn-icon-top .ui-btn-inner { padding: 45px 5px 15px; text-align: center; } -.ui-navbar-expanded .ui-btn-icon-top .ui-icon { top: 15px; } -.ui-navbar-expanded .ui-btn-icon-bottom .ui-btn-inner { padding: 15px 5px 45px; text-align: center; } -.ui-navbar-expanded .ui-btn-icon-bottom .ui-icon { bottom: 15px; } -.ui-navbar-expanded li .ui-btn .ui-btn-inner { min-height: 2.5em; } -.ui-navbar-expanded .ui-navbar-noicons .ui-btn .ui-btn-inner { padding-top: 1.8em; padding-bottom: 1.9em; } -.ui-btn { display: block; text-align: center; cursor:pointer; position: relative; margin: .5em 5px; padding: 0; } -.ui-mini { margin: .25em 5px; } -.ui-btn-inner { padding: .6em 20px; min-width: .75em; display: block; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; position: relative; zoom: 1; } -.ui-btn input, .ui-btn button { z-index: 2; } -.ui-btn-left, .ui-btn-right, .ui-btn-inline { display: inline-block; } -.ui-btn-block { display: block; } -.ui-header .ui-btn, -.ui-footer .ui-btn { display: inline-block; margin: 0; } -.ui-header .ui-btn-inner, -.ui-footer .ui-btn-inner, -.ui-mini .ui-btn-inner { font-size: 12.5px; padding: .55em 11px .5em; } -.ui-header .ui-fullsize .ui-btn-inner, -.ui-footer .ui-fullsize .ui-btn-inner { font-size: 16px; padding: .6em 25px; } -.ui-btn-icon-notext { width: 24px; height: 24px; } -.ui-btn-icon-notext .ui-btn-inner { padding: 0; height: 100%; } -.ui-btn-icon-notext .ui-btn-inner .ui-icon { margin: 2px 1px 2px 3px; } -.ui-btn-text { position: relative; z-index: 1; width: 100%; } -.ui-btn-icon-notext .ui-btn-text { position: absolute; left: -9999px; } -.ui-btn-icon-left .ui-btn-inner { padding-left: 40px; } -.ui-btn-icon-right .ui-btn-inner { padding-right: 40px; } -.ui-btn-icon-top .ui-btn-inner { padding-top: 40px; } -.ui-btn-icon-bottom .ui-btn-inner { padding-bottom: 40px; } -.ui-header .ui-btn-icon-left .ui-btn-inner, -.ui-footer .ui-btn-icon-left .ui-btn-inner, -.ui-mini .ui-btn-icon-left .ui-btn-inner { padding-left: 30px; } -.ui-header .ui-btn-icon-right .ui-btn-inner, -.ui-footer .ui-btn-icon-right .ui-btn-inner, -.ui-mini .ui-btn-icon-right .ui-btn-inner { padding-right: 30px; } -.ui-header .ui-btn-icon-top .ui-btn-inner, -.ui-footer .ui-btn-icon-top .ui-btn-inner, -.ui-mini .ui-btn-icon-top .ui-btn-inner { padding: 30px 3px .5em 3px; } -.ui-header .ui-btn-icon-bottom .ui-btn-inner, -.ui-footer .ui-btn-icon-bottom .ui-btn-inner, -.ui-mini .ui-btn-icon-bottom .ui-btn-inner { padding: .55em 3px 30px 3px; } -/*btn icon positioning*/ -.ui-btn-icon-notext .ui-icon { display: block; z-index: 0;} -.ui-btn-icon-left .ui-btn-inner .ui-icon, .ui-btn-icon-right .ui-btn-inner .ui-icon { position: absolute; top: 50%; margin-top: -9px; } -.ui-btn-icon-top .ui-btn-inner .ui-icon, .ui-btn-icon-bottom .ui-btn-inner .ui-icon { position: absolute; left: 50%; margin-left: -9px; } -.ui-btn-icon-left .ui-icon { left: 10px; } -.ui-btn-icon-right .ui-icon { right: 10px; } -.ui-btn-icon-top .ui-icon { top: 10px; } -.ui-btn-icon-bottom .ui-icon { top: auto; bottom: 10px; } -.ui-header .ui-btn-icon-left .ui-icon, -.ui-footer .ui-btn-icon-left .ui-icon, -.ui-mini.ui-btn-icon-left .ui-icon, -.ui-mini .ui-btn-icon-left .ui-icon { left: 5px; } -.ui-header .ui-btn-icon-right .ui-icon, -.ui-footer .ui-btn-icon-right .ui-icon, -.ui-mini.ui-btn-icon-right .ui-icon, -.ui-mini .ui-btn-icon-right .ui-icon { right: 5px; } -.ui-header .ui-btn-icon-top .ui-icon, -.ui-footer .ui-btn-icon-top .ui-icon, -.ui-mini.ui-btn-icon-top .ui-icon, -.ui-mini .ui-btn-icon-top .ui-icon { top: 5px; } -.ui-header .ui-btn-icon-bottom .ui-icon, -.ui-footer .ui-btn-icon-bottom .ui-icon, -.ui-mini.ui-btn-icon-bottom .ui-icon, -.ui-mini .ui-btn-icon-bottom .ui-icon { bottom: 5px; } -/*hiding native button,inputs */ -.ui-btn-hidden { position: absolute; top: 0; left: 0; width: 100%; height: 100%; -webkit-appearance: button; opacity: .1; cursor: pointer; background: #fff; background: rgba(255,255,255,0); filter: Alpha(Opacity=.0001); font-size: 1px; border: none; text-indent: -9999px; } -.ui-collapsible { margin: .5em 0; } -.ui-collapsible-heading { font-size: 16px; display: block; margin: 0 -8px; padding: 0; border-width: 0 0 1px 0; position: relative; } -.ui-collapsible-heading a { text-align: left; margin: 0; } -.ui-collapsible-heading .ui-btn-inner, -.ui-collapsible-heading .ui-btn-icon-left .ui-btn-inner { padding-left: 40px; } -.ui-collapsible-heading .ui-btn-icon-right .ui-btn-inner { padding-left: 12px; padding-right: 40px; } -.ui-collapsible-heading .ui-btn-icon-top .ui-btn-inner, -.ui-collapsible-heading .ui-btn-icon-bottom .ui-btn-inner { padding-right: 40px; text-align: center; } -.ui-collapsible-heading a span.ui-btn { position: absolute; left: 6px; top: 50%; margin: -12px 0 0 0; width: 20px; height: 20px; padding: 1px 0px 1px 2px; text-indent: -9999px; } -.ui-collapsible-heading a span.ui-btn .ui-btn-inner { padding: 10px 0; } -.ui-collapsible-heading a span.ui-btn .ui-icon { left: 0; margin-top: -10px; } -.ui-collapsible-heading-status { position: absolute; top: -9999px; left:0px; } -.ui-collapsible-content { - display: block; - margin: 0 -8px; - padding: 10px 16px; - border-top: none; /* Overrides ui-btn-up-* */ - background-image: none; /* Overrides ui-btn-up-* */ - font-weight: normal; /* Overrides ui-btn-up-* */ -} -.ui-collapsible-content-collapsed { display: none; } -.ui-collapsible-set { margin: .5em 0; } -.ui-collapsible-set .ui-collapsible { margin: -1px 0 0; } -.ui-controlgroup, fieldset.ui-controlgroup { padding: 0; margin: 0em 0 .5em; zoom: 1; } -.ui-bar .ui-controlgroup { margin: 0 .3em; } -.ui-controlgroup-label { font-size: 16px; line-height: 1.4; font-weight: normal; margin: 0 0 .4em; } -.ui-controlgroup-controls { display: block; width: 100%;} -.ui-controlgroup li { list-style: none; } -.ui-controlgroup-vertical .ui-btn, -.ui-controlgroup-vertical .ui-checkbox, .ui-controlgroup-vertical .ui-radio { margin: 0; border-bottom-width: 0; } -.ui-controlgroup-controls label.ui-select { position: absolute; left: -9999px; } -.ui-controlgroup-vertical .ui-controlgroup-last { border-bottom-width: 1px; } -.ui-controlgroup-horizontal { padding: 0; } -.ui-controlgroup-horizontal .ui-btn-inner { text-align:center; } -.ui-controlgroup-horizontal .ui-btn, .ui-controlgroup-horizontal .ui-select { display: inline-block; margin: 0 -6px 0 0; } -.ui-controlgroup-horizontal .ui-checkbox, .ui-controlgroup-horizontal .ui-radio { float: left; clear: none; margin: 0 -1px 0 0; } -.ui-controlgroup-horizontal .ui-checkbox .ui-btn, .ui-controlgroup-horizontal .ui-radio .ui-btn, -.ui-controlgroup-horizontal .ui-checkbox:last-child, .ui-controlgroup-horizontal .ui-radio:last-child { margin-right: 0; } -.ui-controlgroup-horizontal .ui-controlgroup-last { margin-right: 0; } -.ui-controlgroup .ui-checkbox label, .ui-controlgroup .ui-radio label { font-size: 16px; } -/* conflicts with listview.. -.ui-controlgroup .ui-btn-icon-notext { width: 30px; height: 30px; text-indent: -9999px; } -.ui-controlgroup .ui-btn-icon-notext .ui-btn-inner { padding: 5px 6px 5px 5px; } -*/ -@media all and (min-width: 450px){ - .ui-field-contain .ui-controlgroup-label { vertical-align: top; display: inline-block; width: 20%; margin: 0 2% 0 0; } - .ui-field-contain .ui-controlgroup-controls { width: 60%; display: inline-block; } - .ui-field-contain .ui-controlgroup .ui-select { width: 100%; } - .ui-field-contain .ui-controlgroup-horizontal .ui-select { width: auto; } -} -.ui-dialog { - background: none !important; /* this is to ensure that dialog theming does not apply (by default at least) on the page div */ -} -.ui-dialog-contain { width: 92.5%; max-width: 500px; margin: 10% auto 15px auto; padding: 0; } -.ui-dialog .ui-header { - margin-top: 15%; - border: none; - overflow: hidden; -} -.ui-dialog .ui-header, -.ui-dialog .ui-content, -.ui-dialog .ui-footer { - display: block; - position: relative; - width: auto; -} -.ui-dialog .ui-header, -.ui-dialog .ui-footer { - z-index: 10; - padding: 0; -} -.ui-dialog .ui-footer { - padding: 0 15px; -} -.ui-dialog .ui-content { - padding: 15px; -} -.ui-dialog { - margin-top: -15px; -} -.ui-checkbox, .ui-radio { position: relative; clear: both; margin: .2em 0 .5em; z-index: 1; } -.ui-checkbox .ui-btn, .ui-radio .ui-btn { margin: 0; text-align: left; z-index: 2; } -.ui-checkbox .ui-btn-inner, .ui-radio .ui-btn-inner { white-space: normal; } -.ui-checkbox .ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-btn-icon-left .ui-btn-inner { padding-left: 45px; } -.ui-checkbox .ui-mini.ui-btn-icon-left .ui-btn-inner,.ui-radio .ui-mini.ui-btn-icon-left .ui-btn-inner { padding-left: 36px; } -.ui-checkbox .ui-btn-icon-right .ui-btn-inner, .ui-radio .ui-btn-icon-right .ui-btn-inner { padding-right: 45px; } -.ui-checkbox .ui-mini.ui-btn-icon-right .ui-btn-inner, .ui-radio .ui-mini.ui-btn-icon-right .ui-btn-inner { padding-right: 36px; } -.ui-checkbox .ui-btn-icon-top .ui-btn-inner,.ui-radio .ui-btn-icon-top .ui-btn-inner { padding-right: 0; padding-left: 0; text-align: center; } -.ui-checkbox .ui-btn-icon-bottom .ui-btn-inner, .ui-radio .ui-btn-icon-bottom .ui-btn-inner { padding-right: 0; padding-left: 0; text-align: center; } -.ui-checkbox .ui-icon, .ui-radio .ui-icon { top: 1.1em; } -.ui-checkbox .ui-btn-icon-left .ui-icon, .ui-radio .ui-btn-icon-left .ui-icon { left: 15px; } -.ui-checkbox .ui-mini.ui-btn-icon-left .ui-icon, .ui-radio .ui-mini.ui-btn-icon-left .ui-icon { left: 9px; } -.ui-checkbox .ui-btn-icon-right .ui-icon, .ui-radio .ui-btn-icon-right .ui-icon { right: 15px; } -.ui-checkbox .ui-mini.ui-btn-icon-right .ui-icon, .ui-radio .ui-mini.ui-btn-icon-right .ui-icon { right: 9px; } -.ui-checkbox .ui-btn-icon-top .ui-icon, .ui-radio .ui-btn-icon-top .ui-icon { top: 10px; } -.ui-checkbox .ui-btn-icon-bottom .ui-icon, .ui-radio .ui-btn-icon-bottom .ui-icon { top: auto; bottom: 10px; } -.ui-checkbox .ui-btn-icon-right .ui-icon, .ui-radio .ui-btn-icon-right .ui-icon { right: 15px; } -.ui-checkbox .ui-mini.ui-btn-icon-right .ui-icon, .ui-radio .ui-mini.ui-btn-icon-right .ui-icon { right: 9px; } -/* input, label positioning */ -.ui-checkbox input,.ui-radio input { position:absolute; left:20px; top:50%; width: 10px; height: 10px; margin:-5px 0 0 0; outline: 0 !important; z-index: 1; } -.ui-field-contain, fieldset.ui-field-contain { padding: .8em 0; margin: 0; border-width: 0 0 1px 0; overflow: visible; } -.ui-field-contain:first-child { border-top-width: 0; } -.ui-header .ui-field-contain-left, -.ui-header .ui-field-contain-right { - position: absolute; - top: 0; - width: 25%; -} -.ui-header .ui-field-contain-left { - left: 1em; -} -.ui-header .ui-field-contain-right { - right: 1em; -} -@media all and (min-width: 450px){ - .ui-field-contain, .ui-mobile fieldset.ui-field-contain { border-width: 0; padding: 0; margin: 1em 0; } -} -.ui-select { display: block; position: relative; } -.ui-select select { position: absolute; left: -9999px; top: -9999px; } -.ui-select .ui-btn { overflow: hidden; opacity: 1; margin: 0; } -/* Fixes #2588 — When Windows Phone 7.5 (Mango) tries to calculate a numeric opacity for a select—including “inherit”—without explicitly specifying an opacity on the parent to give it context, a bug appears where clicking elsewhere on the page after opening the select will open the select again. */ -.ui-select .ui-btn select { cursor: pointer; -webkit-appearance: button; left: 0; top:0; width: 100%; min-height: 1.5em; min-height: 100%; height: 3em; max-height: 100%; opacity: 0; -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=0)"; filter: alpha(opacity=0); z-index: 2; } -.ui-select .ui-disabled { opacity: .3; } -@-moz-document url-prefix() {.ui-select .ui-btn select { opacity: 0.0001; }} -.ui-select .ui-btn select.ui-select-nativeonly { opacity: 1; text-indent: 0; } -.ui-select .ui-btn-icon-right .ui-btn-inner { padding-right: 45px; } -.ui-select .ui-btn-icon-right .ui-icon { right: 15px; } -.ui-select .ui-mini.ui-btn-icon-right .ui-icon { right: 7px; } -/* labels */ -label.ui-select { font-size: 16px; line-height: 1.4; font-weight: normal; margin: 0 0 .3em; display: block; } -/*listbox*/ -.ui-select .ui-btn-text, .ui-selectmenu .ui-btn-text { display: block; min-height: 1em; overflow: hidden !important; -/* This !important is required for iPad Safari specifically. See https://github.com/jquery/jquery-mobile/issues/2647 */ } -.ui-select .ui-btn-text { text-overflow: ellipsis; } -.ui-selectmenu { position: absolute; padding: 0; z-index: 1100 !important; width: 80%; max-width: 350px; padding: 6px; } -.ui-selectmenu .ui-listview { margin: 0; } -.ui-selectmenu .ui-btn.ui-li-divider { cursor: default; } -.ui-selectmenu-hidden { top: -9999px; left: -9999px; } -.ui-selectmenu-screen { position: absolute; top: 0; left: 0; width: 100%; height: 100%; z-index: 99; } -.ui-screen-hidden, .ui-selectmenu-list .ui-li .ui-icon { display: none; } -.ui-selectmenu-list .ui-li .ui-icon { display: block; } -.ui-li.ui-selectmenu-placeholder { display: none; } -.ui-selectmenu .ui-header .ui-title { margin: 0.6em 46px 0.8em; } -@media all and (min-width: 450px){ - .ui-field-contain label.ui-select { vertical-align: top; display: inline-block; width: 20%; margin: 0 2% 0 0; } - .ui-field-contain .ui-select { width: 60%; display: inline-block; } -} -/* when no placeholder is defined in a multiple select, the header height doesn't even extend past the close button. this shim's content in there */ -.ui-selectmenu .ui-header h1:after { content: '.'; visibility: hidden; } -label.ui-input-text { font-size: 16px; line-height: 1.4; display: block; font-weight: normal; margin: 0 0 .3em; } -input.ui-input-text, textarea.ui-input-text { background-image: none; padding: .4em; line-height: 1.4; font-size: 16px; display: block; width: 97%; outline: 0; } -.ui-header input.ui-input-text, -.ui-footer input.ui-input-text { margin-left: 1.25%; padding: .4em 1%; width: 95.5% } /* Note that padding left/right on text inputs is factored into how the element is displayed in Firefox, but does not actually pad the text inside it. */ - input.ui-input-text { -webkit-appearance: none; } -textarea.ui-input-text { height: 50px; -webkit-transition: height 200ms linear; -moz-transition: height 200ms linear; -o-transition: height 200ms linear; transition: height 200ms linear; } -.ui-input-search { padding: 0 30px; background-image: none; position: relative; } -.ui-icon-searchfield:after { position: absolute; left: 7px; top: 50%; margin-top: -9px; content: ""; width: 18px; height: 18px; opacity: .5; } -.ui-input-search input.ui-input-text { border: none; width: 98%; padding: .4em 0; margin: 0; display: block; background: transparent none; outline: 0 !important; } -.ui-input-search .ui-input-clear { position: absolute; right: 0; top: 50%; margin-top: -13px; } -.ui-mini .ui-input-clear { right: -3px; } -.ui-input-search .ui-input-clear-hidden { display: none; } -input.ui-mini, .ui-mini input, textarea.ui-mini { font-size: 14px; } -textarea.ui-mini { height: 45px; } -/* orientation adjustments - incomplete!*/ -@media all and (min-width: 450px){ - .ui-field-contain label.ui-input-text { vertical-align: top; display: inline-block; width: 20%; margin: 0 2% 0 0 } - .ui-field-contain input.ui-input-text, - .ui-field-contain textarea.ui-input-text, - .ui-field-contain .ui-input-search { width: 60%; display: inline-block; } - .ui-field-contain .ui-input-search { width: 50%; } - .ui-hide-label input.ui-input-text, - .ui-hide-label textarea.ui-input-text, - .ui-hide-label .ui-input-search { padding: .4em; width: 97%; } - .ui-input-search input.ui-input-text { width: 98%; /*echos rule from above*/ } -} -.ui-listview { margin: 0; counter-reset: listnumbering; } -.ui-content .ui-listview { margin: -15px; } -.ui-content .ui-listview-inset { margin: 1em 0; } -.ui-listview, .ui-li { list-style:none; padding:0; } -.ui-li, .ui-li.ui-field-contain { display: block; margin:0; position: relative; overflow: visible; text-align: left; border-width: 0; border-top-width: 1px; } -.ui-li .ui-btn-text a.ui-link-inherit { text-overflow: ellipsis; overflow: hidden; white-space: nowrap; } -.ui-li-divider, .ui-li-static { padding: .5em 15px; font-size: 14px; font-weight: bold; } -.ui-li-divider { counter-reset: listnumbering; } -ol.ui-listview .ui-link-inherit:before, ol.ui-listview .ui-li-static:before, .ui-li-dec { font-size: .8em; display: inline-block; padding-right: .3em; font-weight: normal;counter-increment: listnumbering; content: counter(listnumbering) ". "; } -ol.ui-listview .ui-li-jsnumbering:before { content: "" !important; } /* to avoid chance of duplication */ -.ui-listview-inset .ui-li { border-right-width: 1px; border-left-width: 1px; } -.ui-li:last-child, .ui-li.ui-field-contain:last-child { border-bottom-width: 1px; } -.ui-li>.ui-btn-inner { display: block; position: relative; padding: 0; } -.ui-li .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li { padding: .7em 15px .7em 15px; display: block; } -.ui-li-has-thumb .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-thumb { min-height: 60px; padding-left: 100px; } -.ui-li-has-icon .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-icon { min-height: 20px; padding-left: 40px; } -.ui-li-has-count .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-count { padding-right: 45px; } -.ui-li-has-arrow .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-arrow { padding-right: 30px; } -.ui-li-has-arrow.ui-li-has-count .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-arrow.ui-li-has-count { padding-right: 75px; } -.ui-li-has-count .ui-btn-text { padding-right: 15px; } -.ui-li-heading { font-size: 16px; font-weight: bold; display: block; margin: .6em 0; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; } -.ui-li-desc { font-size: 12px; font-weight: normal; display: block; margin: -.5em 0 .6em; text-overflow: ellipsis; overflow: hidden; white-space: nowrap; } -.ui-li-thumb, .ui-listview .ui-li-icon { position: absolute; left: 1px; top: 0; max-height: 80px; max-width: 80px; } -.ui-listview .ui-li-icon { max-height: 40px; max-width: 40px; left: 10px; top: .9em; } -.ui-li-thumb, .ui-listview .ui-li-icon, .ui-li-content { float: left; margin-right: 10px; } -.ui-li-aside { float: right; width: 50%; text-align: right; margin: .3em 0; } -@media all and (min-width: 480px){ - .ui-li-aside { width: 45%; } -} -.ui-li-divider { cursor: default; } -.ui-li-has-alt .ui-btn-inner a.ui-link-inherit, .ui-li-static.ui-li-has-alt { padding-right: 95px; } -.ui-li-has-count .ui-li-count { position: absolute; font-size: 11px; font-weight: bold; padding: .2em .5em; top: 50%; margin-top: -.9em; right: 48px; } -.ui-li-divider .ui-li-count, .ui-li-static .ui-li-count { right: 10px; } -.ui-li-has-alt .ui-li-count { right: 55px; } -.ui-li-link-alt { position: absolute; width: 40px; height: 100%; border-width: 0; border-left-width: 1px; top: 0; right: 0; margin: 0; padding: 0; z-index: 2; } -.ui-li-link-alt .ui-btn { overflow: hidden; position: absolute; right: 8px; top: 50%; margin: -11px 0 0 0; border-bottom-width: 1px; z-index: -1;} -.ui-li-link-alt .ui-btn-inner { padding: 0; height: 100%; position: absolute; width: 100%; top: 0; left: 0;} -.ui-li-link-alt .ui-btn .ui-icon { right: 50%; margin-right: -9px; } -.ui-listview * .ui-btn-inner > .ui-btn > .ui-btn-inner { border-top: 0px; } -.ui-listview-filter { border-width: 0; overflow: hidden; margin: -15px -15px 15px -15px } -.ui-listview-filter .ui-input-search { margin: 5px; width: auto; display: block; } -.ui-listview-filter-inset { margin: -15px -5px -15px -5px; background: transparent; } -.ui-li.ui-screen-hidden{display:none;} -/* Odd iPad positioning issue. */ -@media only screen and (min-device-width: 768px) and (max-device-width: 1024px) { - .ui-li .ui-btn-text { overflow: visible; } -} -label.ui-slider { font-size: 16px; line-height: 1.4; font-weight: normal; margin: 0 0 .3em; display: block; } -input.ui-slider-input, -.ui-field-contain input.ui-slider-input { display: inline-block; width: 50px; } -select.ui-slider-switch { display: none; } -div.ui-slider { position: relative; display: inline-block; overflow: visible; height: 15px; padding: 0; margin: 0 2% 0 20px; top: 4px; width: 65%; } -div.ui-slider-mini { height: 12px; margin-left: 10px; } -div.ui-slider-bg { border: none; height: 100%; padding-right: 8px; } -.ui-controlgroup a.ui-slider-handle, a.ui-slider-handle { position: absolute; z-index: 1; top: 50%; width: 28px; height: 28px; margin-top: -15px; margin-left: -15px; outline: 0; } -a.ui-slider-handle .ui-btn-inner { padding: 0; height: 100%; } -div.ui-slider-mini a.ui-slider-handle { height: 14px; width: 14px; margin: -8px 0 0 -7px; } -div.ui-slider-mini a.ui-slider-handle .ui-btn-inner { height: 30px; width: 30px; padding: 0; margin: -9px 0 0 -9px; } -@media all and (min-width: 450px){ - .ui-field-contain label.ui-slider { vertical-align: top; display: inline-block; width: 20%; margin: 0 2% 0 0; } - .ui-field-contain div.ui-slider { width: 43%; } - .ui-field-contain div.ui-slider-switch { width: 5.5em; } -} -div.ui-slider-switch { height: 32px; margin-left: 0; width: 5.8em; } -a.ui-slider-handle-snapping { -webkit-transition: left 70ms linear; -moz-transition: left 70ms linear; } -div.ui-slider-switch .ui-slider-handle { margin-top: 1px; } -.ui-slider-inneroffset { margin: 0 16px; position: relative; z-index: 1; } -div.ui-slider-switch.ui-slider-mini { width: 5em; height: 29px; } -div.ui-slider-switch.ui-slider-mini .ui-slider-inneroffset { margin: 0 15px 0 14px; } -div.ui-slider-switch.ui-slider-mini .ui-slider-handle { width: 25px; height: 25px; margin: 1px 0 0 -13px; } -div.ui-slider-switch.ui-slider-mini a.ui-slider-handle .ui-btn-inner { height: 30px; width: 30px; padding: 0; margin: 0; } -span.ui-slider-label { position: absolute; text-align: center; width: 100%; overflow: hidden; font-size: 16px; top: 0; line-height: 2; min-height: 100%; border-width: 0; white-space: nowrap; } -.ui-slider-mini span.ui-slider-label { font-size: 14px; } -span.ui-slider-label-a { z-index: 1; left: 0; text-indent: -1.5em; } -span.ui-slider-label-b { z-index: 0; right: 0; text-indent: 1.5em;} -.ui-slider-inline { width: 120px; display: inline-block; } diff --git a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/jquery.mobile-1.1.0.js b/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/jquery.mobile-1.1.0.js deleted file mode 100644 index c12426c0ae..0000000000 --- a/MediaBrowser.HtmlBrowser/Html/thirdparty/jquery.mobile110/jquery.mobile-1.1.0.js +++ /dev/null @@ -1,7551 +0,0 @@ -/* -* jQuery Mobile Framework 1.1.0 db342b1f315c282692791aa870455901fdb46a55 -* http://jquerymobile.com -* -* Copyright 2011 (c) jQuery Project -* Dual licensed under the MIT or GPL Version 2 licenses. -* http://jquery.org/license -* -*/ -(function ( root, doc, factory ) { - if ( typeof define === "function" && define.amd ) { - // AMD. Register as an anonymous module. - define( [ "jquery" ], function ( $ ) { - factory( $, root, doc ); - return $.mobile; - }); - } else { - // Browser globals - factory( root.jQuery, root, doc ); - } -}( this, document, function ( $, window, document, undefined ) { - - -// This plugin is an experiment for abstracting away the touch and mouse -// events so that developers don't have to worry about which method of input -// the device their document is loaded on supports. -// -// The idea here is to allow the developer to register listeners for the -// basic mouse events, such as mousedown, mousemove, mouseup, and click, -// and the plugin will take care of registering the correct listeners -// behind the scenes to invoke the listener at the fastest possible time -// for that device, while still retaining the order of event firing in -// the traditional mouse environment, should multiple handlers be registered -// on the same element for different events. -// -// The current version exposes the following virtual events to jQuery bind methods: -// "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel" - -(function( $, window, document, undefined ) { - -var dataPropertyName = "virtualMouseBindings", - touchTargetPropertyName = "virtualTouchID", - virtualEventNames = "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split( " " ), - touchEventProps = "clientX clientY pageX pageY screenX screenY".split( " " ), - mouseHookProps = $.event.mouseHooks ? $.event.mouseHooks.props : [], - mouseEventProps = $.event.props.concat( mouseHookProps ), - activeDocHandlers = {}, - resetTimerID = 0, - startX = 0, - startY = 0, - didScroll = false, - clickBlockList = [], - blockMouseTriggers = false, - blockTouchTriggers = false, - eventCaptureSupported = "addEventListener" in document, - $document = $( document ), - nextTouchID = 1, - lastTouchID = 0; - -$.vmouse = { - moveDistanceThreshold: 10, - clickDistanceThreshold: 10, - resetTimerDuration: 1500 -}; - -function getNativeEvent( event ) { - - while ( event && typeof event.originalEvent !== "undefined" ) { - event = event.originalEvent; - } - return event; -} - -function createVirtualEvent( event, eventType ) { - - var t = event.type, - oe, props, ne, prop, ct, touch, i, j; - - event = $.Event(event); - event.type = eventType; - - oe = event.originalEvent; - props = $.event.props; - - // addresses separation of $.event.props in to $.event.mouseHook.props and Issue 3280 - // https://github.com/jquery/jquery-mobile/issues/3280 - if ( t.search( /^(mouse|click)/ ) > -1 ) { - props = mouseEventProps; - } - - // copy original event properties over to the new event - // this would happen if we could call $.event.fix instead of $.Event - // but we don't have a way to force an event to be fixed multiple times - if ( oe ) { - for ( i = props.length, prop; i; ) { - prop = props[ --i ]; - event[ prop ] = oe[ prop ]; - } - } - - // make sure that if the mouse and click virtual events are generated - // without a .which one is defined - if ( t.search(/mouse(down|up)|click/) > -1 && !event.which ){ - event.which = 1; - } - - if ( t.search(/^touch/) !== -1 ) { - ne = getNativeEvent( oe ); - t = ne.touches; - ct = ne.changedTouches; - touch = ( t && t.length ) ? t[0] : ( (ct && ct.length) ? ct[ 0 ] : undefined ); - - if ( touch ) { - for ( j = 0, len = touchEventProps.length; j < len; j++){ - prop = touchEventProps[ j ]; - event[ prop ] = touch[ prop ]; - } - } - } - - return event; -} - -function getVirtualBindingFlags( element ) { - - var flags = {}, - b, k; - - while ( element ) { - - b = $.data( element, dataPropertyName ); - - for ( k in b ) { - if ( b[ k ] ) { - flags[ k ] = flags.hasVirtualBinding = true; - } - } - element = element.parentNode; - } - return flags; -} - -function getClosestElementWithVirtualBinding( element, eventType ) { - var b; - while ( element ) { - - b = $.data( element, dataPropertyName ); - - if ( b && ( !eventType || b[ eventType ] ) ) { - return element; - } - element = element.parentNode; - } - return null; -} - -function enableTouchBindings() { - blockTouchTriggers = false; -} - -function disableTouchBindings() { - blockTouchTriggers = true; -} - -function enableMouseBindings() { - lastTouchID = 0; - clickBlockList.length = 0; - blockMouseTriggers = false; - - // When mouse bindings are enabled, our - // touch bindings are disabled. - disableTouchBindings(); -} - -function disableMouseBindings() { - // When mouse bindings are disabled, our - // touch bindings are enabled. - enableTouchBindings(); -} - -function startResetTimer() { - clearResetTimer(); - resetTimerID = setTimeout(function(){ - resetTimerID = 0; - enableMouseBindings(); - }, $.vmouse.resetTimerDuration ); -} - -function clearResetTimer() { - if ( resetTimerID ){ - clearTimeout( resetTimerID ); - resetTimerID = 0; - } -} - -function triggerVirtualEvent( eventType, event, flags ) { - var ve; - - if ( ( flags && flags[ eventType ] ) || - ( !flags && getClosestElementWithVirtualBinding( event.target, eventType ) ) ) { - - ve = createVirtualEvent( event, eventType ); - - $( event.target).trigger( ve ); - } - - return ve; -} - -function mouseEventCallback( event ) { - var touchID = $.data(event.target, touchTargetPropertyName); - - if ( !blockMouseTriggers && ( !lastTouchID || lastTouchID !== touchID ) ){ - var ve = triggerVirtualEvent( "v" + event.type, event ); - if ( ve ) { - if ( ve.isDefaultPrevented() ) { - event.preventDefault(); - } - if ( ve.isPropagationStopped() ) { - event.stopPropagation(); - } - if ( ve.isImmediatePropagationStopped() ) { - event.stopImmediatePropagation(); - } - } - } -} - -function handleTouchStart( event ) { - - var touches = getNativeEvent( event ).touches, - target, flags; - - if ( touches && touches.length === 1 ) { - - target = event.target; - flags = getVirtualBindingFlags( target ); - - if ( flags.hasVirtualBinding ) { - - lastTouchID = nextTouchID++; - $.data( target, touchTargetPropertyName, lastTouchID ); - - clearResetTimer(); - - disableMouseBindings(); - didScroll = false; - - var t = getNativeEvent( event ).touches[ 0 ]; - startX = t.pageX; - startY = t.pageY; - - triggerVirtualEvent( "vmouseover", event, flags ); - triggerVirtualEvent( "vmousedown", event, flags ); - } - } -} - -function handleScroll( event ) { - if ( blockTouchTriggers ) { - return; - } - - if ( !didScroll ) { - triggerVirtualEvent( "vmousecancel", event, getVirtualBindingFlags( event.target ) ); - } - - didScroll = true; - startResetTimer(); -} - -function handleTouchMove( event ) { - if ( blockTouchTriggers ) { - return; - } - - var t = getNativeEvent( event ).touches[ 0 ], - didCancel = didScroll, - moveThreshold = $.vmouse.moveDistanceThreshold; - didScroll = didScroll || - ( Math.abs(t.pageX - startX) > moveThreshold || - Math.abs(t.pageY - startY) > moveThreshold ), - flags = getVirtualBindingFlags( event.target ); - - if ( didScroll && !didCancel ) { - triggerVirtualEvent( "vmousecancel", event, flags ); - } - - triggerVirtualEvent( "vmousemove", event, flags ); - startResetTimer(); -} - -function handleTouchEnd( event ) { - if ( blockTouchTriggers ) { - return; - } - - disableTouchBindings(); - - var flags = getVirtualBindingFlags( event.target ), - t; - triggerVirtualEvent( "vmouseup", event, flags ); - - if ( !didScroll ) { - var ve = triggerVirtualEvent( "vclick", event, flags ); - if ( ve && ve.isDefaultPrevented() ) { - // The target of the mouse events that follow the touchend - // event don't necessarily match the target used during the - // touch. This means we need to rely on coordinates for blocking - // any click that is generated. - t = getNativeEvent( event ).changedTouches[ 0 ]; - clickBlockList.push({ - touchID: lastTouchID, - x: t.clientX, - y: t.clientY - }); - - // Prevent any mouse events that follow from triggering - // virtual event notifications. - blockMouseTriggers = true; - } - } - triggerVirtualEvent( "vmouseout", event, flags); - didScroll = false; - - startResetTimer(); -} - -function hasVirtualBindings( ele ) { - var bindings = $.data( ele, dataPropertyName ), - k; - - if ( bindings ) { - for ( k in bindings ) { - if ( bindings[ k ] ) { - return true; - } - } - } - return false; -} - -function dummyMouseHandler(){} - -function getSpecialEventObject( eventType ) { - var realType = eventType.substr( 1 ); - - return { - setup: function( data, namespace ) { - // If this is the first virtual mouse binding for this element, - // add a bindings object to its data. - - if ( !hasVirtualBindings( this ) ) { - $.data( this, dataPropertyName, {}); - } - - // If setup is called, we know it is the first binding for this - // eventType, so initialize the count for the eventType to zero. - var bindings = $.data( this, dataPropertyName ); - bindings[ eventType ] = true; - - // If this is the first virtual mouse event for this type, - // register a global handler on the document. - - activeDocHandlers[ eventType ] = ( activeDocHandlers[ eventType ] || 0 ) + 1; - - if ( activeDocHandlers[ eventType ] === 1 ) { - $document.bind( realType, mouseEventCallback ); - } - - // Some browsers, like Opera Mini, won't dispatch mouse/click events - // for elements unless they actually have handlers registered on them. - // To get around this, we register dummy handlers on the elements. - - $( this ).bind( realType, dummyMouseHandler ); - - // For now, if event capture is not supported, we rely on mouse handlers. - if ( eventCaptureSupported ) { - // If this is the first virtual mouse binding for the document, - // register our touchstart handler on the document. - - activeDocHandlers[ "touchstart" ] = ( activeDocHandlers[ "touchstart" ] || 0) + 1; - - if (activeDocHandlers[ "touchstart" ] === 1) { - $document.bind( "touchstart", handleTouchStart ) - .bind( "touchend", handleTouchEnd ) - - // On touch platforms, touching the screen and then dragging your finger - // causes the window content to scroll after some distance threshold is - // exceeded. On these platforms, a scroll prevents a click event from being - // dispatched, and on some platforms, even the touchend is suppressed. To - // mimic the suppression of the click event, we need to watch for a scroll - // event. Unfortunately, some platforms like iOS don't dispatch scroll - // events until *AFTER* the user lifts their finger (touchend). This means - // we need to watch both scroll and touchmove events to figure out whether - // or not a scroll happenens before the touchend event is fired. - - .bind( "touchmove", handleTouchMove ) - .bind( "scroll", handleScroll ); - } - } - }, - - teardown: function( data, namespace ) { - // If this is the last virtual binding for this eventType, - // remove its global handler from the document. - - --activeDocHandlers[ eventType ]; - - if ( !activeDocHandlers[ eventType ] ) { - $document.unbind( realType, mouseEventCallback ); - } - - if ( eventCaptureSupported ) { - // If this is the last virtual mouse binding in existence, - // remove our document touchstart listener. - - --activeDocHandlers[ "touchstart" ]; - - if ( !activeDocHandlers[ "touchstart" ] ) { - $document.unbind( "touchstart", handleTouchStart ) - .unbind( "touchmove", handleTouchMove ) - .unbind( "touchend", handleTouchEnd ) - .unbind( "scroll", handleScroll ); - } - } - - var $this = $( this ), - bindings = $.data( this, dataPropertyName ); - - // teardown may be called when an element was - // removed from the DOM. If this is the case, - // jQuery core may have already stripped the element - // of any data bindings so we need to check it before - // using it. - if ( bindings ) { - bindings[ eventType ] = false; - } - - // Unregister the dummy event handler. - - $this.unbind( realType, dummyMouseHandler ); - - // If this is the last virtual mouse binding on the - // element, remove the binding data from the element. - - if ( !hasVirtualBindings( this ) ) { - $this.removeData( dataPropertyName ); - } - } - }; -} - -// Expose our custom events to the jQuery bind/unbind mechanism. - -for ( var i = 0; i < virtualEventNames.length; i++ ){ - $.event.special[ virtualEventNames[ i ] ] = getSpecialEventObject( virtualEventNames[ i ] ); -} - -// Add a capture click handler to block clicks. -// Note that we require event capture support for this so if the device -// doesn't support it, we punt for now and rely solely on mouse events. -if ( eventCaptureSupported ) { - document.addEventListener( "click", function( e ){ - var cnt = clickBlockList.length, - target = e.target, - x, y, ele, i, o, touchID; - - if ( cnt ) { - x = e.clientX; - y = e.clientY; - threshold = $.vmouse.clickDistanceThreshold; - - // The idea here is to run through the clickBlockList to see if - // the current click event is in the proximity of one of our - // vclick events that had preventDefault() called on it. If we find - // one, then we block the click. - // - // Why do we have to rely on proximity? - // - // Because the target of the touch event that triggered the vclick - // can be different from the target of the click event synthesized - // by the browser. The target of a mouse/click event that is syntehsized - // from a touch event seems to be implementation specific. For example, - // some browsers will fire mouse/click events for a link that is near - // a touch event, even though the target of the touchstart/touchend event - // says the user touched outside the link. Also, it seems that with most - // browsers, the target of the mouse/click event is not calculated until the - // time it is dispatched, so if you replace an element that you touched - // with another element, the target of the mouse/click will be the new - // element underneath that point. - // - // Aside from proximity, we also check to see if the target and any - // of its ancestors were the ones that blocked a click. This is necessary - // because of the strange mouse/click target calculation done in the - // Android 2.1 browser, where if you click on an element, and there is a - // mouse/click handler on one of its ancestors, the target will be the - // innermost child of the touched element, even if that child is no where - // near the point of touch. - - ele = target; - - while ( ele ) { - for ( i = 0; i < cnt; i++ ) { - o = clickBlockList[ i ]; - touchID = 0; - - if ( ( ele === target && Math.abs( o.x - x ) < threshold && Math.abs( o.y - y ) < threshold ) || - $.data( ele, touchTargetPropertyName ) === o.touchID ) { - // XXX: We may want to consider removing matches from the block list - // instead of waiting for the reset timer to fire. - e.preventDefault(); - e.stopPropagation(); - return; - } - } - ele = ele.parentNode; - } - } - }, true); -} -})( jQuery, window, document ); - - - -// Script: jQuery hashchange event -// -// *Version: 1.3, Last updated: 7/21/2010* -// -// Project Home - http://benalman.com/projects/jquery-hashchange-plugin/ -// GitHub - http://github.com/cowboy/jquery-hashchange/ -// Source - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.js -// (Minified) - http://github.com/cowboy/jquery-hashchange/raw/master/jquery.ba-hashchange.min.js (0.8kb gzipped) -// -// About: License -// -// Copyright (c) 2010 "Cowboy" Ben Alman, -// Dual licensed under the MIT and GPL licenses. -// http://benalman.com/about/license/ -// -// About: Examples -// -// These working examples, complete with fully commented code, illustrate a few -// ways in which this plugin can be used. -// -// hashchange event - http://benalman.com/code/projects/jquery-hashchange/examples/hashchange/ -// document.domain - http://benalman.com/code/projects/jquery-hashchange/examples/document_domain/ -// -// About: Support and Testing -// -// Information about what version or versions of jQuery this plugin has been -// tested with, what browsers it has been tested in, and where the unit tests -// reside (so you can test it yourself). -// -// jQuery Versions - 1.2.6, 1.3.2, 1.4.1, 1.4.2 -// Browsers Tested - Internet Explorer 6-8, Firefox 2-4, Chrome 5-6, Safari 3.2-5, -// Opera 9.6-10.60, iPhone 3.1, Android 1.6-2.2, BlackBerry 4.6-5. -// Unit Tests - http://benalman.com/code/projects/jquery-hashchange/unit/ -// -// About: Known issues -// -// While this jQuery hashchange event implementation is quite stable and -// robust, there are a few unfortunate browser bugs surrounding expected -// hashchange event-based behaviors, independent of any JavaScript -// window.onhashchange abstraction. See the following examples for more -// information: -// -// Chrome: Back Button - http://benalman.com/code/projects/jquery-hashchange/examples/bug-chrome-back-button/ -// Firefox: Remote XMLHttpRequest - http://benalman.com/code/projects/jquery-hashchange/examples/bug-firefox-remote-xhr/ -// WebKit: Back Button in an Iframe - http://benalman.com/code/projects/jquery-hashchange/examples/bug-webkit-hash-iframe/ -// Safari: Back Button from a different domain - http://benalman.com/code/projects/jquery-hashchange/examples/bug-safari-back-from-diff-domain/ -// -// Also note that should a browser natively support the window.onhashchange -// event, but not report that it does, the fallback polling loop will be used. -// -// About: Release History -// -// 1.3 - (7/21/2010) Reorganized IE6/7 Iframe code to make it more -// "removable" for mobile-only development. Added IE6/7 document.title -// support. Attempted to make Iframe as hidden as possible by using -// techniques from http://www.paciellogroup.com/blog/?p=604. Added -// support for the "shortcut" format $(window).hashchange( fn ) and -// $(window).hashchange() like jQuery provides for built-in events. -// Renamed jQuery.hashchangeDelay to and -// lowered its default value to 50. Added -// and properties plus document-domain.html -// file to address access denied issues when setting document.domain in -// IE6/7. -// 1.2 - (2/11/2010) Fixed a bug where coming back to a page using this plugin -// from a page on another domain would cause an error in Safari 4. Also, -// IE6/7 Iframe is now inserted after the body (this actually works), -// which prevents the page from scrolling when the event is first bound. -// Event can also now be bound before DOM ready, but it won't be usable -// before then in IE6/7. -// 1.1 - (1/21/2010) Incorporated document.documentMode test to fix IE8 bug -// where browser version is incorrectly reported as 8.0, despite -// inclusion of the X-UA-Compatible IE=EmulateIE7 meta tag. -// 1.0 - (1/9/2010) Initial Release. Broke out the jQuery BBQ event.special -// window.onhashchange functionality into a separate plugin for users -// who want just the basic event & back button support, without all the -// extra awesomeness that BBQ provides. This plugin will be included as -// part of jQuery BBQ, but also be available separately. - -(function($,window,undefined){ - // Reused string. - var str_hashchange = 'hashchange', - - // Method / object references. - doc = document, - fake_onhashchange, - special = $.event.special, - - // Does the browser support window.onhashchange? Note that IE8 running in - // IE7 compatibility mode reports true for 'onhashchange' in window, even - // though the event isn't supported, so also test document.documentMode. - doc_mode = doc.documentMode, - supports_onhashchange = 'on' + str_hashchange in window && ( doc_mode === undefined || doc_mode > 7 ); - - // Get location.hash (or what you'd expect location.hash to be) sans any - // leading #. Thanks for making this necessary, Firefox! - function get_fragment( url ) { - url = url || location.href; - return '#' + url.replace( /^[^#]*#?(.*)$/, '$1' ); - }; - - // Method: jQuery.fn.hashchange - // - // Bind a handler to the window.onhashchange event or trigger all bound - // window.onhashchange event handlers. This behavior is consistent with - // jQuery's built-in event handlers. - // - // Usage: - // - // > jQuery(window).hashchange( [ handler ] ); - // - // Arguments: - // - // handler - (Function) Optional handler to be bound to the hashchange - // event. This is a "shortcut" for the more verbose form: - // jQuery(window).bind( 'hashchange', handler ). If handler is omitted, - // all bound window.onhashchange event handlers will be triggered. This - // is a shortcut for the more verbose - // jQuery(window).trigger( 'hashchange' ). These forms are described in - // the section. - // - // Returns: - // - // (jQuery) The initial jQuery collection of elements. - - // Allow the "shortcut" format $(elem).hashchange( fn ) for binding and - // $(elem).hashchange() for triggering, like jQuery does for built-in events. - $.fn[ str_hashchange ] = function( fn ) { - return fn ? this.bind( str_hashchange, fn ) : this.trigger( str_hashchange ); - }; - - // Property: jQuery.fn.hashchange.delay - // - // The numeric interval (in milliseconds) at which the - // polling loop executes. Defaults to 50. - - // Property: jQuery.fn.hashchange.domain - // - // If you're setting document.domain in your JavaScript, and you want hash - // history to work in IE6/7, not only must this property be set, but you must - // also set document.domain BEFORE jQuery is loaded into the page. This - // property is only applicable if you are supporting IE6/7 (or IE8 operating - // in "IE7 compatibility" mode). - // - // In addition, the property must be set to the - // path of the included "document-domain.html" file, which can be renamed or - // modified if necessary (note that the document.domain specified must be the - // same in both your main JavaScript as well as in this file). - // - // Usage: - // - // jQuery.fn.hashchange.domain = document.domain; - - // Property: jQuery.fn.hashchange.src - // - // If, for some reason, you need to specify an Iframe src file (for example, - // when setting document.domain as in ), you can - // do so using this property. Note that when using this property, history - // won't be recorded in IE6/7 until the Iframe src file loads. This property - // is only applicable if you are supporting IE6/7 (or IE8 operating in "IE7 - // compatibility" mode). - // - // Usage: - // - // jQuery.fn.hashchange.src = 'path/to/file.html'; - - $.fn[ str_hashchange ].delay = 50; - /* - $.fn[ str_hashchange ].domain = null; - $.fn[ str_hashchange ].src = null; - */ - - // Event: hashchange event - // - // Fired when location.hash changes. In browsers that support it, the native - // HTML5 window.onhashchange event is used, otherwise a polling loop is - // initialized, running every milliseconds to - // see if the hash has changed. In IE6/7 (and IE8 operating in "IE7 - // compatibility" mode), a hidden Iframe is created to allow the back button - // and hash-based history to work. - // - // Usage as described in : - // - // > // Bind an event handler. - // > jQuery(window).hashchange( function(e) { - // > var hash = location.hash; - // > ... - // > }); - // > - // > // Manually trigger the event handler. - // > jQuery(window).hashchange(); - // - // A more verbose usage that allows for event namespacing: - // - // > // Bind an event handler. - // > jQuery(window).bind( 'hashchange', function(e) { - // > var hash = location.hash; - // > ... - // > }); - // > - // > // Manually trigger the event handler. - // > jQuery(window).trigger( 'hashchange' ); - // - // Additional Notes: - // - // * The polling loop and Iframe are not created until at least one handler - // is actually bound to the 'hashchange' event. - // * If you need the bound handler(s) to execute immediately, in cases where - // a location.hash exists on page load, via bookmark or page refresh for - // example, use jQuery(window).hashchange() or the more verbose - // jQuery(window).trigger( 'hashchange' ). - // * The event can be bound before DOM ready, but since it won't be usable - // before then in IE6/7 (due to the necessary Iframe), recommended usage is - // to bind it inside a DOM ready handler. - - // Override existing $.event.special.hashchange methods (allowing this plugin - // to be defined after jQuery BBQ in BBQ's source code). - special[ str_hashchange ] = $.extend( special[ str_hashchange ], { - - // Called only when the first 'hashchange' event is bound to window. - setup: function() { - // If window.onhashchange is supported natively, there's nothing to do.. - if ( supports_onhashchange ) { return false; } - - // Otherwise, we need to create our own. And we don't want to call this - // until the user binds to the event, just in case they never do, since it - // will create a polling loop and possibly even a hidden Iframe. - $( fake_onhashchange.start ); - }, - - // Called only when the last 'hashchange' event is unbound from window. - teardown: function() { - // If window.onhashchange is supported natively, there's nothing to do.. - if ( supports_onhashchange ) { return false; } - - // Otherwise, we need to stop ours (if possible). - $( fake_onhashchange.stop ); - } - - }); - - // fake_onhashchange does all the work of triggering the window.onhashchange - // event for browsers that don't natively support it, including creating a - // polling loop to watch for hash changes and in IE 6/7 creating a hidden - // Iframe to enable back and forward. - fake_onhashchange = (function(){ - var self = {}, - timeout_id, - - // Remember the initial hash so it doesn't get triggered immediately. - last_hash = get_fragment(), - - fn_retval = function(val){ return val; }, - history_set = fn_retval, - history_get = fn_retval; - - // Start the polling loop. - self.start = function() { - timeout_id || poll(); - }; - - // Stop the polling loop. - self.stop = function() { - timeout_id && clearTimeout( timeout_id ); - timeout_id = undefined; - }; - - // This polling loop checks every $.fn.hashchange.delay milliseconds to see - // if location.hash has changed, and triggers the 'hashchange' event on - // window when necessary. - function poll() { - var hash = get_fragment(), - history_hash = history_get( last_hash ); - - if ( hash !== last_hash ) { - history_set( last_hash = hash, history_hash ); - - $(window).trigger( str_hashchange ); - - } else if ( history_hash !== last_hash ) { - location.href = location.href.replace( /#.*/, '' ) + history_hash; - } - - timeout_id = setTimeout( poll, $.fn[ str_hashchange ].delay ); - }; - - // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - // vvvvvvvvvvvvvvvvvvv REMOVE IF NOT SUPPORTING IE6/7/8 vvvvvvvvvvvvvvvvvvv - // vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv - $.browser.msie && !supports_onhashchange && (function(){ - // Not only do IE6/7 need the "magical" Iframe treatment, but so does IE8 - // when running in "IE7 compatibility" mode. - - var iframe, - iframe_src; - - // When the event is bound and polling starts in IE 6/7, create a hidden - // Iframe for history handling. - self.start = function(){ - if ( !iframe ) { - iframe_src = $.fn[ str_hashchange ].src; - iframe_src = iframe_src && iframe_src + get_fragment(); - - // Create hidden Iframe. Attempt to make Iframe as hidden as possible - // by using techniques from http://www.paciellogroup.com/blog/?p=604. - iframe = $('