diff --git a/dashboard-ui/advanced.html b/dashboard-ui/advanced.html index 2946e104c6..f4e529bc54 100644 --- a/dashboard-ui/advanced.html +++ b/dashboard-ui/advanced.html @@ -11,7 +11,7 @@
General - Http Server + Server Transcoding
diff --git a/dashboard-ui/advancedserversettings.html b/dashboard-ui/advancedserversettings.html index b2eab62e4b..e4bbefdfa0 100644 --- a/dashboard-ui/advancedserversettings.html +++ b/dashboard-ui/advancedserversettings.html @@ -11,7 +11,7 @@
General - Http Server + Server Transcoding
@@ -25,6 +25,11 @@ +
  • + + +
    If you have a dynamic DNS enter it here. Media Browser apps will use it when connecting remotely.
    +
  • diff --git a/dashboard-ui/autoorganizelog.html b/dashboard-ui/autoorganizelog.html index 577e6b1dd8..eec31292f5 100644 --- a/dashboard-ui/autoorganizelog.html +++ b/dashboard-ui/autoorganizelog.html @@ -14,7 +14,7 @@ TV Settings -
    +
    diff --git a/dashboard-ui/css/detailtable.css b/dashboard-ui/css/detailtable.css index c7920d5fdd..5111c8dae7 100644 --- a/dashboard-ui/css/detailtable.css +++ b/dashboard-ui/css/detailtable.css @@ -11,6 +11,7 @@ text-align: left; width: 100%; margin: 0 auto; + text-shadow: none!important; } .stretchedDetailTable { diff --git a/dashboard-ui/css/images/items/list/remotesearch.png b/dashboard-ui/css/images/items/list/remotesearch.png new file mode 100644 index 0000000000..979ba2e8e7 Binary files /dev/null and b/dashboard-ui/css/images/items/list/remotesearch.png differ diff --git a/dashboard-ui/css/librarybrowser.css b/dashboard-ui/css/librarybrowser.css index a268f6d7d2..9ce0576fe4 100644 --- a/dashboard-ui/css/librarybrowser.css +++ b/dashboard-ui/css/librarybrowser.css @@ -385,7 +385,7 @@ a.itemTag:hover { background-size: cover; background-position: center 15%; background-repeat: no-repeat; - height: 500px; + height: 550px; border-bottom: 1px solid #111; position: relative; } @@ -869,6 +869,26 @@ a.itemTag:hover { background-color: transparent !important; } +.unidentifiedIndicator { + display: block; + position: absolute; + top: 5px; + left: 5px; + text-align: center; + vertical-align: middle; + width: 24px; + height: 19px; + padding-top: 3px; + border-radius: 50%; + color: #fff; + background: rgb(204, 0, 0); + background: rgba(204, 0, 0, .8); +} + + .unidentifiedIndicator div:after { + background-color: transparent !important; + } + .itemProgress { vertical-align: top; font-size: 19px; diff --git a/dashboard-ui/css/metadataeditor.css b/dashboard-ui/css/metadataeditor.css index e481ece130..2896e6fd6f 100644 --- a/dashboard-ui/css/metadataeditor.css +++ b/dashboard-ui/css/metadataeditor.css @@ -53,6 +53,9 @@ background-repeat: no-repeat; background-size: contain; display: block; + /* For the box shadow so that the bottom border isnt underneath the text */ + z-index: 100000; + position: relative; } .remotePosterImage { @@ -84,6 +87,43 @@ padding-right: 0!important; } + +.searchImage { + background-position: center bottom; + background-repeat: no-repeat; + background-size: contain; + display: block; +} + +.searchBackdropImageContainer { + width: 160px; +} + +.searchDiscImageContainer { + width: 150px; +} + +.searchPosterImageContainer { + width: 140px; +} + +.searchBackdropImageContainer .searchImage { + height: 90px; +} + +.searchDiscImageContainer .searchImage { + height: 150px; +} + +.searchPosterImageContainer .searchImage { + height: 210px; +} + +.searchImageContainer .remoteImageDetails { + overflow-x: hidden; + text-overflow: ellipsis; +} + @media all and (min-width: 500px) { .availableImagesList { @@ -104,6 +144,28 @@ } } +.libraryReportIndicator { + position: relative; + display: block; + text-align: center; + vertical-align: middle; + width: 24px; + height: 19px; + padding-top: 3px; + border-radius: 50%; + color: #fff; + background: rgb(204, 0, 0); + background: rgba(204, 0, 0, .8); +} + + .libraryReportIndicator div:after { + background-color: transparent !important; + } + +.clearLibraryReportIndicator { + background-color: transparent !important; +} + .editorTile { display: inline-block; margin: 5px; @@ -134,11 +196,33 @@ padding: 0 0 1em 0; } +.remoteImage:hover, .searchImageContainer:hover { + -moz-box-shadow: 0 0 12px 7px #38c; + -webkit-box-shadow: 0 0 12px 7px #38c; + box-shadow: 0 0 12px 7px #38c; +} + +.tblLibraryReport img { + height: 18px; + margin-right: 10px; +} + +@media all and (min-width: 600px) { + + .popupIdentify { + width: 400px; + } +} + @media all and (min-width: 700px) { .availableImagesList { width: 600px; } + + .popupIdentify { + width: 500px; + } } @media all and (min-width: 800px) { @@ -163,6 +247,10 @@ float: right; width: 67.5%; } + + .popupIdentify { + width: 600px; + } } @media all and (min-width: 900px) { @@ -170,6 +258,10 @@ .availableImagesList { width: 800px; } + + .popupIdentify { + width: 700px; + } } @media all and (min-width: 1000px) { @@ -177,6 +269,10 @@ .availableImagesList { width: 900px; } + + .popupIdentify { + width: 800px; + } } @media all and (min-width: 1100px) { @@ -184,6 +280,10 @@ .availableImagesList { width: 1000px; } + + .popupIdentify { + width: 900px; + } } @media all and (min-width: 1200px) { @@ -191,6 +291,10 @@ .availableImagesList { width: 1100px; } + + .popupIdentify { + width: 1000px; + } } @media all and (min-width: 1300px) { @@ -225,11 +329,41 @@ } } +.popupIdentifyForm, .identificationSearchResults { + overflow-y: auto; +} + + +@media all and (min-height: 500px) { + + .popupIdentifyForm, .identificationSearchResults { + height: 350px; + } +} + +@media all and (min-height: 600px) { + + .popupIdentifyForm, .identificationSearchResults { + height: 450px; + } +} + +@media all and (min-height: 700px) { + + .popupIdentifyForm, .identificationSearchResults { + height: 550px; + } +} + @media all and (min-height: 800px) { .availableImagesList { height: 600px; } + + .popupIdentifyForm, .identificationSearchResults { + height: 600px; + } } @media all and (min-height: 900px) { @@ -237,4 +371,8 @@ .availableImagesList { height: 700px; } + + .popupIdentifyForm, .identificationSearchResults { + height: 700px; + } } diff --git a/dashboard-ui/css/notifications.css b/dashboard-ui/css/notifications.css index 8d84476b73..5c96a2315e 100644 --- a/dashboard-ui/css/notifications.css +++ b/dashboard-ui/css/notifications.css @@ -182,19 +182,4 @@ .notificationContent p { max-width: 350px; } -} - -@media all and (min-width: 600px) { - .notificationsFlyout { - width: 500px; - } - - .imgNotification, .imgNotificationInner { - width: 60px; - height: 60px; - } - - .notificationContent p { - max-width: 400px; - } -} +} \ No newline at end of file diff --git a/dashboard-ui/css/site.css b/dashboard-ui/css/site.css index 3eb3895026..6d4e081c19 100644 --- a/dashboard-ui/css/site.css +++ b/dashboard-ui/css/site.css @@ -253,7 +253,7 @@ h1 .imageLink { color: #fff!important; text-shadow: none!important; font-weight: 400!important; - font-size: 15px; + font-size: 14px; } .sidebarLinks a:hover { @@ -268,7 +268,7 @@ h1 .imageLink { .sidebarDivider { height: 1px; - background: #444; + background: #404040; margin: .25em 0; } diff --git a/dashboard-ui/edititemmetadata.html b/dashboard-ui/edititemmetadata.html index 67f8166cd1..1c8dccac1f 100644 --- a/dashboard-ui/edititemmetadata.html +++ b/dashboard-ui/edititemmetadata.html @@ -36,17 +36,18 @@
    - +
    - + + + +
    +
    +
    +
    +
    diff --git a/dashboard-ui/encodingsettings.html b/dashboard-ui/encodingsettings.html index 4b30344134..66a05c89bc 100644 --- a/dashboard-ui/encodingsettings.html +++ b/dashboard-ui/encodingsettings.html @@ -11,7 +11,7 @@ diff --git a/dashboard-ui/libraryreport.html b/dashboard-ui/libraryreport.html new file mode 100644 index 0000000000..329d7a6e31 --- /dev/null +++ b/dashboard-ui/libraryreport.html @@ -0,0 +1,155 @@ + + + + Media Browser + + +
    +
    +
    +
    +
      +
    +
    +
    +
    + +

    Reports

    + +
    +
    + Report: +
    + +
    + +
    +
    +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +
    + +
    + Filters: + + + + +
    +
    +
    + + Video Type: + + + + + + + + + + + + + + + + + + + + + +
    +
    +
    + + Episodes: + + + + + + + +
    +
    + + + +
    +
    + +
    + + diff --git a/dashboard-ui/scripts/advancedserversettings.js b/dashboard-ui/scripts/advancedserversettings.js index e45b0a7d3f..0cccc9eccd 100644 --- a/dashboard-ui/scripts/advancedserversettings.js +++ b/dashboard-ui/scripts/advancedserversettings.js @@ -13,6 +13,8 @@ $('#txtPortNumber', page).val(config.HttpServerPortNumber); + $('#txtDdns', page).val(config.WanDdns || ''); + $('#chkEnableUpnp', page).checked(config.EnableUPnP).checkboxradio('refresh'); Dashboard.hideLoadingMsg(); @@ -49,6 +51,8 @@ config.HttpServerPortNumber = $('#txtPortNumber', form).val(); config.EnableUPnP = $('#chkEnableUpnp', form).checked(); + config.WanDdns = $('#txtDdns', form).val(); + ApiClient.updateServerConfiguration(config).done(Dashboard.processServerConfigurationUpdateResult); }); diff --git a/dashboard-ui/scripts/edititemimages.js b/dashboard-ui/scripts/edititemimages.js index d5f782e6fd..4accdb59c2 100644 --- a/dashboard-ui/scripts/edititemimages.js +++ b/dashboard-ui/scripts/edititemimages.js @@ -538,6 +538,15 @@ $('.libraryTree', page).on('itemclicked', function (event, data) { + if (data.itemType == "libraryreport") { + Dashboard.navigate('libraryreport.html'); + return; + } + + if (data.itemType == "livetvservice") { + return; + } + if (data.id != currentItem.Id) { MetadataEditor.currentItemId = data.id; diff --git a/dashboard-ui/scripts/edititemmetadata.js b/dashboard-ui/scripts/edititemmetadata.js index f800651580..55cce057e3 100644 --- a/dashboard-ui/scripts/edititemmetadata.js +++ b/dashboard-ui/scripts/edititemmetadata.js @@ -31,7 +31,7 @@ $.when(promise1, promise2, promise3).done(function (response1, response2, response3) { var item = response1[0]; - + currentItem = item; if (item.Type == "UserRootFolder") { @@ -271,7 +271,6 @@ $('#fldSortName', page).hide(); $('#fldDateAdded', page).hide(); $('#fldYear', page).hide(); - $('.fldRefresh', page).hide(); } else { $('#tagsCollapsible', page).show(); $('#metadataSettingsCollapsible', page).show(); @@ -279,7 +278,12 @@ $('#fldSortName', page).show(); $('#fldDateAdded', page).show(); $('#fldYear', page).show(); - $('.fldRefresh', page).show(); + } + + if (item.Type == "Movie" || item.Type == "Trailer" || item.Type == "AdultVideo" || item.Type == "Series" || item.Type == "Game" || item.Type == "BoxSet" || item.Type == "Person" || item.Type == "Book") { + $('#btnIdentify', page).show(); + } else { + $('#btnIdentify', page).hide(); } if (item.Type == "Movie" || item.Type == "Trailer" || item.Type == "BoxSet") { @@ -713,7 +717,7 @@ Revenue: $('#txtRevenue', form).val(), CriticRating: $('#txtCriticRating', form).val(), CriticRatingSummary: $('#txtCriticRatingSummary', form).val(), - IndexNumber: $('#txtIndexNumber', form).val(), + IndexNumber: $('#txtIndexNumber', form).val() || null, DisplaySpecialsWithSeasons: $('#chkDisplaySpecialsInline', form).checked(), AbsoluteEpisodeNumber: $('#txtAbsoluteEpisodeNumber', form).val(), DvdEpisodeNumber: $('#txtDvdEpisodeNumber', form).val(), @@ -721,7 +725,7 @@ AirsBeforeSeasonNumber: $('#txtAirsBeforeSeason', form).val(), AirsAfterSeasonNumber: $('#txtAirsAfterSeason', form).val(), AirsBeforeEpisodeNumber: $('#txtAirsBeforeEpisode', form).val(), - ParentIndexNumber: $('#txtParentIndexNumber', form).val(), + ParentIndexNumber: $('#txtParentIndexNumber', form).val() || null, DisplayOrder: $('#selectDisplayOrder', form).val(), Players: $('#txtPlayers', form).val(), Album: $('#txtAlbum', form).val(), @@ -809,6 +813,10 @@ Dashboard.alert('Item saved.'); + MetadataEditor.getItemPromise().done(function (i) { + $(form).parents('.page').trigger('itemsaved', [i]); + }); + }); return false; @@ -851,10 +859,217 @@ return false; }; + + self.onIdentificationFormSubmitted = function () { + + var page = $(this).parents('.page'); + + searchForIdentificationResults(page); + return false; + }; } window.EditItemMetadataPage = new editItemMetadataPage(); + function showIdentificationForm(page) { + + var item = currentItem; + + $.getJSON(ApiClient.getUrl("Items/" + item.Id + "/ExternalIdInfos")).done(function (idList) { + + var html = ''; + + var providerIds = item.ProviderIds || {}; + + for (var i = 0, length = idList.length; i < length; i++) { + + var idInfo = idList[i]; + + var id = "txtLookup" + idInfo.Key; + + html += '
    '; + html += ''; + + var value = providerIds[idInfo.Key] || ''; + + html += ''; + + html += '
    '; + } + + $('#txtLookupName', page).val(item.Name); + + if (item.Type == "Person" || item.Type == "BoxSet") { + + $('.fldLookupYear', page).hide(); + $('#txtLookupYear', page).val(''); + } else { + + $('.fldLookupYear', page).show(); + $('#txtLookupYear', page).val(item.ProductionYear); + } + + $('.identifyProviderIds', page).html(html).trigger('create'); + + var friendlyName = item.Type == "BoxSet" ? "Collection" : item.Type; + + $('.identificationHeader', page).html('Identify ' + friendlyName); + + $('.popupIdentifyForm', page).show(); + $('.identificationSearchResults', page).hide(); + $('.btnSearchAgain', page).hide(); + + $('.popupIdentify', page).popup('open'); + }); + } + + function searchForIdentificationResults(page) { + + var lookupInfo = { + ProviderIds: {} + }; + + $('.identifyField', page).each(function () { + + var value = this.value; + + if (value) { + + if (this.type == 'number') { + value = parseInt(value); + } + + lookupInfo[this.getAttribute('data-lookup')] = value; + } + + }); + + var hasId = false; + + $('.txtLookupId', page).each(function () { + + var value = this.value; + + if (value) { + hasId = true; + } + lookupInfo.ProviderIds[this.getAttribute('data-providerkey')] = value; + + }); + + if (!hasId && !lookupInfo.Name) { + Dashboard.alert('Please enter a name or an external Id.'); + return; + } + + if (currentItem.GameSystem) { + lookupInfo.GameSystem = currentItem.GameSystem; + } + + lookupInfo = { + SearchInfo: lookupInfo, + IncludeDisabledProviders: true + }; + + Dashboard.showLoadingMsg(); + + $.ajax({ + type: "POST", + url: ApiClient.getUrl("Items/RemoteSearch/" + currentItem.Type), + data: JSON.stringify(lookupInfo), + contentType: "application/json" + + }).done(function (results) { + + Dashboard.hideLoadingMsg(); + showIdentificationSearchResults(page, results); + }); + } + + function getSearchImageDisplayUrl(url, provider) { + return ApiClient.getUrl("Items/RemoteSearch/Image", { imageUrl: url, ProviderName: provider }); + } + + function showIdentificationSearchResults(page, results) { + + $('.popupIdentifyForm', page).hide(); + $('.identificationSearchResults', page).show(); + $('.btnSearchAgain', page).show(); + + var html = ''; + + for (var i = 0, length = results.length; i < length; i++) { + + var result = results[i]; + + var cssClass = "searchImageContainer remoteImageContainer"; + + if (currentItem.Type == "Episode") { + cssClass += " searchBackdropImageContainer"; + } + else if (currentItem.Type == "MusicAlbum" || currentItem.Type == "MusicArtist") { + cssClass += " searchDiscImageContainer"; + } + else { + cssClass += " searchPosterImageContainer"; + } + + html += '
    '; + + if (result.ImageUrl) { + var displayUrl = getSearchImageDisplayUrl(result.ImageUrl, result.SearchProviderName); + + html += ''; + } else { + + html += ''; + } + html += ''; + + html += '
    '; + html += result.Name; + html += '
    '; + + html += '
    '; + html += result.ProductionYear || ' '; + html += '
    '; + + if (result.GameSystem) { + html += '
    '; + html += result.GameSystem; + html += '
    '; + } + + html += '
    '; + } + + var elem = $('.identificationSearchResultList', page).html(html).trigger('create'); + + $('.searchImage', elem).on('click', function () { + + Dashboard.showLoadingMsg(); + + var index = parseInt(this.getAttribute('data-index')); + + var currentResult = results[index]; + + $.ajax({ + type: "POST", + url: ApiClient.getUrl("Items/RemoteSearch/Apply/" + currentItem.Id), + data: JSON.stringify(currentResult), + contentType: "application/json" + + }).done(function () { + + Dashboard.hideLoadingMsg(); + + $('.popupIdentify', page).popup('close'); + + reload(page); + }); + }); + } + $(document).on('pageinit', "#editItemMetadataPage", function () { var page = this; @@ -900,6 +1115,19 @@ }); }); + $('#btnIdentify', page).on('click', function () { + + showIdentificationForm(page); + }); + + $('.btnSearchAgain', page).on('click', function () { + + $('.popupIdentifyForm', page).show(); + $('.identificationSearchResults', page).hide(); + $('.btnSearchAgain', page).hide(); + + }); + function getRandomInt(min, max) { return Math.floor(Math.random() * (max - min + 1) + min); } @@ -937,6 +1165,11 @@ $('.libraryTree', page).on('itemclicked', function (event, data) { + if (data.itemType == "libraryreport") { + Dashboard.navigate('libraryreport.html'); + return; + } + if (data.itemType == "livetvservice") { return; } diff --git a/dashboard-ui/scripts/edititempeople.js b/dashboard-ui/scripts/edititempeople.js index b88a6622e4..897df48bc7 100644 --- a/dashboard-ui/scripts/edititempeople.js +++ b/dashboard-ui/scripts/edititempeople.js @@ -254,6 +254,15 @@ $('.libraryTree', page).on('itemclicked', function (event, data) { + if (data.itemType == "libraryreport") { + Dashboard.navigate('libraryreport.html'); + return; + } + + if (data.itemType == "livetvservice") { + return; + } + if (data.id != currentItem.Id) { MetadataEditor.currentItemId = data.id; MetadataEditor.currentItemName = data.itemName; diff --git a/dashboard-ui/scripts/editorsidebar.js b/dashboard-ui/scripts/editorsidebar.js index cf8f95c3b1..b3dbdd9810 100644 --- a/dashboard-ui/scripts/editorsidebar.js +++ b/dashboard-ui/scripts/editorsidebar.js @@ -4,6 +4,15 @@ var state = item.IsFolder ? folderState : ''; + var htmlName = getNodeInnerHtml(item); + + var rel = item.IsFolder ? 'folder' : 'default'; + + return { attr: { id: item.Id, rel: rel, itemtype: item.Type }, data: htmlName, state: state }; + } + + function getNodeInnerHtml(item) { + var name = item.Name; // Channel number @@ -62,12 +71,10 @@ htmlName += ""; - var rel = item.IsFolder ? 'folder' : 'default'; - - return { attr: { id: item.Id, rel: rel, itemtype: item.Type }, data: htmlName, state: state }; + return htmlName; } - function loadChildrenOfRootNode(callback, openItems) { + function loadChildrenOfRootNode(page, callback, openItems, selectedId) { var promise1 = $.getJSON(ApiClient.getUrl("Library/MediaFolders")); @@ -95,9 +102,7 @@ var name = service.Name; - var cssClass = "editorNode"; - - var htmlName = "
    "; + var htmlName = "
    "; htmlName += name; @@ -106,8 +111,18 @@ nodes.push({ attr: { id: name, rel: 'folder', itemtype: 'livetvservice' }, data: htmlName, state: 'closed' }); } + nodes.push({ attr: { id: 'libraryreport', rel: 'default', itemtype: 'libraryreport' }, data: 'Reports' }); + callback(nodes); + if (selectedId && nodes.filter(function (f) { + + return f.attr.id == selectedId; + + }).length) { + + selectNode(page, selectedId); + } }); } @@ -133,7 +148,7 @@ if (node == '-1') { - loadChildrenOfRootNode(callback, openItems); + loadChildrenOfRootNode(page, callback, openItems, selectedId); return; } @@ -141,6 +156,11 @@ var itemtype = node.attr("itemtype"); + if (itemtype == 'libraryreport') { + + return; + } + if (itemtype == 'livetvservice') { loadLiveTvChannels(id, openItems, callback); @@ -231,8 +251,32 @@ }); } + + function updateEditorNode(page, item) { - $(document).on('pagebeforeshow', ".metadataEditorPage", function () { + var elem = $('#' + item.Id + '>a', page)[0]; + + if (elem == null) { + return; + } + + $('.editorNode', elem).remove(); + + $(elem).append(getNodeInnerHtml(item)); + + if (item.IsFolder) { + + var tree = jQuery.jstree._reference(".libraryTree"); + var currentNode = tree._get_node(null, false); + tree.refresh(currentNode); + } + } + + $(document).on('itemsaved', ".metadataEditorPage", function (e, item) { + + updateEditorNode(this, item); + + }).on('pagebeforeshow', ".metadataEditorPage", function () { window.MetadataEditor = new metadataEditor(); diff --git a/dashboard-ui/scripts/itemdetailpage.js b/dashboard-ui/scripts/itemdetailpage.js index 292212db78..5730fe76d5 100644 --- a/dashboard-ui/scripts/itemdetailpage.js +++ b/dashboard-ui/scripts/itemdetailpage.js @@ -35,7 +35,7 @@ $('#editButtonContainer', page).hide(); } - if (MediaPlayer.canPlay(item, user) && item.LocationType !== "Offline" && item.LocationType !== "Virtual") { + if (MediaPlayer.canPlay(item, user)) { var url = MediaPlayer.getPlayUrl(item); diff --git a/dashboard-ui/scripts/librarybrowser.js b/dashboard-ui/scripts/librarybrowser.js index 78be7dc074..f25dcffd4d 100644 --- a/dashboard-ui/scripts/librarybrowser.js +++ b/dashboard-ui/scripts/librarybrowser.js @@ -373,9 +373,9 @@ if (sortField == selectedSortField) { if (sortDirection == "Descending") { - html += ''; + html += ''; } else { - html += ''; + html += ''; } } } @@ -906,6 +906,10 @@ html += LibraryBrowser.getPlayedIndicatorHtml(item); } + if (item.IsUnidentified) { + html += '
    '; + } + if (!options.overlayText) { if (progressHtml) { @@ -1359,7 +1363,7 @@ html += '
    '; - html += ''; + html += ''; var startAtDisplay = totalRecordCount ? query.StartIndex + 1 : 0; html += startAtDisplay + '-' + recordsEnd + ' of ' + totalRecordCount; @@ -1756,7 +1760,8 @@ if (item.Status == "Continuing") { miscInfo.push(item.ProductionYear + "-Present"); - } else if (item.ProductionYear) { + } + else if (item.ProductionYear) { text = item.ProductionYear; diff --git a/dashboard-ui/scripts/libraryreport.js b/dashboard-ui/scripts/libraryreport.js new file mode 100644 index 0000000000..4575595da5 --- /dev/null +++ b/dashboard-ui/scripts/libraryreport.js @@ -0,0 +1,721 @@ +(function ($, document, window) { + + // The base query options + var query = { + + SortBy: "SeriesSortName,SortName", + SortOrder: "Ascending", + Recursive: true, + Fields: "MediaStreams,DateCreated,Settings,Studios", + StartIndex: 0, + IncludeItemTypes: "Movie", + IsMissing: false, + IsVirtualUnaired: false + }; + + function getHeaderCells(reportType) { + + switch (reportType) { + + case 'Season': + { + return [ + {}, + { name: 'Series' }, + { name: 'Season' }, + { name: 'Date Added' } + ]; + } + case 'Series': + { + return [ + {}, + { name: 'Name' }, + { name: 'Network' }, + { name: 'Date Added' }, + { name: 'Year' }, + { name: 'Rating' }, + { name: 'Runtime' }, + { name: 'Trailers' }, + { name: 'Specials' } + ]; + } + case 'Game': + { + return [ + {}, + { name: 'Name' }, + { name: 'Game System' }, + { name: 'Date Added' }, + { name: 'Release Date' }, + { name: 'Rating' }, + { name: 'Players' }, + { name: 'Trailers' } + ]; + } + case 'Audio': + { + return [ + {}, + { name: 'Album Artist' }, + { name: 'Album' }, + { name: 'Track' }, + { name: 'Name' }, + { name: 'Date Added' }, + { name: 'Release Date' }, + { name: 'Runtime' }, + { name: 'Audio' }, + { name: 'Embedded Image' } + ]; + } + case 'Episode': + { + return [ + {}, + { name: 'Series' }, + { name: 'Season' }, + { name: 'Name' }, + { name: 'Date Added' }, + { name: 'Release Date' }, + { name: 'Runtime' }, + { name: 'Video' }, + { name: 'Audio' }, + { name: 'Subtitles' } + ]; + } + case 'BoxSet': + { + return [ + {}, + { name: 'Name' }, + { name: 'Date Added' }, + { name: 'Release Date' }, + { name: 'Rating' }, + { name: 'Trailers' } + ]; + } + case 'Book': + { + return [ + {}, + { name: 'Series' }, + { name: 'Name' }, + { name: 'Date Added' }, + { name: 'Release Date' }, + { name: 'Rating' } + ]; + } + case 'MusicArtist': + { + return [ + {}, + { name: 'Name' }, + { name: 'Date Added' } + ]; + } + case 'MusicAlbum': + { + return [ + {}, + { name: 'Album Artist' }, + { name: 'Name' }, + { name: 'Date Added' }, + { name: 'Release Date' }, + { name: 'Rating' }, + { name: 'Runtime' } + ]; + } + default: + { + return [ + {}, + { name: 'Name' }, + { name: 'Date Added' }, + { name: 'Release Date' }, + { name: 'Rating' }, + { name: 'Runtime' }, + { name: 'Video' }, + { name: 'Audio' }, + { name: 'Subtitles' }, + { name: 'Trailers' }, + { name: 'Specials' } + ]; + } + } + } + + function getItemCellsHtml(item, headercells) { + + return headercells.map(function (cell) { + + var html = ''; + html += ''; + + switch (cell.type || cell.name) { + + case 'Album Artist': + { + html += item.AlbumArtist || ' '; + break; + } + case 'Album': + { + html += item.Album || ' '; + break; + } + case 'Series': + { + html += item.SeriesName || ' '; + break; + } + case 'Game System': + { + html += item.GameSystem || ' '; + break; + } + case 'Network': + { + html += item.Studios.length ? item.Studios[0].Name : ' '; + break; + } + case 'Track': + { + html += item.IndexNumber == null ? '' : item.IndexNumber; + break; + } + case 'Players': + { + html += item.Players || ' '; + break; + } + case 'Audio': + { + var stream = (item.MediaStreams || []).filter(function (s) { + + return s.Type == 'Audio'; + + })[0]; + + if (stream) { + + var name = (stream.Codec || '').toUpperCase(); + html += name == 'DCA' ? (stream.Profile || '').toUpperCase() : name; + } + break; + } + case 'Video': + { + var stream = (item.MediaStreams || []).filter(function (s) { + + return s.Type == 'Video'; + + })[0]; + + if (stream) { + html += (stream.Codec || '').toUpperCase(); + } + break; + } + case 'Embedded Image': + { + if ((item.MediaStreams || []).filter(function (s) { + + return s.Type == 'Video'; + + }).length) { + html += '
    '; + } + break; + } + case 'Subtitles': + { + var hasSubtitles = (item.MediaStreams || []).filter(function (s) { + + return s.Type == 'Subtitle'; + + }).length; + + if (hasSubtitles) { + html += '
    '; + } + break; + } + case 'Runtime': + { + if (item.RunTimeTicks) { + html += Dashboard.getDisplayTime(item.RunTimeTicks); + } else { + html += ' '; + } + break; + } + case 'Trailers': + { + if (item.LocalTrailerCount) { + + html += '
    '; + } + break; + } + case 'Specials': + { + if (item.SpecialFeatureCount) { + + html += '
    '; + } + break; + } + + case 'Season': + { + if (item.Type == "Episode") { + html += item.ParentIndexNumber == null ? '' : ('Season ' + item.ParentIndexNumber); + } else { + html += '' + LibraryBrowser.getPosterViewDisplayName(item, false, false) + ''; + } + break; + } + + case 'Name': + { + html += '' + LibraryBrowser.getPosterViewDisplayName(item, false, false) + ''; + break; + } + case 'Rating': + { + html += item.OfficialRating || ' '; + break; + } + + case 'Year': + case 'Release Date': + { + if (item.PremiereDate && item.Type != "Series") { + try { + var date = parseISO8601Date(item.PremiereDate, { toLocal: true }); + + html += date.toLocaleDateString(); + } + catch (e) { + html += ' '; + } + } + else if (item.ProductionYear) { + html += item.ProductionYear; + + if (item.Status == "Continuing") { + html += "-Present"; + } + else if (item.EndDate) { + + try { + + var endYear = parseISO8601Date(item.EndDate, { toLocal: true }).getFullYear(); + + if (endYear != item.ProductionYear) { + html += "-" + parseISO8601Date(item.EndDate, { toLocal: true }).getFullYear(); + } + + } + catch (e) { + console.log("Error parsing date: " + item.EndDate); + } + } + + } else { + html += ' '; + } + break; + } + case 'Date Added': + { + if (item.DateCreated) { + try { + html += parseISO8601Date(item.DateCreated, { toLocal: true }).toLocaleDateString(); + } + catch (e) { + html += ' '; + } + } + break; + } + default: + { + if (item.LockData) { + html += ''; + } + if (item.IsUnidentified) { + html += '
    '; + } + + if (!item.LocalTrailerCount && item.Type == "Movie") { + html += ''; + } + + if (!item.ImageTags || !item.ImageTags.Primary) { + html += ''; + } + + if (!item.BackdropImageTags || !item.BackdropImageTags.length) { + if (item.Type !== "Episode" && item.Type !== "Season" && item.MediaType !== "Audio" && item.Type !== "Channel") { + html += ''; + } + } + + if (!item.ImageTags || !item.ImageTags.Logo) { + if (item.Type == "Movie" || item.Type == "Trailer" || item.Type == "Series" || item.Type == "MusicArtist" || item.Type == "BoxSet") { + html += ''; + } + } + + break; + } + } + + html += ''; + return html; + + }).join(''); + } + + function getReportHtml(items, reportType) { + + var html = ''; + + html += ''; + + html += ''; + html += ''; + + var cells = getHeaderCells(reportType); + + html += cells.map(function (c) { + + return ''; + + }).join(''); + + html += ''; + html += ''; + + html += ''; + + for (var i = 0, length = items.length; i < length; i++) { + + var item = items[i]; + + html += ''; + html += getItemCellsHtml(item, cells); + html += ''; + } + + html += ''; + + html += '
    ' + (c.name || ' ') + '
    '; + + return html; + } + + function renderItems(page, result, reportType) { + + // Scroll back up so they can see the results from the beginning + $(document).scrollTop(0); + + $('.listTopPaging', page).html(LibraryBrowser.getPagingHtml(query, result.TotalRecordCount, true)).trigger('create'); + + updateFilterControls(page); + + $('.listBottomPaging', page).html(LibraryBrowser.getPagingHtml(query, result.TotalRecordCount)).trigger('create'); + + $('.reportContainer', page).html(getReportHtml(result.Items, reportType)).trigger('create'); + + $('.btnNextPage', page).on('click', function () { + query.StartIndex += query.Limit; + reloadItems(page); + }); + + $('.btnPreviousPage', page).on('click', function () { + query.StartIndex -= query.Limit; + reloadItems(page); + }); + + $('.selectPageSize', page).on('change', function () { + query.Limit = parseInt(this.value); + query.StartIndex = 0; + reloadItems(page); + }); + } + + function reloadItems(page) { + + var url = ApiClient.getUrl("Items", query); + var reportType = $('#selectView', page).val(); + + $.getJSON(url).done(function (result) { + + renderItems(page, result, reportType); + + }); + } + + function updateFilterControls(page) { + + $('#selectView').val(query.IncludeItemTypes).selectmenu('refresh'); + + $('.chkVideoTypeFilter', page).each(function () { + + var filters = "," + (query.VideoTypes || ""); + var filterName = this.getAttribute('data-filter'); + + this.checked = filters.indexOf(',' + filterName) != -1; + + }).checkboxradio('refresh'); + + $('#chk3D', page).checked(query.Is3D == true).checkboxradio('refresh'); + $('#chkHD', page).checked(query.IsHD == true).checkboxradio('refresh'); + $('#chkSD', page).checked(query.IsHD == false).checkboxradio('refresh'); + + $('#chkSubtitle', page).checked(query.HasSubtitles == true).checkboxradio('refresh'); + $('#chkTrailer', page).checked(query.HasTrailer == true).checkboxradio('refresh'); + $('#chkSpecialFeature', page).checked(query.HasSpecialFeature == true).checkboxradio('refresh'); + $('#chkThemeSong', page).checked(query.HasThemeSong == true).checkboxradio('refresh'); + $('#chkThemeVideo', page).checked(query.HasThemeVideo == true).checkboxradio('refresh'); + $('#chkIsPlaceHolder', page).checked(query.IsPlaceHolder == true).checkboxradio('refresh'); + + $('#chkMissingRating', page).checked(query.HasOfficialRating == false).checkboxradio('refresh'); + $('#chkMissingOverview', page).checked(query.HasOverview == false).checkboxradio('refresh'); + $('#chkYearMismatch', page).checked(query.IsYearMismatched == true).checkboxradio('refresh'); + + $('#chkIsUnidentified', page).checked(query.IsUnidentified == true).checkboxradio('refresh'); + $('#chkIsLocked', page).checked(query.IsLocked == true).checkboxradio('refresh'); + + $('#chkSpecialEpisode', page).checked(query.ParentIndexNumber == 0).checkboxradio('refresh'); + $('#chkMissingEpisode', page).checked(query.IsMissing == true).checkboxradio('refresh'); + $('#chkFutureEpisode', page).checked(query.IsUnaired == true).checkboxradio('refresh'); + } + + $(document).on('pageinit', "#libraryReportPage", function () { + + var page = this; + + $('.libraryTree', page).on('itemclicked', function (event, data) { + + if (data.itemType == "libraryreport") { + return; + } + + if (data.itemType == "livetvservice") { + return; + } + + Dashboard.navigate('edititemmetadata.html?id=' + data.id); + }); + + $('#radioBasicFilters', page).on('change', function () { + + if (this.checked) { + $('.basicFilters', page).show(); + $('.advancedFilters', page).hide(); + } else { + $('.basicFilters', page).hide(); + } + }); + + $('#radioAdvancedFilters', page).on('change', function () { + + if (this.checked) { + $('.advancedFilters', page).show(); + $('.basicFilters', page).hide(); + } else { + $('.advancedFilters', page).hide(); + } + }); + + $('#selectView', page).on('change', function () { + + query.StartIndex = 0; + query.IncludeItemTypes = this.value; + + reloadItems(page); + }); + + $('.chkVideoTypeFilter', page).on('change', function () { + + var filterName = this.getAttribute('data-filter'); + var filters = query.VideoTypes || ""; + + filters = (',' + filters).replace(',' + filterName, '').substring(1); + + if (this.checked) { + filters = filters ? (filters + ',' + filterName) : filterName; + } + + query.StartIndex = 0; + query.VideoTypes = filters; + + reloadItems(page); + }); + + $('#chk3D', page).on('change', function () { + + query.StartIndex = 0; + query.Is3D = this.checked ? true : null; + + reloadItems(page); + }); + + $('#chkHD', page).on('change', function () { + + query.StartIndex = 0; + query.IsHD = this.checked ? true : null; + + reloadItems(page); + }); + + $('#chkSD', page).on('change', function () { + + query.StartIndex = 0; + query.IsHD = this.checked ? false : null; + + reloadItems(page); + }); + + $('#chkSubtitle', page).on('change', function () { + + query.StartIndex = 0; + query.HasSubtitles = this.checked ? true : null; + + reloadItems(page); + }); + + $('#chkTrailer', page).on('change', function () { + + query.StartIndex = 0; + query.HasTrailer = this.checked ? true : null; + + reloadItems(page); + }); + + $('#chkSpecialFeature', page).on('change', function () { + + query.StartIndex = 0; + query.HasSpecialFeature = this.checked ? true : null; + + reloadItems(page); + }); + + $('#chkIsPlaceHolder', page).on('change', function () { + + query.StartIndex = 0; + query.IsPlaceHolder = this.checked ? true : null; + + reloadItems(page); + }); + + $('#chkThemeSong', page).on('change', function () { + + query.StartIndex = 0; + query.HasThemeSong = this.checked ? true : null; + + reloadItems(page); + }); + + $('#chkThemeVideo', page).on('change', function () { + + query.StartIndex = 0; + query.HasThemeVideo = this.checked ? true : null; + + reloadItems(page); + }); + + $('#chkMissingOverview', page).on('change', function () { + + query.StartIndex = 0; + query.HasOverview = this.checked ? false : null; + + reloadItems(page); + }); + + $('#chkMissingRating', page).on('change', function () { + + query.StartIndex = 0; + query.HasOfficialRating = this.checked ? false : null; + + reloadItems(page); + }); + + $('#chkYearMismatch', page).on('change', function () { + + query.StartIndex = 0; + query.IsYearMismatched = this.checked ? true : null; + + reloadItems(page); + }); + + $('#chkIsUnidentified', page).on('change', function () { + + query.StartIndex = 0; + query.IsUnidentified = this.checked ? true : null; + + reloadItems(page); + }); + + $('#chkIsLocked', page).on('change', function () { + + query.StartIndex = 0; + query.IsLocked = this.checked ? true : null; + + reloadItems(page); + }); + + $('#chkMissingEpisode', page).on('change', function () { + + query.StartIndex = 0; + query.IsMissing = this.checked ? true : false; + + reloadItems(page); + }); + + $('#chkFutureEpisode', page).on('change', function () { + + query.StartIndex = 0; + + if (this.checked) { + query.IsUnaired = true; + query.IsVirtualUnaired = null; + } else { + query.IsUnaired = null; + query.IsVirtualUnaired = false; + } + + + reloadItems(page); + }); + + $('#chkSpecialEpisode', page).on('change', function () { + + query.ParentIndexNumber = this.checked ? 0 : null; + + reloadItems(page); + }); + + }).on('pagebeforeshow', "#libraryReportPage", function () { + + var page = this; + var limit = LibraryBrowser.getDefaultPageSize(); + + // If the default page size has changed, the start index will have to be reset + if (limit != query.Limit) { + query.Limit = limit; + query.StartIndex = 0; + } + + reloadItems(page); + + }).on('pageshow', "#libraryReportPage", function () { + + updateFilterControls(this); + }); + +})(jQuery, document, window); + diff --git a/dashboard-ui/scripts/mediaplayer.js b/dashboard-ui/scripts/mediaplayer.js index 5795cedf71..bb3142c4db 100644 --- a/dashboard-ui/scripts/mediaplayer.js +++ b/dashboard-ui/scripts/mediaplayer.js @@ -24,29 +24,11 @@ self.playlist = []; var currentPlaylistIndex = 0; - var channelsListPromise; - var channelsListPromiseTime; - function updateCanClientSeek(elem) { var duration = elem.duration; canClientSeek = duration && !isNaN(duration) && duration != Number.POSITIVE_INFINITY && duration != Number.NEGATIVE_INFINITY; } - function getChannelsListPromise() { - - var lastUpdateTime = channelsListPromiseTime || 0; - - // Update every three minutes - if (!channelsListPromise || !lastUpdateTime || (new Date().getTime() - lastUpdateTime) > 10800000) { - - channelsListPromise = ApiClient.getLiveTvChannels({ - userId: Dashboard.getCurrentUserId() - }); - } - - return channelsListPromise; - } - function requestFullScreen(element) { // Supports most browsers and their versions. var requestMethod = element.requestFullScreen || element.webkitRequestFullScreen || element.mozRequestFullScreen || element.msRequestFullScreen; @@ -353,16 +335,6 @@ hideFlyout($('#qualityFlyout')); }); - - $('#channelsFlyout').on('click', '.mediaFlyoutOption', function () { - - if (!$(this).hasClass('selectedMediaFlyoutOption')) { - var channelId = this.getAttribute('data-channelid'); - self.playById(channelId); - } - - hideFlyout($('#channelsFlyout')); - }); }); function endsWith(text, pattern) { @@ -476,7 +448,6 @@ $('#audioTracksButton', nowPlayingBar).hide(); $('#subtitleButton', nowPlayingBar).hide(); $('#chaptersButton', nowPlayingBar).hide(); - $('#channelsButton', nowPlayingBar).hide(); $('#mediaElement', nowPlayingBar).html(html); var audioElement = $("audio", nowPlayingBar); @@ -852,12 +823,6 @@ $('#fullscreenButton', nowPlayingBar).show(); } - if (isFullScreen() == false) { - repositionPlayer(); - } - - var channelsButton = $('#channelsButton', nowPlayingBar).hide(); - var videoElement = $("video", nowPlayingBar); var initialVolume = localStorage.getItem("volume") || 0.5; @@ -926,15 +891,6 @@ currentItem = item; curentDurationTicks = item.RunTimeTicks; - getChannelsListPromise().done(function (result) { - - if (result.Items.length) { - channelsButton.show(); - } else { - channelsButton.hide(); - } - }); - return videoElement[0]; }; @@ -1021,7 +977,7 @@ return false; } - if (item.LocationType == "Virtual") { + if (item.LocationType == "Virtual" || item.IsPlaceHolder) { return false; } if (item.Type == "MusicAlbum" || item.Type == "MusicArtist" || item.Type == "MusicGenre") { @@ -1923,61 +1879,6 @@ return html; } - function getChannelsFlyoutHtml(channels) { - - var html = ''; - - for (var i = 0, length = channels.length; i < length; i++) { - - var channel = channels[i]; - - html += '
    '; - - var imgUrl; - - if (channel.ImageTags.Primary) { - - imgUrl = ApiClient.getImageUrl(channel.Id, { - maxwidth: 200, - tag: channel.ImageTags.Primary, - type: "Primary" - }); - } - else { - imgUrl = "css/images/media/tvflyout.png"; - } - - html += ''; - - html += '
    '; - - var name = channel.Number + ' ' + channel.Name; - - html += '
    ' + name + '
    '; - html += '
    ' + channel.CurrentProgram.Name + '
    '; - - html += '
    '; - - html += "
    "; - } - - return html; - } - - self.showChannelsFlyout = function () { - - var flyout = $('#channelsFlyout'); - - if (!flyout.is(':visible')) { - getChannelsListPromise().done(function (result) { - - showFlyout(flyout, '#channelsButton'); - - flyout.html(getChannelsFlyoutHtml(result.Items)).scrollTop(0); - }); - } - }; - self.showAudioTracksFlyout = function () { var flyout = $('#audioTracksFlyout'); diff --git a/dashboard-ui/scripts/movies.js b/dashboard-ui/scripts/movies.js index c964c2fb61..69ae53e56d 100644 --- a/dashboard-ui/scripts/movies.js +++ b/dashboard-ui/scripts/movies.js @@ -176,24 +176,6 @@ reloadItems(page); }); - - $('.chkVideoTypeFilter', this).on('change', function () { - - var filterName = this.getAttribute('data-filter'); - var filters = query.VideoTypes || ""; - - filters = (',' + filters).replace(',' + filterName, '').substring(1); - - if (this.checked) { - filters = filters ? (filters + ',' + filterName) : filterName; - } - - query.StartIndex = 0; - query.VideoTypes = filters; - - reloadItems(page); - }); - $('#selectView', this).on('change', function () { view = this.value; @@ -212,6 +194,23 @@ LibraryBrowser.saveViewSetting('movies', view); }); + $('.chkVideoTypeFilter', this).on('change', function () { + + var filterName = this.getAttribute('data-filter'); + var filters = query.VideoTypes || ""; + + filters = (',' + filters).replace(',' + filterName, '').substring(1); + + if (this.checked) { + filters = filters ? (filters + ',' + filterName) : filterName; + } + + query.StartIndex = 0; + query.VideoTypes = filters; + + reloadItems(page); + }); + $('#chk3D', this).on('change', function () { query.StartIndex = 0; diff --git a/dashboard-ui/scripts/notifications.js b/dashboard-ui/scripts/notifications.js index cf18c4a3e6..b1dce5f82e 100644 --- a/dashboard-ui/scripts/notifications.js +++ b/dashboard-ui/scripts/notifications.js @@ -131,16 +131,16 @@ html += '
    '; - html += '

    ' + notification.Name + '

    '; + html += '

    ' + notification.Name + '

    '; - html += '

    ' + humane_date(notification.Date) + '

    '; + html += '

    ' + humane_date(notification.Date) + '

    '; if (notification.Description) { - html += '

    ' + notification.Description + '

    '; + html += '

    ' + notification.Description + '

    '; } if (notification.Url) { - html += '

    More information

    '; + html += '

    More information

    '; } html += '
    '; diff --git a/dashboard-ui/scripts/site.js b/dashboard-ui/scripts/site.js index 07296f29dc..5996033318 100644 --- a/dashboard-ui/scripts/site.js +++ b/dashboard-ui/scripts/site.js @@ -713,7 +713,7 @@ var Dashboard = { href: "dashboard.html", selected: page.hasClass("dashboardHomePage") }, { - name: "Media Library", + name: "Library", divider: true, href: "library.html", selected: page.hasClass("mediaLibraryPage") @@ -1347,9 +1347,6 @@ $(function () { footerHtml += ''; - footerHtml += ''; - footerHtml += '
    '; - footerHtml += ''; footerHtml += '
    '; diff --git a/dashboard-ui/thirdparty/jquerymobile-1.4.1/jquery.mobile-1.4.1.min.js b/dashboard-ui/thirdparty/jquerymobile-1.4.1/jquery.mobile-1.4.1.min.js deleted file mode 100644 index 32664b1229..0000000000 --- a/dashboard-ui/thirdparty/jquerymobile-1.4.1/jquery.mobile-1.4.1.min.js +++ /dev/null @@ -1,10 +0,0 @@ -/*! jQuery Mobile 1.4.1 | Git HEAD hash: 18c1e32 <> 2014-02-12T22:15:20Z | (c) 2010, 2014 jQuery Foundation, Inc. | jquery.org/license */ - -!function(a,b,c){"function"==typeof define&&define.amd?define(["jquery"],function(d){return c(d,a,b),d.mobile}):c(a.jQuery,a,b)}(this,document,function(a,b,c){!function(a){a.mobile={}}(a),function(a){a.extend(a.mobile,{version:"1.4.1",subPageUrlKey:"ui-page",hideUrlBar:!0,keepNative:":jqmData(role='none'), :jqmData(role='nojs')",activePageClass:"ui-page-active",activeBtnClass:"ui-btn-active",focusClass:"ui-focus",ajaxEnabled:!0,hashListeningEnabled:!0,linkBindingEnabled:!0,defaultPageTransition:"fade",maxTransitionWidth:!1,minScrollBack:0,defaultDialogTransition:"pop",pageLoadErrorMessage:"Error Loading Page",pageLoadErrorMessageTheme:"a",phonegapNavigationEnabled:!1,autoInitializePage:!0,pushStateEnabled:!0,ignoreContentEnabled:!1,buttonMarkup:{hoverDelay:200},dynamicBaseEnabled:!0,pageContainer:a(),allowCrossDomainPages:!1,dialogHashKey:"&ui-state=dialog"})}(a,this),function(a,b,c){var d={},e=a.find,f=/(?:\{[\s\S]*\}|\[[\s\S]*\])$/,g=/:jqmData\(([^)]*)\)/g;a.extend(a.mobile,{ns:"",getAttribute:function(b,c){var d;b=b.jquery?b[0]:b,b&&b.getAttribute&&(d=b.getAttribute("data-"+a.mobile.ns+c));try{d="true"===d?!0:"false"===d?!1:"null"===d?null:+d+""===d?+d:f.test(d)?JSON.parse(d):d}catch(e){}return d},nsNormalizeDict:d,nsNormalize:function(b){return d[b]||(d[b]=a.camelCase(a.mobile.ns+b))},closestPageData:function(a){return a.closest(":jqmData(role='page'), :jqmData(role='dialog')").data("mobile-page")}}),a.fn.jqmData=function(b,d){var e;return"undefined"!=typeof b&&(b&&(b=a.mobile.nsNormalize(b)),e=arguments.length<2||d===c?this.data(b):this.data(b,d)),e},a.jqmData=function(b,c,d){var e;return"undefined"!=typeof c&&(e=a.data(b,c?a.mobile.nsNormalize(c):c,d)),e},a.fn.jqmRemoveData=function(b){return this.removeData(a.mobile.nsNormalize(b))},a.jqmRemoveData=function(b,c){return a.removeData(b,a.mobile.nsNormalize(c))},a.find=function(b,c,d,f){return b.indexOf(":jqmData")>-1&&(b=b.replace(g,"[data-"+(a.mobile.ns||"")+"$1]")),e.call(this,b,c,d,f)},a.extend(a.find,e)}(a,this),function(a,b){function d(b,c){var d,f,g,h=b.nodeName.toLowerCase();return"area"===h?(d=b.parentNode,f=d.name,b.href&&f&&"map"===d.nodeName.toLowerCase()?(g=a("img[usemap=#"+f+"]")[0],!!g&&e(g)):!1):(/input|select|textarea|button|object/.test(h)?!b.disabled:"a"===h?b.href||c:c)&&e(b)}function e(b){return a.expr.filters.visible(b)&&!a(b).parents().addBack().filter(function(){return"hidden"===a.css(this,"visibility")}).length}var f=0,g=/^ui-id-\d+$/;a.ui=a.ui||{},a.extend(a.ui,{version:"c0ab71056b936627e8a7821f03c044aec6280a40",keyCode:{BACKSPACE:8,COMMA:188,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SPACE:32,TAB:9,UP:38}}),a.fn.extend({focus:function(b){return function(c,d){return"number"==typeof c?this.each(function(){var b=this;setTimeout(function(){a(b).focus(),d&&d.call(b)},c)}):b.apply(this,arguments)}}(a.fn.focus),scrollParent:function(){var b;return b=a.ui.ie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?this.parents().filter(function(){return/(relative|absolute|fixed)/.test(a.css(this,"position"))&&/(auto|scroll)/.test(a.css(this,"overflow")+a.css(this,"overflow-y")+a.css(this,"overflow-x"))}).eq(0):this.parents().filter(function(){return/(auto|scroll)/.test(a.css(this,"overflow")+a.css(this,"overflow-y")+a.css(this,"overflow-x"))}).eq(0),/fixed/.test(this.css("position"))||!b.length?a(this[0].ownerDocument||c):b},uniqueId:function(){return this.each(function(){this.id||(this.id="ui-id-"+ ++f)})},removeUniqueId:function(){return this.each(function(){g.test(this.id)&&a(this).removeAttr("id")})}}),a.extend(a.expr[":"],{data:a.expr.createPseudo?a.expr.createPseudo(function(b){return function(c){return!!a.data(c,b)}}):function(b,c,d){return!!a.data(b,d[3])},focusable:function(b){return d(b,!isNaN(a.attr(b,"tabindex")))},tabbable:function(b){var c=a.attr(b,"tabindex"),e=isNaN(c);return(e||c>=0)&&d(b,!e)}}),a("").outerWidth(1).jquery||a.each(["Width","Height"],function(c,d){function e(b,c,d,e){return a.each(f,function(){c-=parseFloat(a.css(b,"padding"+this))||0,d&&(c-=parseFloat(a.css(b,"border"+this+"Width"))||0),e&&(c-=parseFloat(a.css(b,"margin"+this))||0)}),c}var f="Width"===d?["Left","Right"]:["Top","Bottom"],g=d.toLowerCase(),h={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};a.fn["inner"+d]=function(c){return c===b?h["inner"+d].call(this):this.each(function(){a(this).css(g,e(this,c)+"px")})},a.fn["outer"+d]=function(b,c){return"number"!=typeof b?h["outer"+d].call(this,b):this.each(function(){a(this).css(g,e(this,b,!0,c)+"px")})}}),a.fn.addBack||(a.fn.addBack=function(a){return this.add(null==a?this.prevObject:this.prevObject.filter(a))}),a("").data("a-b","a").removeData("a-b").data("a-b")&&(a.fn.removeData=function(b){return function(c){return arguments.length?b.call(this,a.camelCase(c)):b.call(this)}}(a.fn.removeData)),a.ui.ie=!!/msie [\w.]+/.exec(navigator.userAgent.toLowerCase()),a.support.selectstart="onselectstart"in c.createElement("div"),a.fn.extend({disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")},zIndex:function(d){if(d!==b)return this.css("zIndex",d);if(this.length)for(var e,f,g=a(this[0]);g.length&&g[0]!==c;){if(e=g.css("position"),("absolute"===e||"relative"===e||"fixed"===e)&&(f=parseInt(g.css("zIndex"),10),!isNaN(f)&&0!==f))return f;g=g.parent()}return 0}}),a.ui.plugin={add:function(b,c,d){var e,f=a.ui[b].prototype;for(e in d)f.plugins[e]=f.plugins[e]||[],f.plugins[e].push([c,d[e]])},call:function(a,b,c,d){var e,f=a.plugins[b];if(f&&(d||a.element[0].parentNode&&11!==a.element[0].parentNode.nodeType))for(e=0;eg;g++){for(e=b.eq(g),f=!1,d=b[g];d;){if(h=d.getAttribute?d.getAttribute("data-"+a.mobile.ns+c):"","false"===h){f=!0;break}d=d.parentNode}f||(j=j.add(e))}return j},getScreenHeight:function(){return b.innerHeight||a.mobile.window.height()},resetActivePageHeight:function(b){var c=a("."+a.mobile.activePageClass),d=c.height(),e=c.outerHeight(!0);b="number"==typeof b?b:a.mobile.getScreenHeight(),c.css("min-height",b-(e-d))},loading:function(){var b=this.loading._widget||a(a.mobile.loader.prototype.defaultHtml).loader(),c=b.loader.apply(b,arguments);return this.loading._widget=b,c}}),a.addDependents=function(b,c){var d=a(b),e=d.jqmData("dependents")||a();d.jqmData("dependents",a(e).add(c))},a.fn.extend({removeWithDependents:function(){a.removeWithDependents(this)},enhanceWithin:function(){var b,c={},d=a.mobile.page.prototype.keepNativeSelector(),e=this;a.mobile.nojs&&a.mobile.nojs(this),a.mobile.links&&a.mobile.links(this),a.mobile.degradeInputsWithin&&a.mobile.degradeInputsWithin(this),a.fn.buttonMarkup&&this.find(a.fn.buttonMarkup.initSelector).not(d).jqmEnhanceable().buttonMarkup(),a.fn.fieldcontain&&this.find(":jqmData(role='fieldcontain')").not(d).jqmEnhanceable().fieldcontain(),a.each(a.mobile.widgets,function(b,f){if(f.initSelector){var g=a.mobile.enhanceable(e.find(f.initSelector));g.length>0&&(g=g.not(d)),g.length>0&&(c[f.prototype.widgetName]=g)}});for(b in c)c[b][b]();return this},addDependents:function(b){a.addDependents(this,b)},getEncodedText:function(){return a("").text(this.text()).html()},jqmEnhanceable:function(){return a.mobile.enhanceable(this)},jqmHijackable:function(){return a.mobile.hijackable(this)}}),a.removeWithDependents=function(b){var c=a(b);(c.jqmData("dependents")||a()).remove(),c.remove()},a.addDependents=function(b,c){var d=a(b),e=d.jqmData("dependents")||a();d.jqmData("dependents",a(e).add(c))},a.find.matches=function(b,c){return a.find(b,null,null,c)},a.find.matchesSelector=function(b,c){return a.find(c,null,null,[b]).length>0}}(a,this),function(a,b){var c=0,d=Array.prototype.slice,e=a.cleanData;a.cleanData=function(b){for(var c,d=0;null!=(c=b[d]);d++)try{a(c).triggerHandler("remove")}catch(f){}e(b)},a.widget=function(b,c,d){var e,f,g,h,i={},j=b.split(".")[0];return b=b.split(".")[1],e=j+"-"+b,d||(d=c,c=a.Widget),a.expr[":"][e.toLowerCase()]=function(b){return!!a.data(b,e)},a[j]=a[j]||{},f=a[j][b],g=a[j][b]=function(a,b){return this._createWidget?void(arguments.length&&this._createWidget(a,b)):new g(a,b)},a.extend(g,f,{version:d.version,_proto:a.extend({},d),_childConstructors:[]}),h=new c,h.options=a.widget.extend({},h.options),a.each(d,function(b,d){return a.isFunction(d)?void(i[b]=function(){var a=function(){return c.prototype[b].apply(this,arguments)},e=function(a){return c.prototype[b].apply(this,a)};return function(){var b,c=this._super,f=this._superApply;return this._super=a,this._superApply=e,b=d.apply(this,arguments),this._super=c,this._superApply=f,b}}()):void(i[b]=d)}),g.prototype=a.widget.extend(h,{widgetEventPrefix:f?h.widgetEventPrefix||b:b},i,{constructor:g,namespace:j,widgetName:b,widgetFullName:e}),f?(a.each(f._childConstructors,function(b,c){var d=c.prototype;a.widget(d.namespace+"."+d.widgetName,g,c._proto)}),delete f._childConstructors):c._childConstructors.push(g),a.widget.bridge(b,g),g},a.widget.extend=function(c){for(var e,f,g=d.call(arguments,1),h=0,i=g.length;i>h;h++)for(e in g[h])f=g[h][e],g[h].hasOwnProperty(e)&&f!==b&&(c[e]=a.isPlainObject(f)?a.isPlainObject(c[e])?a.widget.extend({},c[e],f):a.widget.extend({},f):f);return c},a.widget.bridge=function(c,e){var f=e.prototype.widgetFullName||c;a.fn[c]=function(g){var h="string"==typeof g,i=d.call(arguments,1),j=this;return g=!h&&i.length?a.widget.extend.apply(null,[g].concat(i)):g,this.each(h?function(){var d,e=a.data(this,f);return"instance"===g?(j=e,!1):e?a.isFunction(e[g])&&"_"!==g.charAt(0)?(d=e[g].apply(e,i),d!==e&&d!==b?(j=d&&d.jquery?j.pushStack(d.get()):d,!1):void 0):a.error("no such method '"+g+"' for "+c+" widget instance"):a.error("cannot call methods on "+c+" prior to initialization; attempted to call method '"+g+"'")}:function(){var b=a.data(this,f);b?b.option(g||{})._init():a.data(this,f,new e(g,this))}),j}},a.Widget=function(){},a.Widget._childConstructors=[],a.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",defaultElement:"
    ",options:{disabled:!1,create:null},_createWidget:function(b,d){d=a(d||this.defaultElement||this)[0],this.element=a(d),this.uuid=c++,this.eventNamespace="."+this.widgetName+this.uuid,this.options=a.widget.extend({},this.options,this._getCreateOptions(),b),this.bindings=a(),this.hoverable=a(),this.focusable=a(),d!==this&&(a.data(d,this.widgetFullName,this),this._on(!0,this.element,{remove:function(a){a.target===d&&this.destroy()}}),this.document=a(d.style?d.ownerDocument:d.document||d),this.window=a(this.document[0].defaultView||this.document[0].parentWindow)),this._create(),this._trigger("create",null,this._getCreateEventData()),this._init()},_getCreateOptions:a.noop,_getCreateEventData:a.noop,_create:a.noop,_init:a.noop,destroy:function(){this._destroy(),this.element.unbind(this.eventNamespace).removeData(this.widgetFullName).removeData(a.camelCase(this.widgetFullName)),this.widget().unbind(this.eventNamespace).removeAttr("aria-disabled").removeClass(this.widgetFullName+"-disabled ui-state-disabled"),this.bindings.unbind(this.eventNamespace),this.hoverable.removeClass("ui-state-hover"),this.focusable.removeClass("ui-state-focus")},_destroy:a.noop,widget:function(){return this.element},option:function(c,d){var e,f,g,h=c;if(0===arguments.length)return a.widget.extend({},this.options);if("string"==typeof c)if(h={},e=c.split("."),c=e.shift(),e.length){for(f=h[c]=a.widget.extend({},this.options[c]),g=0;g

    ",fakeFixLoader:function(){var b=a("."+a.mobile.activeBtnClass).first();this.element.css({top:a.support.scrollTop&&this.window.scrollTop()+this.window.height()/2||b.length&&b.offset().top||100})},checkLoaderPosition:function(){var b=this.element.offset(),c=this.window.scrollTop(),d=a.mobile.getScreenHeight();(b.topd)&&(this.element.addClass("ui-loader-fakefix"),this.fakeFixLoader(),this.window.unbind("scroll",this.checkLoaderPosition).bind("scroll",a.proxy(this.fakeFixLoader,this)))},resetHtml:function(){this.element.html(a(this.defaultHtml).html())},show:function(d,e,f){var g,h,i;this.resetHtml(),"object"===a.type(d)?(i=a.extend({},this.options,d),d=i.theme):(i=this.options,d=d||i.theme),h=e||(i.text===!1?"":i.text),c.addClass("ui-loading"),g=i.textVisible,this.element.attr("class",b+" ui-corner-all ui-body-"+d+" ui-loader-"+(g||e||d.text?"verbose":"default")+(i.textonly||f?" ui-loader-textonly":"")),i.html?this.element.html(i.html):this.element.find("h1").text(h),this.element.appendTo(a.mobile.pageContainer),this.checkLoaderPosition(),this.window.bind("scroll",a.proxy(this.checkLoaderPosition,this))},hide:function(){c.removeClass("ui-loading"),this.options.text&&this.element.removeClass("ui-loader-fakefix"),a.mobile.window.unbind("scroll",this.fakeFixLoader),a.mobile.window.unbind("scroll",this.checkLoaderPosition)}})}(a,this),function(a,b,d){"$:nomunge";function e(a){return a=a||location.href,"#"+a.replace(/^[^#]*#?(.*)$/,"$1")}var f,g="hashchange",h=c,i=a.event.special,j=h.documentMode,k="on"+g in b&&(j===d||j>7);a.fn[g]=function(a){return a?this.bind(g,a):this.trigger(g)},a.fn[g].delay=50,i[g]=a.extend(i[g],{setup:function(){return k?!1:void a(f.start)},teardown:function(){return k?!1:void a(f.stop)}}),f=function(){function c(){var d=e(),h=n(j);d!==j?(m(j=d,h),a(b).trigger(g)):h!==j&&(location.href=location.href.replace(/#.*/,"")+h),f=setTimeout(c,a.fn[g].delay)}var f,i={},j=e(),l=function(a){return a},m=l,n=l;return i.start=function(){f||c()},i.stop=function(){f&&clearTimeout(f),f=d},b.attachEvent&&!b.addEventListener&&!k&&function(){var b,d;i.start=function(){b||(d=a.fn[g].src,d=d&&d+e(),b=a('